diff --git a/NSspi/Contexts/ImpersonationHandle.cs b/NSspi/Contexts/ImpersonationHandle.cs index 8bdbdf0..6c5c530 100644 --- a/NSspi/Contexts/ImpersonationHandle.cs +++ b/NSspi/Contexts/ImpersonationHandle.cs @@ -31,13 +31,16 @@ namespace NSspi.Contexts this.disposed = false; } + /// + /// Finalizes the ImpersonationHandle by reverting the impersonation. + /// ~ImpersonationHandle() { Dispose( false ); } /// - /// Reverts the impersonation. + /// Reverts impersonation. /// public void Dispose() { @@ -45,11 +48,27 @@ namespace NSspi.Contexts GC.SuppressFinalize( this ); } - protected virtual void Dispose( bool disposing ) + /// + /// Reverts impersonation. + /// + /// True if being disposed, false if being finalized. + private void Dispose( bool disposing ) { - if( disposing && this.disposed == false && this.server != null && this.server.Disposed == false ) + // This implements a variant of the typical dispose pattern. Always try to revert + // impersonation, even if finalizing. Don't do anything if we're already reverted. + + if( this.disposed == false ) { - this.server.RevertImpersonate(); + this.disposed = true; + + // Just in case the reference is being pulled out from under us, pull a stable copy + // of the reference while we're null-checking. + var serverCopy = this.server; + + if( serverCopy != null && serverCopy.Disposed == false ) + { + serverCopy.RevertImpersonate(); + } } } }