[PATCH 2/2] ntdll: Extend NtGetTickCount() to return 64-bits. Forward kernel32 functions to it.

Andrew Wesie awesie at gmail.com
Tue May 28 16:04:06 CDT 2019


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



More information about the wine-devel mailing list