Skip to content

Commit

Permalink
Fea #71, 优化DrawThemeTextEx实现,不存在时优先调用uxtheme内部非导出函数版本。
Browse files Browse the repository at this point in the history
  • Loading branch information
mingkuang-Chuyu committed May 27, 2024
1 parent 33e3a56 commit d60bbd8
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 31 deletions.
2 changes: 1 addition & 1 deletion ThunksList.md
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@
## uxtheme.dll
| 函数 | Fallback
| ---- | -----------
| DrawThemeTextEx | 不存在时,调用DrawThemeText
| DrawThemeTextEx | 不存在时,尝试获取非导出DrawThemeTextEx。如果任然获取失败则调用DrawThemeText
| GetThemeTransitionDuration | 不存在时,返回E_NOTIMPL。
| SetWindowThemeAttribute | 不存在时,返回E_NOTIMPL。

Expand Down
41 changes: 25 additions & 16 deletions src/Thunks/YY_Thunks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,19 +165,7 @@ RtlCutoverTimeToSystemTime(
#define __DEFINE_THUNK(_MODULE, _SIZE, _RETURN_, _CONVENTION_, _FUNCTION, ...) \
__APPLY_UNIT_TEST_BOOL(_FUNCTION); \
EXTERN_C _RETURN_ _CONVENTION_ _FUNCTION(__VA_ARGS__); \
static decltype(_FUNCTION)* __cdecl _CRT_CONCATENATE(try_get_, _FUNCTION)() noexcept \
{ \
__CHECK_UNIT_TEST_BOOL(_FUNCTION); \
__declspec(allocate(".YYThr$AAA")) static void* _CRT_CONCATENATE(pInit_ ,_FUNCTION) = \
reinterpret_cast<void*>(&_CRT_CONCATENATE(try_get_, _FUNCTION)); \
/*为了避免编译器将 YYThr$AAA 节优化掉*/ \
__foreinclude(_CRT_CONCATENATE(pInit_ ,_FUNCTION)); \
__declspec(allocate(".YYThu$AAB")) static void* _CRT_CONCATENATE(pFun_, _FUNCTION); \
return reinterpret_cast<decltype(_FUNCTION)*>(try_get_function( \
&_CRT_CONCATENATE(pFun_ ,_FUNCTION), \
_CRT_STRINGIZE(_FUNCTION), \
&_CRT_CONCATENATE(try_get_module_, _MODULE))); \
} \
static decltype(_FUNCTION)* __cdecl _CRT_CONCATENATE(try_get_, _FUNCTION)() noexcept; \
__if_not_exists(_CRT_CONCATENATE(try_get_, _FUNCTION))


Expand Down Expand Up @@ -770,9 +758,30 @@ namespace YY::Thunks::internal

//导入实际的实现
#define YY_Thunks_Implemented
#define __DEFINE_THUNK(_MODULE, _SIZE, _RETURN_, _CONVENTION_, _FUNCTION, ...) \
_LCRT_DEFINE_IAT_SYMBOL(_FUNCTION, _SIZE); \
_YY_THUNKS_DEFINE_RUST_RAW_DYLIB_IAT_SYMBOL(_FUNCTION, _SIZE); \
#define __DEFINE_THUNK(_MODULE, _SIZE, _RETURN_, _CONVENTION_, _FUNCTION, ...) \
static decltype(_FUNCTION)* __cdecl _CRT_CONCATENATE(try_get_, _FUNCTION)() noexcept \
{ \
__CHECK_UNIT_TEST_BOOL(_FUNCTION); \
__declspec(allocate(".YYThr$AAA")) static void* _CRT_CONCATENATE(pInit_ ,_FUNCTION) = \
reinterpret_cast<void*>(&_CRT_CONCATENATE(try_get_, _FUNCTION)); \
/*为了避免编译器将 YYThr$AAA 节优化掉*/ \
__foreinclude(_CRT_CONCATENATE(pInit_ ,_FUNCTION)); \
__declspec(allocate(".YYThu$AAB")) static void* _CRT_CONCATENATE(pFun_, _FUNCTION); \
static const ProcInfo _ProcInfo = \
{ \
_CRT_STRINGIZE(_FUNCTION), \
&_CRT_CONCATENATE(try_get_module_, _MODULE), \
__if_exists(YY::Thunks::Fallback::_CRT_CONCATENATE(try_get_, _FUNCTION)) \
{ \
&YY::Thunks::Fallback::_CRT_CONCATENATE(try_get_, _FUNCTION) \
} \
}; \
return reinterpret_cast<decltype(_FUNCTION)*>(try_get_function( \
&_CRT_CONCATENATE(pFun_ ,_FUNCTION), \
_ProcInfo)); \
} \
_LCRT_DEFINE_IAT_SYMBOL(_FUNCTION, _SIZE); \
_YY_THUNKS_DEFINE_RUST_RAW_DYLIB_IAT_SYMBOL(_FUNCTION, _SIZE); \
EXTERN_C _RETURN_ _CONVENTION_ _FUNCTION(__VA_ARGS__)

#include "YY_Thunks_List.hpp"
Expand Down
46 changes: 32 additions & 14 deletions src/Thunks/YY_Thunks.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,28 +309,39 @@ static HMODULE __fastcall try_get_module(volatile HMODULE* pModule, const wchar_
}

#define _APPLY(_MODULE, _NAME, _FLAGS) \
static volatile HMODULE __fastcall _CRT_CONCATENATE(try_get_module_, _MODULE)() noexcept \
static HMODULE __fastcall _CRT_CONCATENATE(try_get_module_, _MODULE)() noexcept \
{ \
__declspec(allocate(".YYThu$AAA")) static volatile HMODULE hModule; \
return try_get_module<_FLAGS>(&hModule, _CRT_CONCATENATE(module_name_, _MODULE)); \
}
_YY_APPLY_TO_LATE_BOUND_MODULES(_APPLY)
#undef _APPLY

typedef volatile HMODULE (__fastcall* try_get_module_fun)();
typedef HMODULE (__fastcall* try_get_module_fun)();
typedef void*(__fastcall* try_get_proc_fallback_fun)();

struct ProcInfo
{
char const* const szProcName;
try_get_module_fun pfnGetModule;
try_get_proc_fallback_fun pfnGetProcFallback;
};

static __forceinline void* __fastcall try_get_proc_address_from_first_available_module(
try_get_module_fun get_module,
char const* const name
) noexcept
const ProcInfo& _ProcInfo
) noexcept
{
HMODULE const module_handle = get_module();
HMODULE const module_handle = _ProcInfo.pfnGetModule();
if (!module_handle)
{
return nullptr;
}

return reinterpret_cast<void*>(GetProcAddress(module_handle, name));
auto _pProc = reinterpret_cast<void*>(GetProcAddress(module_handle, _ProcInfo.szProcName));
if (_pProc || _ProcInfo.pfnGetProcFallback == nullptr)
return _pProc;

return _ProcInfo.pfnGetProcFallback();
}


