⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 closent.bas

📁 此文档为VB公共模块
💻 BAS
字号:
Attribute VB_Name = "CloseNt"
Option Explicit
'*************************关闭WINNT系统**********************
'*  作者:谢建军                                            *
'*  创建日期:2002年11月18日  20:47                        *
'************************************************************
'*  1.CloseWinNt(ByVal ClsMth As ClsNTMthd)                 *
'************************************************************
'Get local computer's name
Private Declare Function GetComputerName Lib "kernel32" Alias "GetComputerNameA" (ByVal lpBuffer As String, nSize As Long) As Long
Public Enum ClsNTMthd
  NTReboot = 1#
  NTPowerOff = 0#
  NTCancelClose = 2#
End Enum

Private eeSSDErrorBase As Integer
Private Type OSVERSIONINFO
    dwOSVersionInfoSize As Long
    dwMajorVersion As Long
    dwMinorVersion As Long
    dwBuildNumber As Long
    dwPlatformId As Long
    szCSDVersion As String * 128 ' Maintenance string for PSS usage
End Type
Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (lpVersionInformation As OSVERSIONINFO) As Long
Private Const VER_PLATFORM_WIN32_NT = 2
Private Const VER_PLATFORM_WIN32_WINDOWS = 1
Private Const VER_PLATFORM_WIN32s = 0 '报告API错误:
Private Const FORMAT_MESSAGE_ALLOCATE_BUFFER = &H100
Private Const FORMAT_MESSAGE_ARGUMENT_ARRAY = &H2000
Private Const FORMAT_MESSAGE_FROM_HMODULE = &H800
Private Const FORMAT_MESSAGE_FROM_STRING = &H400
Private Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
Private Const FORMAT_MESSAGE_IGNORE_INSERTS = &H200
Private Const FORMAT_MESSAGE_MAX_WIDTH_MASK = &HFF
Private Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" (ByVal dwFlags As Long, lpSource As Any, ByVal dwMessageId As Long, ByVal dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Long) As Long
' ===================================================================== NT Only
Private Type LARGE_INTEGER
    LowPart As Long
    HighPart As Long
End Type

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(0 To 0) As LUID_AND_ATTRIBUTES
End Type
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function GetTokenInformation Lib "advapi32.dll" (ByVal TokenHandle As Long, TokenInformationClass As Integer, TokenInformation As Any, ByVal TokenInformationLength As Long, ReturnLength As Long) 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 LookupPrivilegeValue Lib "advapi32.dll" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long
Private Const SE_SHUTDOWN_NAME = "SeShutdownPrivilege"
Private Const SE_PRIVILEGE_ENABLED = &H2
Private Const READ_CONTROL = &H20000
Private Const STANDARD_RIGHTS_ALL = &H1F0000
Private Const STANDARD_RIGHTS_EXECUTE = (READ_CONTROL)
Private Const STANDARD_RIGHTS_READ = (READ_CONTROL)
Private Const STANDARD_RIGHTS_REQUIRED = &HF0000
Private Const STANDARD_RIGHTS_WRITE = (READ_CONTROL)
Private Const TOKEN_ASSIGN_PRIMARY = &H1
Private Const TOKEN_DUPLICATE = (&H2)
Private Const TOKEN_IMPERSONATE = (&H4)
Private Const TOKEN_QUERY = (&H8)
Private Const TOKEN_QUERY_SOURCE = (&H10)
Private Const TOKEN_ADJUST_PRIVILEGES = (&H20)
Private Const TOKEN_ADJUST_GROUPS = (&H40)
Private Const TOKEN_ADJUST_DEFAULT = (&H80)
Private Const TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or _
                        TOKEN_ASSIGN_PRIMARY Or _
                        TOKEN_DUPLICATE Or _
                        TOKEN_IMPERSONATE Or _
                        TOKEN_QUERY Or _
                        TOKEN_QUERY_SOURCE Or _
                        TOKEN_ADJUST_PRIVILEGES Or _
                        TOKEN_ADJUST_GROUPS Or _
                        TOKEN_ADJUST_DEFAULT)
Private Const TOKEN_READ = (STANDARD_RIGHTS_READ Or TOKEN_QUERY)
Private Const TOKEN_WRITE = (STANDARD_RIGHTS_WRITE Or _
                        TOKEN_ADJUST_PRIVILEGES Or _
                        TOKEN_ADJUST_GROUPS Or _
                        TOKEN_ADJUST_DEFAULT)
Private Const TOKEN_EXECUTE = (STANDARD_RIGHTS_EXECUTE)
Private Const TokenDefaultDacl = 6
Private Const TokenGroups = 2
Private Const TokenImpersonationLevel = 9
Private Const TokenOwner = 4
Private Const TokenPrimaryGroup = 5
Private Const TokenPrivileges = 3
Private Const TokenSource = 7
Private Const TokenStatistics = 10
Private Const TokenType = 8
Private Const TokenUser = 1
Private Declare Function InitiateSystemShutdown Lib "advapi32.dll" Alias "InitiateSystemShutdownA" (ByVal lpMachineName As String, ByVal lpMessage As String, ByVal dwTimeout As Long, ByVal bForceAppsClosed As Long, ByVal bRebootAfterShutdown As Long) As Long
Private Declare Function AbortSystemShutdown Lib "advapi32.dll" Alias "AbortSystemShutdownA" (ByVal lpMachineName As String) As Long
' ================================================================
Public Function WinError(ByVal lLastDLLError As Long) As String

Dim sBuff As String
Dim lCount As Long
    '返回与LastDLLError关联的错误消息:
    sBuff = String$(256, 0)
    lCount = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM Or FORMAT_MESSAGE_IGNORE_INSERTS, _
                           0, lLastDLLError, 0&, sBuff, Len(sBuff), ByVal 0)
    If lCount Then
      WinError = Left$(sBuff, lCount)
    End If
