3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/device.c
6 * PURPOSE: Manage devices
7 * PROGRAMMER: David Welch (welch@cwcom.net)
12 /* INCLUDES *******************************************************************/
16 #include <internal/debug.h>
18 /* GLOBALS ********************************************************************/
20 #define TAG_DEVICE_EXTENSION TAG('D', 'E', 'X', 'T')
22 static ULONG IopDeviceObjectNumber
= 0;
24 /* PRIVATE FUNCTIONS **********************************************************/
28 PDEVICE_NODE DeviceNode
,
29 PDRIVER_OBJECT DriverObject
)
31 IO_STATUS_BLOCK IoStatusBlock
;
32 IO_STACK_LOCATION Stack
;
36 if (DriverObject
->DriverExtension
->AddDevice
)
38 /* This is a Plug and Play driver */
39 DPRINT("Plug and Play driver found\n");
41 ASSERT(DeviceNode
->PhysicalDeviceObject
);
43 DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
44 DriverObject
->DriverExtension
->AddDevice
);
46 Status
= DriverObject
->DriverExtension
->AddDevice(
47 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
49 if (!NT_SUCCESS(Status
))
54 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
56 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
58 /* FIXME: What do we do? Unload the driver or just disable the device? */
59 DbgPrint("An FDO was not attached\n");
60 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
61 return STATUS_UNSUCCESSFUL
;
64 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
66 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
68 /* FIXME: Should be DeviceNode->ResourceList */
69 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->BootResources
;
70 /* FIXME: Should be DeviceNode->ResourceListTranslated */
71 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->BootResources
;
73 Status
= IopInitiatePnpIrp(
79 if (!NT_SUCCESS(Status
))
81 DPRINT("IopInitiatePnpIrp() failed\n");
82 ObDereferenceObject(Fdo
);
87 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
89 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
91 /* There can be only one system power device */
92 if (!SystemPowerDeviceNodeCreated
)
94 PopSystemPowerDeviceNode
= DeviceNode
;
95 SystemPowerDeviceNodeCreated
= TRUE
;
100 if (Fdo
->DeviceType
== FILE_DEVICE_BUS_EXTENDER
||
101 Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
103 DPRINT("Bus extender found\n");
105 Status
= IopInvalidateDeviceRelations(DeviceNode
, BusRelations
);
106 if (!NT_SUCCESS(Status
))
108 ObDereferenceObject(Fdo
);
113 ObDereferenceObject(Fdo
);
116 return STATUS_SUCCESS
;
124 POBJECT_ATTRIBUTES ObjectAttributes
)
126 DPRINT("IopCreateDevice(ObjectBody %x, Parent %x, RemainingPath %S)\n",
127 ObjectBody
, Parent
, RemainingPath
);
129 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+ 1, '\\') != NULL
)
130 return STATUS_UNSUCCESSFUL
;
132 return STATUS_SUCCESS
;
135 /* PUBLIC FUNCTIONS ***********************************************************/
138 * IoAttachDeviceByPointer
145 IoAttachDeviceByPointer(
146 IN PDEVICE_OBJECT SourceDevice
,
147 IN PDEVICE_OBJECT TargetDevice
)
149 PDEVICE_OBJECT AttachedDevice
;
151 DPRINT("IoAttachDeviceByPointer(SourceDevice %x, TargetDevice %x)\n",
152 SourceDevice
, TargetDevice
);
154 AttachedDevice
= IoAttachDeviceToDeviceStack(SourceDevice
, TargetDevice
);
155 if (AttachedDevice
== NULL
)
156 return STATUS_NO_SUCH_DEVICE
;
158 return STATUS_SUCCESS
;
166 IoAttachDeviceToDeviceStackSafe(
167 IN PDEVICE_OBJECT SourceDevice
,
168 IN PDEVICE_OBJECT TargetDevice
,
169 OUT PDEVICE_OBJECT
*AttachedToDeviceObject
173 return STATUS_NOT_IMPLEMENTED
;
184 IoDeleteDevice(PDEVICE_OBJECT DeviceObject
)
186 PDEVICE_OBJECT Previous
;
188 if (DeviceObject
->Flags
& DO_SHUTDOWN_REGISTERED
)
189 IoUnregisterShutdownNotification(DeviceObject
);
191 /* Remove the timer if it exists */
192 if (DeviceObject
->Timer
)
194 IopRemoveTimerFromTimerList(DeviceObject
->Timer
);
195 ExFreePool(DeviceObject
->Timer
);
198 /* Free device extension */
199 if (DeviceObject
->DeviceObjectExtension
)
200 ExFreePool(DeviceObject
->DeviceObjectExtension
);
202 /* Remove device from driver device list */
203 Previous
= DeviceObject
->DriverObject
->DeviceObject
;
204 if (Previous
== DeviceObject
)
206 DeviceObject
->DriverObject
->DeviceObject
= DeviceObject
->NextDevice
;
210 while (Previous
->NextDevice
!= DeviceObject
)
211 Previous
= Previous
->NextDevice
;
212 Previous
->NextDevice
= DeviceObject
->NextDevice
;
215 ObDereferenceObject(DeviceObject
);
224 IoEnumerateDeviceObjectList(
225 IN PDRIVER_OBJECT DriverObject
,
226 IN PDEVICE_OBJECT
*DeviceObjectList
,
227 IN ULONG DeviceObjectListSize
,
228 OUT PULONG ActualNumberDeviceObjects
232 return STATUS_NOT_IMPLEMENTED
;
241 IoGetDeviceAttachmentBaseRef(
242 IN PDEVICE_OBJECT DeviceObject
254 IoGetDiskDeviceObject(
255 IN PDEVICE_OBJECT FileSystemDeviceObject
,
256 OUT PDEVICE_OBJECT
*DiskDeviceObject
260 return STATUS_NOT_IMPLEMENTED
;
268 IoGetLowerDeviceObject(
269 IN PDEVICE_OBJECT DeviceObject
277 * IoGetRelatedDeviceObject
280 * See "Windows NT File System Internals", page 633 - 634.
286 PDEVICE_OBJECT STDCALL
287 IoGetRelatedDeviceObject(
288 IN PFILE_OBJECT FileObject
)
291 * Get logical volume mounted on a physical/virtual/logical device
294 if (FileObject
->Vpb
&& FileObject
->Vpb
->DeviceObject
)
296 return IoGetAttachedDevice(FileObject
->Vpb
->DeviceObject
);
300 * Check if file object has an associated device object mounted by some
304 if (FileObject
->DeviceObject
->Vpb
&&
305 FileObject
->DeviceObject
->Vpb
->DeviceObject
)
307 return IoGetAttachedDevice(FileObject
->DeviceObject
->Vpb
->DeviceObject
);
310 return IoGetAttachedDevice(FileObject
->DeviceObject
);
314 * IoGetDeviceObjectPointer
321 IoGetDeviceObjectPointer(
322 IN PUNICODE_STRING ObjectName
,
323 IN ACCESS_MASK DesiredAccess
,
324 OUT PFILE_OBJECT
*FileObject
,
325 OUT PDEVICE_OBJECT
*DeviceObject
)
327 OBJECT_ATTRIBUTES ObjectAttributes
;
328 IO_STATUS_BLOCK StatusBlock
;
329 PFILE_OBJECT LocalFileObject
;
333 DPRINT("IoGetDeviceObjectPointer(ObjectName %wZ, DesiredAccess %x, FileObject %p DeviceObject %p)\n",
334 ObjectName
, DesiredAccess
, FileObject
, DeviceObject
);
336 InitializeObjectAttributes(
349 FILE_NON_DIRECTORY_FILE
);
351 if (!NT_SUCCESS(Status
))
354 Status
= ObReferenceObjectByHandle(
359 (PVOID
*)&LocalFileObject
,
362 if (NT_SUCCESS(Status
))
364 *DeviceObject
= IoGetRelatedDeviceObject(LocalFileObject
);
365 *FileObject
= LocalFileObject
;
381 IoDetachDevice(PDEVICE_OBJECT TargetDevice
)
383 DPRINT("IoDetachDevice(TargetDevice %x) - UNIMPLEMENTED\n", TargetDevice
);
387 * IoGetAttachedDevice
393 PDEVICE_OBJECT STDCALL
394 IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject
)
396 PDEVICE_OBJECT Current
= DeviceObject
;
398 while (Current
->AttachedDevice
!= NULL
)
399 Current
= Current
->AttachedDevice
;
405 * IoGetAttachedDeviceReference
411 PDEVICE_OBJECT STDCALL
412 IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject
)
414 PDEVICE_OBJECT Current
= IoGetAttachedDevice(DeviceObject
);
415 ObReferenceObject(Current
);
420 * IoAttachDeviceToDeviceStack
426 PDEVICE_OBJECT STDCALL
427 IoAttachDeviceToDeviceStack(
428 PDEVICE_OBJECT SourceDevice
,
429 PDEVICE_OBJECT TargetDevice
)
431 PDEVICE_OBJECT AttachedDevice
;
433 DPRINT("IoAttachDeviceToDeviceStack(SourceDevice %x, TargetDevice %x)\n",
434 SourceDevice
, TargetDevice
);
436 AttachedDevice
= IoGetAttachedDevice(TargetDevice
);
437 AttachedDevice
->AttachedDevice
= SourceDevice
;
438 SourceDevice
->AttachedDevice
= NULL
;
439 SourceDevice
->StackSize
= AttachedDevice
->StackSize
+ 1;
440 SourceDevice
->AlignmentRequirement
= AttachedDevice
->AlignmentRequirement
;
441 SourceDevice
->SectorSize
= AttachedDevice
->SectorSize
;
442 SourceDevice
->Vpb
= AttachedDevice
->Vpb
;
443 return AttachedDevice
;
449 * Layers a device over the highest device in a device stack.
453 * Device to be attached.
456 * Name of the target device.
459 * Caller storage for the device attached to.
467 PDEVICE_OBJECT SourceDevice
,
468 PUNICODE_STRING TargetDeviceName
,
469 PDEVICE_OBJECT
*AttachedDevice
)
472 PFILE_OBJECT FileObject
;
473 PDEVICE_OBJECT TargetDevice
;
475 Status
= IoGetDeviceObjectPointer(
477 FILE_READ_ATTRIBUTES
,
481 if (!NT_SUCCESS(Status
))
486 *AttachedDevice
= IoAttachDeviceToDeviceStack(
490 ObDereferenceObject(FileObject
);
492 return STATUS_SUCCESS
;
498 * Allocates memory for and intializes a device object for use for
503 * Driver object passed by IO Manager when the driver was loaded.
505 * DeviceExtensionSize
506 * Number of bytes for the device extension.
509 * Unicode name of device.
512 * Device type of the new device.
514 * DeviceCharacteristics
515 * Bit mask of device characteristics.
518 * TRUE if only one thread can access the device at a time.
521 * On successful return this parameter is filled by pointer to
522 * allocated device object.
530 PDRIVER_OBJECT DriverObject
,
531 ULONG DeviceExtensionSize
,
532 PUNICODE_STRING DeviceName
,
533 DEVICE_TYPE DeviceType
,
534 ULONG DeviceCharacteristics
,
536 PDEVICE_OBJECT
*DeviceObject
)
538 WCHAR AutoNameBuffer
[20];
539 UNICODE_STRING AutoName
;
540 PDEVICE_OBJECT CreatedDeviceObject
;
541 PDEVOBJ_EXTENSION DeviceObjectExtension
;
542 OBJECT_ATTRIBUTES ObjectAttributes
;
545 ASSERT_IRQL(PASSIVE_LEVEL
);
547 if (DeviceName
!= NULL
)
549 DPRINT("IoCreateDevice(DriverObject %x, DeviceName %S)\n",
550 DriverObject
, DeviceName
->Buffer
);
554 DPRINT("IoCreateDevice(DriverObject %x)\n",DriverObject
);
557 if (DeviceCharacteristics
& FILE_AUTOGENERATED_DEVICE_NAME
)
559 swprintf(AutoNameBuffer
,
561 InterlockedIncrementUL(&IopDeviceObjectNumber
));
562 RtlInitUnicodeString(&AutoName
,
564 DeviceName
= &AutoName
;
567 if (DeviceName
!= NULL
)
569 InitializeObjectAttributes(&ObjectAttributes
, DeviceName
, 0, NULL
, NULL
);
570 Status
= ObCreateObject(
576 sizeof(DEVICE_OBJECT
),
579 (PVOID
*)&CreatedDeviceObject
);
583 Status
= ObCreateObject(
589 sizeof(DEVICE_OBJECT
),
592 (PVOID
*)&CreatedDeviceObject
);
595 *DeviceObject
= NULL
;
597 if (!NT_SUCCESS(Status
))
599 DPRINT("IoCreateDevice() ObCreateObject failed, status: 0x%08X\n", Status
);
603 if (DriverObject
->DeviceObject
== NULL
)
605 DriverObject
->DeviceObject
= CreatedDeviceObject
;
606 CreatedDeviceObject
->NextDevice
= NULL
;
610 CreatedDeviceObject
->NextDevice
= DriverObject
->DeviceObject
;
611 DriverObject
->DeviceObject
= CreatedDeviceObject
;
614 CreatedDeviceObject
->Type
= DeviceType
;
615 CreatedDeviceObject
->DriverObject
= DriverObject
;
616 CreatedDeviceObject
->CurrentIrp
= NULL
;
617 CreatedDeviceObject
->Flags
= 0;
619 CreatedDeviceObject
->DeviceExtension
=
620 ExAllocatePoolWithTag(
623 TAG_DEVICE_EXTENSION
);
625 if (DeviceExtensionSize
> 0 && CreatedDeviceObject
->DeviceExtension
== NULL
)
627 ExFreePool(CreatedDeviceObject
);
628 DPRINT("IoCreateDevice() ExAllocatePoolWithTag failed, returning: 0x%08X\n", STATUS_INSUFFICIENT_RESOURCES
);
629 return STATUS_INSUFFICIENT_RESOURCES
;
632 if (DeviceExtensionSize
> 0)
634 RtlZeroMemory(CreatedDeviceObject
->DeviceExtension
, DeviceExtensionSize
);
637 CreatedDeviceObject
->Size
= sizeof(DEVICE_OBJECT
) + DeviceExtensionSize
;
638 CreatedDeviceObject
->ReferenceCount
= 1;
639 CreatedDeviceObject
->AttachedDevice
= NULL
;
640 CreatedDeviceObject
->DeviceType
= DeviceType
;
641 CreatedDeviceObject
->StackSize
= 1;
642 CreatedDeviceObject
->AlignmentRequirement
= 1;
643 CreatedDeviceObject
->Characteristics
= DeviceCharacteristics
;
644 CreatedDeviceObject
->Timer
= NULL
;
645 CreatedDeviceObject
->Vpb
= NULL
;
646 KeInitializeDeviceQueue(&CreatedDeviceObject
->DeviceQueue
);
649 &CreatedDeviceObject
->DeviceLock
,
650 SynchronizationEvent
,
653 /* FIXME: Do we need to add network drives too?! */
654 if (CreatedDeviceObject
->DeviceType
== FILE_DEVICE_DISK
||
655 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_CD_ROM
||
656 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_TAPE
)
658 IoAttachVpb(CreatedDeviceObject
);
660 CreatedDeviceObject
->SectorSize
= 512; /* FIXME */
662 DeviceObjectExtension
=
663 ExAllocatePoolWithTag(
665 sizeof(DEVOBJ_EXTENSION
),
666 TAG_DEVICE_EXTENSION
);
668 DeviceObjectExtension
->Type
= 0 /* ?? */;
669 DeviceObjectExtension
->Size
= sizeof(DEVOBJ_EXTENSION
);
670 DeviceObjectExtension
->DeviceObject
= CreatedDeviceObject
;
671 DeviceObjectExtension
->DeviceNode
= NULL
;
673 CreatedDeviceObject
->DeviceObjectExtension
= DeviceObjectExtension
;
675 *DeviceObject
= CreatedDeviceObject
;
677 return STATUS_SUCCESS
;
681 * IoOpenDeviceInstanceKey
688 IoOpenDeviceInstanceKey(
696 return STATUS_NOT_IMPLEMENTED
;
704 IoRegisterBootDriverReinitialization(
705 IN PDRIVER_OBJECT DriverObject
,
706 IN PDRIVER_REINITIALIZE DriverReinitializationRoutine
,
719 IoRegisterLastChanceShutdownNotification(
720 IN PDEVICE_OBJECT DeviceObject
724 return STATUS_NOT_IMPLEMENTED
;
728 * IoQueryDeviceEnumInfo
735 IoQueryDeviceEnumInfo(
748 IoSetStartIoAttributes(
749 IN PDEVICE_OBJECT DeviceObject
,
750 IN BOOLEAN DeferredStartIo
,
751 IN BOOLEAN NonCancelable
762 IoSynchronousInvalidateDeviceRelations(
763 IN PDEVICE_OBJECT DeviceObject
,
764 IN DEVICE_RELATION_TYPE Type
776 IoValidateDeviceIoControlAccess(
778 IN ULONG RequiredAccess
782 return STATUS_NOT_IMPLEMENTED
;