diff --git a/ThunksList.md b/ThunksList.md index 8edd493..da91614 100644 --- a/ThunksList.md +++ b/ThunksList.md @@ -311,6 +311,14 @@ | SetFileCompletionNotificationModes | 不存在时,什么也不做。 | GetQueuedCompletionStatusEx | 不存在时,调用 GetQueuedCompletionStatus。 | FindFirstFileEx(W/A) | Windows XP、Vista兼容 FIND_FIRST_EX_LARGE_FETCH、FindExInfoStandard参数。 +| GetProcessGroupAffinity | 不存在时,始终认为只有一组CPU。 +| QueryUnbiasedInterruptTime | 不存在时,调用QueryPerformanceCounter。 +| FindStringOrdinal | 不存在时,调用CompareStringOrdinal。 +| GetEnabledXStateFeatures | 不存在时,调用IsProcessorFeaturePresent。 +| SetXStateFeaturesMask | 不存在时,内部实现。 +| InitializeContext | 不存在时,内部实现。 +| InitializeContext2 | 不存在时,调用InitializeContext。 +| LocateXStateFeature | 不存在时,内部实现。 ## mfplat.dll | 函数 | Fallback diff --git a/src/Thunks/api-ms-win-core-libraryloader.hpp b/src/Thunks/api-ms-win-core-libraryloader.hpp index 20a35fd..903a026 100644 --- a/src/Thunks/api-ms-win-core-libraryloader.hpp +++ b/src/Thunks/api-ms-win-core-libraryloader.hpp @@ -738,5 +738,102 @@ namespace YY return EnumResourceLanguagesA(_hModule, _lpType, _lpName, _lpEnumFunc, _lParam); } #endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN7) + + // 最低受支持的客户端 Windows 7 [桌面应用 |UWP 应用] + // 最低受支持的服务器 Windows Server 2008 R2[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 24, + int, + WINAPI, + FindStringOrdinal, + _In_ DWORD _uFindStringOrdinalFlags, + _In_reads_(_cchSource) LPCWSTR _pStringSource, + _In_ int _cchSource, + _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); + } + + SetLastError(ERROR_SUCCESS); + if (_pStringSource == nullptr || _cchSource < -1 || _pStringValue == nullptr || _cchValue < -1) + { + SetLastError(ERROR_INVALID_PARAMETER); + return -1; + } + + if (_cchSource == -1) + { + _cchSource = wcslen(_pStringSource); + } + + if (_cchSource == 0) + { + return -1; + } + + if (_cchValue == -1) + { + _cchValue = wcslen(_pStringValue); + } + + if (_cchValue == 0 || _cchValue > _cchSource) + { + return -1; + } + + switch (_uFindStringOrdinalFlags) + { + case 0: + case FIND_FROMSTART: + for (auto _pStart = _pStringSource; _cchValue <= _cchSource;++_pStart, --_cchSource) + { + if (CompareStringOrdinal(_pStart, _cchValue, _pStringValue, _cchValue, _bIgnoreCase) == CSTR_EQUAL) + { + return _pStart - _pStringSource; + } + } + return -1; + break; + case FIND_FROMEND: + for (auto _pStart = _pStringSource + _cchSource - _cchValue; _cchValue <= _cchSource; --_pStart, --_cchSource) + { + if (CompareStringOrdinal(_pStart, _cchValue, _pStringValue, _cchValue, _bIgnoreCase) == CSTR_EQUAL) + { + return _pStart - _pStringSource; + } + } + return -1; + break; + case FIND_STARTSWITH: + if (CompareStringOrdinal(_pStringSource, _cchValue, _pStringValue, _cchValue, _bIgnoreCase) == CSTR_EQUAL) + { + return 0; + } + return -1; + break; + case FIND_ENDSWITH: + _cchSource -= _cchValue; + if (CompareStringOrdinal(_pStringSource + _cchSource, _cchValue, _pStringValue, _cchValue, _bIgnoreCase) == CSTR_EQUAL) + { + return _cchSource; + } + return -1; + break; + default: + SetLastError(ERROR_INVALID_FLAGS); + return -1; + break; + } + } +#endif } -} \ No newline at end of file +} diff --git a/src/Thunks/api-ms-win-core-processtopology.hpp b/src/Thunks/api-ms-win-core-processtopology.hpp new file mode 100644 index 0000000..454e451 --- /dev/null +++ b/src/Thunks/api-ms-win-core-processtopology.hpp @@ -0,0 +1,45 @@ +#include + +namespace YY +{ + namespace Thunks + { +#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, + 12, + BOOL, + WINAPI, + GetProcessGroupAffinity, + _In_ HANDLE _hProcess, + _Inout_ PUSHORT _pGroupCount, + _Out_writes_(*_pGroupCount) PUSHORT _pGroupArray + ) + { + if (const auto _pfnGetProcessGroupAffinity = try_get_GetProcessGroupAffinity()) + { + return _pfnGetProcessGroupAffinity(_hProcess, _pGroupCount, _pGroupArray); + } + + // 更低版本系统不支持 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; + } +#endif + } // namespace Thunks +} // namespace YY diff --git a/src/Thunks/api-ms-win-core-realtime.hpp b/src/Thunks/api-ms-win-core-realtime.hpp index 6235761..bfaf61d 100644 --- a/src/Thunks/api-ms-win-core-realtime.hpp +++ b/src/Thunks/api-ms-win-core-realtime.hpp @@ -79,11 +79,56 @@ namespace YY ((ULARGE_INTEGER*)CycleTime)->LowPart = UserTime.dwLowDateTime; ((ULARGE_INTEGER*)CycleTime)->HighPart = UserTime.dwHighDateTime; - return TRUE; } #endif + +#if (YY_Thunks_Support_Version < NTDDI_WIN7) + + // 最低受支持的客户端 Windows 7、Windows 8 [桌面应用 |UWP 应用] + // 最低受支持的服务器 Windows Server 2008 R2[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 4, + BOOL, + WINAPI, + QueryUnbiasedInterruptTime, + _Out_ PULONGLONG _puUnbiasedTime + ) + { + if (const auto _pfnQueryUnbiasedInterruptTime = try_get_QueryUnbiasedInterruptTime()) + { + return _pfnQueryUnbiasedInterruptTime(_puUnbiasedTime); + } + + if (!_puUnbiasedTime) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // 使用中断时间模拟非中断时间,先合凑合吧…… + static LARGE_INTEGER _Frequency; + if (_Frequency.QuadPart == 0ll) + { + if (!QueryPerformanceFrequency(&_Frequency)) + { + return FALSE; + } + } + + LARGE_INTEGER _PerformanceCount; + if (!QueryPerformanceCounter(&_PerformanceCount)) + { + return FALSE; + } + + // 单位需要转换到 100纳秒 + *_puUnbiasedTime = _PerformanceCount.QuadPart * 1'000'000'0 / _Frequency.QuadPart; + return TRUE; + } +#endif }//namespace Thunks -} //namespace YY \ No newline at end of file +} //namespace YY diff --git a/src/Thunks/api-ms-win-core-xstate.hpp b/src/Thunks/api-ms-win-core-xstate.hpp new file mode 100644 index 0000000..c519b8c --- /dev/null +++ b/src/Thunks/api-ms-win-core-xstate.hpp @@ -0,0 +1,204 @@ +namespace YY +{ + namespace Thunks + { +#if (YY_Thunks_Support_Version < NTDDI_WIN6SP1) + + // 最低受支持的客户端 Windows 7 SP1[桌面应用 | UWP 应用] + // 最低受支持的服务器 Windows Server 2008 R2 SP1[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 0, + DWORD64, + WINAPI, + GetEnabledXStateFeatures, + VOID + ) + { + if (auto const _pfnGetEnabledXStateFeatures = try_get_GetEnabledXStateFeatures()) + { + return _pfnGetEnabledXStateFeatures(); + } + + static DWORD64 s_uXState = 0; + if (s_uXState) + { + return s_uXState; + } + + DWORD64 _uXState = XSTATE_MASK_LEGACY_FLOATING_POINT; + if (IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) + { + _uXState |= XSTATE_MASK_LEGACY_SSE; + } + + s_uXState = _uXState; + return _uXState; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6SP1) + + // 最低受支持的客户端 Windows 7 SP1 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008 R2 SP1[仅限桌面应用] + __DEFINE_THUNK( + kernel32, + 12, + BOOL, + WINAPI, + SetXStateFeaturesMask, + _Inout_ PCONTEXT Context, + _In_ DWORD64 FeatureMask + ) + { + if (auto const _pfnSetXStateFeaturesMask = try_get_SetXStateFeaturesMask()) + { + return _pfnSetXStateFeaturesMask(Context, FeatureMask); + } + const auto _uSupportFeatures = GetEnabledXStateFeatures(); + + if (FeatureMask & (~_uSupportFeatures)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + else + { + return TRUE; + } + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6SP1) + + // 最低受支持的客户端 Windows 7 SP1 [桌面应用 |UWP 应用] + // 最低受支持的服务器 Windows Server 2008 R2 SP1[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 12, + PVOID, + WINAPI, + LocateXStateFeature, + _In_ PCONTEXT Context, + _In_ DWORD FeatureId, + _Out_opt_ PDWORD Length + ) + { + if (auto const _pfnLocateXStateFeature = try_get_LocateXStateFeature()) + { + return _pfnLocateXStateFeature(Context, FeatureId, Length); + } + +#if defined(_X86_) + auto& _XSave = *(XSAVE_FORMAT*)Context->ExtendedRegisters; + constexpr auto kThreadContext = CONTEXT_i386; + +#elif defined(_AMD64_) + auto& _XSave = Context->FltSave; + constexpr auto kThreadContext = CONTEXT_AMD64; +#else +#error unknow OS. +#endif + if (kThreadContext & Context->ContextFlags) + { + if (XSTATE_LEGACY_FLOATING_POINT == FeatureId) + { + if (Length) + { + *Length = UFIELD_OFFSET(XSAVE_FORMAT, XmmRegisters); + } + return &_XSave; + } + else if (XSTATE_LEGACY_SSE == FeatureId) + { + if (IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) + { + if (Length) + { + *Length = sizeof(_XSave.XmmRegisters); + } + return &_XSave.XmmRegisters; + } + } + } + + if (Length) + *Length = 0; + return nullptr; + } +#endif + +#if (YY_Thunks_Support_Version < NTDDI_WIN6SP1) + + // 最低受支持的客户端 Windows 7 SP1 [桌面应用 |UWP 应用] + // 最低受支持的服务器 Windows Server 2008 R2 SP1[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + InitializeContext, + _Out_writes_bytes_opt_(*ContextLength) PVOID Buffer, + _In_ DWORD ContextFlags, + _Out_ PCONTEXT* Context, + _Inout_ PDWORD ContextLength + ) + { + if (auto const _pfnInitializeContext = try_get_InitializeContext()) + { + return _pfnInitializeContext(Buffer, ContextFlags, Context, ContextLength); + } + + constexpr auto kSupportContextFlags = CONTEXT_ALL | CONTEXT_EXCEPTION_ACTIVE | CONTEXT_SERVICE_ACTIVE | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING; + + if (ContextFlags & (~kSupportContextFlags)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (Buffer == nullptr || *ContextLength < sizeof(CONTEXT)) + { + *ContextLength = sizeof(CONTEXT); + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + + auto _pContext = reinterpret_cast(Buffer); + _pContext->ContextFlags = ContextFlags; + *ContextLength = sizeof(CONTEXT); + *Context = _pContext; + return TRUE; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN10_FE) + + // 最低受支持的客户端 Windows 10内部版本 20348 + // 最低受支持的服务器 Windows 10内部版本 20348 + __DEFINE_THUNK( + kernel32, + 24, + BOOL, + WINAPI, + InitializeContext2, + _Out_writes_bytes_opt_(*ContextLength) PVOID Buffer, + _In_ DWORD ContextFlags, + _Out_ PCONTEXT* Context, + _Inout_ PDWORD ContextLength, + _In_ ULONG64 XStateCompactionMask + ) + { + if (auto const _pfnInitializeContext2 = try_get_InitializeContext2()) + { + return _pfnInitializeContext2(Buffer, ContextFlags, Context, ContextLength, XStateCompactionMask); + } + + return InitializeContext(Buffer, ContextFlags, Context, ContextLength); + } +#endif + } +} diff --git a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj index 0b19370..1edf002 100644 --- a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj +++ b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj @@ -100,6 +100,7 @@ Use MultiThreadedDLL false + 4715;%(TreatSpecificWarningsAsErrors) Windows @@ -118,6 +119,7 @@ Use MultiThreadedDebugDLL false + 4715;%(TreatSpecificWarningsAsErrors) Windows @@ -134,6 +136,7 @@ Use MultiThreadedDebugDLL false + 4715;%(TreatSpecificWarningsAsErrors) Windows @@ -152,6 +155,7 @@ Use MultiThreadedDLL false + 4715;%(TreatSpecificWarningsAsErrors) Windows @@ -194,7 +198,9 @@ + + diff --git a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters index 9e237a7..c80ae63 100644 --- a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters +++ b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters @@ -239,6 +239,12 @@ Thunks + + Thunks + + + Thunks +