1. API 的宣告: Enum HowExitConst EWX_FORCE = 4 ' 强制关机 EWX_LOGOFF = 0 ' 登出 EWX_REBOOT = 2 ' 重开机 EWX_SHUTDOWN = 1 ' 关机 End Enum Const TOKEN_ADJUST_PRIVILEGES = &H20 Const TOKEN_QUERY = &H8 Const SE_PRIVILEGE_ENABLED = &H2 Const ANYSIZE_ARRAY = 1 Private Type LUID lowpart As Long highpart As Long End Type Private Type LUID_AND_ATTRIBUTES pLuid As LUID Attributes As Long End Type Private Type TOKEN_PRIVILEGES PrivilegeCount As Long Privileges(ANYSIZE_ARRAY) As LUID_AND_ATTRIBUTES End Type Private Declare Function ExitWindowsEx Lib "user32" (ByVal uFlags As Long, _ ByVal dwReserved As Long) As Long Private Declare Function GetCurrentProcess Lib "kernel32" () As Long Private Declare Function LookupPrivilegeValue Lib"advapi32.dll" Alias _ "LookupPrivilegeValueA" (ByVal lpSystemName As String, _ ByVal lpName As String, lpLuid As LUID) As Long Private Declare Function AdjustTokenPrivileges Lib "advapi32.dll" _ (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, _ NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, _ PreviousState As TOKEN_PRIVILEGES, ReturnLength As Long) As Long Private Declare Function OpenProcessToken Lib "advapi32.dll" _ (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, _ TokenHandle As Long) As Long2. AdjustToken 副程式:Private Sub AdjustToken() Dim hdlProcessHandle As Long Dim hdlTokenHandle As Long Dim tmpLuid As LUID Dim tkp As TOKEN_PRIVILEGES Dim tkpNewButIgnored As TOKEN_PRIVILEGES Dim lBufferNeeded As Long
hdlProcessHandle = GetCurrentProcess() OpenProcessToken hdlProcessHandle,(TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY), _ hdlTokenHandle 'Get the LUID for shutdown privilege. LookupPrivilegeValue "","SeShutdownPrivilege", tmpLuid tkp.PrivilegeCount = 1 ' One privilege to set tkp.Privileges(0).pLuid = tmpLuid tkp.Privileges(0).Attributes = SE_PRIVILEGE_ENABLED 'Enable the shutdown privilege in the access token of this process. AdjustTokenPrivileges hdlTokenHandle, False, tkp, Len(tkpNewButIgnored), _ tkpNewButIgnored, lBufferNeeded End Sub3. 呼叫的范例: AdjustToken Call ExitWindowsEx(how, 0) 'how 等於 EWX_LOGOFF 、 EWX_REBOOT 、 EWX_SHUTDOWN、 或EWX_FORCE在 Windows 95 底下呼叫了 AdjustToken 也没关系,因为 Windows 95 并不会 理会安全性的设定。
Private Const EWX_LOGOFF = 0 Private Const EWX_SHUTDOWN = 1 Private Const EWX_REBOOT = 2 Private Const EWX_FORCE = 4 Private Const TOKEN_ADJUST_PRIVILEGES = &H20 Private Const TOKEN_QUERY = &H8 Private Const SE_PRIVILEGE_ENABLED = &H2 Private Const ANYSIZE_ARRAY = 1 Private Const VER_PLATFORM_WIN32_NT = 2 Type OSVERSIONINFO dwOSVersionInfoSize As Long dwMajorVersion As Long dwMinorVersion As Long dwBuildNumber As Long dwPlatformId As Long szCSDVersion As String * 128 End Type Type LUID LowPart As Long HighPart As Long End Type Type LUID_AND_ATTRIBUTES pLuid As LUID Attributes As Long End Type Type TOKEN_PRIVILEGES PrivilegeCount As Long Privileges(ANYSIZE_ARRAY) As LUID_AND_ATTRIBUTES End Type Private Declare Function GetCurrentProcess Lib "kernel32" () As Long Private Declare Function OpenProcessToken Lib "advapi32" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long Private Declare Function LookupPrivilegeValue Lib "advapi32" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long Private Declare Function AdjustTokenPrivileges Lib "advapi32" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, PreviousState As TOKEN_PRIVILEGES, ReturnLength As Long) As Long Private Declare Function ExitWindowsEx Lib "user32" (ByVal uFlags As Long, ByVal dwReserved As Long) As Long Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (ByRef lpVersionInformation As OSVERSIONINFO) As Long 'Detect if the program is running under Windows NT Public Function IsWinNT() As Boolean Dim myOS As OSVERSIONINFO myOS.dwOSVersionInfoSize = Len(myOS) GetVersionEx myOS IsWinNT = (myOS.dwPlatformId = VER_PLATFORM_WIN32_NT) End Function 'set the shut down privilege for the current application Private Sub EnableShutDown() Dim hProc As Long Dim hToken As Long Dim mLUID As LUID Dim mPriv As TOKEN_PRIVILEGES Dim mNewPriv As TOKEN_PRIVILEGES hProc = GetCurrentProcess() OpenProcessToken hProc, TOKEN_ADJUST_PRIVILEGES + TOKEN_QUERY, hToken LookupPrivilegeValue "", "SeShutdownPrivilege", mLUID mPriv.PrivilegeCount = 1 mPriv.Privileges(0).Attributes = SE_PRIVILEGE_ENABLED mPriv.Privileges(0).pLuid = mLUID ' enable shutdown privilege for the current application AdjustTokenPrivileges hToken, False, mPriv, 4 + (12 * mPriv.PrivilegeCount), mNewPriv, 4 + (12 * mNewPriv.PrivilegeCount) End Sub ' Shut Down NT Public Sub ShutDownNT(Force As Boolean) Dim ret As Long Dim Flags As Long Flags = EWX_SHUTDOWN If Force Then Flags = Flags + EWX_FORCE If IsWinNT Then EnableShutDown ExitWindowsEx Flags, 0 End Sub 'Restart NT Public Sub RebootNT(Force As Boolean) Dim ret As Long Dim Flags As Long Flags = EWX_REBOOT If Force Then Flags = Flags + EWX_FORCE If IsWinNT Then EnableShutDown ExitWindowsEx Flags, 0 End Sub 'Log off the current user Public Sub LogOffNT(Force As Boolean) Dim ret As Long Dim Flags As Long Flags = EWX_LOGOFF If Force Then Flags = Flags + EWX_FORCE ExitWindowsEx Flags, 0 End Sub
Public Declare Function ExitWindowsEx Lib "user32" _ (ByVal uFlags As Long, ByVal dwReserved As Long) As Long
Public Declare Function AdjustTokenPrivileges Lib "advapi32" _ (ByVal TokenHandle As Long, _ ByVal DisableAllPrivileges As Long, _ NewState As TOKEN_PRIVILEGES, _ ByVal BufferLength As Long, _ PreviousState As TOKEN_PRIVILEGES, _ ReturnLength As Long) As LongPublic Declare Function OpenProcessToken Lib "advapi32" _ (ByVal ProcessHandle As Long, _ ByVal DesiredAccess As Long, _ TokenHandle As Long) As LongPublic Declare Function GetCurrentProcess Lib "kernel32" () As LongPublic Declare Function LookupPrivilegeValue Lib "advapi32" _ Alias "LookupPrivilegeValueA" _ (ByVal lpSystemName As String, _ ByVal lpName As String, _ lpLuid As LUID) As LongPublic Type LUID UsedPart As Long IgnoredForNowHigh32BitPart As Long End TypePublic Type TOKEN_PRIVILEGES PrivilegeCount As Long TheLuid As LUID Attributes As Long End TypePublic Sub PowerOff() AdjustToken ExitWindowsEx EWX_SHUTDOWN Or EWX_POWEROFF Or EWX_FORCE, &HFFFF 'MsgBox "Powering off"
End SubPrivate Sub AdjustToken()
'******************************************************************** '* This procedure sets the proper privileges to allow a log off or a '* shut down to occur under Windows NT. '********************************************************************
Dim hdlProcessHandle As Long Dim hdlTokenHandle As Long Dim tmpLuid As LUID Dim tkp As TOKEN_PRIVILEGES Dim tkpNewButIgnored As TOKEN_PRIVILEGES Dim lBufferNeeded As Long
'Use the GetCurrentProcess function to set the hdlProcessHandle 'variable. hdlProcessHandle = GetCurrentProcess()
OpenProcessToken hdlProcessHandle, _ (TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY), hdlTokenHandle
'Get the LUID for shutdown privilege LookupPrivilegeValue "", "SeShutdownPrivilege", tmpLuid
tkp.PrivilegeCount = 1 ' One privilege to set tkp.TheLuid = tmpLuid tkp.Attributes = SE_PRIVILEGE_ENABLED
'Enable the shutdown privilege in the access token of this process AdjustTokenPrivileges hdlTokenHandle, False, tkp, Len(tkpNewButIgnored), _ tkpNewButIgnored, lBufferNeeded
EWX_FORCE = 4 ' 强制关机
EWX_LOGOFF = 0 ' 登出
EWX_REBOOT = 2 ' 重开机
EWX_SHUTDOWN = 1 ' 关机
End Enum Const TOKEN_ADJUST_PRIVILEGES = &H20
Const TOKEN_QUERY = &H8
Const SE_PRIVILEGE_ENABLED = &H2
Const ANYSIZE_ARRAY = 1
Private Type LUID
lowpart As Long
highpart As Long
End Type Private Type LUID_AND_ATTRIBUTES
pLuid As LUID
Attributes As Long
End Type Private Type TOKEN_PRIVILEGES
PrivilegeCount As Long
Privileges(ANYSIZE_ARRAY) As LUID_AND_ATTRIBUTES
End Type Private Declare Function ExitWindowsEx Lib "user32" (ByVal uFlags As Long, _
ByVal dwReserved As Long) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function LookupPrivilegeValue Lib"advapi32.dll" Alias _
"LookupPrivilegeValueA" (ByVal lpSystemName As String, _
ByVal lpName As String, lpLuid As LUID) As Long
Private Declare Function AdjustTokenPrivileges Lib "advapi32.dll" _
(ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, _
NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, _
PreviousState As TOKEN_PRIVILEGES, ReturnLength As Long) As Long
Private Declare Function OpenProcessToken Lib "advapi32.dll" _
(ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, _
TokenHandle As Long) As Long2. AdjustToken 副程式:Private Sub AdjustToken() Dim hdlProcessHandle As Long
Dim hdlTokenHandle As Long
Dim tmpLuid As LUID
Dim tkp As TOKEN_PRIVILEGES
Dim tkpNewButIgnored As TOKEN_PRIVILEGES
Dim lBufferNeeded As Long
hdlProcessHandle = GetCurrentProcess()
OpenProcessToken hdlProcessHandle,(TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY), _
hdlTokenHandle 'Get the LUID for shutdown privilege.
LookupPrivilegeValue "","SeShutdownPrivilege", tmpLuid
tkp.PrivilegeCount = 1 ' One privilege to set
tkp.Privileges(0).pLuid = tmpLuid
tkp.Privileges(0).Attributes = SE_PRIVILEGE_ENABLED 'Enable the shutdown privilege in the access token of this process.
AdjustTokenPrivileges hdlTokenHandle, False, tkp, Len(tkpNewButIgnored), _
tkpNewButIgnored, lBufferNeeded
End Sub3. 呼叫的范例: AdjustToken
Call ExitWindowsEx(how, 0)
'how 等於 EWX_LOGOFF 、 EWX_REBOOT 、 EWX_SHUTDOWN、 或EWX_FORCE在 Windows 95 底下呼叫了 AdjustToken 也没关系,因为 Windows 95 并不会
理会安全性的设定。
Private Const EWX_SHUTDOWN = 1
Private Const EWX_REBOOT = 2
Private Const EWX_FORCE = 4
Private Const TOKEN_ADJUST_PRIVILEGES = &H20
Private Const TOKEN_QUERY = &H8
Private Const SE_PRIVILEGE_ENABLED = &H2
Private Const ANYSIZE_ARRAY = 1
Private Const VER_PLATFORM_WIN32_NT = 2
Type OSVERSIONINFO
dwOSVersionInfoSize As Long
dwMajorVersion As Long
dwMinorVersion As Long
dwBuildNumber As Long
dwPlatformId As Long
szCSDVersion As String * 128
End Type
Type LUID
LowPart As Long
HighPart As Long
End Type
Type LUID_AND_ATTRIBUTES
pLuid As LUID
Attributes As Long
End Type
Type TOKEN_PRIVILEGES
PrivilegeCount As Long
Privileges(ANYSIZE_ARRAY) As LUID_AND_ATTRIBUTES
End Type
Private Declare Function GetCurrentProcess Lib "kernel32" ()
As Long
Private Declare Function OpenProcessToken Lib "advapi32"
(ByVal ProcessHandle As Long, ByVal DesiredAccess As Long,
TokenHandle As Long) As Long
Private Declare Function LookupPrivilegeValue Lib "advapi32"
Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String,
ByVal lpName As String, lpLuid As LUID) As Long
Private Declare Function AdjustTokenPrivileges Lib "advapi32"
(ByVal TokenHandle As Long, ByVal DisableAllPrivileges As
Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As
Long, PreviousState As TOKEN_PRIVILEGES, ReturnLength As Long)
As Long
Private Declare Function ExitWindowsEx Lib "user32" (ByVal
uFlags As Long, ByVal dwReserved As Long) As Long
Private Declare Function GetVersionEx Lib "kernel32" Alias
"GetVersionExA" (ByRef lpVersionInformation As OSVERSIONINFO)
As Long
'Detect if the program is running under Windows NT
Public Function IsWinNT() As Boolean
Dim myOS As OSVERSIONINFO
myOS.dwOSVersionInfoSize = Len(myOS)
GetVersionEx myOS
IsWinNT = (myOS.dwPlatformId = VER_PLATFORM_WIN32_NT)
End Function
'set the shut down privilege for the current application
Private Sub EnableShutDown()
Dim hProc As Long
Dim hToken As Long
Dim mLUID As LUID
Dim mPriv As TOKEN_PRIVILEGES
Dim mNewPriv As TOKEN_PRIVILEGES
hProc = GetCurrentProcess()
OpenProcessToken hProc, TOKEN_ADJUST_PRIVILEGES +
TOKEN_QUERY, hToken
LookupPrivilegeValue "", "SeShutdownPrivilege", mLUID
mPriv.PrivilegeCount = 1
mPriv.Privileges(0).Attributes = SE_PRIVILEGE_ENABLED
mPriv.Privileges(0).pLuid = mLUID
' enable shutdown privilege for the current
application
AdjustTokenPrivileges hToken, False, mPriv, 4 + (12 *
mPriv.PrivilegeCount), mNewPriv, 4 + (12 *
mNewPriv.PrivilegeCount)
End Sub
' Shut Down NT
Public Sub ShutDownNT(Force As Boolean)
Dim ret As Long
Dim Flags As Long
Flags = EWX_SHUTDOWN
If Force Then Flags = Flags + EWX_FORCE
If IsWinNT Then EnableShutDown
ExitWindowsEx Flags, 0
End Sub
'Restart NT
Public Sub RebootNT(Force As Boolean)
Dim ret As Long
Dim Flags As Long
Flags = EWX_REBOOT
If Force Then Flags = Flags + EWX_FORCE
If IsWinNT Then EnableShutDown
ExitWindowsEx Flags, 0
End Sub
'Log off the current user
Public Sub LogOffNT(Force As Boolean)
Dim ret As Long
Dim Flags As Long
Flags = EWX_LOGOFF
If Force Then Flags = Flags + EWX_FORCE
ExitWindowsEx Flags, 0
End Sub
(ByVal uFlags As Long, ByVal dwReserved As Long) As Long
Public Declare Function AdjustTokenPrivileges Lib "advapi32" _
(ByVal TokenHandle As Long, _
ByVal DisableAllPrivileges As Long, _
NewState As TOKEN_PRIVILEGES, _
ByVal BufferLength As Long, _
PreviousState As TOKEN_PRIVILEGES, _
ReturnLength As Long) As LongPublic Declare Function OpenProcessToken Lib "advapi32" _
(ByVal ProcessHandle As Long, _
ByVal DesiredAccess As Long, _
TokenHandle As Long) As LongPublic Declare Function GetCurrentProcess Lib "kernel32" () As LongPublic Declare Function LookupPrivilegeValue Lib "advapi32" _
Alias "LookupPrivilegeValueA" _
(ByVal lpSystemName As String, _
ByVal lpName As String, _
lpLuid As LUID) As LongPublic Type LUID
UsedPart As Long
IgnoredForNowHigh32BitPart As Long
End TypePublic Type TOKEN_PRIVILEGES
PrivilegeCount As Long
TheLuid As LUID
Attributes As Long
End TypePublic Sub PowerOff() AdjustToken ExitWindowsEx EWX_SHUTDOWN Or EWX_POWEROFF Or EWX_FORCE, &HFFFF 'MsgBox "Powering off"
End SubPrivate Sub AdjustToken()
'********************************************************************
'* This procedure sets the proper privileges to allow a log off or a
'* shut down to occur under Windows NT.
'********************************************************************
Const TOKEN_ADJUST_PRIVILEGES = &H20
Const TOKEN_QUERY = &H8
Const SE_PRIVILEGE_ENABLED = &H2
Dim hdlProcessHandle As Long
Dim hdlTokenHandle As Long
Dim tmpLuid As LUID
Dim tkp As TOKEN_PRIVILEGES
Dim tkpNewButIgnored As TOKEN_PRIVILEGES
Dim lBufferNeeded As Long
'Use the GetCurrentProcess function to set the hdlProcessHandle
'variable.
hdlProcessHandle = GetCurrentProcess()
OpenProcessToken hdlProcessHandle, _
(TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY), hdlTokenHandle
'Get the LUID for shutdown privilege
LookupPrivilegeValue "", "SeShutdownPrivilege", tmpLuid
tkp.PrivilegeCount = 1 ' One privilege to set
tkp.TheLuid = tmpLuid
tkp.Attributes = SE_PRIVILEGE_ENABLED
'Enable the shutdown privilege in the access token of this process
AdjustTokenPrivileges hdlTokenHandle, False, tkp, Len(tkpNewButIgnored), _
tkpNewButIgnored, lBufferNeeded
End Sub