阅读:10175回复: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年了,终于搞明白了!!!
|
|
|