Improved the impersonation revert process.

The Dispose(bool) method will still act even if finalizing, but it armors its access to the server to ensure that it doesn't accidentally cause a nullref trying to revert itself.
This commit is contained in:
Kevin Thompson
2019-06-16 16:57:23 -04:00
parent 4bd2ad0024
commit bbb7c7a060

View File

@@ -31,13 +31,16 @@ namespace NSspi.Contexts
this.disposed = false; this.disposed = false;
} }
/// <summary>
/// Finalizes the ImpersonationHandle by reverting the impersonation.
/// </summary>
~ImpersonationHandle() ~ImpersonationHandle()
{ {
Dispose( false ); Dispose( false );
} }
/// <summary> /// <summary>
/// Reverts the impersonation. /// Reverts impersonation.
/// </summary> /// </summary>
public void Dispose() public void Dispose()
{ {
@@ -45,11 +48,27 @@ namespace NSspi.Contexts
GC.SuppressFinalize( this ); GC.SuppressFinalize( this );
} }
protected virtual void Dispose( bool disposing ) /// <summary>
/// Reverts impersonation.
/// </summary>
/// <param name="disposing">True if being disposed, false if being finalized.</param>
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();
}
} }
} }
} }