0
回答
菜鸟之驱动开发2
利用AWS快速构建适用于生产的无服务器应用程序,免费试用12个月>>>   
 

上一篇文章里我们写了第一个驱动程序-HelloWorld, 今天我们来完善它,主要完成两个功能:添加一个驱动设备与给驱动添加默认派遣(IRP)。

首先我们来完成第一个功能:添加一个驱动设备。

代码如下:

 

NTSTATUS CreateTheDevice(IN PDRIVER_OBJECT pDeviceObject)
{
	NTSTATUS status;
	PDEVICE_OBJECT pDevObj;
	
	UNICODE_STRING devName;
	UNICODE_STRING symLinkName;
	
	RtlInitUnicodeString(&devName, L"\\Device\\first_Device");
	
	//create device
	status = IoCreateDevice(pDeviceObject,\
		0,\
		&devName,\
		FILE_DEVICE_UNKNOWN,\
		0,\
		TRUE,\
		&pDevObj\
	);
	if (!NT_SUCCESS(status))
	{
		if (STATUS_INSUFFICIENT_RESOURCES == status)
		{
			KdPrint(("资源不足"));
		}
		
		if (STATUS_OBJECT_NAME_EXISTS == status)
		{
			KdPrint(("指定对象名存在"));
		}
		
		if (STATUS_OBJECT_NAME_COLLISION == status)
		{
			KdPrint(("//对象名有冲突"));
		}
        
		KdPrint(("设备创建失败"));
		return status;
	}
	
	KdPrint(("创建设备成功"));
	
	pDevObj->Flags |= DO_BUFFERED_IO;
	
	//创建符号链接
	RtlInitUnicodeString(&symLinkName,L"\\??\\firstSymDevice");
	status = IoCreateSymbolicLink( &symLinkName,&devName );
	if (!NT_SUCCESS(status)) /*status等于0*/
	{
		IoDeleteDevice( pDevObj );
		return status;
	}
	return STATUS_SUCCESS;
}


这样就可以给我们的驱动加入一个设备,驱动开发是unicode的方式,所以不能直接用用户态的API去处理字符串,必须用Rtl开头的内核函数,如上面RtlInitUnicodeString就是给第一个参数初始化。

第二个功能是关于IRP的,什么叫IRP(I/O Request  Package).用户模式下所有对驱动的I/O请求,全部由操作系统转化为一个叫着IRP的数据结构,不同的IRP请求会被“派遣”到不同的派遣函数中。

有五种常用IRP类型,分别是:

#define IRP_MJ_CREATE                     0x00 //CreateFile()
#define IRP_MJ_CLOSE                      0x02 //CloseHandle()  
#define IRP_MJ_READ                       0x03//ReadFile
#define IRP_MJ_WRITE                      0x04//WriteFile
#define IRP_MJ_DEVICE_CONTROL           0x0e//DeviceIoControl 


步骤是:

1.创建IRP处理函数

2.在驱动入口外注册IRP处理发函数

3.实现IRP处理函数

有两种方式注册IRP派遣函数,第一种是只有一个派遣函数,在该派遣函数内分别对根据IRP类型做不同的处理,这种方式代码如下:

//注册派遗函数
pDriverObject->MajorFunction[IRP_MJ_CREATE]=ddk_DispatchRoutine;
//注册派遗函数
pDriverObject->MajorFunction[IRP_MJ_CLOSE]=ddk_DispatchRoutine;
//注册派遗函数
pDriverObject->MajorFunction[IRP_MJ_READ]=ddk_DispatchRoutine;
//注册派遗函数
pDriverObject->MajorFunction[IRP_MJ_WRITE]=ddk_DispatchRoutine;
//注册派遗函数
pDriverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL]=ddk_DispatchRoutine;





NTSTATUS ddk_DispatchRoutine(IN PDEVICE_OBJECT pDevobj,IN PIRP pIrp	)
{
   PIO_STACK_LOCATION irpsp=IoGetCurrentIrpStackLocation(pIrp);
   switch (irpsp->MajorFunction) 
   {
	   case IRP_MJ_CREATE:
		   break;
	   case IRP_MJ_CLOSE:
		   break;
	   case IRP_MJ_READ:
		   break;
	   case IRP_MJ_WRITE:
		   break;
	   case  IRP_MJ_DEVICE_CONTROL:
		   break;
	   default:
     KdPrint(("其它处理"));
//指示完成此IRP
		    
}
 //成功返回
	return STATUS_SUCCESS;
}


 

第二种是对每一种类型的IRP注册一个派遣函数,代码如下:

 

//注册派遗函数
pDriverObject->MajorFunction[IRP_MJ_CREATE]=ddk_DispatchRoutine_CREATE;
//注册派遗函数
pDriverObject->MajorFunction[IRP_MJ_CLOSE]=ddk_DispatchRoutine_CLOSE;
//注册派遗函数
pDriverObject->MajorFunction[IRP_MJ_READ]=ddk_DispatchRoutine_READ;
//注册派遗函数
pDriverObject->MajorFunction[IRP_MJ_WRITE]=ddk_DispatchRoutine_WRITE;
//注册派遗函数
pDriverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL]=ddk_DispatchRoutine_CONTROL;

NTSTATUS ddk_DispatchRoutine_CONTROL(IN PDEVICE_OBJECT pDevobj,IN PIRP pIrp	)
{
    //对相应的IPR进行处理
   pIrp->IoStatus.Information=0;//设置操作的字节数为0,这里无实际意义
   pIrp->IoStatus.Status=STATUS_SUCCESS;//返回成功
   IoCompleteRequest(pIrp,IO_NO_INCREMENT);//指示完成此IRP
   KdPrint(("离开派遣函数\n"));//调试信息
   return STATUS_SUCCESS; //返回成功
}


到此代码介绍完毕, 记得在卸载驱动的时候,要卸载设备,不然下次加载驱动的时候,因为设备没有卸载而不能成功创建设备。请参看完整的源码 。


原文链接:http://blog.csdn.net/favormm/article/details/6689835
<无标签>
举报
长平狐
发帖于5年前 0回/75阅
顶部