Author: ion Date: Sun Jul 2 01:29:50 2006 New Revision: 22746
URL: http://svn.reactos.org/svn/reactos?rev=22746&view=rev Log: - Add definitions for additional DOE flags to NDK. - I/O Packet APIs improvements Part 2: - Implement IoSetStartIoAttributes - Obey StartIo Flags set by IoSetStartIoAttributes and change Packet functions to Windows XP/2003 semantics by supporting non-cancelable packets and deferred Start I/O calling.
Modified: trunk/reactos/include/ndk/iotypes.h trunk/reactos/ntoskrnl/io/device.c
Modified: trunk/reactos/include/ndk/iotypes.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/iotypes.h?rev=2... ============================================================================== --- trunk/reactos/include/ndk/iotypes.h (original) +++ trunk/reactos/include/ndk/iotypes.h Sun Jul 2 01:29:50 2006 @@ -123,6 +123,15 @@ #define DOE_REMOVE_PENDING 0x4 #define DOE_REMOVE_PROCESSED 0x8 #define DOE_START_PENDING 0x10 + +// +// Device Object StartIo Flags +// +#define DOE_SIO_NO_KEY 0x20 +#define DOE_SIO_WITH_KEY 0x40 +#define DOE_SIO_CANCELABLE 0x80 +#define DOE_SIO_DEFERRED 0x100 +#define DOE_SIO_NO_CANCEL 0x200
// // Device Node Flags
Modified: trunk/reactos/ntoskrnl/io/device.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/device.c?rev=22... ============================================================================== --- trunk/reactos/ntoskrnl/io/device.c (original) +++ trunk/reactos/ntoskrnl/io/device.c Sun Jul 2 01:29:50 2006 @@ -358,6 +358,171 @@ } }
+VOID +NTAPI +IopStartNextPacketByKey(IN PDEVICE_OBJECT DeviceObject, + IN BOOLEAN Cancelable, + IN ULONG Key) +{ + PKDEVICE_QUEUE_ENTRY Entry; + PIRP Irp; + KIRQL OldIrql; + + /* Acquire the cancel lock if this is cancelable */ + if (Cancelable) IoAcquireCancelSpinLock(&OldIrql); + + /* Clear the current IRP */ + DeviceObject->CurrentIrp = NULL; + + /* Remove an entry from the queue */ + Entry = KeRemoveByKeyDeviceQueue(&DeviceObject->DeviceQueue, Key); + if (Entry) + { + /* Get the IRP and set it */ + Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DeviceQueueEntry); + DeviceObject->CurrentIrp = Irp; + + /* Check if this is a cancelable packet */ + if (Cancelable) + { + /* Check if the caller requested no cancellation */ + if (IoGetDevObjExtension(DeviceObject)->StartIoFlags & + DOE_SIO_NO_CANCEL) + { + /* He did, so remove the cancel routine */ + Irp->CancelRoutine = NULL; + } + + /* Release the cancel lock */ + IoReleaseCancelSpinLock(OldIrql); + } + + /* Call the Start I/O Routine */ + DeviceObject->DriverObject->DriverStartIo(DeviceObject, Irp); + } + else + { + /* Otherwise, release the cancel lock if we had acquired it */ + if (Cancelable) IoReleaseCancelSpinLock(OldIrql); + } +} + +VOID +NTAPI +IopStartNextPacket(IN PDEVICE_OBJECT DeviceObject, + IN BOOLEAN Cancelable) +{ + PKDEVICE_QUEUE_ENTRY Entry; + PIRP Irp; + KIRQL OldIrql; + + /* Acquire the cancel lock if this is cancelable */ + if (Cancelable) IoAcquireCancelSpinLock(&OldIrql); + + /* Clear the current IRP */ + DeviceObject->CurrentIrp = NULL; + + /* Remove an entry from the queue */ + Entry = KeRemoveDeviceQueue(&DeviceObject->DeviceQueue); + if (Entry) + { + /* Get the IRP and set it */ + Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DeviceQueueEntry); + DeviceObject->CurrentIrp = Irp; + + /* Check if this is a cancelable packet */ + if (Cancelable) + { + /* Check if the caller requested no cancellation */ + if (IoGetDevObjExtension(DeviceObject)->StartIoFlags & + DOE_SIO_NO_CANCEL) + { + /* He did, so remove the cancel routine */ + Irp->CancelRoutine = NULL; + } + + /* Release the cancel lock */ + IoReleaseCancelSpinLock(OldIrql); + } + + /* Call the Start I/O Routine */ + DeviceObject->DriverObject->DriverStartIo(DeviceObject, Irp); + } + else + { + /* Otherwise, release the cancel lock if we had acquired it */ + if (Cancelable) IoReleaseCancelSpinLock(OldIrql); + } +} + +VOID +NTAPI +IopStartNextPacketByKeyEx(IN PDEVICE_OBJECT DeviceObject, + IN ULONG Key, + IN ULONG Flags) +{ + PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; + ULONG CurrentKey = Key; + ULONG CurrentFlags = Flags; + + /* Get the device extension and start the packet loop */ + DeviceExtension = IoGetDevObjExtension(DeviceObject); + while (TRUE) + { + /* Increase the count */ + if (InterlockedIncrement(&DeviceExtension->StartIoCount) > 1) + { + /* + * We've already called the routine once... + * All we have to do is save the key and add the new flags + */ + DeviceExtension->StartIoFlags |= CurrentFlags; + DeviceExtension->StartIoKey = CurrentKey; + } + else + { + /* Mask out the current packet flags and key */ + DeviceExtension->StartIoFlags &= ~(DOE_SIO_WITH_KEY | + DOE_SIO_NO_KEY | + DOE_SIO_CANCELABLE); + DeviceExtension->StartIoKey = 0; + + /* Check if this is a packet start with key */ + if (Flags & DOE_SIO_WITH_KEY) + { + /* Start the packet with a key */ + IopStartNextPacketByKey(DeviceObject, + (DOE_SIO_CANCELABLE) ? TRUE : FALSE, + CurrentKey); + } + else if (Flags & DOE_SIO_NO_KEY) + { + /* Start the packet */ + IopStartNextPacket(DeviceObject, + (DOE_SIO_CANCELABLE) ? TRUE : FALSE); + } + } + + /* Decrease the Start I/O count and check if it's 0 now */ + if (!InterlockedDecrement(&DeviceExtension->StartIoCount)) + { + /* Get the current active key and flags */ + CurrentKey = DeviceExtension->StartIoKey; + CurrentFlags = DeviceExtension->StartIoFlags & (DOE_SIO_WITH_KEY | + DOE_SIO_NO_KEY | + DOE_SIO_CANCELABLE); + + /* Check if we should still loop */ + if (!(CurrentFlags & (DOE_SIO_WITH_KEY | DOE_SIO_NO_KEY))) break; + } + else + { + /* There are still Start I/Os active, so quit this loop */ + break; + } + } +} + /* PUBLIC FUNCTIONS ***********************************************************/
/* @@ -1129,15 +1294,22 @@ }
/* - * @unimplemented + * @implemented */ VOID -STDCALL +NTAPI IoSetStartIoAttributes(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN DeferredStartIo, IN BOOLEAN NonCancelable) { - UNIMPLEMENTED; + PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; + + /* Get the Device Extension */ + DeviceExtension = IoGetDevObjExtension(DeviceObject); + + /* Set the flags the caller requested */ + DeviceExtension->StartIoFlags |= (DeferredStartIo) ? DOE_SIO_DEFERRED : 0; + DeviceExtension->StartIoFlags |= (NonCancelable) ? DOE_SIO_NO_CANCEL : 0; }
/* @@ -1149,34 +1321,24 @@ IN BOOLEAN Cancelable, IN ULONG Key) { - PKDEVICE_QUEUE_ENTRY Entry; - PIRP Irp; - KIRQL OldIrql; - - /* Acquire the cancel lock if this is cancelable */ - if (Cancelable) IoAcquireCancelSpinLock(&OldIrql); - - /* Clear the current IRP */ - DeviceObject->CurrentIrp = NULL; - - /* Remove an entry from the queue */ - Entry = KeRemoveByKeyDeviceQueue(&DeviceObject->DeviceQueue, Key); - if (Entry) - { - /* Get the IRP and set it */ - Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DeviceQueueEntry); - DeviceObject->CurrentIrp = Irp; - - /* Release the cancel lock if we had acquired it */ - if (Cancelable) IoReleaseCancelSpinLock(OldIrql); - - /* Call the Start I/O Routine */ - DeviceObject->DriverObject->DriverStartIo(DeviceObject, Irp); + PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; + + /* Get the Device Extension */ + DeviceExtension = IoGetDevObjExtension(DeviceObject); + + /* Check if deferred start was requested */ + if (DeviceExtension->StartIoFlags & DOE_SIO_DEFERRED) + { + /* Call our internal function to handle the defered case */ + return IopStartNextPacketByKeyEx(DeviceObject, + Key, + DOE_SIO_WITH_KEY | + (Cancelable) ? DOE_SIO_CANCELABLE : 0); } else { - /* Otherwise, release the cancel lock if we had acquired it */ - if (Cancelable) IoReleaseCancelSpinLock(OldIrql); + /* Call the normal routine */ + return IopStartNextPacketByKey(DeviceObject, Cancelable, Key); } }
@@ -1188,31 +1350,24 @@ IoStartNextPacket(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Cancelable) { - PKDEVICE_QUEUE_ENTRY Entry; - PIRP Irp; - KIRQL OldIrql; - - /* Acquire the cancel lock if this is cancelable */ - if (Cancelable) IoAcquireCancelSpinLock(&OldIrql); - - /* Clear the current IRP */ - DeviceObject->CurrentIrp = NULL; - - /* Remove an entry from the queue */ - Entry = KeRemoveDeviceQueue(&DeviceObject->DeviceQueue); - if (Entry) - { - /* Get the IRP and set it */ - Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DeviceQueueEntry); - DeviceObject->CurrentIrp = Irp; - - /* Call the Start I/O Routine */ - DeviceObject->DriverObject->DriverStartIo(DeviceObject, Irp); + PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; + + /* Get the Device Extension */ + DeviceExtension = IoGetDevObjExtension(DeviceObject); + + /* Check if deferred start was requested */ + if (DeviceExtension->StartIoFlags & DOE_SIO_DEFERRED) + { + /* Call our internal function to handle the defered case */ + return IopStartNextPacketByKeyEx(DeviceObject, + 0, + DOE_SIO_NO_KEY | + (Cancelable) ? DOE_SIO_CANCELABLE : 0); } else { - /* Otherwise, release the cancel lock if we had acquired it */ - if (Cancelable) IoReleaseCancelSpinLock(OldIrql); + /* Call the normal routine */ + return IopStartNextPacket(DeviceObject, Cancelable); } }
@@ -1261,8 +1416,20 @@ /* Set the IRP */ DeviceObject->CurrentIrp = Irp;
- /* Release the cancel lock if we had a cancel function */ - if (CancelFunction) IoReleaseCancelSpinLock(CancelIrql); + /* Check if this is a cancelable packet */ + if (CancelFunction) + { + /* Check if the caller requested no cancellation */ + if (IoGetDevObjExtension(DeviceObject)->StartIoFlags & + DOE_SIO_NO_CANCEL) + { + /* He did, so remove the cancel routine */ + Irp->CancelRoutine = NULL; + } + + /* Release the cancel lock */ + IoReleaseCancelSpinLock(OldIrql); + }
/* Call the Start I/O function */ DeviceObject->DriverObject->DriverStartIo(DeviceObject, Irp);