您的位置:首页 > 其它

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

2013-02-25 14:25 417 查看
  这个模块主要是实现加载/卸载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


程序下载:http://files.cnblogs.com/nbsofer/load_driver.7z
女孩不哭(QQ:191035066)@2013-02-25 14:23:59 http://www.cnblogs.com/nbsofer
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