Программное выключение компьютера

Option Explicit

    Private Type LUID
       UsedPart As Long
       IgnoredForNowHigh32BitPart As Long
    End Type

    Private Type TOKEN_PRIVILEGES
      PrivilegeCount As Long
      TheLuid As LUID
      Attributes As Long
    End Type
    
    Private Const EWX_LogOff As Long = 0
    Private Const EWX_SHUTDOWN As Long = 1
    Private Const EWX_FORCE As Long = 4
    Private Const EWX_REBOOT = 2

    Private Declare Function ExitWindowsEx Lib "user32" (ByVal _
         dwOptions As Long, ByVal dwReserved As Long) As Long

    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 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

    Private Sub cmdLogoff_Click()
        ExitWindowsEx (EWX_LogOff), &HFFFF
    End Sub

    Private Sub cmdForceLogoff_Click()
        ExitWindowsEx (EWX_LogOff Or EWX_FORCE), &HFFFF
    End Sub

    Private Sub cmdShutdown_Click()
        AdjustToken
        ExitWindowsEx (EWX_SHUTDOWN), &HFFFF
    End Sub

    Private Sub cmdForceShutdown_Click()
        AdjustToken
        ExitWindowsEx (EWX_SHUTDOWN Or EWX_FORCE Or EWX_REBOOT), &HFFFF
    End Sub