如何在Windows服务程序中读写HKEY_CURRENT_USER注册表
在服务程序中想要对注册表HKEY_CURRENT_USER下的内容进行读写,不会返回失败,但是始终无效。原因是:
1.服务运行在系统权限之下,而不是任何一个用户
2.HKEY_CURRENT_USER存储的是当前用户的信息================>导致在服务中读取HKEY_CURRENT_USER实际操作的不是当前登录的用户的数据。
所以如果我要操作HKEY_CURRENT_USER之内的键值,就必须模拟当前用户去读取。
网上找了很久的资料,找到了一种实现方式,记录下,思路,代码如下
思路:让当前线程模拟当前登录用户的安全上下文(lets the calling thread impersonate the security context of a logged-on user)。使用ImpersonateLoggedOnUser 函数可以做到。
代码:
void windowsService() { //用户名 TCHAR szUsername[MAX_PATH]; BOOL flag = FALSE; HANDLE g_hToken = NULL; do { Logger::getInstance()->info(__FILE__, __LINE__, "开始获取token"); flag = INTER_GetExplorerToken(&g_hToken); if (flag) { Logger::getInstance()->info(__FILE__, __LINE__, "获取token失败"); break; } else { Logger::getInstance()->info(__FILE__, __LINE__, "获取token成功"); } // 模拟登录用户的安全上下文 if (FALSE == ImpersonateLoggedOnUser(g_hToken)) { break; } DWORD dwUsernameLen = MAX_PATH; if (FALSE == GetUserName(szUsername, &dwUsernameLen)) break; //// 到这里已经模拟完了,别忘记返回原来的安全上下文 if (FALSE == RevertToSelf()) break; } while (false); // 获取sid PSID pSid = NULL; LPWSTR sid; GetAccountSid(szUsername, &pSid); //获取得到的是一个结构体 ConvertSidToStringSid(pSid, &sid); //从结构体中得到sid串 wchar_t lswKeyPath[MAX_PATH] = { 0 }; StringCchPrintf(lswKeyPath, MAX_PATH, L"%ls\\SOFTWARE\\FatsClient", sid); LPCWSTR strSubKey = lswKeyPath;//_T("SOFTWARE\\FatsClient"); LPCWSTR strValueName = _T("path"); char strValue[256] = {0}; int length = 256; //读注册表 bool status = QueryRegKey(strSubKey, strValueName, strValue, length); sprintf_s(buf, "path=%s ,len=%d,status=%d,sid=%ls", strValue,length,status, sid); Logger::getInstance()->info(__FILE__, __LINE__,buf); }
DWORD INTER_GetExplorerToken(PHANDLE phExplorerToken) { DWORD dwStatus = ERROR_FILE_NOT_FOUND; BOOL bRet = FALSE; HANDLE hProcess = NULL; HANDLE hProcessSnap = NULL; char szExplorerPath[MAX_PATH] = { 0 }; char FileName[MAX_PATH] = { 0 }; PROCESSENTRY32 pe32 = { 0 }; try { hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hProcessSnap == INVALID_HANDLE_VALUE) { dwStatus = GetLastError(); } else { pe32.dwSize = sizeof(PROCESSENTRY32); int bMore = ::Process32First(hProcessSnap, &pe32); while (bMore) { if (::wcscmp(pe32.szExeFile, _T("explorer.exe")) == 0) { hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID); if (OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, phExplorerToken)) { dwStatus = 0; } else { dwStatus = GetLastError(); } break; } bMore = ::Process32Next(hProcessSnap, &pe32); } } } catch (...) { } if (hProcess) { CloseHandle(hProcess); } if (hProcessSnap) { CloseHandle(hProcessSnap); } return dwStatus; }
bool GetAccountSid(LPTSTR AccountName, PSID *Sid) { PSID pSID = NULL; DWORD cbSid = 0; LPTSTR DomainName = NULL; DWORD cbDomainName = 0; SID_NAME_USE SIDNameUse; BOOL bDone = FALSE; try { if (!LookupAccountName(NULL, AccountName, pSID, &cbSid, DomainName, &cbDomainName, &SIDNameUse)) { pSID = (PSID)malloc(cbSid); DomainName = (LPTSTR)malloc(cbDomainName * sizeof(TCHAR)); if (!pSID || !DomainName) { throw; } if (!LookupAccountName(NULL, AccountName, pSID, &cbSid, DomainName, &cbDomainName, &SIDNameUse)) { throw; } bDone = TRUE; } } catch (...) { //nothing } if (DomainName) { free(DomainName); } if (!bDone && pSID) { free(pSID); } if (bDone) { *Sid = pSID; } return bDone; }
bool QueryRegKey(LPCWSTR strSubKey, LPCWSTR strValueName, char *strValue, int length)//这里是传3个参数 { DWORD dwType = REG_SZ;//定义数据类型 DWORD dwLen = MAX_PATH; wchar_t data[MAX_PATH] = {0}; HKEY hKey; long err = ERROR_SUCCESS; //HKEY_CURRENT_USER KEY_READ err == RegOpenKeyEx(HKEY_USERS, strSubKey, 0, KEY_READ, &hKey); if (err == ERROR_SUCCESS) { char bufLog[128] = { 0 }; Logger::getInstance()->info(__FILE__, __LINE__, "RegOpenKeyEx success"); long errRet = RegQueryValueEx(hKey, _T("path"), NULL, &dwType, (LPBYTE)&data, &dwLen); if (ERROR_SUCCESS == errRet) { wcharTochar(data, strValue, length); //wprintf(L"data = %ls,len= %d\n", data, strlen((const char *)data)); sprintf_s(bufLog, "RegQueryValueEx:data=%ls ,len=%d", data, strlen((const char *)data)); Logger::getInstance()->info(__FILE__, __LINE__, bufLog); sprintf_s(bufLog, "RegQueryValueEx:strValue=%s ,length=%d", strValue, length); Logger::getInstance()->info(__FILE__, __LINE__, bufLog); RegCloseKey(hKey); //关闭注册表 return true; } else { char bufLog[128] = { 0 }; sprintf_s(bufLog, "RegQueryValueEx fail:ret=%d", errRet); Logger::getInstance()->info(__FILE__, __LINE__, bufLog); } RegCloseKey(hKey); //关闭注册表 } else { char bufLog[128] = { 0 }; sprintf_s(bufLog, "RegOpenKeyEx:strSubKey=%ls ,len=%ld", strSubKey, err); Logger::getInstance()->info(__FILE__, __LINE__, "RegOpenKeyEx successOpenRegKey return is false!"); } return false; }
所需要的头文件:#include <iostream> #include <assert.h> #include "windows.h" #include "tchar.h" #include "conio.h" #include "stdio.h" #include <strsafe.h> #include <sddl.h> #include "tlhelp32.h" #include <atlstr.h>