2 * PROJECT: ReactOS Kernel
3 * COPYRIGHT: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/pnpmgr/pnpreport.c
5 * PURPOSE: Device Changes Reporting Functions
6 * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
9 /* INCLUDES ******************************************************************/
17 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
21 IopAssignDeviceResources(
22 IN PDEVICE_NODE DeviceNode
,
23 OUT ULONG
*pRequiredSize
);
26 IopSetDeviceInstanceData(HANDLE InstanceKey
,
27 PDEVICE_NODE DeviceNode
);
30 IopTranslateDeviceResources(
31 IN PDEVICE_NODE DeviceNode
,
32 IN ULONG RequiredSize
);
35 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
39 IopUpdateResourceMapForPnPDevice(
40 IN PDEVICE_NODE DeviceNode
);
43 IopDetectResourceConflict(
44 IN PCM_RESOURCE_LIST ResourceList
);
46 /* PRIVATE FUNCTIONS *********************************************************/
49 IopGetInterfaceTypeString(INTERFACE_TYPE IfType
)
63 return L
"MicroChannel";
66 return L
"TurboChannel";
89 case ProcessorInternal
:
90 return L
"ProcessorInternal";
102 DPRINT1("Invalid bus type: %d\n", IfType
);
107 /* PUBLIC FUNCTIONS **********************************************************/
114 IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject
,
115 IN INTERFACE_TYPE LegacyBusType
,
118 IN PCM_RESOURCE_LIST ResourceList
,
119 IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements OPTIONAL
,
120 IN BOOLEAN ResourceAssigned
,
121 IN OUT PDEVICE_OBJECT
*DeviceObject OPTIONAL
)
123 PDEVICE_NODE DeviceNode
;
127 ULONG RequiredLength
;
128 UNICODE_STRING ValueName
, ServiceName
;
129 WCHAR HardwareId
[256];
133 DPRINT("IoReportDetectedDevice (DeviceObject %p, *DeviceObject %p)\n",
134 DeviceObject
, DeviceObject
? *DeviceObject
: NULL
);
136 /* Create the service name (eg. ACPI_HAL) */
137 ServiceName
.Buffer
= DriverObject
->DriverName
.Buffer
+
138 sizeof(DRIVER_ROOT_NAME
) / sizeof(WCHAR
) - 1;
139 ServiceName
.Length
= DriverObject
->DriverName
.Length
-
140 sizeof(DRIVER_ROOT_NAME
) + sizeof(WCHAR
);
141 ServiceName
.MaximumLength
= ServiceName
.Length
;
143 /* If the interface type is unknown, treat it as internal */
144 if (LegacyBusType
== InterfaceTypeUndefined
)
145 LegacyBusType
= Internal
;
147 /* Get the string equivalent of the interface type */
148 IfString
= IopGetInterfaceTypeString(LegacyBusType
);
150 /* If NULL is returned then it's a bad type */
152 return STATUS_INVALID_PARAMETER
;
154 /* We use the caller's PDO if they supplied one */
155 if (DeviceObject
&& *DeviceObject
)
158 DeviceNode
= IopGetDeviceNode(*DeviceObject
);
163 Status
= PnpRootCreateDevice(&ServiceName
,
166 if (!NT_SUCCESS(Status
))
168 DPRINT("PnpRootCreateDevice() failed (Status 0x%08lx)\n", Status
);
172 /* Create the device node for the new PDO */
173 Status
= IopCreateDeviceNode(IopRootDeviceNode
,
178 if (!NT_SUCCESS(Status
))
180 DPRINT("IopCreateDeviceNode() failed (Status 0x%08lx)\n", Status
);
185 /* We don't call AddDevice for devices reported this way */
186 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
188 /* We don't send IRP_MN_START_DEVICE */
189 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
191 /* This is a legacy driver for this device */
192 IopDeviceNodeSetFlag(DeviceNode
, DNF_LEGACY_DRIVER
);
194 /* Perform a manual configuration of our device */
195 IopActionInterrogateDeviceStack(DeviceNode
, DeviceNode
->Parent
);
196 IopActionConfigureChildServices(DeviceNode
, DeviceNode
->Parent
);
198 /* Open a handle to the instance path key */
199 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, &InstanceKey
);
200 if (!NT_SUCCESS(Status
))
203 /* Add DETECTEDInterfaceType\DriverName */
205 IdLength
+= swprintf(&HardwareId
[IdLength
],
209 HardwareId
[IdLength
++] = UNICODE_NULL
;
211 /* Add DETECTED\DriverName */
212 IdLength
+= swprintf(&HardwareId
[IdLength
],
215 HardwareId
[IdLength
++] = UNICODE_NULL
;
217 /* Terminate the string with another null */
218 HardwareId
[IdLength
] = UNICODE_NULL
;
220 /* Store the value for CompatibleIDs */
221 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
222 Status
= ZwSetValueKey(InstanceKey
, &ValueName
, 0, REG_MULTI_SZ
, HardwareId
, IdLength
* sizeof(WCHAR
));
223 if (!NT_SUCCESS(Status
))
225 DPRINT("Failed to write the compatible IDs: 0x%x\n", Status
);
226 ZwClose(InstanceKey
);
230 /* Add a hardware ID if the driver didn't report one */
231 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
232 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
234 /* Just use our most specific compatible ID */
236 IdLength
+= swprintf(&HardwareId
[IdLength
],
240 HardwareId
[++IdLength
] = UNICODE_NULL
;
242 /* Write the value to the registry */
243 Status
= ZwSetValueKey(InstanceKey
, &ValueName
, 0, REG_SZ
, HardwareId
, IdLength
* sizeof(WCHAR
));
244 if (!NT_SUCCESS(Status
))
246 DPRINT("Failed to write the hardware ID: 0x%x\n", Status
);
247 ZwClose(InstanceKey
);
252 /* Assign the resources to the device node */
253 DeviceNode
->BootResources
= ResourceList
;
254 DeviceNode
->ResourceRequirements
= ResourceRequirements
;
256 /* Set appropriate flags */
257 if (DeviceNode
->BootResources
)
258 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
260 if (DeviceNode
->ResourceRequirements
)
261 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
263 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
265 /* Write the resource information to the registry */
266 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
268 /* Close the instance key handle */
269 ZwClose(InstanceKey
);
271 /* If the caller didn't get the resources assigned for us, do it now */
272 if (!ResourceAssigned
)
274 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
275 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
276 if (NT_SUCCESS(Status
))
278 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
279 if (NT_SUCCESS(Status
))
280 Status
= IopUpdateResourceMapForPnPDevice(DeviceNode
);
282 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
284 /* See if we failed */
285 if (!NT_SUCCESS(Status
))
287 DPRINT("Assigning resources failed: 0x%x\n", Status
);
292 /* Report the device's enumeration to umpnpmgr */
293 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
294 &DeviceNode
->InstancePath
);
296 /* Report the device's arrival to umpnpmgr */
297 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
298 &DeviceNode
->InstancePath
);
300 DPRINT1("Reported device: %S (%wZ)\n", HardwareId
, &DeviceNode
->InstancePath
);
303 if (DeviceObject
) *DeviceObject
= Pdo
;
305 return STATUS_SUCCESS
;
313 IoReportResourceForDetection(IN PDRIVER_OBJECT DriverObject
,
314 IN PCM_RESOURCE_LIST DriverList OPTIONAL
,
315 IN ULONG DriverListSize OPTIONAL
,
316 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
317 IN PCM_RESOURCE_LIST DeviceList OPTIONAL
,
318 IN ULONG DeviceListSize OPTIONAL
,
319 OUT PBOOLEAN ConflictDetected
)
321 PCM_RESOURCE_LIST ResourceList
;
324 *ConflictDetected
= FALSE
;
326 if (!DriverList
&& !DeviceList
)
327 return STATUS_INVALID_PARAMETER
;
329 /* Find the real list */
331 ResourceList
= DeviceList
;
333 ResourceList
= DriverList
;
335 /* Look for a resource conflict */
336 Status
= IopDetectResourceConflict(ResourceList
);
337 if (Status
== STATUS_CONFLICTING_ADDRESSES
)
340 *ConflictDetected
= TRUE
;
342 else if (NT_SUCCESS(Status
))
344 /* Looks like we're good to go */
346 /* TODO: Claim the resources in the ResourceMap */
354 IopSetEvent(IN PVOID Context
)
356 PKEVENT Event
= Context
;
359 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
367 IoReportTargetDeviceChange(IN PDEVICE_OBJECT PhysicalDeviceObject
,
368 IN PVOID NotificationStructure
)
371 return STATUS_NOT_IMPLEMENTED
;
379 IoReportTargetDeviceChangeAsynchronous(IN PDEVICE_OBJECT PhysicalDeviceObject
,
380 IN PVOID NotificationStructure
,
381 IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL
,
382 IN PVOID Context OPTIONAL
)
385 return STATUS_NOT_IMPLEMENTED
;