Expand All @@ -342,9 +353,8 @@ static __forceinline void* __cdecl invalid_function_sentinel() noexcept

static void* __fastcall try_get_function(
void** ppFunAddress,
char const* const name,
try_get_module_fun get_module
) noexcept
const ProcInfo& _ProcInfo
) noexcept
{
// First check to see if we've cached the function pointer:
{
Expand All @@ -365,7 +375,7 @@ static void* __fastcall try_get_function(
// If we haven't yet cached the function pointer, try to import it from any
// of the modules in which it might be defined. If this fails, cache the
// sentinel pointer so that we don't attempt to load this function again:
void* const new_fp = try_get_proc_address_from_first_available_module(get_module, name);
void* const new_fp = try_get_proc_address_from_first_available_module(_ProcInfo);
if (!new_fp)
{
void* const cached_fp = __crt_fast_decode_pointer(
Expand Down Expand Up @@ -406,15 +416,23 @@ static void* __fastcall try_get_function(
static _CRT_CONCATENATE(_FUNCTION, _pft) __cdecl _CRT_CONCATENATE(try_get_, _FUNCTION)() noexcept \
{ \
__CHECK_UNIT_TEST_BOOL(_FUNCTION); \
__declspec(allocate(".YYThr$AAA")) static void* _CRT_CONCATENATE(pInit_ ,_FUNCTION) = \
__declspec(allocate(".YYThr$AAA")) static void* const _CRT_CONCATENATE(pInit_ ,_FUNCTION) = \
reinterpret_cast<void*>(&_CRT_CONCATENATE(try_get_, _FUNCTION)); \
/*为了避免编译器将 YYThr$AAA 节优化掉*/ \
__foreinclude(_CRT_CONCATENATE(pInit_ ,_FUNCTION)); \
__declspec(allocate(".YYThu$AAB")) static void* _CRT_CONCATENATE( pFun_ ,_FUNCTION); \
static const ProcInfo _ProcInfo = \
{ \
_CRT_STRINGIZE(_FUNCTION), \
&_CRT_CONCATENATE(try_get_module_, _MODULE), \
__if_exists(YY::Thunks::Fallback::_CRT_CONCATENATE(try_get_, _FUNCTION)) \
{ \
&YY::Thunks::Fallback::_CRT_CONCATENATE(try_get_, _FUNCTION) \
} \
}; \
return reinterpret_cast<_CRT_CONCATENATE(_FUNCTION, _pft)>(try_get_function( \
&_CRT_CONCATENATE(pFun_ ,_FUNCTION), \
_CRT_STRINGIZE(_FUNCTION), \
&_CRT_CONCATENATE(try_get_module_, _MODULE))); \
_ProcInfo)); \
}
_YY_APPLY_TO_LATE_BOUND_FUNCTIONS(_APPLY)
#undef _APPLY
Expand Down
40 changes: 40 additions & 0 deletions src/Thunks/uxtheme.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,40 @@
#pragma comment(lib, "UxTheme.lib")
#endif

#if defined(YY_Thunks_Implemented) && defined(_X86_) && (YY_Thunks_Support_Version < NTDDI_WIN6)
namespace YY::Thunks::Fallback
{
static void* __fastcall try_get_DrawThemeTextEx() noexcept
{
auto _pUxThemeBase = (const char*)try_get_module_uxtheme();
if (!_pUxThemeBase)
return nullptr;

MEMORY_BASIC_INFORMATION _BaseInfo;

// Windows XP SP3 其实已经实现了DrawThemeTextEx,只是没有导出。
static const BYTE kAttributeCode_6_0_2900_5512[] =
{
0x8B, 0xFF, 0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x0C,
0x83, 0x4D, 0xF8, 0xFF, 0x83, 0x65, 0xF4, 0x00,
0x83, 0x7D, 0x0C, 0x00, 0x56,
};
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;
}
}
#endif


namespace YY::Thunks
{
#if (YY_Thunks_Support_Version < NTDDI_WIN6)
Expand Down Expand Up @@ -60,6 +94,12 @@ namespace YY::Thunks
return _pfnGetThemeTransitionDuration(hTheme, iPartId, iStateIdFrom, iStateIdTo, iPropId, pdwDuration);
}

if (pdwDuration == nullptr || iStateIdFrom <= 0 || iStateIdTo <= 0)
{
return E_INVALIDARG;
}

*pdwDuration = 0;
return E_NOTIMPL;
}
#endif
Expand Down

0 comments on commit d60bbd8

Please sign in to comment.