2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/io/device.c
5 * PURPOSE: Device Object Management, including Notifications and Queues.
7 * PROGRAMMERS: Alex Ionescu
8 * David Welch (welch@cwcom.net)
11 /* INCLUDES *******************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS ********************************************************************/
19 static ULONG IopDeviceObjectNumber
= 0;
21 typedef struct _SHUTDOWN_ENTRY
23 LIST_ENTRY ShutdownList
;
24 PDEVICE_OBJECT DeviceObject
;
25 } SHUTDOWN_ENTRY
, *PSHUTDOWN_ENTRY
;
27 LIST_ENTRY ShutdownListHead
;
28 KSPIN_LOCK ShutdownListLock
;
30 /* PRIVATE FUNCTIONS **********************************************************/
33 IoShutdownRegisteredDevices(VOID
)
35 PSHUTDOWN_ENTRY ShutdownEntry
;
37 IO_STATUS_BLOCK StatusBlock
;
42 Entry
= ShutdownListHead
.Flink
;
43 while (Entry
!= &ShutdownListHead
)
45 ShutdownEntry
= CONTAINING_RECORD(Entry
, SHUTDOWN_ENTRY
, ShutdownList
);
47 KeInitializeEvent (&Event
,
51 Irp
= IoBuildSynchronousFsdRequest (IRP_MJ_SHUTDOWN
,
52 ShutdownEntry
->DeviceObject
,
59 Status
= IoCallDriver (ShutdownEntry
->DeviceObject
,
61 if (Status
== STATUS_PENDING
)
63 KeWaitForSingleObject (&Event
,
76 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
77 PDRIVER_OBJECT DriverObject
)
82 if (DriverObject
->DriverExtension
->AddDevice
)
84 /* This is a Plug and Play driver */
85 DPRINT("Plug and Play driver found\n");
87 ASSERT(DeviceNode
->PhysicalDeviceObject
);
89 DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
90 DriverObject
->DriverExtension
->AddDevice
);
92 Status
= DriverObject
->DriverExtension
->AddDevice(
93 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
95 if (!NT_SUCCESS(Status
))
100 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
102 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
104 /* FIXME: What do we do? Unload the driver or just disable the device? */
105 DbgPrint("An FDO was not attached\n");
106 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
107 return STATUS_UNSUCCESSFUL
;
110 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
112 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
114 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
116 /* There can be only one system power device */
117 if (!SystemPowerDeviceNodeCreated
)
119 PopSystemPowerDeviceNode
= DeviceNode
;
120 SystemPowerDeviceNodeCreated
= TRUE
;
124 ObDereferenceObject(Fdo
);
127 return STATUS_SUCCESS
;
132 PDEVICE_NODE DeviceNode
)
134 IO_STATUS_BLOCK IoStatusBlock
;
135 IO_STACK_LOCATION Stack
;
139 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
141 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
142 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->ResourceList
;
143 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->ResourceListTranslated
;
145 Status
= IopInitiatePnpIrp(
151 if (!NT_SUCCESS(Status
))
153 DPRINT("IopInitiatePnpIrp() failed\n");
157 if (Fdo
->DeviceType
== FILE_DEVICE_BUS_EXTENDER
||
158 Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
160 DPRINT("Bus extender found\n");
162 Status
= IopInvalidateDeviceRelations(DeviceNode
, BusRelations
);
166 ObDereferenceObject(Fdo
);
173 IopGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName
,
174 IN ACCESS_MASK DesiredAccess
,
175 OUT PFILE_OBJECT
*FileObject
,
176 OUT PDEVICE_OBJECT
*DeviceObject
,
179 OBJECT_ATTRIBUTES ObjectAttributes
;
180 IO_STATUS_BLOCK StatusBlock
;
181 PFILE_OBJECT LocalFileObject
;
185 DPRINT("IoGetDeviceObjectPointer(ObjectName %wZ, DesiredAccess %x,"
186 "FileObject %p DeviceObject %p)\n",
187 ObjectName
, DesiredAccess
, FileObject
, DeviceObject
);
189 /* Open the Device */
190 InitializeObjectAttributes(&ObjectAttributes
,
195 Status
= ZwOpenFile(&FileHandle
,
200 FILE_NON_DIRECTORY_FILE
| AttachFlag
);
202 if (!NT_SUCCESS(Status
))
204 DPRINT1("NtOpenFile failed, Status: 0x%x\n", Status
);
208 /* Get File Object */
209 Status
= ObReferenceObjectByHandle(FileHandle
,
213 (PVOID
*)&LocalFileObject
,
215 if (NT_SUCCESS(Status
))
217 /* Return the requested data */
218 *DeviceObject
= IoGetRelatedDeviceObject(LocalFileObject
);
219 *FileObject
= LocalFileObject
;
222 /* Close the handle */
227 /* PUBLIC FUNCTIONS ***********************************************************/
232 * Layers a device over the highest device in a device stack.
236 * Device to be attached.
239 * Name of the target device.
242 * Caller storage for the device attached to.
249 IoAttachDevice(PDEVICE_OBJECT SourceDevice
,
250 PUNICODE_STRING TargetDeviceName
,
251 PDEVICE_OBJECT
*AttachedDevice
)
254 PFILE_OBJECT FileObject
= NULL
;
255 PDEVICE_OBJECT TargetDevice
= NULL
;
257 /* Call the helper routine for an attach operation */
258 DPRINT("IoAttachDevice\n");
259 Status
= IopGetDeviceObjectPointer(TargetDeviceName
,
260 FILE_READ_ATTRIBUTES
,
263 IO_ATTACH_DEVICE_API
);
265 if (!NT_SUCCESS(Status
))
267 DPRINT1("Failed to get Device Object\n");
271 /* Attach the device */
272 IoAttachDeviceToDeviceStackSafe(SourceDevice
, TargetDevice
, AttachedDevice
);
275 ObDereferenceObject(FileObject
);
276 return STATUS_SUCCESS
;
280 * IoAttachDeviceByPointer
287 IoAttachDeviceByPointer(IN PDEVICE_OBJECT SourceDevice
,
288 IN PDEVICE_OBJECT TargetDevice
)
290 PDEVICE_OBJECT AttachedDevice
;
291 NTSTATUS Status
= STATUS_SUCCESS
;
293 DPRINT("IoAttachDeviceByPointer(SourceDevice 0x%p, TargetDevice 0x%p)\n",
294 SourceDevice
, TargetDevice
);
297 AttachedDevice
= IoAttachDeviceToDeviceStack(SourceDevice
, TargetDevice
);
298 if (AttachedDevice
== NULL
) Status
= STATUS_NO_SUCH_DEVICE
;
300 /* Return the status */
305 * IoAttachDeviceToDeviceStack
312 IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice
,
313 PDEVICE_OBJECT TargetDevice
)
316 PDEVICE_OBJECT LocalAttach
;
318 /* Attach it safely */
319 DPRINT("IoAttachDeviceToDeviceStack\n");
320 Status
= IoAttachDeviceToDeviceStackSafe(SourceDevice
,
325 DPRINT("IoAttachDeviceToDeviceStack DONE: 0x%p\n", LocalAttach
);
334 IoAttachDeviceToDeviceStackSafe(IN PDEVICE_OBJECT SourceDevice
,
335 IN PDEVICE_OBJECT TargetDevice
,
336 OUT PDEVICE_OBJECT
*AttachedToDeviceObject
)
338 PDEVICE_OBJECT AttachedDevice
;
339 PDEVOBJ_EXTENSION SourceDeviceExtension
;
341 DPRINT("IoAttachDeviceToDeviceStack(SourceDevice 0x%p, TargetDevice 0x%p)\n",
342 SourceDevice
, TargetDevice
);
344 /* Get the Attached Device and source extension */
345 AttachedDevice
= IoGetAttachedDevice(TargetDevice
);
346 SourceDeviceExtension
= SourceDevice
->DeviceObjectExtension
;
348 /* Make sure that it's in a correct state */
349 if (!(AttachedDevice
->DeviceObjectExtension
->ExtensionFlags
&
350 (DOE_UNLOAD_PENDING
| DOE_DELETE_PENDING
|
351 DOE_REMOVE_PENDING
| DOE_REMOVE_PROCESSED
)))
354 AttachedDevice
->AttachedDevice
= SourceDevice
;
355 SourceDevice
->AttachedDevice
= NULL
;
356 SourceDevice
->StackSize
= AttachedDevice
->StackSize
+ 1;
357 SourceDevice
->AlignmentRequirement
= AttachedDevice
->AlignmentRequirement
;
358 SourceDevice
->SectorSize
= AttachedDevice
->SectorSize
;
359 SourceDevice
->Vpb
= AttachedDevice
->Vpb
;
361 /* Set the attachment in the device extension */
362 SourceDeviceExtension
->AttachedTo
= AttachedDevice
;
366 /* Device was unloading or being removed */
367 AttachedDevice
= NULL
;
370 /* Return the attached device */
371 *AttachedToDeviceObject
= AttachedDevice
;
372 return STATUS_SUCCESS
;
378 * Allocates memory for and intializes a device object for use for
383 * Driver object passed by IO Manager when the driver was loaded.
385 * DeviceExtensionSize
386 * Number of bytes for the device extension.
389 * Unicode name of device.
392 * Device type of the new device.
394 * DeviceCharacteristics
395 * Bit mask of device characteristics.
398 * TRUE if only one thread can access the device at a time.
401 * On successful return this parameter is filled by pointer to
402 * allocated device object.
409 IoCreateDevice(PDRIVER_OBJECT DriverObject
,
410 ULONG DeviceExtensionSize
,
411 PUNICODE_STRING DeviceName
,
412 DEVICE_TYPE DeviceType
,
413 ULONG DeviceCharacteristics
,
415 PDEVICE_OBJECT
*DeviceObject
)
417 WCHAR AutoNameBuffer
[20];
418 UNICODE_STRING AutoName
;
419 PDEVICE_OBJECT CreatedDeviceObject
;
420 PDEVOBJ_EXTENSION DeviceObjectExtension
;
421 OBJECT_ATTRIBUTES ObjectAttributes
;
423 ULONG AlignedDeviceExtensionSize
;
427 ASSERT_IRQL(PASSIVE_LEVEL
);
428 DPRINT("IoCreateDevice(DriverObject 0x%p)\n", DriverObject
);
430 /* Generate a name if we have to */
431 if (DeviceCharacteristics
& FILE_AUTOGENERATED_DEVICE_NAME
)
433 swprintf(AutoNameBuffer
,
435 InterlockedIncrementUL(&IopDeviceObjectNumber
));
436 RtlInitUnicodeString(&AutoName
, AutoNameBuffer
);
437 DeviceName
= &AutoName
;
440 /* Initialize the Object Attributes */
441 InitializeObjectAttributes(&ObjectAttributes
, DeviceName
, 0, NULL
, NULL
);
443 /* Honor exclusive flag */
444 ObjectAttributes
.Attributes
|= OBJ_EXCLUSIVE
;
446 /* Create a permanent object for named devices */
447 if (DeviceName
!= NULL
)
449 ObjectAttributes
.Attributes
|= OBJ_PERMANENT
;
452 /* Align the Extension Size to 8-bytes */
453 AlignedDeviceExtensionSize
= (DeviceExtensionSize
+ 7) &~ 7;
454 DPRINT("AlignedDeviceExtensionSize %x\n", AlignedDeviceExtensionSize
);
457 TotalSize
= AlignedDeviceExtensionSize
+
458 sizeof(DEVICE_OBJECT
) + sizeof(DEVOBJ_EXTENSION
);
459 DPRINT("TotalSize %x\n", TotalSize
);
461 /* Create the Device Object */
462 Status
= ObCreateObject(KernelMode
,
470 (PVOID
*)&CreatedDeviceObject
);
472 if (!NT_SUCCESS(Status
))
474 DPRINT1("IoCreateDevice() ObCreateObject failed, status: 0x%08X\n", Status
);
478 /* Clear the whole Object and extension so we don't null stuff manually */
479 RtlZeroMemory(CreatedDeviceObject
, TotalSize
);
480 DPRINT("CreatedDeviceObject 0x%p\n", CreatedDeviceObject
);
483 * Setup the Type and Size. Note that we don't use the aligned size,
484 * because that's only padding for the DevObjExt and not part of the Object.
486 CreatedDeviceObject
->Type
= IO_TYPE_DEVICE
;
487 CreatedDeviceObject
->Size
= sizeof(DEVICE_OBJECT
) + DeviceExtensionSize
;
489 /* The kernel extension is after the driver internal extension */
490 DeviceObjectExtension
= (PDEVOBJ_EXTENSION
)
491 ((ULONG_PTR
)(CreatedDeviceObject
+ 1) +
492 AlignedDeviceExtensionSize
);
494 /* Set the Type and Size. Question: why is Size 0 on Windows? */
495 DPRINT("DeviceObjectExtension 0x%p\n", DeviceObjectExtension
);
496 DeviceObjectExtension
->Type
= IO_TYPE_DEVICE_OBJECT_EXTENSION
;
497 DeviceObjectExtension
->Size
= 0;
499 /* Link the Object and Extension */
500 DeviceObjectExtension
->DeviceObject
= CreatedDeviceObject
;
501 CreatedDeviceObject
->DeviceObjectExtension
= DeviceObjectExtension
;
503 /* Set Device Object Data */
504 CreatedDeviceObject
->DeviceType
= DeviceType
;
505 CreatedDeviceObject
->Characteristics
= DeviceCharacteristics
;
506 CreatedDeviceObject
->DeviceExtension
= CreatedDeviceObject
+ 1;
507 CreatedDeviceObject
->StackSize
= 1;
508 CreatedDeviceObject
->AlignmentRequirement
= 1; /* FIXME */
511 /* FIXME: After the Driver is Loaded, the flag below should be removed */
512 CreatedDeviceObject
->Flags
= DO_DEVICE_INITIALIZING
;
513 if (Exclusive
) CreatedDeviceObject
->Flags
|= DO_EXCLUSIVE
;
514 if (DeviceName
) CreatedDeviceObject
->Flags
|= DO_DEVICE_HAS_NAME
;
516 /* Attach a Vpb for Disks and Tapes, and create the Device Lock */
517 if (CreatedDeviceObject
->DeviceType
== FILE_DEVICE_DISK
||
518 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_VIRTUAL_DISK
||
519 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_CD_ROM
||
520 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_TAPE
)
523 IopAttachVpb(CreatedDeviceObject
);
525 /* Initialize Lock Event */
526 KeInitializeEvent(&CreatedDeviceObject
->DeviceLock
,
527 SynchronizationEvent
,
531 /* Set the right Sector Size */
534 case FILE_DEVICE_DISK_FILE_SYSTEM
:
535 case FILE_DEVICE_DISK
:
536 case FILE_DEVICE_VIRTUAL_DISK
:
537 CreatedDeviceObject
->SectorSize
= 512;
540 case FILE_DEVICE_CD_ROM_FILE_SYSTEM
:
541 CreatedDeviceObject
->SectorSize
= 2048;
545 /* Create the Device Queue */
546 KeInitializeDeviceQueue(&CreatedDeviceObject
->DeviceQueue
);
548 /* Insert the Object */
549 Status
= ObInsertObject(CreatedDeviceObject
,
551 FILE_READ_DATA
| FILE_WRITE_DATA
,
556 if (!NT_SUCCESS(Status
))
558 DPRINT1("Cannot insert Device Object into Handle Table\n");
559 *DeviceObject
= NULL
;
563 /* Now do the final linking */
564 ObReferenceObject(DriverObject
);
565 CreatedDeviceObject
->DriverObject
= DriverObject
;
566 CreatedDeviceObject
->NextDevice
= DriverObject
->DeviceObject
;
567 DriverObject
->DeviceObject
= CreatedDeviceObject
;
571 /* Return to caller */
572 *DeviceObject
= CreatedDeviceObject
;
573 return STATUS_SUCCESS
;
584 IoDeleteDevice(PDEVICE_OBJECT DeviceObject
)
586 PDEVICE_OBJECT Previous
;
588 if (DeviceObject
->Flags
& DO_SHUTDOWN_REGISTERED
)
589 IoUnregisterShutdownNotification(DeviceObject
);
591 /* Remove the timer if it exists */
592 if (DeviceObject
->Timer
)
594 IopRemoveTimerFromTimerList(DeviceObject
->Timer
);
595 ExFreePoolWithTag(DeviceObject
->Timer
, TAG_IO_TIMER
);
598 /* Remove device from driver device list */
599 Previous
= DeviceObject
->DriverObject
->DeviceObject
;
600 if (Previous
== DeviceObject
)
602 DeviceObject
->DriverObject
->DeviceObject
= DeviceObject
->NextDevice
;
606 while (Previous
->NextDevice
!= DeviceObject
)
607 Previous
= Previous
->NextDevice
;
608 Previous
->NextDevice
= DeviceObject
->NextDevice
;
611 /* I guess this should be removed later... but it shouldn't cause problems */
612 DeviceObject
->DeviceObjectExtension
->ExtensionFlags
|= DOE_DELETE_PENDING
;
614 /* Make the object temporary. This should automatically remove the device
615 from the namespace */
616 ObMakeTemporaryObject(DeviceObject
);
618 /* Dereference the driver object */
619 ObDereferenceObject(DeviceObject
->DriverObject
);
621 /* Remove the keep-alive reference */
622 ObDereferenceObject(DeviceObject
);
633 IoDetachDevice(PDEVICE_OBJECT TargetDevice
)
635 DPRINT("IoDetachDevice(TargetDevice 0x%p)\n", TargetDevice
);
637 /* Remove the attachment */
638 TargetDevice
->AttachedDevice
->DeviceObjectExtension
->AttachedTo
= NULL
;
639 TargetDevice
->AttachedDevice
= NULL
;
647 IoEnumerateDeviceObjectList(IN PDRIVER_OBJECT DriverObject
,
648 IN PDEVICE_OBJECT
*DeviceObjectList
,
649 IN ULONG DeviceObjectListSize
,
650 OUT PULONG ActualNumberDeviceObjects
)
652 ULONG ActualDevices
= 1;
653 PDEVICE_OBJECT CurrentDevice
= DriverObject
->DeviceObject
;
655 DPRINT1("IoEnumerateDeviceObjectList\n");
657 /* Find out how many devices we'll enumerate */
658 while ((CurrentDevice
= CurrentDevice
->NextDevice
))
663 /* Go back to the first */
664 CurrentDevice
= DriverObject
->DeviceObject
;
666 /* Start by at least returning this */
667 *ActualNumberDeviceObjects
= ActualDevices
;
669 /* Check if we can support so many */
670 if ((ActualDevices
* 4) > DeviceObjectListSize
)
672 /* Fail because the buffer was too small */
673 return STATUS_BUFFER_TOO_SMALL
;
676 /* Check if the caller only wanted the size */
677 if (DeviceObjectList
)
679 /* Loop through all the devices */
680 while (ActualDevices
)
682 /* Reference each Device */
683 ObReferenceObject(CurrentDevice
);
685 /* Add it to the list */
686 *DeviceObjectList
= CurrentDevice
;
688 /* Go to the next one */
689 CurrentDevice
= CurrentDevice
->NextDevice
;
695 /* Return the status */
696 return STATUS_SUCCESS
;
700 * IoGetAttachedDevice
707 IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject
)
709 PDEVICE_OBJECT Current
= DeviceObject
;
711 /* Get the last attached device */
712 while (Current
->AttachedDevice
)
714 Current
= Current
->AttachedDevice
;
722 * IoGetAttachedDeviceReference
729 IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject
)
731 PDEVICE_OBJECT Current
= IoGetAttachedDevice(DeviceObject
);
733 /* Reference the ATtached Device */
734 ObReferenceObject(Current
);
743 IoGetDeviceAttachmentBaseRef(IN PDEVICE_OBJECT DeviceObject
)
745 /* Return the attached Device */
746 return (DeviceObject
->DeviceObjectExtension
->AttachedTo
);
750 * IoGetDeviceObjectPointer
757 IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName
,
758 IN ACCESS_MASK DesiredAccess
,
759 OUT PFILE_OBJECT
*FileObject
,
760 OUT PDEVICE_OBJECT
*DeviceObject
)
762 /* Call the helper routine for a normal operation */
763 return IopGetDeviceObjectPointer(ObjectName
,
775 IoGetDiskDeviceObject(IN PDEVICE_OBJECT FileSystemDeviceObject
,
776 OUT PDEVICE_OBJECT
*DiskDeviceObject
)
778 PDEVOBJ_EXTENSION DeviceExtension
;
782 /* Make sure there's a VPB */
783 if (!FileSystemDeviceObject
->Vpb
) return STATUS_INVALID_PARAMETER
;
786 IoAcquireVpbSpinLock(&OldIrql
);
788 /* Get the Device Extension */
789 DeviceExtension
= FileSystemDeviceObject
->DeviceObjectExtension
;
791 /* Make sure this one has a VPB too */
792 Vpb
= DeviceExtension
->Vpb
;
793 if (!Vpb
) return STATUS_INVALID_PARAMETER
;
795 /* Make sure someone it's mounted */
796 if ((!Vpb
->ReferenceCount
) || (Vpb
->Flags
& VPB_MOUNTED
)) return STATUS_VOLUME_DISMOUNTED
;
798 /* Return the Disk Device Object */
799 *DiskDeviceObject
= Vpb
->RealDevice
;
801 /* Release the lock */
802 IoReleaseVpbSpinLock(OldIrql
);
803 return STATUS_SUCCESS
;
811 IoGetLowerDeviceObject(IN PDEVICE_OBJECT DeviceObject
)
813 PDEVOBJ_EXTENSION DeviceExtension
= DeviceObject
->DeviceObjectExtension
;
814 PDEVICE_OBJECT LowerDeviceObject
= NULL
;
816 /* Make sure it's not getting deleted */
817 if (DeviceExtension
->ExtensionFlags
& (DOE_UNLOAD_PENDING
|
820 DOE_REMOVE_PROCESSED
))
822 /* Get the Lower Device Object */
823 LowerDeviceObject
= DeviceExtension
->AttachedTo
;
826 ObReferenceObject(LowerDeviceObject
);
830 return LowerDeviceObject
;
834 * IoGetRelatedDeviceObject
837 * See "Windows NT File System Internals", page 633 - 634.
844 IoGetRelatedDeviceObject(IN PFILE_OBJECT FileObject
)
846 PDEVICE_OBJECT DeviceObject
= FileObject
->DeviceObject
;
848 /* Get logical volume mounted on a physical/virtual/logical device */
849 if (FileObject
->Vpb
&& FileObject
->Vpb
->DeviceObject
)
851 DeviceObject
= FileObject
->Vpb
->DeviceObject
;
855 * Check if file object has an associated device object mounted by some
858 if (FileObject
->DeviceObject
->Vpb
&&
859 FileObject
->DeviceObject
->Vpb
->DeviceObject
)
861 DeviceObject
= FileObject
->DeviceObject
->Vpb
->DeviceObject
;
864 /* Return the highest attached device */
865 return IoGetAttachedDevice(DeviceObject
);
873 IoRegisterLastChanceShutdownNotification(IN PDEVICE_OBJECT DeviceObject
)
876 return STATUS_NOT_IMPLEMENTED
;
884 IoRegisterShutdownNotification(PDEVICE_OBJECT DeviceObject
)
886 PSHUTDOWN_ENTRY Entry
;
888 Entry
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(SHUTDOWN_ENTRY
),
891 return STATUS_INSUFFICIENT_RESOURCES
;
893 Entry
->DeviceObject
= DeviceObject
;
895 ExInterlockedInsertHeadList(&ShutdownListHead
,
896 &Entry
->ShutdownList
,
899 DeviceObject
->Flags
|= DO_SHUTDOWN_REGISTERED
;
901 return STATUS_SUCCESS
;
909 IoSetStartIoAttributes(IN PDEVICE_OBJECT DeviceObject
,
910 IN BOOLEAN DeferredStartIo
,
911 IN BOOLEAN NonCancelable
)
919 * FUNCTION: Dequeues the next packet from the given device object's
920 * associated device queue according to a specified sort-key value and calls
921 * the drivers StartIo routine with that IRP
923 * DeviceObject = Device object for which the irp is to dequeued
924 * Cancelable = True if IRPs in the key can be canceled
925 * Key = Sort key specifing which entry to remove from the queue
929 IoStartNextPacketByKey(PDEVICE_OBJECT DeviceObject
,
933 PKDEVICE_QUEUE_ENTRY entry
;
936 entry
= KeRemoveByKeyDeviceQueue(&DeviceObject
->DeviceQueue
,
941 Irp
= CONTAINING_RECORD(entry
,
943 Tail
.Overlay
.DeviceQueueEntry
);
944 DeviceObject
->CurrentIrp
= Irp
;
945 DPRINT("Next irp is 0x%p\n", Irp
);
946 DeviceObject
->DriverObject
->DriverStartIo(DeviceObject
, Irp
);
950 DPRINT("No next irp\n");
951 DeviceObject
->CurrentIrp
= NULL
;
958 * FUNCTION: Removes the next packet from the device's queue and calls
959 * the driver's StartIO
961 * DeviceObject = Device
962 * Cancelable = True if irps in the queue can be canceled
966 IoStartNextPacket(PDEVICE_OBJECT DeviceObject
,
969 PKDEVICE_QUEUE_ENTRY entry
;
972 DPRINT("IoStartNextPacket(DeviceObject 0x%p, Cancelable %d)\n",
973 DeviceObject
, Cancelable
);
975 entry
= KeRemoveDeviceQueue(&DeviceObject
->DeviceQueue
);
979 Irp
= CONTAINING_RECORD(entry
,IRP
,Tail
.Overlay
.DeviceQueueEntry
);
980 DeviceObject
->CurrentIrp
= Irp
;
981 DeviceObject
->DriverObject
->DriverStartIo(DeviceObject
,Irp
);
985 DeviceObject
->CurrentIrp
= NULL
;
992 * FUNCTION: Either call the device's StartIO routine with the packet or,
993 * if the device is busy, queue it.
995 * DeviceObject = Device to start the packet on
997 * Key = Where to insert the irp
998 * If zero then insert in the tail of the queue
999 * CancelFunction = Optional function to cancel the irqp
1003 IoStartPacket(PDEVICE_OBJECT DeviceObject
,
1006 PDRIVER_CANCEL CancelFunction
)
1011 DPRINT("IoStartPacket(Irp 0x%p)\n", Irp
);
1013 ASSERT_IRQL(DISPATCH_LEVEL
);
1015 IoAcquireCancelSpinLock(&oldirql
);
1017 if (CancelFunction
!= NULL
)
1019 Irp
->CancelRoutine
= CancelFunction
;
1024 stat
= KeInsertByKeyDeviceQueue(&DeviceObject
->DeviceQueue
,
1025 &Irp
->Tail
.Overlay
.DeviceQueueEntry
,
1030 stat
= KeInsertDeviceQueue(&DeviceObject
->DeviceQueue
,
1031 &Irp
->Tail
.Overlay
.DeviceQueueEntry
);
1037 IoReleaseCancelSpinLock(DISPATCH_LEVEL
);
1038 DeviceObject
->CurrentIrp
= Irp
;
1039 DeviceObject
->DriverObject
->DriverStartIo(DeviceObject
,Irp
);
1040 if (oldirql
< DISPATCH_LEVEL
)
1042 KeLowerIrql(oldirql
);
1047 IoReleaseCancelSpinLock(oldirql
);
1057 IoSynchronousInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject
,
1058 IN DEVICE_RELATION_TYPE Type
)
1068 IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject
)
1070 PSHUTDOWN_ENTRY ShutdownEntry
;
1074 Entry
= ShutdownListHead
.Flink
;
1075 while (Entry
!= &ShutdownListHead
)
1077 ShutdownEntry
= CONTAINING_RECORD(Entry
, SHUTDOWN_ENTRY
, ShutdownList
);
1078 if (ShutdownEntry
->DeviceObject
== DeviceObject
)
1080 DeviceObject
->Flags
&= ~DO_SHUTDOWN_REGISTERED
;
1082 KeAcquireSpinLock(&ShutdownListLock
,&oldlvl
);
1083 RemoveEntryList(Entry
);
1084 KeReleaseSpinLock(&ShutdownListLock
,oldlvl
);
1090 Entry
= Entry
->Flink
;
1099 IoValidateDeviceIoControlAccess(IN PIRP Irp
,
1100 IN ULONG RequiredAccess
)
1103 return STATUS_NOT_IMPLEMENTED
;