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);
168 IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject)
170 PDEVICE_OBJECT Current = DeviceObject;
172 // DPRINT("IoGetAttachedDevice(DeviceObject %x)\n",DeviceObject);
174 while (Current->AttachedDevice!=NULL)
176 Current = Current->AttachedDevice;
177 // DPRINT("Current %x\n",Current);
180 // DPRINT("IoGetAttachedDevice() = %x\n",DeviceObject);
186 IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
188 PDEVICE_OBJECT Current = DeviceObject;
190 while (Current->AttachedDevice!=NULL)
192 Current = Current->AttachedDevice;
195 ObReferenceObject(Current);
199 PDEVICE_OBJECT STDCALL
200 IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice,
201 PDEVICE_OBJECT TargetDevice)
203 PDEVICE_OBJECT AttachedDevice;
205 DPRINT("IoAttachDeviceToDeviceStack(SourceDevice %x, TargetDevice %x)\n",
206 SourceDevice,TargetDevice);
208 AttachedDevice = IoGetAttachedDevice(TargetDevice);
209 AttachedDevice->AttachedDevice = SourceDevice;
210 SourceDevice->AttachedDevice = NULL;
211 SourceDevice->StackSize = AttachedDevice->StackSize + 1;
212 SourceDevice->Vpb = AttachedDevice->Vpb;
213 return(AttachedDevice);
217 IoRegisterDriverReinitialization(PDRIVER_OBJECT DriverObject,
218 PDRIVER_REINITIALIZE ReinitRoutine,
225 IopDefaultDispatchFunction(PDEVICE_OBJECT DeviceObject,
228 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
229 Irp->IoStatus.Information = 0;
231 IoCompleteRequest(Irp, IO_NO_INCREMENT);
232 return(STATUS_NOT_IMPLEMENTED);
237 IopCreateDriverObject(PDRIVER_OBJECT *DriverObject,
238 PUNICODE_STRING ServiceName,
241 PDRIVER_OBJECT Object;
242 HANDLE DriverHandle = 0;
244 WCHAR NameBuffer[MAX_PATH];
245 UNICODE_STRING DriverName;
246 OBJECT_ATTRIBUTES ObjectAttributes;
249 DPRINT("IopCreateDriverObject(%p '%wZ' %x)\n", DriverObject, ServiceName, FileSystem);
251 *DriverObject = NULL;
253 /* Create ModuleName string */
254 if (ServiceName != NULL)
256 if (FileSystem == TRUE)
257 wcscpy(NameBuffer, FILESYSTEM_ROOT_NAME);
259 wcscpy(NameBuffer, DRIVER_ROOT_NAME);
260 wcscat(NameBuffer, ServiceName->Buffer);
262 RtlInitUnicodeString(&DriverName,
264 DPRINT("Driver name: '%wZ'\n", &DriverName);
267 /* Initialize ObjectAttributes for ModuleObject */
268 InitializeObjectAttributes(&ObjectAttributes,
269 (ServiceName != NULL)? &DriverName : NULL,
274 /* Create module object */
275 Status = ObCreateObject(&DriverHandle,
276 STANDARD_RIGHTS_REQUIRED,
280 if (!NT_SUCCESS(Status))
285 NtClose(DriverHandle);
287 /* Create driver extension */
288 Object->DriverExtension = (PDRIVER_EXTENSION)
289 ExAllocatePoolWithTag(NonPagedPool,
290 sizeof(DRIVER_EXTENSION),
291 TAG_DRIVER_EXTENSION);
292 if (Object->DriverExtension == NULL)
295 return(STATUS_INSUFFICIENT_RESOURCES);
298 RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
300 Object->Type = InternalDriverType;
302 for (i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++)
304 Object->MajorFunction[i] = (PDRIVER_DISPATCH) IopDefaultDispatchFunction;
307 *DriverObject = Object;
309 return STATUS_SUCCESS;
313 IopAttachFilterDrivers(PDEVICE_NODE DeviceNode,
316 return STATUS_SUCCESS;
320 IopInitializeDevice(PDEVICE_NODE DeviceNode,
321 BOOLEAN BootDriversOnly)
323 IO_STATUS_BLOCK IoStatusBlock;
324 PDRIVER_OBJECT DriverObject;
325 IO_STACK_LOCATION Stack;
329 DriverObject = DeviceNode->DriverObject;
331 if (DriverObject->DriverExtension->AddDevice)
333 /* This is a Plug and Play driver */
334 DPRINT("Plug and Play driver found\n");
336 assert(DeviceNode->Pdo);
338 DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
339 DriverObject->DriverExtension->AddDevice);
340 Status = DriverObject->DriverExtension->AddDevice(
341 DriverObject, DeviceNode->Pdo);
342 if (!NT_SUCCESS(Status))
347 IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED);
349 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
351 Fdo = IoGetAttachedDeviceReference(DeviceNode->Pdo);
353 if (Fdo == DeviceNode->Pdo)
355 /* FIXME: What do we do? Unload the driver or just disable the device? */
356 DbgPrint("An FDO was not attached\n");
360 /* FIXME: Put some resources in the IRP for the device */
361 Stack.Parameters.StartDevice.AllocatedResources = NULL;
362 Stack.Parameters.StartDevice.AllocatedResourcesTranslated = NULL;
364 Status = IopInitiatePnpIrp(
369 if (!NT_SUCCESS(Status))
371 DPRINT("IopInitiatePnpIrp() failed\n");
372 ObDereferenceObject(Fdo);
376 if (Fdo->DeviceType == FILE_DEVICE_BUS_EXTENDER)
378 DPRINT("Bus extender found\n");
380 Status = IopInterrogateBusExtender(
381 DeviceNode, Fdo, BootDriversOnly);
382 if (!NT_SUCCESS(Status))
384 ObDereferenceObject(Fdo);
388 else if (Fdo->DeviceType == FILE_DEVICE_ACPI)
391 static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;
393 /* There can be only one system power device */
394 if (!SystemPowerDeviceNodeCreated)
396 PopSystemPowerDeviceNode = DeviceNode;
397 SystemPowerDeviceNodeCreated = TRUE;
401 ObDereferenceObject(Fdo);
404 return STATUS_SUCCESS;
408 IopInitializeService(
409 PDEVICE_NODE DeviceNode,
410 PUNICODE_STRING ImagePath)
412 PMODULE_OBJECT ModuleObject;
415 ModuleObject = LdrGetModuleObject(&DeviceNode->ServiceName);
416 if (ModuleObject == NULL)
418 /* The module is currently not loaded, so load it now */
420 Status = LdrLoadModule(ImagePath, &ModuleObject);
421 if (!NT_SUCCESS(Status))
423 /* FIXME: Log the error */
424 CPRINT("Driver load failed\n");
428 Status = IopInitializeDriver(ModuleObject->EntryPoint, DeviceNode, FALSE);
429 if (!NT_SUCCESS(Status))
431 LdrUnloadModule(ModuleObject);
433 /* FIXME: Log the error */
434 CPRINT("A driver failed to initialize\n");
439 Status = IopInitializeDevice(DeviceNode, TRUE);
445 IopInitializeDeviceNodeService(PDEVICE_NODE DeviceNode)
447 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
448 UNICODE_STRING ImagePath;
452 Status = RtlpGetRegistryHandle(
453 RTL_REGISTRY_SERVICES,
454 DeviceNode->ServiceName.Buffer,
457 if (!NT_SUCCESS(Status))
459 DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status);
463 RtlZeroMemory(QueryTable, sizeof(QueryTable));
465 RtlInitUnicodeString(&ImagePath, NULL);
467 QueryTable[0].Name = L"ImagePath";
468 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
469 QueryTable[0].EntryContext = &ImagePath;
471 Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
478 DPRINT("RtlQueryRegistryValues() returned status %x\n", Status);
480 if (NT_SUCCESS(Status))
482 DPRINT("Got ImagePath %S\n", ImagePath.Buffer);
484 Status = IopInitializeService(DeviceNode, &ImagePath);
486 RtlFreeUnicodeString(&ImagePath);
493 IopInitializeDriver(PDRIVER_INITIALIZE DriverEntry,
494 PDEVICE_NODE DeviceNode,
495 BOOLEAN FileSystemDriver)
497 * FUNCTION: Called to initalize a loaded driver
499 * DriverEntry = Pointer to driver entry routine
500 * DeviceNode = Pointer to device node
503 WCHAR RegistryKeyBuffer[MAX_PATH];
504 PDRIVER_OBJECT DriverObject;
505 UNICODE_STRING RegistryKey;
508 DPRINT("IopInitializeDriver(DriverEntry %08lx, DeviceNode %08lx)\n",
509 DriverEntry, DeviceNode);
511 Status = IopCreateDriverObject(&DriverObject,
512 &DeviceNode->ServiceName,
514 if (!NT_SUCCESS(Status))
519 DeviceNode->DriverObject = DriverObject;
521 if (DeviceNode->ServiceName.Buffer)
523 wcscpy(RegistryKeyBuffer, DRIVER_REGISTRY_KEY_BASENAME);
524 wcscat(RegistryKeyBuffer, DeviceNode->ServiceName.Buffer);
525 RtlInitUnicodeString(&RegistryKey, RegistryKeyBuffer);
529 RtlInitUnicodeString(&RegistryKey, NULL);
532 DPRINT("RegistryKey: %wZ\n", &RegistryKey);
533 DPRINT("Calling driver entrypoint at %08lx\n", DriverEntry);
535 Status = DriverEntry(DriverObject, &RegistryKey);
536 if (!NT_SUCCESS(Status))
538 DeviceNode->DriverObject = NULL;
539 ExFreePool(DriverObject->DriverExtension);
540 ObMakeTemporaryObject(DriverObject);
541 ObDereferenceObject(DriverObject);
545 Status = IopInitializeDevice(DeviceNode, TRUE);
552 IoAttachDevice(PDEVICE_OBJECT SourceDevice,
553 PUNICODE_STRING TargetDevice,
554 PDEVICE_OBJECT* AttachedDevice)
556 * FUNCTION: Layers a device over the highest device in a device stack
558 * SourceDevice = Device to attached
559 * TargetDevice = Name of the target device
560 * AttachedDevice (OUT) = Caller storage for the device attached to
568 IopCreateDevice(PVOID ObjectBody,
571 POBJECT_ATTRIBUTES ObjectAttributes)
574 DPRINT("IopCreateDevice(ObjectBody %x, Parent %x, RemainingPath %S)\n",
575 ObjectBody, Parent, RemainingPath);
577 if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
579 return(STATUS_UNSUCCESSFUL);
582 return(STATUS_SUCCESS);
585 #endif /* LIBCAPTIVE */
588 IoCreateDevice(PDRIVER_OBJECT DriverObject,
589 ULONG DeviceExtensionSize,
590 PUNICODE_STRING DeviceName,
591 DEVICE_TYPE DeviceType,
592 ULONG DeviceCharacteristics,
594 PDEVICE_OBJECT* DeviceObject)
596 * FUNCTION: Allocates memory for and intializes a device object for use for
599 * DriverObject : Driver object passed by iomgr when the driver was
601 * DeviceExtensionSize : Number of bytes for the device extension
602 * DeviceName : Unicode name of device
603 * DeviceType : Device type
604 * DeviceCharacteristics : Bit mask of device characteristics
605 * Exclusive : True if only one thread can access the device at a
609 * DeviceObject : Contains a pointer to allocated device object
610 * if the call succeeded
611 * NOTES: See the DDK documentation for more information
614 PDEVICE_OBJECT CreatedDeviceObject;
615 OBJECT_ATTRIBUTES ObjectAttributes;
619 assert_irql(PASSIVE_LEVEL);
621 if (DeviceName != NULL)
623 DPRINT("IoCreateDevice(DriverObject %x, DeviceName %S)\n",DriverObject,
628 DPRINT("IoCreateDevice(DriverObject %x)\n",DriverObject);
631 if (DeviceName != NULL)
633 InitializeObjectAttributes(&ObjectAttributes,DeviceName,0,NULL,NULL);
634 Status = ObCreateObject(&DeviceHandle,
638 (PVOID*)&CreatedDeviceObject);
642 Status = ObCreateObject(&DeviceHandle,
646 (PVOID*)&CreatedDeviceObject);
649 *DeviceObject = NULL;
651 if (!NT_SUCCESS(Status))
653 DPRINT("IoCreateDevice() ObCreateObject failed, status: 0x%08X\n", Status);
657 if (DriverObject->DeviceObject == NULL)
659 DriverObject->DeviceObject = CreatedDeviceObject;
660 CreatedDeviceObject->NextDevice = NULL;
664 CreatedDeviceObject->NextDevice = DriverObject->DeviceObject;
665 DriverObject->DeviceObject = CreatedDeviceObject;
668 CreatedDeviceObject->Type = DeviceType;
669 CreatedDeviceObject->DriverObject = DriverObject;
670 CreatedDeviceObject->CurrentIrp = NULL;
671 CreatedDeviceObject->Flags = 0;
673 CreatedDeviceObject->DeviceExtension =
674 ExAllocatePoolWithTag(NonPagedPool, DeviceExtensionSize,
675 TAG_DEVICE_EXTENSION);
676 if (DeviceExtensionSize > 0 && CreatedDeviceObject->DeviceExtension == NULL)
678 ExFreePool(CreatedDeviceObject);
679 DPRINT("IoCreateDevice() ExAllocatePoolWithTag failed, returning: 0x%08X\n", STATUS_INSUFFICIENT_RESOURCES);
680 return(STATUS_INSUFFICIENT_RESOURCES);
683 if (DeviceExtensionSize > 0)
685 RtlZeroMemory(CreatedDeviceObject->DeviceExtension,
686 DeviceExtensionSize);
689 CreatedDeviceObject->AttachedDevice = NULL;
690 CreatedDeviceObject->DeviceType = DeviceType;
691 CreatedDeviceObject->StackSize = 1;
692 CreatedDeviceObject->AlignmentRequirement = 1;
693 KeInitializeDeviceQueue(&CreatedDeviceObject->DeviceQueue);
695 KeInitializeEvent(&CreatedDeviceObject->DeviceLock,
696 SynchronizationEvent,
699 /* FIXME: Do we need to add network drives too?! */
700 if (CreatedDeviceObject->DeviceType == FILE_DEVICE_DISK ||
701 CreatedDeviceObject->DeviceType == FILE_DEVICE_CD_ROM ||
702 CreatedDeviceObject->DeviceType == FILE_DEVICE_TAPE)
704 IoAttachVpb(CreatedDeviceObject);
707 *DeviceObject = CreatedDeviceObject;
709 return(STATUS_SUCCESS);
716 IoOpenDeviceInstanceKey (
725 return(STATUS_NOT_IMPLEMENTED);
731 IoQueryDeviceEnumInfo (
740 #endif /* LIBCAPTIVE */