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 /* Close the instance key handle */
270 ZwClose(InstanceKey
);
272 /* If the caller didn't get the resources assigned for us, do it now */
273 if (!ResourceAssigned
)
275 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
276 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
277 if (NT_SUCCESS(Status
))
279 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
280 if (NT_SUCCESS(Status
))
281 Status
= IopUpdateResourceMapForPnPDevice(DeviceNode
);
283 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
285 /* See if we failed */
286 if (!NT_SUCCESS(Status
))
288 DPRINT("Assigning resources failed: 0x%x\n", Status
);
293 /* Report the device's enumeration to umpnpmgr */
294 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
295 &DeviceNode
->InstancePath
);
297 /* Report the device's arrival to umpnpmgr */
298 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
299 &DeviceNode
->InstancePath
);
301 DPRINT1("Reported device: %S (%wZ)\n", HardwareId
, &DeviceNode
->InstancePath
);
304 if (DeviceObject
) *DeviceObject
= Pdo
;
306 return STATUS_SUCCESS
;
314 IoReportResourceForDetection(IN PDRIVER_OBJECT DriverObject
,
315 IN PCM_RESOURCE_LIST DriverList OPTIONAL
,
316 IN ULONG DriverListSize OPTIONAL
,
317 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
318 IN PCM_RESOURCE_LIST DeviceList OPTIONAL
,
319 IN ULONG DeviceListSize OPTIONAL
,
320 OUT PBOOLEAN ConflictDetected
)
322 PCM_RESOURCE_LIST ResourceList
;
325 *ConflictDetected
= FALSE
;
327 if (!DriverList
&& !DeviceList
)
328 return STATUS_INVALID_PARAMETER
;
330 /* Find the real list */
332 ResourceList
= DeviceList
;
334 ResourceList
= DriverList
;
336 /* Look for a resource conflict */
337 Status
= IopDetectResourceConflict(ResourceList
);
338 if (Status
== STATUS_CONFLICTING_ADDRESSES
)
341 *ConflictDetected
= TRUE
;
343 else if (NT_SUCCESS(Status
))
345 /* Looks like we're good to go */
347 /* TODO: Claim the resources in the ResourceMap */
355 IopSetEvent(IN PVOID Context
)
357 PKEVENT Event
= Context
;
360 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
368 IoReportTargetDeviceChange(IN PDEVICE_OBJECT PhysicalDeviceObject
,
369 IN PVOID NotificationStructure
)
372 return STATUS_NOT_IMPLEMENTED
;
380 IoReportTargetDeviceChangeAsynchronous(IN PDEVICE_OBJECT PhysicalDeviceObject
,
381 IN PVOID NotificationStructure
,
382 IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL
,
383 IN PVOID Context OPTIONAL
)
386 return STATUS_NOT_IMPLEMENTED
;