Searching for a SID in an Access Token

The following example uses the OpenProcessToken and GetTokenInformation functions to get the group memberships in an access token. Then it uses the AllocateAndInitializeSid function to create a SID that identifies the well-known SID of the administrator's group for the local computer. Next, it uses the EqualSid function to compare the well-known SID with the group SIDs from the access token. If the SID is present in the token, the function checks the SIDs attributes to see if it is enabled.

Windows NT 5.0 and later: You can use the CheckTokenMembership function to determine whether a specified SID is present and enabled in an access token.

#define MAX_NAME 256

BOOL SearchTokenGroupsForSID (VOID) 
{
DWORD i, dwSize = 0, dwResult = 0;
HANDLE hToken;
PTOKEN_GROUPS pGroupInfo;
SID_NAME_USE SidType;
char lpName[MAX_NAME];
char lpDomain[MAX_NAME];
BYTE sidBuffer[100];
PSID pSID = (PSID)&sidBuffer;
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
   
// Open a handle to the access token for the calling process.

if (!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken )) {
    printf( "OpenProcessToken Error %u\n", GetLastError() );
    return FALSE;
}

// Call GetTokenInformation to get the buffer size.

if(!GetTokenInformation(hToken, TokenGroups, NULL, dwSize, &dwSize)) {
    dwResult = GetLastError();
    if( dwResult != ERROR_INSUFFICIENT_BUFFER ) {
        printf( "GetTokenInformation Error %u\n", dwResult );
        return FALSE;
    }
}

// Allocate the buffer.

pGroupInfo = (PTOKEN_GROUPS) GlobalAlloc( GPTR, dwSize );

// Call GetTokenInformation again to get the group information.

if(! GetTokenInformation(hToken, TokenGroups, pGroupInfo, 
                        dwSize, &dwSize ) ) {
    printf( "GetTokenInformation Error %u\n", GetLastError() );
    return FALSE;
   }

// Create a SID for the BUILTIN\Administrators group.

if(! AllocateAndInitializeSid( &SIDAuth, 2,
                 SECURITY_BUILTIN_DOMAIN_RID,
                 DOMAIN_ALIAS_RID_ADMINS,
                 0, 0, 0, 0, 0, 0,
                 &pSID) ) {
    printf( "AllocateAndInitializeSid Error %u\n", GetLastError() );
    return FALSE;
   }

// Loop through the group SIDs looking for the administrator SID.

for(i=0; i<pGroupInfo->GroupCount; i++) {
    if ( EqualSid(pSID, pGroupInfo->Groups[i].Sid) ) {

        // Lookup the account name and print it.

        dwSize = MAX_NAME;
        if( !LookupAccountSid( NULL, pGroupInfo->Groups[i].Sid,
                              lpName, &dwSize, lpDomain, 
                              &dwSize, &SidType ) ) {
            dwResult = GetLastError();
            if( dwResult == ERROR_NONE_MAPPED )
                strcpy( lpName, "NONE_MAPPED" );
            else {
                printf("LookupAccountSid Error %u\n", GetLastError());
                return FALSE;
            }
        }
        printf( "Current user is a member of the %s\\%s group\n", 
                lpDomain, lpName );
  
        // Find out if the SID is enabled in the token

        if (pGroupInfo->Groups[i].Attributes & SE_GROUP_ENABLED)
            printf("The group SID is enabled.\n");
         else if (pGroupInfo->Groups[i].Attributes & 
                          SE_GROUP_USE_FOR_DENY_ONLY)
            printf("The group SID is a deny-only SID.\n");
         else 
            printf("The group SID is not enabled.\n");
    }
}

if (pSID)
    FreeSid(pSID);
if ( pGroupInfo )
    GlobalFree( pGroupInfo );
return TRUE;
}