Module: wine Branch: master Commit: 495711c251bad8d39e13af7addfaccc938a2a670 URL: https://gitlab.winehq.org/wine/wine/-/commit/495711c251bad8d39e13af7addfaccc...
Author: Eric Pouech eric.pouech@gmail.com Date: Mon Dec 12 16:58:12 2022 +0100
ntdll: Fix export and calling convention of RtlUlonglongByteSwap().
The RtlU*ByteSwap() family: - has FASTCALL calling convention - is only exported from ntdll and ntoskrnl.exe in 32bit mode (didn't check ARM though)
Wine's support for RtlUlonglongByteSwap() doesn't follow these constraints. Note: in __fastcall, 64bit paramaters are passed on the stack, to RtlUlonglongByteSwap() calling convention acts as __stdcall.
So: - fix ntdll.spec (resp. ntoskrnl.exe.spec) to only export (resp. forward) RtlUlonglongByteSwap for i386 - always provide an inline implementation in winternl.h - reimplement ntdll.RtlUlonglongByteSwap() for i386 with __fastcall calling convention. - fix ntdll/tests/rtl.c to use correct calling convention. - add test in ntdll/tests/rtl.c for inlined version.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53536 Signed-off-by: Eric Pouech eric.pouech@gmail.com
---
dlls/ntdll/ntdll.spec | 2 +- dlls/ntdll/rtl.c | 12 ++++++++---- dlls/ntdll/tests/rtl.c | 24 ++++++++++++++---------- dlls/ntoskrnl.exe/ntoskrnl.c | 13 +++++++++++++ dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- include/winternl.h | 15 +++++++-------- 6 files changed, 44 insertions(+), 24 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 1e6576a5422..5b4cbbaa7fe 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1039,7 +1039,7 @@ @ stdcall RtlTryEnterCriticalSection(ptr) @ stdcall RtlUTF8ToUnicodeN(ptr long ptr ptr long) @ cdecl -i386 -norelay RtlUlongByteSwap() NTDLL_RtlUlongByteSwap -@ cdecl -ret64 RtlUlonglongByteSwap(int64) +@ stdcall -fastcall -arch=i386 -norelay RtlUlonglongByteSwap(int64) # @ stub RtlUnhandledExceptionFilter2 # @ stub RtlUnhandledExceptionFilter @ stdcall RtlUnicodeStringToAnsiSize(ptr) diff --git a/dlls/ntdll/rtl.c b/dlls/ntdll/rtl.c index 5ff6205fe05..00bc16bbfa5 100644 --- a/dlls/ntdll/rtl.c +++ b/dlls/ntdll/rtl.c @@ -641,10 +641,14 @@ DWORD WINAPI RtlComputeCrc32(DWORD dwInitial, const BYTE *pData, INT iLen) * RETURNS * The value with its bytes swapped. */ -ULONGLONG __cdecl RtlUlonglongByteSwap(ULONGLONG i) -{ - return ((ULONGLONG)RtlUlongByteSwap(i) << 32) | RtlUlongByteSwap(i>>32); -} +#ifdef __i386__ +__ASM_FASTCALL_FUNC(RtlUlonglongByteSwap, 8, + "movl 4(%esp),%edx\n\t" + "bswap %edx\n\t" + "movl 8(%esp),%eax\n\t" + "bswap %eax\n\t" + "ret $8") +#endif
/************************************************************************* * RtlUlongByteSwap [NTDLL.@] diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c index 2e0bfb650e4..8f698454957 100644 --- a/dlls/ntdll/tests/rtl.c +++ b/dlls/ntdll/tests/rtl.c @@ -68,7 +68,7 @@ static VOID (WINAPI *pRtlMoveMemory)(LPVOID,LPCVOID,SIZE_T); static VOID (WINAPI *pRtlFillMemory)(LPVOID,SIZE_T,BYTE); static VOID (WINAPI *pRtlFillMemoryUlong)(LPVOID,SIZE_T,ULONG); static VOID (WINAPI *pRtlZeroMemory)(LPVOID,SIZE_T); -static ULONGLONG (WINAPIV *pRtlUlonglongByteSwap)(ULONGLONG source); +static ULONGLONG (FASTCALL *pRtlUlonglongByteSwap)(ULONGLONG source); static DWORD (WINAPI *pRtlGetThreadErrorMode)(void); static NTSTATUS (WINAPI *pRtlSetThreadErrorMode)(DWORD, LPDWORD); static NTSTATUS (WINAPI *pRtlIpv4AddressToStringExA)(const IN_ADDR *, USHORT, LPSTR, PULONG); @@ -319,18 +319,22 @@ static void test_RtlZeroMemory(void)
static void test_RtlUlonglongByteSwap(void) { - ULONGLONG result; + ULONGLONG llresult;
- if ( !pRtlUlonglongByteSwap ) +#ifdef _WIN64 + /* the Rtl*ByteSwap() are always inlined and not exported from ntdll on 64bit */ + llresult = RtlUlonglongByteSwap( 0x7654321087654321ull ); + ok( 0x2143658710325476 == llresult, + "inlined RtlUlonglongByteSwap() returns %#I64x\n", llresult ); +#else + ok( pRtlUlonglongByteSwap != NULL, "RtlUlonglongByteSwap is not available\n"); + if ( pRtlUlonglongByteSwap ) { - win_skip("RtlUlonglongByteSwap is not available\n"); - return; + llresult = pRtlUlonglongByteSwap( 0x7654321087654321ull ); + ok( 0x2143658710325476ull == llresult, + "ntdll.RtlUlonglongByteSwap() returns %#I64x\n", llresult ); } - - result = pRtlUlonglongByteSwap( ((ULONGLONG)0x76543210 << 32) | 0x87654321 ); - ok( (((ULONGLONG)0x21436587 << 32) | 0x10325476) == result, - "RtlUlonglongByteSwap(0x7654321087654321) returns 0x%s, expected 0x2143658710325476\n", - wine_dbgstr_longlong(result)); +#endif }
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index ce92f6805ab..9548eb98542 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -2185,6 +2185,19 @@ LONG FASTCALL NTOSKRNL_InterlockedIncrement( LONG volatile *dest ) return InterlockedIncrement( dest ); }
+#ifdef __i386__ + +/************************************************************************* + * RtlUlonglongByteSwap (NTOSKRNL.EXE.@) + */ +__ASM_FASTCALL_FUNC(RtlUlonglongByteSwap, 8, + "movl 4(%esp),%edx\n\t" + "bswap %edx\n\t" + "movl 8(%esp),%eax\n\t" + "bswap %eax\n\t" + "ret $8") + +#endif /* __i386__ */
/*********************************************************************** * ExAllocatePool (NTOSKRNL.EXE.@) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 0a484829ca3..321083e5ac4 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -68,7 +68,7 @@ @ stdcall -fastcall ObfReferenceObject(ptr) @ stub RtlPrefetchMemoryNonTemporal @ cdecl -i386 -norelay RtlUlongByteSwap() -@ cdecl -ret64 RtlUlonglongByteSwap(int64) +@ stdcall -fastcall -arch=i386 -norelay RtlUlonglongByteSwap(int64) @ cdecl -i386 -norelay RtlUshortByteSwap() @ stub WmiGetClock @ stub Kei386EoiHelper diff --git a/include/winternl.h b/include/winternl.h index 5a99827fe65..c720d962933 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -4567,7 +4567,6 @@ NTSYSAPI BOOLEAN WINAPI RtlTryAcquireSRWLockExclusive(RTL_SRWLOCK *); NTSYSAPI BOOLEAN WINAPI RtlTryAcquireSRWLockShared(RTL_SRWLOCK *); NTSYSAPI BOOL WINAPI RtlTryEnterCriticalSection(RTL_CRITICAL_SECTION *); NTSYSAPI NTSTATUS WINAPI RtlUTF8ToUnicodeN(WCHAR*,DWORD,DWORD*,const char*,DWORD); -NTSYSAPI ULONGLONG __cdecl RtlUlonglongByteSwap(ULONGLONG); NTSYSAPI DWORD WINAPI RtlUnicodeStringToAnsiSize(const UNICODE_STRING*); NTSYSAPI NTSTATUS WINAPI RtlUnicodeStringToAnsiString(PANSI_STRING,PCUNICODE_STRING,BOOLEAN); NTSYSAPI NTSTATUS WINAPI RtlUnicodeStringToInteger(const UNICODE_STRING *,ULONG,ULONG *); @@ -4733,20 +4732,20 @@ static inline BOOLEAN RtlCheckBit(PCRTL_BITMAP lpBits, ULONG ulBit) return FALSE; }
-/* These are implemented as __fastcall, so we can't let Winelib apps link with them */ +/* These are implemented as __fastcall, so we can't let Winelib apps link with them. + * Moreover, they're always inlined and not exported on 64bit systems. + */ static inline USHORT RtlUshortByteSwap(USHORT s) { return (s >> 8) | (s << 8); } static inline ULONG RtlUlongByteSwap(ULONG i) { -#if defined(__i386__) && defined(__GNUC__) - ULONG ret; - __asm__("bswap %0" : "=r" (ret) : "0" (i) ); - return ret; -#else return ((ULONG)RtlUshortByteSwap((USHORT)i) << 16) | RtlUshortByteSwap((USHORT)(i >> 16)); -#endif +} +static inline ULONGLONG RtlUlonglongByteSwap(ULONGLONG i) +{ + return ((ULONGLONG)RtlUlongByteSwap((ULONG)i) << 32) | RtlUlongByteSwap((ULONG)(i >> 32)); }
/* list manipulation macros */