引用chatgpt内容作答:
在 WDM 驱动中,您可以使用其他方法来获取 ACPI PDO 设备的 _UID(唯一 ID)。由于 IoGetDeviceProperty 函数不直接提供 _UID 属性的查询,您可以尝试以下方法来获取 _UID:
1、使用 IRP_MN_QUERY_ID 请求:
您可以向 ACPI PDO 设备发送 IRP_MN_QUERY_ID 请求,并指定 QueryType 为 BusQueryDeviceID。这将使设备栈返回设备的标识符字符串,其中包含设备的 _UID。
2、使用 IRP_MN_QUERY_DEVICE_TEXT 请求:
同样,您可以向 ACPI PDO 设备发送 IRP_MN_QUERY_DEVICE_TEXT 请求,并指定 RequestType 为 DeviceTextDescription。这将使设备栈返回设备的描述字符串,其中可能包含设备的 _UID。
3、解析 ACPI 配置:
ACPI 设备对象通常包含一个名为 _HID 的属性,它是硬件 ID。该 ID 通常与设备的 _UID 相对应。您可以通过解析 ACPI 配置来获取这些属性,并从中提取 _UID。
以下是第一种方法的示例代码:
NTSTATUS GetAcpiDeviceUid(PDEVICE_OBJECT pdo, PWSTR* pUid)
{
NTSTATUS status = STATUS_SUCCESS;
PIRP irp = NULL;
KEVENT event;
IO_STATUS_BLOCK ioStatusBlock;
PAGED_CODE();
*pUid = NULL;
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, pdo, NULL, 0, NULL, &event, &ioStatusBlock);
if (irp == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
PIO_STACK_LOCATION irpSp = IoGetNextIrpStackLocation(irp);
irpSp->MinorFunction = IRP_MN_QUERY_ID;
irpSp->Parameters.QueryId.IdType = BusQueryDeviceID;
status = IoCallDriver(pdo, irp);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatusBlock.Status;
}
if (NT_SUCCESS(status))
{
*pUid = ExAllocatePoolWithTag(PagedPool, ioStatusBlock.Information, 'myTag');
if (*pUid != NULL)
{
RtlCopyMemory(*pUid, ioStatusBlock.Information, ioStatusBlock.Information);
}
else
{
status = STATUS_INSUFFICIENT_RESOURCES;
}
}
return status;
}
这只是获取 ACPI PDO 设备 _UID 的一种方法。在实际实现中,您可能需要根据具体的设备和驱动情况进行适当的调整。同时,记得在使用 ExAllocatePoolWithTag 分配的内存后,在不再使用时使用 ExFreePool 释放它,以避免内存泄漏。
ACPI 设备的 _UID 并非硬件标识符,而是与 ACPI 设备节点相关的标识符。如果您需要硬件 ID,请使用 IRP_MN_QUERY_ID 请求并指定 QueryType 为 BusQueryHardwareIDs。