在 Visual Basic 6 中使用 GetTokenInformation 确定用户是否为管理员

发布于 2024-08-13 06:51:34 字数 1589 浏览 6 评论 0原文

我使用 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)

第一次调用是获取缓冲区长度,然后再次调用它以获取令牌信息。

无论如何,当运行应用程序的帐户连接到域时,应用程序会突然崩溃。显然,大小

Groups(500) As SID.AND.ATTRIBUTES

不够,导致缓冲区溢出。我不知道为什么会这样(MSDN 说我应该提供一个 ANYSIZE_ARRAY 或 1)。将组的大小增加到 1000 可解决此问题。

作为快速修复,由于我不知道如何获得适当大小的组,因此我计划仅 ReDim 组,直到调用成功。

这是我的问题:

  1. 我有一个 On Error 子句,但是当发生缓冲区溢出时,On Error 无法捕获它,我的应用程序突然崩溃。这是为什么?

  2. 给出下面的代码

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 时,GetTokenInformation 调用没有失败() 并将其重新调整为 1000,它失败了吗?

I am using GetTokenInformation as a part of the code that determines if the current thread is running as an Administrator.

Anyway, I have a structure for TOKEN INFORMATION that looks like this:

Private Type TOKEN_GROUPS
   GroupCount As Long
   Groups(500) As SID_AND_ATTRIBUTES
End Type

Then, I invoke GetTokenInformation like so:

res = GetTokenInformation(<Process Handle>, 2, <TOKEN_GROUPS>, _
                            <Token Info Length>, <Buffer Length)

The first invocation is to get the Buffer Length, then I invoke it again to get the token information.

Anyway, the application will suddenly crash when the account that run the application is connected to a domain. Apparently, the size of the,

Groups(500) As SID.AND.ATTRIBUTES

is not enough and is causing a buffer overrun. I don't know why that is (MSDN says that I should provide an ANYSIZE_ARRAY or 1). Increasing the size of the Groups to 1000 fixes the problem.

As a quick fix and since I don't have an idea on how to get the appropriate size of Groups, I am planning to just ReDim the Groups until the call succeeds.

Here's my question:

  1. I have an On Error clause, but when the buffer overrun occurs, the On Error can't catch it and my app suddenly crashes. Why is that?

  2. Given the code below

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)

Why is that when I declared Groups as 1000, the GetTokenInformation call is not failing but when I declared an "empty" Groups() and ReDim'd it to 1000, it is failing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笔落惊风雨 2024-08-20 06:51:34

如果您想对使用动态大小的数组,您将需要“自定义 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

If you want to use dynamicly sized array for Groups you'll need "custom API call marshaling" code. Basicly couple of CopyMemory's and an array resize

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
哭泣的笑容 2024-08-20 06:51:34

还有另一个问题这里似乎已经解决了 GetTokenInformation 调用。
从已接受的答案中复制:

Call GetTokenInformation(hToken, 1, ByVal 0, 0, lNeeded)
ReDim baBuffer(0 To lNeeded)
...

There is another question here that seems to have solved the GetTokenInformation call.
Copied from the accepted answer:

Call GetTokenInformation(hToken, 1, ByVal 0, 0, lNeeded)
ReDim baBuffer(0 To lNeeded)
...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文