C Board  

Go Back   C Board > Platform Specific Boards > Windows Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 10-27-2009, 02:01 PM   #1
A7X for life...
 
Join Date: Jan 2005
Posts: 167
Unhappy GetTokenInformation() confusion

Heya all.

I have spent the whole day trying to write a function that will return 0 if the process is running elevated. (It's been a while since I wrote anything Windows related.) Eventually, I wrote something close to working code:

Code:
int TokenIsElevated()    // Returns 0 if process is elevated, 1 if process is not elevated or -1 if a function fails.
{
    DWORD CurrentProcPID = GetCurrentProcessId();
    
    if (!CurrentProcPID)
    {
        MessageBox(NULL, "GetCurrentProcessID function call failed.", "Test 4.exe", MB_ICONEXCLAMATION | MB_OK);
        return -1;
    }
    
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, CurrentProcPID);
    
    if (!hProcess)
    {
        MessageBox(NULL, "OpenProcess function call failed.", "Test 4.exe", MB_ICONEXCLAMATION | MB_OK);
        CloseHandle(hProcess);
        return -1;
    }
    
    PHANDLE hToken;
    
    if(OpenProcessToken(hProcess, TOKEN_READ, hToken) == 0)
    {
        MessageBox(NULL, "OpenProcessToken function call failed.", "Test 4.exe", MB_ICONEXCLAMATION | MB_OK);
        CloseHandle(hProcess);
        CloseHandle(hToken);
        return -1;
    }
    
    TOKEN_ELEVATION_TYPE ElevationType = TokenElevationTypeDefault;
    DWORD SizeReturned = 0;
    
    if (!GetTokenInformation(hToken, TokenElevationType, &ElevationType, sizeof(ElevationType), &SizeReturned))
    {
        MessageBox(NULL, "GetTokenInformation function call failed.", "Test 4.exe", MB_ICONEXCLAMATION | MB_OK);
        CloseHandle(hProcess);
        CloseHandle(hToken);
        return -1;
    }
    
    if (ElevationType == TokenElevationTypeFull);
    {
        CloseHandle(hProcess);
        CloseHandle(hToken);
        return 0;
    }
    
    else
    {
        CloseHandle(hProcess);
        CloseHandle(hToken);
        return 1;
    }
}
The code compiled fine until I wrote this section:

Code:
    TOKEN_ELEVATION_TYPE ElevationType = TokenElevationTypeDefault;
    DWORD SizeReturned = 0;
    
    if (!GetTokenInformation(hToken, TokenElevationType, &ElevationType, sizeof(ElevationType), &SizeReturned))
    {
        MessageBox(NULL, "GetTokenInformation function call failed.", "Test 4.exe", MB_ICONEXCLAMATION | MB_OK);
        CloseHandle(hProcess);
        CloseHandle(hToken);
        return -1;
    }
    
    if (ElevationType == TokenElevationTypeFull);
    {
        CloseHandle(hProcess);
        CloseHandle(hToken);
        return 0;
    }
    
    else
    {
        CloseHandle(hProcess);
        CloseHandle(hToken);
        return 1;
    }
The above section of code will not compile because TOKEN_ELEVATION_TYPE, TokenElevationType and TokenElevationTypeFull are undefined. So I started searching the internet to find out where these definitions are (which took a very long time due to the limited documentation). I found that these were included in a Vista SDK. So I tried to create them myself by placing the following at the top of my code:

Code:
typedef enum _TOKEN_INFORMATION_CLASS
{
    TokenUser = 1,
    TokenGroups,
    TokenPrivileges,
    TokenOwner,
    TokenPrimaryGroup,
    TokenDefaultDacl,
    TokenSource,
    TokenType,
    TokenImpersonationLevel,
    TokenStatistics,
    TokenRestrictedSids,
    TokenSessionId,
    TokenGroupsAndPrivileges,
    TokenSessionReference,
    TokenSandBoxInert,
    TokenAuditPolicy,
    TokenOrigin,
    TokenElevationType,
    TokenLinkedToken,
    TokenElevation,
    TokenHasRestrictions,
    TokenAccessInformation,
    TokenVirtualizationAllowed,
    TokenVirtualizationEnabled,
    TokenIntegrityLevel,
    TokenUIAccess,
    TokenMandatoryPolicy,
    TokenLogonSid,
    MaxTokenInfoClass             // MaxTokenInfoClass should always be the last enum
}   TOKEN_INFORMATION_CLASS, *PTOKEN_INFORMATION_CLASS;

