这个课题主要是讲如何动态加载驱动,虽然现在已经存在很多的动态驱动加载器,但是使用自己编写的东西,还是有不同的感觉的。当是科普吧。

在这里,主要使用SCM来进行驱动的动态加载和卸载。

先介绍下SCM,服务控制管理器(Service Control Manager , SCM )。服务(Service)是在后台运行配套的程序,并且不需要用户交互(也就是说没有常见的用户界面或者控制台)。换句话说,一个服务就是一个始终运行于系统中的 Win32 进程,即使没有用户登陆进来也如此。SC 管理器(即服务控制管理器)可以控制服务和驱动程序。

主要涉及的函数如下:
名 称    描 述 
CloseServiceHandle  关闭来自 OpenSCManager() 、 CreateService() 或 OpenService() 的句柄
ControlService  停止、暂停、继续、查询或通知已加载的服务 / 驱动程序
CreateService  加载一个服务 / 驱动程序
DeleteService  卸载一个服务 / 驱动程序
OpenSCManager  获取 SC 管理器的句柄
OpenService   获取一个已加载的服务 / 驱动程序的句柄
QueryServiceStatus   查询一个服务 / 驱动程序的属性和当前状态
StartService   启动一个已加载的服务 / 驱动程序

加载和运行一个服务需要执行的典型操作步骤: 

1. 调用 OpenSCManager() 以获取一个管理器句柄 
2. 调用 CreateService() 来向系统中添加一个服务 
3. 调用 StartService() 来运行一个服务 
4. 调用 CloseServiceHandle() 来释放管理器或服务句柄

不过我这里决定把加载驱动和启动驱动的过程分开,这样容易看明白,如果想整合也很容易,直接调用两个函数就可以了。

一 打开SCM
第一步需要做的是和SCM交互,则要使用OpenSCManager函数。原型如下:
SC_HANDLE OpenSCManager(LPCTSTR lpMachineName,
              LPCTSTR lpDatabaseName,
              DWORD dwDesiredAccess);
lpMachineName:电脑名。如果为NULL,则为本机。
lpDatabaseName:SCM数据库标识,应该为SERVICES_ACTIVE_DATABASE或者如果为NULL,则SEVICES_ACTIVE_DATABASE数据库作为默认数据库被打开。
dwDesiredAccess:以何种权限打开。
本函数返回一个SC_HANDLE的句柄以便作为其他函数的参数来操作SCM数据库。

当完成对SCM数据库的访问后,在退出前必须使用CloseServiceHandle关闭它。原型为:
BOOL CloseServiceHandle(SC_HANDLE hSCManger);

二 创建服务
增加一个Service,需要用到CreateService函数,原型如下:
SC_HANDLE CreateService(SC_HANDLE hSCManager,
             LPCTSTR lpServiceName,
             LPCTSTR lpDisplayName,
             DWORD dwDesireAccess,
             DWORD dwServiceType,
             DWORD dwStartType,
             DWORD dwErrorControl,
             LPCTSTR lpBinaryPathName,
             LPCTSTR lpLoadOrderGroup,
             LPDWORD lpdwTagId,
             LPCTSTR lpDependencies,
             LPCTSTR lpServiceStartName,
             LPCTSTR lpPassword);
这个函数有十三个参数:
hSCManager:是OpenSCManager得到的返回值,即服务管理器的句柄。
lpServiceName:Service的名字,,同时注册表也使用这个名字,这个Service的相应信息存放在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Service\lpServiceName子键下;
lpDisplayName:Service在服务控制面板中显示的名字;
dwDesireAccess:访问Service的权限类型;
dwServiceType:Service的类型,可以是SERVICE_FILE_SYSTEM_DRIVER、SERVICE_KERNEL_DRIVER、SERVICE_WIN32_OWN_PROCESSS、SERVICE_WIN32_SHARE_PROCESS之一;
dwStartType:Service启动类型,可以是自动(SERVICE_ATUO_START)、手动(SERVICE_DEMAND_START)、禁止(SERVICE_DISABLED);
dwErrorControl:出错控制,SERVICE_ERROR_IGNORE和SERVICE_ERROR_NORMAL表示出错时在日志中纪录并继续。两个参数的区别是SERVICE_ERROR_NORMAL将会在出错时向用户显示一条出错信息,SERVICE_ERROR_SERVER和SERVICE_ERROR_CRITICAL告诉系统在失败时重启;
lpBinaryPathName:驱动的路径,也是服务的路径;
lpLoadOrderGroup:如果这个服务是加载服务组中的一个,这个指针指向这者字符串数组,一般为NULL;
lpdwTagId:指针,指向的变量,接收的值用於区别lpLoadOrderGroup服务组中的不同服务,一般为NULL;
lpDependencies:这个Service所依赖的其他服务,在启动本Service之前需要先启动这些服务;
lpServiceStartName:帐号;
lpPassword:密码。
需要注意的是,如果要增加一个Service,那么OpenSCManager函数中的dwDesiredAccess参数至少需要为SC_MANAGER_CREATE_SERVICE。

