2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/device.c
5 * PURPOSE: Device Object Management, including Notifications and Queues.
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Filip Navara (navaraf@reactos.org)
8 * Hervé Poussineau (hpoussin@reactos.org)
11 /* INCLUDES *******************************************************************/
17 /* GLOBALS ********************************************************************/
19 ULONG IopDeviceObjectNumber
= 0;
20 LIST_ENTRY ShutdownListHead
, LastChanceShutdownListHead
;
21 KSPIN_LOCK ShutdownListLock
;
22 extern LIST_ENTRY IopDiskFsListHead
;
23 extern LIST_ENTRY IopCdRomFsListHead
;
24 extern LIST_ENTRY IopTapeFsListHead
;
26 /* PRIVATE FUNCTIONS **********************************************************/
30 IopDeleteDevice(IN PVOID ObjectBody
)
32 PDEVICE_OBJECT DeviceObject
= ObjectBody
;
35 /* TODO: Delete Device Node */
37 /* Dereference the driver object, referenced in IoCreateDevice */
38 if (DeviceObject
->DriverObject
)
39 ObDereferenceObject(DeviceObject
->DriverObject
);
45 IopAttachDeviceToDeviceStackSafe(IN PDEVICE_OBJECT SourceDevice
,
46 IN PDEVICE_OBJECT TargetDevice
,
47 OUT PDEVICE_OBJECT
*AttachedToDeviceObject OPTIONAL
)
49 PDEVICE_OBJECT AttachedDevice
;
50 PEXTENDED_DEVOBJ_EXTENSION SourceDeviceExtension
;
52 /* Get the Attached Device and source extension */
53 AttachedDevice
= IoGetAttachedDevice(TargetDevice
);
54 SourceDeviceExtension
= IoGetDevObjExtension(SourceDevice
);
55 ASSERT(SourceDeviceExtension
->AttachedTo
== NULL
);
57 /* Make sure that it's in a correct state */
58 if ((AttachedDevice
->Flags
& DO_DEVICE_INITIALIZING
) ||
59 (IoGetDevObjExtension(AttachedDevice
)->ExtensionFlags
&
63 DOE_REMOVE_PROCESSED
)))
65 /* Device was unloading or being removed */
66 AttachedDevice
= NULL
;
70 /* Update atached device fields */
71 AttachedDevice
->AttachedDevice
= SourceDevice
;
72 AttachedDevice
->Spare1
++;
74 /* Update the source with the attached data */
75 SourceDevice
->StackSize
= AttachedDevice
->StackSize
+ 1;
76 SourceDevice
->AlignmentRequirement
= AttachedDevice
->
78 SourceDevice
->SectorSize
= AttachedDevice
->SectorSize
;
80 /* Check for pending start flag */
81 if (IoGetDevObjExtension(AttachedDevice
)->ExtensionFlags
&
85 IoGetDevObjExtension(SourceDevice
)->ExtensionFlags
|=
89 /* Set the attachment in the device extension */
90 SourceDeviceExtension
->AttachedTo
= AttachedDevice
;
93 /* Return the attached device */
94 if (AttachedToDeviceObject
) *AttachedToDeviceObject
= AttachedDevice
;
95 return AttachedDevice
;
100 IoShutdownPnpDevices(VOID
)
102 /* This routine is only used by Driver Verifier to validate shutdown */
108 IoShutdownSystem(IN ULONG Phase
)
110 PLIST_ENTRY ListEntry
;
111 PDEVICE_OBJECT DeviceObject
;
112 PSHUTDOWN_ENTRY ShutdownEntry
;
113 IO_STATUS_BLOCK StatusBlock
;
118 /* Initialize an event to wait on */
119 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
125 IoShutdownPnpDevices();
127 /* Loop first-chance shutdown notifications */
128 ListEntry
= ExInterlockedRemoveHeadList(&ShutdownListHead
,
132 /* Get the shutdown entry */
133 ShutdownEntry
= CONTAINING_RECORD(ListEntry
,
137 /* Get the attached device */
138 DeviceObject
= IoGetAttachedDevice(ShutdownEntry
->DeviceObject
);
140 /* Build the shutdown IRP and call the driver */
141 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN
,
148 Status
= IoCallDriver(DeviceObject
, Irp
);
149 if (Status
== STATUS_PENDING
)
151 /* Wait on the driver */
152 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
155 /* Get rid of our reference to it */
156 ObDereferenceObject(DeviceObject
);
158 /* Free the shutdown entry and reset the event */
159 ExFreePoolWithTag(ShutdownEntry
, TAG_SHUTDOWN_ENTRY
);
160 KeClearEvent(&Event
);
162 /* Go to the next entry */
163 ListEntry
= ExInterlockedRemoveHeadList(&ShutdownListHead
,
169 /* Shutdown disk file systems */
170 IopShutdownBaseFileSystems(&IopDiskFsListHead
);
172 /* Shutdown cdrom file systems */
173 IopShutdownBaseFileSystems(&IopCdRomFsListHead
);
175 /* Shutdown tape filesystems */
176 IopShutdownBaseFileSystems(&IopTapeFsListHead
);
178 /* Loop last-chance shutdown notifications */
179 ListEntry
= ExInterlockedRemoveHeadList(&LastChanceShutdownListHead
,
183 /* Get the shutdown entry */
184 ShutdownEntry
= CONTAINING_RECORD(ListEntry
,
188 /* Get the attached device */
189 DeviceObject
= IoGetAttachedDevice(ShutdownEntry
->DeviceObject
);
191 /* Build the shutdown IRP and call the driver */
192 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN
,
199 Status
= IoCallDriver(DeviceObject
, Irp
);
200 if (Status
== STATUS_PENDING
)
202 /* Wait on the driver */
203 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
206 /* Get rid of our reference to it */
207 ObDereferenceObject(DeviceObject
);
209 /* Free the shutdown entry and reset the event */
210 ExFreePoolWithTag(ShutdownEntry
, TAG_SHUTDOWN_ENTRY
);
211 KeClearEvent(&Event
);
213 /* Go to the next entry */
214 ListEntry
= ExInterlockedRemoveHeadList(&LastChanceShutdownListHead
,
223 IopGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName
,
224 IN ACCESS_MASK DesiredAccess
,
225 OUT PFILE_OBJECT
*FileObject
,
226 OUT PDEVICE_OBJECT
*DeviceObject
,
229 OBJECT_ATTRIBUTES ObjectAttributes
;
230 IO_STATUS_BLOCK StatusBlock
;
231 PFILE_OBJECT LocalFileObject
;
235 /* Open the Device */
236 InitializeObjectAttributes(&ObjectAttributes
,
241 Status
= ZwOpenFile(&FileHandle
,
246 FILE_NON_DIRECTORY_FILE
| AttachFlag
);
247 if (!NT_SUCCESS(Status
)) return Status
;
249 /* Get File Object */
250 Status
= ObReferenceObjectByHandle(FileHandle
,
254 (PVOID
*)&LocalFileObject
,
256 if (NT_SUCCESS(Status
))
258 /* Return the requested data */
259 *DeviceObject
= IoGetRelatedDeviceObject(LocalFileObject
);
260 *FileObject
= LocalFileObject
;
263 /* Close the handle */
271 IopGetLowestDevice(IN PDEVICE_OBJECT DeviceObject
)
273 PDEVICE_OBJECT LowestDevice
;
274 PEXTENDED_DEVOBJ_EXTENSION DeviceExtension
;
276 /* Get the current device and its extension */
277 LowestDevice
= DeviceObject
;
278 DeviceExtension
= IoGetDevObjExtension(LowestDevice
);
280 /* Keep looping as long as we're attached */
281 while (DeviceExtension
->AttachedTo
)
283 /* Get the lowest device and its extension */
284 LowestDevice
= DeviceExtension
->AttachedTo
;
285 DeviceExtension
= IoGetDevObjExtension(LowestDevice
);
288 /* Return the lowest device */
294 IopEditDeviceList(IN PDRIVER_OBJECT DriverObject
,
295 IN PDEVICE_OBJECT DeviceObject
,
296 IN IOP_DEVICE_LIST_OPERATION Type
)
298 PDEVICE_OBJECT Previous
;
300 /* Check the type of operation */
301 if (Type
== IopRemove
)
303 /* Get the current device and check if it's the current one */
304 Previous
= DeviceObject
->DriverObject
->DeviceObject
;
305 if (Previous
== DeviceObject
)
307 /* It is, simply unlink this one directly */
308 DeviceObject
->DriverObject
->DeviceObject
=
309 DeviceObject
->NextDevice
;
313 /* It's not, so loop until we find the device */
314 while (Previous
->NextDevice
!= DeviceObject
)
316 /* Not this one, keep moving */
317 Previous
= Previous
->NextDevice
;
320 /* We found it, now unlink us */
321 Previous
->NextDevice
= DeviceObject
->NextDevice
;
326 /* Link the device object and the driver object */
327 DeviceObject
->NextDevice
= DriverObject
->DeviceObject
;
328 DriverObject
->DeviceObject
= DeviceObject
;
334 IopUnloadDevice(IN PDEVICE_OBJECT DeviceObject
)
336 PDRIVER_OBJECT DriverObject
= DeviceObject
->DriverObject
;
337 PDEVICE_OBJECT AttachedDeviceObject
, LowestDeviceObject
;
338 PEXTENDED_DEVOBJ_EXTENSION ThisExtension
, DeviceExtension
;
339 PDEVICE_NODE DeviceNode
;
340 BOOLEAN SafeToUnload
= TRUE
;
342 /* Check if removal is pending */
343 ThisExtension
= IoGetDevObjExtension(DeviceObject
);
344 if (ThisExtension
->ExtensionFlags
& DOE_REMOVE_PENDING
)
346 /* Get the PDO, extension, and node */
347 LowestDeviceObject
= IopGetLowestDevice(DeviceObject
);
348 DeviceExtension
= IoGetDevObjExtension(LowestDeviceObject
);
349 DeviceNode
= DeviceExtension
->DeviceNode
;
351 /* The PDO needs a device node */
352 ASSERT(DeviceNode
!= NULL
);
354 /* Loop all attached objects */
355 AttachedDeviceObject
= LowestDeviceObject
;
356 while (AttachedDeviceObject
)
358 /* Make sure they're dereferenced */
359 if (AttachedDeviceObject
->ReferenceCount
) return;
360 AttachedDeviceObject
= AttachedDeviceObject
->AttachedDevice
;
363 /* Loop all attached objects */
364 AttachedDeviceObject
= LowestDeviceObject
;
365 while (AttachedDeviceObject
)
367 /* Get the device extension */
368 DeviceExtension
= IoGetDevObjExtension(AttachedDeviceObject
);
370 /* Remove the pending flag and set processed */
371 DeviceExtension
->ExtensionFlags
&= ~DOE_REMOVE_PENDING
;
372 DeviceExtension
->ExtensionFlags
|= DOE_REMOVE_PROCESSED
;
373 AttachedDeviceObject
= AttachedDeviceObject
->AttachedDevice
;
377 * FIXME: TODO HPOUSSIN
378 * We need to parse/lock the device node, and if we have any pending
379 * surprise removals, query all relationships and send IRP_MN_REMOVE_
380 * _DEVICE to the devices related...
385 /* Check if deletion is pending */
386 if (ThisExtension
->ExtensionFlags
& DOE_DELETE_PENDING
)
388 /* Make sure unload is pending */
389 if (!(ThisExtension
->ExtensionFlags
& DOE_UNLOAD_PENDING
) ||
390 (DriverObject
->Flags
& DRVO_UNLOAD_INVOKED
))
392 /* We can't unload anymore */
393 SafeToUnload
= FALSE
;
397 * Check if we have an attached device and fail if we're attached
398 * and still have a reference count.
400 AttachedDeviceObject
= DeviceObject
->AttachedDevice
;
401 if ((AttachedDeviceObject
) && (DeviceObject
->ReferenceCount
)) return;
403 /* Check if we have a Security Descriptor */
404 if (DeviceObject
->SecurityDescriptor
)
407 ExFreePoolWithTag(DeviceObject
->SecurityDescriptor
, TAG_SD
);
410 /* Remove the device from the list */
411 IopEditDeviceList(DeviceObject
->DriverObject
, DeviceObject
, IopRemove
);
413 /* Dereference the keep-alive */
414 ObDereferenceObject(DeviceObject
);
416 /* If we're not unloading, stop here */
417 if (!SafeToUnload
) return;
420 /* Loop all the device objects */
421 DeviceObject
= DriverObject
->DeviceObject
;
425 * Make sure we're not attached, having a reference count
426 * or already deleting
428 if ((DeviceObject
->ReferenceCount
) ||
429 (DeviceObject
->AttachedDevice
) ||
430 (IoGetDevObjExtension(DeviceObject
)->ExtensionFlags
&
431 (DOE_DELETE_PENDING
| DOE_REMOVE_PENDING
)))
433 /* We're not safe to unload, quit */
437 /* Check the next device */
438 DeviceObject
= DeviceObject
->NextDevice
;
441 /* Set the unload invoked flag */
442 DriverObject
->Flags
|= DRVO_UNLOAD_INVOKED
;
445 if (DriverObject
->DriverUnload
) DriverObject
->DriverUnload(DriverObject
);
447 /* Make object temporary so it can be deleted */
448 ObMakeTemporaryObject(DriverObject
);
450 /* Dereference once more, referenced at driver object creation */
451 ObDereferenceObject(DriverObject
);
457 IopDereferenceDeviceObject(IN PDEVICE_OBJECT DeviceObject
,
458 IN BOOLEAN ForceUnload
)
461 ASSERT(DeviceObject
->ReferenceCount
);
463 /* Dereference the device */
464 DeviceObject
->ReferenceCount
--;
467 * Check if we can unload it and it's safe to unload (or if we're forcing
468 * an unload, which is OK too).
470 if (!(DeviceObject
->ReferenceCount
) &&
471 ((ForceUnload
) || (IoGetDevObjExtension(DeviceObject
)->ExtensionFlags
&
472 (DOE_UNLOAD_PENDING
|
475 DOE_REMOVE_PROCESSED
))))
478 IopUnloadDevice(DeviceObject
);
484 IopStartNextPacketByKey(IN PDEVICE_OBJECT DeviceObject
,
485 IN BOOLEAN Cancelable
,
488 PKDEVICE_QUEUE_ENTRY Entry
;
492 /* Acquire the cancel lock if this is cancelable */
493 if (Cancelable
) IoAcquireCancelSpinLock(&OldIrql
);
495 /* Clear the current IRP */
496 DeviceObject
->CurrentIrp
= NULL
;
498 /* Remove an entry from the queue */
499 Entry
= KeRemoveByKeyDeviceQueue(&DeviceObject
->DeviceQueue
, Key
);
502 /* Get the IRP and set it */
503 Irp
= CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.DeviceQueueEntry
);
504 DeviceObject
->CurrentIrp
= Irp
;
506 /* Check if this is a cancelable packet */
509 /* Check if the caller requested no cancellation */
510 if (IoGetDevObjExtension(DeviceObject
)->StartIoFlags
&
513 /* He did, so remove the cancel routine */
514 Irp
->CancelRoutine
= NULL
;
517 /* Release the cancel lock */
518 IoReleaseCancelSpinLock(OldIrql
);
521 /* Call the Start I/O Routine */
522 DeviceObject
->DriverObject
->DriverStartIo(DeviceObject
, Irp
);
526 /* Otherwise, release the cancel lock if we had acquired it */
527 if (Cancelable
) IoReleaseCancelSpinLock(OldIrql
);
533 IopStartNextPacket(IN PDEVICE_OBJECT DeviceObject
,
534 IN BOOLEAN Cancelable
)
536 PKDEVICE_QUEUE_ENTRY Entry
;
540 /* Acquire the cancel lock if this is cancelable */
541 if (Cancelable
) IoAcquireCancelSpinLock(&OldIrql
);
543 /* Clear the current IRP */
544 DeviceObject
->CurrentIrp
= NULL
;
546 /* Remove an entry from the queue */
547 Entry
= KeRemoveDeviceQueue(&DeviceObject
->DeviceQueue
);
550 /* Get the IRP and set it */
551 Irp
= CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.DeviceQueueEntry
);
552 DeviceObject
->CurrentIrp
= Irp
;
554 /* Check if this is a cancelable packet */
557 /* Check if the caller requested no cancellation */
558 if (IoGetDevObjExtension(DeviceObject
)->StartIoFlags
&
561 /* He did, so remove the cancel routine */
562 Irp
->CancelRoutine
= NULL
;
565 /* Release the cancel lock */
566 IoReleaseCancelSpinLock(OldIrql
);
569 /* Call the Start I/O Routine */
570 DeviceObject
->DriverObject
->DriverStartIo(DeviceObject
, Irp
);
574 /* Otherwise, release the cancel lock if we had acquired it */
575 if (Cancelable
) IoReleaseCancelSpinLock(OldIrql
);
581 IopStartNextPacketByKeyEx(IN PDEVICE_OBJECT DeviceObject
,
585 PEXTENDED_DEVOBJ_EXTENSION DeviceExtension
;
586 ULONG CurrentKey
= Key
;
587 ULONG CurrentFlags
= Flags
;
589 /* Get the device extension and start the packet loop */
590 DeviceExtension
= IoGetDevObjExtension(DeviceObject
);
593 /* Increase the count */
594 if (InterlockedIncrement(&DeviceExtension
->StartIoCount
) > 1)
597 * We've already called the routine once...
598 * All we have to do is save the key and add the new flags
600 DeviceExtension
->StartIoFlags
|= CurrentFlags
;
601 DeviceExtension
->StartIoKey
= CurrentKey
;
605 /* Mask out the current packet flags and key */
606 DeviceExtension
->StartIoFlags
&= ~(DOE_SIO_WITH_KEY
|
609 DeviceExtension
->StartIoKey
= 0;
611 /* Check if this is a packet start with key */
612 if (Flags
& DOE_SIO_WITH_KEY
)
614 /* Start the packet with a key */
615 IopStartNextPacketByKey(DeviceObject
,
616 (Flags
& DOE_SIO_CANCELABLE
) ?
620 else if (Flags
& DOE_SIO_NO_KEY
)
622 /* Start the packet */
623 IopStartNextPacket(DeviceObject
,
624 (Flags
& DOE_SIO_CANCELABLE
) ?
629 /* Decrease the Start I/O count and check if it's 0 now */
630 if (!InterlockedDecrement(&DeviceExtension
->StartIoCount
))
632 /* Get the current active key and flags */
633 CurrentKey
= DeviceExtension
->StartIoKey
;
634 CurrentFlags
= DeviceExtension
->StartIoFlags
& (DOE_SIO_WITH_KEY
|
638 /* Check if we should still loop */
639 if (!(CurrentFlags
& (DOE_SIO_WITH_KEY
| DOE_SIO_NO_KEY
))) break;
643 /* There are still Start I/Os active, so quit this loop */
651 IopGetRelatedTargetDevice(IN PFILE_OBJECT FileObject
,
652 OUT PDEVICE_NODE
*DeviceNode
)
655 IO_STACK_LOCATION Stack
= {0};
656 IO_STATUS_BLOCK IoStatusBlock
;
657 PDEVICE_RELATIONS DeviceRelations
;
658 PDEVICE_OBJECT DeviceObject
= NULL
;
662 /* Get DeviceObject related to given FileObject */
663 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
664 if (!DeviceObject
) return STATUS_NO_SUCH_DEVICE
;
666 /* Define input parameters */
667 Stack
.Parameters
.QueryDeviceRelations
.Type
= TargetDeviceRelation
;
668 Stack
.FileObject
= FileObject
;
670 /* Call the driver to query all relations (IRP_MJ_PNP) */
671 Status
= IopInitiatePnpIrp(DeviceObject
,
673 IRP_MN_QUERY_DEVICE_RELATIONS
,
675 if (!NT_SUCCESS(Status
)) return Status
;
677 /* Get returned pointer to DEVICE_RELATIONS */
678 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
680 /* Make sure it's not NULL and contains only one object */
681 ASSERT(DeviceRelations
);
682 ASSERT(DeviceRelations
->Count
== 1);
684 /* Finally get the device node */
685 *DeviceNode
= IopGetDeviceNode(DeviceRelations
->Objects
[0]);
686 if (!*DeviceNode
) Status
= STATUS_NO_SUCH_DEVICE
;
688 /* Free the DEVICE_RELATIONS structure, it's not needed anymore */
689 ExFreePool(DeviceRelations
);
694 /* PUBLIC FUNCTIONS ***********************************************************/
699 * Layers a device over the highest device in a device stack.
703 * Device to be attached.
706 * Name of the target device.
709 * Caller storage for the device attached to.
716 IoAttachDevice(PDEVICE_OBJECT SourceDevice
,
717 PUNICODE_STRING TargetDeviceName
,
718 PDEVICE_OBJECT
*AttachedDevice
)
721 PFILE_OBJECT FileObject
= NULL
;
722 PDEVICE_OBJECT TargetDevice
= NULL
;
724 /* Call the helper routine for an attach operation */
725 Status
= IopGetDeviceObjectPointer(TargetDeviceName
,
726 FILE_READ_ATTRIBUTES
,
729 IO_ATTACH_DEVICE_API
);
730 if (!NT_SUCCESS(Status
)) return Status
;
732 /* Attach the device */
733 Status
= IoAttachDeviceToDeviceStackSafe(SourceDevice
,
738 ObDereferenceObject(FileObject
);
743 * IoAttachDeviceByPointer
750 IoAttachDeviceByPointer(IN PDEVICE_OBJECT SourceDevice
,
751 IN PDEVICE_OBJECT TargetDevice
)
753 PDEVICE_OBJECT AttachedDevice
;
754 NTSTATUS Status
= STATUS_SUCCESS
;
757 AttachedDevice
= IoAttachDeviceToDeviceStack(SourceDevice
, TargetDevice
);
758 if (!AttachedDevice
) Status
= STATUS_NO_SUCH_DEVICE
;
760 /* Return the status */
769 IoAttachDeviceToDeviceStack(IN PDEVICE_OBJECT SourceDevice
,
770 IN PDEVICE_OBJECT TargetDevice
)
772 /* Attach it safely */
773 return IopAttachDeviceToDeviceStackSafe(SourceDevice
,
783 IoAttachDeviceToDeviceStackSafe(IN PDEVICE_OBJECT SourceDevice
,
784 IN PDEVICE_OBJECT TargetDevice
,
785 IN OUT PDEVICE_OBJECT
*AttachedToDeviceObject
)
787 /* Call the internal function */
788 if (!IopAttachDeviceToDeviceStackSafe(SourceDevice
,
790 AttachedToDeviceObject
))
793 return STATUS_NO_SUCH_DEVICE
;
797 return STATUS_SUCCESS
;
803 * Allocates memory for and intializes a device object for use for
808 * Driver object passed by IO Manager when the driver was loaded.
810 * DeviceExtensionSize
811 * Number of bytes for the device extension.
814 * Unicode name of device.
817 * Device type of the new device.
819 * DeviceCharacteristics
820 * Bit mask of device characteristics.
823 * TRUE if only one thread can access the device at a time.
826 * On successful return this parameter is filled by pointer to
827 * allocated device object.
834 IoCreateDevice(IN PDRIVER_OBJECT DriverObject
,
835 IN ULONG DeviceExtensionSize
,
836 IN PUNICODE_STRING DeviceName
,
837 IN DEVICE_TYPE DeviceType
,
838 IN ULONG DeviceCharacteristics
,
839 IN BOOLEAN Exclusive
,
840 OUT PDEVICE_OBJECT
*DeviceObject
)
842 WCHAR AutoNameBuffer
[20];
843 UNICODE_STRING AutoName
;
844 PDEVICE_OBJECT CreatedDeviceObject
;
845 PDEVOBJ_EXTENSION DeviceObjectExtension
;
846 OBJECT_ATTRIBUTES ObjectAttributes
;
848 ULONG AlignedDeviceExtensionSize
;
853 /* Check if we have to generate a name */
854 if (DeviceCharacteristics
& FILE_AUTOGENERATED_DEVICE_NAME
)
857 swprintf(AutoNameBuffer
,
859 InterlockedIncrementUL(&IopDeviceObjectNumber
));
861 /* Initialize the name */
862 RtlInitUnicodeString(&AutoName
, AutoNameBuffer
);
863 DeviceName
= &AutoName
;
866 /* Initialize the Object Attributes */
867 InitializeObjectAttributes(&ObjectAttributes
,
873 /* Honor exclusive flag */
874 if (Exclusive
) ObjectAttributes
.Attributes
|= OBJ_EXCLUSIVE
;
876 /* Create a permanent object for named devices */
877 if (DeviceName
) ObjectAttributes
.Attributes
|= OBJ_PERMANENT
;
879 /* Align the Extension Size to 8-bytes */
880 AlignedDeviceExtensionSize
= (DeviceExtensionSize
+ 7) &~ 7;
883 TotalSize
= AlignedDeviceExtensionSize
+
884 sizeof(DEVICE_OBJECT
) +
885 sizeof(EXTENDED_DEVOBJ_EXTENSION
);
887 /* Create the Device Object */
888 *DeviceObject
= NULL
;
889 Status
= ObCreateObject(KernelMode
,
897 (PVOID
*)&CreatedDeviceObject
);
898 if (!NT_SUCCESS(Status
)) return Status
;
900 /* Clear the whole Object and extension so we don't null stuff manually */
901 RtlZeroMemory(CreatedDeviceObject
, TotalSize
);
904 * Setup the Type and Size. Note that we don't use the aligned size,
905 * because that's only padding for the DevObjExt and not part of the Object.
907 CreatedDeviceObject
->Type
= IO_TYPE_DEVICE
;
908 CreatedDeviceObject
->Size
= sizeof(DEVICE_OBJECT
) + (USHORT
)DeviceExtensionSize
;
910 /* The kernel extension is after the driver internal extension */
911 DeviceObjectExtension
= (PDEVOBJ_EXTENSION
)
912 ((ULONG_PTR
)(CreatedDeviceObject
+ 1) +
913 AlignedDeviceExtensionSize
);
915 /* Set the Type and Size. Question: why is Size 0 on Windows? */
916 DeviceObjectExtension
->Type
= IO_TYPE_DEVICE_OBJECT_EXTENSION
;
917 DeviceObjectExtension
->Size
= 0;
919 /* Initialize with Power Manager */
920 PoInitializeDeviceObject(DeviceObjectExtension
);
922 /* Link the Object and Extension */
923 DeviceObjectExtension
->DeviceObject
= CreatedDeviceObject
;
924 CreatedDeviceObject
->DeviceObjectExtension
= DeviceObjectExtension
;
926 /* Set Device Object Data */
927 CreatedDeviceObject
->DeviceType
= DeviceType
;
928 CreatedDeviceObject
->Characteristics
= DeviceCharacteristics
;
929 CreatedDeviceObject
->DeviceExtension
= DeviceExtensionSize
?
930 CreatedDeviceObject
+ 1 :
932 CreatedDeviceObject
->StackSize
= 1;
933 CreatedDeviceObject
->AlignmentRequirement
= 0;
936 CreatedDeviceObject
->Flags
= DO_DEVICE_INITIALIZING
;
937 if (Exclusive
) CreatedDeviceObject
->Flags
|= DO_EXCLUSIVE
;
938 if (DeviceName
) CreatedDeviceObject
->Flags
|= DO_DEVICE_HAS_NAME
;
940 /* Attach a Vpb for Disks and Tapes, and create the Device Lock */
941 if ((CreatedDeviceObject
->DeviceType
== FILE_DEVICE_DISK
) ||
942 (CreatedDeviceObject
->DeviceType
== FILE_DEVICE_VIRTUAL_DISK
) ||
943 (CreatedDeviceObject
->DeviceType
== FILE_DEVICE_CD_ROM
) ||
944 (CreatedDeviceObject
->DeviceType
== FILE_DEVICE_TAPE
))
947 Status
= IopCreateVpb(CreatedDeviceObject
);
948 if (!NT_SUCCESS(Status
))
950 /* Reference the device object and fail */
951 ObDereferenceObject(DeviceObject
);
955 /* Initialize Lock Event */
956 KeInitializeEvent(&CreatedDeviceObject
->DeviceLock
,
957 SynchronizationEvent
,
961 /* Set the right Sector Size */
964 /* All disk systems */
965 case FILE_DEVICE_DISK_FILE_SYSTEM
:
966 case FILE_DEVICE_DISK
:
967 case FILE_DEVICE_VIRTUAL_DISK
:
969 /* The default is 512 bytes */
970 CreatedDeviceObject
->SectorSize
= 512;
973 /* CD-ROM file systems */
974 case FILE_DEVICE_CD_ROM_FILE_SYSTEM
:
976 /* The default is 2048 bytes */
977 CreatedDeviceObject
->SectorSize
= 2048;
980 /* Create the Device Queue */
981 if ((CreatedDeviceObject
->DeviceType
== FILE_DEVICE_DISK_FILE_SYSTEM
) ||
982 (CreatedDeviceObject
->DeviceType
== FILE_DEVICE_FILE_SYSTEM
) ||
983 (CreatedDeviceObject
->DeviceType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
) ||
984 (CreatedDeviceObject
->DeviceType
== FILE_DEVICE_NETWORK_FILE_SYSTEM
) ||
985 (CreatedDeviceObject
->DeviceType
== FILE_DEVICE_TAPE_FILE_SYSTEM
))
987 /* Simple FS Devices, they don't need a real Device Queue */
988 InitializeListHead(&CreatedDeviceObject
->Queue
.ListEntry
);
992 /* An actual Device, initialize its DQ */
993 KeInitializeDeviceQueue(&CreatedDeviceObject
->DeviceQueue
);
996 /* Insert the Object */
997 Status
= ObInsertObject(CreatedDeviceObject
,
999 FILE_READ_DATA
| FILE_WRITE_DATA
,
1001 (PVOID
*)&CreatedDeviceObject
,
1003 if (!NT_SUCCESS(Status
)) return Status
;
1005 /* Now do the final linking */
1006 ObReferenceObject(DriverObject
);
1007 ASSERT((DriverObject
->Flags
& DRVO_UNLOAD_INVOKED
) == 0);
1008 CreatedDeviceObject
->DriverObject
= DriverObject
;
1009 IopEditDeviceList(DriverObject
, CreatedDeviceObject
, IopAdd
);
1011 /* Link with the power manager */
1012 if (CreatedDeviceObject
->Vpb
) PoVolumeDevice(CreatedDeviceObject
);
1014 /* Close the temporary handle and return to caller */
1015 ObCloseHandle(TempHandle
, KernelMode
);
1016 *DeviceObject
= CreatedDeviceObject
;
1017 return STATUS_SUCCESS
;
1028 IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject
)
1032 /* Check if the device is registered for shutdown notifications */
1033 if (DeviceObject
->Flags
& DO_SHUTDOWN_REGISTERED
)
1035 /* Call the shutdown notifications */
1036 IoUnregisterShutdownNotification(DeviceObject
);
1039 /* Check if it has a timer */
1040 Timer
= DeviceObject
->Timer
;
1043 /* Remove it and free it */
1044 IopRemoveTimerFromTimerList(Timer
);
1045 ExFreePoolWithTag(Timer
, TAG_IO_TIMER
);
1048 /* Check if the device has a name */
1049 if (DeviceObject
->Flags
& DO_DEVICE_HAS_NAME
)
1051 /* It does, make it temporary so we can remove it */
1052 ObMakeTemporaryObject(DeviceObject
);
1055 /* Set the pending delete flag */
1056 IoGetDevObjExtension(DeviceObject
)->ExtensionFlags
|= DOE_DELETE_PENDING
;
1058 /* Check if the device object can be unloaded */
1059 if (!DeviceObject
->ReferenceCount
) IopUnloadDevice(DeviceObject
);
1070 IoDetachDevice(IN PDEVICE_OBJECT TargetDevice
)
1072 PEXTENDED_DEVOBJ_EXTENSION DeviceExtension
;
1075 DeviceExtension
= IoGetDevObjExtension(TargetDevice
->AttachedDevice
);
1076 ASSERT(DeviceExtension
->AttachedTo
== TargetDevice
);
1078 /* Remove the attachment */
1079 DeviceExtension
->AttachedTo
= NULL
;
1080 TargetDevice
->AttachedDevice
= NULL
;
1082 /* Check if it's ok to delete this device */
1083 if ((IoGetDevObjExtension(TargetDevice
)->ExtensionFlags
&
1084 (DOE_UNLOAD_PENDING
| DOE_DELETE_PENDING
| DOE_REMOVE_PENDING
)) &&
1085 !(TargetDevice
->ReferenceCount
))
1088 IopUnloadDevice(TargetDevice
);
1097 IoEnumerateDeviceObjectList(IN PDRIVER_OBJECT DriverObject
,
1098 IN PDEVICE_OBJECT
*DeviceObjectList
,
1099 IN ULONG DeviceObjectListSize
,
1100 OUT PULONG ActualNumberDeviceObjects
)
1102 ULONG ActualDevices
= 1;
1103 PDEVICE_OBJECT CurrentDevice
= DriverObject
->DeviceObject
;
1105 /* Find out how many devices we'll enumerate */
1106 while ((CurrentDevice
= CurrentDevice
->NextDevice
)) ActualDevices
++;
1108 /* Go back to the first */
1109 CurrentDevice
= DriverObject
->DeviceObject
;
1111 /* Start by at least returning this */
1112 *ActualNumberDeviceObjects
= ActualDevices
;
1114 /* Check if we can support so many */
1115 if ((ActualDevices
* 4) > DeviceObjectListSize
)
1117 /* Fail because the buffer was too small */
1118 return STATUS_BUFFER_TOO_SMALL
;
1121 /* Check if the caller only wanted the size */
1122 if (DeviceObjectList
)
1124 /* Loop through all the devices */
1125 while (ActualDevices
)
1127 /* Reference each Device */
1128 ObReferenceObject(CurrentDevice
);
1130 /* Add it to the list */
1131 *DeviceObjectList
= CurrentDevice
;
1133 /* Go to the next one */
1134 CurrentDevice
= CurrentDevice
->NextDevice
;
1140 /* Return the status */
1141 return STATUS_SUCCESS
;
1145 * IoGetAttachedDevice
1152 IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject
)
1154 /* Get the last attached device */
1155 while (DeviceObject
->AttachedDevice
)
1157 /* Move to the next one */
1158 DeviceObject
= DeviceObject
->AttachedDevice
;
1162 return DeviceObject
;
1166 * IoGetAttachedDeviceReference
1173 IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject
)
1175 /* Reference the Attached Device */
1176 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
1177 ObReferenceObject(DeviceObject
);
1178 return DeviceObject
;
1186 IoGetDeviceAttachmentBaseRef(IN PDEVICE_OBJECT DeviceObject
)
1188 /* Reference the lowest attached device */
1189 DeviceObject
= IopGetLowestDevice(DeviceObject
);
1190 ObReferenceObject(DeviceObject
);
1191 return DeviceObject
;
1195 * IoGetDeviceObjectPointer
1202 IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName
,
1203 IN ACCESS_MASK DesiredAccess
,
1204 OUT PFILE_OBJECT
*FileObject
,
1205 OUT PDEVICE_OBJECT
*DeviceObject
)
1207 /* Call the helper routine for a normal operation */
1208 return IopGetDeviceObjectPointer(ObjectName
,
1220 IoGetDiskDeviceObject(IN PDEVICE_OBJECT FileSystemDeviceObject
,
1221 OUT PDEVICE_OBJECT
*DiskDeviceObject
)
1223 PEXTENDED_DEVOBJ_EXTENSION DeviceExtension
;
1228 /* Make sure there's a VPB */
1229 if (!FileSystemDeviceObject
->Vpb
) return STATUS_INVALID_PARAMETER
;
1232 IoAcquireVpbSpinLock(&OldIrql
);
1234 /* Get the Device Extension */
1235 DeviceExtension
= IoGetDevObjExtension(FileSystemDeviceObject
);
1237 /* Make sure this one has a VPB too */
1238 Vpb
= DeviceExtension
->Vpb
;
1241 /* Make sure that it's mounted */
1242 if ((Vpb
->ReferenceCount
) &&
1243 (Vpb
->Flags
& VPB_MOUNTED
))
1245 /* Return the Disk Device Object */
1246 *DiskDeviceObject
= Vpb
->RealDevice
;
1248 /* Reference it and return success */
1249 ObReferenceObject(Vpb
->RealDevice
);
1250 Status
= STATUS_SUCCESS
;
1254 /* It's not, so return failure */
1255 Status
= STATUS_VOLUME_DISMOUNTED
;
1261 Status
= STATUS_INVALID_PARAMETER
;
1264 /* Release the lock */
1265 IoReleaseVpbSpinLock(OldIrql
);
1274 IoGetLowerDeviceObject(IN PDEVICE_OBJECT DeviceObject
)
1276 PEXTENDED_DEVOBJ_EXTENSION DeviceExtension
;
1277 PDEVICE_OBJECT LowerDeviceObject
= NULL
;
1279 /* Make sure it's not getting deleted */
1280 DeviceExtension
= IoGetDevObjExtension(DeviceObject
);
1281 if (!(DeviceExtension
->ExtensionFlags
& (DOE_UNLOAD_PENDING
|
1282 DOE_DELETE_PENDING
|
1283 DOE_REMOVE_PENDING
|
1284 DOE_REMOVE_PROCESSED
)))
1286 /* Get the Lower Device Object */
1287 LowerDeviceObject
= DeviceExtension
->AttachedTo
;
1289 /* Check that we got a valid device object */
1290 if (LowerDeviceObject
)
1292 /* We did so let's reference it */
1293 ObReferenceObject(LowerDeviceObject
);
1298 return LowerDeviceObject
;
1306 IoGetRelatedDeviceObject(IN PFILE_OBJECT FileObject
)
1308 PDEVICE_OBJECT DeviceObject
= FileObject
->DeviceObject
;
1310 /* Check if we have a VPB with a device object */
1311 if ((FileObject
->Vpb
) && (FileObject
->Vpb
->DeviceObject
))
1313 /* Then use the DO from the VPB */
1314 ASSERT(!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
));
1315 DeviceObject
= FileObject
->Vpb
->DeviceObject
;
1317 else if (!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
) &&
1318 (FileObject
->DeviceObject
->Vpb
) &&
1319 (FileObject
->DeviceObject
->Vpb
->DeviceObject
))
1321 /* The disk device actually has a VPB, so get the DO from there */
1322 DeviceObject
= FileObject
->DeviceObject
->Vpb
->DeviceObject
;
1326 /* Otherwise, this was a direct open */
1327 DeviceObject
= FileObject
->DeviceObject
;
1331 ASSERT(DeviceObject
!= NULL
);
1333 /* Check if we were attached */
1334 if (DeviceObject
->AttachedDevice
)
1336 /* Check if the file object has an extension present */
1337 if (FileObject
->Flags
& FO_FILE_OBJECT_HAS_EXTENSION
)
1339 /* Sanity check, direct open files can't have this */
1340 ASSERT(!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
));
1342 /* Check if the extension is really present */
1343 if (FileObject
->FileObjectExtension
)
1345 /* FIXME: Unhandled yet */
1346 DPRINT1("FOEs not supported\n");
1351 /* Return the highest attached device */
1352 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
1355 /* Return the DO we found */
1356 return DeviceObject
;
1364 IoGetRelatedTargetDevice(IN PFILE_OBJECT FileObject
,
1365 OUT PDEVICE_OBJECT
*DeviceObject
)
1368 PDEVICE_NODE DeviceNode
= NULL
;
1370 /* Call the internal helper function */
1371 Status
= IopGetRelatedTargetDevice(FileObject
, &DeviceNode
);
1372 if (NT_SUCCESS(Status
) && DeviceNode
)
1374 *DeviceObject
= DeviceNode
->PhysicalDeviceObject
;
1384 IoGetBaseFileSystemDeviceObject(IN PFILE_OBJECT FileObject
)
1386 PDEVICE_OBJECT DeviceObject
;
1389 * If the FILE_OBJECT's VPB is defined,
1390 * get the device from it.
1392 if ((FileObject
->Vpb
) && (FileObject
->Vpb
->DeviceObject
))
1394 /* Use the VPB's Device Object's */
1395 DeviceObject
= FileObject
->Vpb
->DeviceObject
;
1397 else if (!(FileObject
->Flags
& FO_DIRECT_DEVICE_OPEN
) &&
1398 (FileObject
->DeviceObject
->Vpb
) &&
1399 (FileObject
->DeviceObject
->Vpb
->DeviceObject
))
1401 /* Use the VPB's File System Object */
1402 DeviceObject
= FileObject
->DeviceObject
->Vpb
->DeviceObject
;
1406 /* Use the FO's Device Object */
1407 DeviceObject
= FileObject
->DeviceObject
;
1410 /* Return the device object we found */
1411 ASSERT(DeviceObject
!= NULL
);
1412 return DeviceObject
;
1420 IoRegisterLastChanceShutdownNotification(IN PDEVICE_OBJECT DeviceObject
)
1422 PSHUTDOWN_ENTRY Entry
;
1424 /* Allocate the shutdown entry */
1425 Entry
= ExAllocatePoolWithTag(NonPagedPool
,
1426 sizeof(SHUTDOWN_ENTRY
),
1427 TAG_SHUTDOWN_ENTRY
);
1428 if (!Entry
) return STATUS_INSUFFICIENT_RESOURCES
;
1431 Entry
->DeviceObject
= DeviceObject
;
1433 /* Reference it so it doesn't go away */
1434 ObReferenceObject(DeviceObject
);
1436 /* Insert it into the list */
1437 ExInterlockedInsertHeadList(&LastChanceShutdownListHead
,
1438 &Entry
->ShutdownList
,
1441 /* Set the shutdown registered flag */
1442 DeviceObject
->Flags
|= DO_SHUTDOWN_REGISTERED
;
1443 return STATUS_SUCCESS
;
1451 IoRegisterShutdownNotification(PDEVICE_OBJECT DeviceObject
)
1453 PSHUTDOWN_ENTRY Entry
;
1455 /* Allocate the shutdown entry */
1456 Entry
= ExAllocatePoolWithTag(NonPagedPool
,
1457 sizeof(SHUTDOWN_ENTRY
),
1458 TAG_SHUTDOWN_ENTRY
);
1459 if (!Entry
) return STATUS_INSUFFICIENT_RESOURCES
;
1462 Entry
->DeviceObject
= DeviceObject
;
1464 /* Reference it so it doesn't go away */
1465 ObReferenceObject(DeviceObject
);
1467 /* Insert it into the list */
1468 ExInterlockedInsertHeadList(&ShutdownListHead
,
1469 &Entry
->ShutdownList
,
1472 /* Set the shutdown registered flag */
1473 DeviceObject
->Flags
|= DO_SHUTDOWN_REGISTERED
;
1474 return STATUS_SUCCESS
;
1482 IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject
)
1484 PSHUTDOWN_ENTRY ShutdownEntry
;
1485 PLIST_ENTRY NextEntry
;
1488 /* Acquire the shutdown lock and loop the shutdown list */
1489 KeAcquireSpinLock(&ShutdownListLock
, &OldIrql
);
1490 NextEntry
= ShutdownListHead
.Flink
;
1491 while (NextEntry
!= &ShutdownListHead
)
1494 ShutdownEntry
= CONTAINING_RECORD(NextEntry
,
1498 /* Get if the DO matches */
1499 if (ShutdownEntry
->DeviceObject
== DeviceObject
)
1501 /* Remove it from the list */
1502 RemoveEntryList(NextEntry
);
1503 NextEntry
= NextEntry
->Blink
;
1505 /* Free the entry */
1506 ExFreePoolWithTag(ShutdownEntry
, TAG_SHUTDOWN_ENTRY
);
1508 /* Get rid of our reference to it */
1509 ObDereferenceObject(DeviceObject
);
1512 /* Go to the next entry */
1513 NextEntry
= NextEntry
->Flink
;
1516 /* Now loop the last chance list */
1517 NextEntry
= LastChanceShutdownListHead
.Flink
;
1518 while (NextEntry
!= &LastChanceShutdownListHead
)
1521 ShutdownEntry
= CONTAINING_RECORD(NextEntry
,
1525 /* Get if the DO matches */
1526 if (ShutdownEntry
->DeviceObject
== DeviceObject
)
1528 /* Remove it from the list */
1529 RemoveEntryList(NextEntry
);
1530 NextEntry
= NextEntry
->Blink
;
1532 /* Free the entry */
1533 ExFreePoolWithTag(ShutdownEntry
, TAG_SHUTDOWN_ENTRY
);
1535 /* Get rid of our reference to it */
1536 ObDereferenceObject(DeviceObject
);
1539 /* Go to the next entry */
1540 NextEntry
= NextEntry
->Flink
;
1543 /* Release the shutdown lock */
1544 KeReleaseSpinLock(&ShutdownListLock
, OldIrql
);
1546 /* Now remove the flag */
1547 DeviceObject
->Flags
&= ~DO_SHUTDOWN_REGISTERED
;
1555 IoSetStartIoAttributes(IN PDEVICE_OBJECT DeviceObject
,
1556 IN BOOLEAN DeferredStartIo
,
1557 IN BOOLEAN NonCancelable
)
1559 PEXTENDED_DEVOBJ_EXTENSION DeviceExtension
;
1561 /* Get the Device Extension */
1562 DeviceExtension
= IoGetDevObjExtension(DeviceObject
);
1564 /* Set the flags the caller requested */
1565 DeviceExtension
->StartIoFlags
|= (DeferredStartIo
) ? DOE_SIO_DEFERRED
: 0;
1566 DeviceExtension
->StartIoFlags
|= (NonCancelable
) ? DOE_SIO_NO_CANCEL
: 0;
1574 IoStartNextPacketByKey(IN PDEVICE_OBJECT DeviceObject
,
1575 IN BOOLEAN Cancelable
,
1578 PEXTENDED_DEVOBJ_EXTENSION DeviceExtension
;
1580 /* Get the Device Extension */
1581 DeviceExtension
= IoGetDevObjExtension(DeviceObject
);
1583 /* Check if deferred start was requested */
1584 if (DeviceExtension
->StartIoFlags
& DOE_SIO_DEFERRED
)
1586 /* Call our internal function to handle the defered case */
1587 IopStartNextPacketByKeyEx(DeviceObject
,
1590 (Cancelable
? DOE_SIO_CANCELABLE
: 0));
1594 /* Call the normal routine */
1595 IopStartNextPacketByKey(DeviceObject
, Cancelable
, Key
);
1604 IoStartNextPacket(IN PDEVICE_OBJECT DeviceObject
,
1605 IN BOOLEAN Cancelable
)
1607 PEXTENDED_DEVOBJ_EXTENSION DeviceExtension
;
1609 /* Get the Device Extension */
1610 DeviceExtension
= IoGetDevObjExtension(DeviceObject
);
1612 /* Check if deferred start was requested */
1613 if (DeviceExtension
->StartIoFlags
& DOE_SIO_DEFERRED
)
1615 /* Call our internal function to handle the defered case */
1616 IopStartNextPacketByKeyEx(DeviceObject
,
1619 (Cancelable
? DOE_SIO_CANCELABLE
: 0));
1623 /* Call the normal routine */
1624 IopStartNextPacket(DeviceObject
, Cancelable
);
1633 IoStartPacket(IN PDEVICE_OBJECT DeviceObject
,
1636 IN PDRIVER_CANCEL CancelFunction
)
1639 KIRQL OldIrql
, CancelIrql
;
1641 /* Raise to dispatch level */
1642 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
1644 /* Check if we should acquire the cancel lock */
1647 /* Acquire and set it */
1648 IoAcquireCancelSpinLock(&CancelIrql
);
1649 Irp
->CancelRoutine
= CancelFunction
;
1652 /* Check if we have a key */
1656 Stat
= KeInsertByKeyDeviceQueue(&DeviceObject
->DeviceQueue
,
1657 &Irp
->Tail
.Overlay
.DeviceQueueEntry
,
1662 /* Insert without a key */
1663 Stat
= KeInsertDeviceQueue(&DeviceObject
->DeviceQueue
,
1664 &Irp
->Tail
.Overlay
.DeviceQueueEntry
);
1667 /* Check if this was a first insert */
1671 DeviceObject
->CurrentIrp
= Irp
;
1673 /* Check if this is a cancelable packet */
1676 /* Check if the caller requested no cancellation */
1677 if (IoGetDevObjExtension(DeviceObject
)->StartIoFlags
&
1680 /* He did, so remove the cancel routine */
1681 Irp
->CancelRoutine
= NULL
;
1684 /* Release the cancel lock */
1685 IoReleaseCancelSpinLock(CancelIrql
);
1688 /* Call the Start I/O function */
1689 DeviceObject
->DriverObject
->DriverStartIo(DeviceObject
, Irp
);
1693 /* The packet was inserted... check if we have a cancel function */
1696 /* Check if the IRP got cancelled */
1700 * Set the cancel IRQL, clear the currnet cancel routine and
1703 Irp
->CancelIrql
= CancelIrql
;
1704 Irp
->CancelRoutine
= NULL
;
1705 CancelFunction(DeviceObject
, Irp
);
1709 /* Otherwise, release the lock */
1710 IoReleaseCancelSpinLock(CancelIrql
);
1715 /* Return back to previous IRQL */
1716 KeLowerIrql(OldIrql
);