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=…
==============================================================================
--- 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=2…
==============================================================================
--- 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);