如何在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>

 

posted @ 2020-03-04 16:46  木木ing  阅读(984)  评论(0编辑  收藏  举报