分类: C/C++
2008-03-14 13:51:08
BOOL CSecurityTool::GetCurrProcessUser(CString& strName) { BOOL bRet(TRUE); strName = _T(""); DWORD dwSize = MAX_PATH; TCHAR *pszName = new TCHAR[dwSize]; if (!GetUserName(pszName, &dwSize)) { delete[] pszName; pszName = new TCHAR[dwSize]; bRet = GetUserName(pszName, &dwSize); } strName = pszName; delete[] pszName; return bRet; }此函数目的准确来说是获取当前线程的用户名(MSDN语:retrieves the user name of the current thread)。如果是NT service(NT服务程序)将此进程启动,得到的结果是NT Service进程的用户名,即“SYSTEM”,而不是登陆用户名;同理,如果此进程是通过CreateProcessAsUser创建的,GetUserName获取的用户将是“AsUser”的用户名。另外,如果当前线程正impersonate其他用户环境(用函数ImpersonateLoggedOnUser可达到此目的),它获取的将是其他用户名。因此,此函数只能在特定环境中才可以获取登陆用户名。
BOOL CSecurityTool::GetLogUserXP(CString& strName) { BOOL bRet = FALSE; strName = _T(""); //for xp or above TCHAR *szLogName = NULL; DWORD dwSize = 0; if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSUserName, &szLogName, &dwSize)) { strName = szLogName; WTSFreeMemory(szLogName); bRet = TRUE; } return bRet; }如果用户还没有登陆,获取的用户名将为空(譬如在NT service程序中)。虽然MSDN中指明WTSQuerySessionInformation可以在win2000 pro 中使用,但由于安装win2000 professional时,terminal service是没有安装的(除非用特殊方法如第三方工具可以安装terminal service),所以调用此函数会失败,需要寻找其他方法。
//获取win2000登陆用户 BOOL CSecurityTool::GetLogUser2K(CString& strName) { BOOL bRet = FALSE; HANDLE hSnapshot = NULL; strName = _T(""); __try { // Get a snapshot of the processes in the system hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot == NULL) { __leave; } PROCESSENTRY32 pe32; pe32.dwSize = sizeof(pe32); // Find the "System" process BOOL fProcess = Process32First(hSnapshot, &pe32); while (fProcess) { if (lstrcmpi(pe32.szExeFile, TEXT("explorer.exe")) == 0) { TCHAR szUserName[MAX_PATH]; if (GetProcessUser(pe32.th32ProcessID, szUserName, MAX_PATH)) { bRet = TRUE; strName = szUserName; } break; } fProcess = Process32Next(hSnapshot, &pe32); } if (!fProcess) { __leave; // Didn''t find "System" process } } __finally { // Cleanup the snapshot if (hSnapshot != NULL) CloseHandle(hSnapshot); } return bRet; } //获取进程的用户名 BOOL CSecurityTool::GetProcessUser(DWORD dwProcessID, TCHAR *szUserName, DWORD nNameLen) { BOOL fResult = FALSE; HANDLE hProc = NULL; HANDLE hToken = NULL; TOKEN_USER *pTokenUser = NULL; __try { // Open the process with PROCESS_QUERY_INFORMATION access hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessID); if (hProc == NULL) { __leave; } fResult = OpenProcessToken(hProc, TOKEN_QUERY, &hToken); if(!fResult) { __leave; } DWORD dwNeedLen = 0; fResult = GetTokenInformation(hToken,TokenUser, NULL, 0, &dwNeedLen); if (dwNeedLen > 0) { pTokenUser = (TOKEN_USER*)new BYTE[dwNeedLen]; fResult = GetTokenInformation(hToken, TokenUser, pTokenUser, dwNeedLen, &dwNeedLen); if (!fResult) { __leave; } } else { __leave; } SID_NAME_USE sn; TCHAR szDomainName[MAX_PATH]; DWORD dwDmLen = MAX_PATH; fResult = LookupAccountSid(NULL, pTokenUser->User.Sid, szUserName, &nNameLen, szDomainName, &dwDmLen, &sn); } __finally { if (hProc) ::CloseHandle(hProc); if (hToken) ::CloseHandle(hToken); if (pTokenUser) delete[] (char*)pTokenUser; return fResult; } }熟悉win2000系统的同仁肯定会发现此方法存在缺陷:explorer.exe进程可能不存在(被用户kill掉或自己中断了),这时候这个方法就获取不到登陆用户名。但在没有更好方法前,只能将就。