转载自: https://blog.csdn.net/nirendao/article/details/52077637
有效性未经验证
首先,对“活动用户”的定义是,当前拥有桌面的用户。对于Windows XP及其以后的系统,即使是可以多个用户同时登录了,拥有桌面的也仅仅只有一个。
如果系统级服务调用Windows API来获取注册表键值的时候,直接以HKEY_CURRENT_USER为参数,则取到的并不是活动用户的注册表信息,而是系统用户的注册表信息,即,位于HKEY_LOCAL_MACHINE之下的。那么如何以系统服务的身份获取活动用户(真正的HKEY_CURRENT_USER)之下的注册表信息呢?主要有以下这么几步:
系统服务程序调用 WTSGetActiveConsoleSessionId() 以获取当前活动用户的sessionId.
以此sessionId为参数,调用 WTSQueryUserToken() 以获取当前活动用户的 hUserToken.
以此hUserToken为参数,调用 DuplicateTokenEx() 以复制一个token,如hFakeToken.
以此hFakeToken为参数,调用 ImpersonateLoggedOnUser() 以模拟活动用户登录的环境.
调用 RegOpenCurrentUser() 以打开活动用户的 HKEY_CURRENT_USER.
调用 RegOpenKeyEx() 以获取指定位置的注册表键值.
以QT和Windows API来实现的代码如下:
1 void GetUserRegistryFromSystemService() 2 { 3 #ifdef Q_OS_WIN 4 5 DWORD sessionId = WTSGetActiveConsoleSessionId(); 6 qInfo() << "Session ID = " << sessionId; 7 8 wchar_t * ppUserName[100]; 9 DWORD sizeOfUserName; 10 WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, ppUserName, &sizeOfUserName); 11 qInfo() << "Windows User Name = " << QString::fromWCharArray(*ppUserName); 12 13 std::wstring strValueOfBinDir = L"Unknown Value"; 14 LONG regOpenResult = ERROR_SUCCESS; 15 16 HANDLE hUserToken = NULL; 17 HANDLE hFakeToken = NULL; 18 19 if (WTSQueryUserToken(sessionId, &hUserToken)) 20 { 21 if (DuplicateTokenEx(hUserToken, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &hFakeToken) == TRUE) 22 { 23 if (ImpersonateLoggedOnUser(hFakeToken)) 24 { 25 HKEY hKey; 26 27 regOpenResult = RegOpenCurrentUser(KEY_READ, &hKey); 28 if (regOpenResult != ERROR_SUCCESS) 29 { 30 qCritical() << "Failed to call RegOpenCurrentUser(), Error is " << regOpenResult; 31 } 32 33 HKEY hSubKey; 34 35 RegOpenKeyEx(hKey, 36 TEXT("Software\Baidu\BaiduYunGuanjia"), 37 0, 38 KEY_READ, 39 &hSubKey); 40 GetStringRegKey(hSubKey, TEXT("installDir"), strValueOfBinDir, TEXT("Unknown")); 41 42 RevertToSelf(); 43 } 44 else 45 { 46 qCritical() << "Failed to ImpersonateLoggedOnUser..."; 47 } 48 CloseHandle(hFakeToken); 49 } 50 else 51 { 52 qCritical() << "Failed to call DuplicateTokenEx..."; 53 } 54 CloseHandle(hUserToken); 55 } 56 else 57 { 58 qCritical() << "Failed to get the user token of session " << sessionId; 59 } 60 61 qInfo() << "The value of Registry is " << QString::fromWCharArray( strValueOfBinDir.c_str() ); 62 63 #endif 64 }