|
阅读:10727回复:7
PCI\<device-ID>\<instance-specific-ID>,请问instance-specific-ID是什么意思?
我在ddk中看到Device Instance IDs是由<device-ID>\<instance-specific-ID>这种形式组成的,
在我机器中可以找到usb控制器的键值如下 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\PCI\VEN_8086&DEV_24C2&SUBSYS_3080103C&REV_03\3&61aaa01&0&E8 请问3&61aaa01&0&E8,也就是instance-specific-ID是什么意思,系统是怎么得到的? |
|
|
|
沙发#
发布于:2005-08-06 08:20
自己顶
|
|
|
|
板凳#
发布于:2005-08-06 21:03
同感,帮你顶!
|
|
|
|
地板#
发布于:2008-08-04 16:19
2002年
2005年 2008年 每三年顶一次,希望楼上的可以解决 |
|
|
地下室#
发布于:2008-08-06 13:24
仍然未解决么?
先上代码.... //********************************************************************
// created: 23:7:2008 19:29
// file: pci.id.cpp
// author: tiamo
// purpose: device id
//********************************************************************
#include "stdafx.h"
#pragma alloc_text(PAGE,PciGetDeviceDescriptionMessage)
#pragma alloc_text(PAGE,PciQueryId)
#pragma alloc_text(PAGE,PciQueryDeviceText)
//
// id buffer
//
typedef struct _PCI_ID_BUFFER
{
//
// count
//
ULONG Count;
//
// ansi string
//
ANSI_STRING AnsiString[8];
//
// unicode string size
//
USHORT UnicodeStringSize[8];
//
// total length
//
USHORT TotalLength;
//
// buffer
//
PCHAR CurrentBuffer;
//
// storage
//
CHAR StorageBuffer[0x100];
}PCI_ID_BUFFER,*PPCI_ID_BUFFER;
//
// query id
//
NTSTATUS PciQueryId(__in PPCI_PDO_EXTENSION PdoExt,__in BUS_QUERY_ID_TYPE Type,__out PWCHAR* IdBuffer)
{
PAGED_CODE();
static CHAR Null[2] = {0};
NTSTATUS Status = STATUS_SUCCESS;
*IdBuffer = 0;
PWCHAR Buffer = 0;
ULONG SubSystemVendorId = (PdoExt->SubSystemId << 16) | PdoExt->SubVendorId;
PCI_ID_BUFFER PciIdBuffer;
__try
{
__try
{
if(Type < BusQueryDeviceID || Type > BusQueryInstanceID)
try_leave(Status = STATUS_NOT_SUPPORTED);
if(Type == BusQueryInstanceID)
{
PciIdPrintf(&PciIdBuffer,Null);
PciIdPrintfAppend(&PciIdBuffer,"%02X",(PdoExt->Slot.u.bits.DeviceNumber << 3) | PdoExt->Slot.u.bits.FunctionNumber);
PPCI_FDO_EXTENSION FdoExt = PdoExt->ParentFdoExtension;
while(FdoExt != FdoExt->BusRootFdoExtension)
{
PCI_SLOT_NUMBER Slot = static_cast<PPCI_PDO_EXTENSION>(FdoExt->PhysicalDeviceObject->DeviceExtension)->Slot;
PciIdPrintfAppend(&PciIdBuffer,"%02X",(Slot.u.bits.DeviceNumber << 3) | PdoExt->Slot.u.bits.FunctionNumber);
FdoExt = static_cast<PPCI_PDO_EXTENSION>(FdoExt->PhysicalDeviceObject->DeviceExtension)->ParentFdoExtension;
}
try_leave(NOTHING);
}
if(Type == BusQueryDeviceID || Type == BusQueryHardwareIDs)
{
PciIdPrintf(&PciIdBuffer,"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",PdoExt->VendorId,PdoExt->DeviceId,SubSystemVendorId,PdoExt->RevisionId);
if(Type == BusQueryDeviceID)
try_leave(NOTHING);
PciIdPrintf(&PciIdBuffer,"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X",PdoExt->VendorId,PdoExt->DeviceId,SubSystemVendorId);
}
if((Type == BusQueryHardwareIDs && !SubSystemVendorId) || (SubSystemVendorId && Type == BusQueryCompatibleIDs))
{
PciIdPrintf(&PciIdBuffer,"PCI\\VEN_%04X&DEV_%04X&REV_%02X",PdoExt->VendorId,PdoExt->DeviceId,PdoExt->RevisionId);
PciIdPrintf(&PciIdBuffer,"PCI\\VEN_%04X&DEV_%04X",PdoExt->VendorId,PdoExt->DeviceId);
}
if(Type == BusQueryHardwareIDs)
{
PciIdPrintf(&PciIdBuffer,"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X%02X",PdoExt->VendorId,PdoExt->DeviceId,PdoExt->BaseClass,PdoExt->SubClass,PdoExt->ProgIf);
PciIdPrintf(&PciIdBuffer,"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X",PdoExt->VendorId,PdoExt->DeviceId,PdoExt->BaseClass,PdoExt->SubClass);
}
if(Type == BusQueryCompatibleIDs)
{
PciIdPrintf(&PciIdBuffer,"PCI\\VEN_%04X&CC_%02X%02X%02X",PdoExt->VendorId,PdoExt->BaseClass,PdoExt->SubClass,PdoExt->ProgIf);
PciIdPrintf(&PciIdBuffer,"PCI\\VEN_%04X&CC_%02X%02X",PdoExt->VendorId,PdoExt->BaseClass,PdoExt->SubClass);
PciIdPrintf(&PciIdBuffer,"PCI\\VEN_%04X",PdoExt->VendorId);
PciIdPrintf(&PciIdBuffer,"PCI\\&CC_%02X%02X%02X",PdoExt->BaseClass,PdoExt->SubClass,PdoExt->ProgIf);
PciIdPrintf(&PciIdBuffer,"PCI\\&CC_%02X%02X",PdoExt->BaseClass,PdoExt->SubClass);
}
//
// append a null
//
PciIdPrintf(&PciIdBuffer,Null);
}
__finally
{
}
if(!NT_SUCCESS(Status))
try_leave(NOTHING);
ASSERT(PciIdBuffer.Count);
//
// allocate buffer
//
Buffer = static_cast<PWCHAR>(PciAllocateColdPoolWithTag(PagedPool,PciIdBuffer.TotalLength,'BicP'));
if(!Buffer)
try_leave(Status = STATUS_INSUFFICIENT_RESOURCES);
//
// convert to unicode
//
UNICODE_STRING String;
String.Buffer = Buffer;
String.MaximumLength = PciIdBuffer.TotalLength;
for(ULONG i = 0; i < PciIdBuffer.Count; i ++)
{
if(!NT_SUCCESS(RtlAnsiStringToUnicodeString(&String,&PciIdBuffer.AnsiString[i],FALSE)))
try_leave(NOTHING);
String.MaximumLength -= PciIdBuffer.UnicodeStringSize[i];
String.Buffer += PciIdBuffer.UnicodeStringSize[i] / sizeof(WCHAR);
}
*IdBuffer = Buffer;
}
__finally
{
if(!NT_SUCCESS(Status) || AbnormalTermination())
{
if(Buffer)
ExFreePool(Buffer);
}
}
return Status;
}
//
// query text
//
NTSTATUS PciQueryDeviceText(__in PPCI_PDO_EXTENSION PdoExt,__in DEVICE_TEXT_TYPE Type,__in LCID LocalId,__out PWCHAR* TextBuffer)
{
PAGED_CODE();
NTSTATUS Status = STATUS_NOT_SUPPORTED;
switch(Type)
{
case DeviceTextDescription:
*TextBuffer = PciGetDeviceDescriptionMessage(PdoExt->BaseClass,PdoExt->SubClass);
Status = *TextBuffer ? STATUS_SUCCESS : STATUS_NOT_SUPPORTED;
break;
case DeviceTextLocationInformation:
{
PWCHAR Format = 0;
__try
{
Format = PciGetDescriptionMessage(0x10000);
if(!Format)
try_leave(Status = STATUS_NOT_SUPPORTED);
ULONG Length = (wcslen(Format) + 7) * sizeof(WCHAR);
PWCHAR Buffer = static_cast<PWCHAR>(PciAllocateColdPoolWithTag(PagedPool,Length,'BicP'));
if(!Buffer)
try_leave(Status = STATUS_INSUFFICIENT_RESOURCES);
RtlStringCchPrintfW(Buffer,Length / sizeof(WCHAR) - 1,Format,PdoExt->ParentFdoExtension->BaseBus,
PdoExt->Slot.u.bits.DeviceNumber,PdoExt->Slot.u.bits.FunctionNumber);
*TextBuffer = Buffer;
Status = STATUS_SUCCESS;
}
__finally
{
if(Format)
ExFreePool(Format);
}
}
break;
}
return Status;
}
//
// get device description message
//
PWCHAR PciGetDeviceDescriptionMessage(__in UCHAR BaseClass,__in UCHAR SubClass)
{
PAGED_CODE();
USHORT Class = (BaseClass << 8) | SubClass;
PWCHAR Ret = PciGetDescriptionMessage(Class);
if(Ret)
return Ret;
Ret = static_cast<PWCHAR>(ExAllocatePoolWithTag(PagedPool,sizeof(L"PCI Device"),'BicP'));
if(Ret)
RtlCopyMemory(Ret,L"PCI Device",sizeof(L"PCI Device"));
return Ret;
}
//
// get string from resource
//
PWCHAR PciGetDescriptionMessage(__in ULONG ResourceId)
{
PMESSAGE_RESOURCE_ENTRY Entry = 0;
if(!NT_SUCCESS(RtlFindMessage(PciDriverObject->DriverStart,0x0b,0x0,ResourceId,&Entry)))
return 0;
if(Entry->Flags & MESSAGE_RESOURCE_UNICODE)
{
ULONG Length = Entry->Length - sizeof(MESSAGE_RESOURCE_ENTRY) - sizeof(WCHAR);
PWCHAR Buffer = Add2Ptr(Entry->Text,0,PWCHAR);
if(!Buffer[Length / sizeof(WCHAR)])
Length -= sizeof(WCHAR);
ASSERT(Length > 1);
ASSERT(Buffer[Length / sizeof(WCHAR)] == 0x000a);
PWCHAR Ret = static_cast<PWCHAR>(PciAllocateColdPoolWithTag(PagedPool,Length,'BicP'));
if(Ret)
{
RtlCopyMemory(Ret,Buffer,Length);
Ret[Length / sizeof(WCHAR)] = 0;
}
return Ret;
}
ANSI_STRING AnsiString;
RtlInitAnsiString(&AnsiString,Add2Ptr(Entry->Text,0,PCHAR));
AnsiString.Length -= 2;
UNICODE_STRING UnicodeString;
RtlAnsiStringToUnicodeString(&UnicodeString,&AnsiString,TRUE);
return UnicodeString.Buffer;
}
//
// init id buffer
//
VOID PciInitIdBuffer(__in PPCI_ID_BUFFER IdBuffer)
{
PAGED_CODE();
IdBuffer->Count = 0;
IdBuffer->TotalLength = 0;
IdBuffer->CurrentBuffer = IdBuffer->StorageBuffer;
}
//
// id printf
//
VOID PciIdPrintf(__in PPCI_ID_BUFFER IdBuffer,__in PCHAR Format,...)
{
PAGED_CODE();
ASSERT(IdBuffer->Count < ARRAYSIZE(IdBuffer->AnsiString));
ULONG Length = IdBuffer->StorageBuffer + ARRAYSIZE(IdBuffer->StorageBuffer) - IdBuffer->CurrentBuffer;
size_t LeftLength;
va_list list;
va_start(list,Format);
RtlStringCchVPrintfExA(IdBuffer->CurrentBuffer,Length,0,&LeftLength,0,Format,list);
va_end(list);
Length = static_cast<ULONG>(Length - LeftLength);
IdBuffer->AnsiString[IdBuffer->Count].Buffer = IdBuffer->CurrentBuffer;
IdBuffer->AnsiString[IdBuffer->Count].Length = static_cast<USHORT>(Length);
IdBuffer->AnsiString[IdBuffer->Count].MaximumLength = static_cast<USHORT>(Length + sizeof(CHAR));
ULONG Size = RtlAnsiStringToUnicodeSize(&IdBuffer->AnsiString[IdBuffer->Count]);
IdBuffer->UnicodeStringSize[IdBuffer->Count] = static_cast<USHORT>(Size);
IdBuffer->TotalLength += static_cast<USHORT>(Size);
IdBuffer->Count += 1;
IdBuffer->CurrentBuffer += Length + 1;
}
//
// append printf
//
VOID PciIdPrintfAppend(__in PPCI_ID_BUFFER IdBuffer,__in PCHAR Format,...)
{
PAGED_CODE();
ASSERT(IdBuffer->Count);
ULONG Length = IdBuffer->StorageBuffer + ARRAYSIZE(IdBuffer->StorageBuffer) - IdBuffer->CurrentBuffer + 1;
size_t LeftLength;
va_list list;
va_start(list,Format);
RtlStringCchVPrintfExA(IdBuffer->CurrentBuffer - 1,Length,0,&LeftLength,0,Format,list);
va_end(list);
Length = static_cast<ULONG>(Length - LeftLength);
IdBuffer->AnsiString[IdBuffer->Count - 1].Length += static_cast<USHORT>(Length);
IdBuffer->AnsiString[IdBuffer->Count - 1].MaximumLength += static_cast<USHORT>(Length);
ULONG Size = RtlAnsiStringToUnicodeSize(&IdBuffer->AnsiString[IdBuffer->Count]);
IdBuffer->UnicodeStringSize[IdBuffer->Count - 1] = static_cast<USHORT>(Size);
IdBuffer->TotalLength += static_cast<USHORT>(Size);
IdBuffer->CurrentBuffer += Length;
}NTSTATUS
IopMakeGloballyUniqueId(
IN PDEVICE_OBJECT DeviceObject,
IN PWCHAR UniqueId,
OUT PWCHAR *GloballyUniqueId
)
{
NTSTATUS status;
ULONG length;
PWSTR id, Prefix = NULL;
HANDLE enumKey;
HANDLE instanceKey;
UCHAR keyBuffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + sizeof(ULONG)];
PKEY_VALUE_PARTIAL_INFORMATION keyValue, stringValueBuffer = NULL;
UNICODE_STRING valueName;
ULONG uniqueIdValue, Hash, hashInstance;
PDEVICE_NODE parentNode;
PAGED_CODE();
//
// We need to build an instance id to uniquely identify this
// device. We will accomplish this by producing a prefix that will be
// prepended to the non-unique device id supplied.
//
//
// To 'unique-ify' the child's instance ID, we will retrieve
// the unique "UniqueParentID" number that has been assigned
// to the parent and use it to construct a prefix. This is
// the legacy mechanism supported here so that existing device
// settings are not lost on upgrade.
//
KeEnterCriticalRegion();
ExAcquireResourceShared(&PpRegistryDeviceResource, TRUE);
parentNode = ((PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode)->Parent;
status = IopOpenRegistryKeyEx( &enumKey,
NULL,
&CmRegistryMachineSystemCurrentControlSetEnumName,
KEY_READ | KEY_WRITE
);
if (!NT_SUCCESS(status)) {
DbgPrint("IopQueryUniqueId:\tUnable to open HKLM\\SYSTEM\\CCS\\ENUM (status %08lx)\n",
status
);
goto clean0;
}
//
// Open the instance key for this devnode
//
status = IopOpenRegistryKeyEx( &instanceKey,
enumKey,
&parentNode->InstancePath,
KEY_READ | KEY_WRITE
);
if (!NT_SUCCESS(status)) {
DbgPrint("IopQueryUniqueId:\tUnable to open registry key for %wZ (status %08lx)\n",
&parentNode->InstancePath,
status
);
goto clean1;
}
//
// Attempt to retrieve the "UniqueParentID" value from the device
// instance key.
//
keyValue = (PKEY_VALUE_PARTIAL_INFORMATION)keyBuffer;
PiWstrToUnicodeString(&valueName, REGSTR_VALUE_UNIQUE_PARENT_ID);
status = ZwQueryValueKey(instanceKey,
&valueName,
KeyValuePartialInformation,
keyValue,
sizeof(keyBuffer),
&length
);
if (NT_SUCCESS(status)) {
ASSERT(keyValue->Type == REG_DWORD);
ASSERT(keyValue->DataLength == sizeof(ULONG));
if ((keyValue->Type != REG_DWORD) ||
(keyValue->DataLength != sizeof(ULONG))) {
status = STATUS_INVALID_PARAMETER;
goto clean2;
}
uniqueIdValue = *(PULONG)(keyValue->Data);
//
// OK, we have a unique parent ID number to prefix to the
// instance ID.
Prefix = (PWSTR)ExAllocatePool(PagedPool, 9 * sizeof(WCHAR));
if (!Prefix) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto clean2;
}
swprintf(Prefix, L"%x", uniqueIdValue);
} else {
//
// This is the current mechanism for finding existing
// device instance prefixes and calculating new ones if
// required.
//
//
// Attempt to retrieve the "ParentIdPrefix" value from the device
// instance key.
//
PiWstrToUnicodeString(&valueName, REGSTR_VALUE_PARENT_ID_PREFIX);
length = (MAX_PARENT_PREFIX + 1) * sizeof(WCHAR) +
FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
stringValueBuffer = ExAllocatePool(PagedPool,
length);
if (stringValueBuffer) {
status = ZwQueryValueKey(instanceKey,
&valueName,
KeyValuePartialInformation,
stringValueBuffer,
length,
&length);
}
else {
status = STATUS_INSUFFICIENT_RESOURCES;
goto clean2;
}
if (NT_SUCCESS(status)) {
ASSERT(stringValueBuffer->Type == REG_SZ);
if (stringValueBuffer->Type != REG_SZ) {
status = STATUS_INVALID_PARAMETER;
goto clean2;
}
//
// Parent has already been assigned a "ParentIdPrefix".
//
Prefix = (PWSTR) ExAllocatePool(PagedPool,
stringValueBuffer->DataLength);
if (!Prefix)
{
status = STATUS_INSUFFICIENT_RESOURCES;
goto clean2;
}
wcscpy(Prefix, (PWSTR) stringValueBuffer->Data);
}
else
{
//
// Parent has not been assigned a "ParentIdPrefix".
// Compute the prefix:
// * Compute Hash
// * Look for value of the form:
// NextParentId.<level>.<hash>:REG_DWORD: <NextInstance>
// under CCS\Enum. If not present, create it.
// * Assign the new "ParentIdPrefix" which will be of
// of the form:
// <level>&<hash>&<instance>
//
// Allocate a buffer once for the NextParentId... value
// and for the prefix.
length = max(wcslen(REGSTR_VALUE_NEXT_PARENT_ID) + 2 + 8 + 8,
MAX_PARENT_PREFIX) + 1;
// Device instances are case in-sensitive. Upcase before
// performing hash to ensure that the hash is case-insensitve.
status = RtlUpcaseUnicodeString(&valueName,
&parentNode->InstancePath,
TRUE);
if (!NT_SUCCESS(status))
{
goto clean2;
}
HASH_UNICODE_STRING(&valueName, &Hash);
RtlFreeUnicodeString(&valueName);
Prefix = (PWSTR) ExAllocatePool(PagedPool,
length * sizeof(WCHAR));
if (!Prefix) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto clean2;
}
// Check for existence of "NextParentId...." value and update.
swprintf(Prefix, L"%s.%x.%x", REGSTR_VALUE_NEXT_PARENT_ID,
Hash, parentNode->Level);
RtlInitUnicodeString(&valueName, Prefix);
keyValue = (PKEY_VALUE_PARTIAL_INFORMATION)keyBuffer;
status = ZwQueryValueKey(enumKey,
&valueName,
KeyValuePartialInformation,
keyValue,
sizeof(keyBuffer),
&length
);
if (NT_SUCCESS(status) && (keyValue->Type == REG_DWORD) &&
(keyValue->DataLength == sizeof(ULONG))) {
hashInstance = *(PULONG)(keyValue->Data);
}
else {
hashInstance = 0;
}
hashInstance++;
status = ZwSetValueKey(enumKey,
&valueName,
TITLE_INDEX_VALUE,
REG_DWORD,
&hashInstance,
sizeof(hashInstance)
);
if (!NT_SUCCESS(status)) {
goto clean2;
}
hashInstance--;
// Create actual ParentIdPrefix string
PiWstrToUnicodeString(&valueName, REGSTR_VALUE_PARENT_ID_PREFIX);
length = swprintf(Prefix, L"%x&%x&%x", parentNode->Level,
Hash, hashInstance) + 1;
status = ZwSetValueKey(instanceKey,
&valueName,
TITLE_INDEX_VALUE,
REG_SZ,
Prefix,
length * sizeof(WCHAR)
);
if (!NT_SUCCESS(status))
{
goto clean2;
}
}
}
// Construct the instance id from the non-unique id (if any)
// provided by the child and the prefix we've constructed.
length = wcslen(Prefix) + (UniqueId ? wcslen(UniqueId) : 0) + 2;
id = (PWSTR)ExAllocatePool(PagedPool, length * sizeof(WCHAR));
if (!id) {
status = STATUS_INSUFFICIENT_RESOURCES;
} else if (UniqueId) {
swprintf(id, L"%s&%s", Prefix, UniqueId);
} else {
wcscpy(id, Prefix);
}
clean2:
ZwClose(instanceKey);
clean1:
ZwClose(enumKey);
clean0:
ExReleaseResource(&PpRegistryDeviceResource);
KeLeaveCriticalRegion();
if (stringValueBuffer) {
ExFreePool(stringValueBuffer);
}
if (Prefix) {
ExFreePool(Prefix);
}
*GloballyUniqueId = id;
return status;
} |
|
|
5楼#
发布于:2008-08-06 13:38
Re:PCI\<device-ID>\<instance-specific-ID>,请问i
你的这个例子前面VEN_什么什么的很容易理解他就是的device id.他是怎么来的看上面的PciQueryId里面关于device id的处理 后面这个3&61aaa01&0&E8分成4个部分 第一个3表示这个device在整个device tree里面的level.他在第三级 root是0,root下面是acpi再下面是pci root bridge.这个设备就直接在root bridge下面 第二个是个hash值.他是这个设备的parent 设备的instance path大写以后计算出来的hash值 instance path是从current control set下面的enum算起(不包含enum) 第三个是hash instance.你很少有看到这个值不为0的 他表示为同一个parent计算上面这个hash的次数 - 1.通常都只是计算一次.计算以后就会保存下面.下一次就直接读取了而不会再重新计算 最后一个就是由bus驱动为他们的pdo返回的instance id了 pci的话看上面PciQueryId的代码 就是从当前设备开始依次回溯他root bridge然后把他们的dev,fun合起来.. 希望有帮助.... P.S.08年力作..windows xp sp2 checked build pci.sys全部逆向完成并已经转换成c代码 近日公布...敬请期待.. |
|
|
6楼#
发布于:2009-03-11 10:19
强帖要留名,顶tiamo 顶楼主 !!!
|
|
|
|
7楼#
发布于:2023-04-21 16:42
感谢tiamo大神, 18年了,终于搞明白了!!!
|
|
|