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
,
18 IN ULONG CreateOptions
,
22 IopAssignDeviceResources(
23 IN PDEVICE_NODE DeviceNode
,
24 OUT ULONG
*pRequiredSize
);
27 IopSetDeviceInstanceData(HANDLE InstanceKey
,
28 PDEVICE_NODE DeviceNode
);
31 IopTranslateDeviceResources(
32 IN PDEVICE_NODE DeviceNode
,
33 IN ULONG RequiredSize
);
36 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
40 IopUpdateResourceMapForPnPDevice(
41 IN PDEVICE_NODE DeviceNode
);
44 IopDetectResourceConflict(
45 IN PCM_RESOURCE_LIST ResourceList
);
47 /* PRIVATE FUNCTIONS *********************************************************/
50 IopGetInterfaceTypeString(INTERFACE_TYPE IfType
)
64 return L
"MicroChannel";
67 return L
"TurboChannel";
90 case ProcessorInternal
:
91 return L
"ProcessorInternal";
103 DPRINT1("Invalid bus type: %d\n", IfType
);
108 /* PUBLIC FUNCTIONS **********************************************************/
115 IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject
,
116 IN INTERFACE_TYPE LegacyBusType
,
119 IN PCM_RESOURCE_LIST ResourceList
,
120 IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements OPTIONAL
,
121 IN BOOLEAN ResourceAssigned
,
122 IN OUT PDEVICE_OBJECT
*DeviceObject OPTIONAL
)
124 PDEVICE_NODE DeviceNode
;
128 ULONG RequiredLength
;
129 UNICODE_STRING ValueName
, ServiceName
;
130 WCHAR HardwareId
[256];
134 DPRINT("IoReportDetectedDevice (DeviceObject %p, *DeviceObject %p)\n",
135 DeviceObject
, DeviceObject
? *DeviceObject
: NULL
);
137 /* Create the service name (eg. ACPI_HAL) */
138 ServiceName
.Buffer
= DriverObject
->DriverName
.Buffer
+
139 sizeof(DRIVER_ROOT_NAME
) / sizeof(WCHAR
) - 1;
140 ServiceName
.Length
= DriverObject
->DriverName
.Length
-
141 sizeof(DRIVER_ROOT_NAME
) + sizeof(WCHAR
);
142 ServiceName
.MaximumLength
= ServiceName
.Length
;
144 /* If the interface type is unknown, treat it as internal */
145 if (LegacyBusType
== InterfaceTypeUndefined
)
146 LegacyBusType
= Internal
;
148 /* Get the string equivalent of the interface type */
149 IfString
= IopGetInterfaceTypeString(LegacyBusType
);
151 /* If NULL is returned then it's a bad type */
153 return STATUS_INVALID_PARAMETER
;
155 /* We use the caller's PDO if they supplied one */
156 if (DeviceObject
&& *DeviceObject
)
159 DeviceNode
= IopGetDeviceNode(*DeviceObject
);
164 Status
= PnpRootCreateDevice(&ServiceName
,
167 if (!NT_SUCCESS(Status
))
169 DPRINT("PnpRootCreateDevice() failed (Status 0x%08lx)\n", Status
);
173 /* Create the device node for the new PDO */
174 Status
= IopCreateDeviceNode(IopRootDeviceNode
,
179 if (!NT_SUCCESS(Status
))
181 DPRINT("IopCreateDeviceNode() failed (Status 0x%08lx)\n", Status
);
186 /* We don't call AddDevice for devices reported this way */
187 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
189 /* We don't send IRP_MN_START_DEVICE */
190 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
192 /* This is a legacy driver for this device */
193 IopDeviceNodeSetFlag(DeviceNode
, DNF_LEGACY_DRIVER
);
195 /* Perform a manual configuration of our device */
196 IopActionInterrogateDeviceStack(DeviceNode
, DeviceNode
->Parent
);
197 IopActionConfigureChildServices(DeviceNode
, DeviceNode
->Parent
);
199 /* Open a handle to the instance path key */
200 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
201 if (!NT_SUCCESS(Status
))
204 /* Add DETECTEDInterfaceType\DriverName */
206 IdLength
+= swprintf(&HardwareId
[IdLength
],
210 HardwareId
[IdLength
++] = UNICODE_NULL
;
212 /* Add DETECTED\DriverName */
213 IdLength
+= swprintf(&HardwareId
[IdLength
],
216 HardwareId
[IdLength
++] = UNICODE_NULL
;
218 /* Terminate the string with another null */
219 HardwareId
[IdLength
] = UNICODE_NULL
;
221 /* Store the value for CompatibleIDs */
222 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
223 Status
= ZwSetValueKey(InstanceKey
, &ValueName
, 0, REG_MULTI_SZ
, HardwareId
, IdLength
* sizeof(WCHAR
));
224 if (!NT_SUCCESS(Status
))
226 DPRINT("Failed to write the compatible IDs: 0x%x\n", Status
);
227 ZwClose(InstanceKey
);
231 /* Add a hardware ID if the driver didn't report one */
232 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
233 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
235 /* Just use our most specific compatible ID */
237 IdLength
+= swprintf(&HardwareId
[IdLength
],
241 HardwareId
[++IdLength
] = UNICODE_NULL
;
243 /* Write the value to the registry */
244 Status
= ZwSetValueKey(InstanceKey
, &ValueName
, 0, REG_SZ
, HardwareId
, IdLength
* sizeof(WCHAR
));
245 if (!NT_SUCCESS(Status
))
247 DPRINT("Failed to write the hardware ID: 0x%x\n", Status
);
248 ZwClose(InstanceKey
);
253 /* Assign the resources to the device node */
254 DeviceNode
->BootResources
= ResourceList
;
255 DeviceNode
->ResourceRequirements
= ResourceRequirements
;
257 /* Set appropriate flags */
258 if (DeviceNode
->BootResources
)
259 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
261 if (DeviceNode
->ResourceRequirements
)
262 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
264 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
266 /* Write the resource information to the registry */
267 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
269 /* If the caller didn't get the resources assigned for us, do it now */
270 if (!ResourceAssigned
)
272 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
273 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
274 if (NT_SUCCESS(Status
))
276 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
277 if (NT_SUCCESS(Status
))
279 Status
= IopUpdateResourceMapForPnPDevice(DeviceNode
);
280 if (NT_SUCCESS(Status
) && DeviceNode
->ResourceList
)
282 RtlInitUnicodeString(&ValueName
, L
"AllocConfig");
283 Status
= ZwSetValueKey(InstanceKey
,
287 DeviceNode
->ResourceList
,
288 CM_RESOURCE_LIST_SIZE(DeviceNode
->ResourceList
));
292 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
294 /* See if we failed */
295 if (!NT_SUCCESS(Status
))
297 DPRINT("Assigning resources failed: 0x%x\n", Status
);
298 ZwClose(InstanceKey
);
303 /* Close the instance key handle */
304 ZwClose(InstanceKey
);
306 /* Report the device's enumeration to umpnpmgr */
307 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
308 &DeviceNode
->InstancePath
);
310 /* Report the device's arrival to umpnpmgr */
311 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
312 &DeviceNode
->InstancePath
);
314 DPRINT1("Reported device: %S (%wZ)\n", HardwareId
, &DeviceNode
->InstancePath
);
317 if (DeviceObject
) *DeviceObject
= Pdo
;
319 return STATUS_SUCCESS
;
327 IoReportResourceForDetection(IN PDRIVER_OBJECT DriverObject
,
328 IN PCM_RESOURCE_LIST DriverList OPTIONAL
,
329 IN ULONG DriverListSize OPTIONAL
,
330 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
331 IN PCM_RESOURCE_LIST DeviceList OPTIONAL
,
332 IN ULONG DeviceListSize OPTIONAL
,
333 OUT PBOOLEAN ConflictDetected
)
335 PCM_RESOURCE_LIST ResourceList
;
338 *ConflictDetected
= FALSE
;
340 if (!DriverList
&& !DeviceList
)
341 return STATUS_INVALID_PARAMETER
;
343 /* Find the real list */
345 ResourceList
= DeviceList
;
347 ResourceList
= DriverList
;
349 /* Look for a resource conflict */
350 Status
= IopDetectResourceConflict(ResourceList
);
351 if (Status
== STATUS_CONFLICTING_ADDRESSES
)
354 *ConflictDetected
= TRUE
;
356 else if (NT_SUCCESS(Status
))
358 /* Looks like we're good to go */
360 /* TODO: Claim the resources in the ResourceMap */
368 IopSetEvent(IN PVOID Context
)
370 PKEVENT Event
= Context
;
373 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
381 IoReportTargetDeviceChange(IN PDEVICE_OBJECT PhysicalDeviceObject
,
382 IN PVOID NotificationStructure
)
385 return STATUS_NOT_IMPLEMENTED
;
393 IoReportTargetDeviceChangeAsynchronous(IN PDEVICE_OBJECT PhysicalDeviceObject
,
394 IN PVOID NotificationStructure
,
395 IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL
,
396 IN PVOID Context OPTIONAL
)
399 return STATUS_NOT_IMPLEMENTED
;