diff --git a/ThunksList.md b/ThunksList.md index 00d5fd3..71b3207 100644 --- a/ThunksList.md +++ b/ThunksList.md @@ -168,8 +168,10 @@ ## CfgMgr32.dll | 函数 | Fallback | ---- | ----------- -| CM_Get_DevNode_PropertyW | 不存在时,调用CM_Get_DevNode_Registry_PropertyW。 -| CM_Set_DevNode_PropertyW | 不存在时,调用CM_Set_DevNode_Registry_PropertyW。 +| CM_Get_DevNode_Property_ExW | 不存在时,调用CM_Get_DevNode_Registry_PropertyW。 +| CM_Set_DevNode_Property_ExW | 不存在时,调用CM_Set_DevNode_Registry_PropertyW。 +| CM_Get_DevNode_PropertyW | 不存在时,调用CM_Get_DevNode_Property_ExW。 +| CM_Set_DevNode_PropertyW | 不存在时,调用CM_Set_DevNode_Property_ExW。 ## Crypt32.dll | 函数 | Fallback diff --git a/src/Thunks/CfgMgr32.hpp b/src/Thunks/CfgMgr32.hpp index 6b5ebc4..f655e58 100644 --- a/src/Thunks/CfgMgr32.hpp +++ b/src/Thunks/CfgMgr32.hpp @@ -194,6 +194,50 @@ namespace YY::Thunks::Fallback return &_Item; } + void* __fastcall try_get_CM_Get_DevNode_Property_ExW(const ProcInfo& _ProcInfo) + { + auto _pProc = try_get_proc_address_from_dll(_ProcInfo); + if (_pProc) + return _pProc; + + static constexpr const ProcOffsetInfo s_ProcInfo[] = + { +#if defined(_X86_) + { 0x4549BDB0ul, 0x7427B681ul - 0x74270000ul }, // 6.0.6000.16386 (Windows Vista RTM) + { 0x4791A754ul, 0x738DB93Dul - 0x738D0000ul }, // 6.0.6002.18000 (Windows Vista SP1) + { 0x49E037E9ul, 0x744DED36ul - 0x744D0000ul }, // 6.0.6002.18005 (Windows Vista SP2) +#elif defined(_AMD64_) + { 0x4549D318ul, 0x000007FF7C006400ull - 0x7FF7C000000ull }, // 6.0.6000.16386 (Windows Vista RTM) + { 0x4791ADA3ul, 0x000007FF7BC06E00ull - 0x7FF7BC00000ull }, // 6.0.6002.18000 (Windows Vista SP1) + { 0x49E041EDul, 0x000007FF7C007090ull - 0x7FF7C000000ull }, // 6.0.6002.18005 (Windows Vista SP2) +#endif + }; + + __WarningMessage__("try_get_CM_Get_DevNode_Property_ExW 可能遗漏Vista/2008某些补丁中的setupapi.dll,如果你知道详细可以提交PR。"); + return try_get_proc_address_from_offset(try_get_module_setupapi(), s_ProcInfo); + } + + void* __fastcall try_get_CM_Set_DevNode_Property_ExW(const ProcInfo& _ProcInfo) + { + auto _pProc = try_get_proc_address_from_dll(_ProcInfo); + if (_pProc) + return _pProc; + static constexpr const ProcOffsetInfo s_ProcInfo[] = + { +#if defined(_X86_) + { 0x4549BDB0ul, 0x7433C705ul - 0x74270000ul }, // 6.0.6000.16386 (Windows Vista RTM) + { 0x4791A754ul, 0x7399D7ADul - 0x738D0000ul }, // 6.0.6002.18000 (Windows Vista SP1) + { 0x49E037E9ul, 0x7459DC1Dul - 0x744D0000ul }, // 6.0.6002.18005 (Windows Vista SP2) +#elif defined(_AMD64_) + { 0x4549D318ul, 0x000007FF7C0FDD70ull - 0x7FF7C000000ull }, // 6.0.6000.16386 (Windows Vista RTM) + { 0x4791ADA3ul, 0x000007FF7BCE1E08ull - 0x7FF7BC00000ull }, // 6.0.6002.18000 (Windows Vista SP1) + { 0x49E041EDul, 0x000007FF7C0E2550ull - 0x7FF7C000000ull }, // 6.0.6002.18005 (Windows Vista SP2) +#endif + }; + + __WarningMessage__("try_get_CM_Set_DevNode_Property_ExW 可能遗漏Vista/2008某些补丁中的setupapi.dll,如果你知道详细可以提交PR。"); + return try_get_proc_address_from_offset(try_get_module_setupapi(), s_ProcInfo); + } #endif } } @@ -203,29 +247,28 @@ namespace YY::Thunks { #if (YY_Thunks_Support_Version < NTDDI_WIN7) - // 最低受支持的客户端 在 Microsoft Windows Vista 和更高版本的 Windows 中可用。 - // 实际Windows Vista RTM根本就没有这个接口 + // Windows 7 RTM 导出 + // Windows Vista有这个函数但是没有导出 __DEFINE_THUNK( cfgmgr32, - 24, + 28, CONFIGRET, WINAPI, - CM_Get_DevNode_PropertyW, + CM_Get_DevNode_Property_ExW, _In_ DEVINST dnDevInst, _In_ CONST DEVPROPKEY* PropertyKey, _Out_ DEVPROPTYPE* PropertyType, _Out_writes_bytes_opt_(*PropertyBufferSize) PBYTE PropertyBuffer, _Inout_ PULONG PropertyBufferSize, - _In_ ULONG ulFlags + _In_ ULONG ulFlags, + _In_opt_ HMACHINE hMachine ) { - if (const auto _pfnCM_Get_DevNode_PropertyW = try_get_CM_Get_DevNode_PropertyW()) + if (const auto _pfnCM_Get_DevNode_Property_ExW = try_get_CM_Get_DevNode_Property_ExW()) { - return _pfnCM_Get_DevNode_PropertyW(dnDevInst, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, ulFlags); + return _pfnCM_Get_DevNode_Property_ExW(dnDevInst, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, ulFlags, hMachine); } - __WarningMessage__("Opt,Vista系统的setuapi.dll存在CM_Get_DevNode_Property_ExW,但是没有导出。"); - if (!PropertyKey) return CR_INVALID_DEVINST; @@ -243,18 +286,18 @@ namespace YY::Thunks if (!Fallback::DevNodeTempPropertyBufffer::HasTransform(_pProperty->PropertyType)) { - return CM_Get_DevNode_Registry_PropertyW(dnDevInst, _pProperty->CM_DeviceRegistryProperty, nullptr, PropertyBuffer, PropertyBufferSize, ulFlags); + return CM_Get_DevNode_Registry_Property_ExW(dnDevInst, _pProperty->CM_DeviceRegistryProperty, nullptr, PropertyBuffer, PropertyBufferSize, ulFlags, hMachine); } Fallback::DevNodeTempPropertyBufffer TempBuffer = {}; ULONG _cbTempBuffer = sizeof(TempBuffer); - auto _Error = CM_Get_DevNode_Registry_PropertyW(dnDevInst, _pProperty->CM_DeviceRegistryProperty, nullptr, &TempBuffer, &_cbTempBuffer, ulFlags); + auto _Error = CM_Get_DevNode_Registry_Property_ExW(dnDevInst, _pProperty->CM_DeviceRegistryProperty, nullptr, &TempBuffer, &_cbTempBuffer, ulFlags, hMachine); if (CR_SUCCESS != _Error) { return _Error; } - if(!TempBuffer.TryTransformGetBuffer(_pProperty->PropertyType, PropertyBuffer, PropertyBufferSize)) + if (!TempBuffer.TryTransformGetBuffer(_pProperty->PropertyType, PropertyBuffer, PropertyBufferSize)) return CR_BUFFER_SMALL; return CR_SUCCESS; @@ -264,26 +307,27 @@ namespace YY::Thunks #if (YY_Thunks_Support_Version < NTDDI_WIN7) - // 最低受支持的客户端 在 Microsoft Windows Vista 和更高版本的 Windows 中可用。 - // 实际Windows Vista RTM根本就没有这个接口 + // Windows 7 RTM 导出 + // Windows Vista有这个函数但是没有导出 __DEFINE_THUNK( cfgmgr32, - 24, + 28, CONFIGRET, WINAPI, - CM_Set_DevNode_PropertyW, + CM_Set_DevNode_Property_ExW, _In_ DEVINST dnDevInst, - _In_ CONST DEVPROPKEY *PropertyKey, + _In_ CONST DEVPROPKEY* PropertyKey, _In_ DEVPROPTYPE PropertyType, _In_reads_bytes_opt_(PropertyBufferSize) PBYTE PropertyBuffer, _In_ ULONG PropertyBufferSize, - _In_ ULONG ulFlags + _In_ ULONG ulFlags, + _In_opt_ HMACHINE hMachine ) { - if (const auto _pfnCM_Set_DevNode_PropertyW = try_get_CM_Set_DevNode_PropertyW()) + if (const auto _pfnCM_Set_DevNode_Property_ExW = try_get_CM_Set_DevNode_Property_ExW()) { - return _pfnCM_Set_DevNode_PropertyW(dnDevInst, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, ulFlags); - } + return _pfnCM_Set_DevNode_Property_ExW(dnDevInst, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, ulFlags, hMachine); + } if (!PropertyKey) return CR_INVALID_DEVINST; @@ -305,7 +349,63 @@ namespace YY::Thunks if (!TempBuffer.TryTransformSetBuffer(PropertyType, &PropertyBuffer, &PropertyBufferSize)) return CR_BUFFER_SMALL; - return CM_Set_DevNode_Registry_PropertyW(dnDevInst, _pProperty->CM_DeviceRegistryProperty, PropertyBuffer, PropertyBufferSize, ulFlags); + return CM_Set_DevNode_Registry_Property_ExW(dnDevInst, _pProperty->CM_DeviceRegistryProperty, PropertyBuffer, PropertyBufferSize, ulFlags, hMachine); + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN7) + + // 最低受支持的客户端 在 Microsoft Windows Vista 和更高版本的 Windows 中可用。 + // 实际Windows Vista RTM根本就没有这个接口 + __DEFINE_THUNK( + cfgmgr32, + 24, + CONFIGRET, + WINAPI, + CM_Get_DevNode_PropertyW, + _In_ DEVINST dnDevInst, + _In_ CONST DEVPROPKEY* PropertyKey, + _Out_ DEVPROPTYPE* PropertyType, + _Out_writes_bytes_opt_(*PropertyBufferSize) PBYTE PropertyBuffer, + _Inout_ PULONG PropertyBufferSize, + _In_ ULONG ulFlags + ) + { + if (const auto _pfnCM_Get_DevNode_PropertyW = try_get_CM_Get_DevNode_PropertyW()) + { + return _pfnCM_Get_DevNode_PropertyW(dnDevInst, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, ulFlags); + } + + return ::CM_Get_DevNode_Property_ExW(dnDevInst, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, ulFlags, nullptr); + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN7) + + // 最低受支持的客户端 在 Microsoft Windows Vista 和更高版本的 Windows 中可用。 + // 实际Windows Vista RTM根本就没有这个接口 + __DEFINE_THUNK( + cfgmgr32, + 24, + CONFIGRET, + WINAPI, + CM_Set_DevNode_PropertyW, + _In_ DEVINST dnDevInst, + _In_ CONST DEVPROPKEY *PropertyKey, + _In_ DEVPROPTYPE PropertyType, + _In_reads_bytes_opt_(PropertyBufferSize) PBYTE PropertyBuffer, + _In_ ULONG PropertyBufferSize, + _In_ ULONG ulFlags + ) + { + if (const auto _pfnCM_Set_DevNode_PropertyW = try_get_CM_Set_DevNode_PropertyW()) + { + return _pfnCM_Set_DevNode_PropertyW(dnDevInst, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, ulFlags); + } + + return ::CM_Set_DevNode_Property_ExW(dnDevInst, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, ulFlags, nullptr); } #endif } diff --git a/src/Thunks/YY_Thunks.cpp b/src/Thunks/YY_Thunks.cpp index 9396d18..eceb611 100644 --- a/src/Thunks/YY_Thunks.cpp +++ b/src/Thunks/YY_Thunks.cpp @@ -1117,15 +1117,10 @@ static HMODULE __fastcall try_get_module(volatile HMODULE* pModule, const wchar_ return new_handle; } -static __forceinline void* __fastcall try_get_proc_address_from_first_available_module( - const ProcInfo& _ProcInfo +static __forceinline void* __fastcall try_get_proc_address_from_dll( + const ProcInfo& _ProcInfo ) noexcept { - if (_ProcInfo.pfnCustomGetProcAddress) - { - return _ProcInfo.pfnCustomGetProcAddress(_ProcInfo); - } - HMODULE const module_handle = _ProcInfo.pfnGetModule(); if (!module_handle) { @@ -1155,3 +1150,15 @@ static __forceinline void* __fastcall try_get_proc_address_from_first_available_ return reinterpret_cast(GetProcAddress(module_handle, _ProcInfo.szProcName)); #endif // defined(__USING_NTDLL_LIB) } + +static __forceinline void* __fastcall try_get_proc_address_from_first_available_module( + const ProcInfo& _ProcInfo + ) noexcept +{ + if (_ProcInfo.pfnCustomGetProcAddress) + { + return _ProcInfo.pfnCustomGetProcAddress(_ProcInfo); + } + + return try_get_proc_address_from_dll(_ProcInfo); +} diff --git a/src/Thunks/YY_Thunks.h b/src/Thunks/YY_Thunks.h index f7ffad0..e9c193e 100644 --- a/src/Thunks/YY_Thunks.h +++ b/src/Thunks/YY_Thunks.h @@ -196,6 +196,16 @@ static PVOID __fastcall YY_ImageDirectoryEntryToData( return PBYTE(pBaseAddress) + _DataDirectory.VirtualAddress; } +static DWORD __fastcall GetDllTimeDateStamp(_In_ HMODULE _hModule) +{ + if (!_hModule) + return 0; + + auto _pDosHeader = (PIMAGE_DOS_HEADER)_hModule; + auto _pNtHerder = reinterpret_cast(PBYTE(_hModule) + _pDosHeader->e_lfanew); + return _pNtHerder->FileHeader.TimeDateStamp; +} + enum : int { __crt_maximum_pointer_shift = sizeof(uintptr_t) * 8 @@ -329,6 +339,47 @@ static __forceinline void* __fastcall try_get_proc_address_from_first_available_ const ProcInfo& _ProcInfo ) noexcept; +static __forceinline void* __fastcall try_get_proc_address_from_dll( + const ProcInfo& _ProcInfo + ) noexcept; + +struct ProcOffsetInfo +{ + DWORD uTimeDateStamp; + DWORD uProcOffset; +}; + +template +static __forceinline void* __fastcall try_get_proc_address_from_offset( + HMODULE _hModule, + const ProcOffsetInfo (&_ProcOffsetInfos)[kLength] + ) noexcept +{ + if (_hModule) + { + __try + { + const auto _uTimeDateStamp = GetDllTimeDateStamp(_hModule); + if (_uTimeDateStamp) + { + for (auto& _ProcOffsetInfo : _ProcOffsetInfos) + { + if (_ProcOffsetInfo.uTimeDateStamp == _uTimeDateStamp) + { + return PBYTE(_hModule) + _ProcOffsetInfo.uProcOffset; + } + } + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + // 避免遇到畸形DLL而触发异常。 + } + } + + return nullptr; +} + static __forceinline void* __cdecl invalid_function_sentinel() noexcept { return reinterpret_cast(static_cast(-1)); diff --git a/src/Thunks/uxtheme.hpp b/src/Thunks/uxtheme.hpp index f424708..0a493ac 100644 --- a/src/Thunks/uxtheme.hpp +++ b/src/Thunks/uxtheme.hpp @@ -7,39 +7,33 @@ #pragma comment(lib, "UxTheme.lib") #endif -#if defined(YY_Thunks_Implemented) && defined(_X86_) && (YY_Thunks_Support_Version < NTDDI_WIN6) +#if defined(YY_Thunks_Implemented) && (YY_Thunks_Support_Version < NTDDI_WIN6) namespace YY::Thunks::Fallback { static void* __fastcall try_get_DrawThemeTextEx(const ProcInfo& _ProcInfo) noexcept { - auto _pUxThemeBase = (const char*)_ProcInfo.pfnGetModule(); - if (!_pUxThemeBase) - return nullptr; + auto _pProc = try_get_proc_address_from_dll(_ProcInfo); + if (_pProc) + return _pProc; - auto _pfn = ::GetProcAddress((HMODULE)_pUxThemeBase, _ProcInfo.szProcName); - if (_pfn) - return _pfn; - - MEMORY_BASIC_INFORMATION _BaseInfo; - - // Windows XP SP3 其实已经实现了DrawThemeTextEx,只是没有导出。 - static const BYTE kAttributeCode_6_0_2900_5512[] = + static constexpr const ProcOffsetInfo s_ProcInfo[] = { - 0x8B, 0xFF, 0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x0C, - 0x83, 0x4D, 0xF8, 0xFF, 0x83, 0x65, 0xF4, 0x00, - 0x83, 0x7D, 0x0C, 0x00, 0x56, +#if defined(_X86_) + { 0x3B901769ul, 0x5ADC5C2Ful - 0x5ADC0000ul }, // 6.0.2600.0 (Windows XP RTM) + { 0x3D7D2609ul, 0x5ADC5AEDul - 0x5ADC0000ul }, // 6.0.2800.1106 (Windows XP SP1) + { 0x4121457Aul, 0x5ADC645Cul - 0x5ADC0000ul }, // 6.0.2900.2180 (Windows XP SP2) + { 0x4802BDC0ul, 0x5ADC2FF8ul - 0x5ADC0000ul }, // 6.0.2900.5512 (Windows XP SP3) + { 0x3E8024BEul, 0x71B8ACA0ul - 0x71B70000ul }, // 6.0.3790.0 (Windows 2003) + { 0x42437794ul, 0x7DF64466ul - 0x7DF50000ul }, // 6.0.3790.1830 (Windows 2003 SP1) + { 0x45D70ACBul, 0x71B91D41ul - 0x71B70000ul }, // 6.0.3790.3959 (Windows 2003 SP2) +#elif defined(_AMD64_) + { 0x42438B57ul, 0x7FF77069A60ull - 0x7FF77060000ull }, // 6.0.3790.1830 (Windows 2003 SP1) + { 0x45D6CCAEul, 0x000007FF77239A70ull - 0x7FF77230000ull }, // 6.0.3790.3959 (Windows 2003 SP2) +#endif }; - constexpr auto kAttributeCode_6_0_2900_5512_Offset = 0x5ADC2FF8 - 0x5ADC0000; - auto _pTarget = _pUxThemeBase + kAttributeCode_6_0_2900_5512_Offset; - if (VirtualQuery(_pTarget, &_BaseInfo, sizeof(_BaseInfo)) && _BaseInfo.AllocationBase == _pUxThemeBase) - { - if (memcmp(_pTarget, kAttributeCode_6_0_2900_5512, sizeof(kAttributeCode_6_0_2900_5512)) == 0) - { - return (void*)_pTarget; - } - } - return nullptr; + __WarningMessage__("try_get_DrawThemeTextEx 可能遗漏某些XP/2003补丁中的uxtheme.dll,如果你知道详细可以提交PR。"); + return try_get_proc_address_from_offset(try_get_module_uxtheme(), s_ProcInfo); } } #endif