typedef enum _TOKEN_ELEVATION_TYPE
{
    TokenElevationTypeDefault = 1,
    TokenElevationTypeFull,
    TokenElevationTypeLimited,
}   TOKEN_ELEVATION_TYPE, *PTOKEN_ELEVATION_TYPE;
However, this results in multiple definitions of _TOKEN_INFORMATION_CLASS and _TOKEN_ELEVATION_TYPE (and their members), and, because I do not understand this code (I found it on the internet), I do not know what to do.

Any advice would be greatly appreciated.
Thankyou for your time.
Necrofear

IDE: Dev-C++ 4.9.9.2
__________________
It is much better to pretend you know, than to know you're pretending.
Necrofear is offline   Reply With Quote
Old 10-27-2009, 02:13 PM   #2
and the Hat of Guessing
 
tabstop's Avatar
 
Join Date: Nov 2007
Posts: 8,740
Say what you want about MS documentation, they always tell you what headers things are defined in: TOKEN_ELEVATION_TYPE Enumeration (Windows) (Look toward the bottom.)
tabstop is offline   Reply With Quote
Old 10-27-2009, 04:21 PM   #3
A7X for life...
 
Join Date: Jan 2005
Posts: 167
The definition in winnt.h is different because it lacks certain members (including ElevationType, which is the one I intended to use.) I have come across this code several times on the internet (the one with ElevationType) and I could find no one else with a similar problem. Have they explicitly excluded winnt.h??
__________________
It is much better to pretend you know, than to know you're pretending.
Necrofear is offline   Reply With Quote
Old 10-27-2009, 04:45 PM   #4
Registered User
 
Join Date: Mar 2005
Location: Mountaintop, Pa
Posts: 1,054
They're defined in ntifs.h which is found in the Windows DDK version 6001.18001.
BobS0327 is offline   Reply With Quote
Old 10-27-2009, 04:56 PM   #5
and the Hat of Guessing
 
tabstop's Avatar
 
Join Date: Nov 2007
Posts: 8,740
Are you using the (10-year-old-or-so) winnt.h provided by Dev-C++, or the winnt.h from your system?
tabstop is offline   Reply With Quote
Old 10-27-2009, 06:56 PM   #6
A7X for life...
 
Join Date: Jan 2005
Posts: 167
Oh, yeah I was using the one that came with the compiler. In all honesty, I was unaware that the system had a winnt.h... Where is this? Is it best to use this or download an up to date DDK?

EDIT: I have found a version of ntifs.h in a folder named ddk (don't know which version). I tried to include it, but it made no difference - they were still undefined. I guess it's outdated.
__________________
It is much better to pretend you know, than to know you're pretending.

Last edited by Necrofear; 10-27-2009 at 07:10 PM.
Necrofear is offline   Reply With Quote
Old 10-27-2009, 08:09 PM   #7
and the Hat of Guessing
 
tabstop's Avatar
 
Join Date: Nov 2007
Posts: 8,740
If that ddk folder is in the Dev-Cpp tree, then it's an old old file. You will need the platform SDK for the platform you are actually on. For some reason, I thought there were more header files in /system32 than there actually are. If you have VS, then VS came with those header files. If not you'll have to do some downloading (there's probably a way to get the header files without also downloading VS, but I didn't look hard enough to find it).
tabstop is offline   Reply With Quote
Old 10-27-2009, 08:23 PM   #8
Registered User
 
Join Date: Mar 2005
Location: Mountaintop, Pa
Posts: 1,054
This is all you need for the above code:

Code:
typedef enum _TOKEN_ELEVATION_TYPE {
    TokenElevationTypeDefault = 1,
        TokenElevationTypeFull,
        TokenElevationTypeLimited,
} TOKEN_ELEVATION_TYPE, *PTOKEN_ELEVATION_TYPE;

TOKEN_INFORMATION_CLASS TokenElevationType;
Here's your modified code. It still needs a lot of work but it now compiles.

Code:
#define _WIN32_WINNT 0x0501

#include <windows.h>
#include <stdio.h>

#pragma comment (lib,"advapi32.lib")

typedef enum _TOKEN_ELEVATION_TYPE {
    TokenElevationTypeDefault = 1,
        TokenElevationTypeFull,
        TokenElevationTypeLimited,
} TOKEN_ELEVATION_TYPE, *PTOKEN_ELEVATION_TYPE;

TOKEN_INFORMATION_CLASS TokenElevationType;

VOID DisplayError(CHAR* pMessage)
{
    DWORD eNum;
    CHAR sysMsg[256] = {0};
    CHAR* p;

    eNum = GetLastError( );
    FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL, eNum,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
        sysMsg, 256, NULL );
    // Trim the end of the line and terminate it with a null
    p = sysMsg;
    while( ( *p > 31 ) || ( *p == 9 ) )
        ++p;
    do { *p-- = 0; } while( ( p >= sysMsg ) &&
        ( ( *p == '.' ) || ( *p < 33 ) ) );
    // Display the message
    printf( "\n  WARNING: %s failed with error %d (%s)", pMessage, eNum, sysMsg );
}

