Golden Blonde 发表于 2014-5-2 18:55:38

【C++】驱动加载/卸载/通信代码(兼容WIN32/WIN64)

类代码:
//Author: Anonymous
//#include <Windows.h>

class cDrvCtrl
{
public:
    cDrvCtrl()
    {
      m_pSysPath = NULL;
      m_pServiceName = NULL;
      m_pDisplayName = NULL;
      m_hSCManager = NULL;
      m_hService = NULL;
      m_hDriver = INVALID_HANDLE_VALUE;
    }
    ~cDrvCtrl()
    {
      CloseServiceHandle(m_hService);
      CloseServiceHandle(m_hSCManager);
      CloseHandle(m_hDriver);
    }
public:
    DWORD m_dwLastError;
    PCHAR m_pSysPath;
    PCHAR m_pServiceName;
    PCHAR m_pDisplayName;
public:
    BOOL Install(PCHAR pSysPath,PCHAR pServiceName,PCHAR pDisplayName);
    BOOL Start();
    BOOL Stop();
    BOOL Remove();
    BOOL Open(PCHAR pLinkName);
    BOOL IoControl(DWORD dwIoCode, PVOID InBuff, DWORD InBuffLen, PVOID OutBuff, DWORD OutBuffLen);
protected:
private:
    SC_HANDLE m_hSCManager;
    SC_HANDLE m_hService;
    HANDLE m_hDriver;
};

BOOL cDrvCtrl::Install(PCHAR pSysPath,PCHAR pServiceName,PCHAR pDisplayName)
{
    m_pSysPath = pSysPath;
    m_pServiceName = pServiceName;
    m_pDisplayName = pDisplayName;

    m_hSCManager = OpenSCManagerA(NULL,NULL,SC_MANAGER_ALL_ACCESS);
    if (NULL == m_hSCManager)
    {
      m_dwLastError = GetLastError();
      return FALSE;
    }

    m_hService = CreateServiceA(m_hSCManager,m_pServiceName,m_pDisplayName,
                  SERVICE_ALL_ACCESS,SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,
                  m_pSysPath,NULL,NULL,NULL,NULL,NULL);
    if (NULL == m_hService)
    {
      m_dwLastError = GetLastError();
      if (ERROR_SERVICE_EXISTS == m_dwLastError)
      {
            m_hService = OpenServiceA(m_hSCManager,m_pServiceName,SERVICE_ALL_ACCESS);
            if (NULL == m_hService)
            {
                CloseServiceHandle(m_hSCManager);
                return FALSE;
            }
      }
      else
      {
            CloseServiceHandle(m_hSCManager);
            return FALSE;
      }
    }
    return TRUE;
}

BOOL cDrvCtrl::Start()
{
    if (!StartServiceA(m_hService,NULL,NULL))
    {
      m_dwLastError = GetLastError();
      return FALSE;
    }
    return TRUE;
}

BOOL cDrvCtrl::Stop()
{
    SERVICE_STATUS ss;
    if (!ControlService(m_hService,SERVICE_CONTROL_STOP,&ss))
    {
      m_dwLastError = GetLastError();
      return FALSE;
    }
    return TRUE;

}

BOOL cDrvCtrl::Remove()
{
    if (!DeleteService(m_hService))
    {
      m_dwLastError = GetLastError();
      return FALSE;
    }
    return TRUE;
}

BOOL cDrvCtrl::Open(PCHAR pLinkName)//example: \\\\.\\xxoo      
{
    if (m_hDriver != INVALID_HANDLE_VALUE)
      return TRUE;
    m_hDriver = CreateFileA(pLinkName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if(m_hDriver != INVALID_HANDLE_VALUE)
      return TRUE;
    else
      return FALSE;
}

DWORD CTL_CODE_GEN(DWORD lngFunction)
{
    return (FILE_DEVICE_UNKNOWN * 65536) | (FILE_ANY_ACCESS * 16384) | (lngFunction * 4) | METHOD_BUFFERED;
}

BOOL cDrvCtrl::IoControl(DWORD dwIoCode, PVOID InBuff, DWORD InBuffLen, PVOID OutBuff, DWORD OutBuffLen)
{
    DWORD dw;
    return DeviceIoControl(m_hDriver,CTL_CODE_GEN(dwIoCode),InBuff,InBuffLen,OutBuff,OutBuffLen,&dw,NULL);
}范例代码:void test6()
{
    cDrvCtrl dc;
    BOOL b;
    DWORD dw=0x1234,dw0=0;
    //load drv
    b=dc.Install("D:\\temp\\MyDriver.sys","MyDriver","MyDriver");
    printf("dc.Install=%d\n",b);
    b=dc.Start();
    printf("dc.Start=%d\n",b);
    //call drv
    b=dc.Open("\\\\.\\MyDriver");
    printf("dc.Open=%d\n",b);
    b=dc.IoControl(0x800,&dw,sizeof(dw),&dw0,sizeof(dw0));
    printf("dc.IoControl=%d\n",b);
    if(!b)
    {
      dw0=GetLastError();
      printf("LastError=%ld\n",dw0);
    }
    else
    {
      printf("dw0=%ld\n",dw0);
    }
    //unload drv
    b=dc.Stop();
    printf("dc.Stop=%d\n",b);
    b=dc.Remove();
    printf("dc.Remove=%d\n",b);
}

0xAA55 发表于 2019-7-30 18:50:59

关键在于使用sc来控制service,通过创建SERVICE_KERNEL_DRIVER来创建一个内核驱动方式的服务。

我突然在想,如果是单片机,想要动态加载驱动,该怎么设计单片机系统。

虽说,单片机没人把指令放RAM上,都是放ROM的。但可以设计一个功能让它从UART等接口动态读取bin然后自己烧自己的ROM。

虽说STM32F103的每个ROM页只能被烧10000次

xiawan 发表于 2022-5-13 16:41:37


感谢楼主分享~~~

xiawan 发表于 2022-5-13 16:45:49


楼主大能,感谢感谢
页: [1]
查看完整版本: 【C++】驱动加载/卸载/通信代码(兼容WIN32/WIN64)