NT式驱动基本结构

1.对于NT式驱动来说,主要的函数是DriveEntry函数,卸载函数,以及各个IRP的派遣函数
2.驱动加载过程与驱动入口函数(DriverEntry)
   NTSTATUS DriveEntry(IN PDRIVER_OBJECT pDriverobject,
  IN PUNICODE_STRING pRegistryPath);//函数名可以自己定义

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\。




你可能感兴趣的:(内核,NT驱动)