在服务程序中想要对注册表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
", 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>