End Function
Public Function IsNT() As Boolean
  
  Static bOnce As Boolean
  Static bValue As Boolean    '返回系统是否为NT:
    If Not (bOnce) Then
      Dim tVI As OSVERSIONINFO
      tVI.dwOSVersionInfoSize = Len(tVI)
      If (GetVersionEx(tVI) <> 0) Then
        bValue = (tVI.dwPlatformId = VER_PLATFORM_WIN32_NT)
        bOnce = True
      End If
    End If
    IsNT = bValue
End Function
Private Function NTEnableShutDown(ByRef sMsg As String) As Boolean
Dim tLUID As LUID
Dim hProcess As Long
Dim hToken As Long
Dim tTP As TOKEN_PRIVILEGES, tTPOld As TOKEN_PRIVILEGES
Dim lTpOld As Long
Dim lR As Long
'在NT下,我们必须给试图关闭系统的进程SE_SHUTDOWN_NAME特权,
'否则,所有企图关闭系统的调用都会无效!
'寻找Shoudown特权令牌的LUID:

lR = LookupPrivilegeValue(vbNullString, SE_SHUTDOWN_NAME, tLUID)
    '如果我们找到了
If (lR <> 0) Then    '取得当前进程的句柄:
  hProcess = GetCurrentProcess()
  If (hProcess <> 0) Then    '打开令牌来Adjust和Query(用户可能没有权限)
    lR = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, hToken)
    If (lR <> 0) Then  '好,我们现在可以调整Shutdown特权了:
      With tTP
        .PrivilegeCount = 1
        With .Privileges(0)
          .Attributes = SE_PRIVILEGE_ENABLED
          .pLuid.HighPart = tLUID.HighPart
          .pLuid.LowPart = tLUID.LowPart
        End With
      End With   '现在允许这个进程关闭系统:
      lR = AdjustTokenPrivileges(hToken, 0, tTP, Len(tTP), tTPOld, lTpOld)
      If (lR <> 0) Then
        NTEnableShutDown = True
      Else
        Err.Raise eeSSDErrorBase + 6, App.EXEName & ".mShutDown", "不能shutdown:你没有关闭本系统的权限。[" & WinError(Err.LastDllError) & "]"
      End If
      CloseHandle hToken '记得用完后关闭这个句柄
    Else
      Err.Raise eeSSDErrorBase + 6, App.EXEName & ".mShutDown", "不能shutdown:你没有关闭本系统的权限。[" & WinError(Err.LastDllError) & "]"
    End If
  Else
    Err.Raise eeSSDErrorBase + 5, App.EXEName & ".mShutDown", "不能shutdown:不能终止当前进程。[" & WinError(Err.LastDllError) & "]"
  End If
Else
  Err.Raise eeSSDErrorBase + 4, App.EXEName & ".mShutDown", "不能shutdown:找不到SE_SHUTDOWN_NAME特权值。[" & WinError(Err.LastDllError) & "]"
End If
End Function
'Public Function NTForceTimedShutdown( _
'    Optional ByVal lTimeOut As Long = -1, _
'    Optional ByVal sMsg As String = "", _
'    Optional ByVal sMachineNetworkName As String = vbNullString, _
'    Optional ByVal bForceAppsToClose As Boolean = False, _
'    Optional ByVal bReboot As Boolean = False _
'    ) As Boolean
Private Function NTForceTimedShutdown( _
  ByVal LsMachineName As String, _
  ByVal LsMessage As String, _
  ByVal LsTimeOut As Long, _
  ByVal LsForceAppToClose As Long, _
  ByVal LsReboot As Long)
  
  Dim lR As Long
    If IsNT Then    '如果我们在NT下,确信我们已经给了这个进程关闭系统的特权:
    If Not (NTEnableShutDown(LsMessage)) Then
        MsgBox "你没有关机权限!"
        Exit Function
    End If        '这是定时关闭系统的代码:
    lR = InitiateSystemShutdown(LsMachineName, LsMessage, LsTimeOut, LsForceAppToClose, LsReboot)
    If (lR = 0) Then
      Err.Raise eeSSDErrorBase + 2, App.EXEName & ".mShutDown", "InitiateSystemShutdown failed: " & WinError(Err.LastDllError)
    End If
    Else
      Err.Raise eeSSDErrorBase + 1, App.EXEName & ".mShutDown", "函数仅在Windows NT下有效。"
    End If
End Function
Private Function NTAbortTimedShutdown(Optional ByVal sMachineNetworkName As String = vbNullString)
  AbortSystemShutdown sMachineNetworkName
End Function

'************
'Get local computer's name.
'************
Private Function GetCptName() As String
  Dim T_Str As String * 255
  Dim T_Len As Integer
  T_Str = Space(255)
  T_Len = GetComputerName(T_Str, Len(T_Str) - 1)
  GetCptName = Left(T_Str, InStr(T_Str, Chr(0)) - 1)
End Function

'Close Nt
Public Sub CloseWinNt(ByVal ClsMth As ClsNTMthd, Optional ByVal cMsg$, Optional ByVal cWaitTime As Long)
    If cWaitTime < 0 Then
      cWaitTime = 0
    End If
    If cMsg = "" Then
      cMsg = "计算机将在" & cWaitTime & "内关闭,请保存你所做的所有更改!"
    End If
    Select Case ClsMth
        Case NTPowerOff, NTReboot
            NTForceTimedShutdown GetCptName, cMsg, cWaitTime, 1, ClsMth
        Case NTCancelClose
            NTAbortTimedShutdown GetCptName
        Case Else
    End Select
End Sub

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -