Retrieving current user and domain names on Windows NT, Windows 2000, or Windows XP Code Example
A program may sometimes need to display the user name and domain name for the
current thread. Prior to Windows NT, it could be assumed that a thread was running
under the account of the interactively logged on user. Windows NT, however,
allows threads to run under multiple security contexts, potentially representing
multiple users. For instance, in a client/server application, a thread in the
server might impersonate a client through the ImpersonateNamedPipeClient() function.
In this case, it runs under the user context of the client. Another example
of a thread running in a different security context is a service thread, which
has a domain name of NT AUTHORITY and a user name of SYSTEM, assuming that the
service is running in the local system account.
If you need to obtain both the user name and the domain name for the current
thread, you must first extract the user's security identifier (SID) from the
thread's access token by using the GetTokenInformation() function. Then, a call
to the LookupAccountSid() function can be used to retrieve the account name
and domain name associated with the SID. The sample code at the end of this
article demonstrates this technique. The 32-bit functions just mentioned are
not available on Microsoft Windows 95 or Microsoft Windows 98. To retrieve the
name and domain of the interactive user on Windows 95 or Windows 98, you must
call a 16-bit LAN Manager function. The following program example demonstrates
how to programmatically retrieve the user name and domain name on Windows NT
by using security functions within the Win32 Application Programming Interface
(API).
Create a new empty Win32 console application project. Give a suitable project name and change the project location if needed.
Then, add the source file and give it a suitable name.
Next, add the following source code.
#include <windows.h>
#include <stdio.h>
//**********************************************************************
// FUNCTION: GetCurrentUserAndDomain - This function looks up
// the user name and domain name for the user account
// associated with the calling thread.
// PARAMETERS: szUser - a buffer that receives the user name
// pcchUser - the size, in characters, of szUser
// szDomain - a buffer that receives the domain name
// pcchDomain - the size, in characters, of szDomain
// RETURN VALUE: TRUE if the function succeeds. Otherwise, FALSE and
// GetLastError() will return the failure reason.
//
// If either of the supplied buffers are too small,
// GetLastError() will return ERROR_INSUFFICIENT_BUFFER
// and pcchUser and pcchDomain will be adjusted to
// reflect the required buffer sizes.
//**********************************************************************
#define MAX_NAME 256
int wmain(int argc, WCHAR **argv)
{
WCHAR szUser[MAX_NAME];
WCHAR szDomain[MAX_NAME];
BOOL fSuccess = FALSE;
HANDLE hToken = NULL;
PTOKEN_USER ptiUser = NULL;
DWORD cbti = 0;
SID_NAME_USE snu;
__try {
// Get the calling thread's access token.
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken))
{
if (GetLastError() != ERROR_NO_TOKEN)
{
wprintf(LNo thread token available!\n);
__leave;
}
// Retry against process token if no thread token exists.
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
wprintf(LNo process token available! error %u\n, GetLastError());
__leave;
}
else
wprintf(LProcess token available! Overiding the thread token if available!\n);
}
else
wprintf(LThread token available!\n);
// Obtain the size of the user information in the token.
if (GetTokenInformation(hToken, TokenUser, NULL, 0, &cbti))
{
// Call should have failed due to zero-length buffer.
wprintf(LGetting the size of the user info in the token!\n);
__leave;
}
else
{
// Call should have failed due to zero-length buffer.
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
wprintf(LInsufficient buffer! Re-allocating...\n);
__leave;
}
}
// Allocate buffer for user information in the token.
ptiUser = (PTOKEN_USER) HeapAlloc(GetProcessHeap(), 0, cbti);
if (!ptiUser)
{
wprintf(LHeap allocation for ptiUser failed, error %u\n, GetLastError());
__leave;
}
else
wprintf(LHeap allocated for ptiUser!\n);
// Retrieve the user information from the token.
if (!GetTokenInformation(hToken, TokenUser, ptiUser, cbti, &cbti))
{
wprintf(LGetTokenInformation() failed, error %u\n, GetLastError());
__leave;
}
else
wprintf(LRetrieving the user info from the token!\n);
// Retrieve user name and domain name based on user's SID.
// The 1st NULL means search the local pc and then domain controller...
if (!LookupAccountSid(NULL, ptiUser->User.Sid, szUser, &cbti, szDomain, &cbti, &snu))
{
wprintf(LLookupAccountSid() failed, error %u\n, GetLastError());
__leave;
}
else
{
wprintf(LLookupAccountSid() is OK\n);
wprintf(LCurrent user: %s\n, szUser);
wprintf(LCurrent domain name (or local pc): %s\n, szDomain);
}
// All should be OK
fSuccess = TRUE;
}
__finally
{
// Free resources.
wprintf(LFreeing up all the allocated resources and handle!\n);
if (hToken)
CloseHandle(hToken);
if (ptiUser)
HeapFree(GetProcessHeap(), 0, ptiUser);
}
return fSuccess;
}
Build and run the project. The following screenshot is a sample output.