65.9K
CodeProject 正在变化。 阅读更多。
Home

一个 C++ 类封装,用于加载/卸载设备驱动程序

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (15投票s)

2008 年 12 月 20 日

CPOL

2分钟阅读

viewsIcon

74293

downloadIcon

5587

一个用于注册和启动设备驱动程序的 C++ 类。

引言

如果你经常玩弄设备驱动程序,那么一个加载/卸载工具会非常有用。有很多好用的工具,我认为最受欢迎的是 OSRLoader。但是,我决定编写这个封装,以解释哪些 Win32 API 参与了这个过程。

Win32 API

设备驱动程序与普通的用户级程序不同,因此它的安装和执行更加复杂,因为我们在内核空间中。我们必须执行两个主要操作:

  1. 将驱动程序注册为 Windows 服务。
  2. 将驱动程序作为服务启动。

原因在于 Windows 将设备驱动程序视为普通服务。现在,我们可以探索允许我们处理进程的 API。服务控制管理器 (SCM) 是管理一个包含所有已安装的服务和设备驱动程序的数据库的组件。让我们看看用于连接到我们机器上的 SCM 的 API。

SC_HANDLE WINAPI OpenSCManager(
  __in_opt  LPCTSTR lpMachineName,
  __in_opt  LPCTSTR lpDatabaseName,
  __in      DWORD dwDesiredAccess
);

之后,我们可以创建一个新服务,如下所示:

SC_HANDLE WINAPI CreateService(
  __in       SC_HANDLE hSCManager,
  __in       LPCTSTR lpServiceName,
  __in_opt   LPCTSTR lpDisplayName,
  __in       DWORD dwDesiredAccess,
  __in       DWORD dwServiceType,
  __in       DWORD dwStartType,
  __in       DWORD dwErrorControl,
  __in_opt   LPCTSTR lpBinaryPathName,
  __in_opt   LPCTSTR lpLoadOrderGroup,
  __out_opt  LPDWORD lpdwTagId,
  __in_opt   LPCTSTR lpDependencies,
  __in_opt   LPCTSTR lpServiceStartName,
  __in_opt   LPCTSTR lpPassword
);

MSDN 上提供了对每个参数的解释。现在,我将向您展示如何使用此 API 创建一个新服务

DWORD CService::CreateSvc(void)
{
    if (!IsInit())
        return SVC_NOT_INIT;
    
    if (IsLoaded())
        return SVC_OK;

    SC_HANDLE hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE);

    if (hSCManager == NULL)
        return SVC_ERROR_SCMANAGER;

    hService = CreateService(hSCManager,lpServiceName,lpDisplayName,
                             SERVICE_ALL_ACCESS,    
                             SERVICE_KERNEL_DRIVER, 
                             dwStartType,  
                             SERVICE_ERROR_NORMAL,  
                             lpFilePath,              
                             NULL,                  
                             NULL,                  
                             NULL,                 
                             NULL,                  
                             NULL);

    if (hService == NULL){

        hService = OpenService(hSCManager, lpServiceName, SERVICE_ALL_ACCESS);
        
        if (hService == NULL) {
            CloseServiceHandle(hSCManager);
            return SVC_ERROR_CREATE;
        }
    }
    
    loaded = true;
    CloseServiceHandle(hSCManager);
    
    return SVC_OK;    
}

OpenSCManager(…) 返回 SCM 的句柄,因此我们将其用于 CreateService(…) 中以安装设备驱动程序。 hService 是已安装服务的句柄。现在,我们可以启动它。 API

BOOL WINAPI StartService(
  __in      SC_HANDLE hService,
  __in      DWORD dwNumServiceArgs,
  __in_opt  LPCTSTR *lpServiceArgVectors
);

这是代码

DWORD CService::StartSvc(void)
{
    if (!IsLoaded())
        return SVC_NOT_CREATE;

    if (IsStarted())
        return SVC_OK;

    SC_HANDLE hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE);

    if (hSCManager == NULL)
        return SVC_ERROR_SCMANAGER;

    hService = OpenService(hSCManager, lpServiceName, SERVICE_ALL_ACCESS);
        
    if (hService == NULL) {
        CloseServiceHandle(hSCManager);
        return SVC_ERROR_OPEN;
    }

    if (StartService(hService,0,NULL)== NULL){
        CloseServiceHandle(hSCManager);
        CloseServiceHandle(hService);
        return SVC_ERROR_START;
    }

    CloseServiceHandle(hSCManager);
    started = true;

    return SVC_OK;
}

StartService 函数接受三个参数:服务的句柄、参数的数量以及一个包含参数的数组。

好的,在工作之后,是时候关闭驱动程序了。要停止驱动程序,我们使用此 API

BOOL WINAPI ControlService(
  __in   SC_HANDLE hService,
  __in   DWORD dwControl,
  __out  LPSERVICE_STATUS lpServiceStatus
);

这会将控制消息发送到服务,在我们的例子中是 dwControl = SERVICE_CONTROL_STOP。输出的 SERVICE_STATUS 结构包含有关服务的状态信息。

DWORD CService::StopSvc(void)
{
    SERVICE_STATUS ss;

    if (!IsStarted())
        return SVC_OK;

    SC_HANDLE hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE);

    if (hSCManager == NULL)
        return SVC_ERROR_SCMANAGER;

    hService = OpenService(hSCManager, lpServiceName, SERVICE_ALL_ACCESS);
        
    if (hService == NULL) {
        CloseServiceHandle(hSCManager);
        return SVC_ERROR_OPEN;
    }

    if (ControlService(hService,SERVICE_CONTROL_STOP,&ss) == NULL){
        CloseServiceHandle(hSCManager);
        CloseServiceHandle(hService);
        return SVC_ERROR_STOP;
    
    }
    
    started = false;

    CloseServiceHandle(hSCManager);
    CloseServiceHandle(hService);
    return SVC_OK;
}

最后,我们必须卸载驱动程序。

BOOL WINAPI DeleteService(
  __in  SC_HANDLE hService
);

这是从 SCM 中删除驱动程序的 API,这就是我们使用它的方式

DWORD CService::UnloadSvc(void)
{
    if (!IsLoaded())
        return SVC_OK;

    if (IsStarted())
        if (StopSvc() != SVC_OK)
            return SVC_ERROR_UNLOAD;

    SC_HANDLE hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE);

    if (hSCManager == NULL)
        return SVC_ERROR_SCMANAGER;

    hService = OpenService(hSCManager, lpServiceName, SERVICE_ALL_ACCESS);
        
    if (hService == NULL) {
        CloseServiceHandle(hSCManager);
        return SVC_ERROR_OPEN;
    }

    DeleteService(hService);
    CloseServiceHandle(hSCManager);
    
    loaded = false;

    return SVC_OK;
}

使用代码

好吧,如果你很懒,或者你不能浪费时间去理解所有这些 API 的工作原理,我已经编写了这个简单的封装,我希望你会发现它很有用

#include <windows.h>
#include "stdafx.h"

//Error codes

#define SVC_OK (DWORD)0
#define SVC_NOT_CREATE (DWORD)1
#define SVC_NOT_START (DWORD)2
#define SVC_NOT_INIT (DWORD)3
#define SVC_ERROR_SCMANAGER (DWORD)4
#define SVC_ERROR_CREATE (DWORD)5
#define SVC_ERROR_START (DWORD)6
#define SVC_ERROR_OPEN (DWORD) 7
#define SVC_ERROR_STOP (DWORD)8
#define SVC_ERROR_UNLOAD (DWORD) 9


class CService
{
public:
    //Constructor
    CService(void);
    CService(LPTSTR _lpFilePath,LPTSTR _lpServiceName,
             LPTSTR _lpDisplayName,DWORD _dwStartType);
    //Destructor
    ~CService(void);
    
    //init function
    DWORD InitSvc(LPTSTR _lpFilePath,LPTSTR _lpServiceName,
                  LPTSTR _lpDisplayName,DWORD _dwStartType);
    DWORD CreateSvc(void);  //create service
    DWORD UnloadSvc(void);  //unload service
    DWORD StartSvc(void);  //start service
    DWORD StopSvc(void);   //stop service


    BOOL   IsInit(void); //check if service is init
    BOOL   IsLoaded(void); //check if service is loaded
    BOOL   IsStarted(void); //check if service is started

private:
    
    LPTSTR lpFilePath; //driver file path
    LPTSTR lpServiceName; //service name
    LPTSTR lpDisplayName; //service's dos name

    DWORD dwStartType; //start type

    SC_HANDLE hService; //service's handle
    
    // Status variables
    BOOL init; 
    BOOL loaded;
    BOOL started;    

};

CService 对象创建

CService svc(“C:\\test.sys”,”Test”,”Test”,SERVICE_DEMAND_START);

驱动程序注册

if (svc.CreateSvc() == SVC_OK)
        …
else{
        …
}

驱动程序启动

if (svc.StartSvc() == SVC_OK)
        …
else{
        …
}

驱动程序停止

if (svc.StopSvc() == SVC_OK)
        …
else{
        …
}

驱动程序擦除

if (svc.UnloadSvc() == SVC_OK)
        …
else{
        …
}

结论

好的,就这样。我还编写了一个使用 CService 类的小应用程序。我希望你会发现这几行代码很有用。

© . All rights reserved.