为加载驱动程序写的模块函数LoadDriver/UnLoadDriver

  这个模块主要是实现加载/卸载Windows内核驱动程序(不是硬件驱动), 属于软件驱动, 也就是是在软件启动的时候加载驱动, 在软件退出的时候卸载驱动程序. 刚开始学驱动时问题用SrvInst.exe, 感觉不太方便, 不能随程序的启动,退出, 自动加载与卸载, 所以写成了这个模块, 这下方便好多了.
  BUG:关于加载多个驱动程序那里的计数器, 还未做测试, 不知道能否正常工作.
    有时候在卸载驱动程序会遇到"驱动程序已标记为删除"的错误消息, 这个还未解决. 貌似这种情况多发生在应用程序完全释放其所打开的资料所致.
    比如:1)加载驱动; 2)打开设备 3)关闭设备 4)卸载驱动, 这样就不会出问题, 如果省略第3步, 下一次加载驱动程序的时候可能会报错说"已标记为删除", 这个BUG还未修复, 如果有谁找到了, 还望提醒一下.

  所致的服务函数:CreateService,DeleteService,ControlService, ...

  源代码(最后有示例程序,打开预编译开关即可):
  

//LoadDriver.h
#ifndef __LOADDRIVER_H__
#define __LOADDRIVER_H__

/**********************************************************
文件名称:LoadDriver.h/LoadDriver.c
文件路径:./LoadDriver/LoadDriver.h,LoadDriver.c
创建时间:2013-2-1,22:24:09
文件作者:女孩不哭
文件说明:该C语言程序实现对内核驱动程序的加载与卸载
    LoadDriver - 加载驱动
    UnloadDriver - 卸载驱动
**********************************************************/

#ifdef __cplusplus
extern "C" {
#endif

int LoadDriver(char* DriverAbsPath, char* ServiceName, char* DisplayName,int PromptIfExists);
int UnloadDriver(char* ServiceName);

#ifdef __cplusplus
}
#endif

#endif//!__LOADDRIVER_H__
//LoadDriver.c
#include <windows.h>
#include <stdio.h>
#include "LoadDriver.h"

static SC_HANDLE hScManager;

static void drvShowError(char* msg);
static int drvOpenScManager(int open);
static int drvCreateService(char* DriverAbsolutePath,char* ServiceName,char* ServiceDispalyName,SC_HANDLE* phService);
static int drvAddService(char* DriverAbsPath, char* ServiceName, char* DisplayName, int PromptIfExists);
static int drvDeleteService(char* ServiceName);

/**************************************************
函  数:drvShowError@4
功  能:显示最后一次系统函数调用的错误消息
参  数:msg - 消息前缀说明
返回值:(none)
说  明:内部调用,这里使用MessageBox,可以改成自己的
**************************************************/
void drvShowError(char* msg)
{
    void* pBuffer = NULL;
    DWORD dwLastError;
    dwLastError = GetLastError();
    if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL, dwLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), (LPSTR)&pBuffer, 1, NULL))
    {
        char buf[1024];
        _snprintf(buf,sizeof(buf),"%s\n\n%s", msg,pBuffer);
        MessageBox(NULL,buf,NULL,MB_OK);
        LocalFree((HLOCAL)pBuffer);
    }
}

/**************************************************
函  数:drvOpenScManager@4
功  能:打开服务控制管理器
参  数:open - !0:打开,0:关闭
返回值:成功:!0;失败:0
说  明:内部调用
    2013-02-17:
        增加了 引用计数以支持加载多个驱动,未测试
**************************************************/
int drvOpenScManager(int open)
{
    static DWORD refcount=0;
    if(open){
        if(hScManager){
            InterlockedIncrement(&refcount);
            return 1;
        }
        hScManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
        if(hScManager == NULL){
            drvShowError("打开服务控制管理器失败!");
            return 0;
        }
        InterlockedIncrement(&refcount);
        return 1;
    }else{
        if(hScManager&&!InterlockedDecrement(&refcount)){
            CloseServiceHandle(hScManager);
            hScManager=NULL;
        }
        return 1;
    }
}

/**************************************************
函  数:drvCreateService@16
功  能:创建新服务,并返回服务句柄(if succeeded)
参  数: DriverAbsolutePath - 驱动文件的绝对路径
        ServiceName - 服务名
        ServiceDisplayName - 服务的显示名
        *phService - 返回的服务句柄
返回值:成功:!0;失败:0
说  明:内部调用
**************************************************/
int drvCreateService(char* DriverAbsolutePath,char* ServiceName,char* ServiceDispalyName,SC_HANDLE* phService)
{
    SC_HANDLE hService;
    hService = CreateService(
        hScManager,             //服务控制器管理器句柄
        ServiceName,            //服务的名称
        ServiceDispalyName,     //服务的显示名称
        SERVICE_ALL_ACCESS,     //对该服务的访问权限
        SERVICE_KERNEL_DRIVER,  //服务的类型:内核驱动
        SERVICE_DEMAND_START,   //启动类型:手动启动
        SERVICE_ERROR_NORMAL,   //服务错误控制:正常
        DriverAbsolutePath,     //服务文件的绝对路径
        NULL,                   //没有启动组
        NULL,                   //不更改默认的标签ID
        NULL,                   //没有服务依赖项
        NULL,                   //使用默认对象名称
        NULL                    //没有密码
        );
    *phService = hService;
    return hService!=NULL;
}

