Skip to content

Commit

Permalink
Fea #80, WSASocketW(A) 添加 WSA_FLAG_NO_HANDLE_INHERIT标记兼容(PR# 126)
Browse files Browse the repository at this point in the history
  • Loading branch information
stevefan1999-personal authored and mingkuang-Chuyu committed Oct 19, 2024
1 parent 841f26f commit 2dfa6e5
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 10 deletions.
1 change: 1 addition & 0 deletions ThunksList.md
Original file line number Diff line number Diff line change
Expand Up @@ -813,3 +813,4 @@
| FreeAddrInfoEx(W) | 不存在时,内部实现。
| GetAddrInfoW | 不存在时,调用getaddrinfo。
| FreeAddrInfoW | 不存在时,内部实现。
| WSASocketW(A) | 低于6.1.7601时自动去除 `WSA_FLAG_NO_HANDLE_INHERIT`
85 changes: 84 additions & 1 deletion src/Thunks/WS2_32.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
#include <winsock2.h>
#if (YY_Thunks_Target < __WindowsNT6_2)
#include <winsock2.h>
#include <ws2tcpip.h>

#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
{
Expand Down Expand Up @@ -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 应用]
Expand Down
14 changes: 9 additions & 5 deletions src/Thunks/YY_Thunks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion src/YY-Thunks.UnitTest/Crypt32.UnitTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Crypt32
public:
CryptBinaryToStringW()
{
g_uSystemVersion = MakeVersion(5, 1);
g_uSystemVersion = MakeVersion(5, 1, 2600);
}

~CryptBinaryToStringW()
Expand Down
10 changes: 7 additions & 3 deletions src/YY-Thunks.UnitTest/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

#include <SharedDefs.h>

EXTERN_C DWORD g_uSystemVersion;
EXTERN_C uint64_t g_uSystemVersion;

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 2dfa6e5

Please sign in to comment.