"""微信 4.1.15.13 联系人缓存的只读名字快照;调用方必须先核对核心 DLL 指纹。""" from __future__ import annotations import struct from .account import APP_GLOBAL_RVA, _pointer, read_current_account, validate_account CACHE_PROVIDER_GETTER_RVA = 0x36C7B0 CACHE_PROVIDER_VTABLE_RVA = 0x8F9BF98 CONTACT_CACHE_VTABLE_RVA = 0x8FA2538 def read_contact_name(read_memory, core_base, wxid, *, expected_account=None): """按实际成员 ID 读取微信名。缺失、切换、重建缓存时返回 None,不猜名字。 仅遍历已核对的缓存对象,不调用微信函数、不扫描整个进程、不读取群昵称或备注。 """ validate_account(wxid) account = read_current_account(read_memory, core_base) if not account or (expected_account is not None and account != expected_account): return None try: def read(address, length): value = read_memory(_pointer(address), length) if len(value) != length: raise ValueError("联系人名字读取不完整") return value def ptr(address): return struct.unpack(" 64 or any(ord(ch) < 32 for ch in name): return None if (ptr(node + 0x30) != contact or string(node + 0x10, 127) != wxid or read(cache + 0xC8, 0x38) != layout or read(bucket_address, 16) != bucket or ptr(context + 0x460) != provider or read_current_account(read_memory, core_base) != account): return None return name.strip() if node == first: return None node = ptr(node + 8) return None except (OSError, ValueError, struct.error): return None