Как получить текущее имя пользователя и имя
домена в Windows NT
Иногда приложению требуется знать имя
пользователя и имя домена для текущего потока.
Эта статья демонстрирует, как сделать это в Windows NT
при помощи security функций в Win32 Application Programming Interface
(API).
До Windows NT, считалось, что поток запускается под
учётной записью пользователя, залогинившегося в
интерактивном режим. Однако, Windows NT позволяет
потокам запускаться под разными учётными
записями. Например, поток, запущенный как сервис,
имеет имя домена AUTHORITY и имя пользователя SYSTEM, Это
значит, что сервисы запускаются с правами
системы.
Если необходимо получить как имя пользователя
так и имя домена для текущего потока, то сначала,
при помощи функции GetTokenInformation надо
распаковать пользовательский идентификатор (SID)
из потока. А затем вызвать функцию LookupAccountSid,
чтобы получить имя учётной записи и имя домена,
связанные с этим SID. Нижеприведённый пример,
демонстрирует данную технологию.
32-битные функции, упомянутые выше не доступны в
Microsoft Windows 95 или Microsoft Windows 98. Чтобы получить имя и
домен залогинившегося пользователя в Windows 95 или
Windows 98, Вам необходимо вызвать функцию 16-битного
LAN Менеджера. Как это делается, можно узнать в
статье из Microsoft Knowledge Base:
Q155698 Как получить текущее имя
пользователя и домена в Windows 95 и Windows 98
ЗАМЕЧАНИЕ: Если требуется только имя
пользователя, то можно использовать функцию 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;
}
|