Как получить текущее имя пользователя и имя домена в 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:

Как получить текущее имя пользователя и домена в 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; }



Литература по Windows NT