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 IopSetDeviceInstanceData(HANDLE InstanceKey
,
23 PDEVICE_NODE DeviceNode
);
26 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
30 IopDetectResourceConflict(
31 IN PCM_RESOURCE_LIST ResourceList
);
33 /* PRIVATE FUNCTIONS *********************************************************/
36 IopGetInterfaceTypeString(INTERFACE_TYPE IfType
)
50 return L
"MicroChannel";
53 return L
"TurboChannel";
76 case ProcessorInternal
:
77 return L
"ProcessorInternal";
89 DPRINT1("Invalid bus type: %d\n", IfType
);
94 /* PUBLIC FUNCTIONS **********************************************************/
101 IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject
,
102 IN INTERFACE_TYPE LegacyBusType
,
105 IN PCM_RESOURCE_LIST ResourceList
,
106 IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements OPTIONAL
,
107 IN BOOLEAN ResourceAssigned
,
108 IN OUT PDEVICE_OBJECT
*DeviceObject OPTIONAL
)
110 PDEVICE_NODE DeviceNode
;
114 ULONG RequiredLength
;
115 UNICODE_STRING ValueName
, ServiceName
;
116 WCHAR HardwareId
[256];
120 DPRINT("IoReportDetectedDevice (DeviceObject %p, *DeviceObject %p)\n",
121 DeviceObject
, DeviceObject
? *DeviceObject
: NULL
);
123 /* Create the service name (eg. ACPI_HAL) */
124 ServiceName
.Buffer
= DriverObject
->DriverName
.Buffer
+
125 sizeof(DRIVER_ROOT_NAME
) / sizeof(WCHAR
) - 1;
126 ServiceName
.Length
= DriverObject
->DriverName
.Length
-
127 sizeof(DRIVER_ROOT_NAME
) + sizeof(WCHAR
);
128 ServiceName
.MaximumLength
= ServiceName
.Length
;
130 /* If the interface type is unknown, treat it as internal */
131 if (LegacyBusType
== InterfaceTypeUndefined
)
132 LegacyBusType
= Internal
;
134 /* Get the string equivalent of the interface type */
135 IfString
= IopGetInterfaceTypeString(LegacyBusType
);
137 /* If NULL is returned then it's a bad type */
139 return STATUS_INVALID_PARAMETER
;
141 /* We use the caller's PDO if they supplied one */
142 if (DeviceObject
&& *DeviceObject
)
145 DeviceNode
= IopGetDeviceNode(*DeviceObject
);
150 Status
= PnpRootCreateDevice(&ServiceName
,
153 if (!NT_SUCCESS(Status
))
155 DPRINT("PnpRootCreateDevice() failed (Status 0x%08lx)\n", Status
);
159 /* Create the device node for the new PDO */
160 Status
= IopCreateDeviceNode(IopRootDeviceNode
,
165 if (!NT_SUCCESS(Status
))
167 DPRINT("IopCreateDeviceNode() failed (Status 0x%08lx)\n", Status
);
172 /* We don't call AddDevice for devices reported this way */
173 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
175 /* We don't send IRP_MN_START_DEVICE */
176 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
178 /* We need to get device IDs */
180 IopDeviceNodeSetFlag(DeviceNode
, DNF_NEED_QUERY_IDS
);
183 /* This is a legacy driver for this device */
184 IopDeviceNodeSetFlag(DeviceNode
, DNF_LEGACY_DRIVER
);
186 /* Perform a manual configuration of our device */
187 IopActionInterrogateDeviceStack(DeviceNode
, DeviceNode
->Parent
);
188 IopActionConfigureChildServices(DeviceNode
, DeviceNode
->Parent
);
190 /* Open a handle to the instance path key */
191 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
192 if (!NT_SUCCESS(Status
))
195 /* Add DETECTEDInterfaceType\DriverName */
197 IdLength
+= swprintf(&HardwareId
[IdLength
],
201 HardwareId
[IdLength
++] = UNICODE_NULL
;
203 /* Add DETECTED\DriverName */
204 IdLength
+= swprintf(&HardwareId
[IdLength
],
207 HardwareId
[IdLength
++] = UNICODE_NULL
;
209 /* Terminate the string with another null */
210 HardwareId
[IdLength
] = UNICODE_NULL
;
212 /* Store the value for CompatibleIDs */
213 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
214 Status
= ZwSetValueKey(InstanceKey
, &ValueName
, 0, REG_MULTI_SZ
, HardwareId
, IdLength
* sizeof(WCHAR
));
215 if (!NT_SUCCESS(Status
))
217 DPRINT("Failed to write the compatible IDs: 0x%x\n", Status
);
218 ZwClose(InstanceKey
);
222 /* Add a hardware ID if the driver didn't report one */
223 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
224 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
226 /* Just use our most specific compatible ID */
228 IdLength
+= swprintf(&HardwareId
[IdLength
],
232 HardwareId
[++IdLength
] = UNICODE_NULL
;
234 /* Write the value to the registry */
235 Status
= ZwSetValueKey(InstanceKey
, &ValueName
, 0, REG_SZ
, HardwareId
, IdLength
* sizeof(WCHAR
));
236 if (!NT_SUCCESS(Status
))
238 DPRINT("Failed to write the hardware ID: 0x%x\n", Status
);
239 ZwClose(InstanceKey
);
244 /* Assign the resources to the device node */
245 DeviceNode
->BootResources
= ResourceList
;
246 DeviceNode
->ResourceRequirements
= ResourceRequirements
;
248 /* Set appropriate flags */
249 if (DeviceNode
->BootResources
)
250 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
252 if (!DeviceNode
->ResourceRequirements
&& !DeviceNode
->BootResources
)
253 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
255 /* Write the resource information to the registry */
256 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
258 /* If the caller didn't get the resources assigned for us, do it now */
259 if (!ResourceAssigned
)
261 Status
= IopAssignDeviceResources(DeviceNode
);
263 /* See if we failed */
264 if (!NT_SUCCESS(Status
))
266 DPRINT("Assigning resources failed: 0x%x\n", Status
);
267 ZwClose(InstanceKey
);
272 /* Close the instance key handle */
273 ZwClose(InstanceKey
);
275 /* Report the device's enumeration to umpnpmgr */
276 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
277 &DeviceNode
->InstancePath
);
279 /* Report the device's arrival to umpnpmgr */
280 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
281 &DeviceNode
->InstancePath
);
283 DPRINT1("Reported device: %S (%wZ)\n", HardwareId
, &DeviceNode
->InstancePath
);
286 if (DeviceObject
) *DeviceObject
= Pdo
;
288 return STATUS_SUCCESS
;
296 IoReportResourceForDetection(IN PDRIVER_OBJECT DriverObject
,
297 IN PCM_RESOURCE_LIST DriverList OPTIONAL
,
298 IN ULONG DriverListSize OPTIONAL
,
299 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
300 IN PCM_RESOURCE_LIST DeviceList OPTIONAL
,
301 IN ULONG DeviceListSize OPTIONAL
,
302 OUT PBOOLEAN ConflictDetected
)
304 PCM_RESOURCE_LIST ResourceList
;
307 *ConflictDetected
= FALSE
;
309 if (!DriverList
&& !DeviceList
)
310 return STATUS_INVALID_PARAMETER
;
312 /* Find the real list */
314 ResourceList
= DeviceList
;
316 ResourceList
= DriverList
;
318 /* Look for a resource conflict */
319 Status
= IopDetectResourceConflict(ResourceList
);
320 if (Status
== STATUS_CONFLICTING_ADDRESSES
)
323 *ConflictDetected
= TRUE
;
325 else if (NT_SUCCESS(Status
))
327 /* Looks like we're good to go */
329 /* TODO: Claim the resources in the ResourceMap */
337 IopSetEvent(IN PVOID Context
)
339 PKEVENT Event
= Context
;
342 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
350 IoReportTargetDeviceChange(IN PDEVICE_OBJECT PhysicalDeviceObject
,
351 IN PVOID NotificationStructure
)
354 return STATUS_NOT_IMPLEMENTED
;
362 IoReportTargetDeviceChangeAsynchronous(IN PDEVICE_OBJECT PhysicalDeviceObject
,
363 IN PVOID NotificationStructure
,
364 IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL
,
365 IN PVOID Context OPTIONAL
)
368 return STATUS_NOT_IMPLEMENTED
;