標籤:style blog http color io os 使用 ar for
在服務程式中想要對註冊表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 函數可以做到。
第一個方法需要用到另外一個程式,感覺比較麻煩。
以下示範第二種方法:
BOOL GetTokenByName(HANDLE &hToken,LPTSTR lpName){ if (!lpName) return FALSE; HANDLE hProcessSnap = NULL; BOOL bRet = FALSE; PROCESSENTRY32 pe32 = {0}; hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hProcessSnap == INVALID_HANDLE_VALUE) return (FALSE); pe32.dwSize = sizeof(PROCESSENTRY32); if (Process32First(hProcessSnap, &pe32)) { do { if(!_tcscmp(_tcsupr(pe32.szExeFile),_tcsupr(lpName))) { HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,pe32.th32ProcessID); bRet = OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,&hToken); CloseHandle (hProcess); CloseHandle (hProcessSnap); return (bRet); } } while (Process32Next(hProcessSnap, &pe32)); bRet = FALSE; } else { bRet = FALSE; } CloseHandle (hProcessSnap); return (bRet);}////擷取使用者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;}// 類比目前使用者環境設定預設印表機void SimulateCurrentUserSetDefaultPrinter(){ HANDLE hToken = NULL; do { if (!GetTokenByName(hToken,_T("EXPLORER.EXE"))) { break; } // 類比登入使用者的安全上下文 if(FALSE == ImpersonateLoggedOnUser(hToken)) { break; } // 擷取使用者名稱 TCHAR szUsername[MAX_PATH]; DWORD dwUsernameLen = MAX_PATH; if(FALSE == GetUserName(szUsername, &dwUsernameLen)) break; // 到這裡已經類比完了,別忘記返回原來的安全上下文 if(FALSE == RevertToSelf()) break; // 擷取sid PSID pSid = NULL; LPWSTR sid; GetAccountSid(szUsername, &pSid); //擷取得到的是一個結構體 ConvertSidToStringSid(pSid, &sid); //從結構體中得到sid串 // 設定預設印表機資訊 //SetDefaultPrinter(PSSD_PRINTER_NAME); HKEY hKey; int i=0; //操作結果:0==succeed wchar_t lswRegValue[MAX_PATH]; StringCchPrintf(lswRegValue, MAX_PATH, L"%s,winspool,%s", PSSD_PRINTER_NAME, PSSD_PRINTER_PORT_NAME); wchar_t lswKeyPath[MAX_PATH] = {0}; StringCchPrintf(lswKeyPath, MAX_PATH, L"%s\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows", sid); if(RegOpenKeyEx(HKEY_USERS, lswKeyPath, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) { if(RegSetValueEx(hKey,L"Device",NULL,REG_SZ, (const LPBYTE)lswRegValue, (wcslen(lswRegValue) + 1) * sizeof(wchar_t))!=ERROR_SUCCESS) { i=1; } RegCloseKey(hKey); } else { i=1; } if(1 == i) { OutputDebugStringW(L"STST: 設定預設印表機失敗"); } else { SendNotifyMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0); } } while (false); if(NULL != hToken) CloseHandle(hToken);}
如何在Windows服務程式中讀寫HKEY_CURRENT_USER註冊表