IRP_完成例程(二)-返回STATUS_MORE_PROCESSING_REQUIRED

说明:
(1)当IRP被IoCompleteRequest完成时,就开始从设备堆栈一层一层的向上“回卷”。
(2)当在某一层堆栈遇到有完成例程,则会进入到该完成例程,若这个完成例程返回STATUS_MORE_PROCESSING_REQUIRED,则停止向上“回卷”。
(3)此时本层设备栈又重新获得对IRP的控制权,并且该IRP又变成未完成状态,需要再次调用IoCompleteRequest来完成IRP。


下面示例代码:

///
///
/// Copyright (c) 2014 - <company name here>
///
/// Original filename: DriverB.cpp
/// Project          : DriverB
/// Date of creation : 2014-06-27
/// Author(s)        : <author name(s)>
///
/// Purpose          : <description>
///
/// Revisions:
///  0000 [2014-06-27] Initial revision.
///
///

// $Id$

#ifdef __cplusplus
extern "C" {
#endif
#include <ntddk.h>
#include <string.h>
#ifdef __cplusplus
}; // extern "C"
#endif

#include "DriverB.h"

#ifdef __cplusplus
namespace { // anonymous namespace to limit the scope of this global variable!
#endif
PDRIVER_OBJECT pdoGlobalDrvObj = 0;
#ifdef __cplusplus
}; // anonymous namespace
#endif



typedef struct _DEVICE_EXTENSION 
{
	PDEVICE_OBJECT pCreateDevObj;
	UNICODE_STRING usCreateDevName;
	UNICODE_STRING usCreateLinkName;

	PDEVICE_OBJECT pTargetedDevObj;

}DEVICE_EXTENSION,*PDEVICE_EXTENSION;


NTSTATUS DRIVERB_DispatchCreateClose(
    IN PDEVICE_OBJECT		DeviceObject,
    IN PIRP					Irp
    )
{
     NTSTATUS status = STATUS_SUCCESS;
//     Irp->IoStatus.Status = status;
//     Irp->IoStatus.Information = 0;
//     IoCompleteRequest(Irp, IO_NO_INCREMENT);

	 PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;

	 IoSkipCurrentIrpStackLocation(Irp);
	 status = IoCallDriver(pdx->pTargetedDevObj,Irp);

    return status;
}

NTSTATUS DRIVERB_DispatchDeviceControl(
    IN PDEVICE_OBJECT		DeviceObject,
    IN PIRP					Irp
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);

    switch(irpSp->Parameters.DeviceIoControl.IoControlCode)
    {
    case IOCTL_DRIVERB_OPERATION:
        // status = SomeHandlerFunction(irpSp);
        break;
    default:
        Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
        Irp->IoStatus.Information = 0;
        break;
    }

    status = Irp->IoStatus.Status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
}

VOID DRIVERB_DriverUnload(
    IN PDRIVER_OBJECT		DriverObject
    )
{
    PDEVICE_OBJECT pdoNextDeviceObj = pdoGlobalDrvObj->DeviceObject;
    //IoDeleteSymbolicLink(&usSymlinkName);


    // Delete all the device objects
    while(pdoNextDeviceObj)
    {
		PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pdoNextDeviceObj->DeviceExtension;
		pdoNextDeviceObj = pDevExt->pCreateDevObj->NextDevice;//pdoThisDeviceObj->NextDevice;
		 IoDetachDevice(pDevExt->pTargetedDevObj);
		 IoDeleteSymbolicLink(&pDevExt->usCreateLinkName);
		 IoDeleteDevice(pDevExt->pCreateDevObj);
		 
    }
}

NTSTATUS
IoReadCompletion(
			 __in PDEVICE_OBJECT  DeviceObject,
			 __in PIRP  Irp,
			 __in PVOID  Context
			 )

{
	//进入此函数标志底层驱动设备将IRP完成
	KdPrint(("entry..IoReadCompletion..."));

/*
	if (Irp->PendingReturned)
	{
		//传播pending位
		IoMarkIrpPending(Irp);//完成例程返回STATUS_MORE_PROCESSING_REQUIRED时,不可以设置IoMarkIrpPending

		//PKEVENT PKevent = (PKEVENT)Context;
		//KeSetEvent(PKevent,IO_NO_INCREMENT,FALSE);
	}
*/

	
	KdPrint(("leave..IoReadCompletion..."));

	PKEVENT PKevent = (PKEVENT)Context;
	KeSetEvent(PKevent,IO_NO_INCREMENT,FALSE);
	
	return STATUS_MORE_PROCESSING_REQUIRED;//STATUS_SUCCESS;

}

