tag: 服务 HKEY_CURRENT_USER HKEY_USER 读取 RegQueryValueEx 注册表
我在服务程序中使用RegQueryValueEx读取注册表HKEY_CURRENT_USER下的内容,发现读取到的内容不是预期的内容。
原因是:
1.服务运行在系统权限之下,而不是任何一个用户
2.HKEY_CURRENT_USER存储的是当前用户的信息
================>导致在服务中读取HKEY_CURRENT_USER,不是当前登录的用户。同样,写入也不是。
所以如果我要操作HKEY_CURRENT_USER之内的键值,就必须模拟当前用户去读取。
有几种思路可以做到:
1.创建一个用户进程去操作注册表,使用CreateProcessAsUser函数可以做到
2.让当前线程模拟当前登录用户的安全上下文(lets the calling thread impersonate the security context of a logged-on user)。使用ImpersonateLoggedOnUser 函数可以做到。
第一个方法需要用到另外一个程序,感觉比较麻烦。
以下演示第二种方法:
1.要调用ImpersonateLoggedOnUser 函数,就先要获得该用户的令牌 (token)
DWORD pid = FindProcessByName(L"explorer.exe");
HANDLE ph = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
HANDLE token;
OpenProcessToken (ph, TOKEN_QUERY | TOKEN_DUPLICATE, &token);
2.模拟登录用户的安全上下文
ImpersonateLoggedOnUser (token);
3.获取用户名
wchar_t szBuf[MAX_PATH] = L"";
DWORD dwRet = MAX_PATH;
GetUserName(szBuf, &dwRet);
4.到这里已经模拟完了,别忘记返回原来的安全上下文
RevertToSelf();
5.获取sid
PSID pSid = NULL;
LPWSTR sid;
GetAccountSid(szBuf, &pSid); //获取得到的是一个结构体
ConvertSidToStringSid(pSid, &sid); //从结构体中得到sid串
6.构造 sid+注册表位置
例如想读取的注册表位置为,Software\\Microsoft\\Windows\\CurrentVersion\\Intern Settings\\
你得到的sid为:S-1-5-21-1229272821-1897051121-682003330-1003
那么,应该组合成 :"S-1-5-21-1229272821-1897051121-682003330-1003\\Software\\Microsoft\\Windows\\CurrentVersion\\Intern Settings\\";
7.可以读取了,注意RegQueryValueEx的参数“HKEY_USERS”
keyPosition就是上面构造的那一串。
bool result = RegOpenKeyEx(HKEY_USERS,keyPosition,0,KEY_READ,&hKEY);
DWORD it = sizeof(DWORD);
DWORD dwType = REG_NONE;
DWORD dwCount = 0;
RegQueryValueEx(hKEY, 你要读的键值名, NULL, &dwType, NULL, &dwCount); //获取长度
RegQueryValueEx(hKEY,你要读的键值名, NULL, &dwType, (LPBYTE)(&it), &dwCount);//读取
流程就是这样,有什么bug,欢迎反映
补上前面用到的两个函数:
//
// 查找进程pid
//
DWORD FindProcessByName(LPCWSTR ProcessName)
{
HANDLE hHandle;
DWORD i;
BOOL Next;
wchar_t szName[MAX_PATH];
PROCESSENTRY32 p32 = {sizeof(p32)};
hHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
Next = Process32First(hHandle, &p32);
i = 0;
while (Next)
{
wsprintf(szName, L"%s", p32.szExeFile);
if (lstrcmpi(szName, ProcessName) == 0)
{
return p32.th32ProcessID ;
}
Next = Process32Next(hHandle, &p32);
i++;
}
CloseHandle(hHandle);
return 0;
}
//
//获取用户sid
//
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;
}