Private Sub AdjustToken()
Const
TOKEN_ADJUST_PRIVILEGES As Short = &H20S
Const
TOKEN_QUERY As Short = &H8S
Const
SE_PRIVILEGE_ENABLED As Short = &H2S
Dim
hdlProcessHandle As Integer
Dim
hdlTokenHandle As Integer
Dim
tmpLuid As LUID
Dim tkp
As TOKEN_PRIVILEGES
Dim
tkpNewButIgnored As TOKEN_PRIVILEGES
Dim
lBufferNeeded As Integer
hdlProcessHandle = GetCurrentProcess()
OpenProcessToken(hdlProcessHandle,TOKEN_ADJUST_PRIVILEGES Or
TOKEN_QUERY, _ hdlTokenHandle)
LookupPrivilegeValue("",
"SeShutdownPrivilege", tmpLuid)
tkp.PrivilegeCount = 1 ' One privilege to set
tkp.TheLuid = tmpLuid
tkp.Attributes = SE_PRIVILEGE_ENABLED
AdjustTokenPrivileges(hdlTokenHandle,False, tkp,
Len(tkpNewButIgnored), _ tkpNewButIgnored, lBufferNeeded)
End Sub
Going through this code in a bit more detail, we can break
the process down into a number of steps. Privileges are granted or revoked on a
process-by-process basis, thus the first step is to ascertain the process ID of
the current process, using the GetCurrentProcess API call. To change the privilege levels for this
process, it is necessary to open the process first. Opening the process
involves passing the process ID to the OpenProcessToken API call.
This call also includes parameters that indicate the purpose of opening the
process, in this case, the purpose is to query the token, and adjust its
privileges
There is only one specific privilege that needs to be
changed, - that being the shutdown privilege. The lookupPrivilegeValue is
used to obtain a reference to the shutdown privilege. The TOKEN_PRIVILIGES structure
is set to enabled, and then applied to the process.
In order to make calls to windows API functions, they must
be declared in advance. This tells .NET where to look for the implementation of
each of the functions, in each case they will be contained in a DLL in the
Windows system folder. These files are common to all windows PC’s and therefore
do not need to be redistributed when deploying your application.
[StructLayout(LayoutKind.Sequential, Pack=1)]
internal struct TOKEN_PRIVILEGES
{
public
int Count;
public
long Luid;
public
int Attr;
}
internal const int EWX_SHUTDOWN = 0x00000001;
internal const int EWX_REBOOT = 0x00000002;
internal const int EWX_FORCE = 0x00000004;
[DllImport("kernel32.dll",
ExactSpelling=true) ]
internal static extern IntPtr
GetCurrentProcess();
[DllImport("advapi32.dll",
ExactSpelling=true, SetLastError=true) ]
internal static extern bool OpenProcessToken(
IntPtr h, int acc, ref IntPtr phtok );
[DllImport("advapi32.dll",
SetLastError=true) ]
internal static extern bool
LookupPrivilegeValue( string host, string name, ref long pluid );
[DllImport("advapi32.dll",
ExactSpelling=true, SetLastError=true) ]
internal static extern bool
AdjustTokenPrivileges( IntPtr htok, bool disall,
ref
TOKEN_PRIVILEGES newst, int len, IntPtr prev, IntPtr relen );
[DllImport("user32.dll",
ExactSpelling=true, SetLastError=true) ]
internal static extern bool ExitWindowsEx( int
flg, int rea );
internal const int SE_PRIVILEGE_ENABLED =
0x00000002;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES =
0x00000020;
internal const string SE_SHUTDOWN_NAME =
"SeShutdownPrivilege";
Private Structure LUID
Dim UsedPart
As Integer
Dim
IgnoredForNowHigh32BitPart As Integer
End Structure
Private Structure TOKEN_PRIVILEGES
Dim
PrivilegeCount As Integer
Dim
TheLuid As Form1.LUID
Dim
Attributes As Integer
End Structure
Private Const EWX_SHUTDOWN As Integer = 1
Private Const EWX_FORCE As Integer = 4
Private Const EWX_REBOOT As Short = 2
Page 2
Page 4