1 /* $Id: device.c,v 1.72 2004/08/12 16:43:12 ion Exp $
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 *******************************************************************/
14 #define NTOS_MODE_KERNEL
16 #include <internal/io.h>
17 #include <internal/po.h>
18 #include <internal/ldr.h>
19 #include <internal/id.h>
20 #include <internal/pool.h>
25 #include <internal/debug.h>
29 /* GLOBALS ********************************************************************/
31 #define TAG_DEVICE_EXTENSION TAG('D', 'E', 'X', 'T')
33 /* PRIVATE FUNCTIONS **********************************************************/
37 PDEVICE_NODE DeviceNode
,
38 PDRIVER_OBJECT DriverObject
)
40 IO_STATUS_BLOCK IoStatusBlock
;
41 IO_STACK_LOCATION Stack
;
45 if (DriverObject
->DriverExtension
->AddDevice
)
47 /* This is a Plug and Play driver */
48 DPRINT("Plug and Play driver found\n");
50 ASSERT(DeviceNode
->Pdo
);
52 DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
53 DriverObject
->DriverExtension
->AddDevice
);
55 Status
= DriverObject
->DriverExtension
->AddDevice(
56 DriverObject
, DeviceNode
->Pdo
);
58 if (!NT_SUCCESS(Status
))
63 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->Pdo
);
65 if (Fdo
== DeviceNode
->Pdo
)
67 /* FIXME: What do we do? Unload the driver or just disable the device? */
68 DbgPrint("An FDO was not attached\n");
69 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
70 return STATUS_UNSUCCESSFUL
;
73 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
75 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
77 /* FIXME: Put some resources in the IRP for the device */
78 Stack
.Parameters
.StartDevice
.AllocatedResources
= NULL
;
79 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= NULL
;
81 Status
= IopInitiatePnpIrp(
87 if (!NT_SUCCESS(Status
))
89 DPRINT("IopInitiatePnpIrp() failed\n");
90 ObDereferenceObject(Fdo
);
94 if (Fdo
->DeviceType
== FILE_DEVICE_BUS_EXTENDER
)
96 DPRINT("Bus extender found\n");
98 Status
= IopInvalidateDeviceRelations(DeviceNode
, BusRelations
);
100 if (!NT_SUCCESS(Status
))
102 ObDereferenceObject(Fdo
);
106 else if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
109 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
111 /* There can be only one system power device */
112 if (!SystemPowerDeviceNodeCreated
)
114 PopSystemPowerDeviceNode
= DeviceNode
;
115 SystemPowerDeviceNodeCreated
= TRUE
;
119 ObDereferenceObject(Fdo
);
122 return STATUS_SUCCESS
;
130 POBJECT_ATTRIBUTES ObjectAttributes
)
132 DPRINT("IopCreateDevice(ObjectBody %x, Parent %x, RemainingPath %S)\n",
133 ObjectBody
, Parent
, RemainingPath
);
135 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+ 1, '\\') != NULL
)
136 return STATUS_UNSUCCESSFUL
;
138 return STATUS_SUCCESS
;
141 /* PUBLIC FUNCTIONS ***********************************************************/
144 * IoAttachDeviceByPointer
151 IoAttachDeviceByPointer(
152 IN PDEVICE_OBJECT SourceDevice
,
153 IN PDEVICE_OBJECT TargetDevice
)
155 PDEVICE_OBJECT AttachedDevice
;
157 DPRINT("IoAttachDeviceByPointer(SourceDevice %x, TargetDevice %x)\n",
158 SourceDevice
, TargetDevice
);
160 AttachedDevice
= IoAttachDeviceToDeviceStack(SourceDevice
, TargetDevice
);
161 if (AttachedDevice
== NULL
)
162 return STATUS_NO_SUCH_DEVICE
;
164 return STATUS_SUCCESS
;
172 IoAttachDeviceToDeviceStackSafe(
173 IN PDEVICE_OBJECT SourceDevice
,
174 IN PDEVICE_OBJECT TargetDevice
,
175 OUT PDEVICE_OBJECT
*AttachedToDeviceObject
179 return STATUS_NOT_IMPLEMENTED
;
190 IoDeleteDevice(PDEVICE_OBJECT DeviceObject
)
192 PDEVICE_OBJECT Previous
;
194 if (DeviceObject
->Flags
& DO_SHUTDOWN_REGISTERED
)
195 IoUnregisterShutdownNotification(DeviceObject
);
197 /* Remove the timer if it exists */
198 if (DeviceObject
->Timer
)
200 IoStopTimer(DeviceObject
);
201 ExFreePool(DeviceObject
->Timer
);
204 /* Free device extension */
205 if (DeviceObject
->DeviceObjectExtension
)
206 ExFreePool(DeviceObject
->DeviceObjectExtension
);
208 /* Remove device from driver device list */
209 Previous
= DeviceObject
->DriverObject
->DeviceObject
;
210 if (Previous
== DeviceObject
)
212 DeviceObject
->DriverObject
->DeviceObject
= DeviceObject
->NextDevice
;
216 while (Previous
->NextDevice
!= DeviceObject
)
217 Previous
= Previous
->NextDevice
;
218 Previous
->NextDevice
= DeviceObject
->NextDevice
;
221 ObDereferenceObject(DeviceObject
);
230 IoEnumerateDeviceObjectList(
231 IN PDRIVER_OBJECT DriverObject
,
232 IN PDEVICE_OBJECT
*DeviceObjectList
,
233 IN ULONG DeviceObjectListSize
,
234 OUT PULONG ActualNumberDeviceObjects
238 return STATUS_NOT_IMPLEMENTED
;
247 IoGetDeviceAttachmentBaseRef(
248 IN PDEVICE_OBJECT DeviceObject
260 IoGetDiskDeviceObject(
261 IN PDEVICE_OBJECT FileSystemDeviceObject
,
262 OUT PDEVICE_OBJECT
*DiskDeviceObject
266 return STATUS_NOT_IMPLEMENTED
;
274 IoGetLowerDeviceObject(
275 IN PDEVICE_OBJECT DeviceObject
283 * IoGetRelatedDeviceObject
286 * See "Windows NT File System Internals", page 633 - 634.
292 PDEVICE_OBJECT STDCALL
293 IoGetRelatedDeviceObject(
294 IN PFILE_OBJECT FileObject
)
297 * Get logical volume mounted on a physical/virtual/logical device
300 if (FileObject
->Vpb
&& FileObject
->Vpb
->DeviceObject
)
302 return IoGetAttachedDevice(FileObject
->Vpb
->DeviceObject
);
306 * Check if file object has an associated device object mounted by some
310 if (FileObject
->DeviceObject
->Vpb
&&
311 FileObject
->DeviceObject
->Vpb
->DeviceObject
)
313 return IoGetAttachedDevice(FileObject
->DeviceObject
->Vpb
->DeviceObject
);
316 return IoGetAttachedDevice(FileObject
->DeviceObject
);
320 * IoGetDeviceObjectPointer
327 IoGetDeviceObjectPointer(
328 IN PUNICODE_STRING ObjectName
,
329 IN ACCESS_MASK DesiredAccess
,
330 OUT PFILE_OBJECT
*FileObject
,
331 OUT PDEVICE_OBJECT
*DeviceObject
)
333 OBJECT_ATTRIBUTES ObjectAttributes
;
334 IO_STATUS_BLOCK StatusBlock
;
335 PFILE_OBJECT LocalFileObject
;
339 DPRINT("IoGetDeviceObjectPointer(ObjectName %wZ, DesiredAccess %x, FileObject %p DeviceObject %p)\n",
340 ObjectName
, DesiredAccess
, FileObject
, DeviceObject
);
342 InitializeObjectAttributes(
355 FILE_NON_DIRECTORY_FILE
);
357 if (!NT_SUCCESS(Status
))
360 Status
= ObReferenceObjectByHandle(
365 (PVOID
*)&LocalFileObject
,
368 if (NT_SUCCESS(Status
))
370 *DeviceObject
= IoGetRelatedDeviceObject(LocalFileObject
);
371 *FileObject
= LocalFileObject
;
387 IoDetachDevice(PDEVICE_OBJECT TargetDevice
)
389 DPRINT("IoDetachDevice(TargetDevice %x) - UNIMPLEMENTED\n", TargetDevice
);
393 * IoGetAttachedDevice
399 PDEVICE_OBJECT STDCALL
400 IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject
)
402 PDEVICE_OBJECT Current
= DeviceObject
;
404 while (Current
->AttachedDevice
!= NULL
)
405 Current
= Current
->AttachedDevice
;
411 * IoGetAttachedDeviceReference
417 PDEVICE_OBJECT STDCALL
418 IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject
)
420 PDEVICE_OBJECT Current
= IoGetAttachedDevice(DeviceObject
);
421 ObReferenceObject(Current
);
426 * IoAttachDeviceToDeviceStack
432 PDEVICE_OBJECT STDCALL
433 IoAttachDeviceToDeviceStack(
434 PDEVICE_OBJECT SourceDevice
,
435 PDEVICE_OBJECT TargetDevice
)
437 PDEVICE_OBJECT AttachedDevice
;
439 DPRINT("IoAttachDeviceToDeviceStack(SourceDevice %x, TargetDevice %x)\n",
440 SourceDevice
, TargetDevice
);
442 AttachedDevice
= IoGetAttachedDevice(TargetDevice
);
443 AttachedDevice
->AttachedDevice
= SourceDevice
;
444 SourceDevice
->AttachedDevice
= NULL
;
445 SourceDevice
->StackSize
= AttachedDevice
->StackSize
+ 1;
446 SourceDevice
->Vpb
= AttachedDevice
->Vpb
;
447 return AttachedDevice
;
453 * Layers a device over the highest device in a device stack.
457 * Device to be attached.
460 * Name of the target device.
463 * Caller storage for the device attached to.
471 PDEVICE_OBJECT SourceDevice
,
472 PUNICODE_STRING TargetDeviceName
,
473 PDEVICE_OBJECT
*AttachedDevice
)
476 PFILE_OBJECT FileObject
;
477 PDEVICE_OBJECT TargetDevice
;
479 Status
= IoGetDeviceObjectPointer(
481 FILE_READ_ATTRIBUTES
,
485 if (!NT_SUCCESS(Status
))
490 *AttachedDevice
= IoAttachDeviceToDeviceStack(
494 ObDereferenceObject(FileObject
);
496 return STATUS_SUCCESS
;
502 * Allocates memory for and intializes a device object for use for
507 * Driver object passed by IO Manager when the driver was loaded.
509 * DeviceExtensionSize
510 * Number of bytes for the device extension.
513 * Unicode name of device.
516 * Device type of the new device.
518 * DeviceCharacteristics
519 * Bit mask of device characteristics.
522 * TRUE if only one thread can access the device at a time.
525 * On successful return this parameter is filled by pointer to
526 * allocated device object.
534 PDRIVER_OBJECT DriverObject
,
535 ULONG DeviceExtensionSize
,
536 PUNICODE_STRING DeviceName
,
537 DEVICE_TYPE DeviceType
,
538 ULONG DeviceCharacteristics
,
540 PDEVICE_OBJECT
*DeviceObject
)
542 PDEVICE_OBJECT CreatedDeviceObject
;
543 PDEVOBJ_EXTENSION DeviceObjectExtension
;
544 OBJECT_ATTRIBUTES ObjectAttributes
;
547 assert_irql(PASSIVE_LEVEL
);
549 if (DeviceName
!= NULL
)
551 DPRINT("IoCreateDevice(DriverObject %x, DeviceName %S)\n",
552 DriverObject
, DeviceName
->Buffer
);
556 DPRINT("IoCreateDevice(DriverObject %x)\n",DriverObject
);
559 if (DeviceName
!= NULL
)
561 InitializeObjectAttributes(&ObjectAttributes
, DeviceName
, 0, NULL
, NULL
);
562 Status
= ObCreateObject(
568 sizeof(DEVICE_OBJECT
),
571 (PVOID
*)&CreatedDeviceObject
);
575 Status
= ObCreateObject(
581 sizeof(DEVICE_OBJECT
),
584 (PVOID
*)&CreatedDeviceObject
);
587 *DeviceObject
= NULL
;
589 if (!NT_SUCCESS(Status
))
591 DPRINT("IoCreateDevice() ObCreateObject failed, status: 0x%08X\n", Status
);
595 if (DriverObject
->DeviceObject
== NULL
)
597 DriverObject
->DeviceObject
= CreatedDeviceObject
;
598 CreatedDeviceObject
->NextDevice
= NULL
;
602 CreatedDeviceObject
->NextDevice
= DriverObject
->DeviceObject
;
603 DriverObject
->DeviceObject
= CreatedDeviceObject
;
606 CreatedDeviceObject
->Type
= DeviceType
;
607 CreatedDeviceObject
->DriverObject
= DriverObject
;
608 CreatedDeviceObject
->CurrentIrp
= NULL
;
609 CreatedDeviceObject
->Flags
= 0;
611 CreatedDeviceObject
->DeviceExtension
=
612 ExAllocatePoolWithTag(
615 TAG_DEVICE_EXTENSION
);
617 if (DeviceExtensionSize
> 0 && CreatedDeviceObject
->DeviceExtension
== NULL
)
619 ExFreePool(CreatedDeviceObject
);
620 DPRINT("IoCreateDevice() ExAllocatePoolWithTag failed, returning: 0x%08X\n", STATUS_INSUFFICIENT_RESOURCES
);
621 return STATUS_INSUFFICIENT_RESOURCES
;
624 if (DeviceExtensionSize
> 0)
626 RtlZeroMemory(CreatedDeviceObject
->DeviceExtension
, DeviceExtensionSize
);
629 CreatedDeviceObject
->Size
= sizeof(DEVICE_OBJECT
) + DeviceExtensionSize
;
630 CreatedDeviceObject
->ReferenceCount
= 1;
631 CreatedDeviceObject
->AttachedDevice
= NULL
;
632 CreatedDeviceObject
->DeviceType
= DeviceType
;
633 CreatedDeviceObject
->StackSize
= 1;
634 CreatedDeviceObject
->AlignmentRequirement
= 1;
635 CreatedDeviceObject
->Characteristics
= DeviceCharacteristics
;
636 CreatedDeviceObject
->Timer
= NULL
;
637 CreatedDeviceObject
->Vpb
= NULL
;
638 KeInitializeDeviceQueue(&CreatedDeviceObject
->DeviceQueue
);
641 &CreatedDeviceObject
->DeviceLock
,
642 SynchronizationEvent
,
645 /* FIXME: Do we need to add network drives too?! */
646 if (CreatedDeviceObject
->DeviceType
== FILE_DEVICE_DISK
||
647 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_CD_ROM
||
648 CreatedDeviceObject
->DeviceType
== FILE_DEVICE_TAPE
)
650 IoAttachVpb(CreatedDeviceObject
);
651 CreatedDeviceObject
->SectorSize
= 512; /* FIXME */
654 DeviceObjectExtension
=
655 ExAllocatePoolWithTag(
657 sizeof(DEVOBJ_EXTENSION
),
658 TAG_DEVICE_EXTENSION
);
660 DeviceObjectExtension
->Type
= 0 /* ?? */;
661 DeviceObjectExtension
->Size
= sizeof(DEVOBJ_EXTENSION
);
662 DeviceObjectExtension
->DeviceObject
= CreatedDeviceObject
;
663 DeviceObjectExtension
->DeviceNode
= NULL
;
665 CreatedDeviceObject
->DeviceObjectExtension
= DeviceObjectExtension
;
667 *DeviceObject
= CreatedDeviceObject
;
669 return STATUS_SUCCESS
;
673 * IoOpenDeviceInstanceKey
680 IoOpenDeviceInstanceKey(
688 return STATUS_NOT_IMPLEMENTED
;
696 IoRegisterBootDriverReinitialization(
697 IN PDRIVER_OBJECT DriverObject
,
698 IN PDRIVER_REINITIALIZE DriverReinitializationRoutine
,
711 IoRegisterLastChanceShutdownNotification(
712 IN PDEVICE_OBJECT DeviceObject
716 return STATUS_NOT_IMPLEMENTED
;
720 * IoQueryDeviceEnumInfo
727 IoQueryDeviceEnumInfo(
740 IoSetStartIoAttributes(
741 IN PDEVICE_OBJECT DeviceObject
,
742 IN BOOLEAN DeferredStartIo
,
743 IN BOOLEAN NonCancelable
754 IoSynchronousInvalidateDeviceRelations(
755 IN PDEVICE_OBJECT DeviceObject
,
756 IN DEVICE_RELATION_TYPE Type
768 IoValidateDeviceIoControlAccess(
770 IN ULONG RequiredAccess
774 return STATUS_NOT_IMPLEMENTED
;