三 启动服务
启动Service,相应函数如下:
BOOL StartService(SC_HANDLE hService,
         DWORD dwNumServiceArgs,
         LPCTSTR *lpServiceArgVectors);
hService:Service的句柄;
dwNumServiceArgs:指定在lpServiceArgVectors指向的数组中参数的个数,如果lpServiceArgVectors为NULL,这个值为0;
lpServiceArgVectors:指向传递给Service的参数字符串数组的指针,可以为NULL;

Service运行之后,ControlService函数用于的控制,函数原型如下:
BOOL ControlService(SC_HANDLE hService,
          DWORD dwControl,
          LPSERVICE_STATUS lpServiceStatus);
hService:Service句柄;
dwControl:SERVICE_CONTROL_STOP,SERVICE_CONTROL_PAUSE,SERVICE_CONTROL_CONTINUE,SERVICE_CONTROL_INTERROGATE之一,也可以自定义(128~255);
lpServiceStatus:一个LPSERVICE_STATUS的结构指针。

如果想停止服务,也需要使用该函数来进行控制。

BOOL QueryServiceStatus(SC_HANDLE hService,
            LPSERVICE_STATUS lpServiceStatus);
调用QueryServiceStatus函数和调用带SERVICE_CONTROL_INTERROGATE参数的ControlService相差无几。
使用该函数进行服务状态的查询,比如判断服务是否已经启动,服务是否停止了。

好,下面就是代码了,我使用的是delphi7,把这些功能写在一个类中,代码很容易明白。也就不多说了。


代码:
unit untServiceMan;



interface



uses windows, WinSvc;



type

  TServiceMan = class

  private

    function ServiceConnect:SC_HANDLE;

    function ServiceDisconn(hService:SC_HANDLE):SC_HANDLE;



    function ServiceOpen(hService:SC_HANDLE; AServName:PChar):SC_HANDLE;

    function ServiceClose(hService:SC_HANDLE):Boolean;



    function ServiceGetStatus(hService:SC_HANDLE; AServName:PChar ):DWord;



    function ServiceUninstalled(hService:SC_HANDLE; AServName:PChar):Boolean;

    function ServiceRunning(hService:SC_HANDLE; AServName:PChar):Boolean;

    function ServiceStopped(hService:SC_HANDLE; AServName:PChar):Boolean;

  public

    function ServiceInstall(AServName, ADispName, AServPath:PChar):SC_HANDLE;

    function ServiceUnInstall(AServName:PChar):DWORD;

    function ServiceStart(AServName:PChar):DWORD;

    function ServiceStop(AServName:PChar):DWORD;

  end;

  

implementation

{ TServiceMan }



{**********************************************************

**功能:装载服务                                          *

**参数1:服务名                                           *

**参数2:服务描述                                         *

**参数3:服务文件的地址                                   *

***********************************************************}

function TServiceMan.ServiceInstall(AServName, ADispName, AServPath: PChar): SC_HANDLE;

var

  hManager:SC_HANDLE;

begin

  result := 0;



  hManager := ServiceConnect;



  try

    if ServiceUninstalled(hManager, AServName) then

    begin

      result := CreateService(hManager,

                         AServName,

                         ADispName,

                         SERVICE_ALL_ACCESS,

                         SERVICE_KERNEL_DRIVER,

                         SERVICE_DEMAND_START,

                         SERVICE_ERROR_NORMAL,

                         AServPath,

                         nil,

                         nil,

                         nil,

                         nil,

                         nil);



      ServiceClose(result);           //记住关闭句柄,否则会无法卸载服务

    end;

  finally

    ServiceDisconn(hManager);

  end;

end;



{**********************************************************

**功能:关闭打开的服务句柄                                *

**参数1:服务句柄                                         *

***********************************************************}

function TServiceMan.ServiceClose(hService: SC_HANDLE): Boolean;

begin

  if (hService <> 0) then

    result := CloseServiceHandle(hService)

  else

    result := True;

end;



{**********************************************************

**功能:打开服务管理器                                    *

**返回值为其句柄                                          *

***********************************************************}

function TServiceMan.ServiceConnect: SC_HANDLE;

begin

  result := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);

end;



{**********************************************************

**功能:关闭管理器句柄                                    *

**参数1:服务句柄                                         *

***********************************************************}

function TServiceMan.ServiceDisconn(hService: SC_HANDLE): SC_HANDLE;

begin

  if (hService <> 0) then

    CloseServiceHandle(hService);

  result := 0;

