@@ -53,14 +53,17 @@ namespace NLog.Targets.Wrappers
5353 [ Target ( "ImpersonatingWrapper" , IsWrapper = true ) ]
5454 public class ImpersonatingTargetWrapper : WrapperTargetBase
5555 {
56- private NewIdentityHandle _newIdentity ;
56+ private readonly Action < AsyncLogEventInfo > _writeLogEvent ;
57+ private readonly Action < IList < AsyncLogEventInfo > > _writeLogEvents ;
58+ private NewIdentityHandle ? _newIdentity ;
5759
5860 /// <summary>
5961 /// Initializes a new instance of the <see cref="ImpersonatingTargetWrapper" /> class.
6062 /// </summary>
6163 public ImpersonatingTargetWrapper ( )
62- : this ( null )
6364 {
65+ _writeLogEvent = ( l ) => WrappedTarget ? . WriteAsyncLogEvent ( l ) ;
66+ _writeLogEvents = ( l ) => WrappedTarget ? . WriteAsyncLogEvents ( l ) ;
6467 }
6568
6669 /// <summary>
@@ -79,6 +82,7 @@ public ImpersonatingTargetWrapper(string name, Target wrappedTarget)
7982 /// </summary>
8083 /// <param name="wrappedTarget">The wrapped target.</param>
8184 public ImpersonatingTargetWrapper ( Target wrappedTarget )
85+ : this ( )
8286 {
8387 WrappedTarget = wrappedTarget ;
8488 }
@@ -90,13 +94,13 @@ public ImpersonatingTargetWrapper(Target wrappedTarget)
9094 /// If you use the user principal name (UPN) format, User@DNSDomainName, the <see cref="Domain"/> must be NULL.
9195 /// </remarks>
9296 /// <docgen category='Impersonation Options' order='10' />
93- public Layout UserName { get ; set ; }
97+ public Layout ? UserName { get ; set ; }
9498
9599 /// <summary>
96100 /// Gets or sets the user account password.
97101 /// </summary>
98102 /// <docgen category='Impersonation Options' order='10' />
99- public Layout Password { get ; set ; }
103+ public Layout ? Password { get ; set ; }
100104
101105 /// <summary>
102106 /// Gets or sets Windows domain name to change context to.
@@ -141,7 +145,7 @@ protected override void InitializeTarget()
141145 base . InitializeTarget ( ) ;
142146 }
143147
144- private NewIdentityHandle ResolveNewIdentity ( LogEventInfo logEvent , bool forceCreate )
148+ private NewIdentityHandle ? ResolveNewIdentity ( LogEventInfo logEvent , bool forceCreate )
145149 {
146150 if ( RevertToSelf )
147151 {
@@ -192,13 +196,9 @@ protected override void CloseTarget()
192196 /// <param name="logEvent">The log event.</param>
193197 protected override void Write ( AsyncLogEventInfo logEvent )
194198 {
195- if ( _writeLogEvent is null )
196- _writeLogEvent = ( l ) => WrappedTarget . WriteAsyncLogEvent ( l ) ;
197-
198199 var newIdentity = ResolveNewIdentity ( logEvent . LogEvent , true ) ;
199200 RunImpersonated ( newIdentity , _writeLogEvent , logEvent ) ;
200201 }
201- private Action < AsyncLogEventInfo > _writeLogEvent ;
202202
203203 /// <summary>
204204 /// Changes the security context, forwards the call to the <see cref="WrapperTargetBase.WrappedTarget"/>.Write()
@@ -207,17 +207,13 @@ protected override void Write(AsyncLogEventInfo logEvent)
207207 /// <param name="logEvents">Log events.</param>
208208 protected override void Write ( IList < AsyncLogEventInfo > logEvents )
209209 {
210- if ( _writeLogEvents is null )
211- _writeLogEvents = ( l ) => WrappedTarget . WriteAsyncLogEvents ( l ) ;
212-
213210 if ( logEvents . Count > 0 )
214211 {
215212 var firstLogEvent = logEvents [ 0 ] . LogEvent ;
216213 var newIdentity = ResolveNewIdentity ( firstLogEvent , true ) ;
217214 RunImpersonated ( newIdentity , _writeLogEvents , logEvents ) ;
218215 }
219216 }
220- private Action < IList < AsyncLogEventInfo > > _writeLogEvents ;
221217
222218 /// <summary>
223219 /// Flush any pending log messages (in case of asynchronous targets).
@@ -226,10 +222,10 @@ protected override void Write(IList<AsyncLogEventInfo> logEvents)
226222 protected override void FlushAsync ( AsyncContinuation asyncContinuation )
227223 {
228224 var newIdentity = ResolveNewIdentity ( LogEventInfo . CreateNullEvent ( ) , true ) ;
229- RunImpersonated ( newIdentity , ( s ) => WrappedTarget . Flush ( s ) , asyncContinuation ) ;
225+ RunImpersonated ( newIdentity , ( s ) => WrappedTarget ? . Flush ( s ) , asyncContinuation ) ;
230226 }
231227
232- private void RunImpersonated < T > ( NewIdentityHandle newIdentity , Action < T > executeOperation , T state )
228+ private static void RunImpersonated < T > ( NewIdentityHandle ? newIdentity , Action < T > executeOperation , T state )
233229 {
234230 NewIdentityHandle . RunImpersonated ( newIdentity , executeOperation , state ) ;
235231 }
@@ -240,19 +236,20 @@ internal sealed class NewIdentityHandle : IDisposable
240236 public string Domain { get ; }
241237 public int Password { get ; }
242238
243- #if NETSTANDARD
244- public Microsoft . Win32 . SafeHandles . SafeAccessTokenHandle Handle { get ; }
245- #else
239+ #if NETFRAMEWORK
246240 public WindowsIdentity Handle { get ; }
247241 private readonly IntPtr _handle = IntPtr . Zero ;
248-
242+ #else
243+ public Microsoft . Win32 . SafeHandles . SafeAccessTokenHandle Handle { get ; }
249244#endif
245+
250246 public NewIdentityHandle ( string userName , string domain , string password , SecurityLogOnType logOnType , LogOnProviderType logOnProvider , SecurityImpersonationLevel impersonationLevel )
251247 {
252248 UserName = userName ;
253249 Domain = domain ;
254250 Password = password ? . GetHashCode ( ) ?? 0 ;
255251
252+ #pragma warning disable CS8604 // Possible null reference argument.
256253 if ( ! NativeMethods . LogonUser (
257254 userName ,
258255 domain ,
@@ -263,10 +260,9 @@ public NewIdentityHandle(string userName, string domain, string password, Securi
263260 {
264261 throw Marshal . GetExceptionForHR ( Marshal . GetHRForLastWin32Error ( ) ) ;
265262 }
263+ #pragma warning restore CS8604 // Possible null reference argument.
266264
267- #if NETSTANDARD
268- Handle = logonHandle ;
269- #else
265+ #if NETFRAMEWORK
270266 // adapted from:
271267 // https://www.codeproject.com/csharp/cpimpersonation1.asp
272268 if ( ! NativeMethods . DuplicateToken ( logonHandle , ( int ) impersonationLevel , out _handle ) )
@@ -279,6 +275,8 @@ public NewIdentityHandle(string userName, string domain, string password, Securi
279275
280276 // create new identity using new primary token)
281277 Handle = new WindowsIdentity ( _handle ) ;
278+ #else
279+ Handle = logonHandle ;
282280#endif
283281 }
284282
@@ -290,7 +288,7 @@ public bool IsValid(string userName, string domain, string password)
290288 public void Close ( )
291289 {
292290 Handle . Dispose ( ) ;
293- #if ! NETSTANDARD
291+ #if NETFRAMEWORK
294292 if ( _handle != IntPtr . Zero )
295293 NativeMethods . CloseHandle ( _handle ) ;
296294#endif
@@ -301,12 +299,10 @@ public void Dispose()
301299 Close ( ) ;
302300 }
303301
304- internal static void RunImpersonated < T > ( NewIdentityHandle newIdentity , Action < T > executeOperation , T state )
302+ internal static void RunImpersonated < T > ( NewIdentityHandle ? newIdentity , Action < T > executeOperation , T state )
305303 {
306- #if NETSTANDARD
307- WindowsIdentity . RunImpersonated ( newIdentity ? . Handle ?? Microsoft . Win32 . SafeHandles . SafeAccessTokenHandle . InvalidHandle , ( ) => executeOperation . Invoke ( state ) ) ;
308- #else
309- WindowsImpersonationContext context = null ;
304+ #if NETFRAMEWORK
305+ WindowsImpersonationContext ? context = null ;
310306 try
311307 {
312308 context = newIdentity ? . Handle . Impersonate ( ) ?? WindowsIdentity . Impersonate ( IntPtr . Zero ) ;
@@ -316,6 +312,8 @@ internal static void RunImpersonated<T>(NewIdentityHandle newIdentity, Action<T>
316312 {
317313 context ? . Undo ( ) ;
318314 }
315+ #else
316+ WindowsIdentity . RunImpersonated ( newIdentity ? . Handle ?? Microsoft . Win32 . SafeHandles . SafeAccessTokenHandle . InvalidHandle , ( ) => executeOperation . Invoke ( state ) ) ;
319317#endif
320318 }
321319 }
0 commit comments