diff --git a/ThunksList.md b/ThunksList.md index 8b45bde..ea0b13f 100644 --- a/ThunksList.md +++ b/ThunksList.md @@ -221,7 +221,7 @@ ## dwrite.dll | 函数 | Fallback | ---- | ----------- -| DWriteCreateFactory | 不存在时,返回 `E_NOINTERFACE`。 +| DWriteCreateFactory | 不存在时,返回 `E_NOINTERFACE`。
此外NT6或者更高版本提供IDWriteFactory3模拟。 ## dxgi.dll | 函数 | Fallback diff --git a/src/Build.cmd b/src/Build.cmd index c496c59..1dda907 100644 --- a/src/Build.cmd +++ b/src/Build.cmd @@ -26,7 +26,7 @@ goto:eof :BuildObj echo BuildObj %1 %2 %3 -cl /O1 /Os /Oi /GS- /std:c++17 /execution-charset:utf-8 /arch:IA32 /Z7 /MT /Fo"objs\\%Platform%\\%1" /Zl /c /D "NDEBUG" /D "YY_Thunks_Support_Version=%2" "%~dp0Thunks\YY_Thunks.cpp" +cl /O1 /Os /Oi /GS- /std:c++17 /execution-charset:utf-8 /arch:IA32 /Z7 /MT /Fo"objs\\%Platform%\\%1" /Zl /c /D "NDEBUG" /D "YY_Thunks_Target=%2" "%~dp0Thunks\YY_Thunks.cpp" if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% ::weakţһЩDZŰΪweakԱʧ @@ -52,7 +52,7 @@ echo BuildLib %1 %2 %3 md "Lib\\%1\\%Platform%" -cl /O1 /Os /Oi /GS- /std:c++17 /execution-charset:utf-8 /arch:IA32 /Z7 /MT /Fo"Lib\\%1\\%Platform%\\YY_Thunks_for_%1.obj" /Zl /c /D "__APPLY_CHROMIUM_WORKAROUNDS" /D "__USING_NTDLL_LIB" /D "NDEBUG" /D "YY_Thunks_Support_Version=%2" /D "__FALLBACK_PREFIX=YY_Thunks_" "%~dp0Thunks\YY_Thunks.cpp" +cl /O1 /Os /Oi /GS- /std:c++17 /execution-charset:utf-8 /arch:IA32 /Z7 /MT /Fo"Lib\\%1\\%Platform%\\YY_Thunks_for_%1.obj" /Zl /c /D "__APPLY_CHROMIUM_WORKAROUNDS" /D "__USING_NTDLL_LIB" /D "NDEBUG" /D "YY_Thunks_Target=%2" /D "__FALLBACK_PREFIX=YY_Thunks_" "%~dp0Thunks\YY_Thunks.cpp" if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% @@ -95,25 +95,25 @@ goto:eof :Buildx86 set PointType=4 -call:BuildX 5.0.2195.0 YY_Thunks_for_Win2K.obj NTDDI_WIN2K PSAPI2Kernel32.def+esent.def +call:BuildX 5.0.2195.0 YY_Thunks_for_Win2K.obj __WindowsNT5 PSAPI2Kernel32.def+esent.def if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% -call:BuildX 5.1.2600.0 YY_Thunks_for_WinXP.obj NTDDI_WINXP PSAPI2Kernel32.def+esent.def +call:BuildX 5.1.2600.0 YY_Thunks_for_WinXP.obj __WindowsNT5_1 PSAPI2Kernel32.def+esent.def if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% -call:BuildX 6.0.6000.0 YY_Thunks_for_Vista.obj NTDDI_WIN6 PSAPI2Kernel32.def +call:BuildX 6.0.6000.0 YY_Thunks_for_Vista.obj __WindowsNT6 PSAPI2Kernel32.def if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% -call:BuildX 6.1.7600.0 YY_Thunks_for_Win7.obj NTDDI_WIN7 +call:BuildX 6.1.7600.0 YY_Thunks_for_Win7.obj __WindowsNT6_1 if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% -call:BuildX 6.2.9200.0 YY_Thunks_for_Win8.obj NTDDI_WIN8 +call:BuildX 6.2.9200.0 YY_Thunks_for_Win8.obj __WindowsNT6_2 if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% -call:BuildX 10.0.10240.0 YY_Thunks_for_Win10.0.10240.obj NTDDI_WIN10 +call:BuildX 10.0.10240.0 YY_Thunks_for_Win10.0.10240.obj __WindowsNT10_10240 if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% -call:BuildX 10.0.19041.0 YY_Thunks_for_Win10.0.19041.obj NTDDI_WIN10_VB +call:BuildX 10.0.19041.0 YY_Thunks_for_Win10.0.19041.obj __WindowsNT10_19041 if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% goto:eof @@ -121,46 +121,45 @@ goto:eof :Buildx64 set PointType=8 -call:BuildX 5.2.3790.1180 YY_Thunks_for_WinXP.obj NTDDI_WS03SP1 PSAPI2Kernel32.def+esent.def +call:BuildX 5.2.3790.1830 YY_Thunks_for_WinXP.obj __WindowsNT5_2_SP1 PSAPI2Kernel32.def+esent.def if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% -call:BuildX 6.0.6000.0 YY_Thunks_for_Vista.obj NTDDI_WIN6 PSAPI2Kernel32.def +call:BuildX 6.0.6000.0 YY_Thunks_for_Vista.obj __WindowsNT6 PSAPI2Kernel32.def if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% -call:BuildX 6.1.7600.0 YY_Thunks_for_Win7.obj NTDDI_WIN7 +call:BuildX 6.1.7600.0 YY_Thunks_for_Win7.obj __WindowsNT6_1 if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% -call:BuildX 6.2.9200.0 YY_Thunks_for_Win8.obj NTDDI_WIN8 +call:BuildX 6.2.9200.0 YY_Thunks_for_Win8.obj __WindowsNT6_2 if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% -call:BuildX 10.0.10240.0 YY_Thunks_for_Win10.0.10240.obj NTDDI_WIN10 +call:BuildX 10.0.10240.0 YY_Thunks_for_Win10.0.10240.obj __WindowsNT10_10240 if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% -call:BuildX 10.0.19041.0 YY_Thunks_for_Win10.0.19041.obj NTDDI_WIN10_VB +call:BuildX 10.0.19041.0 YY_Thunks_for_Win10.0.19041.obj __WindowsNT10_19041 if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% goto:eof :Buildarm set PointType=4 -call:BuildX 6.2.9200.0 YY_Thunks_for_Win8.obj NTDDI_WIN8 +call:BuildX 6.2.9200.0 YY_Thunks_for_Win8.obj __WindowsNT6_2 if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% -call:BuildX 10.0.10240.0 YY_Thunks_for_Win10.0.10240.obj NTDDI_WIN10 +call:BuildX 10.0.10240.0 YY_Thunks_for_Win10.0.10240.obj __WindowsNT10_10240 if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% -call:BuildX 10.0.19041.0 YY_Thunks_for_Win10.0.19041.obj NTDDI_WIN10_VB +call:BuildX 10.0.19041.0 YY_Thunks_for_Win10.0.19041.obj __WindowsNT10_19041 if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% goto:eof :Buildarm64 set PointType=8 -; NTDDI_WIN10_RS3 = 16299 -call:BuildX 10.0.10240.0 YY_Thunks_for_Win10.0.10240.obj NTDDI_WIN10_RS3 +call:BuildX 10.0.10240.0 YY_Thunks_for_Win10.0.10240.obj __WindowsNT10_16299 if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% -call:BuildX 10.0.19041.0 YY_Thunks_for_Win10.0.19041.obj NTDDI_WIN10_VB +call:BuildX 10.0.19041.0 YY_Thunks_for_Win10.0.19041.obj __WindowsNT10_19041 if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% goto:eof diff --git a/src/Shared/SharedDefs.h b/src/Shared/SharedDefs.h index b19d3ac..5b067b7 100644 --- a/src/Shared/SharedDefs.h +++ b/src/Shared/SharedDefs.h @@ -33,3 +33,82 @@ using _Type = std::underlying_type<_ENUM>::type; \ return (_Type)_eLeft & (_Type)_eRight; \ } + +#define __Version(Major, Minor, Build, Revision) (Major * 0x1000000000000ull + Minor * 0x100000000ull + Build * 0x10000ull + Revision) + +// 版本号参考来源: +// https://github.com/MouriNaruto/MouriDocs/tree/main/docs/18 + +// Windows 2000 RTM x86 +#define __WindowsNT5 __Version(5, 0, 2195, 0) + +// Windows XP RTM x86 +#define __WindowsNT5_1 __Version(5, 1, 2600, 0) + +#define __WindowsNT5_1_SP1 __Version(5, 1, 2600, 1106) + +#define __WindowsNT5_1_SP2 __Version(5, 1, 2600, 2180) + +#define __WindowsNT5_1_SP3 __Version(5, 1, 2600, 5512) + +// Windows 2003 RTM x86 +#define __WindowsNT5_2 __Version(5, 2, 3790, 0) + +// Windows XP RTM x64,Windows 2003 SP1 +#define __WindowsNT5_2_SP1 __Version(5, 2, 3790, 1830) + +// Windows Vista RTM, Windows Server 2008 RTM +#define __WindowsNT6 __Version(6, 0, 6000, 0) + +#define __WindowsNT6_SP1 __Version(6, 0, 6001, 0) + +#define __WindowsNT6_SP2 __Version(6, 0, 6002, 0) + +// Windows 7 RTM, Windows Server 2008 R2 RTM +#define __WindowsNT6_1 __Version(6, 1, 7600, 0) + +#define __WindowsNT6_1_SP1 __Version(6, 1, 7601, 0) + +// Windows 8 RTM, Windows Server 2012 RTM +#define __WindowsNT6_2 __Version(6, 2, 9200, 0) + +// Windows 8.1 RTM, Windows Server 2012 R2 RTM +#define __WindowsNT6_3 __Version(6, 3, 9600, 0) + +// Windows 10 1507 +#define __WindowsNT10_10240 __Version(10, 0, 10240, 0) + +// Windows 10 1607(RS1) +#define __WindowsNT10_14393 __Version(10, 0, 14393, 0) + +// Windows 10 1703(RS2) +#define __WindowsNT10_15063 __Version(10, 0, 15063, 0) + +// Windows 10 1709(RS3),注意ARM64从这个版本开始才支持。 +#define __WindowsNT10_16299 __Version(10, 0, 16299, 0) + +// Windows 10 2004(VB) +#define __WindowsNT10_19041 __Version(10, 0, 19041, 0) + +// Windows Server 2022(FE) +#define __WindowsNT10_20348 __Version(10, 0, 20348, 0) + +#if defined(_M_IX86) +#define __WindowsMinTarget __WindowsNT5 +#elif defined(_M_AMD64) +#define __WindowsMinTarget __WindowsNT5_2_SP1 +#elif defined(_M_ARM) +#define __WindowsMinTarget __WindowsNT6_2 +#elif defined(_M_ARM64) +#define __WindowsMinTarget __WindowsNT10_16299 +#endif + +#ifndef YY_Thunks_Target +#define YY_Thunks_Target __WindowsMinTarget +#endif + +// 输错了版本号? +#if YY_Thunks_Target < __WindowsMinTarget +#undef YY_Thunks_Target +#define YY_Thunks_Target __WindowsMinTarget +#endif diff --git a/src/Thunks/BCryptPrimitives.hpp b/src/Thunks/BCryptPrimitives.hpp index b508fe0..4c2ab44 100644 --- a/src/Thunks/BCryptPrimitives.hpp +++ b/src/Thunks/BCryptPrimitives.hpp @@ -6,23 +6,23 @@ extern "C" BOOL WINAPI ProcessPrng( namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - // 用户反馈Windows 7也会报告此API不存在。 - __DEFINE_THUNK( - bcryptprimitives, - 8, - BOOL, - WINAPI, - ProcessPrng, + // 用户反馈Windows 7也会报告此API不存在。 + __DEFINE_THUNK( + bcryptprimitives, + 8, + BOOL, + WINAPI, + ProcessPrng, _Out_writes_bytes_(_cbBuffer) PUCHAR _pbBuffer, _In_ ULONG _cbBuffer ) - { - if (auto _pfnProcessPrng = try_get_ProcessPrng()) - { - return _pfnProcessPrng(_pbBuffer, _cbBuffer); - } + { + if (auto _pfnProcessPrng = try_get_ProcessPrng()) + { + return _pfnProcessPrng(_pbBuffer, _cbBuffer); + } const auto _pfnRtlGenRandom = try_get_SystemFunction036(); if (!_pfnRtlGenRandom) @@ -32,6 +32,6 @@ namespace YY::Thunks } return _pfnRtlGenRandom(_pbBuffer, _cbBuffer); - } + } #endif } // namespace YY::Thunks diff --git a/src/Thunks/CfgMgr32.hpp b/src/Thunks/CfgMgr32.hpp index d240b17..3fc11f1 100644 --- a/src/Thunks/CfgMgr32.hpp +++ b/src/Thunks/CfgMgr32.hpp @@ -1,14 +1,14 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) #include #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) && !defined(__Comment_Lib_setupapi) +#if (YY_Thunks_Target < __WindowsNT6_1) && !defined(__Comment_Lib_setupapi) #define __Comment_Lib_setupapi #pragma comment(lib, "SetupAPI.Lib") #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) && __YY_Thunks_libs && !defined(__Comment_Lib_cfgmgr32) +#if (YY_Thunks_Target < __WindowsNT6_1) && __YY_Thunks_libs && !defined(__Comment_Lib_cfgmgr32) #define __Comment_Lib_cfgmgr32 #pragma comment(lib, "cfgmgr32.Lib") #endif @@ -18,7 +18,7 @@ namespace YY::Thunks::Fallback { namespace { -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) struct DevNodeTempPropertyBufffer { wchar_t szId[39]; @@ -251,7 +251,7 @@ namespace YY::Thunks::Fallback namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) // Windows 7 RTM 导出 // Windows Vista有这个函数但是没有导出 @@ -311,7 +311,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) // Windows 7 RTM 导出 // Windows Vista有这个函数但是没有导出 @@ -360,7 +360,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) // 最低受支持的客户端 在 Microsoft Windows Vista 和更高版本的 Windows 中可用。 // 实际Windows Vista RTM根本就没有这个接口 @@ -388,7 +388,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) // 最低受支持的客户端 在 Microsoft Windows Vista 和更高版本的 Windows 中可用。 // 实际Windows Vista RTM根本就没有这个接口 diff --git a/src/Thunks/Crypt32.hpp b/src/Thunks/Crypt32.hpp index 191789f..04e297e 100644 --- a/src/Thunks/Crypt32.hpp +++ b/src/Thunks/Crypt32.hpp @@ -1,56 +1,55 @@ -#include +#if (YY_Thunks_Target < __WindowsNT6) +#include +#endif -namespace YY +namespace YY::Thunks { - namespace Thunks - { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - crypt32, - 12, - BOOL, - WINAPI, - CryptProtectMemory, - _Inout_ LPVOID pDataIn, - _In_ DWORD cbDataIn, - _In_ DWORD dwFlags - ) - { - if (const auto _pfnProcessPrng = try_get_CryptProtectMemory()) - { - return _pfnProcessPrng(pDataIn, cbDataIn, dwFlags); - } + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + crypt32, + 12, + BOOL, + WINAPI, + CryptProtectMemory, + _Inout_ LPVOID pDataIn, + _In_ DWORD cbDataIn, + _In_ DWORD dwFlags + ) + { + if (const auto _pfnProcessPrng = try_get_CryptProtectMemory()) + { + return _pfnProcessPrng(pDataIn, cbDataIn, dwFlags); + } - return TRUE; - } + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - crypt32, - 12, - BOOL, - WINAPI, - CryptUnprotectMemory, - _Inout_ LPVOID pDataIn, - _In_ DWORD cbDataIn, - _In_ DWORD dwFlags - ) - { - if (const auto _pfnProcessPrng = try_get_CryptUnprotectMemory()) - { - return _pfnProcessPrng(pDataIn, cbDataIn, dwFlags); - } + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + crypt32, + 12, + BOOL, + WINAPI, + CryptUnprotectMemory, + _Inout_ LPVOID pDataIn, + _In_ DWORD cbDataIn, + _In_ DWORD dwFlags + ) + { + if (const auto _pfnProcessPrng = try_get_CryptUnprotectMemory()) + { + return _pfnProcessPrng(pDataIn, cbDataIn, dwFlags); + } - return TRUE; - } + return TRUE; + } #endif - } // namespace Thunks -} // namespace YY +} // namespace YY::Thunks diff --git a/src/Thunks/DllMainCRTStartup.hpp b/src/Thunks/DllMainCRTStartup.hpp index 235e51b..10a5faa 100644 --- a/src/Thunks/DllMainCRTStartup.hpp +++ b/src/Thunks/DllMainCRTStartup.hpp @@ -11,7 +11,7 @@ namespace YY::Thunks::internal // 如果希望自定义函数入口点,可以设置此函数 extern "C" extern decltype(_DllMainCRTStartup)* const __pfnDllMainCRTStartupForYY_Thunks; -#if YY_Thunks_Support_Version < NTDDI_WIN6 +#if YY_Thunks_Target < __WindowsNT6 extern "C" ULONG _tls_index; static ULONG _tls_index_old; #ifdef _WIN64 @@ -375,7 +375,7 @@ namespace YY::Thunks::internal { } } -#endif // YY_Thunks_Support_Version < NTDDI_WIN6 +#endif // YY_Thunks_Target < __WindowsNT6 // 我们始终提供DllMainCRTStartupForYY_Thunks函数,虽然理论上Vista(包含)以上就不用修正了,但是为了做到体验统一 // 避免Vista模式设置 DllMainCRTStartupForYY_Thunks 就发生链接失败问题。 @@ -394,7 +394,7 @@ namespace YY::Thunks::internal case DLL_PROCESS_ATTACH: _YY_initialize_winapi_thunks(ThunksInitStatus::InitByDllMain); -#if YY_Thunks_Support_Version < NTDDI_WIN6 +#if YY_Thunks_Target < __WindowsNT6 if (internal::GetSystemVersion() < internal::MakeVersion(6, 0)) { __declspec(allocate(".CRT$XLB")) static const PIMAGE_TLS_CALLBACK s_FirstCallback = FirstCallback; @@ -413,7 +413,7 @@ namespace YY::Thunks::internal #endif return _pfnDllMainCRTStartup(_hInstance, _uReason, _pReserved); break; -#if YY_Thunks_Support_Version < NTDDI_WIN6 +#if YY_Thunks_Target < __WindowsNT6 case DLL_THREAD_ATTACH: if (internal::GetSystemVersion() < internal::MakeVersion(6, 0) && _tls_index_old == 0 && g_TlsMode == TlsMode::ByDllMainCRTStartupForYY_Thunks) { @@ -437,11 +437,11 @@ namespace YY::Thunks::internal break; #endif case DLL_PROCESS_DETACH: -#if (YY_Thunks_Support_Version < NTDDI_WINXP) +#if (YY_Thunks_Target < __WindowsNT5_1) __YY_Thunks_Process_Terminating = _pReserved != nullptr; #endif -#if YY_Thunks_Support_Version < NTDDI_WIN6 +#if YY_Thunks_Target < __WindowsNT6 if (internal::GetSystemVersion() < internal::MakeVersion(6, 0) && _tls_index_old == 0 && g_TlsMode == TlsMode::ByDllMainCRTStartupForYY_Thunks) { CallTlsCallback(_hInstance, _uReason); diff --git a/src/Thunks/Iphlpapi.hpp b/src/Thunks/Iphlpapi.hpp index b2f4b6b..120899b 100644 --- a/src/Thunks/Iphlpapi.hpp +++ b/src/Thunks/Iphlpapi.hpp @@ -1,10 +1,10 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS2) +#if (YY_Thunks_Target < __WindowsNT10_15063) #include #include #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS2) && !defined(__Comment_Lib_iphlpapi) +#if (YY_Thunks_Target < __WindowsNT10_15063) && !defined(__Comment_Lib_iphlpapi) #define __Comment_Lib_iphlpapi #pragma comment(lib, "Iphlpapi.lib") #endif @@ -12,138 +12,138 @@ #if defined(YY_Thunks_Implemented) namespace YY::Thunks { - namespace - { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - static void MIB_IFROW_To_MIB_IF_ROW2(_In_ const MIB_IFROW* _pRow, _Out_ MIB_IF_ROW2* _pRow2) - { - memset(_pRow2, 0, sizeof(*_pRow2)); - - _pRow2->InterfaceLuid.Info.NetLuidIndex = _pRow->dwIndex; - _pRow2->InterfaceLuid.Info.IfType = _pRow->dwType; - _pRow2->InterfaceIndex = _pRow->dwIndex; - - internal::StringToGuid(wcsrchr(_pRow->wszName, L'{'), &_pRow2->InterfaceGuid); - // memcpy(_pRow2->Alias, _pRow->wszName, sizeof(_pRow->wszName)); - const auto _cchDescr = min(sizeof(_pRow->bDescr), _pRow->dwDescrLen); - for (size_t i = 0; i != _cchDescr; ++i) - { - _pRow2->Description[i] = _pRow->bDescr[i]; - } - _pRow2->PhysicalAddressLength = _pRow->dwPhysAddrLen; - memcpy(_pRow2->PhysicalAddress, _pRow->bPhysAddr, min(sizeof(_pRow->bPhysAddr), _pRow->dwPhysAddrLen)); - memcpy(_pRow2->PermanentPhysicalAddress, _pRow->bPhysAddr, min(sizeof(_pRow->bPhysAddr), _pRow->dwPhysAddrLen)); - - _pRow2->Mtu = _pRow->dwMtu; - _pRow2->Type = _pRow->dwType; - - if (IF_TYPE_SOFTWARE_LOOPBACK == _pRow->dwType) - { - _pRow2->MediaType = NdisMediumLoopback; - _pRow2->AccessType = NET_IF_ACCESS_LOOPBACK; - _pRow2->DirectionType = NET_IF_DIRECTION_SENDRECEIVE; - } - else - { - // 设置一个默认值,都假装自己是普通的网口 - _pRow2->MediaType = NdisMedium802_3; - _pRow2->AccessType = NET_IF_ACCESS_BROADCAST; - _pRow2->DirectionType = NET_IF_DIRECTION_SENDRECEIVE; - } - - switch (_pRow->dwOperStatus) - { - case IF_OPER_STATUS_OPERATIONAL: - case IF_OPER_STATUS_CONNECTED: - _pRow2->OperStatus = IF_OPER_STATUS::IfOperStatusUp; - _pRow2->MediaConnectState = MediaConnectStateConnected; - break; - default: - _pRow2->OperStatus = IF_OPER_STATUS::IfOperStatusDown; - break; - } - - // - _pRow2->AdminStatus = (NET_IF_ADMIN_STATUS)_pRow->dwAdminStatus; - _pRow2->ConnectionType = NET_IF_CONNECTION_DEDICATED; - - - _pRow2->TransmitLinkSpeed = _pRow->dwSpeed; - _pRow2->ReceiveLinkSpeed = _pRow->dwSpeed; - _pRow2->InOctets = _pRow->dwInOctets; - _pRow2->InUcastPkts = _pRow->dwInUcastPkts; - _pRow2->InNUcastPkts = _pRow->dwInNUcastPkts; - _pRow2->InDiscards = _pRow->dwInDiscards; - _pRow2->InErrors = _pRow->dwInErrors; - _pRow2->InUnknownProtos = _pRow->dwInUnknownProtos; - // 伪造一下 InUcastOctets - _pRow2->InUcastOctets = _pRow->dwInOctets; - _pRow2->InMulticastOctets = 0; - _pRow2->InBroadcastOctets = 0; - _pRow2->OutOctets = _pRow->dwOutOctets; - _pRow2->OutUcastPkts = _pRow->dwOutUcastPkts; - _pRow2->OutNUcastPkts = _pRow->dwOutNUcastPkts; - _pRow2->OutDiscards = _pRow->dwOutDiscards; - _pRow2->OutErrors = _pRow->dwOutErrors; - // 伪造一下 OutUcastOctets - _pRow2->OutUcastOctets = _pRow->dwOutOctets; - _pRow2->OutMulticastOctets = 0; - _pRow2->OutBroadcastOctets = 0; - _pRow2->OutQLen = _pRow->dwOutQLen; - } - - static - NETIOAPI_API - GetIfTable2ExDownlevel( - _In_ MIB_IF_TABLE_LEVEL _eLevel, - _Outptr_ PMIB_IF_TABLE2* _ppTable2 - ) - { - // Windows XP 无法支持_eLevel - // 相比较无法启动,一些状态报告不对就这样凑合吧。 - UNREFERENCED_PARAMETER(_eLevel); - - if (!_ppTable2) - return ERROR_INVALID_PARAMETER; - *_ppTable2 = nullptr; - - const auto _hProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; - - constexpr DWORD _cbTable = sizeof(MIB_IFTABLE) + 256 * sizeof(MIB_IFROW); - auto _pTable = (MIB_IFTABLE*)HeapAlloc(_hProcessHeap, 0, _cbTable); - if (!_pTable) - return ERROR_NOT_ENOUGH_MEMORY; - - LSTATUS _lStatus; - do - { - DWORD _uSize = _cbTable; - _lStatus = ::GetIfTable(_pTable, &_uSize, FALSE); - if (_lStatus != NO_ERROR) - break; - - const DWORD _cbTable2 = sizeof(MIB_IF_TABLE2) + _pTable->dwNumEntries * sizeof(MIB_IF_ROW2); - auto _pTable2 = (MIB_IF_TABLE2*)HeapAlloc(_hProcessHeap, 0, _cbTable2); - if (!_pTable2) - { - _lStatus = ERROR_NOT_ENOUGH_MEMORY; - break; - } - - _pTable2->NumEntries = _pTable->dwNumEntries; - for (DWORD i = 0; i != _pTable->dwNumEntries; ++i) - { - MIB_IFROW_To_MIB_IF_ROW2(&_pTable->table[i], &_pTable2->Table[i]); - } - - *_ppTable2 = _pTable2; - } while (false); - - HeapFree(_hProcessHeap, 0, _pTable); - - return _lStatus; - } + namespace + { +#if (YY_Thunks_Target < __WindowsNT6) + + static void MIB_IFROW_To_MIB_IF_ROW2(_In_ const MIB_IFROW* _pRow, _Out_ MIB_IF_ROW2* _pRow2) + { + memset(_pRow2, 0, sizeof(*_pRow2)); + + _pRow2->InterfaceLuid.Info.NetLuidIndex = _pRow->dwIndex; + _pRow2->InterfaceLuid.Info.IfType = _pRow->dwType; + _pRow2->InterfaceIndex = _pRow->dwIndex; + + internal::StringToGuid(wcsrchr(_pRow->wszName, L'{'), &_pRow2->InterfaceGuid); + // memcpy(_pRow2->Alias, _pRow->wszName, sizeof(_pRow->wszName)); + const auto _cchDescr = min(sizeof(_pRow->bDescr), _pRow->dwDescrLen); + for (size_t i = 0; i != _cchDescr; ++i) + { + _pRow2->Description[i] = _pRow->bDescr[i]; + } + _pRow2->PhysicalAddressLength = _pRow->dwPhysAddrLen; + memcpy(_pRow2->PhysicalAddress, _pRow->bPhysAddr, min(sizeof(_pRow->bPhysAddr), _pRow->dwPhysAddrLen)); + memcpy(_pRow2->PermanentPhysicalAddress, _pRow->bPhysAddr, min(sizeof(_pRow->bPhysAddr), _pRow->dwPhysAddrLen)); + + _pRow2->Mtu = _pRow->dwMtu; + _pRow2->Type = _pRow->dwType; + + if (IF_TYPE_SOFTWARE_LOOPBACK == _pRow->dwType) + { + _pRow2->MediaType = NdisMediumLoopback; + _pRow2->AccessType = NET_IF_ACCESS_LOOPBACK; + _pRow2->DirectionType = NET_IF_DIRECTION_SENDRECEIVE; + } + else + { + // 设置一个默认值,都假装自己是普通的网口 + _pRow2->MediaType = NdisMedium802_3; + _pRow2->AccessType = NET_IF_ACCESS_BROADCAST; + _pRow2->DirectionType = NET_IF_DIRECTION_SENDRECEIVE; + } + + switch (_pRow->dwOperStatus) + { + case IF_OPER_STATUS_OPERATIONAL: + case IF_OPER_STATUS_CONNECTED: + _pRow2->OperStatus = IF_OPER_STATUS::IfOperStatusUp; + _pRow2->MediaConnectState = MediaConnectStateConnected; + break; + default: + _pRow2->OperStatus = IF_OPER_STATUS::IfOperStatusDown; + break; + } + + // + _pRow2->AdminStatus = (NET_IF_ADMIN_STATUS)_pRow->dwAdminStatus; + _pRow2->ConnectionType = NET_IF_CONNECTION_DEDICATED; + + + _pRow2->TransmitLinkSpeed = _pRow->dwSpeed; + _pRow2->ReceiveLinkSpeed = _pRow->dwSpeed; + _pRow2->InOctets = _pRow->dwInOctets; + _pRow2->InUcastPkts = _pRow->dwInUcastPkts; + _pRow2->InNUcastPkts = _pRow->dwInNUcastPkts; + _pRow2->InDiscards = _pRow->dwInDiscards; + _pRow2->InErrors = _pRow->dwInErrors; + _pRow2->InUnknownProtos = _pRow->dwInUnknownProtos; + // 伪造一下 InUcastOctets + _pRow2->InUcastOctets = _pRow->dwInOctets; + _pRow2->InMulticastOctets = 0; + _pRow2->InBroadcastOctets = 0; + _pRow2->OutOctets = _pRow->dwOutOctets; + _pRow2->OutUcastPkts = _pRow->dwOutUcastPkts; + _pRow2->OutNUcastPkts = _pRow->dwOutNUcastPkts; + _pRow2->OutDiscards = _pRow->dwOutDiscards; + _pRow2->OutErrors = _pRow->dwOutErrors; + // 伪造一下 OutUcastOctets + _pRow2->OutUcastOctets = _pRow->dwOutOctets; + _pRow2->OutMulticastOctets = 0; + _pRow2->OutBroadcastOctets = 0; + _pRow2->OutQLen = _pRow->dwOutQLen; + } + + static + NETIOAPI_API + GetIfTable2ExDownlevel( + _In_ MIB_IF_TABLE_LEVEL _eLevel, + _Outptr_ PMIB_IF_TABLE2* _ppTable2 + ) + { + // Windows XP 无法支持_eLevel + // 相比较无法启动,一些状态报告不对就这样凑合吧。 + UNREFERENCED_PARAMETER(_eLevel); + + if (!_ppTable2) + return ERROR_INVALID_PARAMETER; + *_ppTable2 = nullptr; + + const auto _hProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; + + constexpr DWORD _cbTable = sizeof(MIB_IFTABLE) + 256 * sizeof(MIB_IFROW); + auto _pTable = (MIB_IFTABLE*)HeapAlloc(_hProcessHeap, 0, _cbTable); + if (!_pTable) + return ERROR_NOT_ENOUGH_MEMORY; + + LSTATUS _lStatus; + do + { + DWORD _uSize = _cbTable; + _lStatus = ::GetIfTable(_pTable, &_uSize, FALSE); + if (_lStatus != NO_ERROR) + break; + + const DWORD _cbTable2 = sizeof(MIB_IF_TABLE2) + _pTable->dwNumEntries * sizeof(MIB_IF_ROW2); + auto _pTable2 = (MIB_IF_TABLE2*)HeapAlloc(_hProcessHeap, 0, _cbTable2); + if (!_pTable2) + { + _lStatus = ERROR_NOT_ENOUGH_MEMORY; + break; + } + + _pTable2->NumEntries = _pTable->dwNumEntries; + for (DWORD i = 0; i != _pTable->dwNumEntries; ++i) + { + MIB_IFROW_To_MIB_IF_ROW2(&_pTable->table[i], &_pTable2->Table[i]); + } + + *_ppTable2 = _pTable2; + } while (false); + + HeapFree(_hProcessHeap, 0, _pTable); + + return _lStatus; + } struct IfTypeToNameItem { @@ -194,161 +194,161 @@ namespace YY::Thunks return "other"; } -#endif // (YY_Thunks_Support_Version < NTDDI_WIN6) - } +#endif // (YY_Thunks_Target < __WindowsNT6) + } } #endif // !YY_Thunks_Implemented namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - iphlpapi, - 4, - NETIO_STATUS, - NETIOAPI_API_, - GetIfTable2, - _Outptr_ PMIB_IF_TABLE2 * _ppTable2 - ) - { - if (auto _pfnGetIfTable2 = try_get_GetIfTable2()) - { - return _pfnGetIfTable2(_ppTable2); - } - - return GetIfTable2ExDownlevel(MibIfTableNormal, _ppTable2); - } +#if (YY_Thunks_Target < __WindowsNT6) + + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + iphlpapi, + 4, + NETIO_STATUS, + NETIOAPI_API_, + GetIfTable2, + _Outptr_ PMIB_IF_TABLE2 * _ppTable2 + ) + { + if (auto _pfnGetIfTable2 = try_get_GetIfTable2()) + { + return _pfnGetIfTable2(_ppTable2); + } + + return GetIfTable2ExDownlevel(MibIfTableNormal, _ppTable2); + } #endif - -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - iphlpapi, - 8, - NETIO_STATUS, - NETIOAPI_API_, - GetIfTable2Ex, - _In_ MIB_IF_TABLE_LEVEL _eLevel, - _Outptr_ PMIB_IF_TABLE2* _ppTable2 - ) - { - if (auto _pfnGetIfTable2Ex = try_get_GetIfTable2Ex()) - { - return _pfnGetIfTable2Ex(_eLevel, _ppTable2); - } - - return GetIfTable2ExDownlevel(_eLevel, _ppTable2); - } + +#if (YY_Thunks_Target < __WindowsNT6) + + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + iphlpapi, + 8, + NETIO_STATUS, + NETIOAPI_API_, + GetIfTable2Ex, + _In_ MIB_IF_TABLE_LEVEL _eLevel, + _Outptr_ PMIB_IF_TABLE2* _ppTable2 + ) + { + if (auto _pfnGetIfTable2Ex = try_get_GetIfTable2Ex()) + { + return _pfnGetIfTable2Ex(_eLevel, _ppTable2); + } + + return GetIfTable2ExDownlevel(_eLevel, _ppTable2); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - iphlpapi, - 4, - NETIO_STATUS, - NETIOAPI_API_, - GetIfEntry2, - _Inout_ PMIB_IF_ROW2 _pRow - ) - { - if (auto _pfnGetIfEntry2 = try_get_GetIfEntry2()) - { - return _pfnGetIfEntry2(_pRow); - } - - if (!_pRow) - return ERROR_INVALID_PARAMETER; - - MIB_IFROW _IfRow; - _IfRow.dwIndex = _pRow->InterfaceLuid.Value ? static_cast(_pRow->InterfaceLuid.Info.NetLuidIndex) : _pRow->InterfaceIndex; - - auto _lStatus = GetIfEntry(&_IfRow); - if (NO_ERROR != _lStatus) - return _lStatus; - - MIB_IFROW_To_MIB_IF_ROW2(&_IfRow, _pRow); - return NO_ERROR; - } +#if (YY_Thunks_Target < __WindowsNT6) + + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + iphlpapi, + 4, + NETIO_STATUS, + NETIOAPI_API_, + GetIfEntry2, + _Inout_ PMIB_IF_ROW2 _pRow + ) + { + if (auto _pfnGetIfEntry2 = try_get_GetIfEntry2()) + { + return _pfnGetIfEntry2(_pRow); + } + + if (!_pRow) + return ERROR_INVALID_PARAMETER; + + MIB_IFROW _IfRow; + _IfRow.dwIndex = _pRow->InterfaceLuid.Value ? static_cast(_pRow->InterfaceLuid.Info.NetLuidIndex) : _pRow->InterfaceIndex; + + auto _lStatus = GetIfEntry(&_IfRow); + if (NO_ERROR != _lStatus) + return _lStatus; + + MIB_IFROW_To_MIB_IF_ROW2(&_IfRow, _pRow); + return NO_ERROR; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS2) - - // 最低受支持的客户端 Windows 10版本 1703[仅限桌面应用] - // 最低受支持的服务器 Windows Server 2016[仅限桌面应用] - __DEFINE_THUNK( - iphlpapi, - 8, - NETIO_STATUS, - NETIOAPI_API_, - GetIfEntry2Ex, - _In_ MIB_IF_ENTRY_LEVEL _eLevel, - _Inout_ PMIB_IF_ROW2 _pRow - ) - { - if (auto _pfnGetIfEntry2Ex = try_get_GetIfEntry2Ex()) - { - return _pfnGetIfEntry2Ex(_eLevel, _pRow); - } - // 忽略Level,理论上说 多取了 Statistics信息也没有太大影响。 - UNREFERENCED_PARAMETER(_eLevel); - - return ::GetIfEntry2(_pRow); - } +#if (YY_Thunks_Target < __WindowsNT10_15063) + + // 最低受支持的客户端 Windows 10版本 1703[仅限桌面应用] + // 最低受支持的服务器 Windows Server 2016[仅限桌面应用] + __DEFINE_THUNK( + iphlpapi, + 8, + NETIO_STATUS, + NETIOAPI_API_, + GetIfEntry2Ex, + _In_ MIB_IF_ENTRY_LEVEL _eLevel, + _Inout_ PMIB_IF_ROW2 _pRow + ) + { + if (auto _pfnGetIfEntry2Ex = try_get_GetIfEntry2Ex()) + { + return _pfnGetIfEntry2Ex(_eLevel, _pRow); + } + // 忽略Level,理论上说 多取了 Statistics信息也没有太大影响。 + UNREFERENCED_PARAMETER(_eLevel); + + return ::GetIfEntry2(_pRow); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - iphlpapi, - 4, - void, - NETIOAPI_API_, - FreeMibTable, - _In_ PVOID _pMemory - ) - { - if (auto _pfnFreeMibTable = try_get_FreeMibTable()) - { - return _pfnFreeMibTable(_pMemory); - } - - if (_pMemory) - { - const auto _hProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; - HeapFree(_hProcessHeap, 0, _pMemory); - } - } +#if (YY_Thunks_Target < __WindowsNT6) + + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + iphlpapi, + 4, + void, + NETIOAPI_API_, + FreeMibTable, + _In_ PVOID _pMemory + ) + { + if (auto _pfnFreeMibTable = try_get_FreeMibTable()) + { + return _pfnFreeMibTable(_pMemory); + } + + if (_pMemory) + { + const auto _hProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; + HeapFree(_hProcessHeap, 0, _pMemory); + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - iphlpapi, - 8, - DWORD, +#if (YY_Thunks_Target < __WindowsNT6) + + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + iphlpapi, + 8, + DWORD, NETIOAPI_API_, ConvertInterfaceIndexToLuid, _In_ NET_IFINDEX InterfaceIndex, _Out_ PNET_LUID InterfaceLuid ) - { - if (const auto _pfnConvertInterfaceIndexToLuid = try_get_ConvertInterfaceIndexToLuid()) - { - return _pfnConvertInterfaceIndexToLuid(InterfaceIndex, InterfaceLuid); - } + { + if (const auto _pfnConvertInterfaceIndexToLuid = try_get_ConvertInterfaceIndexToLuid()) + { + return _pfnConvertInterfaceIndexToLuid(InterfaceIndex, InterfaceLuid); + } MIB_IFROW _IfRow; _IfRow.dwIndex = InterfaceIndex; @@ -367,25 +367,25 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [仅限桌面应用] + // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] - __DEFINE_THUNK( - iphlpapi, - 12, - DWORD, + __DEFINE_THUNK( + iphlpapi, + 12, + DWORD, NETIOAPI_API_, ConvertInterfaceLuidToNameA, _In_ CONST NET_LUID* InterfaceLuid, _Out_writes_(Length) PSTR InterfaceName, _In_ SIZE_T Length ) - { - if (const auto _pfnConvertInterfaceLuidToNameA = try_get_ConvertInterfaceLuidToNameA()) - { - return _pfnConvertInterfaceLuidToNameA(InterfaceLuid, InterfaceName, Length); - } + { + if (const auto _pfnConvertInterfaceLuidToNameA = try_get_ConvertInterfaceLuidToNameA()) + { + return _pfnConvertInterfaceLuidToNameA(InterfaceLuid, InterfaceName, Length); + } internal::StringBuffer _StringBuffer(InterfaceName, Length); if (!_StringBuffer.AppendString(GetAnsiNameFormeIndex(InterfaceLuid->Info.IfType))) @@ -407,24 +407,24 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - // 最低受支持的客户端 Windows Vista [仅限桌面应用] +#if (YY_Thunks_Target < __WindowsNT6) + // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] - __DEFINE_THUNK( - iphlpapi, - 12, - DWORD, + __DEFINE_THUNK( + iphlpapi, + 12, + DWORD, NETIOAPI_API_, ConvertInterfaceLuidToNameW, _In_ CONST NET_LUID* InterfaceLuid, _Out_writes_(Length) PWSTR InterfaceName, _In_ SIZE_T Length ) - { - if (const auto _pfnConvertInterfaceLuidToNameW = try_get_ConvertInterfaceLuidToNameW()) - { - return _pfnConvertInterfaceLuidToNameW(InterfaceLuid, InterfaceName, Length); - } + { + if (const auto _pfnConvertInterfaceLuidToNameW = try_get_ConvertInterfaceLuidToNameW()) + { + return _pfnConvertInterfaceLuidToNameW(InterfaceLuid, InterfaceName, Length); + } internal::StringBuffer _StringBuffer(InterfaceName, Length); if (!_StringBuffer.AppendString(GetAnsiNameFormeIndex(InterfaceLuid->Info.IfType))) @@ -446,24 +446,24 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [仅限桌面应用] + // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] - __DEFINE_THUNK( - iphlpapi, - 8, - DWORD, + __DEFINE_THUNK( + iphlpapi, + 8, + DWORD, NETIOAPI_API_, ConvertInterfaceNameToLuidA, _In_z_ CONST CHAR* InterfaceName, _Out_ NET_LUID* InterfaceLuid ) - { - if (const auto _pfnConvertInterfaceNameToLuidA = try_get_ConvertInterfaceNameToLuidA()) - { - return _pfnConvertInterfaceNameToLuidA(InterfaceName, InterfaceLuid); - } + { + if (const auto _pfnConvertInterfaceNameToLuidA = try_get_ConvertInterfaceNameToLuidA()) + { + return _pfnConvertInterfaceNameToLuidA(InterfaceName, InterfaceLuid); + } auto& _Map = GetIfTypeMapItems(); @@ -500,24 +500,24 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [仅限桌面应用] + // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] - __DEFINE_THUNK( - iphlpapi, - 8, - DWORD, + __DEFINE_THUNK( + iphlpapi, + 8, + DWORD, NETIOAPI_API_, ConvertInterfaceNameToLuidW, _In_z_ CONST WCHAR* InterfaceName, _Out_ NET_LUID* InterfaceLuid ) - { - if (const auto _pfnConvertInterfaceNameToLuidW = try_get_ConvertInterfaceNameToLuidW()) - { - return _pfnConvertInterfaceNameToLuidW(InterfaceName, InterfaceLuid); - } + { + if (const auto _pfnConvertInterfaceNameToLuidW = try_get_ConvertInterfaceNameToLuidW()) + { + return _pfnConvertInterfaceNameToLuidW(InterfaceName, InterfaceLuid); + } auto& _Map = GetIfTypeMapItems(); @@ -554,23 +554,23 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - iphlpapi, - 4, - NET_IFINDEX, + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + iphlpapi, + 4, + NET_IFINDEX, NETIOAPI_API_, if_nametoindex, _In_ PCSTR _szInterfaceName ) - { - if (const auto _pfnif_nametoindex = try_get_if_nametoindex()) - { - return _pfnif_nametoindex(_szInterfaceName); - } + { + if (const auto _pfnif_nametoindex = try_get_if_nametoindex()) + { + return _pfnif_nametoindex(_szInterfaceName); + } auto& _Map = GetIfTypeMapItems(); @@ -627,28 +627,28 @@ namespace YY::Thunks SetLastError(ERROR_INVALID_PARAMETER); return 0; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - iphlpapi, - 8, - PCHAR, + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + iphlpapi, + 8, + PCHAR, NETIOAPI_API_, if_indextoname, _In_ NET_IFINDEX InterfaceIndex, _Out_writes_(IF_NAMESIZE) PCHAR InterfaceName ) - { - if (const auto _pfnif_indextoname = try_get_if_indextoname()) - { - return _pfnif_indextoname(InterfaceIndex, InterfaceName); - } + { + if (const auto _pfnif_indextoname = try_get_if_indextoname()) + { + return _pfnif_indextoname(InterfaceIndex, InterfaceName); + } InterfaceName[0] = '\0'; NET_LUID InterfaceLuid; @@ -670,24 +670,24 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [仅限桌面应用] + // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] - __DEFINE_THUNK( - iphlpapi, - 8, + __DEFINE_THUNK( + iphlpapi, + 8, NETIO_STATUS, NETIOAPI_API_, ConvertInterfaceLuidToGuid, _In_ CONST NET_LUID* _pInterfaceLuid, _Out_ GUID* _pInterfaceGuid ) - { - if (const auto _pfnConvertInterfaceLuidToGuid = try_get_ConvertInterfaceLuidToGuid()) - { - return _pfnConvertInterfaceLuidToGuid(_pInterfaceLuid, _pInterfaceGuid); - } + { + if (const auto _pfnConvertInterfaceLuidToGuid = try_get_ConvertInterfaceLuidToGuid()) + { + return _pfnConvertInterfaceLuidToGuid(_pInterfaceLuid, _pInterfaceGuid); + } if (_pInterfaceLuid == nullptr || _pInterfaceGuid == nullptr) { @@ -711,24 +711,24 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [仅限桌面应用] + // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] - __DEFINE_THUNK( - iphlpapi, - 8, + __DEFINE_THUNK( + iphlpapi, + 8, NETIO_STATUS, NETIOAPI_API_, ConvertInterfaceLuidToIndex, _In_ CONST NET_LUID* _pInterfaceLuid, _Out_ PNET_IFINDEX _pInterfaceIndex ) - { - if (const auto _pfnConvertInterfaceLuidToIndex = try_get_ConvertInterfaceLuidToIndex()) - { - return _pfnConvertInterfaceLuidToIndex(_pInterfaceLuid, _pInterfaceIndex); - } + { + if (const auto _pfnConvertInterfaceLuidToIndex = try_get_ConvertInterfaceLuidToIndex()) + { + return _pfnConvertInterfaceLuidToIndex(_pInterfaceLuid, _pInterfaceIndex); + } if (_pInterfaceLuid == nullptr || _pInterfaceIndex == nullptr) { diff --git a/src/Thunks/Pdh.hpp b/src/Thunks/Pdh.hpp index 4c46f29..42d67e0 100644 --- a/src/Thunks/Pdh.hpp +++ b/src/Thunks/Pdh.hpp @@ -1,15 +1,15 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_pdh) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_pdh) #define __Comment_Lib_pdh #pragma comment(lib, "Pdh.lib") #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Windows Vista [desktop apps only] // Windows Server 2008 [desktop apps only] @@ -35,7 +35,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Windows Vista [desktop apps only] // Windows Server 2008 [desktop apps only] diff --git a/src/Thunks/PropSys.hpp b/src/Thunks/PropSys.hpp index 5e5fe09..c7ae3d3 100644 --- a/src/Thunks/PropSys.hpp +++ b/src/Thunks/PropSys.hpp @@ -1,14 +1,14 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_oleaut32) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_oleaut32) #define __Comment_Lib_oleaut32 // SafeArrayGetElement、SafeArrayGetLBound、SafeArrayGetUBound、VariantClear、VarCmp #pragma comment(lib, "OleAut32.lib") #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_ole32) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_ole32) #define __Comment_Lib_ole32 // CoTaskMemAlloc #pragma comment(lib, "ole32.lib") @@ -19,7 +19,7 @@ namespace YY::Thunks::internal { namespace { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) static HRESULT __fastcall SafeArrayGetCount(SAFEARRAY* _pArray, LONG* _pnLbound) { *_pnLbound = 0; @@ -289,7 +289,7 @@ namespace YY::Thunks::internal namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows XP SP2、Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2003 SP1[仅限桌面应用] @@ -322,7 +322,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows XP SP2、Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2003 SP1[仅限桌面应用] @@ -350,7 +350,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows XP SP2、Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2003 SP1[仅限桌面应用] @@ -378,7 +378,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows XP SP2、Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2003 SP1[仅限桌面应用] diff --git a/src/Thunks/SetupAPI.hpp b/src/Thunks/SetupAPI.hpp index 77827c1..158bc82 100644 --- a/src/Thunks/SetupAPI.hpp +++ b/src/Thunks/SetupAPI.hpp @@ -1,22 +1,22 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_setupapi) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_setupapi) #define __Comment_Lib_setupapi #pragma comment(lib, "Setupapi.lib") #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) //Available in Windows Vista and later versions of Windows. __DEFINE_THUNK( setupapi, 32, _Success_(return) - BOOL, + BOOL, WINAPI, SetupDiGetDevicePropertyW, _In_ HDEVINFO DeviceInfoSet, @@ -83,10 +83,10 @@ namespace YY::Thunks return _bRet; } -#endif //!YY_Thunks_Support_Version < NTDDI_WIN6 +#endif //!YY_Thunks_Target < __WindowsNT6 -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Available in Windows Vista and later versions of Windows. __DEFINE_THUNK( @@ -158,7 +158,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Available in Windows Vista and later versions of Windows. __DEFINE_THUNK( @@ -222,7 +222,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) //Available in Windows Vista and later versions of Windows. __DEFINE_THUNK( @@ -287,7 +287,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) //Available in Windows Vista and later versions of Windows. __DEFINE_THUNK( @@ -346,7 +346,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) //Available in Windows Vista and later versions of Windows. __DEFINE_THUNK( diff --git a/src/Thunks/UIAutomationCore.hpp b/src/Thunks/UIAutomationCore.hpp index 0d96394..5903b37 100644 --- a/src/Thunks/UIAutomationCore.hpp +++ b/src/Thunks/UIAutomationCore.hpp @@ -1,8 +1,10 @@ -#include +#if (YY_Thunks_Target < __WindowsNT10_16299) +#include +#endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows XP [桌面应用 | UWP 应用](需要安装 .NET) // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] @@ -25,7 +27,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows XP [桌面应用 | UWP 应用](需要安装 .NET) // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] @@ -51,7 +53,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows XP [桌面应用 | UWP 应用](需要安装 .NET) // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] @@ -75,7 +77,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows XP [桌面应用 | UWP 应用](需要安装 .NET) // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] @@ -101,7 +103,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows XP [桌面应用 | UWP 应用](需要安装 .NET) // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] @@ -127,7 +129,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows XP [桌面应用 | UWP 应用](需要安装 .NET) // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] @@ -153,7 +155,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows XP [桌面应用 | UWP 应用](需要安装 .NET) // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] @@ -177,7 +179,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows XP [桌面应用 | UWP 应用](需要安装 .NET) // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] @@ -203,7 +205,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS3) +#if (YY_Thunks_Target < __WindowsNT10_16299) // 最低受支持的客户端 Windows 10版本 1709 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2016[桌面应用 | UWP 应用] diff --git a/src/Thunks/WS2_32.hpp b/src/Thunks/WS2_32.hpp index 39200f2..0cada93 100644 --- a/src/Thunks/WS2_32.hpp +++ b/src/Thunks/WS2_32.hpp @@ -9,7 +9,7 @@ namespace YY::Thunks { namespace { -#if defined(YY_Thunks_Implemented) && YY_Thunks_Support_Version < NTDDI_WIN8 +#if defined(YY_Thunks_Implemented) && YY_Thunks_Target < __WindowsNT6_2 struct GetAddrInfoExParameter { // Parameter 的引用计数,如果引用归 0 则释放内存。 @@ -392,7 +392,7 @@ namespace YY::Thunks return WSA_NOT_ENOUGH_MEMORY; } -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) static INT WSAAPI GetAddrInfoExWDownlevel( _In_opt_ PCWSTR _szName, _In_opt_ PCWSTR _szServiceName, @@ -431,7 +431,7 @@ namespace YY::Thunks PADDRINFOEXW _pResultEx = nullptr; -#if (YY_Thunks_Support_Version < NTDDI_WINXPSP2) +#if (YY_Thunks_Target < __WindowsNT5_1_SP2) auto const GetAddrInfoW = try_get_GetAddrInfoW(); if (!GetAddrInfoW) { @@ -456,7 +456,7 @@ namespace YY::Thunks ::freeaddrinfo(_pResultA); return _lStatus; } -#endif // ! (YY_Thunks_Support_Version < NTDDI_WINXPSP2) +#endif // ! (YY_Thunks_Target < __WindowsNT5_1_SP2) PADDRINFOW _pResult = nullptr; auto _lStatus = GetAddrInfoW(_szName, _szServiceName, _pHintsEx ? &_Hints : nullptr, &_pResult); @@ -467,10 +467,10 @@ namespace YY::Thunks ::FreeAddrInfoW(_pResult); return _lStatus; } -#endif // ! (YY_Thunks_Support_Version < NTDDI_WIN6) +#endif // ! (YY_Thunks_Target < __WindowsNT6) -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) static INT WSAAPI GetAddrInfoExADownlevel( _In_opt_ PCSTR _szName, _In_opt_ PCSTR _szServiceName, @@ -520,963 +520,967 @@ namespace YY::Thunks ::freeaddrinfo(_pResultA); return _lStatus; } -#endif // ! (YY_Thunks_Support_Version < NTDDI_WIN6) +#endif // ! (YY_Thunks_Target < __WindowsNT6) -#endif // ! defined(YY_Thunks_Implemented) && YY_Thunks_Support_Version < NTDDI_WIN8 +#endif // ! defined(YY_Thunks_Implemented) && YY_Thunks_Target < __WindowsNT6_2 } +} -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows 8.1, Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - ws2_32, - 12, - INT, - WINAPI, - inet_pton, - _In_ INT Family, - _In_ PCSTR pszAddrString, - _When_(Family == AF_INET, _Out_writes_bytes_(sizeof(IN_ADDR))) - _When_(Family == AF_INET6, _Out_writes_bytes_(sizeof(IN6_ADDR))) - PVOID pAddrBuf - ) - { - if (auto pinet_pton = try_get_inet_pton()) - { - return pinet_pton(Family, pszAddrString, pAddrBuf); - } - - typedef char Char; - - if (nullptr == pszAddrString || nullptr == pAddrBuf) - { - WSASetLastError(WSAEFAULT); - return -1; - } - - if (AF_INET == Family) - { - //IPv4 - UCHAR IPAddress[4] = {}; - - unsigned i = 0; - for (; i != _countof(IPAddress); ) - { - auto& IPNum = IPAddress[i++]; - - auto Start = pszAddrString; - for (; *Start && *Start != Char('.'); ++Start) - { - auto& Ch = *Start; - - //必须是0~9数字 - if (Ch >= Char('0') && Ch <= Char('9')) - { - auto NewNum = IPNum * 10ul + (Ch & 0x0Ful); - if (NewNum > 0xFF) - { - //不能大于255 - return 0; - } - - IPNum = (UCHAR)NewNum; - } - else - { - return 0; - } - } - - // - if (Start == pszAddrString) - return 0; - - pszAddrString = Start; - - if (*pszAddrString == Char('\0')) - break; - else - ++pszAddrString; - } - - //未正常截断 - if (i != _countof(IPAddress) || *pszAddrString != Char('\0')) - return 0; - - - ((IN_ADDR *)pAddrBuf)->S_un.S_addr = *(ULONG*)IPAddress; - - return 1; - } - else if (AF_INET6 == Family) - { - //IPv6 - - IN6_ADDR IPAddress; - - int i = 0; - int InsertIndex = -1; - - for (; i != _countof(IPAddress.u.Word) && *pszAddrString; ) - { - if (pszAddrString[0] == Char(':') && pszAddrString[1] == Char(':')) - { - //缩进只能有一次 - if (InsertIndex != -1) - return 0; - - - InsertIndex = i; - - pszAddrString += 2; - continue; - } - - auto& IPNum = IPAddress.u.Word[i++]; - IPNum = 0; - - auto Start = pszAddrString; - for (; *Start && *Start != Char(':'); ++Start) - { - auto& Ch = *Start; - - - unsigned int NewNum; - - //0~9数字 - if (Ch >= Char('0') && Ch <= Char('9')) - { - NewNum = Ch & 0x0Ful; - } - else if (Ch >= Char('a') && Ch <= Char('f')) - { - NewNum = Ch - Char('a') + 10; - } - else if (Ch >= Char('A') && Ch <= Char('F')) - { - NewNum = Ch - Char('A') + 10; - } - else - { - //无法识别 - return 0; - } - - NewNum = ((unsigned int)IPNum << 4) | NewNum; - - if (NewNum > 0xFFFF) - { - //不能大于255 - return 0; - } - - IPNum = NewNum; - } - - - //截断错误 - if (Start == pszAddrString) - { - return 0; - } - - - IPNum = _byteswap_ushort(IPNum); - - pszAddrString = Start; - - if (*pszAddrString == Char('\0')) - { - break; - } - else if (pszAddrString[1] == Char(':')) - { - } - else - { - ++pszAddrString; - } - } - - - //未正常截断 - if (*pszAddrString != Char('\0')) - { - return 0; - } - else if (i != _countof(IPAddress.u.Word) && InsertIndex == -1) - { - return 0; - } - else - { - if (InsertIndex == -1) - { - *(IN6_ADDR*)pAddrBuf = IPAddress; - } - else - { - //先复制头 - - auto j = 0u; - for (; j != InsertIndex; ++j) - { - ((IN6_ADDR*)pAddrBuf)->u.Word[j] = IPAddress.u.Word[j]; - } - - //补充中间 0 - for (const auto Count = _countof(IPAddress.u.Word) - i + j; j != Count; ++j) - { - ((IN6_ADDR*)pAddrBuf)->u.Word[j] = 0; - } - - //复制小尾巴 - for (; j != _countof(IPAddress.u.Word); ++j, ++InsertIndex) - { - ((IN6_ADDR*)pAddrBuf)->u.Word[j] = IPAddress.u.Word[InsertIndex]; - } - } - return 1; - } - } - else - { - WSASetLastError(WSAEAFNOSUPPORT); - return -1; - } - } + +namespace YY::Thunks +{ +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows 8.1, Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + ws2_32, + 12, + INT, + WINAPI, + inet_pton, + _In_ INT Family, + _In_ PCSTR pszAddrString, + _When_(Family == AF_INET, _Out_writes_bytes_(sizeof(IN_ADDR))) + _When_(Family == AF_INET6, _Out_writes_bytes_(sizeof(IN6_ADDR))) + PVOID pAddrBuf + ) + { + if (auto pinet_pton = try_get_inet_pton()) + { + return pinet_pton(Family, pszAddrString, pAddrBuf); + } + + typedef char Char; + + if (nullptr == pszAddrString || nullptr == pAddrBuf) + { + WSASetLastError(WSAEFAULT); + return -1; + } + + if (AF_INET == Family) + { + //IPv4 + UCHAR IPAddress[4] = {}; + + unsigned i = 0; + for (; i != _countof(IPAddress); ) + { + auto& IPNum = IPAddress[i++]; + + auto Start = pszAddrString; + for (; *Start && *Start != Char('.'); ++Start) + { + auto& Ch = *Start; + + //必须是0~9数字 + if (Ch >= Char('0') && Ch <= Char('9')) + { + auto NewNum = IPNum * 10ul + (Ch & 0x0Ful); + if (NewNum > 0xFF) + { + //不能大于255 + return 0; + } + + IPNum = (UCHAR)NewNum; + } + else + { + return 0; + } + } + + // + if (Start == pszAddrString) + return 0; + + pszAddrString = Start; + + if (*pszAddrString == Char('\0')) + break; + else + ++pszAddrString; + } + + //未正常截断 + if (i != _countof(IPAddress) || *pszAddrString != Char('\0')) + return 0; + + + ((IN_ADDR *)pAddrBuf)->S_un.S_addr = *(ULONG*)IPAddress; + + return 1; + } + else if (AF_INET6 == Family) + { + //IPv6 + + IN6_ADDR IPAddress; + + int i = 0; + int InsertIndex = -1; + + for (; i != _countof(IPAddress.u.Word) && *pszAddrString; ) + { + if (pszAddrString[0] == Char(':') && pszAddrString[1] == Char(':')) + { + //缩进只能有一次 + if (InsertIndex != -1) + return 0; + + + InsertIndex = i; + + pszAddrString += 2; + continue; + } + + auto& IPNum = IPAddress.u.Word[i++]; + IPNum = 0; + + auto Start = pszAddrString; + for (; *Start && *Start != Char(':'); ++Start) + { + auto& Ch = *Start; + + + unsigned int NewNum; + + //0~9数字 + if (Ch >= Char('0') && Ch <= Char('9')) + { + NewNum = Ch & 0x0Ful; + } + else if (Ch >= Char('a') && Ch <= Char('f')) + { + NewNum = Ch - Char('a') + 10; + } + else if (Ch >= Char('A') && Ch <= Char('F')) + { + NewNum = Ch - Char('A') + 10; + } + else + { + //无法识别 + return 0; + } + + NewNum = ((unsigned int)IPNum << 4) | NewNum; + + if (NewNum > 0xFFFF) + { + //不能大于255 + return 0; + } + + IPNum = NewNum; + } + + + //截断错误 + if (Start == pszAddrString) + { + return 0; + } + + + IPNum = _byteswap_ushort(IPNum); + + pszAddrString = Start; + + if (*pszAddrString == Char('\0')) + { + break; + } + else if (pszAddrString[1] == Char(':')) + { + } + else + { + ++pszAddrString; + } + } + + + //未正常截断 + if (*pszAddrString != Char('\0')) + { + return 0; + } + else if (i != _countof(IPAddress.u.Word) && InsertIndex == -1) + { + return 0; + } + else + { + if (InsertIndex == -1) + { + *(IN6_ADDR*)pAddrBuf = IPAddress; + } + else + { + //先复制头 + + auto j = 0u; + for (; j != InsertIndex; ++j) + { + ((IN6_ADDR*)pAddrBuf)->u.Word[j] = IPAddress.u.Word[j]; + } + + //补充中间 0 + for (const auto Count = _countof(IPAddress.u.Word) - i + j; j != Count; ++j) + { + ((IN6_ADDR*)pAddrBuf)->u.Word[j] = 0; + } + + //复制小尾巴 + for (; j != _countof(IPAddress.u.Word); ++j, ++InsertIndex) + { + ((IN6_ADDR*)pAddrBuf)->u.Word[j] = IPAddress.u.Word[InsertIndex]; + } + } + return 1; + } + } + else + { + WSASetLastError(WSAEAFNOSUPPORT); + return -1; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows 8.1, Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - ws2_32, - 12, - INT, - WINAPI, - InetPtonW, - _In_ INT Family, - _In_ PCWSTR pszAddrString, - _When_(Family == AF_INET, _Out_writes_bytes_(sizeof(IN_ADDR))) - _When_(Family == AF_INET6, _Out_writes_bytes_(sizeof(IN6_ADDR))) - PVOID pAddrBuf - ) - { - if (auto pInetPtonW = try_get_InetPtonW()) - { - return pInetPtonW(Family, pszAddrString, pAddrBuf); - } - - typedef wchar_t Char; - - if (nullptr == pszAddrString || nullptr == pAddrBuf) - { - WSASetLastError(WSAEFAULT); - return -1; - } - - if (AF_INET == Family) - { - //IPv4 - UCHAR IPAddress[4] = {}; - - unsigned i = 0; - for (; i != _countof(IPAddress); ) - { - auto& IPNum = IPAddress[i++]; - - auto Start = pszAddrString; - for (; *Start && *Start != Char('.'); ++Start) - { - auto& Ch = *Start; - - //必须是0~9数字 - if (Ch >= Char('0') && Ch <= Char('9')) - { - auto NewNum = IPNum * 10ul + (Ch & 0x0Ful); - if (NewNum > 0xFF) - { - //不能大于255 - return 0; - } - - IPNum = (UCHAR)NewNum; - } - else - { - return 0; - } - } - - // - if (Start == pszAddrString) - return 0; - - pszAddrString = Start; - - if (*pszAddrString == Char('\0')) - break; - else - ++pszAddrString; - } - - //未正常截断 - if (i != _countof(IPAddress) || *pszAddrString != Char('\0')) - return 0; - - - ((IN_ADDR *)pAddrBuf)->S_un.S_addr = *(ULONG*)IPAddress; - - return 1; - } - else if (AF_INET6 == Family) - { - //IPv6 - - IN6_ADDR IPAddress; - - int i = 0; - int InsertIndex = -1; - - for (; i != _countof(IPAddress.u.Word) && *pszAddrString; ) - { - if (pszAddrString[0] == Char(':') && pszAddrString[1] == Char(':')) - { - //缩进只能有一次 - if (InsertIndex != -1) - return 0; - - - InsertIndex = i; - - pszAddrString += 2; - continue; - } - - auto& IPNum = IPAddress.u.Word[i++]; - IPNum = 0; - - auto Start = pszAddrString; - for (; *Start && *Start != Char(':'); ++Start) - { - auto& Ch = *Start; - - - unsigned int NewNum; - - //0~9数字 - if (Ch >= Char('0') && Ch <= Char('9')) - { - NewNum = Ch & 0x0Ful; - } - else if (Ch >= Char('a') && Ch <= Char('f')) - { - NewNum = Ch - Char('a') + 10; - } - else if (Ch >= Char('A') && Ch <= Char('F')) - { - NewNum = Ch - Char('A') + 10; - } - else - { - //无法识别 - return 0; - } - - NewNum = ((unsigned int)IPNum << 4) | NewNum; - - if (NewNum > 0xFFFF) - { - //不能大于255 - return 0; - } - - IPNum = NewNum; - } - - - //截断错误 - if (Start == pszAddrString) - { - return 0; - } - - - IPNum = _byteswap_ushort(IPNum); - - pszAddrString = Start; - - if (*pszAddrString == Char('\0')) - { - break; - } - else if (pszAddrString[1] == Char(':')) - { - } - else - { - ++pszAddrString; - } - } - - - //未正常截断 - if (*pszAddrString != Char('\0')) - { - return 0; - } - else if (i != _countof(IPAddress.u.Word) && InsertIndex == -1) - { - return 0; - } - else - { - if (InsertIndex == -1) - { - *(IN6_ADDR*)pAddrBuf = IPAddress; - } - else - { - //先复制头 - - auto j = 0u; - for (; j != InsertIndex; ++j) - { - ((IN6_ADDR*)pAddrBuf)->u.Word[j] = IPAddress.u.Word[j]; - } - - //补充中间 0 - for (const auto Count = _countof(IPAddress.u.Word) - i + j; j != Count; ++j) - { - ((IN6_ADDR*)pAddrBuf)->u.Word[j] = 0; - } - - //复制小尾巴 - for (; j != _countof(IPAddress.u.Word); ++j, ++InsertIndex) - { - ((IN6_ADDR*)pAddrBuf)->u.Word[j] = IPAddress.u.Word[InsertIndex]; - } - } - return 1; - } - } - else - { - WSASetLastError(WSAEAFNOSUPPORT); - return -1; - } - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows 8.1, Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + ws2_32, + 12, + INT, + WINAPI, + InetPtonW, + _In_ INT Family, + _In_ PCWSTR pszAddrString, + _When_(Family == AF_INET, _Out_writes_bytes_(sizeof(IN_ADDR))) + _When_(Family == AF_INET6, _Out_writes_bytes_(sizeof(IN6_ADDR))) + PVOID pAddrBuf + ) + { + if (auto pInetPtonW = try_get_InetPtonW()) + { + return pInetPtonW(Family, pszAddrString, pAddrBuf); + } + + typedef wchar_t Char; + + if (nullptr == pszAddrString || nullptr == pAddrBuf) + { + WSASetLastError(WSAEFAULT); + return -1; + } + + if (AF_INET == Family) + { + //IPv4 + UCHAR IPAddress[4] = {}; + + unsigned i = 0; + for (; i != _countof(IPAddress); ) + { + auto& IPNum = IPAddress[i++]; + + auto Start = pszAddrString; + for (; *Start && *Start != Char('.'); ++Start) + { + auto& Ch = *Start; + + //必须是0~9数字 + if (Ch >= Char('0') && Ch <= Char('9')) + { + auto NewNum = IPNum * 10ul + (Ch & 0x0Ful); + if (NewNum > 0xFF) + { + //不能大于255 + return 0; + } + + IPNum = (UCHAR)NewNum; + } + else + { + return 0; + } + } + + // + if (Start == pszAddrString) + return 0; + + pszAddrString = Start; + + if (*pszAddrString == Char('\0')) + break; + else + ++pszAddrString; + } + + //未正常截断 + if (i != _countof(IPAddress) || *pszAddrString != Char('\0')) + return 0; + + + ((IN_ADDR *)pAddrBuf)->S_un.S_addr = *(ULONG*)IPAddress; + + return 1; + } + else if (AF_INET6 == Family) + { + //IPv6 + + IN6_ADDR IPAddress; + + int i = 0; + int InsertIndex = -1; + + for (; i != _countof(IPAddress.u.Word) && *pszAddrString; ) + { + if (pszAddrString[0] == Char(':') && pszAddrString[1] == Char(':')) + { + //缩进只能有一次 + if (InsertIndex != -1) + return 0; + + + InsertIndex = i; + + pszAddrString += 2; + continue; + } + + auto& IPNum = IPAddress.u.Word[i++]; + IPNum = 0; + + auto Start = pszAddrString; + for (; *Start && *Start != Char(':'); ++Start) + { + auto& Ch = *Start; + + + unsigned int NewNum; + + //0~9数字 + if (Ch >= Char('0') && Ch <= Char('9')) + { + NewNum = Ch & 0x0Ful; + } + else if (Ch >= Char('a') && Ch <= Char('f')) + { + NewNum = Ch - Char('a') + 10; + } + else if (Ch >= Char('A') && Ch <= Char('F')) + { + NewNum = Ch - Char('A') + 10; + } + else + { + //无法识别 + return 0; + } + + NewNum = ((unsigned int)IPNum << 4) | NewNum; + + if (NewNum > 0xFFFF) + { + //不能大于255 + return 0; + } + + IPNum = NewNum; + } + + + //截断错误 + if (Start == pszAddrString) + { + return 0; + } + + + IPNum = _byteswap_ushort(IPNum); + + pszAddrString = Start; + + if (*pszAddrString == Char('\0')) + { + break; + } + else if (pszAddrString[1] == Char(':')) + { + } + else + { + ++pszAddrString; + } + } + + + //未正常截断 + if (*pszAddrString != Char('\0')) + { + return 0; + } + else if (i != _countof(IPAddress.u.Word) && InsertIndex == -1) + { + return 0; + } + else + { + if (InsertIndex == -1) + { + *(IN6_ADDR*)pAddrBuf = IPAddress; + } + else + { + //先复制头 + + auto j = 0u; + for (; j != InsertIndex; ++j) + { + ((IN6_ADDR*)pAddrBuf)->u.Word[j] = IPAddress.u.Word[j]; + } + + //补充中间 0 + for (const auto Count = _countof(IPAddress.u.Word) - i + j; j != Count; ++j) + { + ((IN6_ADDR*)pAddrBuf)->u.Word[j] = 0; + } + + //复制小尾巴 + for (; j != _countof(IPAddress.u.Word); ++j, ++InsertIndex) + { + ((IN6_ADDR*)pAddrBuf)->u.Word[j] = IPAddress.u.Word[InsertIndex]; + } + } + return 1; + } + } + else + { + WSASetLastError(WSAEAFNOSUPPORT); + return -1; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows 8.1, Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - ws2_32, - 16, - PCSTR, - WINAPI, - inet_ntop, - _In_ INT Family, - _In_ const VOID * pAddr, - _Out_writes_(StringBufSize) PSTR pStringBuf, - _In_ size_t StringBufSize - ) - { - if (auto pinet_ntop = try_get_inet_ntop()) - { - return pinet_ntop(Family, pAddr, pStringBuf, StringBufSize); - } - - NTSTATUS WSAError = ERROR_SUCCESS; - - if (pAddr == nullptr || pStringBuf == nullptr) - { - WSAError = ERROR_INVALID_PARAMETER; - } - else - { - char BufferTemp[64]; - auto szString = pStringBuf; - size_t cchString = 0; - - constexpr const char Hex[] = "0123456789abcdef"; - - - if (AF_INET == Family) - { - //IPv4 - if (StringBufSize < 16) - { - szString = BufferTemp; - } - - auto& IPv4 = *((unsigned char(*)[4])pAddr); - - for (int i = 0; i != _countof(IPv4); ++i) - { - auto Num = IPv4[i]; - if (Num < 10) - { - //1 位 - szString[cchString++] = Hex[Num]; - } - else if (Num < 100) - { - //2 位 - szString[cchString++] = Hex[Num / 10]; - szString[cchString++] = Hex[Num % 10]; - } - else - { - //3 位 - szString[cchString++] = Hex[Num / 100]; - szString[cchString++] = Hex[(Num / 10) % 10]; - szString[cchString++] = Hex[Num % 10]; - } - - szString[cchString++] = '.'; - } - - --cchString; - } - else if (AF_INET6 == Family) - { - //IPv6 - if (StringBufSize < 46) - { - szString = BufferTemp; - } - - auto& IPv6 = ((const IN6_ADDR*)pAddr)->u.Word; - - int ZeroIndex = -1; - int ZeroCount = 1; - - //统计 连续 0个数最多的情况 - for (int i = 0; i != _countof(IPv6);) - { - auto j = i; - - for (; j != _countof(IPv6) && IPv6[j] == 0; ++j); - - auto Count = j - i; - - if (Count) - { - if (Count > ZeroCount) - { - ZeroCount = Count; - ZeroIndex = i; - } - - i = j; - } - else - { - ++i; - } - } - - - for (int i = 0; i != _countof(IPv6);) - { - if (ZeroIndex == i) - { - if (i == 0) - { - szString[cchString++] = ':'; - } - - szString[cchString++] = ':'; - i += ZeroCount; - } - else - { - auto Num = _byteswap_ushort(IPv6[i++]); - - if (Num <= 0xF) - { - //1 位 - szString[cchString++] = Hex[Num]; - } - else if (Num <= 0xFF) - { - //2 位 - szString[cchString++] = Hex[Num >> 4]; - szString[cchString++] = Hex[Num & 0x0F]; - } - else if (Num <= 0xFFF) - { - //3 位 - szString[cchString++] = Hex[(Num >> 8)]; - - szString[cchString++] = Hex[(Num >> 4) & 0x0F]; - szString[cchString++] = Hex[(Num >> 0) & 0x0F]; - } - else - { - //4位 - szString[cchString++] = Hex[(Num >> 12)]; - szString[cchString++] = Hex[(Num >> 8) & 0x0F]; - - szString[cchString++] = Hex[(Num >> 4) & 0x0F]; - szString[cchString++] = Hex[(Num >> 0) & 0x0F]; - } - - if (i != _countof(IPv6)) - szString[cchString++] = ':'; - } - } - } - else - { - WSAError = WSAEAFNOSUPPORT; - } - - if (WSAError == ERROR_SUCCESS) - { - if (cchString >= StringBufSize) - { - WSAError = ERROR_INVALID_PARAMETER; - } - else - { - if (szString != BufferTemp) - { - //缓冲区不足 - - memcpy(pStringBuf, szString, sizeof(szString[0]) * cchString); - } - - pStringBuf[cchString] = '\0'; - - return pStringBuf; - } - } - } - - - WSASetLastError(WSAError); - return nullptr; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows 8.1, Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + ws2_32, + 16, + PCSTR, + WINAPI, + inet_ntop, + _In_ INT Family, + _In_ const VOID * pAddr, + _Out_writes_(StringBufSize) PSTR pStringBuf, + _In_ size_t StringBufSize + ) + { + if (auto pinet_ntop = try_get_inet_ntop()) + { + return pinet_ntop(Family, pAddr, pStringBuf, StringBufSize); + } + + NTSTATUS WSAError = ERROR_SUCCESS; + + if (pAddr == nullptr || pStringBuf == nullptr) + { + WSAError = ERROR_INVALID_PARAMETER; + } + else + { + char BufferTemp[64]; + auto szString = pStringBuf; + size_t cchString = 0; + + constexpr const char Hex[] = "0123456789abcdef"; + + + if (AF_INET == Family) + { + //IPv4 + if (StringBufSize < 16) + { + szString = BufferTemp; + } + + auto& IPv4 = *((unsigned char(*)[4])pAddr); + + for (int i = 0; i != _countof(IPv4); ++i) + { + auto Num = IPv4[i]; + if (Num < 10) + { + //1 位 + szString[cchString++] = Hex[Num]; + } + else if (Num < 100) + { + //2 位 + szString[cchString++] = Hex[Num / 10]; + szString[cchString++] = Hex[Num % 10]; + } + else + { + //3 位 + szString[cchString++] = Hex[Num / 100]; + szString[cchString++] = Hex[(Num / 10) % 10]; + szString[cchString++] = Hex[Num % 10]; + } + + szString[cchString++] = '.'; + } + + --cchString; + } + else if (AF_INET6 == Family) + { + //IPv6 + if (StringBufSize < 46) + { + szString = BufferTemp; + } + + auto& IPv6 = ((const IN6_ADDR*)pAddr)->u.Word; + + int ZeroIndex = -1; + int ZeroCount = 1; + + //统计 连续 0个数最多的情况 + for (int i = 0; i != _countof(IPv6);) + { + auto j = i; + + for (; j != _countof(IPv6) && IPv6[j] == 0; ++j); + + auto Count = j - i; + + if (Count) + { + if (Count > ZeroCount) + { + ZeroCount = Count; + ZeroIndex = i; + } + + i = j; + } + else + { + ++i; + } + } + + + for (int i = 0; i != _countof(IPv6);) + { + if (ZeroIndex == i) + { + if (i == 0) + { + szString[cchString++] = ':'; + } + + szString[cchString++] = ':'; + i += ZeroCount; + } + else + { + auto Num = _byteswap_ushort(IPv6[i++]); + + if (Num <= 0xF) + { + //1 位 + szString[cchString++] = Hex[Num]; + } + else if (Num <= 0xFF) + { + //2 位 + szString[cchString++] = Hex[Num >> 4]; + szString[cchString++] = Hex[Num & 0x0F]; + } + else if (Num <= 0xFFF) + { + //3 位 + szString[cchString++] = Hex[(Num >> 8)]; + + szString[cchString++] = Hex[(Num >> 4) & 0x0F]; + szString[cchString++] = Hex[(Num >> 0) & 0x0F]; + } + else + { + //4位 + szString[cchString++] = Hex[(Num >> 12)]; + szString[cchString++] = Hex[(Num >> 8) & 0x0F]; + + szString[cchString++] = Hex[(Num >> 4) & 0x0F]; + szString[cchString++] = Hex[(Num >> 0) & 0x0F]; + } + + if (i != _countof(IPv6)) + szString[cchString++] = ':'; + } + } + } + else + { + WSAError = WSAEAFNOSUPPORT; + } + + if (WSAError == ERROR_SUCCESS) + { + if (cchString >= StringBufSize) + { + WSAError = ERROR_INVALID_PARAMETER; + } + else + { + if (szString != BufferTemp) + { + //缓冲区不足 + + memcpy(pStringBuf, szString, sizeof(szString[0]) * cchString); + } + + pStringBuf[cchString] = '\0'; + + return pStringBuf; + } + } + } + + + WSASetLastError(WSAError); + return nullptr; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows 8.1, Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - ws2_32, - 16, - PCWSTR, - WINAPI, - InetNtopW, - _In_ INT Family, - _In_ const VOID * pAddr, - _Out_writes_(StringBufSize) PWSTR pStringBuf, - _In_ size_t StringBufSize - ) - { - if (auto pInetNtopW = try_get_InetNtopW()) - { - return pInetNtopW(Family, pAddr, pStringBuf, StringBufSize); - } - - NTSTATUS WSAError = ERROR_SUCCESS; - - if (pAddr == nullptr || pStringBuf == nullptr) - { - WSAError = ERROR_INVALID_PARAMETER; - } - else - { - wchar_t BufferTemp[64]; - auto szString = pStringBuf; - size_t cchString = 0; - - constexpr const char Hex[] = "0123456789abcdef"; - - - if (AF_INET == Family) - { - //IPv4 - if (StringBufSize < 16) - { - szString = BufferTemp; - } - - auto& IPv4 = *((unsigned char(*)[4])pAddr); - - for (int i = 0; i != _countof(IPv4); ++i) - { - auto Num = IPv4[i]; - if (Num < 10) - { - //1 位 - szString[cchString++] = Hex[Num]; - } - else if (Num < 100) - { - //2 位 - szString[cchString++] = Hex[Num / 10]; - szString[cchString++] = Hex[Num % 10]; - } - else - { - //3 位 - szString[cchString++] = Hex[Num / 100]; - szString[cchString++] = Hex[(Num / 10) % 10]; - szString[cchString++] = Hex[Num % 10]; - } - - szString[cchString++] = '.'; - } - - --cchString; - } - else if (AF_INET6 == Family) - { - //IPv6 - if (StringBufSize < 46) - { - szString = BufferTemp; - } - - auto& IPv6 = ((const IN6_ADDR*)pAddr)->u.Word; - - int ZeroIndex = -1; - int ZeroCount = 1; - - //统计 连续 0个数最多的情况 - for (int i = 0; i != _countof(IPv6);) - { - auto j = i; - - for (; j != _countof(IPv6) && IPv6[j] == 0; ++j); - - auto Count = j - i; - - if (Count) - { - if (Count > ZeroCount) - { - ZeroCount = Count; - ZeroIndex = i; - } - - i = j; - } - else - { - ++i; - } - } - - - for (int i = 0; i != _countof(IPv6);) - { - if (ZeroIndex == i) - { - if (i == 0) - { - szString[cchString++] = ':'; - } - - szString[cchString++] = ':'; - i += ZeroCount; - } - else - { - auto Num = _byteswap_ushort(IPv6[i++]); - - if (Num <= 0xF) - { - //1 位 - szString[cchString++] = Hex[Num]; - } - else if (Num <= 0xFF) - { - //2 位 - szString[cchString++] = Hex[Num >> 4]; - szString[cchString++] = Hex[Num & 0x0F]; - } - else if (Num <= 0xFFF) - { - //3 位 - szString[cchString++] = Hex[(Num >> 8)]; - - szString[cchString++] = Hex[(Num >> 4) & 0x0F]; - szString[cchString++] = Hex[(Num >> 0) & 0x0F]; - } - else - { - //4位 - szString[cchString++] = Hex[(Num >> 12)]; - szString[cchString++] = Hex[(Num >> 8) & 0x0F]; - - szString[cchString++] = Hex[(Num >> 4) & 0x0F]; - szString[cchString++] = Hex[(Num >> 0) & 0x0F]; - } - - if (i != _countof(IPv6)) - szString[cchString++] = ':'; - } - } - } - else - { - WSAError = WSAEAFNOSUPPORT; - } - - if (WSAError == ERROR_SUCCESS) - { - if (cchString >= StringBufSize) - { - WSAError = ERROR_INVALID_PARAMETER; - } - else - { - if (szString != BufferTemp) - { - //缓冲区不足 - - memcpy(pStringBuf, szString, sizeof(szString[0]) * cchString); - } - - pStringBuf[cchString] = '\0'; - - return pStringBuf; - } - } - } - - - WSASetLastError(WSAError); - return nullptr; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows 8.1, Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + ws2_32, + 16, + PCWSTR, + WINAPI, + InetNtopW, + _In_ INT Family, + _In_ const VOID * pAddr, + _Out_writes_(StringBufSize) PWSTR pStringBuf, + _In_ size_t StringBufSize + ) + { + if (auto pInetNtopW = try_get_InetNtopW()) + { + return pInetNtopW(Family, pAddr, pStringBuf, StringBufSize); + } + + NTSTATUS WSAError = ERROR_SUCCESS; + + if (pAddr == nullptr || pStringBuf == nullptr) + { + WSAError = ERROR_INVALID_PARAMETER; + } + else + { + wchar_t BufferTemp[64]; + auto szString = pStringBuf; + size_t cchString = 0; + + constexpr const char Hex[] = "0123456789abcdef"; + + + if (AF_INET == Family) + { + //IPv4 + if (StringBufSize < 16) + { + szString = BufferTemp; + } + + auto& IPv4 = *((unsigned char(*)[4])pAddr); + + for (int i = 0; i != _countof(IPv4); ++i) + { + auto Num = IPv4[i]; + if (Num < 10) + { + //1 位 + szString[cchString++] = Hex[Num]; + } + else if (Num < 100) + { + //2 位 + szString[cchString++] = Hex[Num / 10]; + szString[cchString++] = Hex[Num % 10]; + } + else + { + //3 位 + szString[cchString++] = Hex[Num / 100]; + szString[cchString++] = Hex[(Num / 10) % 10]; + szString[cchString++] = Hex[Num % 10]; + } + + szString[cchString++] = '.'; + } + + --cchString; + } + else if (AF_INET6 == Family) + { + //IPv6 + if (StringBufSize < 46) + { + szString = BufferTemp; + } + + auto& IPv6 = ((const IN6_ADDR*)pAddr)->u.Word; + + int ZeroIndex = -1; + int ZeroCount = 1; + + //统计 连续 0个数最多的情况 + for (int i = 0; i != _countof(IPv6);) + { + auto j = i; + + for (; j != _countof(IPv6) && IPv6[j] == 0; ++j); + + auto Count = j - i; + + if (Count) + { + if (Count > ZeroCount) + { + ZeroCount = Count; + ZeroIndex = i; + } + + i = j; + } + else + { + ++i; + } + } + + + for (int i = 0; i != _countof(IPv6);) + { + if (ZeroIndex == i) + { + if (i == 0) + { + szString[cchString++] = ':'; + } + + szString[cchString++] = ':'; + i += ZeroCount; + } + else + { + auto Num = _byteswap_ushort(IPv6[i++]); + + if (Num <= 0xF) + { + //1 位 + szString[cchString++] = Hex[Num]; + } + else if (Num <= 0xFF) + { + //2 位 + szString[cchString++] = Hex[Num >> 4]; + szString[cchString++] = Hex[Num & 0x0F]; + } + else if (Num <= 0xFFF) + { + //3 位 + szString[cchString++] = Hex[(Num >> 8)]; + + szString[cchString++] = Hex[(Num >> 4) & 0x0F]; + szString[cchString++] = Hex[(Num >> 0) & 0x0F]; + } + else + { + //4位 + szString[cchString++] = Hex[(Num >> 12)]; + szString[cchString++] = Hex[(Num >> 8) & 0x0F]; + + szString[cchString++] = Hex[(Num >> 4) & 0x0F]; + szString[cchString++] = Hex[(Num >> 0) & 0x0F]; + } + + if (i != _countof(IPv6)) + szString[cchString++] = ':'; + } + } + } + else + { + WSAError = WSAEAFNOSUPPORT; + } + + if (WSAError == ERROR_SUCCESS) + { + if (cchString >= StringBufSize) + { + WSAError = ERROR_INVALID_PARAMETER; + } + else + { + if (szString != BufferTemp) + { + //缓冲区不足 + + memcpy(pStringBuf, szString, sizeof(szString[0]) * cchString); + } + + pStringBuf[cchString] = '\0'; + + return pStringBuf; + } + } + } + + + WSASetLastError(WSAError); + return nullptr; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows 8.1, Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - //参考 https://blog.csdn.net/liangzhao_jay/article/details/53261684 实现 - __DEFINE_THUNK( - ws2_32, - 12, - int, - WSAAPI, - WSAPoll, - _Inout_ LPWSAPOLLFD fdArray, - _In_ ULONG fds, - _In_ INT timeout - ) - { - if (auto const pWSAPoll = try_get_WSAPoll()) - { - return pWSAPoll(fdArray, fds, timeout); - } - - fd_set readfds; - fd_set writefds; - fd_set exceptfds; - - FD_ZERO(&readfds); - FD_ZERO(&writefds); - FD_ZERO(&exceptfds); - - for (ULONG i = 0; i < fds; i++) - { - auto& fd = fdArray[i]; - - //Read (in) socket - if (fd.events & (POLLRDNORM | POLLRDBAND | POLLPRI)) - { - FD_SET(fd.fd, &readfds); - } - - //Write (out) socket - if (fd.events & (POLLWRNORM | POLLWRBAND)) - { - FD_SET(fd.fd, &writefds); - } - - //异常 - if (fd.events & (POLLERR | POLLHUP | POLLNVAL)) - { - FD_SET(fd.fd, &exceptfds); - } - } - - - /* - timeout < 0 ,无限等待 - timeout == 0 ,马上回来 - timeout >0 ,最长等这个时间 - */ - timeval* __ptimeout = nullptr; - - timeval time_out; - - if (timeout >= 0) - { - time_out.tv_sec = timeout / 1000; - time_out.tv_usec = (timeout % 1000) * 1000; - __ptimeout = &time_out; - } - - const auto result = select(1, &readfds, &writefds, &exceptfds, __ptimeout); - - if (result > 0) - { - for (ULONG i = 0; i < fds; i++) - { - auto& fd = fdArray[i]; - - fd.revents = 0; - if (FD_ISSET(fd.fd, &readfds)) - fd.revents |= fd.events & (POLLRDNORM | POLLRDBAND | POLLPRI); - - if (FD_ISSET(fd.fd, &writefds)) - fd.revents |= fd.events & (POLLWRNORM | POLLWRBAND); - - if (FD_ISSET(fd.fd, &exceptfds)) - fd.revents |= fd.events & (POLLERR | POLLHUP | POLLNVAL); - } - } - - return result; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows 8.1, Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + //参考 https://blog.csdn.net/liangzhao_jay/article/details/53261684 实现 + __DEFINE_THUNK( + ws2_32, + 12, + int, + WSAAPI, + WSAPoll, + _Inout_ LPWSAPOLLFD fdArray, + _In_ ULONG fds, + _In_ INT timeout + ) + { + if (auto const pWSAPoll = try_get_WSAPoll()) + { + return pWSAPoll(fdArray, fds, timeout); + } + + fd_set readfds; + fd_set writefds; + fd_set exceptfds; + + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&exceptfds); + + for (ULONG i = 0; i < fds; i++) + { + auto& fd = fdArray[i]; + + //Read (in) socket + if (fd.events & (POLLRDNORM | POLLRDBAND | POLLPRI)) + { + FD_SET(fd.fd, &readfds); + } + + //Write (out) socket + if (fd.events & (POLLWRNORM | POLLWRBAND)) + { + FD_SET(fd.fd, &writefds); + } + + //异常 + if (fd.events & (POLLERR | POLLHUP | POLLNVAL)) + { + FD_SET(fd.fd, &exceptfds); + } + } + + + /* + timeout < 0 ,无限等待 + timeout == 0 ,马上回来 + timeout >0 ,最长等这个时间 + */ + timeval* __ptimeout = nullptr; + + timeval time_out; + + if (timeout >= 0) + { + time_out.tv_sec = timeout / 1000; + time_out.tv_usec = (timeout % 1000) * 1000; + __ptimeout = &time_out; + } + + const auto result = select(1, &readfds, &writefds, &exceptfds, __ptimeout); + + if (result > 0) + { + for (ULONG i = 0; i < fds; i++) + { + auto& fd = fdArray[i]; + + fd.revents = 0; + if (FD_ISSET(fd.fd, &readfds)) + fd.revents |= fd.events & (POLLRDNORM | POLLRDBAND | POLLPRI); + + if (FD_ISSET(fd.fd, &writefds)) + fd.revents |= fd.events & (POLLWRNORM | POLLWRBAND); + + if (FD_ISSET(fd.fd, &exceptfds)) + fd.revents |= fd.events & (POLLERR | POLLHUP | POLLNVAL); + } + } + + return result; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - // 最低受支持的客户端 Windows 8.1、Windows 8 [桌面应用 |UWP 应用] + // 最低受支持的客户端 Windows 8.1、Windows 8 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] - __DEFINE_THUNK( - ws2_32, - 4, - INT, + __DEFINE_THUNK( + ws2_32, + 4, + INT, WSAAPI, GetAddrInfoExCancel, _In_ LPHANDLE _phHandle ) - { - if (auto const _pfnGetAddrInfoExCancel = try_get_GetAddrInfoExCancel()) - { - return _pfnGetAddrInfoExCancel(_phHandle); - } + { + if (auto const _pfnGetAddrInfoExCancel = try_get_GetAddrInfoExCancel()) + { + return _pfnGetAddrInfoExCancel(_phHandle); + } if (!_phHandle) return WSA_INVALID_HANDLE; @@ -1500,20 +1504,20 @@ namespace YY::Thunks _pParameter->Release(); return ERROR_SUCCESS; } - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] // Vista虽然有这个函数,但是不支持异步,所以也要修正。 - __DEFINE_THUNK( - ws2_32, - 40, - INT, + __DEFINE_THUNK( + ws2_32, + 40, + INT, WSAAPI, GetAddrInfoExW, _In_opt_ PCWSTR _szName, @@ -1527,20 +1531,20 @@ namespace YY::Thunks _In_opt_ LPLOOKUPSERVICE_COMPLETION_ROUTINE _pfnCompletionRoutine, _Out_opt_ LPHANDLE _pHandle ) - { + { auto _pfnGetAddrInfoExW = try_get_GetAddrInfoExW(); -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 正常情况下,Vista必定存在这个函数 if (!_pfnGetAddrInfoExW) _pfnGetAddrInfoExW = &GetAddrInfoExWDownlevel; -#endif // ! (YY_Thunks_Support_Version < NTDDI_WIN6) +#endif // ! (YY_Thunks_Target < __WindowsNT6) const bool _bAsync = _pTimeout || _pOverlapped || _pfnCompletionRoutine || _pHandle; - if (_pfnGetAddrInfoExW && (_bAsync == false || try_get_GetAddrInfoExCancel())) - { + if (_pfnGetAddrInfoExW && (_bAsync == false || try_get_GetAddrInfoExCancel())) + { // 如果GetAddrInfoExCancel函数存在说明是Windows 8以上操作系统,这时已经原生支持异步。 // 直接调用即可。 return _pfnGetAddrInfoExW(_szName, _szServiceName, _uNameSpace, _pNspId, _pHints, _ppResult, _pTimeout, _pOverlapped, _pfnCompletionRoutine, _pHandle); - } + } if (_pHandle) *_pHandle = nullptr; @@ -1622,7 +1626,7 @@ namespace YY::Thunks do { auto _pfnGetAddrInfoExW = try_get_GetAddrInfoExW(); -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) if (!_pfnGetAddrInfoExW) { _pfnGetAddrInfoExW = &GetAddrInfoExWDownlevel; @@ -1659,19 +1663,19 @@ namespace YY::Thunks *_pHandle = _pParameter; return WSA_IO_PENDING; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] // Vista虽然有这个函数,但是不支持异步,所以也要修正。 - __DEFINE_THUNK( - ws2_32, - 40, - INT, + __DEFINE_THUNK( + ws2_32, + 40, + INT, WSAAPI, GetAddrInfoExA, _In_opt_ PCSTR _szName, @@ -1685,21 +1689,21 @@ namespace YY::Thunks _In_opt_ LPLOOKUPSERVICE_COMPLETION_ROUTINE _pfnCompletionRoutine, _Out_opt_ LPHANDLE _pHandle ) - { + { auto _pfnGetAddrInfoExA = try_get_GetAddrInfoExA(); -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) if (!_pfnGetAddrInfoExA) _pfnGetAddrInfoExA = &GetAddrInfoExADownlevel; -#endif // ! (YY_Thunks_Support_Version < NTDDI_WIN6) +#endif // ! (YY_Thunks_Target < __WindowsNT6) const bool _bAsync = _pTimeout || _pOverlapped || _pfnCompletionRoutine || _pHandle; - if (_pfnGetAddrInfoExA && (_bAsync == false || try_get_GetAddrInfoExCancel())) - { + if (_pfnGetAddrInfoExA && (_bAsync == false || try_get_GetAddrInfoExCancel())) + { // 如果GetAddrInfoExCancel函数存在说明是Windows 8以上操作系统,这时已经原生支持异步。 // 直接调用即可。 return _pfnGetAddrInfoExA(_szName, _szServiceName, _uNameSpace, _pNspId, _pHints, _ppResult, _pTimeout, _pOverlapped, _pfnCompletionRoutine, _pHandle); - } + } if (_pHandle) *_pHandle = nullptr; @@ -1784,7 +1788,7 @@ namespace YY::Thunks do { auto _pfnGetAddrInfoExA = try_get_GetAddrInfoExA(); -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) if (!_pfnGetAddrInfoExA) { _pfnGetAddrInfoExA = &GetAddrInfoExADownlevel; @@ -1821,49 +1825,49 @@ namespace YY::Thunks *_pHandle = _pParameter; return WSA_IO_PENDING; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - // 最低受支持的客户端 Windows 8.1、Windows 8 [桌面应用 |UWP 应用] + // 最低受支持的客户端 Windows 8.1、Windows 8 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] - __DEFINE_THUNK( - ws2_32, - 4, - INT, + __DEFINE_THUNK( + ws2_32, + 4, + INT, WSAAPI, GetAddrInfoExOverlappedResult, _In_ LPOVERLAPPED _pOverlapped ) - { - if (auto const _pfnGetAddrInfoExOverlappedResult = try_get_GetAddrInfoExOverlappedResult()) - { - return _pfnGetAddrInfoExOverlappedResult(_pOverlapped); - } + { + if (auto const _pfnGetAddrInfoExOverlappedResult = try_get_GetAddrInfoExOverlappedResult()) + { + return _pfnGetAddrInfoExOverlappedResult(_pOverlapped); + } return _pOverlapped ? static_cast(_pOverlapped->Internal) : WSAEINVAL; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows 8.1,Windows Vista [桌面应用 |UWP 应用] + // 最低受支持的客户端 Windows 8.1,Windows Vista [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - ws2_32, - 4, - void, + __DEFINE_THUNK( + ws2_32, + 4, + void, WSAAPI, FreeAddrInfoExW, _In_opt_ PADDRINFOEXW _pAddrInfoEx ) - { - if (auto const _pfnFreeAddrInfoExW = try_get_FreeAddrInfoExW()) - { - return _pfnFreeAddrInfoExW(_pAddrInfoEx); - } + { + if (auto const _pfnFreeAddrInfoExW = try_get_FreeAddrInfoExW()) + { + return _pfnFreeAddrInfoExW(_pAddrInfoEx); + } // 跟微软实现存在略微差异,微软的实现每一个成员都需要申请内存。 // 而YY-Thunks为了优化性能,一块 _pAddrInfoEx的内存是一次内存申请。 @@ -1873,27 +1877,27 @@ namespace YY::Thunks internal::Free(_pAddrInfoEx); _pAddrInfoEx = _pNext; } - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows 8.1,Windows Vista [桌面应用 |UWP 应用] + // 最低受支持的客户端 Windows 8.1,Windows Vista [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - ws2_32, - 4, - void, + __DEFINE_THUNK( + ws2_32, + 4, + void, WSAAPI, FreeAddrInfoEx, _In_opt_ PADDRINFOEXA _pAddrInfoEx ) - { - if (auto const _pfnFreeAddrInfoEx = try_get_FreeAddrInfoEx()) - { - return _pfnFreeAddrInfoEx(_pAddrInfoEx); - } + { + if (auto const _pfnFreeAddrInfoEx = try_get_FreeAddrInfoEx()) + { + return _pfnFreeAddrInfoEx(_pAddrInfoEx); + } // 跟微软实现存在略微差异,微软的实现每一个成员都需要申请内存。 // 而YY-Thunks为了优化性能,一块 _pAddrInfoEx的内存是一次内存申请。 @@ -1903,18 +1907,18 @@ namespace YY::Thunks internal::Free(_pAddrInfoEx); _pAddrInfoEx = _pNext; } - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WINXPSP2) +#if (YY_Thunks_Target < __WindowsNT5_1_SP2) - // 最低受支持的客户端 Windows XP SP2 [桌面应用 |UWP 应用] + // 最低受支持的客户端 Windows XP SP2 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] - __DEFINE_THUNK( - ws2_32, - 16, - INT, + __DEFINE_THUNK( + ws2_32, + 16, + INT, WSAAPI, GetAddrInfoW, _In_opt_ PCWSTR _szNodeName, @@ -1922,11 +1926,11 @@ namespace YY::Thunks _In_opt_ const ADDRINFOW * _pHints, _Outptr_ PADDRINFOW * _ppResult ) - { - if (auto const _pfnGetAddrInfoW = try_get_GetAddrInfoW()) - { - return _pfnGetAddrInfoW(_szNodeName, _szServiceName, _pHints, _ppResult); - } + { + if (auto const _pfnGetAddrInfoW = try_get_GetAddrInfoW()) + { + return _pfnGetAddrInfoW(_szNodeName, _szServiceName, _pHints, _ppResult); + } *_ppResult = nullptr; if (_pHints && (_pHints->ai_addrlen || _pHints->ai_canonname || _pHints->ai_addr || _pHints->ai_next)) @@ -1953,27 +1957,27 @@ namespace YY::Thunks _lStatus = Convert(_pResultA, _ppResult); freeaddrinfo(_pResultA); return _lStatus; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WINXPSP2) +#if (YY_Thunks_Target < __WindowsNT5_1_SP2) // 最低受支持的客户端 Windows XP SP2 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] - __DEFINE_THUNK( - ws2_32, - 4, - void, + __DEFINE_THUNK( + ws2_32, + 4, + void, WSAAPI, FreeAddrInfoW, _In_opt_ PADDRINFOW _pAddrInfo ) - { - if (auto const _pfnFreeAddrInfoW = try_get_FreeAddrInfoW()) - { - return _pfnFreeAddrInfoW(_pAddrInfo); - } + { + if (auto const _pfnFreeAddrInfoW = try_get_FreeAddrInfoW()) + { + return _pfnFreeAddrInfoW(_pAddrInfo); + } // 跟微软实现存在略微差异,微软的实现每一个成员都需要申请内存。 // 而YY-Thunks为了优化性能,一块 _pAddrInfoEx的内存是一次内存申请。 @@ -1983,6 +1987,6 @@ namespace YY::Thunks internal::Free(_pAddrInfo); _pAddrInfo = _pNext; } - } + } #endif } //namespace YY diff --git a/src/Thunks/WinHttp.hpp b/src/Thunks/WinHttp.hpp index 51a942a..2223848 100644 --- a/src/Thunks/WinHttp.hpp +++ b/src/Thunks/WinHttp.hpp @@ -1,13 +1,13 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) && !defined(__Comment_Lib_winhttp) +#if (YY_Thunks_Target < __WindowsNT6_2) && !defined(__Comment_Lib_winhttp) #define __Comment_Lib_winhttp #pragma comment(lib, "winhttp.lib") #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) && defined(YY_Thunks_Implemented) +#if (YY_Thunks_Target < __WindowsNT6_2) && defined(YY_Thunks_Implemented) namespace YY::Thunks::Fallback { namespace @@ -363,24 +363,24 @@ namespace YY::Thunks::Fallback namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - // 最低受支持的客户端 Windows 8 [仅限桌面应用] + // 最低受支持的客户端 Windows 8 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] - __DEFINE_THUNK( - winhttp, - 8, - DWORD, + __DEFINE_THUNK( + winhttp, + 8, + DWORD, WINAPI, WinHttpCreateProxyResolver, _In_ HINTERNET _hSession, _Out_ HINTERNET* _phResolver ) - { - if (const auto _pfnWinHttpCreateProxyResolver = try_get_WinHttpCreateProxyResolver()) - { - return _pfnWinHttpCreateProxyResolver(_hSession, _phResolver); - } + { + if (const auto _pfnWinHttpCreateProxyResolver = try_get_WinHttpCreateProxyResolver()) + { + return _pfnWinHttpCreateProxyResolver(_hSession, _phResolver); + } // WinHttpConnect接口不会实际访问网络,这里调用以下主要是2个目的 // 1. 维持 _hSession 的引用计数,避免hResolver存在期间调用者就主动关闭了hSession。 @@ -399,25 +399,25 @@ namespace YY::Thunks _pResolver->hSession = _hSession; _pResolver->hConnect = _hConnect; *_phResolver = reinterpret_cast(_pResolver); - return ERROR_SUCCESS; - } + return ERROR_SUCCESS; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - // 最低受支持的客户端 Windows XP、Windows 2000 Professional SP3 [仅限桌面应用] + // 最低受支持的客户端 Windows XP、Windows 2000 Professional SP3 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2003、Windows 2000 Server SP3[仅限桌面应用] // 1. 额外修正了Windows 8新增的ProxyResolver特性。 - __DEFINE_THUNK( - winhttp, - 4, - BOOL, + __DEFINE_THUNK( + winhttp, + 4, + BOOL, WINAPI, WinHttpCloseHandle, IN HINTERNET _hInternet ) - { + { if (!Fallback::Is(_hInternet)) { if (const auto _pfnWinHttpCloseHandle = try_get_WinHttpCloseHandle()) @@ -430,22 +430,22 @@ namespace YY::Thunks return FALSE; } } - + reinterpret_cast(_hInternet)->Release(); return TRUE; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - // 最低受支持的客户端 Windows XP、Windows 2000 Professional 和 SP3 [仅限桌面应用] + // 最低受支持的客户端 Windows XP、Windows 2000 Professional 和 SP3 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2003、Windows 2000 Server SP3[仅限桌面应用] // 1. 额外修正了Windows 8新增的ProxyResolver特性。 - __DEFINE_THUNK( - winhttp, - 16, - WINHTTP_STATUS_CALLBACK, + __DEFINE_THUNK( + winhttp, + 16, + WINHTTP_STATUS_CALLBACK, WINAPI, WinHttpSetStatusCallback, IN HINTERNET _hInternet, @@ -453,7 +453,7 @@ namespace YY::Thunks IN DWORD _fNotificationFlags, IN DWORD_PTR _uReserved ) - { + { if (!Fallback::Is(_hInternet)) { if (const auto _pfnWinHttpSetStatusCallback = try_get_WinHttpSetStatusCallback()) @@ -477,18 +477,18 @@ namespace YY::Thunks auto _pResolver = reinterpret_cast(_hInternet); _pResolver->fNotificationFlags = _fNotificationFlags; return (WINHTTP_STATUS_CALLBACK)InterlockedExchange((uintptr_t*)&_pResolver->pfnGetProxyForUrlCallback, (uintptr_t)_pfnInternetCallback); - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - // 最低受支持的客户端 Windows 8 [仅限桌面应用] + // 最低受支持的客户端 Windows 8 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] - __DEFINE_THUNK( - winhttp, - 16, - DWORD, + __DEFINE_THUNK( + winhttp, + 16, + DWORD, WINAPI, WinHttpGetProxyForUrlEx, _In_ HINTERNET _hResolver, @@ -496,11 +496,11 @@ namespace YY::Thunks _In_ WINHTTP_AUTOPROXY_OPTIONS* _pAutoProxyOptions, _In_opt_ DWORD_PTR _pContext ) - { - if (const auto _pfnWinHttpGetProxyForUrlEx = try_get_WinHttpGetProxyForUrlEx()) - { - return _pfnWinHttpGetProxyForUrlEx(_hResolver, _szUrl, _pAutoProxyOptions, _pContext); - } + { + if (const auto _pfnWinHttpGetProxyForUrlEx = try_get_WinHttpGetProxyForUrlEx()) + { + return _pfnWinHttpGetProxyForUrlEx(_hResolver, _szUrl, _pAutoProxyOptions, _pContext); + } if (_szUrl == NULL) return ERROR_WINHTTP_INVALID_URL; @@ -557,25 +557,25 @@ namespace YY::Thunks return ERROR_NOT_ENOUGH_MEMORY; } - return ERROR_IO_PENDING; - } + return ERROR_IO_PENDING; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - // 最低受支持的客户端 Windows 8 [仅限桌面应用] + // 最低受支持的客户端 Windows 8 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] - __DEFINE_THUNK( - winhttp, - 8, - DWORD, + __DEFINE_THUNK( + winhttp, + 8, + DWORD, WINAPI, WinHttpGetProxyResult, _In_ HINTERNET _hResolver, _Out_ WINHTTP_PROXY_RESULT* _pProxyResult ) - { + { if (const auto _pfnWinHttpGetProxyResult = try_get_WinHttpGetProxyResult()) { return _pfnWinHttpGetProxyResult(_hResolver, _pProxyResult); @@ -653,31 +653,31 @@ namespace YY::Thunks _pResult->Release(); return _lStatus; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - // 最低受支持的客户端 Windows 8 [仅限桌面应用] + // 最低受支持的客户端 Windows 8 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] - __DEFINE_THUNK( - winhttp, - 4, - VOID, + __DEFINE_THUNK( + winhttp, + 4, + VOID, WINAPI, WinHttpFreeProxyResult, _Inout_ WINHTTP_PROXY_RESULT* _pProxyResult ) - { - if (const auto _pfnWinHttpFreeProxyResult = try_get_WinHttpFreeProxyResult()) - { - return _pfnWinHttpFreeProxyResult(_pProxyResult); - } + { + if (const auto _pfnWinHttpFreeProxyResult = try_get_WinHttpFreeProxyResult()) + { + return _pfnWinHttpFreeProxyResult(_pProxyResult); + } if(_pProxyResult) internal::Free(_pProxyResult->pEntries); - return; - } + return; + } #endif } diff --git a/src/Thunks/WinUsb.hpp b/src/Thunks/WinUsb.hpp index 11aea0f..2a0c46a 100644 --- a/src/Thunks/WinUsb.hpp +++ b/src/Thunks/WinUsb.hpp @@ -1,10 +1,10 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) #include #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 __DEFINE_THUNK( @@ -32,7 +32,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 __DEFINE_THUNK( @@ -55,7 +55,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 __DEFINE_THUNK( @@ -80,7 +80,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 __DEFINE_THUNK( @@ -106,7 +106,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 __DEFINE_THUNK( @@ -130,7 +130,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 __DEFINE_THUNK( @@ -158,7 +158,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 __DEFINE_THUNK( @@ -182,7 +182,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 __DEFINE_THUNK( @@ -206,7 +206,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 __DEFINE_THUNK( diff --git a/src/Thunks/YY_Thunks.cpp b/src/Thunks/YY_Thunks.cpp index 55b667f..e91aeee 100644 --- a/src/Thunks/YY_Thunks.cpp +++ b/src/Thunks/YY_Thunks.cpp @@ -43,9 +43,9 @@ YY-Thunks支持的控制宏: _APPLY(psapi, "psapi" , 0 ) \ _APPLY(pdh, "pdh" , 0 ) \ _APPLY(version, "version" , 0 ) \ - _APPLY(advapi32, "advapi32" , 0 ) \ - _APPLY(bcrypt, "bcrypt" , 0 ) \ - _APPLY(bcryptprimitives, "bcryptprimitives" , 0 ) \ + _APPLY(advapi32, "advapi32" , 0 ) \ + _APPLY(bcrypt, "bcrypt" , 0 ) \ + _APPLY(bcryptprimitives, "bcryptprimitives" , 0 ) \ _APPLY(user32, "user32" , 0 ) \ _APPLY(ws2_32, "ws2_32" , 0 ) \ _APPLY(shell32, "shell32" , 0 ) \ @@ -118,10 +118,7 @@ YY-Thunks支持的控制宏: #include - -#ifndef YY_Thunks_Support_Version -#define YY_Thunks_Support_Version WDK_NTDDI_VERSION -#endif +#include #ifndef _WINSOCK_DEPRECATED_NO_WARNINGS #define _WINSOCK_DEPRECATED_NO_WARNINGS @@ -130,7 +127,7 @@ YY-Thunks支持的控制宏: #define _WINSOCKAPI_ #define PSAPI_VERSION 1 -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) #define INITKNOWNFOLDERS #endif @@ -155,7 +152,7 @@ YY-Thunks支持的控制宏: #define __YY_Thunks_libs 1 #endif -#if !defined(__USING_NTDLL_LIB) && (__YY_Thunks_libs || YY_Thunks_Support_Version >= NTDDI_WIN10) +#if !defined(__USING_NTDLL_LIB) && (__YY_Thunks_libs || YY_Thunks_Target >= __WindowsNT10_10240) // lib模式下必然存在 ntdll.lib,此外最小支持Windows 10时,我们因为强制依赖Windows 10 SDK,所以也必然存在ntdll.lib。 #define __USING_NTDLL_LIB 1 #endif @@ -190,53 +187,53 @@ RtlCutoverTimeToSystemTime( #include "YY_Thunks.h" -#if (YY_Thunks_Support_Version < NTDDI_WS03SP1) && !defined(__Comment_Lib_advapi32) +#if (YY_Thunks_Target < __WindowsNT5_2_SP1) && !defined(__Comment_Lib_advapi32) #define __Comment_Lib_advapi32 #pragma comment(lib, "Advapi32.lib") #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_shlwapi) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_shlwapi) #define __Comment_Lib_shlwapi #pragma comment(lib, "Shlwapi.lib") #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_ws2_32) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_ws2_32) #define __Comment_Lib_ws2_32 #pragma comment(lib, "Ws2_32.lib") #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_version) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_version) #define __Comment_Lib_version #pragma comment(lib, "version.lib") #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_ole32) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_ole32) #define __Comment_Lib_ole32 #pragma comment(lib, "ole32.lib") #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_shell32) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_shell32) #define __Comment_Lib_shell32 #pragma comment(lib, "shell32.lib") #endif // PSAPI2Kernel32.def -#if (YY_Thunks_Support_Version < NTDDI_WIN7) && !defined(__Comment_Lib_psapi) +#if (YY_Thunks_Target < __WindowsNT6_1) && !defined(__Comment_Lib_psapi) #define __Comment_Lib_psapi #pragma comment(lib, "psapi.lib") #endif -#if (YY_Thunks_Support_Version >= NTDDI_WINBLUE) && !defined(__Comment_Lib_shcore) +#if (YY_Thunks_Target >= __WindowsNT6_3) && !defined(__Comment_Lib_shcore) #define __Comment_Lib_shcore #pragma comment(lib, "Shcore.lib") #endif -#if (YY_Thunks_Support_Version < NTDDI_WINBLUE) && !defined(__Comment_Lib_gdi32) +#if (YY_Thunks_Target < __WindowsNT6_3) && !defined(__Comment_Lib_gdi32) #define __Comment_Lib_gdi32 #pragma comment(lib, "Gdi32.lib") #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10) && !defined(__Comment_Lib_user32) +#if (YY_Thunks_Target < __WindowsNT10_10240) && !defined(__Comment_Lib_user32) #define __Comment_Lib_user32 #pragma comment(lib, "User32.lib") #endif @@ -251,8 +248,8 @@ RtlCutoverTimeToSystemTime( #define __DEFINE_THUNK_EXTERN_PREFIX(_PREFIX, _MODULE, _SIZE, _RETURN_, _CONVENTION_, _FUNCTION, ...) \ __APPLY_UNIT_TEST_BOOL(_FUNCTION); \ EXTERN_C _RETURN_ _CONVENTION_ _CRT_CONCATENATE_(_PREFIX, _FUNCTION)(__VA_ARGS__); \ - static decltype(_CRT_CONCATENATE_(_PREFIX, _FUNCTION))* __cdecl _CRT_CONCATENATE(try_get_, _FUNCTION)() noexcept; \ - __if_not_exists(_CRT_CONCATENATE(try_get_, _FUNCTION)) + static decltype(_CRT_CONCATENATE_(_PREFIX, _FUNCTION))* __cdecl _CRT_CONCATENATE(try_get_, _FUNCTION)() noexcept; \ + __if_not_exists(_CRT_CONCATENATE(try_get_, _FUNCTION)) #define __DEFINE_THUNK(_MODULE, _SIZE, _RETURN_, _CONVENTION_, _FUNCTION, ...) __DEFINE_THUNK_EXTERN_PREFIX(__FALLBACK_PREFIX, _MODULE, _SIZE, _RETURN_, _CONVENTION_, _FUNCTION, __VA_ARGS__) @@ -262,8 +259,8 @@ RtlCutoverTimeToSystemTime( namespace YY::Thunks::internal { - namespace - { + namespace + { inline UINT8 __fastcall BitsCount(ULONG32 _fBitMask) { #if defined(_M_IX86) || defined(_M_AMD64) @@ -295,10 +292,10 @@ namespace YY::Thunks::internal #endif } - __forceinline constexpr DWORD __fastcall MakeVersion(_In_ DWORD _uMajorVersion, _In_ DWORD _uMinorVersion) - { - return (_uMajorVersion << 16) | _uMinorVersion; - } + __forceinline constexpr DWORD __fastcall MakeVersion(_In_ DWORD _uMajorVersion, _In_ DWORD _uMinorVersion) + { + return (_uMajorVersion << 16) | _uMinorVersion; + } __forceinline DWORD __fastcall GetSystemVersion() { @@ -386,198 +383,198 @@ namespace YY::Thunks::internal } } - //代码块,分割任务 - template - auto __forceinline Block(Callback&& _Callback, Params&&... args) -> decltype(_Callback(args...)) - { - return _Callback(args...); - } - - static DWORD __fastcall NtStatusToDosError( - _In_ NTSTATUS Status - ) - { - if (STATUS_TIMEOUT == Status) - { - /* - https://github.com/Chuyu-Team/YY-Thunks/issues/10 - - 用户报告,Windows XP 无法转换 STATUS_TIMEOUT。实际结果也是rubin,因此,特殊处理一下。 - */ - return ERROR_TIMEOUT; - } - else if (auto pRtlNtStatusToDosError = try_get_RtlNtStatusToDosError()) - { - return pRtlNtStatusToDosError(Status); - } - else - { - //如果没有RtlNtStatusToDosError就直接设置Status代码吧,反正至少比没有错误代码强 - return Status; - } - - } - - static DWORD __fastcall BaseSetLastNTError( - _In_ NTSTATUS Status - ) - { - auto lStatus = NtStatusToDosError(Status); - SetLastError(lStatus); - return lStatus; - } - - static __analysis_noreturn void __fastcall RaiseStatus(NTSTATUS Status) - { - RaiseException(Status, EXCEPTION_NONCONTINUABLE, 0, NULL); - } - - static LARGE_INTEGER* __fastcall BaseFormatTimeOut(LARGE_INTEGER* Timeout, DWORD dwMilliseconds) - { - if (dwMilliseconds == INFINITE) - return nullptr; - - Timeout->QuadPart = -10000ll * dwMilliseconds; - - return Timeout; - } - - static LSTATUS __fastcall Basep8BitStringToStaticUnicodeString(UNICODE_STRING* pDst, LPCSTR Src) - { - const UINT CodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; - - auto cchDst = MultiByteToWideChar(CodePage, MB_ERR_INVALID_CHARS, Src, -1, pDst->Buffer, pDst->MaximumLength / sizeof(wchar_t)); - if (cchDst <= 0) - { - return GetLastError(); - } + //代码块,分割任务 + template + auto __forceinline Block(Callback&& _Callback, Params&&... args) -> decltype(_Callback(args...)) + { + return _Callback(args...); + } + + static DWORD __fastcall NtStatusToDosError( + _In_ NTSTATUS Status + ) + { + if (STATUS_TIMEOUT == Status) + { + /* + https://github.com/Chuyu-Team/YY-Thunks/issues/10 + + 用户报告,Windows XP 无法转换 STATUS_TIMEOUT。实际结果也是rubin,因此,特殊处理一下。 + */ + return ERROR_TIMEOUT; + } + else if (auto pRtlNtStatusToDosError = try_get_RtlNtStatusToDosError()) + { + return pRtlNtStatusToDosError(Status); + } + else + { + //如果没有RtlNtStatusToDosError就直接设置Status代码吧,反正至少比没有错误代码强 + return Status; + } + + } + + static DWORD __fastcall BaseSetLastNTError( + _In_ NTSTATUS Status + ) + { + auto lStatus = NtStatusToDosError(Status); + SetLastError(lStatus); + return lStatus; + } + + static __analysis_noreturn void __fastcall RaiseStatus(NTSTATUS Status) + { + RaiseException(Status, EXCEPTION_NONCONTINUABLE, 0, NULL); + } + + static LARGE_INTEGER* __fastcall BaseFormatTimeOut(LARGE_INTEGER* Timeout, DWORD dwMilliseconds) + { + if (dwMilliseconds == INFINITE) + return nullptr; + + Timeout->QuadPart = -10000ll * dwMilliseconds; + + return Timeout; + } + + static LSTATUS __fastcall Basep8BitStringToStaticUnicodeString(UNICODE_STRING* pDst, LPCSTR Src) + { + const UINT CodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + + auto cchDst = MultiByteToWideChar(CodePage, MB_ERR_INVALID_CHARS, Src, -1, pDst->Buffer, pDst->MaximumLength / sizeof(wchar_t)); + if (cchDst <= 0) + { + return GetLastError(); + } cchDst *= sizeof(wchar_t); if (cchDst > MAXUINT16) { return ERROR_BAD_PATHNAME; } - pDst->Length = static_cast(cchDst); - return ERROR_SUCCESS; - } + pDst->Length = static_cast(cchDst); + return ERROR_SUCCESS; + } - static BOOL __fastcall BasepGetVolumeGUIDFromNTName(const UNICODE_STRING* NtName, wchar_t szVolumeGUID[MAX_PATH]) - { + static BOOL __fastcall BasepGetVolumeGUIDFromNTName(const UNICODE_STRING* NtName, wchar_t szVolumeGUID[MAX_PATH]) + { #define __szVolumeMountPointPrefix__ L"\\\\?\\GLOBALROOT" - //一个设备名称 512 长度够多了吧? - wchar_t szVolumeMountPoint[512]; - - //检查缓冲区是否充足 - auto cbBufferNeed = sizeof(__szVolumeMountPointPrefix__) + NtName->Length; + //一个设备名称 512 长度够多了吧? + wchar_t szVolumeMountPoint[512]; + + //检查缓冲区是否充足 + auto cbBufferNeed = sizeof(__szVolumeMountPointPrefix__) + NtName->Length; - if (cbBufferNeed > sizeof(szVolumeMountPoint)) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - memcpy(szVolumeMountPoint, __szVolumeMountPointPrefix__, sizeof(__szVolumeMountPointPrefix__) - sizeof(__szVolumeMountPointPrefix__[0])); - memcpy((char*)szVolumeMountPoint + sizeof(__szVolumeMountPointPrefix__) - sizeof(__szVolumeMountPointPrefix__[0]), NtName->Buffer, NtName->Length); + if (cbBufferNeed > sizeof(szVolumeMountPoint)) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + memcpy(szVolumeMountPoint, __szVolumeMountPointPrefix__, sizeof(__szVolumeMountPointPrefix__) - sizeof(__szVolumeMountPointPrefix__[0])); + memcpy((char*)szVolumeMountPoint + sizeof(__szVolumeMountPointPrefix__) - sizeof(__szVolumeMountPointPrefix__[0]), NtName->Buffer, NtName->Length); - szVolumeMountPoint[cbBufferNeed / 2 - 1] = L'\0'; + szVolumeMountPoint[cbBufferNeed / 2 - 1] = L'\0'; - return GetVolumeNameForVolumeMountPointW(szVolumeMountPoint, szVolumeGUID, MAX_PATH); + return GetVolumeNameForVolumeMountPointW(szVolumeMountPoint, szVolumeGUID, MAX_PATH); #undef __szVolumeMountPointPrefix__ - } - - static BOOL __fastcall BasepGetVolumeDosLetterNameFromNTName(const UNICODE_STRING* NtName, wchar_t szVolumeDosLetter[MAX_PATH]) - { - wchar_t szVolumeName[MAX_PATH]; - - if (!BasepGetVolumeGUIDFromNTName(NtName, szVolumeName)) - { - return FALSE; - } - - DWORD cchVolumePathName = 0; - - if (!GetVolumePathNamesForVolumeNameW(szVolumeName, szVolumeDosLetter + 4, MAX_PATH - 4, &cchVolumePathName)) - { - return FALSE; - } - - szVolumeDosLetter[0] = L'\\'; - szVolumeDosLetter[1] = L'\\'; - szVolumeDosLetter[2] = L'?'; - szVolumeDosLetter[3] = L'\\'; - - return TRUE; - } - - static unsigned __fastcall CharToHex(_In_ wchar_t _ch) - { - if (_ch >= L'0' && _ch <= L'9') - { - return _ch - L'0'; - } - else if (_ch >= L'A' && _ch <= L'F') - { - return _ch - L'A' + 0xA; - } - else if (_ch >= L'a' && _ch <= L'f') - { - return _ch - L'a' + 0xA; - } - else - { - return -1; - } - } - - static BOOL __fastcall StringToGuid(_In_z_ const wchar_t* _szInput, _Out_ GUID* _pId) - { - *_pId = GUID{}; - - if (!_szInput) - return FALSE; - - if (*_szInput == L'{') - ++_szInput; + } -#define _IS_HEX_CHAR(C) (CharToHex(C) != (unsigned)-1) + static BOOL __fastcall BasepGetVolumeDosLetterNameFromNTName(const UNICODE_STRING* NtName, wchar_t szVolumeDosLetter[MAX_PATH]) + { + wchar_t szVolumeName[MAX_PATH]; - if (!(_IS_HEX_CHAR(_szInput[0]) && _IS_HEX_CHAR(_szInput[1]) && _IS_HEX_CHAR(_szInput[2]) && _IS_HEX_CHAR(_szInput[3]) - && _IS_HEX_CHAR(_szInput[4]) && _IS_HEX_CHAR(_szInput[5]) && _IS_HEX_CHAR(_szInput[6]) && _IS_HEX_CHAR(_szInput[7]) - && _szInput[8] == L'-' - && _IS_HEX_CHAR(_szInput[9]) && _IS_HEX_CHAR(_szInput[10]) && _IS_HEX_CHAR(_szInput[11]) && _IS_HEX_CHAR(_szInput[12]) - && _szInput[13] == L'-' - && _IS_HEX_CHAR(_szInput[14]) && _IS_HEX_CHAR(_szInput[15]) && _IS_HEX_CHAR(_szInput[16]) && _IS_HEX_CHAR(_szInput[17]) - && _szInput[18] == L'-' - && _IS_HEX_CHAR(_szInput[19]) && _IS_HEX_CHAR(_szInput[20]) && _IS_HEX_CHAR(_szInput[21]) && _IS_HEX_CHAR(_szInput[22]) - && _szInput[23] == L'-' - && _IS_HEX_CHAR(_szInput[24]) && _IS_HEX_CHAR(_szInput[25]) && _IS_HEX_CHAR(_szInput[26]) && _IS_HEX_CHAR(_szInput[27]) - && _IS_HEX_CHAR(_szInput[28]) && _IS_HEX_CHAR(_szInput[29]) && _IS_HEX_CHAR(_szInput[30]) && _IS_HEX_CHAR(_szInput[31]) - && _IS_HEX_CHAR(_szInput[32]) && _IS_HEX_CHAR(_szInput[33]) && _IS_HEX_CHAR(_szInput[34]) && _IS_HEX_CHAR(_szInput[35]))) - { - return FALSE; - } -#undef _IS_HEX_CHAR + if (!BasepGetVolumeGUIDFromNTName(NtName, szVolumeName)) + { + return FALSE; + } + + DWORD cchVolumePathName = 0; + + if (!GetVolumePathNamesForVolumeNameW(szVolumeName, szVolumeDosLetter + 4, MAX_PATH - 4, &cchVolumePathName)) + { + return FALSE; + } + + szVolumeDosLetter[0] = L'\\'; + szVolumeDosLetter[1] = L'\\'; + szVolumeDosLetter[2] = L'?'; + szVolumeDosLetter[3] = L'\\'; + + return TRUE; + } + + static unsigned __fastcall CharToHex(_In_ wchar_t _ch) + { + if (_ch >= L'0' && _ch <= L'9') + { + return _ch - L'0'; + } + else if (_ch >= L'A' && _ch <= L'F') + { + return _ch - L'A' + 0xA; + } + else if (_ch >= L'a' && _ch <= L'f') + { + return _ch - L'a' + 0xA; + } + else + { + return -1; + } + } - _pId->Data1 = (CharToHex(_szInput[0]) << 28) | (CharToHex(_szInput[1]) << 24) | (CharToHex(_szInput[2]) << 20) | (CharToHex(_szInput[3]) << 16) - | (CharToHex(_szInput[4]) << 12) | (CharToHex(_szInput[5]) << 8) | (CharToHex(_szInput[6]) << 4) | (CharToHex(_szInput[7]) << 0); + static BOOL __fastcall StringToGuid(_In_z_ const wchar_t* _szInput, _Out_ GUID* _pId) + { + *_pId = GUID{}; - _pId->Data2 = (CharToHex(_szInput[9]) << 12) | (CharToHex(_szInput[10]) << 8) | (CharToHex(_szInput[11]) << 4) | (CharToHex(_szInput[12]) << 0); + if (!_szInput) + return FALSE; - _pId->Data3 = (CharToHex(_szInput[14]) << 12) | (CharToHex(_szInput[15]) << 8) | (CharToHex(_szInput[16]) << 4) | (CharToHex(_szInput[17]) << 0); - - _pId->Data4[0] = (CharToHex(_szInput[19]) << 4) | (CharToHex(_szInput[20]) << 0); - _pId->Data4[1] = (CharToHex(_szInput[21]) << 4) | (CharToHex(_szInput[22]) << 0); - _pId->Data4[2] = (CharToHex(_szInput[24]) << 4) | (CharToHex(_szInput[25]) << 0); - _pId->Data4[3] = (CharToHex(_szInput[26]) << 4) | (CharToHex(_szInput[27]) << 0); - _pId->Data4[4] = (CharToHex(_szInput[28]) << 4) | (CharToHex(_szInput[29]) << 0); - _pId->Data4[5] = (CharToHex(_szInput[30]) << 4) | (CharToHex(_szInput[31]) << 0); - _pId->Data4[6] = (CharToHex(_szInput[32]) << 4) | (CharToHex(_szInput[33]) << 0); - _pId->Data4[7] = (CharToHex(_szInput[34]) << 4) | (CharToHex(_szInput[35]) << 0); - return TRUE; - } + if (*_szInput == L'{') + ++_szInput; + +#define _IS_HEX_CHAR(C) (CharToHex(C) != (unsigned)-1) + + if (!(_IS_HEX_CHAR(_szInput[0]) && _IS_HEX_CHAR(_szInput[1]) && _IS_HEX_CHAR(_szInput[2]) && _IS_HEX_CHAR(_szInput[3]) + && _IS_HEX_CHAR(_szInput[4]) && _IS_HEX_CHAR(_szInput[5]) && _IS_HEX_CHAR(_szInput[6]) && _IS_HEX_CHAR(_szInput[7]) + && _szInput[8] == L'-' + && _IS_HEX_CHAR(_szInput[9]) && _IS_HEX_CHAR(_szInput[10]) && _IS_HEX_CHAR(_szInput[11]) && _IS_HEX_CHAR(_szInput[12]) + && _szInput[13] == L'-' + && _IS_HEX_CHAR(_szInput[14]) && _IS_HEX_CHAR(_szInput[15]) && _IS_HEX_CHAR(_szInput[16]) && _IS_HEX_CHAR(_szInput[17]) + && _szInput[18] == L'-' + && _IS_HEX_CHAR(_szInput[19]) && _IS_HEX_CHAR(_szInput[20]) && _IS_HEX_CHAR(_szInput[21]) && _IS_HEX_CHAR(_szInput[22]) + && _szInput[23] == L'-' + && _IS_HEX_CHAR(_szInput[24]) && _IS_HEX_CHAR(_szInput[25]) && _IS_HEX_CHAR(_szInput[26]) && _IS_HEX_CHAR(_szInput[27]) + && _IS_HEX_CHAR(_szInput[28]) && _IS_HEX_CHAR(_szInput[29]) && _IS_HEX_CHAR(_szInput[30]) && _IS_HEX_CHAR(_szInput[31]) + && _IS_HEX_CHAR(_szInput[32]) && _IS_HEX_CHAR(_szInput[33]) && _IS_HEX_CHAR(_szInput[34]) && _IS_HEX_CHAR(_szInput[35]))) + { + return FALSE; + } +#undef _IS_HEX_CHAR + + _pId->Data1 = (CharToHex(_szInput[0]) << 28) | (CharToHex(_szInput[1]) << 24) | (CharToHex(_szInput[2]) << 20) | (CharToHex(_szInput[3]) << 16) + | (CharToHex(_szInput[4]) << 12) | (CharToHex(_szInput[5]) << 8) | (CharToHex(_szInput[6]) << 4) | (CharToHex(_szInput[7]) << 0); + + _pId->Data2 = (CharToHex(_szInput[9]) << 12) | (CharToHex(_szInput[10]) << 8) | (CharToHex(_szInput[11]) << 4) | (CharToHex(_szInput[12]) << 0); + + _pId->Data3 = (CharToHex(_szInput[14]) << 12) | (CharToHex(_szInput[15]) << 8) | (CharToHex(_szInput[16]) << 4) | (CharToHex(_szInput[17]) << 0); + + _pId->Data4[0] = (CharToHex(_szInput[19]) << 4) | (CharToHex(_szInput[20]) << 0); + _pId->Data4[1] = (CharToHex(_szInput[21]) << 4) | (CharToHex(_szInput[22]) << 0); + _pId->Data4[2] = (CharToHex(_szInput[24]) << 4) | (CharToHex(_szInput[25]) << 0); + _pId->Data4[3] = (CharToHex(_szInput[26]) << 4) | (CharToHex(_szInput[27]) << 0); + _pId->Data4[4] = (CharToHex(_szInput[28]) << 4) | (CharToHex(_szInput[29]) << 0); + _pId->Data4[5] = (CharToHex(_szInput[30]) << 4) | (CharToHex(_szInput[31]) << 0); + _pId->Data4[6] = (CharToHex(_szInput[32]) << 4) | (CharToHex(_szInput[33]) << 0); + _pId->Data4[7] = (CharToHex(_szInput[34]) << 4) | (CharToHex(_szInput[35]) << 0); + return TRUE; + } template static bool __fastcall StringStartsWithI(_In_z_ const Char1* _szStr, _In_z_ const Char2* _szStartsWith, _Outptr_opt_result_z_ const Char1** _szEnd = nullptr) @@ -983,7 +980,7 @@ namespace YY::Thunks::internal UNICODE_STRING _Result = { (kLength - 1)* sizeof(_Right[0]), kLength * sizeof(_Right[0]), const_cast(_Right) }; return _Result; } - } + } } //namespace YY @@ -996,13 +993,13 @@ namespace YY::Thunks::internal #define YY_Thunks_Implemented #define __DEFINE_THUNK_IMP_PREFIX(_PREFIX, _MODULE, _SIZE, _RETURN_, _CONVENTION_, _FUNCTION, ...) \ static decltype(_CRT_CONCATENATE_(_PREFIX, _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(&_CRT_CONCATENATE(try_get_, _FUNCTION)); \ /*为了避免编译器将 YYThr$AAA 节优化掉*/ \ __foreinclude(_CRT_CONCATENATE(pInit_ ,_FUNCTION)); \ - __declspec(allocate(".YYThu$AAB")) static void* _CRT_CONCATENATE(pFun_, _FUNCTION); \ + __declspec(allocate(".YYThu$AAB")) static void* _CRT_CONCATENATE(pFun_, _FUNCTION); \ static const ProcInfo _ProcInfo = \ { \ _CRT_STRINGIZE(_FUNCTION), \ @@ -1012,10 +1009,10 @@ __if_exists(YY::Thunks::Fallback::_CRT_CONCATENATE(try_get_, _FUNCTION)) &YY::Thunks::Fallback::_CRT_CONCATENATE(try_get_, _FUNCTION) \ } \ }; \ - return reinterpret_cast(try_get_function( \ - &_CRT_CONCATENATE(pFun_ ,_FUNCTION), \ - _ProcInfo)); \ - } \ + return reinterpret_cast(try_get_function( \ + &_CRT_CONCATENATE(pFun_ ,_FUNCTION), \ + _ProcInfo)); \ + } \ _DEFINE_IAT_SYMBOL_PREFIX(_PREFIX, _FUNCTION, _SIZE); \ _YY_THUNKS_DEFINE_RUST_RAW_DYLIB_IAT_SYMBOL_PREFIX(_PREFIX, _FUNCTION, _SIZE); \ EXTERN_C _RETURN_ _CONVENTION_ _CRT_CONCATENATE_(_PREFIX, _FUNCTION)(__VA_ARGS__) @@ -1069,7 +1066,7 @@ static HMODULE __fastcall try_get_module(volatile HMODULE* pModule, const wchar_ else { // 使用DLL安全加载 -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) if (!try_get_AddDllDirectory()) { #if !defined(__USING_NTDLL_LIB) @@ -1122,7 +1119,7 @@ static HMODULE __fastcall try_get_module(volatile HMODULE* pModule, const wchar_ } static __forceinline void* __fastcall try_get_proc_address_from_dll( - const ProcInfo& _ProcInfo + const ProcInfo& _ProcInfo ) noexcept { HMODULE const module_handle = _ProcInfo.pfnGetModule(); diff --git a/src/Thunks/YY_Thunks.h b/src/Thunks/YY_Thunks.h index e9c193e..0f20a13 100644 --- a/src/Thunks/YY_Thunks.h +++ b/src/Thunks/YY_Thunks.h @@ -13,18 +13,18 @@ #if defined(_M_IX86) - #define _LCRT_DEFINE_IAT_SYMBOL_MAKE_NAME(_FUNCTION, _SIZE) _CRT_CONCATENATE(_CRT_CONCATENATE(_imp__, _FUNCTION), _CRT_CONCATENATE(_, _SIZE)) + #define _LCRT_DEFINE_IAT_SYMBOL_MAKE_NAME(_FUNCTION, _SIZE) _CRT_CONCATENATE(_CRT_CONCATENATE(_imp__, _FUNCTION), _CRT_CONCATENATE(_, _SIZE)) #elif defined(_M_AMD64) - #define _LCRT_DEFINE_IAT_SYMBOL_MAKE_NAME(_FUNCTION, _SIZE) _CRT_CONCATENATE(__imp_, _FUNCTION) + #define _LCRT_DEFINE_IAT_SYMBOL_MAKE_NAME(_FUNCTION, _SIZE) _CRT_CONCATENATE(__imp_, _FUNCTION) #else - #error "不支持此体系" + #error "不支持此体系" #endif #if defined(_M_IX86) //x86的符号存在@ 我们使用 identifier 特性解决 #define _LCRT_DEFINE_IAT_SYMBOL(_FUNCTION, _SIZE) \ - __pragma(warning(suppress:4483)) \ - extern "C" __declspec(selectany) void const* const __identifier(_CRT_STRINGIZE_(_imp__ ## _FUNCTION ## @ ## _SIZE)) \ + __pragma(warning(suppress:4483)) \ + extern "C" __declspec(selectany) void const* const __identifier(_CRT_STRINGIZE_(_imp__ ## _FUNCTION ## @ ## _SIZE)) \ = reinterpret_cast(_FUNCTION) #else #define _LCRT_DEFINE_IAT_SYMBOL(_FUNCTION, _SIZE) \ @@ -43,11 +43,11 @@ #endif #ifdef __YY_Thunks_Unit_Test - #define __APPLY_UNIT_TEST_BOOL(_FUNCTION) bool _CRT_CONCATENATE(aways_null_try_get_, _FUNCTION) = false - #define __CHECK_UNIT_TEST_BOOL(_FUNCTION) if(_CRT_CONCATENATE(aways_null_try_get_, _FUNCTION)) return nullptr + #define __APPLY_UNIT_TEST_BOOL(_FUNCTION) bool _CRT_CONCATENATE(aways_null_try_get_, _FUNCTION) = false + #define __CHECK_UNIT_TEST_BOOL(_FUNCTION) if(_CRT_CONCATENATE(aways_null_try_get_, _FUNCTION)) return nullptr #else - #define __APPLY_UNIT_TEST_BOOL(_FUNCTION) - #define __CHECK_UNIT_TEST_BOOL(_FUNCTION) + #define __APPLY_UNIT_TEST_BOOL(_FUNCTION) + #define __CHECK_UNIT_TEST_BOOL(_FUNCTION) #endif @@ -75,7 +75,7 @@ __declspec(allocate(".YYThr$AAC")) static void* __YY_THUNKS_UNINIT_FUN_END[] = { typedef void* (__cdecl* InitFunType)(); typedef void (__cdecl* UninitFunType)(); -#pragma detect_mismatch("YY-Thunks-Mode", "ver:" _CRT_STRINGIZE(YY_Thunks_Support_Version)) +#pragma detect_mismatch("YY-Thunks-Mode", "ver:" _CRT_STRINGIZE(YY_Thunks_Target)) /* 导出一个外部符号,指示当前鸭船Thunks等级。 @@ -83,15 +83,26 @@ typedef void (__cdecl* UninitFunType)(); 2. 当调用者同时使用多个鸭船时,使其链接失败! //自行定义为 C 弱符号,C++支持不佳! -EXTERN_C const DWORD __YY_Thunks_Installed; +EXTERN_C const UINT64 __YY_Thunks_Installed; if(__YY_Thunks_Installed) - wprintf(L"检测到使用YY-Thunks,Thunks级别=0x%.8X\n", __YY_Thunks_Installed); +{ + wprintf( + L"检测到使用YY-Thunks,Thunks级别=%hd.%hd.%hd.%hd。\n", + UINT16(__YY_Thunks_Installed >> 48), + UINT16(__YY_Thunks_Installed >> 32), + UINT16(__YY_Thunks_Installed >> 16), + UINT16(__YY_Thunks_Installed)); +} else - wprintf(L"没有使用YY-Thunks!\n"); +{ + wprintf(L"没有使用YY-Thunks!\n"); +} +// 如果选择兼容到Vista,上述代码将输出:检测到使用YY-Thunks,Thunks级别=6.0.6000.0。 +// 如果没有使用YY-Thunks,那么上述代码将输出:没有使用YY-Thunks! */ -EXTERN_C const DWORD __YY_Thunks_Installed = YY_Thunks_Support_Version; +EXTERN_C const UINT64 __YY_Thunks_Installed = YY_Thunks_Target; /* 导出一个外部弱符号,指示当前是否处于强行卸载模式。 @@ -100,22 +111,22 @@ EXTERN_C BOOL __YY_Thunks_Process_Terminating; BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { - switch(dwReason) - { - case DLL_PROCESS_DETACH: - //我们可以通过 lpReserved != NULL 判断,当前是否处于强行卸载模式。 - __YY_Thunks_Process_Terminating = lpReserved != NULL; - - …… - break; - …… + switch(dwReason) + { + case DLL_PROCESS_DETACH: + //我们可以通过 lpReserved != NULL 判断,当前是否处于强行卸载模式。 + __YY_Thunks_Process_Terminating = lpReserved != NULL; + + …… + break; + …… */ -#if (YY_Thunks_Support_Version < NTDDI_WINXP) +#if (YY_Thunks_Target < __WindowsNT5_1) //Windows 2000不支持RtlDllShutdownInProgress,因此依然引入__YY_Thunks_Process_Terminating EXTERN_C extern BOOL __YY_Thunks_Process_Terminating; #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) static HANDLE _GlobalKeyedEventHandle; #endif @@ -123,12 +134,12 @@ static uintptr_t __security_cookie_yy_thunks; #define _APPLY(_SYMBOL, _NAME, ...) \ constexpr const wchar_t* _CRT_CONCATENATE(module_name_, _SYMBOL) = _CRT_WIDE(_NAME); - _YY_APPLY_TO_LATE_BOUND_MODULES(_APPLY) + _YY_APPLY_TO_LATE_BOUND_MODULES(_APPLY) #undef _APPLY #define _APPLY(_FUNCTION, _MODULES) \ using _CRT_CONCATENATE(_FUNCTION, _pft) = decltype(_FUNCTION)*; - _YY_APPLY_TO_LATE_BOUND_FUNCTIONS(_APPLY) + _YY_APPLY_TO_LATE_BOUND_FUNCTIONS(_APPLY) #undef _APPLY @@ -138,23 +149,23 @@ static uintptr_t __security_cookie_yy_thunks; template static int _fastcall StringCompareIgnoreCaseByAscii(const Char1* string1, const Char2* string2, size_t count) noexcept { - wchar_t f, l; - int result = 0; - - if (count) - { - /* validation section */ - do { - f = __ascii_towlower(*string1); - l = __ascii_towlower(*string2); - string1++; - string2++; - } while ((--count) && f && (f == l)); - - result = (int)(f - l); - } - - return result; + wchar_t f, l; + int result = 0; + + if (count) + { + /* validation section */ + do { + f = __ascii_towlower(*string1); + l = __ascii_towlower(*string2); + string1++; + string2++; + } while ((--count) && f && (f == l)); + + result = (int)(f - l); + } + + return result; } template @@ -208,27 +219,27 @@ static DWORD __fastcall GetDllTimeDateStamp(_In_ HMODULE _hModule) enum : int { - __crt_maximum_pointer_shift = sizeof(uintptr_t) * 8 + __crt_maximum_pointer_shift = sizeof(uintptr_t) * 8 }; static __forceinline unsigned int __fastcall __crt_rotate_pointer_value(unsigned int const value, int const shift) noexcept { - return RotateRight32(value, shift); + return RotateRight32(value, shift); } static __forceinline unsigned __int64 __fastcall __crt_rotate_pointer_value(unsigned __int64 const value, int const shift) noexcept { - return RotateRight64(value, shift); + return RotateRight64(value, shift); } #ifdef _WIN64 #define __foreinclude(p) \ - __pragma(warning(suppress:6031)) \ - _bittest64((LONG_PTR*)(&p), 0) + __pragma(warning(suppress:6031)) \ + _bittest64((LONG_PTR*)(&p), 0) #else #define __foreinclude(p) \ - __pragma(warning(suppress:6031)) \ - _bittest((LONG_PTR*)(&p), 0) + __pragma(warning(suppress:6031)) \ + _bittest((LONG_PTR*)(&p), 0) #endif enum class ThunksInitStatus : LONG @@ -247,64 +258,64 @@ enum class ThunksInitStatus : LONG static ThunksInitStatus __cdecl _YY_initialize_winapi_thunks(ThunksInitStatus _sInitStatus); static PVOID __fastcall __CRT_DecodePointer( - PVOID Ptr - ) + PVOID Ptr + ) { - return reinterpret_cast( - __crt_rotate_pointer_value( - reinterpret_cast(Ptr) ^ __security_cookie_yy_thunks, - __security_cookie_yy_thunks % __crt_maximum_pointer_shift - ) - ); + return reinterpret_cast( + __crt_rotate_pointer_value( + reinterpret_cast(Ptr) ^ __security_cookie_yy_thunks, + __security_cookie_yy_thunks % __crt_maximum_pointer_shift + ) + ); } static PVOID __fastcall __CRT_EncodePointer(PVOID const Ptr) { - return reinterpret_cast( - __crt_rotate_pointer_value( - reinterpret_cast(Ptr), - __crt_maximum_pointer_shift - (__security_cookie_yy_thunks % __crt_maximum_pointer_shift) - ) ^ __security_cookie_yy_thunks - ); + return reinterpret_cast( + __crt_rotate_pointer_value( + reinterpret_cast(Ptr), + __crt_maximum_pointer_shift - (__security_cookie_yy_thunks % __crt_maximum_pointer_shift) + ) ^ __security_cookie_yy_thunks + ); } template static __forceinline T __fastcall __crt_fast_decode_pointer(T const p) noexcept { - return reinterpret_cast(__CRT_DecodePointer(p)); + return reinterpret_cast(__CRT_DecodePointer(p)); } template static __forceinline T __fastcall __crt_fast_encode_pointer(T const p) noexcept { - return reinterpret_cast(__CRT_EncodePointer(p)); + return reinterpret_cast(__CRT_EncodePointer(p)); } template static __forceinline T* __fastcall __crt_interlocked_exchange_pointer(T* const volatile* target, V const value) noexcept { - // This is required to silence a spurious unreferenced formal parameter - // warning. - UNREFERENCED_PARAMETER(value); + // This is required to silence a spurious unreferenced formal parameter + // warning. + UNREFERENCED_PARAMETER(value); - return reinterpret_cast(_InterlockedExchangePointer((void**)target, (void*)value)); + return reinterpret_cast(_InterlockedExchangePointer((void**)target, (void*)value)); } template static __forceinline T* __fastcall __crt_interlocked_compare_exchange_pointer(T* const volatile* target, E const exchange, C const comparand) noexcept { - UNREFERENCED_PARAMETER(exchange); // These are required to silence spurious - UNREFERENCED_PARAMETER(comparand); // unreferenced formal parameter warnings. + UNREFERENCED_PARAMETER(exchange); // These are required to silence spurious + UNREFERENCED_PARAMETER(comparand); // unreferenced formal parameter warnings. - return reinterpret_cast(_InterlockedCompareExchangePointer( - (void**)target, (void*)exchange, (void*)comparand)); + return reinterpret_cast(_InterlockedCompareExchangePointer( + (void**)target, (void*)exchange, (void*)comparand)); } template static __forceinline T* __fastcall __crt_interlocked_read_pointer(T* const volatile* target) noexcept { - return __crt_interlocked_compare_exchange_pointer(target, nullptr, nullptr); + return __crt_interlocked_compare_exchange_pointer(target, nullptr, nullptr); } // 改选项非常危险,只调用GetModuleHandleW!!! @@ -336,11 +347,11 @@ struct ProcInfo }; static __forceinline void* __fastcall try_get_proc_address_from_first_available_module( - const ProcInfo& _ProcInfo + const ProcInfo& _ProcInfo ) noexcept; static __forceinline void* __fastcall try_get_proc_address_from_dll( - const ProcInfo& _ProcInfo + const ProcInfo& _ProcInfo ) noexcept; struct ProcOffsetInfo @@ -351,7 +362,7 @@ struct ProcOffsetInfo template static __forceinline void* __fastcall try_get_proc_address_from_offset( - HMODULE _hModule, + HMODULE _hModule, const ProcOffsetInfo (&_ProcOffsetInfos)[kLength] ) noexcept { @@ -382,12 +393,12 @@ static __forceinline void* __fastcall try_get_proc_address_from_offset( static __forceinline void* __cdecl invalid_function_sentinel() noexcept { - return reinterpret_cast(static_cast(-1)); + return reinterpret_cast(static_cast(-1)); } static void* __fastcall try_get_function( - void** ppFunAddress, + void** ppFunAddress, const ProcInfo& _ProcInfo ) noexcept { @@ -397,58 +408,58 @@ static void* __fastcall try_get_function( _YY_initialize_winapi_thunks(ThunksInitStatus::InitByAPI); } - // First check to see if we've cached the function pointer: - { - void* const cached_fp = __crt_fast_decode_pointer( - __crt_interlocked_read_pointer(ppFunAddress)); - - if (cached_fp == invalid_function_sentinel()) - { - return nullptr; - } - - if (cached_fp) - { - return cached_fp; - } - } - - // 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(_ProcInfo); - if (!new_fp) - { - void* const cached_fp = __crt_fast_decode_pointer( - __crt_interlocked_exchange_pointer( - ppFunAddress, - __crt_fast_encode_pointer(invalid_function_sentinel()))); - - if (cached_fp) - { - _ASSERTE(cached_fp == invalid_function_sentinel()); - } - - return nullptr; - } - - // Swap the newly obtained function pointer into the cache. The cache may - // no longer contain an encoded null pointer if another thread obtained the - // function address while we were doing the same (both threads should have - // gotten the same function pointer): - { - void* const cached_fp = __crt_fast_decode_pointer( - __crt_interlocked_exchange_pointer( - ppFunAddress, - __crt_fast_encode_pointer(new_fp))); - - if (cached_fp) - { - _ASSERTE(cached_fp == new_fp); - } - } - - return new_fp; + // First check to see if we've cached the function pointer: + { + void* const cached_fp = __crt_fast_decode_pointer( + __crt_interlocked_read_pointer(ppFunAddress)); + + if (cached_fp == invalid_function_sentinel()) + { + return nullptr; + } + + if (cached_fp) + { + return cached_fp; + } + } + + // 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(_ProcInfo); + if (!new_fp) + { + void* const cached_fp = __crt_fast_decode_pointer( + __crt_interlocked_exchange_pointer( + ppFunAddress, + __crt_fast_encode_pointer(invalid_function_sentinel()))); + + if (cached_fp) + { + _ASSERTE(cached_fp == invalid_function_sentinel()); + } + + return nullptr; + } + + // Swap the newly obtained function pointer into the cache. The cache may + // no longer contain an encoded null pointer if another thread obtained the + // function address while we were doing the same (both threads should have + // gotten the same function pointer): + { + void* const cached_fp = __crt_fast_decode_pointer( + __crt_interlocked_exchange_pointer( + ppFunAddress, + __crt_fast_encode_pointer(new_fp))); + + if (cached_fp) + { + _ASSERTE(cached_fp == new_fp); + } + } + + return new_fp; } @@ -475,7 +486,7 @@ __if_exists(YY::Thunks::Fallback::_CRT_CONCATENATE(try_get_, _FUNCTION)) &_CRT_CONCATENATE(pFun_ ,_FUNCTION), \ _ProcInfo)); \ } - _YY_APPLY_TO_LATE_BOUND_FUNCTIONS(_APPLY) + _YY_APPLY_TO_LATE_BOUND_FUNCTIONS(_APPLY) #undef _APPLY @@ -510,14 +521,14 @@ static UINT_PTR GetSecurityNewCookie() cookie ^= GetCurrentThreadId(); cookie ^= GetCurrentProcessId(); -#if (YY_Thunks_Support_Version >= NTDDI_WIN6) +#if (YY_Thunks_Target >= __WindowsNT6) #if defined (_WIN64) cookie ^= (((UINT_PTR)GetTickCount64()) << 56); #endif /* defined (_WIN64) */ cookie ^= (UINT_PTR)GetTickCount64(); -#else // (YY_Thunks_Support_Version < NTDDI_WIN6) +#else // (YY_Thunks_Target < __WindowsNT6) cookie ^= (UINT_PTR)GetTickCount(); -#endif // !(YY_Thunks_Support_Version < NTDDI_WIN6) +#endif // !(YY_Thunks_Target < __WindowsNT6) QueryPerformanceCounter(&perfctr); #if defined (_WIN64) @@ -552,14 +563,14 @@ static volatile ThunksInitStatus s_eThunksStatus /*= ThunksInitStatus::None*/; static void __cdecl __YY_uninitialize_winapi_thunks() { - // 只反初始化一次 + // 只反初始化一次 const auto _eStatus = (ThunksInitStatus)InterlockedExchange((volatile LONG*)&s_eThunksStatus, LONG(ThunksInitStatus::Uninitialized)); // Uninitialized : 已经反初始化,那么也就没有必要再次反初始化。 // Wait : 其他线程还在等待……保险起见我就直接跳过反初始化吧。崩溃还是如何听天由命吧 // None : 怎么还没初始化呢……这是在逗我? - if (LONG(_eStatus) <= 0) - return; + if (LONG(_eStatus) <= 0) + return; //当DLL被强行卸载时,我们什么都不做,因为依赖的函数指针可能是无效的。 __if_exists(__YY_Thunks_Process_Terminating) @@ -567,38 +578,38 @@ static void __cdecl __YY_uninitialize_winapi_thunks() if (__YY_Thunks_Process_Terminating) return; } - if (auto pRtlDllShutdownInProgress = (decltype(RtlDllShutdownInProgress)*)GetProcAddress(try_get_module_ntdll(), "RtlDllShutdownInProgress")) - { - if(pRtlDllShutdownInProgress()) - return; - } - - auto pModule = (HMODULE*)__YY_THUNKS_MODULE_START; - auto pModuleEnd = (HMODULE*)__YY_THUNKS_FUN_START; - - for (; pModule != pModuleEnd; ++pModule) - { - auto& module = *pModule; - if (module) - { - if (module != INVALID_HANDLE_VALUE) - { - FreeLibrary(module); - } - - module = nullptr; - } - } -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - CloseHandle(_GlobalKeyedEventHandle); + if (auto pRtlDllShutdownInProgress = (decltype(RtlDllShutdownInProgress)*)GetProcAddress(try_get_module_ntdll(), "RtlDllShutdownInProgress")) + { + if(pRtlDllShutdownInProgress()) + return; + } + + auto pModule = (HMODULE*)__YY_THUNKS_MODULE_START; + auto pModuleEnd = (HMODULE*)__YY_THUNKS_FUN_START; + + for (; pModule != pModuleEnd; ++pModule) + { + auto& module = *pModule; + if (module) + { + if (module != INVALID_HANDLE_VALUE) + { + FreeLibrary(module); + } + + module = nullptr; + } + } +#if (YY_Thunks_Target < __WindowsNT6) + CloseHandle(_GlobalKeyedEventHandle); #endif - //执行本库中所有的反初始化工作。 - for (auto p = (UninitFunType*)__YY_THUNKS_UNINIT_FUN_START; p != (UninitFunType*)__YY_THUNKS_UNINIT_FUN_END; ++p) - { - if (auto pUninitFun = *p) - pUninitFun(); - } + //执行本库中所有的反初始化工作。 + for (auto p = (UninitFunType*)__YY_THUNKS_UNINIT_FUN_START; p != (UninitFunType*)__YY_THUNKS_UNINIT_FUN_END; ++p) + { + if (auto pUninitFun = *p) + pUninitFun(); + } } static ThunksInitStatus __cdecl _YY_initialize_winapi_thunks(ThunksInitStatus _sInitStatus) @@ -665,26 +676,26 @@ EXTERN_C extern void* __acrt_atexit_table; static int __cdecl __YY_initialize_winapi_thunks() { - const auto _eStatus = _YY_initialize_winapi_thunks(ThunksInitStatus::InitByCRT); + const auto _eStatus = _YY_initialize_winapi_thunks(ThunksInitStatus::InitByCRT); if (_eStatus != ThunksInitStatus::InitByCRT && _eStatus != ThunksInitStatus::InitByAPI) { // 不接管由DllMain触发的初始化,因为它可以自行反初始化。 return 0; } - // 如果 == null,那么有2种情况: - // 1. 非UCRT,比如2008,VC6,这时,调用 atexit是安全的,因为atexit在 XIA初始化完成了。 - // 2. UCRT 并且处于MD状态。这时 atexit初始化 会提与 XIA,这时也是没有问题的。 - // 如果 != null: - // 那么说明UCRT处于静态状态(CRT DLL其实也是静态的一种) - // 这时,XTY是可以正确执行的,这时就不用调用atexit了 - // 由于XTY晚于onexit,所以它是可靠的。 - if (__acrt_atexit_table == nullptr) - { - atexit(__YY_uninitialize_winapi_thunks); - } - - return 0; + // 如果 == null,那么有2种情况: + // 1. 非UCRT,比如2008,VC6,这时,调用 atexit是安全的,因为atexit在 XIA初始化完成了。 + // 2. UCRT 并且处于MD状态。这时 atexit初始化 会提与 XIA,这时也是没有问题的。 + // 如果 != null: + // 那么说明UCRT处于静态状态(CRT DLL其实也是静态的一种) + // 这时,XTY是可以正确执行的,这时就不用调用atexit了 + // 由于XTY晚于onexit,所以它是可靠的。 + if (__acrt_atexit_table == nullptr) + { + atexit(__YY_uninitialize_winapi_thunks); + } + + return 0; } diff --git a/src/Thunks/api-ms-win-core-com.hpp b/src/Thunks/api-ms-win-core-com.hpp index 8fdcf35..83c851b 100644 --- a/src/Thunks/api-ms-win-core-com.hpp +++ b/src/Thunks/api-ms-win-core-com.hpp @@ -1,77 +1,77 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) && !defined(__Comment_Lib_ole32) +#if (YY_Thunks_Target < __WindowsNT6_1) && !defined(__Comment_Lib_ole32) #define __Comment_Lib_ole32 #pragma comment(lib, "ole32.lib") #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) - // Windows 7 [桌面应用|UWP 应用], Windows Server 2008 R2 [桌面应用|UWP 应用] - __DEFINE_THUNK( - ole32, - 8, - HRESULT, - WINAPI, - CoGetApartmentType, - _Out_ APTTYPE* _pAptType, - _Out_ APTTYPEQUALIFIER* _pAptQualifier - ) - { - if (auto _pfnCoGetApartmentType = try_get_CoGetApartmentType()) - { - return _pfnCoGetApartmentType(_pAptType, _pAptQualifier); - } + // Windows 7 [桌面应用|UWP 应用], Windows Server 2008 R2 [桌面应用|UWP 应用] + __DEFINE_THUNK( + ole32, + 8, + HRESULT, + WINAPI, + CoGetApartmentType, + _Out_ APTTYPE* _pAptType, + _Out_ APTTYPEQUALIFIER* _pAptQualifier + ) + { + if (auto _pfnCoGetApartmentType = try_get_CoGetApartmentType()) + { + return _pfnCoGetApartmentType(_pAptType, _pAptQualifier); + } - if (_pAptType == nullptr || _pAptQualifier == nullptr) - return E_INVALIDARG; + if (_pAptType == nullptr || _pAptQualifier == nullptr) + return E_INVALIDARG; - *_pAptType = APTTYPE_CURRENT; - *_pAptQualifier = APTTYPEQUALIFIER_NONE; + *_pAptType = APTTYPE_CURRENT; + *_pAptQualifier = APTTYPEQUALIFIER_NONE; - IUnknown* _pContextToken; - auto _hr = CoGetContextToken((ULONG_PTR*)&_pContextToken); - if (FAILED(_hr)) - return _hr; + IUnknown* _pContextToken; + auto _hr = CoGetContextToken((ULONG_PTR*)&_pContextToken); + if (FAILED(_hr)) + return _hr; - IComThreadingInfo* _pComThreadingInfo; - _hr = _pContextToken->QueryInterface(&_pComThreadingInfo); - if (FAILED(_hr)) - return _hr; + IComThreadingInfo* _pComThreadingInfo; + _hr = _pContextToken->QueryInterface(&_pComThreadingInfo); + if (FAILED(_hr)) + return _hr; - _hr = _pComThreadingInfo->GetCurrentApartmentType(_pAptType); - _pComThreadingInfo->Release(); - if (FAILED(_hr)) - return _hr; + _hr = _pComThreadingInfo->GetCurrentApartmentType(_pAptType); + _pComThreadingInfo->Release(); + if (FAILED(_hr)) + return _hr; - switch (*_pAptType) - { - case APTTYPE_STA: - *_pAptQualifier = APTTYPEQUALIFIER_APPLICATION_STA; - break; - case APTTYPE_MTA: - // todo: 无法区分: - // APTTYPEQUALIFIER_NONE - // APTTYPEQUALIFIER_IMPLICIT_MTA - break; - case APTTYPE_NA: - // todo: 无法区分 - // APTTYPEQUALIFIER_NA_ON_MTA - // APTTYPEQUALIFIER_NA_ON_STA - // APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA - // APTTYPEQUALIFIER_NA_ON_MAINSTA - break; - case APTTYPE_MAINSTA: - break; - default: - break; - } + switch (*_pAptType) + { + case APTTYPE_STA: + *_pAptQualifier = APTTYPEQUALIFIER_APPLICATION_STA; + break; + case APTTYPE_MTA: + // todo: 无法区分: + // APTTYPEQUALIFIER_NONE + // APTTYPEQUALIFIER_IMPLICIT_MTA + break; + case APTTYPE_NA: + // todo: 无法区分 + // APTTYPEQUALIFIER_NA_ON_MTA + // APTTYPEQUALIFIER_NA_ON_STA + // APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA + // APTTYPEQUALIFIER_NA_ON_MAINSTA + break; + case APTTYPE_MAINSTA: + break; + default: + break; + } - return S_OK; - } + return S_OK; + } #endif } diff --git a/src/Thunks/api-ms-win-core-datetime.hpp b/src/Thunks/api-ms-win-core-datetime.hpp index 96862eb..d77ac20 100644 --- a/src/Thunks/api-ms-win-core-datetime.hpp +++ b/src/Thunks/api-ms-win-core-datetime.hpp @@ -1,81 +1,75 @@  -namespace YY +namespace YY::Thunks { - namespace Thunks - { +#if (YY_Thunks_Target < __WindowsNT6) -#if (YY_Thunks_Support_Version < NTDDI_WIN6) + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + kernel32, + 28, + int, + WINAPI, + GetDateFormatEx, + _In_opt_ LPCWSTR lpLocaleName, + _In_ DWORD dwFlags, + _In_opt_ CONST SYSTEMTIME* lpDate, + _In_opt_ LPCWSTR lpFormat, + _Out_writes_opt_(cchDate) LPWSTR lpDateStr, + _In_ int cchDate, + _In_opt_ LPCWSTR lpCalendar + ) + { + if (auto pGetDateFormatEx = try_get_GetDateFormatEx()) + { + return pGetDateFormatEx(lpLocaleName, dwFlags, lpDate, lpFormat, lpDateStr, cchDate, lpCalendar); + } - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - kernel32, - 28, - int, - WINAPI, - GetDateFormatEx, - _In_opt_ LPCWSTR lpLocaleName, - _In_ DWORD dwFlags, - _In_opt_ CONST SYSTEMTIME* lpDate, - _In_opt_ LPCWSTR lpFormat, - _Out_writes_opt_(cchDate) LPWSTR lpDateStr, - _In_ int cchDate, - _In_opt_ LPCWSTR lpCalendar - ) - { - if (auto pGetDateFormatEx = try_get_GetDateFormatEx()) - { - return pGetDateFormatEx(lpLocaleName, dwFlags, lpDate, lpFormat, lpDateStr, cchDate, lpCalendar); - } + auto Locale = LocaleNameToLCID(lpLocaleName, 0); - auto Locale = LocaleNameToLCID(lpLocaleName, 0); + if (Locale == 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } - if (Locale == 0) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - return GetDateFormatW(Locale, dwFlags, lpDate, lpFormat, lpDateStr, cchDate); - } + return GetDateFormatW(Locale, dwFlags, lpDate, lpFormat, lpDateStr, cchDate); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - kernel32, - 24, - int, - WINAPI, - GetTimeFormatEx, - _In_opt_ LPCWSTR lpLocaleName, - _In_ DWORD dwFlags, - _In_opt_ CONST SYSTEMTIME* lpTime, - _In_opt_ LPCWSTR lpFormat, - _Out_writes_opt_(cchTime) LPWSTR lpTimeStr, - _In_ int cchTime - ) - { - if (auto pGetTimeFormatEx = try_get_GetTimeFormatEx()) - { - return pGetTimeFormatEx(lpLocaleName, dwFlags, lpTime, lpFormat, lpTimeStr, cchTime); - } + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + kernel32, + 24, + int, + WINAPI, + GetTimeFormatEx, + _In_opt_ LPCWSTR lpLocaleName, + _In_ DWORD dwFlags, + _In_opt_ CONST SYSTEMTIME* lpTime, + _In_opt_ LPCWSTR lpFormat, + _Out_writes_opt_(cchTime) LPWSTR lpTimeStr, + _In_ int cchTime + ) + { + if (auto pGetTimeFormatEx = try_get_GetTimeFormatEx()) + { + return pGetTimeFormatEx(lpLocaleName, dwFlags, lpTime, lpFormat, lpTimeStr, cchTime); + } - auto Locale = LocaleNameToLCID(lpLocaleName, 0); + auto Locale = LocaleNameToLCID(lpLocaleName, 0); - if (Locale == 0) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } + if (Locale == 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } - return GetTimeFormatW(Locale, dwFlags, lpTime, lpFormat, lpTimeStr, cchTime); - } + return GetTimeFormatW(Locale, dwFlags, lpTime, lpFormat, lpTimeStr, cchTime); + } #endif - - }//namespace Thunks - -} //namespace YY \ No newline at end of file +} //namespace YY::Thunks diff --git a/src/Thunks/api-ms-win-core-errorhandling.hpp b/src/Thunks/api-ms-win-core-errorhandling.hpp index 6e45272..d7780da 100644 --- a/src/Thunks/api-ms-win-core-errorhandling.hpp +++ b/src/Thunks/api-ms-win-core-errorhandling.hpp @@ -1,134 +1,128 @@  -namespace YY +namespace YY::Thunks { - namespace Thunks - { - -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - //Windows 7 [desktop apps | UWP apps] - //Windows Server 2008 R2 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 12, - VOID, - WINAPI, - RaiseFailFastException, - _In_opt_ PEXCEPTION_RECORD pExceptionRecord, - _In_opt_ PCONTEXT pContextRecord, - _In_ DWORD dwFlags - ) - { - if (auto pRaiseFailFastException = try_get_RaiseFailFastException()) - { - return pRaiseFailFastException(pExceptionRecord, pContextRecord, dwFlags); - } - - //直接结束进程 - TerminateProcess(NtGetCurrentProcess(), pExceptionRecord ? pExceptionRecord->ExceptionCode : STATUS_FAIL_FAST_EXCEPTION); - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + //Windows 7 [desktop apps | UWP apps] + //Windows Server 2008 R2 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 12, + VOID, + WINAPI, + RaiseFailFastException, + _In_opt_ PEXCEPTION_RECORD pExceptionRecord, + _In_opt_ PCONTEXT pContextRecord, + _In_ DWORD dwFlags + ) + { + if (auto pRaiseFailFastException = try_get_RaiseFailFastException()) + { + return pRaiseFailFastException(pExceptionRecord, pContextRecord, dwFlags); + } + + //直接结束进程 + TerminateProcess(NtGetCurrentProcess(), pExceptionRecord ? pExceptionRecord->ExceptionCode : STATUS_FAIL_FAST_EXCEPTION); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - //Windows 7 [desktop apps | UWP apps] - //Windows Server 2008 R2 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - SetThreadErrorMode, - _In_ DWORD dwNewMode, - _In_opt_ LPDWORD lpOldMode - ) - { - if (auto pSetThreadErrorMode = try_get_SetThreadErrorMode()) - { - return pSetThreadErrorMode(dwNewMode, lpOldMode); - } - - auto dwOldMode = SetErrorMode(dwNewMode); - if (lpOldMode) - *lpOldMode = dwOldMode; - - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + //Windows 7 [desktop apps | UWP apps] + //Windows Server 2008 R2 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + SetThreadErrorMode, + _In_ DWORD dwNewMode, + _In_opt_ LPDWORD lpOldMode + ) + { + if (auto pSetThreadErrorMode = try_get_SetThreadErrorMode()) + { + return pSetThreadErrorMode(dwNewMode, lpOldMode); + } + + auto dwOldMode = SetErrorMode(dwNewMode); + if (lpOldMode) + *lpOldMode = dwOldMode; + + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - //Windows 7 [desktop apps | UWP apps] - //Windows Server 2008 R2 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 0, - DWORD, - WINAPI, - GetThreadErrorMode, - VOID - ) - { - if (auto pGetThreadErrorMode = try_get_GetThreadErrorMode()) - { - return pGetThreadErrorMode(); - } - - return GetErrorMode(); - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + //Windows 7 [desktop apps | UWP apps] + //Windows Server 2008 R2 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 0, + DWORD, + WINAPI, + GetThreadErrorMode, + VOID + ) + { + if (auto pGetThreadErrorMode = try_get_GetThreadErrorMode()) + { + return pGetThreadErrorMode(); + } + + return GetErrorMode(); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 0, - UINT, - WINAPI, - GetErrorMode, - VOID - ) - { - if (auto pGetErrorMode = try_get_GetErrorMode()) - { - return pGetErrorMode(); - } - else if (auto pNtQueryInformationProcess = try_get_NtQueryInformationProcess()) - { - DWORD dwDefaultHardErrorMode; - - auto Status = pNtQueryInformationProcess(NtCurrentProcess(), ProcessDefaultHardErrorMode, &dwDefaultHardErrorMode, sizeof(dwDefaultHardErrorMode), nullptr); - - if (Status >= 0) - { - if (dwDefaultHardErrorMode & 0x00000001) - { - return dwDefaultHardErrorMode & 0xFFFFFFFE; - } - else - { - return dwDefaultHardErrorMode | 0x00000001; - } - } - - internal::BaseSetLastNTError(Status); - - return 0; - } - else - { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; - } - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 0, + UINT, + WINAPI, + GetErrorMode, + VOID + ) + { + if (auto pGetErrorMode = try_get_GetErrorMode()) + { + return pGetErrorMode(); + } + else if (auto pNtQueryInformationProcess = try_get_NtQueryInformationProcess()) + { + DWORD dwDefaultHardErrorMode; + + auto Status = pNtQueryInformationProcess(NtCurrentProcess(), ProcessDefaultHardErrorMode, &dwDefaultHardErrorMode, sizeof(dwDefaultHardErrorMode), nullptr); + + if (Status >= 0) + { + if (dwDefaultHardErrorMode & 0x00000001) + { + return dwDefaultHardErrorMode & 0xFFFFFFFE; + } + else + { + return dwDefaultHardErrorMode | 0x00000001; + } + } + + internal::BaseSetLastNTError(Status); + + return 0; + } + else + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; + } + } #endif - - }//namespace Thunks - -} //namespace YY \ No newline at end of file +} //namespace YY::Thunks diff --git a/src/Thunks/api-ms-win-core-fibers.hpp b/src/Thunks/api-ms-win-core-fibers.hpp index 7c10143..effbaed 100644 --- a/src/Thunks/api-ms-win-core-fibers.hpp +++ b/src/Thunks/api-ms-win-core-fibers.hpp @@ -1,163 +1,162 @@  -namespace YY::Thunks +namespace YY::Thunks::Fallback { -#if defined(YY_Thunks_Implemented) && (YY_Thunks_Support_Version < NTDDI_WS03) - namespace Fallback +#if defined(YY_Thunks_Implemented) && (YY_Thunks_Target < __WindowsNT5_2) + namespace { - namespace + //Vista的Fls数量只有128,所以我们将长度固定为128,模拟Vista + constexpr auto kMaxFlsIndexCount = 128; + + struct FlsData { - //Vista的Fls数量只有128,所以我们将长度固定为128,模拟Vista - constexpr auto kMaxFlsIndexCount = 128; + FlsData* pNext; + FlsData* pPrev; - struct FlsData - { - FlsData* pNext; - FlsData* pPrev; + //此线程存储的数据 + LPVOID lpFlsData; + }; - //此线程存储的数据 - LPVOID lpFlsData; - }; + struct FlsDataBlock + { + FlsData FlsDataArray[kMaxFlsIndexCount] = {}; + DWORD uRef = 1; - struct FlsDataBlock + void AddRef() { - FlsData FlsDataArray[kMaxFlsIndexCount] = {}; - DWORD uRef = 1; + InterlockedIncrement(&uRef); + } - void AddRef() + void Release() + { + if (InterlockedDecrement(&uRef) == 0) { - InterlockedIncrement(&uRef); + internal::Delete(this); } + } + }; - void Release() - { - if (InterlockedDecrement(&uRef) == 0) - { - internal::Delete(this); - } - } - }; + static thread_local FlsDataBlock* s_pFlsDataBlock; - static thread_local FlsDataBlock* s_pFlsDataBlock; + struct FlsIndex + { + volatile LONG fFlags; + //FlsAlloc 传入的参数 + volatile PFLS_CALLBACK_FUNCTION pfnCallback; + FlsData Root; - struct FlsIndex + enum { - volatile LONG fFlags; - //FlsAlloc 传入的参数 - volatile PFLS_CALLBACK_FUNCTION pfnCallback; - FlsData Root; - - enum - { - TlsUsedBitIndex = 0, - DataLockBitIndex, - }; + TlsUsedBitIndex = 0, + DataLockBitIndex, }; - static FlsIndex s_FlsIndexArray[kMaxFlsIndexCount]; - static DWORD s_FlsIndexArrayBitMap[kMaxFlsIndexCount / 32]; - static_assert(sizeof(s_FlsIndexArrayBitMap) * 8 == kMaxFlsIndexCount, ""); - - static VOID NTAPI ThreadDetachCallback( - PVOID DllHandle, - DWORD Reason, - PVOID Reserved - ) + }; + static FlsIndex s_FlsIndexArray[kMaxFlsIndexCount]; + static DWORD s_FlsIndexArrayBitMap[kMaxFlsIndexCount / 32]; + static_assert(sizeof(s_FlsIndexArrayBitMap) * 8 == kMaxFlsIndexCount, ""); + + static VOID NTAPI ThreadDetachCallback( + PVOID DllHandle, + DWORD Reason, + PVOID Reserved + ) + { + if (DLL_THREAD_DETACH == Reason && s_pFlsDataBlock) { - if (DLL_THREAD_DETACH == Reason && s_pFlsDataBlock) + //线程退出时我们需要调用Fls的 Callback + for (DWORD i = 0; i != kMaxFlsIndexCount; ++i) { - //线程退出时我们需要调用Fls的 Callback - for (DWORD i = 0; i != kMaxFlsIndexCount; ++i) + auto& _FlsData = s_pFlsDataBlock->FlsDataArray[i]; + if (/*_FlsData.pPrev == nullptr ||*/ _FlsData.lpFlsData == nullptr) + continue; + + auto& _FlsIndex = s_FlsIndexArray[i]; + + for (auto _fLastFlags = _FlsIndex.fFlags; _FlsIndex.pfnCallback;) { - auto& _FlsData = s_pFlsDataBlock->FlsDataArray[i]; - if (/*_FlsData.pPrev == nullptr ||*/ _FlsData.lpFlsData == nullptr) - continue; + if ((_fLastFlags & (1 << FlsIndex::TlsUsedBitIndex)) == 0) + { + break; + } - auto& _FlsIndex = s_FlsIndexArray[i]; + if (_fLastFlags & (1 << FlsIndex::DataLockBitIndex)) + { + YieldProcessor(); + _fLastFlags = _FlsIndex.fFlags; + continue; + } - for (auto _fLastFlags = _FlsIndex.fFlags; _FlsIndex.pfnCallback;) + auto _Result = InterlockedCompareExchange(&_FlsIndex.fFlags, _fLastFlags | (1 << FlsIndex::DataLockBitIndex), _fLastFlags); + if (_Result == _fLastFlags) { - if ((_fLastFlags & (1 << FlsIndex::TlsUsedBitIndex)) == 0) + auto pPrev = _FlsData.pPrev; + auto pNext = _FlsData.pNext; + _FlsData.pNext = nullptr; + _FlsData.pPrev = nullptr; + if (pNext) { - break; + pNext->pPrev = pPrev; } + pPrev->pNext = pNext; - if (_fLastFlags & (1 << FlsIndex::DataLockBitIndex)) - { - YieldProcessor(); - _fLastFlags = _FlsIndex.fFlags; - continue; - } + auto _pfnCallback = _FlsIndex.pfnCallback; + _interlockedbittestandreset(&_FlsIndex.fFlags, FlsIndex::DataLockBitIndex); - auto _Result = InterlockedCompareExchange(&_FlsIndex.fFlags, _fLastFlags | (1 << FlsIndex::DataLockBitIndex), _fLastFlags); - if (_Result == _fLastFlags) + __try { - auto pPrev = _FlsData.pPrev; - auto pNext = _FlsData.pNext; - _FlsData.pNext = nullptr; - _FlsData.pPrev = nullptr; - if (pNext) - { - pNext->pPrev = pPrev; - } - pPrev->pNext = pNext; - - auto _pfnCallback = _FlsIndex.pfnCallback; - _interlockedbittestandreset(&_FlsIndex.fFlags, FlsIndex::DataLockBitIndex); - - __try + if (_pfnCallback && _FlsData.lpFlsData) { - if (_pfnCallback && _FlsData.lpFlsData) - { - _pfnCallback(_FlsData.lpFlsData); - } + _pfnCallback(_FlsData.lpFlsData); } - __except (EXCEPTION_EXECUTE_HANDLER) - { - } - s_pFlsDataBlock->Release(); - break; } - - _fLastFlags = _Result; + __except (EXCEPTION_EXECUTE_HANDLER) + { + } + s_pFlsDataBlock->Release(); + break; } - } - s_pFlsDataBlock->Release(); + _fLastFlags = _Result; + } } + + s_pFlsDataBlock->Release(); } + } #pragma section(".CRT$XLY", long, read) // MS CRT Loader TLS Callback - extern "C" extern bool _tls_used; - } + extern "C" extern bool _tls_used; } #endif +} + +namespace YY::Thunks +{ +#if (YY_Thunks_Target < __WindowsNT5_2) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2003 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + DWORD, + WINAPI, + FlsAlloc, + _In_opt_ PFLS_CALLBACK_FUNCTION lpCallback + ) + { + if (const auto pFlsAlloc = try_get_FlsAlloc()) + { + return pFlsAlloc(lpCallback); + } + //当系统不支持时,我们使用TLS的机制来实现FLS的功能。 + //当然这个模拟的不完整的,无法完全的支持纤程,但是我认为这不重要。 + //因为很显然,使用纤程的代码很少。 + __declspec(allocate(".CRT$XLY")) static PIMAGE_TLS_CALLBACK const s_ThreadDetachCallback = Fallback::ThreadDetachCallback; -#if (YY_Thunks_Support_Version < NTDDI_WS03) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2003 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - DWORD, - WINAPI, - FlsAlloc, - _In_opt_ PFLS_CALLBACK_FUNCTION lpCallback - ) - { - if (const auto pFlsAlloc = try_get_FlsAlloc()) - { - return pFlsAlloc(lpCallback); - } - - //当系统不支持时,我们使用TLS的机制来实现FLS的功能。 - //当然这个模拟的不完整的,无法完全的支持纤程,但是我认为这不重要。 - //因为很显然,使用纤程的代码很少。 - __declspec(allocate(".CRT$XLY")) static PIMAGE_TLS_CALLBACK const s_ThreadDetachCallback = Fallback::ThreadDetachCallback; - - __foreinclude(s_ThreadDetachCallback); - __foreinclude(Fallback::_tls_used); + __foreinclude(s_ThreadDetachCallback); + __foreinclude(Fallback::_tls_used); DWORD _uFlsIndex; for (size_t i = 0; i != _countof(Fallback::s_FlsIndexArrayBitMap); ++i) @@ -177,29 +176,29 @@ namespace YY::Thunks } } - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FLS_OUT_OF_INDEXES; - } + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FLS_OUT_OF_INDEXES; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2003 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - PVOID, - WINAPI, - FlsGetValue, - _In_ DWORD dwFlsIndex - ) - { - if (const auto pFlsGetValue = try_get_FlsGetValue()) - { - return pFlsGetValue(dwFlsIndex); - } +#if (YY_Thunks_Target < __WindowsNT5_2) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2003 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + PVOID, + WINAPI, + FlsGetValue, + _In_ DWORD dwFlsIndex + ) + { + if (const auto pFlsGetValue = try_get_FlsGetValue()) + { + return pFlsGetValue(dwFlsIndex); + } if (dwFlsIndex >= Fallback::kMaxFlsIndexCount || Fallback::s_pFlsDataBlock == nullptr) { @@ -207,32 +206,32 @@ namespace YY::Thunks return nullptr; } - return Fallback::s_pFlsDataBlock->FlsDataArray[dwFlsIndex].lpFlsData; - } + return Fallback::s_pFlsDataBlock->FlsDataArray[dwFlsIndex].lpFlsData; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2003 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - FlsSetValue, - _In_ DWORD dwFlsIndex, - _In_opt_ PVOID lpFlsData - ) - { - if (const auto pFlsSetValue = try_get_FlsSetValue()) - { - return pFlsSetValue(dwFlsIndex, lpFlsData); - } - - do - { +#if (YY_Thunks_Target < __WindowsNT5_2) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2003 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + FlsSetValue, + _In_ DWORD dwFlsIndex, + _In_opt_ PVOID lpFlsData + ) + { + if (const auto pFlsSetValue = try_get_FlsSetValue()) + { + return pFlsSetValue(dwFlsIndex, lpFlsData); + } + + do + { if (dwFlsIndex >= Fallback::kMaxFlsIndexCount) break; @@ -305,31 +304,31 @@ namespace YY::Thunks break; } - } while (false); + } while (false); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2003 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - BOOL, - WINAPI, - FlsFree, - _In_ DWORD dwFlsIndex - ) - { - if (const auto pFlsFree = try_get_FlsFree()) - { - return pFlsFree(dwFlsIndex); - } +#if (YY_Thunks_Target < __WindowsNT5_2) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2003 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + BOOL, + WINAPI, + FlsFree, + _In_ DWORD dwFlsIndex + ) + { + if (const auto pFlsFree = try_get_FlsFree()) + { + return pFlsFree(dwFlsIndex); + } if (dwFlsIndex >= _countof(Fallback::s_FlsIndexArray)) { @@ -375,58 +374,58 @@ namespace YY::Thunks _interlockedbittestandreset((volatile LONG*)&Fallback::s_FlsIndexArrayBitMap[dwFlsIndex / 32], dwFlsIndex % 32); return TRUE; - } + } #endif - -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 0, - BOOL, - WINAPI, - IsThreadAFiber, - VOID - ) - { - if (const auto pIsThreadAFiber = try_get_IsThreadAFiber()) - { - return pIsThreadAFiber(); - } - - //如果当前没有 Fiber,那么我们认为这不是一个纤程 - auto pFiber = GetCurrentFiber(); - - //0x1e00 是一个魔幻数字,似乎所有NT系统都会这样,当前不是一个Fiber时,第一次会返回 0x1e00。 - return pFiber != nullptr && pFiber != (void*)0x1e00; - } + +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 0, + BOOL, + WINAPI, + IsThreadAFiber, + VOID + ) + { + if (const auto pIsThreadAFiber = try_get_IsThreadAFiber()) + { + return pIsThreadAFiber(); + } + + //如果当前没有 Fiber,那么我们认为这不是一个纤程 + auto pFiber = GetCurrentFiber(); + + //0x1e00 是一个魔幻数字,似乎所有NT系统都会这样,当前不是一个Fiber时,第一次会返回 0x1e00。 + return pFiber != nullptr && pFiber != (void*)0x1e00; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 8, - LPVOID, - WINAPI, - ConvertThreadToFiberEx, - _In_opt_ LPVOID lpParameter, - _In_ DWORD dwFlags - ) - { - if (const auto pConvertThreadToFiberEx = try_get_ConvertThreadToFiberEx()) - { - return pConvertThreadToFiberEx(lpParameter, dwFlags); - } - - //FIBER_FLAG_FLOAT_SWITCH 无法使用,不过似乎关系不大。一些boost基础设施中都不切换浮点状态。 - return ConvertThreadToFiber(lpParameter); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 8, + LPVOID, + WINAPI, + ConvertThreadToFiberEx, + _In_opt_ LPVOID lpParameter, + _In_ DWORD dwFlags + ) + { + if (const auto pConvertThreadToFiberEx = try_get_ConvertThreadToFiberEx()) + { + return pConvertThreadToFiberEx(lpParameter, dwFlags); + } + + //FIBER_FLAG_FLOAT_SWITCH 无法使用,不过似乎关系不大。一些boost基础设施中都不切换浮点状态。 + return ConvertThreadToFiber(lpParameter); + } #endif } diff --git a/src/Thunks/api-ms-win-core-file.hpp b/src/Thunks/api-ms-win-core-file.hpp index c863d44..dba6f40 100644 --- a/src/Thunks/api-ms-win-core-file.hpp +++ b/src/Thunks/api-ms-win-core-file.hpp @@ -1,1333 +1,1334 @@  +#ifdef YY_Thunks_Implemented +namespace YY::Thunks +{ + namespace + { +#if (YY_Thunks_Target < __WindowsNT6) + enum _FILE_ID_TYPE_win7 + { + FileIdType, + ObjectIdType, + MaximumFileIdType + }; + + struct FILE_ID_DESCRIPTOR_win7 + { + DWORD dwSize; // Size of the struct + FILE_ID_TYPE Type; // Describes the type of identifier passed in. + union { + LARGE_INTEGER FileId; + GUID ObjectId; + } DUMMYUNIONNAME; + }; +#endif + } +} +#endif -namespace YY +namespace YY::Thunks { - namespace Thunks - { -#ifdef YY_Thunks_Implemented +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + kernel32, + 16, + _Success_(return) + BOOL, + WINAPI, + GetFileInformationByHandleEx, + _In_ HANDLE hFile, + _In_ FILE_INFO_BY_HANDLE_CLASS FileInformationClass, + _Out_writes_bytes_(dwBufferSize) LPVOID lpFileInformation, + _In_ DWORD dwBufferSize + ) + { + if (auto const pGetFileInformationByHandleEx = try_get_GetFileInformationByHandleEx()) + { + return pGetFileInformationByHandleEx(hFile, FileInformationClass, lpFileInformation, dwBufferSize); + } + + + FILE_INFORMATION_CLASS NtFileInformationClass; + DWORD cbMinBufferSize; + bool bNtQueryDirectoryFile = false; + BOOLEAN RestartScan = false; + + switch (FileInformationClass) + { + case FileBasicInfo: + NtFileInformationClass = FileBasicInformation; + cbMinBufferSize = sizeof(FILE_BASIC_INFO); + break; + case FileStandardInfo: + NtFileInformationClass = FileStandardInformation; + cbMinBufferSize = sizeof(FILE_STANDARD_INFO); + break; + case FileNameInfo: + NtFileInformationClass = FileNameInformation; + cbMinBufferSize = sizeof(FILE_NAME_INFO); + break; + case FileStreamInfo: + NtFileInformationClass = FileStreamInformation; + cbMinBufferSize = sizeof(FILE_STREAM_INFO); + break; + case FileCompressionInfo: + NtFileInformationClass = FileCompressionInformation; + cbMinBufferSize = sizeof(FILE_COMPRESSION_INFO); + break; + case FileAttributeTagInfo: + NtFileInformationClass = FileAttributeTagInformation; + cbMinBufferSize = sizeof(FILE_ATTRIBUTE_TAG_INFO); + break; + case FileIdBothDirectoryRestartInfo: + RestartScan = true; + case FileIdBothDirectoryInfo: + NtFileInformationClass = FileIdBothDirectoryInformation; + cbMinBufferSize = sizeof(FILE_ID_BOTH_DIR_INFO); + bNtQueryDirectoryFile = true; + break; + case FileRemoteProtocolInfo: + NtFileInformationClass = FileRemoteProtocolInformation; + cbMinBufferSize = sizeof(FILE_REMOTE_PROTOCOL_INFO); + break; + default: + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + break; + } + + + if (cbMinBufferSize > dwBufferSize) + { + SetLastError(ERROR_BAD_LENGTH); + return FALSE; + } + + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + if (bNtQueryDirectoryFile) + { + auto pNtQueryDirectoryFile = try_get_NtQueryDirectoryFile(); + if (!pNtQueryDirectoryFile) + { + SetLastError(ERROR_INVALID_FUNCTION); + return FALSE; + } - enum _FILE_ID_TYPE_win7 - { - FileIdType, - ObjectIdType, - MaximumFileIdType - }; - - struct FILE_ID_DESCRIPTOR_win7 - { - DWORD dwSize; // Size of the struct - FILE_ID_TYPE Type; // Describes the type of identifier passed in. - union { - LARGE_INTEGER FileId; - GUID ObjectId; - } DUMMYUNIONNAME; - }; + Status = pNtQueryDirectoryFile( + hFile, + nullptr, + nullptr, + nullptr, + &IoStatusBlock, + lpFileInformation, + dwBufferSize, + NtFileInformationClass, + false, + nullptr, + RestartScan + ); + + if (STATUS_PENDING == Status) + { + if (WaitForSingleObjectEx(hFile, 0, FALSE) == WAIT_FAILED) + { + //WaitForSingleObjectEx会设置LastError + return FALSE; + } -#endif + Status = IoStatusBlock.Status; + } + } + else + { + auto pNtQueryInformationFile = try_get_NtQueryInformationFile(); + + if (!pNtQueryInformationFile) + { + SetLastError(ERROR_INVALID_FUNCTION); + return FALSE; + } -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - kernel32, - 16, - _Success_(return) - BOOL, - WINAPI, - GetFileInformationByHandleEx, - _In_ HANDLE hFile, - _In_ FILE_INFO_BY_HANDLE_CLASS FileInformationClass, - _Out_writes_bytes_(dwBufferSize) LPVOID lpFileInformation, - _In_ DWORD dwBufferSize - ) - { - if (auto const pGetFileInformationByHandleEx = try_get_GetFileInformationByHandleEx()) - { - return pGetFileInformationByHandleEx(hFile, FileInformationClass, lpFileInformation, dwBufferSize); - } - - - FILE_INFORMATION_CLASS NtFileInformationClass; - DWORD cbMinBufferSize; - bool bNtQueryDirectoryFile = false; - BOOLEAN RestartScan = false; - - switch (FileInformationClass) - { - case FileBasicInfo: - NtFileInformationClass = FileBasicInformation; - cbMinBufferSize = sizeof(FILE_BASIC_INFO); - break; - case FileStandardInfo: - NtFileInformationClass = FileStandardInformation; - cbMinBufferSize = sizeof(FILE_STANDARD_INFO); - break; - case FileNameInfo: - NtFileInformationClass = FileNameInformation; - cbMinBufferSize = sizeof(FILE_NAME_INFO); - break; - case FileStreamInfo: - NtFileInformationClass = FileStreamInformation; - cbMinBufferSize = sizeof(FILE_STREAM_INFO); - break; - case FileCompressionInfo: - NtFileInformationClass = FileCompressionInformation; - cbMinBufferSize = sizeof(FILE_COMPRESSION_INFO); - break; - case FileAttributeTagInfo: - NtFileInformationClass = FileAttributeTagInformation; - cbMinBufferSize = sizeof(FILE_ATTRIBUTE_TAG_INFO); - break; - case FileIdBothDirectoryRestartInfo: - RestartScan = true; - case FileIdBothDirectoryInfo: - NtFileInformationClass = FileIdBothDirectoryInformation; - cbMinBufferSize = sizeof(FILE_ID_BOTH_DIR_INFO); - bNtQueryDirectoryFile = true; - break; - case FileRemoteProtocolInfo: - NtFileInformationClass = FileRemoteProtocolInformation; - cbMinBufferSize = sizeof(FILE_REMOTE_PROTOCOL_INFO); - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - break; - } - - - if (cbMinBufferSize > dwBufferSize) - { - SetLastError(ERROR_BAD_LENGTH); - return FALSE; - } - - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - - if (bNtQueryDirectoryFile) - { - auto pNtQueryDirectoryFile = try_get_NtQueryDirectoryFile(); - if (!pNtQueryDirectoryFile) - { - SetLastError(ERROR_INVALID_FUNCTION); - return FALSE; - } - - Status = pNtQueryDirectoryFile( - hFile, - nullptr, - nullptr, - nullptr, - &IoStatusBlock, - lpFileInformation, - dwBufferSize, - NtFileInformationClass, - false, - nullptr, - RestartScan - ); - - if (STATUS_PENDING == Status) - { - if (WaitForSingleObjectEx(hFile, 0, FALSE) == WAIT_FAILED) - { - //WaitForSingleObjectEx会设置LastError - return FALSE; - } - - Status = IoStatusBlock.Status; - } - } - else - { - auto pNtQueryInformationFile = try_get_NtQueryInformationFile(); - - if (!pNtQueryInformationFile) - { - SetLastError(ERROR_INVALID_FUNCTION); - return FALSE; - } - - Status = pNtQueryInformationFile(hFile, &IoStatusBlock, lpFileInformation, dwBufferSize, NtFileInformationClass); - } - - if (Status >= STATUS_SUCCESS) - { - if (FileStreamInfo == FileInformationClass && IoStatusBlock.Information == 0) - { - SetLastError(ERROR_HANDLE_EOF); - return FALSE; - } - else - { - return TRUE; - } - } - else - { - internal::BaseSetLastNTError(Status); - - return FALSE; - } - } + Status = pNtQueryInformationFile(hFile, &IoStatusBlock, lpFileInformation, dwBufferSize, NtFileInformationClass); + } + + if (Status >= STATUS_SUCCESS) + { + if (FileStreamInfo == FileInformationClass && IoStatusBlock.Information == 0) + { + SetLastError(ERROR_HANDLE_EOF); + return FALSE; + } + else + { + return TRUE; + } + } + else + { + internal::BaseSetLastNTError(Status); + + return FALSE; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - SetFileInformationByHandle, - _In_ HANDLE hFile, - _In_ FILE_INFO_BY_HANDLE_CLASS FileInformationClass, - _In_reads_bytes_(dwBufferSize) LPVOID lpFileInformation, - _In_ DWORD dwBufferSize - ) - { - if (auto pSetFileInformationByHandle = try_get_SetFileInformationByHandle()) - { - return pSetFileInformationByHandle(hFile, FileInformationClass, lpFileInformation, dwBufferSize); - } - - - auto pNtSetInformationFile = try_get_NtSetInformationFile(); - if (!pNtSetInformationFile) - { - SetLastError(ERROR_INVALID_FUNCTION); - return FALSE; - } - - const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; - FILE_INFORMATION_CLASS NtFileInformationClass; - DWORD cbMinBufferSize; - bool bFreeFileInformation = false; - - switch (FileInformationClass) - { - case FileBasicInfo: - NtFileInformationClass = FileBasicInformation; - cbMinBufferSize = sizeof(FILE_BASIC_INFO); - break; - case FileRenameInfo: - NtFileInformationClass = FileRenameInformation; - cbMinBufferSize = sizeof(FILE_RENAME_INFO); - - if (cbMinBufferSize > dwBufferSize) - { - SetLastError(ERROR_BAD_LENGTH); - return FALSE; - } - - if (lpFileInformation == nullptr) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - else - { - auto pRenameInfo = (FILE_RENAME_INFO*)lpFileInformation; - - if (pRenameInfo->FileNameLength < sizeof(wchar_t) || pRenameInfo->FileName[0] != L':') - { - auto pRtlDosPathNameToNtPathName_U = try_get_RtlDosPathNameToNtPathName_U(); - auto pRtlFreeUnicodeString = try_get_RtlFreeUnicodeString(); - - if (pRtlDosPathNameToNtPathName_U == nullptr || pRtlFreeUnicodeString ==nullptr) - { - SetLastError(ERROR_INVALID_FUNCTION); - return FALSE; - } - - UNICODE_STRING NtName = {}; - - - if (!pRtlDosPathNameToNtPathName_U(pRenameInfo->FileName, &NtName, nullptr, nullptr)) - { - SetLastError(ERROR_INVALID_PARAMETER); - - return FALSE; - } - - DWORD dwNewBufferSize = sizeof(FILE_RENAME_INFO) + NtName.Length; - - auto NewRenameInfo = (FILE_RENAME_INFO*)HeapAlloc(ProcessHeap, 0, dwNewBufferSize); - if (!NewRenameInfo) - { - auto lStatus = GetLastError(); - - pRtlFreeUnicodeString(&NtName); - - SetLastError(lStatus); - return FALSE; - } - - bFreeFileInformation = true; - - NewRenameInfo->ReplaceIfExists = pRenameInfo->ReplaceIfExists; - NewRenameInfo->RootDirectory = pRenameInfo->RootDirectory; - NewRenameInfo->FileNameLength = NtName.Length; - - memcpy(NewRenameInfo->FileName, NtName.Buffer, NtName.Length); - - *(wchar_t*)((byte*)NewRenameInfo->FileName + NtName.Length) = L'\0'; - - - lpFileInformation = NewRenameInfo; - dwBufferSize = dwNewBufferSize; - - pRtlFreeUnicodeString(&NtName); - } - } - break; - case FileDispositionInfo: - NtFileInformationClass = FileDispositionInformation; - cbMinBufferSize = sizeof(FILE_DISPOSITION_INFO); - break; - case FileAllocationInfo: - NtFileInformationClass = FileAllocationInformation; - cbMinBufferSize = sizeof(FILE_ALLOCATION_INFO); - break; - case FileEndOfFileInfo: - NtFileInformationClass = FileEndOfFileInformation; - cbMinBufferSize = sizeof(FILE_END_OF_FILE_INFO); - break; - case FileIoPriorityHintInfo: - NtFileInformationClass = FileIoPriorityHintInformation; - cbMinBufferSize = sizeof(FILE_IO_PRIORITY_HINT_INFO); - - //长度检查,微软原版似乎没有该安全检查 - if (cbMinBufferSize > dwBufferSize) - { - SetLastError(ERROR_BAD_LENGTH); - return FALSE; - } - - if (lpFileInformation == nullptr || ((FILE_IO_PRIORITY_HINT_INFO*)lpFileInformation)->PriorityHint >= MaximumIoPriorityHintType) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - break; - } - - if (cbMinBufferSize > dwBufferSize) - { - if (bFreeFileInformation) - { - HeapFree(ProcessHeap, 0, lpFileInformation); - } - - SetLastError(ERROR_BAD_LENGTH); - return FALSE; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + SetFileInformationByHandle, + _In_ HANDLE hFile, + _In_ FILE_INFO_BY_HANDLE_CLASS FileInformationClass, + _In_reads_bytes_(dwBufferSize) LPVOID lpFileInformation, + _In_ DWORD dwBufferSize + ) + { + if (auto pSetFileInformationByHandle = try_get_SetFileInformationByHandle()) + { + return pSetFileInformationByHandle(hFile, FileInformationClass, lpFileInformation, dwBufferSize); + } + + + auto pNtSetInformationFile = try_get_NtSetInformationFile(); + if (!pNtSetInformationFile) + { + SetLastError(ERROR_INVALID_FUNCTION); + return FALSE; + } + + const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; + FILE_INFORMATION_CLASS NtFileInformationClass; + DWORD cbMinBufferSize; + bool bFreeFileInformation = false; + + switch (FileInformationClass) + { + case FileBasicInfo: + NtFileInformationClass = FileBasicInformation; + cbMinBufferSize = sizeof(FILE_BASIC_INFO); + break; + case FileRenameInfo: + NtFileInformationClass = FileRenameInformation; + cbMinBufferSize = sizeof(FILE_RENAME_INFO); + + if (cbMinBufferSize > dwBufferSize) + { + SetLastError(ERROR_BAD_LENGTH); + return FALSE; + } + + if (lpFileInformation == nullptr) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + else + { + auto pRenameInfo = (FILE_RENAME_INFO*)lpFileInformation; + + if (pRenameInfo->FileNameLength < sizeof(wchar_t) || pRenameInfo->FileName[0] != L':') + { + auto pRtlDosPathNameToNtPathName_U = try_get_RtlDosPathNameToNtPathName_U(); + auto pRtlFreeUnicodeString = try_get_RtlFreeUnicodeString(); + + if (pRtlDosPathNameToNtPathName_U == nullptr || pRtlFreeUnicodeString ==nullptr) + { + SetLastError(ERROR_INVALID_FUNCTION); + return FALSE; + } - IO_STATUS_BLOCK IoStatusBlock; - - auto Status = pNtSetInformationFile(hFile, &IoStatusBlock, lpFileInformation, dwBufferSize, NtFileInformationClass); + UNICODE_STRING NtName = {}; - if (bFreeFileInformation) - { - HeapFree(ProcessHeap, 0, lpFileInformation); - } - if (Status >= STATUS_SUCCESS) - return TRUE; + if (!pRtlDosPathNameToNtPathName_U(pRenameInfo->FileName, &NtName, nullptr, nullptr)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } - - internal::BaseSetLastNTError(Status); - - return FALSE; - } + DWORD dwNewBufferSize = sizeof(FILE_RENAME_INFO) + NtName.Length; + + auto NewRenameInfo = (FILE_RENAME_INFO*)HeapAlloc(ProcessHeap, 0, dwNewBufferSize); + if (!NewRenameInfo) + { + auto lStatus = GetLastError(); + + pRtlFreeUnicodeString(&NtName); + + SetLastError(lStatus); + return FALSE; + } + + bFreeFileInformation = true; + + NewRenameInfo->ReplaceIfExists = pRenameInfo->ReplaceIfExists; + NewRenameInfo->RootDirectory = pRenameInfo->RootDirectory; + NewRenameInfo->FileNameLength = NtName.Length; + + memcpy(NewRenameInfo->FileName, NtName.Buffer, NtName.Length); + + *(wchar_t*)((byte*)NewRenameInfo->FileName + NtName.Length) = L'\0'; + + + lpFileInformation = NewRenameInfo; + dwBufferSize = dwNewBufferSize; + + pRtlFreeUnicodeString(&NtName); + } + } + break; + case FileDispositionInfo: + NtFileInformationClass = FileDispositionInformation; + cbMinBufferSize = sizeof(FILE_DISPOSITION_INFO); + break; + case FileAllocationInfo: + NtFileInformationClass = FileAllocationInformation; + cbMinBufferSize = sizeof(FILE_ALLOCATION_INFO); + break; + case FileEndOfFileInfo: + NtFileInformationClass = FileEndOfFileInformation; + cbMinBufferSize = sizeof(FILE_END_OF_FILE_INFO); + break; + case FileIoPriorityHintInfo: + NtFileInformationClass = FileIoPriorityHintInformation; + cbMinBufferSize = sizeof(FILE_IO_PRIORITY_HINT_INFO); + + //长度检查,微软原版似乎没有该安全检查 + if (cbMinBufferSize > dwBufferSize) + { + SetLastError(ERROR_BAD_LENGTH); + return FALSE; + } + + if (lpFileInformation == nullptr || ((FILE_IO_PRIORITY_HINT_INFO*)lpFileInformation)->PriorityHint >= MaximumIoPriorityHintType) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + break; + default: + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + break; + } + + if (cbMinBufferSize > dwBufferSize) + { + if (bFreeFileInformation) + { + HeapFree(ProcessHeap, 0, lpFileInformation); + } + + SetLastError(ERROR_BAD_LENGTH); + return FALSE; + } + + IO_STATUS_BLOCK IoStatusBlock; + + auto Status = pNtSetInformationFile(hFile, &IoStatusBlock, lpFileInformation, dwBufferSize, NtFileInformationClass); + + if (bFreeFileInformation) + { + HeapFree(ProcessHeap, 0, lpFileInformation); + } + + if (Status >= STATUS_SUCCESS) + return TRUE; + + + + internal::BaseSetLastNTError(Status); + + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - kernel32, - 16, - DWORD, - WINAPI, - GetFinalPathNameByHandleW, - _In_ HANDLE hFile, - _Out_writes_(cchFilePath) LPWSTR lpszFilePath, - _In_ DWORD cchFilePath, - _In_ DWORD dwFlags - ) - { - if (auto pGetFinalPathNameByHandleW = try_get_GetFinalPathNameByHandleW()) - { - return pGetFinalPathNameByHandleW(hFile, lpszFilePath, cchFilePath, dwFlags); - } - - //参数检查 - if (INVALID_HANDLE_VALUE == hFile) - { - SetLastError(ERROR_INVALID_HANDLE); - return 0; - } - - - switch (dwFlags & (VOLUME_NAME_DOS | VOLUME_NAME_GUID | VOLUME_NAME_NONE | VOLUME_NAME_NT)) - { - case VOLUME_NAME_DOS: - break; - case VOLUME_NAME_GUID: - break; - case VOLUME_NAME_NT: - break; - case VOLUME_NAME_NONE: - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - break; - } - - - auto pNtQueryObject = try_get_NtQueryObject(); - auto pNtQueryInformationFile = try_get_NtQueryInformationFile(); - - if (nullptr == pNtQueryObject - || nullptr == pNtQueryInformationFile) - { - SetLastError(ERROR_INVALID_FUNCTION); - return 0; - } - - UNICODE_STRING VolumeNtName = {}; - - wchar_t szVolumeRoot[MAX_PATH]; - szVolumeRoot[0] = L'\0'; - - wchar_t* szLongPathNameBuffer = nullptr; - - //目标所需的分区名称,不包含最后的 '\\' - UNICODE_STRING TargetVolumeName = {}; - //目标所需的文件名,开始包含 '\\' - UNICODE_STRING TargetFileName = {}; - - const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; - LSTATUS lStatus = ERROR_SUCCESS; - DWORD cchReturn = 0; - - OBJECT_NAME_INFORMATION* pObjectName = nullptr; - ULONG cbObjectName = 528; - - FILE_NAME_INFORMATION* pFileNameInfo = nullptr; - ULONG cbFileNameInfo = 528; - - for (;;) - { - if (pObjectName) - { - auto pNewBuffer = (OBJECT_NAME_INFORMATION*)HeapReAlloc(ProcessHeap, 0, pObjectName, cbObjectName); - - if (!pNewBuffer) - { - lStatus = ERROR_NOT_ENOUGH_MEMORY; - goto __Exit; - } - - pObjectName = pNewBuffer; - } - else - { - pObjectName = (OBJECT_NAME_INFORMATION*)HeapAlloc(ProcessHeap, 0, cbObjectName); - - if (!pObjectName) - { - //内存不足? - lStatus = ERROR_NOT_ENOUGH_MEMORY; - goto __Exit; - } - } - - auto Status = pNtQueryObject(hFile, ObjectNameInformation, pObjectName, cbObjectName, &cbObjectName); - - if (STATUS_BUFFER_OVERFLOW == Status) - { - continue; - } - else if (Status < 0) - { - lStatus = internal::NtStatusToDosError(Status); - - goto __Exit; - } - else - { - break; - } - } - - for (;;) - { - if (pFileNameInfo) - { - auto pNewBuffer = (FILE_NAME_INFORMATION*)HeapReAlloc(ProcessHeap, 0, pFileNameInfo, cbFileNameInfo); - if (!pNewBuffer) - { - lStatus = ERROR_NOT_ENOUGH_MEMORY; - goto __Exit; - } - - pFileNameInfo = pNewBuffer; - } - else - { - pFileNameInfo = (FILE_NAME_INFORMATION*)HeapAlloc(ProcessHeap, 0, cbFileNameInfo); - - if (!pFileNameInfo) - { - //内存不足? - lStatus = ERROR_NOT_ENOUGH_MEMORY; - goto __Exit; - } - } - - IO_STATUS_BLOCK IoStatusBlock; - - auto Status = pNtQueryInformationFile(hFile, &IoStatusBlock, pFileNameInfo, cbFileNameInfo, FileNameInformation); - - if (STATUS_BUFFER_OVERFLOW == Status) - { - cbFileNameInfo = pFileNameInfo->FileNameLength + sizeof(FILE_NAME_INFORMATION); - continue; - } - else if (Status < 0) - { - lStatus = internal::NtStatusToDosError(Status); - - goto __Exit; - } - else - { - break; - } - } - - if (pFileNameInfo->FileName[0] != '\\') - { - lStatus = ERROR_ACCESS_DENIED; - goto __Exit; - } - - - - if (pFileNameInfo->FileNameLength >= pObjectName->Name.Length) - { - lStatus = ERROR_BAD_PATHNAME; - goto __Exit; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + kernel32, + 16, + DWORD, + WINAPI, + GetFinalPathNameByHandleW, + _In_ HANDLE hFile, + _Out_writes_(cchFilePath) LPWSTR lpszFilePath, + _In_ DWORD cchFilePath, + _In_ DWORD dwFlags + ) + { + if (auto pGetFinalPathNameByHandleW = try_get_GetFinalPathNameByHandleW()) + { + return pGetFinalPathNameByHandleW(hFile, lpszFilePath, cchFilePath, dwFlags); + } + + //参数检查 + if (INVALID_HANDLE_VALUE == hFile) + { + SetLastError(ERROR_INVALID_HANDLE); + return 0; + } + + + switch (dwFlags & (VOLUME_NAME_DOS | VOLUME_NAME_GUID | VOLUME_NAME_NONE | VOLUME_NAME_NT)) + { + case VOLUME_NAME_DOS: + break; + case VOLUME_NAME_GUID: + break; + case VOLUME_NAME_NT: + break; + case VOLUME_NAME_NONE: + break; + default: + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + break; + } + + + auto pNtQueryObject = try_get_NtQueryObject(); + auto pNtQueryInformationFile = try_get_NtQueryInformationFile(); + + if (nullptr == pNtQueryObject + || nullptr == pNtQueryInformationFile) + { + SetLastError(ERROR_INVALID_FUNCTION); + return 0; + } + + UNICODE_STRING VolumeNtName = {}; + + wchar_t szVolumeRoot[MAX_PATH]; + szVolumeRoot[0] = L'\0'; + + wchar_t* szLongPathNameBuffer = nullptr; + + //目标所需的分区名称,不包含最后的 '\\' + UNICODE_STRING TargetVolumeName = {}; + //目标所需的文件名,开始包含 '\\' + UNICODE_STRING TargetFileName = {}; + + const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; + LSTATUS lStatus = ERROR_SUCCESS; + DWORD cchReturn = 0; + + OBJECT_NAME_INFORMATION* pObjectName = nullptr; + ULONG cbObjectName = 528; + + FILE_NAME_INFORMATION* pFileNameInfo = nullptr; + ULONG cbFileNameInfo = 528; + + for (;;) + { + if (pObjectName) + { + auto pNewBuffer = (OBJECT_NAME_INFORMATION*)HeapReAlloc(ProcessHeap, 0, pObjectName, cbObjectName); + + if (!pNewBuffer) + { + lStatus = ERROR_NOT_ENOUGH_MEMORY; + goto __Exit; + } + pObjectName = pNewBuffer; + } + else { - const auto _uNewLength = pObjectName->Name.Length - pFileNameInfo->FileNameLength + sizeof(wchar_t); - if (_uNewLength > MAXUINT16) + pObjectName = (OBJECT_NAME_INFORMATION*)HeapAlloc(ProcessHeap, 0, cbObjectName); + + if (!pObjectName) { - lStatus = ERROR_BAD_PATHNAME; + //内存不足? + lStatus = ERROR_NOT_ENOUGH_MEMORY; goto __Exit; } - VolumeNtName.Buffer = pObjectName->Name.Buffer; - VolumeNtName.Length = VolumeNtName.MaximumLength = static_cast(_uNewLength); } + auto Status = pNtQueryObject(hFile, ObjectNameInformation, pObjectName, cbObjectName, &cbObjectName); - if (VOLUME_NAME_NT & dwFlags) - { - //返回NT路径 - TargetVolumeName.Buffer = VolumeNtName.Buffer; - TargetVolumeName.Length = TargetVolumeName.MaximumLength = VolumeNtName.Length - sizeof(wchar_t); - } - else if (VOLUME_NAME_NONE & dwFlags) - { - //仅返回文件名 - } - else - { - if (VOLUME_NAME_GUID & dwFlags) - { - //返回分区GUID名称 - if (!internal::BasepGetVolumeGUIDFromNTName(&VolumeNtName, szVolumeRoot)) - { - lStatus = GetLastError(); - goto __Exit; - } - } - else - { - //返回Dos路径 - if (!internal::BasepGetVolumeDosLetterNameFromNTName(&VolumeNtName, szVolumeRoot)) - { - lStatus = GetLastError(); - goto __Exit; - } - } - - const auto _uNewLength = (wcslen(szVolumeRoot) - 1) * sizeof(szVolumeRoot[0]); - if (_uNewLength > MAXUINT16) + if (STATUS_BUFFER_OVERFLOW == Status) + { + continue; + } + else if (Status < 0) + { + lStatus = internal::NtStatusToDosError(Status); + + goto __Exit; + } + else + { + break; + } + } + + for (;;) + { + if (pFileNameInfo) + { + auto pNewBuffer = (FILE_NAME_INFORMATION*)HeapReAlloc(ProcessHeap, 0, pFileNameInfo, cbFileNameInfo); + if (!pNewBuffer) { - lStatus = ERROR_BAD_PATHNAME; + lStatus = ERROR_NOT_ENOUGH_MEMORY; goto __Exit; } - TargetVolumeName.Buffer = szVolumeRoot; - TargetVolumeName.Length = TargetVolumeName.MaximumLength = static_cast(_uNewLength); - } - //将路径进行规范化 - if ((FILE_NAME_OPENED & dwFlags) == 0) - { - //由于 Windows XP不支持 FileNormalizedNameInformation,所以我们直接调用 GetLongPathNameW 获取完整路径。 + pFileNameInfo = pNewBuffer; + } + else + { + pFileNameInfo = (FILE_NAME_INFORMATION*)HeapAlloc(ProcessHeap, 0, cbFileNameInfo); + + if (!pFileNameInfo) + { + //内存不足? + lStatus = ERROR_NOT_ENOUGH_MEMORY; + goto __Exit; + } + } + + IO_STATUS_BLOCK IoStatusBlock; - DWORD cbszVolumeRoot = TargetVolumeName.Length; + auto Status = pNtQueryInformationFile(hFile, &IoStatusBlock, pFileNameInfo, cbFileNameInfo, FileNameInformation); + + if (STATUS_BUFFER_OVERFLOW == Status) + { + cbFileNameInfo = pFileNameInfo->FileNameLength + sizeof(FILE_NAME_INFORMATION); + continue; + } + else if (Status < 0) + { + lStatus = internal::NtStatusToDosError(Status); + + goto __Exit; + } + else + { + break; + } + } - if (szVolumeRoot[0] == L'\0') - { - //转换分区信息 + if (pFileNameInfo->FileName[0] != '\\') + { + lStatus = ERROR_ACCESS_DENIED; + goto __Exit; + } - if (!internal::BasepGetVolumeDosLetterNameFromNTName(&VolumeNtName, szVolumeRoot)) - { - lStatus = GetLastError(); - if(lStatus == ERROR_NOT_ENOUGH_MEMORY) - goto __Exit; - if (!internal::BasepGetVolumeGUIDFromNTName(&VolumeNtName, szVolumeRoot)) - { - lStatus = GetLastError(); - goto __Exit; - } - } + if (pFileNameInfo->FileNameLength >= pObjectName->Name.Length) + { + lStatus = ERROR_BAD_PATHNAME; + goto __Exit; + } - const auto _cbData = (wcslen(szVolumeRoot) - 1) * sizeof(szVolumeRoot[0]); - if (_cbData > MAXUINT16) + { + const auto _uNewLength = pObjectName->Name.Length - pFileNameInfo->FileNameLength + sizeof(wchar_t); + if (_uNewLength > MAXUINT16) + { + lStatus = ERROR_BAD_PATHNAME; + goto __Exit; + } + VolumeNtName.Buffer = pObjectName->Name.Buffer; + VolumeNtName.Length = VolumeNtName.MaximumLength = static_cast(_uNewLength); + } + + + if (VOLUME_NAME_NT & dwFlags) + { + //返回NT路径 + TargetVolumeName.Buffer = VolumeNtName.Buffer; + TargetVolumeName.Length = TargetVolumeName.MaximumLength = VolumeNtName.Length - sizeof(wchar_t); + } + else if (VOLUME_NAME_NONE & dwFlags) + { + //仅返回文件名 + } + else + { + if (VOLUME_NAME_GUID & dwFlags) + { + //返回分区GUID名称 + if (!internal::BasepGetVolumeGUIDFromNTName(&VolumeNtName, szVolumeRoot)) + { + lStatus = GetLastError(); + goto __Exit; + } + } + else + { + //返回Dos路径 + if (!internal::BasepGetVolumeDosLetterNameFromNTName(&VolumeNtName, szVolumeRoot)) + { + lStatus = GetLastError(); + goto __Exit; + } + } + + const auto _uNewLength = (wcslen(szVolumeRoot) - 1) * sizeof(szVolumeRoot[0]); + if (_uNewLength > MAXUINT16) + { + lStatus = ERROR_BAD_PATHNAME; + goto __Exit; + } + TargetVolumeName.Buffer = szVolumeRoot; + TargetVolumeName.Length = TargetVolumeName.MaximumLength = static_cast(_uNewLength); + } + + //将路径进行规范化 + if ((FILE_NAME_OPENED & dwFlags) == 0) + { + //由于 Windows XP不支持 FileNormalizedNameInformation,所以我们直接调用 GetLongPathNameW 获取完整路径。 + + DWORD cbszVolumeRoot = TargetVolumeName.Length; + + if (szVolumeRoot[0] == L'\0') + { + //转换分区信息 + + if (!internal::BasepGetVolumeDosLetterNameFromNTName(&VolumeNtName, szVolumeRoot)) + { + lStatus = GetLastError(); + + if(lStatus == ERROR_NOT_ENOUGH_MEMORY) + goto __Exit; + + if (!internal::BasepGetVolumeGUIDFromNTName(&VolumeNtName, szVolumeRoot)) { - lStatus = ERROR_BAD_PATHNAME; + lStatus = GetLastError(); goto __Exit; } + } - cbszVolumeRoot = static_cast(_cbData); - } - - - - auto cbLongPathNameBufferSize = cbszVolumeRoot + pFileNameInfo->FileNameLength + 1024; - - szLongPathNameBuffer = (wchar_t*)HeapAlloc(ProcessHeap, 0, cbLongPathNameBufferSize); - if (!szLongPathNameBuffer) - { - lStatus = ERROR_NOT_ENOUGH_MEMORY; - goto __Exit; - } - - DWORD cchLongPathNameBufferSize = cbLongPathNameBufferSize / sizeof(szLongPathNameBuffer[0]); - - memcpy(szLongPathNameBuffer, szVolumeRoot, cbszVolumeRoot); - memcpy((char*)szLongPathNameBuffer + cbszVolumeRoot, pFileNameInfo->FileName, pFileNameInfo->FileNameLength); - szLongPathNameBuffer[(cbszVolumeRoot + pFileNameInfo->FileNameLength) / sizeof(wchar_t)] = L'\0'; - - for (;;) - { - auto result = GetLongPathNameW(szLongPathNameBuffer, szLongPathNameBuffer, cchLongPathNameBufferSize); - - if (result == 0) - { - //失败 - lStatus = GetLastError(); - goto __Exit; - } - else if (result >= cchLongPathNameBufferSize) - { - cchLongPathNameBufferSize = result + 1; - - auto pNewLongPathName = (wchar_t*)HeapReAlloc(ProcessHeap, 0, szLongPathNameBuffer, cchLongPathNameBufferSize * sizeof(wchar_t)); - if (!pNewLongPathName) - { - lStatus = ERROR_NOT_ENOUGH_MEMORY; - goto __Exit; - } - - szLongPathNameBuffer = pNewLongPathName; - - } - else - { - const auto _uNewLength = result * sizeof(wchar_t) - cbszVolumeRoot; - if (_uNewLength > MAXUINT16) - { - lStatus = ERROR_BAD_PATHNAME; - goto __Exit; - } - - //转换成功 - TargetFileName.Buffer = (wchar_t*)((char*)szLongPathNameBuffer + cbszVolumeRoot); - TargetFileName.Length = TargetFileName.MaximumLength = static_cast(_uNewLength); - break; - } - } - } - else - { - if (pFileNameInfo->FileNameLength > MAXUINT16) + const auto _cbData = (wcslen(szVolumeRoot) - 1) * sizeof(szVolumeRoot[0]); + if (_cbData > MAXUINT16) { lStatus = ERROR_BAD_PATHNAME; goto __Exit; } - //直接返回原始路径 - TargetFileName.Buffer = pFileNameInfo->FileName; - TargetFileName.Length = TargetFileName.MaximumLength = static_cast(pFileNameInfo->FileNameLength); - } - - - //返回结果,根目录 + 文件名 的长度 - cchReturn = (TargetVolumeName.Length + TargetFileName.Length) / sizeof(wchar_t); - - if (cchFilePath <= cchReturn) - { - //长度不足…… - - cchReturn += 1; - } - else - { - //复制根目录 - memcpy(lpszFilePath, TargetVolumeName.Buffer, TargetVolumeName.Length); - //复制文件名 - memcpy((char*)lpszFilePath + TargetVolumeName.Length, TargetFileName.Buffer, TargetFileName.Length); - //保证字符串 '\0' 截断 - lpszFilePath[cchReturn] = L'\0'; - } - - __Exit: - if (pFileNameInfo) - HeapFree(ProcessHeap, 0, pFileNameInfo); - if (pObjectName) - HeapFree(ProcessHeap, 0, pObjectName); - if (szLongPathNameBuffer) - HeapFree(ProcessHeap, 0, szLongPathNameBuffer); - - if (lStatus != ERROR_SUCCESS) - { - SetLastError(lStatus); - return 0; - } - else - { - return cchReturn; - } - } -#endif + cbszVolumeRoot = static_cast(_cbData); + } + + + + auto cbLongPathNameBufferSize = cbszVolumeRoot + pFileNameInfo->FileNameLength + 1024; + + szLongPathNameBuffer = (wchar_t*)HeapAlloc(ProcessHeap, 0, cbLongPathNameBufferSize); + if (!szLongPathNameBuffer) + { + lStatus = ERROR_NOT_ENOUGH_MEMORY; + goto __Exit; + } + + DWORD cchLongPathNameBufferSize = cbLongPathNameBufferSize / sizeof(szLongPathNameBuffer[0]); + memcpy(szLongPathNameBuffer, szVolumeRoot, cbszVolumeRoot); + memcpy((char*)szLongPathNameBuffer + cbszVolumeRoot, pFileNameInfo->FileName, pFileNameInfo->FileNameLength); + szLongPathNameBuffer[(cbszVolumeRoot + pFileNameInfo->FileNameLength) / sizeof(wchar_t)] = L'\0'; + + for (;;) + { + auto result = GetLongPathNameW(szLongPathNameBuffer, szLongPathNameBuffer, cchLongPathNameBufferSize); -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - kernel32, - 16, - DWORD, - WINAPI, - GetFinalPathNameByHandleA, - _In_ HANDLE hFile, - _Out_writes_(cchFilePath) LPSTR lpszFilePath, - _In_ DWORD cchFilePath, - _In_ DWORD dwFlags - ) - { - if (auto pGetFinalPathNameByHandleA = try_get_GetFinalPathNameByHandleA()) - { - return pGetFinalPathNameByHandleA(hFile, lpszFilePath, cchFilePath, dwFlags); - } - - const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; - wchar_t* szFilePathUnicode = nullptr; - for (DWORD cchszFilePathUnicode = 1040;;) - { - if (szFilePathUnicode) - { - auto pNewBuffer = (wchar_t*)HeapReAlloc(ProcessHeap, 0, szFilePathUnicode, cchszFilePathUnicode * sizeof(wchar_t)); - if (!pNewBuffer) - { - HeapFree(ProcessHeap, 0, szFilePathUnicode); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - - szFilePathUnicode = pNewBuffer; - } - else - { - szFilePathUnicode = (wchar_t*)HeapAlloc(ProcessHeap, 0, cchszFilePathUnicode * sizeof(wchar_t)); - if (!szFilePathUnicode) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - } - - auto cchReturn = GetFinalPathNameByHandleW(hFile, szFilePathUnicode, cchszFilePathUnicode, dwFlags); - - if (cchReturn == 0) - { - __Error: - - auto lStatus = GetLastError(); - HeapFree(ProcessHeap, 0, szFilePathUnicode); - SetLastError(lStatus); - - return 0; - } - else if (cchReturn > cchszFilePathUnicode) - { - //缓冲区不足 - cchszFilePathUnicode = cchReturn; - continue; - } - else - { - //操作成功! - const UINT CodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; - - auto cchReturnANSI = WideCharToMultiByte(CodePage, WC_NO_BEST_FIT_CHARS, szFilePathUnicode, cchReturn, nullptr, 0, nullptr, nullptr); - - if (cchReturnANSI <= 0) - { - goto __Error; - } - else if (static_cast(cchReturnANSI) >= cchFilePath) - { - //长度不足 - ++cchReturnANSI; - } - else - { - WideCharToMultiByte(CodePage, WC_NO_BEST_FIT_CHARS, szFilePathUnicode, cchReturn, lpszFilePath, cchFilePath, nullptr, nullptr); - lpszFilePath[cchReturnANSI] = '\0'; - } - - HeapFree(ProcessHeap, 0, szFilePathUnicode); - return cchReturnANSI; - } - } - } + if (result == 0) + { + //失败 + lStatus = GetLastError(); + goto __Exit; + } + else if (result >= cchLongPathNameBufferSize) + { + cchLongPathNameBufferSize = result + 1; + + auto pNewLongPathName = (wchar_t*)HeapReAlloc(ProcessHeap, 0, szLongPathNameBuffer, cchLongPathNameBufferSize * sizeof(wchar_t)); + if (!pNewLongPathName) + { + lStatus = ERROR_NOT_ENOUGH_MEMORY; + goto __Exit; + } + + szLongPathNameBuffer = pNewLongPathName; + + } + else + { + const auto _uNewLength = result * sizeof(wchar_t) - cbszVolumeRoot; + if (_uNewLength > MAXUINT16) + { + lStatus = ERROR_BAD_PATHNAME; + goto __Exit; + } + + //转换成功 + TargetFileName.Buffer = (wchar_t*)((char*)szLongPathNameBuffer + cbszVolumeRoot); + TargetFileName.Length = TargetFileName.MaximumLength = static_cast(_uNewLength); + break; + } + } + } + else + { + if (pFileNameInfo->FileNameLength > MAXUINT16) + { + lStatus = ERROR_BAD_PATHNAME; + goto __Exit; + } + + //直接返回原始路径 + TargetFileName.Buffer = pFileNameInfo->FileName; + TargetFileName.Length = TargetFileName.MaximumLength = static_cast(pFileNameInfo->FileNameLength); + } + + + //返回结果,根目录 + 文件名 的长度 + cchReturn = (TargetVolumeName.Length + TargetFileName.Length) / sizeof(wchar_t); + + if (cchFilePath <= cchReturn) + { + //长度不足…… + + cchReturn += 1; + } + else + { + //复制根目录 + memcpy(lpszFilePath, TargetVolumeName.Buffer, TargetVolumeName.Length); + //复制文件名 + memcpy((char*)lpszFilePath + TargetVolumeName.Length, TargetFileName.Buffer, TargetFileName.Length); + //保证字符串 '\0' 截断 + lpszFilePath[cchReturn] = L'\0'; + } + + __Exit: + if (pFileNameInfo) + HeapFree(ProcessHeap, 0, pFileNameInfo); + if (pObjectName) + HeapFree(ProcessHeap, 0, pObjectName); + if (szLongPathNameBuffer) + HeapFree(ProcessHeap, 0, szLongPathNameBuffer); + + if (lStatus != ERROR_SUCCESS) + { + SetLastError(lStatus); + return 0; + } + else + { + return cchReturn; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Windows 8 [desktop apps | UWP apps] - //Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 20, - HANDLE, - WINAPI, - CreateFile2, - _In_ LPCWSTR lpFileName, - _In_ DWORD dwDesiredAccess, - _In_ DWORD dwShareMode, - _In_ DWORD dwCreationDisposition, - _In_opt_ LPCREATEFILE2_EXTENDED_PARAMETERS pCreateExParams - ) - { - if (auto pCreateFile2 = try_get_CreateFile2()) - { - return pCreateFile2(lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, pCreateExParams); - } - - DWORD dwFlagsAndAttributes = 0; - LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr; - HANDLE hTemplateFile = nullptr; - - if (pCreateExParams) - { - if (pCreateExParams->dwSize < sizeof(*pCreateExParams)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return INVALID_HANDLE_VALUE; - } - - dwFlagsAndAttributes = pCreateExParams->dwFileAttributes | pCreateExParams->dwFileFlags; - - if (pCreateExParams->dwSecurityQosFlags != 0) - dwFlagsAndAttributes |= SECURITY_SQOS_PRESENT | pCreateExParams->dwSecurityQosFlags; - - lpSecurityAttributes = pCreateExParams->lpSecurityAttributes; - hTemplateFile = pCreateExParams->hTemplateFile; - } - - return CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + kernel32, + 16, + DWORD, + WINAPI, + GetFinalPathNameByHandleA, + _In_ HANDLE hFile, + _Out_writes_(cchFilePath) LPSTR lpszFilePath, + _In_ DWORD cchFilePath, + _In_ DWORD dwFlags + ) + { + if (auto pGetFinalPathNameByHandleA = try_get_GetFinalPathNameByHandleA()) + { + return pGetFinalPathNameByHandleA(hFile, lpszFilePath, cchFilePath, dwFlags); + } + + const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; + wchar_t* szFilePathUnicode = nullptr; + for (DWORD cchszFilePathUnicode = 1040;;) + { + if (szFilePathUnicode) + { + auto pNewBuffer = (wchar_t*)HeapReAlloc(ProcessHeap, 0, szFilePathUnicode, cchszFilePathUnicode * sizeof(wchar_t)); + if (!pNewBuffer) + { + HeapFree(ProcessHeap, 0, szFilePathUnicode); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + szFilePathUnicode = pNewBuffer; + } + else + { + szFilePathUnicode = (wchar_t*)HeapAlloc(ProcessHeap, 0, cchszFilePathUnicode * sizeof(wchar_t)); + if (!szFilePathUnicode) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + } + + auto cchReturn = GetFinalPathNameByHandleW(hFile, szFilePathUnicode, cchszFilePathUnicode, dwFlags); + + if (cchReturn == 0) + { + __Error: + + auto lStatus = GetLastError(); + HeapFree(ProcessHeap, 0, szFilePathUnicode); + SetLastError(lStatus); + + return 0; + } + else if (cchReturn > cchszFilePathUnicode) + { + //缓冲区不足 + cchszFilePathUnicode = cchReturn; + continue; + } + else + { + //操作成功! + const UINT CodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + + auto cchReturnANSI = WideCharToMultiByte(CodePage, WC_NO_BEST_FIT_CHARS, szFilePathUnicode, cchReturn, nullptr, 0, nullptr, nullptr); + + if (cchReturnANSI <= 0) + { + goto __Error; + } + else if (static_cast(cchReturnANSI) >= cchFilePath) + { + //长度不足 + ++cchReturnANSI; + } + else + { + WideCharToMultiByte(CodePage, WC_NO_BEST_FIT_CHARS, szFilePathUnicode, cchReturn, lpszFilePath, cchFilePath, nullptr, nullptr); + lpszFilePath[cchReturnANSI] = '\0'; + } + + HeapFree(ProcessHeap, 0, szFilePathUnicode); + return cchReturnANSI; + } + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 24, - HANDLE, - WINAPI, - OpenFileById, - _In_ HANDLE hVolumeHint, - _In_ LPFILE_ID_DESCRIPTOR lpFileId, - _In_ DWORD dwDesiredAccess, - _In_ DWORD dwShareMode, - _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, - _In_ DWORD dwFlagsAndAttributes - ) - { - if (const auto pOpenFileById = try_get_OpenFileById()) - { - return pOpenFileById(hVolumeHint, lpFileId, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwFlagsAndAttributes); - } - - if (lpFileId == nullptr || lpFileId->dwSize < sizeof(FILE_ID_DESCRIPTOR_win7) || lpFileId->Type >= _FILE_ID_TYPE_win7::MaximumFileIdType) - { - SetLastError(ERROR_INVALID_PARAMETER); - return INVALID_HANDLE_VALUE; - } - - const auto pNtCreateFile = try_get_NtCreateFile(); - if (!pNtCreateFile) - { - SetLastError(ERROR_FUNCTION_FAILED); - return INVALID_HANDLE_VALUE; - } - - dwDesiredAccess |= SYNCHRONIZE | FILE_READ_ATTRIBUTES; - - UNICODE_STRING ObjectName; - - if (FileIdType == lpFileId->Type) - { - ObjectName.Buffer = (PWSTR)(&lpFileId->FileId); - ObjectName.Length = ObjectName.MaximumLength = sizeof(lpFileId->FileId); - } - else - { - ObjectName.Buffer = (PWSTR)(&lpFileId->ObjectId); - ObjectName.Length = ObjectName.MaximumLength = sizeof(lpFileId->ObjectId); - } - - OBJECT_ATTRIBUTES ObjectAttributes = {sizeof(ObjectAttributes), hVolumeHint, &ObjectName, OBJ_CASE_INSENSITIVE }; - - ULONG CreateOptions = FILE_OPEN_BY_FILE_ID; - - if (FILE_FLAG_WRITE_THROUGH & dwFlagsAndAttributes) - { - CreateOptions |= FILE_WRITE_THROUGH; - } - - if (FILE_FLAG_NO_BUFFERING & dwFlagsAndAttributes) - { - CreateOptions |= FILE_NO_INTERMEDIATE_BUFFERING; - } - - if (FILE_FLAG_SEQUENTIAL_SCAN & dwFlagsAndAttributes) - { - CreateOptions |= FILE_SEQUENTIAL_ONLY; - } - - if (FILE_FLAG_RANDOM_ACCESS & dwFlagsAndAttributes) - { - CreateOptions |= FILE_RANDOM_ACCESS; - } - - if (FILE_FLAG_BACKUP_SEMANTICS & dwFlagsAndAttributes) - { - CreateOptions |= FILE_OPEN_FOR_BACKUP_INTENT; - } - - if ((FILE_FLAG_OVERLAPPED & dwFlagsAndAttributes) == 0) - { - CreateOptions |= FILE_SYNCHRONOUS_IO_NONALERT; - } - - if (FILE_FLAG_DELETE_ON_CLOSE & dwFlagsAndAttributes) - { - CreateOptions |= FILE_DELETE_ON_CLOSE; - dwDesiredAccess |= DELETE; - } - - if (FILE_FLAG_OPEN_REPARSE_POINT & dwFlagsAndAttributes) - { - CreateOptions |= FILE_OPEN_REPARSE_POINT; - } - - if (FILE_FLAG_OPEN_NO_RECALL & dwFlagsAndAttributes) - { - CreateOptions |= FILE_OPEN_NO_RECALL; - } - - HANDLE hFile; - - IO_STATUS_BLOCK IoStatusBlock; - - auto Status = pNtCreateFile(&hFile, dwDesiredAccess, &ObjectAttributes, &IoStatusBlock, nullptr, 0, dwShareMode, FILE_OPEN, CreateOptions, nullptr, 0); - - if (Status < 0) - { - hFile = INVALID_HANDLE_VALUE; - internal::BaseSetLastNTError(Status); - } - - return hFile; - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Windows 8 [desktop apps | UWP apps] + //Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 20, + HANDLE, + WINAPI, + CreateFile2, + _In_ LPCWSTR lpFileName, + _In_ DWORD dwDesiredAccess, + _In_ DWORD dwShareMode, + _In_ DWORD dwCreationDisposition, + _In_opt_ LPCREATEFILE2_EXTENDED_PARAMETERS pCreateExParams + ) + { + if (auto pCreateFile2 = try_get_CreateFile2()) + { + return pCreateFile2(lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, pCreateExParams); + } + + DWORD dwFlagsAndAttributes = 0; + LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr; + HANDLE hTemplateFile = nullptr; + + if (pCreateExParams) + { + if (pCreateExParams->dwSize < sizeof(*pCreateExParams)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; + } + + dwFlagsAndAttributes = pCreateExParams->dwFileAttributes | pCreateExParams->dwFileFlags; + + if (pCreateExParams->dwSecurityQosFlags != 0) + dwFlagsAndAttributes |= SECURITY_SQOS_PRESENT | pCreateExParams->dwSecurityQosFlags; + + lpSecurityAttributes = pCreateExParams->lpSecurityAttributes; + hTemplateFile = pCreateExParams->hTemplateFile; + } + + return CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008[desktop apps only] - __DEFINE_THUNK( - kernel32, - 12, - BOOLEAN, - APIENTRY, - CreateSymbolicLinkW, - _In_ LPCWSTR lpSymlinkFileName, - _In_ LPCWSTR lpTargetFileName, - _In_ DWORD dwFlags - ) - { - if (const auto pCreateSymbolicLinkW = try_get_CreateSymbolicLinkW()) - { - return pCreateSymbolicLinkW(lpSymlinkFileName, lpTargetFileName, dwFlags); - } - - SetLastError(ERROR_INVALID_FUNCTION); - - return FALSE; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 24, + HANDLE, + WINAPI, + OpenFileById, + _In_ HANDLE hVolumeHint, + _In_ LPFILE_ID_DESCRIPTOR lpFileId, + _In_ DWORD dwDesiredAccess, + _In_ DWORD dwShareMode, + _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, + _In_ DWORD dwFlagsAndAttributes + ) + { + if (const auto pOpenFileById = try_get_OpenFileById()) + { + return pOpenFileById(hVolumeHint, lpFileId, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwFlagsAndAttributes); + } + + if (lpFileId == nullptr || lpFileId->dwSize < sizeof(FILE_ID_DESCRIPTOR_win7) || lpFileId->Type >= _FILE_ID_TYPE_win7::MaximumFileIdType) + { + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; + } + + const auto pNtCreateFile = try_get_NtCreateFile(); + if (!pNtCreateFile) + { + SetLastError(ERROR_FUNCTION_FAILED); + return INVALID_HANDLE_VALUE; + } + + dwDesiredAccess |= SYNCHRONIZE | FILE_READ_ATTRIBUTES; + + UNICODE_STRING ObjectName; + + if (FileIdType == lpFileId->Type) + { + ObjectName.Buffer = (PWSTR)(&lpFileId->FileId); + ObjectName.Length = ObjectName.MaximumLength = sizeof(lpFileId->FileId); + } + else + { + ObjectName.Buffer = (PWSTR)(&lpFileId->ObjectId); + ObjectName.Length = ObjectName.MaximumLength = sizeof(lpFileId->ObjectId); + } + + OBJECT_ATTRIBUTES ObjectAttributes = {sizeof(ObjectAttributes), hVolumeHint, &ObjectName, OBJ_CASE_INSENSITIVE }; + + ULONG CreateOptions = FILE_OPEN_BY_FILE_ID; + + if (FILE_FLAG_WRITE_THROUGH & dwFlagsAndAttributes) + { + CreateOptions |= FILE_WRITE_THROUGH; + } + + if (FILE_FLAG_NO_BUFFERING & dwFlagsAndAttributes) + { + CreateOptions |= FILE_NO_INTERMEDIATE_BUFFERING; + } + + if (FILE_FLAG_SEQUENTIAL_SCAN & dwFlagsAndAttributes) + { + CreateOptions |= FILE_SEQUENTIAL_ONLY; + } + + if (FILE_FLAG_RANDOM_ACCESS & dwFlagsAndAttributes) + { + CreateOptions |= FILE_RANDOM_ACCESS; + } + + if (FILE_FLAG_BACKUP_SEMANTICS & dwFlagsAndAttributes) + { + CreateOptions |= FILE_OPEN_FOR_BACKUP_INTENT; + } + + if ((FILE_FLAG_OVERLAPPED & dwFlagsAndAttributes) == 0) + { + CreateOptions |= FILE_SYNCHRONOUS_IO_NONALERT; + } + + if (FILE_FLAG_DELETE_ON_CLOSE & dwFlagsAndAttributes) + { + CreateOptions |= FILE_DELETE_ON_CLOSE; + dwDesiredAccess |= DELETE; + } + + if (FILE_FLAG_OPEN_REPARSE_POINT & dwFlagsAndAttributes) + { + CreateOptions |= FILE_OPEN_REPARSE_POINT; + } + + if (FILE_FLAG_OPEN_NO_RECALL & dwFlagsAndAttributes) + { + CreateOptions |= FILE_OPEN_NO_RECALL; + } + + HANDLE hFile; + + IO_STATUS_BLOCK IoStatusBlock; + + auto Status = pNtCreateFile(&hFile, dwDesiredAccess, &ObjectAttributes, &IoStatusBlock, nullptr, 0, dwShareMode, FILE_OPEN, CreateOptions, nullptr, 0); + + if (Status < 0) + { + hFile = INVALID_HANDLE_VALUE; + internal::BaseSetLastNTError(Status); + } + + return hFile; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008[desktop apps only] - __DEFINE_THUNK( - kernel32, - 12, - BOOLEAN, - APIENTRY, - CreateSymbolicLinkA, - _In_ LPCSTR lpSymlinkFileName, - _In_ LPCSTR lpTargetFileName, - _In_ DWORD dwFlags - ) - { - if (const auto pCreateSymbolicLinkA = try_get_CreateSymbolicLinkA()) - { - return pCreateSymbolicLinkA(lpSymlinkFileName, lpTargetFileName, dwFlags); - } - - SetLastError(ERROR_INVALID_FUNCTION); - - return FALSE; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008[desktop apps only] + __DEFINE_THUNK( + kernel32, + 12, + BOOLEAN, + APIENTRY, + CreateSymbolicLinkW, + _In_ LPCWSTR lpSymlinkFileName, + _In_ LPCWSTR lpTargetFileName, + _In_ DWORD dwFlags + ) + { + if (const auto pCreateSymbolicLinkW = try_get_CreateSymbolicLinkW()) + { + return pCreateSymbolicLinkW(lpSymlinkFileName, lpTargetFileName, dwFlags); + } + + SetLastError(ERROR_INVALID_FUNCTION); + + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03) - - //Windows Vista [desktop apps only] - //Windows Server 2003 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 16, - HANDLE, - WINAPI, - ReOpenFile, - _In_ HANDLE hOriginalFile, - _In_ DWORD dwDesiredAccess, - _In_ DWORD dwShareMode, - _In_ DWORD dwFlagsAndAttributes - ) - { - if (const auto pReOpenFile = try_get_ReOpenFile()) - { - return pReOpenFile(hOriginalFile, dwDesiredAccess, dwShareMode, dwFlagsAndAttributes); - } - - NTSTATUS Status; - - do - { - const auto pNtCreateFile = try_get_NtCreateFile(); - if (!pNtCreateFile) - { - Status = STATUS_INVALID_INFO_CLASS; - break; - } - - - if ((size_t(hOriginalFile) & 0x10000003) == 3) - { - Status = STATUS_INVALID_HANDLE; - break; - } - - if (dwFlagsAndAttributes & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_SPARSE_FILE | FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_ENCRYPTED)) - { - Status = STATUS_INVALID_PARAMETER; - break; - } - - ULONG CreateOptions = FILE_NON_DIRECTORY_FILE; - - if (FILE_FLAG_WRITE_THROUGH & dwFlagsAndAttributes) - { - CreateOptions |= FILE_WRITE_THROUGH; - } - - if (FILE_FLAG_NO_BUFFERING & dwFlagsAndAttributes) - { - CreateOptions |= FILE_NO_INTERMEDIATE_BUFFERING; - } - - if (FILE_FLAG_SEQUENTIAL_SCAN & dwFlagsAndAttributes) - { - CreateOptions |= FILE_SEQUENTIAL_ONLY; - } - - if (FILE_FLAG_RANDOM_ACCESS & dwFlagsAndAttributes) - { - CreateOptions |= FILE_RANDOM_ACCESS; - } - - if (FILE_FLAG_BACKUP_SEMANTICS & dwFlagsAndAttributes) - { - CreateOptions |= FILE_OPEN_FOR_BACKUP_INTENT; - } - - if ((FILE_FLAG_OVERLAPPED & dwFlagsAndAttributes) == 0) - { - CreateOptions |= FILE_SYNCHRONOUS_IO_NONALERT; - } - - if (FILE_FLAG_OPEN_NO_RECALL & dwFlagsAndAttributes) - { - CreateOptions |= FILE_OPEN_NO_RECALL; - } - - if (FILE_FLAG_OPEN_REPARSE_POINT & dwFlagsAndAttributes) - { - CreateOptions |= FILE_OPEN_REPARSE_POINT; - } - - if (FILE_FLAG_DELETE_ON_CLOSE & dwFlagsAndAttributes) - { - CreateOptions |= FILE_DELETE_ON_CLOSE; - dwDesiredAccess |= DELETE; - } - - dwDesiredAccess |= SYNCHRONIZE | FILE_READ_ATTRIBUTES; - - UNICODE_STRING ObjectName = { 0, 2, (PWSTR)L"" }; - SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService; - - SecurityQualityOfService.Length = sizeof(SecurityQualityOfService); - - if (FILE_FLAG_OPEN_NO_RECALL & dwFlagsAndAttributes) - { - SecurityQualityOfService.ImpersonationLevel = SECURITY_IMPERSONATION_LEVEL((dwFlagsAndAttributes >> 16) & 0x3); - - if (FILE_FLAG_OPEN_REQUIRING_OPLOCK & dwFlagsAndAttributes) - { - SecurityQualityOfService.ContextTrackingMode = TRUE; - } - else - { - SecurityQualityOfService.ContextTrackingMode = FALSE; - } - - - if (FILE_FLAG_FIRST_PIPE_INSTANCE & dwFlagsAndAttributes) - { - SecurityQualityOfService.EffectiveOnly = TRUE; - } - else - { - SecurityQualityOfService.EffectiveOnly = FALSE; - } - } - else - { - SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation; - SecurityQualityOfService.ContextTrackingMode = TRUE; - SecurityQualityOfService.EffectiveOnly = TRUE; - } - - OBJECT_ATTRIBUTES ObjectAttributes = - { - sizeof(ObjectAttributes), - hOriginalFile, - &ObjectName, - FILE_FLAG_POSIX_SEMANTICS & dwFlagsAndAttributes ? 0ul : OBJ_CASE_INSENSITIVE, - nullptr, - &SecurityQualityOfService - }; - - - IO_STATUS_BLOCK IoStatusBlock; - - HANDLE hFile; - - Status = pNtCreateFile( - &hFile, - dwDesiredAccess, - &ObjectAttributes, - &IoStatusBlock, - nullptr, - 0, - dwShareMode, - FILE_OPEN, - CreateOptions, - nullptr, - 0); - - if (Status >= 0) - { - return hFile; - } - - - } while (false); - - - internal::BaseSetLastNTError(Status); - - return INVALID_HANDLE_VALUE; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008[desktop apps only] + __DEFINE_THUNK( + kernel32, + 12, + BOOLEAN, + APIENTRY, + CreateSymbolicLinkA, + _In_ LPCSTR lpSymlinkFileName, + _In_ LPCSTR lpTargetFileName, + _In_ DWORD dwFlags + ) + { + if (const auto pCreateSymbolicLinkA = try_get_CreateSymbolicLinkA()) + { + return pCreateSymbolicLinkA(lpSymlinkFileName, lpTargetFileName, dwFlags); + } + + SetLastError(ERROR_INVALID_FUNCTION); + + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WINXP) - - //Windows XP [desktop apps | UWP apps] - //Windows Server 2003 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 20, - _Success_(return) - BOOL, - WINAPI, - SetFilePointerEx, - _In_ HANDLE hFile, - _In_ LARGE_INTEGER liDistanceToMove, - _Out_opt_ PLARGE_INTEGER lpNewFilePointer, - _In_ DWORD dwMoveMethod - ) - { - if (const auto pSetFilePointerEx = try_get_SetFilePointerEx()) - { - return pSetFilePointerEx(hFile, liDistanceToMove, lpNewFilePointer, dwMoveMethod); - } - - liDistanceToMove.LowPart = SetFilePointer(hFile, liDistanceToMove.LowPart, &liDistanceToMove.HighPart, dwMoveMethod); - - if (liDistanceToMove.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) - { - return FALSE; - } - - if (lpNewFilePointer) - *lpNewFilePointer = liDistanceToMove; - - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT5_2) + + //Windows Vista [desktop apps only] + //Windows Server 2003 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 16, + HANDLE, + WINAPI, + ReOpenFile, + _In_ HANDLE hOriginalFile, + _In_ DWORD dwDesiredAccess, + _In_ DWORD dwShareMode, + _In_ DWORD dwFlagsAndAttributes + ) + { + if (const auto pReOpenFile = try_get_ReOpenFile()) + { + return pReOpenFile(hOriginalFile, dwDesiredAccess, dwShareMode, dwFlagsAndAttributes); + } + + NTSTATUS Status; + + do + { + const auto pNtCreateFile = try_get_NtCreateFile(); + if (!pNtCreateFile) + { + Status = STATUS_INVALID_INFO_CLASS; + break; + } + + + if ((size_t(hOriginalFile) & 0x10000003) == 3) + { + Status = STATUS_INVALID_HANDLE; + break; + } + + if (dwFlagsAndAttributes & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_SPARSE_FILE | FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_ENCRYPTED)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + ULONG CreateOptions = FILE_NON_DIRECTORY_FILE; + + if (FILE_FLAG_WRITE_THROUGH & dwFlagsAndAttributes) + { + CreateOptions |= FILE_WRITE_THROUGH; + } + + if (FILE_FLAG_NO_BUFFERING & dwFlagsAndAttributes) + { + CreateOptions |= FILE_NO_INTERMEDIATE_BUFFERING; + } + + if (FILE_FLAG_SEQUENTIAL_SCAN & dwFlagsAndAttributes) + { + CreateOptions |= FILE_SEQUENTIAL_ONLY; + } + + if (FILE_FLAG_RANDOM_ACCESS & dwFlagsAndAttributes) + { + CreateOptions |= FILE_RANDOM_ACCESS; + } + + if (FILE_FLAG_BACKUP_SEMANTICS & dwFlagsAndAttributes) + { + CreateOptions |= FILE_OPEN_FOR_BACKUP_INTENT; + } + + if ((FILE_FLAG_OVERLAPPED & dwFlagsAndAttributes) == 0) + { + CreateOptions |= FILE_SYNCHRONOUS_IO_NONALERT; + } + + if (FILE_FLAG_OPEN_NO_RECALL & dwFlagsAndAttributes) + { + CreateOptions |= FILE_OPEN_NO_RECALL; + } + + if (FILE_FLAG_OPEN_REPARSE_POINT & dwFlagsAndAttributes) + { + CreateOptions |= FILE_OPEN_REPARSE_POINT; + } + + if (FILE_FLAG_DELETE_ON_CLOSE & dwFlagsAndAttributes) + { + CreateOptions |= FILE_DELETE_ON_CLOSE; + dwDesiredAccess |= DELETE; + } + + dwDesiredAccess |= SYNCHRONIZE | FILE_READ_ATTRIBUTES; + + UNICODE_STRING ObjectName = { 0, 2, (PWSTR)L"" }; + SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService; + + SecurityQualityOfService.Length = sizeof(SecurityQualityOfService); + + if (FILE_FLAG_OPEN_NO_RECALL & dwFlagsAndAttributes) + { + SecurityQualityOfService.ImpersonationLevel = SECURITY_IMPERSONATION_LEVEL((dwFlagsAndAttributes >> 16) & 0x3); + + if (FILE_FLAG_OPEN_REQUIRING_OPLOCK & dwFlagsAndAttributes) + { + SecurityQualityOfService.ContextTrackingMode = TRUE; + } + else + { + SecurityQualityOfService.ContextTrackingMode = FALSE; + } + + + if (FILE_FLAG_FIRST_PIPE_INSTANCE & dwFlagsAndAttributes) + { + SecurityQualityOfService.EffectiveOnly = TRUE; + } + else + { + SecurityQualityOfService.EffectiveOnly = FALSE; + } + } + else + { + SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation; + SecurityQualityOfService.ContextTrackingMode = TRUE; + SecurityQualityOfService.EffectiveOnly = TRUE; + } + + OBJECT_ATTRIBUTES ObjectAttributes = + { + sizeof(ObjectAttributes), + hOriginalFile, + &ObjectName, + FILE_FLAG_POSIX_SEMANTICS & dwFlagsAndAttributes ? 0ul : OBJ_CASE_INSENSITIVE, + nullptr, + &SecurityQualityOfService + }; + + + IO_STATUS_BLOCK IoStatusBlock; + + HANDLE hFile; + + Status = pNtCreateFile( + &hFile, + dwDesiredAccess, + &ObjectAttributes, + &IoStatusBlock, + nullptr, + 0, + dwShareMode, + FILE_OPEN, + CreateOptions, + nullptr, + 0); + + if (Status >= 0) + { + return hFile; + } + + + } while (false); + + + internal::BaseSetLastNTError(Status); + + return INVALID_HANDLE_VALUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - // 最低受支持的客户端 Windows XP [桌面应用 |UWP 应用] - // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 24, - HANDLE, - WINAPI, - FindFirstFileExW, - _In_ LPCWSTR lpFileName, - _In_ FINDEX_INFO_LEVELS fInfoLevelId, - _Out_writes_bytes_(sizeof(WIN32_FIND_DATAW)) LPVOID lpFindFileData, - _In_ FINDEX_SEARCH_OPS fSearchOp, - _Reserved_ LPVOID lpSearchFilter, - _In_ DWORD dwAdditionalFlags - ) - { - if (const auto _pfnFindFirstFileExW = try_get_FindFirstFileExW()) - { - if (internal::GetSystemVersion() < internal::MakeVersion(6, 1)) - { - // dwAdditionalFlags : Windows 7开始才支持 FIND_FIRST_EX_LARGE_FETCH - dwAdditionalFlags &= (FIND_FIRST_EX_CASE_SENSITIVE | FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY); - - // Windows 7开始才支持 FindExInfoBasic - fInfoLevelId = FindExInfoStandard; - } - - - return _pfnFindFirstFileExW(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags); - } - - return FindFirstFileW(lpFileName, (WIN32_FIND_DATAW*)lpFindFileData); - } + +#if (YY_Thunks_Target < __WindowsNT5_1) + + //Windows XP [desktop apps | UWP apps] + //Windows Server 2003 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 20, + _Success_(return) + BOOL, + WINAPI, + SetFilePointerEx, + _In_ HANDLE hFile, + _In_ LARGE_INTEGER liDistanceToMove, + _Out_opt_ PLARGE_INTEGER lpNewFilePointer, + _In_ DWORD dwMoveMethod + ) + { + if (const auto pSetFilePointerEx = try_get_SetFilePointerEx()) + { + return pSetFilePointerEx(hFile, liDistanceToMove, lpNewFilePointer, dwMoveMethod); + } + + liDistanceToMove.LowPart = SetFilePointer(hFile, liDistanceToMove.LowPart, &liDistanceToMove.HighPart, dwMoveMethod); + + if (liDistanceToMove.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) + { + return FALSE; + } + + if (lpNewFilePointer) + *lpNewFilePointer = liDistanceToMove; + + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - // 最低受支持的客户端 Windows XP [桌面应用 |UWP 应用] - // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 24, - HANDLE, - WINAPI, - FindFirstFileExA, - _In_ LPCSTR lpFileName, - _In_ FINDEX_INFO_LEVELS fInfoLevelId, - _Out_writes_bytes_(sizeof(WIN32_FIND_DATAA)) LPVOID lpFindFileData, - _In_ FINDEX_SEARCH_OPS fSearchOp, - _Reserved_ LPVOID lpSearchFilter, - _In_ DWORD dwAdditionalFlags - ) - { - if (const auto _pfnFindFirstFileExA = try_get_FindFirstFileExA()) - { - if (internal::GetSystemVersion() < internal::MakeVersion(6, 1)) - { - // dwAdditionalFlags : Windows 7开始才支持 FIND_FIRST_EX_LARGE_FETCH - dwAdditionalFlags &= (FIND_FIRST_EX_CASE_SENSITIVE | FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY); - - // Windows 7开始才支持 FindExInfoBasic - fInfoLevelId = FindExInfoStandard; - } - - return _pfnFindFirstFileExA(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags); - } - - return FindFirstFileA(lpFileName, (WIN32_FIND_DATAA*)lpFindFileData); - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + // 最低受支持的客户端 Windows XP [桌面应用 |UWP 应用] + // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 24, + HANDLE, + WINAPI, + FindFirstFileExW, + _In_ LPCWSTR lpFileName, + _In_ FINDEX_INFO_LEVELS fInfoLevelId, + _Out_writes_bytes_(sizeof(WIN32_FIND_DATAW)) LPVOID lpFindFileData, + _In_ FINDEX_SEARCH_OPS fSearchOp, + _Reserved_ LPVOID lpSearchFilter, + _In_ DWORD dwAdditionalFlags + ) + { + if (const auto _pfnFindFirstFileExW = try_get_FindFirstFileExW()) + { + if (internal::GetSystemVersion() < internal::MakeVersion(6, 1)) + { + // dwAdditionalFlags : Windows 7开始才支持 FIND_FIRST_EX_LARGE_FETCH + dwAdditionalFlags &= (FIND_FIRST_EX_CASE_SENSITIVE | FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY); + + // Windows 7开始才支持 FindExInfoBasic + fInfoLevelId = FindExInfoStandard; + } + + + return _pfnFindFirstFileExW(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags); + } + + return FindFirstFileW(lpFileName, (WIN32_FIND_DATAW*)lpFindFileData); + } #endif - }//namespace Thunks -} //namespace YY +#if (YY_Thunks_Target < __WindowsNT6_1) + + // 最低受支持的客户端 Windows XP [桌面应用 |UWP 应用] + // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 24, + HANDLE, + WINAPI, + FindFirstFileExA, + _In_ LPCSTR lpFileName, + _In_ FINDEX_INFO_LEVELS fInfoLevelId, + _Out_writes_bytes_(sizeof(WIN32_FIND_DATAA)) LPVOID lpFindFileData, + _In_ FINDEX_SEARCH_OPS fSearchOp, + _Reserved_ LPVOID lpSearchFilter, + _In_ DWORD dwAdditionalFlags + ) + { + if (const auto _pfnFindFirstFileExA = try_get_FindFirstFileExA()) + { + if (internal::GetSystemVersion() < internal::MakeVersion(6, 1)) + { + // dwAdditionalFlags : Windows 7开始才支持 FIND_FIRST_EX_LARGE_FETCH + dwAdditionalFlags &= (FIND_FIRST_EX_CASE_SENSITIVE | FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY); + + // Windows 7开始才支持 FindExInfoBasic + fInfoLevelId = FindExInfoStandard; + } + + return _pfnFindFirstFileExA(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags); + } + + return FindFirstFileA(lpFileName, (WIN32_FIND_DATAA*)lpFindFileData); + } +#endif +} //namespace YY::Thunks diff --git a/src/Thunks/api-ms-win-core-handle.hpp b/src/Thunks/api-ms-win-core-handle.hpp index a673a10..68f79da 100644 --- a/src/Thunks/api-ms-win-core-handle.hpp +++ b/src/Thunks/api-ms-win-core-handle.hpp @@ -1,5 +1,5 @@  -#if (YY_Thunks_Support_Version < NTDDI_WIN10) && !defined(__Comment_Lib_advapi32) +#if (YY_Thunks_Target < __WindowsNT10_10240) && !defined(__Comment_Lib_advapi32) #define __Comment_Lib_advapi32 #pragma comment(lib, "Advapi32.lib") #endif @@ -9,7 +9,7 @@ namespace YY::Thunks { namespace { -#if (YY_Thunks_Support_Version < NTDDI_WIN10) +#if (YY_Thunks_Target < __WindowsNT10_10240) static SRWLOCK g_CompareObjectHandles; union ObjectStaticBuffer @@ -342,7 +342,7 @@ namespace YY::Thunks namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN10) +#if (YY_Thunks_Target < __WindowsNT10_10240) // 最低受支持的客户端 Windows 2000 专业版 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows 2000 Server[桌面应用 | UWP 应用] @@ -378,7 +378,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10) +#if (YY_Thunks_Target < __WindowsNT10_10240) // 最低受支持的客户端 Windows 2000 专业版 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows 2000 Server[桌面应用 | UWP 应用] @@ -434,7 +434,8 @@ namespace YY::Thunks } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10) + +#if (YY_Thunks_Target < __WindowsNT10_10240) // 最低受支持的客户端 Windows 10 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2016[桌面应用 | UWP 应用] diff --git a/src/Thunks/api-ms-win-core-interlocked.hpp b/src/Thunks/api-ms-win-core-interlocked.hpp index 0a1b56c..8fa6ff0 100644 --- a/src/Thunks/api-ms-win-core-interlocked.hpp +++ b/src/Thunks/api-ms-win-core-interlocked.hpp @@ -1,193 +1,187 @@  -namespace YY +namespace YY::Thunks { - namespace Thunks - { - -#if (YY_Thunks_Support_Version < NTDDI_WS03) - - #pragma push_macro("InterlockedCompareExchange64") - #undef InterlockedCompareExchange64 - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2003 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 20, - LONG64, - WINAPI, - InterlockedCompareExchange64, - _Inout_ _Interlocked_operand_ LONG64 volatile *Destination, - _In_ LONG64 ExChange, - _In_ LONG64 Comperand - ) - { - return _InterlockedCompareExchange64(Destination, ExChange, Comperand); - } - #pragma pop_macro("InterlockedCompareExchange64") +#if (YY_Thunks_Target < __WindowsNT5_2) + + #pragma push_macro("InterlockedCompareExchange64") + #undef InterlockedCompareExchange64 + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2003 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 20, + LONG64, + WINAPI, + InterlockedCompareExchange64, + _Inout_ _Interlocked_operand_ LONG64 volatile *Destination, + _In_ LONG64 ExChange, + _In_ LONG64 Comperand + ) + { + return _InterlockedCompareExchange64(Destination, ExChange, Comperand); + } + #pragma pop_macro("InterlockedCompareExchange64") #endif -#if (YY_Thunks_Support_Version < NTDDI_WINXP) - - //Windows XP [desktop apps | UWP apps] - //Windows Server 2003 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - InitializeSListHead, - _Out_ PSLIST_HEADER ListHead - ) - { - *ListHead = SLIST_HEADER{}; - } +#if (YY_Thunks_Target < __WindowsNT5_1) + + //Windows XP [desktop apps | UWP apps] + //Windows Server 2003 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + InitializeSListHead, + _Out_ PSLIST_HEADER ListHead + ) + { + *ListHead = SLIST_HEADER{}; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WINXP) - - //Windows XP [desktop apps | UWP apps] - //Windows Server 2003 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - PSLIST_ENTRY, - WINAPI, - InterlockedFlushSList, - _Inout_ PSLIST_HEADER ListHead - ) +#if (YY_Thunks_Target < __WindowsNT5_1) + + //Windows XP [desktop apps | UWP apps] + //Windows Server 2003 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + PSLIST_ENTRY, + WINAPI, + InterlockedFlushSList, + _Inout_ PSLIST_HEADER ListHead + ) + { + if (const auto pInterlockedFlushSList = try_get_InterlockedFlushSList()) { - if (const auto pInterlockedFlushSList = try_get_InterlockedFlushSList()) - { - return pInterlockedFlushSList(ListHead); - } - - __asm - { - mov ebp, [ListHead] - xor ebx, ebx - mov edx, [ebp + 4] - mov eax, [ebp + 0] + return pInterlockedFlushSList(ListHead); + } - _Loop: - or eax, eax - jz _End - mov ecx, edx - mov cx, bx - lock cmpxchg8b qword ptr[ebp] - jnz _Loop - _End: - } - - //直接返回eax即可。 + __asm + { + mov ebp, [ListHead] + xor ebx, ebx + mov edx, [ebp + 4] + mov eax, [ebp + 0] + + _Loop: + or eax, eax + jz _End + mov ecx, edx + mov cx, bx + lock cmpxchg8b qword ptr[ebp] + jnz _Loop + _End: } -#endif + //直接返回eax即可。 + } +#endif -#if (YY_Thunks_Support_Version < NTDDI_WINXP) - //Windows XP [desktop apps | UWP apps] - //Windows Server 2003 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - USHORT, - WINAPI, - QueryDepthSList, - _In_ PSLIST_HEADER ListHead - ) +#if (YY_Thunks_Target < __WindowsNT5_1) + + //Windows XP [desktop apps | UWP apps] + //Windows Server 2003 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + USHORT, + WINAPI, + QueryDepthSList, + _In_ PSLIST_HEADER ListHead + ) + { + if (const auto pQueryDepthSList = try_get_QueryDepthSList()) { - if (const auto pQueryDepthSList = try_get_QueryDepthSList()) - { - return pQueryDepthSList(ListHead); - } - - return ListHead->Depth; + return pQueryDepthSList(ListHead); } + + return ListHead->Depth; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WINXP) +#if (YY_Thunks_Target < __WindowsNT5_1) + + //Windows XP [desktop apps | UWP apps] + //Windows Server 2003 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 8, + PSLIST_ENTRY, + WINAPI, + InterlockedPushEntrySList, + _Inout_ PSLIST_HEADER ListHead, + _Inout_ __drv_aliasesMem PSLIST_ENTRY ListEntry + ) + { + if (const auto pInterlockedPushEntrySList = try_get_InterlockedPushEntrySList()) + { + return pInterlockedPushEntrySList(ListHead, ListEntry); + } - //Windows XP [desktop apps | UWP apps] - //Windows Server 2003 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 8, - PSLIST_ENTRY, - WINAPI, - InterlockedPushEntrySList, - _Inout_ PSLIST_HEADER ListHead, - _Inout_ __drv_aliasesMem PSLIST_ENTRY ListEntry - ) + __asm { - if (const auto pInterlockedPushEntrySList = try_get_InterlockedPushEntrySList()) - { - return pInterlockedPushEntrySList(ListHead, ListEntry); - } - - __asm - { - mov ebx, [ListEntry] - mov ebp, [ListHead] - - mov edx, [ebp + 4] - mov eax, [ebp + 0] - - _Loop: - mov [ebx], eax - lea ecx, [edx + 10001h] - lock cmpxchg8b qword ptr [ebp] - jnz _Loop - } - - //asm会更新eax + mov ebx, [ListEntry] + mov ebp, [ListHead] + + mov edx, [ebp + 4] + mov eax, [ebp + 0] + + _Loop: + mov [ebx], eax + lea ecx, [edx + 10001h] + lock cmpxchg8b qword ptr [ebp] + jnz _Loop } -#endif + //asm会更新eax + } +#endif -#if (YY_Thunks_Support_Version < NTDDI_WINXP) - //Windows XP [desktop apps | UWP apps] - //Windows Server 2003 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - PSLIST_ENTRY, - WINAPI, - InterlockedPopEntrySList, - _Inout_ PSLIST_HEADER ListHead - ) +#if (YY_Thunks_Target < __WindowsNT5_1) + + //Windows XP [desktop apps | UWP apps] + //Windows Server 2003 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + PSLIST_ENTRY, + WINAPI, + InterlockedPopEntrySList, + _Inout_ PSLIST_HEADER ListHead + ) + { + if (const auto pInterlockedPopEntrySList = try_get_InterlockedPopEntrySList()) { - if (const auto pInterlockedPopEntrySList = try_get_InterlockedPopEntrySList()) - { - return pInterlockedPopEntrySList(ListHead); - } - - __asm - { - mov ebp, [ListHead] - mov edx, [ebp + 4] - mov eax, [ebp + 0] - _Loop: - or eax, eax - jz _End - lea ecx, [edx-1] - mov ebx, [eax] - lock cmpxchg8b qword ptr [ebp] - jnz _Loop - _End: + return pInterlockedPopEntrySList(ListHead); + } - } + __asm + { + mov ebp, [ListHead] + mov edx, [ebp + 4] + mov eax, [ebp + 0] + _Loop: + or eax, eax + jz _End + lea ecx, [edx-1] + mov ebx, [eax] + lock cmpxchg8b qword ptr [ebp] + jnz _Loop + _End: - //asm 会修改eax } -#endif - - }//namespace Thunks -} //namespace YY \ No newline at end of file + //asm 会修改eax + } +#endif +} //namespace YY::Thunks diff --git a/src/Thunks/api-ms-win-core-io.hpp b/src/Thunks/api-ms-win-core-io.hpp index 5452bc0..cc0da7b 100644 --- a/src/Thunks/api-ms-win-core-io.hpp +++ b/src/Thunks/api-ms-win-core-io.hpp @@ -1,167 +1,162 @@  -namespace YY +namespace YY::Thunks { - namespace Thunks - { - -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - CancelIoEx, - _In_ HANDLE hFile, - _In_opt_ LPOVERLAPPED lpOverlapped - ) - { - if (auto pCancelIoEx = try_get_CancelIoEx()) - { - return pCancelIoEx(hFile, lpOverlapped); - } - - //downlevel逻辑会把该文件所有IO动作给取消掉!凑合用吧。 - return CancelIo(hFile); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + CancelIoEx, + _In_ HANDLE hFile, + _In_opt_ LPOVERLAPPED lpOverlapped + ) + { + if (auto pCancelIoEx = try_get_CancelIoEx()) + { + return pCancelIoEx(hFile, lpOverlapped); + } + + //downlevel逻辑会把该文件所有IO动作给取消掉!凑合用吧。 + return CancelIo(hFile); + } #endif - - -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - BOOL, - WINAPI, - CancelSynchronousIo, - _In_ HANDLE _hThread - ) - { - if (const auto _pfnCancelSynchronousIo = try_get_CancelSynchronousIo()) - { - return _pfnCancelSynchronousIo(_hThread); - } - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } + + +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + BOOL, + WINAPI, + CancelSynchronousIo, + _In_ HANDLE _hThread + ) + { + if (const auto _pfnCancelSynchronousIo = try_get_CancelSynchronousIo()) + { + return _pfnCancelSynchronousIo(_hThread); + } + + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 24, - BOOL, - WINAPI, - GetQueuedCompletionStatusEx, - _In_ HANDLE CompletionPort, - _Out_writes_to_(ulCount,*ulNumEntriesRemoved) LPOVERLAPPED_ENTRY lpCompletionPortEntries, - _In_ ULONG ulCount, - _Out_ PULONG ulNumEntriesRemoved, - _In_ DWORD dwMilliseconds, - _In_ BOOL fAlertable - ) - { - if (const auto _pfnGetQueuedCompletionStatusEx = try_get_GetQueuedCompletionStatusEx()) - { - return _pfnGetQueuedCompletionStatusEx(CompletionPort, lpCompletionPortEntries, ulCount, ulNumEntriesRemoved, dwMilliseconds, fAlertable); - } - - if (ulCount == 0 || lpCompletionPortEntries == nullptr || ulNumEntriesRemoved == nullptr) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - *ulNumEntriesRemoved = 0; - - auto& _Entry = lpCompletionPortEntries[0]; - - if (fAlertable) +#if (YY_Thunks_Target < __WindowsNT6) + + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 24, + BOOL, + WINAPI, + GetQueuedCompletionStatusEx, + _In_ HANDLE CompletionPort, + _Out_writes_to_(ulCount,*ulNumEntriesRemoved) LPOVERLAPPED_ENTRY lpCompletionPortEntries, + _In_ ULONG ulCount, + _Out_ PULONG ulNumEntriesRemoved, + _In_ DWORD dwMilliseconds, + _In_ BOOL fAlertable + ) + { + if (const auto _pfnGetQueuedCompletionStatusEx = try_get_GetQueuedCompletionStatusEx()) + { + return _pfnGetQueuedCompletionStatusEx(CompletionPort, lpCompletionPortEntries, ulCount, ulNumEntriesRemoved, dwMilliseconds, fAlertable); + } + + if (ulCount == 0 || lpCompletionPortEntries == nullptr || ulNumEntriesRemoved == nullptr) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + *ulNumEntriesRemoved = 0; + + auto& _Entry = lpCompletionPortEntries[0]; + + if (fAlertable) + { + // 使用 WaitForSingleObjectEx 进行等待触发 APC + auto _uStartTick = GetTickCount(); + for (;;) { - // 使用 WaitForSingleObjectEx 进行等待触发 APC - auto _uStartTick = GetTickCount(); - for (;;) + const auto _uResult = WaitForSingleObjectEx(CompletionPort, dwMilliseconds, TRUE); + if (_uResult == WAIT_OBJECT_0) { - const auto _uResult = WaitForSingleObjectEx(CompletionPort, dwMilliseconds, TRUE); - if (_uResult == WAIT_OBJECT_0) + // 完成端口有数据了 + auto _bRet = GetQueuedCompletionStatus(CompletionPort, &_Entry.dwNumberOfBytesTransferred, &_Entry.lpCompletionKey, &_Entry.lpOverlapped, 0); + if (_bRet) { - // 完成端口有数据了 - auto _bRet = GetQueuedCompletionStatus(CompletionPort, &_Entry.dwNumberOfBytesTransferred, &_Entry.lpCompletionKey, &_Entry.lpOverlapped, 0); - if (_bRet) - { - *ulNumEntriesRemoved = 1; - break; - } - - if (GetLastError() != WAIT_TIMEOUT) - { - return FALSE; - } - - // 无限等待时无脑继续等即可。 - if (dwMilliseconds == INFINITE) - { - continue; - } - - // 计算剩余等待时间,如果剩余等待时间归零则返回 - const DWORD _uTickSpan = GetTickCount() - _uStartTick; - if (_uTickSpan >= dwMilliseconds) - { - SetLastError(WAIT_TIMEOUT); - return FALSE; - } - dwMilliseconds -= _uTickSpan; - _uStartTick += _uTickSpan; - continue; + *ulNumEntriesRemoved = 1; + break; } - else if (_uResult == WAIT_IO_COMPLETION || _uResult == WAIT_TIMEOUT) - { - // 很奇怪,微软原版遇到 APC唤醒直接会设置 LastError WAIT_IO_COMPLETION - // 遇到超时,LastError WAIT_TIMEOUT(注意不是预期的 ERROR_TIMEOUT)不知道是故意还是有意。 - SetLastError(_uResult); - return FALSE; - } - else if (_uResult == WAIT_ABANDONED) + + if (GetLastError() != WAIT_TIMEOUT) { - SetLastError(ERROR_ABANDONED_WAIT_0); return FALSE; } - else if (_uResult == WAIT_FAILED) + + // 无限等待时无脑继续等即可。 + if (dwMilliseconds == INFINITE) { - // LastError - return FALSE; + continue; } - else + + // 计算剩余等待时间,如果剩余等待时间归零则返回 + const DWORD _uTickSpan = GetTickCount() - _uStartTick; + if (_uTickSpan >= dwMilliseconds) { - // LastError ??? + SetLastError(WAIT_TIMEOUT); return FALSE; } + dwMilliseconds -= _uTickSpan; + _uStartTick += _uTickSpan; + continue; } - - return TRUE; - } - else - { - auto _bRet = GetQueuedCompletionStatus(CompletionPort, &_Entry.dwNumberOfBytesTransferred, &_Entry.lpCompletionKey, &_Entry.lpOverlapped, dwMilliseconds); - if (_bRet) + else if (_uResult == WAIT_IO_COMPLETION || _uResult == WAIT_TIMEOUT) + { + // 很奇怪,微软原版遇到 APC唤醒直接会设置 LastError WAIT_IO_COMPLETION + // 遇到超时,LastError WAIT_TIMEOUT(注意不是预期的 ERROR_TIMEOUT)不知道是故意还是有意。 + SetLastError(_uResult); + return FALSE; + } + else if (_uResult == WAIT_ABANDONED) { - *ulNumEntriesRemoved = 1; + SetLastError(ERROR_ABANDONED_WAIT_0); + return FALSE; + } + else if (_uResult == WAIT_FAILED) + { + // LastError + return FALSE; + } + else + { + // LastError ??? + return FALSE; } - return _bRet; } - } -#endif - }//namespace Thunks -} //namespace YY + return TRUE; + } + else + { + auto _bRet = GetQueuedCompletionStatus(CompletionPort, &_Entry.dwNumberOfBytesTransferred, &_Entry.lpCompletionKey, &_Entry.lpOverlapped, dwMilliseconds); + if (_bRet) + { + *ulNumEntriesRemoved = 1; + } + return _bRet; + } + } +#endif +} //namespace YY::Thunks diff --git a/src/Thunks/api-ms-win-core-kernel32-legacy.hpp b/src/Thunks/api-ms-win-core-kernel32-legacy.hpp index d74fbee..4f70a09 100644 --- a/src/Thunks/api-ms-win-core-kernel32-legacy.hpp +++ b/src/Thunks/api-ms-win-core-kernel32-legacy.hpp @@ -2,7 +2,7 @@ namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN7) && defined(YY_Thunks_Implemented) +#if (YY_Thunks_Target < __WindowsNT6_1) && defined(YY_Thunks_Implemented) namespace { struct PowerRequestTaskItem : public internal::TaskItem @@ -202,216 +202,221 @@ namespace YY::Thunks } } #endif +} +namespace YY::Thunks +{ +#if (YY_Thunks_Target < __WindowsNT6_1) + + // 最低受支持的客户端 Windows 7 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] + __DEFINE_THUNK( + kernel32, + 4, + HANDLE, + WINAPI, + PowerCreateRequest, + _In_ PREASON_CONTEXT _pContext + ) + { + if (const auto _pfnPowerCreateRequest = try_get_PowerCreateRequest()) + { + return _pfnPowerCreateRequest(_pContext); + } + + if (_pContext == nullptr || _pContext->Version != POWER_REQUEST_CONTEXT_VERSION) + { + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; + } -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - // 最低受支持的客户端 Windows 7 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] - __DEFINE_THUNK( - kernel32, - 4, - HANDLE, - WINAPI, - PowerCreateRequest, - _In_ PREASON_CONTEXT _pContext - ) - { - if (const auto _pfnPowerCreateRequest = try_get_PowerCreateRequest()) - { - return _pfnPowerCreateRequest(_pContext); - } - - if (_pContext == nullptr || _pContext->Version != POWER_REQUEST_CONTEXT_VERSION) - { - SetLastError(ERROR_INVALID_PARAMETER); - return INVALID_HANDLE_VALUE; - } - - // 因为 PowerCreateRequest创建的句柄需要使用 CloseHandle关闭 - // 所以我们随便复制一个句柄给它…… - HANDLE hTargetHandle; - if (DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &hTargetHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) - { - return hTargetHandle; - } - - return INVALID_HANDLE_VALUE; - } + // 因为 PowerCreateRequest创建的句柄需要使用 CloseHandle关闭 + // 所以我们随便复制一个句柄给它…… + HANDLE hTargetHandle; + if (DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &hTargetHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) + { + return hTargetHandle; + } + + return INVALID_HANDLE_VALUE; + } #endif - -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - // 最低受支持的客户端 Windows 7 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - PowerSetRequest, - _In_ HANDLE _hPowerRequest, - _In_ POWER_REQUEST_TYPE _eRequestType - ) - { - if (const auto _pfnPowerSetRequest = try_get_PowerSetRequest()) - { - return _pfnPowerSetRequest(_hPowerRequest, _eRequestType); - } - - if ((DWORD)_eRequestType >= (DWORD)_countof(PowerRequestTaskItem::RequestTypeCount)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - const auto _uProcessId = GetProcessId(_hPowerRequest); - if (_uProcessId == 0) - { - return FALSE; - } - - if (_uProcessId != GetCurrentProcessId()) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - auto _lStatus = GetPowerRequestCache()->AddRef(); - if (_lStatus == ERROR_SUCCESS) - { - auto _pTask = GetPowerRequestCache()->pTask; - InterlockedIncrement(&_pTask->uCount); - - if (InterlockedIncrement(&_pTask->RequestTypeCount[_eRequestType]) == 0) - { - // 状态发生变化,通知进行更改 - PostMessageW( - internal::GetGlobalThreadRunner()->hWnd, - internal::WM_RUNNER_CALL, - (WPARAM)_pTask, - 0); - } - - return TRUE; - } - - SetLastError(_lStatus); - return FALSE; - } + + +#if (YY_Thunks_Target < __WindowsNT6_1) + + // 最低受支持的客户端 Windows 7 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + PowerSetRequest, + _In_ HANDLE _hPowerRequest, + _In_ POWER_REQUEST_TYPE _eRequestType + ) + { + if (const auto _pfnPowerSetRequest = try_get_PowerSetRequest()) + { + return _pfnPowerSetRequest(_hPowerRequest, _eRequestType); + } + + if ((DWORD)_eRequestType >= (DWORD)_countof(PowerRequestTaskItem::RequestTypeCount)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + const auto _uProcessId = GetProcessId(_hPowerRequest); + if (_uProcessId == 0) + { + return FALSE; + } + + if (_uProcessId != GetCurrentProcessId()) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + auto _lStatus = GetPowerRequestCache()->AddRef(); + if (_lStatus == ERROR_SUCCESS) + { + auto _pTask = GetPowerRequestCache()->pTask; + InterlockedIncrement(&_pTask->uCount); + + if (InterlockedIncrement(&_pTask->RequestTypeCount[_eRequestType]) == 0) + { + // 状态发生变化,通知进行更改 + PostMessageW( + internal::GetGlobalThreadRunner()->hWnd, + internal::WM_RUNNER_CALL, + (WPARAM)_pTask, + 0); + } + + return TRUE; + } + + SetLastError(_lStatus); + return FALSE; + } #endif - -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - // 最低受支持的客户端 Windows 7 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - PowerClearRequest, - _In_ HANDLE _hPowerRequest, - _In_ POWER_REQUEST_TYPE _eRequestType - ) - { - if (const auto _pfnPowerClearRequest = try_get_PowerClearRequest()) - { - return _pfnPowerClearRequest(_hPowerRequest, _eRequestType); - } - - if ((DWORD)_eRequestType >= (DWORD)_countof(PowerRequestTaskItem::RequestTypeCount)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - const auto _uProcessId = GetProcessId(_hPowerRequest); - if (_uProcessId == 0) - { - return FALSE; - } - - if (_uProcessId != GetCurrentProcessId()) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - auto _pTask = GetPowerRequestCache()->pTask; - if (!_pTask) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - auto _uCurrent = _pTask->RequestTypeCount[_eRequestType]; - for (;;) - { - if (_uCurrent == 0) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - const auto _uLast = InterlockedCompareExchange(&_pTask->RequestTypeCount[_eRequestType], _uCurrent - 1, _uCurrent); - if (_uLast != _uCurrent) - { - _uCurrent = _uLast; - continue; - } - - if (_uCurrent == 1) - { - // 状态发生变化,通知进行更改 - if (InterlockedDecrement(&_pTask->uCount) == 0) - { - // 引用归 0,必须保证状态刷新到系统,所以我们不在这里释放引用。 - PostMessageW( - internal::GetGlobalThreadRunner()->hWnd, - internal::WM_RUNNER_CALL, - (WPARAM)_pTask, - (LPARAM)GetPowerRequestCache()); - - return TRUE; - } - else - { - PostMessageW( - internal::GetGlobalThreadRunner()->hWnd, - internal::WM_RUNNER_CALL, - (WPARAM)_pTask, - 0); - } - } - - break; - } - - GetPowerRequestCache()->Release(); - return TRUE; - } + + +#if (YY_Thunks_Target < __WindowsNT6_1) + + // 最低受支持的客户端 Windows 7 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + PowerClearRequest, + _In_ HANDLE _hPowerRequest, + _In_ POWER_REQUEST_TYPE _eRequestType + ) + { + if (const auto _pfnPowerClearRequest = try_get_PowerClearRequest()) + { + return _pfnPowerClearRequest(_hPowerRequest, _eRequestType); + } + + if ((DWORD)_eRequestType >= (DWORD)_countof(PowerRequestTaskItem::RequestTypeCount)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + const auto _uProcessId = GetProcessId(_hPowerRequest); + if (_uProcessId == 0) + { + return FALSE; + } + + if (_uProcessId != GetCurrentProcessId()) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + auto _pTask = GetPowerRequestCache()->pTask; + if (!_pTask) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + auto _uCurrent = _pTask->RequestTypeCount[_eRequestType]; + for (;;) + { + if (_uCurrent == 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + const auto _uLast = InterlockedCompareExchange(&_pTask->RequestTypeCount[_eRequestType], _uCurrent - 1, _uCurrent); + if (_uLast != _uCurrent) + { + _uCurrent = _uLast; + continue; + } + + if (_uCurrent == 1) + { + // 状态发生变化,通知进行更改 + if (InterlockedDecrement(&_pTask->uCount) == 0) + { + // 引用归 0,必须保证状态刷新到系统,所以我们不在这里释放引用。 + PostMessageW( + internal::GetGlobalThreadRunner()->hWnd, + internal::WM_RUNNER_CALL, + (WPARAM)_pTask, + (LPARAM)GetPowerRequestCache()); + + return TRUE; + } + else + { + PostMessageW( + internal::GetGlobalThreadRunner()->hWnd, + internal::WM_RUNNER_CALL, + (WPARAM)_pTask, + 0); + } + } + + break; + } + + GetPowerRequestCache()->Release(); + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - // 支持的最低客户端 Windows Vista [桌面应用程序 |UWP 应用] - // 支持的最低服务器 Windows Server 2008 [桌面应用程序 |UWP 应用] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - SetFileCompletionNotificationModes, - _In_ HANDLE FileHandle, - _In_ UCHAR Flags - ) - { - if (const auto _pfnSetFileCompletionNotificationModes = try_get_SetFileCompletionNotificationModes()) - { -#if (YY_Thunks_Support_Version >= NTDDI_WIN7) + +#if (YY_Thunks_Target < __WindowsNT6_1) + + // 支持的最低客户端 Windows Vista [桌面应用程序 |UWP 应用] + // 支持的最低服务器 Windows Server 2008 [桌面应用程序 |UWP 应用] + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + SetFileCompletionNotificationModes, + _In_ HANDLE FileHandle, + _In_ UCHAR Flags + ) + { + if (const auto _pfnSetFileCompletionNotificationModes = try_get_SetFileCompletionNotificationModes()) + { +#if (YY_Thunks_Target >= __WindowsNT6_1) return _pfnSetFileCompletionNotificationModes(FileHandle, Flags); -#else // (YY_Thunks_Support_Version < NTDDI_WIN7) +#else // (YY_Thunks_Target < __WindowsNT6_1) if (_pfnSetFileCompletionNotificationModes(FileHandle, Flags)) { return TRUE; @@ -425,13 +430,13 @@ namespace YY::Thunks return TRUE; } return FALSE; -#endif // (YY_Thunks_Support_Version < NTDDI_WIN7) - } - - // 初步看起来没有什么的,只是会降低完成端口的效率。 - // 至少需要 Vista才支持 FileIoCompletionNotificationInformation - // 只能假定先返回成功。 - return TRUE; - } +#endif // (YY_Thunks_Target < __WindowsNT6_1) + } + + // 初步看起来没有什么的,只是会降低完成端口的效率。 + // 至少需要 Vista才支持 FileIoCompletionNotificationInformation + // 只能假定先返回成功。 + return TRUE; + } #endif -} //namespace YY +} //namespace YY::Thunks diff --git a/src/Thunks/api-ms-win-core-libraryloader.hpp b/src/Thunks/api-ms-win-core-libraryloader.hpp index cc1a0c2..90cec93 100644 --- a/src/Thunks/api-ms-win-core-libraryloader.hpp +++ b/src/Thunks/api-ms-win-core-libraryloader.hpp @@ -4,7 +4,7 @@ namespace YY::Thunks::Fallback { namespace { -#if YY_Thunks_Support_Version < NTDDI_WIN8 +#if YY_Thunks_Target < __WindowsNT6_2 static DWORD s_DirectoryFlags/* = 0*/; #endif @@ -14,33 +14,33 @@ namespace YY::Thunks::Fallback _Out_ HMODULE* phModule )*/ #define BasepGetModuleHandleExParameterValidation(dwFlags, lpModuleName, phModule) \ - for (;;) \ - { \ - if (phModule) \ - { \ - *phModule = nullptr; \ - if ((dwFlags & ~(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)) == 0 \ - || (dwFlags & (GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) != (GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) \ - || (lpModuleName || (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) == 0)) \ - { \ - if (lpModuleName == nullptr) \ - { \ - *phModule = (HMODULE)((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ImageBaseAddress; \ - return TRUE; \ - } \ - break; \ - } \ - } \ - SetLastError(ERROR_INVALID_PARAMETER); \ - return FALSE; \ - } + for (;;) \ + { \ + if (phModule) \ + { \ + *phModule = nullptr; \ + if ((dwFlags & ~(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)) == 0 \ + || (dwFlags & (GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) != (GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) \ + || (lpModuleName || (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) == 0)) \ + { \ + if (lpModuleName == nullptr) \ + { \ + *phModule = (HMODULE)((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ImageBaseAddress; \ + return TRUE; \ + } \ + break; \ + } \ + } \ + SetLastError(ERROR_INVALID_PARAMETER); \ + return FALSE; \ + } #define __FORWARD_DLL_MODULE HMODULE(((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ImageBaseAddress) template HMODULE __fastcall ForwardDll(_In_z_ const Char* _szLibFileName) { -#if defined(__ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng) && (YY_Thunks_Support_Version < NTDDI_WIN7) +#if defined(__ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng) && (YY_Thunks_Target < __WindowsNT6_1) if (_szLibFileName == nullptr || *_szLibFileName == L'\0') return nullptr; @@ -58,7 +58,7 @@ namespace YY::Thunks::Fallback } } -#if defined(__ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng) && (YY_Thunks_Support_Version < NTDDI_WIN7) +#if defined(__ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng) && (YY_Thunks_Target < __WindowsNT6_1) if (internal::GetSystemVersion() < internal::MakeVersion(6, 1) && StringCompareIgnoreCaseByAscii(_szFileName, L"bcryptprimitives", 16) == 0) { @@ -74,7 +74,7 @@ namespace YY::Thunks::Fallback return nullptr; } -#if defined(__ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng) && YY_Thunks_Support_Version < NTDDI_WIN8 +#if defined(__ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng) && YY_Thunks_Target < __WindowsNT6_2 void* __fastcall try_get_GetProcAddress(const ProcInfo& _ProcInfo) { auto _hModule = _ProcInfo.pfnGetModule(); @@ -131,537 +131,537 @@ namespace YY::Thunks::Fallback namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WINXP) - - //Windows XP [desktop apps only] - //Windows Server 2003 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 12, - BOOL, - WINAPI, - GetModuleHandleExA, - _In_ DWORD dwFlags, - _In_opt_ LPCSTR lpModuleName, - _Out_ HMODULE* phModule - ) - { - if (const auto pGetModuleHandleExA = try_get_GetModuleHandleExA()) - { - return pGetModuleHandleExA(dwFlags, lpModuleName, phModule); - } - - BasepGetModuleHandleExParameterValidation(dwFlags, lpModuleName, phModule); - - if ((dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) == 0) - { - EnterCriticalSection(((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->LoaderLock); - } - - LSTATUS lStatus = ERROR_SUCCESS; - - for (;;) - { - HMODULE hModule; - - if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) - { - auto pRtlPcToFileHeader = try_get_RtlPcToFileHeader(); - if (!pRtlPcToFileHeader) - { - lStatus = ERROR_NOT_SUPPORTED; - break; - } - - hModule = (HMODULE)pRtlPcToFileHeader((PVOID)lpModuleName, (PVOID*)&hModule); - } - else - { - hModule = GetModuleHandleA(lpModuleName); - } - - if (hModule == nullptr) - { - lStatus = ERROR_DLL_NOT_FOUND; - break; - } - - if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) - { - - } - else - { - const auto pLdrAddRefDll = try_get_LdrAddRefDll(); - if (!pLdrAddRefDll) - { - lStatus = ERROR_NOT_SUPPORTED; - break; - } - - auto Status = pLdrAddRefDll(dwFlags& GET_MODULE_HANDLE_EX_FLAG_PIN, hModule); - if (Status < 0) - { - lStatus = internal::BaseSetLastNTError(Status); - break; - } - } - - *phModule = hModule; - - break; - } - - if ((dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) == 0) - { - LeaveCriticalSection(((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->LoaderLock); - } - - if (lStatus) - { - SetLastError(lStatus); - return FALSE; - } - else - { - return TRUE; - } - } +#if (YY_Thunks_Target < __WindowsNT5_1) + + //Windows XP [desktop apps only] + //Windows Server 2003 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 12, + BOOL, + WINAPI, + GetModuleHandleExA, + _In_ DWORD dwFlags, + _In_opt_ LPCSTR lpModuleName, + _Out_ HMODULE* phModule + ) + { + if (const auto pGetModuleHandleExA = try_get_GetModuleHandleExA()) + { + return pGetModuleHandleExA(dwFlags, lpModuleName, phModule); + } + + BasepGetModuleHandleExParameterValidation(dwFlags, lpModuleName, phModule); + + if ((dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) == 0) + { + EnterCriticalSection(((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->LoaderLock); + } + + LSTATUS lStatus = ERROR_SUCCESS; + + for (;;) + { + HMODULE hModule; + + if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) + { + auto pRtlPcToFileHeader = try_get_RtlPcToFileHeader(); + if (!pRtlPcToFileHeader) + { + lStatus = ERROR_NOT_SUPPORTED; + break; + } + + hModule = (HMODULE)pRtlPcToFileHeader((PVOID)lpModuleName, (PVOID*)&hModule); + } + else + { + hModule = GetModuleHandleA(lpModuleName); + } + + if (hModule == nullptr) + { + lStatus = ERROR_DLL_NOT_FOUND; + break; + } + + if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) + { + + } + else + { + const auto pLdrAddRefDll = try_get_LdrAddRefDll(); + if (!pLdrAddRefDll) + { + lStatus = ERROR_NOT_SUPPORTED; + break; + } + + auto Status = pLdrAddRefDll(dwFlags& GET_MODULE_HANDLE_EX_FLAG_PIN, hModule); + if (Status < 0) + { + lStatus = internal::BaseSetLastNTError(Status); + break; + } + } + + *phModule = hModule; + + break; + } + + if ((dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) == 0) + { + LeaveCriticalSection(((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->LoaderLock); + } + + if (lStatus) + { + SetLastError(lStatus); + return FALSE; + } + else + { + return TRUE; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WINXP) - - //Windows XP [desktop apps only] - //Windows Server 2003 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 12, - BOOL, - WINAPI, - GetModuleHandleExW, - _In_ DWORD dwFlags, - _In_opt_ LPCWSTR lpModuleName, - _Out_ HMODULE* phModule - ) - { - if (const auto pGetModuleHandleExW = try_get_GetModuleHandleExW()) - { - return pGetModuleHandleExW(dwFlags, lpModuleName, phModule); - } - - BasepGetModuleHandleExParameterValidation(dwFlags, lpModuleName, phModule); - - if ((dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) == 0) - { - EnterCriticalSection(((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->LoaderLock); - } - - LSTATUS lStatus = ERROR_SUCCESS; - - for (;;) - { - HMODULE hModule; - - if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) - { - const auto pRtlPcToFileHeader = try_get_RtlPcToFileHeader(); - if (!pRtlPcToFileHeader) - { - lStatus = ERROR_NOT_SUPPORTED; - break; - } - - hModule = (HMODULE)pRtlPcToFileHeader((PVOID)lpModuleName, (PVOID*)&hModule); - } - else - { - hModule = GetModuleHandleW(lpModuleName); - } - - if (hModule == nullptr) - { - lStatus = ERROR_DLL_NOT_FOUND; - break; - } - - if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) - { - - } - else - { - const auto pLdrAddRefDll = try_get_LdrAddRefDll(); - if (!pLdrAddRefDll) - { - lStatus = ERROR_NOT_SUPPORTED; - break; - } - - auto Status = pLdrAddRefDll(dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN, hModule); - if (Status < 0) - { - lStatus = internal::BaseSetLastNTError(Status); - break; - } - } - - *phModule = hModule; - - break; - } - - if ((dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) == 0) - { - LeaveCriticalSection(((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->LoaderLock); - } - - if (lStatus) - { - SetLastError(lStatus); - return FALSE; - } - else - { - return TRUE; - } - } +#if (YY_Thunks_Target < __WindowsNT5_1) + + //Windows XP [desktop apps only] + //Windows Server 2003 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 12, + BOOL, + WINAPI, + GetModuleHandleExW, + _In_ DWORD dwFlags, + _In_opt_ LPCWSTR lpModuleName, + _Out_ HMODULE* phModule + ) + { + if (const auto pGetModuleHandleExW = try_get_GetModuleHandleExW()) + { + return pGetModuleHandleExW(dwFlags, lpModuleName, phModule); + } + + BasepGetModuleHandleExParameterValidation(dwFlags, lpModuleName, phModule); + + if ((dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) == 0) + { + EnterCriticalSection(((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->LoaderLock); + } + + LSTATUS lStatus = ERROR_SUCCESS; + + for (;;) + { + HMODULE hModule; + + if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) + { + const auto pRtlPcToFileHeader = try_get_RtlPcToFileHeader(); + if (!pRtlPcToFileHeader) + { + lStatus = ERROR_NOT_SUPPORTED; + break; + } + + hModule = (HMODULE)pRtlPcToFileHeader((PVOID)lpModuleName, (PVOID*)&hModule); + } + else + { + hModule = GetModuleHandleW(lpModuleName); + } + + if (hModule == nullptr) + { + lStatus = ERROR_DLL_NOT_FOUND; + break; + } + + if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) + { + + } + else + { + const auto pLdrAddRefDll = try_get_LdrAddRefDll(); + if (!pLdrAddRefDll) + { + lStatus = ERROR_NOT_SUPPORTED; + break; + } + + auto Status = pLdrAddRefDll(dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN, hModule); + if (Status < 0) + { + lStatus = internal::BaseSetLastNTError(Status); + break; + } + } + + *phModule = hModule; + + break; + } + + if ((dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) == 0) + { + LeaveCriticalSection(((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->LoaderLock); + } + + if (lStatus) + { + SetLastError(lStatus); + return FALSE; + } + else + { + return TRUE; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - //虽然这个早就有了,但是只有Windows 8以及打了KB2533623补丁的系统才支持 LOAD_LIBRARY_SEARCH_SYSTEM32 等特性 - __DEFINE_THUNK( - kernel32, - 12, - _Ret_maybenull_ - HMODULE, - WINAPI, - LoadLibraryExW, - _In_ LPCWSTR lpLibFileName, - _Reserved_ HANDLE hFile, - _In_ DWORD dwFlags - ) - { - const auto pLoadLibraryExW = try_get_LoadLibraryExW(); + //虽然这个早就有了,但是只有Windows 8以及打了KB2533623补丁的系统才支持 LOAD_LIBRARY_SEARCH_SYSTEM32 等特性 + __DEFINE_THUNK( + kernel32, + 12, + _Ret_maybenull_ + HMODULE, + WINAPI, + LoadLibraryExW, + _In_ LPCWSTR lpLibFileName, + _Reserved_ HANDLE hFile, + _In_ DWORD dwFlags + ) + { + const auto pLoadLibraryExW = try_get_LoadLibraryExW(); - if (!pLoadLibraryExW) - { - SetLastError(ERROR_FUNCTION_FAILED); - return nullptr; - } + if (!pLoadLibraryExW) + { + SetLastError(ERROR_FUNCTION_FAILED); + return nullptr; + } - if (dwFlags == 0 || try_get_AddDllDirectory() != nullptr) - { - //存在AddDllDirectory说明支持 LOAD_LIBRARY_SEARCH_SYSTEM32 等功能,直接调用pLoadLibraryExW即可。 + if (dwFlags == 0 || try_get_AddDllDirectory() != nullptr) + { + //存在AddDllDirectory说明支持 LOAD_LIBRARY_SEARCH_SYSTEM32 等功能,直接调用pLoadLibraryExW即可。 - auto _hModule = pLoadLibraryExW(lpLibFileName, hFile, dwFlags); + auto _hModule = pLoadLibraryExW(lpLibFileName, hFile, dwFlags); if (_hModule) return _hModule; return Fallback::ForwardDll(lpLibFileName); - } - -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - //Windows Vista开始才支持 LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE | LOAD_LIBRARY_AS_IMAGE_RESOURCE,对于不支持的系统我们只能Fallblack到 LOAD_LIBRARY_AS_DATAFILE - if (dwFlags & (LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE | LOAD_LIBRARY_AS_IMAGE_RESOURCE)) - { - auto pPeb = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock; - - if (pPeb->OSMajorVersion < 6) - { - dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE | LOAD_LIBRARY_AS_IMAGE_RESOURCE); - dwFlags |= LOAD_LIBRARY_AS_DATAFILE; - } - } + } + +#if (YY_Thunks_Target < __WindowsNT6) + //Windows Vista开始才支持 LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE | LOAD_LIBRARY_AS_IMAGE_RESOURCE,对于不支持的系统我们只能Fallblack到 LOAD_LIBRARY_AS_DATAFILE + if (dwFlags & (LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE | LOAD_LIBRARY_AS_IMAGE_RESOURCE)) + { + auto pPeb = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock; + + if (pPeb->OSMajorVersion < 6) + { + dwFlags &= ~(LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE | LOAD_LIBRARY_AS_IMAGE_RESOURCE); + dwFlags |= LOAD_LIBRARY_AS_DATAFILE; + } + } #endif - wchar_t szFilePathBuffer[1024]; + wchar_t szFilePathBuffer[1024]; + + + + do + { + auto dwLoadLibrarySearchFlags = dwFlags & 0xFFFFFF00; + + if (dwLoadLibrarySearchFlags == 0) + { + break; + } + + if (((LOAD_WITH_ALTERED_SEARCH_PATH | 0xFFFFE000 | 0x00000004) & dwFlags) || lpLibFileName == nullptr || hFile) + { + //LOAD_WITH_ALTERED_SEARCH_PATH 标记不允许跟其他标记组合使用 + //0xFFFFE000 为 其他不支持的数值 + //LOAD_PACKAGED_LIBRARY: 0x00000004 Windows 8以上平台才支持 + SetLastError(ERROR_INVALID_PARAMETER); + return nullptr; + } + + dwFlags &= 0xFF; + + //LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_USER_DIRS | LOAD_LIBRARY_SEARCH_SYSTEM32 等价于 LOAD_LIBRARY_SEARCH_DEFAULT_DIRS标记 + if (dwLoadLibrarySearchFlags & LOAD_LIBRARY_SEARCH_DEFAULT_DIRS) + dwLoadLibrarySearchFlags = (dwLoadLibrarySearchFlags & ~LOAD_LIBRARY_SEARCH_DEFAULT_DIRS) | (LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_USER_DIRS | LOAD_LIBRARY_SEARCH_SYSTEM32); + + + + if (dwLoadLibrarySearchFlags == (LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_USER_DIRS | LOAD_LIBRARY_SEARCH_SYSTEM32)) + { + //如果确定是调用默认体系,则直接调用原始 LoadLibraryExW + + break; + } + + const auto pRtlDetermineDosPathNameType_U = try_get_RtlDetermineDosPathNameType_U(); + + const auto PathType = pRtlDetermineDosPathNameType_U ? pRtlDetermineDosPathNameType_U(lpLibFileName) : RtlPathTypeUnknown; + + if (dwLoadLibrarySearchFlags & LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) + { + //必须是一个完整路径! + if (PathType == RtlPathTypeUnknown || PathType == RtlPathTypeDriveRelative || PathType == RtlPathTypeRelative) + { + SetLastError(ERROR_INVALID_PARAMETER); + return nullptr; + } + if (dwLoadLibrarySearchFlags == (LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_USER_DIRS | LOAD_LIBRARY_SEARCH_SYSTEM32)) + { + //LOAD_WITH_ALTERED_SEARCH_PATH参数能模拟 LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_USER_DIRS | LOAD_LIBRARY_SEARCH_SYSTEM32 组合效果。 + dwFlags |= LOAD_WITH_ALTERED_SEARCH_PATH; + break; + } + } + + + if (LOAD_LIBRARY_SEARCH_USER_DIRS & dwLoadLibrarySearchFlags) + { + //LOAD_LIBRARY_SEARCH_USER_DIRS 无法顺利实现,索性无效参数处理 + SetLastError(ERROR_INVALID_PARAMETER); + return nullptr; + } + + + + + if (dwFlags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)) + { + //以资源方式加载 + + //判断路径是一个绝对路径还是一个相对路径,如果是绝对路径,那么可以直接无视 LOAD_LIBRARY_SEARCH_ 系列参数。 + if ((PathType == RtlPathTypeUnknown || PathType == RtlPathTypeDriveRelative || PathType == RtlPathTypeRelative) == false) + { + //是一个绝对路径,我们直接传递给 pLoadLibraryExW 即可 + + break; + } + + if (dwLoadLibrarySearchFlags & LOAD_LIBRARY_SEARCH_APPLICATION_DIR) + { + auto nSize = GetModuleFileNameW(NULL, szFilePathBuffer, _countof(szFilePathBuffer)); + + if (nSize == 0 || nSize >= _countof(szFilePathBuffer)) + { + SetLastError(ERROR_FUNCTION_FAILED); + return nullptr; + } + + for (;;) + { + if (szFilePathBuffer[nSize] == L'\\' || szFilePathBuffer[nSize] == L'/') + { + ++nSize; + break; + } + + if (nSize == 0) + { + SetLastError(ERROR_FUNCTION_FAILED); + return nullptr; + } + + --nSize; + } + + + for (auto Str = lpLibFileName; *Str; ++Str, ++nSize) + { + if (nSize >= _countof(szFilePathBuffer)) + { + SetLastError(ERROR_FUNCTION_FAILED); + return nullptr; + } + + szFilePathBuffer[nSize] = *Str; + } + + szFilePathBuffer[nSize] = L'\0'; + + + if (GetFileAttributesW(szFilePathBuffer) != -1) + { + lpLibFileName = szFilePathBuffer; + break; + } + } + + if (dwLoadLibrarySearchFlags & LOAD_LIBRARY_SEARCH_SYSTEM32) + { + auto nSize = GetSystemDirectoryW(szFilePathBuffer, _countof(szFilePathBuffer)); + if (nSize == 0 || nSize >= _countof(szFilePathBuffer)) + { + SetLastError(ERROR_FUNCTION_FAILED); + return nullptr; + } - do - { - auto dwLoadLibrarySearchFlags = dwFlags & 0xFFFFFF00; + if (szFilePathBuffer[nSize] != L'\\') + { + if (nSize >= _countof(szFilePathBuffer)) + { + SetLastError(ERROR_FUNCTION_FAILED); + return nullptr; + } - if (dwLoadLibrarySearchFlags == 0) - { - break; - } + szFilePathBuffer[++nSize] = L'\\'; + } - if (((LOAD_WITH_ALTERED_SEARCH_PATH | 0xFFFFE000 | 0x00000004) & dwFlags) || lpLibFileName == nullptr || hFile) - { - //LOAD_WITH_ALTERED_SEARCH_PATH 标记不允许跟其他标记组合使用 - //0xFFFFE000 为 其他不支持的数值 - //LOAD_PACKAGED_LIBRARY: 0x00000004 Windows 8以上平台才支持 - SetLastError(ERROR_INVALID_PARAMETER); - return nullptr; - } + for (auto Str = lpLibFileName; *Str; ++Str, ++nSize) + { + if (nSize >= _countof(szFilePathBuffer)) + { + SetLastError(ERROR_FUNCTION_FAILED); + return nullptr; + } - dwFlags &= 0xFF; + szFilePathBuffer[nSize] = *Str; + } - //LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_USER_DIRS | LOAD_LIBRARY_SEARCH_SYSTEM32 等价于 LOAD_LIBRARY_SEARCH_DEFAULT_DIRS标记 - if (dwLoadLibrarySearchFlags & LOAD_LIBRARY_SEARCH_DEFAULT_DIRS) - dwLoadLibrarySearchFlags = (dwLoadLibrarySearchFlags & ~LOAD_LIBRARY_SEARCH_DEFAULT_DIRS) | (LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_USER_DIRS | LOAD_LIBRARY_SEARCH_SYSTEM32); + szFilePathBuffer[nSize] = L'\0'; + if (GetFileAttributesW(szFilePathBuffer) != -1) + { + lpLibFileName = szFilePathBuffer; + break; + } + } + SetLastError(ERROR_MOD_NOT_FOUND); + return nullptr; + } - if (dwLoadLibrarySearchFlags == (LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_USER_DIRS | LOAD_LIBRARY_SEARCH_SYSTEM32)) - { - //如果确定是调用默认体系,则直接调用原始 LoadLibraryExW - break; - } + //以模块方式加载 - const auto pRtlDetermineDosPathNameType_U = try_get_RtlDetermineDosPathNameType_U(); + const auto pLdrLoadDll = try_get_LdrLoadDll(); + if (!pLdrLoadDll) + { + SetLastError(ERROR_FUNCTION_FAILED); + return nullptr; + } - const auto PathType = pRtlDetermineDosPathNameType_U ? pRtlDetermineDosPathNameType_U(lpLibFileName) : RtlPathTypeUnknown; + DWORD nSize = 0; - if (dwLoadLibrarySearchFlags & LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) - { - //必须是一个完整路径! - if (PathType == RtlPathTypeUnknown || PathType == RtlPathTypeDriveRelative || PathType == RtlPathTypeRelative) - { - SetLastError(ERROR_INVALID_PARAMETER); - return nullptr; - } + if (dwLoadLibrarySearchFlags & LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) + { + for (auto Str = lpLibFileName; *Str; ++Str, ++nSize) + { + if (nSize >= _countof(szFilePathBuffer)) + { + SetLastError(ERROR_FUNCTION_FAILED); + return nullptr; + } - if (dwLoadLibrarySearchFlags == (LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_USER_DIRS | LOAD_LIBRARY_SEARCH_SYSTEM32)) - { - //LOAD_WITH_ALTERED_SEARCH_PATH参数能模拟 LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_USER_DIRS | LOAD_LIBRARY_SEARCH_SYSTEM32 组合效果。 - dwFlags |= LOAD_WITH_ALTERED_SEARCH_PATH; - break; - } - } + szFilePathBuffer[nSize] = *Str; + } + if (nSize == 0) + { + SetLastError(ERROR_FUNCTION_FAILED); + return nullptr; + } - if (LOAD_LIBRARY_SEARCH_USER_DIRS & dwLoadLibrarySearchFlags) - { - //LOAD_LIBRARY_SEARCH_USER_DIRS 无法顺利实现,索性无效参数处理 - SetLastError(ERROR_INVALID_PARAMETER); - return nullptr; - } + --nSize; + //反向剔除文件名 + for (;;) + { + if (szFilePathBuffer[nSize] == L'\\' || szFilePathBuffer[nSize] == L'/') + { + break; + } + if (nSize == 0) + { + SetLastError(ERROR_FUNCTION_FAILED); + return nullptr; + } + --nSize; + } + ++nSize; + szFilePathBuffer[nSize] = L';'; + ++nSize; + } - if (dwFlags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)) - { - //以资源方式加载 + if (dwLoadLibrarySearchFlags & LOAD_LIBRARY_SEARCH_APPLICATION_DIR) + { + const DWORD nBufferMax = _countof(szFilePathBuffer) - nSize; - //判断路径是一个绝对路径还是一个相对路径,如果是绝对路径,那么可以直接无视 LOAD_LIBRARY_SEARCH_ 系列参数。 - if ((PathType == RtlPathTypeUnknown || PathType == RtlPathTypeDriveRelative || PathType == RtlPathTypeRelative) == false) - { - //是一个绝对路径,我们直接传递给 pLoadLibraryExW 即可 + auto nBuffer = GetModuleFileNameW(NULL, szFilePathBuffer + nSize, nBufferMax); - break; - } + if (nBuffer == 0 || nBuffer >= nBufferMax) + { + SetLastError(ERROR_FUNCTION_FAILED); + return nullptr; + } - if (dwLoadLibrarySearchFlags & LOAD_LIBRARY_SEARCH_APPLICATION_DIR) - { - auto nSize = GetModuleFileNameW(NULL, szFilePathBuffer, _countof(szFilePathBuffer)); + nSize += nBuffer - 1; - if (nSize == 0 || nSize >= _countof(szFilePathBuffer)) - { - SetLastError(ERROR_FUNCTION_FAILED); - return nullptr; - } + for (;;) + { + if (szFilePathBuffer[nSize] == L'\\' || szFilePathBuffer[nSize] == L'/') + { + break; + } - for (;;) - { - if (szFilePathBuffer[nSize] == L'\\' || szFilePathBuffer[nSize] == L'/') - { - ++nSize; - break; - } + if (nSize == 0) + { + SetLastError(ERROR_FUNCTION_FAILED); + return nullptr; + } - if (nSize == 0) - { - SetLastError(ERROR_FUNCTION_FAILED); - return nullptr; - } - - --nSize; - } - - - for (auto Str = lpLibFileName; *Str; ++Str, ++nSize) - { - if (nSize >= _countof(szFilePathBuffer)) - { - SetLastError(ERROR_FUNCTION_FAILED); - return nullptr; - } - - szFilePathBuffer[nSize] = *Str; - } - - szFilePathBuffer[nSize] = L'\0'; - - - if (GetFileAttributesW(szFilePathBuffer) != -1) - { - lpLibFileName = szFilePathBuffer; - break; - } - } - - if (dwLoadLibrarySearchFlags & LOAD_LIBRARY_SEARCH_SYSTEM32) - { - auto nSize = GetSystemDirectoryW(szFilePathBuffer, _countof(szFilePathBuffer)); - - if (nSize == 0 || nSize >= _countof(szFilePathBuffer)) - { - SetLastError(ERROR_FUNCTION_FAILED); - return nullptr; - } - - if (szFilePathBuffer[nSize] != L'\\') - { - if (nSize >= _countof(szFilePathBuffer)) - { - SetLastError(ERROR_FUNCTION_FAILED); - return nullptr; - } - - szFilePathBuffer[++nSize] = L'\\'; - } - - for (auto Str = lpLibFileName; *Str; ++Str, ++nSize) - { - if (nSize >= _countof(szFilePathBuffer)) - { - SetLastError(ERROR_FUNCTION_FAILED); - return nullptr; - } - - szFilePathBuffer[nSize] = *Str; - } - - szFilePathBuffer[nSize] = L'\0'; - - if (GetFileAttributesW(szFilePathBuffer) != -1) - { - lpLibFileName = szFilePathBuffer; - break; - } - } - - SetLastError(ERROR_MOD_NOT_FOUND); - return nullptr; - } - - - //以模块方式加载 - - const auto pLdrLoadDll = try_get_LdrLoadDll(); - if (!pLdrLoadDll) - { - SetLastError(ERROR_FUNCTION_FAILED); - return nullptr; - } - - DWORD nSize = 0; - - if (dwLoadLibrarySearchFlags & LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) - { - for (auto Str = lpLibFileName; *Str; ++Str, ++nSize) - { - if (nSize >= _countof(szFilePathBuffer)) - { - SetLastError(ERROR_FUNCTION_FAILED); - return nullptr; - } - - szFilePathBuffer[nSize] = *Str; - } - - if (nSize == 0) - { - SetLastError(ERROR_FUNCTION_FAILED); - return nullptr; - } - - --nSize; - //反向剔除文件名 - for (;;) - { - if (szFilePathBuffer[nSize] == L'\\' || szFilePathBuffer[nSize] == L'/') - { - break; - } - - if (nSize == 0) - { - SetLastError(ERROR_FUNCTION_FAILED); - return nullptr; - } - - --nSize; - } - - ++nSize; - szFilePathBuffer[nSize] = L';'; - ++nSize; - } - - if (dwLoadLibrarySearchFlags & LOAD_LIBRARY_SEARCH_APPLICATION_DIR) - { - const DWORD nBufferMax = _countof(szFilePathBuffer) - nSize; - - auto nBuffer = GetModuleFileNameW(NULL, szFilePathBuffer + nSize, nBufferMax); - - if (nBuffer == 0 || nBuffer >= nBufferMax) - { - SetLastError(ERROR_FUNCTION_FAILED); - return nullptr; - } - - nSize += nBuffer - 1; - - for (;;) - { - if (szFilePathBuffer[nSize] == L'\\' || szFilePathBuffer[nSize] == L'/') - { - break; - } - - if (nSize == 0) - { - SetLastError(ERROR_FUNCTION_FAILED); - return nullptr; - } - - --nSize; - } - - ++nSize; - szFilePathBuffer[nSize] = L';'; - ++nSize; - } - - if (dwLoadLibrarySearchFlags & LOAD_LIBRARY_SEARCH_SYSTEM32) - { - const DWORD nBufferMax = _countof(szFilePathBuffer) - nSize; - - auto nBuffer = GetSystemDirectoryW(szFilePathBuffer + nSize, nBufferMax); - - if (nBuffer == 0 || nBuffer >= nBufferMax) - { - SetLastError(ERROR_FUNCTION_FAILED); - return nullptr; - } - - nSize += nBuffer; - } - - szFilePathBuffer[nSize] = L'\0'; - - UNICODE_STRING ModuleFileName; - ModuleFileName.Buffer = (PWSTR)lpLibFileName; - - for (; *lpLibFileName; ++lpLibFileName); + --nSize; + } + + ++nSize; + szFilePathBuffer[nSize] = L';'; + ++nSize; + } + + if (dwLoadLibrarySearchFlags & LOAD_LIBRARY_SEARCH_SYSTEM32) + { + const DWORD nBufferMax = _countof(szFilePathBuffer) - nSize; + + auto nBuffer = GetSystemDirectoryW(szFilePathBuffer + nSize, nBufferMax); + + if (nBuffer == 0 || nBuffer >= nBufferMax) + { + SetLastError(ERROR_FUNCTION_FAILED); + return nullptr; + } + + nSize += nBuffer; + } + + szFilePathBuffer[nSize] = L'\0'; + + UNICODE_STRING ModuleFileName; + ModuleFileName.Buffer = (PWSTR)lpLibFileName; + + for (; *lpLibFileName; ++lpLibFileName); const auto _uNewLength = (lpLibFileName - ModuleFileName.Buffer) * sizeof(lpLibFileName[0]); if (_uNewLength + sizeof(lpLibFileName[0]) > MAXUINT16) { @@ -669,199 +669,199 @@ namespace YY::Thunks return nullptr; } - ModuleFileName.Length = static_cast(_uNewLength); - ModuleFileName.MaximumLength = ModuleFileName.Length + sizeof(lpLibFileName[0]); + ModuleFileName.Length = static_cast(_uNewLength); + ModuleFileName.MaximumLength = ModuleFileName.Length + sizeof(lpLibFileName[0]); - HMODULE hModule = NULL; + HMODULE hModule = NULL; - ULONG dwLdrLoadDllFlags = 0; + ULONG dwLdrLoadDllFlags = 0; - if (dwFlags & DONT_RESOLVE_DLL_REFERENCES) - { - dwLdrLoadDllFlags |= 0x2; - } + if (dwFlags & DONT_RESOLVE_DLL_REFERENCES) + { + dwLdrLoadDllFlags |= 0x2; + } - if (dwFlags & LOAD_IGNORE_CODE_AUTHZ_LEVEL) - { - dwLdrLoadDllFlags |= 0x1000; - } + if (dwFlags & LOAD_IGNORE_CODE_AUTHZ_LEVEL) + { + dwLdrLoadDllFlags |= 0x1000; + } - if (dwFlags & LOAD_LIBRARY_REQUIRE_SIGNED_TARGET) - { - dwLdrLoadDllFlags |= 0x800000; - } + if (dwFlags & LOAD_LIBRARY_REQUIRE_SIGNED_TARGET) + { + dwLdrLoadDllFlags |= 0x800000; + } #if defined(_X86_) || defined(_M_IX86) - //我们先关闭重定向,再加载DLL,Windows 7 SP1以前的系统不会关闭重定向,而导致某些线程关闭重定向后DLL加载问题。 - PVOID OldFsRedirectionLevel; + //我们先关闭重定向,再加载DLL,Windows 7 SP1以前的系统不会关闭重定向,而导致某些线程关闭重定向后DLL加载问题。 + PVOID OldFsRedirectionLevel; - auto pRtlWow64EnableFsRedirectionEx = try_get_RtlWow64EnableFsRedirectionEx(); - auto StatusFsRedir = pRtlWow64EnableFsRedirectionEx ? pRtlWow64EnableFsRedirectionEx(nullptr, &OldFsRedirectionLevel) : 0; + auto pRtlWow64EnableFsRedirectionEx = try_get_RtlWow64EnableFsRedirectionEx(); + auto StatusFsRedir = pRtlWow64EnableFsRedirectionEx ? pRtlWow64EnableFsRedirectionEx(nullptr, &OldFsRedirectionLevel) : 0; #endif - auto Status = pLdrLoadDll(szFilePathBuffer, &dwLdrLoadDllFlags, &ModuleFileName, &hModule); + auto Status = pLdrLoadDll(szFilePathBuffer, &dwLdrLoadDllFlags, &ModuleFileName, &hModule); #if defined(_X86_) || defined(_M_IX86) - if (StatusFsRedir >= 0 && pRtlWow64EnableFsRedirectionEx) - pRtlWow64EnableFsRedirectionEx(OldFsRedirectionLevel, &OldFsRedirectionLevel); + if (StatusFsRedir >= 0 && pRtlWow64EnableFsRedirectionEx) + pRtlWow64EnableFsRedirectionEx(OldFsRedirectionLevel, &OldFsRedirectionLevel); #endif - if (Status < 0) - { - YY::Thunks::internal::BaseSetLastNTError(Status); - } + if (Status < 0) + { + YY::Thunks::internal::BaseSetLastNTError(Status); + } if (hModule) return hModule; return Fallback::ForwardDll(lpLibFileName); - } while (false); + } while (false); #if defined(_X86_) || defined(_M_IX86) - //我们先关闭重定向,再加载DLL,Windows 7 SP1以前的系统不会关闭重定向,而导致某些线程关闭重定向后DLL加载问题。 - PVOID OldFsRedirectionLevel; + //我们先关闭重定向,再加载DLL,Windows 7 SP1以前的系统不会关闭重定向,而导致某些线程关闭重定向后DLL加载问题。 + PVOID OldFsRedirectionLevel; - auto pRtlWow64EnableFsRedirectionEx = try_get_RtlWow64EnableFsRedirectionEx(); - auto StatusFsRedir = pRtlWow64EnableFsRedirectionEx ? pRtlWow64EnableFsRedirectionEx(nullptr, &OldFsRedirectionLevel) : 0; + auto pRtlWow64EnableFsRedirectionEx = try_get_RtlWow64EnableFsRedirectionEx(); + auto StatusFsRedir = pRtlWow64EnableFsRedirectionEx ? pRtlWow64EnableFsRedirectionEx(nullptr, &OldFsRedirectionLevel) : 0; #endif - auto hModule = pLoadLibraryExW(lpLibFileName, hFile, dwFlags); + auto hModule = pLoadLibraryExW(lpLibFileName, hFile, dwFlags); #if defined(_X86_) || defined(_M_IX86) - if (StatusFsRedir >= 0 && pRtlWow64EnableFsRedirectionEx) - { - LSTATUS lStatus = GetLastError(); - pRtlWow64EnableFsRedirectionEx(OldFsRedirectionLevel, &OldFsRedirectionLevel); - SetLastError(lStatus); - } + if (StatusFsRedir >= 0 && pRtlWow64EnableFsRedirectionEx) + { + LSTATUS lStatus = GetLastError(); + pRtlWow64EnableFsRedirectionEx(OldFsRedirectionLevel, &OldFsRedirectionLevel); + SetLastError(lStatus); + } #endif if(hModule) return hModule; return Fallback::ForwardDll(lpLibFileName); - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - //虽然这个早就有了,但是只有Windows 8以及打了KB2533623补丁的系统才支持 LOAD_LIBRARY_SEARCH_SYSTEM32 等特性 - __DEFINE_THUNK( - kernel32, - 12, - _Ret_maybenull_ - HMODULE, - WINAPI, - LoadLibraryExA, - _In_ LPCSTR lpLibFileName, - _Reserved_ HANDLE hFile, - _In_ DWORD dwFlags - ) - { - const auto pLoadLibraryExA = try_get_LoadLibraryExA(); + //虽然这个早就有了,但是只有Windows 8以及打了KB2533623补丁的系统才支持 LOAD_LIBRARY_SEARCH_SYSTEM32 等特性 + __DEFINE_THUNK( + kernel32, + 12, + _Ret_maybenull_ + HMODULE, + WINAPI, + LoadLibraryExA, + _In_ LPCSTR lpLibFileName, + _Reserved_ HANDLE hFile, + _In_ DWORD dwFlags + ) + { + const auto pLoadLibraryExA = try_get_LoadLibraryExA(); - if (!pLoadLibraryExA) - { - SetLastError(ERROR_FUNCTION_FAILED); - return nullptr; - } + if (!pLoadLibraryExA) + { + SetLastError(ERROR_FUNCTION_FAILED); + return nullptr; + } - if (dwFlags == 0 || try_get_AddDllDirectory() != nullptr) - { - //存在AddDllDirectory说明支持 LOAD_LIBRARY_SEARCH_SYSTEM32 等功能,直接调用pLoadLibraryExW即可。 + if (dwFlags == 0 || try_get_AddDllDirectory() != nullptr) + { + //存在AddDllDirectory说明支持 LOAD_LIBRARY_SEARCH_SYSTEM32 等功能,直接调用pLoadLibraryExW即可。 - auto _hModule = pLoadLibraryExA(lpLibFileName, hFile, dwFlags); + auto _hModule = pLoadLibraryExA(lpLibFileName, hFile, dwFlags); if (_hModule) return _hModule; return Fallback::ForwardDll(lpLibFileName); - } + } - wchar_t szLibFileNameUnicode[512]; + wchar_t szLibFileNameUnicode[512]; - UNICODE_STRING usLibFileName = { 0, sizeof(szLibFileNameUnicode), szLibFileNameUnicode }; + UNICODE_STRING usLibFileName = { 0, sizeof(szLibFileNameUnicode), szLibFileNameUnicode }; - auto lStatus = internal::Basep8BitStringToStaticUnicodeString(&usLibFileName, lpLibFileName); - if (lStatus != ERROR_SUCCESS) - { - SetLastError(lStatus); - return nullptr; - } + auto lStatus = internal::Basep8BitStringToStaticUnicodeString(&usLibFileName, lpLibFileName); + if (lStatus != ERROR_SUCCESS) + { + SetLastError(lStatus); + return nullptr; + } - return LoadLibraryExW(szLibFileNameUnicode, hFile, dwFlags); - } + return LoadLibraryExW(szLibFileNameUnicode, hFile, dwFlags); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - // Windows Vista [仅限桌面应用], Windows Server 2008 [仅限桌面应用] - __DEFINE_THUNK( - kernel32, - 28, - BOOL, - APIENTRY, - EnumResourceLanguagesExW, - _In_opt_ HMODULE _hModule, - _In_ LPCWSTR _lpType, - _In_ LPCWSTR _lpName, - _In_ ENUMRESLANGPROCW _lpEnumFunc, - _In_opt_ LONG_PTR _lParam, - DWORD _dwFlags, - LANGID _LangId - ) - { - const auto _pfnEnumResourceLanguagesExW = try_get_EnumResourceLanguagesExW(); - - if (_pfnEnumResourceLanguagesExW) - { - return _pfnEnumResourceLanguagesExW(_hModule, _lpType, _lpName, _lpEnumFunc, _lParam, _dwFlags, _LangId); - } - - // WinXP不支持MUI,故而忽略 _dwFlags、_LangId - return EnumResourceLanguagesW(_hModule, _lpType, _lpName, _lpEnumFunc, _lParam); - } +#if (YY_Thunks_Target < __WindowsNT6) + + // Windows Vista [仅限桌面应用], Windows Server 2008 [仅限桌面应用] + __DEFINE_THUNK( + kernel32, + 28, + BOOL, + APIENTRY, + EnumResourceLanguagesExW, + _In_opt_ HMODULE _hModule, + _In_ LPCWSTR _lpType, + _In_ LPCWSTR _lpName, + _In_ ENUMRESLANGPROCW _lpEnumFunc, + _In_opt_ LONG_PTR _lParam, + DWORD _dwFlags, + LANGID _LangId + ) + { + const auto _pfnEnumResourceLanguagesExW = try_get_EnumResourceLanguagesExW(); + + if (_pfnEnumResourceLanguagesExW) + { + return _pfnEnumResourceLanguagesExW(_hModule, _lpType, _lpName, _lpEnumFunc, _lParam, _dwFlags, _LangId); + } + + // WinXP不支持MUI,故而忽略 _dwFlags、_LangId + return EnumResourceLanguagesW(_hModule, _lpType, _lpName, _lpEnumFunc, _lParam); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - // Windows Vista [仅限桌面应用], Windows Server 2008 [仅限桌面应用] - __DEFINE_THUNK( - kernel32, - 28, - BOOL, - APIENTRY, - EnumResourceLanguagesExA, - _In_opt_ HMODULE _hModule, - _In_ LPCSTR _lpType, - _In_ LPCSTR _lpName, - _In_ ENUMRESLANGPROCA _lpEnumFunc, - _In_opt_ LONG_PTR _lParam, - DWORD _dwFlags, - LANGID _LangId - ) - { - const auto _pfnEnumResourceLanguagesExA = try_get_EnumResourceLanguagesExA(); - - if (_pfnEnumResourceLanguagesExA) - { - return _pfnEnumResourceLanguagesExA(_hModule, _lpType, _lpName, _lpEnumFunc, _lParam, _dwFlags, _LangId); - } - - // WinXP不支持MUI,故而忽略 _dwFlags、_LangId - return EnumResourceLanguagesA(_hModule, _lpType, _lpName, _lpEnumFunc, _lParam); - } +#if (YY_Thunks_Target < __WindowsNT6) + + // Windows Vista [仅限桌面应用], Windows Server 2008 [仅限桌面应用] + __DEFINE_THUNK( + kernel32, + 28, + BOOL, + APIENTRY, + EnumResourceLanguagesExA, + _In_opt_ HMODULE _hModule, + _In_ LPCSTR _lpType, + _In_ LPCSTR _lpName, + _In_ ENUMRESLANGPROCA _lpEnumFunc, + _In_opt_ LONG_PTR _lParam, + DWORD _dwFlags, + LANGID _LangId + ) + { + const auto _pfnEnumResourceLanguagesExA = try_get_EnumResourceLanguagesExA(); + + if (_pfnEnumResourceLanguagesExA) + { + return _pfnEnumResourceLanguagesExA(_hModule, _lpType, _lpName, _lpEnumFunc, _lParam, _dwFlags, _LangId); + } + + // WinXP不支持MUI,故而忽略 _dwFlags、_LangId + return EnumResourceLanguagesA(_hModule, _lpType, _lpName, _lpEnumFunc, _lParam); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) - // 最低受支持的客户端 Windows 7 [桌面应用 |UWP 应用] + // 最低受支持的客户端 Windows 7 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2008 R2[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 24, + __DEFINE_THUNK( + kernel32, + 24, int, WINAPI, FindStringOrdinal, @@ -871,12 +871,12 @@ namespace YY::Thunks _In_reads_(_cchValue) LPCWSTR _pStringValue, _In_ int _cchValue, _In_ BOOL _bIgnoreCase - ) - { - if (const auto _pfnFindStringOrdinal = try_get_FindStringOrdinal()) - { - return _pfnFindStringOrdinal(_uFindStringOrdinalFlags, _pStringSource, _cchSource, _pStringValue, _cchValue, _bIgnoreCase); - } + ) + { + if (const auto _pfnFindStringOrdinal = try_get_FindStringOrdinal()) + { + return _pfnFindStringOrdinal(_uFindStringOrdinalFlags, _pStringSource, _cchSource, _pStringValue, _cchValue, _bIgnoreCase); + } SetLastError(ERROR_SUCCESS); if (_pStringSource == nullptr || _cchSource < -1 || _pStringValue == nullptr || _cchValue < -1) @@ -948,23 +948,23 @@ namespace YY::Thunks return -1; break; } - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows XP [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] __DEFINE_THUNK( kernel32, 4, - BOOL, + BOOL, WINAPI, DisableThreadLibraryCalls, _In_ HMODULE _hLibModule - ) - { + ) + { // 虽然XP已经支持这个函数,但是Windows XP动态加载的DLL依靠的是DllMainCRTStartupForYY_Thunks通知做的。 // 强制依赖于ThreadLibraryCalls,我们不能正真的禁用它。 if (internal::g_TlsMode != internal::TlsMode::ByDllMainCRTStartupForYY_Thunks) @@ -975,12 +975,12 @@ namespace YY::Thunks } } - return TRUE; - } + return TRUE; + } #endif -#if defined(__ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng) && YY_Thunks_Support_Version < NTDDI_WIN8 +#if defined(__ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng) && YY_Thunks_Target < __WindowsNT6_2 // 所有系统都支持,但是这个函数的存在是为了能顺利取到 ProcessPrng,Windows 8开始原生支持ProcessPrng __DEFINE_THUNK( @@ -993,7 +993,7 @@ namespace YY::Thunks _In_ LPCSTR lpProcName ) { -#if defined(__ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng) && YY_Thunks_Support_Version < NTDDI_WIN8 +#if defined(__ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng) && YY_Thunks_Target < __WindowsNT6_2 if (uintptr_t(lpProcName) > UINT16_MAX) { if (StringCompare(lpProcName, "ProcessPrng", -1) == 0) @@ -1018,7 +1018,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 所有系统都支持,但是现在为了支持 SetDefaultDllDirectories就Thunk下 __DEFINE_THUNK( @@ -1053,7 +1053,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 所有系统都支持,但是现在为了支持 SetDefaultDllDirectories __DEFINE_THUNK( @@ -1088,7 +1088,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8 [仅限桌面应用],在 Windows 7、Windows Server 2008 R2、Windows Vista 和 Windows Server 2008 上KB2533623 // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] diff --git a/src/Thunks/api-ms-win-core-localization.hpp b/src/Thunks/api-ms-win-core-localization.hpp index f285ec8..3fe00b9 100644 --- a/src/Thunks/api-ms-win-core-localization.hpp +++ b/src/Thunks/api-ms-win-core-localization.hpp @@ -1,6 +1,6 @@ namespace YY::Thunks { -#if defined(YY_Thunks_Implemented) && (YY_Thunks_Support_Version < NTDDI_WIN6) +#if defined(YY_Thunks_Implemented) && (YY_Thunks_Target < __WindowsNT6) namespace internal { namespace @@ -884,1416 +884,1416 @@ } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - kernel32, - 8, - LCID, - WINAPI, - LocaleNameToLCID, - _In_ LPCWSTR lpName, - _In_ DWORD dwFlags - ) - { - if (auto pLocaleNameToLCID = try_get_LocaleNameToLCID()) - { - return pLocaleNameToLCID(lpName, dwFlags); - } - - //UNREFRENCED_PARAMETER(dwFlags); - - if (lpName == nullptr) - { - return GetUserDefaultLCID(); - } - else if (StringCompareIgnoreCaseByAscii(lpName, LOCALE_NAME_SYSTEM_DEFAULT, _countof(LOCALE_NAME_SYSTEM_DEFAULT)) == 0) - { - return GetSystemDefaultLCID(); - } - - //Vista虽然不支持 LOCALE_ALLOW_NEUTRAL_NAMES,但是我们好人做到底,就直接支持了吧。 - if ((LOCALE_ALLOW_NEUTRAL_NAMES & dwFlags) == 0) - { - lpName = internal::DownlevelNeutralToSpecificLocaleName(lpName); - } - - // Map of locale name to LCID. - struct LocaleNameToLcid - { - const wchar_t* localeName; - LCID lcid; - }; - - - // Map of locale name to an index in LcidToLocaleNameTable, for Windows XP. - // Data in this table has been obtained from National Language Support (NLS) API Reference at - // http://msdn.microsoft.com/en-us/goglobal/bb896001.aspx - // The table is sorted to improve search performance. - static const LocaleNameToLcid LocaleNameToLcidTable[] = - { - { L"", 0x0000007F }, - { L"af", 0x00000036 }, - { L"af-ZA", 0x00000436 }, - { L"am", 0x0000005E }, - { L"am-ET", 0x0000045E }, - { L"ar", 0x00000001 }, - { L"ar-AE", 0x00003801 }, - { L"ar-BH", 0x00003C01 }, - { L"ar-DZ", 0x00001401 }, - { L"ar-EG", 0x00000C01 }, - { L"ar-IQ", 0x00000801 }, - { L"ar-JO", 0x00002C01 }, - { L"ar-KW", 0x00003401 }, - { L"ar-LB", 0x00003001 }, - { L"ar-LY", 0x00001001 }, - { L"ar-MA", 0x00001801 }, - { L"ar-OM", 0x00002001 }, - { L"ar-QA", 0x00004001 }, - { L"ar-SA", 0x00000401 }, - { L"ar-SY", 0x00002801 }, - { L"ar-TN", 0x00001C01 }, - { L"ar-YE", 0x00002401 }, - { L"arn", 0x0000007A }, - { L"arn-CL", 0x0000047A }, - { L"as", 0x0000004D }, - { L"as-IN", 0x0000044D }, - { L"az", 0x0000002C }, - { L"az-Cyrl", 0x0000742C }, - { L"az-Cyrl-AZ", 0x0000082C }, - { L"az-Latn", 0x0000782C }, - { L"az-Latn-AZ", 0x0000042C }, - { L"ba", 0x0000006D }, - { L"ba-RU", 0x0000046D }, - { L"be", 0x00000023 }, - { L"be-BY", 0x00000423 }, - { L"bg", 0x00000002 }, - { L"bg-BG", 0x00000402 }, - { L"bn", 0x00000045 }, - { L"bn-BD", 0x00000845 }, - { L"bn-IN", 0x00000445 }, - { L"bo", 0x00000051 }, - { L"bo-CN", 0x00000451 }, - { L"br", 0x0000007E }, - { L"br-FR", 0x0000047E }, - { L"bs-Cyrl", 0x0000641A }, - { L"bs-Cyrl-BA", 0x0000201A }, - { L"bs-Latn", 0x0000681A }, - { L"bs-Latn-BA", 0x0000141A }, - { L"ca", 0x00000003 }, - { L"ca-ES", 0x00000403 }, - { L"co", 0x00000083 }, - { L"co-FR", 0x00000483 }, - { L"cs", 0x00000005 }, - { L"cs-CZ", 0x00000405 }, - { L"cy", 0x00000052 }, - { L"cy-GB", 0x00000452 }, - { L"da", 0x00000006 }, - { L"da-DK", 0x00000406 }, - { L"de", 0x00000007 }, - { L"de-AT", 0x00000C07 }, - { L"de-CH", 0x00000807 }, - { L"de-DE", 0x00000407 }, - { L"de-DE_phoneb", 0x00010407 }, - { L"de-LI", 0x00001407 }, - { L"de-LU", 0x00001007 }, - { L"dsb", 0x00007C2E }, - { L"dsb-DE", 0x0000082E }, - { L"dv", 0x00000065 }, - { L"dv-MV", 0x00000465 }, - { L"el", 0x00000008 }, - { L"el-GR", 0x00000408 }, - { L"en", 0x00000009 }, - { L"en-029", 0x00002409 }, - { L"en-AU", 0x00000C09 }, - { L"en-BZ", 0x00002809 }, - { L"en-CA", 0x00001009 }, - { L"en-GB", 0x00000809 }, - { L"en-IE", 0x00001809 }, - { L"en-IN", 0x00004009 }, - { L"en-JM", 0x00002009 }, - { L"en-MY", 0x00004409 }, - { L"en-NZ", 0x00001409 }, - { L"en-PH", 0x00003409 }, - { L"en-SG", 0x00004809 }, - { L"en-TT", 0x00002C09 }, - { L"en-US", 0x00000409 }, - { L"en-ZA", 0x00001C09 }, - { L"en-ZW", 0x00003009 }, - { L"es", 0x0000000A }, - { L"es-AR", 0x00002C0A }, - { L"es-BO", 0x0000400A }, - { L"es-CL", 0x0000340A }, - { L"es-CO", 0x0000240A }, - { L"es-CR", 0x0000140A }, - { L"es-DO", 0x00001C0A }, - { L"es-EC", 0x0000300A }, - { L"es-ES", 0x00000C0A }, - { L"es-ES_tradnl", 0x0000040A }, - { L"es-GT", 0x0000100A }, - { L"es-HN", 0x0000480A }, - { L"es-MX", 0x0000080A }, - { L"es-NI", 0x00004C0A }, - { L"es-PA", 0x0000180A }, - { L"es-PE", 0x0000280A }, - { L"es-PR", 0x0000500A }, - { L"es-PY", 0x00003C0A }, - { L"es-SV", 0x0000440A }, - { L"es-US", 0x0000540A }, - { L"es-UY", 0x0000380A }, - { L"es-VE", 0x0000200A }, - { L"et", 0x00000025 }, - { L"et-EE", 0x00000425 }, - { L"eu", 0x0000002D }, - { L"eu-ES", 0x0000042D }, - { L"fa", 0x00000029 }, - { L"fa-IR", 0x00000429 }, - { L"fi", 0x0000000B }, - { L"fi-FI", 0x0000040B }, - { L"fil", 0x00000064 }, - { L"fil-PH", 0x00000464 }, - { L"fo", 0x00000038 }, - { L"fo-FO", 0x00000438 }, - { L"fr", 0x0000000C }, - { L"fr-BE", 0x0000080C }, - { L"fr-CA", 0x00000C0C }, - { L"fr-CH", 0x0000100C }, - { L"fr-FR", 0x0000040C }, - { L"fr-LU", 0x0000140C }, - { L"fr-MC", 0x0000180C }, - { L"fy", 0x00000062 }, - { L"fy-NL", 0x00000462 }, - { L"ga", 0x0000003C }, - { L"ga-IE", 0x0000083C }, - { L"gd", 0x00000091 }, - { L"gd-GB", 0x00000491 }, - { L"gl", 0x00000056 }, - { L"gl-ES", 0x00000456 }, - { L"gsw", 0x00000084 }, - { L"gsw-FR", 0x00000484 }, - { L"gu", 0x00000047 }, - { L"gu-IN", 0x00000447 }, - { L"ha-Latn", 0x00007C68 }, - { L"ha-Latn-NG", 0x00000468 }, - { L"he", 0x0000000D }, - { L"he-IL", 0x0000040D }, - { L"hi", 0x00000039 }, - { L"hi-IN", 0x00000439 }, - { L"hr", 0x0000001A }, - { L"hr-BA", 0x0000101A }, - { L"hr-HR", 0x0000041A }, - { L"hsb", 0x0000002E }, - { L"hsb-DE", 0x0000042E }, - { L"hu", 0x0000000E }, - { L"hu-HU", 0x0000040E }, - { L"hu-HU_technl", 0x0001040E }, - { L"hy", 0x0000002B }, - { L"hy-AM", 0x0000042B }, - { L"id", 0x00000021 }, - { L"id-ID", 0x00000421 }, - { L"ig", 0x00000070 }, - { L"ig-NG", 0x00000470 }, - { L"ii", 0x00000078 }, - { L"ii-CN", 0x00000478 }, - { L"is", 0x0000000F }, - { L"is-IS", 0x0000040F }, - { L"it", 0x00000010 }, - { L"it-CH", 0x00000810 }, - { L"it-IT", 0x00000410 }, - { L"iu-Cans", 0x0000785D }, - { L"iu-Cans-CA", 0x0000045D }, - { L"iu-Latn", 0x00007C5D }, - { L"iu-Latn-CA", 0x0000085D }, - { L"ja", 0x00000011 }, - { L"ja-JP", 0x00000411 }, - { L"ja-JP_radstr", 0x00040411 }, - { L"ka", 0x00000037 }, - { L"ka-GE", 0x00000437 }, - { L"ka-GE_modern", 0x00010437 }, - { L"kk", 0x0000003F }, - { L"kk-KZ", 0x0000043F }, - { L"kl", 0x0000006F }, - { L"kl-GL", 0x0000046F }, - { L"km", 0x00000053 }, - { L"km-KH", 0x00000453 }, - { L"kn", 0x0000004B }, - { L"kn-IN", 0x0000044B }, - { L"ko", 0x00000012 }, - { L"ko-KR", 0x00000412 }, - { L"kok", 0x00000057 }, - { L"kok-IN", 0x00000457 }, - { L"ky", 0x00000040 }, - { L"ky-KG", 0x00000440 }, - { L"lb", 0x0000006E }, - { L"lb-LU", 0x0000046E }, - { L"lo", 0x00000054 }, - { L"lo-LA", 0x00000454 }, - { L"lt", 0x00000027 }, - { L"lt-LT", 0x00000427 }, - { L"lv", 0x00000026 }, - { L"lv-LV", 0x00000426 }, - { L"mi", 0x00000081 }, - { L"mi-NZ", 0x00000481 }, - { L"mk", 0x0000002F }, - { L"mk-MK", 0x0000042F }, - { L"ml", 0x0000004C }, - { L"ml-IN", 0x0000044C }, - { L"mn", 0x00000050 }, - { L"mn-Cyrl", 0x00007850 }, - { L"mn-MN", 0x00000450 }, - { L"mn-Mong", 0x00007C50 }, - { L"mn-Mong-CN", 0x00000850 }, - { L"moh", 0x0000007C }, - { L"moh-CA", 0x0000047C }, - { L"mr", 0x0000004E }, - { L"mr-IN", 0x0000044E }, - { L"ms", 0x0000003E }, - { L"ms-BN", 0x0000083E }, - { L"ms-MY", 0x0000043E }, - { L"mt", 0x0000003A }, - { L"mt-MT", 0x0000043A }, - { L"nb", 0x00007C14 }, - { L"nb-NO", 0x00000414 }, - { L"ne", 0x00000061 }, - { L"ne-NP", 0x00000461 }, - { L"nl", 0x00000013 }, - { L"nl-BE", 0x00000813 }, - { L"nl-NL", 0x00000413 }, - { L"nn", 0x00007814 }, - { L"nn-NO", 0x00000814 }, - { L"no", 0x00000014 }, - { L"nso", 0x0000006C }, - { L"nso-ZA", 0x0000046C }, - { L"oc", 0x00000082 }, - { L"oc-FR", 0x00000482 }, - { L"or", 0x00000048 }, - { L"or-IN", 0x00000448 }, - { L"pa", 0x00000046 }, - { L"pa-IN", 0x00000446 }, - { L"pl", 0x00000015 }, - { L"pl-PL", 0x00000415 }, - { L"prs", 0x0000008C }, - { L"prs-AF", 0x0000048C }, - { L"ps", 0x00000063 }, - { L"ps-AF", 0x00000463 }, - { L"pt", 0x00000016 }, - { L"pt-BR", 0x00000416 }, - { L"pt-PT", 0x00000816 }, - { L"qps-ploc", 0x00000501 }, - { L"qps-ploca", 0x000005FE }, - { L"qps-plocm", 0x000009FF }, - { L"qut", 0x00000086 }, - { L"qut-GT", 0x00000486 }, - { L"quz", 0x0000006B }, - { L"quz-BO", 0x0000046B }, - { L"quz-EC", 0x0000086B }, - { L"quz-PE", 0x00000C6B }, - { L"rm", 0x00000017 }, - { L"rm-CH", 0x00000417 }, - { L"ro", 0x00000018 }, - { L"ro-RO", 0x00000418 }, - { L"ru", 0x00000019 }, - { L"ru-RU", 0x00000419 }, - { L"rw", 0x00000087 }, - { L"rw-RW", 0x00000487 }, - { L"sa", 0x0000004F }, - { L"sa-IN", 0x0000044F }, - { L"sah", 0x00000085 }, - { L"sah-RU", 0x00000485 }, - { L"se", 0x0000003B }, - { L"se-FI", 0x00000C3B }, - { L"se-NO", 0x0000043B }, - { L"se-SE", 0x0000083B }, - { L"si", 0x0000005B }, - { L"si-LK", 0x0000045B }, - { L"sk", 0x0000001B }, - { L"sk-SK", 0x0000041B }, - { L"sl", 0x00000024 }, - { L"sl-SI", 0x00000424 }, - { L"sma", 0x0000783B }, - { L"sma-NO", 0x0000183B }, - { L"sma-SE", 0x00001C3B }, - { L"smj", 0x00007C3B }, - { L"smj-NO", 0x0000103B }, - { L"smj-SE", 0x0000143B }, - { L"smn", 0x0000703B }, - { L"smn-FI", 0x0000243B }, - { L"sms", 0x0000743B }, - { L"sms-FI", 0x0000203B }, - { L"sq", 0x0000001C }, - { L"sq-AL", 0x0000041C }, - { L"sr", 0x00007C1A }, - { L"sr-Cyrl", 0x00006C1A }, - { L"sr-Cyrl-BA", 0x00001C1A }, - { L"sr-Cyrl-CS", 0x00000C1A }, - { L"sr-Cyrl-ME", 0x0000301A }, - { L"sr-Cyrl-RS", 0x0000281A }, - { L"sr-Latn", 0x0000701A }, - { L"sr-Latn-BA", 0x0000181A }, - { L"sr-Latn-CS", 0x0000081A }, - { L"sr-Latn-ME", 0x00002C1A }, - { L"sr-Latn-RS", 0x0000241A }, - { L"sv", 0x0000001D }, - { L"sv-FI", 0x0000081D }, - { L"sv-SE", 0x0000041D }, - { L"sw", 0x00000041 }, - { L"sw-KE", 0x00000441 }, - { L"syr", 0x0000005A }, - { L"syr-SY", 0x0000045A }, - { L"ta", 0x00000049 }, - { L"ta-IN", 0x00000449 }, - { L"te", 0x0000004A }, - { L"te-IN", 0x0000044A }, - { L"tg-Cyrl", 0x00007C28 }, - { L"tg-Cyrl-TJ", 0x00000428 }, - { L"th", 0x0000001E }, - { L"th-TH", 0x0000041E }, - { L"tk", 0x00000042 }, - { L"tk-TM", 0x00000442 }, - { L"tn", 0x00000032 }, - { L"tn-ZA", 0x00000432 }, - { L"tr", 0x0000001F }, - { L"tr-TR", 0x0000041F }, - { L"tt", 0x00000044 }, - { L"tt-RU", 0x00000444 }, - { L"tzm-Latn", 0x00007C5F }, - { L"tzm-Latn-DZ", 0x0000085F }, - { L"ug", 0x00000080 }, - { L"ug-CN", 0x00000480 }, - { L"uk", 0x00000022 }, - { L"uk-UA", 0x00000422 }, - { L"ur", 0x00000020 }, - { L"ur-PK", 0x00000420 }, - { L"uz", 0x00000043 }, - { L"uz-Cyrl", 0x00007843 }, - { L"uz-Cyrl-UZ", 0x00000843 }, - { L"uz-Latn", 0x00007C43 }, - { L"uz-Latn-UZ", 0x00000443 }, - { L"vi", 0x0000002A }, - { L"vi-VN", 0x0000042A }, - { L"wo", 0x00000088 }, - { L"wo-SN", 0x00000488 }, - { L"x-IV_mathan", 0x0001007F }, - { L"xh", 0x00000034 }, - { L"xh-ZA", 0x00000434 }, - { L"yo", 0x0000006A }, - { L"yo-NG", 0x0000046A }, +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + kernel32, + 8, + LCID, + WINAPI, + LocaleNameToLCID, + _In_ LPCWSTR lpName, + _In_ DWORD dwFlags + ) + { + if (auto pLocaleNameToLCID = try_get_LocaleNameToLCID()) + { + return pLocaleNameToLCID(lpName, dwFlags); + } + + //UNREFRENCED_PARAMETER(dwFlags); + + if (lpName == nullptr) + { + return GetUserDefaultLCID(); + } + else if (StringCompareIgnoreCaseByAscii(lpName, LOCALE_NAME_SYSTEM_DEFAULT, _countof(LOCALE_NAME_SYSTEM_DEFAULT)) == 0) + { + return GetSystemDefaultLCID(); + } + + //Vista虽然不支持 LOCALE_ALLOW_NEUTRAL_NAMES,但是我们好人做到底,就直接支持了吧。 + if ((LOCALE_ALLOW_NEUTRAL_NAMES & dwFlags) == 0) + { + lpName = internal::DownlevelNeutralToSpecificLocaleName(lpName); + } + + // Map of locale name to LCID. + struct LocaleNameToLcid + { + const wchar_t* localeName; + LCID lcid; + }; + + + // Map of locale name to an index in LcidToLocaleNameTable, for Windows XP. + // Data in this table has been obtained from National Language Support (NLS) API Reference at + // http://msdn.microsoft.com/en-us/goglobal/bb896001.aspx + // The table is sorted to improve search performance. + static const LocaleNameToLcid LocaleNameToLcidTable[] = + { + { L"", 0x0000007F }, + { L"af", 0x00000036 }, + { L"af-ZA", 0x00000436 }, + { L"am", 0x0000005E }, + { L"am-ET", 0x0000045E }, + { L"ar", 0x00000001 }, + { L"ar-AE", 0x00003801 }, + { L"ar-BH", 0x00003C01 }, + { L"ar-DZ", 0x00001401 }, + { L"ar-EG", 0x00000C01 }, + { L"ar-IQ", 0x00000801 }, + { L"ar-JO", 0x00002C01 }, + { L"ar-KW", 0x00003401 }, + { L"ar-LB", 0x00003001 }, + { L"ar-LY", 0x00001001 }, + { L"ar-MA", 0x00001801 }, + { L"ar-OM", 0x00002001 }, + { L"ar-QA", 0x00004001 }, + { L"ar-SA", 0x00000401 }, + { L"ar-SY", 0x00002801 }, + { L"ar-TN", 0x00001C01 }, + { L"ar-YE", 0x00002401 }, + { L"arn", 0x0000007A }, + { L"arn-CL", 0x0000047A }, + { L"as", 0x0000004D }, + { L"as-IN", 0x0000044D }, + { L"az", 0x0000002C }, + { L"az-Cyrl", 0x0000742C }, + { L"az-Cyrl-AZ", 0x0000082C }, + { L"az-Latn", 0x0000782C }, + { L"az-Latn-AZ", 0x0000042C }, + { L"ba", 0x0000006D }, + { L"ba-RU", 0x0000046D }, + { L"be", 0x00000023 }, + { L"be-BY", 0x00000423 }, + { L"bg", 0x00000002 }, + { L"bg-BG", 0x00000402 }, + { L"bn", 0x00000045 }, + { L"bn-BD", 0x00000845 }, + { L"bn-IN", 0x00000445 }, + { L"bo", 0x00000051 }, + { L"bo-CN", 0x00000451 }, + { L"br", 0x0000007E }, + { L"br-FR", 0x0000047E }, + { L"bs-Cyrl", 0x0000641A }, + { L"bs-Cyrl-BA", 0x0000201A }, + { L"bs-Latn", 0x0000681A }, + { L"bs-Latn-BA", 0x0000141A }, + { L"ca", 0x00000003 }, + { L"ca-ES", 0x00000403 }, + { L"co", 0x00000083 }, + { L"co-FR", 0x00000483 }, + { L"cs", 0x00000005 }, + { L"cs-CZ", 0x00000405 }, + { L"cy", 0x00000052 }, + { L"cy-GB", 0x00000452 }, + { L"da", 0x00000006 }, + { L"da-DK", 0x00000406 }, + { L"de", 0x00000007 }, + { L"de-AT", 0x00000C07 }, + { L"de-CH", 0x00000807 }, + { L"de-DE", 0x00000407 }, + { L"de-DE_phoneb", 0x00010407 }, + { L"de-LI", 0x00001407 }, + { L"de-LU", 0x00001007 }, + { L"dsb", 0x00007C2E }, + { L"dsb-DE", 0x0000082E }, + { L"dv", 0x00000065 }, + { L"dv-MV", 0x00000465 }, + { L"el", 0x00000008 }, + { L"el-GR", 0x00000408 }, + { L"en", 0x00000009 }, + { L"en-029", 0x00002409 }, + { L"en-AU", 0x00000C09 }, + { L"en-BZ", 0x00002809 }, + { L"en-CA", 0x00001009 }, + { L"en-GB", 0x00000809 }, + { L"en-IE", 0x00001809 }, + { L"en-IN", 0x00004009 }, + { L"en-JM", 0x00002009 }, + { L"en-MY", 0x00004409 }, + { L"en-NZ", 0x00001409 }, + { L"en-PH", 0x00003409 }, + { L"en-SG", 0x00004809 }, + { L"en-TT", 0x00002C09 }, + { L"en-US", 0x00000409 }, + { L"en-ZA", 0x00001C09 }, + { L"en-ZW", 0x00003009 }, + { L"es", 0x0000000A }, + { L"es-AR", 0x00002C0A }, + { L"es-BO", 0x0000400A }, + { L"es-CL", 0x0000340A }, + { L"es-CO", 0x0000240A }, + { L"es-CR", 0x0000140A }, + { L"es-DO", 0x00001C0A }, + { L"es-EC", 0x0000300A }, + { L"es-ES", 0x00000C0A }, + { L"es-ES_tradnl", 0x0000040A }, + { L"es-GT", 0x0000100A }, + { L"es-HN", 0x0000480A }, + { L"es-MX", 0x0000080A }, + { L"es-NI", 0x00004C0A }, + { L"es-PA", 0x0000180A }, + { L"es-PE", 0x0000280A }, + { L"es-PR", 0x0000500A }, + { L"es-PY", 0x00003C0A }, + { L"es-SV", 0x0000440A }, + { L"es-US", 0x0000540A }, + { L"es-UY", 0x0000380A }, + { L"es-VE", 0x0000200A }, + { L"et", 0x00000025 }, + { L"et-EE", 0x00000425 }, + { L"eu", 0x0000002D }, + { L"eu-ES", 0x0000042D }, + { L"fa", 0x00000029 }, + { L"fa-IR", 0x00000429 }, + { L"fi", 0x0000000B }, + { L"fi-FI", 0x0000040B }, + { L"fil", 0x00000064 }, + { L"fil-PH", 0x00000464 }, + { L"fo", 0x00000038 }, + { L"fo-FO", 0x00000438 }, + { L"fr", 0x0000000C }, + { L"fr-BE", 0x0000080C }, + { L"fr-CA", 0x00000C0C }, + { L"fr-CH", 0x0000100C }, + { L"fr-FR", 0x0000040C }, + { L"fr-LU", 0x0000140C }, + { L"fr-MC", 0x0000180C }, + { L"fy", 0x00000062 }, + { L"fy-NL", 0x00000462 }, + { L"ga", 0x0000003C }, + { L"ga-IE", 0x0000083C }, + { L"gd", 0x00000091 }, + { L"gd-GB", 0x00000491 }, + { L"gl", 0x00000056 }, + { L"gl-ES", 0x00000456 }, + { L"gsw", 0x00000084 }, + { L"gsw-FR", 0x00000484 }, + { L"gu", 0x00000047 }, + { L"gu-IN", 0x00000447 }, + { L"ha-Latn", 0x00007C68 }, + { L"ha-Latn-NG", 0x00000468 }, + { L"he", 0x0000000D }, + { L"he-IL", 0x0000040D }, + { L"hi", 0x00000039 }, + { L"hi-IN", 0x00000439 }, + { L"hr", 0x0000001A }, + { L"hr-BA", 0x0000101A }, + { L"hr-HR", 0x0000041A }, + { L"hsb", 0x0000002E }, + { L"hsb-DE", 0x0000042E }, + { L"hu", 0x0000000E }, + { L"hu-HU", 0x0000040E }, + { L"hu-HU_technl", 0x0001040E }, + { L"hy", 0x0000002B }, + { L"hy-AM", 0x0000042B }, + { L"id", 0x00000021 }, + { L"id-ID", 0x00000421 }, + { L"ig", 0x00000070 }, + { L"ig-NG", 0x00000470 }, + { L"ii", 0x00000078 }, + { L"ii-CN", 0x00000478 }, + { L"is", 0x0000000F }, + { L"is-IS", 0x0000040F }, + { L"it", 0x00000010 }, + { L"it-CH", 0x00000810 }, + { L"it-IT", 0x00000410 }, + { L"iu-Cans", 0x0000785D }, + { L"iu-Cans-CA", 0x0000045D }, + { L"iu-Latn", 0x00007C5D }, + { L"iu-Latn-CA", 0x0000085D }, + { L"ja", 0x00000011 }, + { L"ja-JP", 0x00000411 }, + { L"ja-JP_radstr", 0x00040411 }, + { L"ka", 0x00000037 }, + { L"ka-GE", 0x00000437 }, + { L"ka-GE_modern", 0x00010437 }, + { L"kk", 0x0000003F }, + { L"kk-KZ", 0x0000043F }, + { L"kl", 0x0000006F }, + { L"kl-GL", 0x0000046F }, + { L"km", 0x00000053 }, + { L"km-KH", 0x00000453 }, + { L"kn", 0x0000004B }, + { L"kn-IN", 0x0000044B }, + { L"ko", 0x00000012 }, + { L"ko-KR", 0x00000412 }, + { L"kok", 0x00000057 }, + { L"kok-IN", 0x00000457 }, + { L"ky", 0x00000040 }, + { L"ky-KG", 0x00000440 }, + { L"lb", 0x0000006E }, + { L"lb-LU", 0x0000046E }, + { L"lo", 0x00000054 }, + { L"lo-LA", 0x00000454 }, + { L"lt", 0x00000027 }, + { L"lt-LT", 0x00000427 }, + { L"lv", 0x00000026 }, + { L"lv-LV", 0x00000426 }, + { L"mi", 0x00000081 }, + { L"mi-NZ", 0x00000481 }, + { L"mk", 0x0000002F }, + { L"mk-MK", 0x0000042F }, + { L"ml", 0x0000004C }, + { L"ml-IN", 0x0000044C }, + { L"mn", 0x00000050 }, + { L"mn-Cyrl", 0x00007850 }, + { L"mn-MN", 0x00000450 }, + { L"mn-Mong", 0x00007C50 }, + { L"mn-Mong-CN", 0x00000850 }, + { L"moh", 0x0000007C }, + { L"moh-CA", 0x0000047C }, + { L"mr", 0x0000004E }, + { L"mr-IN", 0x0000044E }, + { L"ms", 0x0000003E }, + { L"ms-BN", 0x0000083E }, + { L"ms-MY", 0x0000043E }, + { L"mt", 0x0000003A }, + { L"mt-MT", 0x0000043A }, + { L"nb", 0x00007C14 }, + { L"nb-NO", 0x00000414 }, + { L"ne", 0x00000061 }, + { L"ne-NP", 0x00000461 }, + { L"nl", 0x00000013 }, + { L"nl-BE", 0x00000813 }, + { L"nl-NL", 0x00000413 }, + { L"nn", 0x00007814 }, + { L"nn-NO", 0x00000814 }, + { L"no", 0x00000014 }, + { L"nso", 0x0000006C }, + { L"nso-ZA", 0x0000046C }, + { L"oc", 0x00000082 }, + { L"oc-FR", 0x00000482 }, + { L"or", 0x00000048 }, + { L"or-IN", 0x00000448 }, + { L"pa", 0x00000046 }, + { L"pa-IN", 0x00000446 }, + { L"pl", 0x00000015 }, + { L"pl-PL", 0x00000415 }, + { L"prs", 0x0000008C }, + { L"prs-AF", 0x0000048C }, + { L"ps", 0x00000063 }, + { L"ps-AF", 0x00000463 }, + { L"pt", 0x00000016 }, + { L"pt-BR", 0x00000416 }, + { L"pt-PT", 0x00000816 }, + { L"qps-ploc", 0x00000501 }, + { L"qps-ploca", 0x000005FE }, + { L"qps-plocm", 0x000009FF }, + { L"qut", 0x00000086 }, + { L"qut-GT", 0x00000486 }, + { L"quz", 0x0000006B }, + { L"quz-BO", 0x0000046B }, + { L"quz-EC", 0x0000086B }, + { L"quz-PE", 0x00000C6B }, + { L"rm", 0x00000017 }, + { L"rm-CH", 0x00000417 }, + { L"ro", 0x00000018 }, + { L"ro-RO", 0x00000418 }, + { L"ru", 0x00000019 }, + { L"ru-RU", 0x00000419 }, + { L"rw", 0x00000087 }, + { L"rw-RW", 0x00000487 }, + { L"sa", 0x0000004F }, + { L"sa-IN", 0x0000044F }, + { L"sah", 0x00000085 }, + { L"sah-RU", 0x00000485 }, + { L"se", 0x0000003B }, + { L"se-FI", 0x00000C3B }, + { L"se-NO", 0x0000043B }, + { L"se-SE", 0x0000083B }, + { L"si", 0x0000005B }, + { L"si-LK", 0x0000045B }, + { L"sk", 0x0000001B }, + { L"sk-SK", 0x0000041B }, + { L"sl", 0x00000024 }, + { L"sl-SI", 0x00000424 }, + { L"sma", 0x0000783B }, + { L"sma-NO", 0x0000183B }, + { L"sma-SE", 0x00001C3B }, + { L"smj", 0x00007C3B }, + { L"smj-NO", 0x0000103B }, + { L"smj-SE", 0x0000143B }, + { L"smn", 0x0000703B }, + { L"smn-FI", 0x0000243B }, + { L"sms", 0x0000743B }, + { L"sms-FI", 0x0000203B }, + { L"sq", 0x0000001C }, + { L"sq-AL", 0x0000041C }, + { L"sr", 0x00007C1A }, + { L"sr-Cyrl", 0x00006C1A }, + { L"sr-Cyrl-BA", 0x00001C1A }, + { L"sr-Cyrl-CS", 0x00000C1A }, + { L"sr-Cyrl-ME", 0x0000301A }, + { L"sr-Cyrl-RS", 0x0000281A }, + { L"sr-Latn", 0x0000701A }, + { L"sr-Latn-BA", 0x0000181A }, + { L"sr-Latn-CS", 0x0000081A }, + { L"sr-Latn-ME", 0x00002C1A }, + { L"sr-Latn-RS", 0x0000241A }, + { L"sv", 0x0000001D }, + { L"sv-FI", 0x0000081D }, + { L"sv-SE", 0x0000041D }, + { L"sw", 0x00000041 }, + { L"sw-KE", 0x00000441 }, + { L"syr", 0x0000005A }, + { L"syr-SY", 0x0000045A }, + { L"ta", 0x00000049 }, + { L"ta-IN", 0x00000449 }, + { L"te", 0x0000004A }, + { L"te-IN", 0x0000044A }, + { L"tg-Cyrl", 0x00007C28 }, + { L"tg-Cyrl-TJ", 0x00000428 }, + { L"th", 0x0000001E }, + { L"th-TH", 0x0000041E }, + { L"tk", 0x00000042 }, + { L"tk-TM", 0x00000442 }, + { L"tn", 0x00000032 }, + { L"tn-ZA", 0x00000432 }, + { L"tr", 0x0000001F }, + { L"tr-TR", 0x0000041F }, + { L"tt", 0x00000044 }, + { L"tt-RU", 0x00000444 }, + { L"tzm-Latn", 0x00007C5F }, + { L"tzm-Latn-DZ", 0x0000085F }, + { L"ug", 0x00000080 }, + { L"ug-CN", 0x00000480 }, + { L"uk", 0x00000022 }, + { L"uk-UA", 0x00000422 }, + { L"ur", 0x00000020 }, + { L"ur-PK", 0x00000420 }, + { L"uz", 0x00000043 }, + { L"uz-Cyrl", 0x00007843 }, + { L"uz-Cyrl-UZ", 0x00000843 }, + { L"uz-Latn", 0x00007C43 }, + { L"uz-Latn-UZ", 0x00000443 }, + { L"vi", 0x0000002A }, + { L"vi-VN", 0x0000042A }, + { L"wo", 0x00000088 }, + { L"wo-SN", 0x00000488 }, + { L"x-IV_mathan", 0x0001007F }, + { L"xh", 0x00000034 }, + { L"xh-ZA", 0x00000434 }, + { L"yo", 0x0000006A }, + { L"yo-NG", 0x0000046A }, { L"zh", 0x00007804 }, { L"zh-CHS", 0x00000004 }, { L"zh-CHT", 0x00007C04 }, - { L"zh-CN", 0x00000804 }, - { L"zh-CN_stroke", 0x00020804 }, + { L"zh-CN", 0x00000804 }, + { L"zh-CN_stroke", 0x00020804 }, { L"zh-Hans", 0x00000004 }, { L"zh-Hant", 0x00007C04 }, - { L"zh-HK", 0x00000C04 }, - { L"zh-HK_radstr", 0x00040C04 }, - { L"zh-MO", 0x00001404 }, - { L"zh-MO_radstr", 0x00041404 }, - { L"zh-MO_stroke", 0x00021404 }, - { L"zh-SG", 0x00001004 }, - { L"zh-SG_stroke", 0x00021004 }, - { L"zh-TW", 0x00000404 }, - { L"zh-TW_pronun", 0x00030404 }, - { L"zh-TW_radstr", 0x00040404 }, - { L"zu", 0x00000035 }, - { L"zu-ZA", 0x00000435 }, - }; - - - - int bottom = 0; - int top = _countof(LocaleNameToLcidTable) - 1; - - while (bottom <= top) - { - int middle = (bottom + top) / 2; - int testIndex = StringCompareIgnoreCaseByAscii(lpName, LocaleNameToLcidTable[middle].localeName, LOCALE_NAME_MAX_LENGTH); - - if (testIndex == 0) - return LocaleNameToLcidTable[middle].lcid; - - if (testIndex < 0) - top = middle - 1; - else - bottom = middle + 1; - } - - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } + { L"zh-HK", 0x00000C04 }, + { L"zh-HK_radstr", 0x00040C04 }, + { L"zh-MO", 0x00001404 }, + { L"zh-MO_radstr", 0x00041404 }, + { L"zh-MO_stroke", 0x00021404 }, + { L"zh-SG", 0x00001004 }, + { L"zh-SG_stroke", 0x00021004 }, + { L"zh-TW", 0x00000404 }, + { L"zh-TW_pronun", 0x00030404 }, + { L"zh-TW_radstr", 0x00040404 }, + { L"zu", 0x00000035 }, + { L"zu-ZA", 0x00000435 }, + }; + + + + int bottom = 0; + int top = _countof(LocaleNameToLcidTable) - 1; + + while (bottom <= top) + { + int middle = (bottom + top) / 2; + int testIndex = StringCompareIgnoreCaseByAscii(lpName, LocaleNameToLcidTable[middle].localeName, LOCALE_NAME_MAX_LENGTH); + + if (testIndex == 0) + return LocaleNameToLcidTable[middle].lcid; + + if (testIndex < 0) + top = middle - 1; + else + bottom = middle + 1; + } + + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - kernel32, - 16, - int, - WINAPI, - LCIDToLocaleName, - _In_ LCID Locale, - _Out_writes_opt_(cchName) LPWSTR lpName, - _In_ int cchName, - _In_ DWORD dwFlags - ) - { - if (auto pLCIDToLocaleName = try_get_LCIDToLocaleName()) - { - return pLCIDToLocaleName(Locale, lpName, cchName, dwFlags); - } - - if (Locale == 0 || (lpName == nullptr && cchName > 0) || cchName < 0) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - auto szLocaleName = internal::DownlevelLCIDToLocaleName(Locale); - - if (szLocaleName) - { - //Vista虽然不支持 LOCALE_ALLOW_NEUTRAL_NAMES,但是我们好人做到底,就直接支持了吧。 - if ((LOCALE_ALLOW_NEUTRAL_NAMES & dwFlags) == 0) - { - szLocaleName = internal::DownlevelNeutralToSpecificLocaleName(szLocaleName); - } - - auto count = wcslen(szLocaleName) + 1; - - if (cchName > 0) - { - if ((int)count > cchName) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return 0; - } - - memcpy(lpName, szLocaleName, count * sizeof(szLocaleName[0])); - } - - return (int)count; - } - - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + kernel32, + 16, + int, + WINAPI, + LCIDToLocaleName, + _In_ LCID Locale, + _Out_writes_opt_(cchName) LPWSTR lpName, + _In_ int cchName, + _In_ DWORD dwFlags + ) + { + if (auto pLCIDToLocaleName = try_get_LCIDToLocaleName()) + { + return pLCIDToLocaleName(Locale, lpName, cchName, dwFlags); + } + + if (Locale == 0 || (lpName == nullptr && cchName > 0) || cchName < 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + auto szLocaleName = internal::DownlevelLCIDToLocaleName(Locale); + + if (szLocaleName) + { + //Vista虽然不支持 LOCALE_ALLOW_NEUTRAL_NAMES,但是我们好人做到底,就直接支持了吧。 + if ((LOCALE_ALLOW_NEUTRAL_NAMES & dwFlags) == 0) + { + szLocaleName = internal::DownlevelNeutralToSpecificLocaleName(szLocaleName); + } + + auto count = wcslen(szLocaleName) + 1; + + if (cchName > 0) + { + if ((int)count > cchName) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + + memcpy(lpName, szLocaleName, count * sizeof(szLocaleName[0])); + } + + return (int)count; + } + + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - kernel32, - 16, - int, - WINAPI, - GetLocaleInfoEx, - _In_opt_ LPCWSTR lpLocaleName, - _In_ LCTYPE LCType, - _Out_writes_to_opt_(cchData, return) LPWSTR lpLCData, - _In_ int cchData - ) - { - if (auto pGetLocaleInfoEx = try_get_GetLocaleInfoEx()) - { - return pGetLocaleInfoEx(lpLocaleName, LCType, lpLCData, cchData); - } - - auto Locale = LocaleNameToLCID(lpLocaleName, 0); - - if (Locale == 0) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - return GetLocaleInfoW(Locale, LCType, lpLCData, cchData); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + kernel32, + 16, + int, + WINAPI, + GetLocaleInfoEx, + _In_opt_ LPCWSTR lpLocaleName, + _In_ LCTYPE LCType, + _Out_writes_to_opt_(cchData, return) LPWSTR lpLCData, + _In_ int cchData + ) + { + if (auto pGetLocaleInfoEx = try_get_GetLocaleInfoEx()) + { + return pGetLocaleInfoEx(lpLocaleName, LCType, lpLCData, cchData); + } + + auto Locale = LocaleNameToLCID(lpLocaleName, 0); + + if (Locale == 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + return GetLocaleInfoW(Locale, LCType, lpLCData, cchData); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - kernel32, - 24, - int, - WINAPI, - GetNumberFormatEx, - _In_opt_ LPCWSTR lpLocaleName, - _In_ DWORD dwFlags, - _In_ LPCWSTR lpValue, - _In_opt_ CONST NUMBERFMTW *lpFormat, - _Out_writes_opt_(cchNumber) LPWSTR lpNumberStr, - _In_ int cchNumber - ) - { - if (auto pGetNumberFormatEx = try_get_GetNumberFormatEx()) - { - return pGetNumberFormatEx(lpLocaleName, dwFlags, lpValue, lpFormat, lpNumberStr, cchNumber); - } - - - auto Locale = LocaleNameToLCID(lpLocaleName, 0); - - if (Locale == 0) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - return GetNumberFormatW(Locale, dwFlags, lpValue, lpFormat, lpNumberStr, cchNumber); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + kernel32, + 24, + int, + WINAPI, + GetNumberFormatEx, + _In_opt_ LPCWSTR lpLocaleName, + _In_ DWORD dwFlags, + _In_ LPCWSTR lpValue, + _In_opt_ CONST NUMBERFMTW *lpFormat, + _Out_writes_opt_(cchNumber) LPWSTR lpNumberStr, + _In_ int cchNumber + ) + { + if (auto pGetNumberFormatEx = try_get_GetNumberFormatEx()) + { + return pGetNumberFormatEx(lpLocaleName, dwFlags, lpValue, lpFormat, lpNumberStr, cchNumber); + } + + + auto Locale = LocaleNameToLCID(lpLocaleName, 0); + + if (Locale == 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + return GetNumberFormatW(Locale, dwFlags, lpValue, lpFormat, lpNumberStr, cchNumber); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - kernel32, - 24, - int, - WINAPI, - GetCurrencyFormatEx, - _In_opt_ LPCWSTR lpLocaleName, - _In_ DWORD dwFlags, - _In_ LPCWSTR lpValue, - _In_opt_ CONST CURRENCYFMTW *lpFormat, - _Out_writes_opt_(cchCurrency) LPWSTR lpCurrencyStr, - _In_ int cchCurrency - ) - { - if (auto pGetCurrencyFormatEx = try_get_GetCurrencyFormatEx()) - { - return pGetCurrencyFormatEx(lpLocaleName, dwFlags, lpValue, lpFormat, lpCurrencyStr, cchCurrency); - } - - - auto Locale = LocaleNameToLCID(lpLocaleName, 0); - - if (Locale == 0) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - return GetCurrencyFormatW(Locale, dwFlags, lpValue, lpFormat, lpCurrencyStr, cchCurrency); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + kernel32, + 24, + int, + WINAPI, + GetCurrencyFormatEx, + _In_opt_ LPCWSTR lpLocaleName, + _In_ DWORD dwFlags, + _In_ LPCWSTR lpValue, + _In_opt_ CONST CURRENCYFMTW *lpFormat, + _Out_writes_opt_(cchCurrency) LPWSTR lpCurrencyStr, + _In_ int cchCurrency + ) + { + if (auto pGetCurrencyFormatEx = try_get_GetCurrencyFormatEx()) + { + return pGetCurrencyFormatEx(lpLocaleName, dwFlags, lpValue, lpFormat, lpCurrencyStr, cchCurrency); + } + + + auto Locale = LocaleNameToLCID(lpLocaleName, 0); + + if (Locale == 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + return GetCurrencyFormatW(Locale, dwFlags, lpValue, lpFormat, lpCurrencyStr, cchCurrency); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - kernel32, - 8, - int, - WINAPI, - GetUserDefaultLocaleName, - _Out_writes_(cchLocaleName) LPWSTR lpLocaleName, - _In_ int cchLocaleName - ) - { - if (auto pGetUserDefaultLocaleName = try_get_GetUserDefaultLocaleName()) - { - return pGetUserDefaultLocaleName(lpLocaleName, cchLocaleName); - } + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + kernel32, + 8, + int, + WINAPI, + GetUserDefaultLocaleName, + _Out_writes_(cchLocaleName) LPWSTR lpLocaleName, + _In_ int cchLocaleName + ) + { + if (auto pGetUserDefaultLocaleName = try_get_GetUserDefaultLocaleName()) + { + return pGetUserDefaultLocaleName(lpLocaleName, cchLocaleName); + } - return LCIDToLocaleName(LOCALE_USER_DEFAULT, lpLocaleName, cchLocaleName, 0); - } + return LCIDToLocaleName(LOCALE_USER_DEFAULT, lpLocaleName, cchLocaleName, 0); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - kernel32, - 8, - int, - WINAPI, - GetSystemDefaultLocaleName, - _Out_writes_(cchLocaleName) LPWSTR lpLocaleName, - _In_ int cchLocaleName - ) - { - if (auto pGetSystemDefaultLocaleName = try_get_GetSystemDefaultLocaleName()) - { - return pGetSystemDefaultLocaleName(lpLocaleName, cchLocaleName); - } + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + kernel32, + 8, + int, + WINAPI, + GetSystemDefaultLocaleName, + _Out_writes_(cchLocaleName) LPWSTR lpLocaleName, + _In_ int cchLocaleName + ) + { + if (auto pGetSystemDefaultLocaleName = try_get_GetSystemDefaultLocaleName()) + { + return pGetSystemDefaultLocaleName(lpLocaleName, cchLocaleName); + } - return LCIDToLocaleName(LOCALE_SYSTEM_DEFAULT, lpLocaleName, cchLocaleName, 0); - } + return LCIDToLocaleName(LOCALE_SYSTEM_DEFAULT, lpLocaleName, cchLocaleName, 0); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - kernel32, - 24, - BOOL, - WINAPI, - EnumCalendarInfoExEx, - _In_ CALINFO_ENUMPROCEXEX pCalInfoEnumProcExEx, - _In_opt_ LPCWSTR lpLocaleName, - _In_ CALID Calendar, - _In_opt_ LPCWSTR lpReserved, - _In_ CALTYPE CalType, - _In_ LPARAM lParam - ) - { - if (auto pEnumCalendarInfoExEx = try_get_EnumCalendarInfoExEx()) - { - return pEnumCalendarInfoExEx(pCalInfoEnumProcExEx, lpLocaleName, Calendar, lpReserved, CalType, lParam); - } - - LSTATUS lStatus; - - do - { - if (pCalInfoEnumProcExEx == nullptr) - { - lStatus = ERROR_INVALID_PARAMETER; - break; - } - - auto Locale = LocaleNameToLCID(lpLocaleName, 0); - - if (Locale == 0) - { - lStatus = ERROR_INVALID_PARAMETER; - break; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + kernel32, + 24, + BOOL, + WINAPI, + EnumCalendarInfoExEx, + _In_ CALINFO_ENUMPROCEXEX pCalInfoEnumProcExEx, + _In_opt_ LPCWSTR lpLocaleName, + _In_ CALID Calendar, + _In_opt_ LPCWSTR lpReserved, + _In_ CALTYPE CalType, + _In_ LPARAM lParam + ) + { + if (auto pEnumCalendarInfoExEx = try_get_EnumCalendarInfoExEx()) + { + return pEnumCalendarInfoExEx(pCalInfoEnumProcExEx, lpLocaleName, Calendar, lpReserved, CalType, lParam); + } + + LSTATUS lStatus; + + do + { + if (pCalInfoEnumProcExEx == nullptr) + { + lStatus = ERROR_INVALID_PARAMETER; + break; + } + + auto Locale = LocaleNameToLCID(lpLocaleName, 0); + + if (Locale == 0) + { + lStatus = ERROR_INVALID_PARAMETER; + break; + } #if defined(_X86_) - constexpr const auto lParamOffset = 1; - constexpr const auto pCallBackOffset = 16; - - static constexpr const byte ThunkData[] = - { - //lpCalendarInfoString = 0Ch + 4h - //Calendar = 08h + 8h - 0x68, 0x00, 0x00, 0x00, 0x00, // push lParam ; lParam - 0x6A, 0x00, // push 0 ; lpReserved - 0xFF, 0x74, 0x24, 0x10, // push dword ptr Calendar[esp] ; Calendar - 0xFF, 0x74, 0x24, 0x10, // push dword ptr lpCalendarInfoString[esp] ; lpCalendarInfoString - - 0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, pCalInfoEnumProcExEx - 0xFF, 0xD0, // call eax - 0xC2, 0x08, 0x00, // retn 8 - }; + constexpr const auto lParamOffset = 1; + constexpr const auto pCallBackOffset = 16; + + static constexpr const byte ThunkData[] = + { + //lpCalendarInfoString = 0Ch + 4h + //Calendar = 08h + 8h + 0x68, 0x00, 0x00, 0x00, 0x00, // push lParam ; lParam + 0x6A, 0x00, // push 0 ; lpReserved + 0xFF, 0x74, 0x24, 0x10, // push dword ptr Calendar[esp] ; Calendar + 0xFF, 0x74, 0x24, 0x10, // push dword ptr lpCalendarInfoString[esp] ; lpCalendarInfoString + + 0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, pCalInfoEnumProcExEx + 0xFF, 0xD0, // call eax + 0xC2, 0x08, 0x00, // retn 8 + }; #elif defined(_AMD64_) - constexpr const auto lParamOffset = 2; - constexpr const auto pCallBackOffset = 15; - - static constexpr const byte ThunkData[] = - { - //lpCalendarInfoString = rcx - //Calendar = edx - 0x49, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r9, lParam - 0x45, 0x33, 0xC0, // xor r8d, r8d ; lpReserved - - 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, pCalInfoEnumProcExEx - 0xFF, 0xE0, // jmp rax - }; + constexpr const auto lParamOffset = 2; + constexpr const auto pCallBackOffset = 15; + + static constexpr const byte ThunkData[] = + { + //lpCalendarInfoString = rcx + //Calendar = edx + 0x49, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r9, lParam + 0x45, 0x33, 0xC0, // xor r8d, r8d ; lpReserved + + 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, pCalInfoEnumProcExEx + 0xFF, 0xE0, // jmp rax + }; #endif auto _pThunkData = internal::HookThunkData::Alloc(); - if (!_pThunkData) - { - lStatus = ERROR_NOT_ENOUGH_MEMORY; - break; - } + if (!_pThunkData) + { + lStatus = ERROR_NOT_ENOUGH_MEMORY; + break; + } static_assert(sizeof(_pThunkData->ShellCode) >= sizeof(ThunkData), ""); - memcpy(_pThunkData->ShellCode, ThunkData, sizeof(ThunkData)); - *(size_t*)(_pThunkData->ShellCode + lParamOffset) = lParam; - *(size_t*)(_pThunkData->ShellCode + pCallBackOffset) = (size_t)pCalInfoEnumProcExEx; + memcpy(_pThunkData->ShellCode, ThunkData, sizeof(ThunkData)); + *(size_t*)(_pThunkData->ShellCode + lParamOffset) = lParam; + *(size_t*)(_pThunkData->ShellCode + pCallBackOffset) = (size_t)pCalInfoEnumProcExEx; - auto bSuccess = EnumCalendarInfoExW( + auto bSuccess = EnumCalendarInfoExW( CALINFO_ENUMPROCEXW(&_pThunkData->ShellCode), - Locale, - Calendar, - CalType); + Locale, + Calendar, + CalType); - lStatus = bSuccess ? ERROR_SUCCESS : GetLastError(); + lStatus = bSuccess ? ERROR_SUCCESS : GetLastError(); _pThunkData->Free(); - } while (false); - - if (lStatus == ERROR_SUCCESS) - { - return TRUE; - } - else - { - SetLastError(lStatus); - return FALSE; - } - } + } while (false); + + if (lStatus == ERROR_SUCCESS) + { + return TRUE; + } + else + { + SetLastError(lStatus); + return FALSE; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - EnumDateFormatsExEx, - _In_ DATEFMT_ENUMPROCEXEX lpDateFmtEnumProcExEx, - _In_opt_ LPCWSTR lpLocaleName, - _In_ DWORD dwFlags, - _In_ LPARAM lParam - ) - { - if (auto pEnumDateFormatsExEx = try_get_EnumDateFormatsExEx()) - { - return pEnumDateFormatsExEx(lpDateFmtEnumProcExEx, lpLocaleName, dwFlags, lParam); - } - - LSTATUS lStatus; - - do - { - if (lpDateFmtEnumProcExEx == nullptr) - { - lStatus = ERROR_INVALID_PARAMETER; - break; - } - - auto Locale = LocaleNameToLCID(lpLocaleName, 0); - - if (Locale == 0) - { - lStatus = ERROR_INVALID_PARAMETER; - break; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + EnumDateFormatsExEx, + _In_ DATEFMT_ENUMPROCEXEX lpDateFmtEnumProcExEx, + _In_opt_ LPCWSTR lpLocaleName, + _In_ DWORD dwFlags, + _In_ LPARAM lParam + ) + { + if (auto pEnumDateFormatsExEx = try_get_EnumDateFormatsExEx()) + { + return pEnumDateFormatsExEx(lpDateFmtEnumProcExEx, lpLocaleName, dwFlags, lParam); + } + + LSTATUS lStatus; + + do + { + if (lpDateFmtEnumProcExEx == nullptr) + { + lStatus = ERROR_INVALID_PARAMETER; + break; + } + + auto Locale = LocaleNameToLCID(lpLocaleName, 0); + + if (Locale == 0) + { + lStatus = ERROR_INVALID_PARAMETER; + break; + } #if defined(_X86_) - constexpr const auto lParamOffset = 1; - constexpr const auto pCallBackOffset = 14; - - static constexpr const byte ThunkData[] = - { - //lpDateFormatString = 08h + 4h - //CalendarID = 04h + 8h - 0x68, 0x00, 0x00, 0x00, 0x00, // push lParam ; lParam - 0xFF, 0x74, 0x24, 0x0C, // push dword ptr CalendarID[esp] ; CalendarID - 0xFF, 0x74, 0x24, 0x0C, // push dword ptr lpDateFormatString[esp] ; lpDateFormatString - - 0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, lpDateFmtEnumProcExEx - 0xFF, 0xD0, // call eax - 0xC2, 0x08, 0x00, // retn 8 - }; + constexpr const auto lParamOffset = 1; + constexpr const auto pCallBackOffset = 14; + + static constexpr const byte ThunkData[] = + { + //lpDateFormatString = 08h + 4h + //CalendarID = 04h + 8h + 0x68, 0x00, 0x00, 0x00, 0x00, // push lParam ; lParam + 0xFF, 0x74, 0x24, 0x0C, // push dword ptr CalendarID[esp] ; CalendarID + 0xFF, 0x74, 0x24, 0x0C, // push dword ptr lpDateFormatString[esp] ; lpDateFormatString + + 0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, lpDateFmtEnumProcExEx + 0xFF, 0xD0, // call eax + 0xC2, 0x08, 0x00, // retn 8 + }; #elif defined(_AMD64_) - constexpr const auto lParamOffset = 2; - constexpr const auto pCallBackOffset = 12; - - static constexpr const byte ThunkData[] = - { - //lpDateFormatString = rcx - //CalendarID = edx - 0x49, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r8, lParam - - 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, lpDateFmtEnumProcExEx - 0xFF, 0xE0, // jmp rax - }; + constexpr const auto lParamOffset = 2; + constexpr const auto pCallBackOffset = 12; + + static constexpr const byte ThunkData[] = + { + //lpDateFormatString = rcx + //CalendarID = edx + 0x49, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r8, lParam + + 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, lpDateFmtEnumProcExEx + 0xFF, 0xE0, // jmp rax + }; #endif auto _pThunkData = internal::HookThunkData::Alloc(); - if (!_pThunkData) - { - lStatus = ERROR_NOT_ENOUGH_MEMORY; - break; - } + if (!_pThunkData) + { + lStatus = ERROR_NOT_ENOUGH_MEMORY; + break; + } static_assert(sizeof(_pThunkData->ShellCode) >= sizeof(ThunkData), ""); - memcpy(_pThunkData->ShellCode, ThunkData, sizeof(ThunkData)); - *(size_t*)(_pThunkData->ShellCode + lParamOffset) = lParam; - *(size_t*)(_pThunkData->ShellCode + pCallBackOffset) = (size_t)lpDateFmtEnumProcExEx; + memcpy(_pThunkData->ShellCode, ThunkData, sizeof(ThunkData)); + *(size_t*)(_pThunkData->ShellCode + lParamOffset) = lParam; + *(size_t*)(_pThunkData->ShellCode + pCallBackOffset) = (size_t)lpDateFmtEnumProcExEx; - auto bSuccess = EnumDateFormatsExW( + auto bSuccess = EnumDateFormatsExW( DATEFMT_ENUMPROCEXW(&_pThunkData->ShellCode), - Locale, - dwFlags); + Locale, + dwFlags); - lStatus = bSuccess ? ERROR_SUCCESS : GetLastError(); + lStatus = bSuccess ? ERROR_SUCCESS : GetLastError(); _pThunkData->Free(); - } while (false); - - if (lStatus == ERROR_SUCCESS) - { - return TRUE; - } - else - { - SetLastError(lStatus); - return FALSE; - } - } + } while (false); + + if (lStatus == ERROR_SUCCESS) + { + return TRUE; + } + else + { + SetLastError(lStatus); + return FALSE; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 36, - int, - WINAPI, - LCMapStringEx, - _In_opt_ LPCWSTR lpLocaleName, - _In_ DWORD dwMapFlags, - _In_reads_(cchSrc) LPCWSTR lpSrcStr, - _In_ int cchSrc, - _Out_writes_opt_(cchDest) LPWSTR lpDestStr, - _In_ int cchDest, - _In_opt_ LPNLSVERSIONINFO lpVersionInformation, - _In_opt_ LPVOID lpReserved, - _In_opt_ LPARAM sortHandle - ) - { - if (const auto pLCMapStringEx = try_get_LCMapStringEx()) - { - return pLCMapStringEx(lpLocaleName, dwMapFlags, lpSrcStr, cchSrc, lpDestStr, cchDest, lpVersionInformation, lpReserved, sortHandle); - } - - auto Locale = LocaleNameToLCID(lpLocaleName, 0); - - if (Locale == 0) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - return LCMapStringW(Locale, dwMapFlags, lpSrcStr, cchSrc, lpDestStr, cchDest); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 36, + int, + WINAPI, + LCMapStringEx, + _In_opt_ LPCWSTR lpLocaleName, + _In_ DWORD dwMapFlags, + _In_reads_(cchSrc) LPCWSTR lpSrcStr, + _In_ int cchSrc, + _Out_writes_opt_(cchDest) LPWSTR lpDestStr, + _In_ int cchDest, + _In_opt_ LPNLSVERSIONINFO lpVersionInformation, + _In_opt_ LPVOID lpReserved, + _In_opt_ LPARAM sortHandle + ) + { + if (const auto pLCMapStringEx = try_get_LCMapStringEx()) + { + return pLCMapStringEx(lpLocaleName, dwMapFlags, lpSrcStr, cchSrc, lpDestStr, cchDest, lpVersionInformation, lpReserved, sortHandle); + } + + auto Locale = LocaleNameToLCID(lpLocaleName, 0); + + if (Locale == 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + return LCMapStringW(Locale, dwMapFlags, lpSrcStr, cchSrc, lpDestStr, cchDest); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - EnumSystemLocalesEx, - _In_ LOCALE_ENUMPROCEX lpLocaleEnumProcEx, - _In_ DWORD dwFlags, - _In_ LPARAM lParam, - _In_opt_ LPVOID lpReserved - ) - { - if (const auto pEnumSystemLocalesEx = try_get_EnumSystemLocalesEx()) - { - return pEnumSystemLocalesEx(lpLocaleEnumProcEx, dwFlags, lParam, lpReserved); - } - - LSTATUS lStatus = ERROR_SUCCESS; - - do - { - - if (lpLocaleEnumProcEx == nullptr) - { - lStatus = ERROR_INVALID_PARAMETER; - break; - } - - if (dwFlags & ~(LOCALE_WINDOWS | LOCALE_SUPPLEMENTAL | LOCALE_ALTERNATE_SORTS)) - { - lStatus = ERROR_INVALID_FLAGS; - break; - } - - DWORD dwLCID_Flags = 0; - - if (dwFlags == LOCALE_ALL) - { - dwFlags = LCID_SUPPORTED | LCID_ALTERNATE_SORTS; - } - else - { - dwFlags &= (LOCALE_WINDOWS | LOCALE_SUPPLEMENTAL | LOCALE_ALTERNATE_SORTS); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + EnumSystemLocalesEx, + _In_ LOCALE_ENUMPROCEX lpLocaleEnumProcEx, + _In_ DWORD dwFlags, + _In_ LPARAM lParam, + _In_opt_ LPVOID lpReserved + ) + { + if (const auto pEnumSystemLocalesEx = try_get_EnumSystemLocalesEx()) + { + return pEnumSystemLocalesEx(lpLocaleEnumProcEx, dwFlags, lParam, lpReserved); + } + + LSTATUS lStatus = ERROR_SUCCESS; + + do + { + + if (lpLocaleEnumProcEx == nullptr) + { + lStatus = ERROR_INVALID_PARAMETER; + break; + } + + if (dwFlags & ~(LOCALE_WINDOWS | LOCALE_SUPPLEMENTAL | LOCALE_ALTERNATE_SORTS)) + { + lStatus = ERROR_INVALID_FLAGS; + break; + } + + DWORD dwLCID_Flags = 0; + + if (dwFlags == LOCALE_ALL) + { + dwFlags = LCID_SUPPORTED | LCID_ALTERNATE_SORTS; + } + else + { + dwFlags &= (LOCALE_WINDOWS | LOCALE_SUPPLEMENTAL | LOCALE_ALTERNATE_SORTS); + } #if defined(_X86_) - constexpr auto lParamOffset = 1; - constexpr auto pCallBackOffset = 12; - - static constexpr const byte ThunkData[] = - { - //lpLocaleString = 08h + 4h - 0x68, 0x00, 0x00, 0x00, 0x00, // push lParam ; lParam - 0x6A, 0x00, // push 0 ; dwFlags(目前总是0) - 0xFF, 0x74, 0x24, 0x0C, // push dword ptr lpLocaleString[esp] ; lpLocaleString - - 0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, lpLocaleEnumProcEx - 0xFF, 0xD0, // call eax - 0xC2, 0x04, 0x00, // retn 4 - }; + constexpr auto lParamOffset = 1; + constexpr auto pCallBackOffset = 12; + + static constexpr const byte ThunkData[] = + { + //lpLocaleString = 08h + 4h + 0x68, 0x00, 0x00, 0x00, 0x00, // push lParam ; lParam + 0x6A, 0x00, // push 0 ; dwFlags(目前总是0) + 0xFF, 0x74, 0x24, 0x0C, // push dword ptr lpLocaleString[esp] ; lpLocaleString + + 0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, lpLocaleEnumProcEx + 0xFF, 0xD0, // call eax + 0xC2, 0x04, 0x00, // retn 4 + }; #elif defined(_AMD64_) - constexpr auto lParamOffset = 4; - constexpr auto pCallBackOffset = 14; - - static constexpr const byte ThunkData[] = - { - //lpDateFormatString = rcx - 0x33, 0xD2, // xor edx, edx ; dwFlags(0) - 0x49, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r8, lParam - - 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, lpDateFmtEnumProcExEx - 0xFF, 0xE0, // jmp rax - }; + constexpr auto lParamOffset = 4; + constexpr auto pCallBackOffset = 14; + + static constexpr const byte ThunkData[] = + { + //lpDateFormatString = rcx + 0x33, 0xD2, // xor edx, edx ; dwFlags(0) + 0x49, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r8, lParam + + 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, lpDateFmtEnumProcExEx + 0xFF, 0xE0, // jmp rax + }; #endif auto _pThunkData = internal::HookThunkData::Alloc(); - if (!_pThunkData) - { - lStatus = ERROR_NOT_ENOUGH_MEMORY; - break; - } + if (!_pThunkData) + { + lStatus = ERROR_NOT_ENOUGH_MEMORY; + break; + } static_assert(sizeof(_pThunkData->ShellCode) >= sizeof(ThunkData), ""); - memcpy(_pThunkData->ShellCode, ThunkData, sizeof(ThunkData)); - *(size_t*)(_pThunkData->ShellCode + lParamOffset) = lParam; - *(size_t*)(_pThunkData->ShellCode + pCallBackOffset) = (size_t)lpLocaleEnumProcEx; + memcpy(_pThunkData->ShellCode, ThunkData, sizeof(ThunkData)); + *(size_t*)(_pThunkData->ShellCode + lParamOffset) = lParam; + *(size_t*)(_pThunkData->ShellCode + pCallBackOffset) = (size_t)lpLocaleEnumProcEx; - auto bRet = EnumSystemLocalesW(LOCALE_ENUMPROCW(&_pThunkData->ShellCode), dwFlags); + auto bRet = EnumSystemLocalesW(LOCALE_ENUMPROCW(&_pThunkData->ShellCode), dwFlags); - lStatus = bRet ? ERROR_SUCCESS : GetLastError(); + lStatus = bRet ? ERROR_SUCCESS : GetLastError(); _pThunkData->Free(); - }while (false); - - if (lStatus == ERROR_SUCCESS) - { - return TRUE; - } - else - { - SetLastError(lStatus); - return FALSE; - } - } + }while (false); + + if (lStatus == ERROR_SUCCESS) + { + return TRUE; + } + else + { + SetLastError(lStatus); + return FALSE; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - GetThreadPreferredUILanguages, - _In_ DWORD dwFlags, - _Out_ PULONG pulNumLanguages, - _Out_writes_opt_(*pcchLanguagesBuffer) PZZWSTR pwszLanguagesBuffer, - _Inout_ PULONG pcchLanguagesBuffer - ) - { - if (auto const pGetThreadPreferredUILanguages = try_get_GetThreadPreferredUILanguages()) - { - return pGetThreadPreferredUILanguages(dwFlags, pulNumLanguages, pwszLanguagesBuffer, pcchLanguagesBuffer); - } - - LSTATUS lStatus = ERROR_SUCCESS; - - do - { - //参数验证 - if (pulNumLanguages == nullptr || pcchLanguagesBuffer == nullptr) - { - lStatus = ERROR_INVALID_PARAMETER; - break; - } - - //cchLanguagesBuffer不为 0 时,pwszLanguagesBuffer 不能为 nullptr - const ULONG cchLanguagesBuffer = *pcchLanguagesBuffer; - if (cchLanguagesBuffer && pwszLanguagesBuffer == nullptr) - { - lStatus = ERROR_INVALID_PARAMETER; - break; - } - - //让字符串正常截断 +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + GetThreadPreferredUILanguages, + _In_ DWORD dwFlags, + _Out_ PULONG pulNumLanguages, + _Out_writes_opt_(*pcchLanguagesBuffer) PZZWSTR pwszLanguagesBuffer, + _Inout_ PULONG pcchLanguagesBuffer + ) + { + if (auto const pGetThreadPreferredUILanguages = try_get_GetThreadPreferredUILanguages()) + { + return pGetThreadPreferredUILanguages(dwFlags, pulNumLanguages, pwszLanguagesBuffer, pcchLanguagesBuffer); + } + + LSTATUS lStatus = ERROR_SUCCESS; + + do + { + //参数验证 + if (pulNumLanguages == nullptr || pcchLanguagesBuffer == nullptr) + { + lStatus = ERROR_INVALID_PARAMETER; + break; + } + + //cchLanguagesBuffer不为 0 时,pwszLanguagesBuffer 不能为 nullptr + const ULONG cchLanguagesBuffer = *pcchLanguagesBuffer; + if (cchLanguagesBuffer && pwszLanguagesBuffer == nullptr) + { + lStatus = ERROR_INVALID_PARAMETER; + break; + } + + //让字符串正常截断 if(pwszLanguagesBuffer) - pwszLanguagesBuffer[0] = L'\0'; - if(cchLanguagesBuffer >= 2) - pwszLanguagesBuffer[1] = L'\0'; - - //LOCALE_CUSTOM_DEFAULT; - //检测标记预期 - if (dwFlags & ~(MUI_LANGUAGE_ID | MUI_LANGUAGE_NAME | MUI_MERGE_SYSTEM_FALLBACK | MUI_MERGE_USER_FALLBACK | MUI_THREAD_LANGUAGES)) - { - lStatus = ERROR_INVALID_PARAMETER; - break; - } - - - //MUI_LANGUAGE_ID 与 MUI_LANGUAGE_NAME不能同时使用 - if ((dwFlags & (MUI_LANGUAGE_ID | MUI_LANGUAGE_NAME)) == (MUI_LANGUAGE_ID | MUI_LANGUAGE_NAME)) - { - lStatus = ERROR_INVALID_PARAMETER; - break; - } - - - //MUI_MERGE_USER_FALLBACK | MUI_MERGE_SYSTEM_FALLBACK 不能与 MUI_THREAD_LANGUAGES同时出现 - if ((dwFlags & (MUI_MERGE_USER_FALLBACK | MUI_MERGE_SYSTEM_FALLBACK)) && (dwFlags & MUI_THREAD_LANGUAGES)) - { - lStatus = ERROR_INVALID_PARAMETER; - break; - } - - //MUI_MERGE_USER_FALLBACK 是默认标记 - if ((dwFlags & (MUI_MERGE_SYSTEM_FALLBACK | MUI_MERGE_USER_FALLBACK | MUI_THREAD_LANGUAGES)) == 0) - { - dwFlags |= MUI_MERGE_USER_FALLBACK; - } - - - //最多可能为 3 个ID,线程上下文、User上下文、System上下文 - //WinXP不支持进程上下文……也不支持列表 - LANGID LanguageIds[3 * 5] = {}; - ULONG ulNumLanguages = 0; - - - //检查线程上下文 - if ((dwFlags & (MUI_MERGE_USER_FALLBACK | MUI_THREAD_LANGUAGES)) ) - { - auto LangID = (LANGID)GetThreadLocale(); - internal::AddLangIDToBuffer(LanguageIds, _countof(LanguageIds), ulNumLanguages, LangID); - - if (dwFlags & MUI_MERGE_SYSTEM_FALLBACK) - { - for (; LangID = (LANGID)internal::DownlevelGetFallbackLocaleLCID(LangID);) - { - internal::AddLangIDToBuffer(LanguageIds, _countof(LanguageIds), ulNumLanguages, LangID); - } - } - } - - - if (dwFlags & MUI_MERGE_USER_FALLBACK) - { - auto LangID = GetUserDefaultLangID(); - internal::AddLangIDToBuffer(LanguageIds, _countof(LanguageIds), ulNumLanguages, LangID); - - - for (; LangID = (LANGID)internal::DownlevelGetFallbackLocaleLCID(LangID);) - { - internal::AddLangIDToBuffer(LanguageIds, _countof(LanguageIds), ulNumLanguages, LangID); - } - } - - if (dwFlags & MUI_MERGE_SYSTEM_FALLBACK) - { - auto LangID = GetSystemDefaultLangID(); - internal::AddLangIDToBuffer(LanguageIds, _countof(LanguageIds), ulNumLanguages, LangID); - - - for (; LangID = (LANGID)internal::DownlevelGetFallbackLocaleLCID(LangID);) - { - internal::AddLangIDToBuffer(LanguageIds, _countof(LanguageIds), ulNumLanguages, LangID); - } - } - - - - if (dwFlags & MUI_LANGUAGE_ID) - { - //0804 - - const ULONG cchLanguagesBufferNeed = _countof(L"0804") * ulNumLanguages + 1; - - *pcchLanguagesBuffer = cchLanguagesBufferNeed; - - if (pwszLanguagesBuffer) - { - if (cchLanguagesBuffer < cchLanguagesBufferNeed) - { - lStatus = ERROR_INSUFFICIENT_BUFFER; - break; - } - - constexpr const char Hex[] = "0123456789abcdef"; - - - for (unsigned i = 0; i != ulNumLanguages; ++i) - { - const auto LanguageId = LanguageIds[i]; - - *pwszLanguagesBuffer++ = Hex[(LanguageId & 0xF000ul) >> 12]; - *pwszLanguagesBuffer++ = Hex[(LanguageId & 0x0F00ul) >> 8]; - *pwszLanguagesBuffer++ = Hex[(LanguageId & 0x00F0ul) >> 4]; - *pwszLanguagesBuffer++ = Hex[(LanguageId & 0x000Ful) >> 0]; - *pwszLanguagesBuffer++ = L'\0'; - } - - *pwszLanguagesBuffer = L'\0'; - } - - } - else - { - //zh-cn 风格 - ULONG cchLanguagesBufferNeed = 0; - - if (pwszLanguagesBuffer) - { - wchar_t szLanguageNameStaticBuffer[LOCALE_NAME_MAX_LENGTH * _countof(LanguageIds) + 1]; - - //如果目标缓冲区足够容纳,那么我们直接使用目标缓冲区,否则我们先使用 szLanguageNameStaticBuffer 中转。 - wchar_t* pBuffer = LOCALE_NAME_MAX_LENGTH * ulNumLanguages + 1 <= cchLanguagesBuffer ? pwszLanguagesBuffer : szLanguageNameStaticBuffer; - auto pTmp = pBuffer; - - for (unsigned i = 0; i != ulNumLanguages; ++i) - { - const auto LanguageId = LanguageIds[i]; - - auto szLocaleName = internal::DownlevelLCIDToLocaleName(LanguageId); - - if (szLocaleName) - { - auto result = wcslen(szLocaleName) + 1; + pwszLanguagesBuffer[0] = L'\0'; + if(cchLanguagesBuffer >= 2) + pwszLanguagesBuffer[1] = L'\0'; + + //LOCALE_CUSTOM_DEFAULT; + //检测标记预期 + if (dwFlags & ~(MUI_LANGUAGE_ID | MUI_LANGUAGE_NAME | MUI_MERGE_SYSTEM_FALLBACK | MUI_MERGE_USER_FALLBACK | MUI_THREAD_LANGUAGES)) + { + lStatus = ERROR_INVALID_PARAMETER; + break; + } + + + //MUI_LANGUAGE_ID 与 MUI_LANGUAGE_NAME不能同时使用 + if ((dwFlags & (MUI_LANGUAGE_ID | MUI_LANGUAGE_NAME)) == (MUI_LANGUAGE_ID | MUI_LANGUAGE_NAME)) + { + lStatus = ERROR_INVALID_PARAMETER; + break; + } + + + //MUI_MERGE_USER_FALLBACK | MUI_MERGE_SYSTEM_FALLBACK 不能与 MUI_THREAD_LANGUAGES同时出现 + if ((dwFlags & (MUI_MERGE_USER_FALLBACK | MUI_MERGE_SYSTEM_FALLBACK)) && (dwFlags & MUI_THREAD_LANGUAGES)) + { + lStatus = ERROR_INVALID_PARAMETER; + break; + } + + //MUI_MERGE_USER_FALLBACK 是默认标记 + if ((dwFlags & (MUI_MERGE_SYSTEM_FALLBACK | MUI_MERGE_USER_FALLBACK | MUI_THREAD_LANGUAGES)) == 0) + { + dwFlags |= MUI_MERGE_USER_FALLBACK; + } + + + //最多可能为 3 个ID,线程上下文、User上下文、System上下文 + //WinXP不支持进程上下文……也不支持列表 + LANGID LanguageIds[3 * 5] = {}; + ULONG ulNumLanguages = 0; + + + //检查线程上下文 + if ((dwFlags & (MUI_MERGE_USER_FALLBACK | MUI_THREAD_LANGUAGES)) ) + { + auto LangID = (LANGID)GetThreadLocale(); + internal::AddLangIDToBuffer(LanguageIds, _countof(LanguageIds), ulNumLanguages, LangID); + + if (dwFlags & MUI_MERGE_SYSTEM_FALLBACK) + { + for (; LangID = (LANGID)internal::DownlevelGetFallbackLocaleLCID(LangID);) + { + internal::AddLangIDToBuffer(LanguageIds, _countof(LanguageIds), ulNumLanguages, LangID); + } + } + } + + + if (dwFlags & MUI_MERGE_USER_FALLBACK) + { + auto LangID = GetUserDefaultLangID(); + internal::AddLangIDToBuffer(LanguageIds, _countof(LanguageIds), ulNumLanguages, LangID); + + + for (; LangID = (LANGID)internal::DownlevelGetFallbackLocaleLCID(LangID);) + { + internal::AddLangIDToBuffer(LanguageIds, _countof(LanguageIds), ulNumLanguages, LangID); + } + } + + if (dwFlags & MUI_MERGE_SYSTEM_FALLBACK) + { + auto LangID = GetSystemDefaultLangID(); + internal::AddLangIDToBuffer(LanguageIds, _countof(LanguageIds), ulNumLanguages, LangID); + + + for (; LangID = (LANGID)internal::DownlevelGetFallbackLocaleLCID(LangID);) + { + internal::AddLangIDToBuffer(LanguageIds, _countof(LanguageIds), ulNumLanguages, LangID); + } + } + - if (result <= LOCALE_NAME_MAX_LENGTH) - { - memcpy(pTmp, szLocaleName, result * sizeof(pTmp[0])); - pTmp += result; - } - } - } - - *pTmp++ = L'\0'; - - cchLanguagesBufferNeed = static_cast(pTmp - pBuffer); - *pcchLanguagesBuffer = cchLanguagesBufferNeed; + if (dwFlags & MUI_LANGUAGE_ID) + { + //0804 - if (pBuffer == szLanguageNameStaticBuffer) - { - if (cchLanguagesBuffer < cchLanguagesBufferNeed) - { - lStatus = ERROR_INSUFFICIENT_BUFFER; - break; - } + const ULONG cchLanguagesBufferNeed = _countof(L"0804") * ulNumLanguages + 1; - memcpy(pwszLanguagesBuffer, szLanguageNameStaticBuffer, cchLanguagesBufferNeed * sizeof(pwszLanguagesBuffer[0])); - } - } - else - { - for (unsigned i = 0; i != ulNumLanguages; ++i) - { - const auto LanguageId = LanguageIds[i]; + *pcchLanguagesBuffer = cchLanguagesBufferNeed; - auto szLocaleName = internal::DownlevelLCIDToLocaleName(LanguageId); + if (pwszLanguagesBuffer) + { + if (cchLanguagesBuffer < cchLanguagesBufferNeed) + { + lStatus = ERROR_INSUFFICIENT_BUFFER; + break; + } - if (szLocaleName) - { - auto result = wcslen(szLocaleName) + 1; + constexpr const char Hex[] = "0123456789abcdef"; - if (result <= LOCALE_NAME_MAX_LENGTH) - { - cchLanguagesBufferNeed += static_cast(result); - } - } - } - ++cchLanguagesBufferNeed; + for (unsigned i = 0; i != ulNumLanguages; ++i) + { + const auto LanguageId = LanguageIds[i]; - *pcchLanguagesBuffer = cchLanguagesBufferNeed; - } - } + *pwszLanguagesBuffer++ = Hex[(LanguageId & 0xF000ul) >> 12]; + *pwszLanguagesBuffer++ = Hex[(LanguageId & 0x0F00ul) >> 8]; + *pwszLanguagesBuffer++ = Hex[(LanguageId & 0x00F0ul) >> 4]; + *pwszLanguagesBuffer++ = Hex[(LanguageId & 0x000Ful) >> 0]; + *pwszLanguagesBuffer++ = L'\0'; + } - //返回语言数量 - *pulNumLanguages = ulNumLanguages; + *pwszLanguagesBuffer = L'\0'; + } + + } + else + { + //zh-cn 风格 + ULONG cchLanguagesBufferNeed = 0; - return TRUE; + if (pwszLanguagesBuffer) + { + wchar_t szLanguageNameStaticBuffer[LOCALE_NAME_MAX_LENGTH * _countof(LanguageIds) + 1]; + + //如果目标缓冲区足够容纳,那么我们直接使用目标缓冲区,否则我们先使用 szLanguageNameStaticBuffer 中转。 + wchar_t* pBuffer = LOCALE_NAME_MAX_LENGTH * ulNumLanguages + 1 <= cchLanguagesBuffer ? pwszLanguagesBuffer : szLanguageNameStaticBuffer; + auto pTmp = pBuffer; - } while (false); + for (unsigned i = 0; i != ulNumLanguages; ++i) + { + const auto LanguageId = LanguageIds[i]; + + auto szLocaleName = internal::DownlevelLCIDToLocaleName(LanguageId); + + if (szLocaleName) + { + auto result = wcslen(szLocaleName) + 1; + + if (result <= LOCALE_NAME_MAX_LENGTH) + { + memcpy(pTmp, szLocaleName, result * sizeof(pTmp[0])); + pTmp += result; + } + } + } + + *pTmp++ = L'\0'; + + cchLanguagesBufferNeed = static_cast(pTmp - pBuffer); + + *pcchLanguagesBuffer = cchLanguagesBufferNeed; + + if (pBuffer == szLanguageNameStaticBuffer) + { + if (cchLanguagesBuffer < cchLanguagesBufferNeed) + { + lStatus = ERROR_INSUFFICIENT_BUFFER; + break; + } + + memcpy(pwszLanguagesBuffer, szLanguageNameStaticBuffer, cchLanguagesBufferNeed * sizeof(pwszLanguagesBuffer[0])); + } + } + else + { + for (unsigned i = 0; i != ulNumLanguages; ++i) + { + const auto LanguageId = LanguageIds[i]; + auto szLocaleName = internal::DownlevelLCIDToLocaleName(LanguageId); - SetLastError(lStatus); + if (szLocaleName) + { + auto result = wcslen(szLocaleName) + 1; - return FALSE; - } + if (result <= LOCALE_NAME_MAX_LENGTH) + { + cchLanguagesBufferNeed += static_cast(result); + } + } + } + + ++cchLanguagesBufferNeed; + + *pcchLanguagesBuffer = cchLanguagesBufferNeed; + } + } + + //返回语言数量 + *pulNumLanguages = ulNumLanguages; + + return TRUE; + + } while (false); + + + SetLastError(lStatus); + + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps only] - //Minimum supported server Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 0, - LANGID, - WINAPI, - GetThreadUILanguage, - void - ) - { - if (auto const _pfnGetThreadUILanguage = try_get_GetThreadUILanguage()) - { - return _pfnGetThreadUILanguage(); - } - - return (LANGID)GetThreadLocale(); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps only] + //Minimum supported server Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 0, + LANGID, + WINAPI, + GetThreadUILanguage, + void + ) + { + if (auto const _pfnGetThreadUILanguage = try_get_GetThreadUILanguage()) + { + return _pfnGetThreadUILanguage(); + } + + return (LANGID)GetThreadLocale(); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - //Minimum supported client Windows 7 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 R2 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 12, - int, - WINAPI, - ResolveLocaleName, - _In_opt_ LPCWSTR lpNameToResolve, - _Out_writes_opt_(cchLocaleName) LPWSTR lpLocaleName, - _In_ int cchLocaleName - ) - { - if (auto const pResolveLocaleName = try_get_ResolveLocaleName()) - { - return pResolveLocaleName(lpNameToResolve, lpLocaleName, cchLocaleName); - } - - LCID lcid = 0; - - if (lpNameToResolve == nullptr) - { - lcid = GetUserDefaultLCID(); - } - else - { - wchar_t Buffer[LOCALE_NAME_MAX_LENGTH]; - - unsigned i = 0; - for (; i != _countof(Buffer) && lpNameToResolve[i]; ++i) - Buffer[i] = lpNameToResolve[i]; - - if (i == _countof(Buffer)) - { - //输入异常 - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - //保证 '\0' 截断 - Buffer[i] = L'\0'; - - for (;;) - { - lcid = LocaleNameToLCID(Buffer, 0); - - //成功找到了区域,那么停止搜索 - if (lcid != 0 && lcid != LOCALE_CUSTOM_UNSPECIFIED) - break; - - while(i) - { - --i; - - if (Buffer[i] == L'-') - { - Buffer[i] = L'\0'; - break; - } - } - - //字符串已经达到开始位置,则停止搜索 - if (i == 0) - break; - } - } - - if (lcid !=0 && lcid != LOCALE_CUSTOM_UNSPECIFIED) - { - if (lpLocaleName == nullptr || cchLocaleName == 0) - { - lpLocaleName = nullptr; - cchLocaleName = 0; - } - - //删除排序规则,然后重新转换名称。 - auto result = LCIDToLocaleName(LANGIDFROMLCID(lcid), lpLocaleName, cchLocaleName, 0); - - if (result) - return result; - } - - //如果找不到,那么直接设置为空字符串 - if (lpLocaleName && cchLocaleName) - { - lpLocaleName[0] = L'\0'; - } - - return 1; - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + //Minimum supported client Windows 7 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 R2 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 12, + int, + WINAPI, + ResolveLocaleName, + _In_opt_ LPCWSTR lpNameToResolve, + _Out_writes_opt_(cchLocaleName) LPWSTR lpLocaleName, + _In_ int cchLocaleName + ) + { + if (auto const pResolveLocaleName = try_get_ResolveLocaleName()) + { + return pResolveLocaleName(lpNameToResolve, lpLocaleName, cchLocaleName); + } + + LCID lcid = 0; + + if (lpNameToResolve == nullptr) + { + lcid = GetUserDefaultLCID(); + } + else + { + wchar_t Buffer[LOCALE_NAME_MAX_LENGTH]; + + unsigned i = 0; + for (; i != _countof(Buffer) && lpNameToResolve[i]; ++i) + Buffer[i] = lpNameToResolve[i]; + + if (i == _countof(Buffer)) + { + //输入异常 + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + //保证 '\0' 截断 + Buffer[i] = L'\0'; + + for (;;) + { + lcid = LocaleNameToLCID(Buffer, 0); + + //成功找到了区域,那么停止搜索 + if (lcid != 0 && lcid != LOCALE_CUSTOM_UNSPECIFIED) + break; + + while(i) + { + --i; + + if (Buffer[i] == L'-') + { + Buffer[i] = L'\0'; + break; + } + } + + //字符串已经达到开始位置,则停止搜索 + if (i == 0) + break; + } + } + + if (lcid !=0 && lcid != LOCALE_CUSTOM_UNSPECIFIED) + { + if (lpLocaleName == nullptr || cchLocaleName == 0) + { + lpLocaleName = nullptr; + cchLocaleName = 0; + } + + //删除排序规则,然后重新转换名称。 + auto result = LCIDToLocaleName(LANGIDFROMLCID(lcid), lpLocaleName, cchLocaleName, 0); + + if (result) + return result; + } + + //如果找不到,那么直接设置为空字符串 + if (lpLocaleName && cchLocaleName) + { + lpLocaleName[0] = L'\0'; + } + + return 1; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - GetUserPreferredUILanguages, - _In_ DWORD dwFlags, - _Out_ PULONG pulNumLanguages, - _Out_writes_opt_(*pcchLanguagesBuffer) PZZWSTR pwszLanguagesBuffer, - _Inout_ PULONG pcchLanguagesBuffer - ) - { - if (auto const _pfnGetUserPreferredUILanguages = try_get_GetUserPreferredUILanguages()) - { - return _pfnGetUserPreferredUILanguages(dwFlags, pulNumLanguages, pwszLanguagesBuffer, pcchLanguagesBuffer); - } - +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + GetUserPreferredUILanguages, + _In_ DWORD dwFlags, + _Out_ PULONG pulNumLanguages, + _Out_writes_opt_(*pcchLanguagesBuffer) PZZWSTR pwszLanguagesBuffer, + _Inout_ PULONG pcchLanguagesBuffer + ) + { + if (auto const _pfnGetUserPreferredUILanguages = try_get_GetUserPreferredUILanguages()) + { + return _pfnGetUserPreferredUILanguages(dwFlags, pulNumLanguages, pwszLanguagesBuffer, pcchLanguagesBuffer); + } + dwFlags &= ~(MUI_LANGUAGE_ID | MUI_LANGUAGE_NAME); dwFlags |= MUI_MERGE_USER_FALLBACK; return ::GetThreadPreferredUILanguages(dwFlags, pulNumLanguages, pwszLanguagesBuffer, pcchLanguagesBuffer); - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 16, + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 16, BOOL, WINAPI, EnumTimeFormatsEx, @@ -2301,12 +2301,12 @@ _In_opt_ LPCWSTR _szLocaleName, _In_ DWORD _fFlags, _In_ LPARAM _lParam - ) - { - if (auto const _pfnEnumTimeFormatsEx = try_get_EnumTimeFormatsEx()) - { - return _pfnEnumTimeFormatsEx(_pfnTimeFmtEnumProcEx, _szLocaleName, _fFlags, _lParam); - } + ) + { + if (auto const _pfnEnumTimeFormatsEx = try_get_EnumTimeFormatsEx()) + { + return _pfnEnumTimeFormatsEx(_pfnTimeFmtEnumProcEx, _szLocaleName, _fFlags, _lParam); + } LSTATUS lStatus; do @@ -2383,16 +2383,16 @@ SetLastError(lStatus); return FALSE; } - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, 28, int, WINAPI, @@ -2404,12 +2404,12 @@ _Out_writes_opt_(_cchData) LPWSTR _szCalData, _In_ int _cchData, _Out_opt_ LPDWORD _puValue - ) - { - if (auto const _pfnGetCalendarInfoEx = try_get_GetCalendarInfoEx()) - { - return _pfnGetCalendarInfoEx(_szLocaleName, _Calendar, _szReserved, _CalType, _szCalData, _cchData, _puValue); - } + ) + { + if (auto const _pfnGetCalendarInfoEx = try_get_GetCalendarInfoEx()) + { + return _pfnGetCalendarInfoEx(_szLocaleName, _Calendar, _szReserved, _CalType, _szCalData, _cchData, _puValue); + } const auto _Locale = LocaleNameToLCID(_szLocaleName, 0); @@ -2423,12 +2423,12 @@ #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, 12, BOOL, WINAPI, @@ -2436,12 +2436,12 @@ _In_ NLS_FUNCTION _uFunction, _In_opt_ LPCWSTR _szLocaleName, _Inout_ LPNLSVERSIONINFOEX _pVersionInformation - ) - { - if (auto const _pfnGetNLSVersionEx = try_get_GetNLSVersionEx()) - { - return _pfnGetNLSVersionEx(_uFunction, _szLocaleName, _pVersionInformation); - } + ) + { + if (auto const _pfnGetNLSVersionEx = try_get_GetNLSVersionEx()) + { + return _pfnGetNLSVersionEx(_uFunction, _szLocaleName, _pVersionInformation); + } if (_uFunction != COMPARE_STRING) { @@ -2463,12 +2463,12 @@ #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, 20, BOOL, WINAPI, @@ -2478,12 +2478,12 @@ _In_ LPNLSVERSIONINFO _pVersionInformation, _In_reads_(_cchStr) LPCWSTR _szString, _In_ INT _cchStr - ) - { - if (auto const _pfnIsNLSDefinedString = try_get_IsNLSDefinedString()) - { - return _pfnIsNLSDefinedString(_uFunction, _fFlags, _pVersionInformation, _szString, _cchStr); - } + ) + { + if (auto const _pfnIsNLSDefinedString = try_get_IsNLSDefinedString()) + { + return _pfnIsNLSDefinedString(_uFunction, _fFlags, _pVersionInformation, _szString, _cchStr); + } if (_uFunction != COMPARE_STRING) { diff --git a/src/Thunks/api-ms-win-core-memory.hpp b/src/Thunks/api-ms-win-core-memory.hpp index bad5079..e7e78db 100644 --- a/src/Thunks/api-ms-win-core-memory.hpp +++ b/src/Thunks/api-ms-win-core-memory.hpp @@ -2,584 +2,584 @@ namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - //Minimum supported client Windows 8 [desktop apps only] - //Minimum supported server Windows Server 2012 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 4, - BOOL, - WINAPI, - GetMemoryErrorHandlingCapabilities, - _Out_ PULONG Capabilities - ) - { - if (auto pGetMemoryErrorHandlingCapabilities = try_get_GetMemoryErrorHandlingCapabilities()) - { - return pGetMemoryErrorHandlingCapabilities(Capabilities); - } - - //别怪我,我们什么特性都不支持…… - *Capabilities = 0; - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + //Minimum supported client Windows 8 [desktop apps only] + //Minimum supported server Windows Server 2012 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 4, + BOOL, + WINAPI, + GetMemoryErrorHandlingCapabilities, + _Out_ PULONG Capabilities + ) + { + if (auto pGetMemoryErrorHandlingCapabilities = try_get_GetMemoryErrorHandlingCapabilities()) + { + return pGetMemoryErrorHandlingCapabilities(Capabilities); + } + + //别怪我,我们什么特性都不支持…… + *Capabilities = 0; + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps only] - //Minimum supported server Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 16, - _Success_(return != FALSE) - BOOL, - WINAPI, - AllocateUserPhysicalPagesNuma, - _In_ HANDLE hProcess, - _Inout_ PULONG_PTR NumberOfPages, - _Out_writes_to_(*NumberOfPages,*NumberOfPages) PULONG_PTR PageArray, - _In_ DWORD nndPreferred - ) - { - if (const auto pAllocateUserPhysicalPagesNuma = try_get_AllocateUserPhysicalPagesNuma()) - { - return pAllocateUserPhysicalPagesNuma(hProcess, NumberOfPages, PageArray, nndPreferred); - } - - return AllocateUserPhysicalPages(hProcess, NumberOfPages, PageArray); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps only] + //Minimum supported server Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 16, + _Success_(return != FALSE) + BOOL, + WINAPI, + AllocateUserPhysicalPagesNuma, + _In_ HANDLE hProcess, + _Inout_ PULONG_PTR NumberOfPages, + _Out_writes_to_(*NumberOfPages,*NumberOfPages) PULONG_PTR PageArray, + _In_ DWORD nndPreferred + ) + { + if (const auto pAllocateUserPhysicalPagesNuma = try_get_AllocateUserPhysicalPagesNuma()) + { + return pAllocateUserPhysicalPagesNuma(hProcess, NumberOfPages, PageArray, nndPreferred); + } + + return AllocateUserPhysicalPages(hProcess, NumberOfPages, PageArray); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10) - - //Minimum supported client Windows 10 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2016 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 16, - PVOID, - WINAPI, - VirtualAllocFromApp, - _In_opt_ PVOID BaseAddress, - _In_ SIZE_T Size, - _In_ ULONG AllocationType, - _In_ ULONG Protection - ) - { - if (const auto pVirtualAllocFromApp = try_get_VirtualAllocFromApp()) - { - return pVirtualAllocFromApp(BaseAddress, Size, AllocationType, Protection); - } - - - return VirtualAlloc(BaseAddress, Size, AllocationType, Protection); - } +#if (YY_Thunks_Target < __WindowsNT10_10240) + + //Minimum supported client Windows 10 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2016 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 16, + PVOID, + WINAPI, + VirtualAllocFromApp, + _In_opt_ PVOID BaseAddress, + _In_ SIZE_T Size, + _In_ ULONG AllocationType, + _In_ ULONG Protection + ) + { + if (const auto pVirtualAllocFromApp = try_get_VirtualAllocFromApp()) + { + return pVirtualAllocFromApp(BaseAddress, Size, AllocationType, Protection); + } + + + return VirtualAlloc(BaseAddress, Size, AllocationType, Protection); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps only] - //Minimum supported server Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 24, - LPVOID, - WINAPI, - VirtualAllocExNuma, - _In_ HANDLE hProcess, - _In_opt_ LPVOID lpAddress, - _In_ SIZE_T dwSize, - _In_ DWORD flAllocationType, - _In_ DWORD flProtect, - _In_ DWORD nndPreferred - ) - { - if (const auto pVirtualAllocExNuma = try_get_VirtualAllocExNuma()) - { - return pVirtualAllocExNuma(hProcess, lpAddress, dwSize, flAllocationType, flProtect, nndPreferred); - } - - return VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps only] + //Minimum supported server Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 24, + LPVOID, + WINAPI, + VirtualAllocExNuma, + _In_ HANDLE hProcess, + _In_opt_ LPVOID lpAddress, + _In_ SIZE_T dwSize, + _In_ DWORD flAllocationType, + _In_ DWORD flProtect, + _In_ DWORD nndPreferred + ) + { + if (const auto pVirtualAllocExNuma = try_get_VirtualAllocExNuma()) + { + return pVirtualAllocExNuma(hProcess, lpAddress, dwSize, flAllocationType, flProtect, nndPreferred); + } + + return VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10) - - //Minimum supported client Windows 10 [desktop apps only] - //Minimum supported server Windows Server 2016 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 28, - PVOID, - WINAPI, - VirtualAlloc2, - _In_opt_ HANDLE Process, - _In_opt_ PVOID BaseAddress, - _In_ SIZE_T Size, - _In_ ULONG AllocationType, - _In_ ULONG PageProtection, - _Inout_updates_opt_(ParameterCount) MEM_EXTENDED_PARAMETER* ExtendedParameters, - _In_ ULONG ParameterCount - ) - { - if (const auto pVirtualAlloc2 = try_get_VirtualAlloc2()) - { - return pVirtualAlloc2(Process, BaseAddress, Size, AllocationType, PageProtection, ExtendedParameters, ParameterCount); - } - - //尝试搜索 MemExtendedParameterNumaNode - if (ExtendedParameters && ParameterCount) - { - for (ULONG i = 0; i != ParameterCount; ++i) - { - if (ExtendedParameters[i].Type == MemExtendedParameterNumaNode) - { - return VirtualAllocExNuma(Process, BaseAddress, Size, AllocationType, PageProtection, ExtendedParameters[i].ULong); - } - } - } - - //尽力了,只能调用VirtualAllocEx。 - return VirtualAllocEx(Process, BaseAddress, Size, AllocationType, PageProtection); - } +#if (YY_Thunks_Target < __WindowsNT10_10240) + + //Minimum supported client Windows 10 [desktop apps only] + //Minimum supported server Windows Server 2016 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 28, + PVOID, + WINAPI, + VirtualAlloc2, + _In_opt_ HANDLE Process, + _In_opt_ PVOID BaseAddress, + _In_ SIZE_T Size, + _In_ ULONG AllocationType, + _In_ ULONG PageProtection, + _Inout_updates_opt_(ParameterCount) MEM_EXTENDED_PARAMETER* ExtendedParameters, + _In_ ULONG ParameterCount + ) + { + if (const auto pVirtualAlloc2 = try_get_VirtualAlloc2()) + { + return pVirtualAlloc2(Process, BaseAddress, Size, AllocationType, PageProtection, ExtendedParameters, ParameterCount); + } + + //尝试搜索 MemExtendedParameterNumaNode + if (ExtendedParameters && ParameterCount) + { + for (ULONG i = 0; i != ParameterCount; ++i) + { + if (ExtendedParameters[i].Type == MemExtendedParameterNumaNode) + { + return VirtualAllocExNuma(Process, BaseAddress, Size, AllocationType, PageProtection, ExtendedParameters[i].ULong); + } + } + } + + //尽力了,只能调用VirtualAllocEx。 + return VirtualAllocEx(Process, BaseAddress, Size, AllocationType, PageProtection); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10) - - //Minimum supported client Windows 10 [desktop apps only] - //Minimum supported server Windows Server 2016 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 28, - PVOID, - WINAPI, - VirtualAlloc2FromApp, - _In_opt_ HANDLE Process, - _In_opt_ PVOID BaseAddress, - _In_ SIZE_T Size, - _In_ ULONG AllocationType, - _In_ ULONG PageProtection, - _Inout_updates_opt_(ParameterCount) MEM_EXTENDED_PARAMETER* ExtendedParameters, - _In_ ULONG ParameterCount - ) - { - if (const auto pVirtualAlloc2FromApp = try_get_VirtualAlloc2FromApp()) - { - return pVirtualAlloc2FromApp(Process, BaseAddress, Size, AllocationType, PageProtection, ExtendedParameters, ParameterCount); - } - - //尝试搜索 MemExtendedParameterNumaNode - if (ExtendedParameters && ParameterCount) - { - for (ULONG i = 0; i != ParameterCount; ++i) - { - if (ExtendedParameters[i].Type == MemExtendedParameterNumaNode) - { - return VirtualAllocExNuma(Process, BaseAddress, Size, AllocationType, PageProtection, ExtendedParameters[i].ULong); - } - } - } - - return VirtualAllocEx(Process, BaseAddress, Size, AllocationType, PageProtection); - } +#if (YY_Thunks_Target < __WindowsNT10_10240) + + //Minimum supported client Windows 10 [desktop apps only] + //Minimum supported server Windows Server 2016 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 28, + PVOID, + WINAPI, + VirtualAlloc2FromApp, + _In_opt_ HANDLE Process, + _In_opt_ PVOID BaseAddress, + _In_ SIZE_T Size, + _In_ ULONG AllocationType, + _In_ ULONG PageProtection, + _Inout_updates_opt_(ParameterCount) MEM_EXTENDED_PARAMETER* ExtendedParameters, + _In_ ULONG ParameterCount + ) + { + if (const auto pVirtualAlloc2FromApp = try_get_VirtualAlloc2FromApp()) + { + return pVirtualAlloc2FromApp(Process, BaseAddress, Size, AllocationType, PageProtection, ExtendedParameters, ParameterCount); + } + + //尝试搜索 MemExtendedParameterNumaNode + if (ExtendedParameters && ParameterCount) + { + for (ULONG i = 0; i != ParameterCount; ++i) + { + if (ExtendedParameters[i].Type == MemExtendedParameterNumaNode) + { + return VirtualAllocExNuma(Process, BaseAddress, Size, AllocationType, PageProtection, ExtendedParameters[i].ULong); + } + } + } + + return VirtualAllocEx(Process, BaseAddress, Size, AllocationType, PageProtection); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps only] - //Minimum supported server Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 28, - HANDLE, - WINAPI, - CreateFileMappingNumaW, - _In_ HANDLE hFile, - _In_opt_ LPSECURITY_ATTRIBUTES lpFileMappingAttributes, - _In_ DWORD flProtect, - _In_ DWORD dwMaximumSizeHigh, - _In_ DWORD dwMaximumSizeLow, - _In_opt_ LPCWSTR lpName, - _In_ DWORD nndPreferred - ) - { - if (const auto pCreateFileMappingNumaW = try_get_CreateFileMappingNumaW()) - { - return pCreateFileMappingNumaW(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName, nndPreferred); - } - - return CreateFileMappingW(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps only] + //Minimum supported server Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 28, + HANDLE, + WINAPI, + CreateFileMappingNumaW, + _In_ HANDLE hFile, + _In_opt_ LPSECURITY_ATTRIBUTES lpFileMappingAttributes, + _In_ DWORD flProtect, + _In_ DWORD dwMaximumSizeHigh, + _In_ DWORD dwMaximumSizeLow, + _In_opt_ LPCWSTR lpName, + _In_ DWORD nndPreferred + ) + { + if (const auto pCreateFileMappingNumaW = try_get_CreateFileMappingNumaW()) + { + return pCreateFileMappingNumaW(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName, nndPreferred); + } + + return CreateFileMappingW(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps only] - //Minimum supported server Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 28, - HANDLE, - WINAPI, - CreateFileMappingNumaA, - _In_ HANDLE hFile, - _In_opt_ LPSECURITY_ATTRIBUTES lpFileMappingAttributes, - _In_ DWORD flProtect, - _In_ DWORD dwMaximumSizeHigh, - _In_ DWORD dwMaximumSizeLow, - _In_opt_ LPCSTR lpName, - _In_ DWORD nndPreferred - ) - { - if (const auto pCreateFileMappingNumaA = try_get_CreateFileMappingNumaA()) - { - return pCreateFileMappingNumaA(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName, nndPreferred); - } - - return CreateFileMappingA(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps only] + //Minimum supported server Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 28, + HANDLE, + WINAPI, + CreateFileMappingNumaA, + _In_ HANDLE hFile, + _In_opt_ LPSECURITY_ATTRIBUTES lpFileMappingAttributes, + _In_ DWORD flProtect, + _In_ DWORD dwMaximumSizeHigh, + _In_ DWORD dwMaximumSizeLow, + _In_opt_ LPCSTR lpName, + _In_ DWORD nndPreferred + ) + { + if (const auto pCreateFileMappingNumaA = try_get_CreateFileMappingNumaA()) + { + return pCreateFileMappingNumaA(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName, nndPreferred); + } + + return CreateFileMappingA(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 24, - HANDLE, - WINAPI, - CreateFileMappingFromApp, - _In_ HANDLE hFile, - _In_opt_ PSECURITY_ATTRIBUTES SecurityAttributes, - _In_ ULONG PageProtection, - _In_ ULONG64 MaximumSize, - _In_opt_ PCWSTR Name - ) - { - if (const auto pVirtualAllocExNuma = try_get_CreateFileMappingFromApp()) - { - return pVirtualAllocExNuma(hFile, SecurityAttributes, PageProtection, MaximumSize, Name); - } - - - return CreateFileMappingW(hFile, SecurityAttributes, PageProtection, MaximumSize >> 32, MaximumSize & 0xFFFFFFFF, Name); - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 24, + HANDLE, + WINAPI, + CreateFileMappingFromApp, + _In_ HANDLE hFile, + _In_opt_ PSECURITY_ATTRIBUTES SecurityAttributes, + _In_ ULONG PageProtection, + _In_ ULONG64 MaximumSize, + _In_opt_ PCWSTR Name + ) + { + if (const auto pVirtualAllocExNuma = try_get_CreateFileMappingFromApp()) + { + return pVirtualAllocExNuma(hFile, SecurityAttributes, PageProtection, MaximumSize, Name); + } + + + return CreateFileMappingW(hFile, SecurityAttributes, PageProtection, MaximumSize >> 32, MaximumSize & 0xFFFFFFFF, Name); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 40, - HANDLE, - WINAPI, - CreateFileMapping2, - _In_ HANDLE File, - _In_opt_ SECURITY_ATTRIBUTES* SecurityAttributes, - _In_ ULONG DesiredAccess, - _In_ ULONG PageProtection, - _In_ ULONG AllocationAttributes, - _In_ ULONG64 MaximumSize, - _In_opt_ PCWSTR Name, - _Inout_updates_opt_(ParameterCount) MEM_EXTENDED_PARAMETER* ExtendedParameters, - _In_ ULONG ParameterCount - ) - { - if (const auto pCreateFileMapping2 = try_get_CreateFileMapping2()) - { - return pCreateFileMapping2(File, SecurityAttributes, DesiredAccess, PageProtection, AllocationAttributes, MaximumSize, Name, ExtendedParameters, ParameterCount); - } - - //尝试搜索 MemExtendedParameterNumaNode - if (ExtendedParameters && ParameterCount) - { - for (ULONG i = 0; i != ParameterCount; ++i) - { - if (ExtendedParameters[i].Type == MemExtendedParameterNumaNode) - { - return CreateFileMappingNumaW(File, SecurityAttributes, PageProtection | AllocationAttributes, MaximumSize >> 32, MaximumSize & 0xFFFFFFFF, Name, ExtendedParameters[i].ULong); - } - } - } - - return CreateFileMappingW(File, SecurityAttributes, PageProtection | AllocationAttributes, MaximumSize >> 32, MaximumSize & 0xFFFFFFFF, Name); - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 40, + HANDLE, + WINAPI, + CreateFileMapping2, + _In_ HANDLE File, + _In_opt_ SECURITY_ATTRIBUTES* SecurityAttributes, + _In_ ULONG DesiredAccess, + _In_ ULONG PageProtection, + _In_ ULONG AllocationAttributes, + _In_ ULONG64 MaximumSize, + _In_opt_ PCWSTR Name, + _Inout_updates_opt_(ParameterCount) MEM_EXTENDED_PARAMETER* ExtendedParameters, + _In_ ULONG ParameterCount + ) + { + if (const auto pCreateFileMapping2 = try_get_CreateFileMapping2()) + { + return pCreateFileMapping2(File, SecurityAttributes, DesiredAccess, PageProtection, AllocationAttributes, MaximumSize, Name, ExtendedParameters, ParameterCount); + } + + //尝试搜索 MemExtendedParameterNumaNode + if (ExtendedParameters && ParameterCount) + { + for (ULONG i = 0; i != ParameterCount; ++i) + { + if (ExtendedParameters[i].Type == MemExtendedParameterNumaNode) + { + return CreateFileMappingNumaW(File, SecurityAttributes, PageProtection | AllocationAttributes, MaximumSize >> 32, MaximumSize & 0xFFFFFFFF, Name, ExtendedParameters[i].ULong); + } + } + } + + return CreateFileMappingW(File, SecurityAttributes, PageProtection | AllocationAttributes, MaximumSize >> 32, MaximumSize & 0xFFFFFFFF, Name); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 20, - PVOID, - WINAPI, - MapViewOfFileFromApp, - _In_ HANDLE hFileMappingObject, - _In_ ULONG DesiredAccess, - _In_ ULONG64 FileOffset, - _In_ SIZE_T NumberOfBytesToMap - ) - { - if (const auto pMapViewOfFileFromApp = try_get_MapViewOfFileFromApp()) - { - return pMapViewOfFileFromApp(hFileMappingObject, DesiredAccess, FileOffset, NumberOfBytesToMap); - } - - return MapViewOfFile(hFileMappingObject, DesiredAccess, FileOffset >> 32, FileOffset & 0xFFFFFFFF, NumberOfBytesToMap); - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 20, + PVOID, + WINAPI, + MapViewOfFileFromApp, + _In_ HANDLE hFileMappingObject, + _In_ ULONG DesiredAccess, + _In_ ULONG64 FileOffset, + _In_ SIZE_T NumberOfBytesToMap + ) + { + if (const auto pMapViewOfFileFromApp = try_get_MapViewOfFileFromApp()) + { + return pMapViewOfFileFromApp(hFileMappingObject, DesiredAccess, FileOffset, NumberOfBytesToMap); + } + + return MapViewOfFile(hFileMappingObject, DesiredAccess, FileOffset >> 32, FileOffset & 0xFFFFFFFF, NumberOfBytesToMap); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - UnmapViewOfFileEx, - _In_ PVOID BaseAddress, - _In_ ULONG UnmapFlags - ) - { - if (const auto pUnmapViewOfFileEx = try_get_UnmapViewOfFileEx()) - { - return pUnmapViewOfFileEx(BaseAddress, UnmapFlags); - } - - return UnmapViewOfFile(BaseAddress); - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + UnmapViewOfFileEx, + _In_ PVOID BaseAddress, + _In_ ULONG UnmapFlags + ) + { + if (const auto pUnmapViewOfFileEx = try_get_UnmapViewOfFileEx()) + { + return pUnmapViewOfFileEx(BaseAddress, UnmapFlags); + } + + return UnmapViewOfFile(BaseAddress); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10) - - //Minimum supported client Windows 10 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2016 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - VirtualProtectFromApp, - _In_ PVOID Address, - _In_ SIZE_T Size, - _In_ ULONG NewProtection, - _Out_ PULONG OldProtection - ) - { - if (const auto pVirtualProtectFromApp = try_get_VirtualProtectFromApp()) - { - return pVirtualProtectFromApp(Address, Size, NewProtection, OldProtection); - } - - return VirtualProtect(Address, Size, NewProtection, OldProtection); - } +#if (YY_Thunks_Target < __WindowsNT10_10240) + + //Minimum supported client Windows 10 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2016 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + VirtualProtectFromApp, + _In_ PVOID Address, + _In_ SIZE_T Size, + _In_ ULONG NewProtection, + _Out_ PULONG OldProtection + ) + { + if (const auto pVirtualProtectFromApp = try_get_VirtualProtectFromApp()) + { + return pVirtualProtectFromApp(Address, Size, NewProtection, OldProtection); + } + + return VirtualProtect(Address, Size, NewProtection, OldProtection); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10) - - //Minimum supported client Windows 10 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2016 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 12, - HANDLE, - WINAPI, - OpenFileMappingFromApp, - _In_ ULONG DesiredAccess, - _In_ BOOL InheritHandle, - _In_ PCWSTR Name - ) - { - if (const auto pOpenFileMappingFromApp = try_get_OpenFileMappingFromApp()) - { - return pOpenFileMappingFromApp(DesiredAccess, InheritHandle, Name); - } - - return OpenFileMappingW(DesiredAccess, InheritHandle, Name); - } +#if (YY_Thunks_Target < __WindowsNT10_10240) + + //Minimum supported client Windows 10 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2016 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 12, + HANDLE, + WINAPI, + OpenFileMappingFromApp, + _In_ ULONG DesiredAccess, + _In_ BOOL InheritHandle, + _In_ PCWSTR Name + ) + { + if (const auto pOpenFileMappingFromApp = try_get_OpenFileMappingFromApp()) + { + return pOpenFileMappingFromApp(DesiredAccess, InheritHandle, Name); + } + + return OpenFileMappingW(DesiredAccess, InheritHandle, Name); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03) - - //Minimum supported client Windows Vista[desktop apps | UWP apps] - //Minimum supported server Windows Server 2003[desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 0, - SIZE_T, - WINAPI, - GetLargePageMinimum, - VOID - ) - { - if (const auto pGetLargePageMinimum = try_get_GetLargePageMinimum()) - { - return pGetLargePageMinimum(); - } - - return 0; - } +#if (YY_Thunks_Target < __WindowsNT5_2) + + //Minimum supported client Windows Vista[desktop apps | UWP apps] + //Minimum supported server Windows Server 2003[desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 0, + SIZE_T, + WINAPI, + GetLargePageMinimum, + VOID + ) + { + if (const auto pGetLargePageMinimum = try_get_GetLargePageMinimum()) + { + return pGetLargePageMinimum(); + } + + return 0; + } #endif - -#if (YY_Thunks_Support_Version < NTDDI_WIN10) - - // 最低受支持的客户端 Windows 8.1 更新[桌面应用 | UWP 应用] - // 最低受支持的服务器 Windows Server 2012 R2 更新[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 8, - DWORD, - WINAPI, - DiscardVirtualMemory, - _Inout_updates_(_uSize) PVOID _pVirtualAddress, - _In_ SIZE_T _uSize - ) - { - if (const auto _pfnDiscardVirtualMemory = try_get_DiscardVirtualMemory()) - { - return _pfnDiscardVirtualMemory(_pVirtualAddress, _uSize); - } - - if (!VirtualAlloc(_pVirtualAddress, _uSize, MEM_RESET, PAGE_NOACCESS)) - return GetLastError(); - - return ERROR_SUCCESS; - } + +#if (YY_Thunks_Target < __WindowsNT10_10240) + + // 最低受支持的客户端 Windows 8.1 更新[桌面应用 | UWP 应用] + // 最低受支持的服务器 Windows Server 2012 R2 更新[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 8, + DWORD, + WINAPI, + DiscardVirtualMemory, + _Inout_updates_(_uSize) PVOID _pVirtualAddress, + _In_ SIZE_T _uSize + ) + { + if (const auto _pfnDiscardVirtualMemory = try_get_DiscardVirtualMemory()) + { + return _pfnDiscardVirtualMemory(_pVirtualAddress, _uSize); + } + + if (!VirtualAlloc(_pVirtualAddress, _uSize, MEM_RESET, PAGE_NOACCESS)) + return GetLastError(); + + return ERROR_SUCCESS; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10) - - // 最低受支持的客户端 Windows 8.1 更新[桌面应用 | UWP 应用] - // 最低受支持的服务器 Windows Server 2012 R2 更新[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 12, - DWORD, - WINAPI, - OfferVirtualMemory, - _Inout_updates_(_uSize) PVOID _pVirtualAddress, - _In_ SIZE_T _uSize, - _In_ OFFER_PRIORITY _ePriority - ) - { - if (const auto _pfnOfferVirtualMemory = try_get_OfferVirtualMemory()) - { - return _pfnOfferVirtualMemory(_pVirtualAddress, _uSize, _ePriority); - } - - // 低版本系统不支持这个机制,所以暂时假装内存充足,不触发回收 - UNREFERENCED_PARAMETER(_ePriority); - - MEMORY_BASIC_INFORMATION _Info; - if (VirtualQuery(_pVirtualAddress, &_Info, sizeof(_Info)) == 0) - return GetLastError(); - - if (_Info.State != MEM_COMMIT) - return ERROR_INVALID_PARAMETER; - - - if ((char*)_pVirtualAddress + _uSize > (char*)_Info.BaseAddress + _Info.RegionSize) - return ERROR_INVALID_PARAMETER; - - return ERROR_SUCCESS; - } +#if (YY_Thunks_Target < __WindowsNT10_10240) + + // 最低受支持的客户端 Windows 8.1 更新[桌面应用 | UWP 应用] + // 最低受支持的服务器 Windows Server 2012 R2 更新[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 12, + DWORD, + WINAPI, + OfferVirtualMemory, + _Inout_updates_(_uSize) PVOID _pVirtualAddress, + _In_ SIZE_T _uSize, + _In_ OFFER_PRIORITY _ePriority + ) + { + if (const auto _pfnOfferVirtualMemory = try_get_OfferVirtualMemory()) + { + return _pfnOfferVirtualMemory(_pVirtualAddress, _uSize, _ePriority); + } + + // 低版本系统不支持这个机制,所以暂时假装内存充足,不触发回收 + UNREFERENCED_PARAMETER(_ePriority); + + MEMORY_BASIC_INFORMATION _Info; + if (VirtualQuery(_pVirtualAddress, &_Info, sizeof(_Info)) == 0) + return GetLastError(); + + if (_Info.State != MEM_COMMIT) + return ERROR_INVALID_PARAMETER; + + + if ((char*)_pVirtualAddress + _uSize > (char*)_Info.BaseAddress + _Info.RegionSize) + return ERROR_INVALID_PARAMETER; + + return ERROR_SUCCESS; + } #endif - -#if (YY_Thunks_Support_Version < NTDDI_WIN10) - - // 最低受支持的客户端 Windows 8.1 更新[桌面应用 | UWP 应用] - // 最低受支持的服务器 Windows Server 2012 R2 更新[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 8, - DWORD, - WINAPI, - ReclaimVirtualMemory, - _In_reads_(_uSize) void const* _pVirtualAddress, - _In_ SIZE_T _uSize - ) - { - if (const auto _pfnReclaimVirtualMemory = try_get_ReclaimVirtualMemory()) - { - return _pfnReclaimVirtualMemory(_pVirtualAddress, _uSize); - } - - MEMORY_BASIC_INFORMATION _Info; - if (VirtualQuery(_pVirtualAddress, &_Info, sizeof(_Info)) == 0) - return GetLastError(); - - if (_Info.State != MEM_COMMIT) - return ERROR_INVALID_PARAMETER; - - - if ((char*)_pVirtualAddress + _uSize > (char*)_Info.BaseAddress + _Info.RegionSize) - return ERROR_INVALID_PARAMETER; - - return ERROR_SUCCESS; - } + +#if (YY_Thunks_Target < __WindowsNT10_10240) + + // 最低受支持的客户端 Windows 8.1 更新[桌面应用 | UWP 应用] + // 最低受支持的服务器 Windows Server 2012 R2 更新[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 8, + DWORD, + WINAPI, + ReclaimVirtualMemory, + _In_reads_(_uSize) void const* _pVirtualAddress, + _In_ SIZE_T _uSize + ) + { + if (const auto _pfnReclaimVirtualMemory = try_get_ReclaimVirtualMemory()) + { + return _pfnReclaimVirtualMemory(_pVirtualAddress, _uSize); + } + + MEMORY_BASIC_INFORMATION _Info; + if (VirtualQuery(_pVirtualAddress, &_Info, sizeof(_Info)) == 0) + return GetLastError(); + + if (_Info.State != MEM_COMMIT) + return ERROR_INVALID_PARAMETER; + + + if ((char*)_pVirtualAddress + _uSize > (char*)_Info.BaseAddress + _Info.RegionSize) + return ERROR_INVALID_PARAMETER; + + return ERROR_SUCCESS; + } #endif - -#if (YY_Thunks_Support_Version < NTDDI_WIN10) - - // 最低受支持的客户端 Windows 8 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - PrefetchVirtualMemory, - _In_ HANDLE _hProcess, - _In_ ULONG_PTR _uNumberOfEntries, - _In_reads_(_uNumberOfEntries) PWIN32_MEMORY_RANGE_ENTRY _pVirtualAddresses, - _In_ ULONG _fFlags - ) - { - if (const auto _pfnPrefetchVirtualMemory = try_get_PrefetchVirtualMemory()) - { - return _pfnPrefetchVirtualMemory(_hProcess, _uNumberOfEntries, _pVirtualAddresses, _fFlags); - } - - UNREFERENCED_PARAMETER(_hProcess); - UNREFERENCED_PARAMETER(_uNumberOfEntries); - UNREFERENCED_PARAMETER(_pVirtualAddresses); - UNREFERENCED_PARAMETER(_fFlags); - - // 假装自己预取成功 - return TRUE; - } + +#if (YY_Thunks_Target < __WindowsNT10_10240) + + // 最低受支持的客户端 Windows 8 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + PrefetchVirtualMemory, + _In_ HANDLE _hProcess, + _In_ ULONG_PTR _uNumberOfEntries, + _In_reads_(_uNumberOfEntries) PWIN32_MEMORY_RANGE_ENTRY _pVirtualAddresses, + _In_ ULONG _fFlags + ) + { + if (const auto _pfnPrefetchVirtualMemory = try_get_PrefetchVirtualMemory()) + { + return _pfnPrefetchVirtualMemory(_hProcess, _uNumberOfEntries, _pVirtualAddresses, _fFlags); + } + + UNREFERENCED_PARAMETER(_hProcess); + UNREFERENCED_PARAMETER(_uNumberOfEntries); + UNREFERENCED_PARAMETER(_pVirtualAddresses); + UNREFERENCED_PARAMETER(_fFlags); + + // 假装自己预取成功 + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03) +#if (YY_Thunks_Target < __WindowsNT5_2) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 16, + __DEFINE_THUNK( + kernel32, + 16, BOOL, WINAPI, SetProcessWorkingSetSizeEx, @@ -587,25 +587,25 @@ namespace YY::Thunks _In_ SIZE_T _uMinimumWorkingSetSize, _In_ SIZE_T _uMaximumWorkingSetSize, _In_ DWORD _fFlags - ) - { - if (const auto _pfnSetProcessWorkingSetSizeEx = try_get_SetProcessWorkingSetSizeEx()) - { - return _pfnSetProcessWorkingSetSizeEx(_hProcess, _uMinimumWorkingSetSize, _uMaximumWorkingSetSize, _fFlags); - } + ) + { + if (const auto _pfnSetProcessWorkingSetSizeEx = try_get_SetProcessWorkingSetSizeEx()) + { + return _pfnSetProcessWorkingSetSizeEx(_hProcess, _uMinimumWorkingSetSize, _uMaximumWorkingSetSize, _fFlags); + } - return SetProcessWorkingSetSize(_hProcess, _uMinimumWorkingSetSize, _uMaximumWorkingSetSize); - } + return SetProcessWorkingSetSize(_hProcess, _uMinimumWorkingSetSize, _uMaximumWorkingSetSize); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03) +#if (YY_Thunks_Target < __WindowsNT5_2) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 16, + __DEFINE_THUNK( + kernel32, + 16, BOOL, WINAPI, GetProcessWorkingSetSizeEx, @@ -613,24 +613,24 @@ namespace YY::Thunks _Out_ PSIZE_T _puMinimumWorkingSetSize, _Out_ PSIZE_T _puMaximumWorkingSetSize, _Out_ PDWORD _pfFlags - ) - { - if (const auto _pfnGetProcessWorkingSetSizeEx = try_get_GetProcessWorkingSetSizeEx()) - { - return _pfnGetProcessWorkingSetSizeEx(_hProcess, _puMinimumWorkingSetSize, _puMaximumWorkingSetSize, _pfFlags); - } + ) + { + if (const auto _pfnGetProcessWorkingSetSizeEx = try_get_GetProcessWorkingSetSizeEx()) + { + return _pfnGetProcessWorkingSetSizeEx(_hProcess, _puMinimumWorkingSetSize, _puMaximumWorkingSetSize, _pfFlags); + } *_pfFlags = 0; - return GetProcessWorkingSetSize(_hProcess, _puMinimumWorkingSetSize, _puMaximumWorkingSetSize); - } + return GetProcessWorkingSetSize(_hProcess, _puMinimumWorkingSetSize, _puMaximumWorkingSetSize); + } #endif -#if defined(__ENABLE_WORKAROUND_2_UNNAME_OBJECT_DACL) && (YY_Thunks_Support_Version < NTDDI_WINBLUE) +#if defined(__ENABLE_WORKAROUND_2_UNNAME_OBJECT_DACL) && (YY_Thunks_Target < __WindowsNT6_3) - __DEFINE_THUNK( - kernel32, - 24, + __DEFINE_THUNK( + kernel32, + 24, HANDLE, WINAPI, CreateFileMappingW, @@ -640,8 +640,8 @@ namespace YY::Thunks _In_ DWORD _uMaximumSizeHigh, _In_ DWORD _uMaximumSizeLow, _In_opt_ LPCWSTR _szName - ) - { + ) + { const auto _pfnCreateFileMappingW = try_get_CreateFileMappingW(); if (!_pfnCreateFileMappingW) { @@ -649,7 +649,7 @@ namespace YY::Thunks return NULL; } -#if (YY_Thunks_Support_Version < NTDDI_WINBLUE) +#if (YY_Thunks_Target < __WindowsNT6_3) wchar_t _szTmpMapName[256]; if (_pFileMappingAttributes && (_szName == nullptr || *_szName == L'\0') && internal::GetSystemVersion() < internal::MakeVersion(6, 3)) { @@ -665,6 +665,6 @@ namespace YY::Thunks #endif return _pfnCreateFileMappingW(_hFile, _pFileMappingAttributes, _flProtect, _uMaximumSizeHigh, _uMaximumSizeLow, _szName); - } + } #endif } diff --git a/src/Thunks/api-ms-win-core-path.hpp b/src/Thunks/api-ms-win-core-path.hpp index a26715a..2879f3a 100644 --- a/src/Thunks/api-ms-win-core-path.hpp +++ b/src/Thunks/api-ms-win-core-path.hpp @@ -1,8 +1,10 @@ - +#if (YY_Thunks_Target < __WindowsNT6_2) #define PATHCCH_NO_DEPRECATE #include +#include +#endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) && __YY_Thunks_libs && !defined(__Comment_Lib_pathcch) +#if (YY_Thunks_Target < __WindowsNT6_2) && __YY_Thunks_libs && !defined(__Comment_Lib_pathcch) #define __Comment_Lib_pathcch #pragma comment(lib, "Pathcch.lib") #endif @@ -149,1618 +151,1618 @@ namespace YY::Thunks::internal namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 8, - _Success_(return) - BOOL, - WINAPI, - PathIsUNCEx, - _In_ PCWSTR pszPath, - _Outptr_opt_ PCWSTR* ppszServer - ) - { - if (ppszServer) - *ppszServer = nullptr; - - if (pszPath[0] == L'\\' && pszPath[1] == L'\\') - { - if (pszPath[2] == L'?') - { - if (pszPath[3] == L'\\' - && (pszPath[4] == L'U' || pszPath[4] == L'u') - && (pszPath[5] == L'N' || pszPath[5] == L'n') - && (pszPath[6] == L'C' || pszPath[6] == L'c') - && pszPath[7] == L'\\') - { - pszPath += 8; - } - else - { - return FALSE; - } - } - else - { - //PathIsVolumeGUIDWorker 判断是多余的,因为 "\\\\?\\Volume{GUID}" 这样的形式走不到这个分支 - - pszPath += 2; - } - - if (ppszServer) - *ppszServer = pszPath; - - return TRUE; - } - - return FALSE; - - } -#endif +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 8, + _Success_(return) + BOOL, + WINAPI, + PathIsUNCEx, + _In_ PCWSTR pszPath, + _Outptr_opt_ PCWSTR* ppszServer + ) + { + if (ppszServer) + *ppszServer = nullptr; + if (pszPath[0] == L'\\' && pszPath[1] == L'\\') + { + if (pszPath[2] == L'?') + { + if (pszPath[3] == L'\\' + && (pszPath[4] == L'U' || pszPath[4] == L'u') + && (pszPath[5] == L'N' || pszPath[5] == L'n') + && (pszPath[6] == L'C' || pszPath[6] == L'c') + && pszPath[7] == L'\\') + { + pszPath += 8; + } + else + { + return FALSE; + } + } + else + { + //PathIsVolumeGUIDWorker 判断是多余的,因为 "\\\\?\\Volume{GUID}" 这样的形式走不到这个分支 -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 4, - BOOL, - WINAPI, - PathCchIsRoot, - _In_opt_ PCWSTR pszPath - ) - { - // NULL or "" - if (pszPath == nullptr || pszPath[0] == L'\0') - return FALSE; - - - // "C:\\" 形式 - if (((L'A' <= pszPath[0] && pszPath[0] <= L'Z') || (L'a' <= pszPath[0] && pszPath[0] <= L'z')) // iswalpha(pszPath[0]) - && pszPath[1] == L':' - && pszPath[2] == L'\\' - && pszPath[3] == L'\0') - { - return TRUE; - } - - // "\\" 形式 - if (pszPath[0] == L'\\' && pszPath[1] == L'\0') - { - return TRUE; - } - - - /* - * "\\\path1\\path2" - * "\\\\path1" - * "\\\\?\\UNC\\path1\\path2" - * "\\\\?\\UNC\\path1" - */ - PCWSTR pszServer; - if (PathIsUNCEx(pszPath, &pszServer)) - { - DWORD nSeparatorsCount = 0; - - for (; *pszServer;++pszServer) - { - if (*pszServer == L'\\') - { - ++nSeparatorsCount; - - if (nSeparatorsCount > 1 || pszServer[1] == L'\0') - return FALSE; - } - } - - return TRUE; - } - - /* - * "\\\\?\\C:\\" - * "\\\\?\\Volume{guid}\\" - */ - - if (pszPath[0] == L'\\' - && pszPath[1] == L'\\' - && pszPath[2] == L'?' - && pszPath[3] == L'\\') - { - // "\\\\?\\C:\\" - if (((L'A' <= pszPath[4] && pszPath[4] <= L'Z') || (L'a' <= pszPath[4] && pszPath[4] <= L'z')) // iswalpha(pszPath[4]) - && pszPath[5] == L':' - && pszPath[6] == L'\\' - && pszPath[7] == L'\0') - { - return TRUE; - } - - // "\\\\?\\Volume{guid}\\" - if (internal::PathIsVolumeGUIDWorker(pszPath) - && pszPath[48] == L'\\' - && pszPath[49] == L'\0') - { - return TRUE; - } - - } - - return FALSE; - - } -#endif + pszPath += 2; + } + + if (ppszServer) + *ppszServer = pszPath; + + return TRUE; + } + return FALSE; -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 16, - HRESULT, - WINAPI, - PathCchAddBackslashEx, - _Inout_updates_(cchPath) PWSTR pszPath, - _In_ size_t cchPath, - _Outptr_opt_result_buffer_(*pcchRemaining) PWSTR* ppszEnd, - _Out_opt_ size_t* pcchRemaining - ) - { - if (ppszEnd) - *ppszEnd = nullptr; - - if (pcchRemaining) - *pcchRemaining = 0; - - auto nLength = wcslen(pszPath); - - HRESULT hr; - - do - { - if (nLength >= cchPath) - { - hr = __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - break; - } - - if (nLength && pszPath[nLength - 1] != L'\\') - { - //末尾不是 '\\' 所以我们添加 一个 '\\' 微软原版这里用了 StringCchCopyExW,但是我觉得这没有必要。 - - ++nLength; - if (nLength >= cchPath) - { - hr = __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - break; - } - - pszPath[nLength - 1] = L'\\'; - pszPath[nLength] = L'\0'; - - hr = S_OK; - } - else - { - hr = S_FALSE; - } - - if (ppszEnd) - *ppszEnd = pszPath + nLength; - - if (pcchRemaining) - *pcchRemaining = cchPath - nLength; - - } while (false); - - return hr; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 8, - HRESULT, - WINAPI, - PathCchAddBackslash, - _Inout_updates_(cchPath) PWSTR pszPath, - _In_ size_t cchPath - ) - { - return PathCchAddBackslashEx(pszPath, cchPath, nullptr, nullptr); - } + +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 4, + BOOL, + WINAPI, + PathCchIsRoot, + _In_opt_ PCWSTR pszPath + ) + { + // NULL or "" + if (pszPath == nullptr || pszPath[0] == L'\0') + return FALSE; + + + // "C:\\" 形式 + if (((L'A' <= pszPath[0] && pszPath[0] <= L'Z') || (L'a' <= pszPath[0] && pszPath[0] <= L'z')) // iswalpha(pszPath[0]) + && pszPath[1] == L':' + && pszPath[2] == L'\\' + && pszPath[3] == L'\0') + { + return TRUE; + } + + // "\\" 形式 + if (pszPath[0] == L'\\' && pszPath[1] == L'\0') + { + return TRUE; + } + + + /* + * "\\\path1\\path2" + * "\\\\path1" + * "\\\\?\\UNC\\path1\\path2" + * "\\\\?\\UNC\\path1" + */ + PCWSTR pszServer; + if (PathIsUNCEx(pszPath, &pszServer)) + { + DWORD nSeparatorsCount = 0; + + for (; *pszServer;++pszServer) + { + if (*pszServer == L'\\') + { + ++nSeparatorsCount; + + if (nSeparatorsCount > 1 || pszServer[1] == L'\0') + return FALSE; + } + } + + return TRUE; + } + + /* + * "\\\\?\\C:\\" + * "\\\\?\\Volume{guid}\\" + */ + + if (pszPath[0] == L'\\' + && pszPath[1] == L'\\' + && pszPath[2] == L'?' + && pszPath[3] == L'\\') + { + // "\\\\?\\C:\\" + if (((L'A' <= pszPath[4] && pszPath[4] <= L'Z') || (L'a' <= pszPath[4] && pszPath[4] <= L'z')) // iswalpha(pszPath[4]) + && pszPath[5] == L':' + && pszPath[6] == L'\\' + && pszPath[7] == L'\0') + { + return TRUE; + } + + // "\\\\?\\Volume{guid}\\" + if (internal::PathIsVolumeGUIDWorker(pszPath) + && pszPath[48] == L'\\' + && pszPath[49] == L'\0') + { + return TRUE; + } + + } + + return FALSE; + + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 16, + HRESULT, + WINAPI, + PathCchAddBackslashEx, + _Inout_updates_(cchPath) PWSTR pszPath, + _In_ size_t cchPath, + _Outptr_opt_result_buffer_(*pcchRemaining) PWSTR* ppszEnd, + _Out_opt_ size_t* pcchRemaining + ) + { + if (ppszEnd) + *ppszEnd = nullptr; - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 16, - HRESULT, - WINAPI, - PathCchRemoveBackslashEx, - _Inout_updates_(_Inexpressible_(cchPath)) PWSTR pszPath, - _In_ size_t cchPath, - _Outptr_opt_result_buffer_(*pcchRemaining) PWSTR* ppszEnd, - _Out_opt_ size_t* pcchRemaining - ) - { - if (ppszEnd) - *ppszEnd = nullptr; + if (pcchRemaining) + *pcchRemaining = 0; - if (pcchRemaining) - *pcchRemaining = 0; + auto nLength = wcslen(pszPath); - auto nLength = wcslen(pszPath); + HRESULT hr; - HRESULT hr = S_FALSE; + do + { + if (nLength >= cchPath) + { + hr = __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + break; + } + if (nLength && pszPath[nLength - 1] != L'\\') + { + //末尾不是 '\\' 所以我们添加 一个 '\\' 微软原版这里用了 StringCchCopyExW,但是我觉得这没有必要。 - do - { - if (nLength >= cchPath) - { - hr = E_INVALIDARG; - break; - } + ++nLength; + if (nLength >= cchPath) + { + hr = __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + break; + } - if (nLength && pszPath[nLength - 1] == L'\\') - { - --nLength; + pszPath[nLength - 1] = L'\\'; + pszPath[nLength] = L'\0'; - if (!PathCchIsRoot(pszPath)) - { - pszPath[nLength] = L'\0'; - hr = S_OK; - } - } + hr = S_OK; + } + else + { + hr = S_FALSE; + } - if (ppszEnd) - *ppszEnd = pszPath + nLength; + if (ppszEnd) + *ppszEnd = pszPath + nLength; - if (pcchRemaining) - *pcchRemaining = cchPath - nLength; + if (pcchRemaining) + *pcchRemaining = cchPath - nLength; + } while (false); - } while (false); + return hr; + } +#endif - return hr; - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 8, + HRESULT, + WINAPI, + PathCchAddBackslash, + _Inout_updates_(cchPath) PWSTR pszPath, + _In_ size_t cchPath + ) + { + return PathCchAddBackslashEx(pszPath, cchPath, nullptr, nullptr); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 8, - HRESULT, - WINAPI, - PathCchRemoveBackslash, - _Inout_updates_(cchPath) PWSTR pszPath, - _In_ size_t cchPath - ) - { - return PathCchRemoveBackslashEx(pszPath, cchPath, nullptr, nullptr); - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 16, + HRESULT, + WINAPI, + PathCchRemoveBackslashEx, + _Inout_updates_(_Inexpressible_(cchPath)) PWSTR pszPath, + _In_ size_t cchPath, + _Outptr_opt_result_buffer_(*pcchRemaining) PWSTR* ppszEnd, + _Out_opt_ size_t* pcchRemaining + ) + { + if (ppszEnd) + *ppszEnd = nullptr; + + if (pcchRemaining) + *pcchRemaining = 0; + + auto nLength = wcslen(pszPath); + + HRESULT hr = S_FALSE; + + + do + { + if (nLength >= cchPath) + { + hr = E_INVALIDARG; + break; + } + + if (nLength && pszPath[nLength - 1] == L'\\') + { + --nLength; + + if (!PathCchIsRoot(pszPath)) + { + pszPath[nLength] = L'\0'; + hr = S_OK; + } + } + + if (ppszEnd) + *ppszEnd = pszPath + nLength; + + if (pcchRemaining) + *pcchRemaining = cchPath - nLength; + + + } while (false); + + return hr; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 8, - HRESULT, - WINAPI, - PathCchSkipRoot, - _In_ PCWSTR pszPath, - _Outptr_ PCWSTR* ppszRootEnd - ) - { - if (pszPath == nullptr || *pszPath == L'\0' || ppszRootEnd == nullptr) - return E_INVALIDARG; - - *ppszRootEnd = nullptr; - - PCWSTR szRootEnd; - if (PathIsUNCEx(pszPath, &szRootEnd)) - { - //如果是UNC路径,则尝试跳过 2个 '\\' - DWORD nSeparate = 0; - - for (; *szRootEnd && nSeparate < 2; ++szRootEnd) - { - if (*szRootEnd == L'\\') - { - ++nSeparate; - } - } - } - else if (pszPath[0] == L'\\' && pszPath[1] != L'\\') - { - // "\\XXXXXX" 一个相对路径 - szRootEnd = pszPath + 1; - } - else - { - if (internal::PathIsVolumeGUIDWorker(pszPath)) - { - szRootEnd = pszPath + 48; - } - else if(pszPath[0] == L'\\' - && pszPath[1] == L'\\' - && pszPath[2] == L'?' - && pszPath[3] == L'\\' - && ((L'A' <= pszPath[4] && pszPath[4] <= L'Z') || (L'a' <= pszPath[4] && pszPath[4] <= L'z')) // iswalpha(pszPath[4]) - && pszPath[5] == L':') - { - // "\\\\?\\C:\\" - szRootEnd = pszPath + 6; - } - else if(((L'A' <= pszPath[0] && pszPath[0] <= L'Z') || (L'a' <= pszPath[0] && pszPath[0] <= L'z')) // iswalpha(pszPath[0]) - && pszPath[1] == L':') - { - // "C:\\" - szRootEnd = pszPath + 2; - } - else - { - return E_INVALIDARG; - } - - if (*szRootEnd == L'\\') - ++szRootEnd; - } - - *ppszRootEnd = szRootEnd; - - return S_OK; - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 8, + HRESULT, + WINAPI, + PathCchRemoveBackslash, + _Inout_updates_(cchPath) PWSTR pszPath, + _In_ size_t cchPath + ) + { + return PathCchRemoveBackslashEx(pszPath, cchPath, nullptr, nullptr); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 8, - HRESULT, - WINAPI, - PathCchStripToRoot, - _Inout_updates_(_Inexpressible_(cchPath)) PWSTR pszPath, - _In_ size_t cchPath - ) - { - if (pszPath == nullptr || cchPath == 0 || cchPath > PATHCCH_MAX_CCH) - return E_INVALIDARG; - - PWSTR szRootEnd; - auto hr = PathCchSkipRoot(pszPath, (PCWSTR*)&szRootEnd); - - do - { - if (FAILED(hr)) - break; - - if (szRootEnd >= pszPath + cchPath) - { - hr = E_INVALIDARG; - break; - } - - if (*szRootEnd) - { - *szRootEnd = L'\0'; - PathCchRemoveBackslash(pszPath, cchPath); - hr = S_OK; - } - else - { - hr = PathCchRemoveBackslash(pszPath, cchPath); - if (FAILED(hr)) - break; - } - - return hr; - - } while (false); - - - *pszPath = L'\0'; - - return hr; - - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 8, + HRESULT, + WINAPI, + PathCchSkipRoot, + _In_ PCWSTR pszPath, + _Outptr_ PCWSTR* ppszRootEnd + ) + { + if (pszPath == nullptr || *pszPath == L'\0' || ppszRootEnd == nullptr) + return E_INVALIDARG; + + *ppszRootEnd = nullptr; + + PCWSTR szRootEnd; + if (PathIsUNCEx(pszPath, &szRootEnd)) + { + //如果是UNC路径,则尝试跳过 2个 '\\' + DWORD nSeparate = 0; + + for (; *szRootEnd && nSeparate < 2; ++szRootEnd) + { + if (*szRootEnd == L'\\') + { + ++nSeparate; + } + } + } + else if (pszPath[0] == L'\\' && pszPath[1] != L'\\') + { + // "\\XXXXXX" 一个相对路径 + szRootEnd = pszPath + 1; + } + else + { + if (internal::PathIsVolumeGUIDWorker(pszPath)) + { + szRootEnd = pszPath + 48; + } + else if(pszPath[0] == L'\\' + && pszPath[1] == L'\\' + && pszPath[2] == L'?' + && pszPath[3] == L'\\' + && ((L'A' <= pszPath[4] && pszPath[4] <= L'Z') || (L'a' <= pszPath[4] && pszPath[4] <= L'z')) // iswalpha(pszPath[4]) + && pszPath[5] == L':') + { + // "\\\\?\\C:\\" + szRootEnd = pszPath + 6; + } + else if(((L'A' <= pszPath[0] && pszPath[0] <= L'Z') || (L'a' <= pszPath[0] && pszPath[0] <= L'z')) // iswalpha(pszPath[0]) + && pszPath[1] == L':') + { + // "C:\\" + szRootEnd = pszPath + 2; + } + else + { + return E_INVALIDARG; + } + + if (*szRootEnd == L'\\') + ++szRootEnd; + } + + *ppszRootEnd = szRootEnd; + + return S_OK; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 8, - HRESULT, - WINAPI, - PathCchRemoveFileSpec, - _Inout_updates_(_Inexpressible_(cchPath)) PWSTR pszPath, - _In_ size_t cchPath - ) - { - if (pszPath == nullptr || cchPath == 0 || cchPath > PATHCCH_MAX_CCH) - return E_INVALIDARG; - - PWSTR pszRootEnd; - - if (FAILED(PathCchSkipRoot(pszPath, (PCWSTR*)&pszRootEnd))) - { - pszRootEnd = pszPath; - } - - const auto pszPathBufferEnd = pszPath + cchPath; - - if (pszRootEnd >= pszPathBufferEnd) - return E_INVALIDARG; - - //搜索最后一个 ‘\\’ - - LPWSTR szLast = pszRootEnd; - - for (; *pszRootEnd; ++pszRootEnd) - { - if (pszRootEnd >= pszPathBufferEnd) - return E_INVALIDARG; - - if (*pszRootEnd == L'\\') - szLast = pszRootEnd; - } - - if (*szLast) - { - *szLast = L'\0'; - PathCchRemoveBackslash(pszPath, cchPath); - - return S_OK; - } - else - { - return PathCchRemoveBackslash(pszPath, cchPath); - } - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 8, + HRESULT, + WINAPI, + PathCchStripToRoot, + _Inout_updates_(_Inexpressible_(cchPath)) PWSTR pszPath, + _In_ size_t cchPath + ) + { + if (pszPath == nullptr || cchPath == 0 || cchPath > PATHCCH_MAX_CCH) + return E_INVALIDARG; + + PWSTR szRootEnd; + auto hr = PathCchSkipRoot(pszPath, (PCWSTR*)&szRootEnd); + + do + { + if (FAILED(hr)) + break; + + if (szRootEnd >= pszPath + cchPath) + { + hr = E_INVALIDARG; + break; + } + + if (*szRootEnd) + { + *szRootEnd = L'\0'; + PathCchRemoveBackslash(pszPath, cchPath); + hr = S_OK; + } + else + { + hr = PathCchRemoveBackslash(pszPath, cchPath); + if (FAILED(hr)) + break; + } + + return hr; + + } while (false); + + + *pszPath = L'\0'; + + return hr; + + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 12, - HRESULT, - WINAPI, - PathCchFindExtension, - _In_reads_(_Inexpressible_(cchPath)) PCWSTR pszPath, - _In_ size_t cchPath, - _Outptr_ PCWSTR* ppszExt - ) - { - if(ppszExt == nullptr) - return E_INVALIDARG; - - *ppszExt = nullptr; - - if (pszPath == nullptr || cchPath == 0 || cchPath > PATHCCH_MAX_CCH) - { - return E_INVALIDARG; - } - - const auto szPathBufferEnd = pszPath + cchPath; - PCWSTR pszExt = nullptr; - - for (;*pszPath;++pszPath) - { - if (pszPath >= szPathBufferEnd) - return E_INVALIDARG; - - switch (*pszPath) - { - case L'\\': - case L' ': - pszExt = nullptr; - break; - case L'.': - pszExt = pszPath; - break; - default: - break; - } - } - - *ppszExt = pszExt ? pszExt : pszPath; - - return S_OK; - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 8, + HRESULT, + WINAPI, + PathCchRemoveFileSpec, + _Inout_updates_(_Inexpressible_(cchPath)) PWSTR pszPath, + _In_ size_t cchPath + ) + { + if (pszPath == nullptr || cchPath == 0 || cchPath > PATHCCH_MAX_CCH) + return E_INVALIDARG; + + PWSTR pszRootEnd; + + if (FAILED(PathCchSkipRoot(pszPath, (PCWSTR*)&pszRootEnd))) + { + pszRootEnd = pszPath; + } + + const auto pszPathBufferEnd = pszPath + cchPath; + + if (pszRootEnd >= pszPathBufferEnd) + return E_INVALIDARG; + + //搜索最后一个 ‘\\’ + + LPWSTR szLast = pszRootEnd; + + for (; *pszRootEnd; ++pszRootEnd) + { + if (pszRootEnd >= pszPathBufferEnd) + return E_INVALIDARG; + + if (*pszRootEnd == L'\\') + szLast = pszRootEnd; + } + + if (*szLast) + { + *szLast = L'\0'; + PathCchRemoveBackslash(pszPath, cchPath); + + return S_OK; + } + else + { + return PathCchRemoveBackslash(pszPath, cchPath); + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 12, - HRESULT, - WINAPI, - PathCchAddExtension, - _Inout_updates_(cchPath) PWSTR pszPath, - _In_ size_t cchPath, - _In_ PCWSTR pszExt - ) - { - if (pszPath == nullptr || cchPath == 0 || cchPath > PATHCCH_MAX_CCH || internal::IsValidExtensionWorker(pszExt) == false) - { - //loc_1009895F - return E_INVALIDARG; - } - - - //检测Unicode Path,如果不是,那么最多允许 260 - const auto bExtendedLengthDosDevicePath = internal::IsExtendedLengthDosDevicePath(pszPath); - if (!bExtendedLengthDosDevicePath) - { - cchPath = min(MAX_PATH, cchPath); - } - - PWSTR pszPathExt; - - auto hr = PathCchFindExtension(pszPath, cchPath, (LPCWSTR*)&pszPathExt); - - if (FAILED(hr)) - { - return hr; - } - - if (*pszPathExt != L'\0') - { - //已经存在后缀,所以我们什么也不做。 - return S_FALSE; - } - - - if (*pszExt == L'.') - ++pszExt; - - //后缀是 "" - if (*pszExt == L'\0') - { - return S_OK; - } - - do - { - const auto szPathBufferEnd = pszPath + cchPath; - auto szDest = pszPathExt; - - if (szDest >= szPathBufferEnd) - break; - - *szDest = L'.'; - ++szDest; - - for (; szDest < szPathBufferEnd; ++szDest, ++pszExt) - { - if ((*szDest = *pszExt) == L'\0') - { - return S_OK; - } - } - - } while (false); - - *pszPathExt = L'\0'; - - if (bExtendedLengthDosDevicePath) - { - if (cchPath != PATHCCH_MAX_CCH) - { - return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } - } - else - { - if (cchPath != MAX_PATH) - { - return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } - } - - - return __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); - - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 12, + HRESULT, + WINAPI, + PathCchFindExtension, + _In_reads_(_Inexpressible_(cchPath)) PCWSTR pszPath, + _In_ size_t cchPath, + _Outptr_ PCWSTR* ppszExt + ) + { + if(ppszExt == nullptr) + return E_INVALIDARG; + + *ppszExt = nullptr; + + if (pszPath == nullptr || cchPath == 0 || cchPath > PATHCCH_MAX_CCH) + { + return E_INVALIDARG; + } + + const auto szPathBufferEnd = pszPath + cchPath; + PCWSTR pszExt = nullptr; + + for (;*pszPath;++pszPath) + { + if (pszPath >= szPathBufferEnd) + return E_INVALIDARG; + + switch (*pszPath) + { + case L'\\': + case L' ': + pszExt = nullptr; + break; + case L'.': + pszExt = pszPath; + break; + default: + break; + } + } + + *ppszExt = pszExt ? pszExt : pszPath; + + return S_OK; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 12, - HRESULT, - WINAPI, - PathCchRenameExtension, - _Inout_updates_(cchPath) PWSTR pszPath, - _In_ size_t cchPath, - _In_ PCWSTR pszExt - ) - { - if (pszPath == nullptr || cchPath == 0 || cchPath > PATHCCH_MAX_CCH || internal::IsValidExtensionWorker(pszExt) == false) - return E_INVALIDARG; - - //检测Unicode Path,如果不是,那么最多允许 260 - const auto bExtendedLengthDosDevicePath = internal::IsExtendedLengthDosDevicePath(pszPath); - if (!bExtendedLengthDosDevicePath) - { - cchPath = min(MAX_PATH, cchPath); - } - - PWSTR pszPathExt; - - auto hr = PathCchFindExtension(pszPath, cchPath, (LPCWSTR*)&pszPathExt); - - if (FAILED(hr)) - { - return hr; - } - - if (*pszExt == L'.') - ++pszExt; - - //如果调用者提供的 后缀为空,那么删除现有的,然后立即返回 S_OK - if (*pszExt == L'\0') - { - *pszPathExt = L'\0'; - return S_OK; - } - - //故意不用微软的方法,微软的方法在缓存区不足时会破坏原始值。 - //覆盖现有文件后缀 - const auto szPathBufferEnd = pszPath + cchPath; - const auto cchExt = wcslen(pszExt); - - // . ext < szPathBufferEnd - if (pszPathExt + 1 + cchExt + 1 <= szPathBufferEnd) - { - *pszPathExt = L'.'; - ++pszPathExt; - - memcpy(pszPathExt, pszExt, (cchExt + 1) * sizeof(pszExt[0])); - - return S_OK; - } - - - if (bExtendedLengthDosDevicePath) - { - if (cchPath != PATHCCH_MAX_CCH) - { - return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } - } - else - { - if (cchPath != MAX_PATH) - { - return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } - } - - - return __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 12, + HRESULT, + WINAPI, + PathCchAddExtension, + _Inout_updates_(cchPath) PWSTR pszPath, + _In_ size_t cchPath, + _In_ PCWSTR pszExt + ) + { + if (pszPath == nullptr || cchPath == 0 || cchPath > PATHCCH_MAX_CCH || internal::IsValidExtensionWorker(pszExt) == false) + { + //loc_1009895F + return E_INVALIDARG; + } + + + //检测Unicode Path,如果不是,那么最多允许 260 + const auto bExtendedLengthDosDevicePath = internal::IsExtendedLengthDosDevicePath(pszPath); + if (!bExtendedLengthDosDevicePath) + { + cchPath = min(MAX_PATH, cchPath); + } + + PWSTR pszPathExt; + + auto hr = PathCchFindExtension(pszPath, cchPath, (LPCWSTR*)&pszPathExt); + + if (FAILED(hr)) + { + return hr; + } + + if (*pszPathExt != L'\0') + { + //已经存在后缀,所以我们什么也不做。 + return S_FALSE; + } + + + if (*pszExt == L'.') + ++pszExt; + + //后缀是 "" + if (*pszExt == L'\0') + { + return S_OK; + } + + do + { + const auto szPathBufferEnd = pszPath + cchPath; + auto szDest = pszPathExt; + + if (szDest >= szPathBufferEnd) + break; + + *szDest = L'.'; + ++szDest; + + for (; szDest < szPathBufferEnd; ++szDest, ++pszExt) + { + if ((*szDest = *pszExt) == L'\0') + { + return S_OK; + } + } + + } while (false); + + *pszPathExt = L'\0'; + + if (bExtendedLengthDosDevicePath) + { + if (cchPath != PATHCCH_MAX_CCH) + { + return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + } + else + { + if (cchPath != MAX_PATH) + { + return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + } + + + return __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); + + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 8, - HRESULT, - WINAPI, - PathCchRemoveExtension, - _Inout_updates_(_Inexpressible_(cchPath)) PWSTR pszPath, - _In_ size_t cchPath - ) - { - if (pszPath == nullptr || cchPath == 0 || cchPath > PATHCCH_MAX_CCH) - return E_INVALIDARG; - - const auto bExtendedLengthDosDevicePath = internal::IsExtendedLengthDosDevicePath(pszPath); - if (!bExtendedLengthDosDevicePath) - { - cchPath = min(MAX_PATH, cchPath); - } - - PWSTR pszPathExt; - - auto hr = PathCchFindExtension(pszPath, cchPath, (LPCWSTR*)&pszPathExt); - - if (FAILED(hr)) - { - return hr; - } - - - if (*pszPathExt) - { - *pszPathExt = L'\0'; - return S_OK; - } - else - { - return S_FALSE; - } - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 12, + HRESULT, + WINAPI, + PathCchRenameExtension, + _Inout_updates_(cchPath) PWSTR pszPath, + _In_ size_t cchPath, + _In_ PCWSTR pszExt + ) + { + if (pszPath == nullptr || cchPath == 0 || cchPath > PATHCCH_MAX_CCH || internal::IsValidExtensionWorker(pszExt) == false) + return E_INVALIDARG; + + //检测Unicode Path,如果不是,那么最多允许 260 + const auto bExtendedLengthDosDevicePath = internal::IsExtendedLengthDosDevicePath(pszPath); + if (!bExtendedLengthDosDevicePath) + { + cchPath = min(MAX_PATH, cchPath); + } + + PWSTR pszPathExt; + + auto hr = PathCchFindExtension(pszPath, cchPath, (LPCWSTR*)&pszPathExt); + + if (FAILED(hr)) + { + return hr; + } + + if (*pszExt == L'.') + ++pszExt; + + //如果调用者提供的 后缀为空,那么删除现有的,然后立即返回 S_OK + if (*pszExt == L'\0') + { + *pszPathExt = L'\0'; + return S_OK; + } + + //故意不用微软的方法,微软的方法在缓存区不足时会破坏原始值。 + //覆盖现有文件后缀 + const auto szPathBufferEnd = pszPath + cchPath; + const auto cchExt = wcslen(pszExt); + + // . ext < szPathBufferEnd + if (pszPathExt + 1 + cchExt + 1 <= szPathBufferEnd) + { + *pszPathExt = L'.'; + ++pszPathExt; + + memcpy(pszPathExt, pszExt, (cchExt + 1) * sizeof(pszExt[0])); + + return S_OK; + } + + + if (bExtendedLengthDosDevicePath) + { + if (cchPath != PATHCCH_MAX_CCH) + { + return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + } + else + { + if (cchPath != MAX_PATH) + { + return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + } + + + return __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); + } #endif - - -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 16, - HRESULT, - APIENTRY, - PathCchCanonicalizeEx, - _Out_writes_(cchPathOut) PWSTR pszPathOut, - _In_ size_t cchPathOut, - _In_ PCWSTR pszPathIn, - _In_ ULONG dwFlags - ) - { - if (const auto pPathCchCanonicalizeEx = try_get_PathCchCanonicalizeEx()) - { - return pPathCchCanonicalizeEx(pszPathOut, cchPathOut, pszPathIn, dwFlags); - } - - if (pszPathOut && cchPathOut) - *pszPathOut = L'\0'; - - if (cchPathOut == 0 || cchPathOut > PATHCCH_MAX_CCH) - { - return E_INVALIDARG; - } - - // MAX_PATH 长度的路径重新禁止长命名 - if (cchPathOut <= MAX_PATH) - dwFlags &= ~PATHCCH_ALLOW_LONG_PATHS; - else if ((dwFlags & PATHCCH_ALLOW_LONG_PATHS) == 0) - cchPathOut = MAX_PATH; - - DWORD ulReservedSize = 0; - - auto pTempOut = pszPathOut; - const auto pszPathOutEnd = pszPathOut + cchPathOut; - - HRESULT hr = S_OK; - - do - { - PCWSTR pszServer; - const auto bUNC = PathIsUNCEx(pszPathIn, &pszServer); - if (bUNC) - { - if (dwFlags & PATHCCH_ALLOW_LONG_PATHS) - { - ulReservedSize = 6; - - if (pTempOut + 8 >= pszPathOutEnd) - { - hr = STRSAFE_E_INSUFFICIENT_BUFFER; - } - else - { - *pTempOut++ = L'\\'; - *pTempOut++ = L'\\'; - *pTempOut++ = L'?'; - *pTempOut++ = L'\\'; - *pTempOut++ = L'U'; - *pTempOut++ = L'N'; - *pTempOut++ = L'C'; - *pTempOut++ = L'\\'; - *pTempOut = L'\0'; - } - } - else - { - if (pTempOut + 2 >= pszPathOutEnd) - { - hr = STRSAFE_E_INSUFFICIENT_BUFFER; - } - else - { - *pTempOut++ = L'\\'; - *pTempOut++ = L'\\'; - *pTempOut = L'\0'; - } - } - } - else - { - pszServer = pszPathIn; - - auto bSupportDosDevicePath = false; - - if (internal::IsExtendedLengthDosDevicePath(pszPathIn)) - { - if ((L'A' <= pszPathIn[4] && pszPathIn[4] <= L'Z') || (L'a' <= pszPathIn[4] && pszPathIn[4] <= L'z') - && pszPathIn[5] == L':') - { - pszServer += 4; - bSupportDosDevicePath = true; - } - } - else if ((L'A' <= pszPathIn[0] && pszPathIn[0] <= L'Z') || (L'a' <= pszPathIn[0] && pszPathIn[0] <= L'z') - && pszPathIn[1] == L':') - { - bSupportDosDevicePath = true; - } - - if (bSupportDosDevicePath && (dwFlags & PATHCCH_ALLOW_LONG_PATHS)) - { - ulReservedSize = 4; - - if (pTempOut + 4 >= pszPathOutEnd) - { - hr = STRSAFE_E_INSUFFICIENT_BUFFER; - } - else - { - *pTempOut++ = L'\\'; - *pTempOut++ = L'\\'; - *pTempOut++ = L'?'; - *pTempOut++ = L'\\'; - *pTempOut = L'\0'; - } - } - } - - - //LABEL_49 - //剩余部分是否 <= MAX_PATH,如果满足条件,那么应该重新开始。并且将路径限制在 MAX_PATH - if ((dwFlags & PATHCCH_ALLOW_LONG_PATHS) && ulReservedSize && cchPathOut <= ulReservedSize + MAX_PATH) - { - if (cchPathOut > MAX_PATH) - cchPathOut = MAX_PATH; - - ulReservedSize = 0; - pszServer = pszPathIn; - - pTempOut = pszPathOut; - - //缓冲区必然 >= 1 ,所以我们可以直接设置。 - *pTempOut = L'\0'; - // 清除错误,方便我们重新开始。 - hr = S_OK; - } - - - if (FAILED(hr)) - break; - - for (;*pszServer;) - { - /* 获取下一个文件名,故意不用微软的方案,而且效率低…… - * 遇到 '\\' 则说明文件名结束 - * 遇到 '\0' 则说明路径也结束了 - */ - unsigned cchFileName = 0; - for (; pszServer[cchFileName] && pszServer[cchFileName] != L'\\'; ++cchFileName) - { - /* 安全检查 - * 1. 普通路径中,文件名最多 256个字符 - * 2. 路径最大处理长度为 PATHCCH_MAX_CCH - */ - - if (((dwFlags & PATHCCH_ALLOW_LONG_PATHS) == 0 && cchFileName > MAXIMUM_FILENAME_LENGTH) - || cchFileName >= PATHCCH_MAX_CCH) - { - hr = __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); - goto OnFailedLabel; - } - } - - if (cchFileName == 1 && pszServer[0] == L'.') - { - //表示当前目录 - - ++pszServer; - - if (*pszServer) - { - //说明这里是 '\\',继续跳过 - ++pszServer; - } - else - { - //这里是 L'\0' - - if (pTempOut > pszPathOut && PathCchIsRoot(pszPathOut) == FALSE) - { - //不是跟目录,而且结束,那么需要删除最后的 '\\' - --pTempOut; - *pTempOut = L'\0'; - } - } - - continue; - } - else if (cchFileName == 2 - && pszServer[0] == L'.' - && pszServer[1] == L'.') - { - //表示上级目录 - - pszServer += 2; - - if (pTempOut <= pszPathOut || PathCchIsRoot(pszPathOut)) - { - //文件是根目录,或者开始位置时,遇到 ".." 则直接忽略即可。 - - if (*pszServer == L'\\') - ++pszServer; - } - else - { - auto szPrevious = (wchar_t*)internal::FindPreviousBackslashWorker(pszPathOut, pTempOut - 1); - - pTempOut = szPrevious ? szPrevious : pszPathOut; - - *pTempOut = L'\0'; - } - - continue; - } - else - { - if (cchFileName == 0 - && pszServer[0] == L'\\') - { - cchFileName = 1; - } - - - if (pTempOut + cchFileName >= pszPathOutEnd) - { - //空间不足,特殊判断一下,某些特定的形式是可以处理的。 - if (cchFileName == 1 && pszServer[0] == L'\\') - { - if (pszServer[1] == L'\0' || (pszServer[1] == L'.' && pszServer[2] == L'\0')) - { - //可以确认,路径已经结束,所以无需再添加 '\\' - break; - } - else if (pTempOut + 1 == pszPathOutEnd - && pszServer[1] == L'.' - && pszServer[2] == L'.') - { - //下一个项目是返回上一个项目,所以可以伪造一下,直接设置为 L'\0' 然后往下移动 - ++pszServer; - *pTempOut++ = L'\0'; - continue; - } - } - - hr = __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); - goto OnFailedLabel; - } - - //复制文件名 - memcpy(pTempOut, pszServer, cchFileName * sizeof(pszServer[0])); - pszServer += cchFileName; - pTempOut += cchFileName; - *pTempOut = L'\0'; - } - } - - /* 删除 路径末尾的 . - * "*." 则保留 - */ - if (pTempOut > pszPathOut) - { - auto Str = pTempOut; - --Str; - - if (*Str == L'.') - { - for (;;) - { - if (Str == pszPathOut) - { - *Str = L'\0'; - pTempOut = Str; - break; - } - - --Str; - - if (*Str != L'*') - { - pTempOut = Str + 1; - *pTempOut = L'\0'; - - if (*Str == L'.') - continue; - } - - //goto LABEL_29; - break; - } - - - } - } - - //LABEL_29: - - constexpr int nCountOfData = _countof(L"::$DATA") - 1; - - if (pszPathOut + nCountOfData <= pTempOut - && pTempOut[-7] == L':' - && pTempOut[-6] == L':' - && pTempOut[-5] == L'$' - && (pTempOut[-4] == L'D' || pTempOut[-3] == L'd') - && (pTempOut[-3] == L'A' || pTempOut[-3] == L'a') - && (pTempOut[-2] == L'T' || pTempOut[-1] == L't') - && (pTempOut[-1] == L'A' || pTempOut[-1] == L'a')) - { - pTempOut -= nCountOfData; - *pTempOut = L'\0'; - } - - - //处于长命名模式中,如果规范化后的路径有效部分小于 MAX_PATH,那么删除长命名前缀 - if (ulReservedSize) - { - if (size_t(pTempOut - pszPathOut) <= ulReservedSize + MAX_PATH) - { - if (bUNC) - { - // "\\\\?\\UNC\\" - memmove(pszPathOut + 2, pszPathOut + 8, (pTempOut - (pszPathOut + 8) + 1) * sizeof(pTempOut[0])); - } - else - { - memmove(pszPathOut, pszPathOut + 4, (pTempOut - (pszPathOut + 4) + 1) * sizeof(pTempOut[0])); - } - } - } - - - if (cchPathOut > 1 && *pszPathOut == L'\0') - { - //如果路径为 空,则转换为 "\\" - pszPathOut[0] = L'\\'; - pszPathOut[1] = L'\0'; - } - else if(cchPathOut > 3 && pszPathOut[1] == L':' && pszPathOut[2] == L'\0') - { - // 如果路径为 "X:",则转换为 "X:\\" - pszPathOut[2] = L'\\'; - pszPathOut[3] = L'\0'; - } - - return S_OK; - - } while (false); - - - //LABEL_96 失败 - OnFailedLabel: - - *pszPathOut = L'\0'; - - if (hr == STRSAFE_E_INSUFFICIENT_BUFFER) - { - if (dwFlags & PATHCCH_ALLOW_LONG_PATHS) - { - if(cchPathOut == PATHCCH_MAX_CCH) - hr = __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); - } - else - { - if (cchPathOut == MAX_PATH) - hr = __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); - } - } - - return hr; - - } + + +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 8, + HRESULT, + WINAPI, + PathCchRemoveExtension, + _Inout_updates_(_Inexpressible_(cchPath)) PWSTR pszPath, + _In_ size_t cchPath + ) + { + if (pszPath == nullptr || cchPath == 0 || cchPath > PATHCCH_MAX_CCH) + return E_INVALIDARG; + + const auto bExtendedLengthDosDevicePath = internal::IsExtendedLengthDosDevicePath(pszPath); + if (!bExtendedLengthDosDevicePath) + { + cchPath = min(MAX_PATH, cchPath); + } + + PWSTR pszPathExt; + + auto hr = PathCchFindExtension(pszPath, cchPath, (LPCWSTR*)&pszPathExt); + + if (FAILED(hr)) + { + return hr; + } + + + if (*pszPathExt) + { + *pszPathExt = L'\0'; + return S_OK; + } + else + { + return S_FALSE; + } + } #endif + + +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 16, + HRESULT, + APIENTRY, + PathCchCanonicalizeEx, + _Out_writes_(cchPathOut) PWSTR pszPathOut, + _In_ size_t cchPathOut, + _In_ PCWSTR pszPathIn, + _In_ ULONG dwFlags + ) + { + if (const auto pPathCchCanonicalizeEx = try_get_PathCchCanonicalizeEx()) + { + return pPathCchCanonicalizeEx(pszPathOut, cchPathOut, pszPathIn, dwFlags); + } + + if (pszPathOut && cchPathOut) + *pszPathOut = L'\0'; + + if (cchPathOut == 0 || cchPathOut > PATHCCH_MAX_CCH) + { + return E_INVALIDARG; + } + + // MAX_PATH 长度的路径重新禁止长命名 + if (cchPathOut <= MAX_PATH) + dwFlags &= ~PATHCCH_ALLOW_LONG_PATHS; + else if ((dwFlags & PATHCCH_ALLOW_LONG_PATHS) == 0) + cchPathOut = MAX_PATH; + + DWORD ulReservedSize = 0; + + auto pTempOut = pszPathOut; + const auto pszPathOutEnd = pszPathOut + cchPathOut; + + HRESULT hr = S_OK; + + do + { + PCWSTR pszServer; + const auto bUNC = PathIsUNCEx(pszPathIn, &pszServer); + if (bUNC) + { + if (dwFlags & PATHCCH_ALLOW_LONG_PATHS) + { + ulReservedSize = 6; + + if (pTempOut + 8 >= pszPathOutEnd) + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + else + { + *pTempOut++ = L'\\'; + *pTempOut++ = L'\\'; + *pTempOut++ = L'?'; + *pTempOut++ = L'\\'; + *pTempOut++ = L'U'; + *pTempOut++ = L'N'; + *pTempOut++ = L'C'; + *pTempOut++ = L'\\'; + *pTempOut = L'\0'; + } + } + else + { + if (pTempOut + 2 >= pszPathOutEnd) + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + else + { + *pTempOut++ = L'\\'; + *pTempOut++ = L'\\'; + *pTempOut = L'\0'; + } + } + } + else + { + pszServer = pszPathIn; + + auto bSupportDosDevicePath = false; + + if (internal::IsExtendedLengthDosDevicePath(pszPathIn)) + { + if ((L'A' <= pszPathIn[4] && pszPathIn[4] <= L'Z') || (L'a' <= pszPathIn[4] && pszPathIn[4] <= L'z') + && pszPathIn[5] == L':') + { + pszServer += 4; + bSupportDosDevicePath = true; + } + } + else if ((L'A' <= pszPathIn[0] && pszPathIn[0] <= L'Z') || (L'a' <= pszPathIn[0] && pszPathIn[0] <= L'z') + && pszPathIn[1] == L':') + { + bSupportDosDevicePath = true; + } + + if (bSupportDosDevicePath && (dwFlags & PATHCCH_ALLOW_LONG_PATHS)) + { + ulReservedSize = 4; + + if (pTempOut + 4 >= pszPathOutEnd) + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + else + { + *pTempOut++ = L'\\'; + *pTempOut++ = L'\\'; + *pTempOut++ = L'?'; + *pTempOut++ = L'\\'; + *pTempOut = L'\0'; + } + } + } + + + //LABEL_49 + //剩余部分是否 <= MAX_PATH,如果满足条件,那么应该重新开始。并且将路径限制在 MAX_PATH + if ((dwFlags & PATHCCH_ALLOW_LONG_PATHS) && ulReservedSize && cchPathOut <= ulReservedSize + MAX_PATH) + { + if (cchPathOut > MAX_PATH) + cchPathOut = MAX_PATH; + + ulReservedSize = 0; + pszServer = pszPathIn; + + pTempOut = pszPathOut; + + //缓冲区必然 >= 1 ,所以我们可以直接设置。 + *pTempOut = L'\0'; + // 清除错误,方便我们重新开始。 + hr = S_OK; + } + + + if (FAILED(hr)) + break; + + for (;*pszServer;) + { + /* 获取下一个文件名,故意不用微软的方案,而且效率低…… + * 遇到 '\\' 则说明文件名结束 + * 遇到 '\0' 则说明路径也结束了 + */ + unsigned cchFileName = 0; + for (; pszServer[cchFileName] && pszServer[cchFileName] != L'\\'; ++cchFileName) + { + /* 安全检查 + * 1. 普通路径中,文件名最多 256个字符 + * 2. 路径最大处理长度为 PATHCCH_MAX_CCH + */ + + if (((dwFlags & PATHCCH_ALLOW_LONG_PATHS) == 0 && cchFileName > MAXIMUM_FILENAME_LENGTH) + || cchFileName >= PATHCCH_MAX_CCH) + { + hr = __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); + goto OnFailedLabel; + } + } + + if (cchFileName == 1 && pszServer[0] == L'.') + { + //表示当前目录 + + ++pszServer; + + if (*pszServer) + { + //说明这里是 '\\',继续跳过 + ++pszServer; + } + else + { + //这里是 L'\0' + + if (pTempOut > pszPathOut && PathCchIsRoot(pszPathOut) == FALSE) + { + //不是跟目录,而且结束,那么需要删除最后的 '\\' + --pTempOut; + *pTempOut = L'\0'; + } + } + + continue; + } + else if (cchFileName == 2 + && pszServer[0] == L'.' + && pszServer[1] == L'.') + { + //表示上级目录 + + pszServer += 2; + + if (pTempOut <= pszPathOut || PathCchIsRoot(pszPathOut)) + { + //文件是根目录,或者开始位置时,遇到 ".." 则直接忽略即可。 + + if (*pszServer == L'\\') + ++pszServer; + } + else + { + auto szPrevious = (wchar_t*)internal::FindPreviousBackslashWorker(pszPathOut, pTempOut - 1); + + pTempOut = szPrevious ? szPrevious : pszPathOut; + + *pTempOut = L'\0'; + } + + continue; + } + else + { + if (cchFileName == 0 + && pszServer[0] == L'\\') + { + cchFileName = 1; + } + + + if (pTempOut + cchFileName >= pszPathOutEnd) + { + //空间不足,特殊判断一下,某些特定的形式是可以处理的。 + if (cchFileName == 1 && pszServer[0] == L'\\') + { + if (pszServer[1] == L'\0' || (pszServer[1] == L'.' && pszServer[2] == L'\0')) + { + //可以确认,路径已经结束,所以无需再添加 '\\' + break; + } + else if (pTempOut + 1 == pszPathOutEnd + && pszServer[1] == L'.' + && pszServer[2] == L'.') + { + //下一个项目是返回上一个项目,所以可以伪造一下,直接设置为 L'\0' 然后往下移动 + ++pszServer; + *pTempOut++ = L'\0'; + continue; + } + } + + hr = __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); + goto OnFailedLabel; + } + + //复制文件名 + memcpy(pTempOut, pszServer, cchFileName * sizeof(pszServer[0])); + pszServer += cchFileName; + pTempOut += cchFileName; + *pTempOut = L'\0'; + } + } + + /* 删除 路径末尾的 . + * "*." 则保留 + */ + if (pTempOut > pszPathOut) + { + auto Str = pTempOut; + --Str; + + if (*Str == L'.') + { + for (;;) + { + if (Str == pszPathOut) + { + *Str = L'\0'; + pTempOut = Str; + break; + } + + --Str; + + if (*Str != L'*') + { + pTempOut = Str + 1; + *pTempOut = L'\0'; + + if (*Str == L'.') + continue; + } + + //goto LABEL_29; + break; + } + + + } + } + + //LABEL_29: + + constexpr int nCountOfData = _countof(L"::$DATA") - 1; + + if (pszPathOut + nCountOfData <= pTempOut + && pTempOut[-7] == L':' + && pTempOut[-6] == L':' + && pTempOut[-5] == L'$' + && (pTempOut[-4] == L'D' || pTempOut[-3] == L'd') + && (pTempOut[-3] == L'A' || pTempOut[-3] == L'a') + && (pTempOut[-2] == L'T' || pTempOut[-1] == L't') + && (pTempOut[-1] == L'A' || pTempOut[-1] == L'a')) + { + pTempOut -= nCountOfData; + *pTempOut = L'\0'; + } + + + //处于长命名模式中,如果规范化后的路径有效部分小于 MAX_PATH,那么删除长命名前缀 + if (ulReservedSize) + { + if (size_t(pTempOut - pszPathOut) <= ulReservedSize + MAX_PATH) + { + if (bUNC) + { + // "\\\\?\\UNC\\" + memmove(pszPathOut + 2, pszPathOut + 8, (pTempOut - (pszPathOut + 8) + 1) * sizeof(pTempOut[0])); + } + else + { + memmove(pszPathOut, pszPathOut + 4, (pTempOut - (pszPathOut + 4) + 1) * sizeof(pTempOut[0])); + } + } + } + + + if (cchPathOut > 1 && *pszPathOut == L'\0') + { + //如果路径为 空,则转换为 "\\" + pszPathOut[0] = L'\\'; + pszPathOut[1] = L'\0'; + } + else if(cchPathOut > 3 && pszPathOut[1] == L':' && pszPathOut[2] == L'\0') + { + // 如果路径为 "X:",则转换为 "X:\\" + pszPathOut[2] = L'\\'; + pszPathOut[3] = L'\0'; + } + + return S_OK; + + } while (false); -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 12, - HRESULT, - WINAPI, - PathCchCanonicalize, - _Out_writes_(cchPathOut) PWSTR pszPathOut, - _In_ size_t cchPathOut, - _In_ PCWSTR pszPathIn - ) - { - return PathCchCanonicalizeEx(pszPathOut, cchPathOut, pszPathIn, 0); - } + //LABEL_96 失败 + OnFailedLabel: + + *pszPathOut = L'\0'; + + if (hr == STRSAFE_E_INSUFFICIENT_BUFFER) + { + if (dwFlags & PATHCCH_ALLOW_LONG_PATHS) + { + if(cchPathOut == PATHCCH_MAX_CCH) + hr = __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); + } + else + { + if (cchPathOut == MAX_PATH) + hr = __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); + } + } + + return hr; + + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 20, - HRESULT, - WINAPI, - PathCchCombineEx, - _Out_writes_(cchPathOut) PWSTR pszPathOut, - _In_ size_t cchPathOut, - _In_opt_ PCWSTR pszPathIn, - _In_opt_ PCWSTR pszMore, - _In_ ULONG dwFlags - ) - { - if (pszPathOut == nullptr - || cchPathOut == 0 - || cchPathOut > PATHCCH_MAX_CCH) - { - return E_INVALIDARG; - } - - - wchar_t PathOutStaticBuffer[MAX_PATH]; - PWSTR pszPathOutTmp = nullptr; - size_t cchPathOutTmp = 0; - - HRESULT hr = S_OK; - - do - { - if (pszPathIn == nullptr && pszMore == nullptr) - { - hr = E_INVALIDARG; - break; - } - - size_t cchPathIn = pszPathIn ? wcslen(pszPathIn) : 0; - if (cchPathIn >= PATHCCH_MAX_CCH) - { - hr = __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); - break; - } - - size_t cchMore = pszMore ? wcslen(pszMore) : 0; - if (cchMore >= PATHCCH_MAX_CCH) - { - hr = __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); - break; - } - - //极端情况可能需要额外添加 '\\' 连接,简化处理,直接 + 1。改逻辑与微软不同。 - //字符串末尾需要 '\0' 结束 - const auto cchPathInNeed = cchPathIn + cchMore + 1 + 1; - - - if (cchPathInNeed < _countof(PathOutStaticBuffer)) - { - //静态缓冲区可以容纳,我们直接使用静态缓冲区 - pszPathOutTmp = PathOutStaticBuffer; - } - else - { - //好吧,我们真的需要开辟临时缓冲区 - pszPathOutTmp = (PWSTR)LocalAlloc(LMEM_ZEROINIT, cchPathInNeed * sizeof(wchar_t)); - if (!pszPathOutTmp) - { - hr = E_OUTOFMEMORY; - break; - } - } - - if (cchPathIn == 0) - { - memcpy(pszPathOutTmp, pszMore, cchMore * sizeof(wchar_t)); - cchPathOutTmp = cchMore; - } - else if (cchMore == 0) - { - memcpy(pszPathOutTmp, pszPathIn, cchPathIn * sizeof(wchar_t)); - cchPathOutTmp = cchPathIn; - } - else - { - if (internal::PathIsRelativeWorker(pszMore)) - { - memcpy(pszPathOutTmp, pszPathIn, cchPathIn * sizeof(wchar_t)); - cchPathOutTmp = cchPathIn; - } - else - { - if (pszMore[0] == L'\\' && pszMore[1] != L'\\') - { - //路径是 '\\' 开头,那么 它与 pszPathIn 的根目录进行合并 - ++pszMore; - --cchMore; - - - PCWSTR pszRootEnd; - hr = PathCchSkipRoot(pszPathIn, &pszRootEnd); - if (FAILED(hr)) - { - break; - } - - cchPathOutTmp = pszRootEnd - pszPathIn; - memcpy(pszPathOutTmp, pszPathIn, cchPathOutTmp * sizeof(wchar_t)); - } - else - { - //这是一个绝对的路径,我们只需要把 pszMore 复制到 pszPathOutTmp - memcpy(pszPathOutTmp, pszMore, cchMore * sizeof(wchar_t)); - cchPathOutTmp = cchMore; - break; - } - } - - /* - * 不想调用它……只是追加一个 '\' 而已 - PWSTR pszEnd; - hr = PathCchAddBackslashEx(pszPathOutTmp, cchPathOutTmp, &pszEnd, &cchPathOutTmp); - if (FAILED(hr)) - { - break; - } - */ - if (cchPathOutTmp && pszPathOutTmp[cchPathOutTmp - 1] != L'\\') - { - pszPathOutTmp[cchPathOutTmp] = L'\\'; - ++cchPathOutTmp; - } - - memcpy(pszPathOutTmp + cchPathOutTmp, pszMore, cchMore * sizeof(wchar_t)); - cchPathOutTmp += cchMore; - } - - } while (false); - - if (FAILED(hr)) - { - *pszPathOut = L'\0'; - } - else - { - //保证字符串 '\0' 截断 - pszPathOutTmp[cchPathOutTmp] = L'\0'; - hr = PathCchCanonicalizeEx(pszPathOut, cchPathOut, pszPathOutTmp, dwFlags); - } - - if (pszPathOutTmp && pszPathOutTmp != PathOutStaticBuffer) - LocalFree(pszPathOutTmp); - - return hr; - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 12, + HRESULT, + WINAPI, + PathCchCanonicalize, + _Out_writes_(cchPathOut) PWSTR pszPathOut, + _In_ size_t cchPathOut, + _In_ PCWSTR pszPathIn + ) + { + return PathCchCanonicalizeEx(pszPathOut, cchPathOut, pszPathIn, 0); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 16, - HRESULT, - WINAPI, - PathCchCombine, - _Out_writes_(cchPathOut) PWSTR pszPathOut, - _In_ size_t cchPathOut, - _In_opt_ PCWSTR pszPathIn, - _In_opt_ PCWSTR pszMore - ) - { - return PathCchCombineEx(pszPathOut, cchPathOut, pszPathIn, pszMore, 0); - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 20, + HRESULT, + WINAPI, + PathCchCombineEx, + _Out_writes_(cchPathOut) PWSTR pszPathOut, + _In_ size_t cchPathOut, + _In_opt_ PCWSTR pszPathIn, + _In_opt_ PCWSTR pszMore, + _In_ ULONG dwFlags + ) + { + if (pszPathOut == nullptr + || cchPathOut == 0 + || cchPathOut > PATHCCH_MAX_CCH) + { + return E_INVALIDARG; + } + + + wchar_t PathOutStaticBuffer[MAX_PATH]; + PWSTR pszPathOutTmp = nullptr; + size_t cchPathOutTmp = 0; + + HRESULT hr = S_OK; + + do + { + if (pszPathIn == nullptr && pszMore == nullptr) + { + hr = E_INVALIDARG; + break; + } + + size_t cchPathIn = pszPathIn ? wcslen(pszPathIn) : 0; + if (cchPathIn >= PATHCCH_MAX_CCH) + { + hr = __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); + break; + } + + size_t cchMore = pszMore ? wcslen(pszMore) : 0; + if (cchMore >= PATHCCH_MAX_CCH) + { + hr = __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); + break; + } + + //极端情况可能需要额外添加 '\\' 连接,简化处理,直接 + 1。改逻辑与微软不同。 + //字符串末尾需要 '\0' 结束 + const auto cchPathInNeed = cchPathIn + cchMore + 1 + 1; + + + if (cchPathInNeed < _countof(PathOutStaticBuffer)) + { + //静态缓冲区可以容纳,我们直接使用静态缓冲区 + pszPathOutTmp = PathOutStaticBuffer; + } + else + { + //好吧,我们真的需要开辟临时缓冲区 + pszPathOutTmp = (PWSTR)LocalAlloc(LMEM_ZEROINIT, cchPathInNeed * sizeof(wchar_t)); + if (!pszPathOutTmp) + { + hr = E_OUTOFMEMORY; + break; + } + } + + if (cchPathIn == 0) + { + memcpy(pszPathOutTmp, pszMore, cchMore * sizeof(wchar_t)); + cchPathOutTmp = cchMore; + } + else if (cchMore == 0) + { + memcpy(pszPathOutTmp, pszPathIn, cchPathIn * sizeof(wchar_t)); + cchPathOutTmp = cchPathIn; + } + else + { + if (internal::PathIsRelativeWorker(pszMore)) + { + memcpy(pszPathOutTmp, pszPathIn, cchPathIn * sizeof(wchar_t)); + cchPathOutTmp = cchPathIn; + } + else + { + if (pszMore[0] == L'\\' && pszMore[1] != L'\\') + { + //路径是 '\\' 开头,那么 它与 pszPathIn 的根目录进行合并 + ++pszMore; + --cchMore; + + + PCWSTR pszRootEnd; + hr = PathCchSkipRoot(pszPathIn, &pszRootEnd); + if (FAILED(hr)) + { + break; + } + + cchPathOutTmp = pszRootEnd - pszPathIn; + memcpy(pszPathOutTmp, pszPathIn, cchPathOutTmp * sizeof(wchar_t)); + } + else + { + //这是一个绝对的路径,我们只需要把 pszMore 复制到 pszPathOutTmp + memcpy(pszPathOutTmp, pszMore, cchMore * sizeof(wchar_t)); + cchPathOutTmp = cchMore; + break; + } + } + + /* + * 不想调用它……只是追加一个 '\' 而已 + PWSTR pszEnd; + hr = PathCchAddBackslashEx(pszPathOutTmp, cchPathOutTmp, &pszEnd, &cchPathOutTmp); + if (FAILED(hr)) + { + break; + } + */ + if (cchPathOutTmp && pszPathOutTmp[cchPathOutTmp - 1] != L'\\') + { + pszPathOutTmp[cchPathOutTmp] = L'\\'; + ++cchPathOutTmp; + } + + memcpy(pszPathOutTmp + cchPathOutTmp, pszMore, cchMore * sizeof(wchar_t)); + cchPathOutTmp += cchMore; + } + + } while (false); + + if (FAILED(hr)) + { + *pszPathOut = L'\0'; + } + else + { + //保证字符串 '\0' 截断 + pszPathOutTmp[cchPathOutTmp] = L'\0'; + hr = PathCchCanonicalizeEx(pszPathOut, cchPathOut, pszPathOutTmp, dwFlags); + } + + if (pszPathOutTmp && pszPathOutTmp != PathOutStaticBuffer) + LocalFree(pszPathOutTmp); + + return hr; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 16, - HRESULT, - WINAPI, - PathCchAppendEx, - _Inout_updates_(cchPath) PWSTR pszPath, - _In_ size_t cchPath, - _In_opt_ PCWSTR pszMore, - _In_ ULONG dwFlags - ) - { - if (pszMore && PathIsUNCEx(pszMore, nullptr) == false && internal::IsExtendedLengthDosDevicePath(pszMore) == false) - { - //跳过开头的所有 '\\' - for (;*pszMore == L'\\';++pszMore); - } - - return PathCchCombineEx(pszPath, cchPath, pszPath, pszMore, dwFlags); - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 16, + HRESULT, + WINAPI, + PathCchCombine, + _Out_writes_(cchPathOut) PWSTR pszPathOut, + _In_ size_t cchPathOut, + _In_opt_ PCWSTR pszPathIn, + _In_opt_ PCWSTR pszMore + ) + { + return PathCchCombineEx(pszPathOut, cchPathOut, pszPathIn, pszMore, 0); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 12, - HRESULT, - WINAPI, - PathCchAppend, - _Inout_updates_(cchPath) PWSTR pszPath, - _In_ size_t cchPath, - _In_opt_ PCWSTR pszMore - ) - { - return PathCchAppendEx(pszPath, cchPath, pszMore, 0); - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 16, + HRESULT, + WINAPI, + PathCchAppendEx, + _Inout_updates_(cchPath) PWSTR pszPath, + _In_ size_t cchPath, + _In_opt_ PCWSTR pszMore, + _In_ ULONG dwFlags + ) + { + if (pszMore && PathIsUNCEx(pszMore, nullptr) == false && internal::IsExtendedLengthDosDevicePath(pszMore) == false) + { + //跳过开头的所有 '\\' + for (;*pszMore == L'\\';++pszMore); + } + + return PathCchCombineEx(pszPath, cchPath, pszPath, pszMore, dwFlags); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 8, - HRESULT, - WINAPI, - PathCchStripPrefix, - _Inout_updates_(cchPath) PWSTR pszPath, - _In_ size_t cchPath - ) - { - if (pszPath == nullptr || cchPath == 0 || cchPath > PATHCCH_MAX_CCH) - return E_INVALIDARG; - - if (!internal::IsExtendedLengthDosDevicePath(pszPath)) - return S_FALSE; - - if (cchPath < 4) - return E_INVALIDARG; - - if ((pszPath[4] == L'U' || pszPath[4] == L'u') - && (pszPath[5] == L'N' || pszPath[5] == L'n') - && (pszPath[6] == L'C' || pszPath[6] == L'c') - && pszPath[7] == L'\\') - { - if (cchPath < 8) - return E_INVALIDARG; - - return StringCchCopyW(pszPath + 2, cchPath - 2, pszPath + 8); - } - else if ((L'A' <= pszPath[4] && pszPath[4] <= L'Z' || L'a' <= pszPath[4] && pszPath[4] <= L'z') - && pszPath[5] == L':') - { - return StringCchCopyW(pszPath, cchPath, pszPath + 4); - } - else - { - return S_FALSE; - } - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 12, + HRESULT, + WINAPI, + PathCchAppend, + _Inout_updates_(cchPath) PWSTR pszPath, + _In_ size_t cchPath, + _In_opt_ PCWSTR pszMore + ) + { + return PathCchAppendEx(pszPath, cchPath, pszMore, 0); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 8, + HRESULT, + WINAPI, + PathCchStripPrefix, + _Inout_updates_(cchPath) PWSTR pszPath, + _In_ size_t cchPath + ) + { + if (pszPath == nullptr || cchPath == 0 || cchPath > PATHCCH_MAX_CCH) + return E_INVALIDARG; + + if (!internal::IsExtendedLengthDosDevicePath(pszPath)) + return S_FALSE; + + if (cchPath < 4) + return E_INVALIDARG; + + if ((pszPath[4] == L'U' || pszPath[4] == L'u') + && (pszPath[5] == L'N' || pszPath[5] == L'n') + && (pszPath[6] == L'C' || pszPath[6] == L'c') + && pszPath[7] == L'\\') + { + if (cchPath < 8) + return E_INVALIDARG; + + return StringCchCopyW(pszPath + 2, cchPath - 2, pszPath + 8); + } + else if ((L'A' <= pszPath[4] && pszPath[4] <= L'Z' || L'a' <= pszPath[4] && pszPath[4] <= L'z') + && pszPath[5] == L':') + { + return StringCchCopyW(pszPath, cchPath, pszPath + 4); + } + else + { + return S_FALSE; + } + } +#endif + - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 16, - HRESULT, - WINAPI, - PathAllocCombine, - _In_opt_ PCWSTR pszPathIn, - _In_opt_ PCWSTR pszMore, - _In_ ULONG dwFlags, - _Outptr_ PWSTR* ppszPathOut - ) - { - if (const auto pPathAllocCombine = try_get_PathAllocCombine()) - { - return pPathAllocCombine(pszPathIn, pszMore, dwFlags, ppszPathOut); - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 16, + HRESULT, + WINAPI, + PathAllocCombine, + _In_opt_ PCWSTR pszPathIn, + _In_opt_ PCWSTR pszMore, + _In_ ULONG dwFlags, + _Outptr_ PWSTR* ppszPathOut + ) + { + if (const auto pPathAllocCombine = try_get_PathAllocCombine()) + { + return pPathAllocCombine(pszPathIn, pszMore, dwFlags, ppszPathOut); + } - //参数检查 - if (ppszPathOut == nullptr) - return E_INVALIDARG; + //参数检查 + if (ppszPathOut == nullptr) + return E_INVALIDARG; - *ppszPathOut = nullptr; + *ppszPathOut = nullptr; - //不能同时为 null - if (pszPathIn == nullptr && pszMore == nullptr) - return E_INVALIDARG; + //不能同时为 null + if (pszPathIn == nullptr && pszMore == nullptr) + return E_INVALIDARG; - size_t cchPathIn = pszPathIn ? wcslen(pszPathIn) : 0; + size_t cchPathIn = pszPathIn ? wcslen(pszPathIn) : 0; - if(cchPathIn >= PATHCCH_MAX_CCH) - return __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); + if(cchPathIn >= PATHCCH_MAX_CCH) + return __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); - if (cchPathIn) - ++cchPathIn; - - size_t cchMore = pszMore ? wcslen(pszMore) : 0; + if (cchPathIn) + ++cchPathIn; + + size_t cchMore = pszMore ? wcslen(pszMore) : 0; - if (cchMore >= PATHCCH_MAX_CCH) - return __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); + if (cchMore >= PATHCCH_MAX_CCH) + return __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); - if (cchMore) - ++cchMore; + if (cchMore) + ++cchMore; - auto cchBufferSize = cchPathIn + cchMore; + auto cchBufferSize = cchPathIn + cchMore; - if (cchBufferSize == 0) - { - //"\\\0" - cchBufferSize = 2; - } - else if (cchBufferSize > MAX_PATH && (dwFlags & PATHCCH_ALLOW_LONG_PATHS)) - { - //"\\\\?\\UNC\0" - cchBufferSize += 6; - } + if (cchBufferSize == 0) + { + //"\\\0" + cchBufferSize = 2; + } + else if (cchBufferSize > MAX_PATH && (dwFlags & PATHCCH_ALLOW_LONG_PATHS)) + { + //"\\\\?\\UNC\0" + cchBufferSize += 6; + } - //保证边界依然在 最大值内 - const unsigned cchMaxPath = (dwFlags & PATHCCH_ALLOW_LONG_PATHS) ? PATHCCH_MAX_CCH : MAX_PATH; - if (cchBufferSize > cchMaxPath) - cchBufferSize = cchMaxPath; + //保证边界依然在 最大值内 + const unsigned cchMaxPath = (dwFlags & PATHCCH_ALLOW_LONG_PATHS) ? PATHCCH_MAX_CCH : MAX_PATH; + if (cchBufferSize > cchMaxPath) + cchBufferSize = cchMaxPath; - auto pBuffer = (wchar_t*)LocalAlloc(LMEM_ZEROINIT, sizeof(wchar_t) * cchBufferSize); + auto pBuffer = (wchar_t*)LocalAlloc(LMEM_ZEROINIT, sizeof(wchar_t) * cchBufferSize); - if (pBuffer == nullptr) - return E_OUTOFMEMORY; + if (pBuffer == nullptr) + return E_OUTOFMEMORY; - auto hr = PathCchCombineEx(pBuffer, cchBufferSize, pszPathIn, pszMore, dwFlags); + auto hr = PathCchCombineEx(pBuffer, cchBufferSize, pszPathIn, pszMore, dwFlags); - if (FAILED(hr)) - { - LocalFree(pBuffer); - return hr; - } + if (FAILED(hr)) + { + LocalFree(pBuffer); + return hr; + } - *ppszPathOut = pBuffer; + *ppszPathOut = pBuffer; - return hr; - } + return hr; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_path_l1_1_0, - 12, - HRESULT, - WINAPI, - PathAllocCanonicalize, - _In_ PCWSTR pszPathIn, - _In_ ULONG dwFlags, - _Outptr_ PWSTR* ppszPathOut - ) - { - if (const auto pPathAllocCanonicalize = try_get_PathAllocCanonicalize()) - { - return pPathAllocCanonicalize(pszPathIn, dwFlags, ppszPathOut); - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_path_l1_1_0, + 12, + HRESULT, + WINAPI, + PathAllocCanonicalize, + _In_ PCWSTR pszPathIn, + _In_ ULONG dwFlags, + _Outptr_ PWSTR* ppszPathOut + ) + { + if (const auto pPathAllocCanonicalize = try_get_PathAllocCanonicalize()) + { + return pPathAllocCanonicalize(pszPathIn, dwFlags, ppszPathOut); + } - //参数检查 - if (ppszPathOut == nullptr) - return E_INVALIDARG; + //参数检查 + if (ppszPathOut == nullptr) + return E_INVALIDARG; - *ppszPathOut = nullptr; + *ppszPathOut = nullptr; - auto cchBufferSize = pszPathIn ? wcslen(pszPathIn) : 0; + auto cchBufferSize = pszPathIn ? wcslen(pszPathIn) : 0; - if(cchBufferSize >= PATHCCH_MAX_CCH) - return __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); + if(cchBufferSize >= PATHCCH_MAX_CCH) + return __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); - if (cchBufferSize) - { - ++cchBufferSize; - } - else - { - // "\\\0" - cchBufferSize = 2; - } + if (cchBufferSize) + { + ++cchBufferSize; + } + else + { + // "\\\0" + cchBufferSize = 2; + } - if (cchBufferSize > MAX_PATH && (dwFlags & PATHCCH_ALLOW_LONG_PATHS)) - { - //"\\\\?\\UNC\0" - cchBufferSize += 6; - } + if (cchBufferSize > MAX_PATH && (dwFlags & PATHCCH_ALLOW_LONG_PATHS)) + { + //"\\\\?\\UNC\0" + cchBufferSize += 6; + } - //保证边界依然在 最大值内 - const unsigned cchMaxPath = (dwFlags & PATHCCH_ALLOW_LONG_PATHS) ? PATHCCH_MAX_CCH : MAX_PATH; - if (cchBufferSize > cchMaxPath) - cchBufferSize = cchMaxPath; + //保证边界依然在 最大值内 + const unsigned cchMaxPath = (dwFlags & PATHCCH_ALLOW_LONG_PATHS) ? PATHCCH_MAX_CCH : MAX_PATH; + if (cchBufferSize > cchMaxPath) + cchBufferSize = cchMaxPath; - auto pBuffer = (wchar_t*)LocalAlloc(LMEM_ZEROINIT, sizeof(wchar_t) * cchBufferSize); + auto pBuffer = (wchar_t*)LocalAlloc(LMEM_ZEROINIT, sizeof(wchar_t) * cchBufferSize); - if (pBuffer == nullptr) - return E_OUTOFMEMORY; + if (pBuffer == nullptr) + return E_OUTOFMEMORY; - auto hr = PathCchCanonicalizeEx(pBuffer, cchBufferSize, pszPathIn, dwFlags); + auto hr = PathCchCanonicalizeEx(pBuffer, cchBufferSize, pszPathIn, dwFlags); - if (FAILED(hr)) - { - LocalFree(pBuffer); - return hr; - } + if (FAILED(hr)) + { + LocalFree(pBuffer); + return hr; + } - *ppszPathOut = pBuffer; + *ppszPathOut = pBuffer; - return hr; - } + return hr; + } #endif } diff --git a/src/Thunks/api-ms-win-core-processthreads.hpp b/src/Thunks/api-ms-win-core-processthreads.hpp index c895b89..1fca496 100644 --- a/src/Thunks/api-ms-win-core-processthreads.hpp +++ b/src/Thunks/api-ms-win-core-processthreads.hpp @@ -1,4 +1,4 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) #include #endif @@ -10,27 +10,27 @@ // This structure stores the value for each attribute typedef struct _PROC_THREAD_ATTRIBUTE_ENTRY { - DWORD_PTR Attribute; // PROC_THREAD_ATTRIBUTE_xxx - SIZE_T cbSize; - PVOID lpValue; + DWORD_PTR Attribute; // PROC_THREAD_ATTRIBUTE_xxx + SIZE_T cbSize; + PVOID lpValue; } PROC_THREAD_ATTRIBUTE_ENTRY, * LPPROC_THREAD_ATTRIBUTE_ENTRY; // This structure contains a list of attributes that have been added using UpdateProcThreadAttribute typedef struct _PROC_THREAD_ATTRIBUTE_LIST { - DWORD dwFlags; - ULONG Size; - ULONG Count; - ULONG Reserved; - LPPROC_THREAD_ATTRIBUTE_ENTRY lpExtendedFlags; - PROC_THREAD_ATTRIBUTE_ENTRY Entries[ANYSIZE_ARRAY]; + DWORD dwFlags; + ULONG Size; + ULONG Count; + ULONG Reserved; + LPPROC_THREAD_ATTRIBUTE_ENTRY lpExtendedFlags; + PROC_THREAD_ATTRIBUTE_ENTRY Entries[ANYSIZE_ARRAY]; } PROC_THREAD_ATTRIBUTE_LIST, * LPPROC_THREAD_ATTRIBUTE_LIST; #endif namespace YY::Thunks::Fallback { -#if defined(YY_Thunks_Implemented) && (YY_Thunks_Support_Version < NTDDI_WIN6) +#if defined(YY_Thunks_Implemented) && (YY_Thunks_Target < __WindowsNT6) namespace { static void __cdecl UninitPageVirtualProtect(); @@ -62,24 +62,24 @@ namespace YY::Thunks::Fallback namespace YY ::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WS03) - - //Windows Vista, Windows Server 2003 - __DEFINE_THUNK( - kernel32, - 0, - DWORD, - WINAPI, - GetCurrentProcessorNumber, - VOID - ) - { - if (const auto _pfnGetCurrentProcessorNumber = try_get_GetCurrentProcessorNumber()) - { - return _pfnGetCurrentProcessorNumber(); - } - else - { +#if (YY_Thunks_Target < __WindowsNT5_2) + + //Windows Vista, Windows Server 2003 + __DEFINE_THUNK( + kernel32, + 0, + DWORD, + WINAPI, + GetCurrentProcessorNumber, + VOID + ) + { + if (const auto _pfnGetCurrentProcessorNumber = try_get_GetCurrentProcessorNumber()) + { + return _pfnGetCurrentProcessorNumber(); + } + else + { // Reference: https://www.cs.tcd.ie/Jeremy.Jones/GetCurrentProcessorNumberXP.htm // // The GetCurrentProcessorNumber() function is not available in XP. @@ -95,1021 +95,1021 @@ namespace YY ::Thunks // eax 返回值 mov eax, ebx } - } - } + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - //Windows 7, Windows Server 2008 R2 - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - GetCurrentProcessorNumberEx, - _Out_ PPROCESSOR_NUMBER ProcNumber - ) - { - if (auto pGetCurrentProcessorNumberEx = try_get_GetCurrentProcessorNumberEx()) - { - pGetCurrentProcessorNumberEx(ProcNumber); - } - else - { - //不支持GetCurrentProcessorNumberEx时假定用户只有一组CPU - ProcNumber->Group = 0; - ProcNumber->Number = static_cast(GetCurrentProcessorNumber()); - ProcNumber->Reserved = 0; - } - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + //Windows 7, Windows Server 2008 R2 + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + GetCurrentProcessorNumberEx, + _Out_ PPROCESSOR_NUMBER ProcNumber + ) + { + if (auto pGetCurrentProcessorNumberEx = try_get_GetCurrentProcessorNumberEx()) + { + pGetCurrentProcessorNumberEx(ProcNumber); + } + else + { + //不支持GetCurrentProcessorNumberEx时假定用户只有一组CPU + ProcNumber->Group = 0; + ProcNumber->Number = static_cast(GetCurrentProcessorNumber()); + ProcNumber->Reserved = 0; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2003 [desktop apps | UWP apps] - //感谢 过客 提供 - __DEFINE_THUNK( - kernel32, - 4, - DWORD, - WINAPI, - GetThreadId, - _In_ HANDLE Thread - ) - { - if (auto pGetThreadId = try_get_GetThreadId()) - { - return pGetThreadId(Thread); - } - else if (auto pNtQueryInformationThread = try_get_NtQueryInformationThread()) - { - THREAD_BASIC_INFORMATION ThreadBasicInfo; - - auto Status = pNtQueryInformationThread(Thread, ThreadBasicInformation, &ThreadBasicInfo, sizeof(ThreadBasicInfo), nullptr); - - if (Status < 0) - { - internal::BaseSetLastNTError(Status); - return 0; - } - else - { - return (DWORD)ThreadBasicInfo.ClientId.UniqueThread; - } - } - else - { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; - } - } +#if (YY_Thunks_Target < __WindowsNT5_2) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2003 [desktop apps | UWP apps] + //感谢 过客 提供 + __DEFINE_THUNK( + kernel32, + 4, + DWORD, + WINAPI, + GetThreadId, + _In_ HANDLE Thread + ) + { + if (auto pGetThreadId = try_get_GetThreadId()) + { + return pGetThreadId(Thread); + } + else if (auto pNtQueryInformationThread = try_get_NtQueryInformationThread()) + { + THREAD_BASIC_INFORMATION ThreadBasicInfo; + + auto Status = pNtQueryInformationThread(Thread, ThreadBasicInformation, &ThreadBasicInfo, sizeof(ThreadBasicInfo), nullptr); + + if (Status < 0) + { + internal::BaseSetLastNTError(Status); + return 0; + } + else + { + return (DWORD)ThreadBasicInfo.ClientId.UniqueThread; + } + } + else + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2003 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - DWORD, - WINAPI, - GetProcessIdOfThread, - _In_ HANDLE Thread - ) - { - if (auto pGetProcessIdOfThread = try_get_GetProcessIdOfThread()) - { - return pGetProcessIdOfThread(Thread); - } - else if (auto pNtQueryInformationThread = try_get_NtQueryInformationThread()) - { - THREAD_BASIC_INFORMATION ThreadBasicInfo; - - auto Status = pNtQueryInformationThread(Thread, ThreadBasicInformation, &ThreadBasicInfo, sizeof(ThreadBasicInfo), nullptr); - - if (Status < 0) - { - internal::BaseSetLastNTError(Status); - return 0; - } - else - { - return (DWORD)ThreadBasicInfo.ClientId.UniqueProcess; - } - } - else - { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; - } - } +#if (YY_Thunks_Target < __WindowsNT5_2) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2003 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + DWORD, + WINAPI, + GetProcessIdOfThread, + _In_ HANDLE Thread + ) + { + if (auto pGetProcessIdOfThread = try_get_GetProcessIdOfThread()) + { + return pGetProcessIdOfThread(Thread); + } + else if (auto pNtQueryInformationThread = try_get_NtQueryInformationThread()) + { + THREAD_BASIC_INFORMATION ThreadBasicInfo; + + auto Status = pNtQueryInformationThread(Thread, ThreadBasicInformation, &ThreadBasicInfo, sizeof(ThreadBasicInfo), nullptr); + + if (Status < 0) + { + internal::BaseSetLastNTError(Status); + return 0; + } + else + { + return (DWORD)ThreadBasicInfo.ClientId.UniqueProcess; + } + } + else + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WINXPSP1) - - //Windows Vista, Windows XP with SP1 [desktop apps | UWP apps] - //Windows Server 2003 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - DWORD, - WINAPI, - GetProcessId, - _In_ HANDLE Process - ) - { - if (auto pGetProcessId = try_get_GetProcessId()) - { - return pGetProcessId(Process); - } - else if (auto pNtQueryInformationProcess = try_get_NtQueryInformationProcess()) - { - PROCESS_BASIC_INFORMATION ProcessBasicInfo; - - auto Status = pNtQueryInformationProcess(Process, ProcessBasicInformation, &ProcessBasicInfo, sizeof(ProcessBasicInfo), nullptr); - - if (Status < 0) - { - internal::BaseSetLastNTError(Status); - return 0; - } - else - { - return (DWORD)ProcessBasicInfo.UniqueProcessId; - } - } - else - { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; - } - } +#if (YY_Thunks_Target < __WindowsNT5_1_SP1) + + //Windows Vista, Windows XP with SP1 [desktop apps | UWP apps] + //Windows Server 2003 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + DWORD, + WINAPI, + GetProcessId, + _In_ HANDLE Process + ) + { + if (auto pGetProcessId = try_get_GetProcessId()) + { + return pGetProcessId(Process); + } + else if (auto pNtQueryInformationProcess = try_get_NtQueryInformationProcess()) + { + PROCESS_BASIC_INFORMATION ProcessBasicInfo; + + auto Status = pNtQueryInformationProcess(Process, ProcessBasicInformation, &ProcessBasicInfo, sizeof(ProcessBasicInfo), nullptr); + + if (Status < 0) + { + internal::BaseSetLastNTError(Status); + return 0; + } + else + { + return (DWORD)ProcessBasicInfo.UniqueProcessId; + } + } + else + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 0, - VOID, - WINAPI, - FlushProcessWriteBuffers, - VOID - ) - { - if (auto pFlushProcessWriteBuffers = try_get_FlushProcessWriteBuffers()) - { - return pFlushProcessWriteBuffers(); - } - - - /* - * 参考了 14.29.30037 crt\src\concrt\ResourceManager.cpp 实现 - - */ - - for (;;) - { - auto pOrgPageVirtualProtect = (char*)InterlockedCompareExchangePointer((PVOID volatile*)Fallback::GetPageVirtualProtect(), nullptr, nullptr); - - - //内存存在异常,我们什么也不做。 - if (pOrgPageVirtualProtect == (char*)INVALID_HANDLE_VALUE) - { - break; - } - else if (pOrgPageVirtualProtect == nullptr) - { - //我们需要开辟一段内存 - - auto pPageVirtualProtectTmp = (char*)VirtualAlloc(NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - - if (pPageVirtualProtectTmp == nullptr) - { - //内存申请失败,直接设置为 -1,并且什么也不做 - InterlockedCompareExchangePointer((PVOID volatile*)Fallback::GetPageVirtualProtect(), INVALID_HANDLE_VALUE, nullptr); - break; - } - - *pPageVirtualProtectTmp = 1; - - pOrgPageVirtualProtect = (char*)InterlockedCompareExchangePointer((PVOID volatile*)Fallback::GetPageVirtualProtect(), pPageVirtualProtectTmp, nullptr); - - if (pOrgPageVirtualProtect != nullptr) - { - //说明另外一个线程已经设置,我们释放这次申请的内存 - VirtualFree(pPageVirtualProtectTmp, 0, MEM_RELEASE); - } - else - { - pOrgPageVirtualProtect = pPageVirtualProtectTmp; - } - } - - - // Note that the read of *m_pPageVirtualProtect is very important, as it makes it extremely likely that this memory will - // be in the working set when we call VirtualProtect (see comments below). - if (*pOrgPageVirtualProtect == 1) - { - // - // VirtualProtect simulates FlushProcessWriteBuffers because it happens to send an inter-processor interrupt to all CPUs, - // and inter-processor interrupts happen to cause the CPU's store buffers to be flushed. - // - // Unfortunately, VirtualProtect only does this if the page whose status is being changed is in the process' working set - // (otherwise there's no need to tell the other CPUs that anything has changed). - // - // One way to do this is to lock the page into the process' working set. Unfortunately, it can fail if there are already too many - // locked pages. - // - // We could increase the process' working set limit, using SetProcessWorkingSet, but that would be a) intrusive (the process may - // have its own idea of what the limit should be), and b) race-prone (another thread may be trying to adjust the limit, to a - // different value, at the same time). - // - // We could stop using *m_pPageVirtualProtect as the page we fiddle with, and instead use a page we know is already locked into - // the working set. There's no way to enumerate such pages, so it'd have to be a well-known fixed location that we know is always - // locked, and that can have its protection fiddled with without consequence. We know of no such location, and if we did it would - // undoubtedly be some internal Windows data structure that would be subject to changes in the way its memory is handled at any time. - // - // The VirtualProtect trick has worked for many years in the CLR, without the call to VirtualLock, without apparent problems. - // Part of the reason is because of the equivalent of the check of *m_pPageVirtualProtect above. - // - DWORD oldProtect; - - // We have it on good authority from the kernel team that, although VirtualProtect is repeatedly called with the - // same protection (PAGE_READONLY), the OS will not optimize out the flush buffers as a result. - VirtualProtect(pOrgPageVirtualProtect, sizeof(BYTE), PAGE_READONLY, &oldProtect); - } - - break; - } - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 0, + VOID, + WINAPI, + FlushProcessWriteBuffers, + VOID + ) + { + if (auto pFlushProcessWriteBuffers = try_get_FlushProcessWriteBuffers()) + { + return pFlushProcessWriteBuffers(); + } + + + /* + * 参考了 14.29.30037 crt\src\concrt\ResourceManager.cpp 实现 + + */ + + for (;;) + { + auto pOrgPageVirtualProtect = (char*)InterlockedCompareExchangePointer((PVOID volatile*)Fallback::GetPageVirtualProtect(), nullptr, nullptr); + + + //内存存在异常,我们什么也不做。 + if (pOrgPageVirtualProtect == (char*)INVALID_HANDLE_VALUE) + { + break; + } + else if (pOrgPageVirtualProtect == nullptr) + { + //我们需要开辟一段内存 + + auto pPageVirtualProtectTmp = (char*)VirtualAlloc(NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + + if (pPageVirtualProtectTmp == nullptr) + { + //内存申请失败,直接设置为 -1,并且什么也不做 + InterlockedCompareExchangePointer((PVOID volatile*)Fallback::GetPageVirtualProtect(), INVALID_HANDLE_VALUE, nullptr); + break; + } + + *pPageVirtualProtectTmp = 1; + + pOrgPageVirtualProtect = (char*)InterlockedCompareExchangePointer((PVOID volatile*)Fallback::GetPageVirtualProtect(), pPageVirtualProtectTmp, nullptr); + + if (pOrgPageVirtualProtect != nullptr) + { + //说明另外一个线程已经设置,我们释放这次申请的内存 + VirtualFree(pPageVirtualProtectTmp, 0, MEM_RELEASE); + } + else + { + pOrgPageVirtualProtect = pPageVirtualProtectTmp; + } + } + + + // Note that the read of *m_pPageVirtualProtect is very important, as it makes it extremely likely that this memory will + // be in the working set when we call VirtualProtect (see comments below). + if (*pOrgPageVirtualProtect == 1) + { + // + // VirtualProtect simulates FlushProcessWriteBuffers because it happens to send an inter-processor interrupt to all CPUs, + // and inter-processor interrupts happen to cause the CPU's store buffers to be flushed. + // + // Unfortunately, VirtualProtect only does this if the page whose status is being changed is in the process' working set + // (otherwise there's no need to tell the other CPUs that anything has changed). + // + // One way to do this is to lock the page into the process' working set. Unfortunately, it can fail if there are already too many + // locked pages. + // + // We could increase the process' working set limit, using SetProcessWorkingSet, but that would be a) intrusive (the process may + // have its own idea of what the limit should be), and b) race-prone (another thread may be trying to adjust the limit, to a + // different value, at the same time). + // + // We could stop using *m_pPageVirtualProtect as the page we fiddle with, and instead use a page we know is already locked into + // the working set. There's no way to enumerate such pages, so it'd have to be a well-known fixed location that we know is always + // locked, and that can have its protection fiddled with without consequence. We know of no such location, and if we did it would + // undoubtedly be some internal Windows data structure that would be subject to changes in the way its memory is handled at any time. + // + // The VirtualProtect trick has worked for many years in the CLR, without the call to VirtualLock, without apparent problems. + // Part of the reason is because of the equivalent of the check of *m_pPageVirtualProtect above. + // + DWORD oldProtect; + + // We have it on good authority from the kernel team that, although VirtualProtect is repeatedly called with the + // same protection (PAGE_READONLY), the OS will not optimize out the flush buffers as a result. + VirtualProtect(pOrgPageVirtualProtect, sizeof(BYTE), PAGE_READONLY, &oldProtect); + } + + break; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps only] - //Minimum supported server Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 16, - _Success_(return != FALSE) - BOOL, - WINAPI, - InitializeProcThreadAttributeList, - _Out_writes_bytes_to_opt_(*lpSize,*lpSize) LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList, - _In_ DWORD dwAttributeCount, - _Reserved_ DWORD dwFlags, - _When_(lpAttributeList == nullptr,_Out_) _When_(lpAttributeList != nullptr,_Inout_) PSIZE_T lpSize - ) - { - if (const auto pInitializeProcThreadAttributeList = try_get_InitializeProcThreadAttributeList()) - { - return pInitializeProcThreadAttributeList(lpAttributeList, dwAttributeCount, dwFlags, lpSize); - } - - - LSTATUS lStatus = ERROR_SUCCESS; - - do - { - //参数验证 - if (dwFlags) - { - lStatus = ERROR_INVALID_PARAMETER; - break; - } - - //Vista只支持 3个 Type,所以只有三个 - if (dwAttributeCount > 3) - { - lStatus = ERROR_INVALID_PARAMETER; - break; - } - - - const auto cbSize = *lpSize; - const auto cbSizeNeed = sizeof(PROC_THREAD_ATTRIBUTE_LIST) + dwAttributeCount * sizeof(PROC_THREAD_ATTRIBUTE_ENTRY); - *lpSize = cbSizeNeed; - - if (lpAttributeList == nullptr || cbSize < cbSizeNeed) - { - lStatus = ERROR_INSUFFICIENT_BUFFER; - break; - } - - lpAttributeList->dwFlags = 0; - lpAttributeList->lpExtendedFlags = nullptr; - lpAttributeList->Size = dwAttributeCount; - lpAttributeList->Count = 0; - - return TRUE; - - } while (false); - - - SetLastError(lStatus); - return FALSE; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps only] + //Minimum supported server Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 16, + _Success_(return != FALSE) + BOOL, + WINAPI, + InitializeProcThreadAttributeList, + _Out_writes_bytes_to_opt_(*lpSize,*lpSize) LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList, + _In_ DWORD dwAttributeCount, + _Reserved_ DWORD dwFlags, + _When_(lpAttributeList == nullptr,_Out_) _When_(lpAttributeList != nullptr,_Inout_) PSIZE_T lpSize + ) + { + if (const auto pInitializeProcThreadAttributeList = try_get_InitializeProcThreadAttributeList()) + { + return pInitializeProcThreadAttributeList(lpAttributeList, dwAttributeCount, dwFlags, lpSize); + } + + + LSTATUS lStatus = ERROR_SUCCESS; + + do + { + //参数验证 + if (dwFlags) + { + lStatus = ERROR_INVALID_PARAMETER; + break; + } + + //Vista只支持 3个 Type,所以只有三个 + if (dwAttributeCount > 3) + { + lStatus = ERROR_INVALID_PARAMETER; + break; + } + + + const auto cbSize = *lpSize; + const auto cbSizeNeed = sizeof(PROC_THREAD_ATTRIBUTE_LIST) + dwAttributeCount * sizeof(PROC_THREAD_ATTRIBUTE_ENTRY); + *lpSize = cbSizeNeed; + + if (lpAttributeList == nullptr || cbSize < cbSizeNeed) + { + lStatus = ERROR_INSUFFICIENT_BUFFER; + break; + } + + lpAttributeList->dwFlags = 0; + lpAttributeList->lpExtendedFlags = nullptr; + lpAttributeList->Size = dwAttributeCount; + lpAttributeList->Count = 0; + + return TRUE; + + } while (false); + + + SetLastError(lStatus); + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - //Minimum supported client Windows Vista [desktop apps only] - //Minimum supported server Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - DeleteProcThreadAttributeList, - _Inout_ LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList - ) - { - if (const auto pDeleteProcThreadAttributeList = try_get_DeleteProcThreadAttributeList()) - { - return pDeleteProcThreadAttributeList(lpAttributeList); - } + //Minimum supported client Windows Vista [desktop apps only] + //Minimum supported server Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + DeleteProcThreadAttributeList, + _Inout_ LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList + ) + { + if (const auto pDeleteProcThreadAttributeList = try_get_DeleteProcThreadAttributeList()) + { + return pDeleteProcThreadAttributeList(lpAttributeList); + } - //Vista原版什么也没有做…… - } + //Vista原版什么也没有做…… + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps only] - //Minimum supported server Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 28, - BOOL, - WINAPI, - UpdateProcThreadAttribute, - _Inout_ LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList, - _In_ DWORD dwFlags, - _In_ DWORD_PTR Attribute, - _In_reads_bytes_opt_(cbSize) PVOID lpValue, - _In_ SIZE_T cbSize, - _Out_writes_bytes_opt_(cbSize) PVOID lpPreviousValue, - _In_opt_ PSIZE_T lpReturnSize - ) - { - if (const auto pUpdateProcThreadAttribute = try_get_UpdateProcThreadAttribute()) - { - return pUpdateProcThreadAttribute(lpAttributeList, dwFlags, Attribute, lpValue, cbSize, lpPreviousValue, lpReturnSize); - } - - - LSTATUS lStatus = ERROR_SUCCESS; - - do - { - auto AttributeMark = 1ul << Attribute; - - ///////////////////////////////////////////////////// - // - // 参数检查 - // - - if (dwFlags & (~PROC_THREAD_ATTRIBUTE_REPLACE_VALUE)) - { - lStatus = ERROR_INVALID_PARAMETER; - break; - } - - - if ((Attribute & PROC_THREAD_ATTRIBUTE_ADDITIVE) == 0) - { - if (lpAttributeList->Count == lpAttributeList->Size) - { - //internal::BaseSetLastNTError(0xC0000001); - lStatus = ERROR_GEN_FAILURE; - break; - } - else if (AttributeMark & lpAttributeList->dwFlags) - { - //internal::BaseSetLastNTError(0x40000000); - lStatus = ERROR_OBJECT_NAME_EXISTS; - break; - } - else if (lpPreviousValue) - { - //internal::BaseSetLastNTError(0xC00000F4); - lStatus = ERROR_INVALID_PARAMETER; - break; - } - else if (dwFlags & PROC_THREAD_ATTRIBUTE_REPLACE_VALUE) - { - //internal::BaseSetLastNTError(0xC00000F0); - lStatus = ERROR_INVALID_PARAMETER; - break; - } - } - - - if ((PROC_THREAD_ATTRIBUTE_INPUT & Attribute) && lpReturnSize) - { - //internal::BaseSetLastNTError(0xC00000F5); - lStatus = ERROR_INVALID_PARAMETER; - break; - } - - // - // - //////////////////////////////////////////////////// - - - auto pAttribute = &lpAttributeList->Entries[lpAttributeList->Count]; - - constexpr auto ProcThreadAttributeExtendedFlags = 1; - //0x60001,文档没有公开 - constexpr auto PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS = ProcThreadAttributeValue(ProcThreadAttributeExtendedFlags, FALSE, TRUE, TRUE); - - - if (Attribute == PROC_THREAD_ATTRIBUTE_PARENT_PROCESS) //0x20000 - { - //WinXP不支持 UAC,没实现似乎也没什么的。 - - if (cbSize != sizeof(HANDLE)) - { - //internal::BaseSetLastNTError(0xC0000004); - lStatus = ERROR_INVALID_PARAMETER; - break; - } - } - else if (Attribute == PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS) //0x60001 - { - //系统没有公开这个含义,暂时让他允许通过把…… - - if (cbSize != sizeof(DWORD)) - { - //internal::BaseSetLastNTError(0xC0000004); - lStatus = ERROR_INVALID_PARAMETER; - break; - } - - DWORD dwOrgFlags; - - if (lpAttributeList->lpExtendedFlags) - { - pAttribute = lpAttributeList->lpExtendedFlags; - dwOrgFlags = (DWORD)lpAttributeList->lpExtendedFlags->lpValue; - AttributeMark = 0; - } - else - { - lpAttributeList->lpExtendedFlags = pAttribute; - dwOrgFlags = 0; - } - - - auto dwNewFlags = *(DWORD*)lpValue; - - if (dwNewFlags & ~0x00000003ul) - { - //internal::BaseSetLastNTError(0xC000000D); - lStatus = ERROR_BAD_LENGTH; - break; - } - - if ((dwFlags & PROC_THREAD_ATTRIBUTE_REPLACE_VALUE) == 0 && dwOrgFlags) - { - dwNewFlags |= dwOrgFlags; - } - - if (lpPreviousValue) - *(DWORD*)lpPreviousValue = dwOrgFlags; - - lpValue = (PVOID)dwNewFlags; - } - else if (Attribute == PROC_THREAD_ATTRIBUTE_HANDLE_LIST) //0x20002 - { - //WinXP也不支持指定句柄继承,他会直接继承所有可继承的句柄,所以没实现好像也没什么大不了的。 - - if (cbSize == 0 || cbSize % sizeof(HANDLE) != 0) - { - //internal::BaseSetLastNTError(0xC0000004); - lStatus = ERROR_INVALID_PARAMETER; - break; - } - } - else - { - //internal::BaseSetLastNTError(0xC00000BB); - lStatus = ERROR_NOT_SUPPORTED; - break; - } - - //LABEL_17 - pAttribute->lpValue = lpValue; - - if (AttributeMark) - { - pAttribute->Attribute = Attribute; - pAttribute->cbSize = cbSize; - ++lpAttributeList->Count; - lpAttributeList->dwFlags |= AttributeMark; - } - - return TRUE; - - } while (false); - - SetLastError(lStatus); - - return FALSE; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps only] + //Minimum supported server Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 28, + BOOL, + WINAPI, + UpdateProcThreadAttribute, + _Inout_ LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList, + _In_ DWORD dwFlags, + _In_ DWORD_PTR Attribute, + _In_reads_bytes_opt_(cbSize) PVOID lpValue, + _In_ SIZE_T cbSize, + _Out_writes_bytes_opt_(cbSize) PVOID lpPreviousValue, + _In_opt_ PSIZE_T lpReturnSize + ) + { + if (const auto pUpdateProcThreadAttribute = try_get_UpdateProcThreadAttribute()) + { + return pUpdateProcThreadAttribute(lpAttributeList, dwFlags, Attribute, lpValue, cbSize, lpPreviousValue, lpReturnSize); + } + + + LSTATUS lStatus = ERROR_SUCCESS; + + do + { + auto AttributeMark = 1ul << Attribute; + + ///////////////////////////////////////////////////// + // + // 参数检查 + // + + if (dwFlags & (~PROC_THREAD_ATTRIBUTE_REPLACE_VALUE)) + { + lStatus = ERROR_INVALID_PARAMETER; + break; + } + + + if ((Attribute & PROC_THREAD_ATTRIBUTE_ADDITIVE) == 0) + { + if (lpAttributeList->Count == lpAttributeList->Size) + { + //internal::BaseSetLastNTError(0xC0000001); + lStatus = ERROR_GEN_FAILURE; + break; + } + else if (AttributeMark & lpAttributeList->dwFlags) + { + //internal::BaseSetLastNTError(0x40000000); + lStatus = ERROR_OBJECT_NAME_EXISTS; + break; + } + else if (lpPreviousValue) + { + //internal::BaseSetLastNTError(0xC00000F4); + lStatus = ERROR_INVALID_PARAMETER; + break; + } + else if (dwFlags & PROC_THREAD_ATTRIBUTE_REPLACE_VALUE) + { + //internal::BaseSetLastNTError(0xC00000F0); + lStatus = ERROR_INVALID_PARAMETER; + break; + } + } + + + if ((PROC_THREAD_ATTRIBUTE_INPUT & Attribute) && lpReturnSize) + { + //internal::BaseSetLastNTError(0xC00000F5); + lStatus = ERROR_INVALID_PARAMETER; + break; + } + + // + // + //////////////////////////////////////////////////// + + + auto pAttribute = &lpAttributeList->Entries[lpAttributeList->Count]; + + constexpr auto ProcThreadAttributeExtendedFlags = 1; + //0x60001,文档没有公开 + constexpr auto PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS = ProcThreadAttributeValue(ProcThreadAttributeExtendedFlags, FALSE, TRUE, TRUE); + + + if (Attribute == PROC_THREAD_ATTRIBUTE_PARENT_PROCESS) //0x20000 + { + //WinXP不支持 UAC,没实现似乎也没什么的。 + + if (cbSize != sizeof(HANDLE)) + { + //internal::BaseSetLastNTError(0xC0000004); + lStatus = ERROR_INVALID_PARAMETER; + break; + } + } + else if (Attribute == PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS) //0x60001 + { + //系统没有公开这个含义,暂时让他允许通过把…… + + if (cbSize != sizeof(DWORD)) + { + //internal::BaseSetLastNTError(0xC0000004); + lStatus = ERROR_INVALID_PARAMETER; + break; + } + + DWORD dwOrgFlags; + + if (lpAttributeList->lpExtendedFlags) + { + pAttribute = lpAttributeList->lpExtendedFlags; + dwOrgFlags = (DWORD)lpAttributeList->lpExtendedFlags->lpValue; + AttributeMark = 0; + } + else + { + lpAttributeList->lpExtendedFlags = pAttribute; + dwOrgFlags = 0; + } + + + auto dwNewFlags = *(DWORD*)lpValue; + + if (dwNewFlags & ~0x00000003ul) + { + //internal::BaseSetLastNTError(0xC000000D); + lStatus = ERROR_BAD_LENGTH; + break; + } + + if ((dwFlags & PROC_THREAD_ATTRIBUTE_REPLACE_VALUE) == 0 && dwOrgFlags) + { + dwNewFlags |= dwOrgFlags; + } + + if (lpPreviousValue) + *(DWORD*)lpPreviousValue = dwOrgFlags; + + lpValue = (PVOID)dwNewFlags; + } + else if (Attribute == PROC_THREAD_ATTRIBUTE_HANDLE_LIST) //0x20002 + { + //WinXP也不支持指定句柄继承,他会直接继承所有可继承的句柄,所以没实现好像也没什么大不了的。 + + if (cbSize == 0 || cbSize % sizeof(HANDLE) != 0) + { + //internal::BaseSetLastNTError(0xC0000004); + lStatus = ERROR_INVALID_PARAMETER; + break; + } + } + else + { + //internal::BaseSetLastNTError(0xC00000BB); + lStatus = ERROR_NOT_SUPPORTED; + break; + } + + //LABEL_17 + pAttribute->lpValue = lpValue; + + if (AttributeMark) + { + pAttribute->Attribute = Attribute; + pAttribute->cbSize = cbSize; + ++lpAttributeList->Count; + lpAttributeList->dwFlags |= AttributeMark; + } + + return TRUE; + + } while (false); + + SetLastError(lStatus); + + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03) - - //Windows Vista, Windows XP Professional x64 Edition [desktop apps only] - //Windows Server 2008, Windows Server 2003 with SP1 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 4, - BOOL, - WINAPI, - SetThreadStackGuarantee, - _Inout_ ULONG *StackSizeInBytes - ) - { - if (const auto pSetThreadStackGuarantee = try_get_SetThreadStackGuarantee()) - { - return pSetThreadStackGuarantee(StackSizeInBytes); - } - - // 以下内容来自:ucrt\misc\resetstk.cpp - - - // 因为只面向 Windows XP以及之前的系统,我们可以硬编码的确定,页大小只可能是 4K。 - // 减少 GetSystemInfo 调用。 - constexpr auto PageSize = 4096u; - constexpr auto MinStackRequest = 2u; - - auto pStack = (LPBYTE)_alloca(1); - - auto RegionSize = *StackSizeInBytes; - - // TEB没有 GuaranteedStackBytes,没法知道上一次的结果,我们仅仅返回一个假的数值。 - *StackSizeInBytes = PageSize; - - // 长度为 0 时,不需要额外申请 - if (RegionSize == 0) - return TRUE; - - // 我们需要额外一块 PAGE_GUARD 来进行边界防御。 - RegionSize = (RegionSize + PageSize + (PageSize - 1)) & ~(PageSize - 1); - RegionSize = max(RegionSize, PageSize * MinStackRequest); - - MEMORY_BASIC_INFORMATION mbi; - if (VirtualQuery(pStack, &mbi, sizeof mbi) == 0) - return FALSE; - - auto pStackBase = (LPBYTE)mbi.AllocationBase; - - // - // Find the page(s) just below where the stack pointer currently points. - // This is the highest potential guard page. - auto pMaxGuard = (LPBYTE)(((DWORD_PTR)pStack & ~(DWORD_PTR)(PageSize - 1)) - RegionSize); - - // - // If the potential guard page is too close to the start of the stack - // region, abandon the reset effort for lack of space. Win9x has a - // larger reserved stack requirement. - auto pMinGuard = pStackBase + PageSize; - - if (pMaxGuard < pMinGuard) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - // Set the new guard page just below the current stack page. - DWORD flOldProtect; - if (VirtualAlloc(pMaxGuard, RegionSize, MEM_COMMIT, PAGE_READWRITE) == nullptr - || VirtualProtect(pMaxGuard, RegionSize, PAGE_READWRITE | PAGE_GUARD, &flOldProtect) == 0) - { - return FALSE; - } - - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT5_2) + + //Windows Vista, Windows XP Professional x64 Edition [desktop apps only] + //Windows Server 2008, Windows Server 2003 with SP1 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 4, + BOOL, + WINAPI, + SetThreadStackGuarantee, + _Inout_ ULONG *StackSizeInBytes + ) + { + if (const auto pSetThreadStackGuarantee = try_get_SetThreadStackGuarantee()) + { + return pSetThreadStackGuarantee(StackSizeInBytes); + } + + // 以下内容来自:ucrt\misc\resetstk.cpp + + + // 因为只面向 Windows XP以及之前的系统,我们可以硬编码的确定,页大小只可能是 4K。 + // 减少 GetSystemInfo 调用。 + constexpr auto PageSize = 4096u; + constexpr auto MinStackRequest = 2u; + + auto pStack = (LPBYTE)_alloca(1); + + auto RegionSize = *StackSizeInBytes; + + // TEB没有 GuaranteedStackBytes,没法知道上一次的结果,我们仅仅返回一个假的数值。 + *StackSizeInBytes = PageSize; + + // 长度为 0 时,不需要额外申请 + if (RegionSize == 0) + return TRUE; + + // 我们需要额外一块 PAGE_GUARD 来进行边界防御。 + RegionSize = (RegionSize + PageSize + (PageSize - 1)) & ~(PageSize - 1); + RegionSize = max(RegionSize, PageSize * MinStackRequest); + + MEMORY_BASIC_INFORMATION mbi; + if (VirtualQuery(pStack, &mbi, sizeof mbi) == 0) + return FALSE; + + auto pStackBase = (LPBYTE)mbi.AllocationBase; + + // + // Find the page(s) just below where the stack pointer currently points. + // This is the highest potential guard page. + auto pMaxGuard = (LPBYTE)(((DWORD_PTR)pStack & ~(DWORD_PTR)(PageSize - 1)) - RegionSize); + + // + // If the potential guard page is too close to the start of the stack + // region, abandon the reset effort for lack of space. Win9x has a + // larger reserved stack requirement. + auto pMinGuard = pStackBase + PageSize; + + if (pMaxGuard < pMinGuard) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // Set the new guard page just below the current stack page. + DWORD flOldProtect; + if (VirtualAlloc(pMaxGuard, RegionSize, MEM_COMMIT, PAGE_READWRITE) == nullptr + || VirtualProtect(pMaxGuard, RegionSize, PAGE_READWRITE | PAGE_GUARD, &flOldProtect) == 0) + { + return FALSE; + } + + return TRUE; + } #endif - -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - GetProcessMitigationPolicy, - _In_ HANDLE _hProcess, - _In_ PROCESS_MITIGATION_POLICY _eMitigationPolicy, - _Out_writes_bytes_(_cbLength) PVOID _pBuffer, - _In_ SIZE_T _cbLength - ) - { - if (const auto _pfnGetProcessMitigationPolicy = try_get_GetProcessMitigationPolicy()) - { - return _pfnGetProcessMitigationPolicy(_hProcess, _eMitigationPolicy, _pBuffer, _cbLength); - } - - if (!_pBuffer) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if ((DWORD)_eMitigationPolicy >= (DWORD)MaxProcessMitigationPolicy) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - const auto _pfnNtQueryInformationProcess = try_get_NtQueryInformationProcess(); - if (!_pfnNtQueryInformationProcess) - { - SetLastError(ERROR_NOT_SUPPORTED); - return FALSE; - } - - if (_eMitigationPolicy == ProcessDEPPolicy) - { - if (_cbLength != sizeof(PROCESS_MITIGATION_DEP_POLICY)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - KEXECUTE_OPTIONS _DepOptions = {}; - NTSTATUS _Status = _pfnNtQueryInformationProcess(_hProcess, ProcessExecuteFlags, &_DepOptions, sizeof(_DepOptions), nullptr); - if (_Status >= 0) - { - auto _pDepPolicy = (PROCESS_MITIGATION_DEP_POLICY*)_pBuffer; - _pDepPolicy->Enable = _DepOptions.ExecuteEnable ? 0 : 1; - _pDepPolicy->DisableAtlThunkEmulation = _DepOptions.DisableThunkEmulation; - _pDepPolicy->ReservedFlags = 0; - _pDepPolicy->Permanent = _DepOptions.Permanent; - return TRUE; - } - else if (STATUS_INVALID_INFO_CLASS == _Status || STATUS_NOT_SUPPORTED == _Status) - { - *(DWORD*)_pBuffer = 0; - return TRUE; - } - else - { - internal::BaseSetLastNTError(_Status); - return FALSE; - } - } - else if (_eMitigationPolicy == ProcessMitigationOptionsMask) - { - if (_cbLength < sizeof(UINT64)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - memset(_pBuffer, 0, _cbLength); - return TRUE; - } - else - { - if (_cbLength != sizeof(DWORD)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - YY_ProcessPolicyInfo _Info = { static_cast(_eMitigationPolicy) }; - NTSTATUS _Status = _pfnNtQueryInformationProcess(_hProcess, YY_ProcessPolicy, &_Info, sizeof(_Info), nullptr); - if (_Status >= 0) - { - *(DWORD*)_pBuffer = _Info.Flags; - return TRUE; - } - else if (STATUS_INVALID_INFO_CLASS == _Status || STATUS_NOT_SUPPORTED == _Status) - { - // 如果没有这个特性,那么统一设置为0,表示内部所有环境方案都处于关闭状态 - *(DWORD*)_pBuffer = 0; - return TRUE; - } - else - { - internal::BaseSetLastNTError(_Status); - return FALSE; - } - } - - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } + +#if (YY_Thunks_Target < __WindowsNT6_2) + + // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + GetProcessMitigationPolicy, + _In_ HANDLE _hProcess, + _In_ PROCESS_MITIGATION_POLICY _eMitigationPolicy, + _Out_writes_bytes_(_cbLength) PVOID _pBuffer, + _In_ SIZE_T _cbLength + ) + { + if (const auto _pfnGetProcessMitigationPolicy = try_get_GetProcessMitigationPolicy()) + { + return _pfnGetProcessMitigationPolicy(_hProcess, _eMitigationPolicy, _pBuffer, _cbLength); + } + + if (!_pBuffer) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if ((DWORD)_eMitigationPolicy >= (DWORD)MaxProcessMitigationPolicy) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + const auto _pfnNtQueryInformationProcess = try_get_NtQueryInformationProcess(); + if (!_pfnNtQueryInformationProcess) + { + SetLastError(ERROR_NOT_SUPPORTED); + return FALSE; + } + + if (_eMitigationPolicy == ProcessDEPPolicy) + { + if (_cbLength != sizeof(PROCESS_MITIGATION_DEP_POLICY)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + KEXECUTE_OPTIONS _DepOptions = {}; + NTSTATUS _Status = _pfnNtQueryInformationProcess(_hProcess, ProcessExecuteFlags, &_DepOptions, sizeof(_DepOptions), nullptr); + if (_Status >= 0) + { + auto _pDepPolicy = (PROCESS_MITIGATION_DEP_POLICY*)_pBuffer; + _pDepPolicy->Enable = _DepOptions.ExecuteEnable ? 0 : 1; + _pDepPolicy->DisableAtlThunkEmulation = _DepOptions.DisableThunkEmulation; + _pDepPolicy->ReservedFlags = 0; + _pDepPolicy->Permanent = _DepOptions.Permanent; + return TRUE; + } + else if (STATUS_INVALID_INFO_CLASS == _Status || STATUS_NOT_SUPPORTED == _Status) + { + *(DWORD*)_pBuffer = 0; + return TRUE; + } + else + { + internal::BaseSetLastNTError(_Status); + return FALSE; + } + } + else if (_eMitigationPolicy == ProcessMitigationOptionsMask) + { + if (_cbLength < sizeof(UINT64)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + memset(_pBuffer, 0, _cbLength); + return TRUE; + } + else + { + if (_cbLength != sizeof(DWORD)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + YY_ProcessPolicyInfo _Info = { static_cast(_eMitigationPolicy) }; + NTSTATUS _Status = _pfnNtQueryInformationProcess(_hProcess, YY_ProcessPolicy, &_Info, sizeof(_Info), nullptr); + if (_Status >= 0) + { + *(DWORD*)_pBuffer = _Info.Flags; + return TRUE; + } + else if (STATUS_INVALID_INFO_CLASS == _Status || STATUS_NOT_SUPPORTED == _Status) + { + // 如果没有这个特性,那么统一设置为0,表示内部所有环境方案都处于关闭状态 + *(DWORD*)_pBuffer = 0; + return TRUE; + } + else + { + internal::BaseSetLastNTError(_Status); + return FALSE; + } + } + + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 12, - BOOL, - WINAPI, - SetProcessMitigationPolicy, - _In_ PROCESS_MITIGATION_POLICY _eMitigationPolicy, - _In_reads_bytes_(_cbLength) PVOID _pBuffer, - _In_ SIZE_T _cbLength - ) - { - if (const auto _pfnSetProcessMitigationPolicy = try_get_SetProcessMitigationPolicy()) - { - return _pfnSetProcessMitigationPolicy(_eMitigationPolicy, _pBuffer, _cbLength); - } - - if (!_pBuffer) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if ((DWORD)_eMitigationPolicy >= (DWORD)MaxProcessMitigationPolicy || _eMitigationPolicy == ProcessMitigationOptionsMask) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - const auto _pfnNtSetInformationProcess = try_get_NtSetInformationProcess(); - if (!_pfnNtSetInformationProcess) - { - SetLastError(ERROR_NOT_SUPPORTED); - return FALSE; - } - - NTSTATUS _Status; - if (_eMitigationPolicy == ProcessDEPPolicy) - { - if (_cbLength != sizeof(PROCESS_MITIGATION_DEP_POLICY)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - auto& _DepPolicy = *(PROCESS_MITIGATION_DEP_POLICY*)_pBuffer; - - KEXECUTE_OPTIONS _DepOptions = {}; - if (_DepPolicy.Enable) - { - _DepOptions.ExecuteDisable = 1; - } - else - { - _DepOptions.ExecuteEnable = 1; - } - _DepOptions.DisableThunkEmulation = _DepPolicy.DisableAtlThunkEmulation; - _DepOptions.Permanent = _DepPolicy.Permanent; - - _Status = _pfnNtSetInformationProcess(NtCurrentProcess(), YY_ProcessPolicy, &_DepOptions, sizeof(_DepOptions)); - - } - else - { - if (_cbLength != sizeof(DWORD)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - YY_ProcessPolicyInfo _Info = { static_cast(_eMitigationPolicy), *(DWORD*)_pBuffer }; - _Status = _pfnNtSetInformationProcess(NtCurrentProcess(), YY_ProcessPolicy, &_Info, sizeof(_Info)); - } - - if (_Status >= 0) - { - return TRUE; - } - else - { - internal::BaseSetLastNTError(_Status); - return FALSE; - } - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 12, + BOOL, + WINAPI, + SetProcessMitigationPolicy, + _In_ PROCESS_MITIGATION_POLICY _eMitigationPolicy, + _In_reads_bytes_(_cbLength) PVOID _pBuffer, + _In_ SIZE_T _cbLength + ) + { + if (const auto _pfnSetProcessMitigationPolicy = try_get_SetProcessMitigationPolicy()) + { + return _pfnSetProcessMitigationPolicy(_eMitigationPolicy, _pBuffer, _cbLength); + } + + if (!_pBuffer) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if ((DWORD)_eMitigationPolicy >= (DWORD)MaxProcessMitigationPolicy || _eMitigationPolicy == ProcessMitigationOptionsMask) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + const auto _pfnNtSetInformationProcess = try_get_NtSetInformationProcess(); + if (!_pfnNtSetInformationProcess) + { + SetLastError(ERROR_NOT_SUPPORTED); + return FALSE; + } + + NTSTATUS _Status; + if (_eMitigationPolicy == ProcessDEPPolicy) + { + if (_cbLength != sizeof(PROCESS_MITIGATION_DEP_POLICY)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + auto& _DepPolicy = *(PROCESS_MITIGATION_DEP_POLICY*)_pBuffer; + + KEXECUTE_OPTIONS _DepOptions = {}; + if (_DepPolicy.Enable) + { + _DepOptions.ExecuteDisable = 1; + } + else + { + _DepOptions.ExecuteEnable = 1; + } + _DepOptions.DisableThunkEmulation = _DepPolicy.DisableAtlThunkEmulation; + _DepOptions.Permanent = _DepPolicy.Permanent; + + _Status = _pfnNtSetInformationProcess(NtCurrentProcess(), YY_ProcessPolicy, &_DepOptions, sizeof(_DepOptions)); + + } + else + { + if (_cbLength != sizeof(DWORD)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + YY_ProcessPolicyInfo _Info = { static_cast(_eMitigationPolicy), *(DWORD*)_pBuffer }; + _Status = _pfnNtSetInformationProcess(NtCurrentProcess(), YY_ProcessPolicy, &_Info, sizeof(_Info)); + } + + if (_Status >= 0) + { + return TRUE; + } + else + { + internal::BaseSetLastNTError(_Status); + return FALSE; + } + } #endif - -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - SetProcessInformation, - _In_ HANDLE _hProcess, - _In_ PROCESS_INFORMATION_CLASS _eProcessInformationClass, - _In_reads_bytes_(_cbProcessInformationSize) LPVOID _pProcessInformation, - _In_ DWORD _cbProcessInformationSize - ) - { - if (const auto _pfnSetProcessInformation = try_get_SetProcessInformation()) - { - return _pfnSetProcessInformation(_hProcess, _eProcessInformationClass, _pProcessInformation, _cbProcessInformationSize); - } - - if (_pProcessInformation == nullptr || (DWORD)_eProcessInformationClass >= (DWORD)ProcessInformationClassMax) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - const auto _pfnNtSetInformationProcess = try_get_NtSetInformationProcess(); - if (!_pfnNtSetInformationProcess) - { - SetLastError(ERROR_NOT_SUPPORTED); - return FALSE; - } - - NTSTATUS _Status; - if (_eProcessInformationClass == ProcessMemoryPriority) - { - if (_cbProcessInformationSize != sizeof(MEMORY_PRIORITY_INFORMATION)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - // PAGE_PRIORITY_INFORMATION - _Status = _pfnNtSetInformationProcess(_hProcess, ProcessPagePriority, _pProcessInformation, sizeof(DWORD)); - } - else - { - SetLastError(ERROR_NOT_SUPPORTED); - return FALSE; - } - - if (_Status >= 0) - return TRUE; - - internal::BaseSetLastNTError(_Status); - return FALSE; - } + +#if (YY_Thunks_Target < __WindowsNT6_2) + + // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + SetProcessInformation, + _In_ HANDLE _hProcess, + _In_ PROCESS_INFORMATION_CLASS _eProcessInformationClass, + _In_reads_bytes_(_cbProcessInformationSize) LPVOID _pProcessInformation, + _In_ DWORD _cbProcessInformationSize + ) + { + if (const auto _pfnSetProcessInformation = try_get_SetProcessInformation()) + { + return _pfnSetProcessInformation(_hProcess, _eProcessInformationClass, _pProcessInformation, _cbProcessInformationSize); + } + + if (_pProcessInformation == nullptr || (DWORD)_eProcessInformationClass >= (DWORD)ProcessInformationClassMax) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + const auto _pfnNtSetInformationProcess = try_get_NtSetInformationProcess(); + if (!_pfnNtSetInformationProcess) + { + SetLastError(ERROR_NOT_SUPPORTED); + return FALSE; + } + + NTSTATUS _Status; + if (_eProcessInformationClass == ProcessMemoryPriority) + { + if (_cbProcessInformationSize != sizeof(MEMORY_PRIORITY_INFORMATION)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + // PAGE_PRIORITY_INFORMATION + _Status = _pfnNtSetInformationProcess(_hProcess, ProcessPagePriority, _pProcessInformation, sizeof(DWORD)); + } + else + { + SetLastError(ERROR_NOT_SUPPORTED); + return FALSE; + } + + if (_Status >= 0) + return TRUE; + + internal::BaseSetLastNTError(_Status); + return FALSE; + } #endif - -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - SetThreadInformation, - _In_ HANDLE _hThread, - _In_ THREAD_INFORMATION_CLASS _eThreadInformationClass, - _In_reads_bytes_(_cbThreadInformationSize) LPVOID _pThreadInformation, - _In_ DWORD _cbThreadInformationSize - ) - { - if (const auto _pfnSetThreadInformation = try_get_SetThreadInformation()) - { - return _pfnSetThreadInformation(_hThread, _eThreadInformationClass, _pThreadInformation, _cbThreadInformationSize); - } - - if (_pThreadInformation == nullptr || (DWORD)_eThreadInformationClass >= (DWORD)ThreadInformationClassMax) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - const auto _pfnNtSetInformationThread = try_get_NtSetInformationThread(); - if (!_pfnNtSetInformationThread) - { - SetLastError(ERROR_NOT_SUPPORTED); - return FALSE; - } - - NTSTATUS _Status; - if (_eThreadInformationClass == ThreadMemoryPriority) - { - if (_cbThreadInformationSize != sizeof(MEMORY_PRIORITY_INFORMATION)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - _Status = _pfnNtSetInformationThread(_hThread, ThreadPagePriority, _pThreadInformation, sizeof(DWORD)); - } - else if (_eThreadInformationClass == ThreadAbsoluteCpuPriority) - { - if (_cbThreadInformationSize != sizeof(DWORD)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - _Status = _pfnNtSetInformationThread(_hThread, ThreadActualBasePriority, _pThreadInformation, sizeof(DWORD)); - } - else - { - SetLastError(ERROR_NOT_SUPPORTED); - return FALSE; - } - - if (_Status >= 0) - return TRUE; - - internal::BaseSetLastNTError(_Status); - return FALSE; - } + +#if (YY_Thunks_Target < __WindowsNT6_2) + + // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + SetThreadInformation, + _In_ HANDLE _hThread, + _In_ THREAD_INFORMATION_CLASS _eThreadInformationClass, + _In_reads_bytes_(_cbThreadInformationSize) LPVOID _pThreadInformation, + _In_ DWORD _cbThreadInformationSize + ) + { + if (const auto _pfnSetThreadInformation = try_get_SetThreadInformation()) + { + return _pfnSetThreadInformation(_hThread, _eThreadInformationClass, _pThreadInformation, _cbThreadInformationSize); + } + + if (_pThreadInformation == nullptr || (DWORD)_eThreadInformationClass >= (DWORD)ThreadInformationClassMax) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + const auto _pfnNtSetInformationThread = try_get_NtSetInformationThread(); + if (!_pfnNtSetInformationThread) + { + SetLastError(ERROR_NOT_SUPPORTED); + return FALSE; + } + + NTSTATUS _Status; + if (_eThreadInformationClass == ThreadMemoryPriority) + { + if (_cbThreadInformationSize != sizeof(MEMORY_PRIORITY_INFORMATION)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + _Status = _pfnNtSetInformationThread(_hThread, ThreadPagePriority, _pThreadInformation, sizeof(DWORD)); + } + else if (_eThreadInformationClass == ThreadAbsoluteCpuPriority) + { + if (_cbThreadInformationSize != sizeof(DWORD)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + _Status = _pfnNtSetInformationThread(_hThread, ThreadActualBasePriority, _pThreadInformation, sizeof(DWORD)); + } + else + { + SetLastError(ERROR_NOT_SUPPORTED); + return FALSE; + } + + if (_Status >= 0) + return TRUE; + + internal::BaseSetLastNTError(_Status); + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - GetThreadInformation, - _In_ HANDLE _hThread, - _In_ THREAD_INFORMATION_CLASS _eThreadInformationClass, - _Out_writes_bytes_(_cbThreadInformationSize) LPVOID _pThreadInformation, - _In_ DWORD _cbThreadInformationSize - ) - { - if (const auto _pfnGetThreadInformation = try_get_GetThreadInformation()) - { - return _pfnGetThreadInformation(_hThread, _eThreadInformationClass, _pThreadInformation, _cbThreadInformationSize); - } - - const auto _pfnNtQueryInformationThread = try_get_NtQueryInformationThread(); - if (!_pfnNtQueryInformationThread) - { - SetLastError(ERROR_NOT_SUPPORTED); - return FALSE; - } - - long _Status; - if (_eThreadInformationClass == ThreadMemoryPriority) - { - _Status = _pfnNtQueryInformationThread(_hThread, ThreadPagePriority, _pThreadInformation, _cbThreadInformationSize, nullptr); - } - else if (_eThreadInformationClass == ThreadAbsoluteCpuPriority) - { - _Status = _pfnNtQueryInformationThread(_hThread, ThreadActualBasePriority, _pThreadInformation, _cbThreadInformationSize, nullptr); - } - else - { - _Status = STATUS_INVALID_PARAMETER; - } - - if (_Status < 0) - { - internal::BaseSetLastNTError(_Status); - return FALSE; - } - - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + GetThreadInformation, + _In_ HANDLE _hThread, + _In_ THREAD_INFORMATION_CLASS _eThreadInformationClass, + _Out_writes_bytes_(_cbThreadInformationSize) LPVOID _pThreadInformation, + _In_ DWORD _cbThreadInformationSize + ) + { + if (const auto _pfnGetThreadInformation = try_get_GetThreadInformation()) + { + return _pfnGetThreadInformation(_hThread, _eThreadInformationClass, _pThreadInformation, _cbThreadInformationSize); + } + + const auto _pfnNtQueryInformationThread = try_get_NtQueryInformationThread(); + if (!_pfnNtQueryInformationThread) + { + SetLastError(ERROR_NOT_SUPPORTED); + return FALSE; + } + + long _Status; + if (_eThreadInformationClass == ThreadMemoryPriority) + { + _Status = _pfnNtQueryInformationThread(_hThread, ThreadPagePriority, _pThreadInformation, _cbThreadInformationSize, nullptr); + } + else if (_eThreadInformationClass == ThreadAbsoluteCpuPriority) + { + _Status = _pfnNtQueryInformationThread(_hThread, ThreadActualBasePriority, _pThreadInformation, _cbThreadInformationSize, nullptr); + } + else + { + _Status = STATUS_INVALID_PARAMETER; + } + + if (_Status < 0) + { + internal::BaseSetLastNTError(_Status); + return FALSE; + } + + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) - // 最低受支持的客户端 Windows 7 [桌面应用 |UWP 应用] + // 最低受支持的客户端 Windows 7 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2008 R2[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 12, - BOOL, + __DEFINE_THUNK( + kernel32, + 12, + BOOL, WINAPI, SetThreadIdealProcessorEx, _In_ HANDLE _hThread, _In_ PPROCESSOR_NUMBER _pIdealProcessor, _Out_opt_ PPROCESSOR_NUMBER _pPreviousIdealProcessor - ) - { - if (const auto _pfnSetThreadIdealProcessorEx = try_get_SetThreadIdealProcessorEx()) - { - return _pfnSetThreadIdealProcessorEx(_hThread, _pIdealProcessor, _pPreviousIdealProcessor); - } + ) + { + if (const auto _pfnSetThreadIdealProcessorEx = try_get_SetThreadIdealProcessorEx()) + { + return _pfnSetThreadIdealProcessorEx(_hThread, _pIdealProcessor, _pPreviousIdealProcessor); + } // 不支持的平台统一认为只有一组处理器 // 微软这里就没有检查 _pIdealProcessor @@ -1136,24 +1136,24 @@ namespace YY ::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) - // 最低受支持的客户端 Windows 7 [桌面应用 |UWP 应用] + // 最低受支持的客户端 Windows 7 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2008 R2[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, + __DEFINE_THUNK( + kernel32, + 8, + BOOL, WINAPI, GetThreadIdealProcessorEx, _In_ HANDLE _hThread, _Out_ PPROCESSOR_NUMBER _pIdealProcessor - ) - { - if (const auto _pfnGetThreadIdealProcessorEx = try_get_GetThreadIdealProcessorEx()) - { - return _pfnGetThreadIdealProcessorEx(_hThread, _pIdealProcessor); - } + ) + { + if (const auto _pfnGetThreadIdealProcessorEx = try_get_GetThreadIdealProcessorEx()) + { + return _pfnGetThreadIdealProcessorEx(_hThread, _pIdealProcessor); + } // 不支持的平台统一认为只有一组处理器 const auto _uPreviousIdealProcessor = SetThreadIdealProcessor(_hThread, MAXIMUM_PROCESSORS); @@ -1170,7 +1170,7 @@ namespace YY ::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) // 最低受支持的客户端 Windows 7 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] diff --git a/src/Thunks/api-ms-win-core-processtopology-obsolete.hpp b/src/Thunks/api-ms-win-core-processtopology-obsolete.hpp index 0364a3a..db7cd30 100644 --- a/src/Thunks/api-ms-win-core-processtopology-obsolete.hpp +++ b/src/Thunks/api-ms-win-core-processtopology-obsolete.hpp @@ -28,7 +28,7 @@ namespace YY } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) //Minimum supported client Windows 7 [desktop apps only] //Minimum supported server Windows Server 2008 R2 [desktop apps only] @@ -51,7 +51,7 @@ namespace YY #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) //Minimum supported client Windows 7 [desktop apps only] //Minimum supported server Windows Server 2008 R2 [desktop apps only] @@ -74,7 +74,7 @@ namespace YY #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) //Minimum supported client Windows 7 [desktop apps only] //Minimum supported server Windows Server 2008 R2 [desktop apps only] @@ -98,7 +98,7 @@ namespace YY #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) //Minimum supported client Windows 7 [desktop apps only] //Minimum supported server Windows Server 2008 R2 [desktop apps only] diff --git a/src/Thunks/api-ms-win-core-processtopology.hpp b/src/Thunks/api-ms-win-core-processtopology.hpp index 454e451..c7f79de 100644 --- a/src/Thunks/api-ms-win-core-processtopology.hpp +++ b/src/Thunks/api-ms-win-core-processtopology.hpp @@ -1,45 +1,44 @@ -#include +#if (YY_Thunks_Target < __WindowsNT6_1) +#include +#endif -namespace YY +namespace YY::Thunks { - namespace Thunks - { -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) - //Minimum supported client Windows 7 [desktop apps only] - //Minimum supported server Windows Server 2008 R2 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 12, - BOOL, - WINAPI, - GetProcessGroupAffinity, - _In_ HANDLE _hProcess, - _Inout_ PUSHORT _pGroupCount, - _Out_writes_(*_pGroupCount) PUSHORT _pGroupArray - ) + //Minimum supported client Windows 7 [desktop apps only] + //Minimum supported server Windows Server 2008 R2 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 12, + BOOL, + WINAPI, + GetProcessGroupAffinity, + _In_ HANDLE _hProcess, + _Inout_ PUSHORT _pGroupCount, + _Out_writes_(*_pGroupCount) PUSHORT _pGroupArray + ) + { + if (const auto _pfnGetProcessGroupAffinity = try_get_GetProcessGroupAffinity()) { - if (const auto _pfnGetProcessGroupAffinity = try_get_GetProcessGroupAffinity()) - { - return _pfnGetProcessGroupAffinity(_hProcess, _pGroupCount, _pGroupArray); - } + return _pfnGetProcessGroupAffinity(_hProcess, _pGroupCount, _pGroupArray); + } - // 更低版本系统不支持 CPU组,所以我们可以视为系统只有一组处理器。 - if (_pGroupCount == nullptr || _pGroupArray == nullptr) - { - SetLastError(ERROR_NOACCESS); - return FALSE; - } + // 更低版本系统不支持 CPU组,所以我们可以视为系统只有一组处理器。 + if (_pGroupCount == nullptr || _pGroupArray == nullptr) + { + SetLastError(ERROR_NOACCESS); + return FALSE; + } - if (*_pGroupCount < 1) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } - *_pGroupCount = 1; - _pGroupArray[0] = 0; - return TRUE; + if (*_pGroupCount < 1) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; } + *_pGroupCount = 1; + _pGroupArray[0] = 0; + return TRUE; + } #endif - } // namespace Thunks -} // namespace YY +} // namespace YY::Thunks diff --git a/src/Thunks/api-ms-win-core-psapi.hpp b/src/Thunks/api-ms-win-core-psapi.hpp index ec5e564..679d22b 100644 --- a/src/Thunks/api-ms-win-core-psapi.hpp +++ b/src/Thunks/api-ms-win-core-psapi.hpp @@ -1,99 +1,93 @@  -namespace YY +namespace YY::Thunks { - namespace Thunks - { +#if (YY_Thunks_Target < __WindowsNT6) -#if (YY_Thunks_Support_Version < NTDDI_WIN6) + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + QueryFullProcessImageNameW, + _In_ HANDLE hProcess, + _In_ DWORD dwFlags, + _Out_writes_to_(*lpdwSize, *lpdwSize) LPWSTR lpExeName, + _Inout_ PDWORD lpdwSize + ) + { + if (auto pQueryFullProcessImageNameW = try_get_QueryFullProcessImageNameW()) + { + return pQueryFullProcessImageNameW(hProcess, dwFlags, lpExeName, lpdwSize); + } - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - QueryFullProcessImageNameW, - _In_ HANDLE hProcess, - _In_ DWORD dwFlags, - _Out_writes_to_(*lpdwSize, *lpdwSize) LPWSTR lpExeName, - _Inout_ PDWORD lpdwSize - ) - { - if (auto pQueryFullProcessImageNameW = try_get_QueryFullProcessImageNameW()) - { - return pQueryFullProcessImageNameW(hProcess, dwFlags, lpExeName, lpdwSize); - } + auto dwSize = *lpdwSize; - auto dwSize = *lpdwSize; + if (dwFlags & PROCESS_NAME_NATIVE) + { + dwSize = GetProcessImageFileNameW(hProcess, lpExeName, dwSize); + } + else + { + dwSize = GetModuleFileNameExW(hProcess, nullptr, lpExeName, dwSize); + } - if (dwFlags & PROCESS_NAME_NATIVE) - { - dwSize = GetProcessImageFileNameW(hProcess, lpExeName, dwSize); - } - else - { - dwSize = GetModuleFileNameExW(hProcess, nullptr, lpExeName, dwSize); - } - - if (dwSize) - { - *lpdwSize = dwSize; - return TRUE; - } - else - { - return FALSE; - } - } + if (dwSize) + { + *lpdwSize = dwSize; + return TRUE; + } + else + { + return FALSE; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - QueryFullProcessImageNameA, - _In_ HANDLE hProcess, - _In_ DWORD dwFlags, - _Out_writes_to_(*lpdwSize, *lpdwSize) LPSTR lpExeName, - _Inout_ PDWORD lpdwSize - ) - { - if (auto pQueryFullProcessImageNameA = try_get_QueryFullProcessImageNameA()) - { - return pQueryFullProcessImageNameA(hProcess, dwFlags, lpExeName, lpdwSize); - } + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + QueryFullProcessImageNameA, + _In_ HANDLE hProcess, + _In_ DWORD dwFlags, + _Out_writes_to_(*lpdwSize, *lpdwSize) LPSTR lpExeName, + _Inout_ PDWORD lpdwSize + ) + { + if (auto pQueryFullProcessImageNameA = try_get_QueryFullProcessImageNameA()) + { + return pQueryFullProcessImageNameA(hProcess, dwFlags, lpExeName, lpdwSize); + } - auto dwSize = *lpdwSize; + auto dwSize = *lpdwSize; - if (dwFlags & PROCESS_NAME_NATIVE) - { - dwSize = GetProcessImageFileNameA(hProcess, lpExeName, dwSize); - } - else - { - dwSize = GetModuleFileNameExA(hProcess, nullptr, lpExeName, dwSize); - } + if (dwFlags & PROCESS_NAME_NATIVE) + { + dwSize = GetProcessImageFileNameA(hProcess, lpExeName, dwSize); + } + else + { + dwSize = GetModuleFileNameExA(hProcess, nullptr, lpExeName, dwSize); + } - if (dwSize) - { - *lpdwSize = dwSize; - return TRUE; - } - else - { - return FALSE; - } - } + if (dwSize) + { + *lpdwSize = dwSize; + return TRUE; + } + else + { + return FALSE; + } + } #endif - - }//namespace Thunks - -} //namespace YY \ No newline at end of file +} //namespace YY::Thunks diff --git a/src/Thunks/api-ms-win-core-realtime.hpp b/src/Thunks/api-ms-win-core-realtime.hpp index 2b512ae..22fccd0 100644 --- a/src/Thunks/api-ms-win-core-realtime.hpp +++ b/src/Thunks/api-ms-win-core-realtime.hpp @@ -4,7 +4,7 @@ namespace YY::Thunks::Fallback { namespace { -#if (YY_Thunks_Support_Version < NTDDI_WIN10) && defined(YY_Thunks_Implemented) +#if (YY_Thunks_Target < __WindowsNT10_10240) && defined(YY_Thunks_Implemented) static VOID WINAPI QueryInterruptTimeDownlevel( _Out_ PULONGLONG _puInterruptTime ) @@ -29,101 +29,101 @@ namespace YY::Thunks::Fallback namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 8, - _Success_(return) - BOOL, - WINAPI, - QueryThreadCycleTime, - _In_ HANDLE ThreadHandle, - _Out_ PULONG64 CycleTime - ) - { - if (auto pQueryThreadCycleTime = try_get_QueryThreadCycleTime()) - { - return pQueryThreadCycleTime(ThreadHandle, CycleTime); - } - - - //GetThreadTimes凑合用吧…… - FILETIME CreationTime; - FILETIME ExitTime; - FILETIME KernelTime; - FILETIME UserTime; - - if (!GetThreadTimes(ThreadHandle, &CreationTime, &ExitTime, &KernelTime, &UserTime)) - { - return FALSE; - } - - ((ULARGE_INTEGER*)CycleTime)->LowPart = UserTime.dwLowDateTime; - ((ULARGE_INTEGER*)CycleTime)->HighPart = UserTime.dwHighDateTime; - - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 8, + _Success_(return) + BOOL, + WINAPI, + QueryThreadCycleTime, + _In_ HANDLE ThreadHandle, + _Out_ PULONG64 CycleTime + ) + { + if (auto pQueryThreadCycleTime = try_get_QueryThreadCycleTime()) + { + return pQueryThreadCycleTime(ThreadHandle, CycleTime); + } + + + //GetThreadTimes凑合用吧…… + FILETIME CreationTime; + FILETIME ExitTime; + FILETIME KernelTime; + FILETIME UserTime; + + if (!GetThreadTimes(ThreadHandle, &CreationTime, &ExitTime, &KernelTime, &UserTime)) + { + return FALSE; + } + + ((ULARGE_INTEGER*)CycleTime)->LowPart = UserTime.dwLowDateTime; + ((ULARGE_INTEGER*)CycleTime)->HighPart = UserTime.dwHighDateTime; + + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 8, - _Success_(return) - BOOL, - WINAPI, - QueryProcessCycleTime, - _In_ HANDLE ProcessHandle, - _Out_ PULONG64 CycleTime - ) - { - if (auto pQueryProcessCycleTime = try_get_QueryProcessCycleTime()) - { - return pQueryProcessCycleTime(ProcessHandle, CycleTime); - } - - //GetProcessTimes凑合用吧…… - FILETIME CreationTime; - FILETIME ExitTime; - FILETIME KernelTime; - FILETIME UserTime; - - if (!GetProcessTimes(ProcessHandle, &CreationTime, &ExitTime, &KernelTime, &UserTime)) - { - return FALSE; - } - - ((ULARGE_INTEGER*)CycleTime)->LowPart = UserTime.dwLowDateTime; - ((ULARGE_INTEGER*)CycleTime)->HighPart = UserTime.dwHighDateTime; - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 8, + _Success_(return) + BOOL, + WINAPI, + QueryProcessCycleTime, + _In_ HANDLE ProcessHandle, + _Out_ PULONG64 CycleTime + ) + { + if (auto pQueryProcessCycleTime = try_get_QueryProcessCycleTime()) + { + return pQueryProcessCycleTime(ProcessHandle, CycleTime); + } + + //GetProcessTimes凑合用吧…… + FILETIME CreationTime; + FILETIME ExitTime; + FILETIME KernelTime; + FILETIME UserTime; + + if (!GetProcessTimes(ProcessHandle, &CreationTime, &ExitTime, &KernelTime, &UserTime)) + { + return FALSE; + } + + ((ULARGE_INTEGER*)CycleTime)->LowPart = UserTime.dwLowDateTime; + ((ULARGE_INTEGER*)CycleTime)->HighPart = UserTime.dwHighDateTime; + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) - // 最低受支持的客户端 Windows 7、Windows 8 [桌面应用 |UWP 应用] + // 最低受支持的客户端 Windows 7、Windows 8 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2008 R2[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 4, - BOOL, - WINAPI, - QueryUnbiasedInterruptTime, + __DEFINE_THUNK( + kernel32, + 4, + BOOL, + WINAPI, + QueryUnbiasedInterruptTime, _Out_ PULONGLONG _puUnbiasedTime - ) - { - if (const auto _pfnQueryUnbiasedInterruptTime = try_get_QueryUnbiasedInterruptTime()) - { - return _pfnQueryUnbiasedInterruptTime(_puUnbiasedTime); - } + ) + { + if (const auto _pfnQueryUnbiasedInterruptTime = try_get_QueryUnbiasedInterruptTime()) + { + return _pfnQueryUnbiasedInterruptTime(_puUnbiasedTime); + } if (!_puUnbiasedTime) { @@ -138,23 +138,23 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10) +#if (YY_Thunks_Target < __WindowsNT10_10240) - // 最低受支持的客户端 Windows 10 [桌面应用 |UWP 应用] + // 最低受支持的客户端 Windows 10 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2016[桌面应用 | UWP 应用] - __DEFINE_THUNK( - api_ms_win_core_realtime_l1_1_1, - 4, - VOID, + __DEFINE_THUNK( + api_ms_win_core_realtime_l1_1_1, + 4, + VOID, WINAPI, QueryUnbiasedInterruptTimePrecise, _Out_ PULONGLONG _puUnbiasedInterruptTimePrecise - ) - { - if (const auto _pfnQueryUnbiasedInterruptTimePrecise = try_get_QueryUnbiasedInterruptTimePrecise()) - { - return _pfnQueryUnbiasedInterruptTimePrecise(_puUnbiasedInterruptTimePrecise); - } + ) + { + if (const auto _pfnQueryUnbiasedInterruptTimePrecise = try_get_QueryUnbiasedInterruptTimePrecise()) + { + return _pfnQueryUnbiasedInterruptTimePrecise(_puUnbiasedInterruptTimePrecise); + } // 故意模拟微软原版行为,触发空指针时的内存非法访问。 *_puUnbiasedInterruptTimePrecise = 0; @@ -163,71 +163,71 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10) +#if (YY_Thunks_Target < __WindowsNT10_10240) - // 最低受支持的客户端 Windows 10 [桌面应用 |UWP 应用] + // 最低受支持的客户端 Windows 10 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2016[桌面应用 | UWP 应用] - __DEFINE_THUNK( - api_ms_win_core_realtime_l1_1_1, - 4, - VOID, + __DEFINE_THUNK( + api_ms_win_core_realtime_l1_1_1, + 4, + VOID, WINAPI, QueryInterruptTime, _Out_ PULONGLONG _puInterruptTime - ) - { - if (const auto _pfnQueryInterruptTime = try_get_QueryInterruptTime()) - { - return _pfnQueryInterruptTime(_puInterruptTime); - } + ) + { + if (const auto _pfnQueryInterruptTime = try_get_QueryInterruptTime()) + { + return _pfnQueryInterruptTime(_puInterruptTime); + } Fallback::QueryInterruptTimeDownlevel(_puInterruptTime); } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10) +#if (YY_Thunks_Target < __WindowsNT10_10240) - // 最低受支持的客户端 Windows 10 [桌面应用 |UWP 应用] + // 最低受支持的客户端 Windows 10 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2016[桌面应用 | UWP 应用] - __DEFINE_THUNK( - api_ms_win_core_realtime_l1_1_1, - 4, - VOID, + __DEFINE_THUNK( + api_ms_win_core_realtime_l1_1_1, + 4, + VOID, WINAPI, QueryInterruptTimePrecise, _Out_ PULONGLONG _puInterruptTimePrecise - ) - { - if (const auto _pfnQueryInterruptTimePrecise = try_get_QueryInterruptTimePrecise()) - { - return _pfnQueryInterruptTimePrecise(_puInterruptTimePrecise); - } + ) + { + if (const auto _pfnQueryInterruptTimePrecise = try_get_QueryInterruptTimePrecise()) + { + return _pfnQueryInterruptTimePrecise(_puInterruptTimePrecise); + } Fallback::QueryInterruptTimeDownlevel(_puInterruptTimePrecise); } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) - // 最低受支持的客户端 Windows 7 [仅限桌面应用] + // 最低受支持的客户端 Windows 7 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] - __DEFINE_THUNK( - kernel32, - 12, - BOOL, + __DEFINE_THUNK( + kernel32, + 12, + BOOL, WINAPI, QueryIdleProcessorCycleTimeEx, _In_ USHORT _uGroup, _Inout_ PULONG _puBufferLength, _Out_writes_bytes_opt_(*_puBufferLength) PULONG64 _puProcessorIdleCycleTime - ) - { - if (const auto _pfnQueryIdleProcessorCycleTimeEx = try_get_QueryIdleProcessorCycleTimeEx()) - { - return _pfnQueryIdleProcessorCycleTimeEx(_uGroup, _puBufferLength, _puProcessorIdleCycleTime); - } + ) + { + if (const auto _pfnQueryIdleProcessorCycleTimeEx = try_get_QueryIdleProcessorCycleTimeEx()) + { + return _pfnQueryIdleProcessorCycleTimeEx(_uGroup, _puBufferLength, _puProcessorIdleCycleTime); + } // 不支持的平台统一认为只有1组CPU可用 if (_uGroup != 0) @@ -241,24 +241,24 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [仅限桌面应用] + // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, + __DEFINE_THUNK( + kernel32, + 8, + BOOL, WINAPI, QueryIdleProcessorCycleTime, _Inout_ PULONG _pBufferLength, _Out_writes_bytes_opt_(*_pBufferLength) PULONG64 _pProcessorIdleCycleTime - ) - { - if (const auto _pfnQueryIdleProcessorCycleTime = try_get_QueryIdleProcessorCycleTime()) - { - return _pfnQueryIdleProcessorCycleTime(_pBufferLength, _pProcessorIdleCycleTime); - } + ) + { + if (const auto _pfnQueryIdleProcessorCycleTime = try_get_QueryIdleProcessorCycleTime()) + { + return _pfnQueryIdleProcessorCycleTime(_pBufferLength, _pProcessorIdleCycleTime); + } // Windows Vista开始才支持:SystemProcessorIdleCycleTimeInformation,目前只能自己实现一份。 // 目前随便写一个值,表示现在的空闲时间,一般情况下随便写没有太大问题 diff --git a/src/Thunks/api-ms-win-core-registry.hpp b/src/Thunks/api-ms-win-core-registry.hpp index 648000f..5da8e27 100644 --- a/src/Thunks/api-ms-win-core-registry.hpp +++ b/src/Thunks/api-ms-win-core-registry.hpp @@ -1,765 +1,765 @@  namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WS03SP1) - - //Windows XP Professional x64 Edition, Windows Server 2003 with SP1 - __DEFINE_THUNK( - advapi32, - 16, - LSTATUS, - APIENTRY, - RegDeleteKeyExW, - _In_ HKEY hKey, - _In_ LPCWSTR lpSubKey, - _In_ REGSAM samDesired, - _Reserved_ DWORD Reserved - ) - { - if(auto const pRegDeleteKeyExW = try_get_RegDeleteKeyExW()) - { - return pRegDeleteKeyExW(hKey, lpSubKey, samDesired, Reserved); - } - - - return RegDeleteKeyW(hKey, lpSubKey); - } +#if (YY_Thunks_Target < __WindowsNT5_2_SP1) + + //Windows XP Professional x64 Edition, Windows Server 2003 with SP1 + __DEFINE_THUNK( + advapi32, + 16, + LSTATUS, + APIENTRY, + RegDeleteKeyExW, + _In_ HKEY hKey, + _In_ LPCWSTR lpSubKey, + _In_ REGSAM samDesired, + _Reserved_ DWORD Reserved + ) + { + if(auto const pRegDeleteKeyExW = try_get_RegDeleteKeyExW()) + { + return pRegDeleteKeyExW(hKey, lpSubKey, samDesired, Reserved); + } + + + return RegDeleteKeyW(hKey, lpSubKey); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03SP1) - - //Windows XP Professional x64 Edition, Windows Server 2003 with SP1 - __DEFINE_THUNK( - advapi32, - 16, - LSTATUS, - APIENTRY, - RegDeleteKeyExA, - _In_ HKEY hKey, - _In_ LPCSTR lpSubKey, - _In_ REGSAM samDesired, - _Reserved_ DWORD Reserved - ) - { - if (auto const pRegDeleteKeyExA = try_get_RegDeleteKeyExA()) - { - return pRegDeleteKeyExA(hKey, lpSubKey, samDesired, Reserved); - } - - return RegDeleteKeyA(hKey, lpSubKey); - } +#if (YY_Thunks_Target < __WindowsNT5_2_SP1) + + //Windows XP Professional x64 Edition, Windows Server 2003 with SP1 + __DEFINE_THUNK( + advapi32, + 16, + LSTATUS, + APIENTRY, + RegDeleteKeyExA, + _In_ HKEY hKey, + _In_ LPCSTR lpSubKey, + _In_ REGSAM samDesired, + _Reserved_ DWORD Reserved + ) + { + if (auto const pRegDeleteKeyExA = try_get_RegDeleteKeyExA()) + { + return pRegDeleteKeyExA(hKey, lpSubKey, samDesired, Reserved); + } + + return RegDeleteKeyA(hKey, lpSubKey); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - advapi32, - 24, - LSTATUS, - APIENTRY, - RegSetKeyValueW, - _In_ HKEY hKey, - _In_opt_ LPCWSTR lpSubKey, - _In_opt_ LPCWSTR lpValueName, - _In_ DWORD dwType, - _In_reads_bytes_opt_(cbData) LPCVOID lpData, - _In_ DWORD cbData - ) - { - //Empty? - if (lpSubKey == nullptr || *lpSubKey == L'\0') - { - return RegSetValueExW(hKey, lpValueName, 0, dwType, (const BYTE*)lpData, cbData); - } - else - { - HKEY hSubKey; - auto lStatus = RegCreateKeyExW(hKey, lpSubKey, 0, nullptr, 0, KEY_SET_VALUE, nullptr, &hSubKey, nullptr); - - if (lStatus == ERROR_SUCCESS) - { - lStatus = RegSetValueExW(hSubKey, lpValueName, 0, dwType, (const BYTE*)lpData, cbData); - - RegCloseKey(hSubKey); - } - - return lStatus; - } - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + advapi32, + 24, + LSTATUS, + APIENTRY, + RegSetKeyValueW, + _In_ HKEY hKey, + _In_opt_ LPCWSTR lpSubKey, + _In_opt_ LPCWSTR lpValueName, + _In_ DWORD dwType, + _In_reads_bytes_opt_(cbData) LPCVOID lpData, + _In_ DWORD cbData + ) + { + //Empty? + if (lpSubKey == nullptr || *lpSubKey == L'\0') + { + return RegSetValueExW(hKey, lpValueName, 0, dwType, (const BYTE*)lpData, cbData); + } + else + { + HKEY hSubKey; + auto lStatus = RegCreateKeyExW(hKey, lpSubKey, 0, nullptr, 0, KEY_SET_VALUE, nullptr, &hSubKey, nullptr); + + if (lStatus == ERROR_SUCCESS) + { + lStatus = RegSetValueExW(hSubKey, lpValueName, 0, dwType, (const BYTE*)lpData, cbData); + + RegCloseKey(hSubKey); + } + + return lStatus; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - advapi32, - 24, - LSTATUS, - APIENTRY, - RegSetKeyValueA, - _In_ HKEY hKey, - _In_opt_ LPCSTR lpSubKey, - _In_opt_ LPCSTR lpValueName, - _In_ DWORD dwType, - _In_reads_bytes_opt_(cbData) LPCVOID lpData, - _In_ DWORD cbData - ) - { - //Empty? - if (lpSubKey == nullptr || *lpSubKey == '\0') - { - return RegSetValueExA(hKey, lpValueName, 0, dwType, (const BYTE*)lpData, cbData); - } - else - { - HKEY hSubKey; - auto lStatus = RegCreateKeyExA(hKey, lpSubKey, 0, nullptr, 0, KEY_SET_VALUE, nullptr, &hSubKey, nullptr); - - if (lStatus == ERROR_SUCCESS) - { - lStatus = RegSetValueExA(hSubKey, lpValueName, 0, dwType, (const BYTE*)lpData, cbData); - - RegCloseKey(hSubKey); - } - - return lStatus; - } - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + advapi32, + 24, + LSTATUS, + APIENTRY, + RegSetKeyValueA, + _In_ HKEY hKey, + _In_opt_ LPCSTR lpSubKey, + _In_opt_ LPCSTR lpValueName, + _In_ DWORD dwType, + _In_reads_bytes_opt_(cbData) LPCVOID lpData, + _In_ DWORD cbData + ) + { + //Empty? + if (lpSubKey == nullptr || *lpSubKey == '\0') + { + return RegSetValueExA(hKey, lpValueName, 0, dwType, (const BYTE*)lpData, cbData); + } + else + { + HKEY hSubKey; + auto lStatus = RegCreateKeyExA(hKey, lpSubKey, 0, nullptr, 0, KEY_SET_VALUE, nullptr, &hSubKey, nullptr); + + if (lStatus == ERROR_SUCCESS) + { + lStatus = RegSetValueExA(hSubKey, lpValueName, 0, dwType, (const BYTE*)lpData, cbData); + + RegCloseKey(hSubKey); + } + + return lStatus; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - advapi32, - 12, - LSTATUS, - APIENTRY, - RegDeleteKeyValueW, - _In_ HKEY hKey, - _In_opt_ LPCWSTR lpSubKey, - _In_opt_ LPCWSTR lpValueName - ) - { - HKEY hSubKey; - auto lStatus = RegOpenKeyExW(hKey, lpSubKey, 0, KEY_SET_VALUE, &hSubKey); - - if (lStatus == ERROR_SUCCESS) - { - lStatus = RegDeleteValueW(hSubKey, lpValueName); - RegCloseKey(hSubKey); - } - - return lStatus; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + advapi32, + 12, + LSTATUS, + APIENTRY, + RegDeleteKeyValueW, + _In_ HKEY hKey, + _In_opt_ LPCWSTR lpSubKey, + _In_opt_ LPCWSTR lpValueName + ) + { + HKEY hSubKey; + auto lStatus = RegOpenKeyExW(hKey, lpSubKey, 0, KEY_SET_VALUE, &hSubKey); + + if (lStatus == ERROR_SUCCESS) + { + lStatus = RegDeleteValueW(hSubKey, lpValueName); + RegCloseKey(hSubKey); + } + + return lStatus; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - advapi32, - 12, - LSTATUS, - APIENTRY, - RegDeleteKeyValueA, - _In_ HKEY hKey, - _In_opt_ LPCSTR lpSubKey, - _In_opt_ LPCSTR lpValueName - ) - { - HKEY hSubKey; - auto lStatus = RegOpenKeyExA(hKey, lpSubKey, 0, KEY_SET_VALUE, &hSubKey); - - if (lStatus == ERROR_SUCCESS) - { - lStatus = RegDeleteValueA(hSubKey, lpValueName); - RegCloseKey(hSubKey); - } - - return lStatus; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + advapi32, + 12, + LSTATUS, + APIENTRY, + RegDeleteKeyValueA, + _In_ HKEY hKey, + _In_opt_ LPCSTR lpSubKey, + _In_opt_ LPCSTR lpValueName + ) + { + HKEY hSubKey; + auto lStatus = RegOpenKeyExA(hKey, lpSubKey, 0, KEY_SET_VALUE, &hSubKey); + + if (lStatus == ERROR_SUCCESS) + { + lStatus = RegDeleteValueA(hSubKey, lpValueName); + RegCloseKey(hSubKey); + } + + return lStatus; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - advapi32, - 8, - LSTATUS, - APIENTRY, - RegDeleteTreeW, - _In_ HKEY hKey, - _In_opt_ LPCWSTR lpSubKey - ) - { - return SHDeleteKeyW(hKey, lpSubKey); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + advapi32, + 8, + LSTATUS, + APIENTRY, + RegDeleteTreeW, + _In_ HKEY hKey, + _In_opt_ LPCWSTR lpSubKey + ) + { + return SHDeleteKeyW(hKey, lpSubKey); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - advapi32, - 8, - LSTATUS, - APIENTRY, - RegDeleteTreeA, - _In_ HKEY hKey, - _In_opt_ LPCSTR lpSubKey - ) - { - return SHDeleteKeyA(hKey, lpSubKey); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + advapi32, + 8, + LSTATUS, + APIENTRY, + RegDeleteTreeA, + _In_ HKEY hKey, + _In_opt_ LPCSTR lpSubKey + ) + { + return SHDeleteKeyA(hKey, lpSubKey); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03SP1) - - //Windows Vista, Windows XP Professional x64 Edition, Windows Server 2008, Windows Server 2003 with SP1 - __DEFINE_THUNK( - advapi32, - 28, - LSTATUS, - APIENTRY, - RegGetValueW, - HKEY hkey, - LPCWSTR lpSubKey, - LPCWSTR lpValue, - DWORD dwFlags, - LPDWORD pdwType, - PVOID pvData, - LPDWORD pcbData - ) - { -#if (YY_Thunks_Support_Version >= NTDDI_WINXPSP2) - return SHRegGetValueW(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); +#if (YY_Thunks_Target < __WindowsNT5_2_SP1) + + //Windows Vista, Windows XP Professional x64 Edition, Windows Server 2008, Windows Server 2003 with SP1 + __DEFINE_THUNK( + advapi32, + 28, + LSTATUS, + APIENTRY, + RegGetValueW, + HKEY hkey, + LPCWSTR lpSubKey, + LPCWSTR lpValue, + DWORD dwFlags, + LPDWORD pdwType, + PVOID pvData, + LPDWORD pcbData + ) + { +#if (YY_Thunks_Target >= __WindowsNT5_1_SP2) + return SHRegGetValueW(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); #else - if (auto const pRegGetValueW = try_get_RegGetValueW()) - { - return pRegGetValueW(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); - } - - if (pvData && pcbData == nullptr - || (dwFlags & RRF_RT_ANY) == 0) - { - return ERROR_INVALID_PARAMETER; - } - - LSTATUS lStatus; - - if (lpSubKey&&*lpSubKey) - { - lStatus = RegOpenKeyExW(hkey, lpSubKey, 0, KEY_QUERY_VALUE, &hkey); - if (lStatus != ERROR_SUCCESS) - return lStatus; - } - - DWORD dwType; - DWORD cbData = pvData && pcbData ? *pcbData : 0; - const auto cbDataBackup = cbData; - - - lStatus = RegQueryValueExW(hkey, lpValue, nullptr, &dwType, (LPBYTE)pvData, &cbData); - - DWORD cbDataFix; - if (lStatus == ERROR_SUCCESS - || lStatus == ERROR_MORE_DATA) - { - if (dwType == REG_MULTI_SZ) - { - //连续2个 null 结尾 - cbDataFix = cbData + sizeof(*lpValue) * 2; - } - else if (dwType == REG_SZ) - { - //一个null 结尾 - cbDataFix = cbData + sizeof(*lpValue); - } - else if (dwType == REG_EXPAND_SZ) - { - if (dwFlags & RRF_NOEXPAND) - { - //一个null 结尾 - cbDataFix = cbData + sizeof(*lpValue); - } - else - { - //需要展开 - cbDataFix = pvData && pcbData ? *pcbData : 0; - lStatus = SHQueryValueExW(hkey, lpValue, nullptr, &dwType, pvData, &cbDataFix); - - if (lStatus == ERROR_SUCCESS - || lStatus == ERROR_MORE_DATA) - { - cbData = cbDataFix; - } - } - } - else - { - cbDataFix = cbData; - } - } - - if (lpSubKey&&*lpSubKey) - { - RegCloseKey(hkey); - } - - - if (lStatus == ERROR_SUCCESS - || lStatus == ERROR_MORE_DATA) - { - if (pdwType) - *pdwType = dwType; - - //检测类型是否支持 - switch (dwType) - { - case REG_NONE: - case REG_SZ: - case REG_EXPAND_SZ: - case REG_BINARY: - case REG_DWORD: - if ((dwFlags & (1 << dwType)) == 0) - { - lStatus = ERROR_UNSUPPORTED_TYPE; - break; - } - else if (pvData && lStatus == ERROR_SUCCESS) - { - //当函数成功时,保证字符串正常 NULL 结尾 - if (REG_SZ == dwType || REG_EXPAND_SZ == dwType) - { - //保证1个 NULL 结尾 - - - //sizeof(wchar_t) 边界对齐 - if (cbData % sizeof(*lpValue)) - { - if (cbData >= cbDataBackup) - { - lStatus = ERROR_MORE_DATA; - break; - } - - ((byte*)pvData)[cbData] = 0; - - ++cbData; - } - - - auto cStringMin = cbData / sizeof(*lpValue); - - - auto pString = (wchar_t*)pvData; - - if (cStringMin == 0 || pString[cStringMin - 1]) - { - if (cbData + sizeof(*lpValue) > cbDataBackup) - { - lStatus = ERROR_MORE_DATA; - break; - } - - pString[cStringMin++] = L'\0'; - } - - cbDataFix = cStringMin * sizeof(*lpValue); - } - } - break; - case REG_MULTI_SZ: - if ((dwFlags & RRF_RT_REG_MULTI_SZ) == 0) - { - lStatus = ERROR_UNSUPPORTED_TYPE; - } - else if (pvData && lStatus == ERROR_SUCCESS) - { - //保证最后一个字符串 NULL 结尾 并且 包含 NULL 结束符 - - //sizeof(wchar_t) 边界对齐 - if (cbData % sizeof(*lpValue)) - { - if (cbData >= cbDataBackup) - { - lStatus = ERROR_MORE_DATA; - break; - } - - ((byte*)pvData)[cbData] = 0; - - ++cbData; - } - - auto cStringMin = cbData / sizeof(*lpValue); - - auto pString = (wchar_t*)pvData; - - if (cStringMin == 0) - { - if (cbData + sizeof(*lpValue) > cbDataBackup) - { - lStatus = ERROR_MORE_DATA; - break; - } - - pString[cStringMin++] = L'\0'; - } - else if (pString[cStringMin - 1]) - { - if (cbData + sizeof(*lpValue) * 2 > cbDataBackup) - { - lStatus = ERROR_MORE_DATA; - break; - } - - pString[cStringMin++] = L'\0'; - - pString[cStringMin++] = L'\0'; - } - else if (cStringMin >= 2 && pString[cStringMin - 2]) - { - if (cbData + sizeof(*lpValue) > cbDataBackup) - { - lStatus = ERROR_MORE_DATA; - break; - } - - pString[cStringMin++] = L'\0'; - } - - cbDataFix = cStringMin * sizeof(*lpValue); - } - break; - case REG_QWORD: - if ((dwFlags & RRF_RT_REG_QWORD) == 0) - { - lStatus = ERROR_UNSUPPORTED_TYPE; - } - break; - default: - if((dwFlags & RRF_RT_ANY) != RRF_RT_ANY) - lStatus = ERROR_UNSUPPORTED_TYPE; - break; - } - - if (pcbData) - *pcbData = cbDataFix; - - } - - - if ((RRF_ZEROONFAILURE & dwFlags) != 0 && lStatus) - { - //全0填充 - if (pvData && cbDataBackup) - { - memset(pvData, 0, cbDataBackup); - } - } - - return lStatus; + if (auto const pRegGetValueW = try_get_RegGetValueW()) + { + return pRegGetValueW(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); + } + + if (pvData && pcbData == nullptr + || (dwFlags & RRF_RT_ANY) == 0) + { + return ERROR_INVALID_PARAMETER; + } + + LSTATUS lStatus; + + if (lpSubKey&&*lpSubKey) + { + lStatus = RegOpenKeyExW(hkey, lpSubKey, 0, KEY_QUERY_VALUE, &hkey); + if (lStatus != ERROR_SUCCESS) + return lStatus; + } + + DWORD dwType; + DWORD cbData = pvData && pcbData ? *pcbData : 0; + const auto cbDataBackup = cbData; + + + lStatus = RegQueryValueExW(hkey, lpValue, nullptr, &dwType, (LPBYTE)pvData, &cbData); + + DWORD cbDataFix; + if (lStatus == ERROR_SUCCESS + || lStatus == ERROR_MORE_DATA) + { + if (dwType == REG_MULTI_SZ) + { + //连续2个 null 结尾 + cbDataFix = cbData + sizeof(*lpValue) * 2; + } + else if (dwType == REG_SZ) + { + //一个null 结尾 + cbDataFix = cbData + sizeof(*lpValue); + } + else if (dwType == REG_EXPAND_SZ) + { + if (dwFlags & RRF_NOEXPAND) + { + //一个null 结尾 + cbDataFix = cbData + sizeof(*lpValue); + } + else + { + //需要展开 + cbDataFix = pvData && pcbData ? *pcbData : 0; + lStatus = SHQueryValueExW(hkey, lpValue, nullptr, &dwType, pvData, &cbDataFix); + + if (lStatus == ERROR_SUCCESS + || lStatus == ERROR_MORE_DATA) + { + cbData = cbDataFix; + } + } + } + else + { + cbDataFix = cbData; + } + } + + if (lpSubKey&&*lpSubKey) + { + RegCloseKey(hkey); + } + + + if (lStatus == ERROR_SUCCESS + || lStatus == ERROR_MORE_DATA) + { + if (pdwType) + *pdwType = dwType; + + //检测类型是否支持 + switch (dwType) + { + case REG_NONE: + case REG_SZ: + case REG_EXPAND_SZ: + case REG_BINARY: + case REG_DWORD: + if ((dwFlags & (1 << dwType)) == 0) + { + lStatus = ERROR_UNSUPPORTED_TYPE; + break; + } + else if (pvData && lStatus == ERROR_SUCCESS) + { + //当函数成功时,保证字符串正常 NULL 结尾 + if (REG_SZ == dwType || REG_EXPAND_SZ == dwType) + { + //保证1个 NULL 结尾 + + + //sizeof(wchar_t) 边界对齐 + if (cbData % sizeof(*lpValue)) + { + if (cbData >= cbDataBackup) + { + lStatus = ERROR_MORE_DATA; + break; + } + + ((byte*)pvData)[cbData] = 0; + + ++cbData; + } + + + auto cStringMin = cbData / sizeof(*lpValue); + + + auto pString = (wchar_t*)pvData; + + if (cStringMin == 0 || pString[cStringMin - 1]) + { + if (cbData + sizeof(*lpValue) > cbDataBackup) + { + lStatus = ERROR_MORE_DATA; + break; + } + + pString[cStringMin++] = L'\0'; + } + + cbDataFix = cStringMin * sizeof(*lpValue); + } + } + break; + case REG_MULTI_SZ: + if ((dwFlags & RRF_RT_REG_MULTI_SZ) == 0) + { + lStatus = ERROR_UNSUPPORTED_TYPE; + } + else if (pvData && lStatus == ERROR_SUCCESS) + { + //保证最后一个字符串 NULL 结尾 并且 包含 NULL 结束符 + + //sizeof(wchar_t) 边界对齐 + if (cbData % sizeof(*lpValue)) + { + if (cbData >= cbDataBackup) + { + lStatus = ERROR_MORE_DATA; + break; + } + + ((byte*)pvData)[cbData] = 0; + + ++cbData; + } + + auto cStringMin = cbData / sizeof(*lpValue); + + auto pString = (wchar_t*)pvData; + + if (cStringMin == 0) + { + if (cbData + sizeof(*lpValue) > cbDataBackup) + { + lStatus = ERROR_MORE_DATA; + break; + } + + pString[cStringMin++] = L'\0'; + } + else if (pString[cStringMin - 1]) + { + if (cbData + sizeof(*lpValue) * 2 > cbDataBackup) + { + lStatus = ERROR_MORE_DATA; + break; + } + + pString[cStringMin++] = L'\0'; + + pString[cStringMin++] = L'\0'; + } + else if (cStringMin >= 2 && pString[cStringMin - 2]) + { + if (cbData + sizeof(*lpValue) > cbDataBackup) + { + lStatus = ERROR_MORE_DATA; + break; + } + + pString[cStringMin++] = L'\0'; + } + + cbDataFix = cStringMin * sizeof(*lpValue); + } + break; + case REG_QWORD: + if ((dwFlags & RRF_RT_REG_QWORD) == 0) + { + lStatus = ERROR_UNSUPPORTED_TYPE; + } + break; + default: + if((dwFlags & RRF_RT_ANY) != RRF_RT_ANY) + lStatus = ERROR_UNSUPPORTED_TYPE; + break; + } + + if (pcbData) + *pcbData = cbDataFix; + + } + + + if ((RRF_ZEROONFAILURE & dwFlags) != 0 && lStatus) + { + //全0填充 + if (pvData && cbDataBackup) + { + memset(pvData, 0, cbDataBackup); + } + } + + return lStatus; #endif - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03SP1) - - //Windows Vista, Windows XP Professional x64 Edition, Windows Server 2008, Windows Server 2003 with SP1 - __DEFINE_THUNK( - advapi32, - 28, - LSTATUS, - APIENTRY, - RegGetValueA, - HKEY hkey, - LPCSTR lpSubKey, - LPCSTR lpValue, - DWORD dwFlags, - LPDWORD pdwType, - PVOID pvData, - LPDWORD pcbData - ) - { -#if (YY_Thunks_Support_Version >= NTDDI_WINXPSP2) - return SHRegGetValueA(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); +#if (YY_Thunks_Target < __WindowsNT5_2_SP1) + + //Windows Vista, Windows XP Professional x64 Edition, Windows Server 2008, Windows Server 2003 with SP1 + __DEFINE_THUNK( + advapi32, + 28, + LSTATUS, + APIENTRY, + RegGetValueA, + HKEY hkey, + LPCSTR lpSubKey, + LPCSTR lpValue, + DWORD dwFlags, + LPDWORD pdwType, + PVOID pvData, + LPDWORD pcbData + ) + { +#if (YY_Thunks_Target >= __WindowsNT5_1_SP2) + return SHRegGetValueA(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); #else - if (auto const pRegGetValueA = try_get_RegGetValueA()) - { - return pRegGetValueA(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); - } - - if (pvData && pcbData == nullptr - || (dwFlags & RRF_RT_ANY) == 0) - { - return ERROR_INVALID_PARAMETER; - } - - LSTATUS lStatus; - - if (lpSubKey&&*lpSubKey) - { - lStatus = RegOpenKeyExA(hkey, lpSubKey, 0, KEY_QUERY_VALUE, &hkey); - if (lStatus != ERROR_SUCCESS) - return lStatus; - } - - DWORD dwType; - DWORD cbData = pvData && pcbData ? *pcbData : 0; - const auto cbDataBackup = cbData; - - - lStatus = RegQueryValueExA(hkey, lpValue, nullptr, &dwType, (LPBYTE)pvData, &cbData); - - DWORD cbDataFix; - if (lStatus == ERROR_SUCCESS - || lStatus == ERROR_MORE_DATA) - { - if (dwType == REG_MULTI_SZ) - { - //连续2个 null 结尾 - cbDataFix = cbData + sizeof(*lpValue) * 2; - } - else if (dwType == REG_SZ) - { - //一个null 结尾 - cbDataFix = cbData + sizeof(*lpValue); - } - else if (dwType == REG_EXPAND_SZ) - { - if (dwFlags & RRF_NOEXPAND) - { - //一个null 结尾 - cbDataFix = cbData + sizeof(*lpValue); - } - else - { - //需要展开 - cbDataFix = pvData && pcbData ? *pcbData : 0; - lStatus = SHQueryValueExA(hkey, lpValue, nullptr, &dwType, pvData, &cbDataFix); - - if (lStatus == ERROR_SUCCESS - || lStatus == ERROR_MORE_DATA) - { - cbData = cbDataFix; - } - } - } - else - { - cbDataFix = cbData; - } - } - - if (lpSubKey&&*lpSubKey) - { - RegCloseKey(hkey); - } - - - if (lStatus == ERROR_SUCCESS - || lStatus == ERROR_MORE_DATA) - { - if (pdwType) - *pdwType = dwType; - - //检测类型是否支持 - switch (dwType) - { - case REG_NONE: - case REG_SZ: - case REG_EXPAND_SZ: - case REG_BINARY: - case REG_DWORD: - if ((dwFlags & (1<< dwType)) == 0) - { - lStatus = ERROR_UNSUPPORTED_TYPE; - } - else if (pvData && lStatus == ERROR_SUCCESS) - { - //当函数成功时,保证字符串正常 NULL 结尾 - if (REG_SZ == dwType || REG_EXPAND_SZ == dwType) - { - //保证1个 NULL 结尾 - auto cStringMin = cbData; - - - auto pString = (char*)pvData; - - if (cStringMin == 0 || pString[cStringMin - 1]) - { - if (cbData + sizeof(*lpValue) > cbDataBackup) - { - lStatus = ERROR_MORE_DATA; - break; - } - - pString[cStringMin++] = '\0'; - } - - cbDataFix = cStringMin * sizeof(*lpValue); - } - } - break; - case REG_MULTI_SZ: - if ((dwFlags & RRF_RT_REG_MULTI_SZ) == 0) - { - lStatus = ERROR_UNSUPPORTED_TYPE; - } - else - { - //保证最后一个字符串 NULL 结尾 并且 包含 NULL 结束符 - - auto cStringMin = cbData; - - auto pString = (char*)pvData; - - if (cStringMin == 0) - { - if (cbData + sizeof(*lpValue) > cbDataBackup) - { - lStatus = ERROR_MORE_DATA; - break; - } - - pString[cStringMin++] = '\0'; - } - else if (pString[cStringMin - 1]) - { - if (cbData + sizeof(*lpValue) * 2 > cbDataBackup) - { - lStatus = ERROR_MORE_DATA; - break; - } - - pString[cStringMin++] = '\0'; - - pString[cStringMin++] = '\0'; - } - else if (cStringMin >= 2 && pString[cStringMin - 2]) - { - if (cbData + sizeof(*lpValue) > cbDataBackup) - { - lStatus = ERROR_MORE_DATA; - break; - } - - pString[cStringMin++] = '\0'; - } - - cbDataFix = cStringMin * sizeof(*lpValue); - } - break; - case REG_QWORD: - if ((dwFlags & RRF_RT_REG_QWORD) == 0) - { - lStatus = ERROR_UNSUPPORTED_TYPE; - } - break; - default: - if((dwFlags & RRF_RT_ANY) != RRF_RT_ANY) - lStatus = ERROR_UNSUPPORTED_TYPE; - break; - } - - if (pcbData) - *pcbData = cbDataFix; - - } - - - if ((RRF_ZEROONFAILURE & dwFlags) != 0 && lStatus) - { - //全0填充 - if (pvData && cbDataBackup) - { - memset(pvData, 0, cbDataBackup); - } - } - - return lStatus; + if (auto const pRegGetValueA = try_get_RegGetValueA()) + { + return pRegGetValueA(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); + } + + if (pvData && pcbData == nullptr + || (dwFlags & RRF_RT_ANY) == 0) + { + return ERROR_INVALID_PARAMETER; + } + + LSTATUS lStatus; + + if (lpSubKey&&*lpSubKey) + { + lStatus = RegOpenKeyExA(hkey, lpSubKey, 0, KEY_QUERY_VALUE, &hkey); + if (lStatus != ERROR_SUCCESS) + return lStatus; + } + + DWORD dwType; + DWORD cbData = pvData && pcbData ? *pcbData : 0; + const auto cbDataBackup = cbData; + + + lStatus = RegQueryValueExA(hkey, lpValue, nullptr, &dwType, (LPBYTE)pvData, &cbData); + + DWORD cbDataFix; + if (lStatus == ERROR_SUCCESS + || lStatus == ERROR_MORE_DATA) + { + if (dwType == REG_MULTI_SZ) + { + //连续2个 null 结尾 + cbDataFix = cbData + sizeof(*lpValue) * 2; + } + else if (dwType == REG_SZ) + { + //一个null 结尾 + cbDataFix = cbData + sizeof(*lpValue); + } + else if (dwType == REG_EXPAND_SZ) + { + if (dwFlags & RRF_NOEXPAND) + { + //一个null 结尾 + cbDataFix = cbData + sizeof(*lpValue); + } + else + { + //需要展开 + cbDataFix = pvData && pcbData ? *pcbData : 0; + lStatus = SHQueryValueExA(hkey, lpValue, nullptr, &dwType, pvData, &cbDataFix); + + if (lStatus == ERROR_SUCCESS + || lStatus == ERROR_MORE_DATA) + { + cbData = cbDataFix; + } + } + } + else + { + cbDataFix = cbData; + } + } + + if (lpSubKey&&*lpSubKey) + { + RegCloseKey(hkey); + } + + + if (lStatus == ERROR_SUCCESS + || lStatus == ERROR_MORE_DATA) + { + if (pdwType) + *pdwType = dwType; + + //检测类型是否支持 + switch (dwType) + { + case REG_NONE: + case REG_SZ: + case REG_EXPAND_SZ: + case REG_BINARY: + case REG_DWORD: + if ((dwFlags & (1<< dwType)) == 0) + { + lStatus = ERROR_UNSUPPORTED_TYPE; + } + else if (pvData && lStatus == ERROR_SUCCESS) + { + //当函数成功时,保证字符串正常 NULL 结尾 + if (REG_SZ == dwType || REG_EXPAND_SZ == dwType) + { + //保证1个 NULL 结尾 + auto cStringMin = cbData; + + + auto pString = (char*)pvData; + + if (cStringMin == 0 || pString[cStringMin - 1]) + { + if (cbData + sizeof(*lpValue) > cbDataBackup) + { + lStatus = ERROR_MORE_DATA; + break; + } + + pString[cStringMin++] = '\0'; + } + + cbDataFix = cStringMin * sizeof(*lpValue); + } + } + break; + case REG_MULTI_SZ: + if ((dwFlags & RRF_RT_REG_MULTI_SZ) == 0) + { + lStatus = ERROR_UNSUPPORTED_TYPE; + } + else + { + //保证最后一个字符串 NULL 结尾 并且 包含 NULL 结束符 + + auto cStringMin = cbData; + + auto pString = (char*)pvData; + + if (cStringMin == 0) + { + if (cbData + sizeof(*lpValue) > cbDataBackup) + { + lStatus = ERROR_MORE_DATA; + break; + } + + pString[cStringMin++] = '\0'; + } + else if (pString[cStringMin - 1]) + { + if (cbData + sizeof(*lpValue) * 2 > cbDataBackup) + { + lStatus = ERROR_MORE_DATA; + break; + } + + pString[cStringMin++] = '\0'; + + pString[cStringMin++] = '\0'; + } + else if (cStringMin >= 2 && pString[cStringMin - 2]) + { + if (cbData + sizeof(*lpValue) > cbDataBackup) + { + lStatus = ERROR_MORE_DATA; + break; + } + + pString[cStringMin++] = '\0'; + } + + cbDataFix = cStringMin * sizeof(*lpValue); + } + break; + case REG_QWORD: + if ((dwFlags & RRF_RT_REG_QWORD) == 0) + { + lStatus = ERROR_UNSUPPORTED_TYPE; + } + break; + default: + if((dwFlags & RRF_RT_ANY) != RRF_RT_ANY) + lStatus = ERROR_UNSUPPORTED_TYPE; + break; + } + + if (pcbData) + *pcbData = cbDataFix; + + } + + + if ((RRF_ZEROONFAILURE & dwFlags) != 0 && lStatus) + { + //全0填充 + if (pvData && cbDataBackup) + { + memset(pvData, 0, cbDataBackup); + } + } + + return lStatus; #endif - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - advapi32, - 12, - LSTATUS, - APIENTRY, - RegCopyTreeW, - _In_ HKEY hKeySrc, - _In_opt_ LPCWSTR lpSubKey, - _In_ HKEY hKeyDest - ) - { - if (auto const pRegCopyTreeW = try_get_RegCopyTreeW()) - { - return pRegCopyTreeW(hKeySrc, lpSubKey, hKeyDest); - } - - return SHCopyKeyW(hKeySrc, lpSubKey, hKeyDest, 0); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + advapi32, + 12, + LSTATUS, + APIENTRY, + RegCopyTreeW, + _In_ HKEY hKeySrc, + _In_opt_ LPCWSTR lpSubKey, + _In_ HKEY hKeyDest + ) + { + if (auto const pRegCopyTreeW = try_get_RegCopyTreeW()) + { + return pRegCopyTreeW(hKeySrc, lpSubKey, hKeyDest); + } + + return SHCopyKeyW(hKeySrc, lpSubKey, hKeyDest, 0); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - advapi32, - 12, - LSTATUS, - APIENTRY, - RegCopyTreeA, - _In_ HKEY hKeySrc, - _In_opt_ LPCSTR lpSubKey, - _In_ HKEY hKeyDest - ) - { - if (auto const pRegCopyTreeA = try_get_RegCopyTreeA()) - { - return pRegCopyTreeA(hKeySrc, lpSubKey, hKeyDest); - } - - return SHCopyKeyA(hKeySrc, lpSubKey, hKeyDest, 0); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + advapi32, + 12, + LSTATUS, + APIENTRY, + RegCopyTreeA, + _In_ HKEY hKeySrc, + _In_opt_ LPCSTR lpSubKey, + _In_ HKEY hKeyDest + ) + { + if (auto const pRegCopyTreeA = try_get_RegCopyTreeA()) + { + return pRegCopyTreeA(hKeySrc, lpSubKey, hKeyDest); + } + + return SHCopyKeyA(hKeySrc, lpSubKey, hKeyDest, 0); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10) +#if (YY_Thunks_Target < __WindowsNT10_10240) - // 最低受支持的客户端 Windows 2000 Professional [仅限桌面应用] + // 最低受支持的客户端 Windows 2000 Professional [仅限桌面应用] // 最低受支持的服务器 Windows 2000 Server[仅限桌面应用] // 虽然2000就支持,但是为了实现CompareObjectHandles,目前需要处理一下关闭。 __DEFINE_THUNK( - advapi32, - 4, - LSTATUS, + advapi32, + 4, + LSTATUS, APIENTRY, RegCloseKey, _In_ HKEY _hKey ) - { + { auto const _pfnRegCloseKey = try_get_RegCloseKey(); const auto _pfnCompareObjectHandles = try_get_CompareObjectHandles(); @@ -778,6 +778,6 @@ namespace YY::Thunks } return _lStatus; - } + } #endif } //namespace YY::Thunks diff --git a/src/Thunks/api-ms-win-core-rtlsupport.hpp b/src/Thunks/api-ms-win-core-rtlsupport.hpp index 50b050a..8cbc9be 100644 --- a/src/Thunks/api-ms-win-core-rtlsupport.hpp +++ b/src/Thunks/api-ms-win-core-rtlsupport.hpp @@ -1,33 +1,29 @@  -namespace YY +namespace YY::Thunks { - namespace Thunks - { +#if (YY_Thunks_Target < __WindowsNT5_1) -#if (YY_Thunks_Support_Version < NTDDI_WINXP) + // Available in starting with Windows XP. + // Windows 2000时这个函数就已经存在了,只是从XP开始才从kernel32.dll中导出 + __DEFINE_THUNK( + ntdll, + 16, + WORD, + NTAPI, + RtlCaptureStackBackTrace, + _In_ DWORD _uFramesToSkip, + _In_ DWORD _uFramesToCapture, + _Out_writes_to_(_uFramesToCapture, return) PVOID* _pBackTrace, + _Out_opt_ PDWORD _puBackTraceHash + ) + { + if (const auto _pfnRtlCaptureStackBackTrace = try_get_RtlCaptureStackBackTrace()) + { + return _pfnRtlCaptureStackBackTrace(_uFramesToSkip, _uFramesToCapture, _pBackTrace, _puBackTraceHash); + } - // Available in starting with Windows XP. - // Windows 2000时这个函数就已经存在了,只是从XP开始才从kernel32.dll中导出 - __DEFINE_THUNK( - ntdll, - 16, - WORD, - NTAPI, - RtlCaptureStackBackTrace, - _In_ DWORD _uFramesToSkip, - _In_ DWORD _uFramesToCapture, - _Out_writes_to_(_uFramesToCapture, return) PVOID* _pBackTrace, - _Out_opt_ PDWORD _puBackTraceHash - ) - { - if (const auto _pfnRtlCaptureStackBackTrace = try_get_RtlCaptureStackBackTrace()) - { - return _pfnRtlCaptureStackBackTrace(_uFramesToSkip, _uFramesToCapture, _pBackTrace, _puBackTraceHash); - } - - return 0; - } + return 0; + } #endif - } } diff --git a/src/Thunks/api-ms-win-core-string.hpp b/src/Thunks/api-ms-win-core-string.hpp index c649ac5..1d64cf3 100644 --- a/src/Thunks/api-ms-win-core-string.hpp +++ b/src/Thunks/api-ms-win-core-string.hpp @@ -1,189 +1,169 @@ - +#if (YY_Thunks_Target < __WindowsNT6) #include +#endif -namespace YY +namespace YY::Thunks { - namespace Thunks +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 36, + int, + WINAPI, + CompareStringEx, + _In_opt_ LPCWSTR lpLocaleName, + _In_ DWORD dwCmpFlags, + _In_NLS_string_(cchCount1) LPCWCH lpString1, + _In_ int cchCount1, + _In_NLS_string_(cchCount2) LPCWCH lpString2, + _In_ int cchCount2, + _Reserved_ LPNLSVERSIONINFO lpVersionInformation, + _Reserved_ LPVOID lpReserved, + _Reserved_ LPARAM lParam + ) { - -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 36, - int, - WINAPI, - CompareStringEx, - _In_opt_ LPCWSTR lpLocaleName, - _In_ DWORD dwCmpFlags, - _In_NLS_string_(cchCount1) LPCWCH lpString1, - _In_ int cchCount1, - _In_NLS_string_(cchCount2) LPCWCH lpString2, - _In_ int cchCount2, - _Reserved_ LPNLSVERSIONINFO lpVersionInformation, - _Reserved_ LPVOID lpReserved, - _Reserved_ LPARAM lParam - ) + if (auto const pCompareStringEx = try_get_CompareStringEx()) { - if (auto const pCompareStringEx = try_get_CompareStringEx()) - { - return pCompareStringEx(lpLocaleName, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2, lpVersionInformation, lpReserved, lParam); - } - - const auto Locale = LocaleNameToLCID(lpLocaleName, 0); - if (Locale == 0) - { - return 0; - } + return pCompareStringEx(lpLocaleName, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2, lpVersionInformation, lpReserved, lParam); + } - return CompareStringW(Locale, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2); + const auto Locale = LocaleNameToLCID(lpLocaleName, 0); + if (Locale == 0) + { + return 0; } + + return CompareStringW(Locale, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 20, - int, - WINAPI, - CompareStringOrdinal, - _In_NLS_string_(cchCount1) LPCWCH lpString1, - _In_ int cchCount1, - _In_NLS_string_(cchCount2) LPCWCH lpString2, - _In_ int cchCount2, - _In_ BOOL bIgnoreCase - ) +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 20, + int, + WINAPI, + CompareStringOrdinal, + _In_NLS_string_(cchCount1) LPCWCH lpString1, + _In_ int cchCount1, + _In_NLS_string_(cchCount2) LPCWCH lpString2, + _In_ int cchCount2, + _In_ BOOL bIgnoreCase + ) + { + if (auto const pCompareStringOrdinal = try_get_CompareStringOrdinal()) { - if (auto const pCompareStringOrdinal = try_get_CompareStringOrdinal()) - { - return pCompareStringOrdinal(lpString1, cchCount1, lpString2, cchCount2, bIgnoreCase); - } + return pCompareStringOrdinal(lpString1, cchCount1, lpString2, cchCount2, bIgnoreCase); + } - auto ToLowerCase = [](unsigned short ch) -> wchar_t + auto ToLowerCase = [](unsigned short ch) -> wchar_t + { + static constexpr wchar_t UnicodeCaseTableData[] = { - static constexpr wchar_t UnicodeCaseTableData[] = - { - 0x0110, 0x0120, 0x0130, 0x0140, 0x0150, 0x0160, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0170, 0x0180, 0x0190, - 0x0100, 0x01A0, 0x0100, 0x0100, 0x01B0, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x01C0, 0x01D0, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x01E0, 0x01F0, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, - 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0200, - }; - - return (unsigned int)ch + UnicodeCaseTableData[(ch & 0xF) + UnicodeCaseTableData[((ch >> 4) & 0xF) + UnicodeCaseTableData[(unsigned short)(ch >> 8)]]]; + 0x0110, 0x0120, 0x0130, 0x0140, 0x0150, 0x0160, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0170, 0x0180, 0x0190, + 0x0100, 0x01A0, 0x0100, 0x0100, 0x01B0, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x01C0, 0x01D0, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x01E0, 0x01F0, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0200, }; + return (unsigned int)ch + UnicodeCaseTableData[(ch & 0xF) + UnicodeCaseTableData[((ch >> 4) & 0xF) + UnicodeCaseTableData[(unsigned short)(ch >> 8)]]]; + }; + - if ((bIgnoreCase == TRUE || bIgnoreCase == FALSE) - && lpString1 && lpString2) + if ((bIgnoreCase == TRUE || bIgnoreCase == FALSE) + && lpString1 && lpString2) + { + if (cchCount1 >= 0 || cchCount2 >= 0) { - if (cchCount1 >= 0 || cchCount2 >= 0) - { - //CompareStringOrdinalCounted + //CompareStringOrdinalCounted - size_t __cchCount1; - if (cchCount1 >= 0) - { - __cchCount1 = cchCount1; - } - else if (cchCount1 == -1) - { - if (FAILED(StringCchLengthW(lpString1, cchCount2 + 1, &__cchCount1))) - { - __cchCount1 = cchCount2 + 1; - } - } - else + size_t __cchCount1; + if (cchCount1 >= 0) + { + __cchCount1 = cchCount1; + } + else if (cchCount1 == -1) + { + if (FAILED(StringCchLengthW(lpString1, cchCount2 + 1, &__cchCount1))) { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; + __cchCount1 = cchCount2 + 1; } + } + else + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } - size_t __cchCount2; - if (cchCount2 >= 0) - { - __cchCount2 = cchCount2; - } - else if (cchCount2 == -1) - { - if (FAILED(StringCchLengthW(lpString2, cchCount1 + 1, &__cchCount2))) - { - __cchCount2 = cchCount1 + 1; - } - } - else + size_t __cchCount2; + if (cchCount2 >= 0) + { + __cchCount2 = cchCount2; + } + else if (cchCount2 == -1) + { + if (FAILED(StringCchLengthW(lpString2, cchCount1 + 1, &__cchCount2))) { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; + __cchCount2 = cchCount1 + 1; } + } + else + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } - size_t cchLength = min(__cchCount1, __cchCount2); + size_t cchLength = min(__cchCount1, __cchCount2); - if (bIgnoreCase) + if (bIgnoreCase) + { + for (size_t Index = 0; Index != cchLength; ++Index) { - for (size_t Index = 0; Index != cchLength; ++Index) - { - auto ch1 = lpString1[Index]; - auto ch2 = lpString2[Index]; + auto ch1 = lpString1[Index]; + auto ch2 = lpString2[Index]; - if (ch1 != ch2) - { - ch1 = ToLowerCase(ch1); - ch2 = ToLowerCase(ch2); - - if (ch1 > ch2) - { - return CSTR_GREATER_THAN; - } - else if (ch1 < ch2) - { - return CSTR_LESS_THAN; - } - } - } - } - else - { - for (size_t Index = 0; Index != cchLength; ++Index) + if (ch1 != ch2) { - auto ch1 = lpString1[Index]; - auto ch2 = lpString2[Index]; + ch1 = ToLowerCase(ch1); + ch2 = ToLowerCase(ch2); if (ch1 > ch2) { @@ -195,52 +175,48 @@ namespace YY } } } - - if (__cchCount1 == __cchCount2) - return CSTR_EQUAL; - else if (__cchCount1 > __cchCount2) - return CSTR_GREATER_THAN; - else - return CSTR_LESS_THAN; } - - if(cchCount1 == -1 && cchCount2 == -1) + else { - //CompareStringOrdinalNullTerminated - if (bIgnoreCase) + for (size_t Index = 0; Index != cchLength; ++Index) { - for (;;++lpString1, ++lpString2) - { - auto ch1 = *lpString1; - auto ch2 = *lpString2; + auto ch1 = lpString1[Index]; + auto ch2 = lpString2[Index]; - if (ch1 != ch2) - { - ch1 = ToLowerCase(ch1); - ch2 = ToLowerCase(ch2); - - if (ch1 > ch2) - { - return CSTR_GREATER_THAN; - } - else if (ch1 < ch2) - { - return CSTR_LESS_THAN; - } - } - - if (ch1 == '\0') - { - return CSTR_EQUAL; - } + if (ch1 > ch2) + { + return CSTR_GREATER_THAN; + } + else if (ch1 < ch2) + { + return CSTR_LESS_THAN; } } - else + } + + if (__cchCount1 == __cchCount2) + return CSTR_EQUAL; + else if (__cchCount1 > __cchCount2) + return CSTR_GREATER_THAN; + else + return CSTR_LESS_THAN; + } + + if(cchCount1 == -1 && cchCount2 == -1) + { + //CompareStringOrdinalNullTerminated + if (bIgnoreCase) + { + for (;;++lpString1, ++lpString2) { - for (;;++lpString1, ++lpString2) + auto ch1 = *lpString1; + auto ch2 = *lpString2; + + if (ch1 != ch2) { - auto ch1 = *lpString1; - auto ch2 = *lpString2; + ch1 = ToLowerCase(ch1); + ch2 = ToLowerCase(ch2); + if (ch1 > ch2) { return CSTR_GREATER_THAN; @@ -249,108 +225,129 @@ namespace YY { return CSTR_LESS_THAN; } - else + } + + if (ch1 == '\0') + { + return CSTR_EQUAL; + } + } + } + else + { + for (;;++lpString1, ++lpString2) + { + auto ch1 = *lpString1; + auto ch2 = *lpString2; + if (ch1 > ch2) + { + return CSTR_GREATER_THAN; + } + else if (ch1 < ch2) + { + return CSTR_LESS_THAN; + } + else + { + if (ch1 == '\0') { - if (ch1 == '\0') - { - return CSTR_EQUAL; - } + return CSTR_EQUAL; } } } } } - - SetLastError(ERROR_INVALID_PARAMETER); - return 0; } + + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } #endif -#if defined(YY_Thunks_Implemented) && (YY_Thunks_Support_Version < NTDDI_WINXP) - static bool IsSupportLOCALE_INVARIANT() +#if defined(YY_Thunks_Implemented) && (YY_Thunks_Target < __WindowsNT5_1) + static bool IsSupportLOCALE_INVARIANT() + { + // 特意不考虑多线程支持,因为这里产生写入竞争并没有关系。 + static int s_iStat = 0; + if (s_iStat == 0) { - // 特意不考虑多线程支持,因为这里产生写入竞争并没有关系。 - static int s_iStat = 0; - if (s_iStat == 0) - { - s_iStat = internal::GetSystemVersion() >= internal::MakeVersion(5, 1) ? 1 : -1; - } - return s_iStat == 1; + s_iStat = internal::GetSystemVersion() >= internal::MakeVersion(5, 1) ? 1 : -1; } + return s_iStat == 1; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WINXP) - - // Windows 2000 不支持 LOCALE_INVARIANT 参数特殊处理一下。 - // Minimum supported client Windows 2000 Professional [desktop apps only] - // Minimum supported server Windows 2000 Server [desktop apps only] - __DEFINE_THUNK( - kernel32, - 24, - int, - WINAPI, - CompareStringA, - _In_ LCID Locale, - _In_ DWORD dwCmpFlags, - _In_reads_(cchCount1) PCNZCH lpString1, - _In_ int cchCount1, - _In_reads_(cchCount2) PCNZCH lpString2, - _In_ int cchCount2) +#if (YY_Thunks_Target < __WindowsNT5_1) + + // Windows 2000 不支持 LOCALE_INVARIANT 参数特殊处理一下。 + // Minimum supported client Windows 2000 Professional [desktop apps only] + // Minimum supported server Windows 2000 Server [desktop apps only] + __DEFINE_THUNK( + kernel32, + 24, + int, + WINAPI, + CompareStringA, + _In_ LCID Locale, + _In_ DWORD dwCmpFlags, + _In_reads_(cchCount1) PCNZCH lpString1, + _In_ int cchCount1, + _In_reads_(cchCount2) PCNZCH lpString2, + _In_ int cchCount2) + { + // 网友 海好蓝 提供 + const auto _pfnCompareStringA = try_get_CompareStringA(); + if (!_pfnCompareStringA) { - // 网友 海好蓝 提供 - const auto _pfnCompareStringA = try_get_CompareStringA(); - if (!_pfnCompareStringA) - { - SetLastError(ERROR_NOT_SUPPORTED); - return 0; - } - - if (Locale == LOCALE_INVARIANT && IsSupportLOCALE_INVARIANT() == false) - { - Locale = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); - } + SetLastError(ERROR_NOT_SUPPORTED); + return 0; + } - return _pfnCompareStringA(Locale, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2); + if (Locale == LOCALE_INVARIANT && IsSupportLOCALE_INVARIANT() == false) + { + Locale = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); } + + return _pfnCompareStringA(Locale, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WINXP) - - // Windows 2000 不支持 LOCALE_INVARIANT 参数特殊处理一下。 - // Minimum supported client Windows 2000 Professional [desktop apps only] - // Minimum supported server Windows 2000 Server [desktop apps only] - __DEFINE_THUNK( - kernel32, - 24, - int, - WINAPI, - CompareStringW, - _In_ LCID Locale, - _In_ DWORD dwCmpFlags, - _In_NLS_string_(cchCount1) PCNZWCH lpString1, - _In_ int cchCount1, - _In_NLS_string_(cchCount2) PCNZWCH lpString2, - _In_ int cchCount2 - ) +#if (YY_Thunks_Target < __WindowsNT5_1) + + // Windows 2000 不支持 LOCALE_INVARIANT 参数特殊处理一下。 + // Minimum supported client Windows 2000 Professional [desktop apps only] + // Minimum supported server Windows 2000 Server [desktop apps only] + __DEFINE_THUNK( + kernel32, + 24, + int, + WINAPI, + CompareStringW, + _In_ LCID Locale, + _In_ DWORD dwCmpFlags, + _In_NLS_string_(cchCount1) PCNZWCH lpString1, + _In_ int cchCount1, + _In_NLS_string_(cchCount2) PCNZWCH lpString2, + _In_ int cchCount2 + ) + { + // 网友 海好蓝 提供 + const auto _pfnCompareStringW = try_get_CompareStringW(); + if (!_pfnCompareStringW) { - // 网友 海好蓝 提供 - const auto _pfnCompareStringW = try_get_CompareStringW(); - if (!_pfnCompareStringW) - { - SetLastError(ERROR_NOT_SUPPORTED); - return 0; - } - - if (Locale == LOCALE_INVARIANT && IsSupportLOCALE_INVARIANT() == false) - { - Locale = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); - } + SetLastError(ERROR_NOT_SUPPORTED); + return 0; + } - return _pfnCompareStringW(Locale, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2); + if (Locale == LOCALE_INVARIANT && IsSupportLOCALE_INVARIANT() == false) + { + Locale = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); } -#endif + + return _pfnCompareStringW(Locale, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2); } +#endif } diff --git a/src/Thunks/api-ms-win-core-synch.hpp b/src/Thunks/api-ms-win-core-synch.hpp index adf1a42..b1239b5 100644 --- a/src/Thunks/api-ms-win-core-synch.hpp +++ b/src/Thunks/api-ms-win-core-synch.hpp @@ -26,32 +26,32 @@ //取自Win7 struct _YY_RTL_SRWLOCK { - union - { - struct - { - ULONG_PTR Locked : 1; - ULONG_PTR Waiting : 1; - ULONG_PTR Waking : 1; - ULONG_PTR MultipleShared : 1; + union + { + struct + { + ULONG_PTR Locked : 1; + ULONG_PTR Waiting : 1; + ULONG_PTR Waking : 1; + ULONG_PTR MultipleShared : 1; #ifdef _WIN64 - ULONG_PTR Shared : 60; + ULONG_PTR Shared : 60; #else - ULONG_PTR Shared : 28; + ULONG_PTR Shared : 28; #endif - }; - ULONG_PTR Value; - VOID* Ptr; - }; + }; + ULONG_PTR Value; + VOID* Ptr; + }; }; typedef struct __declspec(align(16)) _YY_SRWLOCK_WAIT_BLOCK { - _YY_SRWLOCK_WAIT_BLOCK* back; - _YY_SRWLOCK_WAIT_BLOCK* notify; - _YY_SRWLOCK_WAIT_BLOCK* next; - volatile size_t shareCount; - volatile size_t flag; + _YY_SRWLOCK_WAIT_BLOCK* back; + _YY_SRWLOCK_WAIT_BLOCK* notify; + _YY_SRWLOCK_WAIT_BLOCK* next; + volatile size_t shareCount; + volatile size_t flag; } YY_SRWLOCK_WAIT_BLOCK; @@ -64,12 +64,12 @@ typedef struct __declspec(align(16)) _YY_SRWLOCK_WAIT_BLOCK typedef struct __declspec(align(16)) _YY_CV_WAIT_BLOCK { - _YY_CV_WAIT_BLOCK* back; - _YY_CV_WAIT_BLOCK* notify; - _YY_CV_WAIT_BLOCK* next; - volatile size_t shareCount; - volatile size_t flag; - volatile PSRWLOCK SRWLock; + _YY_CV_WAIT_BLOCK* back; + _YY_CV_WAIT_BLOCK* notify; + _YY_CV_WAIT_BLOCK* next; + volatile size_t shareCount; + volatile size_t flag; + volatile PSRWLOCK SRWLock; } YY_CV_WAIT_BLOCK; @@ -80,28 +80,28 @@ typedef struct __declspec(align(16)) _YY_CV_WAIT_BLOCK typedef struct __declspec(align(8)) _YY_ADDRESS_WAIT_BLOCK { - volatile void* Address; - //因为Windows 8以及更高版本才支持 ZwWaitForAlertByThreadId,所以我们直接把 ThreadId 砍掉了,反正没鸟用 - //ULONG_PTR ThreadId; - - // 它是后继 - _YY_ADDRESS_WAIT_BLOCK* back; - // 它是前驱 - _YY_ADDRESS_WAIT_BLOCK* notify; - // 似乎指向Root,但是Root时才指向自己,其余情况为 nullptr,这是一种安全性? - _YY_ADDRESS_WAIT_BLOCK* next; - volatile size_t flag; + volatile void* Address; + //因为Windows 8以及更高版本才支持 ZwWaitForAlertByThreadId,所以我们直接把 ThreadId 砍掉了,反正没鸟用 + //ULONG_PTR ThreadId; + + // 它是后继 + _YY_ADDRESS_WAIT_BLOCK* back; + // 它是前驱 + _YY_ADDRESS_WAIT_BLOCK* notify; + // 似乎指向Root,但是Root时才指向自己,其余情况为 nullptr,这是一种安全性? + _YY_ADDRESS_WAIT_BLOCK* next; + volatile size_t flag; } YY_ADDRESS_WAIT_BLOCK; //YY-Thunks中Barrier采用了Windows 8实现 typedef struct _YY_BARRIER { - volatile LONG lRemainderThreads; - volatile LONG lTotalThreads; - HANDLE hEvent[2]; - DWORD dwNumProcessors; - DWORD dwSpinCount; + volatile LONG lRemainderThreads; + volatile LONG lTotalThreads; + HANDLE hEvent[2]; + DWORD dwNumProcessors; + DWORD dwSpinCount; } YY_BARRIER; static_assert(sizeof(SYNCHRONIZATION_BARRIER) >= sizeof(YY_BARRIER), "必须跟系统ABI兼容!!!!"); @@ -112,2757 +112,2757 @@ static_assert(sizeof(SYNCHRONIZATION_BARRIER) >= sizeof(YY_BARRIER), "必须跟 #ifdef YY_Thunks_Implemented namespace YY::Thunks::internal { - namespace - { - static HANDLE __fastcall GetGlobalKeyedEventHandle() - { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - //Windows XP等平台则 使用系统自身的 CritSecOutOfMemoryEvent,Vista或者更高平台 我们直接返回 nullptr 即可。 - if (NtCurrentTeb()->ProcessEnvironmentBlock->OSMajorVersion < 6) - { - if (_GlobalKeyedEventHandle == nullptr) - { - auto pNtOpenKeyedEvent = try_get_NtOpenKeyedEvent(); - - if(pNtOpenKeyedEvent == nullptr) - RaiseStatus(STATUS_RESOURCE_NOT_OWNED); - - constexpr const wchar_t Name[] = L"\\KernelObjects\\CritSecOutOfMemoryEvent"; - - UNICODE_STRING ObjectName = {sizeof(Name) - sizeof(wchar_t),sizeof(Name) - sizeof(wchar_t) ,(PWSTR)Name }; - OBJECT_ATTRIBUTES attr = { sizeof(attr),nullptr,&ObjectName }; - - HANDLE KeyedEventHandle; - - if (pNtOpenKeyedEvent(&KeyedEventHandle, MAXIMUM_ALLOWED, &attr) < 0) - { - RaiseStatus(STATUS_RESOURCE_NOT_OWNED); - } - - if (InterlockedCompareExchange((size_t*)&_GlobalKeyedEventHandle, (size_t)KeyedEventHandle, (size_t)nullptr)) - { - CloseHandle(KeyedEventHandle); - } - } - - return _GlobalKeyedEventHandle; - } + namespace + { + static HANDLE __fastcall GetGlobalKeyedEventHandle() + { +#if (YY_Thunks_Target < __WindowsNT6) + //Windows XP等平台则 使用系统自身的 CritSecOutOfMemoryEvent,Vista或者更高平台 我们直接返回 nullptr 即可。 + if (NtCurrentTeb()->ProcessEnvironmentBlock->OSMajorVersion < 6) + { + if (_GlobalKeyedEventHandle == nullptr) + { + auto pNtOpenKeyedEvent = try_get_NtOpenKeyedEvent(); + + if(pNtOpenKeyedEvent == nullptr) + RaiseStatus(STATUS_RESOURCE_NOT_OWNED); + + constexpr const wchar_t Name[] = L"\\KernelObjects\\CritSecOutOfMemoryEvent"; + + UNICODE_STRING ObjectName = {sizeof(Name) - sizeof(wchar_t),sizeof(Name) - sizeof(wchar_t) ,(PWSTR)Name }; + OBJECT_ATTRIBUTES attr = { sizeof(attr),nullptr,&ObjectName }; + + HANDLE KeyedEventHandle; + + if (pNtOpenKeyedEvent(&KeyedEventHandle, MAXIMUM_ALLOWED, &attr) < 0) + { + RaiseStatus(STATUS_RESOURCE_NOT_OWNED); + } + + if (InterlockedCompareExchange((size_t*)&_GlobalKeyedEventHandle, (size_t)KeyedEventHandle, (size_t)nullptr)) + { + CloseHandle(KeyedEventHandle); + } + } + + return _GlobalKeyedEventHandle; + } #endif - //Vista以上平台支持给 KeyedEvent直接传 nullptr - return nullptr; - } - -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - static void __fastcall RtlpWakeSRWLock(SRWLOCK* SRWLock, size_t Status) - { - auto GlobalKeyedEventHandle = GetGlobalKeyedEventHandle(); - auto pNtReleaseKeyedEvent = try_get_NtReleaseKeyedEvent(); - - if (!pNtReleaseKeyedEvent) - { - RaiseStatus(STATUS_RESOURCE_NOT_OWNED); - } - - for (;;) - { - if ((Status & YY_SRWLOCK_Locked) == 0) - { - //微软就不判断下空指针?如此自信? - auto pWatiBlock = YY_SRWLOCK_GET_BLOCK(Status); - - YY_SRWLOCK_WAIT_BLOCK* notify; - - for (auto pBlock = pWatiBlock; (notify = pBlock->notify) == nullptr;) - { - auto back = pBlock->back; - back->next = pBlock; - - pBlock = back; - } - - pWatiBlock->notify = notify; - - - //判断是否是一个独占链 - if (notify->next && (notify->flag & 1)) - { - pWatiBlock->notify = notify->next; - notify->next = nullptr; - - //SRWLock & (~YY_SRWLOCK_Waking) + //Vista以上平台支持给 KeyedEvent直接传 nullptr + return nullptr; + } + +#if (YY_Thunks_Target < __WindowsNT6) + + static void __fastcall RtlpWakeSRWLock(SRWLOCK* SRWLock, size_t Status) + { + auto GlobalKeyedEventHandle = GetGlobalKeyedEventHandle(); + auto pNtReleaseKeyedEvent = try_get_NtReleaseKeyedEvent(); + + if (!pNtReleaseKeyedEvent) + { + RaiseStatus(STATUS_RESOURCE_NOT_OWNED); + } + + for (;;) + { + if ((Status & YY_SRWLOCK_Locked) == 0) + { + //微软就不判断下空指针?如此自信? + auto pWatiBlock = YY_SRWLOCK_GET_BLOCK(Status); + + YY_SRWLOCK_WAIT_BLOCK* notify; + + for (auto pBlock = pWatiBlock; (notify = pBlock->notify) == nullptr;) + { + auto back = pBlock->back; + back->next = pBlock; + + pBlock = back; + } + + pWatiBlock->notify = notify; + + + //判断是否是一个独占链 + if (notify->next && (notify->flag & 1)) + { + pWatiBlock->notify = notify->next; + notify->next = nullptr; + + //SRWLock & (~YY_SRWLOCK_Waking) #ifdef _WIN64 - _InterlockedAnd64((volatile LONG_PTR *)SRWLock, ~LONG_PTR(YY_SRWLOCK_Waking)); + _InterlockedAnd64((volatile LONG_PTR *)SRWLock, ~LONG_PTR(YY_SRWLOCK_Waking)); #else - _InterlockedAnd((volatile LONG_PTR *)SRWLock, ~LONG_PTR(YY_SRWLOCK_Waking)); + _InterlockedAnd((volatile LONG_PTR *)SRWLock, ~LONG_PTR(YY_SRWLOCK_Waking)); #endif - if (!InterlockedBitTestAndReset((volatile LONG*)¬ify->flag, 1)) - { - //块处于等待状态,我们进行线程唤醒 - - //if(!RtlpWaitCouldDeadlock()) - - pNtReleaseKeyedEvent(GlobalKeyedEventHandle, notify, 0, nullptr); - } - - return; - } - else - { - //等待的是一个共享锁,那么唤醒所有等待的共享锁。 - auto NewStatus = InterlockedCompareExchange((volatile size_t *)SRWLock, 0, Status); - - if (NewStatus == Status) - { - //更新成功! - for (; notify;) - { - auto next = notify->next; - - - if (!InterlockedBitTestAndReset((volatile LONG*)¬ify->flag, 1)) - { - //块处于等待状态,我们进行线程唤醒 - - //if(!RtlpWaitCouldDeadlock()) - - pNtReleaseKeyedEvent(GlobalKeyedEventHandle, notify, 0, nullptr); - } - - notify = next; - } - - return; - } - - Status = NewStatus; - } - - pWatiBlock->notify = notify; - } - else - { - auto NewStatus = InterlockedCompareExchange((volatile size_t*)SRWLock, Status & ~YY_SRWLOCK_Waking, Status); - if (NewStatus == Status) - return; - - Status = NewStatus; - } - } - } - - static void __fastcall RtlpOptimizeSRWLockList(SRWLOCK* SRWLock, size_t Status) - { - for (;;) - { - if (Status & YY_SRWLOCK_Locked) - { - if (auto WatiBlock = (YY_SRWLOCK_WAIT_BLOCK*)(Status & (~YY_SRWLOCK_MASK))) - { - auto pBlock = WatiBlock; - - for (; pBlock->notify == nullptr;) - { - auto back = pBlock->back; - back->next = pBlock; - - pBlock = back; - } - - WatiBlock->notify = pBlock->notify; - } - - //微软为什么用 Status - YY_SRWLOCK_Waking,而为什么不用 Status & ~YY_SRWLOCK_Waking ? - auto CurrentStatus = InterlockedCompareExchange((volatile size_t *)SRWLock, Status - YY_SRWLOCK_Waking, Status); - if (CurrentStatus == Status) - break; - - Status = CurrentStatus; - } - else - { - RtlpWakeSRWLock(SRWLock, Status); - break; - } - } - } - - //将等待块插入 SRWLock 中 - static BOOL __fastcall RtlpQueueWaitBlockToSRWLock(YY_CV_WAIT_BLOCK* pBolck, PSRWLOCK SRWLock, DWORD SRWLockMark) - { - for (;;) - { - auto Current = *(volatile size_t*)SRWLock; - - if ((Current & 0x1) == 0) - break; - - - if (SRWLockMark == 0) - { - pBolck->flag |= 0x1; - } - else if ((Current & 0x2) == 0 && YY_SRWLOCK_GET_BLOCK(Current)) - { - return FALSE; - } - - pBolck->next = nullptr; - - size_t New; + if (!InterlockedBitTestAndReset((volatile LONG*)¬ify->flag, 1)) + { + //块处于等待状态,我们进行线程唤醒 + + //if(!RtlpWaitCouldDeadlock()) + + pNtReleaseKeyedEvent(GlobalKeyedEventHandle, notify, 0, nullptr); + } + + return; + } + else + { + //等待的是一个共享锁,那么唤醒所有等待的共享锁。 + auto NewStatus = InterlockedCompareExchange((volatile size_t *)SRWLock, 0, Status); + + if (NewStatus == Status) + { + //更新成功! + for (; notify;) + { + auto next = notify->next; + + + if (!InterlockedBitTestAndReset((volatile LONG*)¬ify->flag, 1)) + { + //块处于等待状态,我们进行线程唤醒 + + //if(!RtlpWaitCouldDeadlock()) + + pNtReleaseKeyedEvent(GlobalKeyedEventHandle, notify, 0, nullptr); + } + + notify = next; + } + + return; + } + + Status = NewStatus; + } + + pWatiBlock->notify = notify; + } + else + { + auto NewStatus = InterlockedCompareExchange((volatile size_t*)SRWLock, Status & ~YY_SRWLOCK_Waking, Status); + if (NewStatus == Status) + return; + + Status = NewStatus; + } + } + } + + static void __fastcall RtlpOptimizeSRWLockList(SRWLOCK* SRWLock, size_t Status) + { + for (;;) + { + if (Status & YY_SRWLOCK_Locked) + { + if (auto WatiBlock = (YY_SRWLOCK_WAIT_BLOCK*)(Status & (~YY_SRWLOCK_MASK))) + { + auto pBlock = WatiBlock; + + for (; pBlock->notify == nullptr;) + { + auto back = pBlock->back; + back->next = pBlock; + + pBlock = back; + } + + WatiBlock->notify = pBlock->notify; + } + + //微软为什么用 Status - YY_SRWLOCK_Waking,而为什么不用 Status & ~YY_SRWLOCK_Waking ? + auto CurrentStatus = InterlockedCompareExchange((volatile size_t *)SRWLock, Status - YY_SRWLOCK_Waking, Status); + if (CurrentStatus == Status) + break; + + Status = CurrentStatus; + } + else + { + RtlpWakeSRWLock(SRWLock, Status); + break; + } + } + } + + //将等待块插入 SRWLock 中 + static BOOL __fastcall RtlpQueueWaitBlockToSRWLock(YY_CV_WAIT_BLOCK* pBolck, PSRWLOCK SRWLock, DWORD SRWLockMark) + { + for (;;) + { + auto Current = *(volatile size_t*)SRWLock; + + if ((Current & 0x1) == 0) + break; + + + if (SRWLockMark == 0) + { + pBolck->flag |= 0x1; + } + else if ((Current & 0x2) == 0 && YY_SRWLOCK_GET_BLOCK(Current)) + { + return FALSE; + } + + pBolck->next = nullptr; + + size_t New; - if (Current & 0x2) - { - pBolck->notify = nullptr; - pBolck->shareCount = 0; + if (Current & 0x2) + { + pBolck->notify = nullptr; + pBolck->shareCount = 0; - //_YY_CV_WAIT_BLOCK 结构体跟 _YY_SRWLOCK_WAIT_BLOCK兼容,所以能这样强转 - pBolck->back = (_YY_CV_WAIT_BLOCK*)YY_SRWLOCK_GET_BLOCK(Current); + //_YY_CV_WAIT_BLOCK 结构体跟 _YY_SRWLOCK_WAIT_BLOCK兼容,所以能这样强转 + pBolck->back = (_YY_CV_WAIT_BLOCK*)YY_SRWLOCK_GET_BLOCK(Current); - New = size_t(pBolck) | (Current & YY_CV_MASK); - } - else - { - auto shareCount = Current >> 4; + New = size_t(pBolck) | (Current & YY_CV_MASK); + } + else + { + auto shareCount = Current >> 4; - pBolck->shareCount = shareCount; - pBolck->notify = pBolck; - New = shareCount <= 1 ? (size_t(pBolck) | 0x3) : (size_t(pBolck) | 0xB); - } - - //清泠 发现的Bug,我们应该返回 TRUE,减少必要的内核等待。 - if (InterlockedCompareExchange((volatile size_t*)SRWLock, New, Current) == Current) - return TRUE; + pBolck->shareCount = shareCount; + pBolck->notify = pBolck; + New = shareCount <= 1 ? (size_t(pBolck) | 0x3) : (size_t(pBolck) | 0xB); + } + + //清泠 发现的Bug,我们应该返回 TRUE,减少必要的内核等待。 + if (InterlockedCompareExchange((volatile size_t*)SRWLock, New, Current) == Current) + return TRUE; - //RtlBackoff(&v7); - YieldProcessor(); - } + //RtlBackoff(&v7); + YieldProcessor(); + } - return FALSE; - } + return FALSE; + } - static void __fastcall RtlpWakeConditionVariable(PCONDITION_VARIABLE ConditionVariable, size_t ConditionVariableStatus, size_t WakeCount) - { - auto GlobalKeyedEventHandle = GetGlobalKeyedEventHandle(); - auto pNtReleaseKeyedEvent = try_get_NtReleaseKeyedEvent(); + static void __fastcall RtlpWakeConditionVariable(PCONDITION_VARIABLE ConditionVariable, size_t ConditionVariableStatus, size_t WakeCount) + { + auto GlobalKeyedEventHandle = GetGlobalKeyedEventHandle(); + auto pNtReleaseKeyedEvent = try_get_NtReleaseKeyedEvent(); - if (!pNtReleaseKeyedEvent) - { - RaiseStatus(STATUS_RESOURCE_NOT_OWNED); - } + if (!pNtReleaseKeyedEvent) + { + RaiseStatus(STATUS_RESOURCE_NOT_OWNED); + } - //v16 - YY_CV_WAIT_BLOCK* notify = nullptr; + //v16 + YY_CV_WAIT_BLOCK* notify = nullptr; - YY_CV_WAIT_BLOCK* pWake = nullptr; - YY_CV_WAIT_BLOCK** ppInsert = &pWake; + YY_CV_WAIT_BLOCK* pWake = nullptr; + YY_CV_WAIT_BLOCK** ppInsert = &pWake; - size_t Count = 0; + size_t Count = 0; - for (;;) - { - auto pWaitBlock = YY_CV_GET_BLOCK(ConditionVariableStatus); + for (;;) + { + auto pWaitBlock = YY_CV_GET_BLOCK(ConditionVariableStatus); - if ((ConditionVariableStatus & 0x7) == 0x7) - { - ConditionVariableStatus = InterlockedExchange((volatile size_t*)ConditionVariable, 0); + if ((ConditionVariableStatus & 0x7) == 0x7) + { + ConditionVariableStatus = InterlockedExchange((volatile size_t*)ConditionVariable, 0); - *ppInsert = YY_CV_GET_BLOCK(ConditionVariableStatus); + *ppInsert = YY_CV_GET_BLOCK(ConditionVariableStatus); - break; - } + break; + } - const auto MaxWakeCount = WakeCount + (ConditionVariableStatus & 7); + const auto MaxWakeCount = WakeCount + (ConditionVariableStatus & 7); - auto pBlock = pWaitBlock; + auto pBlock = pWaitBlock; - for (; pBlock->notify == nullptr;) - { - auto tmp = pBlock; - pBlock = pBlock->back; - pBlock->next = tmp; - } + for (; pBlock->notify == nullptr;) + { + auto tmp = pBlock; + pBlock = pBlock->back; + pBlock->next = tmp; + } - if (MaxWakeCount <= Count) - { - const auto LastStatus = InterlockedCompareExchange((volatile size_t*)ConditionVariable, size_t(pWaitBlock), ConditionVariableStatus); + if (MaxWakeCount <= Count) + { + const auto LastStatus = InterlockedCompareExchange((volatile size_t*)ConditionVariable, size_t(pWaitBlock), ConditionVariableStatus); - if (LastStatus == ConditionVariableStatus) - { - break; - } + if (LastStatus == ConditionVariableStatus) + { + break; + } - ConditionVariableStatus = LastStatus; - } - else - { - notify = pBlock->notify; + ConditionVariableStatus = LastStatus; + } + else + { + notify = pBlock->notify; - for (; MaxWakeCount > Count && notify->next;) - { - ++Count; - *ppInsert = notify; - notify->back = nullptr; + for (; MaxWakeCount > Count && notify->next;) + { + ++Count; + *ppInsert = notify; + notify->back = nullptr; - auto next = notify->next; + auto next = notify->next; - pWaitBlock->notify = next; - next->back = nullptr; + pWaitBlock->notify = next; + next->back = nullptr; - ppInsert = ¬ify->back; + ppInsert = ¬ify->back; - notify = next; + notify = next; - } + } - if (MaxWakeCount <= Count) - { - const auto LastStatus = InterlockedCompareExchange((volatile size_t*)ConditionVariable, size_t(pWaitBlock), ConditionVariableStatus); + if (MaxWakeCount <= Count) + { + const auto LastStatus = InterlockedCompareExchange((volatile size_t*)ConditionVariable, size_t(pWaitBlock), ConditionVariableStatus); - if (LastStatus == ConditionVariableStatus) - { - break; - } + if (LastStatus == ConditionVariableStatus) + { + break; + } - ConditionVariableStatus = LastStatus; - } - else - { - const auto LastStatus = InterlockedCompareExchange((volatile size_t*)ConditionVariable, 0, ConditionVariableStatus); + ConditionVariableStatus = LastStatus; + } + else + { + const auto LastStatus = InterlockedCompareExchange((volatile size_t*)ConditionVariable, 0, ConditionVariableStatus); - if (LastStatus == ConditionVariableStatus) - { - *ppInsert = notify; - notify->back = 0; + if (LastStatus == ConditionVariableStatus) + { + *ppInsert = notify; + notify->back = 0; - break; - } + break; + } - ConditionVariableStatus = LastStatus; - } - } - } + ConditionVariableStatus = LastStatus; + } + } + } - for (; pWake;) - { - auto back = pWake->back; + for (; pWake;) + { + auto back = pWake->back; - if (!InterlockedBitTestAndReset((volatile LONG*)&pWake->flag, 1)) - { - if (pWake->SRWLock == nullptr || RtlpQueueWaitBlockToSRWLock(pWake, pWake->SRWLock, (pWake->flag >> 2) & 0x1) == FALSE) - { - pNtReleaseKeyedEvent(GlobalKeyedEventHandle, pWake, 0, nullptr); - } - } + if (!InterlockedBitTestAndReset((volatile LONG*)&pWake->flag, 1)) + { + if (pWake->SRWLock == nullptr || RtlpQueueWaitBlockToSRWLock(pWake, pWake->SRWLock, (pWake->flag >> 2) & 0x1) == FALSE) + { + pNtReleaseKeyedEvent(GlobalKeyedEventHandle, pWake, 0, nullptr); + } + } - pWake = back; - } + pWake = back; + } - return; - } - - static void __fastcall RtlpOptimizeConditionVariableWaitList(PCONDITION_VARIABLE ConditionVariable, size_t ConditionVariableStatus) - { - for (;;) - { - auto pWaitBlock = YY_CV_GET_BLOCK(ConditionVariableStatus); - auto pItem = pWaitBlock; - - for (; pItem->notify == nullptr;) - { - auto temp = pItem; - pItem = pItem->back; - pItem->next = temp; - } - - pWaitBlock->notify = pItem->notify; - - const auto LastStatus = InterlockedCompareExchange((volatile size_t*)ConditionVariable, size_t(pWaitBlock), ConditionVariableStatus); - - if (LastStatus == ConditionVariableStatus) - break; - - ConditionVariableStatus = LastStatus; - - if (ConditionVariableStatus & 7) - { - RtlpWakeConditionVariable(ConditionVariable, ConditionVariableStatus, 0); - return; - } - } - } - - static BOOL __fastcall RtlpWakeSingle(PCONDITION_VARIABLE ConditionVariable, YY_CV_WAIT_BLOCK* pBlock) - { - auto Current = *(volatile size_t*)ConditionVariable; - - for (; Current && (Current & 0x7) != 0x7;) - { - if (Current & 0x8) - { - const auto Last = InterlockedCompareExchange((volatile size_t*)ConditionVariable, Current | 0x7, Current); - - if (Last == Current) - return FALSE; - - Current = Last; - } - else - { - auto New = Current | 0x8; - - auto Last = InterlockedCompareExchange((volatile size_t*)ConditionVariable, New, Current); - - if (Last == Current) - { - Current = New; - - YY_CV_WAIT_BLOCK* notify = nullptr; - BOOL bRet = FALSE; - - auto pWaitBlock = YY_CV_GET_BLOCK(Current); - auto pSuccessor = pWaitBlock; - - if (pWaitBlock) - { - for (; pWaitBlock;) - { - if (pWaitBlock == pBlock) - { - if (notify) - { - pWaitBlock = pWaitBlock->back; - bRet = TRUE; - - notify->back = pWaitBlock; - - if (!pWaitBlock) - break; - - pWaitBlock->next = notify; - } - else - { - auto back = size_t(pWaitBlock->back); - - New = back == 0 ? back : back ^ ((New ^ back) & 0xF); - - Last = InterlockedCompareExchange((volatile size_t*)ConditionVariable, New, Current); - - if (Last == Current) - { - Current = New; - if (back == 0) - return TRUE; - - bRet = TRUE; - } - else - { - Current = Last; - } - - pSuccessor = pWaitBlock = YY_CV_GET_BLOCK(Current); - notify = nullptr; - } - } - else - { - pWaitBlock->next = notify; - notify = pWaitBlock; - pWaitBlock = pWaitBlock->back; - } - } - - if (pSuccessor) - pSuccessor->notify = notify; - } - - RtlpWakeConditionVariable(ConditionVariable, Current, 0); - return bRet; - } - - Current = Last; - } - } - - return FALSE; - } - - - static size_t __fastcall RtlpRunOnceWaitForInit( - size_t Current, - LPINIT_ONCE lpInitOnce - ) - { - auto GlobalKeyedEventHandle = internal::GetGlobalKeyedEventHandle(); - auto pNtWaitForKeyedEvent = try_get_NtWaitForKeyedEvent(); - if (!pNtWaitForKeyedEvent) - internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); - - do - { - const auto Old = Current; - - Current = Current & ~size_t(RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC); - - const auto New = (size_t(&Current) & ~size_t(RTL_RUN_ONCE_ASYNC)) | RTL_RUN_ONCE_CHECK_ONLY; - const auto Last = InterlockedCompareExchange((volatile size_t*)lpInitOnce, New, Old); - if (Last == Old) - { - //WinXP等老系统不支持空句柄传入,此行为不能照搬Windows 7 - pNtWaitForKeyedEvent(GlobalKeyedEventHandle, &Current, 0, nullptr); - - Current = *(volatile size_t*)lpInitOnce; - } - else - { - Current = Last; - } - } while ((Current & (RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)) == RTL_RUN_ONCE_CHECK_ONLY); - - return Current; - } - - static NTSTATUS __fastcall RtlRunOnceBeginInitialize( - _Inout_ LPINIT_ONCE lpInitOnce, - _In_ DWORD dwFlags, - _Outptr_opt_result_maybenull_ LPVOID* lpContext - ) - { - //参数检查 - if ((dwFlags & ~(RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)) || ((dwFlags - 1) & dwFlags)) - { - return STATUS_INVALID_PARAMETER_2; - } - - auto Current = *(volatile size_t*)lpInitOnce; - - if ((Current & (RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)) == RTL_RUN_ONCE_ASYNC) - { - //没有想明白这样做的意图,修改lpInitOnce本身有什么意义? nop? - InterlockedExchange((volatile size_t *)&lpInitOnce, dwFlags); - - if (lpContext) - *lpContext = (LPVOID)(Current & ~size_t(RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)); - - return STATUS_SUCCESS; - } - - if (dwFlags & RTL_RUN_ONCE_CHECK_ONLY) - { - return STATUS_UNSUCCESSFUL; - } - - const auto New = (dwFlags & RTL_RUN_ONCE_ASYNC) | RTL_RUN_ONCE_CHECK_ONLY; - - - - for (;;) - { - const auto InitOnceData = Current & 3; - if (InitOnceData == 0) - { - const auto Last = InterlockedCompareExchange((volatile size_t *)lpInitOnce, New, Current); - if (Last == Current) - return STATUS_PENDING; - - Current = Last; - } - else if (InitOnceData == RTL_RUN_ONCE_CHECK_ONLY) - { - if (dwFlags & RTL_RUN_ONCE_ASYNC) - return STATUS_INVALID_PARAMETER_2; - - Current = RtlpRunOnceWaitForInit(Current, lpInitOnce); - } - else - { - //疑惑?为什么微软要这样判断…… - if (Current != (RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)) - { - if (lpContext) - *lpContext = (LPVOID)(Current & ~size_t(RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)); - - return STATUS_SUCCESS; - } - - return (dwFlags & RTL_RUN_ONCE_ASYNC) ? STATUS_PENDING : STATUS_INVALID_PARAMETER_2; - } - } - } - - - static void __fastcall RtlpRunOnceWakeAll(size_t* pWake) - { - auto GlobalKeyedEventHandle = internal::GetGlobalKeyedEventHandle(); - auto pNtReleaseKeyedEvent = try_get_NtReleaseKeyedEvent(); - if (!pNtReleaseKeyedEvent) - internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); - - for (auto WakeAddress = (LPVOID)(*pWake & ~size_t(RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)); WakeAddress; ) - { - //防止地址无效,我们先保存下 - auto NextWakeAddress = *(LPVOID*)WakeAddress; - - //WinXP等老系统不支持空句柄传入,此行为不能照搬Windows 7 - pNtReleaseKeyedEvent(GlobalKeyedEventHandle, WakeAddress, 0, nullptr); - - WakeAddress = NextWakeAddress; - } - } - - static LSTATUS __fastcall RtlRunOnceComplete( - _Inout_ LPINIT_ONCE lpInitOnce, - _In_ DWORD dwFlags, - _In_opt_ LPVOID lpContext - ) - { - //参数检查无效 或者 同时使用了多个标记位 - if ((dwFlags & ~(RTL_RUN_ONCE_ASYNC | RTL_RUN_ONCE_INIT_FAILED)) || ((dwFlags - 1) & dwFlags)) - { - return STATUS_INVALID_PARAMETER_2; - } - - /* - dwFlags = 0, dwNewFlags = 0x3(RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC) - dwFlags = 0x2, dwNewFlags = 0x2(RTL_RUN_ONCE_ASYNC) - dwFlags = 0x4, dwNewFlags = 0x5(RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_INIT_FAILED) - */ - const auto dwNewFlags = (dwFlags ^ ~(dwFlags >> 1)) & 3 ^ dwFlags; - - if (lpContext && ((dwNewFlags & RTL_RUN_ONCE_ASYNC) == 0 || (size_t(lpContext) & (RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)))) - { - return STATUS_INVALID_PARAMETER_3; - } - - auto Current = *(volatile size_t*)lpInitOnce; - auto New = (size_t(lpContext) & ~size_t(RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)) | (dwNewFlags & RTL_RUN_ONCE_ASYNC); - - switch (Current & (RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)) - { - case RTL_RUN_ONCE_CHECK_ONLY: - if ((dwNewFlags & RTL_RUN_ONCE_CHECK_ONLY) == 0) - { - return STATUS_INVALID_PARAMETER_2; - } - - Current = InterlockedExchange((volatile size_t*)lpInitOnce, New); - if ((Current & (RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)) == RTL_RUN_ONCE_CHECK_ONLY) - { - RtlpRunOnceWakeAll(&Current); - - return STATUS_SUCCESS; - } - - return STATUS_INVALID_OWNER; - break; - case RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC: - if (dwNewFlags & RTL_RUN_ONCE_CHECK_ONLY) - { - return STATUS_INVALID_PARAMETER_2; - } - - if (InterlockedCompareExchange((volatile size_t*)lpInitOnce, New, Current) == Current) - { - return STATUS_SUCCESS; - } - - return STATUS_OBJECT_NAME_COLLISION; - - break; - default: - return STATUS_UNSUCCESSFUL; - break; - } - } + return; + } + + static void __fastcall RtlpOptimizeConditionVariableWaitList(PCONDITION_VARIABLE ConditionVariable, size_t ConditionVariableStatus) + { + for (;;) + { + auto pWaitBlock = YY_CV_GET_BLOCK(ConditionVariableStatus); + auto pItem = pWaitBlock; + + for (; pItem->notify == nullptr;) + { + auto temp = pItem; + pItem = pItem->back; + pItem->next = temp; + } + + pWaitBlock->notify = pItem->notify; + + const auto LastStatus = InterlockedCompareExchange((volatile size_t*)ConditionVariable, size_t(pWaitBlock), ConditionVariableStatus); + + if (LastStatus == ConditionVariableStatus) + break; + + ConditionVariableStatus = LastStatus; + + if (ConditionVariableStatus & 7) + { + RtlpWakeConditionVariable(ConditionVariable, ConditionVariableStatus, 0); + return; + } + } + } + + static BOOL __fastcall RtlpWakeSingle(PCONDITION_VARIABLE ConditionVariable, YY_CV_WAIT_BLOCK* pBlock) + { + auto Current = *(volatile size_t*)ConditionVariable; + + for (; Current && (Current & 0x7) != 0x7;) + { + if (Current & 0x8) + { + const auto Last = InterlockedCompareExchange((volatile size_t*)ConditionVariable, Current | 0x7, Current); + + if (Last == Current) + return FALSE; + + Current = Last; + } + else + { + auto New = Current | 0x8; + + auto Last = InterlockedCompareExchange((volatile size_t*)ConditionVariable, New, Current); + + if (Last == Current) + { + Current = New; + + YY_CV_WAIT_BLOCK* notify = nullptr; + BOOL bRet = FALSE; + + auto pWaitBlock = YY_CV_GET_BLOCK(Current); + auto pSuccessor = pWaitBlock; + + if (pWaitBlock) + { + for (; pWaitBlock;) + { + if (pWaitBlock == pBlock) + { + if (notify) + { + pWaitBlock = pWaitBlock->back; + bRet = TRUE; + + notify->back = pWaitBlock; + + if (!pWaitBlock) + break; + + pWaitBlock->next = notify; + } + else + { + auto back = size_t(pWaitBlock->back); + + New = back == 0 ? back : back ^ ((New ^ back) & 0xF); + + Last = InterlockedCompareExchange((volatile size_t*)ConditionVariable, New, Current); + + if (Last == Current) + { + Current = New; + if (back == 0) + return TRUE; + + bRet = TRUE; + } + else + { + Current = Last; + } + + pSuccessor = pWaitBlock = YY_CV_GET_BLOCK(Current); + notify = nullptr; + } + } + else + { + pWaitBlock->next = notify; + notify = pWaitBlock; + pWaitBlock = pWaitBlock->back; + } + } + + if (pSuccessor) + pSuccessor->notify = notify; + } + + RtlpWakeConditionVariable(ConditionVariable, Current, 0); + return bRet; + } + + Current = Last; + } + } + + return FALSE; + } + + + static size_t __fastcall RtlpRunOnceWaitForInit( + size_t Current, + LPINIT_ONCE lpInitOnce + ) + { + auto GlobalKeyedEventHandle = internal::GetGlobalKeyedEventHandle(); + auto pNtWaitForKeyedEvent = try_get_NtWaitForKeyedEvent(); + if (!pNtWaitForKeyedEvent) + internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); + + do + { + const auto Old = Current; + + Current = Current & ~size_t(RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC); + + const auto New = (size_t(&Current) & ~size_t(RTL_RUN_ONCE_ASYNC)) | RTL_RUN_ONCE_CHECK_ONLY; + const auto Last = InterlockedCompareExchange((volatile size_t*)lpInitOnce, New, Old); + if (Last == Old) + { + //WinXP等老系统不支持空句柄传入,此行为不能照搬Windows 7 + pNtWaitForKeyedEvent(GlobalKeyedEventHandle, &Current, 0, nullptr); + + Current = *(volatile size_t*)lpInitOnce; + } + else + { + Current = Last; + } + } while ((Current & (RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)) == RTL_RUN_ONCE_CHECK_ONLY); + + return Current; + } + + static NTSTATUS __fastcall RtlRunOnceBeginInitialize( + _Inout_ LPINIT_ONCE lpInitOnce, + _In_ DWORD dwFlags, + _Outptr_opt_result_maybenull_ LPVOID* lpContext + ) + { + //参数检查 + if ((dwFlags & ~(RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)) || ((dwFlags - 1) & dwFlags)) + { + return STATUS_INVALID_PARAMETER_2; + } + + auto Current = *(volatile size_t*)lpInitOnce; + + if ((Current & (RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)) == RTL_RUN_ONCE_ASYNC) + { + //没有想明白这样做的意图,修改lpInitOnce本身有什么意义? nop? + InterlockedExchange((volatile size_t *)&lpInitOnce, dwFlags); + + if (lpContext) + *lpContext = (LPVOID)(Current & ~size_t(RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)); + + return STATUS_SUCCESS; + } + + if (dwFlags & RTL_RUN_ONCE_CHECK_ONLY) + { + return STATUS_UNSUCCESSFUL; + } + + const auto New = (dwFlags & RTL_RUN_ONCE_ASYNC) | RTL_RUN_ONCE_CHECK_ONLY; + + + + for (;;) + { + const auto InitOnceData = Current & 3; + if (InitOnceData == 0) + { + const auto Last = InterlockedCompareExchange((volatile size_t *)lpInitOnce, New, Current); + if (Last == Current) + return STATUS_PENDING; + + Current = Last; + } + else if (InitOnceData == RTL_RUN_ONCE_CHECK_ONLY) + { + if (dwFlags & RTL_RUN_ONCE_ASYNC) + return STATUS_INVALID_PARAMETER_2; + + Current = RtlpRunOnceWaitForInit(Current, lpInitOnce); + } + else + { + //疑惑?为什么微软要这样判断…… + if (Current != (RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)) + { + if (lpContext) + *lpContext = (LPVOID)(Current & ~size_t(RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)); + + return STATUS_SUCCESS; + } + + return (dwFlags & RTL_RUN_ONCE_ASYNC) ? STATUS_PENDING : STATUS_INVALID_PARAMETER_2; + } + } + } + + + static void __fastcall RtlpRunOnceWakeAll(size_t* pWake) + { + auto GlobalKeyedEventHandle = internal::GetGlobalKeyedEventHandle(); + auto pNtReleaseKeyedEvent = try_get_NtReleaseKeyedEvent(); + if (!pNtReleaseKeyedEvent) + internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); + + for (auto WakeAddress = (LPVOID)(*pWake & ~size_t(RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)); WakeAddress; ) + { + //防止地址无效,我们先保存下 + auto NextWakeAddress = *(LPVOID*)WakeAddress; + + //WinXP等老系统不支持空句柄传入,此行为不能照搬Windows 7 + pNtReleaseKeyedEvent(GlobalKeyedEventHandle, WakeAddress, 0, nullptr); + + WakeAddress = NextWakeAddress; + } + } + + static LSTATUS __fastcall RtlRunOnceComplete( + _Inout_ LPINIT_ONCE lpInitOnce, + _In_ DWORD dwFlags, + _In_opt_ LPVOID lpContext + ) + { + //参数检查无效 或者 同时使用了多个标记位 + if ((dwFlags & ~(RTL_RUN_ONCE_ASYNC | RTL_RUN_ONCE_INIT_FAILED)) || ((dwFlags - 1) & dwFlags)) + { + return STATUS_INVALID_PARAMETER_2; + } + + /* + dwFlags = 0, dwNewFlags = 0x3(RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC) + dwFlags = 0x2, dwNewFlags = 0x2(RTL_RUN_ONCE_ASYNC) + dwFlags = 0x4, dwNewFlags = 0x5(RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_INIT_FAILED) + */ + const auto dwNewFlags = (dwFlags ^ ~(dwFlags >> 1)) & 3 ^ dwFlags; + + if (lpContext && ((dwNewFlags & RTL_RUN_ONCE_ASYNC) == 0 || (size_t(lpContext) & (RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)))) + { + return STATUS_INVALID_PARAMETER_3; + } + + auto Current = *(volatile size_t*)lpInitOnce; + auto New = (size_t(lpContext) & ~size_t(RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)) | (dwNewFlags & RTL_RUN_ONCE_ASYNC); + + switch (Current & (RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)) + { + case RTL_RUN_ONCE_CHECK_ONLY: + if ((dwNewFlags & RTL_RUN_ONCE_CHECK_ONLY) == 0) + { + return STATUS_INVALID_PARAMETER_2; + } + + Current = InterlockedExchange((volatile size_t*)lpInitOnce, New); + if ((Current & (RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC)) == RTL_RUN_ONCE_CHECK_ONLY) + { + RtlpRunOnceWakeAll(&Current); + + return STATUS_SUCCESS; + } + + return STATUS_INVALID_OWNER; + break; + case RTL_RUN_ONCE_CHECK_ONLY | RTL_RUN_ONCE_ASYNC: + if (dwNewFlags & RTL_RUN_ONCE_CHECK_ONLY) + { + return STATUS_INVALID_PARAMETER_2; + } + + if (InterlockedCompareExchange((volatile size_t*)lpInitOnce, New, Current) == Current) + { + return STATUS_SUCCESS; + } + + return STATUS_OBJECT_NAME_COLLISION; + + break; + default: + return STATUS_UNSUCCESSFUL; + break; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - static auto __fastcall GetBlockByWaitOnAddressHashTable(LPVOID Address) - { - static volatile ULONG_PTR WaitOnAddressHashTable[128]; +#if (YY_Thunks_Target < __WindowsNT6_2) + static auto __fastcall GetBlockByWaitOnAddressHashTable(LPVOID Address) + { + static volatile ULONG_PTR WaitOnAddressHashTable[128]; - const auto Index = (size_t(Address) >> 5) & 0x7F; + const auto Index = (size_t(Address) >> 5) & 0x7F; - return &WaitOnAddressHashTable[Index]; - } + return &WaitOnAddressHashTable[Index]; + } - static void __fastcall RtlpWaitOnAddressWakeEntireList(YY_ADDRESS_WAIT_BLOCK* pBlock) - { - auto GlobalKeyedEventHandle = GetGlobalKeyedEventHandle(); - auto pNtReleaseKeyedEvent = try_get_NtReleaseKeyedEvent(); - if (!pNtReleaseKeyedEvent) - internal::RaiseStatus(STATUS_NOT_FOUND); + static void __fastcall RtlpWaitOnAddressWakeEntireList(YY_ADDRESS_WAIT_BLOCK* pBlock) + { + auto GlobalKeyedEventHandle = GetGlobalKeyedEventHandle(); + auto pNtReleaseKeyedEvent = try_get_NtReleaseKeyedEvent(); + if (!pNtReleaseKeyedEvent) + internal::RaiseStatus(STATUS_NOT_FOUND); - for (; pBlock;) - { - auto Tmp = pBlock->back; + for (; pBlock;) + { + auto Tmp = pBlock->back; - if (InterlockedExchange(&pBlock->flag, 2) == 0) - { - pNtReleaseKeyedEvent(GlobalKeyedEventHandle, pBlock, 0, nullptr); - } + if (InterlockedExchange(&pBlock->flag, 2) == 0) + { + pNtReleaseKeyedEvent(GlobalKeyedEventHandle, pBlock, 0, nullptr); + } - pBlock = Tmp; - } - } + pBlock = Tmp; + } + } - static void __fastcall RtlpOptimizeWaitOnAddressWaitList(volatile ULONG_PTR* ppFirstBlock) - { - auto Current = *ppFirstBlock; - - for (;;) - { - auto pBlock = YY_ADDRESS_GET_BLOCK(Current); - - for (auto pItem = pBlock;;) - { - if (pItem->next != nullptr) - { - pBlock->next = pItem->next; - break; - } - - auto Tmp = pItem; - pItem = pItem->back; - pItem->notify = Tmp; - } - - const auto Last = InterlockedCompareExchange(ppFirstBlock, (Current & 1) == 0 ? size_t(pBlock) : 0, Current); + static void __fastcall RtlpOptimizeWaitOnAddressWaitList(volatile ULONG_PTR* ppFirstBlock) + { + auto Current = *ppFirstBlock; + + for (;;) + { + auto pBlock = YY_ADDRESS_GET_BLOCK(Current); + + for (auto pItem = pBlock;;) + { + if (pItem->next != nullptr) + { + pBlock->next = pItem->next; + break; + } + + auto Tmp = pItem; + pItem = pItem->back; + pItem->notify = Tmp; + } + + const auto Last = InterlockedCompareExchange(ppFirstBlock, (Current & 1) == 0 ? size_t(pBlock) : 0, Current); - if (Last == Current) - { - if(Current & 1) - { - RtlpWaitOnAddressWakeEntireList(pBlock); - } - - return; - } + if (Last == Current) + { + if(Current & 1) + { + RtlpWaitOnAddressWakeEntireList(pBlock); + } + + return; + } - Current = Last; - } - } + Current = Last; + } + } - static void __fastcall RtlpAddWaitBlockToWaitList(YY_ADDRESS_WAIT_BLOCK* pWaitBlock) - { - auto ppFirstBlock = GetBlockByWaitOnAddressHashTable((LPVOID)pWaitBlock->Address); + static void __fastcall RtlpAddWaitBlockToWaitList(YY_ADDRESS_WAIT_BLOCK* pWaitBlock) + { + auto ppFirstBlock = GetBlockByWaitOnAddressHashTable((LPVOID)pWaitBlock->Address); - auto Current = *ppFirstBlock; + auto Current = *ppFirstBlock; - for (;;) - { - auto New = size_t(pWaitBlock) | (size_t(Current) & 0x3); + for (;;) + { + auto New = size_t(pWaitBlock) | (size_t(Current) & 0x3); - auto back = YY_ADDRESS_GET_BLOCK(Current); - pWaitBlock->back = back; - if (back) - { - New |= 0x2; + auto back = YY_ADDRESS_GET_BLOCK(Current); + pWaitBlock->back = back; + if (back) + { + New |= 0x2; - pWaitBlock->next = nullptr; - } - else - { - pWaitBlock->next = pWaitBlock; - } + pWaitBlock->next = nullptr; + } + else + { + pWaitBlock->next = pWaitBlock; + } - const auto Last = InterlockedCompareExchange(ppFirstBlock, New, Current); - - if (Last == Current) - { - //0x2状态发生变化 才需要重新优化锁。 - if ((Current ^ New) & 0x2) - { - RtlpOptimizeWaitOnAddressWaitList(ppFirstBlock); - } - - return; - } - - Current = Last; - } - } - - static NTSTATUS __fastcall RtlpWaitOnAddressWithTimeout(YY_ADDRESS_WAIT_BLOCK* pWaitBlock, LARGE_INTEGER *TimeOut); - - static void __fastcall RtlpWaitOnAddressRemoveWaitBlock(YY_ADDRESS_WAIT_BLOCK* pWaitBlock) - { - auto GlobalKeyedEventHandle = GetGlobalKeyedEventHandle(); - auto pNtWaitForKeyedEvent = try_get_NtWaitForKeyedEvent(); - if (!pNtWaitForKeyedEvent) - internal::RaiseStatus(STATUS_NOT_FOUND); - - auto ppFirstBlock = GetBlockByWaitOnAddressHashTable((LPVOID)pWaitBlock->Address); + const auto Last = InterlockedCompareExchange(ppFirstBlock, New, Current); + + if (Last == Current) + { + //0x2状态发生变化 才需要重新优化锁。 + if ((Current ^ New) & 0x2) + { + RtlpOptimizeWaitOnAddressWaitList(ppFirstBlock); + } + + return; + } + + Current = Last; + } + } + + static NTSTATUS __fastcall RtlpWaitOnAddressWithTimeout(YY_ADDRESS_WAIT_BLOCK* pWaitBlock, LARGE_INTEGER *TimeOut); + + static void __fastcall RtlpWaitOnAddressRemoveWaitBlock(YY_ADDRESS_WAIT_BLOCK* pWaitBlock) + { + auto GlobalKeyedEventHandle = GetGlobalKeyedEventHandle(); + auto pNtWaitForKeyedEvent = try_get_NtWaitForKeyedEvent(); + if (!pNtWaitForKeyedEvent) + internal::RaiseStatus(STATUS_NOT_FOUND); + + auto ppFirstBlock = GetBlockByWaitOnAddressHashTable((LPVOID)pWaitBlock->Address); - auto Current = *ppFirstBlock; - size_t Last; + auto Current = *ppFirstBlock; + size_t Last; - for (; Current; Current = Last) - { - if (Current & 2) - { - Last = InterlockedCompareExchange(ppFirstBlock, Current | 1, Current); + for (; Current; Current = Last) + { + if (Current & 2) + { + Last = InterlockedCompareExchange(ppFirstBlock, Current | 1, Current); - if (Last == Current) - { - break; - } - } - else - { - auto New = Current | 0x2; - Last = InterlockedCompareExchange(ppFirstBlock, New, Current); + if (Last == Current) + { + break; + } + } + else + { + auto New = Current | 0x2; + Last = InterlockedCompareExchange(ppFirstBlock, New, Current); - if (Last == Current) - { - Current = New; + if (Last == Current) + { + Current = New; - bool bFind = false; + bool bFind = false; - //同步成功! - auto pBlock = YY_ADDRESS_GET_BLOCK(New); - auto pItem = pBlock; + //同步成功! + auto pBlock = YY_ADDRESS_GET_BLOCK(New); + auto pItem = pBlock; - auto pNotify = pBlock->notify; - YY_ADDRESS_WAIT_BLOCK* Tmp; + auto pNotify = pBlock->notify; + YY_ADDRESS_WAIT_BLOCK* Tmp; - do - { - Tmp = pBlock->back; - - if (pBlock != pWaitBlock) - { - pBlock->notify = pNotify; - pNotify = pBlock; + do + { + Tmp = pBlock->back; + + if (pBlock != pWaitBlock) + { + pBlock->notify = pNotify; + pNotify = pBlock; - pBlock = Tmp; - Tmp = pItem; - continue; - } - - bFind = true; - - - if (pBlock != pItem) - { - pNotify->back = Tmp; - if (Tmp) - Tmp->notify = pNotify; - else - pNotify->next = pNotify; - - pBlock = Tmp; - Tmp = pItem; - continue; - } - - New = size_t(pBlock->back); - if (Tmp) - { - New = size_t(Tmp) ^ (Current ^ size_t(Tmp)) & 0x3; - } - - Last = InterlockedCompareExchange(ppFirstBlock, New, Current); - - if (Last == Current) - { - if (New == 0) - return; - - Tmp->notify = nullptr; - pBlock = Tmp; - } - else - { - Current = Last; - - Tmp = pBlock = YY_ADDRESS_GET_BLOCK(Current); - pNotify = pBlock->notify; - } - - - pItem = Tmp; - } while (pBlock); - - - if (bFind == false && InterlockedExchange(&pWaitBlock->flag, 0) != 2) - { - pNtWaitForKeyedEvent(GlobalKeyedEventHandle, pWaitBlock, 0, nullptr); - } - - Tmp->next = pNotify; - - for (;;) - { - const auto Last = InterlockedCompareExchange(ppFirstBlock, (Current & 1) == 0 ? size_t(YY_ADDRESS_GET_BLOCK(Current)) : 0, Current); - - if (Last == Current) - break; - - Current = Last; - } - - if (Current & 1) - RtlpWaitOnAddressWakeEntireList(YY_ADDRESS_GET_BLOCK(Current)); - - - return; - } - } - } - - if (InterlockedExchange(&pWaitBlock->flag, 1) == 2) - return; - - RtlpWaitOnAddressWithTimeout(pWaitBlock, 0); - } - - static NTSTATUS __fastcall RtlpWaitOnAddressWithTimeout(YY_ADDRESS_WAIT_BLOCK* pWaitBlock, LARGE_INTEGER *TimeOut) - { - //单核 我们无需自旋,直接进入等待过程即可 - if (NtCurrentTeb()->ProcessEnvironmentBlock->NumberOfProcessors > 1 && RtlpWaitOnAddressSpinCount) - { - for (DWORD SpinCount = 0; SpinCount < RtlpWaitOnAddressSpinCount;++SpinCount) - { - if ((pWaitBlock->flag & 1) == 0) - { - //自旋过程中,等到了信号改变 - return STATUS_SUCCESS; - } - - YieldProcessor(); - } - } - - if (!_interlockedbittestandreset((volatile long *)&pWaitBlock->flag, 0)) - { - //本来我是拒绝的,但是运气好,状态已经发生了反转 - return STATUS_SUCCESS; - } - - auto GlobalKeyedEventHandle = GetGlobalKeyedEventHandle(); - auto pNtWaitForKeyedEvent = try_get_NtWaitForKeyedEvent(); - if (!pNtWaitForKeyedEvent) - internal::RaiseStatus(STATUS_NOT_FOUND); - - auto Status = pNtWaitForKeyedEvent(GlobalKeyedEventHandle, pWaitBlock, 0, TimeOut); - - if (Status == STATUS_TIMEOUT) - { - if (InterlockedExchange(&pWaitBlock->flag, 4) == 2) - { - Status = pNtWaitForKeyedEvent(GlobalKeyedEventHandle, pWaitBlock, 0, nullptr); - } - else - { - RtlpWaitOnAddressRemoveWaitBlock(pWaitBlock); - } - } - - return Status; - } + pBlock = Tmp; + Tmp = pItem; + continue; + } + + bFind = true; + + + if (pBlock != pItem) + { + pNotify->back = Tmp; + if (Tmp) + Tmp->notify = pNotify; + else + pNotify->next = pNotify; + + pBlock = Tmp; + Tmp = pItem; + continue; + } + + New = size_t(pBlock->back); + if (Tmp) + { + New = size_t(Tmp) ^ (Current ^ size_t(Tmp)) & 0x3; + } + + Last = InterlockedCompareExchange(ppFirstBlock, New, Current); + + if (Last == Current) + { + if (New == 0) + return; + + Tmp->notify = nullptr; + pBlock = Tmp; + } + else + { + Current = Last; + + Tmp = pBlock = YY_ADDRESS_GET_BLOCK(Current); + pNotify = pBlock->notify; + } + + + pItem = Tmp; + } while (pBlock); + + + if (bFind == false && InterlockedExchange(&pWaitBlock->flag, 0) != 2) + { + pNtWaitForKeyedEvent(GlobalKeyedEventHandle, pWaitBlock, 0, nullptr); + } + + Tmp->next = pNotify; + + for (;;) + { + const auto Last = InterlockedCompareExchange(ppFirstBlock, (Current & 1) == 0 ? size_t(YY_ADDRESS_GET_BLOCK(Current)) : 0, Current); + + if (Last == Current) + break; + + Current = Last; + } + + if (Current & 1) + RtlpWaitOnAddressWakeEntireList(YY_ADDRESS_GET_BLOCK(Current)); + + + return; + } + } + } + + if (InterlockedExchange(&pWaitBlock->flag, 1) == 2) + return; + + RtlpWaitOnAddressWithTimeout(pWaitBlock, 0); + } + + static NTSTATUS __fastcall RtlpWaitOnAddressWithTimeout(YY_ADDRESS_WAIT_BLOCK* pWaitBlock, LARGE_INTEGER *TimeOut) + { + //单核 我们无需自旋,直接进入等待过程即可 + if (NtCurrentTeb()->ProcessEnvironmentBlock->NumberOfProcessors > 1 && RtlpWaitOnAddressSpinCount) + { + for (DWORD SpinCount = 0; SpinCount < RtlpWaitOnAddressSpinCount;++SpinCount) + { + if ((pWaitBlock->flag & 1) == 0) + { + //自旋过程中,等到了信号改变 + return STATUS_SUCCESS; + } + + YieldProcessor(); + } + } + + if (!_interlockedbittestandreset((volatile long *)&pWaitBlock->flag, 0)) + { + //本来我是拒绝的,但是运气好,状态已经发生了反转 + return STATUS_SUCCESS; + } + + auto GlobalKeyedEventHandle = GetGlobalKeyedEventHandle(); + auto pNtWaitForKeyedEvent = try_get_NtWaitForKeyedEvent(); + if (!pNtWaitForKeyedEvent) + internal::RaiseStatus(STATUS_NOT_FOUND); + + auto Status = pNtWaitForKeyedEvent(GlobalKeyedEventHandle, pWaitBlock, 0, TimeOut); + + if (Status == STATUS_TIMEOUT) + { + if (InterlockedExchange(&pWaitBlock->flag, 4) == 2) + { + Status = pNtWaitForKeyedEvent(GlobalKeyedEventHandle, pWaitBlock, 0, nullptr); + } + else + { + RtlpWaitOnAddressRemoveWaitBlock(pWaitBlock); + } + } + + return Status; + } #if defined(_X86_) - #define RtlpWakeByAddress(Address, bWakeAll) YY_RtlpWakeByAddress(0, bWakeAll, Address) - static void __fastcall YY_RtlpWakeByAddress(DWORD dwReserved/*用于平衡栈需要,利于编译器优化成jmp*/, BOOL bWakeAll, LPVOID Address) + #define RtlpWakeByAddress(Address, bWakeAll) YY_RtlpWakeByAddress(0, bWakeAll, Address) + static void __fastcall YY_RtlpWakeByAddress(DWORD dwReserved/*用于平衡栈需要,利于编译器优化成jmp*/, BOOL bWakeAll, LPVOID Address) #else - static void __fastcall RtlpWakeByAddress(LPVOID Address, BOOL bWakeAll) + static void __fastcall RtlpWakeByAddress(LPVOID Address, BOOL bWakeAll) #endif - { - auto ppFirstBlock = GetBlockByWaitOnAddressHashTable(Address); - YY_ADDRESS_WAIT_BLOCK* LastWake = nullptr; - - auto Current = *ppFirstBlock; - size_t Last; - bool bNoRemove = false; - - for (; Current && (Current & 1) ==0; Current = Last) - { - if (Current & 2) - { - Last = InterlockedCompareExchange(ppFirstBlock, Current | 1, Current); - - if (Last == Current) - { - return; - } - } - else - { - auto New = Current | 0x2; - Last = InterlockedCompareExchange(ppFirstBlock, New, Current); - - if (Last == Current) - { - Current = New; - - __retry: - - - auto pBlock = YY_ADDRESS_GET_BLOCK(Current); - auto pItem = pBlock; - - for (; pItem->next == nullptr;) - { - auto Tmp = pItem; - pItem = pItem->back; - pItem->notify = Tmp; - } - - pItem = pItem->next; - pBlock->next = pItem; - - for (; pItem;) - { - auto notify = pItem->notify; - - if (pItem->Address == Address) - { - auto back = pItem->back; - if (pItem == pBlock) - { - New = size_t(back); - if (New) - { - New = (Current ^ New) & 3 ^ New; - } - - Last = InterlockedCompareExchange(ppFirstBlock, New, Current); - - - if (Last != Current) - { - //换个姿势,再来一次 - Current = Last; - goto __retry; - } - - pBlock = YY_ADDRESS_GET_BLOCK(Last); - - bNoRemove = New == 0; - if (back) - { - back->notify = nullptr; - back->next = pItem->next; - } - } - else - { - notify->back = back; - back = pItem->back; - auto notify = pItem->notify; - - if (back) - { - back->notify = notify; - } - else - { - pBlock->next = notify; - notify->next = notify; - } - } - - const auto LastFlag = InterlockedExchange(&pItem->flag, 2); - - if (LastFlag != 2) - { - if (LastFlag == 0) - { - pItem->back = LastWake; - LastWake = pItem; - } - - if (!bWakeAll) - break; - } - } - - pItem = notify; - } - - auto GlobalKeyedEventHandle = GetGlobalKeyedEventHandle(); - auto pNtReleaseKeyedEvent = try_get_NtReleaseKeyedEvent(); - if (!pNtReleaseKeyedEvent) - internal::RaiseStatus(STATUS_NOT_FOUND); - - for (auto pItem = LastWake; pItem;) - { - //NtReleaseKeyedEvent 调用后 pItem 内存块可能无效,因此必须先保存一份。 - auto Tmp = pItem->back; - - //唤醒等待的Key - pNtReleaseKeyedEvent(GlobalKeyedEventHandle, pItem, FALSE, nullptr); - - pItem = Tmp; - } - - if (!bNoRemove) - { - //更新标头块 - - - for (auto Current = *ppFirstBlock;;) - { - const auto Last = InterlockedCompareExchange(ppFirstBlock, (Current & 1) == 0 ? size_t(YY_ADDRESS_GET_BLOCK(Current)) : 0, Current); - - if (Last == Current) - { - if(Current & 1) - RtlpWaitOnAddressWakeEntireList(YY_ADDRESS_GET_BLOCK(Current)); - - break; - } - - Current = Last; - } - } - - return; - } - } - } - - } + { + auto ppFirstBlock = GetBlockByWaitOnAddressHashTable(Address); + YY_ADDRESS_WAIT_BLOCK* LastWake = nullptr; + + auto Current = *ppFirstBlock; + size_t Last; + bool bNoRemove = false; + + for (; Current && (Current & 1) ==0; Current = Last) + { + if (Current & 2) + { + Last = InterlockedCompareExchange(ppFirstBlock, Current | 1, Current); + + if (Last == Current) + { + return; + } + } + else + { + auto New = Current | 0x2; + Last = InterlockedCompareExchange(ppFirstBlock, New, Current); + + if (Last == Current) + { + Current = New; + + __retry: + + + auto pBlock = YY_ADDRESS_GET_BLOCK(Current); + auto pItem = pBlock; + + for (; pItem->next == nullptr;) + { + auto Tmp = pItem; + pItem = pItem->back; + pItem->notify = Tmp; + } + + pItem = pItem->next; + pBlock->next = pItem; + + for (; pItem;) + { + auto notify = pItem->notify; + + if (pItem->Address == Address) + { + auto back = pItem->back; + if (pItem == pBlock) + { + New = size_t(back); + if (New) + { + New = (Current ^ New) & 3 ^ New; + } + + Last = InterlockedCompareExchange(ppFirstBlock, New, Current); + + + if (Last != Current) + { + //换个姿势,再来一次 + Current = Last; + goto __retry; + } + + pBlock = YY_ADDRESS_GET_BLOCK(Last); + + bNoRemove = New == 0; + if (back) + { + back->notify = nullptr; + back->next = pItem->next; + } + } + else + { + notify->back = back; + back = pItem->back; + auto notify = pItem->notify; + + if (back) + { + back->notify = notify; + } + else + { + pBlock->next = notify; + notify->next = notify; + } + } + + const auto LastFlag = InterlockedExchange(&pItem->flag, 2); + + if (LastFlag != 2) + { + if (LastFlag == 0) + { + pItem->back = LastWake; + LastWake = pItem; + } + + if (!bWakeAll) + break; + } + } + + pItem = notify; + } + + auto GlobalKeyedEventHandle = GetGlobalKeyedEventHandle(); + auto pNtReleaseKeyedEvent = try_get_NtReleaseKeyedEvent(); + if (!pNtReleaseKeyedEvent) + internal::RaiseStatus(STATUS_NOT_FOUND); + + for (auto pItem = LastWake; pItem;) + { + //NtReleaseKeyedEvent 调用后 pItem 内存块可能无效,因此必须先保存一份。 + auto Tmp = pItem->back; + + //唤醒等待的Key + pNtReleaseKeyedEvent(GlobalKeyedEventHandle, pItem, FALSE, nullptr); + + pItem = Tmp; + } + + if (!bNoRemove) + { + //更新标头块 + + + for (auto Current = *ppFirstBlock;;) + { + const auto Last = InterlockedCompareExchange(ppFirstBlock, (Current & 1) == 0 ? size_t(YY_ADDRESS_GET_BLOCK(Current)) : 0, Current); + + if (Last == Current) + { + if(Current & 1) + RtlpWaitOnAddressWakeEntireList(YY_ADDRESS_GET_BLOCK(Current)); + + break; + } + + Current = Last; + } + } + + return; + } + } + } + + } #endif - } + } } #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - kernel32, - 12, - BOOL, - WINAPI, - InitializeCriticalSectionEx, - _Out_ LPCRITICAL_SECTION lpCriticalSection, - _In_ DWORD dwSpinCount, - _In_ DWORD Flags - ) - { - if (auto const pInitializeCriticalSectionEx = try_get_InitializeCriticalSectionEx()) - { - return pInitializeCriticalSectionEx(lpCriticalSection, dwSpinCount, Flags); - } - - return InitializeCriticalSectionAndSpinCount(lpCriticalSection, dwSpinCount); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + kernel32, + 12, + BOOL, + WINAPI, + InitializeCriticalSectionEx, + _Out_ LPCRITICAL_SECTION lpCriticalSection, + _In_ DWORD dwSpinCount, + _In_ DWORD Flags + ) + { + if (auto const pInitializeCriticalSectionEx = try_get_InitializeCriticalSectionEx()) + { + return pInitializeCriticalSectionEx(lpCriticalSection, dwSpinCount, Flags); + } + + return InitializeCriticalSectionAndSpinCount(lpCriticalSection, dwSpinCount); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - InitOnceInitialize, - _Out_ PINIT_ONCE InitOnce - ) - { - *InitOnce = INIT_ONCE_STATIC_INIT; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + InitOnceInitialize, + _Out_ PINIT_ONCE InitOnce + ) + { + *InitOnce = INIT_ONCE_STATIC_INIT; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 16, - _Success_(return) - BOOL, - WINAPI, - InitOnceBeginInitialize, - _Inout_ LPINIT_ONCE lpInitOnce, - _In_ DWORD dwFlags, - _Out_ PBOOL fPending, - _Outptr_opt_result_maybenull_ LPVOID* lpContext - ) - { - if (auto const pInitOnceBeginInitialize = try_get_InitOnceBeginInitialize()) - { - return pInitOnceBeginInitialize(lpInitOnce, dwFlags, fPending, lpContext); - } - - auto Status = internal::RtlRunOnceBeginInitialize(lpInitOnce, dwFlags, lpContext); - - if (Status >= STATUS_SUCCESS) - { - *fPending = Status == STATUS_PENDING; - return TRUE; - } - else - { - internal::BaseSetLastNTError(Status); - return FALSE; - } - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 16, + _Success_(return) + BOOL, + WINAPI, + InitOnceBeginInitialize, + _Inout_ LPINIT_ONCE lpInitOnce, + _In_ DWORD dwFlags, + _Out_ PBOOL fPending, + _Outptr_opt_result_maybenull_ LPVOID* lpContext + ) + { + if (auto const pInitOnceBeginInitialize = try_get_InitOnceBeginInitialize()) + { + return pInitOnceBeginInitialize(lpInitOnce, dwFlags, fPending, lpContext); + } + + auto Status = internal::RtlRunOnceBeginInitialize(lpInitOnce, dwFlags, lpContext); + + if (Status >= STATUS_SUCCESS) + { + *fPending = Status == STATUS_PENDING; + return TRUE; + } + else + { + internal::BaseSetLastNTError(Status); + return FALSE; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 12, - BOOL, - WINAPI, - InitOnceComplete, - _Inout_ LPINIT_ONCE lpInitOnce, - _In_ DWORD dwFlags, - _In_opt_ LPVOID lpContext - ) - { - if (auto const pInitOnceComplete = try_get_InitOnceComplete()) - { - return pInitOnceComplete(lpInitOnce, dwFlags, lpContext); - } - - auto Status = internal::RtlRunOnceComplete(lpInitOnce, dwFlags, lpContext); - - if (Status >= 0) - { - return TRUE; - } - else - { - internal::BaseSetLastNTError(Status); - return FALSE; - } - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 12, + BOOL, + WINAPI, + InitOnceComplete, + _Inout_ LPINIT_ONCE lpInitOnce, + _In_ DWORD dwFlags, + _In_opt_ LPVOID lpContext + ) + { + if (auto const pInitOnceComplete = try_get_InitOnceComplete()) + { + return pInitOnceComplete(lpInitOnce, dwFlags, lpContext); + } + + auto Status = internal::RtlRunOnceComplete(lpInitOnce, dwFlags, lpContext); + + if (Status >= 0) + { + return TRUE; + } + else + { + internal::BaseSetLastNTError(Status); + return FALSE; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - InitOnceExecuteOnce, - _Inout_ PINIT_ONCE InitOnce, - _In_ __callback PINIT_ONCE_FN InitFn, - _Inout_opt_ PVOID Parameter, - _Outptr_opt_result_maybenull_ LPVOID* Context - ) - { - if (auto const pInitOnceExecuteOnce = try_get_InitOnceExecuteOnce()) - { - return pInitOnceExecuteOnce(InitOnce, InitFn, Parameter, Context); - } - - auto Status = internal::RtlRunOnceBeginInitialize(InitOnce, 0, Context); - - ULONG_PTR ExceptionArgument; - - do - { - if (Status < STATUS_SUCCESS) - { - ExceptionArgument = 0; - } - else if (Status == STATUS_PENDING) - { - if (InitFn(InitOnce, Parameter, Context)) - { - auto NewContext = Context; - if (NewContext) - NewContext = (LPVOID*)*NewContext; - - Status = internal::RtlRunOnceComplete(InitOnce, 0, NewContext); - - if (Status >= STATUS_SUCCESS) - break; - - ExceptionArgument = 1; - } - else - { - Status = internal::RtlRunOnceComplete(InitOnce, RTL_RUN_ONCE_INIT_FAILED, nullptr); - if (Status >= STATUS_SUCCESS) - { - Status = STATUS_UNSUCCESSFUL; - break; - } - ExceptionArgument = 2; - } - } - else - { - break; - } - - RaiseException(Status, EXCEPTION_NONCONTINUABLE, 1, &ExceptionArgument); - - } while (false); - - //别问我为什么不设置LastError……,Windows 7的这个函数也没设置 LastError,既然这样,我们都偷懒下吧,行为跟微软保持一致。 - return Status >= STATUS_SUCCESS; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + InitOnceExecuteOnce, + _Inout_ PINIT_ONCE InitOnce, + _In_ __callback PINIT_ONCE_FN InitFn, + _Inout_opt_ PVOID Parameter, + _Outptr_opt_result_maybenull_ LPVOID* Context + ) + { + if (auto const pInitOnceExecuteOnce = try_get_InitOnceExecuteOnce()) + { + return pInitOnceExecuteOnce(InitOnce, InitFn, Parameter, Context); + } + + auto Status = internal::RtlRunOnceBeginInitialize(InitOnce, 0, Context); + + ULONG_PTR ExceptionArgument; + + do + { + if (Status < STATUS_SUCCESS) + { + ExceptionArgument = 0; + } + else if (Status == STATUS_PENDING) + { + if (InitFn(InitOnce, Parameter, Context)) + { + auto NewContext = Context; + if (NewContext) + NewContext = (LPVOID*)*NewContext; + + Status = internal::RtlRunOnceComplete(InitOnce, 0, NewContext); + + if (Status >= STATUS_SUCCESS) + break; + + ExceptionArgument = 1; + } + else + { + Status = internal::RtlRunOnceComplete(InitOnce, RTL_RUN_ONCE_INIT_FAILED, nullptr); + if (Status >= STATUS_SUCCESS) + { + Status = STATUS_UNSUCCESSFUL; + break; + } + ExceptionArgument = 2; + } + } + else + { + break; + } + + RaiseException(Status, EXCEPTION_NONCONTINUABLE, 1, &ExceptionArgument); + + } while (false); + + //别问我为什么不设置LastError……,Windows 7的这个函数也没设置 LastError,既然这样,我们都偷懒下吧,行为跟微软保持一致。 + return Status >= STATUS_SUCCESS; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 16, - HANDLE, - WINAPI, - CreateEventExW, - _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes, - _In_opt_ LPCWSTR lpName, - _In_ DWORD dwFlags, - _In_ DWORD dwDesiredAccess - ) - { - if (auto pCreateEventExW = try_get_CreateEventExW()) - { - return pCreateEventExW(lpEventAttributes, lpName, dwFlags, dwDesiredAccess); - } - - return CreateEventW(lpEventAttributes, dwFlags & CREATE_EVENT_MANUAL_RESET, dwFlags & CREATE_EVENT_INITIAL_SET, lpName); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 16, + HANDLE, + WINAPI, + CreateEventExW, + _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes, + _In_opt_ LPCWSTR lpName, + _In_ DWORD dwFlags, + _In_ DWORD dwDesiredAccess + ) + { + if (auto pCreateEventExW = try_get_CreateEventExW()) + { + return pCreateEventExW(lpEventAttributes, lpName, dwFlags, dwDesiredAccess); + } + + return CreateEventW(lpEventAttributes, dwFlags & CREATE_EVENT_MANUAL_RESET, dwFlags & CREATE_EVENT_INITIAL_SET, lpName); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 16, - HANDLE, - WINAPI, - CreateEventExA, - _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes, - _In_opt_ LPCSTR lpName, - _In_ DWORD dwFlags, - _In_ DWORD dwDesiredAccess - ) - { - if (auto pCreateEventExA = try_get_CreateEventExA()) - { - return pCreateEventExA(lpEventAttributes, lpName, dwFlags, dwDesiredAccess); - } - - return CreateEventA(lpEventAttributes, dwFlags & CREATE_EVENT_MANUAL_RESET, dwFlags & CREATE_EVENT_INITIAL_SET, lpName); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 16, + HANDLE, + WINAPI, + CreateEventExA, + _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes, + _In_opt_ LPCSTR lpName, + _In_ DWORD dwFlags, + _In_ DWORD dwDesiredAccess + ) + { + if (auto pCreateEventExA = try_get_CreateEventExA()) + { + return pCreateEventExA(lpEventAttributes, lpName, dwFlags, dwDesiredAccess); + } + + return CreateEventA(lpEventAttributes, dwFlags & CREATE_EVENT_MANUAL_RESET, dwFlags & CREATE_EVENT_INITIAL_SET, lpName); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 16, - HANDLE, - WINAPI, - CreateMutexExW, - _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes, - _In_opt_ LPCWSTR lpName, - _In_ DWORD dwFlags, - _In_ DWORD dwDesiredAccess - ) - { - if (auto pCreateMutexExW = try_get_CreateMutexExW()) - { - return pCreateMutexExW(lpMutexAttributes, lpName, dwFlags, dwDesiredAccess); - } - - return CreateMutexW(lpMutexAttributes, dwFlags & CREATE_MUTEX_INITIAL_OWNER, lpName); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 16, + HANDLE, + WINAPI, + CreateMutexExW, + _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes, + _In_opt_ LPCWSTR lpName, + _In_ DWORD dwFlags, + _In_ DWORD dwDesiredAccess + ) + { + if (auto pCreateMutexExW = try_get_CreateMutexExW()) + { + return pCreateMutexExW(lpMutexAttributes, lpName, dwFlags, dwDesiredAccess); + } + + return CreateMutexW(lpMutexAttributes, dwFlags & CREATE_MUTEX_INITIAL_OWNER, lpName); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 16, - HANDLE, - WINAPI, - CreateMutexExA, - _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes, - _In_opt_ LPCSTR lpName, - _In_ DWORD dwFlags, - _In_ DWORD dwDesiredAccess - ) - { - if (auto pCreateMutexExA = try_get_CreateMutexExA()) - { - return pCreateMutexExA(lpMutexAttributes, lpName, dwFlags, dwDesiredAccess); - } - - return CreateMutexA(lpMutexAttributes, dwFlags & CREATE_MUTEX_INITIAL_OWNER, lpName); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 16, + HANDLE, + WINAPI, + CreateMutexExA, + _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes, + _In_opt_ LPCSTR lpName, + _In_ DWORD dwFlags, + _In_ DWORD dwDesiredAccess + ) + { + if (auto pCreateMutexExA = try_get_CreateMutexExA()) + { + return pCreateMutexExA(lpMutexAttributes, lpName, dwFlags, dwDesiredAccess); + } + + return CreateMutexA(lpMutexAttributes, dwFlags & CREATE_MUTEX_INITIAL_OWNER, lpName); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 24, - HANDLE, - WINAPI, - CreateSemaphoreExW, - _In_opt_ LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, - _In_ LONG lInitialCount, - _In_ LONG lMaximumCount, - _In_opt_ LPCWSTR lpName, - _Reserved_ DWORD dwFlags, - _In_ DWORD dwDesiredAccess - ) - { - if (auto pCreateSemaphoreExW = try_get_CreateSemaphoreExW()) - { - return pCreateSemaphoreExW(lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName, dwFlags, dwDesiredAccess); - } - - return CreateSemaphoreW(lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 24, + HANDLE, + WINAPI, + CreateSemaphoreExW, + _In_opt_ LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, + _In_ LONG lInitialCount, + _In_ LONG lMaximumCount, + _In_opt_ LPCWSTR lpName, + _Reserved_ DWORD dwFlags, + _In_ DWORD dwDesiredAccess + ) + { + if (auto pCreateSemaphoreExW = try_get_CreateSemaphoreExW()) + { + return pCreateSemaphoreExW(lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName, dwFlags, dwDesiredAccess); + } + + return CreateSemaphoreW(lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 16, - HANDLE, - WINAPI, - CreateWaitableTimerExW, - _In_opt_ LPSECURITY_ATTRIBUTES lpTimerAttributes, - _In_opt_ LPCWSTR lpTimerName, - _In_ DWORD dwFlags, - _In_ DWORD dwDesiredAccess - ) - { - if (auto pCreateWaitableTimerExW = try_get_CreateWaitableTimerExW()) - { - return pCreateWaitableTimerExW(lpTimerAttributes, lpTimerName, dwFlags, dwDesiredAccess); - } - - return CreateWaitableTimerW(lpTimerAttributes, dwFlags&CREATE_WAITABLE_TIMER_MANUAL_RESET, lpTimerName); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 16, + HANDLE, + WINAPI, + CreateWaitableTimerExW, + _In_opt_ LPSECURITY_ATTRIBUTES lpTimerAttributes, + _In_opt_ LPCWSTR lpTimerName, + _In_ DWORD dwFlags, + _In_ DWORD dwDesiredAccess + ) + { + if (auto pCreateWaitableTimerExW = try_get_CreateWaitableTimerExW()) + { + return pCreateWaitableTimerExW(lpTimerAttributes, lpTimerName, dwFlags, dwDesiredAccess); + } + + return CreateWaitableTimerW(lpTimerAttributes, dwFlags&CREATE_WAITABLE_TIMER_MANUAL_RESET, lpTimerName); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - InitializeSRWLock, - _Out_ PSRWLOCK SRWLock - ) - { - *SRWLock = RTL_SRWLOCK_INIT; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + InitializeSRWLock, + _Out_ PSRWLOCK SRWLock + ) + { + *SRWLock = RTL_SRWLOCK_INIT; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - AcquireSRWLockExclusive, - _Inout_ PSRWLOCK SRWLock - ) - { - if (auto const pAcquireSRWLockExclusive = try_get_AcquireSRWLockExclusive()) - { - return pAcquireSRWLockExclusive(SRWLock); - } - - YY_SRWLOCK_WAIT_BLOCK StackWaitBlock; - bool bOptimize; - - //尝试加锁一次 +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + AcquireSRWLockExclusive, + _Inout_ PSRWLOCK SRWLock + ) + { + if (auto const pAcquireSRWLockExclusive = try_get_AcquireSRWLockExclusive()) + { + return pAcquireSRWLockExclusive(SRWLock); + } + + YY_SRWLOCK_WAIT_BLOCK StackWaitBlock; + bool bOptimize; + + //尝试加锁一次 #if defined(_WIN64) - auto OldBit = InterlockedBitTestAndSet64((volatile LONG_PTR*)SRWLock, YY_SRWLOCK_Locked_BIT); + auto OldBit = InterlockedBitTestAndSet64((volatile LONG_PTR*)SRWLock, YY_SRWLOCK_Locked_BIT); #else - auto OldBit = InterlockedBitTestAndSet((volatile LONG_PTR*)SRWLock, YY_SRWLOCK_Locked_BIT); + auto OldBit = InterlockedBitTestAndSet((volatile LONG_PTR*)SRWLock, YY_SRWLOCK_Locked_BIT); #endif - if(OldBit == false) - { - //成功锁定 - return; - } - - for (;;) - { - auto SRWLockOld = *(volatile size_t*)SRWLock; - - if (YY_SRWLOCK_Locked & SRWLockOld) - { - /* - if (RtlpWaitCouldDeadlock()) - ZwTerminateProcess((HANDLE)0xFFFFFFFF, 0xC000004B); - */ - - StackWaitBlock.next = nullptr; - StackWaitBlock.flag = 3; - bOptimize = false; - - size_t SRWLockNew; - - if (YY_SRWLOCK_Waiting & SRWLockOld) - { - //有人正在等待连接 - StackWaitBlock.notify = nullptr; - StackWaitBlock.shareCount = 0; - StackWaitBlock.back = (YY_SRWLOCK_WAIT_BLOCK*)(SRWLockOld & (~YY_SRWLOCK_MASK)); - - SRWLockNew = (size_t)(&StackWaitBlock) | (SRWLockOld & YY_SRWLOCK_MultipleShared) | YY_SRWLOCK_Waking | YY_SRWLOCK_Waiting | YY_SRWLOCK_Locked; - - if ((YY_SRWLOCK_Waking & SRWLockOld) == 0) - { - bOptimize = true; - } - } - else - { - //没有其他人没有等待,所以我们需要创建一个 - StackWaitBlock.notify = (YY_SRWLOCK_WAIT_BLOCK*)&StackWaitBlock; - StackWaitBlock.shareCount = (SRWLockOld >> YY_SRWLOCK_BITS); - - - SRWLockNew = StackWaitBlock.shareCount > 1 ? - (size_t)(&StackWaitBlock) | YY_SRWLOCK_MultipleShared | YY_SRWLOCK_Waiting | YY_SRWLOCK_Locked - : (size_t)(&StackWaitBlock) | YY_SRWLOCK_Waiting | YY_SRWLOCK_Locked; - } - - if (InterlockedCompareExchange((volatile size_t*)SRWLock, SRWLockNew, SRWLockOld) != SRWLockOld) - { - //更新锁状态失败,其他线程正在处理改锁,要不咋们换个姿势再来 - - //RtlBackoff就懒得做了,反正只是等待一会而已,直接YieldProcessor再来一次吧。 - //RtlBackoff(&nBackOff) - - YieldProcessor(); - continue; - } - - - if (bOptimize) - { - internal::RtlpOptimizeSRWLockList(SRWLock, SRWLockNew); - } - - auto GlobalKeyedEventHandle = internal::GetGlobalKeyedEventHandle(); - auto pNtWaitForKeyedEvent = try_get_NtWaitForKeyedEvent(); - if (!pNtWaitForKeyedEvent) - { - internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); - } - - //自旋 - for (DWORD SpinCount = SRWLockSpinCount; SpinCount; --SpinCount) - { - if ((StackWaitBlock.flag & 2) == 0) - break; - - YieldProcessor(); - } - - if (InterlockedBitTestAndReset((volatile LONG*)&StackWaitBlock.flag, 1)) - { - pNtWaitForKeyedEvent(GlobalKeyedEventHandle, (PVOID)&StackWaitBlock, 0, nullptr); - } - } - else - { - //尝试获取锁的所有权 - if (InterlockedCompareExchange((volatile size_t*)SRWLock, SRWLockOld | YY_SRWLOCK_Locked, SRWLockOld) == SRWLockOld) - { - //成功加锁 - return; - } - - //可能多线程并发访问,换个姿势再来一次 - YieldProcessor(); - } - } - } + if(OldBit == false) + { + //成功锁定 + return; + } + + for (;;) + { + auto SRWLockOld = *(volatile size_t*)SRWLock; + + if (YY_SRWLOCK_Locked & SRWLockOld) + { + /* + if (RtlpWaitCouldDeadlock()) + ZwTerminateProcess((HANDLE)0xFFFFFFFF, 0xC000004B); + */ + + StackWaitBlock.next = nullptr; + StackWaitBlock.flag = 3; + bOptimize = false; + + size_t SRWLockNew; + + if (YY_SRWLOCK_Waiting & SRWLockOld) + { + //有人正在等待连接 + StackWaitBlock.notify = nullptr; + StackWaitBlock.shareCount = 0; + StackWaitBlock.back = (YY_SRWLOCK_WAIT_BLOCK*)(SRWLockOld & (~YY_SRWLOCK_MASK)); + + SRWLockNew = (size_t)(&StackWaitBlock) | (SRWLockOld & YY_SRWLOCK_MultipleShared) | YY_SRWLOCK_Waking | YY_SRWLOCK_Waiting | YY_SRWLOCK_Locked; + + if ((YY_SRWLOCK_Waking & SRWLockOld) == 0) + { + bOptimize = true; + } + } + else + { + //没有其他人没有等待,所以我们需要创建一个 + StackWaitBlock.notify = (YY_SRWLOCK_WAIT_BLOCK*)&StackWaitBlock; + StackWaitBlock.shareCount = (SRWLockOld >> YY_SRWLOCK_BITS); + + + SRWLockNew = StackWaitBlock.shareCount > 1 ? + (size_t)(&StackWaitBlock) | YY_SRWLOCK_MultipleShared | YY_SRWLOCK_Waiting | YY_SRWLOCK_Locked + : (size_t)(&StackWaitBlock) | YY_SRWLOCK_Waiting | YY_SRWLOCK_Locked; + } + + if (InterlockedCompareExchange((volatile size_t*)SRWLock, SRWLockNew, SRWLockOld) != SRWLockOld) + { + //更新锁状态失败,其他线程正在处理改锁,要不咋们换个姿势再来 + + //RtlBackoff就懒得做了,反正只是等待一会而已,直接YieldProcessor再来一次吧。 + //RtlBackoff(&nBackOff) + + YieldProcessor(); + continue; + } + + + if (bOptimize) + { + internal::RtlpOptimizeSRWLockList(SRWLock, SRWLockNew); + } + + auto GlobalKeyedEventHandle = internal::GetGlobalKeyedEventHandle(); + auto pNtWaitForKeyedEvent = try_get_NtWaitForKeyedEvent(); + if (!pNtWaitForKeyedEvent) + { + internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); + } + + //自旋 + for (DWORD SpinCount = SRWLockSpinCount; SpinCount; --SpinCount) + { + if ((StackWaitBlock.flag & 2) == 0) + break; + + YieldProcessor(); + } + + if (InterlockedBitTestAndReset((volatile LONG*)&StackWaitBlock.flag, 1)) + { + pNtWaitForKeyedEvent(GlobalKeyedEventHandle, (PVOID)&StackWaitBlock, 0, nullptr); + } + } + else + { + //尝试获取锁的所有权 + if (InterlockedCompareExchange((volatile size_t*)SRWLock, SRWLockOld | YY_SRWLOCK_Locked, SRWLockOld) == SRWLockOld) + { + //成功加锁 + return; + } + + //可能多线程并发访问,换个姿势再来一次 + YieldProcessor(); + } + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - //Windows 7 [desktop apps | UWP apps] - //Windows Server 2008 R2 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - BOOLEAN, - WINAPI, - TryAcquireSRWLockExclusive, - _Inout_ PSRWLOCK SRWLock - ) - { - if (auto const pTryAcquireSRWLockExclusive = try_get_TryAcquireSRWLockExclusive()) - { - return pTryAcquireSRWLockExclusive(SRWLock); - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + //Windows 7 [desktop apps | UWP apps] + //Windows Server 2008 R2 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + BOOLEAN, + WINAPI, + TryAcquireSRWLockExclusive, + _Inout_ PSRWLOCK SRWLock + ) + { + if (auto const pTryAcquireSRWLockExclusive = try_get_TryAcquireSRWLockExclusive()) + { + return pTryAcquireSRWLockExclusive(SRWLock); + } #if defined(_WIN64) - return InterlockedBitTestAndSet64((volatile LONG_PTR*)SRWLock, YY_SRWLOCK_Locked_BIT) == 0; + return InterlockedBitTestAndSet64((volatile LONG_PTR*)SRWLock, YY_SRWLOCK_Locked_BIT) == 0; #else - return InterlockedBitTestAndSet((volatile LONG_PTR*)SRWLock, YY_SRWLOCK_Locked_BIT) == 0; + return InterlockedBitTestAndSet((volatile LONG_PTR*)SRWLock, YY_SRWLOCK_Locked_BIT) == 0; #endif - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - ReleaseSRWLockExclusive, - _Inout_ PSRWLOCK SRWLock - ) - { - if (auto const pReleaseSRWLockExclusive = try_get_ReleaseSRWLockExclusive()) - { - return pReleaseSRWLockExclusive(SRWLock); - } - - auto OldSRWLock = InterlockedExchangeAdd((volatile size_t *)SRWLock, size_t(-1)); - if ((OldSRWLock & YY_SRWLOCK_Locked) == 0) - { - internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); - } - - if ((OldSRWLock & YY_SRWLOCK_Waiting) && (OldSRWLock & YY_SRWLOCK_Waking) == 0) - { - OldSRWLock -= YY_SRWLOCK_Locked; - - auto NewSRWLock = OldSRWLock | YY_SRWLOCK_Waking; - auto CurrentSRWLock = InterlockedCompareExchange((volatile size_t *)SRWLock, NewSRWLock, OldSRWLock); - - if (CurrentSRWLock == OldSRWLock) - internal::RtlpWakeSRWLock(SRWLock, NewSRWLock); - } - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + ReleaseSRWLockExclusive, + _Inout_ PSRWLOCK SRWLock + ) + { + if (auto const pReleaseSRWLockExclusive = try_get_ReleaseSRWLockExclusive()) + { + return pReleaseSRWLockExclusive(SRWLock); + } + + auto OldSRWLock = InterlockedExchangeAdd((volatile size_t *)SRWLock, size_t(-1)); + if ((OldSRWLock & YY_SRWLOCK_Locked) == 0) + { + internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); + } + + if ((OldSRWLock & YY_SRWLOCK_Waiting) && (OldSRWLock & YY_SRWLOCK_Waking) == 0) + { + OldSRWLock -= YY_SRWLOCK_Locked; + + auto NewSRWLock = OldSRWLock | YY_SRWLOCK_Waking; + auto CurrentSRWLock = InterlockedCompareExchange((volatile size_t *)SRWLock, NewSRWLock, OldSRWLock); + + if (CurrentSRWLock == OldSRWLock) + internal::RtlpWakeSRWLock(SRWLock, NewSRWLock); + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - AcquireSRWLockShared, - _Inout_ PSRWLOCK SRWLock - ) - { - if (auto const pAcquireSRWLockShared = try_get_AcquireSRWLockShared()) - { - return pAcquireSRWLockShared(SRWLock); - } - - YY_SRWLOCK_WAIT_BLOCK StackWaitBlock; - bool bOptimize; - - //尝试给全新的锁加锁 - auto OldSRWLock = InterlockedCompareExchange((volatile size_t*)SRWLock, size_t(0x11), 0); - - //成功 - if (OldSRWLock == size_t(0)) - { - return; - } - - - size_t NewSRWLock; - - for (;; OldSRWLock = *(volatile size_t *)SRWLock) - { - if ((OldSRWLock & YY_SRWLOCK_Locked) && ((OldSRWLock & YY_SRWLOCK_Waiting) || YY_SRWLOCK_GET_BLOCK(OldSRWLock) == nullptr)) - { - //if ( RtlpWaitCouldDeadlock() ) - // ZwTerminateProcess((HANDLE)0xFFFFFFFF, 0xC000004B); - - - StackWaitBlock.flag = 2; - StackWaitBlock.shareCount = 0; - StackWaitBlock.next = nullptr; - - bOptimize = false; - - if (OldSRWLock & YY_SRWLOCK_Waiting) - { - //已经有人等待,我们插入一个新的等待块 - StackWaitBlock.back = YY_SRWLOCK_GET_BLOCK(OldSRWLock); - StackWaitBlock.notify = nullptr; - - NewSRWLock = size_t(&StackWaitBlock) | (OldSRWLock & YY_SRWLOCK_MultipleShared) | (YY_SRWLOCK_Waking | YY_SRWLOCK_Waiting | YY_SRWLOCK_Locked); - - if ((OldSRWLock & YY_SRWLOCK_Waking) == 0) - { - bOptimize = true; - } - } - else - { - StackWaitBlock.notify = &StackWaitBlock; - NewSRWLock = size_t(&StackWaitBlock) | (YY_SRWLOCK_Waiting | YY_SRWLOCK_Locked); - } - - - if (InterlockedCompareExchange((volatile size_t *)SRWLock, NewSRWLock, OldSRWLock) == OldSRWLock) - { - //更新成功! - - if (bOptimize) - { - internal::RtlpOptimizeSRWLockList(SRWLock, NewSRWLock); - } - - auto GlobalKeyedEventHandle = internal::GetGlobalKeyedEventHandle(); - auto pNtWaitForKeyedEvent = try_get_NtWaitForKeyedEvent(); - if (!pNtWaitForKeyedEvent) - { - internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); - } - - //自旋 - for (DWORD SpinCount = SRWLockSpinCount; SpinCount; --SpinCount) - { - if ((StackWaitBlock.flag & 2) == 0) - break; - - YieldProcessor(); - } - - if (InterlockedBitTestAndReset((volatile LONG*)&StackWaitBlock.flag, 1)) - { - pNtWaitForKeyedEvent(GlobalKeyedEventHandle, (PVOID)&StackWaitBlock, 0, nullptr); - } - - continue; - } - } - else - { - if (OldSRWLock & YY_SRWLOCK_Waiting) - { - //既然有人在等待锁,那么YY_SRWLOCK_Locked应该重新加上 - NewSRWLock = OldSRWLock | YY_SRWLOCK_Locked; - } - else - { - //没有人等待,那么单纯加个 0x10即可 - NewSRWLock = (OldSRWLock + 0x10) | YY_SRWLOCK_Locked; - } - - if (InterlockedCompareExchange((volatile size_t *)SRWLock, NewSRWLock, OldSRWLock) == OldSRWLock) - return; - } - - //偷懒下,直接 YieldProcessor 吧 - //RtlBackoff(&nBackOff); - YieldProcessor(); - } - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + AcquireSRWLockShared, + _Inout_ PSRWLOCK SRWLock + ) + { + if (auto const pAcquireSRWLockShared = try_get_AcquireSRWLockShared()) + { + return pAcquireSRWLockShared(SRWLock); + } + + YY_SRWLOCK_WAIT_BLOCK StackWaitBlock; + bool bOptimize; + + //尝试给全新的锁加锁 + auto OldSRWLock = InterlockedCompareExchange((volatile size_t*)SRWLock, size_t(0x11), 0); + + //成功 + if (OldSRWLock == size_t(0)) + { + return; + } + + + size_t NewSRWLock; + + for (;; OldSRWLock = *(volatile size_t *)SRWLock) + { + if ((OldSRWLock & YY_SRWLOCK_Locked) && ((OldSRWLock & YY_SRWLOCK_Waiting) || YY_SRWLOCK_GET_BLOCK(OldSRWLock) == nullptr)) + { + //if ( RtlpWaitCouldDeadlock() ) + // ZwTerminateProcess((HANDLE)0xFFFFFFFF, 0xC000004B); + + + StackWaitBlock.flag = 2; + StackWaitBlock.shareCount = 0; + StackWaitBlock.next = nullptr; + + bOptimize = false; + + if (OldSRWLock & YY_SRWLOCK_Waiting) + { + //已经有人等待,我们插入一个新的等待块 + StackWaitBlock.back = YY_SRWLOCK_GET_BLOCK(OldSRWLock); + StackWaitBlock.notify = nullptr; + + NewSRWLock = size_t(&StackWaitBlock) | (OldSRWLock & YY_SRWLOCK_MultipleShared) | (YY_SRWLOCK_Waking | YY_SRWLOCK_Waiting | YY_SRWLOCK_Locked); + + if ((OldSRWLock & YY_SRWLOCK_Waking) == 0) + { + bOptimize = true; + } + } + else + { + StackWaitBlock.notify = &StackWaitBlock; + NewSRWLock = size_t(&StackWaitBlock) | (YY_SRWLOCK_Waiting | YY_SRWLOCK_Locked); + } + + + if (InterlockedCompareExchange((volatile size_t *)SRWLock, NewSRWLock, OldSRWLock) == OldSRWLock) + { + //更新成功! + + if (bOptimize) + { + internal::RtlpOptimizeSRWLockList(SRWLock, NewSRWLock); + } + + auto GlobalKeyedEventHandle = internal::GetGlobalKeyedEventHandle(); + auto pNtWaitForKeyedEvent = try_get_NtWaitForKeyedEvent(); + if (!pNtWaitForKeyedEvent) + { + internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); + } + + //自旋 + for (DWORD SpinCount = SRWLockSpinCount; SpinCount; --SpinCount) + { + if ((StackWaitBlock.flag & 2) == 0) + break; + + YieldProcessor(); + } + + if (InterlockedBitTestAndReset((volatile LONG*)&StackWaitBlock.flag, 1)) + { + pNtWaitForKeyedEvent(GlobalKeyedEventHandle, (PVOID)&StackWaitBlock, 0, nullptr); + } + + continue; + } + } + else + { + if (OldSRWLock & YY_SRWLOCK_Waiting) + { + //既然有人在等待锁,那么YY_SRWLOCK_Locked应该重新加上 + NewSRWLock = OldSRWLock | YY_SRWLOCK_Locked; + } + else + { + //没有人等待,那么单纯加个 0x10即可 + NewSRWLock = (OldSRWLock + 0x10) | YY_SRWLOCK_Locked; + } + + if (InterlockedCompareExchange((volatile size_t *)SRWLock, NewSRWLock, OldSRWLock) == OldSRWLock) + return; + } + + //偷懒下,直接 YieldProcessor 吧 + //RtlBackoff(&nBackOff); + YieldProcessor(); + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - //Windows 7 [desktop apps | UWP apps] - //Windows Server 2008 R2 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - BOOLEAN, - WINAPI, - TryAcquireSRWLockShared, - _Inout_ PSRWLOCK SRWLock - ) - { - if (auto const pTryAcquireSRWLockShared = try_get_TryAcquireSRWLockShared()) - { - return pTryAcquireSRWLockShared(SRWLock); - } - - //尝试给全新的锁加锁 - auto OldSRWLock = InterlockedCompareExchange((volatile size_t*)SRWLock, size_t(0x11), 0); - - //成功 - if (OldSRWLock == size_t(0)) - { - return TRUE; - } - - for (;;) - { - if ((OldSRWLock & YY_SRWLOCK_Locked) && ((OldSRWLock & YY_SRWLOCK_Waiting) || YY_SRWLOCK_GET_BLOCK(OldSRWLock) == nullptr)) - { - //正在被锁定中 - return FALSE; - } - else - { - size_t NewSRWLock; - - if (OldSRWLock & YY_SRWLOCK_Waiting) - NewSRWLock = OldSRWLock | YY_SRWLOCK_Locked; - else - NewSRWLock = (OldSRWLock + 0x10) | YY_SRWLOCK_Locked; - - if (InterlockedCompareExchange((volatile size_t*)SRWLock, NewSRWLock, OldSRWLock) == OldSRWLock) - { - //锁定完成 - return TRUE; - } - - //RtlBackoff((unsigned int *)&v4); - YieldProcessor(); - OldSRWLock = *(volatile size_t*)SRWLock; - } - } - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + //Windows 7 [desktop apps | UWP apps] + //Windows Server 2008 R2 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + BOOLEAN, + WINAPI, + TryAcquireSRWLockShared, + _Inout_ PSRWLOCK SRWLock + ) + { + if (auto const pTryAcquireSRWLockShared = try_get_TryAcquireSRWLockShared()) + { + return pTryAcquireSRWLockShared(SRWLock); + } + + //尝试给全新的锁加锁 + auto OldSRWLock = InterlockedCompareExchange((volatile size_t*)SRWLock, size_t(0x11), 0); + + //成功 + if (OldSRWLock == size_t(0)) + { + return TRUE; + } + + for (;;) + { + if ((OldSRWLock & YY_SRWLOCK_Locked) && ((OldSRWLock & YY_SRWLOCK_Waiting) || YY_SRWLOCK_GET_BLOCK(OldSRWLock) == nullptr)) + { + //正在被锁定中 + return FALSE; + } + else + { + size_t NewSRWLock; + + if (OldSRWLock & YY_SRWLOCK_Waiting) + NewSRWLock = OldSRWLock | YY_SRWLOCK_Locked; + else + NewSRWLock = (OldSRWLock + 0x10) | YY_SRWLOCK_Locked; + + if (InterlockedCompareExchange((volatile size_t*)SRWLock, NewSRWLock, OldSRWLock) == OldSRWLock) + { + //锁定完成 + return TRUE; + } + + //RtlBackoff((unsigned int *)&v4); + YieldProcessor(); + OldSRWLock = *(volatile size_t*)SRWLock; + } + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - ReleaseSRWLockShared, - _Inout_ PSRWLOCK SRWLock - ) - { - if (auto const pReleaseSRWLockShared = try_get_ReleaseSRWLockShared()) - { - return pReleaseSRWLockShared(SRWLock); - } - - //尝试解锁只加一次读锁的情况 - - auto OldSRWLock = InterlockedCompareExchange((volatile size_t*)SRWLock, 0, size_t(0x11)); - - //解锁成功 - if (OldSRWLock == size_t(0x11)) - { - return; - } - - if ((OldSRWLock & YY_SRWLOCK_Locked) == 0) - { - internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); - } - - for (;;) - { - if (OldSRWLock & YY_SRWLOCK_Waiting) - { - if (OldSRWLock & YY_SRWLOCK_MultipleShared) - { - auto pLastNode = YY_SRWLOCK_GET_BLOCK(OldSRWLock); - - for (; pLastNode->notify == nullptr; pLastNode = pLastNode->back); - - /* - 既然是在释放共享锁,说明一定有人获取了共享锁 - 如果有人获取了共享锁,就一定没有人获取独到占锁 - 只需要把共享次数减1 - 取出notify节点的共享次数变量的地址, 原子减 - */ - if (InterlockedDecrement((volatile size_t *)&(pLastNode->notify->shareCount)) > 0) - { - return; - } - } - - - for (;;) - { - auto NewSRWLock = OldSRWLock & (~(YY_SRWLOCK_MultipleShared | YY_SRWLOCK_Locked)); - size_t LastSRWLock; - - if (OldSRWLock & YY_SRWLOCK_Waking) - { - LastSRWLock = InterlockedCompareExchange((volatile size_t *)SRWLock, NewSRWLock, OldSRWLock); - - if (LastSRWLock == OldSRWLock) - return; - } - else - { - NewSRWLock |= YY_SRWLOCK_Waking; - - LastSRWLock = InterlockedCompareExchange((volatile size_t *)SRWLock, NewSRWLock, OldSRWLock); - if (LastSRWLock == OldSRWLock) - return internal::RtlpWakeSRWLock(SRWLock, NewSRWLock); - } - - OldSRWLock = LastSRWLock; - } - - break; - } - else - { - auto NewSRWLock = size_t(YY_SRWLOCK_GET_BLOCK(OldSRWLock)) <= 0x10 ? 0 : OldSRWLock - 0x10; - - auto LastSRWLock = InterlockedCompareExchange((volatile size_t *)SRWLock, NewSRWLock, OldSRWLock); - if (LastSRWLock == OldSRWLock) - break; - - OldSRWLock = LastSRWLock; - } - } - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + ReleaseSRWLockShared, + _Inout_ PSRWLOCK SRWLock + ) + { + if (auto const pReleaseSRWLockShared = try_get_ReleaseSRWLockShared()) + { + return pReleaseSRWLockShared(SRWLock); + } + + //尝试解锁只加一次读锁的情况 + + auto OldSRWLock = InterlockedCompareExchange((volatile size_t*)SRWLock, 0, size_t(0x11)); + + //解锁成功 + if (OldSRWLock == size_t(0x11)) + { + return; + } + + if ((OldSRWLock & YY_SRWLOCK_Locked) == 0) + { + internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); + } + + for (;;) + { + if (OldSRWLock & YY_SRWLOCK_Waiting) + { + if (OldSRWLock & YY_SRWLOCK_MultipleShared) + { + auto pLastNode = YY_SRWLOCK_GET_BLOCK(OldSRWLock); + + for (; pLastNode->notify == nullptr; pLastNode = pLastNode->back); + + /* + 既然是在释放共享锁,说明一定有人获取了共享锁 + 如果有人获取了共享锁,就一定没有人获取独到占锁 + 只需要把共享次数减1 + 取出notify节点的共享次数变量的地址, 原子减 + */ + if (InterlockedDecrement((volatile size_t *)&(pLastNode->notify->shareCount)) > 0) + { + return; + } + } + + + for (;;) + { + auto NewSRWLock = OldSRWLock & (~(YY_SRWLOCK_MultipleShared | YY_SRWLOCK_Locked)); + size_t LastSRWLock; + + if (OldSRWLock & YY_SRWLOCK_Waking) + { + LastSRWLock = InterlockedCompareExchange((volatile size_t *)SRWLock, NewSRWLock, OldSRWLock); + + if (LastSRWLock == OldSRWLock) + return; + } + else + { + NewSRWLock |= YY_SRWLOCK_Waking; + + LastSRWLock = InterlockedCompareExchange((volatile size_t *)SRWLock, NewSRWLock, OldSRWLock); + if (LastSRWLock == OldSRWLock) + return internal::RtlpWakeSRWLock(SRWLock, NewSRWLock); + } + + OldSRWLock = LastSRWLock; + } + + break; + } + else + { + auto NewSRWLock = size_t(YY_SRWLOCK_GET_BLOCK(OldSRWLock)) <= 0x10 ? 0 : OldSRWLock - 0x10; + + auto LastSRWLock = InterlockedCompareExchange((volatile size_t *)SRWLock, NewSRWLock, OldSRWLock); + if (LastSRWLock == OldSRWLock) + break; + + OldSRWLock = LastSRWLock; + } + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - InitializeConditionVariable, - _Out_ PCONDITION_VARIABLE ConditionVariable - ) - { - *ConditionVariable = CONDITION_VARIABLE_INIT; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + InitializeConditionVariable, + _Out_ PCONDITION_VARIABLE ConditionVariable + ) + { + *ConditionVariable = CONDITION_VARIABLE_INIT; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 12, - BOOL, - WINAPI, - SleepConditionVariableCS, - _Inout_ PCONDITION_VARIABLE ConditionVariable, - _Inout_ PCRITICAL_SECTION CriticalSection, - _In_ DWORD dwMilliseconds - ) - { - if (auto const pSleepConditionVariableCS = try_get_SleepConditionVariableCS()) - { - return pSleepConditionVariableCS(ConditionVariable, CriticalSection, dwMilliseconds); - } + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 12, + BOOL, + WINAPI, + SleepConditionVariableCS, + _Inout_ PCONDITION_VARIABLE ConditionVariable, + _Inout_ PCRITICAL_SECTION CriticalSection, + _In_ DWORD dwMilliseconds + ) + { + if (auto const pSleepConditionVariableCS = try_get_SleepConditionVariableCS()) + { + return pSleepConditionVariableCS(ConditionVariable, CriticalSection, dwMilliseconds); + } - YY_CV_WAIT_BLOCK StackWaitBlock; + YY_CV_WAIT_BLOCK StackWaitBlock; - StackWaitBlock.next = nullptr; - StackWaitBlock.flag = 2; - StackWaitBlock.SRWLock = nullptr; + StackWaitBlock.next = nullptr; + StackWaitBlock.flag = 2; + StackWaitBlock.SRWLock = nullptr; - auto OldConditionVariable = *(size_t*)ConditionVariable; + auto OldConditionVariable = *(size_t*)ConditionVariable; - size_t NewConditionVariable; + size_t NewConditionVariable; - for (;;) - { - NewConditionVariable = size_t(&StackWaitBlock) | (OldConditionVariable & YY_CV_MASK); - StackWaitBlock.back = YY_CV_GET_BLOCK(OldConditionVariable); + for (;;) + { + NewConditionVariable = size_t(&StackWaitBlock) | (OldConditionVariable & YY_CV_MASK); + StackWaitBlock.back = YY_CV_GET_BLOCK(OldConditionVariable); - if (StackWaitBlock.back) - { - StackWaitBlock.notify = nullptr; + if (StackWaitBlock.back) + { + StackWaitBlock.notify = nullptr; - NewConditionVariable |= 0x8; - } - else - { - StackWaitBlock.notify = &StackWaitBlock; - } + NewConditionVariable |= 0x8; + } + else + { + StackWaitBlock.notify = &StackWaitBlock; + } - auto LastConditionVariable = InterlockedCompareExchange((volatile size_t*)ConditionVariable, NewConditionVariable, OldConditionVariable); + auto LastConditionVariable = InterlockedCompareExchange((volatile size_t*)ConditionVariable, NewConditionVariable, OldConditionVariable); - if (LastConditionVariable == OldConditionVariable) - break; + if (LastConditionVariable == OldConditionVariable) + break; - OldConditionVariable = LastConditionVariable; - } + OldConditionVariable = LastConditionVariable; + } - LeaveCriticalSection(CriticalSection); + LeaveCriticalSection(CriticalSection); - //0x8 标记新增时,才进行优化 ConditionVariableWaitList - if ((OldConditionVariable ^ NewConditionVariable) & 0x8) - { - internal::RtlpOptimizeConditionVariableWaitList(ConditionVariable, NewConditionVariable); - } + //0x8 标记新增时,才进行优化 ConditionVariableWaitList + if ((OldConditionVariable ^ NewConditionVariable) & 0x8) + { + internal::RtlpOptimizeConditionVariableWaitList(ConditionVariable, NewConditionVariable); + } - auto GlobalKeyedEventHandle = internal::GetGlobalKeyedEventHandle(); - auto pNtWaitForKeyedEvent = try_get_NtWaitForKeyedEvent(); - if (!pNtWaitForKeyedEvent) - { - internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); - } + auto GlobalKeyedEventHandle = internal::GetGlobalKeyedEventHandle(); + auto pNtWaitForKeyedEvent = try_get_NtWaitForKeyedEvent(); + if (!pNtWaitForKeyedEvent) + { + internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); + } - //自旋 - for (auto SpinCount = ConditionVariableSpinCount; SpinCount; --SpinCount) - { - if (!(StackWaitBlock.flag & 2)) - break; + //自旋 + for (auto SpinCount = ConditionVariableSpinCount; SpinCount; --SpinCount) + { + if (!(StackWaitBlock.flag & 2)) + break; - YieldProcessor(); - } + YieldProcessor(); + } - NTSTATUS Status = 0; + NTSTATUS Status = 0; - if (InterlockedBitTestAndReset((volatile LONG*)&StackWaitBlock.flag, 1)) - { - LARGE_INTEGER TimeOut; + if (InterlockedBitTestAndReset((volatile LONG*)&StackWaitBlock.flag, 1)) + { + LARGE_INTEGER TimeOut; - Status = pNtWaitForKeyedEvent(GlobalKeyedEventHandle, (PVOID)&StackWaitBlock, 0, internal::BaseFormatTimeOut(&TimeOut, dwMilliseconds)); + Status = pNtWaitForKeyedEvent(GlobalKeyedEventHandle, (PVOID)&StackWaitBlock, 0, internal::BaseFormatTimeOut(&TimeOut, dwMilliseconds)); - if (Status == STATUS_TIMEOUT && internal::RtlpWakeSingle(ConditionVariable, &StackWaitBlock) == FALSE) - { - pNtWaitForKeyedEvent(GlobalKeyedEventHandle, (PVOID)&StackWaitBlock, 0, nullptr); - Status = 0; - } - } + if (Status == STATUS_TIMEOUT && internal::RtlpWakeSingle(ConditionVariable, &StackWaitBlock) == FALSE) + { + pNtWaitForKeyedEvent(GlobalKeyedEventHandle, (PVOID)&StackWaitBlock, 0, nullptr); + Status = 0; + } + } - EnterCriticalSection(CriticalSection); + EnterCriticalSection(CriticalSection); - internal::BaseSetLastNTError(Status); + internal::BaseSetLastNTError(Status); - return Status >= 0 && Status != STATUS_TIMEOUT; - } + return Status >= 0 && Status != STATUS_TIMEOUT; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - SleepConditionVariableSRW, - _Inout_ PCONDITION_VARIABLE ConditionVariable, - _Inout_ PSRWLOCK SRWLock, - _In_ DWORD dwMilliseconds, - _In_ ULONG Flags - ) - { - if (auto const pSleepConditionVariableSRW = try_get_SleepConditionVariableSRW()) - { - return pSleepConditionVariableSRW(ConditionVariable, SRWLock, dwMilliseconds, Flags); - } - - YY_CV_WAIT_BLOCK StackWaitBlock; - - NTSTATUS Status = 0; - - do - { - if (Flags & ~CONDITION_VARIABLE_LOCKMODE_SHARED) - { - Status = STATUS_INVALID_PARAMETER_2; - break; - } - - StackWaitBlock.next = nullptr; - StackWaitBlock.flag = 2; - StackWaitBlock.SRWLock = nullptr; - - if (Flags& CONDITION_VARIABLE_LOCKMODE_SHARED) - { - StackWaitBlock.flag |= 0x4; - } - - size_t Current = *(volatile size_t*)ConditionVariable; - size_t New; - - for (;;) - { - New = size_t(&StackWaitBlock) | (Current & YY_CV_MASK); - - if (StackWaitBlock.back = YY_CV_GET_BLOCK(Current)) - { - StackWaitBlock.notify = nullptr; - - New |= 0x8; - } - else - { - StackWaitBlock.notify = &StackWaitBlock; - } - - const auto Last = InterlockedCompareExchange((volatile size_t*)ConditionVariable, New, Current); - - if (Last == Current) - { - break; - } - - - Current = Last; - } - - if (Flags& CONDITION_VARIABLE_LOCKMODE_SHARED) - ReleaseSRWLockShared(SRWLock); - else - ReleaseSRWLockExclusive(SRWLock); - - if ((Current ^ New) & 0x8) - { - //新增0x8 标记位才调用 RtlpOptimizeConditionVariableWaitList - internal::RtlpOptimizeConditionVariableWaitList(ConditionVariable, New); - } - - auto GlobalKeyedEventHandle = internal::GetGlobalKeyedEventHandle(); - auto pNtWaitForKeyedEvent = try_get_NtWaitForKeyedEvent(); - if (!pNtWaitForKeyedEvent) - { - internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); - } - - //自旋 - for (auto SpinCount = ConditionVariableSpinCount; SpinCount; --SpinCount) - { - if (!(StackWaitBlock.flag & 2)) - break; - - YieldProcessor(); - } - - if (InterlockedBitTestAndReset((volatile LONG*)&StackWaitBlock.flag, 1)) - { - LARGE_INTEGER TimeOut; - - Status = pNtWaitForKeyedEvent(GlobalKeyedEventHandle, (PVOID)&StackWaitBlock, 0, internal::BaseFormatTimeOut(&TimeOut, dwMilliseconds)); - - if (Status == STATUS_TIMEOUT && internal::RtlpWakeSingle(ConditionVariable, &StackWaitBlock) == FALSE) - { - pNtWaitForKeyedEvent(GlobalKeyedEventHandle, (PVOID)&StackWaitBlock, 0, nullptr); - Status = 0; - } - } - - if (Flags& CONDITION_VARIABLE_LOCKMODE_SHARED) - AcquireSRWLockShared(SRWLock); - else - AcquireSRWLockExclusive(SRWLock); +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + SleepConditionVariableSRW, + _Inout_ PCONDITION_VARIABLE ConditionVariable, + _Inout_ PSRWLOCK SRWLock, + _In_ DWORD dwMilliseconds, + _In_ ULONG Flags + ) + { + if (auto const pSleepConditionVariableSRW = try_get_SleepConditionVariableSRW()) + { + return pSleepConditionVariableSRW(ConditionVariable, SRWLock, dwMilliseconds, Flags); + } + + YY_CV_WAIT_BLOCK StackWaitBlock; + + NTSTATUS Status = 0; + + do + { + if (Flags & ~CONDITION_VARIABLE_LOCKMODE_SHARED) + { + Status = STATUS_INVALID_PARAMETER_2; + break; + } + + StackWaitBlock.next = nullptr; + StackWaitBlock.flag = 2; + StackWaitBlock.SRWLock = nullptr; + + if (Flags& CONDITION_VARIABLE_LOCKMODE_SHARED) + { + StackWaitBlock.flag |= 0x4; + } + + size_t Current = *(volatile size_t*)ConditionVariable; + size_t New; + + for (;;) + { + New = size_t(&StackWaitBlock) | (Current & YY_CV_MASK); + + if (StackWaitBlock.back = YY_CV_GET_BLOCK(Current)) + { + StackWaitBlock.notify = nullptr; + + New |= 0x8; + } + else + { + StackWaitBlock.notify = &StackWaitBlock; + } + + const auto Last = InterlockedCompareExchange((volatile size_t*)ConditionVariable, New, Current); + + if (Last == Current) + { + break; + } + + + Current = Last; + } + + if (Flags& CONDITION_VARIABLE_LOCKMODE_SHARED) + ReleaseSRWLockShared(SRWLock); + else + ReleaseSRWLockExclusive(SRWLock); + + if ((Current ^ New) & 0x8) + { + //新增0x8 标记位才调用 RtlpOptimizeConditionVariableWaitList + internal::RtlpOptimizeConditionVariableWaitList(ConditionVariable, New); + } + + auto GlobalKeyedEventHandle = internal::GetGlobalKeyedEventHandle(); + auto pNtWaitForKeyedEvent = try_get_NtWaitForKeyedEvent(); + if (!pNtWaitForKeyedEvent) + { + internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); + } + + //自旋 + for (auto SpinCount = ConditionVariableSpinCount; SpinCount; --SpinCount) + { + if (!(StackWaitBlock.flag & 2)) + break; + + YieldProcessor(); + } + + if (InterlockedBitTestAndReset((volatile LONG*)&StackWaitBlock.flag, 1)) + { + LARGE_INTEGER TimeOut; + + Status = pNtWaitForKeyedEvent(GlobalKeyedEventHandle, (PVOID)&StackWaitBlock, 0, internal::BaseFormatTimeOut(&TimeOut, dwMilliseconds)); + + if (Status == STATUS_TIMEOUT && internal::RtlpWakeSingle(ConditionVariable, &StackWaitBlock) == FALSE) + { + pNtWaitForKeyedEvent(GlobalKeyedEventHandle, (PVOID)&StackWaitBlock, 0, nullptr); + Status = 0; + } + } + + if (Flags& CONDITION_VARIABLE_LOCKMODE_SHARED) + AcquireSRWLockShared(SRWLock); + else + AcquireSRWLockExclusive(SRWLock); - } while (false); + } while (false); - internal::BaseSetLastNTError(Status); + internal::BaseSetLastNTError(Status); - return Status >= 0 && Status != STATUS_TIMEOUT; + return Status >= 0 && Status != STATUS_TIMEOUT; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - WakeConditionVariable, - _Inout_ PCONDITION_VARIABLE ConditionVariable - ) - { - if (auto const pWakeConditionVariable = try_get_WakeConditionVariable()) - { - return pWakeConditionVariable(ConditionVariable); - } - - size_t Current = *(volatile size_t*)ConditionVariable; - size_t Last; - - for (; Current; Current = Last) - { - if (Current & 0x8) - { - if ((Current & 0x7) == 0x7) - { - return; - } - - Last = InterlockedCompareExchange((volatile size_t*)ConditionVariable, Current + 1, Current); - if (Last == Current) - return; - } - else - { - Last = InterlockedCompareExchange((volatile size_t*)ConditionVariable, Current | 0x8, Current); - if (Last == Current) - { - internal::RtlpWakeConditionVariable(ConditionVariable, Current + 8, 1); - return; - } - } - } - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + WakeConditionVariable, + _Inout_ PCONDITION_VARIABLE ConditionVariable + ) + { + if (auto const pWakeConditionVariable = try_get_WakeConditionVariable()) + { + return pWakeConditionVariable(ConditionVariable); + } + + size_t Current = *(volatile size_t*)ConditionVariable; + size_t Last; + + for (; Current; Current = Last) + { + if (Current & 0x8) + { + if ((Current & 0x7) == 0x7) + { + return; + } + + Last = InterlockedCompareExchange((volatile size_t*)ConditionVariable, Current + 1, Current); + if (Last == Current) + return; + } + else + { + Last = InterlockedCompareExchange((volatile size_t*)ConditionVariable, Current | 0x8, Current); + if (Last == Current) + { + internal::RtlpWakeConditionVariable(ConditionVariable, Current + 8, 1); + return; + } + } + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps | UWP apps] - //Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - WakeAllConditionVariable, - _Inout_ PCONDITION_VARIABLE ConditionVariable - ) - { - if (auto const pWakeAllConditionVariable = try_get_WakeAllConditionVariable()) - { - return pWakeAllConditionVariable(ConditionVariable); - } - - size_t Current = *(volatile size_t*)ConditionVariable; - size_t Last; - - for (; Current && (Current & 0x7) != 0x7; Current = Last) - { - if (Current & 0x8) - { - Last = InterlockedCompareExchange((volatile size_t*)ConditionVariable, Current | 0x7, Current); - if (Last == Current) - return; - } - else - { - Last = InterlockedCompareExchange((volatile size_t*)ConditionVariable, 0, Current); - if (Last == Current) - { - auto GlobalKeyedEventHandle = internal::GetGlobalKeyedEventHandle(); - auto pNtReleaseKeyedEvent = try_get_NtReleaseKeyedEvent(); - - if (!pNtReleaseKeyedEvent) - { - internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); - } - - for (auto pBlock = YY_CV_GET_BLOCK(Current); pBlock;) - { - auto Tmp = pBlock->back; - - if (!InterlockedBitTestAndReset((volatile LONG*)&pBlock->flag, 1)) - { - pNtReleaseKeyedEvent(GlobalKeyedEventHandle, pBlock, FALSE, nullptr); - } - - pBlock = Tmp; - } - - return; - } - } - } - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps | UWP apps] + //Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + WakeAllConditionVariable, + _Inout_ PCONDITION_VARIABLE ConditionVariable + ) + { + if (auto const pWakeAllConditionVariable = try_get_WakeAllConditionVariable()) + { + return pWakeAllConditionVariable(ConditionVariable); + } + + size_t Current = *(volatile size_t*)ConditionVariable; + size_t Last; + + for (; Current && (Current & 0x7) != 0x7; Current = Last) + { + if (Current & 0x8) + { + Last = InterlockedCompareExchange((volatile size_t*)ConditionVariable, Current | 0x7, Current); + if (Last == Current) + return; + } + else + { + Last = InterlockedCompareExchange((volatile size_t*)ConditionVariable, 0, Current); + if (Last == Current) + { + auto GlobalKeyedEventHandle = internal::GetGlobalKeyedEventHandle(); + auto pNtReleaseKeyedEvent = try_get_NtReleaseKeyedEvent(); + + if (!pNtReleaseKeyedEvent) + { + internal::RaiseStatus(STATUS_RESOURCE_NOT_OWNED); + } + + for (auto pBlock = YY_CV_GET_BLOCK(Current); pBlock;) + { + auto Tmp = pBlock->back; + + if (!InterlockedBitTestAndReset((volatile LONG*)&pBlock->flag, 1)) + { + pNtReleaseKeyedEvent(GlobalKeyedEventHandle, pBlock, FALSE, nullptr); + } + + pBlock = Tmp; + } + + return; + } + } + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Windows 8 [desktop apps only] - //Windows Server 2012 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 12, - BOOL, - WINAPI, - InitializeSynchronizationBarrier, - _Out_ LPSYNCHRONIZATION_BARRIER lpBarrier, - _In_ LONG lTotalThreads, - _In_ LONG lSpinCount - ) - { - if (auto const pEnterSynchronizationBarrier = try_get_InitializeSynchronizationBarrier()) - { - return pEnterSynchronizationBarrier(lpBarrier, lTotalThreads, lSpinCount); - } - - auto pYYBarrier = (YY_BARRIER*)lpBarrier; - - pYYBarrier->lTotalThreads = lTotalThreads; - pYYBarrier->lRemainderThreads = lTotalThreads; - pYYBarrier->dwNumProcessors = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->NumberOfProcessors; - pYYBarrier->dwSpinCount = lSpinCount == -1 ? 2000 : lSpinCount; - - if ((pYYBarrier->hEvent[0] = CreateEventW(nullptr, TRUE, FALSE, nullptr)) == nullptr) - return FALSE; - - if ((pYYBarrier->hEvent[1] = CreateEventW(nullptr, TRUE, FALSE, nullptr)) == nullptr) - { - auto lStatus = GetLastError(); - CloseHandle(pYYBarrier->hEvent[0]); - SetLastError(lStatus); - return FALSE; - } - - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Windows 8 [desktop apps only] + //Windows Server 2012 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 12, + BOOL, + WINAPI, + InitializeSynchronizationBarrier, + _Out_ LPSYNCHRONIZATION_BARRIER lpBarrier, + _In_ LONG lTotalThreads, + _In_ LONG lSpinCount + ) + { + if (auto const pEnterSynchronizationBarrier = try_get_InitializeSynchronizationBarrier()) + { + return pEnterSynchronizationBarrier(lpBarrier, lTotalThreads, lSpinCount); + } + + auto pYYBarrier = (YY_BARRIER*)lpBarrier; + + pYYBarrier->lTotalThreads = lTotalThreads; + pYYBarrier->lRemainderThreads = lTotalThreads; + pYYBarrier->dwNumProcessors = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->NumberOfProcessors; + pYYBarrier->dwSpinCount = lSpinCount == -1 ? 2000 : lSpinCount; + + if ((pYYBarrier->hEvent[0] = CreateEventW(nullptr, TRUE, FALSE, nullptr)) == nullptr) + return FALSE; + + if ((pYYBarrier->hEvent[1] = CreateEventW(nullptr, TRUE, FALSE, nullptr)) == nullptr) + { + auto lStatus = GetLastError(); + CloseHandle(pYYBarrier->hEvent[0]); + SetLastError(lStatus); + return FALSE; + } + + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - //Windows 8 [desktop apps only] - //Windows Server 2012 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - EnterSynchronizationBarrier, - _Inout_ LPSYNCHRONIZATION_BARRIER lpBarrier, - _In_ DWORD dwFlags - ) - { - if (auto const pEnterSynchronizationBarrier = try_get_EnterSynchronizationBarrier()) - { - return pEnterSynchronizationBarrier(lpBarrier, dwFlags); - } - - if (dwFlags & ~(SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY | SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY | SYNCHRONIZATION_BARRIER_FLAGS_NO_DELETE)) - { - internal::RaiseStatus(STATUS_INVALID_PARAMETER); - } - - DWORD dwRtlBarrierFlags = dwFlags & (SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY | SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY); - - if ((dwFlags & SYNCHRONIZATION_BARRIER_FLAGS_NO_DELETE) == 0) - dwRtlBarrierFlags |= 0x10000; + //Windows 8 [desktop apps only] + //Windows Server 2012 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + EnterSynchronizationBarrier, + _Inout_ LPSYNCHRONIZATION_BARRIER lpBarrier, + _In_ DWORD dwFlags + ) + { + if (auto const pEnterSynchronizationBarrier = try_get_EnterSynchronizationBarrier()) + { + return pEnterSynchronizationBarrier(lpBarrier, dwFlags); + } + + if (dwFlags & ~(SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY | SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY | SYNCHRONIZATION_BARRIER_FLAGS_NO_DELETE)) + { + internal::RaiseStatus(STATUS_INVALID_PARAMETER); + } + + DWORD dwRtlBarrierFlags = dwFlags & (SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY | SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY); + + if ((dwFlags & SYNCHRONIZATION_BARRIER_FLAGS_NO_DELETE) == 0) + dwRtlBarrierFlags |= 0x10000; - - auto pYYBarrier = (YY_BARRIER*)lpBarrier; + + auto pYYBarrier = (YY_BARRIER*)lpBarrier; - auto Current = InterlockedDecrement(&pYYBarrier->lRemainderThreads); - - const auto GroupStatus = Current & 0x80000000; - - const auto EventIndex = Current >= 0 ? 1 : 0; - DWORD dwRemainderThreads = Current & 0x7FFFFFFF; - - if (dwRemainderThreads == 0) - { - //剩余数量已经变成 0 了,我们需要唤醒之前等待的线程,并且翻转 EventIndex - const auto NewEventIndex = EventIndex ? 0 : 1; - - - //将下次需要使用的事件设置为 无信号状态 - auto NewEvent = pYYBarrier->hEvent[NewEventIndex]; - if (size_t(NewEvent) & 0x1) - { - auto hEvent = (HANDLE)(size_t(NewEvent) & ~size_t(0x1)); - pYYBarrier->hEvent[NewEventIndex] = hEvent; - - ResetEvent(hEvent); - } - - //吧当前的 GroupStatus 状态置反,然后组合成新的 RemainderThreads - auto NewRemainderThreads = pYYBarrier->lTotalThreads | (GroupStatus ^ 0x80000000); - - //此标记后将自动删除 Barrier,后续也将无法再次利用 Barrier - if (dwRtlBarrierFlags & 0x10000) - { - pYYBarrier->lTotalThreads = 1; - } - pYYBarrier->lRemainderThreads = NewRemainderThreads; - - auto Event = pYYBarrier->hEvent[EventIndex]; - if (size_t(Event) & 0x1) - { - SetEvent((HANDLE)(size_t(Event) & ~size_t(0x1))); - } - - return TRUE; - } - - if (pYYBarrier->dwSpinCount && ((dwRemainderThreads < pYYBarrier->dwNumProcessors && (dwRtlBarrierFlags & SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY) == 0) || (dwRtlBarrierFlags & SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY))) - { - DWORD CurrentSpinCount = 0; - for (;;) - { - if ((pYYBarrier->lRemainderThreads & 0x80000000) != GroupStatus) - { - //自旋等待成功 - auto dwSpinCount = pYYBarrier->dwSpinCount; - - if (dwSpinCount < 5000) - { - pYYBarrier->dwSpinCount = dwSpinCount + 1; - } - - goto __retrun; - } - - //指定 SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY 标识时会始终自旋,所以没有此标识时我们无需更新当前自旋次数 - if ((dwRtlBarrierFlags & SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY) == 0) - { - ++CurrentSpinCount; - } - - YieldProcessor(); - - auto dwSpinCount = pYYBarrier->dwSpinCount; - - if (CurrentSpinCount >= dwSpinCount) - { - if (dwSpinCount > 50) - { - pYYBarrier->dwSpinCount = dwSpinCount - 1; - } - - break; - } - } - } + auto Current = InterlockedDecrement(&pYYBarrier->lRemainderThreads); + + const auto GroupStatus = Current & 0x80000000; + + const auto EventIndex = Current >= 0 ? 1 : 0; + DWORD dwRemainderThreads = Current & 0x7FFFFFFF; + + if (dwRemainderThreads == 0) + { + //剩余数量已经变成 0 了,我们需要唤醒之前等待的线程,并且翻转 EventIndex + const auto NewEventIndex = EventIndex ? 0 : 1; + + + //将下次需要使用的事件设置为 无信号状态 + auto NewEvent = pYYBarrier->hEvent[NewEventIndex]; + if (size_t(NewEvent) & 0x1) + { + auto hEvent = (HANDLE)(size_t(NewEvent) & ~size_t(0x1)); + pYYBarrier->hEvent[NewEventIndex] = hEvent; + + ResetEvent(hEvent); + } + + //吧当前的 GroupStatus 状态置反,然后组合成新的 RemainderThreads + auto NewRemainderThreads = pYYBarrier->lTotalThreads | (GroupStatus ^ 0x80000000); + + //此标记后将自动删除 Barrier,后续也将无法再次利用 Barrier + if (dwRtlBarrierFlags & 0x10000) + { + pYYBarrier->lTotalThreads = 1; + } + pYYBarrier->lRemainderThreads = NewRemainderThreads; + + auto Event = pYYBarrier->hEvent[EventIndex]; + if (size_t(Event) & 0x1) + { + SetEvent((HANDLE)(size_t(Event) & ~size_t(0x1))); + } + + return TRUE; + } + + if (pYYBarrier->dwSpinCount && ((dwRemainderThreads < pYYBarrier->dwNumProcessors && (dwRtlBarrierFlags & SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY) == 0) || (dwRtlBarrierFlags & SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY))) + { + DWORD CurrentSpinCount = 0; + for (;;) + { + if ((pYYBarrier->lRemainderThreads & 0x80000000) != GroupStatus) + { + //自旋等待成功 + auto dwSpinCount = pYYBarrier->dwSpinCount; + + if (dwSpinCount < 5000) + { + pYYBarrier->dwSpinCount = dwSpinCount + 1; + } + + goto __retrun; + } + + //指定 SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY 标识时会始终自旋,所以没有此标识时我们无需更新当前自旋次数 + if ((dwRtlBarrierFlags & SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY) == 0) + { + ++CurrentSpinCount; + } + + YieldProcessor(); + + auto dwSpinCount = pYYBarrier->dwSpinCount; + + if (CurrentSpinCount >= dwSpinCount) + { + if (dwSpinCount > 50) + { + pYYBarrier->dwSpinCount = dwSpinCount - 1; + } + + break; + } + } + } - { - //如果没有 0x1标记则添加一个,来指示已经 WaitForSingleObject 了 - HANDLE hEnvet = pYYBarrier->hEvent[EventIndex]; - if ((size_t(hEnvet) & 0x1) == 0) - { - pYYBarrier->hEvent[EventIndex] = HANDLE(size_t(hEnvet) | 0x1); - } + { + //如果没有 0x1标记则添加一个,来指示已经 WaitForSingleObject 了 + HANDLE hEnvet = pYYBarrier->hEvent[EventIndex]; + if ((size_t(hEnvet) & 0x1) == 0) + { + pYYBarrier->hEvent[EventIndex] = HANDLE(size_t(hEnvet) | 0x1); + } - if ((pYYBarrier->lRemainderThreads & 0x80000000) == GroupStatus) - WaitForSingleObject((HANDLE)(size_t(hEnvet) & ~size_t(0x1)), INFINITE); - } + if ((pYYBarrier->lRemainderThreads & 0x80000000) == GroupStatus) + WaitForSingleObject((HANDLE)(size_t(hEnvet) & ~size_t(0x1)), INFINITE); + } - __retrun: + __retrun: - if (dwRtlBarrierFlags & 0x10000) - InterlockedIncrement(&pYYBarrier->lTotalThreads); + if (dwRtlBarrierFlags & 0x10000) + InterlockedIncrement(&pYYBarrier->lTotalThreads); - return TRUE; - } + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Windows 8 [desktop apps only] - //Windows Server 2012 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 4, - BOOL, - WINAPI, - DeleteSynchronizationBarrier, - _Inout_ LPSYNCHRONIZATION_BARRIER lpBarrier - ) - { - if (auto const pDeleteSynchronizationBarrier = try_get_DeleteSynchronizationBarrier()) - { - return pDeleteSynchronizationBarrier(lpBarrier); - } - - auto pYYBarrier = (YY_BARRIER*)lpBarrier; - - //自旋等待所有 EnterSynchronizationBarrier 都进入就绪 - for (; pYYBarrier->lTotalThreads != (pYYBarrier->lRemainderThreads & 0x7FFFFFFF);) - { - //等待16毫秒 - Sleep(16); - } - - BOOL bSuccess = FALSE; - if (auto hEnent = (HANDLE)(size_t(pYYBarrier->hEvent[0]) & ~size_t(0x1))) - CloseHandle(hEnent); - - if (auto hEnent = (HANDLE)(size_t(pYYBarrier->hEvent[1]) & ~size_t(0x1))) - CloseHandle(hEnent); - - //微软文档说的,这个函数总是返回 TRUE,但是微软Windows 8的实现略有问题,直接转发了 RtlDeleteBarrier,返回值并不正确 - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Windows 8 [desktop apps only] + //Windows Server 2012 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 4, + BOOL, + WINAPI, + DeleteSynchronizationBarrier, + _Inout_ LPSYNCHRONIZATION_BARRIER lpBarrier + ) + { + if (auto const pDeleteSynchronizationBarrier = try_get_DeleteSynchronizationBarrier()) + { + return pDeleteSynchronizationBarrier(lpBarrier); + } + + auto pYYBarrier = (YY_BARRIER*)lpBarrier; + + //自旋等待所有 EnterSynchronizationBarrier 都进入就绪 + for (; pYYBarrier->lTotalThreads != (pYYBarrier->lRemainderThreads & 0x7FFFFFFF);) + { + //等待16毫秒 + Sleep(16); + } + + BOOL bSuccess = FALSE; + if (auto hEnent = (HANDLE)(size_t(pYYBarrier->hEvent[0]) & ~size_t(0x1))) + CloseHandle(hEnent); + + if (auto hEnent = (HANDLE)(size_t(pYYBarrier->hEvent[1]) & ~size_t(0x1))) + CloseHandle(hEnent); + + //微软文档说的,这个函数总是返回 TRUE,但是微软Windows 8的实现略有问题,直接转发了 RtlDeleteBarrier,返回值并不正确 + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Windows 8 [desktop apps | UWP apps] - //Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_synch_l1_2_0, - 16, - BOOL, - WINAPI, - WaitOnAddress, - _In_reads_bytes_(AddressSize) volatile VOID* Address, - _In_reads_bytes_(AddressSize) PVOID CompareAddress, - _In_ SIZE_T AddressSize, - _In_opt_ DWORD dwMilliseconds - ) - { - if (auto const pWaitOnAddress = try_get_WaitOnAddress()) - { - return pWaitOnAddress(Address, CompareAddress, AddressSize, dwMilliseconds); - } - - //参数检查,AddressSize 只能 为 1,2,4,8 - if (AddressSize > 8 || AddressSize == 0 || ((AddressSize - 1) & AddressSize) != 0) - { - //STATUS_INVALID_PARAMETER - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - YY_ADDRESS_WAIT_BLOCK WaitBlock; - WaitBlock.Address = Address; - WaitBlock.back = nullptr; - WaitBlock.notify = nullptr; - WaitBlock.next = nullptr; - WaitBlock.flag = 1; - - internal::RtlpAddWaitBlockToWaitList(&WaitBlock); - - bool bSame; - switch (AddressSize) - { - case 1: - bSame = *(volatile byte*)Address == *(volatile byte*)CompareAddress; - break; - case 2: - bSame = *(volatile WORD*)Address == *(volatile WORD*)CompareAddress; - break; - case 4: - bSame = *(volatile DWORD*)Address == *(volatile DWORD*)CompareAddress; - break; - default: - //case 8: +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Windows 8 [desktop apps | UWP apps] + //Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_synch_l1_2_0, + 16, + BOOL, + WINAPI, + WaitOnAddress, + _In_reads_bytes_(AddressSize) volatile VOID* Address, + _In_reads_bytes_(AddressSize) PVOID CompareAddress, + _In_ SIZE_T AddressSize, + _In_opt_ DWORD dwMilliseconds + ) + { + if (auto const pWaitOnAddress = try_get_WaitOnAddress()) + { + return pWaitOnAddress(Address, CompareAddress, AddressSize, dwMilliseconds); + } + + //参数检查,AddressSize 只能 为 1,2,4,8 + if (AddressSize > 8 || AddressSize == 0 || ((AddressSize - 1) & AddressSize) != 0) + { + //STATUS_INVALID_PARAMETER + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + YY_ADDRESS_WAIT_BLOCK WaitBlock; + WaitBlock.Address = Address; + WaitBlock.back = nullptr; + WaitBlock.notify = nullptr; + WaitBlock.next = nullptr; + WaitBlock.flag = 1; + + internal::RtlpAddWaitBlockToWaitList(&WaitBlock); + + bool bSame; + switch (AddressSize) + { + case 1: + bSame = *(volatile byte*)Address == *(volatile byte*)CompareAddress; + break; + case 2: + bSame = *(volatile WORD*)Address == *(volatile WORD*)CompareAddress; + break; + case 4: + bSame = *(volatile DWORD*)Address == *(volatile DWORD*)CompareAddress; + break; + default: + //case 8: #if _WIN64 - //64位自身能保证操作的原子性 - bSame = *(volatile unsigned long long*)Address == *(volatile unsigned long long*)CompareAddress; + //64位自身能保证操作的原子性 + bSame = *(volatile unsigned long long*)Address == *(volatile unsigned long long*)CompareAddress; #else - bSame = InterlockedCompareExchange64((volatile long long*)Address, 0, 0) == *(volatile long long*)CompareAddress; + bSame = InterlockedCompareExchange64((volatile long long*)Address, 0, 0) == *(volatile long long*)CompareAddress; #endif - break; - } + break; + } - if (!bSame) - { - //结果不相同,我们从等待队列移除 - internal::RtlpWaitOnAddressRemoveWaitBlock(&WaitBlock); - return TRUE; - } + if (!bSame) + { + //结果不相同,我们从等待队列移除 + internal::RtlpWaitOnAddressRemoveWaitBlock(&WaitBlock); + return TRUE; + } - LARGE_INTEGER TimeOut; + LARGE_INTEGER TimeOut; - auto Status = internal::RtlpWaitOnAddressWithTimeout(&WaitBlock, internal::BaseFormatTimeOut(&TimeOut, dwMilliseconds)); + auto Status = internal::RtlpWaitOnAddressWithTimeout(&WaitBlock, internal::BaseFormatTimeOut(&TimeOut, dwMilliseconds)); - if (Status) - { - internal::BaseSetLastNTError(Status); - } + if (Status) + { + internal::BaseSetLastNTError(Status); + } - return Status < 0 || Status == STATUS_TIMEOUT ? FALSE : TRUE; - } + return Status < 0 || Status == STATUS_TIMEOUT ? FALSE : TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Windows 8 [desktop apps | UWP apps] - //Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_synch_l1_2_0, - 4, - VOID, - WINAPI, - WakeByAddressSingle, - _In_ PVOID Address - ) - { - if (auto const pWakeByAddressSingle = try_get_WakeByAddressSingle()) - { - return pWakeByAddressSingle(Address); - } - - internal::RtlpWakeByAddress(Address, FALSE); - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Windows 8 [desktop apps | UWP apps] + //Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_synch_l1_2_0, + 4, + VOID, + WINAPI, + WakeByAddressSingle, + _In_ PVOID Address + ) + { + if (auto const pWakeByAddressSingle = try_get_WakeByAddressSingle()) + { + return pWakeByAddressSingle(Address); + } + + internal::RtlpWakeByAddress(Address, FALSE); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Windows 8 [desktop apps | UWP apps] - //Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_synch_l1_2_0, - 4, - VOID, - WINAPI, - WakeByAddressAll, - _In_ PVOID Address - ) - { - if (auto const pWakeByAddressAll = try_get_WakeByAddressAll()) - { - return pWakeByAddressAll(Address); - } - - internal::RtlpWakeByAddress(Address, TRUE); - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Windows 8 [desktop apps | UWP apps] + //Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_synch_l1_2_0, + 4, + VOID, + WINAPI, + WakeByAddressAll, + _In_ PVOID Address + ) + { + if (auto const pWakeByAddressAll = try_get_WakeByAddressAll()) + { + return pWakeByAddressAll(Address); + } + + internal::RtlpWakeByAddress(Address, TRUE); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - // Minimum supported client Windows 7 [desktop apps | UWP apps] - // Minimum supported server Windows Server 2008 R2 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 28, - BOOL, - WINAPI, - SetWaitableTimerEx, - _In_ HANDLE _hTimer, - _In_ const LARGE_INTEGER* _lpDueTime, - _In_ LONG _iPeriod, - _In_opt_ PTIMERAPCROUTINE _pfnCompletionRoutine, - _In_opt_ LPVOID _lpArgToCompletionRoutine, - _In_opt_ PREASON_CONTEXT _pWakeContext, - _In_ ULONG _uTolerableDelay - ) - { - if (auto const _pfnSetWaitableTimerEx = try_get_SetWaitableTimerEx()) - { - return _pfnSetWaitableTimerEx(_hTimer, _lpDueTime, _iPeriod, _pfnCompletionRoutine, _lpArgToCompletionRoutine, _pWakeContext, _uTolerableDelay); - } - - UNREFERENCED_PARAMETER(_uTolerableDelay); - - LSTATUS _lStatus = ERROR_SUCCESS; - // 检查 _pWakeContext 参数是否合法 - // Version 必须为 POWER_REQUEST_CONTEXT_VERSION - // Flags 无效标记可参考 DIAGNOSTIC_REASON_INVALID_FLAGS,此外 POWER_REQUEST_CONTEXT_DETAILED_STRING,POWER_REQUEST_CONTEXT_SIMPLE_STRING 必须设置。 - // 有种特殊情况是 DIAGNOSTIC_REASON_NOT_SPECIFIED,它会被直接放行。不要问我……逆向结果如此,微软文档并未公开。 - // 微软文档链接:https://learn.microsoft.com/zh-cn/windows/win32/api/minwinbase/ns-minwinbase-reason_context - do - { - if (!_pWakeContext) - break; - - if (_pWakeContext->Version != POWER_REQUEST_CONTEXT_VERSION) - { - _lStatus = ERROR_INVALID_PARAMETER; - break; - } - - const auto _fFlags = _pWakeContext->Flags; - - // 微软原版就是如此,定义 DIAGNOSTIC_REASON_NOT_SPECIFIED 时会直接放行…… - // 我们保持微软的逻辑,这时不进一步的参数验证。 - if (_fFlags & DIAGNOSTIC_REASON_NOT_SPECIFIED) - break; - - // 无效的Flags组合 - if ((_fFlags & DIAGNOSTIC_REASON_INVALID_FLAGS) != 0 - || (_fFlags & (POWER_REQUEST_CONTEXT_DETAILED_STRING | POWER_REQUEST_CONTEXT_SIMPLE_STRING)) == 0) - { - _lStatus = ERROR_INVALID_PARAMETER; - break; - } - - if (_fFlags & POWER_REQUEST_CONTEXT_DETAILED_STRING) - { - if(_pWakeContext->Reason.Detailed.LocalizedReasonId > 0xFFFFu) - { - _lStatus = ERROR_INVALID_PARAMETER; - break; - } - } - } while (false); - - if (_lStatus != ERROR_SUCCESS) - { - SetLastError(_lStatus); - return FALSE; - } - - return SetWaitableTimer(_hTimer, _lpDueTime, _iPeriod, _pfnCompletionRoutine, _lpArgToCompletionRoutine, _pWakeContext != nullptr); - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + // Minimum supported client Windows 7 [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008 R2 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 28, + BOOL, + WINAPI, + SetWaitableTimerEx, + _In_ HANDLE _hTimer, + _In_ const LARGE_INTEGER* _lpDueTime, + _In_ LONG _iPeriod, + _In_opt_ PTIMERAPCROUTINE _pfnCompletionRoutine, + _In_opt_ LPVOID _lpArgToCompletionRoutine, + _In_opt_ PREASON_CONTEXT _pWakeContext, + _In_ ULONG _uTolerableDelay + ) + { + if (auto const _pfnSetWaitableTimerEx = try_get_SetWaitableTimerEx()) + { + return _pfnSetWaitableTimerEx(_hTimer, _lpDueTime, _iPeriod, _pfnCompletionRoutine, _lpArgToCompletionRoutine, _pWakeContext, _uTolerableDelay); + } + + UNREFERENCED_PARAMETER(_uTolerableDelay); + + LSTATUS _lStatus = ERROR_SUCCESS; + // 检查 _pWakeContext 参数是否合法 + // Version 必须为 POWER_REQUEST_CONTEXT_VERSION + // Flags 无效标记可参考 DIAGNOSTIC_REASON_INVALID_FLAGS,此外 POWER_REQUEST_CONTEXT_DETAILED_STRING,POWER_REQUEST_CONTEXT_SIMPLE_STRING 必须设置。 + // 有种特殊情况是 DIAGNOSTIC_REASON_NOT_SPECIFIED,它会被直接放行。不要问我……逆向结果如此,微软文档并未公开。 + // 微软文档链接:https://learn.microsoft.com/zh-cn/windows/win32/api/minwinbase/ns-minwinbase-reason_context + do + { + if (!_pWakeContext) + break; + + if (_pWakeContext->Version != POWER_REQUEST_CONTEXT_VERSION) + { + _lStatus = ERROR_INVALID_PARAMETER; + break; + } + + const auto _fFlags = _pWakeContext->Flags; + + // 微软原版就是如此,定义 DIAGNOSTIC_REASON_NOT_SPECIFIED 时会直接放行…… + // 我们保持微软的逻辑,这时不进一步的参数验证。 + if (_fFlags & DIAGNOSTIC_REASON_NOT_SPECIFIED) + break; + + // 无效的Flags组合 + if ((_fFlags & DIAGNOSTIC_REASON_INVALID_FLAGS) != 0 + || (_fFlags & (POWER_REQUEST_CONTEXT_DETAILED_STRING | POWER_REQUEST_CONTEXT_SIMPLE_STRING)) == 0) + { + _lStatus = ERROR_INVALID_PARAMETER; + break; + } + + if (_fFlags & POWER_REQUEST_CONTEXT_DETAILED_STRING) + { + if(_pWakeContext->Reason.Detailed.LocalizedReasonId > 0xFFFFu) + { + _lStatus = ERROR_INVALID_PARAMETER; + break; + } + } + } while (false); + + if (_lStatus != ERROR_SUCCESS) + { + SetLastError(_lStatus); + return FALSE; + } + + return SetWaitableTimer(_hTimer, _lpDueTime, _iPeriod, _pfnCompletionRoutine, _lpArgToCompletionRoutine, _pWakeContext != nullptr); + } #endif } //namespace YY::Thunks diff --git a/src/Thunks/api-ms-win-core-sysinfo.hpp b/src/Thunks/api-ms-win-core-sysinfo.hpp index 1b7da55..8e61da2 100644 --- a/src/Thunks/api-ms-win-core-sysinfo.hpp +++ b/src/Thunks/api-ms-win-core-sysinfo.hpp @@ -1,406 +1,400 @@  -namespace YY +namespace YY::Thunks { - namespace Thunks - { - -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - kernel32, - 0, - ULONGLONG, - WINAPI, - GetTickCount64, - VOID - ) - { - if (auto const pGetTickCount64 = try_get_GetTickCount64()) - { - return pGetTickCount64(); - } - - __pragma(warning(suppress:28159)) - return GetTickCount(); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + kernel32, + 0, + ULONGLONG, + WINAPI, + GetTickCount64, + VOID + ) + { + if (auto const pGetTickCount64 = try_get_GetTickCount64()) + { + return pGetTickCount64(); + } + + __pragma(warning(suppress:28159)) + return GetTickCount(); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Windows 8, Windows Server 2012 - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - GetSystemTimePreciseAsFileTime, - _Out_ LPFILETIME lpSystemTimeAsFileTime - ) - { - if (auto const pGetSystemTimePreciseAsFileTime = try_get_GetSystemTimePreciseAsFileTime()) - { - return pGetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime); - } - - return GetSystemTimeAsFileTime(lpSystemTimeAsFileTime); - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Windows 8, Windows Server 2012 + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + GetSystemTimePreciseAsFileTime, + _Out_ LPFILETIME lpSystemTimeAsFileTime + ) + { + if (auto const pGetSystemTimePreciseAsFileTime = try_get_GetSystemTimePreciseAsFileTime()) + { + return pGetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime); + } + + return GetSystemTimeAsFileTime(lpSystemTimeAsFileTime); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WINXPSP3) - - //Windows Vista, Windows XP Professional x64 Edition, Windows XP with SP3 [desktop apps | UWP apps] - //Windows Server 2003 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - GetLogicalProcessorInformation, - _Out_writes_bytes_to_opt_(*ReturnedLength, *ReturnedLength) PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, - _Inout_ PDWORD ReturnedLength - ) - { - if (auto pGetLogicalProcessorInformation = try_get_GetLogicalProcessorInformation()) - { - return pGetLogicalProcessorInformation(Buffer, ReturnedLength); - } - - SetLastError(ERROR_INVALID_FUNCTION); - return FALSE; - } +#if (YY_Thunks_Target < __WindowsNT5_1_SP3) + + //Windows Vista, Windows XP Professional x64 Edition, Windows XP with SP3 [desktop apps | UWP apps] + //Windows Server 2003 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + GetLogicalProcessorInformation, + _Out_writes_bytes_to_opt_(*ReturnedLength, *ReturnedLength) PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, + _Inout_ PDWORD ReturnedLength + ) + { + if (auto pGetLogicalProcessorInformation = try_get_GetLogicalProcessorInformation()) + { + return pGetLogicalProcessorInformation(Buffer, ReturnedLength); + } + + SetLastError(ERROR_INVALID_FUNCTION); + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - //Windows 7, Windows Server 2008 R2 - __DEFINE_THUNK( - kernel32, - 12, - _Success_(return) - BOOL, - WINAPI, - GetLogicalProcessorInformationEx, - _In_ LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType, - _Out_writes_bytes_to_opt_(*ReturnedLength, *ReturnedLength) PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer, - _Inout_ PDWORD ReturnedLength - ) - { - if (auto pGetLogicalProcessorInformationEx = try_get_GetLogicalProcessorInformationEx()) - { - return pGetLogicalProcessorInformationEx(RelationshipType, Buffer, ReturnedLength); - } - - - if (!ReturnedLength) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - const auto cbBuffer = *ReturnedLength; - - if (cbBuffer != 0 && Buffer == nullptr) - { - SetLastError(ERROR_NOACCESS); - return FALSE; - } - - const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; - LSTATUS lStatus = ERROR_SUCCESS; - - SYSTEM_LOGICAL_PROCESSOR_INFORMATION* pProcessorInfo = nullptr; - DWORD cbLogicalProcessorInformation = 0; - - - for (; GetLogicalProcessorInformation(pProcessorInfo, &cbLogicalProcessorInformation) == FALSE;) - { - lStatus = GetLastError(); - - if (ERROR_INSUFFICIENT_BUFFER == lStatus) - { - if (pProcessorInfo) - { - auto pNewBuffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION*)HeapReAlloc(ProcessHeap, 0, pProcessorInfo, cbLogicalProcessorInformation); - if (pNewBuffer) - { - pProcessorInfo = pNewBuffer; - continue; - } - } - else - { - pProcessorInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION*)HeapAlloc(ProcessHeap, 0, cbLogicalProcessorInformation); - - if (pProcessorInfo) - continue; - } - - lStatus = ERROR_NOT_ENOUGH_MEMORY; - } - - goto __End; - } - - - { - const auto pProcessorInfoLastItem = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION*)((byte*)pProcessorInfo + cbLogicalProcessorInformation - sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); - - DWORD cbBufferUsed = 0; - - - - for (auto pProcessorInfoStart = pProcessorInfo; pProcessorInfoStart <= pProcessorInfoLastItem; ++pProcessorInfoStart) - { - if (RelationshipType == LOGICAL_PROCESSOR_RELATIONSHIP::RelationAll - || pProcessorInfoStart->Relationship == RelationshipType) - { - DWORD cbInfoNeed; - - switch (pProcessorInfoStart->Relationship) - { - case RelationProcessorCore: - case RelationProcessorPackage: - cbInfoNeed = RTL_SIZEOF_THROUGH_FIELD(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Processor); - break; - case RelationNumaNode: - cbInfoNeed = RTL_SIZEOF_THROUGH_FIELD(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, NumaNode); - break; - case RelationCache: - cbInfoNeed = RTL_SIZEOF_THROUGH_FIELD(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Cache); - break; - default: - cbInfoNeed = 0; - break; - } - - //不支持传输此类型 - if (0 == cbInfoNeed) - continue; - - cbBufferUsed += cbInfoNeed; - - if (cbBuffer >= cbBufferUsed) - { - auto pInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)((byte*)Buffer + cbBufferUsed); - - memset(pInfo, 0, cbInfoNeed); - - pInfo->Size = cbInfoNeed; - pInfo->Relationship = pProcessorInfoStart->Relationship; - - switch (pProcessorInfoStart->Relationship) - { - case RelationProcessorCore: - case RelationProcessorPackage: - pInfo->Processor.Flags = pProcessorInfoStart->ProcessorCore.Flags; - pInfo->Processor.GroupCount = 1; - pInfo->Processor.GroupMask->Mask = pProcessorInfoStart->ProcessorMask; - break; - case RelationNumaNode: - pInfo->NumaNode.NodeNumber = pProcessorInfoStart->NumaNode.NodeNumber; - pInfo->NumaNode.GroupMask.Mask = pProcessorInfoStart->ProcessorMask; - break; - case RelationCache: - pInfo->Cache.Level = pProcessorInfoStart->Cache.Level; - pInfo->Cache.Associativity = pProcessorInfoStart->Cache.Associativity; - pInfo->Cache.LineSize = pProcessorInfoStart->Cache.LineSize; - pInfo->Cache.CacheSize = pProcessorInfoStart->Cache.Size; - pInfo->Cache.Type = pProcessorInfoStart->Cache.Type; - pInfo->Cache.GroupMask.Mask= pProcessorInfoStart->ProcessorMask; - break; - } - } - } - } - - - //传输 RelationGroup 信息,这里只能假设只有一组CPU - if (RelationshipType == LOGICAL_PROCESSOR_RELATIONSHIP::RelationAll - || RelationGroup == RelationshipType) - { - const auto cbInfoNeed = RTL_SIZEOF_THROUGH_FIELD(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Group); - - cbBufferUsed += cbInfoNeed; - - if (cbBuffer >= cbBufferUsed) - { - auto pInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)((byte*)Buffer + cbBufferUsed); - - memset(pInfo, 0, cbInfoNeed); - - pInfo->Size = cbInfoNeed; - pInfo->Relationship = RelationGroup; - - pInfo->Group.ActiveGroupCount = 1; - pInfo->Group.MaximumGroupCount = 1; - - SYSTEM_INFO SystemInfo; - - GetSystemInfo(&SystemInfo); - - pInfo->Group.GroupInfo->ActiveProcessorMask = SystemInfo.dwActiveProcessorMask; - pInfo->Group.GroupInfo->ActiveProcessorCount = internal::BitsCount(static_cast(SystemInfo.dwActiveProcessorMask)); - pInfo->Group.GroupInfo->MaximumProcessorCount = static_cast(SystemInfo.dwNumberOfProcessors); - } - } - - *ReturnedLength = cbBufferUsed; - - if (cbBufferUsed > cbBuffer) - { - //缓冲区不足 - lStatus = ERROR_INSUFFICIENT_BUFFER; - } - } - - __End: - if (pProcessorInfo) - HeapFree(ProcessHeap, 0, pProcessorInfo); - - if (lStatus != ERROR_SUCCESS) - { - SetLastError(lStatus); - - return FALSE; - } - else - { - return TRUE; - } - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + //Windows 7, Windows Server 2008 R2 + __DEFINE_THUNK( + kernel32, + 12, + _Success_(return) + BOOL, + WINAPI, + GetLogicalProcessorInformationEx, + _In_ LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType, + _Out_writes_bytes_to_opt_(*ReturnedLength, *ReturnedLength) PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer, + _Inout_ PDWORD ReturnedLength + ) + { + if (auto pGetLogicalProcessorInformationEx = try_get_GetLogicalProcessorInformationEx()) + { + return pGetLogicalProcessorInformationEx(RelationshipType, Buffer, ReturnedLength); + } + + + if (!ReturnedLength) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + const auto cbBuffer = *ReturnedLength; + + if (cbBuffer != 0 && Buffer == nullptr) + { + SetLastError(ERROR_NOACCESS); + return FALSE; + } + + const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; + LSTATUS lStatus = ERROR_SUCCESS; + + SYSTEM_LOGICAL_PROCESSOR_INFORMATION* pProcessorInfo = nullptr; + DWORD cbLogicalProcessorInformation = 0; + + + for (; GetLogicalProcessorInformation(pProcessorInfo, &cbLogicalProcessorInformation) == FALSE;) + { + lStatus = GetLastError(); + + if (ERROR_INSUFFICIENT_BUFFER == lStatus) + { + if (pProcessorInfo) + { + auto pNewBuffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION*)HeapReAlloc(ProcessHeap, 0, pProcessorInfo, cbLogicalProcessorInformation); + if (pNewBuffer) + { + pProcessorInfo = pNewBuffer; + continue; + } + } + else + { + pProcessorInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION*)HeapAlloc(ProcessHeap, 0, cbLogicalProcessorInformation); + + if (pProcessorInfo) + continue; + } + + lStatus = ERROR_NOT_ENOUGH_MEMORY; + } + + goto __End; + } + + + { + const auto pProcessorInfoLastItem = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION*)((byte*)pProcessorInfo + cbLogicalProcessorInformation - sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); + + DWORD cbBufferUsed = 0; + + + + for (auto pProcessorInfoStart = pProcessorInfo; pProcessorInfoStart <= pProcessorInfoLastItem; ++pProcessorInfoStart) + { + if (RelationshipType == LOGICAL_PROCESSOR_RELATIONSHIP::RelationAll + || pProcessorInfoStart->Relationship == RelationshipType) + { + DWORD cbInfoNeed; + + switch (pProcessorInfoStart->Relationship) + { + case RelationProcessorCore: + case RelationProcessorPackage: + cbInfoNeed = RTL_SIZEOF_THROUGH_FIELD(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Processor); + break; + case RelationNumaNode: + cbInfoNeed = RTL_SIZEOF_THROUGH_FIELD(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, NumaNode); + break; + case RelationCache: + cbInfoNeed = RTL_SIZEOF_THROUGH_FIELD(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Cache); + break; + default: + cbInfoNeed = 0; + break; + } + + //不支持传输此类型 + if (0 == cbInfoNeed) + continue; + + cbBufferUsed += cbInfoNeed; + + if (cbBuffer >= cbBufferUsed) + { + auto pInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)((byte*)Buffer + cbBufferUsed); + + memset(pInfo, 0, cbInfoNeed); + + pInfo->Size = cbInfoNeed; + pInfo->Relationship = pProcessorInfoStart->Relationship; + + switch (pProcessorInfoStart->Relationship) + { + case RelationProcessorCore: + case RelationProcessorPackage: + pInfo->Processor.Flags = pProcessorInfoStart->ProcessorCore.Flags; + pInfo->Processor.GroupCount = 1; + pInfo->Processor.GroupMask->Mask = pProcessorInfoStart->ProcessorMask; + break; + case RelationNumaNode: + pInfo->NumaNode.NodeNumber = pProcessorInfoStart->NumaNode.NodeNumber; + pInfo->NumaNode.GroupMask.Mask = pProcessorInfoStart->ProcessorMask; + break; + case RelationCache: + pInfo->Cache.Level = pProcessorInfoStart->Cache.Level; + pInfo->Cache.Associativity = pProcessorInfoStart->Cache.Associativity; + pInfo->Cache.LineSize = pProcessorInfoStart->Cache.LineSize; + pInfo->Cache.CacheSize = pProcessorInfoStart->Cache.Size; + pInfo->Cache.Type = pProcessorInfoStart->Cache.Type; + pInfo->Cache.GroupMask.Mask= pProcessorInfoStart->ProcessorMask; + break; + } + } + } + } + + + //传输 RelationGroup 信息,这里只能假设只有一组CPU + if (RelationshipType == LOGICAL_PROCESSOR_RELATIONSHIP::RelationAll + || RelationGroup == RelationshipType) + { + const auto cbInfoNeed = RTL_SIZEOF_THROUGH_FIELD(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Group); + + cbBufferUsed += cbInfoNeed; + + if (cbBuffer >= cbBufferUsed) + { + auto pInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)((byte*)Buffer + cbBufferUsed); + + memset(pInfo, 0, cbInfoNeed); + + pInfo->Size = cbInfoNeed; + pInfo->Relationship = RelationGroup; + + pInfo->Group.ActiveGroupCount = 1; + pInfo->Group.MaximumGroupCount = 1; + + SYSTEM_INFO SystemInfo; + + GetSystemInfo(&SystemInfo); + + pInfo->Group.GroupInfo->ActiveProcessorMask = SystemInfo.dwActiveProcessorMask; + pInfo->Group.GroupInfo->ActiveProcessorCount = internal::BitsCount(static_cast(SystemInfo.dwActiveProcessorMask)); + pInfo->Group.GroupInfo->MaximumProcessorCount = static_cast(SystemInfo.dwNumberOfProcessors); + } + } + + *ReturnedLength = cbBufferUsed; + + if (cbBufferUsed > cbBuffer) + { + //缓冲区不足 + lStatus = ERROR_INSUFFICIENT_BUFFER; + } + } + + __End: + if (pProcessorInfo) + HeapFree(ProcessHeap, 0, pProcessorInfo); + + if (lStatus != ERROR_SUCCESS) + { + SetLastError(lStatus); + + return FALSE; + } + else + { + return TRUE; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WINXP) - - //Windows XP [desktop apps | UWP apps] - //Windows Server 2003 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - GetNativeSystemInfo, - _Out_ LPSYSTEM_INFO lpSystemInfo - ) - { - if (const auto pGetNativeSystemInfo = try_get_GetNativeSystemInfo()) - { - return pGetNativeSystemInfo(lpSystemInfo); - } - - - GetSystemInfo(lpSystemInfo); - } +#if (YY_Thunks_Target < __WindowsNT5_1) + + //Windows XP [desktop apps | UWP apps] + //Windows Server 2003 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + GetNativeSystemInfo, + _Out_ LPSYSTEM_INFO lpSystemInfo + ) + { + if (const auto pGetNativeSystemInfo = try_get_GetNativeSystemInfo()) + { + return pGetNativeSystemInfo(lpSystemInfo); + } + + GetSystemInfo(lpSystemInfo); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows XP [desktop apps | UWP apps] - //Windows Server 2003 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 20, - BOOL, - WINAPI, - GetProductInfo, - _In_ DWORD dwOSMajorVersion, - _In_ DWORD dwOSMinorVersion, - _In_ DWORD dwSpMajorVersion, - _In_ DWORD dwSpMinorVersion, - _Out_ PDWORD pdwReturnedProductType - ) - { - if (const auto pGetProductInfo = try_get_GetProductInfo()) - { - return pGetProductInfo(dwOSMajorVersion, dwOSMinorVersion, dwSpMajorVersion, dwSpMinorVersion, pdwReturnedProductType); - } - - if (!pdwReturnedProductType) - return FALSE; - - //故意不检测版本号,能凑合就尽可能的凑合吧…… - - DWORD dwReturnedProductType = PRODUCT_UNLICENSED; - - //由于不支持这个接口,所以系统版本必然是XP或者以下 - OSVERSIONINFOEXW VersionInfo = { sizeof(VersionInfo) }; - #pragma warning(suppress:4996 28159) - if (GetVersionExW((LPOSVERSIONINFOW)&VersionInfo)) - { - if (VersionInfo.wSuiteMask & VER_SUITE_ENTERPRISE) - { - dwReturnedProductType = PRODUCT_ENTERPRISE_SERVER; - } - else if (VersionInfo.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED) // VER_SUITE_SMALLBUSINESS 与 VER_SUITE_SMALLBUSINESS_RESTRICTED - { - dwReturnedProductType = PRODUCT_SMALLBUSINESS_SERVER; - } - else if (VersionInfo.wSuiteMask & VER_SUITE_EMBEDDED_RESTRICTED) // VER_SUITE_EMBEDDEDNT 与 VER_SUITE_EMBEDDED_RESTRICTED - { - dwReturnedProductType = PRODUCT_EMBEDDED; - } - else if (VersionInfo.wSuiteMask & VER_SUITE_DATACENTER) - { - dwReturnedProductType = PRODUCT_DATACENTER_SERVER; - } - else if (VersionInfo.wSuiteMask & VER_SUITE_PERSONAL) - { - dwReturnedProductType = PRODUCT_HOME_BASIC; - } - else if (VersionInfo.wSuiteMask & VER_SUITE_BLADE) - { - dwReturnedProductType = PRODUCT_WEB_SERVER; - } - else if (VersionInfo.wSuiteMask & VER_SUITE_STORAGE_SERVER) - { - dwReturnedProductType = PRODUCT_STORAGE_STANDARD_SERVER; - } - else if (VersionInfo.wSuiteMask & VER_SUITE_COMPUTE_SERVER) - { - dwReturnedProductType = PRODUCT_CLUSTER_SERVER; - } - else if (VersionInfo.wSuiteMask & VER_SUITE_WH_SERVER) - { - dwReturnedProductType = PRODUCT_HOME_SERVER; - } - else - { - if (VersionInfo.wProductType == VER_NT_WORKSTATION) - { - //如果目标系统是5.1,因为SuiteMask中检测了Home,所以这里只可能是专业版 - // - //如果目标系统是5.0、5.2,只可能是专业版。 - - dwReturnedProductType = PRODUCT_PROFESSIONAL; - } - else if (VersionInfo.wProductType == VER_NT_DOMAIN_CONTROLLER || VersionInfo.wProductType == VER_NT_SERVER) - { - //如果目标系统是5.1、5.2,因为SuiteMask中检测了Small Business Server、Web Edition、Enterprise Edition、 - //Datacenter Edition、Compute Cluster Server、Storage Server,所以这里只可能是Standard Edition - // - //如果目标系统是5.0,因为SuiteMask中检测了Datacenter Server,这里只能是 Advanced Server或者 Server,但是我没有找到 Advanced,姑且用 PRODUCT_STANDARD_SERVER 凑合吧。 - dwReturnedProductType = PRODUCT_STANDARD_SERVER; - } - else - { - //这是什么鬼? - dwReturnedProductType = PRODUCT_UNDEFINED; - } - } - } - - *pdwReturnedProductType = dwReturnedProductType; - - return dwReturnedProductType != PRODUCT_UNDEFINED; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows XP [desktop apps | UWP apps] + //Windows Server 2003 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 20, + BOOL, + WINAPI, + GetProductInfo, + _In_ DWORD dwOSMajorVersion, + _In_ DWORD dwOSMinorVersion, + _In_ DWORD dwSpMajorVersion, + _In_ DWORD dwSpMinorVersion, + _Out_ PDWORD pdwReturnedProductType + ) + { + if (const auto pGetProductInfo = try_get_GetProductInfo()) + { + return pGetProductInfo(dwOSMajorVersion, dwOSMinorVersion, dwSpMajorVersion, dwSpMinorVersion, pdwReturnedProductType); + } + + if (!pdwReturnedProductType) + return FALSE; + + //故意不检测版本号,能凑合就尽可能的凑合吧…… + + DWORD dwReturnedProductType = PRODUCT_UNLICENSED; + + //由于不支持这个接口,所以系统版本必然是XP或者以下 + OSVERSIONINFOEXW VersionInfo = { sizeof(VersionInfo) }; + #pragma warning(suppress:4996 28159) + if (GetVersionExW((LPOSVERSIONINFOW)&VersionInfo)) + { + if (VersionInfo.wSuiteMask & VER_SUITE_ENTERPRISE) + { + dwReturnedProductType = PRODUCT_ENTERPRISE_SERVER; + } + else if (VersionInfo.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED) // VER_SUITE_SMALLBUSINESS 与 VER_SUITE_SMALLBUSINESS_RESTRICTED + { + dwReturnedProductType = PRODUCT_SMALLBUSINESS_SERVER; + } + else if (VersionInfo.wSuiteMask & VER_SUITE_EMBEDDED_RESTRICTED) // VER_SUITE_EMBEDDEDNT 与 VER_SUITE_EMBEDDED_RESTRICTED + { + dwReturnedProductType = PRODUCT_EMBEDDED; + } + else if (VersionInfo.wSuiteMask & VER_SUITE_DATACENTER) + { + dwReturnedProductType = PRODUCT_DATACENTER_SERVER; + } + else if (VersionInfo.wSuiteMask & VER_SUITE_PERSONAL) + { + dwReturnedProductType = PRODUCT_HOME_BASIC; + } + else if (VersionInfo.wSuiteMask & VER_SUITE_BLADE) + { + dwReturnedProductType = PRODUCT_WEB_SERVER; + } + else if (VersionInfo.wSuiteMask & VER_SUITE_STORAGE_SERVER) + { + dwReturnedProductType = PRODUCT_STORAGE_STANDARD_SERVER; + } + else if (VersionInfo.wSuiteMask & VER_SUITE_COMPUTE_SERVER) + { + dwReturnedProductType = PRODUCT_CLUSTER_SERVER; + } + else if (VersionInfo.wSuiteMask & VER_SUITE_WH_SERVER) + { + dwReturnedProductType = PRODUCT_HOME_SERVER; + } + else + { + if (VersionInfo.wProductType == VER_NT_WORKSTATION) + { + //如果目标系统是5.1,因为SuiteMask中检测了Home,所以这里只可能是专业版 + // + //如果目标系统是5.0、5.2,只可能是专业版。 + + dwReturnedProductType = PRODUCT_PROFESSIONAL; + } + else if (VersionInfo.wProductType == VER_NT_DOMAIN_CONTROLLER || VersionInfo.wProductType == VER_NT_SERVER) + { + //如果目标系统是5.1、5.2,因为SuiteMask中检测了Small Business Server、Web Edition、Enterprise Edition、 + //Datacenter Edition、Compute Cluster Server、Storage Server,所以这里只可能是Standard Edition + // + //如果目标系统是5.0,因为SuiteMask中检测了Datacenter Server,这里只能是 Advanced Server或者 Server,但是我没有找到 Advanced,姑且用 PRODUCT_STANDARD_SERVER 凑合吧。 + dwReturnedProductType = PRODUCT_STANDARD_SERVER; + } + else + { + //这是什么鬼? + dwReturnedProductType = PRODUCT_UNDEFINED; + } + } + } + + *pdwReturnedProductType = dwReturnedProductType; + + return dwReturnedProductType != PRODUCT_UNDEFINED; + } #endif - }//namespace Thunks - -} //namespace YY +} //namespace YY::Thunks diff --git a/src/Thunks/api-ms-win-core-systemtopology.hpp b/src/Thunks/api-ms-win-core-systemtopology.hpp index 9a74d21..0b2ba38 100644 --- a/src/Thunks/api-ms-win-core-systemtopology.hpp +++ b/src/Thunks/api-ms-win-core-systemtopology.hpp @@ -1,241 +1,235 @@  -namespace YY +namespace YY::Thunks { - namespace Thunks - { - -#if (YY_Thunks_Support_Version < NTDDI_WINXPSP2) - - //Windows Vista, Windows XP Professional x64 Edition, Windows XP with SP2, Windows Server 2003 - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - GetNumaNodeProcessorMask, - _In_ UCHAR Node, - _Out_ PULONGLONG ProcessorMask - ) - { - if (auto pGetNumaNodeProcessorMask = try_get_GetNumaNodeProcessorMask()) - { - return pGetNumaNodeProcessorMask(Node, ProcessorMask); - } - - if (Node == 0) - { - //因为我们假定只有一个 Node,所以所有处理器必然在这个 Node 中。 - - SYSTEM_INFO SystemInfo; - GetSystemInfo(&SystemInfo); - - *ProcessorMask = (1ull << SystemInfo.dwNumberOfProcessors) - 1; - - return TRUE; - } - - - //不支持此接口 - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - - } +#if (YY_Thunks_Target < __WindowsNT5_1_SP2) + + //Windows Vista, Windows XP Professional x64 Edition, Windows XP with SP2, Windows Server 2003 + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + GetNumaNodeProcessorMask, + _In_ UCHAR Node, + _Out_ PULONGLONG ProcessorMask + ) + { + if (auto pGetNumaNodeProcessorMask = try_get_GetNumaNodeProcessorMask()) + { + return pGetNumaNodeProcessorMask(Node, ProcessorMask); + } + + if (Node == 0) + { + //因为我们假定只有一个 Node,所以所有处理器必然在这个 Node 中。 + + SYSTEM_INFO SystemInfo; + GetSystemInfo(&SystemInfo); + + *ProcessorMask = (1ull << SystemInfo.dwNumberOfProcessors) - 1; + + return TRUE; + } + + + //不支持此接口 + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - //Windows 7, Windows Server 2008 R2 - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - GetNumaNodeProcessorMaskEx, - _In_ USHORT Node, - _Out_ PGROUP_AFFINITY ProcessorMask - ) - { - if (auto pGetNumaNodeProcessorMaskEx = try_get_GetNumaNodeProcessorMaskEx()) - { - return pGetNumaNodeProcessorMaskEx(Node, ProcessorMask); - } - else - { - if (Node > MAXUINT8) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - ULONGLONG ullProcessorMask; - auto bRet = GetNumaNodeProcessorMask(static_cast(Node), &ullProcessorMask); - if (bRet) - { - ProcessorMask->Mask = static_cast(ullProcessorMask); - //假定只有一组CPU - ProcessorMask->Group = 0; - ProcessorMask->Reserved[0] = 0; - ProcessorMask->Reserved[1] = 0; - ProcessorMask->Reserved[2] = 0; - } - - return bRet; - } - - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + //Windows 7, Windows Server 2008 R2 + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + GetNumaNodeProcessorMaskEx, + _In_ USHORT Node, + _Out_ PGROUP_AFFINITY ProcessorMask + ) + { + if (auto pGetNumaNodeProcessorMaskEx = try_get_GetNumaNodeProcessorMaskEx()) + { + return pGetNumaNodeProcessorMaskEx(Node, ProcessorMask); + } + else + { + if (Node > MAXUINT8) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + ULONGLONG ullProcessorMask; + auto bRet = GetNumaNodeProcessorMask(static_cast(Node), &ullProcessorMask); + if (bRet) + { + ProcessorMask->Mask = static_cast(ullProcessorMask); + //假定只有一组CPU + ProcessorMask->Group = 0; + ProcessorMask->Reserved[0] = 0; + ProcessorMask->Reserved[1] = 0; + ProcessorMask->Reserved[2] = 0; + } + + return bRet; + } + + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - // Windows 7 [desktop apps only] - // Windows Server 2008 R2 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - GetThreadGroupAffinity, - _In_ HANDLE _hThread, - _Out_ PGROUP_AFFINITY _pAffinity - ) - { - if (const auto _pfnGetThreadGroupAffinity = try_get_GetThreadGroupAffinity()) - { - return _pfnGetThreadGroupAffinity(_hThread, _pAffinity); - } - else - { - if (!_pAffinity) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - const auto _pfnNtQueryInformationThread = try_get_NtQueryInformationThread(); - if (!_pfnNtQueryInformationThread) - { - SetLastError(ERROR_INVALID_FUNCTION); - return FALSE; - } - - THREAD_BASIC_INFORMATION _ThreadBasicInfo; - long _Status = _pfnNtQueryInformationThread(_hThread, ThreadBasicInformation, &_ThreadBasicInfo, sizeof(_ThreadBasicInfo), nullptr); - - if (_Status < 0) - { - internal::BaseSetLastNTError(_Status); - return FALSE; - } - - _pAffinity->Group = 0; - _pAffinity->Mask = _ThreadBasicInfo.AffinityMask; - _pAffinity->Reserved[0] = 0; - _pAffinity->Reserved[1] = 0; - _pAffinity->Reserved[2] = 0; - return TRUE; - } - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + // Windows 7 [desktop apps only] + // Windows Server 2008 R2 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + GetThreadGroupAffinity, + _In_ HANDLE _hThread, + _Out_ PGROUP_AFFINITY _pAffinity + ) + { + if (const auto _pfnGetThreadGroupAffinity = try_get_GetThreadGroupAffinity()) + { + return _pfnGetThreadGroupAffinity(_hThread, _pAffinity); + } + else + { + if (!_pAffinity) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + const auto _pfnNtQueryInformationThread = try_get_NtQueryInformationThread(); + if (!_pfnNtQueryInformationThread) + { + SetLastError(ERROR_INVALID_FUNCTION); + return FALSE; + } + + THREAD_BASIC_INFORMATION _ThreadBasicInfo; + long _Status = _pfnNtQueryInformationThread(_hThread, ThreadBasicInformation, &_ThreadBasicInfo, sizeof(_ThreadBasicInfo), nullptr); + + if (_Status < 0) + { + internal::BaseSetLastNTError(_Status); + return FALSE; + } + + _pAffinity->Group = 0; + _pAffinity->Mask = _ThreadBasicInfo.AffinityMask; + _pAffinity->Reserved[0] = 0; + _pAffinity->Reserved[1] = 0; + _pAffinity->Reserved[2] = 0; + return TRUE; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - //Windows 7, Windows Server 2008 R2 - __DEFINE_THUNK( - kernel32, - 12, - BOOL, - WINAPI, - SetThreadGroupAffinity, - _In_ HANDLE hThread, - _In_ CONST GROUP_AFFINITY* GroupAffinity, - _Out_opt_ PGROUP_AFFINITY PreviousGroupAffinity - ) - { - if (auto pSetThreadGroupAffinity = try_get_SetThreadGroupAffinity()) - { - return pSetThreadGroupAffinity(hThread, GroupAffinity, PreviousGroupAffinity); - } - - auto NewMask = SetThreadAffinityMask(hThread, GroupAffinity->Mask); - - if (NewMask==0) - { - return FALSE; - } - - if (PreviousGroupAffinity) - { - PreviousGroupAffinity->Mask = NewMask; - PreviousGroupAffinity->Group = 0; - PreviousGroupAffinity->Reserved[0] = 0; - PreviousGroupAffinity->Reserved[1] = 0; - PreviousGroupAffinity->Reserved[2] = 0; - } - - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + //Windows 7, Windows Server 2008 R2 + __DEFINE_THUNK( + kernel32, + 12, + BOOL, + WINAPI, + SetThreadGroupAffinity, + _In_ HANDLE hThread, + _In_ CONST GROUP_AFFINITY* GroupAffinity, + _Out_opt_ PGROUP_AFFINITY PreviousGroupAffinity + ) + { + if (auto pSetThreadGroupAffinity = try_get_SetThreadGroupAffinity()) + { + return pSetThreadGroupAffinity(hThread, GroupAffinity, PreviousGroupAffinity); + } + + auto NewMask = SetThreadAffinityMask(hThread, GroupAffinity->Mask); + + if (NewMask==0) + { + return FALSE; + } + + if (PreviousGroupAffinity) + { + PreviousGroupAffinity->Mask = NewMask; + PreviousGroupAffinity->Group = 0; + PreviousGroupAffinity->Reserved[0] = 0; + PreviousGroupAffinity->Reserved[1] = 0; + PreviousGroupAffinity->Reserved[2] = 0; + } + + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WINXPSP2) - - //Windows Vista, Windows XP Professional x64 Edition, Windows XP with SP2 [desktop apps only] - //Windows Server 2003 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 4, - BOOL, - WINAPI, - GetNumaHighestNodeNumber, - _Out_ PULONG HighestNodeNumber - ) - { - if (auto pGetNumaHighestNodeNumber = try_get_GetNumaHighestNodeNumber()) - { - return pGetNumaHighestNodeNumber(HighestNodeNumber); - } - - //不支持时始终假定只有一个NUMA节点 - *HighestNodeNumber = 0; - - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT5_1_SP2) + + //Windows Vista, Windows XP Professional x64 Edition, Windows XP with SP2 [desktop apps only] + //Windows Server 2003 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 4, + BOOL, + WINAPI, + GetNumaHighestNodeNumber, + _Out_ PULONG HighestNodeNumber + ) + { + if (auto pGetNumaHighestNodeNumber = try_get_GetNumaHighestNodeNumber()) + { + return pGetNumaHighestNodeNumber(HighestNodeNumber); + } + + //不支持时始终假定只有一个NUMA节点 + *HighestNodeNumber = 0; + + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - //Minimum supported client Windows 7 [desktop apps only] - //Minimum supported server Windows Server 2008 R2 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 8, - _Success_(return) - BOOL, - WINAPI, - GetNumaProximityNodeEx, - _In_ ULONG ProximityId, - _Out_ PUSHORT NodeNumber - ) - { - if (const auto pGetNumaProximityNodeEx = try_get_GetNumaProximityNodeEx()) - { - return pGetNumaProximityNodeEx(ProximityId, NodeNumber); - } - - UCHAR NodeNumberTmp; - auto bRet = GetNumaProximityNode(ProximityId, &NodeNumberTmp); - if (bRet) - { - *NodeNumber = NodeNumberTmp; - } - - return bRet; - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + //Minimum supported client Windows 7 [desktop apps only] + //Minimum supported server Windows Server 2008 R2 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 8, + _Success_(return) + BOOL, + WINAPI, + GetNumaProximityNodeEx, + _In_ ULONG ProximityId, + _Out_ PUSHORT NodeNumber + ) + { + if (const auto pGetNumaProximityNodeEx = try_get_GetNumaProximityNodeEx()) + { + return pGetNumaProximityNodeEx(ProximityId, NodeNumber); + } + + UCHAR NodeNumberTmp; + auto bRet = GetNumaProximityNode(ProximityId, &NodeNumberTmp); + if (bRet) + { + *NodeNumber = NodeNumberTmp; + } + + return bRet; + } #endif - - }//namespace Thunks - -} //namespace YY +} //namespace YY::Thunks diff --git a/src/Thunks/api-ms-win-core-threadpool.hpp b/src/Thunks/api-ms-win-core-threadpool.hpp index 85a5ad4..f947b1e 100644 --- a/src/Thunks/api-ms-win-core-threadpool.hpp +++ b/src/Thunks/api-ms-win-core-threadpool.hpp @@ -6,113 +6,113 @@ struct _TP_CLEANUP_GROUP_FUNCS { - //0 - void (__fastcall* pfnTppWorkpFree)(_TP_WORK* Work); - //4 + //0 + void (__fastcall* pfnTppWorkpFree)(_TP_WORK* Work); + //4 void (__fastcall *pfnTppWorkCallbackEpilog)(_TP_WORK* _pWork); - //8 - SRWLOCK srwLock; - //C + //8 + SRWLOCK srwLock; + //C void(__fastcall* pfnTppWorkCancelPendingCallbacks)(_TP_WORK* _pWork); - //0x10 + //0x10 }; union TaskVFuncs { void* pfnCallback; - void(__fastcall* pExecuteCallback)(PTP_CALLBACK_INSTANCE Instance, _TP_WORK* Work); + void(__fastcall* pExecuteCallback)(PTP_CALLBACK_INSTANCE Instance, _TP_WORK* Work); }; struct _TP_CLEANUP_GROUP { - //0 - DWORD p0; - //4 - DWORD p4; - //8 - SRWLOCK srwLock; - //0xC - void* pC; - //0x10 - void* p10; - //0x14 - DWORD p14; - //0x18 - DWORD p18; - //0x1C - DWORD p1C; - //0x20 - SRWLOCK srwLock2; - //0x24 - DWORD p24; - //0x28 - SRWLOCK srwLock3; - //0x2C - void* p2C; - //0x30 - void* p30; - //0x34 - DWORD p34; - //0x38 + //0 + DWORD p0; + //4 + DWORD p4; + //8 + SRWLOCK srwLock; + //0xC + void* pC; + //0x10 + void* p10; + //0x14 + DWORD p14; + //0x18 + DWORD p18; + //0x1C + DWORD p1C; + //0x20 + SRWLOCK srwLock2; + //0x24 + DWORD p24; + //0x28 + SRWLOCK srwLock3; + //0x2C + void* p2C; + //0x30 + void* p30; + //0x34 + DWORD p34; + //0x38 }; //此结构从微软Vista的ntdll 内部扒出来的,我们目前只实现到Vista struct _TP_WORK { - //0 该结构的引用计数 - long nRef; - //4 - const _TP_CLEANUP_GROUP_FUNCS* VFuncs; - //8 - _TP_CLEANUP_GROUP* CleanupGroup; - //0xC - PTP_CLEANUP_GROUP_CANCEL_CALLBACK CleanupGroupCancelCallback; - //0x10 - PTP_SIMPLE_CALLBACK FinalizationCallback; - //0x14 - void* p14; - //0x18 - void* p18; - //0x1C - DWORD un1C; - //0x20 - DWORD p20; - //0x24 - DWORD p24; - //0x28 - SRWLOCK srwLock; - //0x2C - DWORD p2C; - //0x30 - void* Callback; - //0x34 上下文 - PVOID Context; - //0x38 - _ACTIVATION_CONTEXT* ActivationContext; - //0x3C - void* SubProcessTag; - //0x40 - PVOID RaceDll; - //0x44 - PTP_POOL Pool; - //0x48 - DWORD un48; - //0x4C - DWORD un4C; - //0x50 TP_CALLBACK_ENVIRON 中的 Flags - // 0x10000 已经调用Release + //0 该结构的引用计数 + long nRef; + //4 + const _TP_CLEANUP_GROUP_FUNCS* VFuncs; + //8 + _TP_CLEANUP_GROUP* CleanupGroup; + //0xC + PTP_CLEANUP_GROUP_CANCEL_CALLBACK CleanupGroupCancelCallback; + //0x10 + PTP_SIMPLE_CALLBACK FinalizationCallback; + //0x14 + void* p14; + //0x18 + void* p18; + //0x1C + DWORD un1C; + //0x20 + DWORD p20; + //0x24 + DWORD p24; + //0x28 + SRWLOCK srwLock; + //0x2C + DWORD p2C; + //0x30 + void* Callback; + //0x34 上下文 + PVOID Context; + //0x38 + _ACTIVATION_CONTEXT* ActivationContext; + //0x3C + void* SubProcessTag; + //0x40 + PVOID RaceDll; + //0x44 + PTP_POOL Pool; + //0x48 + DWORD un48; + //0x4C + DWORD un4C; + //0x50 TP_CALLBACK_ENVIRON 中的 Flags + // 0x10000 已经调用Release // 0x30000 WaitForThreadpoolIoCallbacks里用了,含义未知 - long uFlags1; - //0x54 似乎保存了 TpAllocWork 函数的返回地址意义暂时不明 - void* retaddr; - //0x58 保存 TpReleaseWork 函数的返回地址 - void* un58; - //0x5C - DWORD un5C; - //0x60 - const TaskVFuncs* pTaskVFuncs; - //0x64 + long uFlags1; + //0x54 似乎保存了 TpAllocWork 函数的返回地址意义暂时不明 + void* retaddr; + //0x58 保存 TpReleaseWork 函数的返回地址 + void* un58; + //0x5C + DWORD un5C; + //0x60 + const TaskVFuncs* pTaskVFuncs; + //0x64 union { volatile DWORD uFlags; @@ -128,17 +128,17 @@ struct _TP_WORK volatile ULONGLONG uFlags64; }; - //0x68 - //附加字段,微软原版没有 - //当没有任务时,改句柄将处于激活状态 - HANDLE hEvent; + //0x68 + //附加字段,微软原版没有 + //当没有任务时,改句柄将处于激活状态 + HANDLE hEvent; }; //0xD8 struct _TP_TIMER : public _TP_WORK { // 以下为YY-Thunks扩展属性 - HANDLE hQueueTimer; + HANDLE hQueueTimer; SRWLOCK QueueTimerLock; }; @@ -146,7 +146,7 @@ struct _TP_TIMER : public _TP_WORK struct _TP_WAIT : public _TP_WORK { // 以下为YY-Thunks扩展属性 - HANDLE hWaitObject; + HANDLE hWaitObject; SRWLOCK WaitObjectLock; }; @@ -168,1144 +168,1144 @@ struct _TP_CALLBACK_INSTANCE //0x25, TpCallbackMayRunLong会修改这个值 bool bCallbackMayRunLong; - //0x40 - PCRITICAL_SECTION CriticalSection; - //0x44 - HMODULE DllHandle; - //0x48 - HANDLE Event; - //0x4C - HANDLE Mutex; - //0x50 - HANDLE Semaphore; - //0x54 - DWORD ReleaseCount; + //0x40 + PCRITICAL_SECTION CriticalSection; + //0x44 + HMODULE DllHandle; + //0x48 + HANDLE Event; + //0x4C + HANDLE Mutex; + //0x50 + HANDLE Semaphore; + //0x54 + DWORD ReleaseCount; }; #endif -namespace YY::Thunks +namespace YY::Thunks::Fallback { -#if defined(YY_Thunks_Implemented) && (YY_Thunks_Support_Version < NTDDI_WIN6) - namespace Fallback +#if defined(YY_Thunks_Implemented) && (YY_Thunks_Target < __WindowsNT6) + namespace { - namespace + template + struct TP_BASE : public Type { - template - struct TP_BASE : public Type + void AddRef() { - void AddRef() - { - InterlockedIncrement(&nRef); - } + InterlockedIncrement(&nRef); + } - void Release() + void Release() + { + if (InterlockedDecrement(&nRef) == 0) { - if (InterlockedDecrement(&nRef) == 0) - { - VFuncs->pfnTppWorkpFree(this); - } + VFuncs->pfnTppWorkpFree(this); } + } - void AddPendingCount() + void AddPendingCount() + { + if (InterlockedAdd((volatile LONG*)&uFlags, 2) < 4) { - if (InterlockedAdd((volatile LONG*)&uFlags, 2) < 4) - { - ResetEvent(hEvent); - } + ResetEvent(hEvent); } + } - bool TryReleasePendingount() + bool TryReleasePendingount() + { + ULARGE_INTEGER _uLast; + for (_uLast.QuadPart = uFlags64;;) { - ULARGE_INTEGER _uLast; - for (_uLast.QuadPart = uFlags64;;) - { - ULARGE_INTEGER _uNew = _uLast; - if (_uNew.LowPart < 2) - return false; + ULARGE_INTEGER _uNew = _uLast; + if (_uNew.LowPart < 2) + return false; - _uNew.LowPart -= 2; + _uNew.LowPart -= 2; - auto _uResult = InterlockedCompareExchange64((volatile LONG64*)&uFlags64, _uNew.QuadPart, _uLast.QuadPart); - if (_uResult == _uLast.QuadPart) + auto _uResult = InterlockedCompareExchange64((volatile LONG64*)&uFlags64, _uNew.QuadPart, _uLast.QuadPart); + if (_uResult == _uLast.QuadPart) + { + //计数为 0,唤醒等待 + if (_uNew.QuadPart < 2ull) { - //计数为 0,唤醒等待 - if (_uNew.QuadPart < 2ull) - { - SetEvent(hEvent); - } - return true; + SetEvent(hEvent); } - - _uLast.QuadPart = _uResult; + return true; } + + _uLast.QuadPart = _uResult; } + } - bool TryReleaseWorkingCountAddWorkingCount() + bool TryReleaseWorkingCountAddWorkingCount() + { + ULARGE_INTEGER _uLast; + for (_uLast.QuadPart = uFlags64;;) { - ULARGE_INTEGER _uLast; - for (_uLast.QuadPart = uFlags64;;) + ULARGE_INTEGER _uNew = _uLast; + if (_uNew.LowPart < 2) { - ULARGE_INTEGER _uNew = _uLast; - if (_uNew.LowPart < 2) - { - return false; - } - else - { - _uNew.LowPart -= 2; - } - - _uNew.HighPart += 1; + return false; + } + else + { + _uNew.LowPart -= 2; + } - auto _uResult = InterlockedCompareExchange64((volatile LONG64*)&uFlags64, _uNew.QuadPart, _uLast.QuadPart); - if (_uResult == _uLast.QuadPart) - { - return true; - } + _uNew.HighPart += 1; - _uLast.QuadPart = _uResult; + auto _uResult = InterlockedCompareExchange64((volatile LONG64*)&uFlags64, _uNew.QuadPart, _uLast.QuadPart); + if (_uResult == _uLast.QuadPart) + { + return true; } + + _uLast.QuadPart = _uResult; } + } - void ReleaseWorkingCount() + void ReleaseWorkingCount() + { + ULARGE_INTEGER _uLast; + for (_uLast.QuadPart = uFlags64;;) { - ULARGE_INTEGER _uLast; - for (_uLast.QuadPart = uFlags64;;) - { - ULARGE_INTEGER _uNew = _uLast; - _uNew.HighPart -= 1; + ULARGE_INTEGER _uNew = _uLast; + _uNew.HighPart -= 1; - auto _uResult = InterlockedCompareExchange64((volatile LONG64*)&uFlags64, _uNew.QuadPart, _uLast.QuadPart); - if (_uResult == _uLast.QuadPart) + auto _uResult = InterlockedCompareExchange64((volatile LONG64*)&uFlags64, _uNew.QuadPart, _uLast.QuadPart); + if (_uResult == _uLast.QuadPart) + { + //计数为 0,唤醒等待 + if (_uNew.QuadPart < 2ull) { - //计数为 0,唤醒等待 - if (_uNew.QuadPart < 2ull) - { - SetEvent(hEvent); - } - return; + SetEvent(hEvent); } - - _uLast.QuadPart = _uResult; + return; } + + _uLast.QuadPart = _uResult; } - }; + } + }; - using TP_Work = TP_BASE<_TP_WORK>; - using TP_Io = TP_BASE<_TP_IO>; - using TP_Timer = TP_BASE<_TP_TIMER>; - using TP_Wait = TP_BASE<_TP_WAIT>; + using TP_Work = TP_BASE<_TP_WORK>; + using TP_Io = TP_BASE<_TP_IO>; + using TP_Timer = TP_BASE<_TP_TIMER>; + using TP_Wait = TP_BASE<_TP_WAIT>; - static void __fastcall DoWhenCallbackReturns(_TP_CALLBACK_INSTANCE* Instance); + static void __fastcall DoWhenCallbackReturns(_TP_CALLBACK_INSTANCE* Instance); - // XP系统默认值是500,我们难以知道 - volatile LONG uAvailableWorkerCount = 500; + // XP系统默认值是500,我们难以知道 + volatile LONG uAvailableWorkerCount = 500; - // 结构跟微软完全不同!!! - class TP_Pool - { - static constexpr DWORD kDefaultParallelMaximum = 200; + // 结构跟微软完全不同!!! + class TP_Pool + { + static constexpr DWORD kDefaultParallelMaximum = 200; - volatile ULONG uRef = 1; + volatile ULONG uRef = 1; - // 允许并行执行的最大个数,0代表默认值,Vista系统默认值为200。 - volatile DWORD uParallelMaximum = 0; + // 允许并行执行的最大个数,0代表默认值,Vista系统默认值为200。 + volatile DWORD uParallelMaximum = 0; - internal::InterlockedQueue oTaskQueue; + internal::InterlockedQueue oTaskQueue; - // |uWeakCount| bPushLock | bStopWakeup | bPushLock | - // | 31 ~ 3 | 2 | 1 | 0 | - union TaskRunnerFlagsType - { - volatile uint64_t fFlags64; - uint32_t uWakeupCountAndPushLock; + // |uWeakCount| bPushLock | bStopWakeup | bPushLock | + // | 31 ~ 3 | 2 | 1 | 0 | + union TaskRunnerFlagsType + { + volatile uint64_t fFlags64; + uint32_t uWakeupCountAndPushLock; - struct - { - volatile uint32_t bPushLock : 1; - volatile uint32_t bStopWakeup : 1; - volatile uint32_t bPopLock : 1; - int32_t uWakeupCount : 29; - // 当前已经启动的线程数 - uint32_t uParallelCurrent; - }; - }; - TaskRunnerFlagsType TaskRunnerFlags = { 0 }; - enum : uint32_t + struct { - LockedQueuePushBitIndex = 0, - StopWakeupBitIndex, - LockedQueuePopBitIndex, - WakeupCountStartBitIndex, - WakeupOnceRaw = 1 << WakeupCountStartBitIndex, - UnlockQueuePushLockBitAndWakeupOnceRaw = WakeupOnceRaw - (1u << LockedQueuePushBitIndex), + volatile uint32_t bPushLock : 1; + volatile uint32_t bStopWakeup : 1; + volatile uint32_t bPopLock : 1; + int32_t uWakeupCount : 29; + // 当前已经启动的线程数 + uint32_t uParallelCurrent; }; + }; + TaskRunnerFlagsType TaskRunnerFlags = { 0 }; + enum : uint32_t + { + LockedQueuePushBitIndex = 0, + StopWakeupBitIndex, + LockedQueuePopBitIndex, + WakeupCountStartBitIndex, + WakeupOnceRaw = 1 << WakeupCountStartBitIndex, + UnlockQueuePushLockBitAndWakeupOnceRaw = WakeupOnceRaw - (1u << LockedQueuePushBitIndex), + }; + + static_assert(sizeof(TaskRunnerFlags) == sizeof(uint64_t)); + + public: + TP_Pool(bool _bDefault = false) + : uRef(_bDefault ? UINT32_MAX : 1) + { + } - static_assert(sizeof(TaskRunnerFlags) == sizeof(uint64_t)); + TP_Pool(const TP_Pool&) = delete; - public: - TP_Pool(bool _bDefault = false) - : uRef(_bDefault? UINT32_MAX : 1) + bool __fastcall PostWork(_In_ TP_Work* _pWork) noexcept + { + if (TaskRunnerFlags.bStopWakeup) { + return false; } - TP_Pool(const TP_Pool&) = delete; - - bool __fastcall PostWork(_In_ TP_Work* _pWork) noexcept + _pWork->AddRef(); + _pWork->AddPendingCount(); + auto _uParallelMaximum = uParallelMaximum; + if (_uParallelMaximum == 0) + _uParallelMaximum = kDefaultParallelMaximum; + + // 将任务提交到任务队列 + AddRef(); + // 尝试 WeakupCount + 1,并锁定Push,也尝试提升 uParallelCurrent + TaskRunnerFlagsType _uOldFlags = { TaskRunnerFlags.fFlags64 }; + TaskRunnerFlagsType _uNewFlags; + for (;;) { - if (TaskRunnerFlags.bStopWakeup) + if (_uOldFlags.uWakeupCountAndPushLock & (1 << LockedQueuePushBitIndex)) { - return false; + YieldProcessor(); + _uOldFlags.fFlags64 = TaskRunnerFlags.fFlags64; + continue; } - _pWork->AddRef(); - _pWork->AddPendingCount(); - auto _uParallelMaximum = uParallelMaximum; - if (_uParallelMaximum == 0) - _uParallelMaximum = kDefaultParallelMaximum; + _uNewFlags.fFlags64 = _uOldFlags.fFlags64; + _uNewFlags.uWakeupCountAndPushLock += WakeupOnceRaw + (1 << LockedQueuePushBitIndex); - // 将任务提交到任务队列 - AddRef(); - // 尝试 WeakupCount + 1,并锁定Push,也尝试提升 uParallelCurrent - TaskRunnerFlagsType _uOldFlags = { TaskRunnerFlags.fFlags64 }; - TaskRunnerFlagsType _uNewFlags; - for (;;) + if (_uNewFlags.uParallelCurrent < _uParallelMaximum && _uNewFlags.uWakeupCount >= (int32_t)_uNewFlags.uParallelCurrent) { - if (_uOldFlags.uWakeupCountAndPushLock & (1 << LockedQueuePushBitIndex)) - { - YieldProcessor(); - _uOldFlags.fFlags64 = TaskRunnerFlags.fFlags64; - continue; - } - - _uNewFlags.fFlags64 = _uOldFlags.fFlags64; - _uNewFlags.uWakeupCountAndPushLock += WakeupOnceRaw + (1 << LockedQueuePushBitIndex); - - if (_uNewFlags.uParallelCurrent < _uParallelMaximum && _uNewFlags.uWakeupCount >= (int32_t)_uNewFlags.uParallelCurrent) - { - _uNewFlags.uParallelCurrent += 1; - } - - auto _uLast = InterlockedCompareExchange(&TaskRunnerFlags.fFlags64, _uNewFlags.fFlags64, _uOldFlags.fFlags64); - if (_uLast == _uOldFlags.fFlags64) - { - // 完成Push锁定,提交任务后再解锁 - oTaskQueue.Push(_pWork); - _interlockedbittestandreset((volatile LONG*)&TaskRunnerFlags.uWakeupCountAndPushLock, LockedQueuePushBitIndex); - break; - } - _uOldFlags.fFlags64 = _uLast; + _uNewFlags.uParallelCurrent += 1; } - // 并发送数量没有提升,所以无需从线程池拉发起新任务 - if (_uOldFlags.uParallelCurrent == _uNewFlags.uParallelCurrent) - return true; - - // 如果是第一次那么再额外 AddRef,避免ExecuteTaskRunner调用时 TP_Pool 被释放了 - // ExecuteTaskRunner内部负责重新减少引用计数 - if (_uOldFlags.uParallelCurrent == 0u) + auto _uLast = InterlockedCompareExchange(&TaskRunnerFlags.fFlags64, _uNewFlags.fFlags64, _uOldFlags.fFlags64); + if (_uLast == _uOldFlags.fFlags64) { - AddRef(); + // 完成Push锁定,提交任务后再解锁 + oTaskQueue.Push(_pWork); + _interlockedbittestandreset((volatile LONG*)&TaskRunnerFlags.uWakeupCountAndPushLock, LockedQueuePushBitIndex); + break; } + _uOldFlags.fFlags64 = _uLast; + } - InterlockedDecrement(&uAvailableWorkerCount); - auto _bRet = QueueUserWorkItem([](LPVOID lpThreadParameter) -> DWORD - { - auto _pPool = (TP_Pool*)lpThreadParameter; - - _pPool->ExecuteTaskRunner(); - InterlockedIncrement(&uAvailableWorkerCount); - return 0; + // 并发送数量没有提升,所以无需从线程池拉发起新任务 + if (_uOldFlags.uParallelCurrent == _uNewFlags.uParallelCurrent) + return true; - }, this, 0); + // 如果是第一次那么再额外 AddRef,避免ExecuteTaskRunner调用时 TP_Pool 被释放了 + // ExecuteTaskRunner内部负责重新减少引用计数 + if (_uOldFlags.uParallelCurrent == 0u) + { + AddRef(); + } - if (!_bRet) + InterlockedDecrement(&uAvailableWorkerCount); + auto _bRet = QueueUserWorkItem([](LPVOID lpThreadParameter) -> DWORD { + auto _pPool = (TP_Pool*)lpThreadParameter; + + _pPool->ExecuteTaskRunner(); InterlockedIncrement(&uAvailableWorkerCount); - Release(); - } + return 0; - return true; - } + }, this, 0); - static _Ret_notnull_ TP_Pool* __fastcall GetDefaultPool() noexcept + if (!_bRet) { - static TP_Pool s_Pool(true); - return &s_Pool; + InterlockedIncrement(&uAvailableWorkerCount); + Release(); } - void __fastcall AddRef() noexcept + return true; + } + + static _Ret_notnull_ TP_Pool* __fastcall GetDefaultPool() noexcept + { + static TP_Pool s_Pool(true); + return &s_Pool; + } + + void __fastcall AddRef() noexcept + { + if (uRef != UINT32_MAX) { - if (uRef != UINT32_MAX) - { - InterlockedIncrement(&uRef); - } + InterlockedIncrement(&uRef); } + } - void __fastcall Release() noexcept + void __fastcall Release() noexcept + { + if (uRef != UINT32_MAX) { - if (uRef != UINT32_MAX) + if (InterlockedDecrement(&uRef) == 0) { - if (InterlockedDecrement(&uRef) == 0) - { - internal::Delete(this); - } + internal::Delete(this); } } + } - void __fastcall Close() noexcept + void __fastcall Close() noexcept + { + if (_interlockedbittestandset((volatile LONG*)&TaskRunnerFlags.uWakeupCountAndPushLock, StopWakeupBitIndex)) { - if (_interlockedbittestandset((volatile LONG*)&TaskRunnerFlags.uWakeupCountAndPushLock, StopWakeupBitIndex)) - { - return; - } - - for (;;) - { - auto _pTask = PopTask(); - if (!_pTask) - break; + return; + } - _pTask->TryReleasePendingount(); - _pTask->Release(); - Release(); - } + for (;;) + { + auto _pTask = PopTask(); + if (!_pTask) + break; + _pTask->TryReleasePendingount(); + _pTask->Release(); Release(); } - void __fastcall SetParallelMaximum(DWORD _uParallelMaximum) - { - uParallelMaximum = _uParallelMaximum; - } + Release(); + } - private: - _Ret_maybenull_ TP_Work* __fastcall PopTask() noexcept + void __fastcall SetParallelMaximum(DWORD _uParallelMaximum) + { + uParallelMaximum = _uParallelMaximum; + } + + private: + _Ret_maybenull_ TP_Work* __fastcall PopTask() noexcept + { + for (;;) { - for (;;) + if (!_interlockedbittestandset((volatile LONG*)&TaskRunnerFlags.uWakeupCountAndPushLock, LockedQueuePopBitIndex)) { - if (!_interlockedbittestandset((volatile LONG*)&TaskRunnerFlags.uWakeupCountAndPushLock, LockedQueuePopBitIndex)) + auto _pWork = oTaskQueue.Pop(); + if (_pWork) { - auto _pWork = oTaskQueue.Pop(); - if (_pWork) - { - // 因为弹出一个有效任务,所以 WakeupCount - 1,同时解除 pop 锁定 - InterlockedAdd((volatile LONG*)&TaskRunnerFlags.uWakeupCountAndPushLock, -(LONG)(WakeupOnceRaw + (1 << LockedQueuePopBitIndex))); - } - else - { - _interlockedbittestandreset((volatile LONG*)&TaskRunnerFlags.uWakeupCountAndPushLock, LockedQueuePopBitIndex); - } - return _pWork; + // 因为弹出一个有效任务,所以 WakeupCount - 1,同时解除 pop 锁定 + InterlockedAdd((volatile LONG*)&TaskRunnerFlags.uWakeupCountAndPushLock, -(LONG)(WakeupOnceRaw + (1 << LockedQueuePopBitIndex))); } - - YieldProcessor(); - } - } - - void __fastcall ExecuteTaskRunner() noexcept - { - __START: - for (;;) - { - auto _pWork = PopTask(); - if (!_pWork) - break; - - if (_pWork->TryReleaseWorkingCountAddWorkingCount()) + else { - TP_CALLBACK_INSTANCE Instance = {}; - _pWork->pTaskVFuncs->pExecuteCallback(&Instance, _pWork); - Fallback::DoWhenCallbackReturns(&Instance); - - _pWork->ReleaseWorkingCount(); + _interlockedbittestandreset((volatile LONG*)&TaskRunnerFlags.uWakeupCountAndPushLock, LockedQueuePopBitIndex); } - - _pWork->Release(); - Release(); + return _pWork; } - // 尝试释放 uParallelCurrent - TaskRunnerFlagsType _uOldFlags = { TaskRunnerFlags.fFlags64 }; - TaskRunnerFlagsType _uNewFlags; - for (;;) - { - // 任然有任务,重新执行 ExecuteTaskRunner - if (_uOldFlags.uWakeupCount > 0) - { - goto __START; - } + YieldProcessor(); + } + } - _uNewFlags = _uOldFlags; - _uNewFlags.uParallelCurrent -= 1; + void __fastcall ExecuteTaskRunner() noexcept + { + __START: + for (;;) + { + auto _pWork = PopTask(); + if (!_pWork) + break; - auto _uLast = InterlockedCompareExchange(&TaskRunnerFlags.fFlags64, _uNewFlags.fFlags64, _uOldFlags.fFlags64); - if (_uLast == _uOldFlags.fFlags64) - break; + if (_pWork->TryReleaseWorkingCountAddWorkingCount()) + { + TP_CALLBACK_INSTANCE Instance = {}; + _pWork->pTaskVFuncs->pExecuteCallback(&Instance, _pWork); + Fallback::DoWhenCallbackReturns(&Instance); - _uOldFlags.fFlags64 = _uLast; + _pWork->ReleaseWorkingCount(); } - if (_uNewFlags.uParallelCurrent == 0u) - { - // 对应上面 QueueUserWorkItem 的AddRef(); - Release(); - } + _pWork->Release(); + Release(); } - }; - static void __fastcall DoWhenCallbackReturns(_TP_CALLBACK_INSTANCE* Instance) - { - if (auto CriticalSection = Instance->CriticalSection) + // 尝试释放 uParallelCurrent + TaskRunnerFlagsType _uOldFlags = { TaskRunnerFlags.fFlags64 }; + TaskRunnerFlagsType _uNewFlags; + for (;;) { - LeaveCriticalSection(CriticalSection); - } + // 任然有任务,重新执行 ExecuteTaskRunner + if (_uOldFlags.uWakeupCount > 0) + { + goto __START; + } - if (auto DllHandle = Instance->DllHandle) - { - FreeLibrary(DllHandle); - } + _uNewFlags = _uOldFlags; + _uNewFlags.uParallelCurrent -= 1; - if (auto Event = Instance->Event) - { - SetEvent(Event); - } + auto _uLast = InterlockedCompareExchange(&TaskRunnerFlags.fFlags64, _uNewFlags.fFlags64, _uOldFlags.fFlags64); + if (_uLast == _uOldFlags.fFlags64) + break; - if (auto Mutex = Instance->Mutex) - { - ReleaseMutex(Mutex); + _uOldFlags.fFlags64 = _uLast; } - if (auto Semaphore = Instance->Semaphore) + if (_uNewFlags.uParallelCurrent == 0u) { - ReleaseSemaphore(Semaphore, Instance->ReleaseCount, nullptr); + // 对应上面 QueueUserWorkItem 的AddRef(); + Release(); } } + }; - static void __fastcall TppWorkpFree(_TP_WORK* Work) + static void __fastcall DoWhenCallbackReturns(_TP_CALLBACK_INSTANCE* Instance) + { + if (auto CriticalSection = Instance->CriticalSection) { - if (Work) - { - const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; - HeapFree(ProcessHeap, 0, Work); - } + LeaveCriticalSection(CriticalSection); } - static void __fastcall TppWorkCallbackEpilog(_TP_WORK* _pWork) + if (auto DllHandle = Instance->DllHandle) { - + FreeLibrary(DllHandle); } - static void __fastcall TppWorkCancelPendingCallbacks(_TP_WORK* _pWork) + if (auto Event = Instance->Event) { - + SetEvent(Event); } - static const _TP_CLEANUP_GROUP_FUNCS* __fastcall GetTppWorkpCleanupGroupMemberVFuncs() + if (auto Mutex = Instance->Mutex) { - static _TP_CLEANUP_GROUP_FUNCS TppWorkpCleanupGroupMemberVFuncs = { &TppWorkpFree, &TppWorkCallbackEpilog, 0, &TppWorkCancelPendingCallbacks }; - return &TppWorkpCleanupGroupMemberVFuncs; + ReleaseMutex(Mutex); } - static void __fastcall TppWorkpExecuteCallback(PTP_CALLBACK_INSTANCE Instance, _TP_WORK* Work) + if (auto Semaphore = Instance->Semaphore) { - ((PTP_WORK_CALLBACK)Work->Callback)(Instance, Work->Context, Work); + ReleaseSemaphore(Semaphore, Instance->ReleaseCount, nullptr); } + } - static const TaskVFuncs* __fastcall GetTppWorkpTaskVFuncs() + static void __fastcall TppWorkpFree(_TP_WORK* Work) + { + if (Work) { - static TaskVFuncs TppWorkpTaskVFuncs = { &TppWorkpExecuteCallback }; - return &TppWorkpTaskVFuncs; + const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; + HeapFree(ProcessHeap, 0, Work); } + } - static void __fastcall TppCleanupGroupMemberWait(_TP_WORK* _pWork, ULONG _uCancelledCallbackCount) - { - if (_pWork->uFlags64 & (~1ull)) - WaitForSingleObject(_pWork->hEvent, INFINITE); - } + static void __fastcall TppWorkCallbackEpilog(_TP_WORK* _pWork) + { - static void __fastcall TppWorkWait(_TP_WORK* _pWork, BOOL _bCancelPendingCallbacks, bool bReleaseRef = false) - { - ULONG _uCancelledCallbackCount = 0; - if (_bCancelPendingCallbacks) - { - for (auto _uLast = _pWork->uFlags;;) - { - _uCancelledCallbackCount = _uLast >> 1; - if (_uCancelledCallbackCount == 0) - break; + } - const auto _uResult = InterlockedCompareExchange(&_pWork->uFlags, _uLast & 1, _uLast); - if (_uResult == _uLast) - { - break; - } + static void __fastcall TppWorkCancelPendingCallbacks(_TP_WORK* _pWork) + { - _uLast = _uResult; - } - } + } - TppCleanupGroupMemberWait(_pWork, _uCancelledCallbackCount); + static const _TP_CLEANUP_GROUP_FUNCS* __fastcall GetTppWorkpCleanupGroupMemberVFuncs() + { + static _TP_CLEANUP_GROUP_FUNCS TppWorkpCleanupGroupMemberVFuncs = { &TppWorkpFree, &TppWorkCallbackEpilog, 0, &TppWorkCancelPendingCallbacks }; + return &TppWorkpCleanupGroupMemberVFuncs; + } + + static void __fastcall TppWorkpExecuteCallback(PTP_CALLBACK_INSTANCE Instance, _TP_WORK* Work) + { + ((PTP_WORK_CALLBACK)Work->Callback)(Instance, Work->Context, Work); + } + + static const TaskVFuncs* __fastcall GetTppWorkpTaskVFuncs() + { + static TaskVFuncs TppWorkpTaskVFuncs = { &TppWorkpExecuteCallback }; + return &TppWorkpTaskVFuncs; + } + + static void __fastcall TppCleanupGroupMemberWait(_TP_WORK* _pWork, ULONG _uCancelledCallbackCount) + { + if (_pWork->uFlags64 & (~1ull)) + WaitForSingleObject(_pWork->hEvent, INFINITE); + } - if (bReleaseRef) + static void __fastcall TppWorkWait(_TP_WORK* _pWork, BOOL _bCancelPendingCallbacks, bool bReleaseRef = false) + { + ULONG _uCancelledCallbackCount = 0; + if (_bCancelPendingCallbacks) + { + for (auto _uLast = _pWork->uFlags;;) { - if (InterlockedAdd((volatile LONG*)&_pWork->nRef, -LONG(_uCancelledCallbackCount)) == 0) + _uCancelledCallbackCount = _uLast >> 1; + if (_uCancelledCallbackCount == 0) + break; + + const auto _uResult = InterlockedCompareExchange(&_pWork->uFlags, _uLast & 1, _uLast); + if (_uResult == _uLast) { - _pWork->VFuncs->pfnTppWorkpFree(_pWork); + break; } + + _uLast = _uResult; } } - static - NTSTATUS - __fastcall - TppCleanupGroupMemberInitialize( - _Inout_ _TP_WORK* pWork, - _Inout_opt_ PVOID pv, - _In_opt_ PTP_CALLBACK_ENVIRON pcbe, - _In_ DWORD uFlags, - const _TP_CLEANUP_GROUP_FUNCS* CleanupGroupVFuncs - ) - { - pWork->nRef = 1; - pWork->VFuncs = CleanupGroupVFuncs; - pWork->p20 = 0; - pWork->p24 = 0; - pWork->p2C = 0; - - ::InitializeSRWLock(&pWork->srwLock); - - pWork->Context = pv; + TppCleanupGroupMemberWait(_pWork, _uCancelledCallbackCount); - if (pcbe) - { - pWork->Pool = pcbe->Pool; - pWork->CleanupGroup = pcbe->CleanupGroup; - pWork->CleanupGroupCancelCallback = pcbe->CleanupGroupCancelCallback; - pWork->FinalizationCallback = NULL; - pWork->ActivationContext = pcbe->ActivationContext; - pWork->RaceDll = pcbe->RaceDll; - } - else + if (bReleaseRef) + { + if (InterlockedAdd((volatile LONG*)&_pWork->nRef, -LONG(_uCancelledCallbackCount)) == 0) { - pWork->Pool = NULL; - pWork->CleanupGroup = NULL; - pWork->CleanupGroupCancelCallback = NULL; - pWork->FinalizationCallback = NULL; - pWork->ActivationContext = NULL; - pWork->RaceDll = NULL; + _pWork->VFuncs->pfnTppWorkpFree(_pWork); } + } + } - pWork->SubProcessTag = NtCurrentTeb()->SubProcessTag; - pWork->uFlags1 = uFlags; - pWork->p18 = pWork->p14 = &pWork->p14; + static + NTSTATUS + __fastcall + TppCleanupGroupMemberInitialize( + _Inout_ _TP_WORK* pWork, + _Inout_opt_ PVOID pv, + _In_opt_ PTP_CALLBACK_ENVIRON pcbe, + _In_ DWORD uFlags, + const _TP_CLEANUP_GROUP_FUNCS* CleanupGroupVFuncs + ) + { + pWork->nRef = 1; + pWork->VFuncs = CleanupGroupVFuncs; + pWork->p20 = 0; + pWork->p24 = 0; + pWork->p2C = 0; + ::InitializeSRWLock(&pWork->srwLock); - if (pWork->ActivationContext != NULL) - { - if (pWork->ActivationContext != (_ACTIVATION_CONTEXT*)-1) - { + pWork->Context = pv; - } - } + if (pcbe) + { + pWork->Pool = pcbe->Pool; + pWork->CleanupGroup = pcbe->CleanupGroup; + pWork->CleanupGroupCancelCallback = pcbe->CleanupGroupCancelCallback; + pWork->FinalizationCallback = NULL; + pWork->ActivationContext = pcbe->ActivationContext; + pWork->RaceDll = pcbe->RaceDll; + } + else + { + pWork->Pool = NULL; + pWork->CleanupGroup = NULL; + pWork->CleanupGroupCancelCallback = NULL; + pWork->FinalizationCallback = NULL; + pWork->ActivationContext = NULL; + pWork->RaceDll = NULL; + } - auto hEvent = CreateEventW(nullptr, TRUE, TRUE, nullptr); + pWork->SubProcessTag = NtCurrentTeb()->SubProcessTag; + pWork->uFlags1 = uFlags; + pWork->p18 = pWork->p14 = &pWork->p14; - if (hEvent == nullptr) + + if (pWork->ActivationContext != NULL) + { + if (pWork->ActivationContext != (_ACTIVATION_CONTEXT*)-1) { - return STATUS_NO_MEMORY; + } + } - pWork->hEvent = hEvent; + auto hEvent = CreateEventW(nullptr, TRUE, TRUE, nullptr); - return STATUS_SUCCESS; + if (hEvent == nullptr) + { + return STATUS_NO_MEMORY; } - static - NTSTATUS - __fastcall - TppWorkInitialize( - _Inout_ _TP_WORK* pWork, - _Inout_opt_ PVOID pv, - _In_opt_ PTP_CALLBACK_ENVIRON pcbe, - _In_ DWORD uFlags, - _In_ const _TP_CLEANUP_GROUP_FUNCS* CleanupGroupVFuncs, - _In_ const TaskVFuncs* TaskVFuncs - ) - { - auto Status = TppCleanupGroupMemberInitialize(pWork, pv, pcbe, uFlags, CleanupGroupVFuncs); + pWork->hEvent = hEvent; - if (Status >= 0) - { - //if(pWork->) - pWork->pTaskVFuncs = TaskVFuncs; - pWork->uFlags = 1; - } + return STATUS_SUCCESS; + } - return Status; - } + static + NTSTATUS + __fastcall + TppWorkInitialize( + _Inout_ _TP_WORK* pWork, + _Inout_opt_ PVOID pv, + _In_opt_ PTP_CALLBACK_ENVIRON pcbe, + _In_ DWORD uFlags, + _In_ const _TP_CLEANUP_GROUP_FUNCS* CleanupGroupVFuncs, + _In_ const TaskVFuncs* TaskVFuncs + ) + { + auto Status = TppCleanupGroupMemberInitialize(pWork, pv, pcbe, uFlags, CleanupGroupVFuncs); - static - void - __fastcall - TppCleanupGroupAddMember( - _Outptr_ _TP_WORK* pWork - ) + if (Status >= 0) { - ::AcquireSRWLockExclusive(&pWork->CleanupGroup->srwLock); + //if(pWork->) + pWork->pTaskVFuncs = TaskVFuncs; + pWork->uFlags = 1; + } - pWork->p14 = &pWork->CleanupGroup->pC; - pWork->p18 = pWork->CleanupGroup->p10; + return Status; + } - *(void**)pWork->CleanupGroup->p10 = pWork->p14; - pWork->CleanupGroup->p10 = &pWork->p14; + static + void + __fastcall + TppCleanupGroupAddMember( + _Outptr_ _TP_WORK* pWork + ) + { + ::AcquireSRWLockExclusive(&pWork->CleanupGroup->srwLock); - ::ReleaseSRWLockExclusive(&pWork->CleanupGroup->srwLock); - } + pWork->p14 = &pWork->CleanupGroup->pC; + pWork->p18 = pWork->CleanupGroup->p10; - static - NTSTATUS - __fastcall - TpAllocWork( - _Outptr_ _TP_WORK** ppWork, - _In_ PTP_WORK_CALLBACK pfnwk, - _Inout_opt_ PVOID pv, - _In_opt_ PTP_CALLBACK_ENVIRON pcbe - ) + *(void**)pWork->CleanupGroup->p10 = pWork->p14; + pWork->CleanupGroup->p10 = &pWork->p14; + + ::ReleaseSRWLockExclusive(&pWork->CleanupGroup->srwLock); + } + + static + NTSTATUS + __fastcall + TpAllocWork( + _Outptr_ _TP_WORK** ppWork, + _In_ PTP_WORK_CALLBACK pfnwk, + _Inout_opt_ PVOID pv, + _In_opt_ PTP_CALLBACK_ENVIRON pcbe + ) + { + if (ppWork == nullptr || pfnwk == nullptr || (pcbe && (pcbe->u.Flags & 0xFFFFFFFE))) { - if (ppWork == nullptr || pfnwk == nullptr || (pcbe && (pcbe->u.Flags & 0xFFFFFFFE))) - { - return STATUS_INVALID_PARAMETER; - } + return STATUS_INVALID_PARAMETER; + } - const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; - auto pWork = (_TP_WORK*)HeapAlloc(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(_TP_WORK)); + const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; + auto pWork = (_TP_WORK*)HeapAlloc(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(_TP_WORK)); - if (!pWork) - return STATUS_NO_MEMORY; + if (!pWork) + return STATUS_NO_MEMORY; - pWork->retaddr = _ReturnAddress(); + pWork->retaddr = _ReturnAddress(); - auto Status = TppWorkInitialize(pWork, pv, pcbe, pcbe ? pcbe->u.Flags : 0, GetTppWorkpCleanupGroupMemberVFuncs(), GetTppWorkpTaskVFuncs()); + auto Status = TppWorkInitialize(pWork, pv, pcbe, pcbe ? pcbe->u.Flags : 0, GetTppWorkpCleanupGroupMemberVFuncs(), GetTppWorkpTaskVFuncs()); - do - { - if (Status < 0) - break; + do + { + if (Status < 0) + break; - pWork->Callback = pfnwk; + pWork->Callback = pfnwk; - if (pcbe) - pWork->FinalizationCallback = pcbe->FinalizationCallback; + if (pcbe) + pWork->FinalizationCallback = pcbe->FinalizationCallback; - if (pWork->CleanupGroup) - TppCleanupGroupAddMember(pWork); + if (pWork->CleanupGroup) + TppCleanupGroupAddMember(pWork); - *ppWork = pWork; + *ppWork = pWork; - return STATUS_SUCCESS; - } while (false); + return STATUS_SUCCESS; + } while (false); - if (pWork) - HeapFree(ProcessHeap, 0, pWork); + if (pWork) + HeapFree(ProcessHeap, 0, pWork); - return Status; - } + return Status; + } - static void __fastcall TppWaitpFree(_TP_WORK* Work) + static void __fastcall TppWaitpFree(_TP_WORK* Work) + { + if (Work) { - if (Work) - { - const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; - HeapFree(ProcessHeap, 0, Work); - } + const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; + HeapFree(ProcessHeap, 0, Work); } + } - static const _TP_CLEANUP_GROUP_FUNCS* __fastcall GetTppWaitpCleanupGroupMemberVFuncs() - { - static const _TP_CLEANUP_GROUP_FUNCS TppWorkpCleanupGroupMemberVFuncs = { &TppWaitpFree, &TppWorkCallbackEpilog, 0, &TppWorkCancelPendingCallbacks }; - return &TppWorkpCleanupGroupMemberVFuncs; - } + static const _TP_CLEANUP_GROUP_FUNCS* __fastcall GetTppWaitpCleanupGroupMemberVFuncs() + { + static const _TP_CLEANUP_GROUP_FUNCS TppWorkpCleanupGroupMemberVFuncs = { &TppWaitpFree, &TppWorkCallbackEpilog, 0, &TppWorkCancelPendingCallbacks }; + return &TppWorkpCleanupGroupMemberVFuncs; + } - static void __fastcall TppWaitpExecuteCallback(PTP_CALLBACK_INSTANCE Instance, _TP_WORK* Work) - { - ((PTP_WAIT_CALLBACK)Work->Callback)(Instance, Work->Context, (PTP_WAIT)Work, 0); - } + static void __fastcall TppWaitpExecuteCallback(PTP_CALLBACK_INSTANCE Instance, _TP_WORK* Work) + { + ((PTP_WAIT_CALLBACK)Work->Callback)(Instance, Work->Context, (PTP_WAIT)Work, 0); + } - static const TaskVFuncs* __fastcall GetTppWaitpTaskVFuncs() - { - static TaskVFuncs TppWorkpTaskVFuncs = { &TppWaitpExecuteCallback }; - return &TppWorkpTaskVFuncs; - } + static const TaskVFuncs* __fastcall GetTppWaitpTaskVFuncs() + { + static TaskVFuncs TppWorkpTaskVFuncs = { &TppWaitpExecuteCallback }; + return &TppWorkpTaskVFuncs; + } - static void __fastcall TppWorkPost(TP_Work* _pWork) - { - auto _pPool = _pWork->Pool ? reinterpret_cast(_pWork->Pool) : TP_Pool::GetDefaultPool(); - _pPool->PostWork(_pWork); - } + static void __fastcall TppWorkPost(TP_Work* _pWork) + { + auto _pPool = _pWork->Pool ? reinterpret_cast(_pWork->Pool) : TP_Pool::GetDefaultPool(); + _pPool->PostWork(_pWork); + } - //暂时我们不需要实现 GetTppSimplepCleanupGroupMemberVFuncs + //暂时我们不需要实现 GetTppSimplepCleanupGroupMemberVFuncs #define GetTppSimplepCleanupGroupMemberVFuncs GetTppWorkpCleanupGroupMemberVFuncs - static void __fastcall TppSimplepExecuteCallback(PTP_CALLBACK_INSTANCE Instance, _TP_WORK* Work) - { - ((PTP_SIMPLE_CALLBACK)Work->Callback)(Instance, Work->Context); - } + static void __fastcall TppSimplepExecuteCallback(PTP_CALLBACK_INSTANCE Instance, _TP_WORK* Work) + { + ((PTP_SIMPLE_CALLBACK)Work->Callback)(Instance, Work->Context); + } - static const TaskVFuncs* __fastcall GetTppSimplepTaskVFuncs() - { - static TaskVFuncs TppWorkpTaskVFuncs = { &TppSimplepExecuteCallback }; - return &TppWorkpTaskVFuncs; - } + static const TaskVFuncs* __fastcall GetTppSimplepTaskVFuncs() + { + static TaskVFuncs TppWorkpTaskVFuncs = { &TppSimplepExecuteCallback }; + return &TppWorkpTaskVFuncs; + } - static void __fastcall TppIopExecuteCallback(TP_Io* _pIoWork, DWORD _lStatus, DWORD _cbNumberOfBytesTransfered, LPOVERLAPPED _pOverlapped) - { - auto _pfnIoCallback = reinterpret_cast(_pIoWork->Callback); + static void __fastcall TppIopExecuteCallback(TP_Io* _pIoWork, DWORD _lStatus, DWORD _cbNumberOfBytesTransfered, LPOVERLAPPED _pOverlapped) + { + auto _pfnIoCallback = reinterpret_cast(_pIoWork->Callback); - if (_pIoWork->TryReleaseWorkingCountAddWorkingCount()) - { - _TP_CALLBACK_INSTANCE _Instance = {}; - _pfnIoCallback(&_Instance, _pIoWork->Context, _pOverlapped, _lStatus, _cbNumberOfBytesTransfered, _pIoWork); - DoWhenCallbackReturns(&_Instance); + if (_pIoWork->TryReleaseWorkingCountAddWorkingCount()) + { + _TP_CALLBACK_INSTANCE _Instance = {}; + _pfnIoCallback(&_Instance, _pIoWork->Context, _pOverlapped, _lStatus, _cbNumberOfBytesTransfered, _pIoWork); + DoWhenCallbackReturns(&_Instance); - _pIoWork->ReleaseWorkingCount(); - _pIoWork->Release(); - } + _pIoWork->ReleaseWorkingCount(); + _pIoWork->Release(); } + } - static const TaskVFuncs* __fastcall GetTppIopExecuteCallback() - { - static TaskVFuncs TppWorkpTaskVFuncs = { &TppIopExecuteCallback }; - return &TppWorkpTaskVFuncs; - } + static const TaskVFuncs* __fastcall GetTppIopExecuteCallback() + { + static TaskVFuncs TppWorkpTaskVFuncs = { &TppIopExecuteCallback }; + return &TppWorkpTaskVFuncs; + } - static void __fastcall TppIopFree(_TP_WORK* _pWork) + static void __fastcall TppIopFree(_TP_WORK* _pWork) + { + if (auto _pIoWork = static_cast<_TP_IO*>(_pWork)) { - if (auto _pIoWork = static_cast<_TP_IO*>(_pWork)) - { - if (_pIoWork->pThunkData) - _pIoWork->pThunkData->Free(); + if (_pIoWork->pThunkData) + _pIoWork->pThunkData->Free(); - internal::Free(_pWork); - } + internal::Free(_pWork); } + } - static void __fastcall TppIopCallbackEpilog(_TP_WORK* _pWork) - { + static void __fastcall TppIopCallbackEpilog(_TP_WORK* _pWork) + { - } + } - static void __fastcall TppIopCancelPendingCallbacks(_TP_WORK* _pWork) - { - } + static void __fastcall TppIopCancelPendingCallbacks(_TP_WORK* _pWork) + { + } - static const _TP_CLEANUP_GROUP_FUNCS* __fastcall GetTppIopCleanupGroupMemberVFuncs() - { - static _TP_CLEANUP_GROUP_FUNCS TppWorkpCleanupGroupMemberVFuncs = { &TppIopFree, &TppWorkCallbackEpilog, 0, &TppIopCancelPendingCallbacks }; - return &TppWorkpCleanupGroupMemberVFuncs; - } + static const _TP_CLEANUP_GROUP_FUNCS* __fastcall GetTppIopCleanupGroupMemberVFuncs() + { + static _TP_CLEANUP_GROUP_FUNCS TppWorkpCleanupGroupMemberVFuncs = { &TppIopFree, &TppWorkCallbackEpilog, 0, &TppIopCancelPendingCallbacks }; + return &TppWorkpCleanupGroupMemberVFuncs; + } - static - NTSTATUS - __fastcall - TpSimpleTryPost( - _In_ PTP_SIMPLE_CALLBACK Callback, - _Inout_opt_ PVOID Context, - _In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron - ) + static + NTSTATUS + __fastcall + TpSimpleTryPost( + _In_ PTP_SIMPLE_CALLBACK Callback, + _Inout_opt_ PVOID Context, + _In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron + ) + { + auto Flags = CallbackEnviron ? CallbackEnviron->u.Flags : 0; + + if (Callback == nullptr || (Flags & 0xFFFFFFFE) != 0) { - auto Flags = CallbackEnviron ? CallbackEnviron->u.Flags : 0; + internal::RaiseStatus(STATUS_INVALID_PARAMETER); + return STATUS_INVALID_PARAMETER; + } - if (Callback == nullptr || (Flags & 0xFFFFFFFE) != 0) - { - internal::RaiseStatus(STATUS_INVALID_PARAMETER); - return STATUS_INVALID_PARAMETER; - } + const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; + auto pWork = (TP_Work*)HeapAlloc(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(TP_WORK)); - const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; - auto pWork = (TP_Work*)HeapAlloc(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(TP_WORK)); + if (!pWork) + return STATUS_NO_MEMORY; - if (!pWork) - return STATUS_NO_MEMORY; + pWork->retaddr = _ReturnAddress(); - pWork->retaddr = _ReturnAddress(); + auto Status = TppWorkInitialize(pWork, Context, CallbackEnviron, Flags, GetTppSimplepCleanupGroupMemberVFuncs(), GetTppSimplepTaskVFuncs()); - auto Status = TppWorkInitialize(pWork, Context, CallbackEnviron, Flags, GetTppSimplepCleanupGroupMemberVFuncs(), GetTppSimplepTaskVFuncs()); + do + { + if (Status < 0) + break; - do - { - if (Status < 0) - break; + pWork->Callback = Callback; - pWork->Callback = Callback; + if (CallbackEnviron) + pWork->FinalizationCallback = CallbackEnviron->FinalizationCallback; - if (CallbackEnviron) - pWork->FinalizationCallback = CallbackEnviron->FinalizationCallback; + if (pWork->CleanupGroup) + Fallback::TppCleanupGroupAddMember(pWork); - if (pWork->CleanupGroup) - Fallback::TppCleanupGroupAddMember(pWork); + TppWorkPost(pWork); - TppWorkPost(pWork); + return STATUS_SUCCESS; + } while (false); - return STATUS_SUCCESS; - } while (false); + if (pWork) + HeapFree(ProcessHeap, 0, pWork); - if (pWork) - HeapFree(ProcessHeap, 0, pWork); + return Status; + } - return Status; - } + static + bool + __fastcall + TppCleanupGroupMemberRelease( + _TP_WORK* CleanupGroupMember, + bool RaiseIfAlreadyRaised + ) + { + auto orgFlags1 = InterlockedOr(&CleanupGroupMember->uFlags1, 0x10000); - static - bool - __fastcall - TppCleanupGroupMemberRelease( - _TP_WORK* CleanupGroupMember, - bool RaiseIfAlreadyRaised - ) + if (RaiseIfAlreadyRaised && (orgFlags1 & 0x10000)) { - auto orgFlags1 = InterlockedOr(&CleanupGroupMember->uFlags1, 0x10000); - - if (RaiseIfAlreadyRaised && (orgFlags1 & 0x10000)) - { - internal::RaiseStatus(STATUS_INVALID_PARAMETER); - } - - return (orgFlags1 & 0x30000) == 0; + internal::RaiseStatus(STATUS_INVALID_PARAMETER); } - static - void - WINAPI - TpReleaseWork( - TP_Work* Work) - { - if (Work == nullptr || (Work->uFlags1 & 0x10000) || Work->VFuncs != Fallback::GetTppWorkpCleanupGroupMemberVFuncs()) - { - internal::RaiseStatus(STATUS_INVALID_PARAMETER); - return; - } - - if (TppCleanupGroupMemberRelease(Work, true)) - { - Work->un58 = _ReturnAddress(); + return (orgFlags1 & 0x30000) == 0; + } - Work->Release(); - } + static + void + WINAPI + TpReleaseWork( + TP_Work* Work) + { + if (Work == nullptr || (Work->uFlags1 & 0x10000) || Work->VFuncs != Fallback::GetTppWorkpCleanupGroupMemberVFuncs()) + { + internal::RaiseStatus(STATUS_INVALID_PARAMETER); + return; } - static void __fastcall TppTimerpFree(_TP_WORK* Work) + if (TppCleanupGroupMemberRelease(Work, true)) { - if (Work) - { - const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; - HeapFree(ProcessHeap, 0, (_TP_TIMER*)Work); - } + Work->un58 = _ReturnAddress(); + + Work->Release(); } + } - static const _TP_CLEANUP_GROUP_FUNCS* __fastcall GetTppTimerpCleanupGroupMemberVFuncs() + static void __fastcall TppTimerpFree(_TP_WORK* Work) + { + if (Work) { - static _TP_CLEANUP_GROUP_FUNCS TppTimerpCleanupGroupMemberVFuncs = { &TppTimerpFree }; - return &TppTimerpCleanupGroupMemberVFuncs; + const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; + HeapFree(ProcessHeap, 0, (_TP_TIMER*)Work); } + } + static const _TP_CLEANUP_GROUP_FUNCS* __fastcall GetTppTimerpCleanupGroupMemberVFuncs() + { + static _TP_CLEANUP_GROUP_FUNCS TppTimerpCleanupGroupMemberVFuncs = { &TppTimerpFree }; + return &TppTimerpCleanupGroupMemberVFuncs; + } - static void __fastcall TppTimerpExecuteCallback(PTP_CALLBACK_INSTANCE Instance, _TP_WORK* Work) - { - ((PTP_TIMER_CALLBACK)Work->Callback)(Instance, Work->Context, (PTP_TIMER)Work); - } - static const TaskVFuncs* __fastcall GetTppTimerpTaskVFuncs() - { - static TaskVFuncs TppTimerpTaskVFuncs = { &TppTimerpExecuteCallback }; + static void __fastcall TppTimerpExecuteCallback(PTP_CALLBACK_INSTANCE Instance, _TP_WORK* Work) + { + ((PTP_TIMER_CALLBACK)Work->Callback)(Instance, Work->Context, (PTP_TIMER)Work); + } - return &TppTimerpTaskVFuncs; - } + static const TaskVFuncs* __fastcall GetTppTimerpTaskVFuncs() + { + static TaskVFuncs TppTimerpTaskVFuncs = { &TppTimerpExecuteCallback }; + return &TppTimerpTaskVFuncs; + } - static - NTSTATUS - __fastcall - TppTimerAlloc( - _TP_TIMER** ppTimer, - _In_ PTP_TIMER_CALLBACK Callback, - _Inout_opt_ PVOID Context, - _In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron, - DWORD Flags - ) - { - *ppTimer = nullptr; + static + NTSTATUS + __fastcall + TppTimerAlloc( + _TP_TIMER** ppTimer, + _In_ PTP_TIMER_CALLBACK Callback, + _Inout_opt_ PVOID Context, + _In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron, + DWORD Flags + ) + { + *ppTimer = nullptr; - const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; - auto pTimer = (_TP_TIMER*)HeapAlloc(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(_TP_TIMER)); - if (!pTimer) - return STATUS_NO_MEMORY; + const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; + auto pTimer = (_TP_TIMER*)HeapAlloc(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(_TP_TIMER)); - pTimer->retaddr = _ReturnAddress(); + if (!pTimer) + return STATUS_NO_MEMORY; - auto Status = TppWorkInitialize(pTimer, Context, CallbackEnviron, Flags | 0x1040000, GetTppTimerpCleanupGroupMemberVFuncs(), GetTppTimerpTaskVFuncs()); + pTimer->retaddr = _ReturnAddress(); - if (Status >= 0) - { - pTimer->Callback = Callback; + auto Status = TppWorkInitialize(pTimer, Context, CallbackEnviron, Flags | 0x1040000, GetTppTimerpCleanupGroupMemberVFuncs(), GetTppTimerpTaskVFuncs()); - if (CallbackEnviron) - pTimer->FinalizationCallback = CallbackEnviron->FinalizationCallback; + if (Status >= 0) + { + pTimer->Callback = Callback; - if (pTimer->CleanupGroup) - TppCleanupGroupAddMember(pTimer); + if (CallbackEnviron) + pTimer->FinalizationCallback = CallbackEnviron->FinalizationCallback; - *ppTimer = pTimer; + if (pTimer->CleanupGroup) + TppCleanupGroupAddMember(pTimer); - return Status; - } + *ppTimer = pTimer; - HeapFree(ProcessHeap, 0, pTimer); return Status; - } + HeapFree(ProcessHeap, 0, pTimer); + return Status; - static - NTSTATUS - __fastcall - TpAllocTimer( - _TP_TIMER** ppTimer, - _In_ PTP_TIMER_CALLBACK Callback, - _Inout_opt_ PVOID Context, - _In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron - ) - { - auto Flags = CallbackEnviron ? CallbackEnviron->u.Flags : 0; + } - if (ppTimer == nullptr || Callback == nullptr || (Flags & 0xFFFFFFFE)) - { - return STATUS_INVALID_PARAMETER; - } - auto Status = TppTimerAlloc(ppTimer, Callback, Context, CallbackEnviron, Flags); + static + NTSTATUS + __fastcall + TpAllocTimer( + _TP_TIMER** ppTimer, + _In_ PTP_TIMER_CALLBACK Callback, + _Inout_opt_ PVOID Context, + _In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron + ) + { + auto Flags = CallbackEnviron ? CallbackEnviron->u.Flags : 0; - if (Status >= 0) - { - (*ppTimer)->retaddr = _ReturnAddress(); - } + if (ppTimer == nullptr || Callback == nullptr || (Flags & 0xFFFFFFFE)) + { + return STATUS_INVALID_PARAMETER; + } - return Status; + auto Status = TppTimerAlloc(ppTimer, Callback, Context, CallbackEnviron, Flags); + + if (Status >= 0) + { + (*ppTimer)->retaddr = _ReturnAddress(); } + + return Status; } } #endif +} -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 12, - PTP_WORK, - WINAPI, - CreateThreadpoolWork, - _In_ PTP_WORK_CALLBACK pfnwk, - _Inout_opt_ PVOID pv, - _In_opt_ PTP_CALLBACK_ENVIRON pcbe - ) - { - if (auto const pCreateThreadpoolWork = try_get_CreateThreadpoolWork()) - { - return pCreateThreadpoolWork(pfnwk, pv, pcbe); - } - - //Fallback到我自己实现的 Tp - _TP_WORK* pWork; - - auto Status = Fallback::TpAllocWork(&pWork, pfnwk, pv, pcbe); - - if (Status >= 0) - { - return pWork; - } - - internal::BaseSetLastNTError(Status); - return nullptr; - } +namespace YY::Thunks +{ +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 12, + PTP_WORK, + WINAPI, + CreateThreadpoolWork, + _In_ PTP_WORK_CALLBACK pfnwk, + _Inout_opt_ PVOID pv, + _In_opt_ PTP_CALLBACK_ENVIRON pcbe + ) + { + if (auto const pCreateThreadpoolWork = try_get_CreateThreadpoolWork()) + { + return pCreateThreadpoolWork(pfnwk, pv, pcbe); + } + + //Fallback到我自己实现的 Tp + _TP_WORK* pWork; + + auto Status = Fallback::TpAllocWork(&pWork, pfnwk, pv, pcbe); + + if (Status >= 0) + { + return pWork; + } + + internal::BaseSetLastNTError(Status); + return nullptr; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - CloseThreadpoolWork, - _Inout_ PTP_WORK pwk - ) - { - if (auto const pCloseThreadpoolWork = try_get_CloseThreadpoolWork()) - { - return pCloseThreadpoolWork(pwk); - } + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + CloseThreadpoolWork, + _Inout_ PTP_WORK pwk + ) + { + if (auto const pCloseThreadpoolWork = try_get_CloseThreadpoolWork()) + { + return pCloseThreadpoolWork(pwk); + } - Fallback::TpReleaseWork(static_cast(pwk)); - } + Fallback::TpReleaseWork(static_cast(pwk)); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - SubmitThreadpoolWork, - _Inout_ PTP_WORK pwk - ) - { - if (auto const pSubmitThreadpoolWork = try_get_SubmitThreadpoolWork()) - { - return pSubmitThreadpoolWork(pwk); - } - - //参数验证 - if (pwk == nullptr - || (pwk->uFlags1 & 0x30000) - || pwk->VFuncs != Fallback::GetTppWorkpCleanupGroupMemberVFuncs()) - { +#if (YY_Thunks_Target < __WindowsNT6) + + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + SubmitThreadpoolWork, + _Inout_ PTP_WORK pwk + ) + { + if (auto const pSubmitThreadpoolWork = try_get_SubmitThreadpoolWork()) + { + return pSubmitThreadpoolWork(pwk); + } + + //参数验证 + if (pwk == nullptr + || (pwk->uFlags1 & 0x30000) + || pwk->VFuncs != Fallback::GetTppWorkpCleanupGroupMemberVFuncs()) + { internal::RaiseStatus(STATUS_INVALID_PARAMETER); - return; - } + return; + } - Fallback::TppWorkPost(static_cast(pwk)); - } + Fallback::TppWorkPost(static_cast(pwk)); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 8, - VOID, - WINAPI, - WaitForThreadpoolWorkCallbacks, - _Inout_ PTP_WORK pwk, - _In_ BOOL fCancelPendingCallbacks - ) - { - if (auto const pWaitForThreadpoolWorkCallbacks = try_get_WaitForThreadpoolWorkCallbacks()) - { - return pWaitForThreadpoolWorkCallbacks(pwk, fCancelPendingCallbacks); - } - - if (pwk == nullptr - || (pwk->uFlags1 & 0x30000) - || (pwk->VFuncs != Fallback::GetTppWorkpCleanupGroupMemberVFuncs())) - { +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 8, + VOID, + WINAPI, + WaitForThreadpoolWorkCallbacks, + _Inout_ PTP_WORK pwk, + _In_ BOOL fCancelPendingCallbacks + ) + { + if (auto const pWaitForThreadpoolWorkCallbacks = try_get_WaitForThreadpoolWorkCallbacks()) + { + return pWaitForThreadpoolWorkCallbacks(pwk, fCancelPendingCallbacks); + } + + if (pwk == nullptr + || (pwk->uFlags1 & 0x30000) + || (pwk->VFuncs != Fallback::GetTppWorkpCleanupGroupMemberVFuncs())) + { internal::RaiseStatus(STATUS_INVALID_PARAMETER); - return; - } + return; + } Fallback::TppWorkWait(pwk, fCancelPendingCallbacks); - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 12, - PTP_TIMER, - WINAPI, - CreateThreadpoolTimer, - _In_ PTP_TIMER_CALLBACK pfnti, - _Inout_opt_ PVOID pv, - _In_opt_ PTP_CALLBACK_ENVIRON pcbe - ) - { - if (auto const pCreateThreadpoolTimer = try_get_CreateThreadpoolTimer()) - { - return pCreateThreadpoolTimer(pfnti, pv, pcbe); - } + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 12, + PTP_TIMER, + WINAPI, + CreateThreadpoolTimer, + _In_ PTP_TIMER_CALLBACK pfnti, + _Inout_opt_ PVOID pv, + _In_opt_ PTP_CALLBACK_ENVIRON pcbe + ) + { + if (auto const pCreateThreadpoolTimer = try_get_CreateThreadpoolTimer()) + { + return pCreateThreadpoolTimer(pfnti, pv, pcbe); + } - PTP_TIMER pTimer; + PTP_TIMER pTimer; - auto Status = Fallback::TpAllocTimer(&pTimer, pfnti, pv, pcbe); + auto Status = Fallback::TpAllocTimer(&pTimer, pfnti, pv, pcbe); - if (Status >= 0) - { - return pTimer; - } + if (Status >= 0) + { + return pTimer; + } - internal::BaseSetLastNTError(Status); + internal::BaseSetLastNTError(Status); - return nullptr; - } + return nullptr; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 16, - VOID, - WINAPI, - SetThreadpoolTimer, - _Inout_ PTP_TIMER pti, - _In_opt_ PFILETIME pftDueTime, - _In_ DWORD msPeriod, - _In_opt_ DWORD msWindowLength - ) - { - if (auto const pSetThreadpoolTimer = try_get_SetThreadpoolTimer()) - { - return pSetThreadpoolTimer(pti, pftDueTime, msPeriod, msWindowLength); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 16, + VOID, + WINAPI, + SetThreadpoolTimer, + _Inout_ PTP_TIMER pti, + _In_opt_ PFILETIME pftDueTime, + _In_ DWORD msPeriod, + _In_opt_ DWORD msWindowLength + ) + { + if (auto const pSetThreadpoolTimer = try_get_SetThreadpoolTimer()) + { + return pSetThreadpoolTimer(pti, pftDueTime, msPeriod, msWindowLength); + } auto _pTimer = static_cast(pti); - if (_pTimer == nullptr - || (_pTimer->uFlags1 & 0x30000) - || _pTimer->VFuncs != Fallback::GetTppTimerpCleanupGroupMemberVFuncs()) - { - internal::RaiseStatus(STATUS_INVALID_PARAMETER); - return; - } + if (_pTimer == nullptr + || (_pTimer->uFlags1 & 0x30000) + || _pTimer->VFuncs != Fallback::GetTppTimerpCleanupGroupMemberVFuncs()) + { + internal::RaiseStatus(STATUS_INVALID_PARAMETER); + return; + } - if (pftDueTime == nullptr) - { + if (pftDueTime == nullptr) + { if (auto hOrgQueueTimer = InterlockedExchangePointer(&pti->hQueueTimer, nullptr)) { //销毁计数器 @@ -1313,35 +1313,35 @@ namespace YY::Thunks SetEvent(pti->hEvent); _pTimer->Release(); } - return; - } + return; + } _pTimer->AddRef(); - DWORD DueTime = 0; - LARGE_INTEGER lDueTime; - lDueTime.LowPart = pftDueTime->dwLowDateTime; - lDueTime.HighPart = pftDueTime->dwHighDateTime; - - if (lDueTime.QuadPart < 0) - { - //相对时间 - DueTime = static_cast(lDueTime.QuadPart / -10'000); - } - else if (lDueTime.QuadPart > 0) - { - //绝对时间 - FILETIME CurrentTime; - GetSystemTimeAsFileTime(&CurrentTime); - LARGE_INTEGER lCurrentTime; - lCurrentTime.LowPart = CurrentTime.dwLowDateTime; - lCurrentTime.HighPart = CurrentTime.dwHighDateTime; - - if (lDueTime.QuadPart > lCurrentTime.QuadPart) - { - DueTime = static_cast((lDueTime.QuadPart - lCurrentTime.QuadPart) / 10'000); - } - } + DWORD DueTime = 0; + LARGE_INTEGER lDueTime; + lDueTime.LowPart = pftDueTime->dwLowDateTime; + lDueTime.HighPart = pftDueTime->dwHighDateTime; + + if (lDueTime.QuadPart < 0) + { + //相对时间 + DueTime = static_cast(lDueTime.QuadPart / -10'000); + } + else if (lDueTime.QuadPart > 0) + { + //绝对时间 + FILETIME CurrentTime; + GetSystemTimeAsFileTime(&CurrentTime); + LARGE_INTEGER lCurrentTime; + lCurrentTime.LowPart = CurrentTime.dwLowDateTime; + lCurrentTime.HighPart = CurrentTime.dwHighDateTime; + + if (lDueTime.QuadPart > lCurrentTime.QuadPart) + { + DueTime = static_cast((lDueTime.QuadPart - lCurrentTime.QuadPart) / 10'000); + } + } // Timer 比较特殊,因为始终只有一个句柄,hEvent不需要引用计数。 ::AcquireSRWLockExclusive(&_pTimer->QueueTimerLock); @@ -1352,59 +1352,59 @@ namespace YY::Thunks _pTimer->Release(); } ResetEvent(_pTimer->hEvent); - auto bRet = CreateTimerQueueTimer(&pti->hQueueTimer, nullptr, [](PVOID Parameter, BOOLEAN) - { - auto _pTimer = (PTP_TIMER)Parameter; - TP_CALLBACK_INSTANCE Instance = {}; + auto bRet = CreateTimerQueueTimer(&pti->hQueueTimer, nullptr, [](PVOID Parameter, BOOLEAN) + { + auto _pTimer = (PTP_TIMER)Parameter; + TP_CALLBACK_INSTANCE Instance = {}; _pTimer->pTaskVFuncs->pExecuteCallback(&Instance, _pTimer); - Fallback::DoWhenCallbackReturns(&Instance); + Fallback::DoWhenCallbackReturns(&Instance); SetEvent(_pTimer->hEvent); - }, pti, DueTime, msPeriod, 0); + }, pti, DueTime, msPeriod, 0); ::ReleaseSRWLockExclusive(&pti->QueueTimerLock); - if (!bRet) - { + if (!bRet) + { // 创建失败了,所以把之前的内存块引用计数撤销 SetEvent(_pTimer->hEvent); _pTimer->Release(); - } - } + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 8, - VOID, - WINAPI, - WaitForThreadpoolTimerCallbacks, - _Inout_ PTP_TIMER Timer, - _In_ BOOL CancelPendingCallbacks - ) - { - if (auto const pWaitForThreadpoolTimerCallbacks = try_get_WaitForThreadpoolTimerCallbacks()) - { - return pWaitForThreadpoolTimerCallbacks(Timer, CancelPendingCallbacks); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 8, + VOID, + WINAPI, + WaitForThreadpoolTimerCallbacks, + _Inout_ PTP_TIMER Timer, + _In_ BOOL CancelPendingCallbacks + ) + { + if (auto const pWaitForThreadpoolTimerCallbacks = try_get_WaitForThreadpoolTimerCallbacks()) + { + return pWaitForThreadpoolTimerCallbacks(Timer, CancelPendingCallbacks); + } auto _pTimer = static_cast(Timer); - if (_pTimer == nullptr - || (_pTimer->uFlags1 & 0x30000) - || _pTimer->VFuncs != Fallback::GetTppTimerpCleanupGroupMemberVFuncs()) - { - internal::RaiseStatus(STATUS_INVALID_PARAMETER); - return; - } + if (_pTimer == nullptr + || (_pTimer->uFlags1 & 0x30000) + || _pTimer->VFuncs != Fallback::GetTppTimerpCleanupGroupMemberVFuncs()) + { + internal::RaiseStatus(STATUS_INVALID_PARAMETER); + return; + } if (CancelPendingCallbacks) { @@ -1423,459 +1423,459 @@ namespace YY::Thunks WaitForSingleObject(_pTimer->hEvent, INFINITE); } } - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - CloseThreadpoolTimer, - _Inout_ PTP_TIMER Timer - ) - { - if (auto const pCloseThreadpoolTimer = try_get_CloseThreadpoolTimer()) - { - return pCloseThreadpoolTimer(Timer); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + CloseThreadpoolTimer, + _Inout_ PTP_TIMER Timer + ) + { + if (auto const pCloseThreadpoolTimer = try_get_CloseThreadpoolTimer()) + { + return pCloseThreadpoolTimer(Timer); + } auto _pTimer = static_cast(Timer); - if (_pTimer == nullptr - || (_pTimer->uFlags1 & 0x10000) - || _pTimer->VFuncs != Fallback::GetTppTimerpCleanupGroupMemberVFuncs()) - { - internal::RaiseStatus(STATUS_INVALID_PARAMETER); - return; - } + if (_pTimer == nullptr + || (_pTimer->uFlags1 & 0x10000) + || _pTimer->VFuncs != Fallback::GetTppTimerpCleanupGroupMemberVFuncs()) + { + internal::RaiseStatus(STATUS_INVALID_PARAMETER); + return; + } - if (Fallback::TppCleanupGroupMemberRelease(_pTimer, true)) - { + if (Fallback::TppCleanupGroupMemberRelease(_pTimer, true)) + { _pTimer->un58 = _ReturnAddress(); - if (auto hOrgQueueTimer = InterlockedExchangePointer(&_pTimer->hQueueTimer, nullptr)) - { - //销毁计数器 - DeleteTimerQueueTimer(nullptr, hOrgQueueTimer, INVALID_HANDLE_VALUE); + if (auto hOrgQueueTimer = InterlockedExchangePointer(&_pTimer->hQueueTimer, nullptr)) + { + //销毁计数器 + DeleteTimerQueueTimer(nullptr, hOrgQueueTimer, INVALID_HANDLE_VALUE); SetEvent(_pTimer->hEvent); _pTimer->Release(); - } + } _pTimer->Release(); - } - } + } + } #endif - -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 8, - VOID, - WINAPI, - SetEventWhenCallbackReturns, - _Inout_ PTP_CALLBACK_INSTANCE Instance, - _In_ HANDLE Event - ) - { - if (auto const pSetEventWhenCallbackReturns = try_get_SetEventWhenCallbackReturns()) - { - return pSetEventWhenCallbackReturns(Instance, Event); - } - - - //只允许被设置一次 - if (Instance == nullptr - || Event == nullptr - || Event == INVALID_HANDLE_VALUE - || Instance->Event != nullptr) - { - internal::RaiseStatus(STATUS_INVALID_PARAMETER); - return; - } - - Instance->Event = Event; - } + +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 8, + VOID, + WINAPI, + SetEventWhenCallbackReturns, + _Inout_ PTP_CALLBACK_INSTANCE Instance, + _In_ HANDLE Event + ) + { + if (auto const pSetEventWhenCallbackReturns = try_get_SetEventWhenCallbackReturns()) + { + return pSetEventWhenCallbackReturns(Instance, Event); + } + + + //只允许被设置一次 + if (Instance == nullptr + || Event == nullptr + || Event == INVALID_HANDLE_VALUE + || Instance->Event != nullptr) + { + internal::RaiseStatus(STATUS_INVALID_PARAMETER); + return; + } + + Instance->Event = Event; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 12, - VOID, - WINAPI, - ReleaseSemaphoreWhenCallbackReturns, - _Inout_ PTP_CALLBACK_INSTANCE Instance, - _In_ HANDLE Semaphore, - _In_ DWORD ReleaseCount - ) - { - if (auto const pReleaseSemaphoreWhenCallbackReturns = try_get_ReleaseSemaphoreWhenCallbackReturns()) - { - return pReleaseSemaphoreWhenCallbackReturns(Instance, Semaphore, ReleaseCount); - } - - //只允许被设置一次 - if (Instance == nullptr - || Semaphore == nullptr - || Semaphore == INVALID_HANDLE_VALUE - || ReleaseCount == 0 - || Instance->Semaphore != nullptr) - { - internal::RaiseStatus(STATUS_INVALID_PARAMETER); - return; - } - - Instance->Semaphore = Semaphore; - Instance->ReleaseCount = ReleaseCount; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 12, + VOID, + WINAPI, + ReleaseSemaphoreWhenCallbackReturns, + _Inout_ PTP_CALLBACK_INSTANCE Instance, + _In_ HANDLE Semaphore, + _In_ DWORD ReleaseCount + ) + { + if (auto const pReleaseSemaphoreWhenCallbackReturns = try_get_ReleaseSemaphoreWhenCallbackReturns()) + { + return pReleaseSemaphoreWhenCallbackReturns(Instance, Semaphore, ReleaseCount); + } + + //只允许被设置一次 + if (Instance == nullptr + || Semaphore == nullptr + || Semaphore == INVALID_HANDLE_VALUE + || ReleaseCount == 0 + || Instance->Semaphore != nullptr) + { + internal::RaiseStatus(STATUS_INVALID_PARAMETER); + return; + } + + Instance->Semaphore = Semaphore; + Instance->ReleaseCount = ReleaseCount; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 8, - VOID, - WINAPI, - ReleaseMutexWhenCallbackReturns, - _Inout_ PTP_CALLBACK_INSTANCE Instance, - _In_ HANDLE Mutex - ) - { - if (auto const pReleaseMutexWhenCallbackReturns = try_get_ReleaseMutexWhenCallbackReturns()) - { - return pReleaseMutexWhenCallbackReturns(Instance, Mutex); - } - - //只允许被设置一次 - if (Instance == nullptr - || Mutex == nullptr - || Mutex == INVALID_HANDLE_VALUE - || Instance->Mutex != nullptr) - { - internal::RaiseStatus(STATUS_INVALID_PARAMETER); - return; - } - - Instance->Mutex = Mutex; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 8, + VOID, + WINAPI, + ReleaseMutexWhenCallbackReturns, + _Inout_ PTP_CALLBACK_INSTANCE Instance, + _In_ HANDLE Mutex + ) + { + if (auto const pReleaseMutexWhenCallbackReturns = try_get_ReleaseMutexWhenCallbackReturns()) + { + return pReleaseMutexWhenCallbackReturns(Instance, Mutex); + } + + //只允许被设置一次 + if (Instance == nullptr + || Mutex == nullptr + || Mutex == INVALID_HANDLE_VALUE + || Instance->Mutex != nullptr) + { + internal::RaiseStatus(STATUS_INVALID_PARAMETER); + return; + } + + Instance->Mutex = Mutex; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 8, - VOID, - WINAPI, - LeaveCriticalSectionWhenCallbackReturns, - _Inout_ PTP_CALLBACK_INSTANCE Instance, - _Inout_ PCRITICAL_SECTION CriticalSection - ) - { - if (auto const pLeaveCriticalSectionWhenCallbackReturns = try_get_LeaveCriticalSectionWhenCallbackReturns()) - { - return pLeaveCriticalSectionWhenCallbackReturns(Instance, CriticalSection); - } - - //只允许被设置一次 - if (Instance == nullptr - || CriticalSection == nullptr - || Instance->CriticalSection != nullptr) - { - internal::RaiseStatus(STATUS_INVALID_PARAMETER); - return; - } - - Instance->CriticalSection = CriticalSection; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 8, + VOID, + WINAPI, + LeaveCriticalSectionWhenCallbackReturns, + _Inout_ PTP_CALLBACK_INSTANCE Instance, + _Inout_ PCRITICAL_SECTION CriticalSection + ) + { + if (auto const pLeaveCriticalSectionWhenCallbackReturns = try_get_LeaveCriticalSectionWhenCallbackReturns()) + { + return pLeaveCriticalSectionWhenCallbackReturns(Instance, CriticalSection); + } + + //只允许被设置一次 + if (Instance == nullptr + || CriticalSection == nullptr + || Instance->CriticalSection != nullptr) + { + internal::RaiseStatus(STATUS_INVALID_PARAMETER); + return; + } + + Instance->CriticalSection = CriticalSection; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 8, - VOID, - WINAPI, - FreeLibraryWhenCallbackReturns, - _Inout_ PTP_CALLBACK_INSTANCE Instance, - _In_ HMODULE DllHandle - ) - { - if (auto const pFreeLibraryWhenCallbackReturns = try_get_FreeLibraryWhenCallbackReturns()) - { - return pFreeLibraryWhenCallbackReturns(Instance, DllHandle); - } - - //只允许被设置一次 - if (Instance == nullptr - || DllHandle == nullptr - || DllHandle == INVALID_HANDLE_VALUE - || Instance->DllHandle != nullptr) - { - internal::RaiseStatus(STATUS_INVALID_PARAMETER); - return; - } - - Instance->DllHandle = DllHandle; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 8, + VOID, + WINAPI, + FreeLibraryWhenCallbackReturns, + _Inout_ PTP_CALLBACK_INSTANCE Instance, + _In_ HMODULE DllHandle + ) + { + if (auto const pFreeLibraryWhenCallbackReturns = try_get_FreeLibraryWhenCallbackReturns()) + { + return pFreeLibraryWhenCallbackReturns(Instance, DllHandle); + } + + //只允许被设置一次 + if (Instance == nullptr + || DllHandle == nullptr + || DllHandle == INVALID_HANDLE_VALUE + || Instance->DllHandle != nullptr) + { + internal::RaiseStatus(STATUS_INVALID_PARAMETER); + return; + } + + Instance->DllHandle = DllHandle; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 12, - BOOL, - WINAPI, - TrySubmitThreadpoolCallback, - _In_ PTP_SIMPLE_CALLBACK Callback, - _Inout_opt_ PVOID Context, - _In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron - ) - { - if (auto const pTrySubmitThreadpoolCallback = try_get_TrySubmitThreadpoolCallback()) - { - return pTrySubmitThreadpoolCallback(Callback, Context, CallbackEnviron); - } - - - auto lStatus = Fallback::TpSimpleTryPost(Callback, Context, CallbackEnviron); - - if (lStatus >= 0) - { - return TRUE; - } - else - { - internal::NtStatusToDosError(lStatus); - return FALSE; - } - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 12, + BOOL, + WINAPI, + TrySubmitThreadpoolCallback, + _In_ PTP_SIMPLE_CALLBACK Callback, + _Inout_opt_ PVOID Context, + _In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron + ) + { + if (auto const pTrySubmitThreadpoolCallback = try_get_TrySubmitThreadpoolCallback()) + { + return pTrySubmitThreadpoolCallback(Callback, Context, CallbackEnviron); + } + + + auto lStatus = Fallback::TpSimpleTryPost(Callback, Context, CallbackEnviron); + + if (lStatus >= 0) + { + return TRUE; + } + else + { + internal::NtStatusToDosError(lStatus); + return FALSE; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 12, - PTP_WAIT, - WINAPI, - CreateThreadpoolWait, - _In_ PTP_WAIT_CALLBACK Callback, - _Inout_opt_ PVOID Context, - _In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron - ) - { - if (auto const pCreateThreadpoolWait = try_get_CreateThreadpoolWait()) - { - return pCreateThreadpoolWait(Callback, Context, CallbackEnviron); - } + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 12, + PTP_WAIT, + WINAPI, + CreateThreadpoolWait, + _In_ PTP_WAIT_CALLBACK Callback, + _Inout_opt_ PVOID Context, + _In_opt_ PTP_CALLBACK_ENVIRON CallbackEnviron + ) + { + if (auto const pCreateThreadpoolWait = try_get_CreateThreadpoolWait()) + { + return pCreateThreadpoolWait(Callback, Context, CallbackEnviron); + } - auto Flags = CallbackEnviron ? CallbackEnviron->u.Flags : 0; + auto Flags = CallbackEnviron ? CallbackEnviron->u.Flags : 0; - if (Callback == nullptr || (Flags & 0xFFFFFFFE) != 0) - { - internal::RaiseStatus(STATUS_INVALID_PARAMETER); - return nullptr; - } + if (Callback == nullptr || (Flags & 0xFFFFFFFE) != 0) + { + internal::RaiseStatus(STATUS_INVALID_PARAMETER); + return nullptr; + } - NTSTATUS Status = STATUS_SUCCESS; + NTSTATUS Status = STATUS_SUCCESS; - const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; - auto pWait = (_TP_WAIT*)HeapAlloc(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(_TP_WAIT)); + const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; + auto pWait = (_TP_WAIT*)HeapAlloc(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(_TP_WAIT)); - do - { - if (!pWait) - { - Status = STATUS_NO_MEMORY; - break; - } + do + { + if (!pWait) + { + Status = STATUS_NO_MEMORY; + break; + } - - pWait->retaddr = _ReturnAddress(); + + pWait->retaddr = _ReturnAddress(); - Status = Fallback::TppWorkInitialize(pWait, Context, CallbackEnviron, Flags | 0x40000, Fallback::GetTppWaitpCleanupGroupMemberVFuncs(), Fallback::GetTppWaitpTaskVFuncs()); + Status = Fallback::TppWorkInitialize(pWait, Context, CallbackEnviron, Flags | 0x40000, Fallback::GetTppWaitpCleanupGroupMemberVFuncs(), Fallback::GetTppWaitpTaskVFuncs()); - if (Status < 0) - break; + if (Status < 0) + break; - pWait->Callback = Callback; + pWait->Callback = Callback; - if (CallbackEnviron) - pWait->FinalizationCallback = CallbackEnviron->FinalizationCallback; + if (CallbackEnviron) + pWait->FinalizationCallback = CallbackEnviron->FinalizationCallback; - if (pWait->CleanupGroup) - Fallback::TppCleanupGroupAddMember(pWait); + if (pWait->CleanupGroup) + Fallback::TppCleanupGroupAddMember(pWait); - return pWait; + return pWait; - } while (false); + } while (false); - if(pWait) - HeapFree(ProcessHeap, 0, pWait); + if(pWait) + HeapFree(ProcessHeap, 0, pWait); - internal::NtStatusToDosError(Status); + internal::NtStatusToDosError(Status); - return nullptr; - } + return nullptr; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - VOID, - WINAPI, - CloseThreadpoolWait, - _Inout_ PTP_WAIT Wait - ) - { - if (auto const pCloseThreadpoolWait = try_get_CloseThreadpoolWait()) - { - return pCloseThreadpoolWait(Wait); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + VOID, + WINAPI, + CloseThreadpoolWait, + _Inout_ PTP_WAIT Wait + ) + { + if (auto const pCloseThreadpoolWait = try_get_CloseThreadpoolWait()) + { + return pCloseThreadpoolWait(Wait); + } auto _pWait = static_cast(Wait); - if (_pWait == nullptr || (_pWait->uFlags1 & 0x10000) || _pWait->VFuncs != Fallback::GetTppWaitpCleanupGroupMemberVFuncs()) - { - internal::RaiseStatus(STATUS_INVALID_PARAMETER); - return; - } - - if (Fallback::TppCleanupGroupMemberRelease(_pWait, true)) - { + if (_pWait == nullptr || (_pWait->uFlags1 & 0x10000) || _pWait->VFuncs != Fallback::GetTppWaitpCleanupGroupMemberVFuncs()) + { + internal::RaiseStatus(STATUS_INVALID_PARAMETER); + return; + } + + if (Fallback::TppCleanupGroupMemberRelease(_pWait, true)) + { _pWait->un58 = _ReturnAddress(); - if (auto hOrgWaitObject = InterlockedExchangePointer(&_pWait->hWaitObject, nullptr)) - { - UnregisterWait(hOrgWaitObject); + if (auto hOrgWaitObject = InterlockedExchangePointer(&_pWait->hWaitObject, nullptr)) + { + UnregisterWait(hOrgWaitObject); _pWait->Release(); - } + } _pWait->Release(); - } - } + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 12, - VOID, - WINAPI, - SetThreadpoolWait, - _Inout_ PTP_WAIT Wait, - _In_opt_ HANDLE Handle, - _In_opt_ PFILETIME Timeout - ) - { - if (auto const pSetThreadpoolWait = try_get_SetThreadpoolWait()) - { - return pSetThreadpoolWait(Wait, Handle, Timeout); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 12, + VOID, + WINAPI, + SetThreadpoolWait, + _Inout_ PTP_WAIT Wait, + _In_opt_ HANDLE Handle, + _In_opt_ PFILETIME Timeout + ) + { + if (auto const pSetThreadpoolWait = try_get_SetThreadpoolWait()) + { + return pSetThreadpoolWait(Wait, Handle, Timeout); + } auto _pWait = static_cast(Wait); - if (_pWait == nullptr || (_pWait->uFlags1 & 0x30000) || _pWait->VFuncs != Fallback::GetTppWaitpCleanupGroupMemberVFuncs()) - { - internal::RaiseStatus(STATUS_INVALID_PARAMETER); - return; - } - - if (Handle == nullptr) - { - //停止 - if (auto hOrgWaitObject = InterlockedExchangePointer(&_pWait->hWaitObject, nullptr)) - { + if (_pWait == nullptr || (_pWait->uFlags1 & 0x30000) || _pWait->VFuncs != Fallback::GetTppWaitpCleanupGroupMemberVFuncs()) + { + internal::RaiseStatus(STATUS_INVALID_PARAMETER); + return; + } + + if (Handle == nullptr) + { + //停止 + if (auto hOrgWaitObject = InterlockedExchangePointer(&_pWait->hWaitObject, nullptr)) + { UnregisterWaitEx(hOrgWaitObject, INVALID_HANDLE_VALUE); SetEvent(_pWait->hEvent); _pWait->Release(); - } - - return; - } - - ULONG dwMilliseconds; - - if (Timeout == nullptr) - { - dwMilliseconds = INFINITE; - } - else - { - LARGE_INTEGER Time; - Time.LowPart = Timeout->dwLowDateTime; - Time.HighPart = Timeout->dwHighDateTime; - - if (Time.QuadPart < 0) - { - //这是一个相对时间 - dwMilliseconds = static_cast(Time.QuadPart / -10'000); - } - else if (Time.QuadPart == 0) - { - dwMilliseconds = 0; - } - else - { - //绝对时间 - FILETIME CurrentTime; - GetSystemTimeAsFileTime(&CurrentTime); - LARGE_INTEGER lCurrentTime; - lCurrentTime.LowPart = CurrentTime.dwLowDateTime; - lCurrentTime.HighPart = CurrentTime.dwHighDateTime; - - if (Time.QuadPart > lCurrentTime.QuadPart) - { - dwMilliseconds = static_cast((Time.QuadPart - lCurrentTime.QuadPart) / 10'000); - } - else - { - dwMilliseconds = 0; - } - } - } + } + + return; + } + + ULONG dwMilliseconds; + + if (Timeout == nullptr) + { + dwMilliseconds = INFINITE; + } + else + { + LARGE_INTEGER Time; + Time.LowPart = Timeout->dwLowDateTime; + Time.HighPart = Timeout->dwHighDateTime; + + if (Time.QuadPart < 0) + { + //这是一个相对时间 + dwMilliseconds = static_cast(Time.QuadPart / -10'000); + } + else if (Time.QuadPart == 0) + { + dwMilliseconds = 0; + } + else + { + //绝对时间 + FILETIME CurrentTime; + GetSystemTimeAsFileTime(&CurrentTime); + LARGE_INTEGER lCurrentTime; + lCurrentTime.LowPart = CurrentTime.dwLowDateTime; + lCurrentTime.HighPart = CurrentTime.dwHighDateTime; + + if (Time.QuadPart > lCurrentTime.QuadPart) + { + dwMilliseconds = static_cast((Time.QuadPart - lCurrentTime.QuadPart) / 10'000); + } + else + { + dwMilliseconds = 0; + } + } + } _pWait->AddRef(); @@ -1888,15 +1888,15 @@ namespace YY::Thunks _pWait->Release(); } ResetEvent(_pWait->hEvent); - auto bRet = RegisterWaitForSingleObject( - &_pWait->hWaitObject, - Handle, - []( - PVOID lpParameter, - BOOLEAN TimerOrWaitFired - ) - { - auto Wait = (PTP_WAIT)lpParameter; + auto bRet = RegisterWaitForSingleObject( + &_pWait->hWaitObject, + Handle, + []( + PVOID lpParameter, + BOOLEAN TimerOrWaitFired + ) + { + auto Wait = (PTP_WAIT)lpParameter; // 准备开始调用,增加一次Working计数 TP_CALLBACK_INSTANCE Instance = {}; @@ -1908,48 +1908,48 @@ namespace YY::Thunks Fallback::DoWhenCallbackReturns(&Instance); SetEvent(Wait->hEvent); - }, + }, _pWait, - dwMilliseconds, - WT_EXECUTEONLYONCE); + dwMilliseconds, + WT_EXECUTEONLYONCE); ::ReleaseSRWLockExclusive(&_pWait->WaitObjectLock); - if (!bRet) - { + if (!bRet) + { SetEvent(_pWait->hEvent); _pWait->Release(); - } - } + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 8, - VOID, - WINAPI, - WaitForThreadpoolWaitCallbacks, - _Inout_ PTP_WAIT Wait, - _In_ BOOL CancelPendingCallbacks - ) - { - if (auto const pWaitForThreadpoolWaitCallbacks = try_get_WaitForThreadpoolWaitCallbacks()) - { - return pWaitForThreadpoolWaitCallbacks(Wait, CancelPendingCallbacks); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 8, + VOID, + WINAPI, + WaitForThreadpoolWaitCallbacks, + _Inout_ PTP_WAIT Wait, + _In_ BOOL CancelPendingCallbacks + ) + { + if (auto const pWaitForThreadpoolWaitCallbacks = try_get_WaitForThreadpoolWaitCallbacks()) + { + return pWaitForThreadpoolWaitCallbacks(Wait, CancelPendingCallbacks); + } auto _pWait = static_cast(Wait); - if (_pWait == nullptr - || (_pWait->uFlags1 & 0x30000) - || _pWait->VFuncs != Fallback::GetTppWaitpCleanupGroupMemberVFuncs()) - { - internal::RaiseStatus(STATUS_INVALID_PARAMETER); - return; - } + if (_pWait == nullptr + || (_pWait->uFlags1 & 0x30000) + || _pWait->VFuncs != Fallback::GetTppWaitpCleanupGroupMemberVFuncs()) + { + internal::RaiseStatus(STATUS_INVALID_PARAMETER); + return; + } if (CancelPendingCallbacks) { @@ -1967,18 +1967,18 @@ namespace YY::Thunks WaitForSingleObject(_pWait->hEvent, INFINITE); } } - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 16, - PTP_IO, + __DEFINE_THUNK( + kernel32, + 16, + PTP_IO, WINAPI, CreateThreadpoolIo, _In_ HANDLE _hFile, @@ -1986,11 +1986,11 @@ namespace YY::Thunks _Inout_opt_ PVOID _pUserData, _In_opt_ PTP_CALLBACK_ENVIRON _pCallbackEnviron ) - { - if (auto const _pfnCreateThreadpoolIo = try_get_CreateThreadpoolIo()) - { - return _pfnCreateThreadpoolIo(_hFile, _pfnIoCallback, _pUserData, _pCallbackEnviron); - } + { + if (auto const _pfnCreateThreadpoolIo = try_get_CreateThreadpoolIo()) + { + return _pfnCreateThreadpoolIo(_hFile, _pfnIoCallback, _pUserData, _pCallbackEnviron); + } ///////////////////////////////////////////////////////// // TpAllocIoCompletion @@ -2093,77 +2093,77 @@ namespace YY::Thunks _pIo->Release(); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return nullptr; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 4, - VOID, + __DEFINE_THUNK( + kernel32, + 4, + VOID, WINAPI, StartThreadpoolIo, _Inout_ PTP_IO _pIo2 ) - { - if (auto const _pfnStartThreadpoolIo = try_get_StartThreadpoolIo()) - { - return _pfnStartThreadpoolIo(_pIo2); - } + { + if (auto const _pfnStartThreadpoolIo = try_get_StartThreadpoolIo()) + { + return _pfnStartThreadpoolIo(_pIo2); + } auto _pIo = static_cast(_pIo2); _pIo->AddRef(); _pIo->AddPendingCount(); - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 4, - VOID, + __DEFINE_THUNK( + kernel32, + 4, + VOID, WINAPI, CancelThreadpoolIo, _Inout_ PTP_IO _pIo2 ) - { - if (auto const _pfnCancelThreadpoolIo = try_get_CancelThreadpoolIo()) - { - return _pfnCancelThreadpoolIo(_pIo2); - } + { + if (auto const _pfnCancelThreadpoolIo = try_get_CancelThreadpoolIo()) + { + return _pfnCancelThreadpoolIo(_pIo2); + } auto _pIo = static_cast(_pIo2); _pIo->TryReleasePendingount(); _pIo->Release(); - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 4, - VOID, + __DEFINE_THUNK( + kernel32, + 4, + VOID, WINAPI, CloseThreadpoolIo, _Inout_ PTP_IO _pIo2 ) - { - if (auto const _pfnCloseThreadpoolIo = try_get_CloseThreadpoolIo()) - { - return _pfnCloseThreadpoolIo(_pIo2); - } + { + if (auto const _pfnCloseThreadpoolIo = try_get_CloseThreadpoolIo()) + { + return _pfnCloseThreadpoolIo(_pIo2); + } // TpReleaseIoCompletion auto _pIo = static_cast(_pIo2); if (Fallback::TppCleanupGroupMemberRelease(_pIo, 1)) @@ -2171,28 +2171,28 @@ namespace YY::Thunks _pIo->un58 = _ReturnAddress(); _pIo->Release(); } - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 8, - VOID, + __DEFINE_THUNK( + kernel32, + 8, + VOID, WINAPI, WaitForThreadpoolIoCallbacks, _Inout_ PTP_IO _pIo, _In_ BOOL _bCancelPendingCallbacks ) - { - if (auto const _pfnWaitForThreadpoolIoCallbacks = try_get_WaitForThreadpoolIoCallbacks()) - { - return _pfnWaitForThreadpoolIoCallbacks(_pIo, _bCancelPendingCallbacks); - } + { + if (auto const _pfnWaitForThreadpoolIoCallbacks = try_get_WaitForThreadpoolIoCallbacks()) + { + return _pfnWaitForThreadpoolIoCallbacks(_pIo, _bCancelPendingCallbacks); + } // TpWaitForIoCompletion if (_pIo == nullptr || (_pIo->uFlags1 & 0x30000) || _pIo->VFuncs != Fallback::GetTppIopCleanupGroupMemberVFuncs()) @@ -2202,27 +2202,27 @@ namespace YY::Thunks } Fallback::TppWorkWait(_pIo, _bCancelPendingCallbacks, true); - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 4, - PTP_POOL, + __DEFINE_THUNK( + kernel32, + 4, + PTP_POOL, WINAPI, CreateThreadpool, _Reserved_ PVOID _pReserved ) - { - if (auto const _pfnCreateThreadpool = try_get_CreateThreadpool()) - { - return _pfnCreateThreadpool(_pReserved); - } + { + if (auto const _pfnCreateThreadpool = try_get_CreateThreadpool()) + { + return _pfnCreateThreadpool(_pReserved); + } auto _pPool = internal::New(); if (!_pPool) @@ -2230,107 +2230,107 @@ namespace YY::Thunks SetLastError(ERROR_NOT_ENOUGH_MEMORY); } return reinterpret_cast(_pPool); - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 4, - VOID, + __DEFINE_THUNK( + kernel32, + 4, + VOID, WINAPI, CloseThreadpool, _Inout_ PTP_POOL _pPool2 ) - { - if (auto const _pfnCloseThreadpool = try_get_CloseThreadpool()) - { - return _pfnCloseThreadpool(_pPool2); - } + { + if (auto const _pfnCloseThreadpool = try_get_CloseThreadpool()) + { + return _pfnCloseThreadpool(_pPool2); + } auto _pPool = reinterpret_cast(_pPool2); if (_pPool) { _pPool->Close(); } - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 8, - VOID, + __DEFINE_THUNK( + kernel32, + 8, + VOID, WINAPI, SetThreadpoolThreadMaximum, _Inout_ PTP_POOL _pPool2, _In_ DWORD _cthrdMost ) - { - if (auto const _pfnSetThreadpoolThreadMaximum = try_get_SetThreadpoolThreadMaximum()) - { - return _pfnSetThreadpoolThreadMaximum(_pPool2, _cthrdMost); - } + { + if (auto const _pfnSetThreadpoolThreadMaximum = try_get_SetThreadpoolThreadMaximum()) + { + return _pfnSetThreadpoolThreadMaximum(_pPool2, _cthrdMost); + } auto _pPool = reinterpret_cast(_pPool2); if (!_pPool) _pPool = Fallback::TP_Pool::GetDefaultPool(); _pPool->SetParallelMaximum(_cthrdMost); - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, + __DEFINE_THUNK( + kernel32, + 8, + BOOL, WINAPI, SetThreadpoolThreadMinimum, _Inout_ PTP_POOL _pPool2, _In_ DWORD _cthrdMic ) - { - if (auto const _pfnSetThreadpoolThreadMinimum = try_get_SetThreadpoolThreadMinimum()) - { - return _pfnSetThreadpoolThreadMinimum(_pPool2, _cthrdMic); - } + { + if (auto const _pfnSetThreadpoolThreadMinimum = try_get_SetThreadpoolThreadMinimum()) + { + return _pfnSetThreadpoolThreadMinimum(_pPool2, _cthrdMic); + } // YY-Thunks因为底层调用的是QueueUserWorkItem // 无法限制最小线程数量,先忽略把…… return TRUE; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 4, - BOOL, + __DEFINE_THUNK( + kernel32, + 4, + BOOL, WINAPI, CallbackMayRunLong, _Inout_ PTP_CALLBACK_INSTANCE pci ) - { - if (auto const _pfnCallbackMayRunLong = try_get_CallbackMayRunLong()) - { - return _pfnCallbackMayRunLong(pci); - } + { + if (auto const _pfnCallbackMayRunLong = try_get_CallbackMayRunLong()) + { + return _pfnCallbackMayRunLong(pci); + } if (pci == nullptr || pci->bCallbackMayRunLong) { @@ -2341,6 +2341,6 @@ namespace YY::Thunks // 底层调用的是QueueUserWorkItem,我们无法完全知道现在可用的线程情况 // 自己记录一个 AvailableWorkerCount凑合用吧…… return Fallback::uAvailableWorkerCount > 0; - } + } #endif } diff --git a/src/Thunks/api-ms-win-core-timezone.hpp b/src/Thunks/api-ms-win-core-timezone.hpp index 42f4ab2..5e8c1e1 100644 --- a/src/Thunks/api-ms-win-core-timezone.hpp +++ b/src/Thunks/api-ms-win-core-timezone.hpp @@ -1,306 +1,306 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) && !defined(__Comment_Lib_advapi32) +#if (YY_Thunks_Target < __WindowsNT6_2) && !defined(__Comment_Lib_advapi32) #define __Comment_Lib_advapi32 #pragma comment(lib, "Advapi32.lib") #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps | UWP apps] - //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 4, - _Success_(return != TIME_ZONE_ID_INVALID) - DWORD, - WINAPI, - GetDynamicTimeZoneInformation, - _Out_ PDYNAMIC_TIME_ZONE_INFORMATION pTimeZoneInformation - ) - { - if (const auto pGetDynamicTimeZoneInformation = try_get_GetDynamicTimeZoneInformation()) - { - return pGetDynamicTimeZoneInformation(pTimeZoneInformation); - } - - memset(pTimeZoneInformation, 0, sizeof(*pTimeZoneInformation)); - - const auto Result = GetTimeZoneInformation((LPTIME_ZONE_INFORMATION)pTimeZoneInformation); - - if (Result == TIME_ZONE_ID_INVALID) - { - return Result; - } - - - pTimeZoneInformation->DynamicDaylightTimeDisabled = TIME_ZONE_ID_UNKNOWN == Result; - - //搜索 TimeZoneKeyName 名称 - - do - { - HKEY hTimeZoneRootKey; - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones)", 0, KEY_READ, &hTimeZoneRootKey) != ERROR_SUCCESS) - { - break; - } - - wchar_t szTimeZoneKeyName[128]; - - for (unsigned i = 0; RegEnumKeyW(hTimeZoneRootKey, i, szTimeZoneKeyName, _countof(szTimeZoneKeyName)) == ERROR_SUCCESS;++i) - { - HKEY hTimeZoneKey; - if (RegOpenKeyExW(hTimeZoneRootKey, szTimeZoneKeyName, 0, KEY_READ, &hTimeZoneKey) != ERROR_SUCCESS) - continue; - - WCHAR StandardName[32] = {}; - //防止奇葩注册表,让 - DWORD cdStandardName = sizeof(StandardName); - auto lStatus = RegQueryValueExW(hTimeZoneKey, L"Std", nullptr, nullptr, (LPBYTE)StandardName, &cdStandardName); - - RegCloseKey(hTimeZoneKey); - - if (lStatus == ERROR_SUCCESS) - { - //始终保持 0 截断 - StandardName[_countof(StandardName) - 1] = L'\0'; - - if (StringCompareIgnoreCaseByAscii(StandardName, pTimeZoneInformation->StandardName, _countof(pTimeZoneInformation->StandardName)) == 0) - { - memcpy(pTimeZoneInformation->TimeZoneKeyName, szTimeZoneKeyName, sizeof(szTimeZoneKeyName)); - - break; - } - } - } - - RegCloseKey(hTimeZoneRootKey); - - } while (false); - - - return Result; - - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps | UWP apps] + //Minimum supported server Windows Server 2008 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 4, + _Success_(return != TIME_ZONE_ID_INVALID) + DWORD, + WINAPI, + GetDynamicTimeZoneInformation, + _Out_ PDYNAMIC_TIME_ZONE_INFORMATION pTimeZoneInformation + ) + { + if (const auto pGetDynamicTimeZoneInformation = try_get_GetDynamicTimeZoneInformation()) + { + return pGetDynamicTimeZoneInformation(pTimeZoneInformation); + } + + memset(pTimeZoneInformation, 0, sizeof(*pTimeZoneInformation)); + + const auto Result = GetTimeZoneInformation((LPTIME_ZONE_INFORMATION)pTimeZoneInformation); + + if (Result == TIME_ZONE_ID_INVALID) + { + return Result; + } + + + pTimeZoneInformation->DynamicDaylightTimeDisabled = TIME_ZONE_ID_UNKNOWN == Result; + + //搜索 TimeZoneKeyName 名称 + + do + { + HKEY hTimeZoneRootKey; + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones)", 0, KEY_READ, &hTimeZoneRootKey) != ERROR_SUCCESS) + { + break; + } + + wchar_t szTimeZoneKeyName[128]; + + for (unsigned i = 0; RegEnumKeyW(hTimeZoneRootKey, i, szTimeZoneKeyName, _countof(szTimeZoneKeyName)) == ERROR_SUCCESS;++i) + { + HKEY hTimeZoneKey; + if (RegOpenKeyExW(hTimeZoneRootKey, szTimeZoneKeyName, 0, KEY_READ, &hTimeZoneKey) != ERROR_SUCCESS) + continue; + + WCHAR StandardName[32] = {}; + //防止奇葩注册表,让 + DWORD cdStandardName = sizeof(StandardName); + auto lStatus = RegQueryValueExW(hTimeZoneKey, L"Std", nullptr, nullptr, (LPBYTE)StandardName, &cdStandardName); + + RegCloseKey(hTimeZoneKey); + + if (lStatus == ERROR_SUCCESS) + { + //始终保持 0 截断 + StandardName[_countof(StandardName) - 1] = L'\0'; + + if (StringCompareIgnoreCaseByAscii(StandardName, pTimeZoneInformation->StandardName, _countof(pTimeZoneInformation->StandardName)) == 0) + { + memcpy(pTimeZoneInformation->TimeZoneKeyName, szTimeZoneKeyName, sizeof(szTimeZoneKeyName)); + + break; + } + } + } + + RegCloseKey(hTimeZoneRootKey); + + } while (false); + + + return Result; + + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps only] - //Minimum supported server Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 4, - BOOL, - WINAPI, - SetDynamicTimeZoneInformation, - _In_ CONST DYNAMIC_TIME_ZONE_INFORMATION* lpTimeZoneInformation - ) - { - if (const auto pSetDynamicTimeZoneInformation = try_get_SetDynamicTimeZoneInformation()) - { - return pSetDynamicTimeZoneInformation(lpTimeZoneInformation); - } - - return SetTimeZoneInformation((TIME_ZONE_INFORMATION*)lpTimeZoneInformation); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps only] + //Minimum supported server Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 4, + BOOL, + WINAPI, + SetDynamicTimeZoneInformation, + _In_ CONST DYNAMIC_TIME_ZONE_INFORMATION* lpTimeZoneInformation + ) + { + if (const auto pSetDynamicTimeZoneInformation = try_get_SetDynamicTimeZoneInformation()) + { + return pSetDynamicTimeZoneInformation(lpTimeZoneInformation); + } + + return SetTimeZoneInformation((TIME_ZONE_INFORMATION*)lpTimeZoneInformation); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - // 最低受支持的客户端 Windows 7 [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2012 [桌面应用|UWP 应用] - __DEFINE_THUNK( - kernel32, - 12, - BOOL, - WINAPI, - TzSpecificLocalTimeToSystemTimeEx, - _In_opt_ CONST DYNAMIC_TIME_ZONE_INFORMATION* _pTimeZoneInformation, - _In_ CONST SYSTEMTIME* _pLocalTime, - _Out_ LPSYSTEMTIME _pUniversalTime - ) - { - if (const auto _pfnTzSpecificLocalTimeToSystemTimeEx = try_get_TzSpecificLocalTimeToSystemTimeEx()) - { - return _pfnTzSpecificLocalTimeToSystemTimeEx(_pTimeZoneInformation, _pLocalTime, _pUniversalTime); - } - - return TzSpecificLocalTimeToSystemTime((LPTIME_ZONE_INFORMATION)_pTimeZoneInformation, _pLocalTime, _pUniversalTime); - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + // 最低受支持的客户端 Windows 7 [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2012 [桌面应用|UWP 应用] + __DEFINE_THUNK( + kernel32, + 12, + BOOL, + WINAPI, + TzSpecificLocalTimeToSystemTimeEx, + _In_opt_ CONST DYNAMIC_TIME_ZONE_INFORMATION* _pTimeZoneInformation, + _In_ CONST SYSTEMTIME* _pLocalTime, + _Out_ LPSYSTEMTIME _pUniversalTime + ) + { + if (const auto _pfnTzSpecificLocalTimeToSystemTimeEx = try_get_TzSpecificLocalTimeToSystemTimeEx()) + { + return _pfnTzSpecificLocalTimeToSystemTimeEx(_pTimeZoneInformation, _pLocalTime, _pUniversalTime); + } + + return TzSpecificLocalTimeToSystemTime((LPTIME_ZONE_INFORMATION)_pTimeZoneInformation, _pLocalTime, _pUniversalTime); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WINXP) - - // 最低受支持的客户端 Windows XP [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2003 [桌面应用|UWP 应用] - __DEFINE_THUNK( - kernel32, - 12, - BOOL, - WINAPI, - TzSpecificLocalTimeToSystemTime, - _In_opt_ CONST TIME_ZONE_INFORMATION* _pTimeZoneInformation, - _In_ CONST SYSTEMTIME* _pLocalTime, - _Out_ LPSYSTEMTIME _pUniversalTime - ) - { - if (const auto _pfnTzSpecificLocalTimeToSystemTime = try_get_TzSpecificLocalTimeToSystemTime()) - { - return _pfnTzSpecificLocalTimeToSystemTime(_pTimeZoneInformation, _pLocalTime, _pUniversalTime); - } - - // 下面实现来自XP系统。 - - // Win2K存在此函数 - const auto _pfnRtlCutoverTimeToSystemTime = try_get_RtlCutoverTimeToSystemTime(); - if (!_pfnRtlCutoverTimeToSystemTime) - { - internal::RaiseStatus(STATUS_NOT_FOUND); - } - - // Get the timezone information into a useful format - TIME_ZONE_INFORMATION _TmpTimeZoneInformation; - if (!_pTimeZoneInformation) - { - // Convert universal time to local time using current timezone info - if (GetTimeZoneInformation(&_TmpTimeZoneInformation) == TIME_ZONE_ID_INVALID) - { - return FALSE; - } - - _pTimeZoneInformation = &_TmpTimeZoneInformation; - } - - // convert the input local time to NT style time - LARGE_INTEGER _CurrentLocalTime; - if (!SystemTimeToFileTime(_pLocalTime, (LPFILETIME)&_CurrentLocalTime)) - { - return FALSE; - } - - // Get the new timezone bias - auto _iTimeZoneBias = _pTimeZoneInformation->Bias; - - // Now see if we have stored cutover times - if (_pTimeZoneInformation->StandardDate.wMonth && _pTimeZoneInformation->DaylightDate.wMonth) - { - LARGE_INTEGER _StandardTime; - TIME_FIELDS _StandardStart; - _StandardStart.Year = _pTimeZoneInformation->StandardDate.wYear; - _StandardStart.Month = _pTimeZoneInformation->StandardDate.wMonth; - _StandardStart.Weekday = _pTimeZoneInformation->StandardDate.wDayOfWeek; - _StandardStart.Day = _pTimeZoneInformation->StandardDate.wDay; - _StandardStart.Hour = _pTimeZoneInformation->StandardDate.wHour; - _StandardStart.Minute = _pTimeZoneInformation->StandardDate.wMinute; - _StandardStart.Second = _pTimeZoneInformation->StandardDate.wSecond; - _StandardStart.Milliseconds = _pTimeZoneInformation->StandardDate.wMilliseconds; - - // We have timezone cutover information. Compute the - // cutover dates and compute what our current bias - // is - if (!_pfnRtlCutoverTimeToSystemTime(&_StandardStart, &_StandardTime, &_CurrentLocalTime, TRUE)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - LARGE_INTEGER _DaylightTime; - TIME_FIELDS _DaylightStart; - _DaylightStart.Year = _pTimeZoneInformation->DaylightDate.wYear; - _DaylightStart.Month = _pTimeZoneInformation->DaylightDate.wMonth; - _DaylightStart.Weekday = _pTimeZoneInformation->DaylightDate.wDayOfWeek; - _DaylightStart.Day = _pTimeZoneInformation->DaylightDate.wDay; - _DaylightStart.Hour = _pTimeZoneInformation->DaylightDate.wHour; - _DaylightStart.Minute = _pTimeZoneInformation->DaylightDate.wMinute; - _DaylightStart.Second = _pTimeZoneInformation->DaylightDate.wSecond; - _DaylightStart.Milliseconds = _pTimeZoneInformation->DaylightDate.wMilliseconds; - - if (!_pfnRtlCutoverTimeToSystemTime(&_DaylightStart, &_DaylightTime, &_CurrentLocalTime, TRUE)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - ULONG _uCurrentTimeZoneId = 0xffffffff; - - // If daylight < standard, then time >= daylight and - // less than standard is daylight - if (_DaylightTime.QuadPart < _StandardTime.QuadPart) - { - // If today is >= DaylightTime and < StandardTime, then - // We are in daylight savings time - if ((_CurrentLocalTime.QuadPart >= _DaylightTime.QuadPart) && - (_CurrentLocalTime.QuadPart < _StandardTime.QuadPart)) - { - _uCurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT; - } - else - { - _uCurrentTimeZoneId = TIME_ZONE_ID_STANDARD; - } - } - else - { - // If today is >= StandardTime and < DaylightTime, then - // We are in standard time - if ((_CurrentLocalTime.QuadPart >= _StandardTime.QuadPart) && - (_CurrentLocalTime.QuadPart < _DaylightTime.QuadPart)) - { - _uCurrentTimeZoneId = TIME_ZONE_ID_STANDARD; - } - else - { - _uCurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT; - } - } - - // At this point, we know our current timezone and the - // local time of the next cutover. - if (_uCurrentTimeZoneId == TIME_ZONE_ID_DAYLIGHT) - { - _iTimeZoneBias += _pTimeZoneInformation->DaylightBias; - } - else - { - _iTimeZoneBias += _pTimeZoneInformation->StandardBias; - } - } - - // _iBias 单位是分钟,FileTime是 100ns 为步进 - _CurrentLocalTime.QuadPart += Int32x32To64(_iTimeZoneBias * 60, 10'000'000); - return FileTimeToSystemTime((LPFILETIME)&_CurrentLocalTime, _pUniversalTime); - } +#if (YY_Thunks_Target < __WindowsNT5_1) + + // 最低受支持的客户端 Windows XP [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2003 [桌面应用|UWP 应用] + __DEFINE_THUNK( + kernel32, + 12, + BOOL, + WINAPI, + TzSpecificLocalTimeToSystemTime, + _In_opt_ CONST TIME_ZONE_INFORMATION* _pTimeZoneInformation, + _In_ CONST SYSTEMTIME* _pLocalTime, + _Out_ LPSYSTEMTIME _pUniversalTime + ) + { + if (const auto _pfnTzSpecificLocalTimeToSystemTime = try_get_TzSpecificLocalTimeToSystemTime()) + { + return _pfnTzSpecificLocalTimeToSystemTime(_pTimeZoneInformation, _pLocalTime, _pUniversalTime); + } + + // 下面实现来自XP系统。 + + // Win2K存在此函数 + const auto _pfnRtlCutoverTimeToSystemTime = try_get_RtlCutoverTimeToSystemTime(); + if (!_pfnRtlCutoverTimeToSystemTime) + { + internal::RaiseStatus(STATUS_NOT_FOUND); + } + + // Get the timezone information into a useful format + TIME_ZONE_INFORMATION _TmpTimeZoneInformation; + if (!_pTimeZoneInformation) + { + // Convert universal time to local time using current timezone info + if (GetTimeZoneInformation(&_TmpTimeZoneInformation) == TIME_ZONE_ID_INVALID) + { + return FALSE; + } + + _pTimeZoneInformation = &_TmpTimeZoneInformation; + } + + // convert the input local time to NT style time + LARGE_INTEGER _CurrentLocalTime; + if (!SystemTimeToFileTime(_pLocalTime, (LPFILETIME)&_CurrentLocalTime)) + { + return FALSE; + } + + // Get the new timezone bias + auto _iTimeZoneBias = _pTimeZoneInformation->Bias; + + // Now see if we have stored cutover times + if (_pTimeZoneInformation->StandardDate.wMonth && _pTimeZoneInformation->DaylightDate.wMonth) + { + LARGE_INTEGER _StandardTime; + TIME_FIELDS _StandardStart; + _StandardStart.Year = _pTimeZoneInformation->StandardDate.wYear; + _StandardStart.Month = _pTimeZoneInformation->StandardDate.wMonth; + _StandardStart.Weekday = _pTimeZoneInformation->StandardDate.wDayOfWeek; + _StandardStart.Day = _pTimeZoneInformation->StandardDate.wDay; + _StandardStart.Hour = _pTimeZoneInformation->StandardDate.wHour; + _StandardStart.Minute = _pTimeZoneInformation->StandardDate.wMinute; + _StandardStart.Second = _pTimeZoneInformation->StandardDate.wSecond; + _StandardStart.Milliseconds = _pTimeZoneInformation->StandardDate.wMilliseconds; + + // We have timezone cutover information. Compute the + // cutover dates and compute what our current bias + // is + if (!_pfnRtlCutoverTimeToSystemTime(&_StandardStart, &_StandardTime, &_CurrentLocalTime, TRUE)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + LARGE_INTEGER _DaylightTime; + TIME_FIELDS _DaylightStart; + _DaylightStart.Year = _pTimeZoneInformation->DaylightDate.wYear; + _DaylightStart.Month = _pTimeZoneInformation->DaylightDate.wMonth; + _DaylightStart.Weekday = _pTimeZoneInformation->DaylightDate.wDayOfWeek; + _DaylightStart.Day = _pTimeZoneInformation->DaylightDate.wDay; + _DaylightStart.Hour = _pTimeZoneInformation->DaylightDate.wHour; + _DaylightStart.Minute = _pTimeZoneInformation->DaylightDate.wMinute; + _DaylightStart.Second = _pTimeZoneInformation->DaylightDate.wSecond; + _DaylightStart.Milliseconds = _pTimeZoneInformation->DaylightDate.wMilliseconds; + + if (!_pfnRtlCutoverTimeToSystemTime(&_DaylightStart, &_DaylightTime, &_CurrentLocalTime, TRUE)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + ULONG _uCurrentTimeZoneId = 0xffffffff; + + // If daylight < standard, then time >= daylight and + // less than standard is daylight + if (_DaylightTime.QuadPart < _StandardTime.QuadPart) + { + // If today is >= DaylightTime and < StandardTime, then + // We are in daylight savings time + if ((_CurrentLocalTime.QuadPart >= _DaylightTime.QuadPart) && + (_CurrentLocalTime.QuadPart < _StandardTime.QuadPart)) + { + _uCurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT; + } + else + { + _uCurrentTimeZoneId = TIME_ZONE_ID_STANDARD; + } + } + else + { + // If today is >= StandardTime and < DaylightTime, then + // We are in standard time + if ((_CurrentLocalTime.QuadPart >= _StandardTime.QuadPart) && + (_CurrentLocalTime.QuadPart < _DaylightTime.QuadPart)) + { + _uCurrentTimeZoneId = TIME_ZONE_ID_STANDARD; + } + else + { + _uCurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT; + } + } + + // At this point, we know our current timezone and the + // local time of the next cutover. + if (_uCurrentTimeZoneId == TIME_ZONE_ID_DAYLIGHT) + { + _iTimeZoneBias += _pTimeZoneInformation->DaylightBias; + } + else + { + _iTimeZoneBias += _pTimeZoneInformation->StandardBias; + } + } + + // _iBias 单位是分钟,FileTime是 100ns 为步进 + _CurrentLocalTime.QuadPart += Int32x32To64(_iTimeZoneBias * 60, 10'000'000); + return FileTimeToSystemTime((LPFILETIME)&_CurrentLocalTime, _pUniversalTime); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_VISTASP1) +#if (YY_Thunks_Target < __WindowsNT6_SP1) - // 最低受支持的客户端 Windows Vista SP1 [桌面应用 |UWP 应用] + // 最低受支持的客户端 Windows Vista SP1 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 12, - BOOL, + __DEFINE_THUNK( + kernel32, + 12, + BOOL, WINAPI, GetTimeZoneInformationForYear, _In_ USHORT _uYear, _In_opt_ PDYNAMIC_TIME_ZONE_INFORMATION _pDynamicTimeZoneInfo, _Out_ LPTIME_ZONE_INFORMATION _pTimeZoneInfo - ) - { - if (const auto _pfnGetTimeZoneInformationForYear = try_get_GetTimeZoneInformationForYear()) - { - return _pfnGetTimeZoneInformationForYear(_uYear, _pDynamicTimeZoneInfo, _pTimeZoneInfo); - } + ) + { + if (const auto _pfnGetTimeZoneInformationForYear = try_get_GetTimeZoneInformationForYear()) + { + return _pfnGetTimeZoneInformationForYear(_uYear, _pDynamicTimeZoneInfo, _pTimeZoneInfo); + } DYNAMIC_TIME_ZONE_INFORMATION _DynamicTimeZoneInfoBuffer; if (!_pDynamicTimeZoneInfo) @@ -392,29 +392,29 @@ namespace YY::Thunks return FALSE; } return TRUE; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - // 最低受支持的客户端 Windows 8 [桌面应用 |UWP 应用] + // 最低受支持的客户端 Windows 8 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] - __DEFINE_THUNK( - advapi32, - 12, - DWORD, + __DEFINE_THUNK( + advapi32, + 12, + DWORD, WINAPI, GetDynamicTimeZoneInformationEffectiveYears, _In_ CONST PDYNAMIC_TIME_ZONE_INFORMATION _pTimeZoneInformation, _Out_ LPDWORD _puFirstYear, _Out_ LPDWORD _puLastYear - ) - { - if (const auto _pfnGetDynamicTimeZoneInformationEffectiveYears = try_get_GetDynamicTimeZoneInformationEffectiveYears()) - { - return _pfnGetDynamicTimeZoneInformationEffectiveYears(_pTimeZoneInformation, _puFirstYear, _puLastYear); - } + ) + { + if (const auto _pfnGetDynamicTimeZoneInformationEffectiveYears = try_get_GetDynamicTimeZoneInformationEffectiveYears()) + { + return _pfnGetDynamicTimeZoneInformationEffectiveYears(_pTimeZoneInformation, _puFirstYear, _puLastYear); + } if (!_pTimeZoneInformation) { @@ -479,6 +479,6 @@ namespace YY::Thunks RegCloseKey(_hTimeZoneRootKey); return _lStatus; - } + } #endif } diff --git a/src/Thunks/api-ms-win-core-util.hpp b/src/Thunks/api-ms-win-core-util.hpp index 05cfd45..086d503 100644 --- a/src/Thunks/api-ms-win-core-util.hpp +++ b/src/Thunks/api-ms-win-core-util.hpp @@ -1,58 +1,51 @@  -namespace YY +namespace YY::Thunks { - namespace Thunks - { - -#if (YY_Thunks_Support_Version < NTDDI_WS03SP1) - - //Windows XP with SP2, Windows Server 2003 with SP1 - __DEFINE_THUNK( - kernel32, - 4, - PVOID, - WINAPI, - DecodePointer, - _In_opt_ PVOID Ptr - ) - { - if (auto const pDecodePointer = try_get_DecodePointer()) - { - return pDecodePointer(Ptr); - } - else - { - return Ptr; - } - } +#if (YY_Thunks_Target < __WindowsNT5_2_SP1) + + //Windows XP with SP2, Windows Server 2003 with SP1 + __DEFINE_THUNK( + kernel32, + 4, + PVOID, + WINAPI, + DecodePointer, + _In_opt_ PVOID Ptr + ) + { + if (auto const pDecodePointer = try_get_DecodePointer()) + { + return pDecodePointer(Ptr); + } + else + { + return Ptr; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03SP1) - - //Windows XP with SP2, Windows Server 2003 with SP1 - __DEFINE_THUNK( - kernel32, - 4, - PVOID, - WINAPI, - EncodePointer, - _In_opt_ PVOID Ptr - ) - { - if (auto const pEncodePointer = try_get_EncodePointer()) - { - return pEncodePointer(Ptr); - } - else - { - return Ptr; - } - } +#if (YY_Thunks_Target < __WindowsNT5_2_SP1) + + //Windows XP with SP2, Windows Server 2003 with SP1 + __DEFINE_THUNK( + kernel32, + 4, + PVOID, + WINAPI, + EncodePointer, + _In_opt_ PVOID Ptr + ) + { + if (auto const pEncodePointer = try_get_EncodePointer()) + { + return pEncodePointer(Ptr); + } + else + { + return Ptr; + } + } #endif - - - }//namespace Thunks - -} //namespace YY \ No newline at end of file +} //namespace YY::Thunks diff --git a/src/Thunks/api-ms-win-core-version.hpp b/src/Thunks/api-ms-win-core-version.hpp index 0329f51..11d853d 100644 --- a/src/Thunks/api-ms-win-core-version.hpp +++ b/src/Thunks/api-ms-win-core-version.hpp @@ -1,112 +1,107 @@  -namespace YY +namespace YY::Thunks { - namespace Thunks - { - -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - version, - 20, - BOOL, - APIENTRY, - GetFileVersionInfoExW, - _In_ DWORD dwFlags, - _In_ LPCWSTR lpwstrFilename, - _Reserved_ DWORD dwHandle, - _In_ DWORD dwLen, - _Out_writes_bytes_(dwLen) LPVOID lpData - ) - { - if (auto pGetFileVersionInfoExW = try_get_GetFileVersionInfoExW()) - { - return pGetFileVersionInfoExW(dwFlags, lpwstrFilename, dwHandle, dwLen, lpData); - } - - return GetFileVersionInfoW(lpwstrFilename, dwHandle, dwLen, lpData); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + version, + 20, + BOOL, + APIENTRY, + GetFileVersionInfoExW, + _In_ DWORD dwFlags, + _In_ LPCWSTR lpwstrFilename, + _Reserved_ DWORD dwHandle, + _In_ DWORD dwLen, + _Out_writes_bytes_(dwLen) LPVOID lpData + ) + { + if (auto pGetFileVersionInfoExW = try_get_GetFileVersionInfoExW()) + { + return pGetFileVersionInfoExW(dwFlags, lpwstrFilename, dwHandle, dwLen, lpData); + } + + return GetFileVersionInfoW(lpwstrFilename, dwHandle, dwLen, lpData); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - version, - 20, - BOOL, - APIENTRY, - GetFileVersionInfoExA, - _In_ DWORD dwFlags, - _In_ LPCSTR lpwstrFilename, - _Reserved_ DWORD dwHandle, - _In_ DWORD dwLen, - _Out_writes_bytes_(dwLen) LPVOID lpData - ) - { - if (auto pGetFileVersionInfoExA = try_get_GetFileVersionInfoExA()) - { - return pGetFileVersionInfoExA(dwFlags, lpwstrFilename, dwHandle, dwLen, lpData); - } - - return GetFileVersionInfoA(lpwstrFilename, dwHandle, dwLen, lpData); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + version, + 20, + BOOL, + APIENTRY, + GetFileVersionInfoExA, + _In_ DWORD dwFlags, + _In_ LPCSTR lpwstrFilename, + _Reserved_ DWORD dwHandle, + _In_ DWORD dwLen, + _Out_writes_bytes_(dwLen) LPVOID lpData + ) + { + if (auto pGetFileVersionInfoExA = try_get_GetFileVersionInfoExA()) + { + return pGetFileVersionInfoExA(dwFlags, lpwstrFilename, dwHandle, dwLen, lpData); + } + + return GetFileVersionInfoA(lpwstrFilename, dwHandle, dwLen, lpData); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - version, - 12, - DWORD, - APIENTRY, - GetFileVersionInfoSizeExW, - _In_ DWORD dwFlags, - _In_ LPCWSTR lpwstrFilename, - _Out_ LPDWORD lpdwHandle - ) - { - if (auto pGetFileVersionInfoSizeExW = try_get_GetFileVersionInfoSizeExW()) - { - return pGetFileVersionInfoSizeExW(dwFlags, lpwstrFilename, lpdwHandle); - } - - return GetFileVersionInfoSizeW(lpwstrFilename, lpdwHandle); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + version, + 12, + DWORD, + APIENTRY, + GetFileVersionInfoSizeExW, + _In_ DWORD dwFlags, + _In_ LPCWSTR lpwstrFilename, + _Out_ LPDWORD lpdwHandle + ) + { + if (auto pGetFileVersionInfoSizeExW = try_get_GetFileVersionInfoSizeExW()) + { + return pGetFileVersionInfoSizeExW(dwFlags, lpwstrFilename, lpdwHandle); + } + + return GetFileVersionInfoSizeW(lpwstrFilename, lpdwHandle); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - version, - 12, - DWORD, - APIENTRY, - GetFileVersionInfoSizeExA, - _In_ DWORD dwFlags, - _In_ LPCSTR lpwstrFilename, - _Out_ LPDWORD lpdwHandle - ) - { - if (auto pGetFileVersionInfoSizeExA = try_get_GetFileVersionInfoSizeExA()) - { - return pGetFileVersionInfoSizeExA(dwFlags, lpwstrFilename, lpdwHandle); - } - - return GetFileVersionInfoSizeA(lpwstrFilename, lpdwHandle); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + version, + 12, + DWORD, + APIENTRY, + GetFileVersionInfoSizeExA, + _In_ DWORD dwFlags, + _In_ LPCSTR lpwstrFilename, + _Out_ LPDWORD lpdwHandle + ) + { + if (auto pGetFileVersionInfoSizeExA = try_get_GetFileVersionInfoSizeExA()) + { + return pGetFileVersionInfoSizeExA(dwFlags, lpwstrFilename, lpdwHandle); + } + + return GetFileVersionInfoSizeA(lpwstrFilename, lpdwHandle); + } #endif - }//namespace Thunks - -} //namespace YY \ No newline at end of file +} //namespace YY::Thunks diff --git a/src/Thunks/api-ms-win-core-windowserrorreporting.hpp b/src/Thunks/api-ms-win-core-windowserrorreporting.hpp index 8206be9..39b8255 100644 --- a/src/Thunks/api-ms-win-core-windowserrorreporting.hpp +++ b/src/Thunks/api-ms-win-core-windowserrorreporting.hpp @@ -1,8 +1,10 @@ -#include +#if (YY_Thunks_Target < __WindowsNT6_1) +#include +#endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) // 最低受支持的客户端 Windows 7 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] @@ -26,7 +28,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) // 最低受支持的客户端 Windows 7 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] diff --git a/src/Thunks/api-ms-win-core-winrt-error.hpp b/src/Thunks/api-ms-win-core-winrt-error.hpp index 33cf899..f9b5c68 100644 --- a/src/Thunks/api-ms-win-core-winrt-error.hpp +++ b/src/Thunks/api-ms-win-core-winrt-error.hpp @@ -1,59 +1,61 @@ -#include +#if (YY_Thunks_Target < __WindowsNT6_2) +#include +#endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - //Windows 8 [desktop apps | UWP apps] - //Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_winrt_error_l1_1_0, - 8, - BOOL, - WINAPI, - RoOriginateError, - _In_ HRESULT error, - _In_opt_ HSTRING message - ) - { - if (auto pRoOriginateError = try_get_RoOriginateError()) - { - return pRoOriginateError(error, message); - } + //Windows 8 [desktop apps | UWP apps] + //Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_winrt_error_l1_1_0, + 8, + BOOL, + WINAPI, + RoOriginateError, + _In_ HRESULT error, + _In_opt_ HSTRING message + ) + { + if (auto pRoOriginateError = try_get_RoOriginateError()) + { + return pRoOriginateError(error, message); + } // According to the C++/WinRT fallback implementation, we should // return TRUE to tell the caller that the error message was // reported successfully. - return TRUE; - } + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - //Windows 8 [desktop apps | UWP apps] - //Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_winrt_error_l1_1_0, - 12, - BOOL, - WINAPI, - RoOriginateErrorW, - _In_ HRESULT error, - _In_ UINT cchMax, - _When_(cchMax == 0, _In_reads_or_z_opt_(MAX_ERROR_MESSAGE_CHARS) ) - _When_(cchMax > 0 && cchMax < MAX_ERROR_MESSAGE_CHARS, _In_reads_or_z_(cchMax) ) - _When_(cchMax >= MAX_ERROR_MESSAGE_CHARS, _In_reads_or_z_(MAX_ERROR_MESSAGE_CHARS) ) PCWSTR message - ) - { - if (auto pRoOriginateErrorW = try_get_RoOriginateErrorW()) - { - return pRoOriginateErrorW(error, cchMax, message); - } + //Windows 8 [desktop apps | UWP apps] + //Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_winrt_error_l1_1_0, + 12, + BOOL, + WINAPI, + RoOriginateErrorW, + _In_ HRESULT error, + _In_ UINT cchMax, + _When_(cchMax == 0, _In_reads_or_z_opt_(MAX_ERROR_MESSAGE_CHARS) ) + _When_(cchMax > 0 && cchMax < MAX_ERROR_MESSAGE_CHARS, _In_reads_or_z_(cchMax) ) + _When_(cchMax >= MAX_ERROR_MESSAGE_CHARS, _In_reads_or_z_(MAX_ERROR_MESSAGE_CHARS) ) PCWSTR message + ) + { + if (auto pRoOriginateErrorW = try_get_RoOriginateErrorW()) + { + return pRoOriginateErrorW(error, cchMax, message); + } // According to the C++/WinRT fallback implementation, we should // return TRUE to tell the caller that the error message was // reported successfully. return TRUE; - } + } #endif } diff --git a/src/Thunks/api-ms-win-core-winrt-string.hpp b/src/Thunks/api-ms-win-core-winrt-string.hpp index e9d5af0..6419d77 100644 --- a/src/Thunks/api-ms-win-core-winrt-string.hpp +++ b/src/Thunks/api-ms-win-core-winrt-string.hpp @@ -1,19 +1,19 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) #include #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) && __YY_Thunks_libs && !defined(__Comment_Lib_runtimeobject) +#if (YY_Thunks_Target < __WindowsNT6_2) && __YY_Thunks_libs && !defined(__Comment_Lib_runtimeobject) #define __Comment_Lib_runtimeobject -// 193行 WindowsCreateString +// WindowsCreateString #pragma comment(lib, "runtimeobject.lib") #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) //Windows 8 [desktop apps | UWP apps] //Windows Server 2012 [desktop apps | UWP apps] @@ -69,7 +69,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) //Windows 8 [desktop apps | UWP apps] //Windows Server 2012 [desktop apps | UWP apps] @@ -121,7 +121,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) //Windows 8 [desktop apps | UWP apps] //Windows Server 2012 [desktop apps | UWP apps] @@ -156,7 +156,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) //Windows 8 [desktop apps | UWP apps] //Windows Server 2012 [desktop apps | UWP apps] @@ -197,7 +197,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) //Windows 8 [desktop apps | UWP apps] //Windows Server 2012 [desktop apps | UWP apps] @@ -224,7 +224,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) //Windows 8 [desktop apps | UWP apps] //Windows Server 2012 [desktop apps | UWP apps] @@ -264,7 +264,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) //Windows 8 [desktop apps | UWP apps] //Windows Server 2012 [desktop apps | UWP apps] @@ -288,7 +288,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) //Windows 8 [desktop apps | UWP apps] //Windows Server 2012 [desktop apps | UWP apps] @@ -343,7 +343,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) //Windows 8 [desktop apps | UWP apps] //Windows Server 2012 [desktop apps | UWP apps] diff --git a/src/Thunks/api-ms-win-core-winrt.hpp b/src/Thunks/api-ms-win-core-winrt.hpp index 4767a5d..dadb811 100644 --- a/src/Thunks/api-ms-win-core-winrt.hpp +++ b/src/Thunks/api-ms-win-core-winrt.hpp @@ -1,240 +1,240 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) && !defined(__Comment_Lib_ole32) +#if (YY_Thunks_Target < __WindowsNT6_2) && !defined(__Comment_Lib_ole32) #define __Comment_Lib_ole32 #pragma comment(lib, "Ole32.lib") #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Windows 8 [desktop apps | UWP apps] - //Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_winrt_l1_1_0, - 4, - HRESULT, - WINAPI, - RoInitialize, - _In_ RO_INIT_TYPE initType - ) - { - if (auto const pRoInitialize = try_get_RoInitialize()) - { - return pRoInitialize(initType); - } - - if ((unsigned)initType > (unsigned)RO_INIT_MULTITHREADED) - { - return E_INVALIDARG; - } - - return CoInitializeEx(nullptr, initType ? COINIT_MULTITHREADED : COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Windows 8 [desktop apps | UWP apps] + //Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_winrt_l1_1_0, + 4, + HRESULT, + WINAPI, + RoInitialize, + _In_ RO_INIT_TYPE initType + ) + { + if (auto const pRoInitialize = try_get_RoInitialize()) + { + return pRoInitialize(initType); + } + + if ((unsigned)initType > (unsigned)RO_INIT_MULTITHREADED) + { + return E_INVALIDARG; + } + + return CoInitializeEx(nullptr, initType ? COINIT_MULTITHREADED : COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Windows 8 [desktop apps | UWP apps] - //Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_winrt_l1_1_0, - 0, - void, - WINAPI, - RoUninitialize, - ) - { - if (auto const pRoUninitialize = try_get_RoUninitialize()) - { - return pRoUninitialize(); - } - - CoUninitialize(); - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Windows 8 [desktop apps | UWP apps] + //Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_winrt_l1_1_0, + 0, + void, + WINAPI, + RoUninitialize, + ) + { + if (auto const pRoUninitialize = try_get_RoUninitialize()) + { + return pRoUninitialize(); + } + + CoUninitialize(); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Windows 8 [desktop apps | UWP apps] - //Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_winrt_l1_1_0, - 8, - HRESULT, - WINAPI, - RoActivateInstance, - _In_ HSTRING activatableClassId, - _COM_Outptr_ IInspectable** instance - ) - { - if (auto const pRoActivateInstance = try_get_RoActivateInstance()) - { - return pRoActivateInstance(activatableClassId, instance); - } - - if (instance) - *instance = nullptr; - - return E_NOTIMPL; - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Windows 8 [desktop apps | UWP apps] + //Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_winrt_l1_1_0, + 8, + HRESULT, + WINAPI, + RoActivateInstance, + _In_ HSTRING activatableClassId, + _COM_Outptr_ IInspectable** instance + ) + { + if (auto const pRoActivateInstance = try_get_RoActivateInstance()) + { + return pRoActivateInstance(activatableClassId, instance); + } + + if (instance) + *instance = nullptr; + + return E_NOTIMPL; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Windows 8 [desktop apps | UWP apps] - //Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_winrt_l1_1_0, - 16, - HRESULT, - WINAPI, - RoRegisterActivationFactories, - _In_reads_(count) HSTRING* activatableClassIds, - _In_reads_(count) PFNGETACTIVATIONFACTORY* activationFactoryCallbacks, - _In_ UINT32 count, - _Out_ RO_REGISTRATION_COOKIE* cookie - ) - { - if (auto const pRoRegisterActivationFactories = try_get_RoRegisterActivationFactories()) - { - return pRoRegisterActivationFactories(activatableClassIds, activationFactoryCallbacks, count, cookie); - } - - if (cookie) - *cookie = nullptr; - - return E_NOTIMPL; - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Windows 8 [desktop apps | UWP apps] + //Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_winrt_l1_1_0, + 16, + HRESULT, + WINAPI, + RoRegisterActivationFactories, + _In_reads_(count) HSTRING* activatableClassIds, + _In_reads_(count) PFNGETACTIVATIONFACTORY* activationFactoryCallbacks, + _In_ UINT32 count, + _Out_ RO_REGISTRATION_COOKIE* cookie + ) + { + if (auto const pRoRegisterActivationFactories = try_get_RoRegisterActivationFactories()) + { + return pRoRegisterActivationFactories(activatableClassIds, activationFactoryCallbacks, count, cookie); + } + + if (cookie) + *cookie = nullptr; + + return E_NOTIMPL; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Windows 8 [desktop apps | UWP apps] - //Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_winrt_l1_1_0, - 4, - void, - WINAPI, - RoRevokeActivationFactories, - _In_ RO_REGISTRATION_COOKIE cookie - ) - { - if (auto const pRoRevokeActivationFactories = try_get_RoRevokeActivationFactories()) - { - return pRoRevokeActivationFactories(cookie); - } - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Windows 8 [desktop apps | UWP apps] + //Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_winrt_l1_1_0, + 4, + void, + WINAPI, + RoRevokeActivationFactories, + _In_ RO_REGISTRATION_COOKIE cookie + ) + { + if (auto const pRoRevokeActivationFactories = try_get_RoRevokeActivationFactories()) + { + return pRoRevokeActivationFactories(cookie); + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Windows 8 [desktop apps | UWP apps] - //Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_winrt_l1_1_0, - 12, - HRESULT, - WINAPI, - RoGetActivationFactory, - _In_ HSTRING activatableClassId, - _In_ REFIID iid, - _COM_Outptr_ void** factory - ) - { - if (auto const pRoGetActivationFactory = try_get_RoGetActivationFactory()) - { - return pRoGetActivationFactory(activatableClassId, iid, factory); - } - - if (factory) - *factory = nullptr; +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Windows 8 [desktop apps | UWP apps] + //Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_winrt_l1_1_0, + 12, + HRESULT, + WINAPI, + RoGetActivationFactory, + _In_ HSTRING activatableClassId, + _In_ REFIID iid, + _COM_Outptr_ void** factory + ) + { + if (auto const pRoGetActivationFactory = try_get_RoGetActivationFactory()) + { + return pRoGetActivationFactory(activatableClassId, iid, factory); + } + + if (factory) + *factory = nullptr; // According to the C++/WinRT fallback implementation, we should // return CLASS_E_CLASSNOTAVAILABLE. - return CLASS_E_CLASSNOTAVAILABLE; - } + return CLASS_E_CLASSNOTAVAILABLE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - //Windows 8 [desktop apps | UWP apps] - //Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_winrt_l1_1_0, - 12, - HRESULT, - WINAPI, - RoRegisterForApartmentShutdown, - _In_ IApartmentShutdown* callbackObject, - _Out_ UINT64* apartmentIdentifier, - _Out_ APARTMENT_SHUTDOWN_REGISTRATION_COOKIE* regCookie - ) - { - if (auto const pRoRegisterForApartmentShutdown = try_get_RoRegisterForApartmentShutdown()) - { - return pRoRegisterForApartmentShutdown(callbackObject, apartmentIdentifier, regCookie); - } + //Windows 8 [desktop apps | UWP apps] + //Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_winrt_l1_1_0, + 12, + HRESULT, + WINAPI, + RoRegisterForApartmentShutdown, + _In_ IApartmentShutdown* callbackObject, + _Out_ UINT64* apartmentIdentifier, + _Out_ APARTMENT_SHUTDOWN_REGISTRATION_COOKIE* regCookie + ) + { + if (auto const pRoRegisterForApartmentShutdown = try_get_RoRegisterForApartmentShutdown()) + { + return pRoRegisterForApartmentShutdown(callbackObject, apartmentIdentifier, regCookie); + } - if (regCookie) - *regCookie = nullptr; + if (regCookie) + *regCookie = nullptr; - return E_NOTIMPL; + return E_NOTIMPL; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) - //Windows 8 [desktop apps | UWP apps] - //Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_winrt_l1_1_0, - 4, - HRESULT, - WINAPI, - RoUnregisterForApartmentShutdown, - _In_ APARTMENT_SHUTDOWN_REGISTRATION_COOKIE regCookie - ) - { - if (auto const pRoUnregisterForApartmentShutdown = try_get_RoUnregisterForApartmentShutdown()) - { - return pRoUnregisterForApartmentShutdown(regCookie); - } + //Windows 8 [desktop apps | UWP apps] + //Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_winrt_l1_1_0, + 4, + HRESULT, + WINAPI, + RoUnregisterForApartmentShutdown, + _In_ APARTMENT_SHUTDOWN_REGISTRATION_COOKIE regCookie + ) + { + if (auto const pRoUnregisterForApartmentShutdown = try_get_RoUnregisterForApartmentShutdown()) + { + return pRoUnregisterForApartmentShutdown(regCookie); + } - return E_NOTIMPL; + return E_NOTIMPL; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - //Windows 8 [desktop apps | UWP apps] - //Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - api_ms_win_core_winrt_l1_1_0, - 4, - HRESULT, - WINAPI, - RoGetApartmentIdentifier, - _Out_ UINT64* apartmentIdentifier - ) - { - if (auto const pRoGetApartmentIdentifier = try_get_RoGetApartmentIdentifier()) - { - return pRoGetApartmentIdentifier(apartmentIdentifier); - } - - return E_NOTIMPL; - - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + //Windows 8 [desktop apps | UWP apps] + //Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + api_ms_win_core_winrt_l1_1_0, + 4, + HRESULT, + WINAPI, + RoGetApartmentIdentifier, + _Out_ UINT64* apartmentIdentifier + ) + { + if (auto const pRoGetApartmentIdentifier = try_get_RoGetApartmentIdentifier()) + { + return pRoGetApartmentIdentifier(apartmentIdentifier); + } + + return E_NOTIMPL; + + } #endif } diff --git a/src/Thunks/api-ms-win-core-wow64.hpp b/src/Thunks/api-ms-win-core-wow64.hpp index b5970b9..c7c3385 100644 --- a/src/Thunks/api-ms-win-core-wow64.hpp +++ b/src/Thunks/api-ms-win-core-wow64.hpp @@ -2,207 +2,207 @@ namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WS03) - - //Windows XP Professional x64 Edition, Windows Server 2003 - __DEFINE_THUNK( - kernel32, - 4, - BOOL, - WINAPI, - Wow64DisableWow64FsRedirection, - _Out_ PVOID* OldValue - ) - { - if (auto const pWow64DisableWow64FsRedirection = try_get_Wow64DisableWow64FsRedirection()) - { - return pWow64DisableWow64FsRedirection(OldValue); - } - - - SetLastError(ERROR_INVALID_FUNCTION); - - return FALSE; - } +#if (YY_Thunks_Target < __WindowsNT5_2) + + //Windows XP Professional x64 Edition, Windows Server 2003 + __DEFINE_THUNK( + kernel32, + 4, + BOOL, + WINAPI, + Wow64DisableWow64FsRedirection, + _Out_ PVOID* OldValue + ) + { + if (auto const pWow64DisableWow64FsRedirection = try_get_Wow64DisableWow64FsRedirection()) + { + return pWow64DisableWow64FsRedirection(OldValue); + } + + + SetLastError(ERROR_INVALID_FUNCTION); + + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03) +#if (YY_Thunks_Target < __WindowsNT5_2) - //Windows XP Professional x64 Edition, Windows Server 2003 - __DEFINE_THUNK( - kernel32, - 4, - BOOL, - WINAPI, - Wow64RevertWow64FsRedirection, - _In_ PVOID OlValue - ) - { - if (auto const pWow64RevertWow64FsRedirection = try_get_Wow64RevertWow64FsRedirection()) - { - return pWow64RevertWow64FsRedirection(OlValue); - } + //Windows XP Professional x64 Edition, Windows Server 2003 + __DEFINE_THUNK( + kernel32, + 4, + BOOL, + WINAPI, + Wow64RevertWow64FsRedirection, + _In_ PVOID OlValue + ) + { + if (auto const pWow64RevertWow64FsRedirection = try_get_Wow64RevertWow64FsRedirection()) + { + return pWow64RevertWow64FsRedirection(OlValue); + } - SetLastError(ERROR_INVALID_FUNCTION); + SetLastError(ERROR_INVALID_FUNCTION); - return FALSE; - } + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03) +#if (YY_Thunks_Target < __WindowsNT5_2) - //Windows XP Professional x64 Edition, Windows Server 2003 - __DEFINE_THUNK( - kernel32, - 4, - BOOLEAN, - WINAPI, - Wow64EnableWow64FsRedirection, - _In_ BOOLEAN Wow64FsEnableRedirection - ) - { - if (auto const pWow64EnableWow64FsRedirection = try_get_Wow64EnableWow64FsRedirection()) - { - return pWow64EnableWow64FsRedirection(Wow64FsEnableRedirection); - } + //Windows XP Professional x64 Edition, Windows Server 2003 + __DEFINE_THUNK( + kernel32, + 4, + BOOLEAN, + WINAPI, + Wow64EnableWow64FsRedirection, + _In_ BOOLEAN Wow64FsEnableRedirection + ) + { + if (auto const pWow64EnableWow64FsRedirection = try_get_Wow64EnableWow64FsRedirection()) + { + return pWow64EnableWow64FsRedirection(Wow64FsEnableRedirection); + } - SetLastError(ERROR_INVALID_FUNCTION); + SetLastError(ERROR_INVALID_FUNCTION); - return FALSE; + return FALSE; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03SP1) +#if (YY_Thunks_Target < __WindowsNT5_2_SP1) - //Windows XP with SP2, Windows Server 2003 with SP1 - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - IsWow64Process, - _In_ HANDLE hProcess, - _Out_ PBOOL Wow64Process - ) - { - if (auto const pIsWow64Process = try_get_IsWow64Process()) - { - return pIsWow64Process(hProcess, Wow64Process); - } + //Windows XP with SP2, Windows Server 2003 with SP1 + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + IsWow64Process, + _In_ HANDLE hProcess, + _Out_ PBOOL Wow64Process + ) + { + if (auto const pIsWow64Process = try_get_IsWow64Process()) + { + return pIsWow64Process(hProcess, Wow64Process); + } - *Wow64Process = FALSE; + *Wow64Process = FALSE; - return TRUE; - } + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS3) && (defined _X86_ || defined _AMD64_) - - //Windows 10, Version 1511 - //微软文档有点问题,实际x86以及amd64系统中,16299(RS3)才开始有此API。 - __DEFINE_THUNK( - kernel32, - 12, - _Success_(return) - BOOL, - WINAPI, - IsWow64Process2, - _In_ HANDLE hProcess, - _Out_ USHORT* pProcessMachine, - _Out_opt_ USHORT* pNativeMachine - ) - { - if (auto const pIsWow64Process2 = try_get_IsWow64Process2()) - { - return pIsWow64Process2(hProcess, pProcessMachine, pNativeMachine); - } - - - //判断是否运行在Wow6432虚拟机 - BOOL bWow64Process; - auto bRet = IsWow64Process(hProcess, &bWow64Process); - - if (bRet) - { - if (bWow64Process) - { - *pProcessMachine = IMAGE_FILE_MACHINE_I386; - - //IA64已经哭晕在厕所 - if (pNativeMachine) - *pNativeMachine = IMAGE_FILE_MACHINE_AMD64; - } - else - { - *pProcessMachine = IMAGE_FILE_MACHINE_UNKNOWN; +#if (YY_Thunks_Target < __WindowsNT10_16299) + + // 最低受支持的客户端 Windows 10版本 1709 [桌面应用 |UWP 应用] + // 最低受支持的服务器 Windows Server 2016版本 1709[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 12, + _Success_(return) + BOOL, + WINAPI, + IsWow64Process2, + _In_ HANDLE hProcess, + _Out_ USHORT* pProcessMachine, + _Out_opt_ USHORT* pNativeMachine + ) + { + if (auto const pIsWow64Process2 = try_get_IsWow64Process2()) + { + return pIsWow64Process2(hProcess, pProcessMachine, pNativeMachine); + } + + + //判断是否运行在Wow6432虚拟机 + BOOL bWow64Process; + auto bRet = IsWow64Process(hProcess, &bWow64Process); + + if (bRet) + { + if (bWow64Process) + { + *pProcessMachine = IMAGE_FILE_MACHINE_I386; + + //IA64已经哭晕在厕所 + if (pNativeMachine) + *pNativeMachine = IMAGE_FILE_MACHINE_AMD64; + } + else + { + *pProcessMachine = IMAGE_FILE_MACHINE_UNKNOWN; #if defined _X86_ - if (pNativeMachine) - *pNativeMachine = IMAGE_FILE_MACHINE_I386; + if (pNativeMachine) + *pNativeMachine = IMAGE_FILE_MACHINE_I386; #elif defined _AMD64_ - if (pNativeMachine) - *pNativeMachine = IMAGE_FILE_MACHINE_AMD64; + if (pNativeMachine) + *pNativeMachine = IMAGE_FILE_MACHINE_AMD64; #else - #error 不支持此体系 + #error 不支持此体系 #endif - } - } + } + } - return bRet; - } + return bRet; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS3) && (defined _X86_ || defined _AMD64_) - - //Windows 10, version 1709 - __DEFINE_THUNK( - kernel32, - 8, - _Must_inspect_result_ - HRESULT, - WINAPI, - IsWow64GuestMachineSupported, - _In_ USHORT WowGuestMachine, - _Out_ BOOL* MachineIsSupported - ) - { - if (auto const pIsWow64GuestMachineSupported = try_get_IsWow64GuestMachineSupported()) - { - return pIsWow64GuestMachineSupported(WowGuestMachine, MachineIsSupported); - } - - if (IMAGE_FILE_MACHINE_I386 == WowGuestMachine) - { +#if (YY_Thunks_Target < __WindowsNT10_16299) + + //Windows 10, version 1709 + __DEFINE_THUNK( + kernel32, + 8, + _Must_inspect_result_ + HRESULT, + WINAPI, + IsWow64GuestMachineSupported, + _In_ USHORT WowGuestMachine, + _Out_ BOOL* MachineIsSupported + ) + { + if (auto const pIsWow64GuestMachineSupported = try_get_IsWow64GuestMachineSupported()) + { + return pIsWow64GuestMachineSupported(WowGuestMachine, MachineIsSupported); + } + + if (IMAGE_FILE_MACHINE_I386 == WowGuestMachine) + { #ifdef _AMD64_ - *MachineIsSupported = TRUE; + *MachineIsSupported = TRUE; #else - SYSTEM_INFO SystemInfo; - GetNativeSystemInfo(&SystemInfo); + SYSTEM_INFO SystemInfo; + GetNativeSystemInfo(&SystemInfo); - *MachineIsSupported = SystemInfo.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL; + *MachineIsSupported = SystemInfo.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL; #endif - } - else - { - *MachineIsSupported = FALSE; - } + } + else + { + *MachineIsSupported = FALSE; + } - return S_OK; - } + return S_OK; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Windows XP x64确认没有这个接口 __DEFINE_THUNK( diff --git a/src/Thunks/api-ms-win-core-xstate.hpp b/src/Thunks/api-ms-win-core-xstate.hpp index cd10e0f..784143f 100644 --- a/src/Thunks/api-ms-win-core-xstate.hpp +++ b/src/Thunks/api-ms-win-core-xstate.hpp @@ -1,6 +1,6 @@ namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6SP1) +#if (YY_Thunks_Target < __WindowsNT6_1_SP1) // 最低受支持的客户端 Windows 7 SP1[桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008 R2 SP1[桌面应用 | UWP 应用] @@ -36,7 +36,7 @@ #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6SP1) +#if (YY_Thunks_Target < __WindowsNT6_1_SP1) // 最低受支持的客户端 Windows 7 SP1 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008 R2 SP1[仅限桌面应用] @@ -69,7 +69,7 @@ #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6SP1) +#if (YY_Thunks_Target < __WindowsNT6_1_SP1) // 最低受支持的客户端 Windows 7 SP1 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2008 R2 SP1[桌面应用 | UWP 应用] @@ -128,7 +128,7 @@ } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6SP1) +#if (YY_Thunks_Target < __WindowsNT6_1_SP1) // 最低受支持的客户端 Windows 7 SP1 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2008 R2 SP1[桌面应用 | UWP 应用] @@ -173,7 +173,7 @@ #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10_FE) +#if (YY_Thunks_Target < __WindowsNT10_20348) // 最低受支持的客户端 Windows 10内部版本 20348 // 最低受支持的服务器 Windows 10内部版本 20348 @@ -200,7 +200,7 @@ #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6SP1) +#if (YY_Thunks_Target < __WindowsNT6_1_SP1) // 最低受支持的客户端 Windows 7 SP1 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008 R2 SP1[仅限桌面应用] diff --git a/src/Thunks/api-ms-win-eventing-provider.hpp b/src/Thunks/api-ms-win-eventing-provider.hpp index 08dbdfb..5df5202 100644 --- a/src/Thunks/api-ms-win-eventing-provider.hpp +++ b/src/Thunks/api-ms-win-eventing-provider.hpp @@ -1,123 +1,123 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) && !defined(__Comment_Lib_advapi32) +#if (YY_Thunks_Target < __WindowsNT6_1) && !defined(__Comment_Lib_advapi32) #define __Comment_Lib_advapi32 #pragma comment(lib, "Advapi32.lib") #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] - __DEFINE_THUNK( - advapi32, - 20, - ULONG, - __stdcall, - EventSetInformation, - _In_ REGHANDLE _hRegHandle, - _In_ EVENT_INFO_CLASS _eInformationClass, - _In_reads_bytes_(_cbInformationLength) PVOID _pEventInformation, - _In_ ULONG _cbInformationLength - ) - { - if (auto const _pfnEventSetInformation = try_get_EventSetInformation()) - { - return _pfnEventSetInformation(_hRegHandle, _eInformationClass, _pEventInformation, _cbInformationLength); - } - - return ERROR_NOT_SUPPORTED; - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] + __DEFINE_THUNK( + advapi32, + 20, + ULONG, + __stdcall, + EventSetInformation, + _In_ REGHANDLE _hRegHandle, + _In_ EVENT_INFO_CLASS _eInformationClass, + _In_reads_bytes_(_cbInformationLength) PVOID _pEventInformation, + _In_ ULONG _cbInformationLength + ) + { + if (auto const _pfnEventSetInformation = try_get_EventSetInformation()) + { + return _pfnEventSetInformation(_hRegHandle, _eInformationClass, _pEventInformation, _cbInformationLength); + } + + return ERROR_NOT_SUPPORTED; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] - __DEFINE_THUNK( - advapi32, - 8, - ULONG, + __DEFINE_THUNK( + advapi32, + 8, + ULONG, WINAPI, EventActivityIdControl, _In_ ULONG _uControlCode, _Inout_ LPGUID _pActivityId - ) - { - if (auto const _pfnEventActivityIdControl = try_get_EventActivityIdControl()) - { - return _pfnEventActivityIdControl(_uControlCode, _pActivityId); - } + ) + { + if (auto const _pfnEventActivityIdControl = try_get_EventActivityIdControl()) + { + return _pfnEventActivityIdControl(_uControlCode, _pActivityId); + } - return ERROR_NOT_SUPPORTED; - } + return ERROR_NOT_SUPPORTED; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] - __DEFINE_THUNK( - advapi32, - 16, - ULONG, + __DEFINE_THUNK( + advapi32, + 16, + ULONG, WINAPI, EventRegister, _In_ LPCGUID _pProviderId, _In_opt_ PENABLECALLBACK _pfnEnableCallback, _In_opt_ PVOID _pCallbackContext, _Out_ PREGHANDLE _phRegHandle - ) - { - if (auto const _pfnEventRegister = try_get_EventRegister()) - { - return _pfnEventRegister(_pProviderId, _pfnEnableCallback, _pCallbackContext, _phRegHandle); - } + ) + { + if (auto const _pfnEventRegister = try_get_EventRegister()) + { + return _pfnEventRegister(_pProviderId, _pfnEnableCallback, _pCallbackContext, _phRegHandle); + } - return ERROR_NOT_SUPPORTED; - } + return ERROR_NOT_SUPPORTED; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] - __DEFINE_THUNK( - advapi32, - 8, - ULONG, + __DEFINE_THUNK( + advapi32, + 8, + ULONG, WINAPI, EventUnregister, _In_ REGHANDLE _hRegHandle - ) - { - if (auto const _pfnEventUnregister = try_get_EventUnregister()) - { - return _pfnEventUnregister(_hRegHandle); - } - return ERROR_NOT_SUPPORTED; - } + ) + { + if (auto const _pfnEventUnregister = try_get_EventUnregister()) + { + return _pfnEventUnregister(_hRegHandle); + } + return ERROR_NOT_SUPPORTED; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] - __DEFINE_THUNK( - advapi32, - 24, + __DEFINE_THUNK( + advapi32, + 24, ULONG, WINAPI, EnumerateTraceGuidsEx, @@ -127,24 +127,24 @@ namespace YY::Thunks _Out_writes_bytes_opt_(OutBufferSize) PVOID OutBuffer, _In_ ULONG OutBufferSize, _Out_ PULONG ReturnLength - ) - { - if (auto const _pfnEnumerateTraceGuidsEx = try_get_EnumerateTraceGuidsEx()) - { - return _pfnEnumerateTraceGuidsEx(TraceQueryInfoClass, InBuffer, InBufferSize, OutBuffer, OutBufferSize, ReturnLength); - } - return ERROR_NOT_SUPPORTED; - } + ) + { + if (auto const _pfnEnumerateTraceGuidsEx = try_get_EnumerateTraceGuidsEx()) + { + return _pfnEnumerateTraceGuidsEx(TraceQueryInfoClass, InBuffer, InBufferSize, OutBuffer, OutBufferSize, ReturnLength); + } + return ERROR_NOT_SUPPORTED; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] - __DEFINE_THUNK( - advapi32, - 28, + __DEFINE_THUNK( + advapi32, + 28, ULONG, WINAPI, EventWriteTransfer, @@ -154,49 +154,49 @@ namespace YY::Thunks _In_opt_ LPCGUID RelatedActivityId, _In_range_(0, MAX_EVENT_DATA_DESCRIPTORS) ULONG UserDataCount, _In_reads_opt_(UserDataCount) PEVENT_DATA_DESCRIPTOR UserData - ) - { - if (auto const _pfnEventWriteTransfer = try_get_EventWriteTransfer()) - { - return _pfnEventWriteTransfer(RegHandle, EventDescriptor, ActivityId, RelatedActivityId, UserDataCount, UserData); - } + ) + { + if (auto const _pfnEventWriteTransfer = try_get_EventWriteTransfer()) + { + return _pfnEventWriteTransfer(RegHandle, EventDescriptor, ActivityId, RelatedActivityId, UserDataCount, UserData); + } - return ERROR_NOT_SUPPORTED; - } + return ERROR_NOT_SUPPORTED; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [仅限桌面应用] + // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] - __DEFINE_THUNK( - advapi32, - 12, + __DEFINE_THUNK( + advapi32, + 12, BOOLEAN, WINAPI, EventEnabled, _In_ REGHANDLE RegHandle, _In_ PCEVENT_DESCRIPTOR EventDescriptor - ) - { - if (auto const _pfnEventEnabled = try_get_EventEnabled()) - { - return _pfnEventEnabled(RegHandle, EventDescriptor); - } + ) + { + if (auto const _pfnEventEnabled = try_get_EventEnabled()) + { + return _pfnEventEnabled(RegHandle, EventDescriptor); + } - return FALSE; - } + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - advapi32, - 20, + __DEFINE_THUNK( + advapi32, + 20, ULONG, WINAPI, EventWrite, @@ -204,25 +204,25 @@ namespace YY::Thunks _In_ PCEVENT_DESCRIPTOR EventDescriptor, _In_range_(0, MAX_EVENT_DATA_DESCRIPTORS) ULONG UserDataCount, _In_reads_opt_(UserDataCount) PEVENT_DATA_DESCRIPTOR UserData - ) - { - if (auto const _pfnEventWrite = try_get_EventWrite()) - { - return _pfnEventWrite(RegHandle, EventDescriptor, UserDataCount, UserData); - } + ) + { + if (auto const _pfnEventWrite = try_get_EventWrite()) + { + return _pfnEventWrite(RegHandle, EventDescriptor, UserDataCount, UserData); + } - return ERROR_NOT_SUPPORTED; - } + return ERROR_NOT_SUPPORTED; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) - // 最低受支持的客户端 Windows 7 [桌面应用 |UWP 应用] + // 最低受支持的客户端 Windows 7 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2008 R2[桌面应用 | UWP 应用] - __DEFINE_THUNK( - advapi32, - 40, + __DEFINE_THUNK( + advapi32, + 40, ULONG, WINAPI, EventWriteEx, @@ -234,25 +234,25 @@ namespace YY::Thunks _In_opt_ LPCGUID RelatedActivityId, _In_range_(0, MAX_EVENT_DATA_DESCRIPTORS) ULONG UserDataCount, _In_reads_opt_(UserDataCount) PEVENT_DATA_DESCRIPTOR UserData - ) - { - if (auto const _pfnEventWriteEx = try_get_EventWriteEx()) - { - return _pfnEventWriteEx(RegHandle, EventDescriptor, Filter, Flags, ActivityId, RelatedActivityId, UserDataCount, UserData); - } + ) + { + if (auto const _pfnEventWriteEx = try_get_EventWriteEx()) + { + return _pfnEventWriteEx(RegHandle, EventDescriptor, Filter, Flags, ActivityId, RelatedActivityId, UserDataCount, UserData); + } - return ::EventWriteTransfer(RegHandle, EventDescriptor, ActivityId, RelatedActivityId, UserDataCount, UserData); - } + return ::EventWriteTransfer(RegHandle, EventDescriptor, ActivityId, RelatedActivityId, UserDataCount, UserData); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - advapi32, - 24, + __DEFINE_THUNK( + advapi32, + 24, ULONG, WINAPI, EventWriteString, @@ -260,13 +260,13 @@ namespace YY::Thunks _In_ UCHAR Level, _In_ ULONGLONG Keyword, _In_ PCWSTR String - ) - { - if (auto const _pfnEventWriteString = try_get_EventWriteString()) - { - return _pfnEventWriteString(RegHandle, Level, Keyword, String); - } + ) + { + if (auto const _pfnEventWriteString = try_get_EventWriteString()) + { + return _pfnEventWriteString(RegHandle, Level, Keyword, String); + } return ERROR_NOT_SUPPORTED; - } + } #endif } diff --git a/src/Thunks/api-ms-win-power-base.hpp b/src/Thunks/api-ms-win-power-base.hpp index 95c5e8a..f6af4d1 100644 --- a/src/Thunks/api-ms-win-power-base.hpp +++ b/src/Thunks/api-ms-win-power-base.hpp @@ -1,170 +1,172 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) && !defined(__Comment_Lib_powrprof) +#if (YY_Thunks_Target < __WindowsNT6_2) && !defined(__Comment_Lib_powrprof) #define __Comment_Lib_powrprof #pragma comment(lib, "PowrProf.lib") #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) && defined(YY_Thunks_Implemented) +#if (YY_Thunks_Target < __WindowsNT6_2) && defined(YY_Thunks_Implemented) namespace YY::Thunks { - namespace - { - static - DWORD - WINAPI - PowerRegisterSuspendResumeNotificationDownlevel( - _In_ DWORD _fFlags, - _In_ HANDLE _hRecipient, - _Out_ PHPOWERNOTIFY _phRegistrationHandle - ) - { - if (!_phRegistrationHandle) - return ERROR_INVALID_PARAMETER; - *_phRegistrationHandle = NULL; - - const auto _hProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; - - - if (DEVICE_NOTIFY_CALLBACK == _fFlags) - { - auto _pDeviceNotifyInfo = (DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS*)_hRecipient; - if(!_pDeviceNotifyInfo) - return ERROR_INVALID_PARAMETER; - - struct DeviceNotifyTaskItem : public internal::TaskItem - { - DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS Parameters; - }; - - auto _pTask = (DeviceNotifyTaskItem*)HeapAlloc(_hProcessHeap, 0, sizeof(DeviceNotifyTaskItem)); - if (!_pTask) - return ERROR_OUTOFMEMORY; - - _pTask->Parameters = *_pDeviceNotifyInfo; - _pTask->pfnCallback = []( - internal::TaskItem* _pWork, - UINT _uMsg, - WPARAM _wParam, - LPARAM _lParam) -> BOOL - { - auto _pWork2 = (DeviceNotifyTaskItem*)_pWork; - - if (WM_POWERBROADCAST == _uMsg) - { - _pWork2->Parameters.Callback(_pWork2->Parameters.Context, static_cast(_wParam), (PVOID)_lParam); - } - - return TRUE; - }; - - if (internal::GetGlobalThreadRunner()->AddTask(_pTask)) - { - *_phRegistrationHandle = _pTask; - return ERROR_SUCCESS; - } - - HeapFree(_hProcessHeap, 0, _pTask); - return ERROR_OUTOFMEMORY; - } - else - { - return ERROR_INVALID_PARAMETER; - } - } - - static - DWORD - WINAPI - PowerUnregisterSuspendResumeNotificationDownlevel( - _Inout_ HPOWERNOTIFY _hRegistrationHandle - ) - { - if (!_hRegistrationHandle) - return ERROR_INVALID_PARAMETER; - - return internal::GetGlobalThreadRunner()->RemoveTask((internal::TaskItem*)_hRegistrationHandle); - } + namespace + { + static + DWORD + WINAPI + PowerRegisterSuspendResumeNotificationDownlevel( + _In_ DWORD _fFlags, + _In_ HANDLE _hRecipient, + _Out_ PHPOWERNOTIFY _phRegistrationHandle + ) + { + if (!_phRegistrationHandle) + return ERROR_INVALID_PARAMETER; + *_phRegistrationHandle = NULL; + + const auto _hProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; + + + if (DEVICE_NOTIFY_CALLBACK == _fFlags) + { + auto _pDeviceNotifyInfo = (DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS*)_hRecipient; + if(!_pDeviceNotifyInfo) + return ERROR_INVALID_PARAMETER; + + struct DeviceNotifyTaskItem : public internal::TaskItem + { + DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS Parameters; + }; + + auto _pTask = (DeviceNotifyTaskItem*)HeapAlloc(_hProcessHeap, 0, sizeof(DeviceNotifyTaskItem)); + if (!_pTask) + return ERROR_OUTOFMEMORY; + + _pTask->Parameters = *_pDeviceNotifyInfo; + _pTask->pfnCallback = []( + internal::TaskItem* _pWork, + UINT _uMsg, + WPARAM _wParam, + LPARAM _lParam) -> BOOL + { + auto _pWork2 = (DeviceNotifyTaskItem*)_pWork; + + if (WM_POWERBROADCAST == _uMsg) + { + _pWork2->Parameters.Callback(_pWork2->Parameters.Context, static_cast(_wParam), (PVOID)_lParam); + } + + return TRUE; + }; + + if (internal::GetGlobalThreadRunner()->AddTask(_pTask)) + { + *_phRegistrationHandle = _pTask; + return ERROR_SUCCESS; + } + + HeapFree(_hProcessHeap, 0, _pTask); + return ERROR_OUTOFMEMORY; + } + else + { + return ERROR_INVALID_PARAMETER; + } + } + + static + DWORD + WINAPI + PowerUnregisterSuspendResumeNotificationDownlevel( + _Inout_ HPOWERNOTIFY _hRegistrationHandle + ) + { + if (!_hRegistrationHandle) + return ERROR_INVALID_PARAMETER; + + return internal::GetGlobalThreadRunner()->RemoveTask((internal::TaskItem*)_hRegistrationHandle); + } } } -#endif // (YY_Thunks_Support_Version < NTDDI_WIN8) && defined(YY_Thunks_Implemented) +#endif // (YY_Thunks_Target < __WindowsNT6_2) && defined(YY_Thunks_Implemented) namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] - __DEFINE_THUNK( - powrprof, - 4, - POWER_PLATFORM_ROLE, - WINAPI, - PowerDeterminePlatformRoleEx, - _In_ ULONG _uVersion - ) - { - if (auto const _pfnPowerDeterminePlatformRoleEx = try_get_PowerDeterminePlatformRoleEx()) - { - return _pfnPowerDeterminePlatformRoleEx(_uVersion); - } - - if (_uVersion == POWER_PLATFORM_ROLE_V1) - { - return PowerDeterminePlatformRole(); - } - else - { - return PlatformRoleUnspecified; - } - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] + __DEFINE_THUNK( + powrprof, + 4, + POWER_PLATFORM_ROLE, + WINAPI, + PowerDeterminePlatformRoleEx, + _In_ ULONG _uVersion + ) + { + if (auto const _pfnPowerDeterminePlatformRoleEx = try_get_PowerDeterminePlatformRoleEx()) + { + return _pfnPowerDeterminePlatformRoleEx(_uVersion); + } + + if (_uVersion == POWER_PLATFORM_ROLE_V1) + { + return PowerDeterminePlatformRole(); + } + else + { + return PlatformRoleUnspecified; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - // 最低受支持的客户端 Windows 8 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] - __DEFINE_THUNK( - powrprof, - 12, - DWORD, - WINAPI, - PowerRegisterSuspendResumeNotification, - _In_ DWORD _fFlags, - _In_ HANDLE _hRecipient, - _Out_ PHPOWERNOTIFY _phRegistrationHandle - ) - { - if (auto const _pfnPowerRegisterSuspendResumeNotification = try_get_PowerRegisterSuspendResumeNotification()) - { - return _pfnPowerRegisterSuspendResumeNotification(_fFlags, _hRecipient, _phRegistrationHandle); - } - - return PowerRegisterSuspendResumeNotificationDownlevel(_fFlags, _hRecipient, _phRegistrationHandle); - } + +#if (YY_Thunks_Target < __WindowsNT6_2) + + // 最低受支持的客户端 Windows 8 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] + __DEFINE_THUNK( + powrprof, + 12, + DWORD, + WINAPI, + PowerRegisterSuspendResumeNotification, + _In_ DWORD _fFlags, + _In_ HANDLE _hRecipient, + _Out_ PHPOWERNOTIFY _phRegistrationHandle + ) + { + if (auto const _pfnPowerRegisterSuspendResumeNotification = try_get_PowerRegisterSuspendResumeNotification()) + { + return _pfnPowerRegisterSuspendResumeNotification(_fFlags, _hRecipient, _phRegistrationHandle); + } + + return PowerRegisterSuspendResumeNotificationDownlevel(_fFlags, _hRecipient, _phRegistrationHandle); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - // 最低受支持的客户端 Windows 8 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] - __DEFINE_THUNK( - powrprof, - 4, - DWORD, - WINAPI, - PowerUnregisterSuspendResumeNotification, - _Inout_ HPOWERNOTIFY _hRegistrationHandle - ) - { - if (auto const _pfnPowerUnregisterSuspendResumeNotification = try_get_PowerUnregisterSuspendResumeNotification()) - { - return _pfnPowerUnregisterSuspendResumeNotification(_hRegistrationHandle); - } - - return PowerUnregisterSuspendResumeNotificationDownlevel(_hRegistrationHandle); - } + +#if (YY_Thunks_Target < __WindowsNT6_2) + + // 最低受支持的客户端 Windows 8 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] + __DEFINE_THUNK( + powrprof, + 4, + DWORD, + WINAPI, + PowerUnregisterSuspendResumeNotification, + _Inout_ HPOWERNOTIFY _hRegistrationHandle + ) + { + if (auto const _pfnPowerUnregisterSuspendResumeNotification = try_get_PowerUnregisterSuspendResumeNotification()) + { + return _pfnPowerUnregisterSuspendResumeNotification(_hRegistrationHandle); + } + + return PowerUnregisterSuspendResumeNotificationDownlevel(_hRegistrationHandle); + } #endif } diff --git a/src/Thunks/api-ms-win-security-base.hpp b/src/Thunks/api-ms-win-security-base.hpp index a20360a..cf1da4d 100644 --- a/src/Thunks/api-ms-win-security-base.hpp +++ b/src/Thunks/api-ms-win-security-base.hpp @@ -1,26 +1,26 @@ namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - advapi32, - 20, - BOOL, - WINAPI, - AddMandatoryAce, + __DEFINE_THUNK( + advapi32, + 20, + BOOL, + WINAPI, + AddMandatoryAce, _Inout_ PACL _pAcl, _In_ DWORD _uAceRevision, _In_ DWORD _fAceFlags, _In_ DWORD _uMandatoryPolicy, _In_ SID* _pLabelSid ) - { - if (const auto _pfnAddMandatoryAce = try_get_AddMandatoryAce()) - { - return _pfnAddMandatoryAce(_pAcl, _uAceRevision, _fAceFlags, _uMandatoryPolicy, _pLabelSid); - } + { + if (const auto _pfnAddMandatoryAce = try_get_AddMandatoryAce()) + { + return _pfnAddMandatoryAce(_pAcl, _uAceRevision, _fAceFlags, _uMandatoryPolicy, _pLabelSid); + } // 参考 ntdll.RtlAddMandatoryAce 实现 @@ -99,6 +99,6 @@ _pAcl->AclRevision = (BYTE)_uAceRevision; return TRUE; - } + } #endif } // namespace YY::Thunks diff --git a/src/Thunks/bcrypt.hpp b/src/Thunks/bcrypt.hpp index 4b19c43..23062ae 100644 --- a/src/Thunks/bcrypt.hpp +++ b/src/Thunks/bcrypt.hpp @@ -1,21 +1,21 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) #include #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_advapi32) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_advapi32) #define __Comment_Lib_advapi32 #pragma comment(lib, "Advapi32.lib") #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) && (YY_Thunks_Support_Version >= NTDDI_WIN6 || __YY_Thunks_libs) && !defined(__Comment_Lib_bcrypt) +#if (YY_Thunks_Target < __WindowsNT6_1) && (YY_Thunks_Target >= __WindowsNT6 || __YY_Thunks_libs) && !defined(__Comment_Lib_bcrypt) #define __Comment_Lib_bcrypt #pragma comment(lib, "bcrypt.lib") #endif namespace YY::Thunks { -#if defined(YY_Thunks_Implemented) && YY_Thunks_Support_Version < NTDDI_WIN6 +#if defined(YY_Thunks_Implemented) && YY_Thunks_Target < __WindowsNT6 namespace { struct BCryptHash; @@ -27,13 +27,13 @@ namespace YY::Thunks _In_ ULONG _fFlags, _Outptr_ BCryptAlgorithm** _ppAlgorithm); - struct BCryptMapItem - { - LPCWSTR szProvider; + struct BCryptMapItem + { + LPCWSTR szProvider; LPCWSTR szAlgName; DWORD cbAlgId; - DWORD uProvType; - DWORD uAlgId; + DWORD uProvType; + DWORD uAlgId; OpenAlgorithmProviderType pfnOpenAlgorithmProviderType; template @@ -46,7 +46,7 @@ namespace YY::Thunks , pfnOpenAlgorithmProviderType(_pOpenAlgorithmProvider) { } - }; + }; enum class BCryptObjectType { @@ -1624,29 +1624,32 @@ namespace YY::Thunks } } #endif +} + +namespace YY::Thunks +{ +#if (YY_Thunks_Target < __WindowsNT6) + + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + bcrypt, + 16, + NTSTATUS, + WINAPI, + BCryptOpenAlgorithmProvider, + _Out_ BCRYPT_ALG_HANDLE* _phAlgorithm, + _In_ LPCWSTR _szAlgId, + _In_opt_ LPCWSTR _szImplementation, + _In_ ULONG _fFlags + ) + { + if (const auto _pfnBCryptOpenAlgorithmProvider = try_get_BCryptOpenAlgorithmProvider()) + { + return _pfnBCryptOpenAlgorithmProvider(_phAlgorithm, _szAlgId, _szImplementation, _fFlags); + } -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - bcrypt, - 16, - NTSTATUS, - WINAPI, - BCryptOpenAlgorithmProvider, - _Out_ BCRYPT_ALG_HANDLE* _phAlgorithm, - _In_ LPCWSTR _szAlgId, - _In_opt_ LPCWSTR _szImplementation, - _In_ ULONG _fFlags - ) - { - if (const auto _pfnBCryptOpenAlgorithmProvider = try_get_BCryptOpenAlgorithmProvider()) - { - return _pfnBCryptOpenAlgorithmProvider(_phAlgorithm, _szAlgId, _szImplementation, _fFlags); - } - - UNREFERENCED_PARAMETER(_szImplementation); + UNREFERENCED_PARAMETER(_szImplementation); if (_phAlgorithm == nullptr || _szAlgId == nullptr || (_fFlags & ~BCRYPT_ALG_HANDLE_HMAC_FLAG)) { @@ -1686,7 +1689,7 @@ namespace YY::Thunks { BCRYPT_RNG_DUAL_EC_ALGORITHM, nullptr, 0, 0, &BCryptRngAlgorithm::Create }, }; -#if (YY_Thunks_Support_Version < NTDDI_WINXPSP3) +#if (YY_Thunks_Target < __WindowsNT5_1_SP3) __WarningMessage__("Windows XP SP3的Crypt开始才支持 CALG_SHA_256、CALG_SHA_384、CALG_SHA_512"); #endif @@ -1699,26 +1702,26 @@ namespace YY::Thunks } return STATUS_NOT_FOUND; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - bcrypt, - 8, - NTSTATUS, - WINAPI, - BCryptCloseAlgorithmProvider, - _Inout_ BCRYPT_ALG_HANDLE _hAlgorithm, - _In_ ULONG _fFlags) - { - if (auto _pfnBCryptCloseAlgorithmProvider = try_get_BCryptCloseAlgorithmProvider()) - { - return _pfnBCryptCloseAlgorithmProvider(_hAlgorithm, _fFlags); - } +#if (YY_Thunks_Target < __WindowsNT6) + + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + bcrypt, + 8, + NTSTATUS, + WINAPI, + BCryptCloseAlgorithmProvider, + _Inout_ BCRYPT_ALG_HANDLE _hAlgorithm, + _In_ ULONG _fFlags) + { + if (auto _pfnBCryptCloseAlgorithmProvider = try_get_BCryptCloseAlgorithmProvider()) + { + return _pfnBCryptCloseAlgorithmProvider(_hAlgorithm, _fFlags); + } if (_fFlags) return STATUS_INVALID_PARAMETER; @@ -1728,72 +1731,72 @@ namespace YY::Thunks reinterpret_cast(_hAlgorithm)->Release(); return STATUS_SUCCESS; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - bcrypt, - 16, - NTSTATUS, - WINAPI, - BCryptGenRandom, - _In_opt_ BCRYPT_ALG_HANDLE _hAlgorithm, - _Out_writes_bytes_(_cbBuffer) PUCHAR _pbBuffer, - _In_ ULONG _cbBuffer, - _In_ ULONG _fFlags - ) - { - if (auto _pfnBCryptGenRandom = try_get_BCryptGenRandom()) - { - return _pfnBCryptGenRandom(_hAlgorithm, _pbBuffer, _cbBuffer, _fFlags); - } - - if (_pbBuffer == nullptr) - return STATUS_INVALID_PARAMETER; - if (_cbBuffer == 0) - return STATUS_SUCCESS; - - if (_fFlags & BCRYPT_USE_SYSTEM_PREFERRED_RNG) - { - if(_hAlgorithm != NULL) - return STATUS_INVALID_PARAMETER; - } - else - { +#if (YY_Thunks_Target < __WindowsNT6) + + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + bcrypt, + 16, + NTSTATUS, + WINAPI, + BCryptGenRandom, + _In_opt_ BCRYPT_ALG_HANDLE _hAlgorithm, + _Out_writes_bytes_(_cbBuffer) PUCHAR _pbBuffer, + _In_ ULONG _cbBuffer, + _In_ ULONG _fFlags + ) + { + if (auto _pfnBCryptGenRandom = try_get_BCryptGenRandom()) + { + return _pfnBCryptGenRandom(_hAlgorithm, _pbBuffer, _cbBuffer, _fFlags); + } + + if (_pbBuffer == nullptr) + return STATUS_INVALID_PARAMETER; + if (_cbBuffer == 0) + return STATUS_SUCCESS; + + if (_fFlags & BCRYPT_USE_SYSTEM_PREFERRED_RNG) + { + if(_hAlgorithm != NULL) + return STATUS_INVALID_PARAMETER; + } + else + { if (!Is(_hAlgorithm)) { return STATUS_INVALID_HANDLE; } - } - - // 此函数内部其实就是用了Crypt API,所以针对Windows XP就直接使用它了。 - const auto _pfnRtlGenRandom = try_get_SystemFunction036(); - if (!_pfnRtlGenRandom) - { - internal::RaiseStatus(STATUS_NOT_IMPLEMENTED); - return STATUS_NOT_IMPLEMENTED; - } - - if (_pfnRtlGenRandom(_pbBuffer, _cbBuffer)) - return STATUS_SUCCESS; - else - return STATUS_UNSUCCESSFUL; - } + } + + // 此函数内部其实就是用了Crypt API,所以针对Windows XP就直接使用它了。 + const auto _pfnRtlGenRandom = try_get_SystemFunction036(); + if (!_pfnRtlGenRandom) + { + internal::RaiseStatus(STATUS_NOT_IMPLEMENTED); + return STATUS_NOT_IMPLEMENTED; + } + + if (_pfnRtlGenRandom(_pbBuffer, _cbBuffer)) + return STATUS_SUCCESS; + else + return STATUS_UNSUCCESSFUL; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - bcrypt, - 24, - NTSTATUS, + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + bcrypt, + 24, + NTSTATUS, WINAPI, BCryptGetProperty, _In_ BCRYPT_HANDLE hObject, @@ -1803,11 +1806,11 @@ namespace YY::Thunks _Out_ ULONG *pcbResult, _In_ ULONG dwFlags ) - { - if (const auto _pfnBCryptGetProperty = try_get_BCryptGetProperty()) - { - return _pfnBCryptGetProperty(hObject, pszProperty, pbOutput, cbOutput, pcbResult, dwFlags); - } + { + if (const auto _pfnBCryptGetProperty = try_get_BCryptGetProperty()) + { + return _pfnBCryptGetProperty(hObject, pszProperty, pbOutput, cbOutput, pcbResult, dwFlags); + } if(pszProperty == nullptr || dwFlags) return STATUS_INVALID_PARAMETER; @@ -1818,18 +1821,18 @@ namespace YY::Thunks } return reinterpret_cast(hObject)->GetProperty(pszProperty, pbOutput, cbOutput, pcbResult, dwFlags); - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - bcrypt, - 20, - NTSTATUS, + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + bcrypt, + 20, + NTSTATUS, WINAPI, BCryptSetProperty, _Inout_ BCRYPT_HANDLE _hObject, @@ -1838,11 +1841,11 @@ namespace YY::Thunks _In_ ULONG _cbInput, _In_ ULONG _fFlags ) - { - if (const auto _pfnBCryptSetProperty = try_get_BCryptSetProperty()) - { - return _pfnBCryptSetProperty(_hObject, _szProperty, _pInput, _cbInput, _fFlags); - } + { + if (const auto _pfnBCryptSetProperty = try_get_BCryptSetProperty()) + { + return _pfnBCryptSetProperty(_hObject, _szProperty, _pInput, _cbInput, _fFlags); + } if(_szProperty == nullptr || _fFlags) return STATUS_INVALID_PARAMETER; @@ -1853,18 +1856,18 @@ namespace YY::Thunks } return reinterpret_cast(_hObject)->SetProperty(_szProperty, _pInput, _cbInput, _fFlags); - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - bcrypt, - 28, - NTSTATUS, + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + bcrypt, + 28, + NTSTATUS, WINAPI, BCryptCreateHash, _Inout_ BCRYPT_ALG_HANDLE hAlgorithm, @@ -1875,11 +1878,11 @@ namespace YY::Thunks _In_ ULONG cbSecret, // optional _In_ ULONG dwFlags ) - { - if (const auto _pfnBCryptCreateHash = try_get_BCryptCreateHash()) - { - return _pfnBCryptCreateHash(hAlgorithm, phHash, pbHashObject, cbHashObject, pbSecret, cbSecret, dwFlags); - } + { + if (const auto _pfnBCryptCreateHash = try_get_BCryptCreateHash()) + { + return _pfnBCryptCreateHash(hAlgorithm, phHash, pbHashObject, cbHashObject, pbSecret, cbSecret, dwFlags); + } if ((cbHashObject && pbHashObject == nullptr) || dwFlags || phHash == nullptr) { @@ -1892,18 +1895,18 @@ namespace YY::Thunks } return reinterpret_cast(hAlgorithm)->CreateHash(reinterpret_cast(phHash), pbHashObject, cbHashObject, pbSecret, cbSecret, dwFlags); - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - bcrypt, - 16, - NTSTATUS, + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + bcrypt, + 16, + NTSTATUS, WINAPI, BCryptHashData, _Inout_ BCRYPT_HASH_HANDLE hHash, @@ -1911,11 +1914,11 @@ namespace YY::Thunks _In_ ULONG cbInput, _In_ ULONG dwFlags ) - { - if (const auto _pfnBCryptHashData = try_get_BCryptHashData()) - { - return _pfnBCryptHashData(hHash, pbInput, cbInput, dwFlags); - } + { + if (const auto _pfnBCryptHashData = try_get_BCryptHashData()) + { + return _pfnBCryptHashData(hHash, pbInput, cbInput, dwFlags); + } if(dwFlags) return STATUS_INVALID_PARAMETER; @@ -1924,18 +1927,18 @@ namespace YY::Thunks return STATUS_INVALID_HANDLE; return reinterpret_cast(hHash)->HashData(pbInput, cbInput, dwFlags); - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - bcrypt, - 16, - NTSTATUS, + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + bcrypt, + 16, + NTSTATUS, WINAPI, BCryptFinishHash, _Inout_ BCRYPT_HASH_HANDLE hHash, @@ -1943,11 +1946,11 @@ namespace YY::Thunks _In_ ULONG cbOutput, _In_ ULONG dwFlags ) - { - if (const auto _pfnBCryptFinishHash = try_get_BCryptFinishHash()) - { - return _pfnBCryptFinishHash(hHash, pbOutput, cbOutput, dwFlags); - } + { + if (const auto _pfnBCryptFinishHash = try_get_BCryptFinishHash()) + { + return _pfnBCryptFinishHash(hHash, pbOutput, cbOutput, dwFlags); + } if(dwFlags) return STATUS_INVALID_PARAMETER; @@ -1956,44 +1959,44 @@ namespace YY::Thunks return STATUS_INVALID_HANDLE; return reinterpret_cast(hHash)->FinishHash(pbOutput, cbOutput, dwFlags); - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] - // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - bcrypt, - 4, - NTSTATUS, + // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + bcrypt, + 4, + NTSTATUS, WINAPI, BCryptDestroyHash, _Inout_ BCRYPT_HASH_HANDLE hHash) - { - if (const auto _pfnBCryptDestroyHash = try_get_BCryptDestroyHash()) - { - return _pfnBCryptDestroyHash(hHash); - } + { + if (const auto _pfnBCryptDestroyHash = try_get_BCryptDestroyHash()) + { + return _pfnBCryptDestroyHash(hHash); + } if (!Is(hHash)) return STATUS_INVALID_PARAMETER; reinterpret_cast(hHash)->Release(); return STATUS_SUCCESS; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) - // 最低受支持的客户端 Windows 7 [桌面应用 |UWP 应用] + // 最低受支持的客户端 Windows 7 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2008 R2[桌面应用 | UWP 应用] - __DEFINE_THUNK( - bcrypt, - 40, - NTSTATUS, + __DEFINE_THUNK( + bcrypt, + 40, + NTSTATUS, WINAPI, BCryptDeriveKeyPBKDF2, _In_ BCRYPT_ALG_HANDLE hPrf, @@ -2006,11 +2009,11 @@ namespace YY::Thunks _In_ ULONG cbDerivedKey, _In_ ULONG dwFlags ) - { - if (const auto _pfnBCryptDeriveKeyPBKDF2 = try_get_BCryptDeriveKeyPBKDF2()) - { - return _pfnBCryptDeriveKeyPBKDF2(hPrf, pbPassword, cbPassword, pbSalt, cbSalt, cIterations, pbDerivedKey, cbDerivedKey, dwFlags); - } + { + if (const auto _pfnBCryptDeriveKeyPBKDF2 = try_get_BCryptDeriveKeyPBKDF2()) + { + return _pfnBCryptDeriveKeyPBKDF2(hPrf, pbPassword, cbPassword, pbSalt, cbSalt, cIterations, pbDerivedKey, cbDerivedKey, dwFlags); + } // 实现参考微软 bcrypt.BCryptDeriveKeyPBKDF2 函数 if ((pbPassword == nullptr && cbPassword) || (pbSalt == nullptr && cbSalt) || cIterations == 0 || pbDerivedKey == nullptr || cbDerivedKey == 0) @@ -2126,18 +2129,18 @@ namespace YY::Thunks if (_pObjectHashBuffer) _freea(_pObjectHashBuffer); return _Status; - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) - // 最低受支持的客户端 Windows 7 [桌面应用 |UWP 应用] + // 最低受支持的客户端 Windows 7 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2008 R2[桌面应用 | UWP 应用] - __DEFINE_THUNK( - bcrypt, - 40, - NTSTATUS, + __DEFINE_THUNK( + bcrypt, + 40, + NTSTATUS, WINAPI, BCryptDeriveKeyCapi, _In_ BCRYPT_HASH_HANDLE hHash, @@ -2146,11 +2149,11 @@ namespace YY::Thunks _In_ ULONG cbDerivedKey, _In_ ULONG dwFlags ) - { - if (const auto _pfnBCryptDeriveKeyCapi = try_get_BCryptDeriveKeyCapi()) - { - return _pfnBCryptDeriveKeyCapi(hHash, hTargetAlg, pbDerivedKey, cbDerivedKey, dwFlags); - } + { + if (const auto _pfnBCryptDeriveKeyCapi = try_get_BCryptDeriveKeyCapi()) + { + return _pfnBCryptDeriveKeyCapi(hHash, hTargetAlg, pbDerivedKey, cbDerivedKey, dwFlags); + } if (dwFlags != 0 || (pbDerivedKey == nullptr && cbDerivedKey)) { @@ -2260,14 +2263,14 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - bcrypt, - 40, - NTSTATUS, + __DEFINE_THUNK( + bcrypt, + 40, + NTSTATUS, WINAPI, BCryptEncrypt, _Inout_ BCRYPT_KEY_HANDLE _hKey, @@ -2280,11 +2283,11 @@ namespace YY::Thunks _In_ ULONG _cbOutput, _Out_ ULONG *_pcbResult, _In_ ULONG _fFlags) - { - if (const auto _pfnBCryptEncrypt = try_get_BCryptEncrypt()) - { - return _pfnBCryptEncrypt(_hKey, _pInput, _cbInput, _pPaddingInfo, _pIV, _cbIV, _pOutput, _cbOutput, _pcbResult, _fFlags); - } + { + if (const auto _pfnBCryptEncrypt = try_get_BCryptEncrypt()) + { + return _pfnBCryptEncrypt(_hKey, _pInput, _cbInput, _pPaddingInfo, _pIV, _cbIV, _pOutput, _cbOutput, _pcbResult, _fFlags); + } if (!Is(_hKey)) { @@ -2296,14 +2299,14 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - bcrypt, - 40, - NTSTATUS, + __DEFINE_THUNK( + bcrypt, + 40, + NTSTATUS, WINAPI, BCryptDecrypt, _Inout_ BCRYPT_KEY_HANDLE _hKey, @@ -2317,11 +2320,11 @@ namespace YY::Thunks _Out_ ULONG* _pcbResult, _In_ ULONG _fFlags ) - { - if (const auto _pfnBCryptDecrypt = try_get_BCryptDecrypt()) - { - return _pfnBCryptDecrypt(_hKey, _pInput, _cbInput, _pPaddingInfo, _pIV, _cbIV, _pOutput, _cbOutput, _pcbResult, _fFlags); - } + { + if (const auto _pfnBCryptDecrypt = try_get_BCryptDecrypt()) + { + return _pfnBCryptDecrypt(_hKey, _pInput, _cbInput, _pPaddingInfo, _pIV, _cbIV, _pOutput, _cbOutput, _pcbResult, _fFlags); + } if (!Is(_hKey)) { @@ -2333,14 +2336,14 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - bcrypt, - 28, - NTSTATUS, + __DEFINE_THUNK( + bcrypt, + 28, + NTSTATUS, WINAPI, BCryptGenerateSymmetricKey, _Inout_ BCRYPT_ALG_HANDLE _hAlgorithm, @@ -2351,11 +2354,11 @@ namespace YY::Thunks _In_ ULONG _cbSecret, _In_ ULONG _fFlags ) - { - if (const auto _pfnBCryptGenerateSymmetricKey = try_get_BCryptGenerateSymmetricKey()) - { - return _pfnBCryptGenerateSymmetricKey(_hAlgorithm, _phKey, _pKeyObject, _cbKeyObject, _pSecret, _cbSecret, _fFlags); - } + { + if (const auto _pfnBCryptGenerateSymmetricKey = try_get_BCryptGenerateSymmetricKey()) + { + return _pfnBCryptGenerateSymmetricKey(_hAlgorithm, _phKey, _pKeyObject, _cbKeyObject, _pSecret, _cbSecret, _fFlags); + } if (_fFlags) { @@ -2373,23 +2376,23 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - bcrypt, - 4, - NTSTATUS, + __DEFINE_THUNK( + bcrypt, + 4, + NTSTATUS, WINAPI, BCryptDestroyKey, _Inout_ BCRYPT_KEY_HANDLE _hKey ) - { - if (const auto _pfnBCryptDestroyKey = try_get_BCryptDestroyKey()) - { - return _pfnBCryptDestroyKey(_hKey); - } + { + if (const auto _pfnBCryptDestroyKey = try_get_BCryptDestroyKey()) + { + return _pfnBCryptDestroyKey(_hKey); + } if (!Is(_hKey)) return STATUS_INVALID_HANDLE; @@ -2400,14 +2403,14 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - bcrypt, - 28, - NTSTATUS, + __DEFINE_THUNK( + bcrypt, + 28, + NTSTATUS, WINAPI, BCryptExportKey, _In_ BCRYPT_KEY_HANDLE _hKey, @@ -2418,11 +2421,11 @@ namespace YY::Thunks _Out_ ULONG* _pcbResult, _In_ ULONG _fFlags ) - { - if (const auto _pfnBCryptExportKey = try_get_BCryptExportKey()) - { - return _pfnBCryptExportKey(_hKey, _hExportKey, _szBlobType, _pOutput, _cbOutput, _pcbResult, _fFlags); - } + { + if (const auto _pfnBCryptExportKey = try_get_BCryptExportKey()) + { + return _pfnBCryptExportKey(_hKey, _hExportKey, _szBlobType, _pOutput, _cbOutput, _pcbResult, _fFlags); + } if (!Is(_hKey)) return STATUS_INVALID_HANDLE; @@ -2435,14 +2438,14 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] - __DEFINE_THUNK( - bcrypt, - 36, - NTSTATUS, + __DEFINE_THUNK( + bcrypt, + 36, + NTSTATUS, WINAPI, BCryptImportKey, _In_ BCRYPT_ALG_HANDLE _hAlgorithm, @@ -2455,11 +2458,11 @@ namespace YY::Thunks _In_ ULONG _cbInput, _In_ ULONG _fFlags ) - { - if (const auto _pfnBCryptImportKey = try_get_BCryptImportKey()) - { - return _pfnBCryptImportKey(_hAlgorithm, _hImportKey, _szBlobType, _phKey, _pKeyObject, _cbKeyObject, _pInput, _cbInput, _fFlags); - } + { + if (const auto _pfnBCryptImportKey = try_get_BCryptImportKey()) + { + return _pfnBCryptImportKey(_hAlgorithm, _hImportKey, _szBlobType, _phKey, _pKeyObject, _cbKeyObject, _pInput, _cbInput, _fFlags); + } if (!Is(_hAlgorithm)) return STATUS_INVALID_HANDLE; diff --git a/src/Thunks/bluetoothapis.hpp b/src/Thunks/bluetoothapis.hpp index c45ba12..8e75466 100644 --- a/src/Thunks/bluetoothapis.hpp +++ b/src/Thunks/bluetoothapis.hpp @@ -1,10 +1,10 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) #include #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8及更高版本的 Windows 中受支持。 __DEFINE_THUNK( @@ -37,7 +37,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8及更高版本的 Windows 中受支持。 __DEFINE_THUNK( @@ -67,7 +67,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8及更高版本的 Windows 中受支持。 __DEFINE_THUNK( @@ -97,7 +97,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8及更高版本的 Windows 中受支持。 __DEFINE_THUNK( @@ -126,7 +126,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8及更高版本的 Windows 中受支持。 __DEFINE_THUNK( @@ -154,7 +154,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8及更高版本的 Windows 中受支持。 __DEFINE_THUNK( @@ -180,7 +180,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8及更高版本的 Windows 中受支持。 __DEFINE_THUNK( @@ -205,7 +205,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8及更高版本的 Windows 中受支持。 __DEFINE_THUNK( diff --git a/src/Thunks/d3d11.hpp b/src/Thunks/d3d11.hpp index 43351c1..0a8ead6 100644 --- a/src/Thunks/d3d11.hpp +++ b/src/Thunks/d3d11.hpp @@ -1,10 +1,10 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) #include #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) // Windows 7自带,Vista需要安装KB971644 __DEFINE_THUNK( diff --git a/src/Thunks/d3d12.hpp b/src/Thunks/d3d12.hpp index 04c8c27..4b9c9a8 100644 --- a/src/Thunks/d3d12.hpp +++ b/src/Thunks/d3d12.hpp @@ -1,10 +1,10 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN10) +#if (YY_Thunks_Target < __WindowsNT10_10240) #include #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN10) +#if (YY_Thunks_Target < __WindowsNT10_10240) // Windows 10 __DEFINE_THUNK( diff --git a/src/Thunks/d3d9.hpp b/src/Thunks/d3d9.hpp index 0b9bcbd..c4edb1b 100644 --- a/src/Thunks/d3d9.hpp +++ b/src/Thunks/d3d9.hpp @@ -1,8 +1,10 @@ -#include +#if (YY_Thunks_Target < __WindowsNT6) +#include +#endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) __DEFINE_THUNK( d3d9, diff --git a/src/Thunks/dbghelp.hpp b/src/Thunks/dbghelp.hpp index 1403334..66669e9 100644 --- a/src/Thunks/dbghelp.hpp +++ b/src/Thunks/dbghelp.hpp @@ -1,15 +1,15 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_dbghelp) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_dbghelp) #define __Comment_Lib_dbghelp #pragma comment(lib, "Dbghelp.lib") #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // XP SP3自带的没有W版 __DEFINE_THUNK( @@ -46,7 +46,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // XP SP3自带的没有W版 __DEFINE_THUNK( diff --git a/src/Thunks/dwmapi.hpp b/src/Thunks/dwmapi.hpp index 6aca9bf..552b050 100644 --- a/src/Thunks/dwmapi.hpp +++ b/src/Thunks/dwmapi.hpp @@ -1,11 +1,13 @@ -#include +#if (YY_Thunks_Target < __WindowsNT6) +#include +#endif // 忽略deprecated,因为是Thunks项目肯定是需要调用老接口的。 #pragma warning(disable:4995) namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -30,7 +32,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -59,7 +61,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -93,7 +95,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -121,7 +123,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -148,7 +150,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -177,7 +179,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -207,7 +209,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -238,7 +240,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -260,7 +262,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista // Minimum supported server Windows Server 2008 @@ -284,7 +286,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Windows Vista [desktop apps only] // Windows Server 2008 [desktop apps only] @@ -307,7 +309,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Windows Vista [desktop apps only] // Windows Server 2008 [desktop apps only] @@ -332,7 +334,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Windows Vista [desktop apps only] // Windows Server 2008 [desktop apps only] diff --git a/src/Thunks/dwrite.hpp b/src/Thunks/dwrite.hpp index 8bb9e36..8d1d07b 100644 --- a/src/Thunks/dwrite.hpp +++ b/src/Thunks/dwrite.hpp @@ -1,4 +1,4 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN10) +#if (YY_Thunks_Target < __WindowsNT10_10240) #include #include #endif @@ -6,1146 +6,1149 @@ #if defined(YY_Thunks_Implemented) namespace YY::Thunks::Fallback { -#if (YY_Thunks_Support_Version < NTDDI_WIN10) - class DWriteRenderingParams : public IDWriteRenderingParams3 + namespace { - private: - ULONG uRef = 1; - DWORD uLevel = 0; - union +#if (YY_Thunks_Target < __WindowsNT10_10240) + class DWriteRenderingParams : public IDWriteRenderingParams3 { - IDWriteRenderingParams* pDWriteRenderingParams = nullptr; - IDWriteRenderingParams1* pDWriteRenderingParams1; - IDWriteRenderingParams2* pDWriteRenderingParams2; - IDWriteRenderingParams3* pDWriteRenderingParams3; - }; - FLOAT enhancedContrastGrayscale = 0.0f; - DWRITE_GRID_FIT_MODE eGridFitMode = DWRITE_GRID_FIT_MODE::DWRITE_GRID_FIT_MODE_DEFAULT; - DWRITE_RENDERING_MODE1 eRenderingMode1 = DWRITE_RENDERING_MODE1::DWRITE_RENDERING_MODE1_DEFAULT; - - public: - DWriteRenderingParams(DWORD uLevel, IDWriteRenderingParams* _pDWriteRenderingParams, - FLOAT _EnhancedContrastGrayscale, - DWRITE_GRID_FIT_MODE _eGridFitMode = DWRITE_GRID_FIT_MODE::DWRITE_GRID_FIT_MODE_DEFAULT, - DWRITE_RENDERING_MODE1 _eRenderingMode1 = DWRITE_RENDERING_MODE1::DWRITE_RENDERING_MODE1_DEFAULT) - : uLevel(uLevel) - , pDWriteRenderingParams(_pDWriteRenderingParams) - , enhancedContrastGrayscale(_EnhancedContrastGrayscale) - , eGridFitMode(_eGridFitMode) - { - pDWriteRenderingParams->AddRef(); - } - - DWriteRenderingParams(IDWriteRenderingParams1* _pDWriteRenderingParams, - DWRITE_GRID_FIT_MODE _eGridFitMode, - DWRITE_RENDERING_MODE1 _eRenderingMode1 = DWRITE_RENDERING_MODE1::DWRITE_RENDERING_MODE1_DEFAULT) - : uLevel(1) - , pDWriteRenderingParams1(_pDWriteRenderingParams) - , eGridFitMode(_eGridFitMode) - { - pDWriteRenderingParams->AddRef(); - } - - DWriteRenderingParams(IDWriteRenderingParams2* _pDWriteRenderingParams, DWRITE_RENDERING_MODE1 _eRenderingMode1) - : uLevel(2) - , pDWriteRenderingParams2(_pDWriteRenderingParams) - , eRenderingMode1(_eRenderingMode1) - { - pDWriteRenderingParams->AddRef(); - } + private: + ULONG uRef = 1; + DWORD uLevel = 0; + union + { + IDWriteRenderingParams* pDWriteRenderingParams = nullptr; + IDWriteRenderingParams1* pDWriteRenderingParams1; + IDWriteRenderingParams2* pDWriteRenderingParams2; + IDWriteRenderingParams3* pDWriteRenderingParams3; + }; + FLOAT enhancedContrastGrayscale = 0.0f; + DWRITE_GRID_FIT_MODE eGridFitMode = DWRITE_GRID_FIT_MODE::DWRITE_GRID_FIT_MODE_DEFAULT; + DWRITE_RENDERING_MODE1 eRenderingMode1 = DWRITE_RENDERING_MODE1::DWRITE_RENDERING_MODE1_DEFAULT; + + public: + DWriteRenderingParams(DWORD uLevel, IDWriteRenderingParams* _pDWriteRenderingParams, + FLOAT _EnhancedContrastGrayscale, + DWRITE_GRID_FIT_MODE _eGridFitMode = DWRITE_GRID_FIT_MODE::DWRITE_GRID_FIT_MODE_DEFAULT, + DWRITE_RENDERING_MODE1 _eRenderingMode1 = DWRITE_RENDERING_MODE1::DWRITE_RENDERING_MODE1_DEFAULT) + : uLevel(uLevel) + , pDWriteRenderingParams(_pDWriteRenderingParams) + , enhancedContrastGrayscale(_EnhancedContrastGrayscale) + , eGridFitMode(_eGridFitMode) + { + pDWriteRenderingParams->AddRef(); + } - DWriteRenderingParams(const DWriteRenderingParams&) = delete; + DWriteRenderingParams(IDWriteRenderingParams1* _pDWriteRenderingParams, + DWRITE_GRID_FIT_MODE _eGridFitMode, + DWRITE_RENDERING_MODE1 _eRenderingMode1 = DWRITE_RENDERING_MODE1::DWRITE_RENDERING_MODE1_DEFAULT) + : uLevel(1) + , pDWriteRenderingParams1(_pDWriteRenderingParams) + , eGridFitMode(_eGridFitMode) + { + pDWriteRenderingParams->AddRef(); + } - ~DWriteRenderingParams() - { - pDWriteRenderingParams->Release(); - } + DWriteRenderingParams(IDWriteRenderingParams2* _pDWriteRenderingParams, DWRITE_RENDERING_MODE1 _eRenderingMode1) + : uLevel(2) + , pDWriteRenderingParams2(_pDWriteRenderingParams) + , eRenderingMode1(_eRenderingMode1) + { + pDWriteRenderingParams->AddRef(); + } - //////////////////////////////////////////////////////// - // IUnknown - HRESULT STDMETHODCALLTYPE QueryInterface( - /* [in] */ REFIID riid, - /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) override - { - if (!ppvObject) - return E_POINTER; + DWriteRenderingParams(const DWriteRenderingParams&) = delete; - *ppvObject = nullptr; - if (riid == __uuidof(IUnknown) - || riid == __uuidof(IDWriteRenderingParams) - || riid == __uuidof(IDWriteRenderingParams1) - || riid == __uuidof(IDWriteRenderingParams2) - || riid == __uuidof(IDWriteRenderingParams3)) + ~DWriteRenderingParams() { - AddRef(); - *ppvObject = this; - return S_OK; + pDWriteRenderingParams->Release(); } - else + + //////////////////////////////////////////////////////// + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface( + /* [in] */ REFIID riid, + /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) override { - return E_NOINTERFACE; - } - } + if (!ppvObject) + return E_POINTER; - ULONG STDMETHODCALLTYPE AddRef(void) override - { - return InterlockedIncrement(&uRef); - } + *ppvObject = nullptr; + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDWriteRenderingParams) + || riid == __uuidof(IDWriteRenderingParams1) + || riid == __uuidof(IDWriteRenderingParams2) + || riid == __uuidof(IDWriteRenderingParams3)) + { + AddRef(); + *ppvObject = this; + return S_OK; + } + else + { + return E_NOINTERFACE; + } + } - ULONG STDMETHODCALLTYPE Release(void) override - { - const auto _uNewRef = InterlockedDecrement(&uRef); - if (_uNewRef == 0) + ULONG STDMETHODCALLTYPE AddRef(void) override { - internal::Delete(this); + return InterlockedIncrement(&uRef); } - return _uNewRef; - } - ///////////////////////////////////////////////////////// - // IDWriteRenderingParams - STDMETHOD_(FLOAT, GetGamma)() override - { - return pDWriteRenderingParams->GetGamma(); - } + ULONG STDMETHODCALLTYPE Release(void) override + { + const auto _uNewRef = InterlockedDecrement(&uRef); + if (_uNewRef == 0) + { + internal::Delete(this); + } + return _uNewRef; + } - STDMETHOD_(FLOAT, GetEnhancedContrast)() override - { - return pDWriteRenderingParams->GetEnhancedContrast(); - } + ///////////////////////////////////////////////////////// + // IDWriteRenderingParams + STDMETHOD_(FLOAT, GetGamma)() override + { + return pDWriteRenderingParams->GetGamma(); + } - STDMETHOD_(FLOAT, GetClearTypeLevel)() override - { - return pDWriteRenderingParams->GetEnhancedContrast(); - } + STDMETHOD_(FLOAT, GetEnhancedContrast)() override + { + return pDWriteRenderingParams->GetEnhancedContrast(); + } - STDMETHOD_(DWRITE_PIXEL_GEOMETRY, GetPixelGeometry)() override - { - return pDWriteRenderingParams->GetPixelGeometry(); - } + STDMETHOD_(FLOAT, GetClearTypeLevel)() override + { + return pDWriteRenderingParams->GetEnhancedContrast(); + } - STDMETHOD_(DWRITE_RENDERING_MODE, GetRenderingMode)() override - { - return pDWriteRenderingParams->GetRenderingMode(); - } + STDMETHOD_(DWRITE_PIXEL_GEOMETRY, GetPixelGeometry)() override + { + return pDWriteRenderingParams->GetPixelGeometry(); + } - ///////////////////////////////////////////////////////// - // IDWriteRenderingParams1 - STDMETHOD_(FLOAT, GetGrayscaleEnhancedContrast)() override - { - if (uLevel >= 1) + STDMETHOD_(DWRITE_RENDERING_MODE, GetRenderingMode)() override { - return pDWriteRenderingParams1->GetGrayscaleEnhancedContrast(); + return pDWriteRenderingParams->GetRenderingMode(); } - return enhancedContrastGrayscale; - } - ///////////////////////////////////////////////////////// - // IDWriteRenderingParams2 - STDMETHOD_(DWRITE_GRID_FIT_MODE, GetGridFitMode)() override - { - if (uLevel >= 2) + ///////////////////////////////////////////////////////// + // IDWriteRenderingParams1 + STDMETHOD_(FLOAT, GetGrayscaleEnhancedContrast)() override { - return pDWriteRenderingParams2->GetGridFitMode(); + if (uLevel >= 1) + { + return pDWriteRenderingParams1->GetGrayscaleEnhancedContrast(); + } + return enhancedContrastGrayscale; } - return eGridFitMode; - } - ///////////////////////////////////////////////////////// - // IDWriteRenderingParams3 - STDMETHOD_(DWRITE_RENDERING_MODE1, GetRenderingMode1)() override - { - if (uLevel >= 3) + ///////////////////////////////////////////////////////// + // IDWriteRenderingParams2 + STDMETHOD_(DWRITE_GRID_FIT_MODE, GetGridFitMode)() override { - return pDWriteRenderingParams3->GetRenderingMode1(); + if (uLevel >= 2) + { + return pDWriteRenderingParams2->GetGridFitMode(); + } + return eGridFitMode; } - return eRenderingMode1; - } - }; + ///////////////////////////////////////////////////////// + // IDWriteRenderingParams3 + STDMETHOD_(DWRITE_RENDERING_MODE1, GetRenderingMode1)() override + { + if (uLevel >= 3) + { + return pDWriteRenderingParams3->GetRenderingMode1(); + } - class DWriteFontCollection : public IDWriteFontCollection1 - { - private: - ULONG uRef = 1; - DWORD uLevel = 0; - union - { - IDWriteFontCollection* pFontCollection = nullptr; - IDWriteFontCollection1* pFontCollection1; + return eRenderingMode1; + } }; - public: - DWriteFontCollection(_In_opt_ IDWriteFontCollection* _pFontCollection = nullptr, DWORD _uLevel = 0) - : uLevel(_uLevel) - , pFontCollection(_pFontCollection) + class DWriteFontCollection : public IDWriteFontCollection1 { - if(pFontCollection) - pFontCollection->AddRef(); - } + private: + ULONG uRef = 1; + DWORD uLevel = 0; + union + { + IDWriteFontCollection* pFontCollection = nullptr; + IDWriteFontCollection1* pFontCollection1; + }; - DWriteFontCollection(const DWriteFontCollection&) = delete; + public: + DWriteFontCollection(_In_opt_ IDWriteFontCollection* _pFontCollection = nullptr, DWORD _uLevel = 0) + : uLevel(_uLevel) + , pFontCollection(_pFontCollection) + { + if(pFontCollection) + pFontCollection->AddRef(); + } - ~DWriteFontCollection() - { - if(pFontCollection) - pFontCollection->Release(); - } + DWriteFontCollection(const DWriteFontCollection&) = delete; - //////////////////////////////////////////////////////// - // IUnknown - HRESULT STDMETHODCALLTYPE QueryInterface( - /* [in] */ REFIID riid, - /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) override - { - if (!ppvObject) - return E_POINTER; - - *ppvObject = nullptr; - if (riid == __uuidof(IUnknown) - || riid == __uuidof(IDWriteFontCollection) - || riid == __uuidof(IDWriteFontCollection1)) + ~DWriteFontCollection() { - AddRef(); - *ppvObject = this; - return S_OK; + if(pFontCollection) + pFontCollection->Release(); } - else if (pFontCollection) + + //////////////////////////////////////////////////////// + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface( + /* [in] */ REFIID riid, + /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) override { - return pFontCollection->QueryInterface(riid, ppvObject); + if (!ppvObject) + return E_POINTER; + + *ppvObject = nullptr; + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDWriteFontCollection) + || riid == __uuidof(IDWriteFontCollection1)) + { + AddRef(); + *ppvObject = this; + return S_OK; + } + else if (pFontCollection) + { + return pFontCollection->QueryInterface(riid, ppvObject); + } + else + { + return E_NOINTERFACE; + } } - else + + ULONG STDMETHODCALLTYPE AddRef(void) override { - return E_NOINTERFACE; + return InterlockedIncrement(&uRef); } - } - ULONG STDMETHODCALLTYPE AddRef(void) override - { - return InterlockedIncrement(&uRef); - } - - ULONG STDMETHODCALLTYPE Release(void) override - { - const auto _uNewRef = InterlockedDecrement(&uRef); - if (_uNewRef == 0) + ULONG STDMETHODCALLTYPE Release(void) override { - internal::Delete(this); + const auto _uNewRef = InterlockedDecrement(&uRef); + if (_uNewRef == 0) + { + internal::Delete(this); + } + return _uNewRef; } - return _uNewRef; - } - - /////////////////////////////////////////////// - // IDWriteFontCollection - STDMETHOD_(UINT32, GetFontFamilyCount)() override - { - return pFontCollection ? pFontCollection->GetFontFamilyCount() : 0u; - } - STDMETHOD(GetFontFamily)( - UINT32 index, - _COM_Outptr_ IDWriteFontFamily** fontFamily - ) override - { - if (pFontCollection) + /////////////////////////////////////////////// + // IDWriteFontCollection + STDMETHOD_(UINT32, GetFontFamilyCount)() override { - return pFontCollection->GetFontFamily(index, fontFamily); + return pFontCollection ? pFontCollection->GetFontFamilyCount() : 0u; } - if (fontFamily) - *fontFamily = nullptr; - - return E_INVALIDARG; - } - - STDMETHOD(FindFamilyName)( - _In_z_ WCHAR const* familyName, - _Out_ UINT32* index, - _Out_ BOOL* exists - ) override - { - if (pFontCollection) + STDMETHOD(GetFontFamily)( + UINT32 index, + _COM_Outptr_ IDWriteFontFamily** fontFamily + ) override { - return pFontCollection->FindFamilyName(familyName, index, exists); - } + if (pFontCollection) + { + return pFontCollection->GetFontFamily(index, fontFamily); + } - if (index == nullptr || exists == nullptr) + if (fontFamily) + *fontFamily = nullptr; + return E_INVALIDARG; + } - *index = UINT_MAX; - *exists = FALSE; - return S_OK; - } - - STDMETHOD(GetFontFromFontFace)( - _In_ IDWriteFontFace* fontFace, - _COM_Outptr_ IDWriteFont** font - ) override - { - if (pFontCollection) + STDMETHOD(FindFamilyName)( + _In_z_ WCHAR const* familyName, + _Out_ UINT32* index, + _Out_ BOOL* exists + ) override { - return pFontCollection->GetFontFromFontFace(fontFace, font); - } + if (pFontCollection) + { + return pFontCollection->FindFamilyName(familyName, index, exists); + } - if (!font) - return E_NOINTERFACE; + if (index == nullptr || exists == nullptr) + return E_INVALIDARG; - *font = nullptr; - return E_NOT_SET; - } + *index = UINT_MAX; + *exists = FALSE; + return S_OK; + } - /////////////////////////////////////////////// - // IDWriteFontCollection1 - STDMETHOD(GetFontSet)( - _COM_Outptr_ IDWriteFontSet** fontSet - ) override - { - if (pFontCollection) + STDMETHOD(GetFontFromFontFace)( + _In_ IDWriteFontFace* fontFace, + _COM_Outptr_ IDWriteFont** font + ) override { - if (uLevel >= 1) + if (pFontCollection) { - return pFontCollection1->GetFontSet(fontSet); + return pFontCollection->GetFontFromFontFace(fontFace, font); } - } - if (!fontSet) - return E_NOINTERFACE; + if (!font) + return E_NOINTERFACE; - *fontSet = nullptr; - return E_NOTIMPL; - } + *font = nullptr; + return E_NOT_SET; + } - STDMETHOD(GetFontFamily)( - UINT32 index, - _COM_Outptr_ IDWriteFontFamily1** fontFamily - ) override - { - if (pFontCollection) + /////////////////////////////////////////////// + // IDWriteFontCollection1 + STDMETHOD(GetFontSet)( + _COM_Outptr_ IDWriteFontSet** fontSet + ) override { - if (uLevel >= 1) + if (pFontCollection) { - return pFontCollection1->GetFontFamily(index, fontFamily); + if (uLevel >= 1) + { + return pFontCollection1->GetFontSet(fontSet); + } } - } - if (!fontFamily) - return E_NOINTERFACE; + if (!fontSet) + return E_NOINTERFACE; - *fontFamily = nullptr; - return E_NOTIMPL; - } + *fontSet = nullptr; + return E_NOTIMPL; + } - using IDWriteFontCollection::GetFontFamily; - }; + STDMETHOD(GetFontFamily)( + UINT32 index, + _COM_Outptr_ IDWriteFontFamily1** fontFamily + ) override + { + if (pFontCollection) + { + if (uLevel >= 1) + { + return pFontCollection1->GetFontFamily(index, fontFamily); + } + } - class DWriteFontFallback : public IDWriteFontFallback - { - private: - ULONG uRef = 1; - DWORD uLevel = 0; - IDWriteFontFallback* pFontFallback = nullptr; + if (!fontFamily) + return E_NOINTERFACE; - public: - DWriteFontFallback() = default; + *fontFamily = nullptr; + return E_NOTIMPL; + } - DWriteFontFallback(const DWriteFontFallback&) = delete; + using IDWriteFontCollection::GetFontFamily; + }; - ~DWriteFontFallback() + class DWriteFontFallback : public IDWriteFontFallback { - if (pFontFallback) - pFontFallback->Release(); - } + private: + ULONG uRef = 1; + DWORD uLevel = 0; + IDWriteFontFallback* pFontFallback = nullptr; - //////////////////////////////////////////////////////// - // IUnknown - HRESULT STDMETHODCALLTYPE QueryInterface( - /* [in] */ REFIID riid, - /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) override - { - if (!ppvObject) - return E_POINTER; + public: + DWriteFontFallback() = default; - *ppvObject = nullptr; - if (riid == __uuidof(IUnknown) - || riid == __uuidof(IDWriteFontFallback)) + DWriteFontFallback(const DWriteFontFallback&) = delete; + + ~DWriteFontFallback() { - AddRef(); - *ppvObject = this; - return S_OK; + if (pFontFallback) + pFontFallback->Release(); } - else if (pFontFallback) + + //////////////////////////////////////////////////////// + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface( + /* [in] */ REFIID riid, + /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) override { - return pFontFallback->QueryInterface(riid, ppvObject); + if (!ppvObject) + return E_POINTER; + + *ppvObject = nullptr; + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDWriteFontFallback)) + { + AddRef(); + *ppvObject = this; + return S_OK; + } + else if (pFontFallback) + { + return pFontFallback->QueryInterface(riid, ppvObject); + } + else + { + return E_NOINTERFACE; + } } - else + + ULONG STDMETHODCALLTYPE AddRef(void) override { - return E_NOINTERFACE; + return InterlockedIncrement(&uRef); } - } - ULONG STDMETHODCALLTYPE AddRef(void) override - { - return InterlockedIncrement(&uRef); - } - - ULONG STDMETHODCALLTYPE Release(void) override - { - const auto _uNewRef = InterlockedDecrement(&uRef); - if (_uNewRef == 0) + ULONG STDMETHODCALLTYPE Release(void) override { - internal::Delete(this); + const auto _uNewRef = InterlockedDecrement(&uRef); + if (_uNewRef == 0) + { + internal::Delete(this); + } + return _uNewRef; } - return _uNewRef; - } - //////////////////////////////////////////////////////// - // IDWriteFontFallback - STDMETHOD(MapCharacters)( - IDWriteTextAnalysisSource* analysisSource, - UINT32 textPosition, - UINT32 textLength, - _In_opt_ IDWriteFontCollection* baseFontCollection, - _In_opt_z_ wchar_t const* baseFamilyName, - DWRITE_FONT_WEIGHT baseWeight, - DWRITE_FONT_STYLE baseStyle, - DWRITE_FONT_STRETCH baseStretch, - _Out_range_(0, textLength) UINT32* mappedLength, - _COM_Outptr_result_maybenull_ IDWriteFont** mappedFont, - _Out_ FLOAT* scale - ) override - { - if (pFontFallback) - { - return pFontFallback->MapCharacters( - analysisSource, - textPosition, - textLength, - baseFontCollection, - baseFamilyName, - baseWeight, - baseStyle, - baseStretch, - mappedLength, - mappedFont, - scale); - } - - if (!mappedFont) - return E_NOINTERFACE; - - if (mappedLength == nullptr || scale == nullptr) - return E_NOINTERFACE; - - // 假装没有字体需要呈现 - *mappedLength = 0; - *scale = 1.0; - *mappedFont = nullptr; - return S_OK; - } - }; - - class DWriteFactory : public IDWriteFactory3 - { - private: - ULONG uRef = 1; - DWORD uLevel = 0; - union - { - IDWriteFactory* pDWriteFactory = nullptr; - IDWriteFactory1* pDWriteFactory1; - IDWriteFactory2* pDWriteFactory2; - IDWriteFactory3* pDWriteFactory3; - }; + //////////////////////////////////////////////////////// + // IDWriteFontFallback + STDMETHOD(MapCharacters)( + IDWriteTextAnalysisSource* analysisSource, + UINT32 textPosition, + UINT32 textLength, + _In_opt_ IDWriteFontCollection* baseFontCollection, + _In_opt_z_ wchar_t const* baseFamilyName, + DWRITE_FONT_WEIGHT baseWeight, + DWRITE_FONT_STYLE baseStyle, + DWRITE_FONT_STRETCH baseStretch, + _Out_range_(0, textLength) UINT32* mappedLength, + _COM_Outptr_result_maybenull_ IDWriteFont** mappedFont, + _Out_ FLOAT* scale + ) override + { + if (pFontFallback) + { + return pFontFallback->MapCharacters( + analysisSource, + textPosition, + textLength, + baseFontCollection, + baseFamilyName, + baseWeight, + baseStyle, + baseStretch, + mappedLength, + mappedFont, + scale); + } - public: - DWriteFactory(IDWriteFactory* _pDWriteFactory, DWORD _uLevel = 0) - : uLevel(_uLevel) - , pDWriteFactory(_pDWriteFactory) - { - pDWriteFactory->AddRef(); - } + if (!mappedFont) + return E_NOINTERFACE; - DWriteFactory(const DWriteFactory&) = delete; + if (mappedLength == nullptr || scale == nullptr) + return E_NOINTERFACE; - ~DWriteFactory() - { - pDWriteFactory->Release(); - } + // 假装没有字体需要呈现 + *mappedLength = 0; + *scale = 1.0; + *mappedFont = nullptr; + return S_OK; + } + }; - //////////////////////////////////////////////////////// - // IUnknown - HRESULT STDMETHODCALLTYPE QueryInterface( - /* [in] */ REFIID riid, - /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) override + class DWriteFactory : public IDWriteFactory3 { - if (riid == __uuidof(IUnknown) - || riid == __uuidof(IDWriteFactory) - || riid == __uuidof(IDWriteFactory1) - || riid == __uuidof(IDWriteFactory2) - || riid == __uuidof(IDWriteFactory3)) + private: + ULONG uRef = 1; + DWORD uLevel = 0; + union { - if (!ppvObject) - return E_POINTER; - - *ppvObject = nullptr; + IDWriteFactory* pDWriteFactory = nullptr; + IDWriteFactory1* pDWriteFactory1; + IDWriteFactory2* pDWriteFactory2; + IDWriteFactory3* pDWriteFactory3; + }; - AddRef(); - *ppvObject = this; - return S_OK; - } - else + public: + DWriteFactory(IDWriteFactory* _pDWriteFactory, DWORD _uLevel = 0) + : uLevel(_uLevel) + , pDWriteFactory(_pDWriteFactory) { - return pDWriteFactory->QueryInterface(riid, ppvObject); + pDWriteFactory->AddRef(); } - } - ULONG STDMETHODCALLTYPE AddRef(void) override - { - return InterlockedIncrement(&uRef); - } + DWriteFactory(const DWriteFactory&) = delete; - ULONG STDMETHODCALLTYPE Release(void) override - { - const auto _uNewRef = InterlockedDecrement(&uRef); - if (_uNewRef == 0) + ~DWriteFactory() { - internal::Delete(this); + pDWriteFactory->Release(); } - return _uNewRef; - } - - //////////////////////////////////////////////////////// - // IDWriteFactory - - STDMETHOD(GetSystemFontCollection)( - _COM_Outptr_ IDWriteFontCollection** fontCollection, - BOOL checkForUpdates = FALSE - ) override - { - return pDWriteFactory->GetSystemFontCollection(fontCollection, checkForUpdates); - } + //////////////////////////////////////////////////////// + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface( + /* [in] */ REFIID riid, + /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) override + { + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDWriteFactory) + || riid == __uuidof(IDWriteFactory1) + || riid == __uuidof(IDWriteFactory2) + || riid == __uuidof(IDWriteFactory3)) + { + if (!ppvObject) + return E_POINTER; - STDMETHOD(CreateCustomFontCollection)( - _In_ IDWriteFontCollectionLoader* collectionLoader, - _In_reads_bytes_(collectionKeySize) void const* collectionKey, - UINT32 collectionKeySize, - _COM_Outptr_ IDWriteFontCollection** fontCollection - ) override - { - return pDWriteFactory->CreateCustomFontCollection(collectionLoader, collectionKey, collectionKeySize, fontCollection); - } + *ppvObject = nullptr; - STDMETHOD(RegisterFontCollectionLoader)( - _In_ IDWriteFontCollectionLoader* fontCollectionLoader - ) override - { - return pDWriteFactory->RegisterFontCollectionLoader(fontCollectionLoader); - } + AddRef(); + *ppvObject = this; + return S_OK; + } + else + { + return pDWriteFactory->QueryInterface(riid, ppvObject); + } + } - STDMETHOD(UnregisterFontCollectionLoader)( - _In_ IDWriteFontCollectionLoader* fontCollectionLoader - ) override - { - return pDWriteFactory->UnregisterFontCollectionLoader(fontCollectionLoader); - } + ULONG STDMETHODCALLTYPE AddRef(void) override + { + return InterlockedIncrement(&uRef); + } - STDMETHOD(CreateFontFileReference)( - _In_z_ WCHAR const* filePath, - _In_opt_ FILETIME const* lastWriteTime, - _COM_Outptr_ IDWriteFontFile** fontFile - ) override - { - return pDWriteFactory->CreateFontFileReference(filePath, lastWriteTime, fontFile); - } + ULONG STDMETHODCALLTYPE Release(void) override + { + const auto _uNewRef = InterlockedDecrement(&uRef); + if (_uNewRef == 0) + { + internal::Delete(this); + } + return _uNewRef; + } - STDMETHOD(CreateCustomFontFileReference)( - _In_reads_bytes_(fontFileReferenceKeySize) void const* fontFileReferenceKey, - UINT32 fontFileReferenceKeySize, - _In_ IDWriteFontFileLoader* fontFileLoader, - _COM_Outptr_ IDWriteFontFile** fontFile - ) override - { - return pDWriteFactory->CreateCustomFontFileReference(fontFileReferenceKey, fontFileReferenceKeySize, fontFileLoader, fontFile); - } + //////////////////////////////////////////////////////// + // IDWriteFactory - STDMETHOD(CreateFontFace)( - DWRITE_FONT_FACE_TYPE fontFaceType, - UINT32 numberOfFiles, - _In_reads_(numberOfFiles) IDWriteFontFile* const* fontFiles, - UINT32 faceIndex, - DWRITE_FONT_SIMULATIONS fontFaceSimulationFlags, - _COM_Outptr_ IDWriteFontFace** fontFace - ) override - { - return pDWriteFactory->CreateFontFace(fontFaceType, numberOfFiles, fontFiles, faceIndex, fontFaceSimulationFlags, fontFace); - } + STDMETHOD(GetSystemFontCollection)( + _COM_Outptr_ IDWriteFontCollection** fontCollection, + BOOL checkForUpdates = FALSE + ) override + { + return pDWriteFactory->GetSystemFontCollection(fontCollection, checkForUpdates); + } - STDMETHOD(CreateRenderingParams)( - _COM_Outptr_ IDWriteRenderingParams** renderingParams - ) override - { - return pDWriteFactory->CreateRenderingParams(renderingParams); - } - STDMETHOD(CreateMonitorRenderingParams)( - HMONITOR monitor, - _COM_Outptr_ IDWriteRenderingParams** renderingParams - ) override - { - return pDWriteFactory->CreateMonitorRenderingParams(monitor, renderingParams); - } + STDMETHOD(CreateCustomFontCollection)( + _In_ IDWriteFontCollectionLoader* collectionLoader, + _In_reads_bytes_(collectionKeySize) void const* collectionKey, + UINT32 collectionKeySize, + _COM_Outptr_ IDWriteFontCollection** fontCollection + ) override + { + return pDWriteFactory->CreateCustomFontCollection(collectionLoader, collectionKey, collectionKeySize, fontCollection); + } - STDMETHOD(CreateCustomRenderingParams)( - FLOAT gamma, - FLOAT enhancedContrast, - FLOAT clearTypeLevel, - DWRITE_PIXEL_GEOMETRY pixelGeometry, - DWRITE_RENDERING_MODE renderingMode, - _COM_Outptr_ IDWriteRenderingParams** renderingParams - ) override - { - return pDWriteFactory->CreateCustomRenderingParams(gamma, enhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, renderingParams); - } + STDMETHOD(RegisterFontCollectionLoader)( + _In_ IDWriteFontCollectionLoader* fontCollectionLoader + ) override + { + return pDWriteFactory->RegisterFontCollectionLoader(fontCollectionLoader); + } - STDMETHOD(RegisterFontFileLoader)( - _In_ IDWriteFontFileLoader* fontFileLoader - ) override - { - return pDWriteFactory->RegisterFontFileLoader(fontFileLoader); - } + STDMETHOD(UnregisterFontCollectionLoader)( + _In_ IDWriteFontCollectionLoader* fontCollectionLoader + ) override + { + return pDWriteFactory->UnregisterFontCollectionLoader(fontCollectionLoader); + } - STDMETHOD(UnregisterFontFileLoader)( - _In_ IDWriteFontFileLoader* fontFileLoader - ) override - { - return pDWriteFactory->UnregisterFontFileLoader(fontFileLoader); - } + STDMETHOD(CreateFontFileReference)( + _In_z_ WCHAR const* filePath, + _In_opt_ FILETIME const* lastWriteTime, + _COM_Outptr_ IDWriteFontFile** fontFile + ) override + { + return pDWriteFactory->CreateFontFileReference(filePath, lastWriteTime, fontFile); + } - STDMETHOD(CreateTextFormat)( - _In_z_ WCHAR const* fontFamilyName, - _In_opt_ IDWriteFontCollection* fontCollection, - DWRITE_FONT_WEIGHT fontWeight, - DWRITE_FONT_STYLE fontStyle, - DWRITE_FONT_STRETCH fontStretch, - FLOAT fontSize, - _In_z_ WCHAR const* localeName, - _COM_Outptr_ IDWriteTextFormat** textFormat - ) override - { - return pDWriteFactory->CreateTextFormat(fontFamilyName, fontCollection, fontWeight, fontStyle, fontStretch, fontSize, localeName, textFormat); - } + STDMETHOD(CreateCustomFontFileReference)( + _In_reads_bytes_(fontFileReferenceKeySize) void const* fontFileReferenceKey, + UINT32 fontFileReferenceKeySize, + _In_ IDWriteFontFileLoader* fontFileLoader, + _COM_Outptr_ IDWriteFontFile** fontFile + ) override + { + return pDWriteFactory->CreateCustomFontFileReference(fontFileReferenceKey, fontFileReferenceKeySize, fontFileLoader, fontFile); + } - STDMETHOD(CreateTypography)( - _COM_Outptr_ IDWriteTypography** typography - ) override - { - return pDWriteFactory->CreateTypography(typography); - } + STDMETHOD(CreateFontFace)( + DWRITE_FONT_FACE_TYPE fontFaceType, + UINT32 numberOfFiles, + _In_reads_(numberOfFiles) IDWriteFontFile* const* fontFiles, + UINT32 faceIndex, + DWRITE_FONT_SIMULATIONS fontFaceSimulationFlags, + _COM_Outptr_ IDWriteFontFace** fontFace + ) override + { + return pDWriteFactory->CreateFontFace(fontFaceType, numberOfFiles, fontFiles, faceIndex, fontFaceSimulationFlags, fontFace); + } - STDMETHOD(GetGdiInterop)( - _COM_Outptr_ IDWriteGdiInterop** gdiInterop - ) override - { - return pDWriteFactory->GetGdiInterop(gdiInterop); - } + STDMETHOD(CreateRenderingParams)( + _COM_Outptr_ IDWriteRenderingParams** renderingParams + ) override + { + return pDWriteFactory->CreateRenderingParams(renderingParams); + } - STDMETHOD(CreateTextLayout)( - _In_reads_(stringLength) WCHAR const* string, - UINT32 stringLength, - _In_ IDWriteTextFormat* textFormat, - FLOAT maxWidth, - FLOAT maxHeight, - _COM_Outptr_ IDWriteTextLayout** textLayout - ) override - { - return pDWriteFactory->CreateTextLayout(string, stringLength, textFormat, maxWidth, maxHeight, textLayout); - } + STDMETHOD(CreateMonitorRenderingParams)( + HMONITOR monitor, + _COM_Outptr_ IDWriteRenderingParams** renderingParams + ) override + { + return pDWriteFactory->CreateMonitorRenderingParams(monitor, renderingParams); + } - STDMETHOD(CreateGdiCompatibleTextLayout)( - _In_reads_(stringLength) WCHAR const* string, - UINT32 stringLength, - _In_ IDWriteTextFormat* textFormat, - FLOAT layoutWidth, - FLOAT layoutHeight, - FLOAT pixelsPerDip, - _In_opt_ DWRITE_MATRIX const* transform, - BOOL useGdiNatural, - _COM_Outptr_ IDWriteTextLayout** textLayout - ) override - { - return pDWriteFactory->CreateGdiCompatibleTextLayout(string, stringLength, textFormat, layoutWidth, layoutHeight, pixelsPerDip, transform, useGdiNatural, textLayout); - } + STDMETHOD(CreateCustomRenderingParams)( + FLOAT gamma, + FLOAT enhancedContrast, + FLOAT clearTypeLevel, + DWRITE_PIXEL_GEOMETRY pixelGeometry, + DWRITE_RENDERING_MODE renderingMode, + _COM_Outptr_ IDWriteRenderingParams** renderingParams + ) override + { + return pDWriteFactory->CreateCustomRenderingParams(gamma, enhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, renderingParams); + } - STDMETHOD(CreateEllipsisTrimmingSign)( - _In_ IDWriteTextFormat* textFormat, - _COM_Outptr_ IDWriteInlineObject** trimmingSign - ) override - { - return pDWriteFactory->CreateEllipsisTrimmingSign(textFormat, trimmingSign); - } + STDMETHOD(RegisterFontFileLoader)( + _In_ IDWriteFontFileLoader* fontFileLoader + ) override + { + return pDWriteFactory->RegisterFontFileLoader(fontFileLoader); + } - STDMETHOD(CreateTextAnalyzer)( - _COM_Outptr_ IDWriteTextAnalyzer** textAnalyzer - ) override - { - return pDWriteFactory->CreateTextAnalyzer(textAnalyzer); - } + STDMETHOD(UnregisterFontFileLoader)( + _In_ IDWriteFontFileLoader* fontFileLoader + ) override + { + return pDWriteFactory->UnregisterFontFileLoader(fontFileLoader); + } - STDMETHOD(CreateNumberSubstitution)( - _In_ DWRITE_NUMBER_SUBSTITUTION_METHOD substitutionMethod, - _In_z_ WCHAR const* localeName, - _In_ BOOL ignoreUserOverride, - _COM_Outptr_ IDWriteNumberSubstitution** numberSubstitution - ) override - { - return pDWriteFactory->CreateNumberSubstitution(substitutionMethod, localeName, ignoreUserOverride, numberSubstitution); - } + STDMETHOD(CreateTextFormat)( + _In_z_ WCHAR const* fontFamilyName, + _In_opt_ IDWriteFontCollection* fontCollection, + DWRITE_FONT_WEIGHT fontWeight, + DWRITE_FONT_STYLE fontStyle, + DWRITE_FONT_STRETCH fontStretch, + FLOAT fontSize, + _In_z_ WCHAR const* localeName, + _COM_Outptr_ IDWriteTextFormat** textFormat + ) override + { + return pDWriteFactory->CreateTextFormat(fontFamilyName, fontCollection, fontWeight, fontStyle, fontStretch, fontSize, localeName, textFormat); + } - STDMETHOD(CreateGlyphRunAnalysis)( - _In_ DWRITE_GLYPH_RUN const* glyphRun, - FLOAT pixelsPerDip, - _In_opt_ DWRITE_MATRIX const* transform, - DWRITE_RENDERING_MODE renderingMode, - DWRITE_MEASURING_MODE measuringMode, - FLOAT baselineOriginX, - FLOAT baselineOriginY, - _COM_Outptr_ IDWriteGlyphRunAnalysis** glyphRunAnalysis - ) override - { - return pDWriteFactory->CreateGlyphRunAnalysis(glyphRun, pixelsPerDip, transform, renderingMode, measuringMode, baselineOriginX, baselineOriginY, glyphRunAnalysis); - } + STDMETHOD(CreateTypography)( + _COM_Outptr_ IDWriteTypography** typography + ) override + { + return pDWriteFactory->CreateTypography(typography); + } - - //////////////////////////////////////////////////////// - // IDWriteFactory1 - STDMETHOD(GetEudcFontCollection)( - _COM_Outptr_ IDWriteFontCollection** fontCollection, - BOOL checkForUpdates = FALSE - ) override - { - if (uLevel >= 1) + STDMETHOD(GetGdiInterop)( + _COM_Outptr_ IDWriteGdiInterop** gdiInterop + ) override { - return pDWriteFactory1->GetEudcFontCollection(fontCollection, checkForUpdates); + return pDWriteFactory->GetGdiInterop(gdiInterop); } - // 假装没有安装 Eudc字体 + STDMETHOD(CreateTextLayout)( + _In_reads_(stringLength) WCHAR const* string, + UINT32 stringLength, + _In_ IDWriteTextFormat* textFormat, + FLOAT maxWidth, + FLOAT maxHeight, + _COM_Outptr_ IDWriteTextLayout** textLayout + ) override + { + return pDWriteFactory->CreateTextLayout(string, stringLength, textFormat, maxWidth, maxHeight, textLayout); + } - if (!fontCollection) - return E_INVALIDARG; - *fontCollection = nullptr; + STDMETHOD(CreateGdiCompatibleTextLayout)( + _In_reads_(stringLength) WCHAR const* string, + UINT32 stringLength, + _In_ IDWriteTextFormat* textFormat, + FLOAT layoutWidth, + FLOAT layoutHeight, + FLOAT pixelsPerDip, + _In_opt_ DWRITE_MATRIX const* transform, + BOOL useGdiNatural, + _COM_Outptr_ IDWriteTextLayout** textLayout + ) override + { + return pDWriteFactory->CreateGdiCompatibleTextLayout(string, stringLength, textFormat, layoutWidth, layoutHeight, pixelsPerDip, transform, useGdiNatural, textLayout); + } - auto _pEmptyCollection = internal::New(); - if (!_pEmptyCollection) - return E_OUTOFMEMORY; - *fontCollection = _pEmptyCollection; - return S_OK; - } + STDMETHOD(CreateEllipsisTrimmingSign)( + _In_ IDWriteTextFormat* textFormat, + _COM_Outptr_ IDWriteInlineObject** trimmingSign + ) override + { + return pDWriteFactory->CreateEllipsisTrimmingSign(textFormat, trimmingSign); + } - STDMETHOD(CreateCustomRenderingParams)( - FLOAT gamma, - FLOAT enhancedContrast, - FLOAT enhancedContrastGrayscale, - FLOAT clearTypeLevel, - DWRITE_PIXEL_GEOMETRY pixelGeometry, - DWRITE_RENDERING_MODE renderingMode, - _COM_Outptr_ IDWriteRenderingParams1** renderingParams - ) override - { - if(uLevel >= 1) + STDMETHOD(CreateTextAnalyzer)( + _COM_Outptr_ IDWriteTextAnalyzer** textAnalyzer + ) override { - return pDWriteFactory1->CreateCustomRenderingParams(gamma, enhancedContrast, enhancedContrastGrayscale, clearTypeLevel, pixelGeometry, renderingMode, renderingParams); + return pDWriteFactory->CreateTextAnalyzer(textAnalyzer); } - if (!renderingParams) - return E_NOINTERFACE; + STDMETHOD(CreateNumberSubstitution)( + _In_ DWRITE_NUMBER_SUBSTITUTION_METHOD substitutionMethod, + _In_z_ WCHAR const* localeName, + _In_ BOOL ignoreUserOverride, + _COM_Outptr_ IDWriteNumberSubstitution** numberSubstitution + ) override + { + return pDWriteFactory->CreateNumberSubstitution(substitutionMethod, localeName, ignoreUserOverride, numberSubstitution); + } - *renderingParams = nullptr; - if (enhancedContrastGrayscale < 0.0f) - return E_NOINTERFACE; + STDMETHOD(CreateGlyphRunAnalysis)( + _In_ DWRITE_GLYPH_RUN const* glyphRun, + FLOAT pixelsPerDip, + _In_opt_ DWRITE_MATRIX const* transform, + DWRITE_RENDERING_MODE renderingMode, + DWRITE_MEASURING_MODE measuringMode, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + _COM_Outptr_ IDWriteGlyphRunAnalysis** glyphRunAnalysis + ) override + { + return pDWriteFactory->CreateGlyphRunAnalysis(glyphRun, pixelsPerDip, transform, renderingMode, measuringMode, baselineOriginX, baselineOriginY, glyphRunAnalysis); + } - IDWriteRenderingParams* _pRenderingParams = nullptr; - auto _hr = pDWriteFactory->CreateCustomRenderingParams(gamma, enhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, &_pRenderingParams); - if (FAILED(_hr) || _pRenderingParams == nullptr) - return _hr; + + //////////////////////////////////////////////////////// + // IDWriteFactory1 + STDMETHOD(GetEudcFontCollection)( + _COM_Outptr_ IDWriteFontCollection** fontCollection, + BOOL checkForUpdates = FALSE + ) override + { + if (uLevel >= 1) + { + return pDWriteFactory1->GetEudcFontCollection(fontCollection, checkForUpdates); + } - auto _pRenderingParams1 = internal::New(uLevel, _pRenderingParams, enhancedContrastGrayscale); - _pRenderingParams->Release(); - if (!_pRenderingParams1) - return E_OUTOFMEMORY; + // 假装没有安装 Eudc字体 - *renderingParams = _pRenderingParams1; - return S_OK; - } + if (!fontCollection) + return E_INVALIDARG; + *fontCollection = nullptr; - using IDWriteFactory::CreateCustomRenderingParams; + auto _pEmptyCollection = internal::New(); + if (!_pEmptyCollection) + return E_OUTOFMEMORY; + *fontCollection = _pEmptyCollection; + return S_OK; + } - //////////////////////////////////////////////////////// - // IDWriteFactory2 - STDMETHOD(GetSystemFontFallback)( - _COM_Outptr_ IDWriteFontFallback** fontFallback - ) override - { - if (uLevel >= 2) + STDMETHOD(CreateCustomRenderingParams)( + FLOAT gamma, + FLOAT enhancedContrast, + FLOAT enhancedContrastGrayscale, + FLOAT clearTypeLevel, + DWRITE_PIXEL_GEOMETRY pixelGeometry, + DWRITE_RENDERING_MODE renderingMode, + _COM_Outptr_ IDWriteRenderingParams1** renderingParams + ) override { - return pDWriteFactory2->GetSystemFontFallback(fontFallback); - } + if(uLevel >= 1) + { + return pDWriteFactory1->CreateCustomRenderingParams(gamma, enhancedContrast, enhancedContrastGrayscale, clearTypeLevel, pixelGeometry, renderingMode, renderingParams); + } - if (!fontFallback) - return E_INVALIDARG; + if (!renderingParams) + return E_NOINTERFACE; - *fontFallback = nullptr; + *renderingParams = nullptr; + if (enhancedContrastGrayscale < 0.0f) + return E_NOINTERFACE; - auto _pFontFallback = internal::New(); - if (!_pFontFallback) - return E_OUTOFMEMORY; + IDWriteRenderingParams* _pRenderingParams = nullptr; + auto _hr = pDWriteFactory->CreateCustomRenderingParams(gamma, enhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, &_pRenderingParams); + if (FAILED(_hr) || _pRenderingParams == nullptr) + return _hr; - *fontFallback = _pFontFallback; - return S_OK; - } + auto _pRenderingParams1 = internal::New(uLevel, _pRenderingParams, enhancedContrastGrayscale); + _pRenderingParams->Release(); + if (!_pRenderingParams1) + return E_OUTOFMEMORY; - STDMETHOD(CreateFontFallbackBuilder)( - _COM_Outptr_ IDWriteFontFallbackBuilder** fontFallbackBuilder - ) override - { - if (uLevel >= 2) - { - return pDWriteFactory2->CreateFontFallbackBuilder(fontFallbackBuilder); + *renderingParams = _pRenderingParams1; + return S_OK; } - if (!fontFallbackBuilder) - return E_INVALIDARG; + using IDWriteFactory::CreateCustomRenderingParams; - *fontFallbackBuilder = nullptr; - return E_NOTIMPL; - } - - STDMETHOD(TranslateColorGlyphRun)( - FLOAT baselineOriginX, - FLOAT baselineOriginY, - _In_ DWRITE_GLYPH_RUN const* glyphRun, - _In_opt_ DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, - DWRITE_MEASURING_MODE measuringMode, - _In_opt_ DWRITE_MATRIX const* worldToDeviceTransform, - UINT32 colorPaletteIndex, - _COM_Outptr_ IDWriteColorGlyphRunEnumerator** colorLayers - ) override - { - if (uLevel >= 2) + //////////////////////////////////////////////////////// + // IDWriteFactory2 + STDMETHOD(GetSystemFontFallback)( + _COM_Outptr_ IDWriteFontFallback** fontFallback + ) override { - return pDWriteFactory2->TranslateColorGlyphRun(baselineOriginX, baselineOriginY, glyphRun, glyphRunDescription, measuringMode, worldToDeviceTransform, colorPaletteIndex, colorLayers); - } + if (uLevel >= 2) + { + return pDWriteFactory2->GetSystemFontFallback(fontFallback); + } - if (!colorLayers) - return E_INVALIDARG; + if (!fontFallback) + return E_INVALIDARG; - *colorLayers = nullptr; - return E_NOTIMPL; - } + *fontFallback = nullptr; - STDMETHOD(CreateCustomRenderingParams)( - FLOAT gamma, - FLOAT enhancedContrast, - FLOAT grayscaleEnhancedContrast, - FLOAT clearTypeLevel, - DWRITE_PIXEL_GEOMETRY pixelGeometry, - DWRITE_RENDERING_MODE renderingMode, - DWRITE_GRID_FIT_MODE gridFitMode, - _COM_Outptr_ IDWriteRenderingParams2** renderingParams - ) override - { - if (uLevel >= 2) - { - return pDWriteFactory2->CreateCustomRenderingParams(gamma, enhancedContrast, grayscaleEnhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, gridFitMode, renderingParams); + auto _pFontFallback = internal::New(); + if (!_pFontFallback) + return E_OUTOFMEMORY; + + *fontFallback = _pFontFallback; + return S_OK; } - if (!renderingParams) - return E_INVALIDARG; + STDMETHOD(CreateFontFallbackBuilder)( + _COM_Outptr_ IDWriteFontFallbackBuilder** fontFallbackBuilder + ) override + { + if (uLevel >= 2) + { + return pDWriteFactory2->CreateFontFallbackBuilder(fontFallbackBuilder); + } - *renderingParams = nullptr; + if (!fontFallbackBuilder) + return E_INVALIDARG; - IDWriteRenderingParams* _pRenderingParams = nullptr; - HRESULT _hr = S_OK; - if (uLevel >= 1) - { - _hr = pDWriteFactory1->CreateCustomRenderingParams(gamma, enhancedContrast, grayscaleEnhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, (IDWriteRenderingParams1**)&_pRenderingParams); + *fontFallbackBuilder = nullptr; + return E_NOTIMPL; } - else + + STDMETHOD(TranslateColorGlyphRun)( + FLOAT baselineOriginX, + FLOAT baselineOriginY, + _In_ DWRITE_GLYPH_RUN const* glyphRun, + _In_opt_ DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, + DWRITE_MEASURING_MODE measuringMode, + _In_opt_ DWRITE_MATRIX const* worldToDeviceTransform, + UINT32 colorPaletteIndex, + _COM_Outptr_ IDWriteColorGlyphRunEnumerator** colorLayers + ) override { - if (grayscaleEnhancedContrast < 0.0) + if (uLevel >= 2) + { + return pDWriteFactory2->TranslateColorGlyphRun(baselineOriginX, baselineOriginY, glyphRun, glyphRunDescription, measuringMode, worldToDeviceTransform, colorPaletteIndex, colorLayers); + } + + if (!colorLayers) return E_INVALIDARG; - _hr = pDWriteFactory->CreateCustomRenderingParams(gamma, enhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, &_pRenderingParams); + *colorLayers = nullptr; + return E_NOTIMPL; } - if (FAILED(_hr) || _pRenderingParams == nullptr) - return _hr; - auto _pTemp = internal::New(uLevel, _pRenderingParams, grayscaleEnhancedContrast, gridFitMode); - _pRenderingParams->Release(); + STDMETHOD(CreateCustomRenderingParams)( + FLOAT gamma, + FLOAT enhancedContrast, + FLOAT grayscaleEnhancedContrast, + FLOAT clearTypeLevel, + DWRITE_PIXEL_GEOMETRY pixelGeometry, + DWRITE_RENDERING_MODE renderingMode, + DWRITE_GRID_FIT_MODE gridFitMode, + _COM_Outptr_ IDWriteRenderingParams2** renderingParams + ) override + { + if (uLevel >= 2) + { + return pDWriteFactory2->CreateCustomRenderingParams(gamma, enhancedContrast, grayscaleEnhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, gridFitMode, renderingParams); + } - if (!_pTemp) - return E_OUTOFMEMORY; + if (!renderingParams) + return E_INVALIDARG; - *renderingParams = _pTemp; - return _hr; - } + *renderingParams = nullptr; - using IDWriteFactory::CreateCustomRenderingParams; - using IDWriteFactory1::CreateCustomRenderingParams; - - STDMETHOD(CreateGlyphRunAnalysis)( - _In_ DWRITE_GLYPH_RUN const* glyphRun, - _In_opt_ DWRITE_MATRIX const* transform, - DWRITE_RENDERING_MODE renderingMode, - DWRITE_MEASURING_MODE measuringMode, - DWRITE_GRID_FIT_MODE gridFitMode, - DWRITE_TEXT_ANTIALIAS_MODE antialiasMode, - FLOAT baselineOriginX, - FLOAT baselineOriginY, - _COM_Outptr_ IDWriteGlyphRunAnalysis** glyphRunAnalysis - ) override - { - if (uLevel >= 2) - { - return pDWriteFactory2->CreateGlyphRunAnalysis(glyphRun, transform, renderingMode, measuringMode, gridFitMode, antialiasMode, baselineOriginX, baselineOriginY, glyphRunAnalysis); - } + IDWriteRenderingParams* _pRenderingParams = nullptr; + HRESULT _hr = S_OK; + if (uLevel >= 1) + { + _hr = pDWriteFactory1->CreateCustomRenderingParams(gamma, enhancedContrast, grayscaleEnhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, (IDWriteRenderingParams1**)&_pRenderingParams); + } + else + { + if (grayscaleEnhancedContrast < 0.0) + return E_INVALIDARG; - return pDWriteFactory->CreateGlyphRunAnalysis(glyphRun, 1.0f, transform, renderingMode, measuringMode, baselineOriginX, baselineOriginY, glyphRunAnalysis); - } + _hr = pDWriteFactory->CreateCustomRenderingParams(gamma, enhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, &_pRenderingParams); + } - using IDWriteFactory::CreateGlyphRunAnalysis; - - - // IDWriteFactory3 - STDMETHOD(CreateGlyphRunAnalysis)( - _In_ DWRITE_GLYPH_RUN const* glyphRun, - _In_opt_ DWRITE_MATRIX const* transform, - DWRITE_RENDERING_MODE1 renderingMode, - DWRITE_MEASURING_MODE measuringMode, - DWRITE_GRID_FIT_MODE gridFitMode, - DWRITE_TEXT_ANTIALIAS_MODE antialiasMode, - FLOAT baselineOriginX, - FLOAT baselineOriginY, - _COM_Outptr_ IDWriteGlyphRunAnalysis** glyphRunAnalysis - ) override - { - if (uLevel >= 3) - { - return pDWriteFactory3->CreateGlyphRunAnalysis(glyphRun, transform, renderingMode, measuringMode, gridFitMode, antialiasMode, baselineOriginX, baselineOriginY, glyphRunAnalysis); - } + if (FAILED(_hr) || _pRenderingParams == nullptr) + return _hr; + auto _pTemp = internal::New(uLevel, _pRenderingParams, grayscaleEnhancedContrast, gridFitMode); + _pRenderingParams->Release(); - DWRITE_RENDERING_MODE _eRenderingMode = renderingMode == DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED ? DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC : DWRITE_RENDERING_MODE(renderingMode); - return CreateGlyphRunAnalysis(glyphRun, transform, _eRenderingMode, measuringMode, gridFitMode, antialiasMode, baselineOriginX, baselineOriginY, glyphRunAnalysis); - } + if (!_pTemp) + return E_OUTOFMEMORY; - using IDWriteFactory::CreateGlyphRunAnalysis; - using IDWriteFactory2::CreateGlyphRunAnalysis; - - STDMETHOD(CreateCustomRenderingParams)( - FLOAT gamma, - FLOAT enhancedContrast, - FLOAT grayscaleEnhancedContrast, - FLOAT clearTypeLevel, - DWRITE_PIXEL_GEOMETRY pixelGeometry, - DWRITE_RENDERING_MODE1 renderingMode, - DWRITE_GRID_FIT_MODE gridFitMode, - _COM_Outptr_ IDWriteRenderingParams3** renderingParams - ) override - { - if (uLevel >= 3) - { - return pDWriteFactory3->CreateCustomRenderingParams(gamma, enhancedContrast, grayscaleEnhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, gridFitMode, renderingParams); + *renderingParams = _pTemp; + return _hr; } - if (!renderingParams) - return E_INVALIDARG; - - *renderingParams = nullptr; - DWRITE_RENDERING_MODE _eRenderingMode = renderingMode == DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED ? DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC : DWRITE_RENDERING_MODE(renderingMode); - IDWriteRenderingParams* _pRenderingParams = nullptr; - HRESULT _hr = S_OK; - if (uLevel >= 2) + using IDWriteFactory::CreateCustomRenderingParams; + using IDWriteFactory1::CreateCustomRenderingParams; + + STDMETHOD(CreateGlyphRunAnalysis)( + _In_ DWRITE_GLYPH_RUN const* glyphRun, + _In_opt_ DWRITE_MATRIX const* transform, + DWRITE_RENDERING_MODE renderingMode, + DWRITE_MEASURING_MODE measuringMode, + DWRITE_GRID_FIT_MODE gridFitMode, + DWRITE_TEXT_ANTIALIAS_MODE antialiasMode, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + _COM_Outptr_ IDWriteGlyphRunAnalysis** glyphRunAnalysis + ) override { - _hr = pDWriteFactory2->CreateCustomRenderingParams(gamma, enhancedContrast, grayscaleEnhancedContrast, clearTypeLevel, pixelGeometry, _eRenderingMode, gridFitMode, (IDWriteRenderingParams2**)&_pRenderingParams); + if (uLevel >= 2) + { + return pDWriteFactory2->CreateGlyphRunAnalysis(glyphRun, transform, renderingMode, measuringMode, gridFitMode, antialiasMode, baselineOriginX, baselineOriginY, glyphRunAnalysis); + } + + return pDWriteFactory->CreateGlyphRunAnalysis(glyphRun, 1.0f, transform, renderingMode, measuringMode, baselineOriginX, baselineOriginY, glyphRunAnalysis); } - else if (uLevel >= 1) + + using IDWriteFactory::CreateGlyphRunAnalysis; + + + // IDWriteFactory3 + STDMETHOD(CreateGlyphRunAnalysis)( + _In_ DWRITE_GLYPH_RUN const* glyphRun, + _In_opt_ DWRITE_MATRIX const* transform, + DWRITE_RENDERING_MODE1 renderingMode, + DWRITE_MEASURING_MODE measuringMode, + DWRITE_GRID_FIT_MODE gridFitMode, + DWRITE_TEXT_ANTIALIAS_MODE antialiasMode, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + _COM_Outptr_ IDWriteGlyphRunAnalysis** glyphRunAnalysis + ) override { + if (uLevel >= 3) + { + return pDWriteFactory3->CreateGlyphRunAnalysis(glyphRun, transform, renderingMode, measuringMode, gridFitMode, antialiasMode, baselineOriginX, baselineOriginY, glyphRunAnalysis); + } + DWRITE_RENDERING_MODE _eRenderingMode = renderingMode == DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED ? DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC : DWRITE_RENDERING_MODE(renderingMode); - _hr = pDWriteFactory1->CreateCustomRenderingParams(gamma, enhancedContrast, grayscaleEnhancedContrast, clearTypeLevel, pixelGeometry, _eRenderingMode, (IDWriteRenderingParams1**)&_pRenderingParams); + return CreateGlyphRunAnalysis(glyphRun, transform, _eRenderingMode, measuringMode, gridFitMode, antialiasMode, baselineOriginX, baselineOriginY, glyphRunAnalysis); } - else + + using IDWriteFactory::CreateGlyphRunAnalysis; + using IDWriteFactory2::CreateGlyphRunAnalysis; + + STDMETHOD(CreateCustomRenderingParams)( + FLOAT gamma, + FLOAT enhancedContrast, + FLOAT grayscaleEnhancedContrast, + FLOAT clearTypeLevel, + DWRITE_PIXEL_GEOMETRY pixelGeometry, + DWRITE_RENDERING_MODE1 renderingMode, + DWRITE_GRID_FIT_MODE gridFitMode, + _COM_Outptr_ IDWriteRenderingParams3** renderingParams + ) override { - if (grayscaleEnhancedContrast < 0.0) + if (uLevel >= 3) + { + return pDWriteFactory3->CreateCustomRenderingParams(gamma, enhancedContrast, grayscaleEnhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, gridFitMode, renderingParams); + } + + if (!renderingParams) return E_INVALIDARG; - _hr = pDWriteFactory->CreateCustomRenderingParams(gamma, enhancedContrast, clearTypeLevel, pixelGeometry, _eRenderingMode, &_pRenderingParams); - } + *renderingParams = nullptr; + DWRITE_RENDERING_MODE _eRenderingMode = renderingMode == DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED ? DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC : DWRITE_RENDERING_MODE(renderingMode); + IDWriteRenderingParams* _pRenderingParams = nullptr; + HRESULT _hr = S_OK; + if (uLevel >= 2) + { + _hr = pDWriteFactory2->CreateCustomRenderingParams(gamma, enhancedContrast, grayscaleEnhancedContrast, clearTypeLevel, pixelGeometry, _eRenderingMode, gridFitMode, (IDWriteRenderingParams2**)&_pRenderingParams); + } + else if (uLevel >= 1) + { + DWRITE_RENDERING_MODE _eRenderingMode = renderingMode == DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED ? DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC : DWRITE_RENDERING_MODE(renderingMode); + _hr = pDWriteFactory1->CreateCustomRenderingParams(gamma, enhancedContrast, grayscaleEnhancedContrast, clearTypeLevel, pixelGeometry, _eRenderingMode, (IDWriteRenderingParams1**)&_pRenderingParams); + } + else + { + if (grayscaleEnhancedContrast < 0.0) + return E_INVALIDARG; - if (FAILED(_hr) || _pRenderingParams == nullptr) - return _hr; + _hr = pDWriteFactory->CreateCustomRenderingParams(gamma, enhancedContrast, clearTypeLevel, pixelGeometry, _eRenderingMode, &_pRenderingParams); + } - auto _pTemp = internal::New(uLevel, _pRenderingParams, grayscaleEnhancedContrast, gridFitMode, renderingMode); - _pRenderingParams->Release(); + if (FAILED(_hr) || _pRenderingParams == nullptr) + return _hr; - if (!_pTemp) - return E_OUTOFMEMORY; + auto _pTemp = internal::New(uLevel, _pRenderingParams, grayscaleEnhancedContrast, gridFitMode, renderingMode); + _pRenderingParams->Release(); - *renderingParams = _pTemp; - return _hr; - } + if (!_pTemp) + return E_OUTOFMEMORY; - using IDWriteFactory::CreateCustomRenderingParams; - using IDWriteFactory1::CreateCustomRenderingParams; - using IDWriteFactory2::CreateCustomRenderingParams; - - STDMETHOD(CreateFontFaceReference)( - _In_z_ WCHAR const* filePath, - _In_opt_ FILETIME const* lastWriteTime, - UINT32 faceIndex, - DWRITE_FONT_SIMULATIONS fontSimulations, - _COM_Outptr_ IDWriteFontFaceReference** fontFaceReference - ) override - { - if (uLevel >= 3) - { - return pDWriteFactory3->CreateFontFaceReference(filePath, lastWriteTime, faceIndex, fontSimulations, fontFaceReference); + *renderingParams = _pTemp; + return _hr; } - if (!fontFaceReference) - return E_NOINTERFACE; + using IDWriteFactory::CreateCustomRenderingParams; + using IDWriteFactory1::CreateCustomRenderingParams; + using IDWriteFactory2::CreateCustomRenderingParams; + + STDMETHOD(CreateFontFaceReference)( + _In_z_ WCHAR const* filePath, + _In_opt_ FILETIME const* lastWriteTime, + UINT32 faceIndex, + DWRITE_FONT_SIMULATIONS fontSimulations, + _COM_Outptr_ IDWriteFontFaceReference** fontFaceReference + ) override + { + if (uLevel >= 3) + { + return pDWriteFactory3->CreateFontFaceReference(filePath, lastWriteTime, faceIndex, fontSimulations, fontFaceReference); + } - *fontFaceReference = nullptr; - return E_NOTIMPL; - } + if (!fontFaceReference) + return E_NOINTERFACE; - STDMETHOD(CreateFontFaceReference)( - _In_ IDWriteFontFile* fontFile, - UINT32 faceIndex, - DWRITE_FONT_SIMULATIONS fontSimulations, - _COM_Outptr_ IDWriteFontFaceReference** fontFaceReference - ) override - { - if (uLevel >= 3) - { - return pDWriteFactory3->CreateFontFaceReference(fontFile, faceIndex, fontSimulations, fontFaceReference); + *fontFaceReference = nullptr; + return E_NOTIMPL; } - if (!fontFaceReference) - return E_NOINTERFACE; + STDMETHOD(CreateFontFaceReference)( + _In_ IDWriteFontFile* fontFile, + UINT32 faceIndex, + DWRITE_FONT_SIMULATIONS fontSimulations, + _COM_Outptr_ IDWriteFontFaceReference** fontFaceReference + ) override + { + if (uLevel >= 3) + { + return pDWriteFactory3->CreateFontFaceReference(fontFile, faceIndex, fontSimulations, fontFaceReference); + } - *fontFaceReference = nullptr; - return E_NOTIMPL; - } + if (!fontFaceReference) + return E_NOINTERFACE; - STDMETHOD(GetSystemFontSet)( - _COM_Outptr_ IDWriteFontSet** fontSet - ) override - { - if (uLevel >= 3) - { - return pDWriteFactory3->GetSystemFontSet(fontSet); + *fontFaceReference = nullptr; + return E_NOTIMPL; } - // E:\Chromium\src\content\browser\renderer_host\dwrite_font_proxy_impl_win.cc - __WarningMessage__("CHrome用到了这个接口 GetSystemFontSet"); + STDMETHOD(GetSystemFontSet)( + _COM_Outptr_ IDWriteFontSet** fontSet + ) override + { + if (uLevel >= 3) + { + return pDWriteFactory3->GetSystemFontSet(fontSet); + } - if (!fontSet) - return E_NOINTERFACE; + // E:\Chromium\src\content\browser\renderer_host\dwrite_font_proxy_impl_win.cc + __WarningMessage__("CHrome用到了这个接口 GetSystemFontSet"); - *fontSet = nullptr; - return E_NOTIMPL; - } + if (!fontSet) + return E_NOINTERFACE; - STDMETHOD(CreateFontSetBuilder)( - _COM_Outptr_ IDWriteFontSetBuilder** fontSetBuilder - ) override - { - if (uLevel >= 3) - { - return pDWriteFactory3->CreateFontSetBuilder(fontSetBuilder); + *fontSet = nullptr; + return E_NOTIMPL; } - __WarningMessage__("CHrome用到了这个接口 CreateFontSetBuilder"); + STDMETHOD(CreateFontSetBuilder)( + _COM_Outptr_ IDWriteFontSetBuilder** fontSetBuilder + ) override + { + if (uLevel >= 3) + { + return pDWriteFactory3->CreateFontSetBuilder(fontSetBuilder); + } - if (!fontSetBuilder) - return E_NOINTERFACE; + __WarningMessage__("CHrome用到了这个接口 CreateFontSetBuilder"); - *fontSetBuilder = nullptr; - return E_NOTIMPL; - } + if (!fontSetBuilder) + return E_NOINTERFACE; - STDMETHOD(CreateFontCollectionFromFontSet)( - IDWriteFontSet* fontSet, - _COM_Outptr_ IDWriteFontCollection1** fontCollection - ) override - { - if (uLevel >= 3) - { - return pDWriteFactory3->CreateFontCollectionFromFontSet(fontSet, fontCollection); + *fontSetBuilder = nullptr; + return E_NOTIMPL; } - if (!fontCollection) - return E_NOINTERFACE; + STDMETHOD(CreateFontCollectionFromFontSet)( + IDWriteFontSet* fontSet, + _COM_Outptr_ IDWriteFontCollection1** fontCollection + ) override + { + if (uLevel >= 3) + { + return pDWriteFactory3->CreateFontCollectionFromFontSet(fontSet, fontCollection); + } - *fontCollection = nullptr; - return E_NOTIMPL; - } + if (!fontCollection) + return E_NOINTERFACE; - STDMETHOD(GetSystemFontCollection)( - BOOL includeDownloadableFonts, - _COM_Outptr_ IDWriteFontCollection1** fontCollection, - BOOL checkForUpdates = FALSE - ) override - { - if (uLevel >= 3) - { - return pDWriteFactory3->GetSystemFontCollection(includeDownloadableFonts, fontCollection, checkForUpdates); + *fontCollection = nullptr; + return E_NOTIMPL; } - if (!fontCollection) - return E_NOINTERFACE; + STDMETHOD(GetSystemFontCollection)( + BOOL includeDownloadableFonts, + _COM_Outptr_ IDWriteFontCollection1** fontCollection, + BOOL checkForUpdates = FALSE + ) override + { + if (uLevel >= 3) + { + return pDWriteFactory3->GetSystemFontCollection(includeDownloadableFonts, fontCollection, checkForUpdates); + } - *fontCollection = nullptr; + if (!fontCollection) + return E_NOINTERFACE; - IDWriteFontCollection* _pFontCollection = nullptr; - auto _hr = pDWriteFactory->GetSystemFontCollection(&_pFontCollection, checkForUpdates); - if (FAILED(_hr) || _pFontCollection == nullptr) - return _hr; + *fontCollection = nullptr; - auto _pResult = internal::New(_pFontCollection, 0); - _pFontCollection->Release(); - if (!_pResult) - return E_OUTOFMEMORY; + IDWriteFontCollection* _pFontCollection = nullptr; + auto _hr = pDWriteFactory->GetSystemFontCollection(&_pFontCollection, checkForUpdates); + if (FAILED(_hr) || _pFontCollection == nullptr) + return _hr; - *fontCollection = _pResult; - return S_OK; - } + auto _pResult = internal::New(_pFontCollection, 0); + _pFontCollection->Release(); + if (!_pResult) + return E_OUTOFMEMORY; - using IDWriteFactory::GetSystemFontCollection; + *fontCollection = _pResult; + return S_OK; + } - STDMETHOD(GetFontDownloadQueue)( - _COM_Outptr_ IDWriteFontDownloadQueue** fontDownloadQueue - ) override - { - if (uLevel >= 3) + using IDWriteFactory::GetSystemFontCollection; + + STDMETHOD(GetFontDownloadQueue)( + _COM_Outptr_ IDWriteFontDownloadQueue** fontDownloadQueue + ) override { - return pDWriteFactory3->GetFontDownloadQueue(fontDownloadQueue); - } + if (uLevel >= 3) + { + return pDWriteFactory3->GetFontDownloadQueue(fontDownloadQueue); + } - if (!fontDownloadQueue) - return E_NOINTERFACE; + if (!fontDownloadQueue) + return E_NOINTERFACE; - *fontDownloadQueue = nullptr; - return E_NOTIMPL; - } - }; -#endif // (YY_Thunks_Support_Version < NTDDI_WIN10) + *fontDownloadQueue = nullptr; + return E_NOTIMPL; + } + }; +#endif // (YY_Thunks_Target < __WindowsNT10_10240) + } } #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN10) +#if (YY_Thunks_Target < __WindowsNT10_10240) // 最低受支持的客户端 Windows 7、带 SP2 的 Windows Vista 和适用于 Windows Vista 的平台更新 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2008 R2、Windows Server 2008 SP2 和适用于 Windows Server 2008 的平台更新[桌面应用 | UWP 应用] diff --git a/src/Thunks/dxgi.hpp b/src/Thunks/dxgi.hpp index 0ddafea..f861d5b 100644 --- a/src/Thunks/dxgi.hpp +++ b/src/Thunks/dxgi.hpp @@ -1,8 +1,10 @@ -#include +#if (YY_Thunks_Target < __WindowsNT6_SP2) +#include +#endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6SP2) +#if (YY_Thunks_Target < __WindowsNT6_SP2) __DEFINE_THUNK( dxgi, @@ -26,7 +28,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista // Minimum supported server Windows Server 2008 diff --git a/src/Thunks/dxva2.hpp b/src/Thunks/dxva2.hpp index 33555e2..58cb9d4 100644 --- a/src/Thunks/dxva2.hpp +++ b/src/Thunks/dxva2.hpp @@ -1,9 +1,11 @@ -#include +#if (YY_Thunks_Target < __WindowsNT6) +#include #include +#endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -29,7 +31,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] diff --git a/src/Thunks/esent.hpp b/src/Thunks/esent.hpp index 84c7c0a..0b17196 100644 --- a/src/Thunks/esent.hpp +++ b/src/Thunks/esent.hpp @@ -1,21 +1,21 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_esent) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_esent) #define __Comment_Lib_esent #pragma comment(lib, "esent.lib") #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // Minimum supported client Windows Vista - // Minimum supported server Windows Server 2008 - __DEFINE_THUNK( + // Minimum supported client Windows Vista + // Minimum supported server Windows Server 2008 + __DEFINE_THUNK( esent, - 16, + 16, JET_ERR, JET_API, JetAttachDatabase2W, @@ -23,12 +23,12 @@ namespace YY::Thunks _In_ JET_PCWSTR szFilename, _In_ const unsigned long cpgDatabaseSizeMax, _In_ JET_GRBIT grbit - ) - { - if (auto const _pfnJetAttachDatabase2W = try_get_JetAttachDatabase2W()) - { - return _pfnJetAttachDatabase2W(sesid, szFilename, cpgDatabaseSizeMax, grbit); - } + ) + { + if (auto const _pfnJetAttachDatabase2W = try_get_JetAttachDatabase2W()) + { + return _pfnJetAttachDatabase2W(sesid, szFilename, cpgDatabaseSizeMax, grbit); + } // 路径的话理论上MAX_PATH就足够了 char szFilenameBufferA[512] = {}; @@ -42,11 +42,11 @@ namespace YY::Thunks } return JetAttachDatabase2A(sesid, szFilename ? szFilenameBufferA : nullptr, cpgDatabaseSizeMax, grbit); - } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista // Minimum supported server Windows Server 2008 @@ -91,7 +91,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) //Minimum supported client Windows Vista //Minimum supported server Windows Server 2008 @@ -123,7 +123,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista // Minimum supported server Windows Server 2008 @@ -157,9 +157,9 @@ namespace YY::Thunks return JetGetTableColumnInfoA(sesid, tableid, szColumnName ? _szColumnNameBuffer.GetC_String() : nullptr, pvResult, cbMax, InfoLevel); } #endif - + -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista // Minimum supported server Windows Server 2008 @@ -205,7 +205,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista // Minimum supported server Windows Server 2008 @@ -244,7 +244,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) //Minimum supported client Windows Vista //Minimum supported server Windows Server 2008 @@ -281,7 +281,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) //Minimum supported client Windows Vista //Minimum supported server Windows Server 2008 diff --git a/src/Thunks/ext-ms-win-ntuser-gui.hpp b/src/Thunks/ext-ms-win-ntuser-gui.hpp index d884838..139b5f2 100644 --- a/src/Thunks/ext-ms-win-ntuser-gui.hpp +++ b/src/Thunks/ext-ms-win-ntuser-gui.hpp @@ -1,6 +1,6 @@ namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) // 最低受支持的客户端 Windows 7 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] diff --git a/src/Thunks/ext-ms-win-ntuser-misc.hpp b/src/Thunks/ext-ms-win-ntuser-misc.hpp index b4ab51f..86d5107 100644 --- a/src/Thunks/ext-ms-win-ntuser-misc.hpp +++ b/src/Thunks/ext-ms-win-ntuser-misc.hpp @@ -1,6 +1,6 @@ namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -23,7 +23,7 @@ #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] diff --git a/src/Thunks/ext-ms-win-ntuser-powermanagement.hpp b/src/Thunks/ext-ms-win-ntuser-powermanagement.hpp index 39e2508..f35f21a 100644 --- a/src/Thunks/ext-ms-win-ntuser-powermanagement.hpp +++ b/src/Thunks/ext-ms-win-ntuser-powermanagement.hpp @@ -1,161 +1,158 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) #include #endif -namespace YY +namespace YY::Thunks { - namespace Thunks - { #ifndef CONST_DEVICE_NOTIFY_WINDOW_HANDLE #define CONST_DEVICE_NOTIFY_WINDOW_HANDLE (HPOWERNOTIFY)0x1001 #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - // Windows 8 [仅限桌面应用],Windows Server 2012 [仅限桌面应用] - __DEFINE_THUNK( - user32, - 8, - HPOWERNOTIFY, - WINAPI, - RegisterSuspendResumeNotification, - IN HANDLE _hRecipient, - IN DWORD _fFlags - ) - { - if (const auto _pfnRegisterSuspendResumeNotification = try_get_RegisterSuspendResumeNotification()) - { - return _pfnRegisterSuspendResumeNotification(_hRecipient, _fFlags); - } - - if (DEVICE_NOTIFY_CALLBACK == _fFlags) - { - HPOWERNOTIFY _hRegistrationHandle = nullptr; - - auto _lStatus = PowerRegisterSuspendResumeNotificationDownlevel(DEVICE_NOTIFY_CALLBACK, _hRecipient, &_hRegistrationHandle); - if (_lStatus == ERROR_SUCCESS) - { - return _hRegistrationHandle; - } - else - { - SetLastError(_lStatus); - return nullptr; - } - } - else if (DEVICE_NOTIFY_WINDOW_HANDLE == _fFlags) - { - // 这种情况需要向窗口发送电源通知,但是老版本系统不支持 现代化睡眠 - // 本身就是可以正确处理这种情况的。所以我们忽略参数,直接返回一个标记常量即可。 - UNREFERENCED_PARAMETER(_hRecipient); - - return CONST_DEVICE_NOTIFY_WINDOW_HANDLE; - } - else - { - // 仅支持这二个参数 - SetLastError(ERROR_INVALID_PARAMETER); - return nullptr; - } - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + // Windows 8 [仅限桌面应用],Windows Server 2012 [仅限桌面应用] + __DEFINE_THUNK( + user32, + 8, + HPOWERNOTIFY, + WINAPI, + RegisterSuspendResumeNotification, + IN HANDLE _hRecipient, + IN DWORD _fFlags + ) + { + if (const auto _pfnRegisterSuspendResumeNotification = try_get_RegisterSuspendResumeNotification()) + { + return _pfnRegisterSuspendResumeNotification(_hRecipient, _fFlags); + } + + if (DEVICE_NOTIFY_CALLBACK == _fFlags) + { + HPOWERNOTIFY _hRegistrationHandle = nullptr; + + auto _lStatus = PowerRegisterSuspendResumeNotificationDownlevel(DEVICE_NOTIFY_CALLBACK, _hRecipient, &_hRegistrationHandle); + if (_lStatus == ERROR_SUCCESS) + { + return _hRegistrationHandle; + } + else + { + SetLastError(_lStatus); + return nullptr; + } + } + else if (DEVICE_NOTIFY_WINDOW_HANDLE == _fFlags) + { + // 这种情况需要向窗口发送电源通知,但是老版本系统不支持 现代化睡眠 + // 本身就是可以正确处理这种情况的。所以我们忽略参数,直接返回一个标记常量即可。 + UNREFERENCED_PARAMETER(_hRecipient); + + return CONST_DEVICE_NOTIFY_WINDOW_HANDLE; + } + else + { + // 仅支持这二个参数 + SetLastError(ERROR_INVALID_PARAMETER); + return nullptr; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - // Windows 8 [仅限桌面应用],Windows Server 2012 [仅限桌面应用] - __DEFINE_THUNK( - user32, - 4, - BOOL, - WINAPI, - UnregisterSuspendResumeNotification, - IN HPOWERNOTIFY _hHandle - ) - { - if (const auto _pfnUnregisterSuspendResumeNotification = try_get_UnregisterSuspendResumeNotification()) - { - return _pfnUnregisterSuspendResumeNotification(_hHandle); - } - - if (_hHandle == nullptr) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - else if (_hHandle == CONST_DEVICE_NOTIFY_WINDOW_HANDLE) - { - // 忽略,这是 DEVICE_NOTIFY_WINDOW_HANDLE 的常量 - return TRUE; - } - else - { - // 来自 DEVICE_NOTIFY_CALLBACK的注册 - auto _lStatus = PowerUnregisterSuspendResumeNotificationDownlevel(_hHandle); - if (_lStatus == ERROR_SUCCESS) - { - return TRUE; - } - else - { - SetLastError(_lStatus); - return FALSE; - } - } - } +#if (YY_Thunks_Target < __WindowsNT6_2) + + // Windows 8 [仅限桌面应用],Windows Server 2012 [仅限桌面应用] + __DEFINE_THUNK( + user32, + 4, + BOOL, + WINAPI, + UnregisterSuspendResumeNotification, + IN HPOWERNOTIFY _hHandle + ) + { + if (const auto _pfnUnregisterSuspendResumeNotification = try_get_UnregisterSuspendResumeNotification()) + { + return _pfnUnregisterSuspendResumeNotification(_hHandle); + } + + if (_hHandle == nullptr) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + else if (_hHandle == CONST_DEVICE_NOTIFY_WINDOW_HANDLE) + { + // 忽略,这是 DEVICE_NOTIFY_WINDOW_HANDLE 的常量 + return TRUE; + } + else + { + // 来自 DEVICE_NOTIFY_CALLBACK的注册 + auto _lStatus = PowerUnregisterSuspendResumeNotificationDownlevel(_hHandle); + if (_lStatus == ERROR_SUCCESS) + { + return TRUE; + } + else + { + SetLastError(_lStatus); + return FALSE; + } + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - // 最低受支持的客户端 Windows Vista [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] - __DEFINE_THUNK( - user32, - 12, - HPOWERNOTIFY, - WINAPI, - RegisterPowerSettingNotification, - IN HANDLE hRecipient, - IN LPCGUID PowerSettingGuid, - IN DWORD Flags - ) - { - if (const auto _pfnRegisterPowerSettingNotification = try_get_RegisterPowerSettingNotification()) - { - return _pfnRegisterPowerSettingNotification(hRecipient, PowerSettingGuid, Flags); - } - - return reinterpret_cast(5); - } +#if (YY_Thunks_Target < __WindowsNT6) + + // 最低受支持的客户端 Windows Vista [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] + __DEFINE_THUNK( + user32, + 12, + HPOWERNOTIFY, + WINAPI, + RegisterPowerSettingNotification, + IN HANDLE hRecipient, + IN LPCGUID PowerSettingGuid, + IN DWORD Flags + ) + { + if (const auto _pfnRegisterPowerSettingNotification = try_get_RegisterPowerSettingNotification()) + { + return _pfnRegisterPowerSettingNotification(hRecipient, PowerSettingGuid, Flags); + } + + return reinterpret_cast(5); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - // 最低受支持的客户端 Windows Vista [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] - __DEFINE_THUNK( - user32, - 4, - BOOL, - WINAPI, - UnregisterPowerSettingNotification, - IN HPOWERNOTIFY Handle - ) - { - if (const auto _pfnUnregisterPowerSettingNotification = try_get_UnregisterPowerSettingNotification()) - { - return _pfnUnregisterPowerSettingNotification(Handle); - } - - if (Handle == reinterpret_cast(5)) - { - return TRUE; - } - - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } +#if (YY_Thunks_Target < __WindowsNT6) + + // 最低受支持的客户端 Windows Vista [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] + __DEFINE_THUNK( + user32, + 4, + BOOL, + WINAPI, + UnregisterPowerSettingNotification, + IN HPOWERNOTIFY Handle + ) + { + if (const auto _pfnUnregisterPowerSettingNotification = try_get_UnregisterPowerSettingNotification()) + { + return _pfnUnregisterPowerSettingNotification(Handle); + } + + if (Handle == reinterpret_cast(5)) + { + return TRUE; + } + + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } #endif - } } diff --git a/src/Thunks/ext-ms-win-ntuser-sysparams-ext.hpp b/src/Thunks/ext-ms-win-ntuser-sysparams-ext.hpp index b5d2334..f3a6771 100644 --- a/src/Thunks/ext-ms-win-ntuser-sysparams-ext.hpp +++ b/src/Thunks/ext-ms-win-ntuser-sysparams-ext.hpp @@ -1,8 +1,10 @@ -#include +#if (YY_Thunks_Target < __WindowsNT6) +#include +#endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 在 Windows Vista 和更高版本的 Windows 操作系统中可用。 __DEFINE_THUNK( @@ -24,7 +26,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 在 Windows Vista 和更高版本的 Windows 操作系统中可用。 __DEFINE_THUNK( @@ -48,7 +50,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 在 Windows Vista 和更高版本的 Windows 操作系统中可用。 __DEFINE_THUNK( diff --git a/src/Thunks/ext-ms-win-ntuser-window.hpp b/src/Thunks/ext-ms-win-ntuser-window.hpp index 3ab1d0d..09e9c6d 100644 --- a/src/Thunks/ext-ms-win-ntuser-window.hpp +++ b/src/Thunks/ext-ms-win-ntuser-window.hpp @@ -1,33 +1,31 @@ -#include +#if (YY_Thunks_Target < __WindowsNT6_2) +#include +#endif -namespace YY +namespace YY::Thunks { - namespace Thunks - { - -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - // Windows 8 [仅限桌面应用],Windows Server 2012 [仅限桌面应用] - __DEFINE_THUNK( - user32, - 20, - UINT_PTR, - WINAPI, - SetCoalescableTimer, - _In_opt_ HWND _hWnd, - _In_ UINT_PTR _nIDEvent, - _In_ UINT _uElapse, - _In_opt_ TIMERPROC _lpTimerFunc, - _In_ ULONG _uToleranceDelay - ) - { - auto _pfnSetCoalescableTimer = try_get_SetCoalescableTimer(); - if (_pfnSetCoalescableTimer) - { - return _pfnSetCoalescableTimer(_hWnd, _nIDEvent, _uElapse, _lpTimerFunc, _uToleranceDelay); - } +#if (YY_Thunks_Target < __WindowsNT6_2) + // Windows 8 [仅限桌面应用],Windows Server 2012 [仅限桌面应用] + __DEFINE_THUNK( + user32, + 20, + UINT_PTR, + WINAPI, + SetCoalescableTimer, + _In_opt_ HWND _hWnd, + _In_ UINT_PTR _nIDEvent, + _In_ UINT _uElapse, + _In_opt_ TIMERPROC _lpTimerFunc, + _In_ ULONG _uToleranceDelay + ) + { + auto _pfnSetCoalescableTimer = try_get_SetCoalescableTimer(); + if (_pfnSetCoalescableTimer) + { + return _pfnSetCoalescableTimer(_hWnd, _nIDEvent, _uElapse, _lpTimerFunc, _uToleranceDelay); + } - return SetTimer(_hWnd, _nIDEvent, _uElapse, _lpTimerFunc); - } + return SetTimer(_hWnd, _nIDEvent, _uElapse, _lpTimerFunc); + } #endif - } -} \ No newline at end of file +} diff --git a/src/Thunks/ext-ms-win-rtcore-ntuser-wmpointer.hpp b/src/Thunks/ext-ms-win-rtcore-ntuser-wmpointer.hpp index f91a68b..dc80ed6 100644 --- a/src/Thunks/ext-ms-win-rtcore-ntuser-wmpointer.hpp +++ b/src/Thunks/ext-ms-win-rtcore-ntuser-wmpointer.hpp @@ -1,6 +1,6 @@ namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] @@ -24,7 +24,7 @@ #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] @@ -49,7 +49,7 @@ #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] @@ -74,7 +74,7 @@ #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] @@ -99,7 +99,7 @@ #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] diff --git a/src/Thunks/ext-ms-win-shell-shell32.hpp b/src/Thunks/ext-ms-win-shell-shell32.hpp index a7cff40..56c29f7 100644 --- a/src/Thunks/ext-ms-win-shell-shell32.hpp +++ b/src/Thunks/ext-ms-win-shell-shell32.hpp @@ -1,26 +1,28 @@ -#include +#if (YY_Thunks_Target < __WindowsNT6) +#include +#endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - // 最低受支持的客户端 Windows Vista [仅限桌面应用] + // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008 [仅限桌面应用] - __DEFINE_THUNK( - shell32, - 12, - HRESULT, - STDAPICALLTYPE, - SHGetStockIconInfo, + __DEFINE_THUNK( + shell32, + 12, + HRESULT, + STDAPICALLTYPE, + SHGetStockIconInfo, SHSTOCKICONID _eSiid, UINT _fFlags, _Inout_ SHSTOCKICONINFO* _pSii ) - { - if (const auto _pfnSHGetStockIconInfo = try_get_SHGetStockIconInfo()) - { - return _pfnSHGetStockIconInfo(_eSiid, _fFlags, _pSii); - } + { + if (const auto _pfnSHGetStockIconInfo = try_get_SHGetStockIconInfo()) + { + return _pfnSHGetStockIconInfo(_eSiid, _fFlags, _pSii); + } if (_pSii == nullptr || _pSii->cbSize != sizeof(SHSTOCKICONINFO)) { @@ -255,6 +257,6 @@ namespace YY::Thunks } return S_OK; - } + } #endif } diff --git a/src/Thunks/kernel32.hpp b/src/Thunks/kernel32.hpp index 22b0683..4e09c70 100644 --- a/src/Thunks/kernel32.hpp +++ b/src/Thunks/kernel32.hpp @@ -1,499 +1,496 @@  -namespace YY +namespace YY::Thunks { - namespace Thunks - { -#if (YY_Thunks_Support_Version < NTDDI_WINXP) - - //Minimum supported client Windows Vista - //Minimum supported server Windows Server 2008 - //Windows XP有这个API啊……微软文档抽风了? - __DEFINE_THUNK( - kernel32, - 0, - DWORD, - WINAPI, - WTSGetActiveConsoleSessionId, - VOID - ) - { - if (const auto pWTSGetActiveConsoleSessionId = try_get_WTSGetActiveConsoleSessionId()) - { - return pWTSGetActiveConsoleSessionId(); - } - - //因为Windows 2000没有会话隔离,所有的进程始终在 0 会话中运行,因此直接返回 0 即可。 - return 0; - } +#if (YY_Thunks_Target < __WindowsNT5_1) + + //Minimum supported client Windows Vista + //Minimum supported server Windows Server 2008 + //Windows XP有这个API啊……微软文档抽风了? + __DEFINE_THUNK( + kernel32, + 0, + DWORD, + WINAPI, + WTSGetActiveConsoleSessionId, + VOID + ) + { + if (const auto pWTSGetActiveConsoleSessionId = try_get_WTSGetActiveConsoleSessionId()) + { + return pWTSGetActiveConsoleSessionId(); + } + + //因为Windows 2000没有会话隔离,所有的进程始终在 0 会话中运行,因此直接返回 0 即可。 + return 0; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WINXPSP2) - - //Minimum supported client Windows Vista, Windows XP Professional x64 Edition, Windows XP with SP2[desktop apps only] - //Minimum supported server Windows Server 2003 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - GetNumaProcessorNode, - _In_ UCHAR Processor, - _Out_ PUCHAR NodeNumber - ) - { - if (const auto pGetNumaProcessorNode = try_get_GetNumaProcessorNode()) - { - return pGetNumaProcessorNode(Processor, NodeNumber); - } - - //对于没有 Node 概念的系统,我们统一认为只有一个 Node。 - - SYSTEM_INFO SystemInfo; - GetSystemInfo(&SystemInfo); - - if (SystemInfo.dwNumberOfProcessors < Processor) - { - *NodeNumber = '\0'; - return TRUE; - } - else - { - *NodeNumber = 0xffu; - - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - } +#if (YY_Thunks_Target < __WindowsNT5_1_SP2) + + //Minimum supported client Windows Vista, Windows XP Professional x64 Edition, Windows XP with SP2[desktop apps only] + //Minimum supported server Windows Server 2003 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + GetNumaProcessorNode, + _In_ UCHAR Processor, + _Out_ PUCHAR NodeNumber + ) + { + if (const auto pGetNumaProcessorNode = try_get_GetNumaProcessorNode()) + { + return pGetNumaProcessorNode(Processor, NodeNumber); + } + + //对于没有 Node 概念的系统,我们统一认为只有一个 Node。 + + SYSTEM_INFO SystemInfo; + GetSystemInfo(&SystemInfo); + + if (SystemInfo.dwNumberOfProcessors < Processor) + { + *NodeNumber = '\0'; + return TRUE; + } + else + { + *NodeNumber = 0xffu; + + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - //Minimum supported client Windows 7 [desktop apps only] - //Minimum supported server Windows Server 2008 R2 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - GetNumaNodeNumberFromHandle, - _In_ HANDLE hFile, - _Out_ PUSHORT NodeNumber - ) - { - if (const auto pGetNumaNodeNumberFromHandle = try_get_GetNumaNodeNumberFromHandle()) - { - return pGetNumaNodeNumberFromHandle(hFile, NodeNumber); - } - - //始终认为来自 Node 0 - *NodeNumber = 0; - - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + //Minimum supported client Windows 7 [desktop apps only] + //Minimum supported server Windows Server 2008 R2 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + GetNumaNodeNumberFromHandle, + _In_ HANDLE hFile, + _Out_ PUSHORT NodeNumber + ) + { + if (const auto pGetNumaNodeNumberFromHandle = try_get_GetNumaNodeNumberFromHandle()) + { + return pGetNumaNodeNumberFromHandle(hFile, NodeNumber); + } + + //始终认为来自 Node 0 + *NodeNumber = 0; + + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - //Minimum supported client Windows 7 [desktop apps only] - //Minimum supported server Windows Server 2008 R2 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - GetNumaProcessorNodeEx, - _In_ PPROCESSOR_NUMBER Processor, - _Out_ PUSHORT NodeNumber - ) - { - if (const auto pGetNumaProcessorNodeEx = try_get_GetNumaProcessorNodeEx()) - { - return pGetNumaProcessorNodeEx(Processor, NodeNumber); - } - - //老版本系统假定只有一组处理器 - if (Processor->Group == 0) - { - UCHAR NodeNumberTmp; - auto bRet = GetNumaProcessorNode(Processor->Number, &NodeNumberTmp); - - if (bRet) - { - *NodeNumber = NodeNumberTmp; - } - else - { - *NodeNumber = 0xffffu; - } - - return bRet; - } - - *NodeNumber = 0xffffu; - - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } -#endif +#if (YY_Thunks_Target < __WindowsNT6_1) + + //Minimum supported client Windows 7 [desktop apps only] + //Minimum supported server Windows Server 2008 R2 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + GetNumaProcessorNodeEx, + _In_ PPROCESSOR_NUMBER Processor, + _Out_ PUSHORT NodeNumber + ) + { + if (const auto pGetNumaProcessorNodeEx = try_get_GetNumaProcessorNodeEx()) + { + return pGetNumaProcessorNodeEx(Processor, NodeNumber); + } + + //老版本系统假定只有一组处理器 + if (Processor->Group == 0) + { + UCHAR NodeNumberTmp; + auto bRet = GetNumaProcessorNode(Processor->Number, &NodeNumberTmp); + + if (bRet) + { + *NodeNumber = NodeNumberTmp; + } + else + { + *NodeNumber = 0xffffu; + } + return bRet; + } -#if (YY_Thunks_Support_Version < NTDDI_WINXPSP2) - - //Minimum supported client Windows Vista, Windows XP Professional x64 Edition, Windows XP with SP2 [desktop apps only] - //Minimum supported server Windows Server 2003 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 8, - _Success_(return) - BOOL, - WINAPI, - GetNumaAvailableMemoryNode, - _In_ UCHAR Node, - _Out_ PULONGLONG AvailableBytes - ) - { - if (const auto pGetNumaAvailableMemoryNode = try_get_GetNumaAvailableMemoryNode()) - { - return pGetNumaAvailableMemoryNode(Node, AvailableBytes); - } - - if (Node == 0) - { - //统一的假定,Node数量为 1,所以该值必然为 0 - //我们把所有可用内存都认为是该节点0的可用内存。 - MEMORYSTATUSEX statex = { sizeof(statex) }; - - if (!GlobalMemoryStatusEx(&statex)) - { - return FALSE; - } - - *AvailableBytes = statex.ullAvailPhys; - return TRUE; - } - - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } + *NodeNumber = 0xffffu; + + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - //Minimum supported client Windows 7 [desktop apps only] - //Minimum supported server Windows Server 2008 R2 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 8, - _Success_(return) - BOOL, - WINAPI, - GetNumaAvailableMemoryNodeEx, - _In_ USHORT Node, - _Out_ PULONGLONG AvailableBytes - ) - { - if (const auto pGetNumaAvailableMemoryNodeEx = try_get_GetNumaAvailableMemoryNodeEx()) - { - return pGetNumaAvailableMemoryNodeEx(Node, AvailableBytes); - } - - - //GetNumaAvailableMemoryNode 最大只接受 0xFF - if (Node >= 0x100u) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - return GetNumaAvailableMemoryNode(UCHAR(Node), AvailableBytes); - } -#endif +#if (YY_Thunks_Target < __WindowsNT5_1_SP2) + + //Minimum supported client Windows Vista, Windows XP Professional x64 Edition, Windows XP with SP2 [desktop apps only] + //Minimum supported server Windows Server 2003 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 8, + _Success_(return) + BOOL, + WINAPI, + GetNumaAvailableMemoryNode, + _In_ UCHAR Node, + _Out_ PULONGLONG AvailableBytes + ) + { + if (const auto pGetNumaAvailableMemoryNode = try_get_GetNumaAvailableMemoryNode()) + { + return pGetNumaAvailableMemoryNode(Node, AvailableBytes); + } + + if (Node == 0) + { + //统一的假定,Node数量为 1,所以该值必然为 0 + //我们把所有可用内存都认为是该节点0的可用内存。 + MEMORYSTATUSEX statex = { sizeof(statex) }; + + if (!GlobalMemoryStatusEx(&statex)) + { + return FALSE; + } + *AvailableBytes = statex.ullAvailPhys; + return TRUE; + } -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps only] - //Minimum supported server Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - GetNumaProximityNode, - _In_ ULONG ProximityId, - _Out_ PUCHAR NodeNumber - ) - { - if (const auto pGetNumaProximityNode = try_get_GetNumaProximityNode()) - { - return pGetNumaProximityNode(ProximityId, NodeNumber); - } - - //我们不知道CPU的组成情况,但是我们可以假定最接近的分组就是 Node 0。 - //对于电脑来说,Node数量始终等于 1,因此问题不是特别的大。 - *NodeNumber = 0; - return TRUE; - } + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps only] - //Minimum supported server Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 28, - LPVOID, - WINAPI, - MapViewOfFileExNuma, - _In_ HANDLE hFileMappingObject, - _In_ DWORD dwDesiredAccess, - _In_ DWORD dwFileOffsetHigh, - _In_ DWORD dwFileOffsetLow, - _In_ SIZE_T dwNumberOfBytesToMap, - _In_opt_ LPVOID lpBaseAddress, - _In_ DWORD nndPreferred - ) - { - if (const auto pMapViewOfFileExNuma = try_get_MapViewOfFileExNuma()) - { - return pMapViewOfFileExNuma(hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap, lpBaseAddress, nndPreferred); - } - - return MapViewOfFileEx(hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap, lpBaseAddress); - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + //Minimum supported client Windows 7 [desktop apps only] + //Minimum supported server Windows Server 2008 R2 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 8, + _Success_(return) + BOOL, + WINAPI, + GetNumaAvailableMemoryNodeEx, + _In_ USHORT Node, + _Out_ PULONGLONG AvailableBytes + ) + { + if (const auto pGetNumaAvailableMemoryNodeEx = try_get_GetNumaAvailableMemoryNodeEx()) + { + return pGetNumaAvailableMemoryNodeEx(Node, AvailableBytes); + } + + + //GetNumaAvailableMemoryNode 最大只接受 0xFF + if (Node >= 0x100u) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return GetNumaAvailableMemoryNode(UCHAR(Node), AvailableBytes); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - // 最低受支持的客户端 Windows 8 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] - __DEFINE_THUNK( - kernel32, - 4, - BOOL, - WINAPI, - GetFirmwareType, - _Inout_ PFIRMWARE_TYPE _peFirmwareType - ) - { - if (const auto _pfnGetFirmwareType = try_get_GetFirmwareType()) - { - return _pfnGetFirmwareType(_peFirmwareType); - } - - if (!_peFirmwareType) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if (auto _pfnNtQuerySystemInformation = try_get_NtQuerySystemInformation()) - { - SYSTEM_BOOT_ENVIRONMENT_INFORMATION _Information; - const auto _Status = (long)_pfnNtQuerySystemInformation(SystemBootEnvironmentInformation, &_Information, sizeof(_Information), nullptr); - - if (_Status >= 0) - { - *_peFirmwareType = _Information.FirmwareType; - return TRUE; - } - else if (_Status != STATUS_INVALID_INFO_CLASS && _Status != STATUS_NOT_IMPLEMENTED) - { - internal::BaseSetLastNTError(_Status); - return FALSE; - } - else - { - // 当前系统不支持 SystemBootEnvironmentInformation,应该是 Windows 2000。 - } - } - - // 理论上不可能走到这里,最大的可能就是Windows 2000或者更早的系统了。 - // 所以我们这里兜底返回 FirmwareTypeBios,因为以前的系统只能是这个了。 - *_peFirmwareType = FIRMWARE_TYPE::FirmwareTypeBios; - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps only] + //Minimum supported server Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + GetNumaProximityNode, + _In_ ULONG ProximityId, + _Out_ PUCHAR NodeNumber + ) + { + if (const auto pGetNumaProximityNode = try_get_GetNumaProximityNode()) + { + return pGetNumaProximityNode(ProximityId, NodeNumber); + } + + //我们不知道CPU的组成情况,但是我们可以假定最接近的分组就是 Node 0。 + //对于电脑来说,Node数量始终等于 1,因此问题不是特别的大。 + *NodeNumber = 0; + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) - - // 最低受支持的客户端 Windows 8 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] - __DEFINE_THUNK( - kernel32, - 4, - BOOL, - WINAPI, - IsNativeVhdBoot, - _Out_ PBOOL _pbNativeVhdBoot - ) - { - if (const auto _pfnIsNativeVhdBoot = try_get_IsNativeVhdBoot()) - { - return _pfnIsNativeVhdBoot(_pbNativeVhdBoot); - } - - if (!_pbNativeVhdBoot) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - // Windows 7支持VHD启动,但是没有这个接口,直接调用 NtQuerySystemInformation 兼容一下。 - if (const auto _pfnNtQuerySystemInformation = try_get_NtQuerySystemInformation()) - { - ULONG _uReturnLength = 0; - auto _Status = (long)_pfnNtQuerySystemInformation(SystemVhdBootInformation, nullptr, 0, &_uReturnLength); - if (_Status == STATUS_BUFFER_TOO_SMALL) - { - union - { - char Buffer[1024]; - SYSTEM_VHD_BOOT_INFORMATION Info; - } _StaticBuffer; - - if (_uReturnLength > sizeof(_StaticBuffer)) - { - const auto _hProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; - auto _pInformation = (SYSTEM_VHD_BOOT_INFORMATION*)HeapAlloc(_hProcessHeap, 0, _uReturnLength); - if (!_pInformation) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - _Status = (long)_pfnNtQuerySystemInformation(SystemVhdBootInformation, _pInformation, _uReturnLength, &_uReturnLength); - _StaticBuffer.Info.OsDiskIsVhd = _pInformation->OsDiskIsVhd; - HeapFree(_hProcessHeap, 0, _pInformation); - } - else - { - _Status = (long)_pfnNtQuerySystemInformation(SystemVhdBootInformation, &_StaticBuffer.Info, _uReturnLength, &_uReturnLength); - } - - if (_Status >= 0) - { - *_pbNativeVhdBoot = _StaticBuffer.Info.OsDiskIsVhd; - } - } - else if (_Status != STATUS_INVALID_INFO_CLASS && _Status != STATUS_NOT_IMPLEMENTED) - { - internal::BaseSetLastNTError(_Status); - return FALSE; - } - else - { - // 当前系统不支持VHD,兜底处理。 - } - } - - // 兜底处理,现在是早期不支持VHD启动的系统。 - // 注意:这里故意设置 ERROR_INVALID_PARAMETER,因为从微软的行为看 - // 未使用VHD时,它将返回这个错误代码。 - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps only] + //Minimum supported server Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 28, + LPVOID, + WINAPI, + MapViewOfFileExNuma, + _In_ HANDLE hFileMappingObject, + _In_ DWORD dwDesiredAccess, + _In_ DWORD dwFileOffsetHigh, + _In_ DWORD dwFileOffsetLow, + _In_ SIZE_T dwNumberOfBytesToMap, + _In_opt_ LPVOID lpBaseAddress, + _In_ DWORD nndPreferred + ) + { + if (const auto pMapViewOfFileExNuma = try_get_MapViewOfFileExNuma()) + { + return pMapViewOfFileExNuma(hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap, lpBaseAddress, nndPreferred); + } + + return MapViewOfFileEx(hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap, lpBaseAddress); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6SP1) - - // 最低受支持的客户端 Windows Vista SP1、Windows XP SP3 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] - __DEFINE_THUNK( - kernel32, - 4, - BOOL, - WINAPI, - SetProcessDEPPolicy, - _In_ DWORD dwFlags - ) - { - if (const auto _pfnSetProcessDEPPolicy = try_get_SetProcessDEPPolicy()) - { - return _pfnSetProcessDEPPolicy(dwFlags); - } - -#if defined(_AMD64_) - // https://learn.microsoft.com/zh-cn/windows/win32/api/winbase/nf-winbase-setprocessdeppolicy - // 微软文档说明,这个函数只限于x64进程调用。 - SetLastError(ERROR_NOT_SUPPORTED); +#if (YY_Thunks_Target < __WindowsNT6_2) + + // 最低受支持的客户端 Windows 8 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] + __DEFINE_THUNK( + kernel32, + 4, + BOOL, + WINAPI, + GetFirmwareType, + _Inout_ PFIRMWARE_TYPE _peFirmwareType + ) + { + if (const auto _pfnGetFirmwareType = try_get_GetFirmwareType()) + { + return _pfnGetFirmwareType(_peFirmwareType); + } + + if (!_peFirmwareType) + { + SetLastError(ERROR_INVALID_PARAMETER); return FALSE; -#elif defined(_X86_) - if (dwFlags & (~(PROCESS_DEP_ENABLE | PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION))) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } + } + + if (auto _pfnNtQuerySystemInformation = try_get_NtQuerySystemInformation()) + { + SYSTEM_BOOT_ENVIRONMENT_INFORMATION _Information; + const auto _Status = (long)_pfnNtQuerySystemInformation(SystemBootEnvironmentInformation, &_Information, sizeof(_Information), nullptr); - DWORD _uInfo = 0; - if (dwFlags == 0) + if (_Status >= 0) { - _uInfo = 2; + *_peFirmwareType = _Information.FirmwareType; + return TRUE; } - else if (dwFlags & PROCESS_DEP_ENABLE) + else if (_Status != STATUS_INVALID_INFO_CLASS && _Status != STATUS_NOT_IMPLEMENTED) { - _uInfo = (dwFlags & PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION) ? 13 : 9; + internal::BaseSetLastNTError(_Status); + return FALSE; } else { - internal::BaseSetLastNTError(0xC0000030); - return FALSE; + // 当前系统不支持 SystemBootEnvironmentInformation,应该是 Windows 2000。 } + } + + // 理论上不可能走到这里,最大的可能就是Windows 2000或者更早的系统了。 + // 所以我们这里兜底返回 FirmwareTypeBios,因为以前的系统只能是这个了。 + *_peFirmwareType = FIRMWARE_TYPE::FirmwareTypeBios; + return TRUE; + } +#endif - const auto _pfnNtSetInformationProcess = try_get_NtSetInformationProcess(); - if (!_pfnNtSetInformationProcess) - { - SetLastError(ERROR_NOT_SUPPORTED); - return FALSE; - } - LONG _Status = _pfnNtSetInformationProcess(NtCurrentProcess(), PROCESSINFOCLASS::ProcessExecuteFlags, &_uInfo, sizeof(_uInfo)); - if (_Status >=0 || STATUS_INVALID_INFO_CLASS == _Status || STATUS_NOT_SUPPORTED == _Status) +#if (YY_Thunks_Target < __WindowsNT6_2) + + // 最低受支持的客户端 Windows 8 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] + __DEFINE_THUNK( + kernel32, + 4, + BOOL, + WINAPI, + IsNativeVhdBoot, + _Out_ PBOOL _pbNativeVhdBoot + ) + { + if (const auto _pfnIsNativeVhdBoot = try_get_IsNativeVhdBoot()) + { + return _pfnIsNativeVhdBoot(_pbNativeVhdBoot); + } + + if (!_pbNativeVhdBoot) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // Windows 7支持VHD启动,但是没有这个接口,直接调用 NtQuerySystemInformation 兼容一下。 + if (const auto _pfnNtQuerySystemInformation = try_get_NtQuerySystemInformation()) + { + ULONG _uReturnLength = 0; + auto _Status = (long)_pfnNtQuerySystemInformation(SystemVhdBootInformation, nullptr, 0, &_uReturnLength); + if (_Status == STATUS_BUFFER_TOO_SMALL) { - // 如果不支持这个接口,那么也认为是成功的。反正不支持DEP。 - return TRUE; + union + { + char Buffer[1024]; + SYSTEM_VHD_BOOT_INFORMATION Info; + } _StaticBuffer; + + if (_uReturnLength > sizeof(_StaticBuffer)) + { + const auto _hProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; + auto _pInformation = (SYSTEM_VHD_BOOT_INFORMATION*)HeapAlloc(_hProcessHeap, 0, _uReturnLength); + if (!_pInformation) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + _Status = (long)_pfnNtQuerySystemInformation(SystemVhdBootInformation, _pInformation, _uReturnLength, &_uReturnLength); + _StaticBuffer.Info.OsDiskIsVhd = _pInformation->OsDiskIsVhd; + HeapFree(_hProcessHeap, 0, _pInformation); + } + else + { + _Status = (long)_pfnNtQuerySystemInformation(SystemVhdBootInformation, &_StaticBuffer.Info, _uReturnLength, &_uReturnLength); + } + + if (_Status >= 0) + { + *_pbNativeVhdBoot = _StaticBuffer.Info.OsDiskIsVhd; + } } - else + else if (_Status != STATUS_INVALID_INFO_CLASS && _Status != STATUS_NOT_IMPLEMENTED) { internal::BaseSetLastNTError(_Status); return FALSE; } + else + { + // 当前系统不支持VHD,兜底处理。 + } + } + + // 兜底处理,现在是早期不支持VHD启动的系统。 + // 注意:这里故意设置 ERROR_INVALID_PARAMETER,因为从微软的行为看 + // 未使用VHD时,它将返回这个错误代码。 + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } +#endif + + +#if (YY_Thunks_Target < __WindowsNT6_SP1) + + // 最低受支持的客户端 Windows Vista SP1、Windows XP SP3 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] + __DEFINE_THUNK( + kernel32, + 4, + BOOL, + WINAPI, + SetProcessDEPPolicy, + _In_ DWORD dwFlags + ) + { + if (const auto _pfnSetProcessDEPPolicy = try_get_SetProcessDEPPolicy()) + { + return _pfnSetProcessDEPPolicy(dwFlags); + } + +#if defined(_AMD64_) + // https://learn.microsoft.com/zh-cn/windows/win32/api/winbase/nf-winbase-setprocessdeppolicy + // 微软文档说明,这个函数只限于x64进程调用。 + SetLastError(ERROR_NOT_SUPPORTED); + return FALSE; +#elif defined(_X86_) + if (dwFlags & (~(PROCESS_DEP_ENABLE | PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION))) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + DWORD _uInfo = 0; + if (dwFlags == 0) + { + _uInfo = 2; + } + else if (dwFlags & PROCESS_DEP_ENABLE) + { + _uInfo = (dwFlags & PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION) ? 13 : 9; + } + else + { + internal::BaseSetLastNTError(0xC0000030); + return FALSE; + } + + const auto _pfnNtSetInformationProcess = try_get_NtSetInformationProcess(); + if (!_pfnNtSetInformationProcess) + { + SetLastError(ERROR_NOT_SUPPORTED); + return FALSE; + } + + LONG _Status = _pfnNtSetInformationProcess(NtCurrentProcess(), PROCESSINFOCLASS::ProcessExecuteFlags, &_uInfo, sizeof(_uInfo)); + if (_Status >=0 || STATUS_INVALID_INFO_CLASS == _Status || STATUS_NOT_SUPPORTED == _Status) + { + // 如果不支持这个接口,那么也认为是成功的。反正不支持DEP。 + return TRUE; + } + else + { + internal::BaseSetLastNTError(_Status); + return FALSE; + } #else #error 未知系统? #endif - } -#endif // (YY_Thunks_Support_Version < NTDDI_WIN6SP1) - - -#if (YY_Thunks_Support_Version < NTDDI_WIN6SP1) - - // 最低受支持的客户端 带 SP1 的 Windows Vista、带 SP3 的 Windows XP [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] - __DEFINE_THUNK( - kernel32, - 0, - DEP_SYSTEM_POLICY_TYPE, - WINAPI, - GetSystemDEPPolicy, - ) - { - if (const auto _pfnGetSystemDEPPolicy = try_get_GetSystemDEPPolicy()) - { - return _pfnGetSystemDEPPolicy(); - } - - return DEP_SYSTEM_POLICY_TYPE::DEPPolicyAlwaysOff; - } -#endif // (YY_Thunks_Support_Version < NTDDI_WIN6SP1) - } + } +#endif // (YY_Thunks_Target < __WindowsNT6_SP1) + + +#if (YY_Thunks_Target < __WindowsNT6_SP1) + + // 最低受支持的客户端 带 SP1 的 Windows Vista、带 SP3 的 Windows XP [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] + __DEFINE_THUNK( + kernel32, + 0, + DEP_SYSTEM_POLICY_TYPE, + WINAPI, + GetSystemDEPPolicy, + ) + { + if (const auto _pfnGetSystemDEPPolicy = try_get_GetSystemDEPPolicy()) + { + return _pfnGetSystemDEPPolicy(); + } + + return DEP_SYSTEM_POLICY_TYPE::DEPPolicyAlwaysOff; + } +#endif // (YY_Thunks_Target < __WindowsNT6_SP1) } diff --git a/src/Thunks/mf.hpp b/src/Thunks/mf.hpp index e2c2ec1..064a896 100644 --- a/src/Thunks/mf.hpp +++ b/src/Thunks/mf.hpp @@ -1,10 +1,10 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) #include #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) // Minimum supported client Windows 7 [desktop apps only] // Minimum supported server Windows Server 2008 R2[desktop apps only] @@ -32,7 +32,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) // Minimum supported client Windows 7 [desktop apps only] // Minimum supported server Windows Server 2008 R2[desktop apps only] diff --git a/src/Thunks/mfplat.hpp b/src/Thunks/mfplat.hpp index 9642289..286b658 100644 --- a/src/Thunks/mfplat.hpp +++ b/src/Thunks/mfplat.hpp @@ -1,14 +1,14 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) #include #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] @@ -38,7 +38,7 @@ namespace YY::Thunks } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] @@ -67,7 +67,7 @@ namespace YY::Thunks } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] @@ -96,7 +96,7 @@ namespace YY::Thunks } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8 [桌面应用|UWP 应用] // 最低受支持的服务器 Windows Server 2012[桌面应用 | UWP 应用] @@ -118,7 +118,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] @@ -147,7 +147,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] @@ -177,7 +177,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] @@ -205,7 +205,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] @@ -232,7 +232,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] @@ -262,7 +262,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] @@ -293,7 +293,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] @@ -320,7 +320,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] @@ -348,7 +348,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] @@ -377,7 +377,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] @@ -404,7 +404,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] @@ -434,7 +434,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] @@ -467,7 +467,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] @@ -496,7 +496,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] @@ -522,7 +522,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] @@ -548,7 +548,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] @@ -571,7 +571,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps | UWP apps] // Minimum supported server Windows Server 2008[desktop apps | UWP apps] @@ -596,7 +596,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) // Minimum supported client Windows 7 [desktop apps | UWP apps] // Minimum supported server Windows Server 2008 R2[desktop apps | UWP apps] diff --git a/src/Thunks/mfreadwrite.hpp b/src/Thunks/mfreadwrite.hpp index 543f393..9a62cbd 100644 --- a/src/Thunks/mfreadwrite.hpp +++ b/src/Thunks/mfreadwrite.hpp @@ -1,10 +1,10 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) #include #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) // 最低受支持的客户端 适用于 Windows Vista 的 Windows 7、Windows Vista 和平台更新补充 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2008 R2[桌面应用 | UWP 应用] diff --git a/src/Thunks/ndfapi.hpp b/src/Thunks/ndfapi.hpp index c6d98b9..8ce4cca 100644 --- a/src/Thunks/ndfapi.hpp +++ b/src/Thunks/ndfapi.hpp @@ -1,10 +1,10 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) #include #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -32,7 +32,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -58,7 +58,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] diff --git a/src/Thunks/netapi32.hpp b/src/Thunks/netapi32.hpp index 978dfb1..78235ad 100644 --- a/src/Thunks/netapi32.hpp +++ b/src/Thunks/netapi32.hpp @@ -1,10 +1,10 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN10) +#if (YY_Thunks_Target < __WindowsNT10_10240) #include #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN10) +#if (YY_Thunks_Target < __WindowsNT10_10240) // 最低受支持的客户端 Windows 10 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2016[仅限桌面应用] @@ -32,7 +32,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10) +#if (YY_Thunks_Target < __WindowsNT10_10240) // 最低受支持的客户端 Windows 10 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2016[仅限桌面应用] diff --git a/src/Thunks/ntdll.hpp b/src/Thunks/ntdll.hpp index df68bc9..f9ecb0a 100644 --- a/src/Thunks/ntdll.hpp +++ b/src/Thunks/ntdll.hpp @@ -1,6 +1,6 @@ namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [桌面应用|UWP 应用] // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] @@ -34,19 +34,19 @@ #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) // 最低受支持的客户端 在 Windows 7 和更高版本的 Windows 中可用。 __DEFINE_THUNK( ntdll, 16, NTSTATUS, - NTAPI, - NtOpenKeyEx, - __out PHANDLE _phKeyHandle, - __in ACCESS_MASK _fDesiredAccess, - __in POBJECT_ATTRIBUTES _pObjectAttributes, - __in ULONG _fOpenOptions + NTAPI, + NtOpenKeyEx, + __out PHANDLE _phKeyHandle, + __in ACCESS_MASK _fDesiredAccess, + __in POBJECT_ATTRIBUTES _pObjectAttributes, + __in ULONG _fOpenOptions ) { if (const auto _pfnNtOpenKeyEx = try_get_NtOpenKeyEx()) diff --git a/src/Thunks/powrprof.hpp b/src/Thunks/powrprof.hpp index d6bb8f8..82ab5a2 100644 --- a/src/Thunks/powrprof.hpp +++ b/src/Thunks/powrprof.hpp @@ -1,13 +1,13 @@ -#if (YY_Thunks_Support_Version < NTDDI_VISTA) +#if (YY_Thunks_Target < __WindowsNT6) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_VISTA) && !defined(__Comment_Lib_powrprof) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_powrprof) #define __Comment_Lib_powrprof #pragma comment(lib, "PowrProf.lib") #endif -#if (YY_Thunks_Support_Version < NTDDI_VISTA) && !defined(__Comment_Lib_shlwapi) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_shlwapi) #define __Comment_Lib_shlwapi #pragma comment(lib, "Shlwapi.lib") #endif @@ -17,7 +17,7 @@ namespace YY::Thunks::Fallback::PowrProf { namespace { -#if (YY_Thunks_Support_Version < NTDDI_VISTA) +#if (YY_Thunks_Target < __WindowsNT6) // 节能模式 static constexpr const GUID kPowerSaver = { 0xa1841308, 0x3541, 0x4fab, { 0xbc, 0x81, 0xf7, 0x15, 0x56, 0xf2, 0x0b, 0x4a } }; // 平衡模式 @@ -109,7 +109,7 @@ namespace YY::Thunks::Fallback::PowrProf namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_VISTA) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -132,7 +132,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_VISTA) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -201,7 +201,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_VISTA) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -228,7 +228,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_VISTA) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] diff --git a/src/Thunks/psapi.hpp b/src/Thunks/psapi.hpp index cd0146c..34491b3 100644 --- a/src/Thunks/psapi.hpp +++ b/src/Thunks/psapi.hpp @@ -3,191 +3,191 @@ #define PSAPI_VERSION 1 #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_psapi) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_psapi) #define __Comment_Lib_psapi #pragma comment(lib, "Psapi.lib") #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - psapi, - 20, - BOOL, - WINAPI, - EnumProcessModulesEx, - _In_ HANDLE hProcess, - _Out_writes_bytes_(cb) HMODULE* lphModule, - _In_ DWORD cb, - _Out_ LPDWORD lpcbNeeded, - _In_ DWORD dwFilterFlag - ) - { - if (auto pEnumProcessModulesEx = try_get_EnumProcessModulesEx()) - { - return pEnumProcessModulesEx(hProcess, lphModule, cb, lpcbNeeded, dwFilterFlag); - } - - return EnumProcessModules(hProcess, lphModule, cb, lpcbNeeded); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + psapi, + 20, + BOOL, + WINAPI, + EnumProcessModulesEx, + _In_ HANDLE hProcess, + _Out_writes_bytes_(cb) HMODULE* lphModule, + _In_ DWORD cb, + _Out_ LPDWORD lpcbNeeded, + _In_ DWORD dwFilterFlag + ) + { + if (auto pEnumProcessModulesEx = try_get_EnumProcessModulesEx()) + { + return pEnumProcessModulesEx(hProcess, lphModule, cb, lpcbNeeded, dwFilterFlag); + } + + return EnumProcessModules(hProcess, lphModule, cb, lpcbNeeded); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - psapi, - 12, - BOOL, - WINAPI, - GetWsChangesEx, - _In_ HANDLE hProcess, - _Out_writes_bytes_to_(*cb, *cb) PPSAPI_WS_WATCH_INFORMATION_EX lpWatchInfoEx, - _Inout_ PDWORD cb - ) - { - if (auto pGetWsChangesEx = try_get_GetWsChangesEx()) - { - return pGetWsChangesEx(hProcess, lpWatchInfoEx, cb); - } - - PPSAPI_WS_WATCH_INFORMATION pWatchInfo = nullptr; - DWORD cbWatchInfo = 1024 * sizeof(pWatchInfo[0]); - const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; - LSTATUS lStatus = ERROR_SUCCESS; - - for (;;) - { - if (pWatchInfo) - { - cbWatchInfo *= 2; - - auto pNewWatchInfo = (PPSAPI_WS_WATCH_INFORMATION)HeapReAlloc(ProcessHeap, 0, pWatchInfo, cbWatchInfo); - - if (!pNewWatchInfo) - { - lStatus = ERROR_OUTOFMEMORY; - break; - } - - pWatchInfo = pNewWatchInfo; - } - else - { - pWatchInfo = (PPSAPI_WS_WATCH_INFORMATION)HeapAlloc(ProcessHeap, 0, cbWatchInfo); - if (!pWatchInfo) - { - lStatus = ERROR_OUTOFMEMORY; - break; - } - } - - if (!GetWsChanges(hProcess, pWatchInfo, cbWatchInfo)) - { - lStatus = GetLastError(); - - if (lStatus == ERROR_INSUFFICIENT_BUFFER) - { - continue; - - } - else - { - break; - } - } - - //确定实际个数 - const auto pWatchInfoMax = (PPSAPI_WS_WATCH_INFORMATION)((byte*)pWatchInfo + cbWatchInfo); - auto pWatchInfoTerminated = pWatchInfo; - for (; pWatchInfoTerminated < pWatchInfoMax && pWatchInfoTerminated->FaultingPc != nullptr; ++pWatchInfoTerminated); - - auto ccWatchInfo = pWatchInfoTerminated - pWatchInfo; - - auto cbWatchInfoExRequest = (ccWatchInfo + 1) * sizeof(lpWatchInfoEx[0]); +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + psapi, + 12, + BOOL, + WINAPI, + GetWsChangesEx, + _In_ HANDLE hProcess, + _Out_writes_bytes_to_(*cb, *cb) PPSAPI_WS_WATCH_INFORMATION_EX lpWatchInfoEx, + _Inout_ PDWORD cb + ) + { + if (auto pGetWsChangesEx = try_get_GetWsChangesEx()) + { + return pGetWsChangesEx(hProcess, lpWatchInfoEx, cb); + } + + PPSAPI_WS_WATCH_INFORMATION pWatchInfo = nullptr; + DWORD cbWatchInfo = 1024 * sizeof(pWatchInfo[0]); + const auto ProcessHeap = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ProcessHeap; + LSTATUS lStatus = ERROR_SUCCESS; + + for (;;) + { + if (pWatchInfo) + { + cbWatchInfo *= 2; + + auto pNewWatchInfo = (PPSAPI_WS_WATCH_INFORMATION)HeapReAlloc(ProcessHeap, 0, pWatchInfo, cbWatchInfo); + + if (!pNewWatchInfo) + { + lStatus = ERROR_OUTOFMEMORY; + break; + } + + pWatchInfo = pNewWatchInfo; + } + else + { + pWatchInfo = (PPSAPI_WS_WATCH_INFORMATION)HeapAlloc(ProcessHeap, 0, cbWatchInfo); + if (!pWatchInfo) + { + lStatus = ERROR_OUTOFMEMORY; + break; + } + } + + if (!GetWsChanges(hProcess, pWatchInfo, cbWatchInfo)) + { + lStatus = GetLastError(); + + if (lStatus == ERROR_INSUFFICIENT_BUFFER) + { + continue; + + } + else + { + break; + } + } + + //确定实际个数 + const auto pWatchInfoMax = (PPSAPI_WS_WATCH_INFORMATION)((byte*)pWatchInfo + cbWatchInfo); + auto pWatchInfoTerminated = pWatchInfo; + for (; pWatchInfoTerminated < pWatchInfoMax && pWatchInfoTerminated->FaultingPc != nullptr; ++pWatchInfoTerminated); + + auto ccWatchInfo = pWatchInfoTerminated - pWatchInfo; + + auto cbWatchInfoExRequest = (ccWatchInfo + 1) * sizeof(lpWatchInfoEx[0]); if (cbWatchInfoExRequest > MAXUINT32) { lStatus = ERROR_FUNCTION_FAILED; break; } - auto cbBuffer = *cb; - *cb = static_cast(cbWatchInfoExRequest); - - if (cbBuffer < cbWatchInfoExRequest) - { - lStatus = ERROR_INSUFFICIENT_BUFFER; - break; - } - - - //复制到新缓冲区 - for (int i = 0; i != ccWatchInfo; ++i) - { - lpWatchInfoEx[i].BasicInfo = pWatchInfo[i]; - lpWatchInfoEx[i].FaultingThreadId = 0; - lpWatchInfoEx[i].Flags = 0; - } - - //插入终止标记 - lpWatchInfoEx[ccWatchInfo] = PSAPI_WS_WATCH_INFORMATION_EX{}; - - lStatus = ERROR_SUCCESS; - break; - } - - if (pWatchInfo) - { - HeapFree(ProcessHeap, 0, pWatchInfo); - } - - if (lStatus == ERROR_SUCCESS) - { - return TRUE; - } - else - { - SetLastError(lStatus); - return FALSE; - } - } + auto cbBuffer = *cb; + *cb = static_cast(cbWatchInfoExRequest); + + if (cbBuffer < cbWatchInfoExRequest) + { + lStatus = ERROR_INSUFFICIENT_BUFFER; + break; + } + + + //复制到新缓冲区 + for (int i = 0; i != ccWatchInfo; ++i) + { + lpWatchInfoEx[i].BasicInfo = pWatchInfo[i]; + lpWatchInfoEx[i].FaultingThreadId = 0; + lpWatchInfoEx[i].Flags = 0; + } + + //插入终止标记 + lpWatchInfoEx[ccWatchInfo] = PSAPI_WS_WATCH_INFORMATION_EX{}; + + lStatus = ERROR_SUCCESS; + break; + } + + if (pWatchInfo) + { + HeapFree(ProcessHeap, 0, pWatchInfo); + } + + if (lStatus == ERROR_SUCCESS) + { + return TRUE; + } + else + { + SetLastError(lStatus); + return FALSE; + } + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03SP1) - - //Windows Vista, Windows XP Professional x64 Edition [desktop apps only] - //Windows Server 2008, Windows Server 2003 with SP1 [desktop apps only] - __DEFINE_THUNK( - psapi, - 12, - BOOL, - WINAPI, - QueryWorkingSetEx, - _In_ HANDLE hProcess, - _Out_writes_bytes_(cb) PVOID pv, - _In_ DWORD cb - ) - { - if (const auto pQueryWorkingSetEx = try_get_QueryWorkingSetEx()) - { - return pQueryWorkingSetEx(hProcess, pv, cb); - } - else - { - SetLastError(ERROR_INVALID_FUNCTION); - return FALSE; - } - } +#if (YY_Thunks_Target < __WindowsNT5_2_SP1) + + //Windows Vista, Windows XP Professional x64 Edition [desktop apps only] + //Windows Server 2008, Windows Server 2003 with SP1 [desktop apps only] + __DEFINE_THUNK( + psapi, + 12, + BOOL, + WINAPI, + QueryWorkingSetEx, + _In_ HANDLE hProcess, + _Out_writes_bytes_(cb) PVOID pv, + _In_ DWORD cb + ) + { + if (const auto pQueryWorkingSetEx = try_get_QueryWorkingSetEx()) + { + return pQueryWorkingSetEx(hProcess, pv, cb); + } + else + { + SetLastError(ERROR_INVALID_FUNCTION); + return FALSE; + } + } #endif } //namespace YY::Thunks diff --git a/src/Thunks/shcore.hpp b/src/Thunks/shcore.hpp index 0a2aac6..2a8a6ef 100644 --- a/src/Thunks/shcore.hpp +++ b/src/Thunks/shcore.hpp @@ -1,74 +1,74 @@ -#if (YY_Thunks_Support_Version < NTDDI_WINBLUE) +#if (YY_Thunks_Target < __WindowsNT6_3) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WINBLUE) && !defined(__Comment_Lib_user32) +#if (YY_Thunks_Target < __WindowsNT6_3) && !defined(__Comment_Lib_user32) #define __Comment_Lib_user32 #pragma comment(lib, "User32.lib") #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WINBLUE) +#if (YY_Thunks_Target < __WindowsNT6_3) - //Windows 8.1 [desktop apps only] - //Windows Server 2012 R2 [desktop apps only] - __DEFINE_THUNK( - shcore, - 16, - HRESULT, - STDAPICALLTYPE, - GetDpiForMonitor, - _In_ HMONITOR hmonitor, - _In_ MONITOR_DPI_TYPE dpiType, - _Out_ UINT* dpiX, - _Out_ UINT* dpiY - ) - { - if (auto const pGetDpiForMonitor = try_get_GetDpiForMonitor()) - { - return pGetDpiForMonitor(hmonitor, dpiType, dpiX, dpiY); - } + //Windows 8.1 [desktop apps only] + //Windows Server 2012 R2 [desktop apps only] + __DEFINE_THUNK( + shcore, + 16, + HRESULT, + STDAPICALLTYPE, + GetDpiForMonitor, + _In_ HMONITOR hmonitor, + _In_ MONITOR_DPI_TYPE dpiType, + _Out_ UINT* dpiX, + _Out_ UINT* dpiY + ) + { + if (auto const pGetDpiForMonitor = try_get_GetDpiForMonitor()) + { + return pGetDpiForMonitor(hmonitor, dpiType, dpiX, dpiY); + } - if (dpiX == nullptr || dpiY == nullptr) - { - return __HRESULT_FROM_WIN32(ERROR_INVALID_ADDRESS); - } + if (dpiX == nullptr || dpiY == nullptr) + { + return __HRESULT_FROM_WIN32(ERROR_INVALID_ADDRESS); + } - auto DpiForSystem = internal::GetDpiForSystemDownlevel(); + auto DpiForSystem = internal::GetDpiForSystemDownlevel(); - *dpiX = DpiForSystem; - *dpiY = DpiForSystem; + *dpiX = DpiForSystem; + *dpiY = DpiForSystem; - return S_OK; - } + return S_OK; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WINBLUE) +#if (YY_Thunks_Target < __WindowsNT6_3) - //Windows 8.1 [desktop apps only] - //Windows Server 2012 R2 [desktop apps only] - __DEFINE_THUNK( - shcore, - 4, - HRESULT, - STDAPICALLTYPE, - SetProcessDpiAwareness, - _In_ PROCESS_DPI_AWARENESS value - ) - { - if (auto const pSetProcessDpiAwareness = try_get_SetProcessDpiAwareness()) - { - return pSetProcessDpiAwareness(value); - } + //Windows 8.1 [desktop apps only] + //Windows Server 2012 R2 [desktop apps only] + __DEFINE_THUNK( + shcore, + 4, + HRESULT, + STDAPICALLTYPE, + SetProcessDpiAwareness, + _In_ PROCESS_DPI_AWARENESS value + ) + { + if (auto const pSetProcessDpiAwareness = try_get_SetProcessDpiAwareness()) + { + return pSetProcessDpiAwareness(value); + } - if (value != PROCESS_DPI_UNAWARE) - { - return SetProcessDPIAware() ? S_OK : E_FAIL; - } + if (value != PROCESS_DPI_UNAWARE) + { + return SetProcessDPIAware() ? S_OK : E_FAIL; + } - return S_OK; - } + return S_OK; + } #endif } //namespace YY::Thunks diff --git a/src/Thunks/shell32.hpp b/src/Thunks/shell32.hpp index 2b8a0b1..4ac928f 100644 --- a/src/Thunks/shell32.hpp +++ b/src/Thunks/shell32.hpp @@ -1,9 +1,9 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) #include #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // FOLDERID_Windows #include @@ -11,521 +11,520 @@ #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_shell32) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_shell32) #define __Comment_Lib_shell32 #pragma comment(lib, "Shell32.lib") #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_ole32) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_ole32) #define __Comment_Lib_ole32 #pragma comment(lib, "Ole32.lib") #endif -namespace YY::Thunks +namespace YY::Thunks::internal { #ifdef YY_Thunks_Implemented - namespace internal + namespace { - namespace +#if (YY_Thunks_Target < __WindowsNT6) + struct KnownFoldersIdKey { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - struct KnownFoldersIdKey - { - const GUID& rfid; - const int csidl; - }; + const GUID& rfid; + const int csidl; + }; - static _Success_(return != -1) _Check_return_ int __fastcall KnownFolderFlagsToCsidlFlags(_In_ DWORD _uKnownFolderFlags) + static _Success_(return != -1) _Check_return_ int __fastcall KnownFolderFlagsToCsidlFlags(_In_ DWORD _uKnownFolderFlags) + { + // 参数验证 + // 1. KF_FLAG_NOT_PARENT_RELATIVE必须跟KF_FLAG_DEFAULT_PATH同时使用 + if (((KF_FLAG_NOT_PARENT_RELATIVE | KF_FLAG_DEFAULT_PATH) & _uKnownFolderFlags) == KF_FLAG_NOT_PARENT_RELATIVE) { - // 参数验证 - // 1. KF_FLAG_NOT_PARENT_RELATIVE必须跟KF_FLAG_DEFAULT_PATH同时使用 - if (((KF_FLAG_NOT_PARENT_RELATIVE | KF_FLAG_DEFAULT_PATH) & _uKnownFolderFlags) == KF_FLAG_NOT_PARENT_RELATIVE) - { - return -1; - } + return -1; + } - static_assert(KF_FLAG_CREATE == CSIDL_FLAG_CREATE, ""); - static_assert(KF_FLAG_DONT_VERIFY == CSIDL_FLAG_DONT_VERIFY, ""); - static_assert(KF_FLAG_DONT_UNEXPAND == CSIDL_FLAG_DONT_UNEXPAND, ""); - static_assert(KF_FLAG_NO_ALIAS == CSIDL_FLAG_NO_ALIAS, ""); - static_assert(KF_FLAG_INIT == CSIDL_FLAG_PER_USER_INIT, ""); + static_assert(KF_FLAG_CREATE == CSIDL_FLAG_CREATE, ""); + static_assert(KF_FLAG_DONT_VERIFY == CSIDL_FLAG_DONT_VERIFY, ""); + static_assert(KF_FLAG_DONT_UNEXPAND == CSIDL_FLAG_DONT_UNEXPAND, ""); + static_assert(KF_FLAG_NO_ALIAS == CSIDL_FLAG_NO_ALIAS, ""); + static_assert(KF_FLAG_INIT == CSIDL_FLAG_PER_USER_INIT, ""); - constexpr auto kWindows2KSupportCsidlFlags = CSIDL_FLAG_CREATE | CSIDL_FLAG_DONT_VERIFY | CSIDL_FLAG_DONT_UNEXPAND; - constexpr auto kWindowsXPSupportCsidlFlags = kWindows2KSupportCsidlFlags | CSIDL_FLAG_NO_ALIAS | CSIDL_FLAG_PER_USER_INIT; + constexpr auto kWindows2KSupportCsidlFlags = CSIDL_FLAG_CREATE | CSIDL_FLAG_DONT_VERIFY | CSIDL_FLAG_DONT_UNEXPAND; + constexpr auto kWindowsXPSupportCsidlFlags = kWindows2KSupportCsidlFlags | CSIDL_FLAG_NO_ALIAS | CSIDL_FLAG_PER_USER_INIT; -#if (YY_Thunks_Support_Version < NTDDI_WINXP) - if (internal::GetSystemVersion() < internal::MakeVersion(5, 1)) - { - return static_cast(_uKnownFolderFlags) & kWindows2KSupportCsidlFlags; - } - else +#if (YY_Thunks_Target < __WindowsNT5_1) + if (internal::GetSystemVersion() < internal::MakeVersion(5, 1)) + { + return static_cast(_uKnownFolderFlags) & kWindows2KSupportCsidlFlags; + } + else #endif - { - return static_cast(_uKnownFolderFlags) & kWindowsXPSupportCsidlFlags; - } + { + return static_cast(_uKnownFolderFlags) & kWindowsXPSupportCsidlFlags; } + } - //Vista以后的Shell32.dll 有个 kfapi::GetFolderIdByCSIDL,我们可以根据它可以反推出出 下面的KnownFoldersIdToCSIDL - static _Success_(return != -1) _Check_return_ int __fastcall KnownFoldersIdToCSIDL(const GUID& rfid) - { + //Vista以后的Shell32.dll 有个 kfapi::GetFolderIdByCSIDL,我们可以根据它可以反推出出 下面的KnownFoldersIdToCSIDL + static _Success_(return != -1) _Check_return_ int __fastcall KnownFoldersIdToCSIDL(const GUID& rfid) + { - constexpr static const KnownFoldersIdKey KnownFoldersIdsMap[] = - { - { FOLDERID_Windows, CSIDL_WINDOWS }, - { FOLDERID_ProgramFilesCommon, CSIDL_PROGRAM_FILES_COMMON }, - { FOLDERID_PublicDesktop, CSIDL_COMMON_DESKTOPDIRECTORY }, - { FOLDERID_CDBurning, CSIDL_CDBURN_AREA }, - { FOLDERID_CommonStartMenu, CSIDL_COMMON_STARTMENU }, - { FOLDERID_Videos, CSIDL_MYVIDEO }, - { FOLDERID_ProgramFilesCommonX86, CSIDL_PROGRAM_FILES_COMMONX86 }, - { FOLDERID_ConnectionsFolder, CSIDL_CONNECTIONS }, - { FOLDERID_PrintersFolder, CSIDL_PRINTERS }, - { FOLDERID_Pictures, CSIDL_MYPICTURES }, - { FOLDERID_ResourceDir, CSIDL_RESOURCES }, - { FOLDERID_CommonStartup, CSIDL_COMMON_STARTUP /*等价CSIDL_COMMON_ALTSTARTUP*/}, - { FOLDERID_PublicVideos, CSIDL_COMMON_VIDEO }, - { FOLDERID_Desktop, CSIDL_DESKTOP /*等价CSIDL_DESKTOPDIRECTORY*/}, - { FOLDERID_History, CSIDL_HISTORY }, - { FOLDERID_SamplePictures, CSIDL_COMMON_PICTURES }, //做个兼容处理吧,反正都是放图片的 - { FOLDERID_RecycleBinFolder, CSIDL_BITBUCKET }, - { FOLDERID_CommonPrograms, CSIDL_COMMON_PROGRAMS }, - { FOLDERID_NetHood, CSIDL_NETHOOD }, - { FOLDERID_Cookies, CSIDL_COOKIES }, - { FOLDERID_LocalizedResourcesDir, CSIDL_RESOURCES_LOCALIZED }, - { FOLDERID_Favorites, CSIDL_FAVORITES /*等价于CSIDL_COMMON_FAVORITES*/}, - { FOLDERID_SampleMusic, CSIDL_COMMON_MUSIC }, //做个兼容处理吧,反正都是放音乐的 - { FOLDERID_SendTo, CSIDL_SENDTO }, - { FOLDERID_AdminTools, CSIDL_ADMINTOOLS }, - { FOLDERID_Music, CSIDL_MYMUSIC }, - { FOLDERID_InternetFolder, CSIDL_INTERNET }, - { FOLDERID_System, CSIDL_SYSTEM }, - { FOLDERID_Programs, CSIDL_PROGRAMS }, + constexpr static const KnownFoldersIdKey KnownFoldersIdsMap[] = + { + { FOLDERID_Windows, CSIDL_WINDOWS }, + { FOLDERID_ProgramFilesCommon, CSIDL_PROGRAM_FILES_COMMON }, + { FOLDERID_PublicDesktop, CSIDL_COMMON_DESKTOPDIRECTORY }, + { FOLDERID_CDBurning, CSIDL_CDBURN_AREA }, + { FOLDERID_CommonStartMenu, CSIDL_COMMON_STARTMENU }, + { FOLDERID_Videos, CSIDL_MYVIDEO }, + { FOLDERID_ProgramFilesCommonX86, CSIDL_PROGRAM_FILES_COMMONX86 }, + { FOLDERID_ConnectionsFolder, CSIDL_CONNECTIONS }, + { FOLDERID_PrintersFolder, CSIDL_PRINTERS }, + { FOLDERID_Pictures, CSIDL_MYPICTURES }, + { FOLDERID_ResourceDir, CSIDL_RESOURCES }, + { FOLDERID_CommonStartup, CSIDL_COMMON_STARTUP /*等价CSIDL_COMMON_ALTSTARTUP*/}, + { FOLDERID_PublicVideos, CSIDL_COMMON_VIDEO }, + { FOLDERID_Desktop, CSIDL_DESKTOP /*等价CSIDL_DESKTOPDIRECTORY*/}, + { FOLDERID_History, CSIDL_HISTORY }, + { FOLDERID_SamplePictures, CSIDL_COMMON_PICTURES }, //做个兼容处理吧,反正都是放图片的 + { FOLDERID_RecycleBinFolder, CSIDL_BITBUCKET }, + { FOLDERID_CommonPrograms, CSIDL_COMMON_PROGRAMS }, + { FOLDERID_NetHood, CSIDL_NETHOOD }, + { FOLDERID_Cookies, CSIDL_COOKIES }, + { FOLDERID_LocalizedResourcesDir, CSIDL_RESOURCES_LOCALIZED }, + { FOLDERID_Favorites, CSIDL_FAVORITES /*等价于CSIDL_COMMON_FAVORITES*/}, + { FOLDERID_SampleMusic, CSIDL_COMMON_MUSIC }, //做个兼容处理吧,反正都是放音乐的 + { FOLDERID_SendTo, CSIDL_SENDTO }, + { FOLDERID_AdminTools, CSIDL_ADMINTOOLS }, + { FOLDERID_Music, CSIDL_MYMUSIC }, + { FOLDERID_InternetFolder, CSIDL_INTERNET }, + { FOLDERID_System, CSIDL_SYSTEM }, + { FOLDERID_Programs, CSIDL_PROGRAMS }, #ifdef _AMD64_ - { FOLDERID_ProgramFilesX64, CSIDL_PROGRAM_FILES }, //兼容下,反正 x64路径 跟 普通的是一样的。 + { FOLDERID_ProgramFilesX64, CSIDL_PROGRAM_FILES }, //兼容下,反正 x64路径 跟 普通的是一样的。 #endif - { FOLDERID_ComputerFolder, CSIDL_DRIVES }, - { FOLDERID_CommonAdminTools, CSIDL_COMMON_ADMINTOOLS }, - { FOLDERID_Recent, CSIDL_RECENT }, - { FOLDERID_ProgramData, CSIDL_COMMON_APPDATA }, - { FOLDERID_LocalAppData, CSIDL_LOCAL_APPDATA }, - { FOLDERID_PublicPictures, CSIDL_COMMON_PICTURES }, - { FOLDERID_PrintHood, CSIDL_PRINTHOOD }, - { FOLDERID_Profile, CSIDL_PROFILE }, - { FOLDERID_SampleVideos, CSIDL_COMMON_VIDEO }, //做个兼容处理吧,反正都是放视频的 - { FOLDERID_LocalAppDataLow, CSIDL_LOCAL_APPDATA }, //兼容下,直接用AppData + { FOLDERID_ComputerFolder, CSIDL_DRIVES }, + { FOLDERID_CommonAdminTools, CSIDL_COMMON_ADMINTOOLS }, + { FOLDERID_Recent, CSIDL_RECENT }, + { FOLDERID_ProgramData, CSIDL_COMMON_APPDATA }, + { FOLDERID_LocalAppData, CSIDL_LOCAL_APPDATA }, + { FOLDERID_PublicPictures, CSIDL_COMMON_PICTURES }, + { FOLDERID_PrintHood, CSIDL_PRINTHOOD }, + { FOLDERID_Profile, CSIDL_PROFILE }, + { FOLDERID_SampleVideos, CSIDL_COMMON_VIDEO }, //做个兼容处理吧,反正都是放视频的 + { FOLDERID_LocalAppDataLow, CSIDL_LOCAL_APPDATA }, //兼容下,直接用AppData #ifdef _AMD64_ - { FOLDERID_ProgramFilesCommonX64, CSIDL_PROGRAM_FILES_COMMON }, //兼容下,反正 x64路径 跟 普通的是一样的。 + { FOLDERID_ProgramFilesCommonX64, CSIDL_PROGRAM_FILES_COMMON }, //兼容下,反正 x64路径 跟 普通的是一样的。 #endif - { FOLDERID_PublicDocuments, CSIDL_COMMON_DOCUMENTS }, - { FOLDERID_SystemX86, CSIDL_SYSTEMX86 }, - { FOLDERID_PublicMusic, CSIDL_COMMON_MUSIC }, - { FOLDERID_ProgramFiles, CSIDL_PROGRAM_FILES }, - { FOLDERID_Fonts, CSIDL_FONTS }, - { FOLDERID_Startup, CSIDL_STARTUP /*等效CSIDL_ALTSTARTUP*/}, - { FOLDERID_StartMenu, CSIDL_STARTMENU }, - { FOLDERID_NetworkFolder, CSIDL_NETWORK /*等效CSIDL_COMPUTERSNEARME*/}, - { FOLDERID_Documents, CSIDL_MYDOCUMENTS }, - { FOLDERID_CommonOEMLinks, CSIDL_COMMON_OEM_LINKS }, - { FOLDERID_RoamingAppData, CSIDL_APPDATA }, - { FOLDERID_CommonTemplates, CSIDL_COMMON_TEMPLATES }, - { FOLDERID_InternetCache, CSIDL_INTERNET_CACHE }, - { FOLDERID_Templates, CSIDL_TEMPLATES }, - { FOLDERID_ControlPanelFolder, CSIDL_CONTROLS }, - { FOLDERID_ProgramFilesX86, CSIDL_PROGRAM_FILESX86 }, - - //{ FOLDERID_SyncManagerFolder, CSIDL_PRINTERS }, - //{ FOLDERID_SyncSetupFolder, CSIDL_PRINTERS }, - //{ FOLDERID_ConflictFolder, CSIDL_PRINTERS }, - //{ FOLDERID_SyncResultsFolder, CSIDL_PRINTERS }, - //{ FOLDERID_UserProgramFiles, CSIDL_PROGRAM_FILES_COMMON }, - //{ FOLDERID_UserProgramFilesCommon, CSIDL_PROGRAM_FILES_COMMON }, - //{ FOLDERID_Ringtones, CSIDL_MYVIDEO }, - //{ FOLDERID_PublicRingtones, CSIDL_COMMON_VIDEO }, - //{ FOLDERID_UserProfiles, CSIDL_CDBURN_AREA }, - //{ FOLDERID_Playlists, CSIDL_CDBURN_AREA }, - //{ FOLDERID_SamplePlaylists, CSIDL_CDBURN_AREA }, - //{ FOLDERID_PhotoAlbums, CSIDL_CDBURN_AREA }, - //{ FOLDERID_Public, CSIDL_CDBURN_AREA }, - //{ FOLDERID_ChangeRemovePrograms, CSIDL_CDBURN_AREA }, - //{ FOLDERID_AppUpdates, CSIDL_CDBURN_AREA }, - //{ FOLDERID_AddNewPrograms, CSIDL_CDBURN_AREA }, - //{ FOLDERID_Downloads, CSIDL_CDBURN_AREA }, - //{ FOLDERID_PublicDownloads, CSIDL_CDBURN_AREA }, - //{ FOLDERID_SavedSearches, CSIDL_CDBURN_AREA }, - //{ FOLDERID_QuickLaunch, CSIDL_CDBURN_AREA }, - //{ FOLDERID_Contacts, CSIDL_CDBURN_AREA }, - //{ FOLDERID_SidebarParts, CSIDL_CDBURN_AREA }, - //{ FOLDERID_SidebarDefaultParts, CSIDL_CDBURN_AREA }, - //{ FOLDERID_PublicGameTasks, CSIDL_CDBURN_AREA }, - //{ FOLDERID_GameTasks, CSIDL_CDBURN_AREA }, - //{ FOLDERID_SavedGames, CSIDL_CDBURN_AREA }, - //{ FOLDERID_Games, CSIDL_CDBURN_AREA }, - //{ FOLDERID_SEARCH_MAPI, CSIDL_CDBURN_AREA }, - //{ FOLDERID_SEARCH_CSC, CSIDL_CDBURN_AREA }, - //{ FOLDERID_Links, CSIDL_CDBURN_AREA }, - //{ FOLDERID_UsersFiles, CSIDL_CDBURN_AREA }, - //{ FOLDERID_UsersLibraries, CSIDL_CDBURN_AREA }, - //{ FOLDERID_SearchHome, CSIDL_CDBURN_AREA }, - //{ FOLDERID_OriginalImages, CSIDL_CDBURN_AREA }, - //{ FOLDERID_DocumentsLibrary, CSIDL_CDBURN_AREA }, - //{ FOLDERID_MusicLibrary, CSIDL_CDBURN_AREA }, - //{ FOLDERID_PicturesLibrary, CSIDL_CDBURN_AREA }, - //{ FOLDERID_VideosLibrary, CSIDL_CDBURN_AREA }, - //{ FOLDERID_RecordedTVLibrary, CSIDL_CDBURN_AREA }, - //{ FOLDERID_HomeGroup, CSIDL_CDBURN_AREA }, - //{ FOLDERID_HomeGroupCurrentUser, CSIDL_CDBURN_AREA }, - //{ FOLDERID_DeviceMetadataStore, CSIDL_CDBURN_AREA }, - //{ FOLDERID_Libraries, CSIDL_CDBURN_AREA }, - //{ FOLDERID_PublicLibraries, CSIDL_CDBURN_AREA }, - //{ FOLDERID_UserPinned, CSIDL_CDBURN_AREA }, - //{ FOLDERID_ImplicitAppShortcuts, CSIDL_CDBURN_AREA }, - //{ FOLDERID_AccountPictures, CSIDL_CDBURN_AREA }, - //{ FOLDERID_PublicUserTiles, CSIDL_CDBURN_AREA }, - //{ FOLDERID_AppsFolder, CSIDL_CDBURN_AREA }, - //{ FOLDERID_StartMenuAllPrograms, CSIDL_CDBURN_AREA }, - }; + { FOLDERID_PublicDocuments, CSIDL_COMMON_DOCUMENTS }, + { FOLDERID_SystemX86, CSIDL_SYSTEMX86 }, + { FOLDERID_PublicMusic, CSIDL_COMMON_MUSIC }, + { FOLDERID_ProgramFiles, CSIDL_PROGRAM_FILES }, + { FOLDERID_Fonts, CSIDL_FONTS }, + { FOLDERID_Startup, CSIDL_STARTUP /*等效CSIDL_ALTSTARTUP*/}, + { FOLDERID_StartMenu, CSIDL_STARTMENU }, + { FOLDERID_NetworkFolder, CSIDL_NETWORK /*等效CSIDL_COMPUTERSNEARME*/}, + { FOLDERID_Documents, CSIDL_MYDOCUMENTS }, + { FOLDERID_CommonOEMLinks, CSIDL_COMMON_OEM_LINKS }, + { FOLDERID_RoamingAppData, CSIDL_APPDATA }, + { FOLDERID_CommonTemplates, CSIDL_COMMON_TEMPLATES }, + { FOLDERID_InternetCache, CSIDL_INTERNET_CACHE }, + { FOLDERID_Templates, CSIDL_TEMPLATES }, + { FOLDERID_ControlPanelFolder, CSIDL_CONTROLS }, + { FOLDERID_ProgramFilesX86, CSIDL_PROGRAM_FILESX86 }, + + //{ FOLDERID_SyncManagerFolder, CSIDL_PRINTERS }, + //{ FOLDERID_SyncSetupFolder, CSIDL_PRINTERS }, + //{ FOLDERID_ConflictFolder, CSIDL_PRINTERS }, + //{ FOLDERID_SyncResultsFolder, CSIDL_PRINTERS }, + //{ FOLDERID_UserProgramFiles, CSIDL_PROGRAM_FILES_COMMON }, + //{ FOLDERID_UserProgramFilesCommon, CSIDL_PROGRAM_FILES_COMMON }, + //{ FOLDERID_Ringtones, CSIDL_MYVIDEO }, + //{ FOLDERID_PublicRingtones, CSIDL_COMMON_VIDEO }, + //{ FOLDERID_UserProfiles, CSIDL_CDBURN_AREA }, + //{ FOLDERID_Playlists, CSIDL_CDBURN_AREA }, + //{ FOLDERID_SamplePlaylists, CSIDL_CDBURN_AREA }, + //{ FOLDERID_PhotoAlbums, CSIDL_CDBURN_AREA }, + //{ FOLDERID_Public, CSIDL_CDBURN_AREA }, + //{ FOLDERID_ChangeRemovePrograms, CSIDL_CDBURN_AREA }, + //{ FOLDERID_AppUpdates, CSIDL_CDBURN_AREA }, + //{ FOLDERID_AddNewPrograms, CSIDL_CDBURN_AREA }, + //{ FOLDERID_Downloads, CSIDL_CDBURN_AREA }, + //{ FOLDERID_PublicDownloads, CSIDL_CDBURN_AREA }, + //{ FOLDERID_SavedSearches, CSIDL_CDBURN_AREA }, + //{ FOLDERID_QuickLaunch, CSIDL_CDBURN_AREA }, + //{ FOLDERID_Contacts, CSIDL_CDBURN_AREA }, + //{ FOLDERID_SidebarParts, CSIDL_CDBURN_AREA }, + //{ FOLDERID_SidebarDefaultParts, CSIDL_CDBURN_AREA }, + //{ FOLDERID_PublicGameTasks, CSIDL_CDBURN_AREA }, + //{ FOLDERID_GameTasks, CSIDL_CDBURN_AREA }, + //{ FOLDERID_SavedGames, CSIDL_CDBURN_AREA }, + //{ FOLDERID_Games, CSIDL_CDBURN_AREA }, + //{ FOLDERID_SEARCH_MAPI, CSIDL_CDBURN_AREA }, + //{ FOLDERID_SEARCH_CSC, CSIDL_CDBURN_AREA }, + //{ FOLDERID_Links, CSIDL_CDBURN_AREA }, + //{ FOLDERID_UsersFiles, CSIDL_CDBURN_AREA }, + //{ FOLDERID_UsersLibraries, CSIDL_CDBURN_AREA }, + //{ FOLDERID_SearchHome, CSIDL_CDBURN_AREA }, + //{ FOLDERID_OriginalImages, CSIDL_CDBURN_AREA }, + //{ FOLDERID_DocumentsLibrary, CSIDL_CDBURN_AREA }, + //{ FOLDERID_MusicLibrary, CSIDL_CDBURN_AREA }, + //{ FOLDERID_PicturesLibrary, CSIDL_CDBURN_AREA }, + //{ FOLDERID_VideosLibrary, CSIDL_CDBURN_AREA }, + //{ FOLDERID_RecordedTVLibrary, CSIDL_CDBURN_AREA }, + //{ FOLDERID_HomeGroup, CSIDL_CDBURN_AREA }, + //{ FOLDERID_HomeGroupCurrentUser, CSIDL_CDBURN_AREA }, + //{ FOLDERID_DeviceMetadataStore, CSIDL_CDBURN_AREA }, + //{ FOLDERID_Libraries, CSIDL_CDBURN_AREA }, + //{ FOLDERID_PublicLibraries, CSIDL_CDBURN_AREA }, + //{ FOLDERID_UserPinned, CSIDL_CDBURN_AREA }, + //{ FOLDERID_ImplicitAppShortcuts, CSIDL_CDBURN_AREA }, + //{ FOLDERID_AccountPictures, CSIDL_CDBURN_AREA }, + //{ FOLDERID_PublicUserTiles, CSIDL_CDBURN_AREA }, + //{ FOLDERID_AppsFolder, CSIDL_CDBURN_AREA }, + //{ FOLDERID_StartMenuAllPrograms, CSIDL_CDBURN_AREA }, + }; - int bottom = 0; - int top = _countof(KnownFoldersIdsMap) - 1; + int bottom = 0; + int top = _countof(KnownFoldersIdsMap) - 1; - while (bottom <= top) - { - int middle = (bottom + top) / 2; + while (bottom <= top) + { + int middle = (bottom + top) / 2; - auto& KnownFoldersId = KnownFoldersIdsMap[middle]; + auto& KnownFoldersId = KnownFoldersIdsMap[middle]; - int testIndex = memcmp(&rfid, &KnownFoldersId.rfid, sizeof(rfid)); + int testIndex = memcmp(&rfid, &KnownFoldersId.rfid, sizeof(rfid)); - if (testIndex == 0) - { - return KnownFoldersId.csidl; - } - if (testIndex < 0) - top = middle - 1; - else - bottom = middle + 1; + if (testIndex == 0) + { + return KnownFoldersId.csidl; } - - return -1; + if (testIndex < 0) + top = middle - 1; + else + bottom = middle + 1; } - static __forceinline PIDLIST_RELATIVE __fastcall ILCloneParent(LPCITEMIDLIST pidl) - { - auto pClone = ILClone(pidl); - if (pClone) - ILRemoveLastID(pClone); - - return pClone; - } + return -1; + } - static __forceinline HRESULT __fastcall SHILCloneParent(PCUIDLIST_RELATIVE pidl, PUIDLIST_RELATIVE* pidl_new) - { - auto Clone = ILCloneParent(pidl); - *pidl_new = Clone; - return Clone ? S_OK : E_OUTOFMEMORY; - } + static __forceinline PIDLIST_RELATIVE __fastcall ILCloneParent(LPCITEMIDLIST pidl) + { + auto pClone = ILClone(pidl); + if (pClone) + ILRemoveLastID(pClone); - static - HRESULT - STDAPICALLTYPE - SHBindToObject( - _In_opt_ IShellFolder* psf, - _In_ PCUIDLIST_RELATIVE pidl, - _In_opt_ IBindCtx* pbc, - _In_ REFIID riid, - _Outptr_ void** ppv - ) - { - *ppv = nullptr; + return pClone; + } - IShellFolder* ppshf; + static __forceinline HRESULT __fastcall SHILCloneParent(PCUIDLIST_RELATIVE pidl, PUIDLIST_RELATIVE* pidl_new) + { + auto Clone = ILCloneParent(pidl); + *pidl_new = Clone; + return Clone ? S_OK : E_OUTOFMEMORY; + } - auto hr = psf ? psf->QueryInterface(__uuidof(IShellFolder), (void**)&ppshf) : SHGetDesktopFolder(&ppshf); + static + HRESULT + STDAPICALLTYPE + SHBindToObject( + _In_opt_ IShellFolder* psf, + _In_ PCUIDLIST_RELATIVE pidl, + _In_opt_ IBindCtx* pbc, + _In_ REFIID riid, + _Outptr_ void** ppv + ) + { + *ppv = nullptr; - if (SUCCEEDED(hr)) - { - if (ILIsEmpty(pidl)) - { - hr = ppshf->QueryInterface(riid, ppv); - } - else - { - hr = ppshf->BindToObject(pidl, pbc, riid, ppv); - } + IShellFolder* ppshf; - if (SUCCEEDED(hr) && *ppv == nullptr) - hr = E_FAIL; + auto hr = psf ? psf->QueryInterface(__uuidof(IShellFolder), (void**)&ppshf) : SHGetDesktopFolder(&ppshf); - ppshf->Release(); + if (SUCCEEDED(hr)) + { + if (ILIsEmpty(pidl)) + { + hr = ppshf->QueryInterface(riid, ppv); + } + else + { + hr = ppshf->BindToObject(pidl, pbc, riid, ppv); } + if (SUCCEEDED(hr) && *ppv == nullptr) + hr = E_FAIL; - return hr; + ppshf->Release(); } - static - HRESULT - STDAPICALLTYPE - SHBindToFolderIDListParentEx( - _In_opt_ IShellFolder* psfRoot, - _In_ PCUIDLIST_RELATIVE pidl, - _In_opt_ IBindCtx* ppbc, - _In_ REFIID riid, - _Outptr_ void** ppv, - _Outptr_opt_ PCUITEMID_CHILD* ppidlLast - ) - { - *ppv = nullptr; - if (ppidlLast) - *ppidlLast = nullptr; - - HRESULT hr; - - if (pidl != nullptr) - { - if (psfRoot && ILIsChild(pidl)) - { - hr = psfRoot->QueryInterface(riid, ppv); - } - else - { - PUIDLIST_RELATIVE pidl_new; - hr = SHILCloneParent(pidl, &pidl_new); + return hr; + } - if (FAILED(hr)) - return hr; + static + HRESULT + STDAPICALLTYPE + SHBindToFolderIDListParentEx( + _In_opt_ IShellFolder* psfRoot, + _In_ PCUIDLIST_RELATIVE pidl, + _In_opt_ IBindCtx* ppbc, + _In_ REFIID riid, + _Outptr_ void** ppv, + _Outptr_opt_ PCUITEMID_CHILD* ppidlLast + ) + { + *ppv = nullptr; + if (ppidlLast) + *ppidlLast = nullptr; - hr = internal::SHBindToObject(psfRoot, pidl_new, ppbc, riid, ppv); + HRESULT hr; - ILFree(pidl_new); - } - - if (SUCCEEDED(hr) && ppidlLast) - *ppidlLast = ILFindLastID(pidl); + if (pidl != nullptr) + { + if (psfRoot && ILIsChild(pidl)) + { + hr = psfRoot->QueryInterface(riid, ppv); } else { - hr = E_INVALIDARG; - } + PUIDLIST_RELATIVE pidl_new; - return hr; - } + hr = SHILCloneParent(pidl, &pidl_new); - EXTERN_C __declspec(selectany) const CLSID CLSID_ShellItem = __uuidof(ShellItem); + if (FAILED(hr)) + return hr; - static HRESULT __fastcall CShellItem_CreateInstance(PCWSTR pszCLSID, const IID& riid, void** ppv) - { - *ppv = nullptr; + hr = internal::SHBindToObject(psfRoot, pidl_new, ppbc, riid, ppv); + + ILFree(pidl_new); + } - IShellItem* psi; + if (SUCCEEDED(hr) && ppidlLast) + *ppidlLast = ILFindLastID(pidl); + } + else + { + hr = E_INVALIDARG; + } - auto hr = SHCoCreateInstance(nullptr, &CLSID_ShellItem, nullptr, __uuidof(IShellItem), (void**)&psi); + return hr; + } - if (SUCCEEDED(hr)) - { - hr = psi->QueryInterface(riid, ppv); + EXTERN_C __declspec(selectany) const CLSID CLSID_ShellItem = __uuidof(ShellItem); - psi->Release(); - } + static HRESULT __fastcall CShellItem_CreateInstance(PCWSTR pszCLSID, const IID& riid, void** ppv) + { + *ppv = nullptr; - return hr; + IShellItem* psi; - } + auto hr = SHCoCreateInstance(nullptr, &CLSID_ShellItem, nullptr, __uuidof(IShellItem), (void**)&psi); - static - HRESULT - STDAPICALLTYPE - SHCreateItemFromIDList( - _In_ PCIDLIST_ABSOLUTE pidl, - _In_ REFIID riid, - _Outptr_ void** ppv - ) + if (SUCCEEDED(hr)) { - *ppv = nullptr; + hr = psi->QueryInterface(riid, ppv); - IPersistIDList* ppidl; + psi->Release(); + } - auto hr = CShellItem_CreateInstance(nullptr, __uuidof(IPersistIDList), (void**)&ppidl); + return hr; - if (SUCCEEDED(hr)) - { - hr = ppidl->SetIDList(pidl); + } - if (SUCCEEDED(hr)) - { - hr = ppidl->QueryInterface(riid, ppv); - } + static + HRESULT + STDAPICALLTYPE + SHCreateItemFromIDList( + _In_ PCIDLIST_ABSOLUTE pidl, + _In_ REFIID riid, + _Outptr_ void** ppv + ) + { + *ppv = nullptr; - ppidl->Release(); - } + IPersistIDList* ppidl; - return hr; - } + auto hr = CShellItem_CreateInstance(nullptr, __uuidof(IPersistIDList), (void**)&ppidl); - __forceinline - static - HRESULT - ParseDisplayNameChild( - IShellFolder* pShellFolder, - /* [unique][in] */ __RPC__in_opt HWND hwnd, - /* [unique][in] */ __RPC__in_opt IBindCtx* pbc, - /* [string][in] */ __RPC__in_string LPWSTR pszDisplayName, - /* [annotation][unique][out][in] */ - _Reserved_ ULONG* pchEaten, - /* [out] */ __RPC__deref_out_opt PIDLIST_RELATIVE* ppidl, - /* [unique][out][in] */ __RPC__inout_opt ULONG* pdwAttributes - ) + if (SUCCEEDED(hr)) { - *ppidl = nullptr; - - PIDLIST_RELATIVE pidl; - - auto hr = pShellFolder->ParseDisplayName(hwnd, pbc, pszDisplayName, pchEaten, &pidl, pdwAttributes); + hr = ppidl->SetIDList(pidl); if (SUCCEEDED(hr)) { - *ppidl = pidl; + hr = ppidl->QueryInterface(riid, ppv); } - return hr; + ppidl->Release(); } + return hr; + } + __forceinline static - HRESULT - STDAPICALLTYPE - SHCreateItemWithParent( - _In_opt_ PCIDLIST_ABSOLUTE pidlParent, - _In_opt_ IShellFolder* psfParent, - _In_ PCUITEMID_CHILD pidl, - _In_ REFIID riid, - _Outptr_ void** ppvItem - ) - { - *ppvItem = nullptr; + HRESULT + ParseDisplayNameChild( + IShellFolder* pShellFolder, + /* [unique][in] */ __RPC__in_opt HWND hwnd, + /* [unique][in] */ __RPC__in_opt IBindCtx* pbc, + /* [string][in] */ __RPC__in_string LPWSTR pszDisplayName, + /* [annotation][unique][out][in] */ + _Reserved_ ULONG* pchEaten, + /* [out] */ __RPC__deref_out_opt PIDLIST_RELATIVE* ppidl, + /* [unique][out][in] */ __RPC__inout_opt ULONG* pdwAttributes + ) + { + *ppidl = nullptr; - IParentAndItem* ppai; - auto hr = CShellItem_CreateInstance(nullptr, __uuidof(IParentAndItem), (void**)&ppai); + PIDLIST_RELATIVE pidl; - if (SUCCEEDED(hr)) - { - hr = ppai->SetParentAndItem(pidlParent, psfParent, pidl); + auto hr = pShellFolder->ParseDisplayName(hwnd, pbc, pszDisplayName, pchEaten, &pidl, pdwAttributes); - if (SUCCEEDED(hr)) - { - hr = ppai->QueryInterface(riid, ppvItem); - } + if (SUCCEEDED(hr)) + { + *ppidl = pidl; + } - ppai->Release(); - } + return hr; + } - return hr; - } - static - HRESULT - STDAPICALLTYPE - SHCreateItemFromRelativeName( - _In_ IShellItem* psiParent, - _In_ PCWSTR pszName, - _In_opt_ IBindCtx* pbc, - _In_ REFIID riid, - _Outptr_ void** ppv - ) - { - *ppv = nullptr; + static + HRESULT + STDAPICALLTYPE + SHCreateItemWithParent( + _In_opt_ PCIDLIST_ABSOLUTE pidlParent, + _In_opt_ IShellFolder* psfParent, + _In_ PCUITEMID_CHILD pidl, + _In_ REFIID riid, + _Outptr_ void** ppvItem + ) + { + *ppvItem = nullptr; - IShellFolder* pShellFolder; + IParentAndItem* ppai; + auto hr = CShellItem_CreateInstance(nullptr, __uuidof(IParentAndItem), (void**)&ppai); - auto hr = psiParent->BindToHandler(nullptr, BHID_SFObject, __uuidof(pShellFolder), (void**)&pShellFolder); + if (SUCCEEDED(hr)) + { + hr = ppai->SetParentAndItem(pidlParent, psfParent, pidl); if (SUCCEEDED(hr)) { - PIDLIST_RELATIVE pidl; + hr = ppai->QueryInterface(riid, ppvItem); + } - hr = internal::ParseDisplayNameChild(pShellFolder, nullptr, pbc, (LPWSTR)pszName, nullptr, &pidl, nullptr); + ppai->Release(); + } + return hr; + } - if (SUCCEEDED(hr)) - { - hr = internal::SHCreateItemWithParent(nullptr, pShellFolder, pidl, riid, ppv); + static + HRESULT + STDAPICALLTYPE + SHCreateItemFromRelativeName( + _In_ IShellItem* psiParent, + _In_ PCWSTR pszName, + _In_opt_ IBindCtx* pbc, + _In_ REFIID riid, + _Outptr_ void** ppv + ) + { + *ppv = nullptr; - ILFree(pidl); - } + IShellFolder* pShellFolder; + + auto hr = psiParent->BindToHandler(nullptr, BHID_SFObject, __uuidof(pShellFolder), (void**)&pShellFolder); + if (SUCCEEDED(hr)) + { + PIDLIST_RELATIVE pidl; - pShellFolder->Release(); + hr = internal::ParseDisplayNameChild(pShellFolder, nullptr, pbc, (LPWSTR)pszName, nullptr, &pidl, nullptr); + + if (SUCCEEDED(hr)) + { + hr = internal::SHCreateItemWithParent(nullptr, pShellFolder, pidl, riid, ppv); + + ILFree(pidl); } - return hr; + + pShellFolder->Release(); + } + return hr; + } + #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - static BOOL WINAPI ReadProcessMemory64( - _In_ HANDLE hProcess, - _In_ PVOID64 lpBaseAddress, - _Out_writes_bytes_to_(nSize, *lpNumberOfBytesRead) LPVOID lpBuffer, - _In_ ULONGLONG nSize, - _Out_opt_ PULONGLONG lpNumberOfBytesRead - ) - { +#if (YY_Thunks_Target < __WindowsNT6_1) + static BOOL WINAPI ReadProcessMemory64( + _In_ HANDLE hProcess, + _In_ PVOID64 lpBaseAddress, + _Out_writes_bytes_to_(nSize, *lpNumberOfBytesRead) LPVOID lpBuffer, + _In_ ULONGLONG nSize, + _Out_opt_ PULONGLONG lpNumberOfBytesRead + ) + { #if defined(_WIN64) - static_assert(sizeof(SIZE_T) == sizeof(*lpNumberOfBytesRead), ""); - return ::ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, reinterpret_cast(lpNumberOfBytesRead)); + static_assert(sizeof(SIZE_T) == sizeof(*lpNumberOfBytesRead), ""); + return ::ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, reinterpret_cast(lpNumberOfBytesRead)); #else - if (const auto _pfnNtWow64ReadVirtualMemory64 = try_get_NtWow64ReadVirtualMemory64()) - { - LONG _lStatus = _pfnNtWow64ReadVirtualMemory64(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead); - return _lStatus >= 0; - } - - *lpNumberOfBytesRead = 0; - return ::ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, (SIZE_T)nSize, reinterpret_cast(lpNumberOfBytesRead)); -#endif + if (const auto _pfnNtWow64ReadVirtualMemory64 = try_get_NtWow64ReadVirtualMemory64()) + { + LONG _lStatus = _pfnNtWow64ReadVirtualMemory64(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead); + return _lStatus >= 0; } + + *lpNumberOfBytesRead = 0; + return ::ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, (SIZE_T)nSize, reinterpret_cast(lpNumberOfBytesRead)); #endif } +#endif } #endif +} +namespace YY::Thunks +{ +#if (YY_Thunks_Target < __WindowsNT6) -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - shell32, - 16, - HRESULT, - STDAPICALLTYPE, - SHGetKnownFolderPath, - _In_ REFKNOWNFOLDERID rfid, - _In_ DWORD /* KNOWN_FOLDER_FLAG */ dwFlags, - _In_opt_ HANDLE hToken, - _Outptr_ PWSTR* ppszPath - ) - { - if (const auto pSHGetKnownFolderPath = try_get_SHGetKnownFolderPath()) - { - return pSHGetKnownFolderPath(rfid, dwFlags, hToken, ppszPath); - } + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + shell32, + 16, + HRESULT, + STDAPICALLTYPE, + SHGetKnownFolderPath, + _In_ REFKNOWNFOLDERID rfid, + _In_ DWORD /* KNOWN_FOLDER_FLAG */ dwFlags, + _In_opt_ HANDLE hToken, + _Outptr_ PWSTR* ppszPath + ) + { + if (const auto pSHGetKnownFolderPath = try_get_SHGetKnownFolderPath()) + { + return pSHGetKnownFolderPath(rfid, dwFlags, hToken, ppszPath); + } if (!ppszPath) { return E_POINTER; } - *ppszPath = nullptr; + *ppszPath = nullptr; const auto _iCsidl = internal::KnownFoldersIdToCSIDL(rfid); - if (_iCsidl == -1) - { - return __HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - } + if (_iCsidl == -1) + { + return __HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + } const auto _iCsidlFlags = internal::KnownFolderFlagsToCsidlFlags(dwFlags); if (_iCsidlFlags == -1) @@ -533,415 +532,415 @@ namespace YY::Thunks return E_INVALIDARG; } - auto pPathBuffer = (wchar_t*)CoTaskMemAlloc(MAX_PATH * sizeof(wchar_t)); - if (!pPathBuffer) - return E_OUTOFMEMORY; + auto pPathBuffer = (wchar_t*)CoTaskMemAlloc(MAX_PATH * sizeof(wchar_t)); + if (!pPathBuffer) + return E_OUTOFMEMORY; - auto hr = SHGetFolderPathW( + auto hr = SHGetFolderPathW( nullptr, _iCsidl | _iCsidlFlags, hToken, (KF_FLAG_DEFAULT_PATH & dwFlags) ? SHGFP_TYPE_DEFAULT : SHGFP_TYPE_CURRENT, pPathBuffer); - if (hr != S_OK) - { - CoTaskMemFree(pPathBuffer); - return hr; - } - - *ppszPath = pPathBuffer; - return S_OK; - } + if (hr != S_OK) + { + CoTaskMemFree(pPathBuffer); + return hr; + } + + *ppszPath = pPathBuffer; + return S_OK; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - shell32, - 16, - HRESULT, - STDAPICALLTYPE, - SHSetKnownFolderPath, - _In_ REFKNOWNFOLDERID rfid, - _In_ DWORD /* KNOWN_FOLDER_FLAG */ dwFlags, - _In_opt_ HANDLE hToken, - _In_ PCWSTR pszPath - ) - { - if (const auto pSHSetKnownFolderPath = try_get_SHSetKnownFolderPath()) - { - return pSHSetKnownFolderPath(rfid, dwFlags, hToken, pszPath); - } - - const auto _iCsidl = internal::KnownFoldersIdToCSIDL(rfid); - if (_iCsidl == -1) - { - return __HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + shell32, + 16, + HRESULT, + STDAPICALLTYPE, + SHSetKnownFolderPath, + _In_ REFKNOWNFOLDERID rfid, + _In_ DWORD /* KNOWN_FOLDER_FLAG */ dwFlags, + _In_opt_ HANDLE hToken, + _In_ PCWSTR pszPath + ) + { + if (const auto pSHSetKnownFolderPath = try_get_SHSetKnownFolderPath()) + { + return pSHSetKnownFolderPath(rfid, dwFlags, hToken, pszPath); + } + + const auto _iCsidl = internal::KnownFoldersIdToCSIDL(rfid); + if (_iCsidl == -1) + { + return __HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + } const auto _iCsidlFlags = internal::KnownFolderFlagsToCsidlFlags(dwFlags); if (_iCsidlFlags == -1) { return E_INVALIDARG; } - return SHSetFolderPathW(_iCsidl | _iCsidlFlags, hToken, 0u, pszPath); - } + return SHSetFolderPathW(_iCsidl | _iCsidlFlags, hToken, 0u, pszPath); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - shell32, - 16, - HRESULT, - STDAPICALLTYPE, - SHGetKnownFolderIDList, - _In_ REFKNOWNFOLDERID rfid, - _In_ DWORD /* KNOWN_FOLDER_FLAG */ dwFlags, - _In_opt_ HANDLE hToken, - _Outptr_ PIDLIST_ABSOLUTE *ppidl - ) - { - if (const auto pSHGetKnownFolderIDList = try_get_SHGetKnownFolderIDList()) - { - return pSHGetKnownFolderIDList(rfid, dwFlags, hToken, ppidl); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + shell32, + 16, + HRESULT, + STDAPICALLTYPE, + SHGetKnownFolderIDList, + _In_ REFKNOWNFOLDERID rfid, + _In_ DWORD /* KNOWN_FOLDER_FLAG */ dwFlags, + _In_opt_ HANDLE hToken, + _Outptr_ PIDLIST_ABSOLUTE *ppidl + ) + { + if (const auto pSHGetKnownFolderIDList = try_get_SHGetKnownFolderIDList()) + { + return pSHGetKnownFolderIDList(rfid, dwFlags, hToken, ppidl); + } if (!ppidl) { return E_POINTER; } *ppidl = nullptr; - const auto _iCsidl = internal::KnownFoldersIdToCSIDL(rfid); - if (_iCsidl == -1) - { - return __HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - } + const auto _iCsidl = internal::KnownFoldersIdToCSIDL(rfid); + if (_iCsidl == -1) + { + return __HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + } const auto _iCsidlFlags = internal::KnownFolderFlagsToCsidlFlags(dwFlags); if (_iCsidlFlags == -1) { return E_INVALIDARG; } - return SHGetFolderLocation(nullptr, _iCsidl | _iCsidlFlags, hToken, 0u, ppidl); - } + return SHGetFolderLocation(nullptr, _iCsidl | _iCsidlFlags, hToken, 0u, ppidl); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - shell32, - 20, - HRESULT, - STDAPICALLTYPE, - SHBindToFolderIDListParent, - _In_opt_ IShellFolder *psfRoot, - _In_ PCUIDLIST_RELATIVE pidl, - _In_ REFIID riid, - _Outptr_ void **ppv, - _Outptr_opt_ PCUITEMID_CHILD *ppidlLast - ) - { - if (const auto pSHBindToFolderIDListParent = try_get_SHBindToFolderIDListParent()) - { - return pSHBindToFolderIDListParent(psfRoot, pidl, riid, ppv, ppidlLast); - } - - return internal::SHBindToFolderIDListParentEx(psfRoot, pidl, nullptr, riid, ppv, ppidlLast); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + shell32, + 20, + HRESULT, + STDAPICALLTYPE, + SHBindToFolderIDListParent, + _In_opt_ IShellFolder *psfRoot, + _In_ PCUIDLIST_RELATIVE pidl, + _In_ REFIID riid, + _Outptr_ void **ppv, + _Outptr_opt_ PCUITEMID_CHILD *ppidlLast + ) + { + if (const auto pSHBindToFolderIDListParent = try_get_SHBindToFolderIDListParent()) + { + return pSHBindToFolderIDListParent(psfRoot, pidl, riid, ppv, ppidlLast); + } + + return internal::SHBindToFolderIDListParentEx(psfRoot, pidl, nullptr, riid, ppv, ppidlLast); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - shell32, - 24, - HRESULT, - STDAPICALLTYPE, - SHBindToFolderIDListParentEx, - _In_opt_ IShellFolder *psfRoot, - _In_ PCUIDLIST_RELATIVE pidl, - _In_opt_ IBindCtx *ppbc, - _In_ REFIID riid, - _Outptr_ void **ppv, - _Outptr_opt_ PCUITEMID_CHILD *ppidlLast - ) - { - if (const auto pSHBindToFolderIDListParentEx = try_get_SHBindToFolderIDListParentEx()) - { - return pSHBindToFolderIDListParentEx(psfRoot, pidl, ppbc, riid, ppv, ppidlLast); - } - - return internal::SHBindToFolderIDListParentEx(psfRoot, pidl, ppbc, riid, ppv, ppidlLast); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + shell32, + 24, + HRESULT, + STDAPICALLTYPE, + SHBindToFolderIDListParentEx, + _In_opt_ IShellFolder *psfRoot, + _In_ PCUIDLIST_RELATIVE pidl, + _In_opt_ IBindCtx *ppbc, + _In_ REFIID riid, + _Outptr_ void **ppv, + _Outptr_opt_ PCUITEMID_CHILD *ppidlLast + ) + { + if (const auto pSHBindToFolderIDListParentEx = try_get_SHBindToFolderIDListParentEx()) + { + return pSHBindToFolderIDListParentEx(psfRoot, pidl, ppbc, riid, ppv, ppidlLast); + } + + return internal::SHBindToFolderIDListParentEx(psfRoot, pidl, ppbc, riid, ppv, ppidlLast); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - shell32, - 20, - HRESULT, - STDAPICALLTYPE, - SHBindToObject, - _In_opt_ IShellFolder *psf, - _In_ PCUIDLIST_RELATIVE pidl, - _In_opt_ IBindCtx *pbc, - _In_ REFIID riid, - _Outptr_ void **ppv - ) - { - if (const auto pSHBindToObject = try_get_SHBindToObject()) - { - return pSHBindToObject(psf, pidl, pbc, riid, ppv); - } - - return internal::SHBindToObject(psf, pidl, pbc, riid, ppv); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + shell32, + 20, + HRESULT, + STDAPICALLTYPE, + SHBindToObject, + _In_opt_ IShellFolder *psf, + _In_ PCUIDLIST_RELATIVE pidl, + _In_opt_ IBindCtx *pbc, + _In_ REFIID riid, + _Outptr_ void **ppv + ) + { + if (const auto pSHBindToObject = try_get_SHBindToObject()) + { + return pSHBindToObject(psf, pidl, pbc, riid, ppv); + } + + return internal::SHBindToObject(psf, pidl, pbc, riid, ppv); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - shell32, - 12, - HRESULT, - STDAPICALLTYPE, - SHCreateItemFromIDList, - _In_ PCIDLIST_ABSOLUTE pidl, - _In_ REFIID riid, - _Outptr_ void **ppv - ) - { - if (const auto pSHCreateItemFromIDList = try_get_SHCreateItemFromIDList()) - { - return pSHCreateItemFromIDList(pidl, riid, ppv); - } - - - return internal::SHCreateItemFromIDList(pidl, riid, ppv); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + shell32, + 12, + HRESULT, + STDAPICALLTYPE, + SHCreateItemFromIDList, + _In_ PCIDLIST_ABSOLUTE pidl, + _In_ REFIID riid, + _Outptr_ void **ppv + ) + { + if (const auto pSHCreateItemFromIDList = try_get_SHCreateItemFromIDList()) + { + return pSHCreateItemFromIDList(pidl, riid, ppv); + } + + + return internal::SHCreateItemFromIDList(pidl, riid, ppv); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - shell32, - 20, - HRESULT, - STDAPICALLTYPE, - SHCreateItemWithParent, - _In_opt_ PCIDLIST_ABSOLUTE pidlParent, - _In_opt_ IShellFolder *psfParent, - _In_ PCUITEMID_CHILD pidl, - _In_ REFIID riid, - _Outptr_ void **ppvItem - ) - { - if (const auto pSHCreateItemWithParent = try_get_SHCreateItemWithParent()) - { - return pSHCreateItemWithParent(pidlParent, psfParent, pidl, riid, ppvItem); - } - - return internal::SHCreateItemWithParent(pidlParent, psfParent, pidl, riid, ppvItem); - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + shell32, + 20, + HRESULT, + STDAPICALLTYPE, + SHCreateItemWithParent, + _In_opt_ PCIDLIST_ABSOLUTE pidlParent, + _In_opt_ IShellFolder *psfParent, + _In_ PCUITEMID_CHILD pidl, + _In_ REFIID riid, + _Outptr_ void **ppvItem + ) + { + if (const auto pSHCreateItemWithParent = try_get_SHCreateItemWithParent()) + { + return pSHCreateItemWithParent(pidlParent, psfParent, pidl, riid, ppvItem); + } + + return internal::SHCreateItemWithParent(pidlParent, psfParent, pidl, riid, ppvItem); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - shell32, - 20, - HRESULT, - STDAPICALLTYPE, - SHCreateItemFromRelativeName, - _In_ IShellItem *psiParent, - _In_ PCWSTR pszName, - _In_opt_ IBindCtx* pbc, - _In_ REFIID riid, - _Outptr_ void **ppv - ) - { - if (const auto pSHCreateItemFromRelativeName = try_get_SHCreateItemFromRelativeName()) - { - return pSHCreateItemFromRelativeName(psiParent, pszName, pbc, riid, ppv); - } + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + shell32, + 20, + HRESULT, + STDAPICALLTYPE, + SHCreateItemFromRelativeName, + _In_ IShellItem *psiParent, + _In_ PCWSTR pszName, + _In_opt_ IBindCtx* pbc, + _In_ REFIID riid, + _Outptr_ void **ppv + ) + { + if (const auto pSHCreateItemFromRelativeName = try_get_SHCreateItemFromRelativeName()) + { + return pSHCreateItemFromRelativeName(psiParent, pszName, pbc, riid, ppv); + } - *ppv = nullptr; + *ppv = nullptr; - IShellFolder* pShellFolder; + IShellFolder* pShellFolder; - auto hr = psiParent->BindToHandler(nullptr, BHID_SFObject, __uuidof(pShellFolder), (void**)&pShellFolder); + auto hr = psiParent->BindToHandler(nullptr, BHID_SFObject, __uuidof(pShellFolder), (void**)&pShellFolder); - if (SUCCEEDED(hr)) - { - PIDLIST_RELATIVE pidl; + if (SUCCEEDED(hr)) + { + PIDLIST_RELATIVE pidl; - hr = internal::ParseDisplayNameChild(pShellFolder, nullptr, pbc, (LPWSTR)pszName, nullptr, &pidl, nullptr); + hr = internal::ParseDisplayNameChild(pShellFolder, nullptr, pbc, (LPWSTR)pszName, nullptr, &pidl, nullptr); - if (SUCCEEDED(hr)) - { - hr = internal::SHCreateItemWithParent(nullptr, pShellFolder, pidl, riid, ppv); - ILFree(pidl); - } + if (SUCCEEDED(hr)) + { + hr = internal::SHCreateItemWithParent(nullptr, pShellFolder, pidl, riid, ppv); + ILFree(pidl); + } - pShellFolder->Release(); - } + pShellFolder->Release(); + } - return hr; - } + return hr; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - shell32, - 12, - HRESULT, - STDAPICALLTYPE, - SHGetNameFromIDList, - _In_ PCIDLIST_ABSOLUTE pidl, - _In_ SIGDN sigdnName, - _Outptr_ PWSTR *ppszName - ) - { - if (const auto pSHGetNameFromIDList = try_get_SHGetNameFromIDList()) - { - return pSHGetNameFromIDList(pidl, sigdnName, ppszName); - } + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + shell32, + 12, + HRESULT, + STDAPICALLTYPE, + SHGetNameFromIDList, + _In_ PCIDLIST_ABSOLUTE pidl, + _In_ SIGDN sigdnName, + _Outptr_ PWSTR *ppszName + ) + { + if (const auto pSHGetNameFromIDList = try_get_SHGetNameFromIDList()) + { + return pSHGetNameFromIDList(pidl, sigdnName, ppszName); + } - *ppszName = NULL; + *ppszName = NULL; - IShellItem* ppsi; + IShellItem* ppsi; - - auto hr = internal::SHCreateItemFromIDList(pidl, __uuidof(ppsi), (void**)&ppsi); + + auto hr = internal::SHCreateItemFromIDList(pidl, __uuidof(ppsi), (void**)&ppsi); - if (SUCCEEDED(hr)) - { - hr = ppsi->GetDisplayName(sigdnName, ppszName); + if (SUCCEEDED(hr)) + { + hr = ppsi->GetDisplayName(sigdnName, ppszName); - ppsi->Release(); - } + ppsi->Release(); + } - return hr; - } + return hr; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WINXPSP1) - - //Windows XP with SP1 [desktop apps only] - //Windows Server 2003 [desktop apps only] - __DEFINE_THUNK( - shell32, - 16, - HRESULT, - STDAPICALLTYPE, - SHCreateShellItem, - _In_opt_ PCIDLIST_ABSOLUTE pidlParent, - _In_opt_ IShellFolder *psfParent, - _In_ PCUITEMID_CHILD pidl, - _Outptr_ IShellItem **ppsi - ) - { - if (const auto pSHCreateShellItem = try_get_SHCreateShellItem()) - { - return pSHCreateShellItem(pidlParent, psfParent, pidl, ppsi); - } - - *ppsi = nullptr; - - if (pidlParent || psfParent) - return internal::SHCreateItemWithParent(pidlParent, psfParent, pidl, __uuidof(IShellItem), (void**)ppsi); - else - return internal::SHCreateItemFromIDList(pidl, __uuidof(IShellItem), (void**)ppsi); - } +#if (YY_Thunks_Target < __WindowsNT5_1_SP1) + + //Windows XP with SP1 [desktop apps only] + //Windows Server 2003 [desktop apps only] + __DEFINE_THUNK( + shell32, + 16, + HRESULT, + STDAPICALLTYPE, + SHCreateShellItem, + _In_opt_ PCIDLIST_ABSOLUTE pidlParent, + _In_opt_ IShellFolder *psfParent, + _In_ PCUITEMID_CHILD pidl, + _Outptr_ IShellItem **ppsi + ) + { + if (const auto pSHCreateShellItem = try_get_SHCreateShellItem()) + { + return pSHCreateShellItem(pidlParent, psfParent, pidl, ppsi); + } + + *ppsi = nullptr; + + if (pidlParent || psfParent) + return internal::SHCreateItemWithParent(pidlParent, psfParent, pidl, __uuidof(IShellItem), (void**)ppsi); + else + return internal::SHCreateItemFromIDList(pidl, __uuidof(IShellItem), (void**)ppsi); + } #endif - - -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Minimum supported client Windows Vista [desktop apps only] - //Minimum supported server Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - shell32, - 16, - HRESULT, - STDAPICALLTYPE, - SHCreateItemFromParsingName, - _In_ PCWSTR pszPath, - _In_opt_ IBindCtx* pbc, - _In_ REFIID riid, - _Outptr_ void** ppv - ) - { - if (const auto pSHCreateItemFromParsingName = try_get_SHCreateItemFromParsingName()) - { - return pSHCreateItemFromParsingName(pszPath, pbc, riid, ppv); - } - - *ppv = nullptr; - - PIDLIST_ABSOLUTE pidl; - auto hr = ::SHParseDisplayName(pszPath, pbc, &pidl, 0, nullptr); - if (SUCCEEDED(hr)) - { - hr = internal::SHCreateItemFromIDList(pidl, riid, ppv); - - ILFree(pidl); - } - - return hr; - } + + +#if (YY_Thunks_Target < __WindowsNT6) + + //Minimum supported client Windows Vista [desktop apps only] + //Minimum supported server Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + shell32, + 16, + HRESULT, + STDAPICALLTYPE, + SHCreateItemFromParsingName, + _In_ PCWSTR pszPath, + _In_opt_ IBindCtx* pbc, + _In_ REFIID riid, + _Outptr_ void** ppv + ) + { + if (const auto pSHCreateItemFromParsingName = try_get_SHCreateItemFromParsingName()) + { + return pSHCreateItemFromParsingName(pszPath, pbc, riid, ppv); + } + + *ppv = nullptr; + + PIDLIST_ABSOLUTE pidl; + auto hr = ::SHParseDisplayName(pszPath, pbc, &pidl, 0, nullptr); + if (SUCCEEDED(hr)) + { + hr = internal::SHCreateItemFromIDList(pidl, riid, ppv); + + ILFree(pidl); + } + + return hr; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) - // 最低受支持的客户端 Windows 7 [仅限桌面应用] + // 最低受支持的客户端 Windows 7 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] - __DEFINE_THUNK( - shell32, - 8, - HRESULT, - STDAPICALLTYPE, - Shell_NotifyIconGetRect, + __DEFINE_THUNK( + shell32, + 8, + HRESULT, + STDAPICALLTYPE, + Shell_NotifyIconGetRect, _In_ const NOTIFYICONIDENTIFIER* _pIdentifier, _Out_ RECT* _pIconLocation ) - { - if (const auto _pfnShell_NotifyIconGetRect = try_get_Shell_NotifyIconGetRect()) - { - return _pfnShell_NotifyIconGetRect(_pIdentifier, _pIconLocation); - } + { + if (const auto _pfnShell_NotifyIconGetRect = try_get_Shell_NotifyIconGetRect()) + { + return _pfnShell_NotifyIconGetRect(_pIdentifier, _pIconLocation); + } if (!_pIconLocation) { @@ -1141,12 +1140,12 @@ namespace YY::Thunks if(_hTrayProcess) CloseHandle(_hTrayProcess); - return _hr; - } + return _hr; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#if (YY_Thunks_Target < __WindowsNT6_1) // 最低受支持的客户端 Windows 7 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] @@ -1174,7 +1173,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -1198,7 +1197,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] diff --git a/src/Thunks/shlwapi.hpp b/src/Thunks/shlwapi.hpp index 74ac13d..814568c 100644 --- a/src/Thunks/shlwapi.hpp +++ b/src/Thunks/shlwapi.hpp @@ -1,177 +1,177 @@ - +#if (YY_Thunks_Target < __WindowsNT5_1) #include - -namespace YY -{ - namespace Thunks - { +#endif #ifdef YY_Thunks_Implemented - namespace internal - { - template - static - _Success_(return) - BOOL - WINAPI - StrToInt64ExT( - _In_ const Char* pszString, - _In_ STIF_FLAGS dwFlags, - _Out_ LONGLONG* pllRet - ) - { - if (!pszString) - return FALSE; - - - for (; ; ++pszString) - { - const auto ch = *pszString; - - if (ch == Char(' ') || ch == Char('\n') || ch == Char('\t')) - { - continue; - } - - break; - } - - bool Sign = true; - if (*pszString == Char('+')) - { - ++pszString; - } - else if (*pszString == Char('-')) - { - ++pszString; - Sign = false; - } - - ULONGLONG result = 0; - - if (dwFlags & STIF_SUPPORT_HEX) - { - //二种形式0x????, 0X????? - if (*pszString == Char('0') && (pszString[1] == Char('x') || pszString[1] == Char('X'))) - { - pszString += 2; - - for (auto String = pszString; ; ++String) - { - const auto ch = *String; - if (ch >= Char('0') && ch <= Char('9')) - { - result = (result << 4) | ((ULONGLONG)ch - Char('0')); - } - else if (ch >= Char('a') && ch <= Char('f')) - { - result = (result << 4) | ((ULONGLONG)ch - Char('a') + 10); - } - else if (ch >= Char('A') && ch <= Char('F')) - { - result = (result << 4) | ((ULONGLONG)ch - Char('A') + 10); - } - else - { - if (String == pszString) - { - return FALSE; - } - - if (pllRet) - { - *pllRet = result; - } - - return TRUE; - } - } - } - } - - for (auto String = pszString; ; ++String) - { - const auto ch = *String; - if (ch >= Char('0') && ch <= ('9')) - { - result = (result * 10) + ((ULONGLONG)ch - Char('0')); - } - else - { - if (String == pszString) - { - return FALSE; - } - - if (pllRet) - { - if (!Sign) - { - result = ~result + 1; - } - - *pllRet = result; - } - - return TRUE; - } - } - - return FALSE; - } - } +namespace YY::Thunks::internal +{ + namespace + { + template + static + _Success_(return) + BOOL + WINAPI + StrToInt64ExT( + _In_ const Char* pszString, + _In_ STIF_FLAGS dwFlags, + _Out_ LONGLONG* pllRet + ) + { + if (!pszString) + return FALSE; + + + for (; ; ++pszString) + { + const auto ch = *pszString; + + if (ch == Char(' ') || ch == Char('\n') || ch == Char('\t')) + { + continue; + } + + break; + } + + bool Sign = true; + if (*pszString == Char('+')) + { + ++pszString; + } + else if (*pszString == Char('-')) + { + ++pszString; + Sign = false; + } + + ULONGLONG result = 0; + + if (dwFlags & STIF_SUPPORT_HEX) + { + //二种形式0x????, 0X????? + if (*pszString == Char('0') && (pszString[1] == Char('x') || pszString[1] == Char('X'))) + { + pszString += 2; + + for (auto String = pszString; ; ++String) + { + const auto ch = *String; + if (ch >= Char('0') && ch <= Char('9')) + { + result = (result << 4) | ((ULONGLONG)ch - Char('0')); + } + else if (ch >= Char('a') && ch <= Char('f')) + { + result = (result << 4) | ((ULONGLONG)ch - Char('a') + 10); + } + else if (ch >= Char('A') && ch <= Char('F')) + { + result = (result << 4) | ((ULONGLONG)ch - Char('A') + 10); + } + else + { + if (String == pszString) + { + return FALSE; + } + + if (pllRet) + { + *pllRet = result; + } + + return TRUE; + } + } + } + } + + for (auto String = pszString; ; ++String) + { + const auto ch = *String; + if (ch >= Char('0') && ch <= ('9')) + { + result = (result * 10) + ((ULONGLONG)ch - Char('0')); + } + else + { + if (String == pszString) + { + return FALSE; + } + + if (pllRet) + { + if (!Sign) + { + result = ~result + 1; + } + + *pllRet = result; + } + + return TRUE; + } + } + + return FALSE; + } + } +} #endif -#if (YY_Thunks_Support_Version < NTDDI_WINXP) - - // Windows 2000 Professional, Windows XP [desktop apps only] - // Windows 2000 Server [desktop apps only] - // 虽然Windows 2000支持,但是在IE6里面而IE6不一定所有Windows 2000都有,因此低于5.1我们就静态引入。 - __DEFINE_THUNK( - shlwapi, - 12, - BOOL, - WINAPI, - StrToInt64ExA, - _In_ PCSTR pszString, - STIF_FLAGS dwFlags, - _Out_ LONGLONG* pllRet - ) - { - if (const auto pStrToInt64ExA = try_get_StrToInt64ExA()) - { - return pStrToInt64ExA(pszString, dwFlags, pllRet); - } - - return internal::StrToInt64ExT(pszString, dwFlags, pllRet); - } -#endif //YY_Thunks_Support_Version < NTDDI_WINXP - - -#if (YY_Thunks_Support_Version < NTDDI_WINXP) - - // Windows 2000 Professional, Windows XP [desktop apps only] - // Windows 2000 Server [desktop apps only] - // 虽然Windows 2000支持,但是在IE6里面而IE6不一定所有Windows 2000都有,因此低于5.1我们就静态引入。 - __DEFINE_THUNK( - shlwapi, - 12, - BOOL, - WINAPI, - StrToInt64ExW, - _In_ PCWSTR pszString, - STIF_FLAGS dwFlags, - _Out_ LONGLONG* pllRet - ) - { - if (const auto pStrToInt64ExW = try_get_StrToInt64ExW()) - { - return pStrToInt64ExW(pszString, dwFlags, pllRet); - } - - return internal::StrToInt64ExT(pszString, dwFlags, pllRet); - } -#endif //YY_Thunks_Support_Version < NTDDI_WINXP - } -} \ No newline at end of file +namespace YY::Thunks +{ +#if (YY_Thunks_Target < __WindowsNT5_1) + + // Windows 2000 Professional, Windows XP [desktop apps only] + // Windows 2000 Server [desktop apps only] + // 虽然Windows 2000支持,但是在IE6里面而IE6不一定所有Windows 2000都有,因此低于5.1我们就静态引入。 + __DEFINE_THUNK( + shlwapi, + 12, + BOOL, + WINAPI, + StrToInt64ExA, + _In_ PCSTR pszString, + STIF_FLAGS dwFlags, + _Out_ LONGLONG* pllRet + ) + { + if (const auto pStrToInt64ExA = try_get_StrToInt64ExA()) + { + return pStrToInt64ExA(pszString, dwFlags, pllRet); + } + + return internal::StrToInt64ExT(pszString, dwFlags, pllRet); + } +#endif //YY_Thunks_Target < __WindowsNT5_1 + + +#if (YY_Thunks_Target < __WindowsNT5_1) + + // Windows 2000 Professional, Windows XP [desktop apps only] + // Windows 2000 Server [desktop apps only] + // 虽然Windows 2000支持,但是在IE6里面而IE6不一定所有Windows 2000都有,因此低于5.1我们就静态引入。 + __DEFINE_THUNK( + shlwapi, + 12, + BOOL, + WINAPI, + StrToInt64ExW, + _In_ PCWSTR pszString, + STIF_FLAGS dwFlags, + _Out_ LONGLONG* pllRet + ) + { + if (const auto pStrToInt64ExW = try_get_StrToInt64ExW()) + { + return pStrToInt64ExW(pszString, dwFlags, pllRet); + } + + return internal::StrToInt64ExT(pszString, dwFlags, pllRet); + } +#endif //YY_Thunks_Target < __WindowsNT5_1 +} diff --git a/src/Thunks/user32.hpp b/src/Thunks/user32.hpp index c87a530..10b16de 100644 --- a/src/Thunks/user32.hpp +++ b/src/Thunks/user32.hpp @@ -1,18 +1,18 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS2) +#if (YY_Thunks_Target < __WindowsNT10_15063) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS1) && !defined(__Comment_Lib_user32) +#if (YY_Thunks_Target < __WindowsNT10_14393) && !defined(__Comment_Lib_user32) #define __Comment_Lib_user32 #pragma comment(lib, "User32.lib") #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS2) && (YY_Thunks_Support_Version >= NTDDI_WINBLUE || __YY_Thunks_libs) && !defined(__Comment_Lib_shcore) +#if (YY_Thunks_Target < __WindowsNT10_15063) && (YY_Thunks_Target >= __WindowsNT6_3 || __YY_Thunks_libs) && !defined(__Comment_Lib_shcore) #define __Comment_Lib_shcore #pragma comment(lib, "Shcore.lib") #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS1) && !defined(__Comment_Lib_gdi32) +#if (YY_Thunks_Target < __WindowsNT10_14393) && !defined(__Comment_Lib_gdi32) #define __Comment_Lib_gdi32 #pragma comment(lib, "Gdi32.lib") #endif @@ -20,697 +20,698 @@ #if defined(YY_Thunks_Implemented) namespace YY::Thunks::internal { - namespace - { -#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS1) - static UINT __fastcall GetDpiForSystemDownlevel() - { - static int nDPICache = 0; - - if (nDPICache) - { - return nDPICache; - } - - int nDpiX = USER_DEFAULT_SCREEN_DPI; - - if (HDC hdc = GetDC(NULL)) - { - nDpiX = GetDeviceCaps(hdc, LOGPIXELSX); - ReleaseDC(NULL, hdc); - } - - return nDPICache = nDpiX; - } + namespace + { +#if (YY_Thunks_Target < __WindowsNT10_14393) + static UINT __fastcall GetDpiForSystemDownlevel() + { + static int nDPICache = 0; + + if (nDPICache) + { + return nDPICache; + } + + int nDpiX = USER_DEFAULT_SCREEN_DPI; + + if (HDC hdc = GetDC(NULL)) + { + nDpiX = GetDeviceCaps(hdc, LOGPIXELSX); + ReleaseDC(NULL, hdc); + } + + return nDPICache = nDpiX; + } #endif - } + } } #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WS03SP1) - - //Windows XP with SP2, Windows Server 2003 with SP1 - __DEFINE_THUNK( - user32, - 0, - BOOL, - WINAPI, - IsWow64Message, - VOID - ) - { - if (auto const pIsWow64Message = try_get_IsWow64Message()) - { - return pIsWow64Message(); - } - - return FALSE; - } +#if (YY_Thunks_Target < __WindowsNT5_2_SP1) + + //Windows XP with SP2, Windows Server 2003 with SP1 + __DEFINE_THUNK( + user32, + 0, + BOOL, + WINAPI, + IsWow64Message, + VOID + ) + { + if (auto const pIsWow64Message = try_get_IsWow64Message()) + { + return pIsWow64Message(); + } + + return FALSE; + } #endif - - -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - // 最低受支持的客户端 Windows Vista [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] - __DEFINE_THUNK( - user32, - 0, - BOOL, - WINAPI, - IsProcessDPIAware, - void) - { - if (const auto _pfnIsProcessDPIAware = try_get_IsProcessDPIAware()) - { - return _pfnIsProcessDPIAware(); - } - - // XP 无法感知DPI,返回的Rect始终被系统缩放了。 - return FALSE; - } + + +#if (YY_Thunks_Target < __WindowsNT6) + + // 最低受支持的客户端 Windows Vista [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] + __DEFINE_THUNK( + user32, + 0, + BOOL, + WINAPI, + IsProcessDPIAware, + void) + { + if (const auto _pfnIsProcessDPIAware = try_get_IsProcessDPIAware()) + { + return _pfnIsProcessDPIAware(); + } + + // XP 无法感知DPI,返回的Rect始终被系统缩放了。 + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - user32, - 0, - BOOL, - WINAPI, - SetProcessDPIAware, - VOID - ) - { - if (auto const pSetProcessDPIAware = try_get_SetProcessDPIAware()) - { - return pSetProcessDPIAware(); - } - - // 假装成功,其实我们都知道,我们没有成功…… - // XP系统无法感知 DPI - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT6) + + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + user32, + 0, + BOOL, + WINAPI, + SetProcessDPIAware, + VOID + ) + { + if (auto const pSetProcessDPIAware = try_get_SetProcessDPIAware()) + { + return pSetProcessDPIAware(); + } + + // 假装成功,其实我们都知道,我们没有成功…… + // XP系统无法感知 DPI + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS2) - - //Windows 10, version 1703 [desktop apps only] - //Windows Server 2016 [desktop apps only] - __DEFINE_THUNK( - user32, - 4, - BOOL, - WINAPI, - SetProcessDpiAwarenessContext, - _In_ DPI_AWARENESS_CONTEXT value - ) - { - if (auto const pSetProcessDpiAwarenessContext = try_get_SetProcessDpiAwarenessContext()) - { - return pSetProcessDpiAwarenessContext(value); - } - - LSTATUS lStatus; - - do - { - PROCESS_DPI_AWARENESS DpiAwareness; - - if (DPI_AWARENESS_CONTEXT_UNAWARE == value - || DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED == value) - { - DpiAwareness = PROCESS_DPI_UNAWARE; - } - else if (DPI_AWARENESS_CONTEXT_SYSTEM_AWARE == value) - { - DpiAwareness = PROCESS_SYSTEM_DPI_AWARE; - } - else if (DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE == value - || DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 == value) - { - DpiAwareness = PROCESS_PER_MONITOR_DPI_AWARE; - } - else - { - lStatus = ERROR_INVALID_PARAMETER; - break; - } - - auto hr = SetProcessDpiAwareness(DpiAwareness); - - if (SUCCEEDED(hr)) - { - return TRUE; - } - - //将 HRESULT 错误代码转换到 LSTATUS - if (hr & 0xFFFF0000) - { - if (HRESULT_FACILITY(hr) == FACILITY_WIN32) - { - lStatus = HRESULT_CODE(hr); - } - else - { - lStatus = ERROR_FUNCTION_FAILED; - } - } - else - { - lStatus = hr; - } - - } while (false); - - - SetLastError(lStatus); - return FALSE; - } +#if (YY_Thunks_Target < __WindowsNT10_15063) + + //Windows 10, version 1703 [desktop apps only] + //Windows Server 2016 [desktop apps only] + __DEFINE_THUNK( + user32, + 4, + BOOL, + WINAPI, + SetProcessDpiAwarenessContext, + _In_ DPI_AWARENESS_CONTEXT value + ) + { + if (auto const pSetProcessDpiAwarenessContext = try_get_SetProcessDpiAwarenessContext()) + { + return pSetProcessDpiAwarenessContext(value); + } + + LSTATUS lStatus; + + do + { + PROCESS_DPI_AWARENESS DpiAwareness; + + if (DPI_AWARENESS_CONTEXT_UNAWARE == value + || DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED == value) + { + DpiAwareness = PROCESS_DPI_UNAWARE; + } + else if (DPI_AWARENESS_CONTEXT_SYSTEM_AWARE == value) + { + DpiAwareness = PROCESS_SYSTEM_DPI_AWARE; + } + else if (DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE == value + || DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 == value) + { + DpiAwareness = PROCESS_PER_MONITOR_DPI_AWARE; + } + else + { + lStatus = ERROR_INVALID_PARAMETER; + break; + } + + auto hr = SetProcessDpiAwareness(DpiAwareness); + + if (SUCCEEDED(hr)) + { + return TRUE; + } + + //将 HRESULT 错误代码转换到 LSTATUS + if (hr & 0xFFFF0000) + { + if (HRESULT_FACILITY(hr) == FACILITY_WIN32) + { + lStatus = HRESULT_CODE(hr); + } + else + { + lStatus = ERROR_FUNCTION_FAILED; + } + } + else + { + lStatus = hr; + } + + } while (false); + + + SetLastError(lStatus); + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS1) - - //Windows 10, version 1607 [desktop apps only] - __DEFINE_THUNK( - user32, - 0, - UINT, - WINAPI, - GetDpiForSystem, - VOID - ) - { - if (auto const pGetDpiForSystem = try_get_GetDpiForSystem()) - { - return pGetDpiForSystem(); - } - - return internal::GetDpiForSystemDownlevel(); - } +#if (YY_Thunks_Target < __WindowsNT10_14393) + + //Windows 10, version 1607 [desktop apps only] + __DEFINE_THUNK( + user32, + 0, + UINT, + WINAPI, + GetDpiForSystem, + VOID + ) + { + if (auto const pGetDpiForSystem = try_get_GetDpiForSystem()) + { + return pGetDpiForSystem(); + } + + return internal::GetDpiForSystemDownlevel(); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS1) - - //Windows 10, version 1607 [desktop apps only] - __DEFINE_THUNK( - user32, - 4, - UINT, - WINAPI, - GetDpiForWindow, - _In_ HWND hwnd - ) - { - if (auto const pGetDpiForWindow = try_get_GetDpiForWindow()) - { - return pGetDpiForWindow(hwnd); - } - - if (HMONITOR hMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY)) - { - UINT nDpiX, nDpiY; - if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &nDpiX, &nDpiY))) - { - return nDpiX; - } - } - - return internal::GetDpiForSystemDownlevel(); - } +#if (YY_Thunks_Target < __WindowsNT10_14393) + + //Windows 10, version 1607 [desktop apps only] + __DEFINE_THUNK( + user32, + 4, + UINT, + WINAPI, + GetDpiForWindow, + _In_ HWND hwnd + ) + { + if (auto const pGetDpiForWindow = try_get_GetDpiForWindow()) + { + return pGetDpiForWindow(hwnd); + } + + if (HMONITOR hMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY)) + { + UINT nDpiX, nDpiY; + if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &nDpiX, &nDpiY))) + { + return nDpiX; + } + } + + return internal::GetDpiForSystemDownlevel(); + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS1) - - //Windows 10, version 1607 [desktop apps only] - __DEFINE_THUNK( - user32, - 8, - int, - WINAPI, - GetSystemMetricsForDpi, - _In_ int nIndex, - _In_ UINT dpi - ) - { - if (auto const pGetSystemMetricsForDpi = try_get_GetSystemMetricsForDpi()) - { - return pGetSystemMetricsForDpi(nIndex, dpi); - } - - auto nValue = GetSystemMetrics(nIndex); - - if (nValue != 0) - { - switch (nIndex) - { - case SM_CYSIZE: - case SM_CXVSCROLL: - case SM_CYSMICON: - case SM_CYVSCROLL: - case SM_CXPADDEDBORDER: - case SM_CXSMICON: - case SM_CYSMSIZE: - case SM_CYICON: - case SM_CYHSCROLL: - case SM_CYMENUCHECK: - case SM_CYCAPTION: - case SM_CXHSCROLL: - case SM_CXFRAME: - case SM_CYMENUSIZE: - case SM_CYFRAME: - case SM_CYMENU: - case SM_CXICON: - case SM_CXICONSPACING: - case SM_CYICONSPACING: - case SM_CYVTHUMB: - case SM_CXHTHUMB: - case SM_CXCURSOR: - case SM_CYCURSOR: - case SM_CXMIN: - case SM_CXMINTRACK: - case SM_CYMIN: - case SM_CYMINTRACK: - case SM_CXSIZE: - case SM_CYSMCAPTION: - case SM_CXSMSIZE: - case SM_CXMENUSIZE: - case SM_CXMENUCHECK: - { - auto nDpiX = internal::GetDpiForSystemDownlevel(); - if (nDpiX != dpi) - { - nValue *= dpi; - nValue += nDpiX / 2; - nValue /= nDpiX; - } - - break; - } - default: - break; - } - } - - return nValue; - } +#if (YY_Thunks_Target < __WindowsNT10_14393) + + //Windows 10, version 1607 [desktop apps only] + __DEFINE_THUNK( + user32, + 8, + int, + WINAPI, + GetSystemMetricsForDpi, + _In_ int nIndex, + _In_ UINT dpi + ) + { + if (auto const pGetSystemMetricsForDpi = try_get_GetSystemMetricsForDpi()) + { + return pGetSystemMetricsForDpi(nIndex, dpi); + } + + auto nValue = GetSystemMetrics(nIndex); + + if (nValue != 0) + { + switch (nIndex) + { + case SM_CYSIZE: + case SM_CXVSCROLL: + case SM_CYSMICON: + case SM_CYVSCROLL: + case SM_CXPADDEDBORDER: + case SM_CXSMICON: + case SM_CYSMSIZE: + case SM_CYICON: + case SM_CYHSCROLL: + case SM_CYMENUCHECK: + case SM_CYCAPTION: + case SM_CXHSCROLL: + case SM_CXFRAME: + case SM_CYMENUSIZE: + case SM_CYFRAME: + case SM_CYMENU: + case SM_CXICON: + case SM_CXICONSPACING: + case SM_CYICONSPACING: + case SM_CYVTHUMB: + case SM_CXHTHUMB: + case SM_CXCURSOR: + case SM_CYCURSOR: + case SM_CXMIN: + case SM_CXMINTRACK: + case SM_CYMIN: + case SM_CYMINTRACK: + case SM_CXSIZE: + case SM_CYSMCAPTION: + case SM_CXSMSIZE: + case SM_CXMENUSIZE: + case SM_CXMENUCHECK: + { + auto nDpiX = internal::GetDpiForSystemDownlevel(); + if (nDpiX != dpi) + { + nValue *= dpi; + nValue += nDpiX / 2; + nValue /= nDpiX; + } + + break; + } + default: + break; + } + } + + return nValue; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS1) - - //Windows 10, version 1607 [desktop apps only] - __DEFINE_THUNK( - user32, - 20, - BOOL, - WINAPI, - AdjustWindowRectExForDpi, - _Inout_ LPRECT lpRect, - _In_ DWORD dwStyle, - _In_ BOOL bMenu, - _In_ DWORD dwExStyle, - _In_ UINT dpi - ) - { - if (auto const pAdjustWindowRectExForDpi = try_get_AdjustWindowRectExForDpi()) - { - return pAdjustWindowRectExForDpi(lpRect, dwStyle, bMenu, dwExStyle, dpi); - } - - RECT FrameRect = {}; - - if (!AdjustWindowRectEx(&FrameRect, dwStyle, bMenu, dwExStyle)) - { - return FALSE; - } - - auto nDpiX = internal::GetDpiForSystemDownlevel(); - - if (nDpiX != dpi) - { - FrameRect.left = MulDiv(FrameRect.left, dpi, nDpiX); - FrameRect.top = MulDiv(FrameRect.top, dpi, nDpiX); - FrameRect.right = MulDiv(FrameRect.right, dpi, nDpiX); - FrameRect.bottom = MulDiv(FrameRect.bottom, dpi, nDpiX); - } - - lpRect->left += FrameRect.left; - lpRect->top += FrameRect.top; - lpRect->right += FrameRect.right; - lpRect->bottom += FrameRect.bottom; - - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT10_14393) + + //Windows 10, version 1607 [desktop apps only] + __DEFINE_THUNK( + user32, + 20, + BOOL, + WINAPI, + AdjustWindowRectExForDpi, + _Inout_ LPRECT lpRect, + _In_ DWORD dwStyle, + _In_ BOOL bMenu, + _In_ DWORD dwExStyle, + _In_ UINT dpi + ) + { + if (auto const pAdjustWindowRectExForDpi = try_get_AdjustWindowRectExForDpi()) + { + return pAdjustWindowRectExForDpi(lpRect, dwStyle, bMenu, dwExStyle, dpi); + } + + RECT FrameRect = {}; + + if (!AdjustWindowRectEx(&FrameRect, dwStyle, bMenu, dwExStyle)) + { + return FALSE; + } + + auto nDpiX = internal::GetDpiForSystemDownlevel(); + + if (nDpiX != dpi) + { + FrameRect.left = MulDiv(FrameRect.left, dpi, nDpiX); + FrameRect.top = MulDiv(FrameRect.top, dpi, nDpiX); + FrameRect.right = MulDiv(FrameRect.right, dpi, nDpiX); + FrameRect.bottom = MulDiv(FrameRect.bottom, dpi, nDpiX); + } + + lpRect->left += FrameRect.left; + lpRect->top += FrameRect.top; + lpRect->right += FrameRect.right; + lpRect->bottom += FrameRect.bottom; + + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS1) - - //Windows 10, version 1607 [desktop apps only] - __DEFINE_THUNK( - user32, - 20, - BOOL, - WINAPI, - SystemParametersInfoForDpi, - _In_ UINT uiAction, - _In_ UINT uiParam, - _Pre_maybenull_ _Post_valid_ PVOID pvParam, - _In_ UINT fWinIni, - _In_ UINT dpi - ) - { - if (auto const pSystemParametersInfoForDpi = try_get_SystemParametersInfoForDpi()) - { - return pSystemParametersInfoForDpi(uiAction, uiParam, pvParam, fWinIni, dpi); - } - - if (!SystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni)) - return FALSE; - - if (SPI_GETICONTITLELOGFONT == uiAction - || SPI_GETICONMETRICS == uiAction - || SPI_GETNONCLIENTMETRICS == uiAction) - { - auto nDpiX = internal::GetDpiForSystemDownlevel(); - - if (nDpiX != dpi) - { - if (SPI_GETICONTITLELOGFONT == uiAction) - { - if (auto pInfo = (LOGFONTW*)pvParam) - { - pInfo->lfHeight = MulDiv(pInfo->lfHeight, dpi, nDpiX); - } - } - else if (SPI_GETICONMETRICS == uiAction) - { - if (auto pInfo = (ICONMETRICSW*)pvParam) - { - if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iHorzSpacing)) - pInfo->iHorzSpacing = MulDiv(pInfo->iHorzSpacing, dpi, nDpiX); - - if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iVertSpacing)) - pInfo->iVertSpacing = MulDiv(pInfo->iVertSpacing, dpi, nDpiX); - - if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, lfFont)) - pInfo->lfFont.lfHeight = MulDiv(pInfo->lfFont.lfHeight, dpi, nDpiX); - } - } - else if (SPI_GETNONCLIENTMETRICS == uiAction) - { - if (auto pInfo = (NONCLIENTMETRICSW*)pvParam) - { - if(RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iBorderWidth)) - pInfo->iBorderWidth = MulDiv(pInfo->iBorderWidth, dpi, nDpiX); - - if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iScrollWidth)) - pInfo->iScrollWidth = MulDiv(pInfo->iScrollWidth, dpi, nDpiX); - - if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iScrollHeight)) - pInfo->iScrollHeight = MulDiv(pInfo->iScrollHeight, dpi, nDpiX); - - if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iCaptionWidth)) - pInfo->iCaptionWidth= MulDiv(pInfo->iCaptionWidth, dpi, nDpiX); - - if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iCaptionHeight)) - pInfo->iCaptionHeight= MulDiv(pInfo->iCaptionHeight, dpi, nDpiX); - - if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, lfCaptionFont)) - pInfo->lfCaptionFont.lfHeight = MulDiv(pInfo->lfCaptionFont.lfHeight, dpi, nDpiX); - - if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iSmCaptionWidth)) - pInfo->iSmCaptionWidth = MulDiv(pInfo->iSmCaptionWidth, dpi, nDpiX); - - if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iSmCaptionHeight)) - pInfo->iSmCaptionHeight = MulDiv(pInfo->iSmCaptionHeight, dpi, nDpiX); - - if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, lfSmCaptionFont)) - pInfo->lfSmCaptionFont.lfHeight = MulDiv(pInfo->lfSmCaptionFont.lfHeight, dpi, nDpiX); - - if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iMenuWidth)) - pInfo->iMenuWidth = MulDiv(pInfo->iMenuWidth, dpi, nDpiX); - - if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iMenuHeight)) - pInfo->iMenuHeight = MulDiv(pInfo->iMenuHeight, dpi, nDpiX); - - if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, lfMenuFont)) - pInfo->lfMenuFont.lfHeight = MulDiv(pInfo->lfMenuFont.lfHeight, dpi, nDpiX); - - if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, lfStatusFont)) - pInfo->lfStatusFont.lfHeight = MulDiv(pInfo->lfStatusFont.lfHeight, dpi, nDpiX); - - if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, lfMessageFont)) - pInfo->lfMessageFont.lfHeight = MulDiv(pInfo->lfMessageFont.lfHeight, dpi, nDpiX); - - if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iPaddedBorderWidth)) - pInfo->iPaddedBorderWidth = MulDiv(pInfo->iPaddedBorderWidth, dpi, nDpiX); - } - } - } - } - - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT10_14393) + + //Windows 10, version 1607 [desktop apps only] + __DEFINE_THUNK( + user32, + 20, + BOOL, + WINAPI, + SystemParametersInfoForDpi, + _In_ UINT uiAction, + _In_ UINT uiParam, + _Pre_maybenull_ _Post_valid_ PVOID pvParam, + _In_ UINT fWinIni, + _In_ UINT dpi + ) + { + if (auto const pSystemParametersInfoForDpi = try_get_SystemParametersInfoForDpi()) + { + return pSystemParametersInfoForDpi(uiAction, uiParam, pvParam, fWinIni, dpi); + } + + if (!SystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni)) + return FALSE; + + if (SPI_GETICONTITLELOGFONT == uiAction + || SPI_GETICONMETRICS == uiAction + || SPI_GETNONCLIENTMETRICS == uiAction) + { + auto nDpiX = internal::GetDpiForSystemDownlevel(); + + if (nDpiX != dpi) + { + if (SPI_GETICONTITLELOGFONT == uiAction) + { + if (auto pInfo = (LOGFONTW*)pvParam) + { + pInfo->lfHeight = MulDiv(pInfo->lfHeight, dpi, nDpiX); + } + } + else if (SPI_GETICONMETRICS == uiAction) + { + if (auto pInfo = (ICONMETRICSW*)pvParam) + { + if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iHorzSpacing)) + pInfo->iHorzSpacing = MulDiv(pInfo->iHorzSpacing, dpi, nDpiX); + + if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iVertSpacing)) + pInfo->iVertSpacing = MulDiv(pInfo->iVertSpacing, dpi, nDpiX); + + if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, lfFont)) + pInfo->lfFont.lfHeight = MulDiv(pInfo->lfFont.lfHeight, dpi, nDpiX); + } + } + else if (SPI_GETNONCLIENTMETRICS == uiAction) + { + if (auto pInfo = (NONCLIENTMETRICSW*)pvParam) + { + if(RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iBorderWidth)) + pInfo->iBorderWidth = MulDiv(pInfo->iBorderWidth, dpi, nDpiX); + + if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iScrollWidth)) + pInfo->iScrollWidth = MulDiv(pInfo->iScrollWidth, dpi, nDpiX); + + if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iScrollHeight)) + pInfo->iScrollHeight = MulDiv(pInfo->iScrollHeight, dpi, nDpiX); + + if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iCaptionWidth)) + pInfo->iCaptionWidth= MulDiv(pInfo->iCaptionWidth, dpi, nDpiX); + + if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iCaptionHeight)) + pInfo->iCaptionHeight= MulDiv(pInfo->iCaptionHeight, dpi, nDpiX); + + if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, lfCaptionFont)) + pInfo->lfCaptionFont.lfHeight = MulDiv(pInfo->lfCaptionFont.lfHeight, dpi, nDpiX); + + if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iSmCaptionWidth)) + pInfo->iSmCaptionWidth = MulDiv(pInfo->iSmCaptionWidth, dpi, nDpiX); + + if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iSmCaptionHeight)) + pInfo->iSmCaptionHeight = MulDiv(pInfo->iSmCaptionHeight, dpi, nDpiX); + + if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, lfSmCaptionFont)) + pInfo->lfSmCaptionFont.lfHeight = MulDiv(pInfo->lfSmCaptionFont.lfHeight, dpi, nDpiX); + + if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iMenuWidth)) + pInfo->iMenuWidth = MulDiv(pInfo->iMenuWidth, dpi, nDpiX); + + if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iMenuHeight)) + pInfo->iMenuHeight = MulDiv(pInfo->iMenuHeight, dpi, nDpiX); + + if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, lfMenuFont)) + pInfo->lfMenuFont.lfHeight = MulDiv(pInfo->lfMenuFont.lfHeight, dpi, nDpiX); + + if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, lfStatusFont)) + pInfo->lfStatusFont.lfHeight = MulDiv(pInfo->lfStatusFont.lfHeight, dpi, nDpiX); + + if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, lfMessageFont)) + pInfo->lfMessageFont.lfHeight = MulDiv(pInfo->lfMessageFont.lfHeight, dpi, nDpiX); + + if (RTL_CONTAINS_FIELD(pInfo, pInfo->cbSize, iPaddedBorderWidth)) + pInfo->iPaddedBorderWidth = MulDiv(pInfo->iPaddedBorderWidth, dpi, nDpiX); + } + } + } + } + + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - // 最低受支持的客户端 Windows 7 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] - __DEFINE_THUNK( - user32, - 8, - BOOL, - WINAPI, - GetWindowDisplayAffinity, - _In_ HWND _hWnd, - _Out_ DWORD* _pdwAffinity) - { - if (auto const _pfnGetWindowDisplayAffinity = try_get_GetWindowDisplayAffinity()) - { - return _pfnGetWindowDisplayAffinity(_hWnd, _pdwAffinity); - } - - if (!_pdwAffinity) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - // 系统不支持,假装自己不需要任何保护 - *_pdwAffinity = WDA_NONE; - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + // 最低受支持的客户端 Windows 7 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] + __DEFINE_THUNK( + user32, + 8, + BOOL, + WINAPI, + GetWindowDisplayAffinity, + _In_ HWND _hWnd, + _Out_ DWORD* _pdwAffinity) + { + if (auto const _pfnGetWindowDisplayAffinity = try_get_GetWindowDisplayAffinity()) + { + return _pfnGetWindowDisplayAffinity(_hWnd, _pdwAffinity); + } + + if (!_pdwAffinity) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // 系统不支持,假装自己不需要任何保护 + *_pdwAffinity = WDA_NONE; + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - // 最低受支持的客户端 Windows 7 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] - __DEFINE_THUNK( - user32, - 8, - BOOL, - WINAPI, - SetWindowDisplayAffinity, - _In_ HWND _hWnd, - _In_ DWORD _dwAffinity) - { - if (auto const _pfnSetWindowDisplayAffinity = try_get_SetWindowDisplayAffinity()) - { - return _pfnSetWindowDisplayAffinity(_hWnd, _dwAffinity); - } - - // 系统不支持,假装自己成功…… - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + // 最低受支持的客户端 Windows 7 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] + __DEFINE_THUNK( + user32, + 8, + BOOL, + WINAPI, + SetWindowDisplayAffinity, + _In_ HWND _hWnd, + _In_ DWORD _dwAffinity) + { + if (auto const _pfnSetWindowDisplayAffinity = try_get_SetWindowDisplayAffinity()) + { + return _pfnSetWindowDisplayAffinity(_hWnd, _dwAffinity); + } + + // 系统不支持,假装自己成功…… + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - // 最低受支持的客户端 Windows 7 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] - __DEFINE_THUNK( - user32, - 8, - BOOL, - WINAPI, - RegisterTouchWindow, - _In_ HWND _hWnd, - _In_ ULONG _ulFlags) - { - if (auto const _pfnRegisterTouchWindow = try_get_RegisterTouchWindow()) - { - return _pfnRegisterTouchWindow(_hWnd, _ulFlags); - } - - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + // 最低受支持的客户端 Windows 7 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] + __DEFINE_THUNK( + user32, + 8, + BOOL, + WINAPI, + RegisterTouchWindow, + _In_ HWND _hWnd, + _In_ ULONG _ulFlags) + { + if (auto const _pfnRegisterTouchWindow = try_get_RegisterTouchWindow()) + { + return _pfnRegisterTouchWindow(_hWnd, _ulFlags); + } + + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - // 最低受支持的客户端 Windows 7 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] - __DEFINE_THUNK( - user32, - 4, - BOOL, - WINAPI, - UnregisterTouchWindow, - _In_ HWND _hWnd) - { - if (auto const _pfnUnregisterTouchWindow = try_get_UnregisterTouchWindow()) - { - return _pfnUnregisterTouchWindow(_hWnd); - } - - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + // 最低受支持的客户端 Windows 7 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] + __DEFINE_THUNK( + user32, + 4, + BOOL, + WINAPI, + UnregisterTouchWindow, + _In_ HWND _hWnd) + { + if (auto const _pfnUnregisterTouchWindow = try_get_UnregisterTouchWindow()) + { + return _pfnUnregisterTouchWindow(_hWnd); + } + + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - // 最低受支持的客户端 Windows 7 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] - __DEFINE_THUNK( - user32, - 8, - BOOL, - WINAPI, - IsTouchWindow, - _In_ HWND _hWnd, - _Out_opt_ PULONG _puFlags) - { - if (auto const _pfnIsTouchWindow = try_get_IsTouchWindow()) - { - return _pfnIsTouchWindow(_hWnd, _puFlags); - } - - if (_puFlags) - *_puFlags = 0; - - return TRUE; - } +#if (YY_Thunks_Target < __WindowsNT6_1) + + // 最低受支持的客户端 Windows 7 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] + __DEFINE_THUNK( + user32, + 8, + BOOL, + WINAPI, + IsTouchWindow, + _In_ HWND _hWnd, + _Out_opt_ PULONG _puFlags) + { + if (auto const _pfnIsTouchWindow = try_get_IsTouchWindow()) + { + return _pfnIsTouchWindow(_hWnd, _puFlags); + } + + if (_puFlags) + *_puFlags = 0; + + return TRUE; + } #endif - - -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - // 最低受支持的客户端 Windows 7 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] - __DEFINE_THUNK( - user32, - 16, - BOOL, - WINAPI, - GetTouchInputInfo, - _In_ HTOUCHINPUT _hTouchInput, - _In_ UINT _uInputs, - _Out_writes_(_uInputs) PTOUCHINPUT _pInputs, - _In_ int _cbSize) - { - if (auto const _pfnGetTouchInputInfo = try_get_GetTouchInputInfo()) - { - return _pfnGetTouchInputInfo(_hTouchInput, _uInputs, _pInputs, _cbSize); - } - - // 老版本系统没有触摸消息,_hTouchInput 必然无效 - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } + + +#if (YY_Thunks_Target < __WindowsNT6_1) + + // 最低受支持的客户端 Windows 7 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] + __DEFINE_THUNK( + user32, + 16, + BOOL, + WINAPI, + GetTouchInputInfo, + _In_ HTOUCHINPUT _hTouchInput, + _In_ UINT _uInputs, + _Out_writes_(_uInputs) PTOUCHINPUT _pInputs, + _In_ int _cbSize) + { + if (auto const _pfnGetTouchInputInfo = try_get_GetTouchInputInfo()) + { + return _pfnGetTouchInputInfo(_hTouchInput, _uInputs, _pInputs, _cbSize); + } + + // 老版本系统没有触摸消息,_hTouchInput 必然无效 + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN7) - - // 最低受支持的客户端 Windows 7 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] - __DEFINE_THUNK( - user32, - 4, - BOOL, - WINAPI, - CloseTouchInputHandle, - _In_ HTOUCHINPUT _hTouchInput) - { - if (auto const _pfnCloseTouchInputHandle = try_get_CloseTouchInputHandle()) - { - return _pfnCloseTouchInputHandle(_hTouchInput); - } - - // 老版本系统没有触摸消息,_hTouchInput 必然无效 - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } + +#if (YY_Thunks_Target < __WindowsNT6_1) + + // 最低受支持的客户端 Windows 7 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008 R2[仅限桌面应用] + __DEFINE_THUNK( + user32, + 4, + BOOL, + WINAPI, + CloseTouchInputHandle, + _In_ HTOUCHINPUT _hTouchInput) + { + if (auto const _pfnCloseTouchInputHandle = try_get_CloseTouchInputHandle()) + { + return _pfnCloseTouchInputHandle(_hTouchInput); + } + + // 老版本系统没有触摸消息,_hTouchInput 必然无效 + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) -// 最低受支持的客户端 Windows Vista [仅限桌面应用] -// 最低受支持的服务器 Windows Server 2008[仅限桌面应用] -__DEFINE_THUNK( -user32, -8, -BOOL, -WINAPI, -ChangeWindowMessageFilter, - _In_ UINT _uMessage, - _In_ DWORD _fFlag - ) -{ - if (const auto _pfnChangeWindowMessageFilter = try_get_ChangeWindowMessageFilter()) + // 最低受支持的客户端 Windows Vista [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] + __DEFINE_THUNK( + user32, + 8, + BOOL, + WINAPI, + ChangeWindowMessageFilter, + _In_ UINT _uMessage, + _In_ DWORD _fFlag + ) { - return _pfnChangeWindowMessageFilter(_uMessage, _fFlag); - } + if (const auto _pfnChangeWindowMessageFilter = try_get_ChangeWindowMessageFilter()) + { + return _pfnChangeWindowMessageFilter(_uMessage, _fFlag); + } - return TRUE; -} + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) -// 最低受支持的客户端 Windows Vista [仅限桌面应用] -// 最低受支持的服务器 Windows Server 2008[仅限桌面应用] -__DEFINE_THUNK( -user32, -8, -BOOL, -WINAPI, -UpdateLayeredWindowIndirect, - _In_ HWND hWnd, - _In_ const UPDATELAYEREDWINDOWINFO* pULWInfo - ) -{ - if (const auto _pfnUpdateLayeredWindowIndirect = try_get_UpdateLayeredWindowIndirect()) + // 最低受支持的客户端 Windows Vista [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] + __DEFINE_THUNK( + user32, + 8, + BOOL, + WINAPI, + UpdateLayeredWindowIndirect, + _In_ HWND hWnd, + _In_ const UPDATELAYEREDWINDOWINFO* pULWInfo + ) { - return _pfnUpdateLayeredWindowIndirect(hWnd, pULWInfo); + if (const auto _pfnUpdateLayeredWindowIndirect = try_get_UpdateLayeredWindowIndirect()) + { + return _pfnUpdateLayeredWindowIndirect(hWnd, pULWInfo); + } + + return UpdateLayeredWindow( + hWnd, + pULWInfo->hdcDst, + const_cast(pULWInfo->pptDst), + const_cast(pULWInfo->psize), + pULWInfo->hdcSrc, + const_cast(pULWInfo->pptSrc), + pULWInfo->crKey, + const_cast(pULWInfo->pblend), pULWInfo->dwFlags); } - - return UpdateLayeredWindow( - hWnd, - pULWInfo->hdcDst, - const_cast(pULWInfo->pptDst), - const_cast(pULWInfo->psize), - pULWInfo->hdcSrc, - const_cast(pULWInfo->pptSrc), - pULWInfo->crKey, - const_cast(pULWInfo->pblend), pULWInfo->dwFlags); -} #endif } //namespace YY::Thunks diff --git a/src/Thunks/userenv.hpp b/src/Thunks/userenv.hpp index 0cb06b5..22facc7 100644 --- a/src/Thunks/userenv.hpp +++ b/src/Thunks/userenv.hpp @@ -1,10 +1,10 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) #include #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] @@ -35,7 +35,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] @@ -58,7 +58,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] @@ -84,7 +84,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] @@ -110,7 +110,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN8) +#if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8 [仅限桌面应用] // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] diff --git a/src/Thunks/uxtheme.hpp b/src/Thunks/uxtheme.hpp index be4b5a3..2846c48 100644 --- a/src/Thunks/uxtheme.hpp +++ b/src/Thunks/uxtheme.hpp @@ -1,13 +1,13 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_uxtheme) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_uxtheme) #define __Comment_Lib_uxtheme #pragma comment(lib, "UxTheme.lib") #endif -#if defined(YY_Thunks_Implemented) && (YY_Thunks_Support_Version < NTDDI_WIN6) +#if defined(YY_Thunks_Implemented) && (YY_Thunks_Target < __WindowsNT6) namespace YY::Thunks::Fallback { static void* __fastcall try_get_DrawThemeTextEx(const ProcInfo& _ProcInfo) noexcept @@ -41,7 +41,7 @@ namespace YY::Thunks::Fallback namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -72,7 +72,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] @@ -106,7 +106,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // 最低受支持的客户端 Windows Vista [仅限桌面应用] // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] diff --git a/src/Thunks/wevtapi.hpp b/src/Thunks/wevtapi.hpp index 024af15..f43a096 100644 --- a/src/Thunks/wevtapi.hpp +++ b/src/Thunks/wevtapi.hpp @@ -1,38 +1,38 @@ -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) #include #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_wevtapi) +#if (YY_Thunks_Target < __WindowsNT6) && !defined(__Comment_Lib_wevtapi) #define __Comment_Lib_wevtapi #pragma comment(lib, "wevtapi.lib") #endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps only] // Minimum supported server Windows Server 2008[desktop apps only] - __DEFINE_THUNK( + __DEFINE_THUNK( wevtapi, - 4, + 4, BOOL, WINAPI, EvtClose, _In_ _Post_invalid_ EVT_HANDLE Object - ) - { - if (auto const _pfnEvtClose = try_get_EvtClose()) - { - return _pfnEvtClose(Object); - } - - return TRUE; - } + ) + { + if (auto const _pfnEvtClose = try_get_EvtClose()) + { + return _pfnEvtClose(Object); + } + + return TRUE; + } #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps only] // Minimum supported server Windows Server 2008[desktop apps only] @@ -58,7 +58,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps only] // Minimum supported server Windows Server 2008[desktop apps only] @@ -87,7 +87,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps only] // Minimum supported server Windows Server 2008[desktop apps only] @@ -113,7 +113,7 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#if (YY_Thunks_Target < __WindowsNT6) // Minimum supported client Windows Vista [desktop apps only] // Minimum supported server Windows Server 2008[desktop apps only] diff --git a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj index 35d5de7..1bdf82a 100644 --- a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj +++ b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj @@ -98,7 +98,7 @@ true true $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) - SymbolBuildTestPath=LR"($(ProjectDir)TestProject\)";YY_ThunksRootPath=LR"($(ProjectDir)..\..\)";MSBuildBinPath=LR"($(MSBuildBinPath)\)";__YY_Thunks_Unit_Test;WIN32;NDEBUG;YY_Thunks_Support_Version=NTDDI_WIN2K;__ENABLE_WORKAROUND_ALL;__USING_NTDLL_LIB;%(PreprocessorDefinitions) + SymbolBuildTestPath=LR"($(ProjectDir)TestProject\)";YY_ThunksRootPath=LR"($(ProjectDir)..\..\)";MSBuildBinPath=LR"($(MSBuildBinPath)\)";__YY_Thunks_Unit_Test;WIN32;NDEBUG;__ENABLE_WORKAROUND_ALL;__USING_NTDLL_LIB;%(PreprocessorDefinitions) true pch.h Use @@ -121,7 +121,7 @@ Level3 $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) - SymbolBuildTestPath=LR"($(ProjectDir)TestProject\)";YY_ThunksRootPath=LR"($(ProjectDir)..\..\)";MSBuildBinPath=LR"($(MSBuildBinPath)\)";__YY_Thunks_Unit_Test;WIN32;_DEBUG;YY_Thunks_Support_Version=NTDDI_WIN2K;__ENABLE_WORKAROUND_ALL;__USING_NTDLL_LIB;%(PreprocessorDefinitions) + SymbolBuildTestPath=LR"($(ProjectDir)TestProject\)";YY_ThunksRootPath=LR"($(ProjectDir)..\..\)";MSBuildBinPath=LR"($(MSBuildBinPath)\)";__YY_Thunks_Unit_Test;WIN32;_DEBUG;__ENABLE_WORKAROUND_ALL;__USING_NTDLL_LIB;%(PreprocessorDefinitions) true pch.h Use @@ -141,7 +141,7 @@ Level3 $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) - SymbolBuildTestPath=LR"($(ProjectDir)TestProject\)";YY_ThunksRootPath=LR"($(ProjectDir)..\..\)";MSBuildBinPath=LR"($(MSBuildBinPath)\)";__YY_Thunks_Unit_Test;_DEBUG;YY_Thunks_Support_Version=NTDDI_WS03;%(PreprocessorDefinitions) + SymbolBuildTestPath=LR"($(ProjectDir)TestProject\)";YY_ThunksRootPath=LR"($(ProjectDir)..\..\)";MSBuildBinPath=LR"($(MSBuildBinPath)\)";__YY_Thunks_Unit_Test;_DEBUG;%(PreprocessorDefinitions) true pch.h Use @@ -163,7 +163,7 @@ true true $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) - SymbolBuildTestPath=LR"($(ProjectDir)TestProject\)";YY_ThunksRootPath=LR"($(ProjectDir)..\..\)";MSBuildBinPath=LR"($(MSBuildBinPath)\)";__YY_Thunks_Unit_Test;NDEBUG;YY_Thunks_Support_Version=NTDDI_WS03;%(PreprocessorDefinitions) + SymbolBuildTestPath=LR"($(ProjectDir)TestProject\)";YY_ThunksRootPath=LR"($(ProjectDir)..\..\)";MSBuildBinPath=LR"($(MSBuildBinPath)\)";__YY_Thunks_Unit_Test;NDEBUG;%(PreprocessorDefinitions) true pch.h Use diff --git a/src/YY-Thunks.UnitTest/pch.h b/src/YY-Thunks.UnitTest/pch.h index faf79d1..dad98c2 100644 --- a/src/YY-Thunks.UnitTest/pch.h +++ b/src/YY-Thunks.UnitTest/pch.h @@ -25,6 +25,8 @@ #include #include +#include + using namespace Microsoft::VisualStudio::CppUnitTestFramework; #define __DEFINE_THUNK(_MODULE, _SIZE, _RETURN_, _CONVENTION_, _FUNCTION, ...) \