Click here to Skip to main content
15,885,365 members
Please Sign up or sign in to vote.
5.00/5 (2 votes)
See more:
Hey Friends

Is it possible somehow to determine whether any application is running as Administrator

on my Desktop using Win32 API or some other API ?

Something like

EnumProcess (enumFunc); and for each process check whether i do

enumFunc()
{
if(I am Running as Administrator)
{
TRACE("Found It\n");
}

}
Regards
Posted
Comments
Akinmade Bond 12-Feb-13 9:59am    
Do you want to check only for your application or for others running on the pc?
vikrant kpr 12-Feb-13 10:00am    
other applications
José Amílcar Casimiro 12-Feb-13 10:05am    
Use OpenProcessToken to get the token (obviously), then GetTokenInformation with the TokenOwner flag to get the SID of the owner. Then you can use LookupAccountSid to get the username.
vikrant kpr 12-Feb-13 10:21am    
i guess this will fail if i am using this on a computer with only one user account (who is admin) and launches an application using right click and run as administrator
José Amílcar Casimiro 12-Feb-13 10:26am    
Did you check the sample code for the LookupAccountSid? http://msdn.microsoft.com/en-us/library/aa379554(v=vs.85).aspx

What you want, looks something like this:
HRESULT CheckIfIsUserAdmin(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;
 
    hProcess = GetCurrentProcess();
    if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hProcessToken))
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }
 
    char AdminSID[SECURITY_MAX_SID_SIZE];
    dwLength = sizeof(AdminSID);
    if(!CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &AdminSID, &dwLength)) 
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    } 

    if (!CheckTokenMembership( NULL, &AdminSID, &fIsAdmin)) 
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }
 
    if (fIsAdmin) 
    {
        *pIsAdmin = TRUE;
        goto Exit;
    }
 
    if (!GetVersionEx(&osver))
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }
 
    if (osver.dwMajorVersion < 6) 
    {
        goto Exit;        
    }
 
    // Code to handle admin SID filtering in Vista and above
    if (!GetTokenInformation(hProcessToken, TokenLinkedToken,
                                (VOID*) &hLinkedToken, sizeof(HANDLE), &dwLength) )
    {
        b = GetLastError();
        if( b == ERROR_NO_SUCH_LOGON_SESSION ||  b == ERROR_PRIVILEGE_NOT_HELD)
        {
            goto Exit;
        }
 
        hr = HRESULT_FROM_WIN32(b);
        goto Exit;
    } 

    if (!CheckTokenMembership(hLinkedToken, &AdminSID, &fIsAdmin))
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }
 
    if (fIsAdmin)
    {
        *pIsAdmin = TRUE;
    }
 
Exit:
    if (hProcess) 
    {
        CloseHandle(hProcess);
    }
 
    if (hProcessToken)
    {
        CloseHandle(hProcessToken);
    }
 
    if (hLinkedToken)
    {
        CloseHandle(hLinkedToken);
    }
 
    return hr;
}

If the current token does not contain the administrator SID, that does not always mean that the current user is not an admininistrator since for Vista and above the default is to filter the admininistrator SID on the tokens for members of the administrator group.

So, we need to call GetTokenInformation to retrieve the linked token, and then call CheckTokenMembership once more on the liked token to check for the unfiltered admininistrator SID.

Best regards
Espen Harlinn
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 12-Feb-13 14:19pm    
Very nice, a 5.
(I was wondering: who has asked this pretty tricky question?)
—SA
Espen Harlinn 12-Feb-13 14:37pm    
Thank you, Sergey :-D
vikrant kpr 13-Feb-13 0:10am    
i could not have imagined this way in my wildest dreams and yes thanks a ton. it will take me some time to understand all this :-)
Thanks a ton.
vikrant kpr 13-Feb-13 0:26am    
Checked the code and it seems like i am not asking the question properly.

I am Admin of my PC.

My EXE can be launched normally or by right clicking on the application and clicking on Run as Administrator

I need to distinguish between whether i am running an application normally or by clicking on Run as Administrator.

The Sample Code simply tells whether the user who has launched the application is admin or not.

Sample Scenario:

Now when my application is launched normally even though i am admin, the application cannot create a directory in c:\windows on windows 7 or windows 8