end;



{**********************************************************

**功能:获得一个已经加载的服务的句柄                      *

**参数1:管理器句柄                                       *

**参数2:服务的名称                                       *

***********************************************************}

function TServiceMan.ServiceOpen(hService:SC_HANDLE; AServName: PChar): SC_HANDLE;

begin

  result := OpenService(hService, AServName, SERVICE_ALL_ACCESS);

end;



{**********************************************************

**功能:卸载服务                                          *

**参数1:服务的名称                                       *

***********************************************************}

function TServiceMan.ServiceUnInstall(AServName:PChar): DWORD;

var

  hService, hManager:SC_HANDLE;

  ServiceStatus:TServiceStatus;

begin

  result := 0;



  hManager := ServiceConnect;



  try

    if not ServiceUninstalled(hManager, AServName) then

    begin

      hService := ServiceOpen(hManager, AServName);



      if (hService <> 0) then

      begin

        ControlService(hService, SERVICE_CONTROL_STOP, ServiceStatus);     //在卸载前停止服务,否则需要停止服务才能正常卸载

        if DeleteService(hService) then

          result := 2

        else

          result := 1;

      end;

      ServiceClose(hService);

    end;

  finally

    ServiceDisconn(hManager);

  end;

end;



{**********************************************************

**功能:启动服务                                          *

**参数1:服务的名称                                       *

**返回值:    0:驱动还未安装                             *

              1:驱动已启动                               *

              2:驱动启动成功                             *

              3:驱动启动失败                             *

***********************************************************}

function TServiceMan.ServiceStart(AServName: PChar): DWORD;

var

  hService, hManager:SC_HANDLE;

begin

  result := 0;



  hManager := ServiceConnect;



  try

    if not ServiceUninstalled(hManager, AServName) then

    begin

      if not ServiceRunning(hManager, AServName) then

      begin

        hService := ServiceOpen(hManager, AServName);



        if (hService <> 0) then

          if StartService(hService, 1, AServName) then         //启动服务

            result := 2

          else

            result := 3;



        ServiceClose(hService);

      end

      else

        result := 1;

    end;

  finally

    ServiceDisconn(hManager);

  end;

end;



{**********************************************************

**功能:停止服务                                          *

**参数1:服务的名称                                       *

**返回值:    0:驱动还未安装                             *

              1:驱动已停止                               *

              2:驱动停止成功                             *

              3:驱动停止失败                             *

***********************************************************}

function TServiceMan.ServiceStop(AServName: PChar): DWORD;

var

  hService, hManager:SC_HANDLE;

  ServiceStatus:TServiceStatus;

begin

  result := 0;



  hManager := ServiceConnect;



  try

    if not ServiceUninstalled(hManager, AServName) then

    begin

      if not ServiceStopped(hManager, AServName) then

      begin

        hService := ServiceOpen(hManager, AServName);



        if (hService <> 0) then

          if ControlService(hService, SERVICE_CONTROL_STOP, ServiceStatus) then

            result := 2

          else

            result := 3;



        ServiceClose(hService);

      end

      else

        result := 1;

    end;

  finally

    ServiceDisconn(hManager);

  end;

end;



{**********************************************************

**功能:获得服务的状态                                    *

**参数1:管理器的句柄                                     *

**参数2:服务的名称                                       *

***********************************************************}

function TServiceMan.ServiceGetStatus(hService:SC_HANDLE; AServName:PChar ):DWORD;

var

  hService2:SC_HANDLE;

  queryStatus:TServiceStatus;

  dwStat:DWORD;

begin

  dwStat := 0;



  if(hService > 0)then

  begin

    hService2 := ServiceOpen(hService, AServName);



    if(QueryServiceStatus(hService2, queryStatus))then

    begin

      dwStat := queryStatus.dwCurrentState;

    end;

    

    ServiceClose(hService2);

  end;

  Result := dwStat;

end;



{判断某服务是否安装,未安装返回true,已安装返回false} 

function TServiceMan.ServiceUninstalled(hService:SC_HANDLE; AServName:PChar):Boolean;

begin 

  Result  :=  0 = ServiceGetStatus(hService, AServName);

end; 



{判断某服务是否启动,启动返回true,未启动返回false} 

function TServiceMan.ServiceRunning(hService:SC_HANDLE; AServName:PChar):Boolean;

begin 

  Result := SERVICE_RUNNING = ServiceGetStatus(hService, AServName);

end; 



{判断某服务是否停止,停止返回true,未停止返回false} 

function TServiceMan.ServiceStopped(hService:SC_HANDLE; AServName:PChar):Boolean;

begin 

  Result := SERVICE_STOPPED = ServiceGetStatus(hService, AServName);

end;



end.

上传的附件 驱动安装.rar