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 #define TAG_DEVICE_EXTENSION TAG('D', 'E', 'X', 'T')
20 #define TAG_SHUTDOWN_ENTRY TAG('S', 'H', 'U', 'T')
21 #define TAG_IO_TIMER TAG('I', 'O', 'T', 'M')
23 static ULONG IopDeviceObjectNumber
= 0;
25 typedef struct _SHUTDOWN_ENTRY
27 LIST_ENTRY ShutdownList
;
28 PDEVICE_OBJECT DeviceObject
;
29 } SHUTDOWN_ENTRY
, *PSHUTDOWN_ENTRY
;
31 LIST_ENTRY ShutdownListHead
;
32 KSPIN_LOCK ShutdownListLock
;
34 /* PRIVATE FUNCTIONS **********************************************************/
37 IoShutdownRegisteredDevices(VOID
)
39 PSHUTDOWN_ENTRY ShutdownEntry
;
41 IO_STATUS_BLOCK StatusBlock
;
46 Entry
= ShutdownListHead
.Flink
;
47 while (Entry
!= &ShutdownListHead
)
49 ShutdownEntry
= CONTAINING_RECORD(Entry
, SHUTDOWN_ENTRY
, ShutdownList
);
51 KeInitializeEvent (&Event
,
55 Irp
= IoBuildSynchronousFsdRequest (IRP_MJ_SHUTDOWN
,
56 ShutdownEntry
->DeviceObject
,
63 Status
= IoCallDriver (ShutdownEntry
->DeviceObject
,
65 if (Status
== STATUS_PENDING
)
67 KeWaitForSingleObject (&Event
,
80 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
81 PDRIVER_OBJECT DriverObject
)
83 IO_STATUS_BLOCK IoStatusBlock
;
84 IO_STACK_LOCATION Stack
;
88 if (DriverObject
->DriverExtension
->AddDevice
)
90 /* This is a Plug and Play driver */
91 DPRINT("Plug and Play driver found\n");
93 ASSERT(DeviceNode
->PhysicalDeviceObject
);
95 DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
96 DriverObject
->DriverExtension
->AddDevice
);
98 Status
= DriverObject
->DriverExtension
->AddDevice(
99 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
101 if (!NT_SUCCESS(Status
))
106 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
108 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
110 /* FIXME: What do we do? Unload the driver or just disable the device? */
111 DbgPrint("An FDO was not attached\n");
112 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
113 return STATUS_UNSUCCESSFUL
;
116 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
118 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
120 /* FIXME: Should be DeviceNode->ResourceList */
121 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->BootResources
;
122 /* FIXME: Should be DeviceNode->ResourceListTranslated */
123 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->BootResources
;
125 Status
= IopInitiatePnpIrp(
131 if (!NT_SUCCESS(Status
))
133 DPRINT("IopInitiatePnpIrp() failed\n");
134 ObDereferenceObject(Fdo
);
138 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
140 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
142 /* There can be only one system power device */
143 if (!SystemPowerDeviceNodeCreated
)
145 PopSystemPowerDeviceNode
= DeviceNode
;
146 SystemPowerDeviceNodeCreated
= TRUE
;
150 if (Fdo
->DeviceType
== FILE_DEVICE_BUS_EXTENDER
||
151 Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
153 DPRINT("Bus extender found\n");
155 Status
= IopInvalidateDeviceRelations(DeviceNode
, BusRelations
);
156 if (!NT_SUCCESS(Status
))
158 ObDereferenceObject(Fdo
);
163 ObDereferenceObject(Fdo
);
166 return STATUS_SUCCESS
;
171 IopGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName
,
172 IN ACCESS_MASK DesiredAccess
,
173 OUT PFILE_OBJECT
*FileObject
,
174 OUT PDEVICE_OBJECT
*DeviceObject
,
177 OBJECT_ATTRIBUTES ObjectAttributes
;
178 IO_STATUS_BLOCK StatusBlock
;
179 PFILE_OBJECT LocalFileObject
;
183 DPRINT("IoGetDeviceObjectPointer(ObjectName %wZ, DesiredAccess %x,"
184 "FileObject %p DeviceObject %p)\n",
185 ObjectName
, DesiredAccess
, FileObject
, DeviceObject
);
187 /* Open the Device */
188 InitializeObjectAttributes(&ObjectAttributes
,
193 Status
= ZwOpenFile(&FileHandle
,
198 FILE_NON_DIRECTORY_FILE
| AttachFlag
);
200 if (!NT_SUCCESS(Status
))
202 DPRINT1("NtOpenFile failed, Status: 0x%x\n", Status
);
206 /* Get File Object */
207 Status
= ObReferenceObjectByHandle(FileHandle
,
211 (PVOID
*)&LocalFileObject
,
213 if (NT_SUCCESS(Status
))
215 /* Return the requested data */
216 *DeviceObject
= IoGetRelatedDeviceObject(LocalFileObject
);
217 *FileObject
= LocalFileObject
;
220 /* Close the handle */
225 /* PUBLIC FUNCTIONS ***********************************************************/
230 * Layers a device over the highest device in a device stack.
234 * Device to be attached.
237 * Name of the target device.
240 * Caller storage for the device attached to.
247 IoAttachDevice(PDEVICE_OBJECT SourceDevice
,
248 PUNICODE_STRING TargetDeviceName
,
249 PDEVICE_OBJECT
*AttachedDevice
)
252 PFILE_OBJECT FileObject
;
253 PDEVICE_OBJECT TargetDevice
;
255 /* Call the helper routine for an attach operation */
256 DPRINT("IoAttachDevice\n");
257 Status
= IopGetDeviceObjectPointer(TargetDeviceName
,
258 FILE_READ_ATTRIBUTES
,
261 IO_ATTACH_DEVICE_API
);
263 if (!NT_SUCCESS(Status
))
265 DPRINT1("Failed to get Device Object\n");
269 /* Attach the device */
270 IoAttachDeviceToDeviceStackSafe(SourceDevice
, TargetDevice
, AttachedDevice
);
273 ObDereferenceObject(FileObject
);
274 return STATUS_SUCCESS
;
278 * IoAttachDeviceByPointer
285 IoAttachDeviceByPointer(IN PDEVICE_OBJECT SourceDevice
,
286 IN PDEVICE_OBJECT TargetDevice
)
288 PDEVICE_OBJECT AttachedDevice
;
289 NTSTATUS Status
= STATUS_SUCCESS
;
291 DPRINT("IoAttachDeviceByPointer(SourceDevice %x, TargetDevice %x)\n",
292 SourceDevice
, TargetDevice
);
295 AttachedDevice
= IoAttachDeviceToDeviceStack(SourceDevice
, TargetDevice
);
296 if (AttachedDevice
== NULL
) Status
= STATUS_NO_SUCH_DEVICE
;
298 /* Return the status */
303 * IoAttachDeviceToDeviceStack
310 IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice
,
311 PDEVICE_OBJECT TargetDevice
)
314 PDEVICE_OBJECT LocalAttach
;
316 /* Attach it safely */
317 DPRINT("IoAttachDeviceToDeviceStack\n");
318 Status
= IoAttachDeviceToDeviceStackSafe(SourceDevice
,
323 DPRINT("IoAttachDeviceToDeviceStack DONE: %x\n", LocalAttach
);
332 IoAttachDeviceToDeviceStackSafe(IN PDEVICE_OBJECT SourceDevice
,
333 IN PDEVICE_OBJECT TargetDevice
,
334 OUT PDEVICE_OBJECT
*AttachedToDeviceObject
)
336 PDEVICE_OBJECT AttachedDevice
;
337 PDEVOBJ_EXTENSION SourceDeviceExtension
;
339 DPRINT("IoAttachDeviceToDeviceStack(SourceDevice %x, TargetDevice %x)\n",
340 SourceDevice
, TargetDevice
);
342 /* Get the Attached Device and source extension */
343 AttachedDevice
= IoGetAttachedDevice(TargetDevice
);
344 SourceDeviceExtension
= SourceDevice
->DeviceObjectExtension
;
346 /* Make sure that it's in a correct state */
347 if (!(AttachedDevice
->DeviceObjectExtension
->ExtensionFlags
&
348 (DOE_UNLOAD_PENDING
| DOE_DELETE_PENDING
|
349 DOE_REMOVE_PENDING
| DOE_REMOVE_PROCESSED
)))
352 AttachedDevice
->AttachedDevice
= SourceDevice
;
353 SourceDevice
->AttachedDevice
= NULL
;
354 SourceDevice
->StackSize
= AttachedDevice
->StackSize
+ 1;
355 SourceDevice
->AlignmentRequirement
= AttachedDevice
->AlignmentRequirement
;
356 SourceDevice
->SectorSize
= AttachedDevice
->SectorSize
;
357 SourceDevice
->Vpb
= AttachedDevice
->Vpb
;
359 /* Set the attachment in the device extension */
360 SourceDeviceExtension
->AttachedTo
= AttachedDevice
;
364 /* Device was unloading or being removed */
365 AttachedDevice
= NULL
;
368 /* Return the attached device */
369 *AttachedToDeviceObject
= AttachedDevice
;
370 return STATUS_SUCCESS
;
376 * Allocates memory for and intializes a device object for use for
381 * Driver object passed by IO Manager when the driver was loaded.
383 * DeviceExtensionSize
384 * Number of bytes for the device extension.
387 * Unicode name of device.
390 * Device type of the new device.
392 * DeviceCharacteristics
393 * Bit mask of device characteristics.
396 * TRUE if only one thread can access the device at a time.
399 * On successful return this parameter is filled by pointer to
400 * allocated device object.
407 IoCreateDevice(PDRIVER_OBJECT DriverObject
,
408 ULONG DeviceExtensionSize
,
409 PUNICODE_STRING DeviceName
,
410 DEVICE_TYPE DeviceType
,
411 ULONG DeviceCharacteristics
,
413 PDEVICE_OBJECT
*DeviceObject
)
415 WCHAR AutoNameBuffer
[20];
416 UNICODE_STRING AutoName
;
417 PDEVICE_OBJECT CreatedDeviceObject
;
418 PDEVOBJ_EXTENSION DeviceObjectExtension
;
419 OBJECT_ATTRIBUTES ObjectAttributes
;
421 ULONG AlignedDeviceExtensionSize
;
425 ASSERT_IRQL(PASSIVE_LEVEL
);
426 DPRINT("IoCreateDevice(DriverObject %x)\n",DriverObject
);
428 /* Generate a name if we have to */
429 if (DeviceCharacteristics
& FILE_AUTOGENERATED_DEVICE_NAME
)
431 swprintf(AutoNameBuffer
,
433 InterlockedIncrementUL(&IopDeviceObjectNumber
));
434 RtlInitUnicodeString(&AutoName
, AutoNameBuffer
);
435 DeviceName
= &AutoName
;
438 /* Initialize the Object Attributes */
439 InitializeObjectAttributes(&ObjectAttributes
, DeviceName
, 0, NULL
, NULL
);
441 /* Honor exclusive flag */
442 ObjectAttributes
.Attributes
|= OBJ_EXCLUSIVE
;
444 /* Create a permanent object for named devices */
445 if (DeviceName
!= NULL
)
447 ObjectAttributes
.Attributes
|= OBJ_PERMANENT
;
450 /* Align the Extension Size to 8-bytes */
451 AlignedDeviceExtensionSize
= (DeviceExtensionSize
+ 7) &~ 7;
452 DPRINT("AlignedDeviceExtensionSize %x\n", AlignedDeviceExtensionSize
);
455 TotalSize
= AlignedDeviceExtensionSize
+
456 sizeof(DEVICE_OBJECT
) + sizeof(DEVOBJ_EXTENSION
);
457 DPRINT("TotalSize %x\n", TotalSize
);
459 /* Create the Device Object */
460 Status
= ObCreateObject(KernelMode
,
468 (PVOID
*)&CreatedDeviceObject
);
470 if (!NT_SUCCESS(Status
))
472 DPRINT1("IoCreateDevice() ObCreateObject failed, status: 0x%08X\n", Status
);
476 /* Clear the whole Object and extension so we don't null stuff manually */
477 RtlZeroMemory(CreatedDeviceObject
, TotalSize
);
478 DPRINT("CreatedDeviceObject %x\n", CreatedDeviceObject
);
481 * Setup the Type and Size. Note that we don't use the aligned size,
482 * because that's only padding for the DevObjExt and not part of the Object.
484 CreatedDeviceObject
->Type
= IO_TYPE_DEVICE
;
485 CreatedDeviceObject
->Size
= sizeof(DEVICE_OBJECT
) + DeviceExtensionSize
;
487 /* The kernel extension is after the driver internal extension */
488 DeviceObjectExtension
= (PDEVOBJ_EXTENSION
)
489 ((ULONG_PTR
)(CreatedDeviceObject
+ 1) +
490 AlignedDeviceExtensionSize
);
492 /* Set the Type and Size. Question: why is Size 0 on Windows? */
493 DPRINT("DeviceObjectExtension %x\n", DeviceObjectExtension
);
494 DeviceObjectExtension
->Type
= IO_TYPE_DEVICE_OBJECT_EXTENSION
;
495 DeviceObjectExtension
->Size
= 0;
497 /* Link the Object and Extension */
498 DeviceObjectExtension
->DeviceObject
= CreatedDeviceObject
;
499 CreatedDeviceObject
->DeviceObjectExtension
= DeviceObjectExtension
;
501 /* Set Device Object Data */
502 CreatedDeviceObject
->DeviceType
= DeviceType
;
503 CreatedDeviceObject
->Characteristics
= DeviceCharacteristics
;
504 CreatedDeviceObject
->DeviceExtension
= CreatedDeviceObject
+ 1;
505 CreatedDeviceObject
->StackSize
= 1;
506 CreatedDeviceObject
->AlignmentRequirement
= 1; /* FIXME */
509 /* FIXME: After the Driver is Loaded, the flag below should be removed */
510 CreatedDeviceObject
->Flags
= DO_DEVICE_INITIALIZING
;
511 if (Exclusive
) CreatedDeviceObject
->Flags
|= DO_EXCLUSIVE
;
512 if (DeviceName
) CreatedDeviceObject
->Flags
|= DO_DEVICE_HAS_NAME
;
514 /* Attach a Vpb for Disks and Tapes, and create the Device Lock */
515 if (CreatedDeviceObject
->DeviceType
== FILE_DEVICE_DISK
||
516 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_VIRTUAL_DISK
||
517 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_CD_ROM
||
518 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_TAPE
)
521 IopAttachVpb(CreatedDeviceObject
);
523 /* Initialize Lock Event */
524 KeInitializeEvent(&CreatedDeviceObject
->DeviceLock
,
525 SynchronizationEvent
,
529 /* Set the right Sector Size */
532 case FILE_DEVICE_DISK_FILE_SYSTEM
:
533 case FILE_DEVICE_DISK
:
534 case FILE_DEVICE_VIRTUAL_DISK
:
535 CreatedDeviceObject
->SectorSize
= 512;
538 case FILE_DEVICE_CD_ROM_FILE_SYSTEM
:
539 CreatedDeviceObject
->SectorSize
= 2048;
543 /* Create the Device Queue */
544 KeInitializeDeviceQueue(&CreatedDeviceObject
->DeviceQueue
);
546 /* Insert the Object */
547 Status
= ObInsertObject(CreatedDeviceObject
,
549 FILE_READ_DATA
| FILE_WRITE_DATA
,
554 if (!NT_SUCCESS(Status
))
556 DPRINT1("Cannot insert Device Object into Handle Table\n");
557 *DeviceObject
= NULL
;
561 /* Now do the final linking */
562 ObReferenceObject(DriverObject
);
563 CreatedDeviceObject
->DriverObject
= DriverObject
;
564 CreatedDeviceObject
->NextDevice
= DriverObject
->DeviceObject
;
565 DriverObject
->DeviceObject
= CreatedDeviceObject
;
569 /* Return to caller */
570 *DeviceObject
= CreatedDeviceObject
;
571 return STATUS_SUCCESS
;
582 IoDeleteDevice(PDEVICE_OBJECT DeviceObject
)
584 PDEVICE_OBJECT Previous
;
586 if (DeviceObject
->Flags
& DO_SHUTDOWN_REGISTERED
)
587 IoUnregisterShutdownNotification(DeviceObject
);
589 /* Remove the timer if it exists */
590 if (DeviceObject
->Timer
)
592 IopRemoveTimerFromTimerList(DeviceObject
->Timer
);
593 ExFreePoolWithTag(DeviceObject
->Timer
, TAG_IO_TIMER
);
596 /* Remove device from driver device list */
597 Previous
= DeviceObject
->DriverObject
->DeviceObject
;
598 if (Previous
== DeviceObject
)
600 DeviceObject
->DriverObject
->DeviceObject
= DeviceObject
->NextDevice
;
604 while (Previous
->NextDevice
!= DeviceObject
)
605 Previous
= Previous
->NextDevice
;
606 Previous
->NextDevice
= DeviceObject
->NextDevice
;
609 /* I guess this should be removed later... but it shouldn't cause problems */
610 DeviceObject
->DeviceObjectExtension
->ExtensionFlags
|= DOE_DELETE_PENDING
;
612 /* Make the object temporary. This should automatically remove the device
613 from the namespace */
614 ObMakeTemporaryObject(DeviceObject
);
616 /* Dereference the driver object */
617 ObDereferenceObject(DeviceObject
->DriverObject
);
619 /* Remove the keep-alive reference */
620 ObDereferenceObject(DeviceObject
);
631 IoDetachDevice(PDEVICE_OBJECT TargetDevice
)
633 DPRINT("IoDetachDevice(TargetDevice %x)\n", TargetDevice
);
635 /* Remove the attachment */
636 TargetDevice
->AttachedDevice
->DeviceObjectExtension
->AttachedTo
= NULL
;
637 TargetDevice
->AttachedDevice
= NULL
;
645 IoEnumerateDeviceObjectList(IN PDRIVER_OBJECT DriverObject
,
646 IN PDEVICE_OBJECT
*DeviceObjectList
,
647 IN ULONG DeviceObjectListSize
,
648 OUT PULONG ActualNumberDeviceObjects
)
650 ULONG ActualDevices
= 1;
651 PDEVICE_OBJECT CurrentDevice
= DriverObject
->DeviceObject
;
653 DPRINT1("IoEnumerateDeviceObjectList\n");
655 /* Find out how many devices we'll enumerate */
656 while ((CurrentDevice
= CurrentDevice
->NextDevice
))
661 /* Go back to the first */
662 CurrentDevice
= DriverObject
->DeviceObject
;
664 /* Start by at least returning this */
665 *ActualNumberDeviceObjects
= ActualDevices
;
667 /* Check if we can support so many */
668 if ((ActualDevices
* 4) > DeviceObjectListSize
)
670 /* Fail because the buffer was too small */
671 return STATUS_BUFFER_TOO_SMALL
;
674 /* Check if the caller only wanted the size */
675 if (DeviceObjectList
)
677 /* Loop through all the devices */
678 while (ActualDevices
)
680 /* Reference each Device */
681 ObReferenceObject(CurrentDevice
);
683 /* Add it to the list */
684 *DeviceObjectList
= CurrentDevice
;
686 /* Go to the next one */
687 CurrentDevice
= CurrentDevice
->NextDevice
;
693 /* Return the status */
694 return STATUS_SUCCESS
;
698 * IoGetAttachedDevice
705 IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject
)
707 PDEVICE_OBJECT Current
= DeviceObject
;
709 /* Get the last attached device */
710 while (Current
->AttachedDevice
)
712 Current
= Current
->AttachedDevice
;
720 * IoGetAttachedDeviceReference
727 IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject
)
729 PDEVICE_OBJECT Current
= IoGetAttachedDevice(DeviceObject
);
731 /* Reference the ATtached Device */
732 ObReferenceObject(Current
);
741 IoGetDeviceAttachmentBaseRef(IN PDEVICE_OBJECT DeviceObject
)
743 /* Return the attached Device */
744 return (DeviceObject
->DeviceObjectExtension
->AttachedTo
);
748 * IoGetDeviceObjectPointer
755 IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName
,
756 IN ACCESS_MASK DesiredAccess
,
757 OUT PFILE_OBJECT
*FileObject
,
758 OUT PDEVICE_OBJECT
*DeviceObject
)
760 /* Call the helper routine for a normal operation */
761 return IopGetDeviceObjectPointer(ObjectName
,
773 IoGetDiskDeviceObject(IN PDEVICE_OBJECT FileSystemDeviceObject
,
774 OUT PDEVICE_OBJECT
*DiskDeviceObject
)
776 PDEVOBJ_EXTENSION DeviceExtension
;
780 /* Make sure there's a VPB */
781 if (!FileSystemDeviceObject
->Vpb
) return STATUS_INVALID_PARAMETER
;
784 IoAcquireVpbSpinLock(&OldIrql
);
786 /* Get the Device Extension */
787 DeviceExtension
= FileSystemDeviceObject
->DeviceObjectExtension
;
789 /* Make sure this one has a VPB too */
790 Vpb
= DeviceExtension
->Vpb
;
791 if (!Vpb
) return STATUS_INVALID_PARAMETER
;
793 /* Make sure someone it's mounted */
794 if ((!Vpb
->ReferenceCount
) || (Vpb
->Flags
& VPB_MOUNTED
)) return STATUS_VOLUME_DISMOUNTED
;
796 /* Return the Disk Device Object */
797 *DiskDeviceObject
= Vpb
->RealDevice
;
799 /* Release the lock */
800 IoReleaseVpbSpinLock(OldIrql
);
801 return STATUS_SUCCESS
;
809 IoGetLowerDeviceObject(IN PDEVICE_OBJECT DeviceObject
)
811 PDEVOBJ_EXTENSION DeviceExtension
= DeviceObject
->DeviceObjectExtension
;
812 PDEVICE_OBJECT LowerDeviceObject
= NULL
;
814 /* Make sure it's not getting deleted */
815 if (DeviceExtension
->ExtensionFlags
& (DOE_UNLOAD_PENDING
|
818 DOE_REMOVE_PROCESSED
))
820 /* Get the Lower Device Object */
821 LowerDeviceObject
= DeviceExtension
->AttachedTo
;
824 ObReferenceObject(LowerDeviceObject
);
828 return LowerDeviceObject
;
832 * IoGetRelatedDeviceObject
835 * See "Windows NT File System Internals", page 633 - 634.
842 IoGetRelatedDeviceObject(IN PFILE_OBJECT FileObject
)
844 PDEVICE_OBJECT DeviceObject
= FileObject
->DeviceObject
;
846 /* Get logical volume mounted on a physical/virtual/logical device */
847 if (FileObject
->Vpb
&& FileObject
->Vpb
->DeviceObject
)
849 DeviceObject
= FileObject
->Vpb
->DeviceObject
;
853 * Check if file object has an associated device object mounted by some
856 if (FileObject
->DeviceObject
->Vpb
&&
857 FileObject
->DeviceObject
->Vpb
->DeviceObject
)
859 DeviceObject
= FileObject
->DeviceObject
->Vpb
->DeviceObject
;
862 /* Return the highest attached device */
863 return IoGetAttachedDevice(DeviceObject
);
871 IoRegisterLastChanceShutdownNotification(IN PDEVICE_OBJECT DeviceObject
)
874 return STATUS_NOT_IMPLEMENTED
;
882 IoRegisterShutdownNotification(PDEVICE_OBJECT DeviceObject
)
884 PSHUTDOWN_ENTRY Entry
;
886 Entry
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(SHUTDOWN_ENTRY
),
889 return STATUS_INSUFFICIENT_RESOURCES
;
891 Entry
->DeviceObject
= DeviceObject
;
893 ExInterlockedInsertHeadList(&ShutdownListHead
,
894 &Entry
->ShutdownList
,
897 DeviceObject
->Flags
|= DO_SHUTDOWN_REGISTERED
;
899 return STATUS_SUCCESS
;
907 IoSetStartIoAttributes(IN PDEVICE_OBJECT DeviceObject
,
908 IN BOOLEAN DeferredStartIo
,
909 IN BOOLEAN NonCancelable
)
917 * FUNCTION: Dequeues the next packet from the given device object's
918 * associated device queue according to a specified sort-key value and calls
919 * the drivers StartIo routine with that IRP
921 * DeviceObject = Device object for which the irp is to dequeued
922 * Cancelable = True if IRPs in the key can be canceled
923 * Key = Sort key specifing which entry to remove from the queue
927 IoStartNextPacketByKey(PDEVICE_OBJECT DeviceObject
,
931 PKDEVICE_QUEUE_ENTRY entry
;
934 entry
= KeRemoveByKeyDeviceQueue(&DeviceObject
->DeviceQueue
,
939 Irp
= CONTAINING_RECORD(entry
,
941 Tail
.Overlay
.DeviceQueueEntry
);
942 DeviceObject
->CurrentIrp
= Irp
;
943 DPRINT("Next irp is %x\n", Irp
);
944 DeviceObject
->DriverObject
->DriverStartIo(DeviceObject
, Irp
);
948 DPRINT("No next irp\n");
949 DeviceObject
->CurrentIrp
= NULL
;
956 * FUNCTION: Removes the next packet from the device's queue and calls
957 * the driver's StartIO
959 * DeviceObject = Device
960 * Cancelable = True if irps in the queue can be canceled
964 IoStartNextPacket(PDEVICE_OBJECT DeviceObject
,
967 PKDEVICE_QUEUE_ENTRY entry
;
970 DPRINT("IoStartNextPacket(DeviceObject %x, Cancelable %d)\n",
971 DeviceObject
,Cancelable
);
973 entry
= KeRemoveDeviceQueue(&DeviceObject
->DeviceQueue
);
977 Irp
= CONTAINING_RECORD(entry
,IRP
,Tail
.Overlay
.DeviceQueueEntry
);
978 DeviceObject
->CurrentIrp
= Irp
;
979 DeviceObject
->DriverObject
->DriverStartIo(DeviceObject
,Irp
);
983 DeviceObject
->CurrentIrp
= NULL
;
990 * FUNCTION: Either call the device's StartIO routine with the packet or,
991 * if the device is busy, queue it.
993 * DeviceObject = Device to start the packet on
995 * Key = Where to insert the irp
996 * If zero then insert in the tail of the queue
997 * CancelFunction = Optional function to cancel the irqp
1001 IoStartPacket(PDEVICE_OBJECT DeviceObject
,
1004 PDRIVER_CANCEL CancelFunction
)
1009 DPRINT("IoStartPacket(Irp %x)\n", Irp
);
1011 ASSERT_IRQL(DISPATCH_LEVEL
);
1013 IoAcquireCancelSpinLock(&oldirql
);
1015 if (CancelFunction
!= NULL
)
1017 Irp
->CancelRoutine
= CancelFunction
;
1022 stat
= KeInsertByKeyDeviceQueue(&DeviceObject
->DeviceQueue
,
1023 &Irp
->Tail
.Overlay
.DeviceQueueEntry
,
1028 stat
= KeInsertDeviceQueue(&DeviceObject
->DeviceQueue
,
1029 &Irp
->Tail
.Overlay
.DeviceQueueEntry
);
1035 IoReleaseCancelSpinLock(DISPATCH_LEVEL
);
1036 DeviceObject
->CurrentIrp
= Irp
;
1037 DeviceObject
->DriverObject
->DriverStartIo(DeviceObject
,Irp
);
1038 if (oldirql
< DISPATCH_LEVEL
)
1040 KeLowerIrql(oldirql
);
1045 IoReleaseCancelSpinLock(oldirql
);
1055 IoSynchronousInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject
,
1056 IN DEVICE_RELATION_TYPE Type
)
1066 IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject
)
1068 PSHUTDOWN_ENTRY ShutdownEntry
;
1072 Entry
= ShutdownListHead
.Flink
;
1073 while (Entry
!= &ShutdownListHead
)
1075 ShutdownEntry
= CONTAINING_RECORD(Entry
, SHUTDOWN_ENTRY
, ShutdownList
);
1076 if (ShutdownEntry
->DeviceObject
== DeviceObject
)
1078 DeviceObject
->Flags
&= ~DO_SHUTDOWN_REGISTERED
;
1080 KeAcquireSpinLock(&ShutdownListLock
,&oldlvl
);
1081 RemoveEntryList(Entry
);
1082 KeReleaseSpinLock(&ShutdownListLock
,oldlvl
);
1088 Entry
= Entry
->Flink
;
1097 IoValidateDeviceIoControlAccess(IN PIRP Irp
,
1098 IN ULONG RequiredAccess
)
1101 return STATUS_NOT_IMPLEMENTED
;
1108 NtDeviceIoControlFile (IN HANDLE DeviceHandle
,
1109 IN HANDLE Event OPTIONAL
,
1110 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL
,
1111 IN PVOID UserApcContext OPTIONAL
,
1112 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1113 IN ULONG IoControlCode
,
1114 IN PVOID InputBuffer
,
1115 IN ULONG InputBufferLength OPTIONAL
,
1116 OUT PVOID OutputBuffer
,
1117 IN ULONG OutputBufferLength OPTIONAL
)
1120 PFILE_OBJECT FileObject
;
1121 PDEVICE_OBJECT DeviceObject
;
1123 PIO_STACK_LOCATION StackPtr
;
1124 PKEVENT EventObject
;
1125 KPROCESSOR_MODE PreviousMode
;
1127 DPRINT("NtDeviceIoControlFile(DeviceHandle %x Event %x UserApcRoutine %x "
1128 "UserApcContext %x IoStatusBlock %x IoControlCode %x "
1129 "InputBuffer %x InputBufferLength %x OutputBuffer %x "
1130 "OutputBufferLength %x)\n",
1131 DeviceHandle
,Event
,UserApcRoutine
,UserApcContext
,IoStatusBlock
,
1132 IoControlCode
,InputBuffer
,InputBufferLength
,OutputBuffer
,
1133 OutputBufferLength
);
1135 if (IoStatusBlock
== NULL
)
1136 return STATUS_ACCESS_VIOLATION
;
1138 PreviousMode
= ExGetPreviousMode();
1140 /* Check granted access against the access rights from IoContolCode */
1141 Status
= ObReferenceObjectByHandle (DeviceHandle
,
1142 (IoControlCode
>> 14) & 0x3,
1145 (PVOID
*) &FileObject
,
1147 if (!NT_SUCCESS(Status
))
1154 Status
= ObReferenceObjectByHandle (Event
,
1158 (PVOID
*)&EventObject
,
1160 if (!NT_SUCCESS(Status
))
1162 ObDereferenceObject (FileObject
);
1168 EventObject
= &FileObject
->Event
;
1169 KeResetEvent (EventObject
);
1172 DeviceObject
= FileObject
->DeviceObject
;
1174 Irp
= IoBuildDeviceIoControlRequest (IoControlCode
,
1184 /* Trigger FileObject/Event dereferencing */
1185 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
1187 Irp
->RequestorMode
= PreviousMode
;
1188 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= UserApcRoutine
;
1189 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= UserApcContext
;
1191 StackPtr
= IoGetNextIrpStackLocation(Irp
);
1192 StackPtr
->FileObject
= FileObject
;
1193 StackPtr
->DeviceObject
= DeviceObject
;
1194 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= InputBufferLength
;
1195 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
= OutputBufferLength
;
1197 Status
= IoCallDriver(DeviceObject
,Irp
);
1198 if (Status
== STATUS_PENDING
&& (FileObject
->Flags
& FO_SYNCHRONOUS_IO
))
1200 Status
= KeWaitForSingleObject (EventObject
,
1203 FileObject
->Flags
& FO_ALERTABLE_IO
,
1205 if (Status
!= STATUS_WAIT_0
)
1211 Status
= IoStatusBlock
->Status
;