Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228/* * CSQ Test Driver * Copyright (c) 2004, Vizzini (vizzini@plasmic.com) * Released under the GNU GPL for the ReactOS project * * This driver is designed to exercise the cancel-safe IRP queue logic. * Please refer to reactos/include/ddk/csq.h and reactos/drivers/lib/csq. */#include <ntddk.h>#include <csq.h>
/* XXX shortcomings in our headers... */#define assert(x)#ifndef KdPrint#define KdPrint(x) DbgPrint x#endif
/* Device name */#define NT_DEVICE_NAME L"\\Device\\csqtest"
/* DosDevices name */#define DOS_DEVICE_NAME L"\\??\\csqtest"
/* Global CSQ struct that the CSQ functions init */IO_CSQ Csq;
/* List and lock for the actual IRP queue */LIST_ENTRY IrpQueue;KSPIN_LOCK IrpQueueLock;
/* Device object */PDEVICE_OBJECT DeviceObject;
/* * CSQ Callbacks */VOID NTAPI CsqInsertIrp(PIO_CSQ Csq, PIRP Irp){ KdPrint(("Inserting IRP 0x%x into CSQ\n", Irp)); InsertTailList(&IrpQueue, &Irp->Tail.Overlay.ListEntry);}
VOID NTAPI CsqRemoveIrp(PIO_CSQ Csq, PIRP Irp){ KdPrint(("Removing IRP 0x%x from CSQ\n", Irp)); RemoveEntryList(&Irp->Tail.Overlay.ListEntry);}
PIRP NTAPI CsqPeekNextIrp(PIO_CSQ Csq, PIRP Irp, PVOID PeekContext){ KdPrint(("Peeking for next IRP\n"));
if(Irp) return CONTAINING_RECORD(&Irp->Tail.Overlay.ListEntry.Flink, IRP, Tail.Overlay.ListEntry);
if(IsListEmpty(&IrpQueue)) return NULL;
return CONTAINING_RECORD(IrpQueue.Flink, IRP, Tail.Overlay.ListEntry);}
VOID NTAPI CsqAcquireLock(PIO_CSQ Csq, PKIRQL Irql){ KdPrint(("Acquiring spin lock\n")); KeAcquireSpinLock(&IrpQueueLock, Irql);}
VOID NTAPI CsqReleaseLock(PIO_CSQ Csq, KIRQL Irql){ KdPrint(("Releasing spin lock\n")); KeReleaseSpinLock(&IrpQueueLock, Irql);}
VOID NTAPI CsqCompleteCancelledIrp(PIO_CSQ Csq, PIRP Irp){ KdPrint(("cancelling irp 0x%x\n", Irp)); Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT);}
NTSTATUS NTAPI CsqInsertIrpEx(PIO_CSQ Csq, PIRP Irp, PVOID InsertContext)/* * FUNCTION: Insert into IRP queue, with extra context * * NOTE: Switch call in DriverEntry to IoCsqInitializeEx to use this */{ CsqInsertIrp(Csq, Irp); return STATUS_PENDING;}
/* * DISPATCH ROUTINES */
NTSTATUS NTAPI DispatchCreateCloseCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp){ PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
if(StackLocation->MajorFunction == IRP_MJ_CLEANUP) { /* flush the irp queue */ PIRP CurrentIrp;
KdPrint(("csqtest: Cleanup received; flushing the IRP queue with cancel\n"));
while((CurrentIrp = IoCsqRemoveNextIrp(&Csq, 0))) { CurrentIrp->IoStatus.Status = STATUS_CANCELLED; CurrentIrp->IoStatus.Information = 0;
IoCompleteRequest(CurrentIrp, IO_NO_INCREMENT); } }
Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;}
NTSTATUS NTAPI DispatchReadWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp){ /* According to the cancel sample in the DDK, IoCsqInsertIrp() marks the irp pending */ /* However, I think it's wrong. */ IoMarkIrpPending(Irp); IoCsqInsertIrp(&Csq, Irp, 0);
return STATUS_PENDING;}
NTSTATUS NTAPI DispatchIoctl(PDEVICE_OBJECT DeviceObject, PIRP Irp)/* * all IOCTL requests flush the irp queue */{ PIRP CurrentIrp;
KdPrint(("csqtest: Ioctl received; flushing the IRP queue with success\n"));
while((CurrentIrp = IoCsqRemoveNextIrp(&Csq, 0))) { CurrentIrp->IoStatus.Status = STATUS_SUCCESS; CurrentIrp->IoStatus.Information = 0;
IoCompleteRequest(CurrentIrp, IO_NO_INCREMENT); }
Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;}
VOID NTAPI Unload(PDRIVER_OBJECT DriverObject)/* * Function: called by the OS to release resources before unload */{ UNICODE_STRING LinkName;
RtlInitUnicodeString(&LinkName, DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&LinkName);
if(DeviceObject) IoDeleteDevice(DeviceObject);}
/* * DriverEntry */
NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath){ NTSTATUS Status; UNICODE_STRING NtName; UNICODE_STRING DosName;
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreateCloseCleanup; DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCreateCloseCleanup; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchCreateCloseCleanup; DriverObject->MajorFunction[IRP_MJ_READ] = DispatchReadWrite; DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchReadWrite; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl; DriverObject->DriverUnload = Unload;
Status = IoCsqInitialize(&Csq, CsqInsertIrp, CsqRemoveIrp, CsqPeekNextIrp, CsqAcquireLock, CsqReleaseLock, CsqCompleteCancelledIrp);
if(Status != STATUS_SUCCESS) KdPrint(("csqtest: IoCsqInitialize failed: 0x%x\n", Status)); else KdPrint(("csqtest: IoCsqInitialize succeeded\n"));
InitializeListHead(&IrpQueue); KeInitializeSpinLock(&IrpQueueLock);
/* Set up a device */ RtlInitUnicodeString(&NtName, NT_DEVICE_NAME); Status = IoCreateDevice(DriverObject, 0, &NtName, FILE_DEVICE_UNKNOWN, 0, 0, &DeviceObject);
if(!NT_SUCCESS(Status)) { KdPrint(("csqtest: Unable to create device: 0x%x\n", Status)); return Status; }
RtlInitUnicodeString(&DosName, DOS_DEVICE_NAME); Status = IoCreateSymbolicLink(&DosName, &NtName);
if(!NT_SUCCESS(Status)) { KdPrint(("csqtest: Unable to create link: 0x%x\n", Status)); return Status; }
DeviceObject->Flags |= DO_BUFFERED_IO;
return STATUS_SUCCESS;}