Udostępnij za pośrednictwem


How to tell if the current user is in administrators group programmatically

You can use CheckTokenMembership (https://msdn2.microsoft.com/en-us/library/aa376389.aspx) to check whether a user is in administrators group. There is an example in the MSDN document.

The example will not work in Windows Vista. In Windows Vista, even if the user is in administrators group, the OS will create a filtered user token when user log on. The SID of administrators group is not included in the filtered user token. The full token is linked to the filtered user token, and can be retrieved with API GetTokenInformation with the new TokenLinkedToken information type.

The following is the sample code. You need to download Vista SDK to compile it. Please make sure you read the article in the reference section.

HRESULT IsUserAdmin(BOOL *pIsAdmin)
{
int b;
HANDLE hProcess = NULL;
HANDLE hProcessToken = NULL;
HANDLE hLinkedToken = NULL;
BOOL fIsAdmin = FALSE;
DWORD dwLength = 0;
OSVERSIONINFO osver = {sizeof(OSVERSIONINFO)};
HRESULT hr = S_OK;

    *pIsAdmin = FALSE;

    // get handle to our process token
hProcess = GetCurrentProcess();
if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hProcessToken))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Exit;
}

    // get admin SID
char AdminSID[SECURITY_MAX_SID_SIZE];
dwLength = sizeof(AdminSID);
if(!CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &AdminSID, &dwLength))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Exit;
}

    // check to see if the current token contains admin SID
if (!CheckTokenMembership( NULL, &AdminSID, &fIsAdmin))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Exit;
}

    if (fIsAdmin)
{
// printf("The user is in admin group, and the process is elevated.\n");
*pIsAdmin = TRUE;
goto Exit;
}

  // if the current token does not contain admin SID, it does not mean
// that the current user is not admin. In Vista by default the token of
// users in administrator group has the the admin SID filtered. We nee
// to use the unfiltered token to do the check.
if (!GetVersionEx(&osver))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Exit;
}

    // XP and below, we are done.
if (osver.dwMajorVersion < 6)
{
// printf("The user is not in admin group.\n");
goto Exit;
}

// get handle to linked token (will have one if we are lua)
if (!GetTokenInformation( hProcessToken,
TokenLinkedToken,
(VOID*) &hLinkedToken,
sizeof(HANDLE),
&dwLength) )
{
b = GetLastError();
if ( b == ERROR_NO_SUCH_LOGON_SESSION
|| b == ERROR_PRIVILEGE_NOT_HELD)
{
// printf("The user is not in admin group.\n");
goto Exit;
}

        hr = HRESULT_FROM_WIN32(b); // a real error
goto Exit;
}

    if (!CheckTokenMembership( hLinkedToken, &AdminSID, &fIsAdmin))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Exit;
}

    if (fIsAdmin)
{
// printf("The user is in admin group, and the process is not elevated.\n");
*pIsAdmin = TRUE;
}
else
{
// printf("The user is not in admin group.\n");
}

Exit:
if (hProcess)
{
CloseHandle(hProcess);
}

    if (hProcessToken)
{
CloseHandle(hProcessToken);
}

    if (hLinkedToken)
{
CloseHandle(hLinkedToken);
}

    return hr;
}

Reference:

Teach Your Apps To Play Nicely With Windows Vista User Account Control

Comments

  • Anonymous
    January 29, 2007
    How is this different and/or better than: public static bool IsAdministrator { get {  // Check whether the user is part of the administrator group  AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal); WindowsPrincipal principal = (WindowsPrincipal)Thread.CurrentPrincipal; WindowsIdentity identity = (WindowsIdentity)principal.Identity; return principal.IsInRole(WindowsBuiltInRole.Administrator); } }

  • Anonymous
    January 29, 2007
    Monday, January 29, 2007 11:10 AM by Munish > How is this different and/or better than: [.Net stuff] Difference:  Win32 APIs vs. .Net APIs. Better:  Maybe or maybe not. If you had old Win32 code that worked in XP and you want to make it work in Vista without depending on .Net, then it might be better for your purposes.  If you're writing new code which you don't need to port to XP (or if you know that all your XP customers will download the .Net framework) then the .Net version is easier to understand.

  • Anonymous
    January 29, 2007
    Why don't you try your .Net version and see if it works in Vista?

  • Anonymous
    February 09, 2007
    I tried that .NET version and it works.  Nice little snippet there.  Now if I could only find a way to elevate to administrator in Vista in C#....

  • Anonymous
    February 09, 2007
    You can use the verb "runas" combined with UseShellExecute in ProcessStartInfo to elevate.

  • Anonymous
    April 04, 2007
    Your comment in the top says that this will NOT work in Vista, However, in the middle of the code, you are checking the unfiltered token to see if the user is an admin. So does this really work in Vista or not?

  • Anonymous
    April 25, 2007
    Is it possible to produce the same functionality on Vista using an older version of the SDK (w/o Vista support)? Using other functions or something else.