nt!PipMakeGloballyUniqueId函数分析和注册表中ParentIdPrefix的关系--非常重要
0: kd> kc
#
00 nt!PipMakeGloballyUniqueId
01 nt!PiProcessNewDeviceNode
02 nt!PipProcessDevNodeTree
03 nt!PipDeviceActionWorker
04 nt!PipRequestDeviceAction
05 nt!IopInitializeBootDrivers
06 nt!IoInitSystem
07 nt!Phase1Initialization
08 nt!PspSystemThreadStartup
09 nt!KiThreadStartup
0: kd> dv
DeviceObject = 0x899050e8 Device for "\Driver\ACPI"
UniqueId = 0x00000000
GloballyUniqueId = 0xf789a340
Prefix = 0x80c92e78
0: kd> dt _device_node 0x894ffea8
nt!_DEVICE_NODE
+0x000 Sibling : 0x8952a1e0 _DEVICE_NODE
+0x004 Child : (null)
+0x008 Parent : 0x899c1008 _DEVICE_NODE
0: kd> dx -id 0,0,899a2278 -r1 ((ntkrnlmp!_DEVICE_NODE *)0x899c1008)
((ntkrnlmp!_DEVICE_NODE *)0x899c1008) : 0x899c1008 [Type: _DEVICE_NODE *]
[+0x000] Sibling : 0x0 [Type: _DEVICE_NODE *]
[+0x004] Child : 0x894ffea8 [Type: _DEVICE_NODE *]
[+0x008] Parent : 0x89986008 [Type: _DEVICE_NODE *]
[+0x00c] LastChild : 0x8952a500 [Type: _DEVICE_NODE *]
[+0x010] Level : 0x2 [Type: unsigned long]
[+0x014] Notify : 0x0 [Type: _PO_DEVICE_NOTIFY *]
[+0x018] State : DeviceNodeStarted (776) [Type: _PNP_DEVNODE_STATE]
[+0x01c] PreviousState : DeviceNodeEnumerateCompletion (781) [Type: _PNP_DEVNODE_STATE]
[+0x020] StateHistory [Type: _PNP_DEVNODE_STATE [20]]
[+0x070] StateHistoryEntry : 0x8 [Type: unsigned long]
[+0x074] CompletionStatus : 0 [Type: long]
[+0x078] PendingIrp : 0x0 [Type: _IRP *]
[+0x07c] Flags : 0xf0 [Type: unsigned long]
[+0x080] UserFlags : 0x0 [Type: unsigned long]
[+0x084] Problem : 0x0 [Type: unsigned long]
[+0x088] PhysicalDeviceObject : 0x899c1de0 : Device for "\Driver\ACPI_HAL" [Type: _DEVICE_OBJECT *]
[+0x08c] ResourceList : 0xe127b758 [Type: _CM_RESOURCE_LIST *]
[+0x090] ResourceListTranslated : 0xe127fe58 [Type: _CM_RESOURCE_LIST *]
[+0x094] InstancePath : "ACPI_HAL\PNP0C08\0" [Type: _UNICODE_STRING]
parentNode = ((PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode)->Parent;
status = IopOpenRegistryKeyEx( &enumKey,
NULL,
&CmRegistryMachineSystemCurrentControlSetEnumName,
KEY_READ | KEY_WRITE
);
0: kd> dv enumKey
enumKey = 0x80000230
0: kd> !handle 230
PROCESS 899a2278 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
DirBase: 0a200000 ObjectTable: e1000e38 HandleCount: 33.
Image: System
Kernel handle table at e1000e38 with 33 entries in use
0230: Object: e127f5e0 GrantedAccess: 0002001f Entry: e1004460
Object: e127f5e0 Type: (89996048) Key
ObjectHeader: e127f5c8 (old version)
HandleCount: 1 PointerCount: 1
Directory Object: 00000000 Name: \REGISTRY\MACHINE\SYSTEM\CONTROLSET001\ENUM
//
// Open the instance key for this devnode
//
status = IopOpenRegistryKeyEx( &instanceKey,
enumKey,
&parentNode->InstancePath,
KEY_READ | KEY_WRITE
);
0: kd> dv instanceKey
instanceKey = 0x80000264
0: kd> !handle 264
PROCESS 899a2278 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
DirBase: 0a200000 ObjectTable: e1000e38 HandleCount: 34.
Image: System
Kernel handle table at e1000e38 with 34 entries in use
0264: Object: e1271ae0 GrantedAccess: 0002001f Entry: e10044c8
Object: e1271ae0 Type: (89996048) Key
ObjectHeader: e1271ac8 (old version)
HandleCount: 1 PointerCount: 1
Directory Object: 00000000 Name: \REGISTRY\MACHINE\SYSTEM\CONTROLSET001\ENUM\ACPI_HAL\PNP0C08\0
//
// 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
);
0: kd> p
eax=c0000034 ebx=899c1008 ecx=00000008 edx=80a3dd5d esi=00000000 edi=899c109c
eip=80c92fb7 esp=f789a288 ebp=f789a2cc iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246
nt!PipMakeGloballyUniqueId+0x13f:
80c92fb7 3bc6 cmp eax,esi
} 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. 关键地方:"ParentIdPrefix"
//
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);
0: kd> dv stringValueBuffer
stringValueBuffer = 0xe1279100
0: kd> dx -r1 ((ntkrnlmp!_KEY_VALUE_PARTIAL_INFORMATION *)0xe1279100)
((ntkrnlmp!_KEY_VALUE_PARTIAL_INFORMATION *)0xe1279100) : 0xe1279100 [Type: _KEY_VALUE_PARTIAL_INFORMATION *]
[+0x000] TitleIndex : 0x0 [Type: unsigned long]
[+0x004] Type : 0x1 [Type: unsigned long]
[+0x008] DataLength : 0x18 [Type: unsigned long]
[+0x00c] Data [Type: unsigned char [1]]
0: kd> db 0xe127910c
e127910c 32 00 26 00 64 00 61 00-62 00 61 00 33 00 66 00 2.&.d.a.b.a.3.f.
e127911c 66 00 26 00 30 00 00 00-01 00 00 00 00 02 03 00 f.&.0...........
2.&.d.a.b.a.3.f.f.&.0
2&daba3ff&0
#ifndef REG_SZ
#define REG_SZ 0x0001
#endif
#ifndef REG_BINARY
#define REG_BINARY 0x0003
#endif
#ifndef REG_DWORD
#define REG_DWORD 0x0004
参考:"ParentIdPrefix"="2&daba3ff&2"
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ACPI_HAL\PNP0C08\0]
"Capabilities"=dword:00000030
"HardwareID"=hex(7):41,00,43,00,50,00,49,00,5f,00,48,00,41,00,4c,00,5c,00,50,\
00,4e,00,50,00,30,00,43,00,30,00,38,00,00,00,2a,00,50,00,4e,00,50,00,30,00,\
43,00,30,00,38,00,00,00,00,00
"ContainerID"="{00000000-0000-0000-ffff-ffffffffffff}"
"Service"="ACPI"
"ClassGUID"="{4d36e97d-e325-11ce-bfc1-08002be10318}"
"ConfigFlags"=dword:00000000
"ParentIdPrefix"="2&daba3ff&2" 关键地方:"ParentIdPrefix"
"Driver"="{4d36e97d-e325-11ce-bfc1-08002be10318}\\0012"
"Class"="System"
"Mfg"="@acpi.inf,%msft%;Microsoft"
"DeviceDesc"="@acpi.inf,%*pnp0c08.devicedesc%;Microsoft ACPI-Compliant System"
参考结束:
DevNode 0x89db5008 for PDO 0x89db5cb8
InstancePath is "ACPI_HAL\PNP0C08\0"
ServiceName is "ACPI"
State = DeviceNodeStarted (0x308)
Previous State = DeviceNodeEnumerateCompletion (0x30d)
DevNode 0x89d26558 for PDO 0x89d38bf0
InstancePath is "ACPI\PNP0A03\2&daba3ff&0"
ServiceName is "pci"
State = DeviceNodeStarted (0x308)
Previous State = DeviceNodeEnumerateCompletion (0x30d)
0: kd> dv Prefix
Prefix = 0xe1296370
0: kd> db 0xe1296370
e1296370 32 00 26 00 64 00 61 00-62 00 61 00 33 00 66 00 2.&.d.a.b.a.3.f.
e1296380 66 00 26 00 30 00 00 00-04 06 07 0c 50 70 20 20 f.&.0.......Pp
//
// Construct the instance id from the non-unique id (if any)
// provided by the child and the prefix we've constructed.
//
length = (ULONG)(wcslen(Prefix) + (UniqueId ? wcslen(UniqueId) : 0) + 2);
id = (PWSTR)ExAllocatePool(PagedPool, length * sizeof(WCHAR));
if (!id) {
status = STATUS_INSUFFICIENT_RESOURCES;
} else if (UniqueId) {
StringCchPrintfW(id, length, L"%s&%s", Prefix, UniqueId);
} else {
StringCchCopyW(id, length, Prefix); 这个:
}
0: kd> dv UniqueId
UniqueId = 0x00000000
0: kd> dv length
length = 0xd
0: kd> dv id
id = 0xe1285440
0: kd> dx -r1 ((ntkrnlmp!unsigned short *)0xe1285440)
((ntkrnlmp!unsigned short *)0xe1285440) : 0xe1285440 : 0x32 [Type: unsigned short *]
0x32 [Type: unsigned short]
0: kd> db 0xe1285440
e1285440 32 00 26 00 64 00 61 00-62 00 61 00 33 00 66 00 2.&.d.a.b.a.3.f.
e1285450 66 00 26 00 30 00 00 00-4c 49 53 54 70 b2 b2 b2 f.&.0...LISTp...
*GloballyUniqueId = id;
return status;
}
参考:
// 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>
//
// 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);
//
// Hash routine from CNTFS (see cntfs\prefxsup.c)
// (used here in the construction of unique ids)
//
#define HASH_UNICODE_STRING( _pustr, _phash ) { \
PWCHAR _p = (_pustr)->Buffer; \
PWCHAR _ep = _p + ((_pustr)->Length/sizeof(WCHAR)); \
ULONG _chHolder =0; \
\
while( _p < _ep ) { \
_chHolder = 37 * _chHolder + (unsigned int) (*_p++); \
} \
\
*(_phash) = abs(314159269 * _chHolder) % 1000000007; \
}
参考:
参考:
还需要指出的是, USBSTOR表键下有一名为ParentIdPrefix键值, 该键值数据通过关联MountedDevices表键可以指示出USB设备的盘符信息。
比如, 图2所示的ParentIdPrefix键值数据内容为“ 7& 3a221764& 0” ,
MountedDevices表键下的“ \DosDevices\I:” 键值数据内容中亦出现有“ \Storage#RemoveableMedia#7& 3a221764& 0” 字样(图3),
说明该设备被分配的盘符为I。
遗憾的是, MountedDevices表键下的信息只会存储最近一次挂载的ParentIdPrefix键值信息, 无法追溯盘符分配的历史记录。
Windows 7注册表中则不再含有ParentIdPrefix键值, 而是通过设备序列号与MountedDevices表键关联, 以确定盘符。
参考:
“PNP0C0C”,然后将该设备标识为OSPM的电源按钮。