Attribute VB_Name = "ModShutDown"
'*************************************************************************
'**模 块 名：ModShutDown
'**说    明：关机
'**创 建 人：马大哈
'**日    期：2003年12月17日
'**修 改 人：
'**日    期：
'**描    述：修改强行关机选项
'**版    本：V1.0
'*************************************************************************
Option Explicit

Private Const EWX_LOGOFF = 0                            '注销当前用户
Private Const EWX_POWEROFF = 8                          '关闭系统并关闭电源
Private Const EWX_REBOOT = 2                            '关闭系统并重启
Private Const EWX_SHUTDOWN = 1                          '关闭系统使之能安全关闭电源

Private Const EWX_FORCE = 4                             '应用程序强制关闭
Private Const EWX_FORCEIFHUNG = 16                      '如果应用程序已挂起，强制关闭

Private Const TOKEN_ADJUST_PRIVILEGES = &H20
Private Const TOKEN_QUERY = &H8
Private Const SE_PRIVILEGE_ENABLED = &H2
Private Const ANYSIZE_ARRAY = 1

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 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 Long

'这个函数就是用于NT关机中使用的
Sub AdjustTokenPrivilegesForNT()
    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
    
    LookupPrivilegeValue "", "SeShutdownPrivilege", tmpLuid
    tkp.PrivilegeCount = 1
    tkp.Privileges(0).pLuid = tmpLuid
    tkp.Privileges(0).Attributes = SE_PRIVILEGE_ENABLED
    
    AdjustTokenPrivileges hdlTokenHandle, False, tkp, _
    Len(tkpNewButIgnored), tkpNewButIgnored, _
    lBufferNeeded
End Sub

Public Function ShutDownPC(ByVal sCode As Long, Optional ByVal IsNt As Boolean = True)
    'EWX_LOGOFF = 退出(注销)            (0)
    'EWX_SHUTDOWN = 关机                (1)
    'EWX_REBOOT = 重启动                (2)
    'EWX_FORCE = 强制关机，即不通知现在活动应用程序让其先自我关闭       (4)
    
    If IsNt = True Then Call AdjustTokenPrivilegesForNT             '如果是NT以上系统就要先调用这个
    Select Case sCode
        Case 0
            ExitWindowsEx EWX_LOGOFF, 0             '注销
        Case 1
            ExitWindowsEx EWX_SHUTDOWN Or EWX_POWEROFF, 0           '关机
        Case 2
            ExitWindowsEx EWX_REBOOT, 0             '重启
        Case 4
            ExitWindowsEx EWX_POWEROFF Or EWX_SHUTDOWN Or EWX_FORCE, 0              '强制关机
    End Select
End Function


