加载一个驱动程序,主要就是,在
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
#include
#include
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:
eleteSrevice() Faild %d !\n", GetLastError() );}
else
{
printf( "DelSvr:
eleteSrevice() ok !\n" );}
CloseServiceHandle( hServiceTwdm );
CloseServiceHandle( hServiceMgr );
return;
}
驱动程序:驱动程序很简单,
只有一个文件,实现了DriverEntry,DispatchCreate,DispatchClose,GpdUnload 四个函数。
#include
#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_Test1.zipTest1.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