int TokenIsElevated(void )    // Returns 0 if process is elevated, 1 if process is not elevated or -1 if a function fails.
{
    DWORD CurrentProcPID = GetCurrentProcessId();

    if (!CurrentProcPID)
    {
        // MessageBox(NULL, "GetCurrentProcessID function call failed.", "Test 4.exe", MB_ICONEXCLAMATION | MB_OK);
        DisplayError("GetCurrentProcessID function call failed.");
        return -1;
    }

    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, CurrentProcPID);

    if (!hProcess)
    {
        //MessageBox(NULL, "OpenProcess function call failed.", "Test 4.exe", MB_ICONEXCLAMATION | MB_OK);
        DisplayError("OpenProcess function call failed." );
        CloseHandle(hProcess);
        return -1;
    }

    HANDLE hToken;

    if(OpenProcessToken(hProcess, TOKEN_QUERY, &hToken) == 0)
    {
        // MessageBox(NULL, "OpenProcessToken function call failed.", "Test 4.exe", MB_ICONEXCLAMATION | MB_OK);
        DisplayError("OpenProcessToken function call failed." );
        CloseHandle(hProcess);
        CloseHandle(hToken);
        return -1;
    }

    TOKEN_ELEVATION_TYPE ElevationType = TokenElevationTypeFull;
    DWORD SizeReturned = 0;

    if (!GetTokenInformation(&hToken, TokenElevationType, &ElevationType, sizeof(ElevationType), &SizeReturned))
    {
        // MessageBox(NULL, "GetTokenInformation function call failed.", "Test 4.exe", MB_ICONEXCLAMATION | MB_OK);
        DisplayError( "GetTokenInformation function call failed.");
        CloseHandle(hProcess);
        CloseHandle(hToken);
        return -1;
    }

    if (ElevationType == TokenElevationTypeFull)
    {
        CloseHandle(hProcess);
        CloseHandle(hToken);
        return 0;
    }

    else
    {
        CloseHandle(hProcess);
        CloseHandle(hToken);
        return 1;
    }
}

int main(void)
{
    TokenIsElevated();
    return 0;
}

Last edited by BobS0327; 10-27-2009 at 08:41 PM.
BobS0327 is offline   Reply With Quote
Old 10-28-2009, 07:46 AM   #9
A7X for life...
 
Join Date: Jan 2005
Posts: 167
Thankyou very much for the code Bob, will get to work on it soon.
__________________
It is much better to pretend you know, than to know you're pretending.
Necrofear is offline   Reply With Quote
Old 10-31-2009, 02:08 PM   #10
A7X for life...
 
Join Date: Jan 2005
Posts: 167
Ok, so I've been trying to fix up the code that BobS0327 provided. (Thanks again )
The extra function that he provided (the DisplayError function) printed the following:

Code:
WARNING: GetTokenInformation function call failed. failed with error 87 (The parameter is incorrect)
I have tried my best to determine the cause of the problem, (by altering variable types, using pointers in the function call, NULLifying parameters etc) but I cannot figure it out. I do not wish to be selfish and ask for an excessive amount of help, but if someone could please point me in the right direction, that'd be great.

Thanks for your time and good day.
__________________
It is much better to pretend you know, than to know you're pretending.
Necrofear is offline   Reply With Quote
Old 10-31-2009, 03:19 PM   #11
Hat seller extraordinaire
 
Join Date: Apr 2008
Posts: 159
Change the GetTokenInformation line back to how it is in your first post. Note that if UAC is turned off, the value it returns will be TokenElevationTypeDefault for at least all local users, including administrators. Depending on what you're wanting, that might cause your function as it currently is to return wrong information.

Also, everything above the "HANDLE hToken;" can be deleted if you change the next line to:
if(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) == 0)

Last edited by adeyblue; 10-31-2009 at 03:47 PM.
adeyblue is offline   Reply With Quote
Old 10-31-2009, 06:59 PM   #12
Registered User
 
Join Date: Mar 2005
Location: Mountaintop, Pa
Posts: 1,054
Quote:
Originally Posted by Necrofear View Post
Ok, so I've been trying to fix up the code that BobS0327 provided. (Thanks again )
The extra function that he provided (the DisplayError function) printed the following:

Code:
WARNING: GetTokenInformation function call failed. failed with error 87 (The parameter is incorrect)
I have tried my best to determine the cause of the problem, (by altering variable types, using pointers in the function call, NULLifying parameters etc) but I cannot figure it out. I do not wish to be selfish and ask for an excessive amount of help, but if someone could please point me in the right direction, that'd be great.

