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 #include <ddk/ntddk.h>
15 #include <internal/io.h>
16 #include <internal/po.h>
17 #include <internal/ldr.h>
18 #include <internal/id.h>
19 #include <internal/pool.h>
20 #include <internal/registry.h>
26 #include <internal/debug.h>
28 /* GLOBALS *******************************************************************/
30 #define TAG_DRIVER TAG('D', 'R', 'V', 'R')
31 #define TAG_DRIVER_EXTENSION TAG('D', 'R', 'V', 'E')
32 #define TAG_DEVICE_EXTENSION TAG('D', 'E', 'X', 'T')
34 #define DRIVER_REGISTRY_KEY_BASENAME L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
36 /* FUNCTIONS ***************************************************************/
39 IoAttachDeviceByPointer(IN PDEVICE_OBJECT SourceDevice,
40 IN PDEVICE_OBJECT TargetDevice)
42 PDEVICE_OBJECT AttachedDevice;
44 DPRINT("IoAttachDeviceByPointer(SourceDevice %x, TargetDevice %x)\n",
48 AttachedDevice = IoAttachDeviceToDeviceStack (SourceDevice,
50 if (AttachedDevice == NULL)
51 return STATUS_NO_SUCH_DEVICE;
53 return STATUS_SUCCESS;
58 IoDeleteDevice(PDEVICE_OBJECT DeviceObject)
60 PDEVICE_OBJECT Previous;
62 if (DeviceObject->Flags & DO_SHUTDOWN_REGISTERED)
63 IoUnregisterShutdownNotification(DeviceObject);
65 /* remove the timer if it exists */
66 if (DeviceObject->Timer)
68 IoStopTimer(DeviceObject);
69 ExFreePool(DeviceObject->Timer);
72 /* free device extension */
73 if (DeviceObject->DeviceObjectExtension)
74 ExFreePool (DeviceObject->DeviceObjectExtension);
76 /* remove device from driver device list */
77 Previous = DeviceObject->DriverObject->DeviceObject;
78 if (Previous == DeviceObject)
80 DeviceObject->DriverObject->DeviceObject = DeviceObject->NextDevice;
84 while (Previous->NextDevice != DeviceObject)
85 Previous = Previous->NextDevice;
86 Previous->NextDevice = DeviceObject->NextDevice;
89 ObDereferenceObject (DeviceObject);
95 IoGetRelatedDeviceObject (
96 IN PFILE_OBJECT FileObject
99 return (FileObject->DeviceObject);
105 IoGetDeviceObjectPointer (
106 IN PUNICODE_STRING ObjectName,
107 IN ACCESS_MASK DesiredAccess,
108 OUT PFILE_OBJECT * FileObject,
109 OUT PDEVICE_OBJECT * DeviceObject)
111 OBJECT_ATTRIBUTES ObjectAttributes;
112 IO_STATUS_BLOCK StatusBlock;
113 PFILE_OBJECT LocalFileObject;
117 DPRINT("IoGetDeviceObjectPointer(ObjectName %wZ, DesiredAccess %x, FileObject %p DeviceObject %p)\n",
123 InitializeObjectAttributes (&ObjectAttributes,
129 Status = NtOpenFile (&FileHandle,
134 FILE_NON_DIRECTORY_FILE);
135 if (!NT_SUCCESS(Status))
138 Status = ObReferenceObjectByHandle (FileHandle,
142 (PVOID*)&LocalFileObject,
144 if (NT_SUCCESS(Status))
146 *DeviceObject = IoGetRelatedDeviceObject (LocalFileObject);
147 *FileObject = LocalFileObject;
149 NtClose (FileHandle);
157 IoDetachDevice(PDEVICE_OBJECT TargetDevice)
160 DPRINT("IoDetachDevice(TargetDevice %x) - UNIMPLEMENTED\n", TargetDevice);
166 IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject)
168 PDEVICE_OBJECT Current = DeviceObject;
170 // DPRINT("IoGetAttachedDevice(DeviceObject %x)\n",DeviceObject);
172 while (Current->AttachedDevice!=NULL)
174 Current = Current->AttachedDevice;
175 // DPRINT("Current %x\n",Current);
178 // DPRINT("IoGetAttachedDevice() = %x\n",DeviceObject);
184 IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
186 PDEVICE_OBJECT Current = DeviceObject;
188 while (Current->AttachedDevice!=NULL)
190 Current = Current->AttachedDevice;
193 ObReferenceObject(Current);
197 PDEVICE_OBJECT STDCALL
198 IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice,
199 PDEVICE_OBJECT TargetDevice)
201 PDEVICE_OBJECT AttachedDevice;
203 DPRINT("IoAttachDeviceToDeviceStack(SourceDevice %x, TargetDevice %x)\n",
204 SourceDevice,TargetDevice);
206 AttachedDevice = IoGetAttachedDevice(TargetDevice);
207 AttachedDevice->AttachedDevice = SourceDevice;
208 SourceDevice->AttachedDevice = NULL;
209 SourceDevice->StackSize = AttachedDevice->StackSize + 1;
210 SourceDevice->Vpb = AttachedDevice->Vpb;
211 return(AttachedDevice);
215 IoRegisterDriverReinitialization(PDRIVER_OBJECT DriverObject,
216 PDRIVER_REINITIALIZE ReinitRoutine,
223 IopDefaultDispatchFunction(PDEVICE_OBJECT DeviceObject,
226 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
227 Irp->IoStatus.Information = 0;
229 IoCompleteRequest(Irp, IO_NO_INCREMENT);
230 return(STATUS_NOT_IMPLEMENTED);
235 IopCreateDriverObject(PDRIVER_OBJECT *DriverObject,
236 PUNICODE_STRING ServiceName,
239 PDRIVER_OBJECT Object;
240 HANDLE DriverHandle = 0;
242 WCHAR NameBuffer[MAX_PATH];
243 UNICODE_STRING DriverName;
244 OBJECT_ATTRIBUTES ObjectAttributes;
247 DPRINT("IopCreateDriverObject(%p '%wZ' %x)\n", DriverObject, ServiceName, FileSystem);
249 *DriverObject = NULL;
251 /* Create ModuleName string */
252 if (ServiceName != NULL)
254 if (FileSystem == TRUE)
255 wcscpy(NameBuffer, FILESYSTEM_ROOT_NAME);
257 wcscpy(NameBuffer, DRIVER_ROOT_NAME);
258 wcscat(NameBuffer, ServiceName->Buffer);
260 RtlInitUnicodeString(&DriverName,
262 DPRINT("Driver name: '%wZ'\n", &DriverName);
265 /* Initialize ObjectAttributes for ModuleObject */
266 InitializeObjectAttributes(&ObjectAttributes,
267 (ServiceName != NULL)? &DriverName : NULL,
272 /* Create module object */
273 Status = ObCreateObject(&DriverHandle,
274 STANDARD_RIGHTS_REQUIRED,
278 if (!NT_SUCCESS(Status))
283 NtClose(DriverHandle);
285 /* Create driver extension */
286 Object->DriverExtension = (PDRIVER_EXTENSION)
287 ExAllocatePoolWithTag(NonPagedPool,
288 sizeof(DRIVER_EXTENSION),
289 TAG_DRIVER_EXTENSION);
290 if (Object->DriverExtension == NULL)
293 return(STATUS_INSUFFICIENT_RESOURCES);
296 RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
298 Object->Type = InternalDriverType;
300 for (i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++)
302 Object->MajorFunction[i] = (PDRIVER_DISPATCH) IopDefaultDispatchFunction;
305 *DriverObject = Object;
307 return STATUS_SUCCESS;
311 IopAttachFilterDrivers(PDEVICE_NODE DeviceNode,
314 return STATUS_SUCCESS;
318 IopInitializeDevice(PDEVICE_NODE DeviceNode,
319 BOOLEAN BootDriversOnly)
321 IO_STATUS_BLOCK IoStatusBlock;
322 PDRIVER_OBJECT DriverObject;
323 IO_STACK_LOCATION Stack;
327 DriverObject = DeviceNode->DriverObject;
329 if (DriverObject->DriverExtension->AddDevice)
331 /* This is a Plug and Play driver */
332 DPRINT("Plug and Play driver found\n");
334 assert(DeviceNode->Pdo);
336 DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
337 DriverObject->DriverExtension->AddDevice);
338 Status = DriverObject->DriverExtension->AddDevice(
339 DriverObject, DeviceNode->Pdo);
340 if (!NT_SUCCESS(Status))
345 IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED);
347 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
349 Fdo = IoGetAttachedDeviceReference(DeviceNode->Pdo);
351 if (Fdo == DeviceNode->Pdo)
353 /* FIXME: What do we do? Unload the driver or just disable the device? */
354 DbgPrint("An FDO was not attached\n");
358 /* FIXME: Put some resources in the IRP for the device */
359 Stack.Parameters.StartDevice.AllocatedResources = NULL;
360 Stack.Parameters.StartDevice.AllocatedResourcesTranslated = NULL;
362 Status = IopInitiatePnpIrp(
367 if (!NT_SUCCESS(Status))
369 DPRINT("IopInitiatePnpIrp() failed\n");
370 ObDereferenceObject(Fdo);
374 if (Fdo->DeviceType == FILE_DEVICE_BUS_EXTENDER)
376 DPRINT("Bus extender found\n");
378 Status = IopInterrogateBusExtender(
379 DeviceNode, Fdo, BootDriversOnly);
380 if (!NT_SUCCESS(Status))
382 ObDereferenceObject(Fdo);
386 else if (Fdo->DeviceType == FILE_DEVICE_ACPI)
389 static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;
391 /* There can be only one system power device */
392 if (!SystemPowerDeviceNodeCreated)
394 PopSystemPowerDeviceNode = DeviceNode;
395 SystemPowerDeviceNodeCreated = TRUE;
399 ObDereferenceObject(Fdo);
402 return STATUS_SUCCESS;
406 IopInitializeService(
407 PDEVICE_NODE DeviceNode,
408 PUNICODE_STRING ImagePath)
410 PMODULE_OBJECT ModuleObject;
413 ModuleObject = LdrGetModuleObject(&DeviceNode->ServiceName);
414 if (ModuleObject == NULL)
416 /* The module is currently not loaded, so load it now */
418 Status = LdrLoadModule(ImagePath, &ModuleObject);
419 if (!NT_SUCCESS(Status))
421 /* FIXME: Log the error */
422 CPRINT("Driver load failed\n");
426 Status = IopInitializeDriver(ModuleObject->EntryPoint, DeviceNode, FALSE);
427 if (!NT_SUCCESS(Status))
429 LdrUnloadModule(ModuleObject);
431 /* FIXME: Log the error */
432 CPRINT("A driver failed to initialize\n");
437 Status = IopInitializeDevice(DeviceNode, TRUE);
443 IopInitializeDeviceNodeService(PDEVICE_NODE DeviceNode)
445 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
446 UNICODE_STRING ImagePath;
450 Status = RtlpGetRegistryHandle(
451 RTL_REGISTRY_SERVICES,
452 DeviceNode->ServiceName.Buffer,
455 if (!NT_SUCCESS(Status))
457 DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status);
461 RtlZeroMemory(QueryTable, sizeof(QueryTable));
463 RtlInitUnicodeString(&ImagePath, NULL);
465 QueryTable[0].Name = L"ImagePath";
466 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
467 QueryTable[0].EntryContext = &ImagePath;
469 Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
476 DPRINT("RtlQueryRegistryValues() returned status %x\n", Status);
478 if (NT_SUCCESS(Status))
480 DPRINT("Got ImagePath %S\n", ImagePath.Buffer);
482 Status = IopInitializeService(DeviceNode, &ImagePath);
484 RtlFreeUnicodeString(&ImagePath);
491 IopInitializeDriver(PDRIVER_INITIALIZE DriverEntry,
492 PDEVICE_NODE DeviceNode,
493 BOOLEAN FileSystemDriver)
495 * FUNCTION: Called to initalize a loaded driver
497 * DriverEntry = Pointer to driver entry routine
498 * DeviceNode = Pointer to device node
501 WCHAR RegistryKeyBuffer[MAX_PATH];
502 PDRIVER_OBJECT DriverObject;
503 UNICODE_STRING RegistryKey;
506 DPRINT("IopInitializeDriver(DriverEntry %08lx, DeviceNode %08lx)\n",
507 DriverEntry, DeviceNode);
509 Status = IopCreateDriverObject(&DriverObject,
510 &DeviceNode->ServiceName,
512 if (!NT_SUCCESS(Status))
517 DeviceNode->DriverObject = DriverObject;
519 if (DeviceNode->ServiceName.Buffer)
521 wcscpy(RegistryKeyBuffer, DRIVER_REGISTRY_KEY_BASENAME);
522 wcscat(RegistryKeyBuffer, DeviceNode->ServiceName.Buffer);
523 RtlInitUnicodeString(&RegistryKey, RegistryKeyBuffer);
527 RtlInitUnicodeString(&RegistryKey, NULL);
530 DPRINT("RegistryKey: %wZ\n", &RegistryKey);
531 DPRINT("Calling driver entrypoint at %08lx\n", DriverEntry);
533 Status = DriverEntry(DriverObject, &RegistryKey);
534 if (!NT_SUCCESS(Status))
536 DeviceNode->DriverObject = NULL;
537 ExFreePool(DriverObject->DriverExtension);
538 ObMakeTemporaryObject(DriverObject);
539 ObDereferenceObject(DriverObject);
543 Status = IopInitializeDevice(DeviceNode, TRUE);
550 IoAttachDevice(PDEVICE_OBJECT SourceDevice,
551 PUNICODE_STRING TargetDevice,
552 PDEVICE_OBJECT* AttachedDevice)
554 * FUNCTION: Layers a device over the highest device in a device stack
556 * SourceDevice = Device to attached
557 * TargetDevice = Name of the target device
558 * AttachedDevice (OUT) = Caller storage for the device attached to
566 IopCreateDevice(PVOID ObjectBody,
569 POBJECT_ATTRIBUTES ObjectAttributes)
572 DPRINT("IopCreateDevice(ObjectBody %x, Parent %x, RemainingPath %S)\n",
573 ObjectBody, Parent, RemainingPath);
575 if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
577 return(STATUS_UNSUCCESSFUL);
580 return(STATUS_SUCCESS);
585 IoCreateDevice(PDRIVER_OBJECT DriverObject,
586 ULONG DeviceExtensionSize,
587 PUNICODE_STRING DeviceName,
588 DEVICE_TYPE DeviceType,
589 ULONG DeviceCharacteristics,
591 PDEVICE_OBJECT* DeviceObject)
593 * FUNCTION: Allocates memory for and intializes a device object for use for
596 * DriverObject : Driver object passed by iomgr when the driver was
598 * DeviceExtensionSize : Number of bytes for the device extension
599 * DeviceName : Unicode name of device
600 * DeviceType : Device type
601 * DeviceCharacteristics : Bit mask of device characteristics
602 * Exclusive : True if only one thread can access the device at a
606 * DeviceObject : Contains a pointer to allocated device object
607 * if the call succeeded
608 * NOTES: See the DDK documentation for more information
611 PDEVICE_OBJECT CreatedDeviceObject;
612 OBJECT_ATTRIBUTES ObjectAttributes;
616 assert_irql(PASSIVE_LEVEL);
618 if (DeviceName != NULL)
620 DPRINT("IoCreateDevice(DriverObject %x, DeviceName %S)\n",DriverObject,
625 DPRINT("IoCreateDevice(DriverObject %x)\n",DriverObject);
628 if (DeviceName != NULL)
630 InitializeObjectAttributes(&ObjectAttributes,DeviceName,0,NULL,NULL);
631 Status = ObCreateObject(&DeviceHandle,
635 (PVOID*)&CreatedDeviceObject);
639 Status = ObCreateObject(&DeviceHandle,
643 (PVOID*)&CreatedDeviceObject);
646 *DeviceObject = NULL;
648 if (!NT_SUCCESS(Status))
650 DPRINT("IoCreateDevice() ObCreateObject failed, status: 0x%08X\n", Status);
654 if (DriverObject->DeviceObject == NULL)
656 DriverObject->DeviceObject = CreatedDeviceObject;
657 CreatedDeviceObject->NextDevice = NULL;
661 CreatedDeviceObject->NextDevice = DriverObject->DeviceObject;
662 DriverObject->DeviceObject = CreatedDeviceObject;
665 CreatedDeviceObject->Type = DeviceType;
666 CreatedDeviceObject->DriverObject = DriverObject;
667 CreatedDeviceObject->CurrentIrp = NULL;
668 CreatedDeviceObject->Flags = 0;
670 CreatedDeviceObject->DeviceExtension =
671 ExAllocatePoolWithTag(NonPagedPool, DeviceExtensionSize,
672 TAG_DEVICE_EXTENSION);
673 if (DeviceExtensionSize > 0 && CreatedDeviceObject->DeviceExtension == NULL)
675 ExFreePool(CreatedDeviceObject);
676 DPRINT("IoCreateDevice() ExAllocatePoolWithTag failed, returning: 0x%08X\n", STATUS_INSUFFICIENT_RESOURCES);
677 return(STATUS_INSUFFICIENT_RESOURCES);
680 if (DeviceExtensionSize > 0)
682 RtlZeroMemory(CreatedDeviceObject->DeviceExtension,
683 DeviceExtensionSize);
686 CreatedDeviceObject->AttachedDevice = NULL;
687 CreatedDeviceObject->DeviceType = DeviceType;
688 CreatedDeviceObject->StackSize = 1;
689 CreatedDeviceObject->AlignmentRequirement = 1;
690 KeInitializeDeviceQueue(&CreatedDeviceObject->DeviceQueue);
692 KeInitializeEvent(&CreatedDeviceObject->DeviceLock,
693 SynchronizationEvent,
696 /* FIXME: Do we need to add network drives too?! */
697 if (CreatedDeviceObject->DeviceType == FILE_DEVICE_DISK ||
698 CreatedDeviceObject->DeviceType == FILE_DEVICE_CD_ROM ||
699 CreatedDeviceObject->DeviceType == FILE_DEVICE_TAPE)
701 IoAttachVpb(CreatedDeviceObject);
704 *DeviceObject = CreatedDeviceObject;
706 return(STATUS_SUCCESS);
712 IoOpenDeviceInstanceKey (
721 return(STATUS_NOT_IMPLEMENTED);
727 IoQueryDeviceEnumInfo (