c++练习守护注册表服务程序

来源:互联网 发布:知之深爱之切全书内容 编辑:程序博客网 时间:2024/06/14 00:40

服务程序读写 HKEY_CURRENT_USER 注册表不同于普通程序,需要在路径前面添加用户的SID + “注册表路径”才是当前登录用户的正确注册表位置, 并且主键 HKEY_CURRENT_USER 需改为 HKEY_USERS 。其他路径不用变。
资料参考 http://www.2cto.com/kf/201111/111990.html

// SCguardHomepage.cpp : 定义控制台应用程序的入口点。///*=================================================================================================    如何安装服务:    运行命令提示符cmd.exe    输入 sc create SCguardHomepage binpath= E:\vs-proj\SCguardHomepage\Release\SCguardHomepage.exe    输入 sc start SCguardHomepage  启动服务    输入 sc query  会在最底部显示你的服务当前的状态    输入 sc stop SCguardHomepage  停止服务    输入 sc delete SCguardHomepage  删除服务,该服务将在下次重启后删除,在重启之前将不能注册同一个名字的服务。=================================================================================================*/#include "stdafx.h"#include <stdio.h>#include <Windows.h>#include "CLog.h"#include"tlhelp32.h"#include<Sddl.h>#include <WtsApi32.h>#pragma comment(lib, "WtsApi32.lib")#define SLEEP_TIME 5000 //间隔时间#define FILE_PATH "C:\\cLog.log" //信息输出文件using namespace std;HKEY hKEY;bool brun=false;SERVICE_STATUS servicestatus;SERVICE_STATUS_HANDLE hstatus;int WriteToLog(char* str);void WINAPI ServiceMain(int argc, char** argv);void WINAPI CtrlHandler(DWORD request);int InitService();/*void showNowLog(){    m_LogModule->Init();                ////CLog类的成员    m_LogModule->ShowNowLogConsole();   //Console 显示}void hideNowLog(){    m_LogModule->HideNowLogConsole();   //隐藏 Console}*/int WriteToLog(char* str){    FILE* pfile;    fopen_s(&pfile,FILE_PATH,"a+");    if (pfile==NULL)    {        return -1;    }    time_t t = time(0);     char tmp[64];     strftime( tmp, sizeof(tmp), "%Y/%m/%d %X",localtime(&t));     fprintf_s(pfile,"%s --> %s\n",tmp,str);    fclose(pfile);    return 0;}//查找进程IDDWORD 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;}std::string getUserSid(){    //要调用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);    //模拟登录用户的安全上下文    ImpersonateLoggedOnUser (token);    //获取用户名    wchar_t szBuf[MAX_PATH] = L"";    DWORD dwRet = MAX_PATH;    GetUserName(szBuf, &dwRet);    //到这里已经模拟完了,别忘记返回原来的安全上下文     RevertToSelf();     //获取sid     PSID pSid = NULL;     LPWSTR sid;     GetAccountSid(szBuf, &pSid); //获取得到的是一个结构体     ConvertSidToStringSid(pSid, &sid); //从结构体中得到sid串     //可以读取了,注意RegQueryValueEx的参数“HKEY_USERS”     char cStr[_MAX_PATH];     memset(cStr,'\0',_MAX_PATH);     int iLength = WideCharToMultiByte(CP_ACP, 0, sid, -1, NULL, 0, NULL, NULL);         WideCharToMultiByte(CP_ACP, 0, sid, -1, cStr, iLength, NULL, NULL);       std::string strSid = cStr;     return strSid;}/*------------------------------------------------------------------------------------------------    将你需要执行的任务放到该函数中循环执行即可。    这就是服务程序的工作函数。在ServiceMain执行你的任务前,    需要给SERVICE_TABLE_ENTRY 分派表结构体进行赋值,    注意由于此时服务还没有开始执行你的任务所以我们将服务的状态设置为SERVICE_START_PENDING,即正在初始化------------------------------------------------------------------------------------------------*/void WINAPI ServiceMain(int argc, char** argv){    servicestatus.dwServiceType = SERVICE_WIN32;    servicestatus.dwCurrentState = SERVICE_START_PENDING;    servicestatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN|SERVICE_ACCEPT_STOP;//在本例中只接受系统关机和停止服务两种控制命令    servicestatus.dwWin32ExitCode = 0;    servicestatus.dwServiceSpecificExitCode = 0;    servicestatus.dwCheckPoint = 0;    servicestatus.dwWaitHint = 0;    //Hstatus为SERVICE_STATUS_HANDLE类型的全局变量。当需要改变服务状态时SetServiceStatus()函数需要它做为参数来标识一个服务。    hstatus = ::RegisterServiceCtrlHandler(L"SCguardHomepage", CtrlHandler);    if (hstatus==0)    {        //NowLogStringEx(_T("RegisterServiceCtrlHandler failed"));        WriteToLog("RegisterServiceCtrlHandler failed");        return;    }    //NowLogStringEx(_T("RegisterServiceCtrlHandler success"));    WriteToLog("RegisterServiceCtrlHandler success");    //向SCM 报告运行状态    servicestatus.dwCurrentState = SERVICE_RUNNING;    SetServiceStatus (hstatus, &servicestatus);    //下面就开始任务循环了,你可以添加你自己希望服务做的工作    brun=true;    while (brun)    {        //----------------------------------------        char pBuf[500];        memset(pBuf,'\0',500);        DWORD dllPathLength = GetModuleFileNameA(NULL, pBuf, sizeof(pBuf));        *(strrchr( pBuf, '\\') ) = 0;        strcat_s(pBuf, "\\lewangIE.exe");        CString strDefaultKeyValue=pBuf;        strDefaultKeyValue=_T("\"")+strDefaultKeyValue+_T("\" \"%1\"");         WriteToLog(pBuf);        //--------------------------------------------------------------------服务读注册表例子        std::string keyPosition = getUserSid();        keyPosition += "\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice";        WriteToLog(const_cast<char*>(keyPosition.c_str()));        int result = RegOpenKeyExA(HKEY_USERS,keyPosition.data(),0,KEY_READ,&hKEY);        if(result != 0)        { WriteToLog("没打开注册表");return;}        DWORD dwKeyValueType;        char szRegItem[256] = { 0 }; //注册表值        DWORD iRegItemLen = sizeof(szRegItem);        result = RegQueryValueExA(hKEY, "Progid", 0, &dwKeyValueType, (LPBYTE)szRegItem, &iRegItemLen);        if (result != 0)        {            RegCloseKey(hKEY);            return;        }        RegCloseKey(hKEY);        WriteToLog(szRegItem);        Sleep(SLEEP_TIME);    }    WriteToLog("service stopped");}/*---------------------------------------------------------------------------------    接收系统传递的控制命令,比如当你通过sc.exe关闭服务时,    该函数会收到SERVICE_CONTROL_STOP消息,你就可以对服务进行必要的管理。    在本例子程序中就只接收SERVICE_ACCEPT_SHUTDOWN和SERVICE_ACCEPT_STOP消息,    这是通过前面给servicestatus赋值设定的。----------------------------------------------------------------------------------*/void WINAPI CtrlHandler(DWORD request){    switch (request)    {    case SERVICE_CONTROL_STOP:        brun=false;        servicestatus.dwCurrentState = SERVICE_STOPPED;        break;    case SERVICE_CONTROL_SHUTDOWN:        brun=false;        servicestatus.dwCurrentState = SERVICE_STOPPED;        break;    default:        break;    }    SetServiceStatus (hstatus, &servicestatus);}void main(){    //showNowLog();    //NowLogStringEx(_T("服务开始了"));    SERVICE_TABLE_ENTRY entrytable[2];    entrytable[0].lpServiceName=L"SCguardHomepage";    entrytable[0].lpServiceProc=(LPSERVICE_MAIN_FUNCTION)ServiceMain;    entrytable[1].lpServiceName=NULL;    entrytable[1].lpServiceProc=NULL;    StartServiceCtrlDispatcher(entrytable);}
0 0