Thanks for your time and good day.
It means that you are using a incorrect input parameter. That is, TokenElevationType is the incorrect input parameter. After you determine the correct parameter, you'll have to call LookUpAccoutSid. Next, you'll have to determine whether the the sid is interactive or not. Finally, you'll have to inspect the Sid to determine if it is elevated. Post your problem on the Win32 newsgroup and all of the above will be illustrated in simple to understand, complete, fully functional code snippet.
BobS0327 is offline   Reply With Quote
Old 10-31-2009, 07:37 PM   #13
A7X for life...
 
Join Date: Jan 2005
Posts: 167
Woah, looks like I jumped in at the deep end. Didn't realize that SIDs came into it at all. Ok will get to work again. Thanks for the help.
P.S. With regards to deleting everything above the hToken declaration, I find it a little easier to understand if I am only passing variables to OpenProcessToken (as oppose to the GetCurrentProcess function itself). I realize that this may be less efficient, but I'll be the first to admit that I do get easily confused, even by my own code. Thankyou for your input though, it greatly appreciated.
__________________
It is much better to pretend you know, than to know you're pretending.
Necrofear is offline   Reply With Quote
Old 10-31-2009, 09:05 PM   #14
Registered User
 
Join Date: Mar 2005
Location: Mountaintop, Pa
Posts: 1,054
This may be a much simpler approach for XP and up...

Code:
#include <windows.h>
#include <stdio.h>
#include <tchar.h>

int main(void)
{
    typedef BOOL (WINAPI *LPFNIUA)(void);

    HMODULE hShell32 = LoadLibrary(_T("shell32.dll"));
    LPFNIUA pIsAdmin = NULL;

    if (hShell32)
    {
        pIsAdmin = (LPFNIUA)GetProcAddress(hShell32, MAKEINTRESOURCE(680));
        if (pIsAdmin)
        {
            if(pIsAdmin())
                printf(_T("User is Admin\n"));
            else printf(_T("User is NOT Admin\n"));
        }
        FreeLibrary(hShell32);
    }
    return 0;
}
BobS0327 is offline   Reply With Quote
Old 11-01-2009, 03:07 PM   #15
Registered User
 
Join Date: Mar 2005
Location: Mountaintop, Pa
Posts: 1,054
Quote:
Originally Posted by BobS0327 View Post
It means that you are using a incorrect input parameter. That is, TokenElevationType is the incorrect input parameter. After you determine the correct parameter, you'll have to call LookUpAccoutSid. Next, you'll have to determine whether the the sid is interactive or not. Finally, you'll have to inspect the Sid to determine if it is elevated. Post your problem on the Win32 newsgroup and all of the above will be illustrated in simple to understand, complete, fully functional code snippet.
[EDIT] The reason you're receiving this incorrect parameter message is probably because you're using a very old compiler or your compiler is misconfigured. I'm using Visual Studio 2008 and I do NOT have to manually add the typedef for TOKEN_ELEVATION_TYPE. Once you have your compiler issues resolved, you can use TOKEN_ELEVATION_TYPE.

If your first call to GetTokenInformation returns TokenElevationTypeLimited, you'll have to call GetTokenInformation a second time. This will get you a handle to a linked token. A linked token will exist if the user account is a Least-Privileged User Account (LUA). At this point, you'll create an Administrator SID using the CreateWellKnownSID call. Next, you'll have to call GetTokenInformation a second time with the TokenLinkedToken parameter. After which you'll have to call CheckTokenMembership with what was returned from the second calling of GetTokenInformation. By calling CheckTokenMembership, we can verify whether or not the original token contains an Admin SID. If the first call to GetTokenInformation returns anything other than TokenElevationTypeLimited, the only option you have is to call IsUserAnAdmin, a sample of this call is in a previous post.

If you're still having problems with this task, then post on the Win32 newsgroups and a very simple, fully functional example of the above will be submitted to your post.

Last edited by BobS0327; 11-01-2009 at 06:49 PM.
BobS0327 is offline   Reply With Quote
Reply

Tags
admin, elevated, gettokeninformation(), privileges, process

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
relative virtual addresses confusion MrNoobah Windows Programming 7 10-13-2009 08:45 PM
Pointer + struct w/arrays confusion Viper187 C Programming 1 07-23-2009 09:37 AM
Terrible confusion with time variables LowlyIntern C++ Programming 12 08-01-2008 07:23 AM
confusion with increment and decrement operators cBegginer C Programming 6 03-19-2005 03:45 PM
Unicode - a lot of confusion... Jumper Windows Programming 11 07-05-2004 07:59 AM


All times are GMT -6. The time now is 02:02 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22