3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/device.c
6 * PURPOSE: Manage devices
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
11 /* INCLUDES *******************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS ********************************************************************/
19 #define TAG_DEVICE_EXTENSION TAG('D', 'E', 'X', 'T')
21 static ULONG IopDeviceObjectNumber
= 0;
23 /* PRIVATE FUNCTIONS **********************************************************/
27 PDEVICE_NODE DeviceNode
,
28 PDRIVER_OBJECT DriverObject
)
30 IO_STATUS_BLOCK IoStatusBlock
;
31 IO_STACK_LOCATION Stack
;
35 if (DriverObject
->DriverExtension
->AddDevice
)
37 /* This is a Plug and Play driver */
38 DPRINT("Plug and Play driver found\n");
40 ASSERT(DeviceNode
->PhysicalDeviceObject
);
42 DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
43 DriverObject
->DriverExtension
->AddDevice
);
45 Status
= DriverObject
->DriverExtension
->AddDevice(
46 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
48 if (!NT_SUCCESS(Status
))
53 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
55 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
57 /* FIXME: What do we do? Unload the driver or just disable the device? */
58 DbgPrint("An FDO was not attached\n");
59 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
60 return STATUS_UNSUCCESSFUL
;
63 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
65 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
67 /* FIXME: Should be DeviceNode->ResourceList */
68 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->BootResources
;
69 /* FIXME: Should be DeviceNode->ResourceListTranslated */
70 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->BootResources
;
72 Status
= IopInitiatePnpIrp(
78 if (!NT_SUCCESS(Status
))
80 DPRINT("IopInitiatePnpIrp() failed\n");
81 ObDereferenceObject(Fdo
);
86 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
88 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
90 /* There can be only one system power device */
91 if (!SystemPowerDeviceNodeCreated
)
93 PopSystemPowerDeviceNode
= DeviceNode
;
94 SystemPowerDeviceNodeCreated
= TRUE
;
99 if (Fdo
->DeviceType
== FILE_DEVICE_BUS_EXTENDER
||
100 Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
102 DPRINT("Bus extender found\n");
104 Status
= IopInvalidateDeviceRelations(DeviceNode
, BusRelations
);
105 if (!NT_SUCCESS(Status
))
107 ObDereferenceObject(Fdo
);
112 ObDereferenceObject(Fdo
);
115 return STATUS_SUCCESS
;
123 POBJECT_ATTRIBUTES ObjectAttributes
)
125 DPRINT("IopCreateDevice(ObjectBody %x, Parent %x, RemainingPath %S)\n",
126 ObjectBody
, Parent
, RemainingPath
);
128 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+ 1, '\\') != NULL
)
129 return STATUS_UNSUCCESSFUL
;
131 return STATUS_SUCCESS
;
134 /* PUBLIC FUNCTIONS ***********************************************************/
137 * IoAttachDeviceByPointer
144 IoAttachDeviceByPointer(
145 IN PDEVICE_OBJECT SourceDevice
,
146 IN PDEVICE_OBJECT TargetDevice
)
148 PDEVICE_OBJECT AttachedDevice
;
150 DPRINT("IoAttachDeviceByPointer(SourceDevice %x, TargetDevice %x)\n",
151 SourceDevice
, TargetDevice
);
153 AttachedDevice
= IoAttachDeviceToDeviceStack(SourceDevice
, TargetDevice
);
154 if (AttachedDevice
== NULL
)
155 return STATUS_NO_SUCH_DEVICE
;
157 return STATUS_SUCCESS
;
165 IoAttachDeviceToDeviceStackSafe(
166 IN PDEVICE_OBJECT SourceDevice
,
167 IN PDEVICE_OBJECT TargetDevice
,
168 OUT PDEVICE_OBJECT
*AttachedToDeviceObject
172 return STATUS_NOT_IMPLEMENTED
;
183 IoDeleteDevice(PDEVICE_OBJECT DeviceObject
)
185 PDEVICE_OBJECT Previous
;
187 if (DeviceObject
->Flags
& DO_SHUTDOWN_REGISTERED
)
188 IoUnregisterShutdownNotification(DeviceObject
);
190 /* Remove the timer if it exists */
191 if (DeviceObject
->Timer
)
193 IopRemoveTimerFromTimerList(DeviceObject
->Timer
);
194 ExFreePool(DeviceObject
->Timer
);
197 /* Free device extension */
198 if (DeviceObject
->DeviceObjectExtension
)
199 ExFreePool(DeviceObject
->DeviceObjectExtension
);
201 /* Remove device from driver device list */
202 Previous
= DeviceObject
->DriverObject
->DeviceObject
;
203 if (Previous
== DeviceObject
)
205 DeviceObject
->DriverObject
->DeviceObject
= DeviceObject
->NextDevice
;
209 while (Previous
->NextDevice
!= DeviceObject
)
210 Previous
= Previous
->NextDevice
;
211 Previous
->NextDevice
= DeviceObject
->NextDevice
;
214 ObDereferenceObject(DeviceObject
);
223 IoEnumerateDeviceObjectList(
224 IN PDRIVER_OBJECT DriverObject
,
225 IN PDEVICE_OBJECT
*DeviceObjectList
,
226 IN ULONG DeviceObjectListSize
,
227 OUT PULONG ActualNumberDeviceObjects
231 return STATUS_NOT_IMPLEMENTED
;
240 IoGetDeviceAttachmentBaseRef(
241 IN PDEVICE_OBJECT DeviceObject
253 IoGetDiskDeviceObject(
254 IN PDEVICE_OBJECT FileSystemDeviceObject
,
255 OUT PDEVICE_OBJECT
*DiskDeviceObject
259 return STATUS_NOT_IMPLEMENTED
;
267 IoGetLowerDeviceObject(
268 IN PDEVICE_OBJECT DeviceObject
276 * IoGetRelatedDeviceObject
279 * See "Windows NT File System Internals", page 633 - 634.
285 PDEVICE_OBJECT STDCALL
286 IoGetRelatedDeviceObject(
287 IN PFILE_OBJECT FileObject
)
290 * Get logical volume mounted on a physical/virtual/logical device
293 if (FileObject
->Vpb
&& FileObject
->Vpb
->DeviceObject
)
295 return IoGetAttachedDevice(FileObject
->Vpb
->DeviceObject
);
299 * Check if file object has an associated device object mounted by some
303 if (FileObject
->DeviceObject
->Vpb
&&
304 FileObject
->DeviceObject
->Vpb
->DeviceObject
)
306 return IoGetAttachedDevice(FileObject
->DeviceObject
->Vpb
->DeviceObject
);
309 return IoGetAttachedDevice(FileObject
->DeviceObject
);
313 * IoGetDeviceObjectPointer
320 IoGetDeviceObjectPointer(
321 IN PUNICODE_STRING ObjectName
,
322 IN ACCESS_MASK DesiredAccess
,
323 OUT PFILE_OBJECT
*FileObject
,
324 OUT PDEVICE_OBJECT
*DeviceObject
)
326 OBJECT_ATTRIBUTES ObjectAttributes
;
327 IO_STATUS_BLOCK StatusBlock
;
328 PFILE_OBJECT LocalFileObject
;
332 DPRINT("IoGetDeviceObjectPointer(ObjectName %wZ, DesiredAccess %x, FileObject %p DeviceObject %p)\n",
333 ObjectName
, DesiredAccess
, FileObject
, DeviceObject
);
335 InitializeObjectAttributes(
348 FILE_NON_DIRECTORY_FILE
);
350 if (!NT_SUCCESS(Status
))
353 Status
= ObReferenceObjectByHandle(
358 (PVOID
*)&LocalFileObject
,
361 if (NT_SUCCESS(Status
))
363 *DeviceObject
= IoGetRelatedDeviceObject(LocalFileObject
);
364 *FileObject
= LocalFileObject
;
380 IoDetachDevice(PDEVICE_OBJECT TargetDevice
)
382 DPRINT("IoDetachDevice(TargetDevice %x) - UNIMPLEMENTED\n", TargetDevice
);
386 * IoGetAttachedDevice
392 PDEVICE_OBJECT STDCALL
393 IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject
)
395 PDEVICE_OBJECT Current
= DeviceObject
;
397 while (Current
->AttachedDevice
!= NULL
)
398 Current
= Current
->AttachedDevice
;
404 * IoGetAttachedDeviceReference
410 PDEVICE_OBJECT STDCALL
411 IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject
)
413 PDEVICE_OBJECT Current
= IoGetAttachedDevice(DeviceObject
);
414 ObReferenceObject(Current
);
419 * IoAttachDeviceToDeviceStack
425 PDEVICE_OBJECT STDCALL
426 IoAttachDeviceToDeviceStack(
427 PDEVICE_OBJECT SourceDevice
,
428 PDEVICE_OBJECT TargetDevice
)
430 PDEVICE_OBJECT AttachedDevice
;
432 DPRINT("IoAttachDeviceToDeviceStack(SourceDevice %x, TargetDevice %x)\n",
433 SourceDevice
, TargetDevice
);
435 AttachedDevice
= IoGetAttachedDevice(TargetDevice
);
436 AttachedDevice
->AttachedDevice
= SourceDevice
;
437 SourceDevice
->AttachedDevice
= NULL
;
438 SourceDevice
->StackSize
= AttachedDevice
->StackSize
+ 1;
439 SourceDevice
->AlignmentRequirement
= AttachedDevice
->AlignmentRequirement
;
440 SourceDevice
->SectorSize
= AttachedDevice
->SectorSize
;
441 SourceDevice
->Vpb
= AttachedDevice
->Vpb
;
442 return AttachedDevice
;
448 * Layers a device over the highest device in a device stack.
452 * Device to be attached.
455 * Name of the target device.
458 * Caller storage for the device attached to.
466 PDEVICE_OBJECT SourceDevice
,
467 PUNICODE_STRING TargetDeviceName
,
468 PDEVICE_OBJECT
*AttachedDevice
)
471 PFILE_OBJECT FileObject
;
472 PDEVICE_OBJECT TargetDevice
;
474 Status
= IoGetDeviceObjectPointer(
476 FILE_READ_ATTRIBUTES
,
480 if (!NT_SUCCESS(Status
))
485 *AttachedDevice
= IoAttachDeviceToDeviceStack(
489 ObDereferenceObject(FileObject
);
491 return STATUS_SUCCESS
;
497 * Allocates memory for and intializes a device object for use for
502 * Driver object passed by IO Manager when the driver was loaded.
504 * DeviceExtensionSize
505 * Number of bytes for the device extension.
508 * Unicode name of device.
511 * Device type of the new device.
513 * DeviceCharacteristics
514 * Bit mask of device characteristics.
517 * TRUE if only one thread can access the device at a time.
520 * On successful return this parameter is filled by pointer to
521 * allocated device object.
529 PDRIVER_OBJECT DriverObject
,
530 ULONG DeviceExtensionSize
,
531 PUNICODE_STRING DeviceName
,
532 DEVICE_TYPE DeviceType
,
533 ULONG DeviceCharacteristics
,
535 PDEVICE_OBJECT
*DeviceObject
)
537 WCHAR AutoNameBuffer
[20];
538 UNICODE_STRING AutoName
;
539 PDEVICE_OBJECT CreatedDeviceObject
;
540 PDEVOBJ_EXTENSION DeviceObjectExtension
;
541 OBJECT_ATTRIBUTES ObjectAttributes
;
544 ASSERT_IRQL(PASSIVE_LEVEL
);
546 if (DeviceName
!= NULL
)
548 DPRINT("IoCreateDevice(DriverObject %x, DeviceName %S)\n",
549 DriverObject
, DeviceName
->Buffer
);
553 DPRINT("IoCreateDevice(DriverObject %x)\n",DriverObject
);
556 if (DeviceCharacteristics
& FILE_AUTOGENERATED_DEVICE_NAME
)
558 swprintf(AutoNameBuffer
,
560 InterlockedIncrementUL(&IopDeviceObjectNumber
));
561 RtlInitUnicodeString(&AutoName
,
563 DeviceName
= &AutoName
;
566 if (DeviceName
!= NULL
)
568 InitializeObjectAttributes(&ObjectAttributes
, DeviceName
, 0, NULL
, NULL
);
569 Status
= ObCreateObject(
575 sizeof(DEVICE_OBJECT
),
578 (PVOID
*)&CreatedDeviceObject
);
582 Status
= ObCreateObject(
588 sizeof(DEVICE_OBJECT
),
591 (PVOID
*)&CreatedDeviceObject
);
594 *DeviceObject
= NULL
;
596 if (!NT_SUCCESS(Status
))
598 DPRINT("IoCreateDevice() ObCreateObject failed, status: 0x%08X\n", Status
);
602 if (DriverObject
->DeviceObject
== NULL
)
604 DriverObject
->DeviceObject
= CreatedDeviceObject
;
605 CreatedDeviceObject
->NextDevice
= NULL
;
609 CreatedDeviceObject
->NextDevice
= DriverObject
->DeviceObject
;
610 DriverObject
->DeviceObject
= CreatedDeviceObject
;
613 CreatedDeviceObject
->Type
= DeviceType
;
614 CreatedDeviceObject
->DriverObject
= DriverObject
;
615 CreatedDeviceObject
->CurrentIrp
= NULL
;
616 CreatedDeviceObject
->Flags
= 0;
618 CreatedDeviceObject
->DeviceExtension
=
619 ExAllocatePoolWithTag(
622 TAG_DEVICE_EXTENSION
);
624 if (DeviceExtensionSize
> 0 && CreatedDeviceObject
->DeviceExtension
== NULL
)
626 ExFreePool(CreatedDeviceObject
);
627 DPRINT("IoCreateDevice() ExAllocatePoolWithTag failed, returning: 0x%08X\n", STATUS_INSUFFICIENT_RESOURCES
);
628 return STATUS_INSUFFICIENT_RESOURCES
;
631 if (DeviceExtensionSize
> 0)
633 RtlZeroMemory(CreatedDeviceObject
->DeviceExtension
, DeviceExtensionSize
);
636 CreatedDeviceObject
->Size
= sizeof(DEVICE_OBJECT
) + DeviceExtensionSize
;
637 CreatedDeviceObject
->ReferenceCount
= 1;
638 CreatedDeviceObject
->AttachedDevice
= NULL
;
639 CreatedDeviceObject
->DeviceType
= DeviceType
;
640 CreatedDeviceObject
->StackSize
= 1;
641 CreatedDeviceObject
->AlignmentRequirement
= 1;
642 CreatedDeviceObject
->Characteristics
= DeviceCharacteristics
;
643 CreatedDeviceObject
->Timer
= NULL
;
644 CreatedDeviceObject
->Vpb
= NULL
;
645 KeInitializeDeviceQueue(&CreatedDeviceObject
->DeviceQueue
);
648 &CreatedDeviceObject
->DeviceLock
,
649 SynchronizationEvent
,
652 /* FIXME: Do we need to add network drives too?! */
653 if (CreatedDeviceObject
->DeviceType
== FILE_DEVICE_DISK
||
654 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_CD_ROM
||
655 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_TAPE
)
657 IoAttachVpb(CreatedDeviceObject
);
659 CreatedDeviceObject
->SectorSize
= 512; /* FIXME */
661 DeviceObjectExtension
=
662 ExAllocatePoolWithTag(
664 sizeof(DEVOBJ_EXTENSION
),
665 TAG_DEVICE_EXTENSION
);
667 DeviceObjectExtension
->Type
= 0 /* ?? */;
668 DeviceObjectExtension
->Size
= sizeof(DEVOBJ_EXTENSION
);
669 DeviceObjectExtension
->DeviceObject
= CreatedDeviceObject
;
670 DeviceObjectExtension
->DeviceNode
= NULL
;
672 CreatedDeviceObject
->DeviceObjectExtension
= DeviceObjectExtension
;
674 *DeviceObject
= CreatedDeviceObject
;
676 return STATUS_SUCCESS
;
680 * IoOpenDeviceInstanceKey
687 IoOpenDeviceInstanceKey(
695 return STATUS_NOT_IMPLEMENTED
;
703 IoRegisterBootDriverReinitialization(
704 IN PDRIVER_OBJECT DriverObject
,
705 IN PDRIVER_REINITIALIZE DriverReinitializationRoutine
,
718 IoRegisterLastChanceShutdownNotification(
719 IN PDEVICE_OBJECT DeviceObject
723 return STATUS_NOT_IMPLEMENTED
;
727 * IoQueryDeviceEnumInfo
734 IoQueryDeviceEnumInfo(
747 IoSetStartIoAttributes(
748 IN PDEVICE_OBJECT DeviceObject
,
749 IN BOOLEAN DeferredStartIo
,
750 IN BOOLEAN NonCancelable
761 IoSynchronousInvalidateDeviceRelations(
762 IN PDEVICE_OBJECT DeviceObject
,
763 IN DEVICE_RELATION_TYPE Type
775 IoValidateDeviceIoControlAccess(
777 IN ULONG RequiredAccess
781 return STATUS_NOT_IMPLEMENTED
;