Как получить текущее имя пользователя и имя домена в Windows NT
Иногда приложению требуется знать имя пользователя и имя домена для текущего потока. Эта статья демонстрирует, как сделать это в Windows NT при помощи security функций в Win32 Application Programming Interface (API). До Windows NT, считалось, что поток запускается под учётной записью пользователя, залогинившегося в интерактивном режим. Однако, Windows NT позволяет потокам запускаться под разными учётными записями. Например, поток, запущенный как сервис, имеет имя домена AUTHORITY и имя пользователя SYSTEM, Это значит, что сервисы запускаются с правами системы.
Если необходимо получить как имя пользователя так и имя домена для текущего потока, то сначала, при помощи функции GetTokenInformation надо распаковать пользовательский идентификатор (SID) из потока. А затем вызвать функцию LookupAccountSid, чтобы получить имя учётной записи и имя домена, связанные с этим SID. Нижеприведённый пример, демонстрирует данную технологию.
ЗАМЕЧАНИЕ: Если требуется только имя пользователя, то можно использовать функцию GetUserName, которая прекрасно работает в Windows 95, Windows 98, Windows NT, и Windows 2000.
Пример кода
Следующий пример демонстрирует, как программно получить имя пользователя и имя домена в Windows NT:
//**********************************************************************
//
// ФУНКЦИЯ: GetCurrentUserAndDomain - это функция, определяющая
// имя пользователя и имя домена учётной записи,
// связанной с вызывающим потоком.
//
// ПАРАМЕТРЫ: szUser - буфер, который получает имя пользователя
// pcchUser - размер szUser в символах
// szDomain - буфер, принимающий имя домена
// pcchDomain - размер szDomain в символах
//
// ВОЗВРАЩАЕМЫЕ ЗНАЧЕНИЯ: TRUE если функция выполнена успешно. Иначе, FALSE
// и GetLastError() вернёт код ошибки.
//
// Если любой из буферов слишком маленький, то
// GetLastError() вернёт ERROR_INSUFFICIENT_BUFFER,
// а pcchUser и pcchDomain будут откорректированы в
// соответствии с требуемыми размерами.
//
//**********************************************************************
BOOL GetCurrentUserAndDomain(PTSTR szUser, PDWORD pcchUser,
PTSTR szDomain, PDWORD pcchDomain) {
BOOL fSuccess = FALSE;
HANDLE hToken = NULL;
PTOKEN_USER ptiUser = NULL;
DWORD cbti = 0;
SID_NAME_USE snu;
__try {
// Получаем маркёр доступа вызывающего потока.
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE,
&hToken)) {
if (GetLastError() != ERROR_NO_TOKEN)
__leave;
// Если маркёра потока не существует, то запрашиваем маркёр процесса.
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY,
&hToken))
__leave;
}
// Получаем размер информации о пользователе в маркёре.
if (GetTokenInformation(hToken, TokenUser, NULL, 0, &cbti)) {
// Если длина буфера равна нулю, то ошибка.
__leave;
} else {
// Если длина буфера равна нулю, то ошибка.
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
__leave;
}
// Распределяем буфер для информации о пользователе в маркёре.
ptiUser = (PTOKEN_USER) HeapAlloc(GetProcessHeap(), 0, cbti);
if (!ptiUser)
__leave;
// Получаем информацию о пользователе из маркёра.
if (!GetTokenInformation(hToken, TokenUser, ptiUser, cbti, &cbti))
__leave;
// Получаем имя пользователя и имя домена по пользовательскому SID.
if (!LookupAccountSid(NULL, ptiUser->User.Sid, szUser, pcchUser,
szDomain, pcchDomain, &snu))
__leave;
fSuccess = TRUE;
} __finally {
// Освобождаем ресурсы.
if (hToken)
CloseHandle(hToken);
if (ptiUser)
HeapFree(GetProcessHeap(), 0, ptiUser);
}
return fSuccess;
}