為加載驅動程序寫的模塊函數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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM