如何在Windows服務程序中讀寫HKEY_CURRENT_USER注冊表


在服務程序中想要對注冊表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);
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM