网站已经改版为Wordpress版本,这里是旧版本的快照,请不要在页面中留言.

Windows NT式驱动的加载详解,附示例工程

注:在本文最后附加源代码工程

在windows平台下驱动分为WDM式和NT式2种类型,NT式驱动不支持即插即用,而WDM式可以支持,小悠现在目前学的是NT式的驱动基础,对驱动的知识也算是比较了解了吧,今天在程序中第一次调用了自己的驱动,这里就给大家分享一下NT式驱动的加载方式吧.

 

下面我将从驱动运行的方式和驱动加载的步骤来讲解NT式驱动的加载方法.

·    循环渐进,从基础说起

设备驱动程序的动态加载主要是有服务控制管理程序(Service Control Manager,简称 SCM)系统组件来完成的。SCM为Windows中运行的组件提供了很多服务,比如像启动啊,停止啊,控制啊等等,所以要想用代码动态加载你的驱动的话就得和这货打交道。

    

Windows中的服务可以在系统启动的时候加载,或者你自己在服务管理中自己手动开启或者关闭之类的。在代码中我们可以通过windows提供的相关服务函数进行驱动的加载、卸载操作;

加载NT式驱动一般分为下面的几个步骤:

打开SCM这货

创建你自己的驱动对应的服务

开启你的这个服务,让它跑起来

 

卸载NT式驱动一般分为下面的几个步骤:

依然先打开SCM这货

打开你的驱动服务

停止你的驱动

干掉驱动,就卸载成功了

 

·    说说加载驱动的时候用的一些操作函数

 

1、   打开SCM管理器函数

SC_HANDLE OpenSCManager(

LPCTSTR lpMachineName,  //计算机的名字

LPCTSTR lpDatabaseName,//SCM数据库名称

DWORD   dwDesireAccess//权限

)

lpMachineName:指定一个计算机的名称,使用NULL表示本机操作。

lpDatabaseName:指定SCM数据的名称,使用NULL表示使用默认的数据库

dwDesireAccess表示你的访问权限,一般设置为SC_MANAGER_ALL_ACCESS


    这个函数如果调用成功就返回SCM管理器的句柄,失败的话返回一个NULL

 

2、   关闭服务句柄

对于服务来说,使用的是SC_HANDLE这个类型保存的句柄,所以要是用函数CloseServiceHandle()这个函数去关闭句柄.

 

3、   创建一个你自己的服务

下面的这个函数是创建一个你的服务,他将返回一个与你的服务相关的句柄,以后对你的服务操作全部都是基于这个句柄的。下面是这个函数的原型,它位于WinSvc.h中:

 

SC_HANDLE

CreateService(

     SC_HANDLE   hSCManager,

     LPCWSTR     lpServiceName,

     LPCWSTR     lpDisplayName,

     DWORD       dwDesiredAccess,

     DWORD        dwServiceType,

     DWORD        dwStartType,

     DWORD        dwErrorControl,

     LPCWSTR     lpBinaryPathName,

     LPCWSTR     lpLoadOrderGroup,

     LPDWORD      lpdwTagId,

     LPCWSTR     lpDependencies,

     LPCWSTR     lpServiceStartName,

     LPCWSTR     lpPassword

);

hSCManager:这是你的SCM管理器的句柄。

lpServiceName服务的名字,就是一个字串,用它可以打开你的服务

lpDisplayName服务显示的名称

dwDesiredAccess打开的权限,一般设置为SERVICE_ALL_ACCESS

dwServiceType:服务的类型,其中SERVICE_FILE_SYSTEM_DRIVER表示文件系统类型的驱动,SERVICE_KERNEL_DRIVER表示普通的程序驱动,一般都是使用这货

dwStartType服务打开的时间,是自动还是其他,SERVICE_AUTO_START表示自动加载,SERVICE_BOOT_START表示在系统启动前就被启动,SERVICE_DEMAND_START表示按照你的需要进行加载(手动),一般使用这个方式

dwErrorControl设置有关错误的处理方式,SERVICE_ERROR_IGNORE表示忽略所有的错误,SERVICE_ERROR_NORMAL表示默认处理,SERVICE_ERROR_CRITICAL表示增加对错误处理的校验,弹出对话框,然后记录错误日志信息

lpBinaryPathName你的sys文件的路径

lpLoadOrderGroup指定你的用户组

lpdwTagId输出验证标签

lpDependencies所依赖的服务的名称

lpServiceStartName用户的账户名称

lpPassword用户的密码

 

4、   打开你所创建的服务

这个函数的话是针对你已经创建过的服务,再次打开的时候进行调用

SC_HANDLE

OpenService(

 SC_HANDLE   hSCManager,//SCM的句柄

 LPCWSTR     lpServiceName,//你的服务名称

 DWORD       dwDesiredAccess//访问的权限

    );

 

5、   控制你的服务

这个函数就是对你的服务发送命令用于控制作用的

BOOL

ControlService(

   SC_HANDLE         hService,//服务的句柄

   DWORD             dwControl,//控制码

   LPSERVICE_STATUS  lpServiceStatus//返回的状态

    );

 

·    驱动加载代码的执行流程

下面是NT驱动的加载流程,后面的代码就是根据这个流程来处理的.

首先使用OpenSCManager打开你的SCM管理器,如果返回了NULL,表示失败了,否则的话就继续

使用函数CreateService创建一个驱动的服务,如果成功的话跳转到⑥,返回NULL的话请继续

因为返回了错误,但是错误不一定是致命的,比如我们的服务已经存在了,肯定会返回NULL的,所以这一步使用GetLastError获取到你的错误代码,继续

因为③返回了错误,我们要对返回的错误码进行分析,如果返回值为ERROR_IO_PENDING或者ERROR_SERVICE_EXISTS这说明我们的服务已经存在了,直接使用OpenService进行打开操作

如果OpenService返回NULL的话,就是失败了,退出

使用函数StartService开启你的服务吧

如果开启服务失败,再看看LastError的值,是被挂起了还是已经在运行了。

代码小悠将在最后附加:

·    驱动卸载代码的执行流程

还是先打开你的SCM管理器,失败就返回失败吧

打开你的驱动服务,注意一些错误的处理

控制服务停止

删除服务

 

小悠写了一个MFC下驱动加载的类,给大家分享一下,这里就简单的贴出类的头文件,说明一下函数的作用:

#include <winsvc.h>
#ifndef MAX_PATH       
#define MAX_PATH 260
#endif
#define MAX_NAME_SIZE  MAX_PATH
 
//加载驱动的错误类型
#define LOAD_SUCCESS   0x00//开启成功
#define LOAD_FAILED    0x01//开启失败
class CDriverLoad
{
public:
   CDriverLoad(void);//构造函数
   virtual ~CDriverLoad(void);
   //驱动的加载函数,参数1:驱动的名字(自己起)
//参数2:驱动的路径,可以使用相对路径,例如.\\A.sys
   DWORD LoadDriver(char* lpszRegName,char* lpszPath);
//驱动的卸载函数  
BOOL UnLoadDriver();
//获取到设备的句柄,这个我实现,直接使用CreateFile就行了
HANDLE GetDeviceHandle();
protected:
   //驱动文件的路径
   CString m_szBinPath;
   //驱动的名字
   CString m_szRegName;
};


 

附上小悠写的一个MFC的例子(VS2010编写的)

解压密码 yscode

百度网盘下载地址:http://pan.baidu.com/s/1hqeMxda


本文出自悠然品鉴原创,请勿伪原创抄袭,转载请注明出处:http://www.youranshare.com/blog/sid/66.html


  • 标签:
  • NT驱动加载
  • 驱动加载
  • C++ 驱动
网站已经改版为Wordpress版本,这里是旧版本的快照,请不要在页面中留言.