我使用GetTokenInformation作为代码的一部分,确定当前线程是否以管理员身份运行。
无论如何,我有一个TOKEN INFORMATION的结构,如下所示:
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)
第一次调用是获取缓冲区长度,然后再次调用它以获取令牌信息。
无论如何,当运行应用程序的帐户连接到域时,应用程序将突然崩溃。显然,组(500)As SID.AND.ATTRIBUTES的大小是不够的,并导致缓冲区溢出。我不知道为什么会这样(MSDN说我应该提供一个ANYSIZE_ARRAY或1)。将组的大小增加到1000可以解决问题。
作为一个快速修复,由于我不知道如何获得适当大小的群组,我计划在调用成功之前重新调整群组。
这是我的问题:
我有一个On Error子句,但是当缓冲区溢出发生时,On Error无法捕获它,我的应用程序突然崩溃。那是为什么?
鉴于以下代码
私人类型TOKEN_GROUPS GroupCount As Long Groups()作为SID_AND_ATTRIBUTES'失败 '组(1000)因为SID_AND_ATTRIBUTES没有失败 结束类型
Dim X为TOKEN_GROUPS ReDim保留X.Groups(1000)作为SID_AND_ATTRIBUTES'失败
res = GetTokenInformation(,2 ,,,
res = GetTokenInformation(,2 ,,,
为什么当我将Groups声明为1000时,GetTokenInformation调用没有失败但是当我声明一个“空”的Groups()并将它重新调整为1000时,它失败了?
谢谢!
答案 0 :(得分:2)
如果要为Groups
使用动态大小的数组,则需要“自定义API调用封送”代码。基本上将一对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
答案 1 :(得分:1)
还有另一个问题here似乎解决了GetTokenInformation调用问题。 从接受的答案复制:
Call GetTokenInformation(hToken, 1, ByVal 0, 0, lNeeded) ReDim baBuffer(0 To lNeeded) ...