DriverEntry主要是对驱动程序进行初始化工作,它由系统进程(System)调用。驱动加载的时候,System进程启动新的线程新的线程,调用执行体组件的对象管理器,创建一个驱动对象。另外,System进程调用执行体组件中的配置管理程序,查询此驱动程序对应的注册表中的项。System进程调用DriverEntry例程时,同时传进两个参数。pDriverobject 指向刚被创建驱动对象的指针,pRegistryPath指向设备服务键的键名字符串的指针。这个键名有时候需要保存下来,因为这个字符不是长期存在的(函数返回后可能消失)。如果以后想使用这个UNICODE 字符串就必须先把它复制到安全的地方。
下面是一个NT框架代码:
#include
//自己第一扩展DO结构体
typedef struct _DEVICE_EXTENSIONN
{
PDEVICE_OBJECT pDevObj;//指向DO
UNICODE_STRING ustrDevName;
UNICODE_STRING ustrLinkName;
}DEVICE_EXTENSION,*PDEVICE_EXTENSION;
void MyUnload(PDRIVER_OBJECT pDriverObj)
{
PDEVICE_OBJECT pNexObj;
DbgPrint("Enter DriverUnload");
pNexObj=pDriverObj->DeviceObject;
//枚举所有对象
while(pNexObj)
{
//得到设备扩展
PDEVICE_EXTENSION pDevEx=(PDEVICE_EXTENSION)pNexObj->DeviceExtension;
//删除符号链接
UNICODE_STRING ustrLinkName=pDevEx->ustrLinkName;
IoDeleteSymbolicLink(&ustrLinkName);
pNexObj=pNexObj->NextDevice;
//删除DO
IoDeleteDevice(pDevEx->pDevObj);
}
}
NTSTATUS CreateDevice(PDRIVER_OBJECT pDriverObj)
{
NTSTATUS status;
PDEVICE_OBJECT pDeviceObj;
PDEVICE_EXTENSION pDevEx;
//创建设备名称
UNICODE_STRING devName;
UNICODE_STRING ustrLinkName;
RtlInitUnicodeString(&devName,L"\\Device\\MyDevice");//A named device object has a name of the form \Device\DeviceName.
//This is known as the NT device name of the device object.
#ifdef DBG
_asm int 3;
#endif
// 创建设备
status=IoCreateDevice(pDriverObj,
sizeof(DEVICE_EXTENSION),
&devName,
FILE_DEVICE_UNKNOWN,
0,TRUE,
&pDeviceObj);
//判断设备是否创建成功
if(!NT_SUCCESS(status))
return status;
//将设备设置成缓冲区设备
pDeviceObj->Flags|=DO_BUFFERED_IO;
//得到设备扩展
pDevEx=(PDEVICE_EXTENSION)pDeviceObj->DeviceExtension;
//设置扩展对象的DO
pDevEx->pDevObj=pDeviceObj;
//设置扩展对象DO 名字
pDevEx->ustrDevName=devName;
//创建符号链接
RtlInitUnicodeString(&ustrLinkName,L"\\??\\MyDriverDes");
pDevEx->ustrLinkName=ustrLinkName;
status=IoCreateSymbolicLink(&ustrLinkName,&devName);
//判断是否成功创建符号链接
if(!NT_SUCCESS(status))
{
//IoDeleteSymbolicLink(&ustrLinkName);
IoDeleteDevice(pDeviceObj);
return status;
}
return status;
}
/*
* 函数功能:设置卸载函数和IRP派遣函数
*
*/
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj,
PUNICODE_STRING pRegPath)
{
NTSTATUS s;
UNREFERENCED_PARAMETER(pDriverObj);
UNREFERENCED_PARAMETER(pRegPath);
DbgPrint("Enter DriverEntry");
//注册其他调用函数入口
pDriverObj->DriverUnload=MyUnload;
//pDriverObj->MajorFunction[IRP_MJ_CREATE]=MyDispatchFun;
//pDriverObj->MajorFunction[IRP_MJ_CLOSE]=MyDispatchFun;
//pDriverObj->MajorFunction[IRP_MJ_WRITE]=MyDispatchFun;
//pDriverObj->MajorFunction[IRP_MJ_READ]=MyDispatchFun;
//创建DO
s=CreateDevice(pDriverObj);
DbgPrint("Enter DriverEntry End");
return s;
}
上面代码还有一点需要注意的:
1.IoCreateDevice 被调用时,如果指定了设备名,只能被内核模式下的其他驱动程序所识别。但是在用户模式下
的应用程序无法识别这个设备。让用户模式下的应用程序能识别设备有两种方法,第一种:通过符号链接找到设备,第二种通过设备接口找到设备。设备接口的办法在NT驱动中通常不用,符号链接可以理解为设备对象起了一个“别名”。设备对象名称只能被内核模式下的驱动识别,而别名也可以被用户名模式下的应用程序识别。例如,常说的c盘,D盘就是符号链接。所谓的C盘,指的是名为“C:”的符号链接,而真正的设备对象是"\Device\HarddiskVolume1","D:"所代表的真正设备对象是“\Device\HarddistVolume2”.创建符号链接的函数是IoCreateSymbolicLink.内核模式下是以"\??\"开头的或\DosDevices\。