/**************************************************
函  数:drvDeleteService@4
功  能:删除指定服务名的的服务
参  数:ServiceName - 服务名
返回值:成功:!0;失败:0
说  明: 内部调用
        对不存在的服务返回-1(成功)
**************************************************/
int drvDeleteService(char* ServiceName)
{
    int sehcode=0;
    SERVICE_STATUS ServiceStatus;
    SC_HANDLE hService=NULL;
    DWORD dwLastError;
    __try{
        hService=OpenService(hScManager,ServiceName,SERVICE_ALL_ACCESS);
        if(hService==NULL){
            dwLastError=GetLastError();
            if(dwLastError==ERROR_SERVICE_DOES_NOT_EXIST){
                sehcode=-1;
                __leave;
            }else{
                drvShowError("在打开已经存在的服务时遇到以下错误:");
                __leave;
            }
        }
        if(!ControlService(hService,SERVICE_CONTROL_STOP,&ServiceStatus)){//停止控制失败
            dwLastError = GetLastError();
            if(dwLastError != ERROR_SERVICE_NOT_ACTIVE){//并不是因为没有启动而出错
                drvShowError("在停止服务时遇到以下错误:");
                __leave;
            }
        }
        if(!DeleteService(hService)){
            drvShowError("在删除已存在的服务时遇到以下错误:");
            __leave;
        }
        sehcode=1;
    }
    __finally{
        if(hService){
            CloseServiceHandle(hService);
            hService=NULL;
        }
    }
    return sehcode;
}

/**************************************************
函  数:drvAddService@12
功  能:添加指定的服务
参  数: DriverAbsPath - 驱动程序绝对路径
        ServiceName - 服务名
        DisplayName - 服务显示名
        PromptIfExists - 存在的时候是否继续:
            1:删除并重新创建
            0:不再继续,返回-1(成功)
            -1:提示是否继续
返回值:成功:!0;失败:0
说  明: 内部调用
        若选择了不再继续,返回-1(成功)
**************************************************/
int drvAddService(char* DriverAbsPath, char* ServiceName, char* DisplayName, int PromptIfExists)
{
    int sehcode=0;
    SC_HANDLE hService = NULL;      //创建/打开的服务句柄
    DWORD dwErrCode = 0;
    __try{
        //假定服务不存在并创建
        if(!drvCreateService(DriverAbsPath,ServiceName,DisplayName,&hService)){
            //服务创建失败,可能已经存在
            DWORD dwLastError = GetLastError();
            //如果是服务已经存在,删除,重新安装
            if(dwLastError == ERROR_SERVICE_EXISTS){
                switch(PromptIfExists)
                {
                case 1:break;//重新创建
                case 0:{sehcode=-1;__leave;break;}
                case -1:
                    {
                        char* yesmsg = "指定的服务已经存在,要继续创建吗?";
                        if(MessageBox(NULL,yesmsg,DisplayName,MB_ICONQUESTION|MB_YESNO)!=IDYES){
                            sehcode=-1;
                            __leave;
                        }
                        break;
                    }
                }
                if(!drvDeleteService(ServiceName)){
                    __leave;
                }
                if(!drvCreateService(DriverAbsPath,ServiceName,DisplayName,&hService)){
                    drvShowError("重新创建服务时遇到以下错误:");
                    __leave;
                }
            }else{//其它原因造成服务创建失败
                drvShowError("创建服务时遇到以下错误:");
                __leave;
            }
        }
        //服务成功创建来到这里
        if(!StartService(hService,0,NULL)){
            drvShowError("在启动服务时遇到以下错误:");
            __leave;
        }
        sehcode=1;
    }
    __finally{
        if(hService){
            CloseServiceHandle(hService);
            hService=NULL;
        }
    }
    return sehcode;
}

/**************************************************
函  数:LoadDriver@12
功  能:加载指定驱动
参  数: DriverAbsPath - 驱动程序绝对路径
        ServiceName - 服务名
        DisplayName - 服务显示名
        PromptIfExists - 存在的时候是否继续:
            1:删除并重新创建
            0:不再继续,返回-1(成功)
            -1:提示是否继续
返回值:成功:!0;失败:0
说  明: 外部函数
        加载失败并不一定是完全失败,所有请始终成
对地调用LoadDriver/UnloadDriver以清除注册表残留信息
**************************************************/
int LoadDriver(char* DriverAbsPath, char* ServiceName, char* DisplayName,int PromptIfExists)
{
    if(!drvOpenScManager(1))
        return 0;
    return drvAddService(DriverAbsPath,ServiceName,DisplayName, PromptIfExists);
}

/**************************************************
函  数:UnloadDriver@4
功  能:卸载指定名称的驱动服务
参  数:ServiceName - 服务的名称
返回值:成功:!0;失败:0
说  明: 外部函数
        对不存在的服务返回-1(成功)
**************************************************/
int UnloadDriver(char* ServiceName)
{
    int ret;
    ret=drvDeleteService(ServiceName);
    drvOpenScManager(0);
    return ret;
}

//~~~示例~~~
#if 0
int main(void){
    int err;
    char sys[MAX_PATH];
    GetModuleFileName(NULL,sys,sizeof(sys));
    strcpy(strrchr(sys,'\\'),"\\drv.sys");
    printf("sys:%s\n",sys);
    err=LoadDriver(sys, "drv","drv Test Service",-1);
    MessageBox(NULL,err==-1?"驱动已存在!":err?"驱动已加载!":"驱动未能成功加载!","",MB_OK);
    if(err!=-1){
        err=UnloadDriver("drv");
        MessageBox(NULL,err==-1?"驱动不存在!":err?"驱动已卸载!":"驱动未能成功卸载!","",MB_OK);
    }
    return 0;
}
#endif

程序下载:https://files.cnblogs.com/nbsofer/load_driver.7z
女孩不哭(QQ:191035066)@2013-02-25 14:23:59 http://www.cnblogs.com/nbsofer

posted @ 2013-02-25 14:25  女孩不哭  阅读(4065)  评论(4编辑  收藏  举报