However when my Application is launched by doing a right click and clicking on run as Administrator, it can create a directory in c:\windows
Espen Harlinn 13-Feb-13 4:23am    
You can then look at either or both the TokenElevationType or TokenElevation token property, like:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb530718(v=vs.85).aspx

DWORD infoLen;
TOKEN_ELEVATION_TYPE elevationType;
GetTokenInformation(hToken, TokenElevationType,
&elevationType, sizeof(elevationType), &infoLen)

http://msdn.microsoft.com/en-us/library/windows/desktop/bb530717(v=vs.85).aspx
TOKEN_ELEVATION elevation;
GetTokenInformation(hToken, TokenElevation,&elevation,
sizeof(elevation), &infoLen)
 
Share this answer
 
Here is my "me too" answer, based on KB #Q118626:

//-------------------------------------------------------------------------
// This function checks the token of the calling thread to see if the caller
// belongs to the Administrators group.
//
// Return Value:
//   TRUE if the caller is an administrator on the local machine.
//   Otherwise, FALSE.
// --------------------------------------------------------------------------
// Based on code from KB #Q118626, at http://support.microsoft.com/kb/118626
BOOL IsCurrentUserLocalAdministrator()
{
    BOOL   fReturn         = FALSE;
    DWORD  dwStatus        = 0;
    DWORD  dwAccessMask    = 0;
    DWORD  dwAccessDesired = 0;
    DWORD  dwACLSize       = 0;
    DWORD  dwStructureSize = sizeof(PRIVILEGE_SET);
    PACL   pACL            = NULL;
    PSID   psidAdmin       = NULL;

    HANDLE hToken              = NULL;
    HANDLE hImpersonationToken = NULL;

    PRIVILEGE_SET   ps = {0};
    GENERIC_MAPPING GenericMapping = {0};

    PSECURITY_DESCRIPTOR     psdAdmin           = NULL;
    SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;

    // Determine if the current thread is running as a user that is a member 
    // of the local admins group.  To do this, create a security descriptor 
    // that has a DACL which has an ACE that allows only local administrators 
    // access.  Then, call AccessCheck with the current thread's token and
    // the security descriptor.  It will say whether the user could access an
    // object if it had that security descriptor.  Note: you do not need to
    // actually create the object.  Just checking access against the
    // security descriptor alone will be sufficient.

    const DWORD ACCESS_READ  = 1;
    const DWORD ACCESS_WRITE = 2;

    __try
    {
        // AccessCheck() requires an impersonation token.  We first get a 
        // primary token and then create a duplicate impersonation token.
        // The impersonation token is not actually assigned to the thread, but
        // is used in the call to AccessCheck.  Thus, this function itself never
        // impersonates, but does use the identity of the thread.  If the thread
        // was impersonating already, this function uses that impersonation 
        // context.
        if (!OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE|TOKEN_QUERY, TRUE, &hToken))
        {
            if (GetLastError() != ERROR_NO_TOKEN)
                __leave;

            if (!OpenProcessToken(GetCurrentProcess(), 
                TOKEN_DUPLICATE|TOKEN_QUERY, &hToken))
                __leave;
        }

        if (!DuplicateToken (hToken, SecurityImpersonation, &hImpersonationToken))
            __leave;

        // Create the binary representation of the well-known SID that
        // represents the local administrators group.  Then create the 
        // security descriptor and DACL with an ACE that allows only local
        // admins access.  After that, perform the access check.  This will
        // determine whether the current user is a local admin.
        if (!AllocateAndInitializeSid(&SystemSidAuthority, 2,
            SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
            0, 0, 0, 0, 0, 0, &psidAdmin))
            __leave;

        psdAdmin = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
        if (psdAdmin == NULL)
            __leave;

        if (!InitializeSecurityDescriptor(psdAdmin, SECURITY_DESCRIPTOR_REVISION))
            __leave;

        // Compute size needed for the ACL.
        dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) +
            GetLengthSid(psidAdmin) - sizeof(DWORD);

        pACL = (PACL)LocalAlloc(LPTR, dwACLSize);
        if (pACL == NULL)
            __leave;

        if (!InitializeAcl(pACL, dwACLSize, ACL_REVISION2))
            __leave;

        dwAccessMask= ACCESS_READ | ACCESS_WRITE;

        if (!AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask, psidAdmin))
            __leave;

        if (!SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE))
            __leave;

        // AccessCheck validates a security descriptor somewhat; set the group
        // and owner so that enough of the security descriptor is filled out to
        // make AccessCheck happy.

        SetSecurityDescriptorGroup(psdAdmin, psidAdmin, FALSE);
        SetSecurityDescriptorOwner(psdAdmin, psidAdmin, FALSE);

        if (!IsValidSecurityDescriptor(psdAdmin))
            __leave;

        dwAccessDesired = ACCESS_READ;

        // Initialize GenericMapping structure even though you
        // do not use generic rights.
        GenericMapping.GenericRead    = ACCESS_READ;
        GenericMapping.GenericWrite   = ACCESS_WRITE;
        GenericMapping.GenericExecute = 0;
        GenericMapping.GenericAll     = ACCESS_READ | ACCESS_WRITE;

        if (!AccessCheck(psdAdmin, hImpersonationToken, dwAccessDesired,
            &GenericMapping, &ps, &dwStructureSize, &dwStatus,
            &fReturn))
        {
            fReturn = FALSE;
            __leave;
        }
    }
    __finally
    {
        // Clean up.
        if (pACL)
            LocalFree(pACL);
        if (psdAdmin)
            LocalFree(psdAdmin);
        if (psidAdmin)
            FreeSid(psidAdmin);
        if (hImpersonationToken)
            CloseHandle (hImpersonationToken);
        if (hToken)
            CloseHandle (hToken);
    }

    return fReturn;
}
 
