• 如何在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);
    }
  • 相关阅读:
    mssql索引视图无法对视图创建 索引,因为该视图未绑定到架构
    说说回车键触发表单提交的问题
    在C#中使用SqlDbType.Xml类型参数
    使用nginx实施负载均衡
    SQL Server 索引中include的魅力(具有包含性列的索引)
    群发“站内信”的实现
    ORM映射框架总结终极JSON
    51 地图基本接口(二)
    通用短信平台接口
    ORM映射框架总结Flash 处理
  • 原文地址:https://www.cnblogs.com/monotone/p/3966900.html
Copyright © 2020-2023  润新知