驱动程序的取消IRP

转载自: http://blog.csdn.net/zacklin/article/details/7612888

一、理论

当应用层发出的IRP请求很久得不到处理的时候,有时需要把IRP请求取消,每一个IRP都可以对应一个取消例程,通过IoSetCancelRoutine(pIrp,CancelReadIRP);函数把IRP与取消例程进行关联,当要删除取消例程时,把第二个参数设为空即IoSetCancelRoutine(pIrp,NULL);即可。

程序员可以用IoCancelIrp函数取消IRP的请求,该函数在内部通过在IoAcquireCancelSpinLock函数获得取消自旋锁,因为在我们的取消例程中必须要调用IoReleaseCancelSpinLock函数释放取消自旋锁。在应用层可以通过调用CancelIrp取消IRP请求

二、例子

下面是驱动程序:

 

#include<ntddk.h>

typedef struct _Ext
{
 UNICODE_STRING devicename;
 UNICODE_STRING symbolicname;
}DEVICE_EXTENSION,*PDEVICE_EXTENSION;

VOID CancelReadIRP(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp);
VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject);
NTSTATUS DeviceCreate(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp);
NTSTATUS DeviceClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp);
NTSTATUS DeviceRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp);

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath)
{
	NTSTATUS status=STATUS_SUCCESS;
	PDEVICE_OBJECT pDeviceObject=NULL;
	UNICODE_STRING DeviceName,Symbolname;
	PDEVICE_EXTENSION pDeviceExt=NULL;
	RtlInitUnicodeString(&DeviceName,L"\\Device\\Device_8");
	RtlInitUnicodeString(&Symbolname,L"\\??\\Device_8_Symbol");
	KdPrint(("Enter DriverEntry!\n"));
	pDriverObject->MajorFunction[IRP_MJ_CREATE]=DeviceCreate;
	pDriverObject->MajorFunction[IRP_MJ_CLOSE]=DeviceClose;
	pDriverObject->MajorFunction[IRP_MJ_READ]=DeviceRead;
	pDriverObject->DriverUnload=DriverUnload;
	status=IoCreateDevice(pDriverObject,
	sizeof(DEVICE_EXTENSION),
	&DeviceName,
	FILE_DEVICE_UNKNOWN,
	0,
	TRUE,
	&pDeviceObject);
	if(!NT_SUCCESS(status))
	{
		KdPrint(("\ncreate device fail!\n"));
		return status;
	}
	KdPrint(("\nCreate Device Successfully!\n"));
	pDeviceObject->Flags|=DO_BUFFERED_IO;
	status=IoCreateSymbolicLink(&Symbolname,&DeviceName);
	if(!NT_SUCCESS(status))
	{
		KdPrint(("\nCreate symbolic fail!\n"));
		IoDeleteDevice(pDeviceObject);
		return status;
	}
	KdPrint(("\nCreate symbolicLink successfully!\n"));
	pDeviceExt=(PDEVICE_EXTENSION)pDeviceObject->DeviceExtension;
	pDeviceExt->devicename=DeviceName;
	pDeviceExt->symbolicname=Symbolname;
	return status;
}
VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject)
{
	PDEVICE_OBJECT pDeviceObject;
	PDEVICE_EXTENSION pDeviceExt;
	pDeviceObject=pDriverObject->DeviceObject;
	if(pDeviceObject!=NULL)
	{
		pDeviceExt=(PDEVICE_EXTENSION)pDeviceObject->DeviceExtension;
		if(pDeviceExt!=NULL)
		{
			IoDeleteSymbolicLink(&pDeviceExt->symbolicname);
			IoDeleteDevice(pDeviceObject);
			KdPrint(("\nDriverUnload Successfully!\n"));
			return;
		}
	}
	KdPrint(("\nDriverUnload fail!\n"));
}
NTSTATUS DeviceCreate(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp)
{
	NTSTATUS status=STATUS_SUCCESS;
	KdPrint(("\nEnter Create Device  \n"));
	pIrp->IoStatus.Status=status;
	pIrp->IoStatus.Information=0;
	IoCompleteRequest(pIrp,0);
	return status;
}
NTSTATUS DeviceClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp)
{
	NTSTATUS status=STATUS_SUCCESS;
	KdPrint(("\nEnter Close Device \n"));
	pIrp->IoStatus.Status=status;
	pIrp->IoStatus.Information=0;
	IoCompleteRequest(pIrp,0);
	KdPrint(("\nClose Device Successfully!\n"));
	return status;
}
NTSTATUS DeviceRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp)
{
	KdPrint(("\nEnter Read IRP \n"));
	IoSetCancelRoutine(pIrp,CancelReadIRP);
	IoMarkIrpPending(pIrp);
	KdPrint(("\nLeave Read IRP  \n"));
	return STATUS_PENDING;
}
VOID CancelReadIRP(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp)
{
	KdPrint(("\nEnter CancelReadIRP\n"));
	pIrp->IoStatus.Status=STATUS_CANCELLED;
	pIrp->IoStatus.Information=0;
	IoCompleteRequest(pIrp,0);
	IoReleaseCancelSpinLock(pIrp->CancelIrql);//释放取消锁
	KdPrint(("\nLeave CancelReadIRP\n"));
}


下面的是应用层的测试程序:

#include<windows.h>
#include<stdio.h>
int main()
{
	HANDLE hDevice=CreateFile("\\\\.\\Device_8_Symbol",
	GENERIC_READ|GENERIC_WRITE,
	0,
	NULL,
	OPEN_EXISTING,
	FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
	NULL);
	if(hDevice==INVALID_HANDLE_VALUE)
	{
		printf("Open Device failed!\n");
		return 1;
	}
	OVERLAPPED overlap1={0};
	OVERLAPPED overlap2={0};
	ULONG ulread;
	char buffer[10];
	BOOL bread=ReadFile(hDevice,buffer,10,&ulread,&overlap1);
	if(!bread&&GetLastError()==ERROR_IO_PENDING)
	{
		printf("The Operation is pending\n");
	}
	bread=ReadFile(hDevice,buffer,10,&ulread,&overlap2);
	if(!bread&&GetLastError()==ERROR_IO_PENDING)
	{
		printf("The Operation is pending\n");
	}
	Sleep(3000);
	CancelIo(hDevice);
	CloseHandle(hDevice);
	return 0;
}

现象:会提示“The Operation is pending”, 直到调用了CancelIo(hDevice)后,会调用我们的删除例如程,将IRP删除掉。

你可能感兴趣的:(object,String,File,null,buffer,extension)