阅读:9495回复:22
Win2K 下动态加载驱动程序
加载一个驱动程序,主要就是,在
SYSTEM\CurrentControlSet\Services 建一个键。 如: SYSTEM\CurrentControlSet\Services\Twdm1 Type(1) ErrorControl(0) Start(3) 多数驱动程序都是通过设置 Start 的值为 0, 1, 2 。 在系统启动的过程中加载驱动程序。 在 win2k 下驱动程序的加载处理上述方式外, 还可以在应用程序里用 Service Api 实现,驱动程序的动态加载。 这时候的 Start 为 3 。 所用到的 Api 为: OpenSCManager, CreateService, OpenService, StartService ControlService, DeleteService, CloseServiceHandle 其中需要说明的是: CreateService :他通过参数在注册表里自动创建驱动程序需要的键值。 DeleteService :他自动删除驱动程序在注册表里创的键值。 下面是一个,简单的例子: 应用程序: #include "stdafx.h" #include <windows.h> #include <winsvc.h> #include <conio.h> void DelSvr( char * szSvrName ); //自动卸载驱动程序。 int main(int argc, char* argv[]) { HANDLE hWdm; printf("Hello World!\n"); SC_HANDLE hServiceMgr, hServiceTwdm; BOOL bRtn; DWORD dwRtn, dwSize = 256; char szDir[256]; if( argc > 1 ) //加任一个参数表示卸载驱动程序。 { DelSvr( "Twdm1" ); return 0; } GetCurrentDirectory( dwSize, szDir );//取当前目录 strcat( szDir, "\\Twdm.sys" ); //取驱动程序的全路径 LPCTSTR lpszBinaryPathName = TEXT(szDir); hServiceMgr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); //打开服务控制管理器 if( hServiceMgr == NULL ) { printf( "OpenSCManager() Faild %d ! \n", GetLastError() ); return 0; } else { printf( "OpenSCManager() ok ! \n" ); } hServiceTwdm = CreateService( hServiceMgr, TEXT("Twdm1"), //SYSTEM\CurrentControlSet\Services 驱动程序的在注册表中的名字 TEXT("Twdm1"), // 注册表驱动程序的 DisplayName 值 SERVICE_ALL_ACCESS, // 加载驱动程序的访问权限 SERVICE_KERNEL_DRIVER,// 表示加载的服务是驱动程序 SERVICE_DEMAND_START, // 注册表驱动程序的 Start 值 SERVICE_ERROR_IGNORE, // 注册表驱动程序的 ErrorControl 值 lpszBinaryPathName, // 注册表驱动程序的 ImagePath 值 NULL, NULL, NULL, NULL, NULL); if( hServiceTwdm == NULL ) { dwRtn = GetLastError(); if( dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_EXISTS ) { CloseServiceHandle( hServiceMgr ); printf( "CrateService() Faild %d ! \n", dwRtn ); return 0; } else { printf( "CrateService() Faild Service is ERROR_IO_PENDING or ERROR_SERVICE_EXISTS! \n" ); } // 驱动程序已经加载,只需要打开 hServiceTwdm = OpenService( hServiceMgr, TEXT("Twdm1"), SERVICE_ALL_ACCESS ); if( hServiceTwdm == NULL ) { dwRtn = GetLastError(); CloseServiceHandle( hServiceMgr ); printf( "OpenService() Faild %d ! \n", dwRtn ); return 0; } else { printf( "OpenService() ok ! \n" ); } } else { printf( "CrateService() ok ! \n" ); } // 启动驱动程序,调用驱动程序的 DriverEntry 函数 bRtn = StartService( hServiceTwdm, NULL, NULL ); if( !bRtn ) { dwRtn = GetLastError(); if( dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_ALREADY_RUNNING ) { printf( "StartService() Faild %d ! \n", dwRtn ); CloseServiceHandle( hServiceTwdm ); CloseServiceHandle( hServiceMgr ); return 0; } else { if( dwRtn != ERROR_IO_PENDING ) { printf( "StartService() Faild ERROR_IO_PENDING ! \n"); } else { printf( "StartService() Faild ERROR_SERVICE_ALREADY_RUNNING ! \n"); } } } //测试驱动程序 hWdm = CreateFile("\\\\.\\Twdm1", GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if( hWdm != INVALID_HANDLE_VALUE ) { printf( "Open Driver Twdm ok ! \n" ); } else { printf( "Open Driver Twdm faild %d ! \n", GetLastError() ); } CloseHandle( hWdm ); CloseServiceHandle( hServiceTwdm ); CloseServiceHandle( hServiceMgr ); //这时候你可以通过注册表,或其他查看符号连接的软件验证。 printf( "按任意键 卸载驱动程序 !\n" ); getch(); //卸载驱动程序。 DelSvr( "Twdm1" ); return 0; } //卸载驱动程序。 void DelSvr( char * szSvrName ) { SC_HANDLE hServiceMgr, hServiceTwdm; SERVICE_STATUS SvrSta; hServiceMgr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if( hServiceMgr == NULL ) { printf( "DelSvr::OpenSCManager() Faild %d ! \n", GetLastError() ); return; } else { printf( "DelSvr::OpenSCManager() ok ! \n" ); } hServiceTwdm = OpenService( hServiceMgr, TEXT(szSvrName), SERVICE_ALL_ACCESS ); if( hServiceTwdm == NULL ) { CloseServiceHandle( hServiceMgr ); printf( "DelSvr::OpenService() Faild %d ! \n", GetLastError() ); return; } else { printf( "DelSvr::OpenService() ok ! \n" ); } //停止驱动程序,如果停止失败,只有重新启动才能,再动态加载。 if( !ControlService( hServiceTwdm, SERVICE_CONTROL_STOP , &SvrSta ) ) { printf( "DelSvr::ControlService() Faild %d !\n", GetLastError() ); } else { printf( "DelSvr::ControlService() ok !\n" ); } //动态卸载驱动程序。 if( !DeleteService( hServiceTwdm ) ) { printf( "DelSvr::DeleteSrevice() Faild %d !\n", GetLastError() ); } else { printf( "DelSvr::DeleteSrevice() ok !\n" ); } CloseServiceHandle( hServiceTwdm ); CloseServiceHandle( hServiceMgr ); return; } 驱动程序:驱动程序很简单, 只有一个文件,实现了DriverEntry,DispatchCreate,DispatchClose,GpdUnload 四个函数。 #include <ntddk.h> #define NT_DEVICE_NAME L"\\Device\\Twdm1" #define DOS_DEVICE_NAME L"\\DosDevices\\Twdm1" NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ); NTSTATUS DispatchCreate(PDEVICE_OBJECT fdo, PIRP Irp); NTSTATUS DispatchClose(PDEVICE_OBJECT fdo, PIRP Irp); VOID GpdUnload(PDRIVER_OBJECT DriverObject); ////////////////////// PDEVICE_OBJECT fdo; BOOLEAN fSymbolicLink; NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { //UNREFERENCED_PARAMETER (RegistryPath); NTSTATUS status; UNICODE_STRING ntDeviceName; UNICODE_STRING win32DeviceName; DbgPrint( "TWDM: DriverEntry for Twdm.sys ...... \n" ); fSymbolicLink = FALSE; // // Create dispatch points for the IRPs. // DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose; //DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = GpdDispatch; DriverObject->DriverUnload = GpdUnload; //DriverObject->MajorFunction[IRP_MJ_PNP] = GpdDispatchPnp; //DriverObject->MajorFunction[IRP_MJ_POWER] = GpdDispatchPower; //DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = GpdDispatchSystemControl; //DriverObject->DriverExtension->AddDevice = GpdAddDevice; RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME); //创建设备 status = IoCreateDevice(DriverObject, 0, &ntDeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &fdo); if (!NT_SUCCESS (status)) { DbgPrint( "TWDM: IoCreateDevice() faild ! \n" ); } else { DbgPrint( "TWDM: IoCreateDevice() ok ! \n" ); RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME); //创建符号连接 status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName ); if (!NT_SUCCESS(status)) { DbgPrint( "TWDM: IoCreateSymbolicLink() faild ! \n" ); } else { DbgPrint( "TWDM: IoCreateSymbolicLink() ok ! \n" ); fSymbolicLink = TRUE; } fdo->Flags &= ~DO_DEVICE_INITIALIZING; } if (!NT_SUCCESS(status)) { if(fdo) { IoDeleteDevice(fdo); } if(fSymbolicLink) { IoDeleteSymbolicLink(&win32DeviceName); } } return status; } NTSTATUS DispatchCreate(PDEVICE_OBJECT fdo, PIRP Irp) { NTSTATUS status; DbgPrint( "TWDM: IRP_MJ_CREATE for Twdm.sys ...... \n" ); status = STATUS_SUCCESS; return status; } // DispatchCreate NTSTATUS DispatchClose(PDEVICE_OBJECT fdo, PIRP Irp) { // DispatchClose NTSTATUS status; DbgPrint( "TWDM: IRP_MJ_CLOSE for Twdm.sys ...... \n" ); status = STATUS_SUCCESS; return status; } // DispatchClose VOID GpdUnload(PDRIVER_OBJECT DriverObject) { UNICODE_STRING win32DeviceName; DbgPrint( "TWDM: GpdUnload() for Twdm.sys ...... \n" ); RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME); if(fdo) { IoDeleteDevice(fdo); } if(fSymbolicLink) { IoDeleteSymbolicLink(&win32DeviceName); } } |
|
|
沙发#
发布于:2001-09-24 14:48
Test1.zip 是源代码。
其中驱动程序部分的一个文件,修改以下就可以了。 Mk.cmd @echo off echo Aouther : Qian echo Date : 2001.9.20 echo Function : Start DDK Environment And Build Driver call c:\NTDDK\bin\setenv.bat c:\NTDDK checked //此处改为你的 2k ddk 的路径 rem call c:\NTDDK\bin\setenv.bat c:\NTDDK free echo on d: //此处改为你的编写驱动程序的驱动器 cd \work\qian\wdm\test1\sys ////此处改为你的编写驱动程序的目录 build -b -w -nmake /a |
|
|
板凳#
发布于:2001-10-23 17:38
动态卸载行不行?
我试过Filemon,但不能动态卸载,这样调试起来不太方便! |
|
|
地板#
发布于:2001-10-24 08:42
当然没有问题,你说过的情况我遇到过。
在 unload 里只删除创建的 device ,而没有删除 符号连接的 时候,查看设备表时发现设备已经卸载。但是重新加载驱动程序 却会失败。重新启动机器就可以加载了。 你可以下载 test1.zip 试试。 |
|
|
地下室#
发布于:2001-10-24 10:47
Asm386 说的有道理,我看filemon时也对动态卸载报错搞不懂
|
|
5楼#
发布于:2002-04-15 11:08
请问 test1.zip 在 哪里??
|
|
6楼#
发布于:2002-04-16 08:56
http://www.csdn.net/develop/read_article.asp?id=10729
这里也有。这是最简单的例子。 如果驱动里使用了 irp 或者需要 应用程序用 deviceiocontrol 与驱动通信的话,还要加点处理。 在 create 和 close 里加上下面的处理。 status = STATUS_SUCCESS; Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest( Irp, IO_NO_INCREMENT ); |
|
|
7楼#
发布于:2002-04-28 17:42
关注!
|
|
|
8楼#
发布于:2002-04-28 18:22
Filemon 在 Free版把 irp_mj_unload屏蔽了,自然不能unload.
在checked版,运行应用程序关闭时不能unload这是因为还有 未完成的IRP,此时你断开所以监控的盘,一段时间(有长有短) 它就能顺利unload的。 |
|
|
9楼#
发布于:2002-12-11 18:24
http://www.csdn.net/develop/read_article.asp?id=10729
的test1.zip DOWN不下来,谁能给我发一份或是类似这个例子的VC工程,多谢了! 100分奉上! WESIN@MYREALBOX.COM [编辑 - 12/11/02 by wesintj] [编辑 - 12/11/02 by wesintj] |
|
10楼#
发布于:2002-12-11 20:07
我也要一份
zxy2845986@163.com |
|
11楼#
发布于:2002-12-11 21:20
我也要一份
dupontyp@hotmail.com |
|
12楼#
发布于:2002-12-12 08:59
我也要一份
jsguard2002@163.com |
|
13楼#
发布于:2002-12-12 09:54
请给我发一份
domore@vip.sina.com |
|
14楼#
发布于:2002-12-12 13:09
上传
|
|
|
15楼#
发布于:2002-12-12 14:33
万分 感谢Tomgin的善举
100分在 http://www.driverdevelop.com/forum/html_29515.html?1039674769 送出 |
|
16楼#
发布于:2002-12-13 12:44
不必,应该做的。
我在这个论坛上也学到了不少东西。 |
|
|
17楼#
发布于:2004-03-27 21:40
谁编译过test1.zip?
我编译通过,但没有生成sys 倒是作者给的sys可以加载 怎么回事? |
|
|
18楼#
发布于:2004-10-16 10:40
我为什么不能动态加载呢?
执行CreateService时返回0。 可是执行OpenService时确实正确的。 之后执行到StartService时返回的又是0。最好是执行失败。 这是为什么?望指点。 |
|
19楼#
发布于:2005-01-11 14:51
好帖子啊
|
|
|
上一页
下一页