Windows NT 系列允許執行緒在不同安全性內容下運行(模擬、服務帳號)。若需取得「目前執行緒實際關聯」的使用者與網域名稱,必須存取執行緒/進程 Token 並解析 SID。
OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken) 取得執行緒 Token;失敗且 ERROR_NO_TOKEN 則 OpenProcessToken(GetCurrentProcess(), ...) 取得進程 Token。GetTokenInformation(hToken, TokenUser, ...) 取得 TOKEN_USER 結構中的 SID。LookupAccountSid(NULL, pTokenUser->User.Sid, UserName, ..., DomainName, ..., &sn) 解析 SID 為使用者名稱與網域名稱。BOOL GetThreadUserDomain(TCHAR* szUser, DWORD cchUser, TCHAR* szDomain, DWORD cchDomain) {
HANDLE hToken = NULL; BYTE buf[1024]; DWORD dwLen = 0; BOOL bOk = FALSE;
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken)) {
if (GetLastError() == ERROR_NO_TOKEN)
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
else return FALSE;
}
if (GetTokenInformation(hToken, TokenUser, buf, sizeof(buf), &dwLen)) {
PTOKEN_USER pUser = (PTOKEN_USER)buf;
SID_NAME_USE snu;
bOk = LookupAccountSid(NULL, pUser->User.Sid, szUser, &cchUser, szDomain, &cchDomain, &snu);
}
CloseHandle(hToken); return bOk;
}
作者發現控制台應用程式呼叫 LookupAccountSid 總是失敗,GetLastError() == 14(儲存空間不足),而 GUI 專案正常。原因未明,文中提供雙版本原始碼供參考。
GetUserName 支援 Win9x/NT/2000,自動檢查執行緒/進程 Token。