Windows Process Info

This is a discussion on Windows Process Info within the Windows Programming forums, part of the Platform Specific Boards category; One short thing on processes: How do retreive the "User Name" information for a process. Here is what taksmanager says ...

  1. #1
    HelpingYouHelpUsHelpUsAll
    Join Date
    Dec 2007
    Location
    In your nightmares
    Posts
    223

    Windows Process Info

    One short thing on processes: How do retreive the "User Name" information for a process. Here is what taksmanager says about it:
    The name of the user whoes terminal services session owns the process. The counter is available only when terminal services is installed.
    This is typically "LOCAL SERVICE", "SYSTEM", UserName or NETWORK SERVICE. I couldn't find it on msdn, even under "Obtaining Additional Process Information"
    long time no C; //seige
    You miss 100% of the people you don't C;
    Code:
    if (language != LANG_C && language != LANG_CPP)
        drown(language);

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,701
    Here's some source that shows how to lookup the owner of a process.

    http://win32.mvps.org/security/opt_gti.html

    gg

  3. #3
    HelpingYouHelpUsHelpUsAll
    Join Date
    Dec 2007
    Location
    In your nightmares
    Posts
    223
    Thanks, but i'm having trouble understanding tokens. Here is what i have (its not much):
    Code:
    TOKEN_SOURCE ts;
    DWORD needed;
    OpenProcessToken(hProcess,TOKEN_QUERY_SOURCE,TokenHandle);
    GetTokenInformation(TokenHandle,TOKEN_OWNER,&ts,sizeof(ts),&needed);
    I thought that it would be alot easier to see if the process was a system process, network process, local process or user created. I am doing this in C rather than C++, which makes reading that example even more confusing.
    long time no C; //seige
    You miss 100% of the people you don't C;
    Code:
    if (language != LANG_C && language != LANG_CPP)
        drown(language);

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,701
    >> which makes reading that example even more confusing.
    Dang! What of parts of that C++ code were give'n you problems?

    Just compile and run the code as is. You'll see that it dumps everything that you're looking to know right to the screen.

    gg

  5. #5
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,059
    Thanks, but i'm having trouble understanding tokens. Here is what i have (its not much):

    Code:
    TOKEN_SOURCE ts;
    DWORD needed;
    OpenProcessToken(hProcess,TOKEN_QUERY_SOURCE,Token Handle);
    GetTokenInformation(TokenHandle,TOKEN_OWNER,&ts,si zeof(ts),&needed);
    You have to use TOKEN_OWNER not TOKEN_SOURCE

    A simple example with some basic comments follows. You should attempt to acquire SedebugPriviledge for your current running process. How to do this is illustrated in the link provided by CodePlug.

    Code:
    #pragma comment( lib,"advapi32.lib")
    
    #include <windows.h>
    #include <stdio.h>
    
    #define MAX_NAME 256
    
    BOOL GetTokenOwner(HANDLE Token)
    {
        DWORD dwSize, dwResult;
        SID *sid;
        char  AcctName[MAX_NAME] ,  DomainName[MAX_NAME];
        SID_NAME_USE SidType = SidTypeUnknown;
    
        TOKEN_OWNER *Owner;
        // GetTokenInformation is initially called with the 3rd parm set to NULL
        // to get the size of the token information class that we need for the next
        // call to GetTokenInformation.  Note that TokenInformationLength parm must
        // be set to ZERO for this first call
        dwSize = 0;
        GetTokenInformation(Token, TokenOwner, NULL, 0, &dwSize);
        if (!dwSize)
        {
            printf("Error retrieving initial token information: error code0x%lx\n", GetLastError());
            return FALSE;
        }
        if (( Owner = (TOKEN_OWNER *)malloc(sizeof(DWORD) * dwSize) ) == NULL)
        {
            printf("Error allocating memory for Owner\n");
            return FALSE;
        }
        // This second call retrieves the required data which is stored in the Owner information class variable
        if(!GetTokenInformation(Token, TokenOwner, Owner, dwSize, &dwSize))
        {
            printf("Error retrieving token owner information class data: error code0x%lx\n", GetLastError());
            return FALSE;
        }
        dwSize = GetLengthSid(Owner->Owner);
        sid = (SID *)malloc(dwSize);
        // Extracts the sid (Security identifier) from the token owner information class
        CopySid(dwSize, sid, Owner->Owner);
        // Now we translate the returned sid (Security Identifier) which is in the following general format:
        // S-1-5-21-1482476501-963894560-682003330-123 to an account name.  This is passed to the LookupAccountSid
        // function which will find the sid for a named account.
        dwSize = MAX_NAME;
        if(!    LookupAccountSid(
            NULL,  // local computer
            sid,
            AcctName,
            (LPDWORD)&dwSize,
            DomainName,
            (LPDWORD)&dwSize,
            &SidType))
        {
            dwResult = GetLastError();
            if( dwResult == ERROR_NONE_MAPPED )
                strcpy(AcctName, "NONE_MAPPED" );
            else {
                printf("LookupAccountSid failed %u\n", GetLastError());
                return FALSE;
            }
        }
        printf( "User name: %s     Domain: %s    ", 
            DomainName, AcctName );
        free(sid);
        switch (SidType)
        {
            case SidTypeUser:
                printf("(user)\n");
                break;
            case SidTypeGroup:
                printf("(group)\n");
                break;
            case SidTypeDomain:
                printf("(domain)\n");
                break;
            case SidTypeAlias:
                printf("(alias)\n");
                break;
            case SidTypeWellKnownGroup:
                printf("(well-known group)\n");
                break;
            case SidTypeDeletedAccount:
                printf("(deleted account)\n");
                break;
            case SidTypeInvalid:
                printf("(invalid)\n");
                break;
            case SidTypeUnknown:
                printf("(unknown)\n");
                break;
            case SidTypeComputer:
                printf("(computer)\n");
                break;
        }
        free(Owner);
        return TRUE;
    }
    
    int main(void)
    {
        HANDLE hProcess;
        // Attempt to acquire SedebugPriviledge here for your current process
        // Enumerate all your processes here.  I just used the current process as an example.
        if (!OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &hProcess))
        {
            printf("OpenProcessToken failed: error code 0x%lx\n", GetLastError());
            return -1;
        }
        if (!GetTokenOwner(hProcess))
        {
            printf("GetTokenOwnerInformation for process failed\n");
            return -1;
        }
        return 0;
    }

  6. #6
    HelpingYouHelpUsHelpUsAll
    Join Date
    Dec 2007
    Location
    In your nightmares
    Posts
    223
    I was hoping for an example in C (as opposed to C++), i suppose it is a bit much to ask. I am impressed that Owner->Owner works (thought it was some complicated thing only in C++). Thanks.
    long time no C; //seige
    You miss 100% of the people you don't C;
    Code:
    if (language != LANG_C && language != LANG_CPP)
        drown(language);

  7. #7
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,059
    I was hoping for an example in C (as opposed to C++), i suppose it is a bit much to ask.
    The sample I posted was a stock WIN32 C example. There really isn't anything C++ about it. Is it possible that you're confusing the Owner->Owner with something that is used in C++. The Owner struct is dynamically allocated to accomodate the variable number of LUId & attributes arrays. Thus, the need for pointers. A static struct that uses such items as Owner.Owner would only cause your app to crash.

  8. #8
    HelpingYouHelpUsHelpUsAll
    Join Date
    Dec 2007
    Location
    In your nightmares
    Posts
    223
    Yeah, thanks your code worked perfectly and I was confusing that Owner->Owner with something in C++ as I had not seen it in the C tutorial.
    Also, SidTypeAlias can be either a SYSTEM, LOCAL SERVICE or NETWORK SERVICE, how do you use the well-known Well-known SIDs listed here: http://support.microsoft.com/kb/243330
    primerally these three as well as the user:
    SID: S-1-5-18
    Name: Local System
    Description: A service account that is used by the operating system.
    SID: S-1-5-19
    Name: NT Authority
    Description: Local Service
    SID: S-1-5-20
    Name: NT Authority
    Description: Network Service
    So mabye, if it falls under case SidTypeAlias: I could check if it is one of the above three. The user works fine, so all process started by the user come up correctly (the same as in taskman).
    long time no C; //seige
    You miss 100% of the people you don't C;
    Code:
    if (language != LANG_C && language != LANG_CPP)
        drown(language);

  9. #9
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,059
    One way of identifying the various well known sids would be to extract the Sid2Text function from the code in the link provided by Codeplug. You would call the Sid2Text function right after the CopySid function in the example code. It will translate the sid to a readable format such as

    Code:
    S-1-5-21-1482476501-963894560-682003330-123
    From here it's really obvious how to identify the specific well known sids.

  10. #10
    HelpingYouHelpUsHelpUsAll
    Join Date
    Dec 2007
    Location
    In your nightmares
    Posts
    223
    Sorry for brining this up again, but I have finally got round to trying the copy SID2Text function. What I have now gets the string fine (eg. "S-1-5-21...") but buf always comes out as "S-1-5-32-544" for Administrators. I know that there are some processes running as "LOCAL SERVICE" and "NETWORK SERVICE" aswell. Also when I check:
    Code:
    if (buf == "S-1-5-32-544") return "Administrators";
    It doesn't return "Administrators" even when buf = "S-1-5-32-544" (see code coloured in red). Here is all the code I have:
    Code:
    char *Sid2Text(PSID ps, char *buf, int bufSize)
    {
    	PSID_IDENTIFIER_AUTHORITY psia;
    	DWORD dwSubAuthorities;
    	DWORD dwSidRev = SID_REVISION;
    	DWORD i;
    	int n, size;
    	char *p;
    
    	if (!IsValidSid(ps))
    		return "";
    
    	psia = GetSidIdentifierAuthority(ps);
    	dwSubAuthorities = *GetSidSubAuthorityCount(ps);
    	size = 15 + 12 + (12 * dwSubAuthorities) + 1;
    	if ( bufSize < size )
    	{
    		SetLastError(ERROR_INSUFFICIENT_BUFFER);
    		return "";
    	}
    	size = wsprintf( buf, "S-%lu-", dwSidRev );
    	p = buf + size;
    
    	// Add SID identifier authority to the string.
    	if ( psia->Value[0] != 0 || psia->Value[1] != 0 )
    	{
    		n = wsprintf( p, "0x%02hx%02hx%02hx%02hx%02hx%02hx",
    		(USHORT) psia->Value[0], (USHORT) psia->Value[1],
    		(USHORT) psia->Value[2], (USHORT) psia->Value[3],
    		(USHORT) psia->Value[4], (USHORT) psia->Value[5]);
    		size += n;
    		p += n;
    	}
    	else
    	{
    		n = wsprintf( p, "%lu", ((ULONG) psia->Value[5]) +
    		( (ULONG) psia->Value[4] << 8 ) + ( (ULONG) psia->Value[3] << 16 ) +
    		( (ULONG) psia->Value[2] << 24));
    		size += n;
    		p += n;
    	}
    
    	//Add SID subauthorities to the string.
    	for ( i = 0; i < dwSubAuthorities; ++ i)
    	{
    		n = wsprintf(p, "-%lu", *GetSidSubAuthority(ps, i));
    		size += n;
    		p += n;
    	}
    
    	if (buf == "S-1-5-18") return "Local System";
    	if (buf == "S-1-5-19") return "Local Service";
    	if (buf == "S-1-5-20") return "Network Service";
    	if (buf == "S-1-5-32-544") return "Administrators";
    	if (buf == "S-1-5-32-545") return "Users";
    
    	return buf;
    }
    
    char *GetUserInfo(int ProcessID, HANDLE hProcess) {
    
    	HANDLE Token;
    	BOOL Debug = FALSE;
    	 if (!OpenProcessToken(hProcess, MAXIMUM_ALLOWED, &Token))
    		 return "SYSTEM";
    
        DWORD dwSize, dwResult;
        SID *sid;
    	char buf[MAX_PATH];
        char  AcctName[MAX_PATH],  DomainName[MAX_PATH];
        SID_NAME_USE SidType = SidTypeUnknown;
    
        TOKEN_OWNER *Owner;
        dwSize = 0;
        GetTokenInformation(Token, TokenOwner, NULL, 0, &dwSize);
        if (!dwSize)
        {
            if (Debug) SEEMsgBox("Error retrieving initial token information");
            return "SYSTEM";
        }
        if (( Owner = (TOKEN_OWNER *)malloc(sizeof(DWORD) * dwSize) ) == NULL)
        {
            if (Debug) SEEMsgBox("Error allocating memory for Owner");
            return "SYSTEM";
        }
        // This second call retrieves the required data which is stored in the Owner information class variable
        if(!GetTokenInformation(Token, TokenOwner, Owner, dwSize, &dwSize))
        {
            if (Debug) SEEMsgBox("Error retrieving token owner information class data");
            return "SYSTEM";
        }
        dwSize = GetLengthSid(Owner->Owner);
        sid = (SID *)malloc(dwSize);
        // Extracts the sid (Security identifier) from the token owner information class
        CopySid(dwSize, sid, Owner->Owner);
        // Now we translate the returned sid (Security Identifier) which is in the following general format:
        // S-1-5-21-1482476501-963894560-682003330-123 to an account name.  This is passed to the LookupAccountSid
        // function which will find the sid for a named account.
        dwSize = MAX_PATH;
        if(!LookupAccountSid(NULL,sid,AcctName,(LPDWORD)&dwSize,DomainName,(LPDWORD)&dwSize,&SidType))
        {
            dwResult = GetLastError();
            if( dwResult == ERROR_NONE_MAPPED )
                strcpy(AcctName, "NONE_MAPPED" );
            else {
    			if (Debug) SEEMsgBox("LookupAccountSid failed");
                return "SYSTEM";
            }
        }
        free(sid);
        switch (SidType)
        {
            case SidTypeUser:
    			int bufCharCount = 16380;
    			TCHAR  infoBuf[bufCharCount];
    			GetUserName(infoBuf, &bufCharCount);
    			return infoBuf;
                break;
            case SidTypeAlias:
    			return Sid2Text(Owner->Owner,buf, sizeof(buf));
    			//return "alias";
                break;
            case SidTypeUnknown:
    			return "unknown";
                break;
    		default: return "SYSTEM";
    		break;
        }
    }
    And here is the GetProcesses function that calls GetUserInfo:
    Code:
    int getProcesses() {
    
    	HMODULE hModule;
    	char szProcessName[MAX_PATH] = {0};
    	DWORD dwProcesses[1024], cbNeeded, cProcesses;
    	unsigned int i;
    	char PIDbuf[10];
    	char buf[50];
    
    	if (!EnumProcesses(dwProcesses, sizeof(dwProcesses), &cbNeeded))
    		return -1;
    	cProcesses = cbNeeded / sizeof(DWORD);
    	for (i = 0; i < cProcesses; i++)
    		if(dwProcesses[i] != 0)
    		{
    			HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
    				PROCESS_VM_READ, FALSE, dwProcesses[i]);
    			if (NULL != hProcess)
    			{
    				strcpy(szProcessName, "System");
    				if (EnumProcessModules(hProcess, &hModule, sizeof(hModule),
    					&cbNeeded))
    				{
    					GetModuleBaseName(hProcess, hModule, szProcessName,
    						sizeof(szProcessName)/sizeof(CHAR));
    				}
    			}
    			sprintf(PIDbuf, "%d", dwProcesses[i]);
    			InsertRow(GetDlgItem(hwndMain, ID_LISTVIEW), szProcessName,PIDbuf,
    			GetProcessMemoryWSS(hProcess, buf), GetProcessMemoryPWSS(hProcess, buf),
    		    GetProcessPriority(hProcess),
    			    GetUserInfo(dwProcesses[i], hProcess));
    			//AddIndex(szProcessName, i, 0);
    			CloseHandle(hProcess);
    		}
    	return cProcesses;
    }
    I have removed some of the comments that overlap with those of CodePlug's link (http://win32.mvps.org/security/opt_gti.cpp). Sorry it is so big, there is quite alot of it copyed form what has been previously posted.
    long time no C; //seige
    You miss 100% of the people you don't C;
    Code:
    if (language != LANG_C && language != LANG_CPP)
        drown(language);

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,012
    Sigh. Typical misunderstanding. Use strcmp instead of ==.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    HelpingYouHelpUsHelpUsAll
    Join Date
    Dec 2007
    Location
    In your nightmares
    Posts
    223
    Thanks for clearing that up. I found out that using == to compare strings only compares the pointers to the first characters, which will always be in different locations. Thanks Elysia, that should be it for this thread .

    /***** Fixed, I think strcmp might have solved this as well *****
    However, it always executes the first condition even when I use if, else if & else. Eg.
    Code:
    if (strcmp(buf,"S-1-5-18")) return "Local System";  //Always returns here
    	else if (strcmp(buf,"S-1-5-19")) return "Local Service";
    	else if (strcmp(buf,"S-1-5-20")) return "Network Service";
    	else if (strcmp(buf,"S-1-5-32-544")) return "Administrators";
    	else if (strcmp(buf,"S-1-5-32-545")) return "Users";
    And when i move say line 4 of the above to line 1, that always executes. The if, else if make no difference. I know that since I am iterating through all the processes, The PSID should be different for each one, yet they come out to be all the same, how can that happen?
    Last edited by P4R4N01D; 01-15-2008 at 08:22 PM. Reason: typo -> Fixed
    long time no C; //seige
    You miss 100% of the people you don't C;
    Code:
    if (language != LANG_C && language != LANG_CPP)
        drown(language);

  13. #13
    CSharpener vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,484
    strcmp returns 0 for matching strings
    The first 90% of a project takes 90% of the time,
    the last 10% takes the other 90% of the time.

  14. #14
    HelpingYouHelpUsHelpUsAll
    Join Date
    Dec 2007
    Location
    In your nightmares
    Posts
    223
    Thanks for pointing that out, so it should actually be:
    Code:
    if (!strcmp(buf,"S-1-5-18")) return "Local System";
    long time no C; //seige
    You miss 100% of the people you don't C;
    Code:
    if (language != LANG_C && language != LANG_CPP)
        drown(language);

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Posts
    23,012
    I suggest
    Code:
    if (strcmp(buf,"S-1-5-18") == 0) return "Local System";
    Because it's more readable and more explicit.

    So you're comparing char* to char* and you're returning char* too in several places. Hmm. Not a good idea usually. In fact, it won't work at all. You need to pass in a buffer (plus buffer size) and copy the string into it.
    And while we're at it - you probably need to check your indentation. It's probably weird because you're mixing spaces and tabs. You shouldn't; use one.
    And the if can more easily be if/else if.
    Last edited by Elysia; 01-17-2008 at 04:01 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Check number of times a process is running
    By linuxwolf in forum Windows Programming
    Replies: 6
    Last Post: 10-17-2008, 12:08 PM
  2. how to Search for a certain service and a process in Windows
    By daher in forum Windows Programming
    Replies: 11
    Last Post: 09-04-2008, 09:14 AM
  3. Odd memory leaks
    By VirtualAce in forum C++ Programming
    Replies: 11
    Last Post: 05-25-2006, 01:56 AM
  4. Menu Item Caption - /a for right aligned Accelerator?
    By JasonD in forum Windows Programming
    Replies: 6
    Last Post: 06-25-2003, 12:14 PM
  5. RE: Windows 98 boot up process - missing file
    By mithrandir in forum Tech Board
    Replies: 12
    Last Post: 08-19-2002, 11:00 PM

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