NTSTATUS DispatchRead(PDEVICE_OBJECT pDevObj,PIRP pIrp)
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;

	KdPrint(("entry..DispatchRead..."));

	//将irp下发给 下层驱动处理
	PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;

	//将当前IO堆栈拷贝到下一层堆栈
	IoCopyCurrentIrpStackLocationToNext(pIrp);

	//设置KEVENT传递给完成例程,并将完成例程返回STATUS_MORE_PROCESSING_REQUIRED,irp“回卷”时重新获得IRP的控制权
	KEVENT kEvent;
	KeInitializeEvent(&kEvent,NotificationEvent,FALSE);

	//设置IRP的完成例程
	IoSetCompletionRoutine(pIrp,IoReadCompletion,&kEvent,TRUE,TRUE,TRUE);

	status = IoCallDriver(pDevExt->pTargetedDevObj,pIrp);//转发IRP给下层驱动

	if (status == STATUS_PENDING)
	{
		KdPrint(("DrvierB:DispatchRead::IoCallDriver STATUS_PENDING...."));
		KeWaitForSingleObject(&kEvent,Executive,KernelMode,FALSE,NULL);
		KdPrint(("DrvierB:IoReadCompletion::finish STATUS_PENDING...."));

		status = pIrp->IoStatus.Status;

		
		
	}


	//此时需要再次调用来完成IRP,但是本程序再此处会有发送多个IRP完成的蓝屏?????为什么?
	//原因://完成例程返回STATUS_MORE_PROCESSING_REQUIRED时,不可以设置IoMarkIrpPending
	IoCompleteRequest(pIrp,IO_NO_INCREMENT);
	
	KdPrint(("leave..DispatchRead..."));

	return status;

}

#ifdef __cplusplus
extern "C" {
#endif
NTSTATUS DriverEntry(
    IN OUT PDRIVER_OBJECT   DriverObject,
    IN PUNICODE_STRING      RegistryPath
    )
{
    PDEVICE_OBJECT pdoDeviceObj = 0;
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    pdoGlobalDrvObj = DriverObject;
	PDEVICE_EXTENSION pDevExt = NULL;

	KdPrint(("entry..DriverB::::DriverEntry..."));


    // Create the device object.
    if(!NT_SUCCESS(status = IoCreateDevice(
        DriverObject,
        sizeof(DEVICE_EXTENSION),//0,
        &usDeviceName,
        FILE_DEVICE_UNKNOWN,
        FILE_DEVICE_SECURE_OPEN,
        FALSE,
        &pdoDeviceObj
        )))
    {
		KdPrint(("IoCreateDevice  Error status:0x%x",status));

        // Bail out (implicitly forces the driver to unload).
        return status;
    };

	

    // Now create the respective symbolic link object
    if(!NT_SUCCESS(status = IoCreateSymbolicLink(
        &usSymlinkName,
        &usDeviceName
        )))
    {
		KdPrint(("IoCreateSymbolicLink  Error status:0x%x",status));

        IoDeleteDevice(pdoDeviceObj);
        return status;
    }

    // NOTE: You need not provide your own implementation for any major function that
    //       you do not want to handle. I have seen code using DDKWizard that left the
    //       *empty* dispatch routines intact. This is not necessary at all!
    DriverObject->MajorFunction[IRP_MJ_CREATE] =
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = DRIVERB_DispatchCreateClose;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DRIVERB_DispatchDeviceControl;
	DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
    DriverObject->DriverUnload = DRIVERB_DriverUnload;

	//\\Device\\MDeviceA
	UNICODE_STRING usAttDevName;
	RtlInitUnicodeString(&usAttDevName,L"\\Device\\MDeviceA");

	PDEVICE_OBJECT pAttDevObj;
	PFILE_OBJECT pAttFileObj;

	status  = IoGetDeviceObjectPointer(&usAttDevName,FILE_ALL_ACCESS,&pAttFileObj,&pAttDevObj);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("IoGetDeviceObjectPointer  Error status:0x%x",status));
		IoDeleteSymbolicLink(&usSymlinkName);

		IoDeleteDevice(pdoDeviceObj);

		return status;
	}

	PDEVICE_OBJECT PAttachedDevice = IoAttachDeviceToDeviceStack(pdoDeviceObj,pAttDevObj);
	if (PAttachedDevice == NULL)
	{

		KdPrint(("IoAttachDeviceToDeviceStack  Error status:0x%x",status));

		ObDereferenceObject(pAttFileObj);
		IoDeleteSymbolicLink(&usSymlinkName);
		IoDeleteDevice(pdoDeviceObj);

	}

	//初始化设备扩展
	pDevExt = (PDEVICE_EXTENSION)pdoDeviceObj->DeviceExtension;
	pDevExt->usCreateDevName = usDeviceName;
	pDevExt->usCreateLinkName = usSymlinkName;
	pDevExt->pCreateDevObj = pdoDeviceObj;
	pDevExt->pTargetedDevObj = PAttachedDevice;

	//设置设备属性匹配被绑定的设备
	pdoDeviceObj->Characteristics = PAttachedDevice->Characteristics;
	pdoDeviceObj->DeviceType = PAttachedDevice->DeviceType;
	pdoDeviceObj->Flags &= ~ DO_DEVICE_INITIALIZING;
	pdoDeviceObj->Flags |= PAttachedDevice->Flags &(DO_BUFFERED_IO | DO_DIRECT_IO);

	ObDereferenceObject(&pAttFileObj);

	KdPrint(("leave..DriverB::::DriverEntry..."));


	status = STATUS_SUCCESS;
    return status/*STATUS_SUCCESS*/;
}
#ifdef __cplusplus
}; // extern "C"
#endif


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值