private void ToggleState(bool enable)
{
int error = 0;
//
// All privilege operations must take place on the same thread
//
if (!this.currentThread.Equals(Thread.CurrentThread))
{
throw new InvalidOperationException(SR.InvalidOperation_MustBeSameThread);
}
//
// This privilege was already altered and needs to be reverted before it can be altered again
//
if (this.needToRevert)
{
throw new InvalidOperationException(SR.InvalidOperation_MustRevertPrivilege);
}
//
// Need to make this block of code non-interruptible so that it would preserve
// consistency of thread oken state even in the face of catastrophic exceptions
//
try
{
//
// The payload is entirely in the finally block
// This is how we ensure that the code will not be
// interrupted by catastrophic exceptions
//
}
finally
{
try
{
//
// Retrieve TLS state
//
this.tlsContents = tlsSlotData;
if (this.tlsContents == null)
{
this.tlsContents = new TlsContents();
tlsSlotData = this.tlsContents;
}
else
{
this.tlsContents.IncrementReferenceCount();
}
Interop.Advapi32.LUID_AND_ATTRIBUTES luidAndAttrs = new Interop.Advapi32.LUID_AND_ATTRIBUTES();
luidAndAttrs.Luid = this.luid;
luidAndAttrs.Attributes = enable ? Interop.Advapi32.SEPrivileges.SE_PRIVILEGE_ENABLED : Interop.Advapi32.SEPrivileges.SE_PRIVILEGE_DISABLED;
Interop.Advapi32.TOKEN_PRIVILEGE newState = new Interop.Advapi32.TOKEN_PRIVILEGE();
newState.PrivilegeCount = 1;
newState.Privileges[0] = luidAndAttrs;
Interop.Advapi32.TOKEN_PRIVILEGE previousState = new Interop.Advapi32.TOKEN_PRIVILEGE();
uint previousSize = 0;
//
// Place the new privilege on the thread token and remember the previous state.
//
if (false == Interop.Advapi32.AdjustTokenPrivileges(
this.tlsContents.ThreadHandle,
false,
ref newState,
(uint)Marshal.SizeOf(previousState),
ref previousState,
ref previousSize))
{
error = Marshal.GetLastWin32Error();
}
else if (Interop.Errors.ERROR_NOT_ALL_ASSIGNED == Marshal.GetLastWin32Error())
{
error = Interop.Errors.ERROR_NOT_ALL_ASSIGNED;
}
else
{
//
// This is the initial state that revert will have to go back to
//
this.initialState = ((previousState.Privileges[0].Attributes & Interop.Advapi32.SEPrivileges.SE_PRIVILEGE_ENABLED) != 0);
//
// Remember whether state has changed at all
//
this.stateWasChanged = (this.initialState != enable);
//
// If we had to impersonate, or if the privilege state changed we'll need to revert
//
this.needToRevert = this.tlsContents.IsImpersonating || this.stateWasChanged;
}
}
finally
{
if (!this.needToRevert)
{
this.Reset();
}
}
}
if (error == Interop.Errors.ERROR_NOT_ALL_ASSIGNED)
{
throw new PrivilegeNotHeldException(privileges[this.luid]);
}
if (error == Interop.Errors.ERROR_NOT_ENOUGH_MEMORY)
{
throw new OutOfMemoryException();
}
else if (error == Interop.Errors.ERROR_ACCESS_DENIED ||
error == Interop.Errors.ERROR_CANT_OPEN_ANONYMOUS)
{
throw new UnauthorizedAccessException();
}
else if (error != 0)
{
System.Diagnostics.Debug.Assert(false, string.Format(CultureInfo.InvariantCulture, "AdjustTokenPrivileges() failed with unrecognized error code {0}", error));
throw new InvalidOperationException();
}
}