完成例程

当IRP在某设备桟时,IRP被IoCompleteRequest完成的时候,会一层层出桟.

如果设置了完成例程,那么系统将会调用该层的完成例程.


VOID   IoSetCompletionRoutine(
    IN PIRP  Irp,
    IN PIO_COMPLETION_ROUTINE  CompletionRoutine,
    IN PVOID  Context,
    IN BOOLEAN    InvokeOnSuccess,
    IN BOOLEAN  InvokeOnError,
    IN BOOLEAN  InvokeOnCancel
    );
VOID   IoDetachDevice(
    IN OUT PDEVICE_OBJECT  TargetDevice
    );




下面一个完成例程例子用了一个事件,用这个事件同步

(注:

依然是用到前面几章博文中的被测试驱动,,

还有这篇是在上一篇博文的基础再加一点东西的,如果部分不清楚可以参考上一篇博文)


NTSTATUS IoCompletion(  IN PDEVICE_OBJECT  DeviceObject,
		      IN PIRP  Irp,
		     IN PVOID  Context)
{

	KdPrint(("DRIVER8_IoCompletion"));
	KEVENT *pEvent=(KEVENT*)Context;
	KeSetEvent(pEvent,0,FALSE);
	return STATUS_SUCCESS;
	//return STATUS_MORE_PROCESSING_REQUIRED;
}


NTSTATUS DRIVER8_DispatchRead(
							  IN PDEVICE_OBJECT		DeviceObject,
							  IN PIRP				Irp)
{

	KdPrint(("DRIVER8_DispatchRead entry"));
	NTSTATUS status = STATUS_SUCCESS;
	// 	Irp->IoStatus.Status = status;
	// 	Irp->IoStatus.Information = 0;
	// 	IoCompleteRequest(Irp, IO_NO_INCREMENT);

	DEVICE_EXTENSION *pDex=(DEVICE_EXTENSION*)DeviceObject->DeviceExtension;
	IoSkipCurrentIrpStackLocation(Irp);
	KEVENT kEvent;
	KeInitializeEvent(&kEvent,NotificationEvent,FALSE);
	IoSetCompletionRoutine(Irp,IoCompletion,(PVOID)&kEvent,true,true,true);
	status=IoCallDriver(pDex->pTargetDevObj,Irp);
	KeWaitForSingleObject(&kEvent,Executive,KernelMode,FALSE,NULL);
	//在IoCallDriver后,不能再操作IRP,会出错
	//如果想要再次操作IRP,请在完成例程的返回值改为 STATUS_MORE_PROCESSING_REQUIRED
	KdPrint(("DRIVER8_DispatchRead finished"));
	return status;
}


评论列表