Share this answer
 
Comments
vikrant kpr 13-Feb-13 1:11am    
H.Brydon

You hit the Bulls Eye :-)

Thanks a ton buddy.


Hello All

Thanks to all of you Guys

Without your Help Visual C++ Would be Dead

You all have made my Day and i thank you from my heart.
Although this question was asked an aeon ago, I'd like to point out to a more recent solution, coming straight from the official Microsoft developer documentation that I've been using since 2010, proven to work reliably on Windows 2000, Windows XP and Windows 7 back then and up to Windows 10 as of today.
I came across here while trying to ensure that I would still use a valid solution.

Of course I'd like the original solution authors here to comment on the issue, should there be any objections but I guess this solution would have been adequate already when the question was asked back in 2013.

Solution 1 seems to be the answer but it does not distinguish between elevated and non-elevated privileges, what I read to be the original question. It always returns TRUE on my Windows 10 machine, no matter if I run it within an elevated UAC prompt or not.

The KB article #118626 mentioned in Solution 3 has been removed by Microsoft, but the Web Archive still holds a copy here for anyone interested:
How To Determine Whether a Thread Is Running in User Context of Local Administrator Account[^]

I just mention this because there's already a recommendation at the beginning of its summary:
Quote:
With Windows 2000 and later versions, you can use the CheckTokenMembership() API instead of the steps described in this article. For additional information, see the Microsoft Platform SDK documentation.

CheckTokenMembership function (securitybaseapi.h) - Win32 apps | Microsoft Learn[^]

The docs there say the minimum OS versions are:
Quote:
Minimum supported client Windows XP [desktop apps | UWP apps]
Minimum supported server Windows Server 2003 [desktop apps | UWP apps]
But as mentioned earlier this solution already worked on Windows 2000.

Here is my slightly modernized version of the sample code:
/*
    Routine Description: This routine returns TRUE if the caller's
    process is a member of the Administrators local group. Caller is NOT
    expected to be impersonating anyone and is expected to be able to
    open its own process and process token.

    Arguments: None.

    Return Value:
        true - Caller has Administrators local group.
        false - Caller does not have Administrators local group.
*/
bool IsUserAdmin()
{
    BOOL b;
    SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
    PSID AdministratorsGroup;

    b = AllocateAndInitializeSid(
        &NtAuthority,
        2,
        SECURITY_BUILTIN_DOMAIN_RID,
        DOMAIN_ALIAS_RID_ADMINS,
        0, 0, 0, 0, 0, 0,
        &AdministratorsGroup);

    if (b == TRUE)
    {
        if (CheckTokenMembership(NULL, AdministratorsGroup, &b) == FALSE)
        {
            b = FALSE;
        }
        FreeSid(AdministratorsGroup);
    }

    return (b == TRUE);
}
Many thanks to all of you! It was an interesting read :)
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900