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
;
36 IO_STATUS_BLOCK StatusBlock
;
41 LIST_FOR_EACH(ShutdownEntry
, &ShutdownListHead
, SHUTDOWN_ENTRY
, ShutdownList
)
43 KeInitializeEvent (&Event
,
47 Irp
= IoBuildSynchronousFsdRequest (IRP_MJ_SHUTDOWN
,
48 ShutdownEntry
->DeviceObject
,
55 Status
= IoCallDriver (ShutdownEntry
->DeviceObject
,
57 if (Status
== STATUS_PENDING
)
59 KeWaitForSingleObject (&Event
,
70 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
71 PDRIVER_OBJECT DriverObject
)
75 BOOLEAN IsPnpDriver
= FALSE
;
77 if (DriverObject
->DriverExtension
->AddDevice
)
79 /* This is a Plug and Play driver */
80 DPRINT("Plug and Play driver found\n");
82 ASSERT(DeviceNode
->PhysicalDeviceObject
);
84 DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
85 DriverObject
->DriverExtension
->AddDevice
);
87 IsPnpDriver
= !IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
);
88 Status
= DriverObject
->DriverExtension
->AddDevice(
89 DriverObject
, IsPnpDriver
? DeviceNode
->PhysicalDeviceObject
: NULL
);
91 if (!NT_SUCCESS(Status
))
98 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
100 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
102 /* FIXME: What do we do? Unload the driver or just disable the device? */
103 DbgPrint("An FDO was not attached\n");
104 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
105 return STATUS_UNSUCCESSFUL
;
108 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
110 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
112 /* There can be only one system power device */
113 if (!SystemPowerDeviceNodeCreated
)
115 PopSystemPowerDeviceNode
= DeviceNode
;
116 SystemPowerDeviceNodeCreated
= TRUE
;
120 ObDereferenceObject(Fdo
);
123 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
124 IopDeviceNodeSetFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
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 (IopDeviceNodeHasFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
))
159 DPRINT("Device needs enumeration, invalidating bus relations\n");
160 Status
= IopInvalidateDeviceRelations(DeviceNode
, BusRelations
);
161 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
165 ObDereferenceObject(Fdo
);
167 if (NT_SUCCESS(Status
))
168 DeviceNode
->Flags
|= DN_STARTED
;
175 IopGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName
,
176 IN ACCESS_MASK DesiredAccess
,
177 OUT PFILE_OBJECT
*FileObject
,
178 OUT PDEVICE_OBJECT
*DeviceObject
,
181 OBJECT_ATTRIBUTES ObjectAttributes
;
182 IO_STATUS_BLOCK StatusBlock
;
183 PFILE_OBJECT LocalFileObject
;
187 DPRINT("IoGetDeviceObjectPointer(ObjectName %wZ, DesiredAccess %x,"
188 "FileObject %p DeviceObject %p)\n",
189 ObjectName
, DesiredAccess
, FileObject
, DeviceObject
);
191 /* Open the Device */
192 InitializeObjectAttributes(&ObjectAttributes
,
197 Status
= ZwOpenFile(&FileHandle
,
202 FILE_NON_DIRECTORY_FILE
| AttachFlag
);
204 if (!NT_SUCCESS(Status
))
206 DPRINT1("NtOpenFile failed, Status: 0x%x\n", Status
);
210 /* Get File Object */
211 Status
= ObReferenceObjectByHandle(FileHandle
,
215 (PVOID
*)&LocalFileObject
,
217 if (NT_SUCCESS(Status
))
219 /* Return the requested data */
220 *DeviceObject
= IoGetRelatedDeviceObject(LocalFileObject
);
221 *FileObject
= LocalFileObject
;
224 /* Close the handle */
229 /* PUBLIC FUNCTIONS ***********************************************************/
234 * Layers a device over the highest device in a device stack.
238 * Device to be attached.
241 * Name of the target device.
244 * Caller storage for the device attached to.
251 IoAttachDevice(PDEVICE_OBJECT SourceDevice
,
252 PUNICODE_STRING TargetDeviceName
,
253 PDEVICE_OBJECT
*AttachedDevice
)
256 PFILE_OBJECT FileObject
= NULL
;
257 PDEVICE_OBJECT TargetDevice
= NULL
;
259 /* Call the helper routine for an attach operation */
260 DPRINT("IoAttachDevice\n");
261 Status
= IopGetDeviceObjectPointer(TargetDeviceName
,
262 FILE_READ_ATTRIBUTES
,
265 IO_ATTACH_DEVICE_API
);
267 if (!NT_SUCCESS(Status
))
269 DPRINT1("Failed to get Device Object\n");
273 /* Attach the device */
274 IoAttachDeviceToDeviceStackSafe(SourceDevice
, TargetDevice
, AttachedDevice
);
277 ObDereferenceObject(FileObject
);
278 return STATUS_SUCCESS
;
282 * IoAttachDeviceByPointer
289 IoAttachDeviceByPointer(IN PDEVICE_OBJECT SourceDevice
,
290 IN PDEVICE_OBJECT TargetDevice
)
292 PDEVICE_OBJECT AttachedDevice
;
293 NTSTATUS Status
= STATUS_SUCCESS
;
295 DPRINT("IoAttachDeviceByPointer(SourceDevice 0x%p, TargetDevice 0x%p)\n",
296 SourceDevice
, TargetDevice
);
299 AttachedDevice
= IoAttachDeviceToDeviceStack(SourceDevice
, TargetDevice
);
300 if (AttachedDevice
== NULL
) Status
= STATUS_NO_SUCH_DEVICE
;
302 /* Return the status */
307 * IoAttachDeviceToDeviceStack
314 IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice
,
315 PDEVICE_OBJECT TargetDevice
)
318 PDEVICE_OBJECT LocalAttach
;
320 /* Attach it safely */
321 DPRINT("IoAttachDeviceToDeviceStack\n");
322 Status
= IoAttachDeviceToDeviceStackSafe(SourceDevice
,
327 DPRINT("IoAttachDeviceToDeviceStack DONE: 0x%p\n", LocalAttach
);
336 IoAttachDeviceToDeviceStackSafe(IN PDEVICE_OBJECT SourceDevice
,
337 IN PDEVICE_OBJECT TargetDevice
,
338 OUT PDEVICE_OBJECT
*AttachedToDeviceObject
)
340 PDEVICE_OBJECT AttachedDevice
;
341 PEXTENDED_DEVOBJ_EXTENSION SourceDeviceExtension
;
343 DPRINT("IoAttachDeviceToDeviceStack(SourceDevice 0x%p, TargetDevice 0x%p)\n",
344 SourceDevice
, TargetDevice
);
346 /* Get the Attached Device and source extension */
347 AttachedDevice
= IoGetAttachedDevice(TargetDevice
);
348 SourceDeviceExtension
= (PEXTENDED_DEVOBJ_EXTENSION
)SourceDevice
->DeviceObjectExtension
;
350 /* Make sure that it's in a correct state */
351 if (!(((PEXTENDED_DEVOBJ_EXTENSION
)AttachedDevice
->DeviceObjectExtension
)->ExtensionFlags
&
352 (DOE_UNLOAD_PENDING
| DOE_DELETE_PENDING
|
353 DOE_REMOVE_PENDING
| DOE_REMOVE_PROCESSED
)))
356 AttachedDevice
->AttachedDevice
= SourceDevice
;
357 SourceDevice
->AttachedDevice
= NULL
;
358 SourceDevice
->StackSize
= AttachedDevice
->StackSize
+ 1;
359 SourceDevice
->AlignmentRequirement
= AttachedDevice
->AlignmentRequirement
;
360 SourceDevice
->SectorSize
= AttachedDevice
->SectorSize
;
361 SourceDevice
->Vpb
= AttachedDevice
->Vpb
;
363 /* Set the attachment in the device extension */
364 SourceDeviceExtension
->AttachedTo
= AttachedDevice
;
368 /* Device was unloading or being removed */
369 AttachedDevice
= NULL
;
372 /* Return the attached device */
373 *AttachedToDeviceObject
= AttachedDevice
;
374 return STATUS_SUCCESS
;
380 * Allocates memory for and intializes a device object for use for
385 * Driver object passed by IO Manager when the driver was loaded.
387 * DeviceExtensionSize
388 * Number of bytes for the device extension.
391 * Unicode name of device.
394 * Device type of the new device.
396 * DeviceCharacteristics
397 * Bit mask of device characteristics.
400 * TRUE if only one thread can access the device at a time.
403 * On successful return this parameter is filled by pointer to
404 * allocated device object.
411 IoCreateDevice(PDRIVER_OBJECT DriverObject
,
412 ULONG DeviceExtensionSize
,
413 PUNICODE_STRING DeviceName
,
414 DEVICE_TYPE DeviceType
,
415 ULONG DeviceCharacteristics
,
417 PDEVICE_OBJECT
*DeviceObject
)
419 WCHAR AutoNameBuffer
[20];
420 UNICODE_STRING AutoName
;
421 PDEVICE_OBJECT CreatedDeviceObject
;
422 PDEVOBJ_EXTENSION DeviceObjectExtension
;
423 OBJECT_ATTRIBUTES ObjectAttributes
;
425 ULONG AlignedDeviceExtensionSize
;
429 ASSERT_IRQL(PASSIVE_LEVEL
);
430 DPRINT("IoCreateDevice(DriverObject 0x%p)\n", DriverObject
);
432 /* Generate a name if we have to */
433 if (DeviceCharacteristics
& FILE_AUTOGENERATED_DEVICE_NAME
)
435 swprintf(AutoNameBuffer
,
437 InterlockedIncrementUL(&IopDeviceObjectNumber
));
438 RtlInitUnicodeString(&AutoName
, AutoNameBuffer
);
439 DeviceName
= &AutoName
;
442 /* Initialize the Object Attributes */
443 InitializeObjectAttributes(&ObjectAttributes
, DeviceName
, 0, NULL
, NULL
);
445 /* Honor exclusive flag */
446 ObjectAttributes
.Attributes
|= OBJ_EXCLUSIVE
;
448 /* Create a permanent object for named devices */
449 if (DeviceName
!= NULL
)
451 ObjectAttributes
.Attributes
|= OBJ_PERMANENT
;
454 /* Align the Extension Size to 8-bytes */
455 AlignedDeviceExtensionSize
= (DeviceExtensionSize
+ 7) &~ 7;
456 DPRINT("AlignedDeviceExtensionSize %x\n", AlignedDeviceExtensionSize
);
459 TotalSize
= AlignedDeviceExtensionSize
+
460 sizeof(DEVICE_OBJECT
) + sizeof(EXTENDED_DEVOBJ_EXTENSION
);
461 DPRINT("TotalSize %x\n", TotalSize
);
463 /* Create the Device Object */
464 Status
= ObCreateObject(KernelMode
,
472 (PVOID
*)&CreatedDeviceObject
);
474 if (!NT_SUCCESS(Status
))
476 DPRINT1("IoCreateDevice() ObCreateObject failed, status: 0x%08X\n", Status
);
480 /* Clear the whole Object and extension so we don't null stuff manually */
481 RtlZeroMemory(CreatedDeviceObject
, TotalSize
);
482 DPRINT("CreatedDeviceObject 0x%p\n", CreatedDeviceObject
);
485 * Setup the Type and Size. Note that we don't use the aligned size,
486 * because that's only padding for the DevObjExt and not part of the Object.
488 CreatedDeviceObject
->Type
= IO_TYPE_DEVICE
;
489 CreatedDeviceObject
->Size
= sizeof(DEVICE_OBJECT
) + DeviceExtensionSize
;
491 /* The kernel extension is after the driver internal extension */
492 DeviceObjectExtension
= (PDEVOBJ_EXTENSION
)
493 ((ULONG_PTR
)(CreatedDeviceObject
+ 1) +
494 AlignedDeviceExtensionSize
);
496 /* Set the Type and Size. Question: why is Size 0 on Windows? */
497 DPRINT("DeviceObjectExtension 0x%p\n", DeviceObjectExtension
);
498 DeviceObjectExtension
->Type
= IO_TYPE_DEVICE_OBJECT_EXTENSION
;
499 DeviceObjectExtension
->Size
= 0;
501 /* Link the Object and Extension */
502 DeviceObjectExtension
->DeviceObject
= CreatedDeviceObject
;
503 CreatedDeviceObject
->DeviceObjectExtension
= DeviceObjectExtension
;
505 /* Set Device Object Data */
506 CreatedDeviceObject
->DeviceType
= DeviceType
;
507 CreatedDeviceObject
->Characteristics
= DeviceCharacteristics
;
508 CreatedDeviceObject
->DeviceExtension
= DeviceExtensionSize
?
509 CreatedDeviceObject
+ 1 :
511 CreatedDeviceObject
->StackSize
= 1;
512 CreatedDeviceObject
->AlignmentRequirement
= 1; /* FIXME */
515 /* FIXME: After the Driver is Loaded, the flag below should be removed */
516 CreatedDeviceObject
->Flags
= DO_DEVICE_INITIALIZING
;
517 if (Exclusive
) CreatedDeviceObject
->Flags
|= DO_EXCLUSIVE
;
518 if (DeviceName
) CreatedDeviceObject
->Flags
|= DO_DEVICE_HAS_NAME
;
520 /* Attach a Vpb for Disks and Tapes, and create the Device Lock */
521 if (CreatedDeviceObject
->DeviceType
== FILE_DEVICE_DISK
||
522 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_VIRTUAL_DISK
||
523 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_CD_ROM
||
524 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_TAPE
)
527 IopAttachVpb(CreatedDeviceObject
);
529 /* Initialize Lock Event */
530 KeInitializeEvent(&CreatedDeviceObject
->DeviceLock
,
531 SynchronizationEvent
,
535 /* Set the right Sector Size */
538 case FILE_DEVICE_DISK_FILE_SYSTEM
:
539 case FILE_DEVICE_DISK
:
540 case FILE_DEVICE_VIRTUAL_DISK
:
541 CreatedDeviceObject
->SectorSize
= 512;
544 case FILE_DEVICE_CD_ROM_FILE_SYSTEM
:
545 CreatedDeviceObject
->SectorSize
= 2048;
549 /* Create the Device Queue */
550 if (CreatedDeviceObject
->DeviceType
== FILE_DEVICE_DISK_FILE_SYSTEM
||
551 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_FILE_SYSTEM
||
552 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
||
553 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_NETWORK_FILE_SYSTEM
||
554 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_TAPE_FILE_SYSTEM
)
556 /* Simple FS Devices, they don't need a real Device Queue */
557 InitializeListHead(&CreatedDeviceObject
->Queue
.ListEntry
);
561 /* An actual Device, initialize its DQ */
562 KeInitializeDeviceQueue(&CreatedDeviceObject
->DeviceQueue
);
565 /* Insert the Object */
566 Status
= ObInsertObject(CreatedDeviceObject
,
568 FILE_READ_DATA
| FILE_WRITE_DATA
,
573 if (!NT_SUCCESS(Status
))
575 DPRINT1("Cannot insert Device Object '%wZ' into Handle Table (status 0x%08lx)\n",
577 *DeviceObject
= NULL
;
581 /* Now do the final linking */
582 ObReferenceObject(DriverObject
);
583 CreatedDeviceObject
->DriverObject
= DriverObject
;
584 CreatedDeviceObject
->NextDevice
= DriverObject
->DeviceObject
;
585 DriverObject
->DeviceObject
= CreatedDeviceObject
;
589 /* Return to caller */
590 *DeviceObject
= CreatedDeviceObject
;
591 return STATUS_SUCCESS
;
602 IoDeleteDevice(PDEVICE_OBJECT DeviceObject
)
604 PDEVICE_OBJECT Previous
;
606 if (DeviceObject
->Flags
& DO_SHUTDOWN_REGISTERED
)
607 IoUnregisterShutdownNotification(DeviceObject
);
609 /* Remove the timer if it exists */
610 if (DeviceObject
->Timer
)
612 IopRemoveTimerFromTimerList(DeviceObject
->Timer
);
613 ExFreePoolWithTag(DeviceObject
->Timer
, TAG_IO_TIMER
);
616 /* Remove device from driver device list */
617 Previous
= DeviceObject
->DriverObject
->DeviceObject
;
618 if (Previous
== DeviceObject
)
620 DeviceObject
->DriverObject
->DeviceObject
= DeviceObject
->NextDevice
;
624 while (Previous
->NextDevice
!= DeviceObject
)
625 Previous
= Previous
->NextDevice
;
626 Previous
->NextDevice
= DeviceObject
->NextDevice
;
629 /* I guess this should be removed later... but it shouldn't cause problems */
630 ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->ExtensionFlags
|= DOE_DELETE_PENDING
;
632 /* Make the object temporary. This should automatically remove the device
633 from the namespace */
634 ObMakeTemporaryObject(DeviceObject
);
636 /* Dereference the driver object */
637 ObDereferenceObject(DeviceObject
->DriverObject
);
639 /* Remove the keep-alive reference */
640 ObDereferenceObject(DeviceObject
);
651 IoDetachDevice(PDEVICE_OBJECT TargetDevice
)
653 DPRINT("IoDetachDevice(TargetDevice 0x%p)\n", TargetDevice
);
655 /* Remove the attachment */
656 ((PEXTENDED_DEVOBJ_EXTENSION
)TargetDevice
->AttachedDevice
->DeviceObjectExtension
)->AttachedTo
= NULL
;
657 TargetDevice
->AttachedDevice
= NULL
;
665 IoEnumerateDeviceObjectList(IN PDRIVER_OBJECT DriverObject
,
666 IN PDEVICE_OBJECT
*DeviceObjectList
,
667 IN ULONG DeviceObjectListSize
,
668 OUT PULONG ActualNumberDeviceObjects
)
670 ULONG ActualDevices
= 1;
671 PDEVICE_OBJECT CurrentDevice
= DriverObject
->DeviceObject
;
673 DPRINT1("IoEnumerateDeviceObjectList\n");
675 /* Find out how many devices we'll enumerate */
676 while ((CurrentDevice
= CurrentDevice
->NextDevice
))
681 /* Go back to the first */
682 CurrentDevice
= DriverObject
->DeviceObject
;
684 /* Start by at least returning this */
685 *ActualNumberDeviceObjects
= ActualDevices
;
687 /* Check if we can support so many */
688 if ((ActualDevices
* 4) > DeviceObjectListSize
)
690 /* Fail because the buffer was too small */
691 return STATUS_BUFFER_TOO_SMALL
;
694 /* Check if the caller only wanted the size */
695 if (DeviceObjectList
)
697 /* Loop through all the devices */
698 while (ActualDevices
)
700 /* Reference each Device */
701 ObReferenceObject(CurrentDevice
);
703 /* Add it to the list */
704 *DeviceObjectList
= CurrentDevice
;
706 /* Go to the next one */
707 CurrentDevice
= CurrentDevice
->NextDevice
;
713 /* Return the status */
714 return STATUS_SUCCESS
;
718 * IoGetAttachedDevice
725 IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject
)
727 PDEVICE_OBJECT Current
= DeviceObject
;
729 /* Get the last attached device */
730 while (Current
->AttachedDevice
)
732 Current
= Current
->AttachedDevice
;
740 * IoGetAttachedDeviceReference
747 IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject
)
749 PDEVICE_OBJECT Current
= IoGetAttachedDevice(DeviceObject
);
751 /* Reference the ATtached Device */
752 ObReferenceObject(Current
);
761 IoGetDeviceAttachmentBaseRef(IN PDEVICE_OBJECT DeviceObject
)
763 /* Return the attached Device */
764 return (((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->AttachedTo
);
768 * IoGetDeviceObjectPointer
775 IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName
,
776 IN ACCESS_MASK DesiredAccess
,
777 OUT PFILE_OBJECT
*FileObject
,
778 OUT PDEVICE_OBJECT
*DeviceObject
)
780 /* Call the helper routine for a normal operation */
781 return IopGetDeviceObjectPointer(ObjectName
,
793 IoGetDiskDeviceObject(IN PDEVICE_OBJECT FileSystemDeviceObject
,
794 OUT PDEVICE_OBJECT
*DiskDeviceObject
)
796 PEXTENDED_DEVOBJ_EXTENSION DeviceExtension
;
800 /* Make sure there's a VPB */
801 if (!FileSystemDeviceObject
->Vpb
) return STATUS_INVALID_PARAMETER
;
804 IoAcquireVpbSpinLock(&OldIrql
);
806 /* Get the Device Extension */
807 DeviceExtension
= (PEXTENDED_DEVOBJ_EXTENSION
)FileSystemDeviceObject
->DeviceObjectExtension
;
809 /* Make sure this one has a VPB too */
810 Vpb
= DeviceExtension
->Vpb
;
811 if (!Vpb
) return STATUS_INVALID_PARAMETER
;
813 /* Make sure someone it's mounted */
814 if ((!Vpb
->ReferenceCount
) || (Vpb
->Flags
& VPB_MOUNTED
)) return STATUS_VOLUME_DISMOUNTED
;
816 /* Return the Disk Device Object */
817 *DiskDeviceObject
= Vpb
->RealDevice
;
819 /* Release the lock */
820 IoReleaseVpbSpinLock(OldIrql
);
821 return STATUS_SUCCESS
;
829 IoGetLowerDeviceObject(IN PDEVICE_OBJECT DeviceObject
)
831 PEXTENDED_DEVOBJ_EXTENSION DeviceExtension
= (PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
;
832 PDEVICE_OBJECT LowerDeviceObject
= NULL
;
834 /* Make sure it's not getting deleted */
835 if (DeviceExtension
->ExtensionFlags
& (DOE_UNLOAD_PENDING
|
838 DOE_REMOVE_PROCESSED
))
840 /* Get the Lower Device Object */
841 LowerDeviceObject
= DeviceExtension
->AttachedTo
;
844 ObReferenceObject(LowerDeviceObject
);
848 return LowerDeviceObject
;
852 * IoGetRelatedDeviceObject
855 * See "Windows NT File System Internals", page 633 - 634.
862 IoGetRelatedDeviceObject(IN PFILE_OBJECT FileObject
)
864 PDEVICE_OBJECT DeviceObject
= FileObject
->DeviceObject
;
866 /* Get logical volume mounted on a physical/virtual/logical device */
867 if (FileObject
->Vpb
&& FileObject
->Vpb
->DeviceObject
)
869 DeviceObject
= FileObject
->Vpb
->DeviceObject
;
873 * Check if file object has an associated device object mounted by some
876 if (FileObject
->DeviceObject
->Vpb
&&
877 FileObject
->DeviceObject
->Vpb
->DeviceObject
)
879 DeviceObject
= FileObject
->DeviceObject
->Vpb
->DeviceObject
;
882 /* Return the highest attached device */
883 return IoGetAttachedDevice(DeviceObject
);
891 IoRegisterLastChanceShutdownNotification(IN PDEVICE_OBJECT DeviceObject
)
894 return STATUS_NOT_IMPLEMENTED
;
902 IoRegisterShutdownNotification(PDEVICE_OBJECT DeviceObject
)
904 PSHUTDOWN_ENTRY Entry
;
906 Entry
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(SHUTDOWN_ENTRY
),
909 return STATUS_INSUFFICIENT_RESOURCES
;
911 Entry
->DeviceObject
= DeviceObject
;
913 ExInterlockedInsertHeadList(&ShutdownListHead
,
914 &Entry
->ShutdownList
,
917 DeviceObject
->Flags
|= DO_SHUTDOWN_REGISTERED
;
919 return STATUS_SUCCESS
;
927 IoSetStartIoAttributes(IN PDEVICE_OBJECT DeviceObject
,
928 IN BOOLEAN DeferredStartIo
,
929 IN BOOLEAN NonCancelable
)
937 * FUNCTION: Dequeues the next packet from the given device object's
938 * associated device queue according to a specified sort-key value and calls
939 * the drivers StartIo routine with that IRP
941 * DeviceObject = Device object for which the irp is to dequeued
942 * Cancelable = True if IRPs in the key can be canceled
943 * Key = Sort key specifing which entry to remove from the queue
947 IoStartNextPacketByKey(PDEVICE_OBJECT DeviceObject
,
951 PKDEVICE_QUEUE_ENTRY entry
;
954 entry
= KeRemoveByKeyDeviceQueue(&DeviceObject
->DeviceQueue
,
959 Irp
= CONTAINING_RECORD(entry
,
961 Tail
.Overlay
.DeviceQueueEntry
);
962 DeviceObject
->CurrentIrp
= Irp
;
963 DPRINT("Next irp is 0x%p\n", Irp
);
964 DeviceObject
->DriverObject
->DriverStartIo(DeviceObject
, Irp
);
968 DPRINT("No next irp\n");
969 DeviceObject
->CurrentIrp
= NULL
;
976 * FUNCTION: Removes the next packet from the device's queue and calls
977 * the driver's StartIO
979 * DeviceObject = Device
980 * Cancelable = True if irps in the queue can be canceled
984 IoStartNextPacket(PDEVICE_OBJECT DeviceObject
,
987 PKDEVICE_QUEUE_ENTRY entry
;
990 DPRINT("IoStartNextPacket(DeviceObject 0x%p, Cancelable %d)\n",
991 DeviceObject
, Cancelable
);
993 entry
= KeRemoveDeviceQueue(&DeviceObject
->DeviceQueue
);
997 Irp
= CONTAINING_RECORD(entry
,IRP
,Tail
.Overlay
.DeviceQueueEntry
);
998 DeviceObject
->CurrentIrp
= Irp
;
999 DeviceObject
->DriverObject
->DriverStartIo(DeviceObject
,Irp
);
1003 DeviceObject
->CurrentIrp
= NULL
;
1010 * FUNCTION: Either call the device's StartIO routine with the packet or,
1011 * if the device is busy, queue it.
1013 * DeviceObject = Device to start the packet on
1014 * Irp = Irp to queue
1015 * Key = Where to insert the irp
1016 * If zero then insert in the tail of the queue
1017 * CancelFunction = Optional function to cancel the irqp
1021 IoStartPacket(PDEVICE_OBJECT DeviceObject
,
1024 PDRIVER_CANCEL CancelFunction
)
1029 DPRINT("IoStartPacket(Irp 0x%p)\n", Irp
);
1031 ASSERT_IRQL(DISPATCH_LEVEL
);
1033 IoAcquireCancelSpinLock(&oldirql
);
1035 if (CancelFunction
!= NULL
)
1037 Irp
->CancelRoutine
= CancelFunction
;
1042 stat
= KeInsertByKeyDeviceQueue(&DeviceObject
->DeviceQueue
,
1043 &Irp
->Tail
.Overlay
.DeviceQueueEntry
,
1048 stat
= KeInsertDeviceQueue(&DeviceObject
->DeviceQueue
,
1049 &Irp
->Tail
.Overlay
.DeviceQueueEntry
);
1055 IoReleaseCancelSpinLock(DISPATCH_LEVEL
);
1056 DeviceObject
->CurrentIrp
= Irp
;
1057 DeviceObject
->DriverObject
->DriverStartIo(DeviceObject
,Irp
);
1058 if (oldirql
< DISPATCH_LEVEL
)
1060 KeLowerIrql(oldirql
);
1065 IoReleaseCancelSpinLock(oldirql
);
1075 IoSynchronousInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject
,
1076 IN DEVICE_RELATION_TYPE Type
)
1086 IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject
)
1088 PSHUTDOWN_ENTRY ShutdownEntry
, tmp
;
1091 LIST_FOR_EACH_SAFE(ShutdownEntry
, tmp
, &ShutdownListHead
, SHUTDOWN_ENTRY
, ShutdownList
)
1094 if (ShutdownEntry
->DeviceObject
== DeviceObject
)
1096 DeviceObject
->Flags
&= ~DO_SHUTDOWN_REGISTERED
;
1098 KeAcquireSpinLock(&ShutdownListLock
,&oldlvl
);
1099 RemoveEntryList(&ShutdownEntry
->ShutdownList
);
1100 KeReleaseSpinLock(&ShutdownListLock
,oldlvl
);
1102 ExFreePool(ShutdownEntry
);
1114 IoValidateDeviceIoControlAccess(IN PIRP Irp
,
1115 IN ULONG RequiredAccess
)
1118 return STATUS_NOT_IMPLEMENTED
;