Here is another thing in C that would be worth a translation, if somebody wants to take that challenge.
char *get_owner_username_from_pid ( DWORD pid)
{
HANDLE hToken = NULL;
LPBYTE lpBytes = NULL;
LPTSTR lpszAccountName = NULL;
PTOKEN_USER lpTokenUser = NULL;
DWORD dwSize = 0;
BOOL bSuccess = FALSE;
HANDLE hProcess = NULL;
DWORD
dwSize01 = 0;
DWORD
dwSize02 = 0;
SID_NAME_USE
sid_name_use = {0};
hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
if (hProcess)
{
if (OpenProcessToken ( hProcess, TOKEN_QUERY, &hToken ) && hToken )
{
GetTokenInformation (hToken, TokenUser, (LPVOID)NULL, 0, &dwSize);
if (dwSize > 0)
{
lpBytes = allocmem (dwSize, 1);
lpTokenUser = (PTOKEN_USER)lpBytes;
bSuccess = GetTokenInformation (hToken, TokenUser, (LPVOID)lpTokenUser, dwSize, &dwSize);
if (bSuccess)
{
LookupAccountSid (NULL, (PSID)((lpTokenUser -> User).Sid), NULL,
(LPDWORD)&dwSize01, NULL,(LPDWORD)&dwSize02,
(PSID_NAME_USE)&sid_name_use);
if (dwSize01 > 0)
{
lpszAccountName = allocmem (dwSize01, 1);
bSuccess = LookupAccountSid (NULL, (PSID)(lpTokenUser->User.Sid), lpszAccountName,
(LPDWORD)&dwSize01, NULL,(LPDWORD)&dwSize02,
(PSID_NAME_USE)&sid_name_use);
}
}
freemem (lpBytes);
if (bSuccess && lpszAccountName)
{
return (char*) lpszAccountName;
}
}
}
}
return NULL;
}
This is similar:
' ========================================================================================
' Looks up the user name and domain name for the user account associated with the specified
' process identifier.
' ========================================================================================
FUNCTION AfxGetUserNameAndDomainFromPid (BYVAL pid AS DWORD, BYREF bstrUser AS WSTRING, BYREF bstrDomain AS WSTRING) AS LONG
LOCAL hProcess AS DWORD
LOCAL hToken AS DWORD
LOCAL ptiUser AS TOKEN_USER PTR
LOCAL cbti AS DWORD
LOCAL snu AS LONG ' SID_NAME_USE enumeration
LOCAL wszUser AS WSTRINGZ * 256
LOCAL wszDomain AS WSTRINGZ * %MAX_PATH
' // Open the local process
hProcess = OpenProcess(%PROCESS_ALL_ACCESS, %FALSE, pid)
IF hProcess = %NULL THEN
FUNCTION = GetLastError
EXIT FUNCTION
END IF
' // Get the access token associated with the process
IF ISFALSE OpenProcessToken(hProcess, %TOKEN_QUERY, hToken) THEN
FUNCTION = GetLastError
GOTO LExit
END IF
' // Obtain the size of the user information in the token
IF GetTokenInformation(hToken, %TokenUser, BYVAL %NULL, 0, cbti) <> 0 THEN
FUNCTION = GetLastError
GOTO LExit
END IF
' // Call should have failed due to zero-length buffer
IF GetLastError <> %ERROR_INSUFFICIENT_BUFFER THEN
FUNCTION = GetLastError
GOTO LExit
END IF
' // Allocate buffer for user information in the token
ptiUser = HeapAlloc(GetProcessHeap, %HEAP_GENERATE_EXCEPTIONS, cbti)
IF ptiUser = %NULL THEN
FUNCTION = %E_OUTOFMEMORY
GOTO LExit
END IF
' // Retrieve the user information from the token
IF ISFALSE GetTokenInformation(hToken, %TokenUser, BYVAL ptiUser, cbti, cbti) THEN
FUNCTION = GetLastError
GOTO LExit
END IF
' // Retrieve user name and domain name based on user's SID.
IF ISFALSE LookupAccountSidW(BYVAL %NULL, BYVAL @ptiUser.User.Sid, wszUser, SIZEOF(wszUser), _
wszDomain, SIZEOF(wszDomain), snu) <> 0 THEN
FUNCTION = GetLastError
GOTO LExit
EXIT FUNCTION
END IF
bstrUser = wszUser
bstrDomain = wszDomain
LExit:
' // Free resources
IF hProcess THEN CloseHandle(hProcess)
IF hToken THEN CloseHandle(hToken)
IF ptiUser THEN HeapFree(GetProcessHeap, 0, ptiUser)
END FUNCTION
' ========================================================================================
Thanks, Jose. Your code looks even better then the one from MS.
I'll try yours, its another master-piece i can learn from, how to do such things.
I compiled it (using the proper includes!) and it works.
That function and the following one are new additions to AfxSid.inc, where there are some useful functions more.
' ========================================================================================
' Tests whether the current user is a member of the Administrator's group.
' Caller is NOT expected to be impersonating anyone and is expected to be able to
' open its own process and process token.
' See: http://msdn.microsoft.com/en-us/library/windows/desktop/aa376389%28v=vs.85%29.aspx
' Return Value:
' TRUE - Caller has Administrators local group.
' FALSE - Caller does not have Administrators local group.
' Note: Replacement for the Windows API function IsUserAnAdmin because Microsoft warns
' about the use of this function and advices to call CheckTokenMembership directly.
' ========================================================================================
FUNCTION AfxIsUserAnAdmin () AS LONG
LOCAL IsMember AS LONG
LOCAL NtAuthority AS SID_IDENTIFIER_AUTHORITY
LOCAL AdministratorsGroup AS DWORD
NtAuthority.Value = $SECURITY_NT_AUTHORITY
IF AllocateAndInitializeSid(NtAuthority, 2, %SECURITY_BUILTIN_DOMAIN_RID, _
%DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, AdministratorsGroup) = 0 THEN EXIT FUNCTION
IF CheckTokenMembership(%NULL, BYVAL AdministratorsGroup, IsMember) <> 0 THEN
FUNCTION = IsMember
END IF
FreeSid(BYVAL AdministratorsGroup)
END FUNCTION
' ========================================================================================
"AfxSid.inc" another Goodie! I'll take a look.