WinXp关机程序

来源:互联网 发布:索泰显卡 知乎 编辑:程序博客网 时间:2024/06/05 21:11

'这个程序比较麻烦

变暗是采用以前的98模块,xp存在问题,按个窗口键或热键呼出QQ,变暗的效果就毁了。任务栏也会自己redraw
'所以处理了窗口更新,Hook处理了窗口键
'由于标签的热键是没效果的,只好窗体处理,但牺牲了部分

'窗体部分

Option Explicit

''''''''关机
Private Declare Function RtlAdjustPrivilege& Lib "ntdll" (ByVal Privilege&, ByVal Newvalue&, ByVal NewThread&, Oldvalue&)
Private Declare Function NtShutdownSystem& Lib "ntdll" (ByVal ShutdownAction&)

Private Const SE_SHUTDOWN_PRIVILEGE& = 19
Private Const SHUTDOWN& = 0

''''''''' Mouse

Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwndLock As Long) As Long

Private Type RECT

    Left As Long
    Top As Long
    Right As Long
    Bottom As Long

End Type

'这个函数能为窗口指定一个新位置和状态。它也可改变窗口在内部窗口列表中的位置。
'该函数与DeferWindowPos函数相似,只是它的作用是立即表现出来的(在vb里使用:针对vb窗体,如它们在win32下屏蔽或最小化,则需重设最顶部状态。
'如有必要,请用一个子类处理模块来重设最顶部状态

Private Declare Function SetWindowPos Lib "user32" (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, _
                          ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long

Private Const HWND_TOPMOST = -1     '将窗口置于列表顶部,并位于任何最顶部窗口的前面
Private Const HWND_NOTOPMOST = -2   '将窗口置于列表顶部,并位于任何最顶部窗口的后面
Private Const SWP_NOSIZE = &H1      '保持当前大小(cx和cy被忽略)
Private Const SWP_NOMOVE = &H2      '保持当前位置(cx和cy被忽略)

Private Declare Function SetCursorPos Lib "user32" (ByVal X As Long, ByVal Y As Long) As Long
Private Declare Function ClipCursor Lib "user32" (lpRect As Any) As Long
Private Declare Function DestroyCursor Lib "user32" (ByVal hCursor As Long) As Long
Private Declare Function GetWindowRect Lib "user32" (ByVal hWnd As Long, lpRect As RECT) As Long
Private Declare Function SetClassLong Lib "user32" Alias "SetClassLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function GetClassLong Lib "user32" Alias "GetClassLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)

Private Const GCL_HCURSOR = (-12)

Dim mhBaseCursor As Long
Dim mhAniCursor As Long

''''''''''''' 变黑
Private Declare Function GetDC Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hWnd As Long, ByVal hDC As Long) As Long
Private Declare Function CreatePatternBrush Lib "gdi32" (ByVal hBitmap As Long) As Long
Private Declare Function PatBlt Lib "gdi32" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal dwRop As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function CreateBitmap Lib "gdi32" (ByVal nWidth As Long, ByVal nHeight As Long, ByVal nPlanes As Long, ByVal nBitCount As Long, lpBits As Any) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long
Private Declare Function InvalidateRect Lib "user32" (ByVal hWnd As Long, ByVal lpRect As Long, ByVal bErase As Long) As Long

Private bybits(1 To 16) As Byte
Private hBitmap As Long, hBrush As Long
Private Declare Function GetDesktopWindow Lib "user32" () As Long

Private Sub Form_Activate()

    LockWindow

End Sub

Private Sub Form_Initialize()

    Picture1(1).Picture = Me.Picture '备份背景,因为启动时候会变黑

    Me.KeyPreview = True

End Sub

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)

    If Shift = vbAltMask And KeyCode = vbKeyL Then Image1_Click        '为了这里的热键,牺牲了标签控件的下拉线
    If Shift = vbAltMask And KeyCode = vbKeyU Then Image2_Click
    If Shift = vbAltMask And KeyCode = vbKeyR Then Image3_Click

    If KeyCode = vbKeyEscape Then Unload Me

End Sub

Private Sub Form_Paint()

    OnTop = True

End Sub

Private Sub Image1_Click()

    ExitWindow EWX_LOGOFF

End Sub

Private Sub Image2_Click()

    'RtlAdjustPrivilege SE_SHUTDOWN_PRIVILEGE, 1, 0, 0
    'NtShutdownSystem ShutDown

    ExitWindow WE_POWEROFF

End Sub

Private Sub Image3_Click()

    ExitWindow EWX_REBOOT

End Sub

Private Sub LockWindow()

    Dim ClassName As String
    Dim StartWindow As Long
    Dim ary
    Dim i As Long
    Dim rop As Long, res As Long
    Dim hdc5 As Long, width5 As Long, height5 As Long

    ary = Array(&H55, &H0, &HAA, &H0, &H55, &H0, &HAA, &H0, &H55, &H0, &HAA, &H0, &H55, &H0, &HAA, &H0)

    For i = 1 To 16

        bybits(i) = ary(i - 1)

    Next i

    hBitmap = CreateBitmap(8, 8, 1, 1, bybits(1))
    hBrush = CreatePatternBrush(hBitmap)

    Picture1(0).ForeColor = RGB(0, 0, 0)
    Picture1(0).BackColor = RGB(255, 255, 255)
    Picture1(0).ScaleMode = 3

    '如果只要让Picture1有效果将底下三行unMark取代 hdc5, width5, height5三个值

    'hdc5 = Picture1.hdc

    'width5 = Picture1.ScaleWidth

    'height5 = Picture1.ScaleHeight

    '底下三行设定整个萤幕都暗下来

    hdc5 = GetDC(0)

    width5 = Screen.Width / Screen.TwipsPerPixelX
    height5 = Screen.Height / Screen.TwipsPerPixelY

    rop = &HA000C9 '与原图做and运算

    Call SelectObject(hdc5, hBrush)

    res = PatBlt(hdc5, 0, 0, width5, height5, rop)

    Call DeleteObject(hBrush)

    '如果只暗picture1则底下这一行要mark起来

    res = ReleaseDC(0, hdc5)

    Me.Picture = Picture1(1).Picture

    Call SetCursorPos(425, 380) '设置鼠标坐标,参数由SpyTools提供
    LockWindowUpdate GetDesktopWindow '避免任务栏更新

    '钩子的安装与释放:
    '使用API函数SetWindowsHookEx()把一个应用程序定义的钩子子程安装到钩子链表中。SetWindowsHookEx函数总是在Hook链的开头安装Hook子程。
    '当指定类型的Hook监视的事件发生时,系统就调用与这个Hook关联的Hook链的开头的Hook子程。每一个Hook链中的Hook子程都决定是否把这个事件传递到下一个Hook子程。
    'Hook子程传递事件到下一个Hook子程需要调用CallNextHookEx函数。

    'HHOOK SetWindowsHookEx(
    '     int idHook,      // 钩子的类型,即它处理的消息类型
    '     HOOKPROC lpfn,   // 钩子子程的地址指针。如果dwThreadId参数为0
    '               // 或是一个由别的进程创建的线程的标识,
    '               // lpfn必须指向DLL中的钩子子程。
    '               // 除此以外,lpfn可以指向当前进程的一段钩子子程代码。
    '               // 钩子函数的入口地址,当钩子钩到任何消息后便调用这个函数。
    '     HINSTANCE hMod,  // 应用程序实例的句柄。标识包含lpfn所指的子程的
    'DLL?
    '               // 如果dwThreadId 标识当前进程创建的一个线程,
    '               // 而且子程代码位于当前进程,hMod必须为NULL。
    '               // 可以很简单的设定其为本应用程序的实例句柄。
    '     DWORD dwThreadId // 与安装的钩子子程相关联的线程的标识符。
    '               // 如果为0,钩子子程与所有的线程关联,即为全局钩子。
    '                 );
    '
    '  函数成功则返回钩子子程的句柄,失败返回NULL。
    '  以上所说的钩子子程与线程相关联是指在一钩子链表中发给该线程的消息同时发送给钩子子程,且被钩子子程先处理。

    '   idHook值为它处理的消息类型;lpfn值为钩子子程序的地址指针。如果dwThreadId参数为0或是一个由别的进程创建的线程的标识,
    '   lpfn必须指向DLL中的钩子子程。除此以外,lpfn可以指向当前进程的一段钩子子程代码。hMod值为应用程序的句柄,
    '   标识包含lpfn所指的子程的DLL。如果dwThreadId标识当前进程创建的一个线程,而且子程代码位于当前进程,hMod必须为0。
    '   dwThreadId值为与安装的钩子子程相关联的线程的标识符,如果为0,钩子子程与所有的线程关联。钩子安装成功则返回钩子子程的句柄,失败返回0。

    '当在 Visual Basic 开发环境中使用工程进行工作时,App.hInstance 属性返回 Visual Basic 实例的实例句柄。

    hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf LowLevelKeyboardProc, App.hInstance, 0) '加载钩子

End Sub

Private Sub Timer2_Timer() '即时锁定窗体,避免Ctrl+Alt+Del

    Dim lResult As Long, RT_FormArea As RECT

    mhBaseCursor = GetClassLong((Me.hWnd), GCL_HCURSOR)

    lResult = SetClassLong((Me.hWnd), GCL_HCURSOR, mhAniCursor)
    lResult = GetWindowRect((Me.hWnd), RT_FormArea)
    lResult = ClipCursor(RT_FormArea)

End Sub

Private Sub XPButton1_Click()

    Dim aa As Long

    '如果只暗picture1则底下这一行要unMark起来

    'Picture1.Refresh

    '如果只暗picture1则底下这一行要mark起来

    aa = InvalidateRect(0, 0, 1)

    Unload Me

End Sub

Property Let OnTop(Setting As Boolean)          '总在最前

    SetWindowPos Me.hWnd, IIf(Setting, HWND_TOPMOST, HWND_NOTOPMOST), 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE

End Property

Private Sub UnlockWindow()

    Dim pOld As Boolean
    Dim lResult As Long
    Dim RT_ScreenArea As RECT

    With RT_ScreenArea

        .Top = 0
        .Left = 0
        .Bottom = Screen.Height / Screen.TwipsPerPixelX
        .Right = Screen.Width / Screen.TwipsPerPixelY

    End With

    lResult = ClipCursor(RT_ScreenArea)
    lResult = SetClassLong((Me.hWnd), GCL_HCURSOR, mhBaseCursor)  '解除鼠标范围限制
    lResult = DestroyCursor(mhAniCursor)

    InvalidateRect 0, 0, 1

    If hhkLowLevelKybd <> 0 Then UnhookWindowsHookEx hhkLowLevelKybd  '卸载钩子
    LockWindowUpdate 0      '释放桌面更新

End Sub

Private Sub Form_Unload(Cancel As Integer)

    UnlockWindow
    Set frmMian = Nothing

End Sub

 #####################################################################

'hook

Option Explicit

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal nCode As Long, ByVal wParam As Long, lParam As Any) As Long

Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long

Private Const HC_ACTION = 0
Private Const WM_KEYDOWN = &H100
Private Const WM_KEYUP = &H101
Private Const WM_SYSKEYDOWN = &H104
Private Const WM_SYSKEYUP = &H105
Private Const LLKHF_ALTDOWN = &H20

Public Const WH_KEYBOARD_LL = 13

Private Type KBDLLHOOKSTRUCT  '这个是低级键盘钩子的索引值

    vkCode As Long      '虚拟按键码(1--254)
    scanCode As Long    '硬件按键扫描码
    flags As Long       '键按下:128 抬起:0
    time As Long        '消息时间戳间
    dwExtraInfo As Long '额外信息

End Type

Public Enum VirtualKey

    VK_LBUTTON = &H1
    VK_RBUTTON = &H2
    VK_CTRLBREAK = &H3
    VK_MBUTTON = &H4
    VK_BACKSPACE = &H8
    VK_TAB = &H9
    VK_ENTER = &HD
    VK_SHIFT = &H10
    VK_CONTROL = &H11
    VK_ALT = &H12
    VK_PAUSE = &H13
    VK_CAPSLOCK = &H14
    VK_ESCAPE = &H1B
    VK_SPACE = &H20
    VK_PAGEUP = &H21
    VK_PAGEDOWN = &H22
    VK_END = &H23
    VK_HOME = &H24
    VK_LEFT = &H25
    VK_UP = &H26
    VK_RIGHT = &H27
    VK_DOWN = &H28
    VK_PRINTSCREEN = &H2C
    VK_INSERT = &H2D
    VK_DELETE = &H2E
    VK_0 = &H30
    VK_1 = &H31
    VK_2 = &H32
    VK_3 = &H33
    VK_4 = &H34
    VK_5 = &H35
    VK_6 = &H36
    VK_7 = &H37
    VK_8 = &H38
    VK_9 = &H39
    VK_A = &H41
    VK_B = &H42
    VK_C = &H43
    VK_D = &H44
    VK_E = &H45
    VK_F = &H46
    VK_G = &H47
    VK_H = &H48
    VK_I = &H49
    VK_J = &H4A
    VK_K = &H4B
    VK_L = &H4C
    VK_M = &H4D
    vk_n = &H4E
    VK_O = &H4F
    VK_P = &H50
    VK_Q = &H51
    VK_R = &H52
    VK_S = &H53
    VK_T = &H54
    VK_U = &H55
    VK_V = &H56
    VK_W = &H57
    VK_X = &H58
    VK_Y = &H59
    VK_Z = &H5A
    VK_LWINDOWS = &H5B
    VK_RWINDOWS = &H5C
    VK_APPSPOPUP = &H5D
    VK_NUMPAD_0 = &H60
    VK_NUMPAD_1 = &H61
    VK_NUMPAD_2 = &H62
    VK_NUMPAD_3 = &H63
    VK_NUMPAD_4 = &H64
    VK_NUMPAD_5 = &H65
    VK_NUMPAD_6 = &H66
    VK_NUMPAD_7 = &H67
    VK_NUMPAD_8 = &H68
    VK_NUMPAD_9 = &H69
    VK_NUMPAD_MULTIPLY = &H6A
    VK_NUMPAD_ADD = &H6B
    VK_NUMPAD_PLUS = &H6B
    VK_NUMPAD_SUBTRACT = &H6D
    VK_NUMPAD_MINUS = &H6D
    VK_NUMPAD_MOINS = &H6D
    VK_NUMPAD_DECIMAL = &H6E
    VK_NUMPAD_POINT = &H6E
    VK_NUMPAD_DIVIDE = &H6F
    VK_F1 = &H70
    VK_F2 = &H71
    VK_F3 = &H72
    VK_F4 = &H73
    VK_F5 = &H74
    VK_F6 = &H75
    VK_F7 = &H76
    VK_F8 = &H77
    VK_F9 = &H78
    VK_F10 = &H79
    VK_F11 = &H7A
    VK_F12 = &H7B
    VK_NUMLOCK = &H90
    VK_SCROLL = &H91
    VK_LSHIFT = &HA0
    VK_RSHIFT = &HA1
    VK_LCONTROL = &HA2
    VK_RCONTROL = &HA3
    VK_LALT = &HA4
    VK_RALT = &HA5
    VK_POINTVIRGULE = &HBA
    VK_ADD = &HBB
    VK_PLUS = &HBB
    VK_EQUAL = &HBB
    VK_VIRGULE = &HBC
    VK_SUBTRACT = &HBD
    VK_MINUS = &HBD
    VK_MOINS = &HBD
    VK_UNDERLINE = &HBD
    VK_POINT = &HBE
    VK_SLASH = &HBF
    VK_TILDE = &HC0
    VK_LEFTBRACKET = &HDB
    VK_BACKSLASH = &HDC
    VK_RIGHTBRACKET = &HDD
    VK_QUOTE = &HDE
    VK_APOSTROPHE = &HDE

End Enum

Dim KBDLLHOOKSTRUCT As KBDLLHOOKSTRUCT

Public hhkLowLevelKybd As Long '安装的钩子句柄

Public Function LowLevelKeyboardProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

    Dim fEatKeystroke As Boolean

    If (nCode = HC_ACTION) Then 'nCode值为HC_ACTION时表示WParam和LParam参数包涵了按键消息

        '按下键会产生WM_KEYDOWN或WM_SYSKEYDOWN消息,然后会被放置在当前键盘聚焦的窗口所在线程的消息队列中。同样释放按键也会产生消息,这个消息将会是WM_KEYUP或者WM_SYSKEYUP。
        '系统中系统按键与非系统按键是截然不同的,系统按键产生系统按键消息:WM_SYSKEYDOWN、WM_SYSKEYUP,而非系统按键产生非系统按键消息:WM_KEYDOWN与WM_KEYUP。

        If wParam = WM_KEYDOWN Or wParam = WM_SYSKEYDOWN Or wParam = WM_KEYUP Or wParam = WM_SYSKEYUP Then

            'CopyMemory的历史非常特殊,它的真名并非叫CopyMemory。看看CopyMemory的声明,它是定义在Kernel32.dll中的RtlMoveMemory这个API,
            '32位C函数库中的memcpy就是这个API的封装,如MSDN文档中所言,它的功能是将从Source指针所指处开始的长度为Length的内存拷贝到Destination所指的内存处。
            '它不会管我们的程序有没有读写该内存所应有的权限,一但它想读写被系统所保护的内存时,

            'VOID CopyMemory(
            '  PVOID Destination,  // pointer to address of copy destination
            '  CONST VOID *Source, // pointer to address of block to copy
            '  DWORD Length        // size, in bytes, of block to copy
            ');

            'Parameters
            'Destination
            'Pointer to the starting address of the copied block's destination.
            'Source
            'Pointer to the starting address of the block of memory to copy.
            'Length
            'Specifies the size, in bytes, of the block of memory to copy.

            CopyMemory KBDLLHOOKSTRUCT, ByVal lParam, Len(KBDLLHOOKSTRUCT)

            fEatKeystroke = _
                            (KBDLLHOOKSTRUCT.vkCode = VK_LWINDOWS) _
                            Or (KBDLLHOOKSTRUCT.vkCode = VK_RWINDOWS) Or (KBDLLHOOKSTRUCT.vkCode = VK_APPSPOPUP)
            'TAB+ALT
            'Esc+ALT
            'Alt+Any(Alt+F4)
            'Esc+Ctrl
            '左右Win 和徽标键

        End If

    End If

    If fEatKeystroke Then

        LowLevelKeyboardProc = 1  '吃掉消息

    Else

        LowLevelKeyboardProc = CallNextHookEx(hhkLowLevelKybd, nCode, wParam, ByVal lParam) '如果消息要被处理,则传0或安装的钩子句柄

    End If

End Function

######################################################################

'shutdown

Option Explicit

'退出windows,并用特定的选项重新启动
Private Declare Function ExitWindowsEx Lib "user32" (ByVal uFlags As Long, ByVal dwReserved As Long) As Long

Private Const EWX_FORCE = 4          '强迫中止没有响应的进程
Private Const EWX_FORCEIFHUNG = 16   '如果应用程序已挂起,强制关闭
Public Const EWX_LOGOFF = 0          '中止进程,然后注销
Public Const EWX_REBOOT = 2          '重新引导系统
Public Const EWX_SHUTDOWN = 1        '关闭系统
Public Const WE_POWEROFF = 8         '关掉系统ATX电源,未公开的参数
Public Const WE_Suspend = 1          '自定义休眠常量

'Hibernate带0是休眠、带1是暂停,ForceCritical带0会广播给所有的程式说要执行暂停或休眠、带1则强制执行,DisableWakeEvent带0。
Private Declare Function SetSuspendState Lib "Powrprof" (ByVal Hibernate As Long, ByVal ForceCritical As Long, ByVal DisableWakeEvent As Long) As Long

'GetCurrentProcess获取当前进程的一个伪句柄
'返回值Long,当前进程的伪句柄
'注解只要当前进程需要一个进程句柄,就可以使用这个伪句柄。该句柄可以复制,但不可继承。不必调用CloseHandle函数来关闭这个句柄
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long

'TOKEN_ADJUST_DEFAULT 当呼叫SetTokenInformtion (简短地讨论)改变权限的特色时要求,例如预设的拥有者、主要的群组或是预设的DACL。
'TOKEN_ADJUST_GROUPS 在呼叫AdjustTokenGroups中要求?
'TOKEN_ADJUST_PRIVILEGES 在呼叫AdjustTokenPrivileges中要求?
'TOKEN_ADJUST_SESSIONID 要求调整权限的工作阶段ID以及SE_TCB_NAME权限?
'TOKEN_ASSIGN_PRIMARY 在呼叫CreateProcessAsUser中使用权限时要求?
'TOKEN_DUPLICATE 要求复製权限?
'TOKEN_EXECUTE 等於STANDARD_RIGHTS_EXECUTE。
'TOKEN_IMPERSONATE 要求与ImpersonateLoggedOnUser一起使用这个权限?
'TOKEN_QUERY 要求读取任何的权限资讯,除了使用GetTokenInformation读取它的来源外。
'TOKEN_QUERY_SOURCE 要求使用GetTokenInformation读取权限的来源?
'TOKEN_READ 结合STANDARD_RIGHTS_READ及TOKEN_QUERY。
'TOKEN_WRITE 结合STANDARD_RIGHTS_WRITE、TOKEN_ADJUST_ PRIVILEGES、TOKEN_ADJUST_GROUPS及TOKEN_ADJUST_DEFAULT。
'TOKEN_ALL_ACCESS 完整的存取权限,结合了所有的权利。

'ProcessHandle是要修改访问权限的进程句柄
'DesiredAccess参数指定你要进行的操作类型,如要修改令牌我们要指定第二个参数为TOKEN_ADJUST_PRIVILEGES(其它一些参数可参考Platform SDK)。
'TokenHandle就是返回的访问令牌指针
'通过这个函数我们就可以得到当前进程的访问令牌的句柄(指定函数的第一个参数为GetCurrentProcess()就可以了)
Private Declare Function OpenProcessToken Lib "advapi32" _
                          (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long

'lpSystemName是系统的名称,如果是本地系统只要指明为NULL就可以了
'lpName指明了权限的名称,如“SeDebugPrivilege”
'lpLuid返回LUID的指针
'查询进程的权限
Private Declare Function LookupPrivilegeValue Lib "advapi32" Alias _
                          "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long

'AdjustTokenPrivileges修改访问令牌
'TokenHandle访问令牌的句柄
'DisableAllPrivileges决定是进行权限修改还是除能(Disable)所有权限
'NewState指明要修改的权限,是一个指向TOKEN_PRIVILEGES结构的指针,该结构包含一个数组,数据组的每个项指明了权限的类型和要进行的操作;
'BufferLength是结构PreviousState的长度
'PreviousState是一个指向TOKEN_PRIVILEGES结构的指针,存放修改前的访问权限的信息,可空
'ReturnLength为实际PreviousState结构返回的大小
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 Type LUID

    UsedPart As Long
    IgnoredForNowHigh32BitPart As Long

End Type

Private Type TOKEN_PRIVILEGES

    PrivilegeCount As Long      '数组原素的个数
    TheLuid As LUID             '一个LUID_AND_ATTRIBUTES类型的数组
    Attributes As Long

End Type

Private Const TOKEN_ADJUST_PRIVILEGES = &H20  '能修改令牌
Private Const TOKEN_QUERY = &H8               '要求读取任何的权限资讯,除了使用GetTokenInformation读取它的来源外。
Private Const SE_PRIVILEGE_ENABLED = &H2      '要使能一个权限就指定Attributes为SE_PRIVILEGE_ENABLED。

'快速关机

'RtlAdjustPrivilege&获取关机权限
Private Declare Function RtlAdjustPrivilege& Lib "ntdll" (ByVal Privilege&, ByVal Newvalue&, ByVal NewThread&, Oldvalue&)
'NtShutdownSystem& 关机操作
Private Declare Function NtShutdownSystem& Lib "ntdll" (ByVal ShutdownAction&)

Private Const SE_SHUTDOWN_PRIVILEGE& = 19 '关机特权
Private Const SHUTDOWN& = 0  '关机
Private Const RESTART& = 1   '重启动
Private Const POWEROFF& = 2  '关闭电源

Public Function ExitWindow(lngExtFlag As Long)

    AdjustToken                      '提升权限

    Select Case lngExtFlag           '选择关闭Windows

        Case EWX_LOGOFF              '注销

        ExitWindowsEx (EWX_LOGOFF Or EWX_FORCE), &HFFFF

        Case EWX_REBOOT              '重启

        ExitWindowsEx (EWX_REBOOT Or EWX_FORCE), &HFFFF

        Case WE_POWEROFF             '关机

        ExitWindowsEx (WE_POWEROFF Or EWX_FORCE), &HFFFF

        Case WE_Suspend

        SetSuspendState 0, 0, 0      '挂起,休眠

    End Select

End Function

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 '得到进程的令牌句柄
    LookupPrivilegeValue "", "SeShutdownPrivilege", tmpLuid   '  查询进程的权限

    tkp.PrivilegeCount = 1    '设置权限
    tkp.TheLuid = tmpLuid
    tkp.Attributes = SE_PRIVILEGE_ENABLED

    '修改访问令牌,使进程获得关机权限.
    AdjustTokenPrivileges hdlTokenHandle, False, tkp, Len(tkpNewButIgnored), tkpNewButIgnored, lBufferNeeded

End Sub

Public Sub TurboShutdown(OperateFlag As Long)

    RtlAdjustPrivilege SE_SHUTDOWN_PRIVILEGE, 1, 0, 0

    Select Case OperateFlag

        Case 1

        NtShutdownSystem SHUTDOWN   '关机

        Case 2
        
        NtShutdownSystem RESTART    '重启动

        Case 3

        NtShutdownSystem POWEROFF   '关机

    End Select

End Sub
原创粉丝点击