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>
This commit is contained in:
Eric Pouech 2022-12-12 16:58:12 +01:00 committed by Alexandre Julliard
parent b7380acb6c
commit 495711c251
6 changed files with 44 additions and 24 deletions

View file

@ -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)

View file

@ -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.@]

View file

@ -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
}

View file

@ -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.@)

View file

@ -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

View file

@ -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 */