Иногда приложению требуется знать имя пользователя и имя домена для
текущего потока. Эта статья демонстрирует, как сделать это в 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:
ЗАМЕЧАНИЕ: Если требуется только имя пользователя, то можно
использовать функцию 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
|