diff --git a/ThunksList.md b/ThunksList.md index 3db48f4..60843c0 100644 --- a/ThunksList.md +++ b/ThunksList.md @@ -813,3 +813,4 @@ | FreeAddrInfoEx(W) | 不存在时,内部实现。 | GetAddrInfoW | 不存在时,调用getaddrinfo。 | FreeAddrInfoW | 不存在时,内部实现。 +| WSASocketW(A) | 低于6.1.7601时自动去除 `WSA_FLAG_NO_HANDLE_INHERIT` diff --git a/src/Thunks/WS2_32.hpp b/src/Thunks/WS2_32.hpp index 0cada93..2259e87 100644 --- a/src/Thunks/WS2_32.hpp +++ b/src/Thunks/WS2_32.hpp @@ -1,9 +1,16 @@ -#include +#if (YY_Thunks_Target < __WindowsNT6_2) +#include #include #ifdef FreeAddrInfoEx #undef FreeAddrInfoEx #endif // ! FreeAddrInfoEx +#endif + +#if (YY_Thunks_Target < __WindowsNT6_1_SP1) && !defined(__Comment_Lib_ws2_32) +#define __Comment_Lib_ws2_32 +#pragma comment(lib, "Ws2_32.lib") +#endif namespace YY::Thunks { @@ -1464,6 +1471,82 @@ namespace YY::Thunks #endif +#if (YY_Thunks_Target < __WindowsNT6_1_SP1) + + // Windows XP + // 虽然Windows XP支持这个API,但是Windows 7 SP1开始才支持 WSA_FLAG_NO_HANDLE_INHERIT 标记 + __DEFINE_THUNK( + ws2_32, + 24, + SOCKET, + WSAAPI, + WSASocketW, + _In_ int af, + _In_ int type, + _In_ int protocol, + _In_opt_ LPWSAPROTOCOL_INFOW lpProtocolInfo, + _In_ GROUP g, + _In_ DWORD dwFlags + ) + { + auto const _pfnWSASocketW = try_get_WSASocketW(); + if (!_pfnWSASocketW) + { + WSASetLastError(WSAVERNOTSUPPORTED); + return INVALID_SOCKET; + } + + // This include Windows 7 non-SP1 + if (internal::GetSystemVersion() < __WindowsNT6_1_SP1) + { + // This flag is supported on Windows 7 with SP1, Windows Server 2008 R2 with SP1, and later + // So we strip it to prevent error on prior OS, because process handle inheritance doesn't really matter at that point + dwFlags &= ~WSA_FLAG_NO_HANDLE_INHERIT; + } + + return _pfnWSASocketW(af, type, protocol, lpProtocolInfo, g, dwFlags); + } +#endif + + +#if (YY_Thunks_Target < __WindowsNT6_1_SP1) + + // 最低 Windows XP + // 虽然Windows XP支持这个API,但是Windows 7 SP1开始才支持 WSA_FLAG_NO_HANDLE_INHERIT 标记 + __DEFINE_THUNK( + ws2_32, + 24, + SOCKET, + WSAAPI, + WSASocketA, + _In_ int af, + _In_ int type, + _In_ int protocol, + _In_opt_ LPWSAPROTOCOL_INFOA lpProtocolInfo, + _In_ GROUP g, + _In_ DWORD dwFlags + ) + { + auto const _pfnWSASocketA = try_get_WSASocketA(); + if (!_pfnWSASocketA) + { + WSASetLastError(WSAVERNOTSUPPORTED); + return INVALID_SOCKET; + } + + // This include Windows 7 non-SP1 + if (internal::GetSystemVersion() < __WindowsNT6_1_SP1) + { + // This flag is supported on Windows 7 with SP1, Windows Server 2008 R2 with SP1, and later + // So we strip it to prevent error on prior OS, because process handle inheritance doesn't really matter at that point + dwFlags &= ~WSA_FLAG_NO_HANDLE_INHERIT; + } + + return _pfnWSASocketA(af, type, protocol, lpProtocolInfo, g, dwFlags); + } +#endif + + #if (YY_Thunks_Target < __WindowsNT6_2) // 最低受支持的客户端 Windows 8.1、Windows 8 [桌面应用 |UWP 应用] diff --git a/src/Thunks/YY_Thunks.cpp b/src/Thunks/YY_Thunks.cpp index 7b2f9b4..1eedbad 100644 --- a/src/Thunks/YY_Thunks.cpp +++ b/src/Thunks/YY_Thunks.cpp @@ -292,23 +292,27 @@ namespace YY::Thunks::internal #endif } - __forceinline constexpr DWORD __fastcall MakeVersion(_In_ DWORD _uMajorVersion, _In_ DWORD _uMinorVersion) + __forceinline constexpr uint64_t __fastcall MakeVersion(_In_ uint16_t _uMajor, _In_ uint16_t _uMinor, uint16_t _uBuild = 0, UINT16 _uRevision = 0) { - return (_uMajorVersion << 16) | _uMinorVersion; + uint64_t _uVersion = uint64_t(_uMajor) << 48; + _uVersion |= uint64_t(_uMinor) << 32; + _uVersion |= uint64_t(_uBuild) << 16; + _uVersion |= _uRevision; + return _uVersion; } #ifdef __YY_Thunks_Unit_Test - EXTERN_C DWORD g_uSystemVersion = 0; + EXTERN_C uint64_t g_uSystemVersion = 0; #endif - __forceinline DWORD __fastcall GetSystemVersion() + __forceinline uint64_t __fastcall GetSystemVersion() { #ifdef __YY_Thunks_Unit_Test if (g_uSystemVersion) return g_uSystemVersion; #endif const auto _pPeb = ((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock; - return internal::MakeVersion(_pPeb->OSMajorVersion, _pPeb->OSMinorVersion); + return internal::MakeVersion(_pPeb->OSMajorVersion, _pPeb->OSMinorVersion, _pPeb->OSBuildNumber); } const SYSTEM_INFO& GetNativeSystemInfo() diff --git a/src/YY-Thunks.UnitTest/Crypt32.UnitTest.cpp b/src/YY-Thunks.UnitTest/Crypt32.UnitTest.cpp index 2ca2570..ea8d5e0 100644 --- a/src/YY-Thunks.UnitTest/Crypt32.UnitTest.cpp +++ b/src/YY-Thunks.UnitTest/Crypt32.UnitTest.cpp @@ -14,7 +14,7 @@ namespace Crypt32 public: CryptBinaryToStringW() { - g_uSystemVersion = MakeVersion(5, 1); + g_uSystemVersion = MakeVersion(5, 1, 2600); } ~CryptBinaryToStringW() diff --git a/src/YY-Thunks.UnitTest/pch.h b/src/YY-Thunks.UnitTest/pch.h index 95b3e53..f33c235 100644 --- a/src/YY-Thunks.UnitTest/pch.h +++ b/src/YY-Thunks.UnitTest/pch.h @@ -27,7 +27,7 @@ #include -EXTERN_C DWORD g_uSystemVersion; +EXTERN_C uint64_t g_uSystemVersion; using namespace Microsoft::VisualStudio::CppUnitTestFramework; @@ -111,9 +111,13 @@ inline std::string ToHexString(const BYTE (&_Data)[kDataLength]) return ToHexString(_Data, kDataLength); } -inline constexpr DWORD __fastcall MakeVersion(_In_ DWORD _uMajorVersion, _In_ DWORD _uMinorVersion) +__forceinline constexpr uint64_t __fastcall MakeVersion(_In_ uint16_t _uMajor, _In_ uint16_t _uMinor, uint16_t _uBuild = 0, UINT16 _uRevision = 0) { - return (_uMajorVersion << 16) | _uMinorVersion; + uint64_t _uVersion = uint64_t(_uMajor) << 48; + _uVersion |= uint64_t(_uMinor) << 32; + _uVersion |= uint64_t(_uBuild) << 16; + _uVersion |= _uRevision; + return _uVersion; } std::string ReadFileData(LPCWSTR _szFilePath);