Best way to get user permissions from VB6

Posted on 2009-12-23
Last Modified: 2012-05-08

Hello, I have the unenviable task of modifying an ancient VB6 program.  Don't know if anyone is still using this stuff, but...

A feature we want to add is to disable certain functions if the user is not logged in to that computer as an administrator.

What is the best way (if I recall there are often a few ways to do things in VB6, but they could be of varying reliability/robustness) for a VB6 app to query the OS as to whether the user is part of the Administrators group?

Thanks very much in advance.
Question by:riceman0
    LVL 15

    Assisted Solution

    This looks worth a look
    Private Declare Function IsUserAnAdmin Lib "shell32" () As Long

    Private Sub Form_Load()

       Command1.Caption = "IsUserAnAdmin"
       Label1.Caption = ""
    End Sub

    Private Sub Command1_Click()
       Select Case IsUserAnAdmin()
          Case 1:
             Label1.Caption = "YES"
          Case False:
             Label1.Caption = "NO"
       End Select

    End Sub

    LVL 29

    Expert Comment

    Don't check against being a member of the Administrator group because on newer operating systems ex. Vista, Win7 each process is given a split token which means you can be a member of Administrative group but it doesn't mean the process has administrative rights.
    Option Explicit
    Private Const TOKEN_DUPLICATE = &H2&
    Private Const TOKEN_QUERY = &H8&
    Private Const ERROR_NO_TOKEN = 1008
    Private Const DOMAIN_ALIAS_RID_ADMINS = &H220&
    Private Const SECURITY_NT_AUTHORITY = &H5&
    Value(6) As Byte
    End Type
    End Enum
    Private Declare Function OpenProcessToken Lib "advapi32" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, ByRef TokenHandle As Long) As Long
    Private Declare Function OpenThreadToken Lib "advapi32" (ByVal ThreadHandle As Long, ByVal DesiredAccess As Long, ByVal OpenAsSelf As Long, ByRef TokenHandle As Long) As Long
    Private Declare Function AllocateAndInitializeSid Lib "advapi32" (ByRef pIdentifierAuthority As SID_IDENTIFIER_AUTHORITY, ByVal nSubAuthorityCount As Byte, ByVal nSubAuthority0 As Long, ByVal nSubAuthority1 As Long, ByVal nSubAuthority2 As Long, ByVal nSubAuthority3 As Long, ByVal nSubAuthority4 As Long, ByVal nSubAuthority5 As Long, ByVal nSubAuthority6 As Long, ByVal nSubAuthority7 As Long, ByRef lpPSid As Long) As Long
    Private Declare Function CheckTokenMembership Lib "advapi32" (ByVal TokenHandle As Long, ByVal SidToCheck As Long, ByRef IsMember As Long) As Long
    Private Declare Function DuplicateToken Lib "advapi32" (ByVal ExistingTokenHandle As Long, ByVal ImpersonationLevel As Long, ByRef DuplicateTokenHandle As Long) As Long
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
    Private Declare Function GetCurrentThread Lib "kernel32" () As Long
    Private Declare Sub FreeSid Lib "advapi32.dll" (ByVal pSid As Long)
    Public Function IsInRoleAdmin() As Boolean
        Dim AdminGroup As Long
        Dim Success As Long
        Dim hToken As Long
        Dim hTokenDup As Long
        If OpenThreadToken(GetCurrentThread, TOKEN_DUPLICATE Or TOKEN_QUERY, True, hToken) = 0 Then
            OpenProcessToken GetCurrentProcess, TOKEN_DUPLICATE Or TOKEN_QUERY, hToken
        End If
        If DuplicateToken(hToken, SecurityImpersonation, hTokenDup) Then
            ' Well-known SIDs
            NtAuthority.Value(5) = SECURITY_NT_AUTHORITY
            ' allocates and initializes a security identifier (SID)
            Success = AllocateAndInitializeSid(NtAuthority, 2, _
                SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, AdminGroup)
            If Success Then
                If CheckTokenMembership(hTokenDup, AdminGroup, Success) = 0 Then
                    Success = 0
                End If
            FreeSid AdminGroup
            End If
        End If
        IsInRoleAdmin = Success
        CloseHandle hToken
        CloseHandle hTokenDup
    End Function

    Open in new window


    Author Comment

    egl1044, I guess I'm not sure what it means for a process to have different rights than a user.  I guess our requirement is (not surprisingly) incomplete: "only users with administrator privileges will be able to do X"

    So the right thing to do is to check both "sides" of the token?

    How does a process get granted permissions?  I assume by default a process has the permissions of the user who starts it?

    Thanks for the extra info.
    LVL 29

    Accepted Solution

    This would be the case on Windows XP where an administrator that runs a process is by default granted the administrative token. However on OS using user account control the processes are launched with split tokens this means although you may be using an administrative account the process itself is running as a standard user. This would be like running on a limited account on Window XP regardless if that account was administrator or belongs to the administrative group.

    I would recommend reading the following documentation. This will give you a better understanding of how UAC works.

    Deepraw example is also correct and if you look at the documentation for that API call it's a wrapper for CheckTokenMembership. The one line API internally is doing the same thing that I have shown in my code snippet although microsoft warns you that it might not be supported in later versions so that is something to consider I can confirm it does work up to Windows 7 for now. I don't know if it would work with impersonation token where you might call ImpersonateLoggedOnUser() LogOnUser() to imperonate another account. It might return incorrect information in that sense but I would need to test that to be sure. I personally wouldn't use it for anything commercial but it should be okay for personal use.


    Featured Post

    Find Ransomware Secrets With All-Source Analysis

    Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

    Join & Write a Comment

    The debugging module of the VB 6 IDE can be accessed by way of the Debug menu item. That menu item can normally be found in the IDE's main menu line as shown in this picture.   There is also a companion Debug Toolbar that looks like the followin…
    When trying to find the cause of a problem in VBA or VB6 it's often valuable to know what procedures were executed prior to the error. You can use the Call Stack for that but it is often inadequate because it may show procedures you aren't intereste…
    Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
    This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

    755 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    23 Experts available now in Live!

    Get 1:1 Help Now