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 ***************************************************************/
41 IoAttachDeviceByPointer(IN PDEVICE_OBJECT SourceDevice,
42 IN PDEVICE_OBJECT TargetDevice)
44 PDEVICE_OBJECT AttachedDevice;
46 DPRINT("IoAttachDeviceByPointer(SourceDevice %x, TargetDevice %x)\n",
50 AttachedDevice = IoAttachDeviceToDeviceStack (SourceDevice,
52 if (AttachedDevice == NULL)
53 return STATUS_NO_SUCH_DEVICE;
55 return STATUS_SUCCESS;
60 IoDeleteDevice(PDEVICE_OBJECT DeviceObject)
62 PDEVICE_OBJECT Previous;
64 if (DeviceObject->Flags & DO_SHUTDOWN_REGISTERED)
65 IoUnregisterShutdownNotification(DeviceObject);
67 /* remove the timer if it exists */
68 if (DeviceObject->Timer)
70 IoStopTimer(DeviceObject);
71 ExFreePool(DeviceObject->Timer);
74 /* free device extension */
75 if (DeviceObject->DeviceObjectExtension)
76 ExFreePool (DeviceObject->DeviceObjectExtension);
78 /* remove device from driver device list */
79 Previous = DeviceObject->DriverObject->DeviceObject;
80 if (Previous == DeviceObject)
82 DeviceObject->DriverObject->DeviceObject = DeviceObject->NextDevice;
86 while (Previous->NextDevice != DeviceObject)
87 Previous = Previous->NextDevice;
88 Previous->NextDevice = DeviceObject->NextDevice;
91 ObDereferenceObject (DeviceObject);
97 IoGetRelatedDeviceObject (
98 IN PFILE_OBJECT FileObject
101 return (FileObject->DeviceObject);
107 IoGetDeviceObjectPointer (
108 IN PUNICODE_STRING ObjectName,
109 IN ACCESS_MASK DesiredAccess,
110 OUT PFILE_OBJECT * FileObject,
111 OUT PDEVICE_OBJECT * DeviceObject)
113 OBJECT_ATTRIBUTES ObjectAttributes;
114 IO_STATUS_BLOCK StatusBlock;
115 PFILE_OBJECT LocalFileObject;
119 DPRINT("IoGetDeviceObjectPointer(ObjectName %wZ, DesiredAccess %x, FileObject %p DeviceObject %p)\n",
125 InitializeObjectAttributes (&ObjectAttributes,
131 Status = NtOpenFile (&FileHandle,
136 FILE_NON_DIRECTORY_FILE);
137 if (!NT_SUCCESS(Status))
140 Status = ObReferenceObjectByHandle (FileHandle,
144 (PVOID*)&LocalFileObject,
146 if (NT_SUCCESS(Status))
148 *DeviceObject = IoGetRelatedDeviceObject (LocalFileObject);
149 *FileObject = LocalFileObject;
151 NtClose (FileHandle);
159 IoDetachDevice(PDEVICE_OBJECT TargetDevice)
162 DPRINT("IoDetachDevice(TargetDevice %x) - UNIMPLEMENTED\n", TargetDevice);
165 #endif /* LIBCAPTIVE */
169 IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject)
171 PDEVICE_OBJECT Current = DeviceObject;
173 // DPRINT("IoGetAttachedDevice(DeviceObject %x)\n",DeviceObject);
175 while (Current->AttachedDevice!=NULL)
177 Current = Current->AttachedDevice;
178 // DPRINT("Current %x\n",Current);
181 // DPRINT("IoGetAttachedDevice() = %x\n",DeviceObject);
189 IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
191 PDEVICE_OBJECT Current = DeviceObject;
193 while (Current->AttachedDevice!=NULL)
195 Current = Current->AttachedDevice;
198 ObReferenceObject(Current);
202 PDEVICE_OBJECT STDCALL
203 IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice,
204 PDEVICE_OBJECT TargetDevice)
206 PDEVICE_OBJECT AttachedDevice;
208 DPRINT("IoAttachDeviceToDeviceStack(SourceDevice %x, TargetDevice %x)\n",
209 SourceDevice,TargetDevice);
211 AttachedDevice = IoGetAttachedDevice(TargetDevice);
212 AttachedDevice->AttachedDevice = SourceDevice;
213 SourceDevice->AttachedDevice = NULL;
214 SourceDevice->StackSize = AttachedDevice->StackSize + 1;
215 SourceDevice->Vpb = AttachedDevice->Vpb;
216 return(AttachedDevice);
220 IoRegisterDriverReinitialization(PDRIVER_OBJECT DriverObject,
221 PDRIVER_REINITIALIZE ReinitRoutine,
228 IopDefaultDispatchFunction(PDEVICE_OBJECT DeviceObject,
231 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
232 Irp->IoStatus.Information = 0;
234 IoCompleteRequest(Irp, IO_NO_INCREMENT);
235 return(STATUS_NOT_IMPLEMENTED);
240 IopCreateDriverObject(PDRIVER_OBJECT *DriverObject,
241 PUNICODE_STRING ServiceName,
244 PDRIVER_OBJECT Object;
245 HANDLE DriverHandle = 0;
247 WCHAR NameBuffer[MAX_PATH];
248 UNICODE_STRING DriverName;
249 OBJECT_ATTRIBUTES ObjectAttributes;
252 DPRINT("IopCreateDriverObject(%p '%wZ' %x)\n", DriverObject, ServiceName, FileSystem);
254 *DriverObject = NULL;
256 /* Create ModuleName string */
257 if (ServiceName != NULL)
259 if (FileSystem == TRUE)
260 wcscpy(NameBuffer, FILESYSTEM_ROOT_NAME);
262 wcscpy(NameBuffer, DRIVER_ROOT_NAME);
263 wcscat(NameBuffer, ServiceName->Buffer);
265 RtlInitUnicodeString(&DriverName,
267 DPRINT("Driver name: '%wZ'\n", &DriverName);
270 /* Initialize ObjectAttributes for ModuleObject */
271 InitializeObjectAttributes(&ObjectAttributes,
272 (ServiceName != NULL)? &DriverName : NULL,
277 /* Create module object */
278 Status = ObCreateObject(&DriverHandle,
279 STANDARD_RIGHTS_REQUIRED,
283 if (!NT_SUCCESS(Status))
288 NtClose(DriverHandle);
290 /* Create driver extension */
291 Object->DriverExtension = (PDRIVER_EXTENSION)
292 ExAllocatePoolWithTag(NonPagedPool,
293 sizeof(DRIVER_EXTENSION),
294 TAG_DRIVER_EXTENSION);
295 if (Object->DriverExtension == NULL)
298 return(STATUS_INSUFFICIENT_RESOURCES);
301 RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
303 Object->Type = InternalDriverType;
305 for (i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++)
307 Object->MajorFunction[i] = (PDRIVER_DISPATCH) IopDefaultDispatchFunction;
310 *DriverObject = Object;
312 return STATUS_SUCCESS;
316 IopAttachFilterDrivers(PDEVICE_NODE DeviceNode,
319 return STATUS_SUCCESS;
323 IopInitializeDevice(PDEVICE_NODE DeviceNode,
324 BOOLEAN BootDriversOnly)
326 IO_STATUS_BLOCK IoStatusBlock;
327 PDRIVER_OBJECT DriverObject;
328 IO_STACK_LOCATION Stack;
332 DriverObject = DeviceNode->DriverObject;
334 if (DriverObject->DriverExtension->AddDevice)
336 /* This is a Plug and Play driver */
337 DPRINT("Plug and Play driver found\n");
339 assert(DeviceNode->Pdo);
341 DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
342 DriverObject->DriverExtension->AddDevice);
343 Status = DriverObject->DriverExtension->AddDevice(
344 DriverObject, DeviceNode->Pdo);
345 if (!NT_SUCCESS(Status))
350 IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED);
352 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
354 Fdo = IoGetAttachedDeviceReference(DeviceNode->Pdo);
356 if (Fdo == DeviceNode->Pdo)
358 /* FIXME: What do we do? Unload the driver or just disable the device? */
359 DbgPrint("An FDO was not attached\n");
363 /* FIXME: Put some resources in the IRP for the device */
364 Stack.Parameters.StartDevice.AllocatedResources = NULL;
365 Stack.Parameters.StartDevice.AllocatedResourcesTranslated = NULL;
367 Status = IopInitiatePnpIrp(
372 if (!NT_SUCCESS(Status))
374 DPRINT("IopInitiatePnpIrp() failed\n");
375 ObDereferenceObject(Fdo);
379 if (Fdo->DeviceType == FILE_DEVICE_BUS_EXTENDER)
381 DPRINT("Bus extender found\n");
383 Status = IopInterrogateBusExtender(
384 DeviceNode, Fdo, BootDriversOnly);
385 if (!NT_SUCCESS(Status))
387 ObDereferenceObject(Fdo);
391 else if (Fdo->DeviceType == FILE_DEVICE_ACPI)
394 static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;
396 /* There can be only one system power device */
397 if (!SystemPowerDeviceNodeCreated)
399 PopSystemPowerDeviceNode = DeviceNode;
400 SystemPowerDeviceNodeCreated = TRUE;
404 ObDereferenceObject(Fdo);
407 return STATUS_SUCCESS;
411 IopInitializeService(
412 PDEVICE_NODE DeviceNode,
413 PUNICODE_STRING ImagePath)
415 PMODULE_OBJECT ModuleObject;
418 ModuleObject = LdrGetModuleObject(&DeviceNode->ServiceName);
419 if (ModuleObject == NULL)
421 /* The module is currently not loaded, so load it now */
423 Status = LdrLoadModule(ImagePath, &ModuleObject);
424 if (!NT_SUCCESS(Status))
426 /* FIXME: Log the error */
427 CPRINT("Driver load failed\n");
431 Status = IopInitializeDriver(ModuleObject->EntryPoint, DeviceNode, FALSE);
432 if (!NT_SUCCESS(Status))
434 LdrUnloadModule(ModuleObject);
436 /* FIXME: Log the error */
437 CPRINT("A driver failed to initialize\n");
442 Status = IopInitializeDevice(DeviceNode, TRUE);
448 IopInitializeDeviceNodeService(PDEVICE_NODE DeviceNode)
450 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
451 UNICODE_STRING ImagePath;
455 Status = RtlpGetRegistryHandle(
456 RTL_REGISTRY_SERVICES,
457 DeviceNode->ServiceName.Buffer,
460 if (!NT_SUCCESS(Status))
462 DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status);
466 RtlZeroMemory(QueryTable, sizeof(QueryTable));
468 RtlInitUnicodeString(&ImagePath, NULL);
470 QueryTable[0].Name = L"ImagePath";
471 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
472 QueryTable[0].EntryContext = &ImagePath;
474 Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
481 DPRINT("RtlQueryRegistryValues() returned status %x\n", Status);
483 if (NT_SUCCESS(Status))
485 DPRINT("Got ImagePath %S\n", ImagePath.Buffer);
487 Status = IopInitializeService(DeviceNode, &ImagePath);
489 RtlFreeUnicodeString(&ImagePath);
496 IopInitializeDriver(PDRIVER_INITIALIZE DriverEntry,
497 PDEVICE_NODE DeviceNode,
498 BOOLEAN FileSystemDriver)
500 * FUNCTION: Called to initalize a loaded driver
502 * DriverEntry = Pointer to driver entry routine
503 * DeviceNode = Pointer to device node
506 WCHAR RegistryKeyBuffer[MAX_PATH];
507 PDRIVER_OBJECT DriverObject;
508 UNICODE_STRING RegistryKey;
511 DPRINT("IopInitializeDriver(DriverEntry %08lx, DeviceNode %08lx)\n",
512 DriverEntry, DeviceNode);
514 Status = IopCreateDriverObject(&DriverObject,
515 &DeviceNode->ServiceName,
517 if (!NT_SUCCESS(Status))
522 DeviceNode->DriverObject = DriverObject;
524 if (DeviceNode->ServiceName.Buffer)
526 wcscpy(RegistryKeyBuffer, DRIVER_REGISTRY_KEY_BASENAME);
527 wcscat(RegistryKeyBuffer, DeviceNode->ServiceName.Buffer);
528 RtlInitUnicodeString(&RegistryKey, RegistryKeyBuffer);
532 RtlInitUnicodeString(&RegistryKey, NULL);
535 DPRINT("RegistryKey: %wZ\n", &RegistryKey);
536 DPRINT("Calling driver entrypoint at %08lx\n", DriverEntry);
538 Status = DriverEntry(DriverObject, &RegistryKey);
539 if (!NT_SUCCESS(Status))
541 DeviceNode->DriverObject = NULL;
542 ExFreePool(DriverObject->DriverExtension);
543 ObMakeTemporaryObject(DriverObject);
544 ObDereferenceObject(DriverObject);
548 Status = IopInitializeDevice(DeviceNode, TRUE);
555 IoAttachDevice(PDEVICE_OBJECT SourceDevice,
556 PUNICODE_STRING TargetDevice,
557 PDEVICE_OBJECT* AttachedDevice)
559 * FUNCTION: Layers a device over the highest device in a device stack
561 * SourceDevice = Device to attached
562 * TargetDevice = Name of the target device
563 * AttachedDevice (OUT) = Caller storage for the device attached to
569 #endif /* LIBCAPTIVE */
572 IopCreateDevice(PVOID ObjectBody,
575 POBJECT_ATTRIBUTES ObjectAttributes)
578 DPRINT("IopCreateDevice(ObjectBody %x, Parent %x, RemainingPath %S)\n",
579 ObjectBody, Parent, RemainingPath);
581 if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
583 return(STATUS_UNSUCCESSFUL);
586 return(STATUS_SUCCESS);
590 IoCreateDevice(PDRIVER_OBJECT DriverObject,
591 ULONG DeviceExtensionSize,
592 PUNICODE_STRING DeviceName,
593 DEVICE_TYPE DeviceType,
594 ULONG DeviceCharacteristics,
596 PDEVICE_OBJECT* DeviceObject)
598 * FUNCTION: Allocates memory for and intializes a device object for use for
601 * DriverObject : Driver object passed by iomgr when the driver was
603 * DeviceExtensionSize : Number of bytes for the device extension
604 * DeviceName : Unicode name of device
605 * DeviceType : Device type
606 * DeviceCharacteristics : Bit mask of device characteristics
607 * Exclusive : True if only one thread can access the device at a
611 * DeviceObject : Contains a pointer to allocated device object
612 * if the call succeeded
613 * NOTES: See the DDK documentation for more information
616 PDEVICE_OBJECT CreatedDeviceObject;
617 OBJECT_ATTRIBUTES ObjectAttributes;
621 assert_irql(PASSIVE_LEVEL);
623 if (DeviceName != NULL)
625 DPRINT("IoCreateDevice(DriverObject %x, DeviceName %S)\n",DriverObject,
630 DPRINT("IoCreateDevice(DriverObject %x)\n",DriverObject);
633 if (DeviceName != NULL)
635 InitializeObjectAttributes(&ObjectAttributes,DeviceName,0,NULL,NULL);
636 Status = ObCreateObject(&DeviceHandle,
640 (PVOID*)&CreatedDeviceObject);
644 Status = ObCreateObject(&DeviceHandle,
648 (PVOID*)&CreatedDeviceObject);
651 *DeviceObject = NULL;
653 if (!NT_SUCCESS(Status))
655 DPRINT("IoCreateDevice() ObCreateObject failed, status: 0x%08X\n", Status);
659 if (DriverObject->DeviceObject == NULL)
661 DriverObject->DeviceObject = CreatedDeviceObject;
662 CreatedDeviceObject->NextDevice = NULL;
666 CreatedDeviceObject->NextDevice = DriverObject->DeviceObject;
667 DriverObject->DeviceObject = CreatedDeviceObject;
670 CreatedDeviceObject->Type = DeviceType;
671 CreatedDeviceObject->DriverObject = DriverObject;
672 CreatedDeviceObject->CurrentIrp = NULL;
673 CreatedDeviceObject->Flags = 0;
675 CreatedDeviceObject->DeviceExtension =
676 ExAllocatePoolWithTag(NonPagedPool, DeviceExtensionSize,
677 TAG_DEVICE_EXTENSION);
678 if (DeviceExtensionSize > 0 && CreatedDeviceObject->DeviceExtension == NULL)
680 ExFreePool(CreatedDeviceObject);
681 DPRINT("IoCreateDevice() ExAllocatePoolWithTag failed, returning: 0x%08X\n", STATUS_INSUFFICIENT_RESOURCES);
682 return(STATUS_INSUFFICIENT_RESOURCES);
685 if (DeviceExtensionSize > 0)
687 RtlZeroMemory(CreatedDeviceObject->DeviceExtension,
688 DeviceExtensionSize);
691 CreatedDeviceObject->AttachedDevice = NULL;
692 CreatedDeviceObject->DeviceType = DeviceType;
693 CreatedDeviceObject->StackSize = 1;
694 CreatedDeviceObject->AlignmentRequirement = 1;
695 KeInitializeDeviceQueue(&CreatedDeviceObject->DeviceQueue);
697 KeInitializeEvent(&CreatedDeviceObject->DeviceLock,
698 SynchronizationEvent,
701 /* FIXME: Do we need to add network drives too?! */
702 if (CreatedDeviceObject->DeviceType == FILE_DEVICE_DISK ||
703 CreatedDeviceObject->DeviceType == FILE_DEVICE_CD_ROM ||
704 CreatedDeviceObject->DeviceType == FILE_DEVICE_TAPE)
706 IoAttachVpb(CreatedDeviceObject);
709 *DeviceObject = CreatedDeviceObject;
711 return(STATUS_SUCCESS);
718 IoOpenDeviceInstanceKey (
727 return(STATUS_NOT_IMPLEMENTED);
733 IoQueryDeviceEnumInfo (
742 #endif /* LIBCAPTIVE */