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
,
38 /* PRIVATE FUNCTIONS *********************************************************/
41 IopGetInterfaceTypeString(INTERFACE_TYPE IfType
)
55 return L
"MicroChannel";
58 return L
"TurboChannel";
81 case ProcessorInternal
:
82 return L
"ProcessorInternal";
94 DPRINT1("Invalid bus type: %d\n", IfType
);
99 /* PUBLIC FUNCTIONS **********************************************************/
106 IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject
,
107 IN INTERFACE_TYPE LegacyBusType
,
110 IN PCM_RESOURCE_LIST ResourceList
,
111 IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements OPTIONAL
,
112 IN BOOLEAN ResourceAssigned
,
113 IN OUT PDEVICE_OBJECT
*DeviceObject OPTIONAL
)
115 PDEVICE_NODE DeviceNode
;
119 ULONG RequiredLength
;
120 UNICODE_STRING ValueName
, ServiceName
;
121 WCHAR HardwareId
[256];
125 DPRINT("IoReportDetectedDevice (DeviceObject %p, *DeviceObject %p)\n",
126 DeviceObject
, DeviceObject
? *DeviceObject
: NULL
);
128 /* Create the service name (eg. ACPI_HAL) */
129 ServiceName
.Buffer
= DriverObject
->DriverName
.Buffer
+
130 sizeof(DRIVER_ROOT_NAME
) / sizeof(WCHAR
) - 1;
131 ServiceName
.Length
= DriverObject
->DriverName
.Length
-
132 sizeof(DRIVER_ROOT_NAME
) + sizeof(WCHAR
);
133 ServiceName
.MaximumLength
= ServiceName
.Length
;
135 /* If the interface type is unknown, treat it as internal */
136 if (LegacyBusType
== InterfaceTypeUndefined
)
137 LegacyBusType
= Internal
;
139 /* Get the string equivalent of the interface type */
140 IfString
= IopGetInterfaceTypeString(LegacyBusType
);
142 /* If NULL is returned then it's a bad type */
144 return STATUS_INVALID_PARAMETER
;
146 /* We use the caller's PDO if they supplied one */
147 if (DeviceObject
&& *DeviceObject
)
150 DeviceNode
= IopGetDeviceNode(*DeviceObject
);
155 Status
= PnpRootCreateDevice(&ServiceName
,
157 if (!NT_SUCCESS(Status
))
159 DPRINT("PnpRootCreateDevice() failed (Status 0x%08lx)\n", Status
);
163 /* Create the device node for the new PDO */
164 Status
= IopCreateDeviceNode(IopRootDeviceNode
,
169 if (!NT_SUCCESS(Status
))
171 DPRINT("IopCreateDeviceNode() failed (Status 0x%08lx)\n", Status
);
176 /* We don't call AddDevice for devices reported this way */
177 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
179 /* We don't send IRP_MN_START_DEVICE */
180 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
182 /* This is a legacy driver for this device */
183 IopDeviceNodeSetFlag(DeviceNode
, DNF_LEGACY_DRIVER
);
185 /* Perform a manual configuration of our device */
186 IopActionInterrogateDeviceStack(DeviceNode
, DeviceNode
->Parent
);
187 IopActionConfigureChildServices(DeviceNode
, DeviceNode
->Parent
);
189 /* Open a handle to the instance path key */
190 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, &InstanceKey
);
191 if (!NT_SUCCESS(Status
))
194 /* Add DETECTEDInterfaceType\DriverName */
196 IdLength
+= swprintf(&HardwareId
[IdLength
],
200 HardwareId
[IdLength
++] = UNICODE_NULL
;
202 /* Add DETECTED\DriverName */
203 IdLength
+= swprintf(&HardwareId
[IdLength
],
206 HardwareId
[IdLength
++] = UNICODE_NULL
;
208 /* Terminate the string with another null */
209 HardwareId
[IdLength
] = UNICODE_NULL
;
211 /* Store the value for CompatibleIDs */
212 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
213 Status
= ZwSetValueKey(InstanceKey
, &ValueName
, 0, REG_MULTI_SZ
, HardwareId
, IdLength
* sizeof(WCHAR
));
214 if (!NT_SUCCESS(Status
))
216 DPRINT("Failed to write the compatible IDs: 0x%x\n", Status
);
217 ZwClose(InstanceKey
);
221 /* Add a hardware ID if the driver didn't report one */
222 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
223 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
225 /* Just use our most specific compatible ID */
227 IdLength
+= swprintf(&HardwareId
[IdLength
],
231 HardwareId
[++IdLength
] = UNICODE_NULL
;
233 /* Write the value to the registry */
234 Status
= ZwSetValueKey(InstanceKey
, &ValueName
, 0, REG_SZ
, HardwareId
, IdLength
* sizeof(WCHAR
));
235 if (!NT_SUCCESS(Status
))
237 DPRINT("Failed to write the hardware ID: 0x%x\n", Status
);
238 ZwClose(InstanceKey
);
243 /* Assign the resources to the device node */
244 DeviceNode
->BootResources
= ResourceList
;
245 DeviceNode
->ResourceRequirements
= ResourceRequirements
;
247 /* Set appropriate flags */
248 if (DeviceNode
->BootResources
)
249 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
251 if (DeviceNode
->ResourceRequirements
)
252 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
254 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
256 /* Write the resource information to the registry */
257 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
259 /* Close the instance key handle */
260 ZwClose(InstanceKey
);
262 /* If the caller didn't get the resources assigned for us, do it now */
263 if (!ResourceAssigned
)
265 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
266 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
267 if (NT_SUCCESS(Status
))
269 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
270 if (NT_SUCCESS(Status
))
271 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
273 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
275 /* See if we failed */
276 if (!NT_SUCCESS(Status
))
278 DPRINT("Assigning resources failed: 0x%x\n", Status
);
283 /* Report the device's enumeration to umpnpmgr */
284 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
285 &DeviceNode
->InstancePath
);
287 /* Report the device's arrival to umpnpmgr */
288 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
289 &DeviceNode
->InstancePath
);
291 DPRINT1("Reported device: %S (%wZ)\n", HardwareId
, &DeviceNode
->InstancePath
);
294 if (DeviceObject
) *DeviceObject
= Pdo
;
296 return STATUS_SUCCESS
;
304 IoReportResourceForDetection(IN PDRIVER_OBJECT DriverObject
,
305 IN PCM_RESOURCE_LIST DriverList OPTIONAL
,
306 IN ULONG DriverListSize OPTIONAL
,
307 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
308 IN PCM_RESOURCE_LIST DeviceList OPTIONAL
,
309 IN ULONG DeviceListSize OPTIONAL
,
310 OUT PBOOLEAN ConflictDetected
)
312 static int warned
= 0;
315 DPRINT1("IoReportResourceForDetection partly implemented\n");
319 *ConflictDetected
= FALSE
;
321 if (PopSystemPowerDeviceNode
&& DriverListSize
> 0)
323 /* We hope legacy devices will be enumerated by ACPI */
324 *ConflictDetected
= TRUE
;
325 return STATUS_CONFLICTING_ADDRESSES
;
328 return STATUS_SUCCESS
;
333 IopSetEvent(IN PVOID Context
)
335 PKEVENT Event
= Context
;
338 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
346 IoReportTargetDeviceChange(IN PDEVICE_OBJECT PhysicalDeviceObject
,
347 IN PVOID NotificationStructure
)
350 return STATUS_NOT_IMPLEMENTED
;
358 IoReportTargetDeviceChangeAsynchronous(IN PDEVICE_OBJECT PhysicalDeviceObject
,
359 IN PVOID NotificationStructure
,
360 IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL
,
361 IN PVOID Context OPTIONAL
)
364 return STATUS_NOT_IMPLEMENTED
;