This patch broke the anti-cheat for Blizzard games (https://bugs.winehq.org/show_bug.cgi?id=47265). I narrowed it down to forwarding kernel32's GetTickCount to ntdll's NtGetTickCount. Writing a small C wrapper "fixes" the problem, and a sample patch is attached to the bug report.
It would be nice to get this fixed for the next Wine release.
-Andrew
On Thu, May 16, 2019 at 4:21 AM Huw Davies huw@codeweavers.com wrote:
Marking the function as DECLSPEC_HOTPATCH to avoid reopening https://bugs.winehq.org/show_bug.cgi?id=36486 . Even with -fno-PIC, without DECLSPEC_HOTPATCH the generated code has a pushl at offset 7 that triggers the failure.
Signed-off-by: Huw Davies huw@codeweavers.com
dlls/kernel32/kernel32.spec | 4 ++-- dlls/kernel32/kernel_main.c | 32 -------------------------------- dlls/kernel32/path.c | 2 +- dlls/ntdll/ntdll.spec | 4 ++-- dlls/ntdll/ntdll_misc.h | 4 ++++ dlls/ntdll/time.c | 2 +- 6 files changed, 10 insertions(+), 38 deletions(-)
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index f887b1dc8c..691cc60d86 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -858,8 +858,8 @@ @ stdcall GetThreadPriorityBoost(long ptr) @ stdcall GetThreadSelectorEntry(long long ptr) @ stdcall GetThreadTimes(long ptr ptr ptr ptr) -@ stdcall GetTickCount() -@ stdcall -ret64 GetTickCount64() +@ stdcall GetTickCount() ntdll.NtGetTickCount +@ stdcall -ret64 GetTickCount64() ntdll.NtGetTickCount @ stdcall GetTimeFormatA(long long ptr str ptr long) @ stdcall GetTimeFormatEx(wstr long ptr wstr ptr long) @ stdcall GetTimeFormatW(long long ptr wstr ptr long) diff --git a/dlls/kernel32/kernel_main.c b/dlls/kernel32/kernel_main.c index d3420ece06..dfa66f0295 100644 --- a/dlls/kernel32/kernel_main.c +++ b/dlls/kernel32/kernel_main.c @@ -178,38 +178,6 @@ INT WINAPI MulDiv( INT nMultiplicand, INT nMultiplier, INT nDivisor) return ret; }
-/******************************************************************************
GetTickCount64 (KERNEL32.@)
- */
-ULONGLONG WINAPI DECLSPEC_HOTPATCH GetTickCount64(void) -{
- LARGE_INTEGER counter, frequency;
- NtQueryPerformanceCounter( &counter, &frequency );
- return counter.QuadPart * 1000 / frequency.QuadPart;
-}
-/***********************************************************************
GetTickCount (KERNEL32.@)
- Get the number of milliseconds the system has been running.
- PARAMS
- None.
- RETURNS
- The current tick count.
- NOTES
- The value returned will wrap around every 2^32 milliseconds.
- */
-DWORD WINAPI DECLSPEC_HOTPATCH GetTickCount(void) -{
- return GetTickCount64();
-}
/******************************************************************************
GetSystemRegistryQuota (KERNEL32.@)
*/ diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c index b8f49bd597..5fed28da0e 100644 --- a/dlls/kernel32/path.c +++ b/dlls/kernel32/path.c @@ -737,7 +737,7 @@ UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, LPWSTR { /* get a "random" unique number and try to create the file */ HANDLE handle;
UINT num = GetTickCount() & 0xffff;
UINT num = NtGetTickCount() & 0xffff; static UINT last; /* avoid using the same name twice in a short interval */
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index aeb9735ba1..050ebc7641 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -194,7 +194,7 @@ @ stdcall NtGetCurrentProcessorNumber() # @ stub NtGetDevicePowerState @ stub NtGetPlugPlayEvent -@ stdcall NtGetTickCount() +@ stdcall -ret64 NtGetTickCount() get_tick_count64 @ stdcall NtGetWriteWatch(long long ptr long ptr ptr ptr) @ stdcall NtImpersonateAnonymousToken(long) @ stub NtImpersonateClientOfPort @@ -1142,7 +1142,7 @@ @ stdcall -private ZwGetCurrentProcessorNumber() NtGetCurrentProcessorNumber # @ stub ZwGetDevicePowerState @ stub ZwGetPlugPlayEvent -@ stdcall -private ZwGetTickCount() NtGetTickCount +@ stdcall -private -ret64 ZwGetTickCount() get_tick_count64 @ stdcall -private ZwGetWriteWatch(long long ptr long ptr ptr ptr) NtGetWriteWatch @ stdcall -private ZwImpersonateAnonymousToken(long) NtImpersonateAnonymousToken @ stub ZwImpersonateClientOfPort diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 3463ebd38a..2d83f541bd 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -268,4 +268,8 @@ void WINAPI LdrInitializeThunk(CONTEXT*,void**,ULONG_PTR,ULONG_PTR); /* string functions */ int __cdecl NTDLL_tolower( int c ); int __cdecl _stricmp( LPCSTR str1, LPCSTR str2 );
+/* time functions */ +ULONGLONG WINAPI get_tick_count64( void ); +#define NtGetTickCount get_tick_count64 #endif diff --git a/dlls/ntdll/time.c b/dlls/ntdll/time.c index 20de627c28..41e456398e 100644 --- a/dlls/ntdll/time.c +++ b/dlls/ntdll/time.c @@ -557,7 +557,7 @@ NTSTATUS WINAPI NtQueryPerformanceCounter( LARGE_INTEGER *counter, LARGE_INTEGER
- NtGetTickCount (NTDLL.@)
- ZwGetTickCount (NTDLL.@)
*/ -ULONG WINAPI NtGetTickCount(void) +ULONGLONG WINAPI DECLSPEC_HOTPATCH get_tick_count64(void) { return monotonic_counter() / TICKSPERMSEC; } -- 2.17.1