我使用 GetTokenInformation
作为确定当前线程是否以管理员身份运行的代码的一部分。
无论如何,我有一个 token 信息结构,如下所示:
Private Type TOKEN_GROUPS
GroupCount As Long
Groups(500) As SID_AND_ATTRIBUTES
End Type
然后,我像这样调用
GetTokenInformation
:res = GetTokenInformation(<Process Handle>, 2, <TOKEN_GROUPS>, _
<Token Info Length>, <Buffer Length)
第一次调用是获取缓冲区长度,然后我再次调用它以获取 token 信息。
无论如何,当运行应用程序的帐户连接到域时,应用程序会突然崩溃。显然,大小,
Groups(500) As SID.AND.ATTRIBUTES
不够,导致缓冲区溢出。我不知道为什么会这样(MSDN 说我应该提供
ANYSIZE_ARRAY
或 1)。将组的大小增加到 1000 可以解决此问题。作为一个快速解决方案,并且由于我不知道如何获得适当大小的组,我计划在调用成功之前重新调整组的大小。
这是我的问题:
On Error
子句,但是当发生缓冲区溢出时,On Error
无法捕获它,我的应用程序突然崩溃。这是为什么? Private Type TOKEN_GROUPS
GroupCount As Long
Groups() As SID_AND_ATTRIBUTES 'FAILING
'Groups(1000) As SID_AND_ATTRIBUTES DOES NOT FAIL
End Type
Dim X as TOKEN_GROUPS
ReDim Preserve X.Groups(1000) As SID_AND_ATTRIBUTES 'FAILING
res = GetTokenInformation(<Process Handle>, 2, <TOKEN_GROUPS>, <Token Info Length>, <Buffer Length)
res = GetTokenInformation(<Process Handle>, 2, <TOKEN_GROUPS>, <Token Info Length>, <Buffer Length)
为什么当我将 Groups 声明为 1000 时,
GetTokenInformation
调用没有失败,但是当我声明一个“空”Groups()
并将其重新调整为 1000 时,它却失败了? 最佳答案
如果要为 Groups
使用动态大小的数组,则需要“自定义 API 调用编码(marshal)”代码。基本上是一对 CopyMemory 和一个数组调整大小
Option Explicit
'--- for OpenProcessToken
Private Const TOKEN_READ As Long = &H20008
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pTo As Any, uFrom As Any, ByVal lSize As Long)
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) 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 GetTokenInformation Lib "advapi32.dll" (ByVal TokenHandle As Long, ByVal TokenInformationClass As Long, TokenInformation As Any, ByVal TokenInformationLength As Long, ReturnLength As Long) As Long
Private Type SID_AND_ATTRIBUTES
Sid As Long
Attributes As Long
End Type
Private Type VB_TOKEN_GROUPS
GroupCount As Long
Groups() As SID_AND_ATTRIBUTES
End Type
Private Sub Command1_Click()
Dim hProcessID As Long
Dim hToken As Long
Dim lNeeded As Long
Dim baBuffer() As Byte
Dim uGroups As VB_TOKEN_GROUPS
hProcessID = GetCurrentProcess()
If hProcessID <> 0 Then
If OpenProcessToken(hProcessID, TOKEN_READ, hToken) = 1 Then
Call GetTokenInformation(hToken, 2, ByVal 0, 0, lNeeded)
ReDim baBuffer(0 To lNeeded)
'--- enum TokenInformationClass { TokenUser = 1, TokenGroups = 2, ... }
If GetTokenInformation(hToken, 2, baBuffer(0), UBound(baBuffer), lNeeded) = 1 Then
Call CopyMemory(uGroups.GroupCount, baBuffer(0), 4)
ReDim uGroups.Groups(0 To uGroups.GroupCount - 1)
Call CopyMemory(uGroups.Groups(0), baBuffer(4), uGroups.GroupCount * Len(uGroups.Groups(0)))
End If
Call CloseHandle(hToken)
End If
Call CloseHandle(hProcessID)
End If
End Sub
关于winapi - 在 Visual Basic 6 中使用 GetTokenInformation 确定用户是否为管理员,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1847226/