這個模塊主要是實現加載/卸載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