From a4ce2f652d76d033a79434416ff585cd15356a87 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 11 Jun 2020 10:07:09 +0200 Subject: [PATCH] ntdll: Move Nt system time functions to the Unix library. Signed-off-by: Alexandre Julliard --- dlls/ntdll/time.c | 125 +++------------------------------ dlls/ntdll/unix/loader.c | 3 + dlls/ntdll/unix/sync.c | 110 +++++++++++++++++++++++++++++ dlls/ntdll/unix/unix_private.h | 1 + dlls/ntdll/unix/virtual.c | 2 +- dlls/ntdll/unixlib.h | 5 +- 6 files changed, 127 insertions(+), 119 deletions(-) diff --git a/dlls/ntdll/time.c b/dlls/ntdll/time.c index f900b55d839..4d3c8afae65 100644 --- a/dlls/ntdll/time.c +++ b/dlls/ntdll/time.c @@ -38,9 +38,6 @@ #ifdef HAVE_UNISTD_H # include #endif -#ifdef __APPLE__ -# include -#endif #include "ntstatus.h" #define WIN32_NO_STATUS @@ -103,33 +100,6 @@ static inline BOOL IsLeapYear(int Year) return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0); } -/* return a monotonic time counter, in Win32 ticks */ -static inline ULONGLONG monotonic_counter(void) -{ - struct timeval now; - -#ifdef __APPLE__ - static mach_timebase_info_data_t timebase; - - if (!timebase.denom) mach_timebase_info( &timebase ); -#ifdef HAVE_MACH_CONTINUOUS_TIME - if (&mach_continuous_time != NULL) - return mach_continuous_time() * timebase.numer / timebase.denom / 100; -#endif - return mach_absolute_time() * timebase.numer / timebase.denom / 100; -#elif defined(HAVE_CLOCK_GETTIME) - struct timespec ts; -#ifdef CLOCK_MONOTONIC_RAW - if (!clock_gettime( CLOCK_MONOTONIC_RAW, &ts )) - return ts.tv_sec * (ULONGLONG)TICKSPERSEC + ts.tv_nsec / 100; -#endif - if (!clock_gettime( CLOCK_MONOTONIC, &ts )) - return ts.tv_sec * (ULONGLONG)TICKSPERSEC + ts.tv_nsec / 100; -#endif - - gettimeofday( &now, 0 ); - return now.tv_sec * (ULONGLONG)TICKSPERSEC + now.tv_usec * 10 + TICKS_1601_TO_1970 - server_start_time; -} /****************************************************************************** * RtlTimeToTimeFields [NTDLL.@] @@ -471,38 +441,7 @@ void WINAPI RtlTimeToElapsedTimeFields( const LARGE_INTEGER *Time, PTIME_FIELDS */ NTSTATUS WINAPI NtQuerySystemTime( LARGE_INTEGER *time ) { -#ifdef HAVE_CLOCK_GETTIME - struct timespec ts; - static clockid_t clock_id = CLOCK_MONOTONIC; /* placeholder */ - - if (clock_id == CLOCK_MONOTONIC) - { -#ifdef CLOCK_REALTIME_COARSE - struct timespec res; - - /* Use CLOCK_REALTIME_COARSE if it has 1 ms or better resolution */ - if (!clock_getres( CLOCK_REALTIME_COARSE, &res ) && res.tv_sec == 0 && res.tv_nsec <= 1000000) - clock_id = CLOCK_REALTIME_COARSE; - else -#endif /* CLOCK_REALTIME_COARSE */ - clock_id = CLOCK_REALTIME; - } - - if (!clock_gettime( clock_id, &ts )) - { - time->QuadPart = ts.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970; - time->QuadPart += (ts.tv_nsec + 50) / 100; - } - else -#endif /* HAVE_CLOCK_GETTIME */ - { - struct timeval now; - - gettimeofday( &now, 0 ); - time->QuadPart = now.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970; - time->QuadPart += now.tv_usec * 10; - } - return STATUS_SUCCESS; + return unix_funcs->NtQuerySystemTime( time ); } /*********************************************************************** @@ -543,18 +482,18 @@ LONGLONG WINAPI RtlGetSystemTimePrecise( void ) */ NTSTATUS WINAPI NtQueryPerformanceCounter( LARGE_INTEGER *counter, LARGE_INTEGER *frequency ) { + NTSTATUS status; + __TRY { - counter->QuadPart = monotonic_counter(); - if (frequency) frequency->QuadPart = TICKSPERSEC; + status = unix_funcs->NtQueryPerformanceCounter( counter, frequency ); } __EXCEPT_PAGE_FAULT { return STATUS_ACCESS_VIOLATION; } __ENDTRY - - return STATUS_SUCCESS; + return status; } /****************************************************************************** @@ -562,7 +501,7 @@ NTSTATUS WINAPI NtQueryPerformanceCounter( LARGE_INTEGER *counter, LARGE_INTEGER */ BOOL WINAPI DECLSPEC_HOTPATCH RtlQueryPerformanceCounter( LARGE_INTEGER *counter ) { - counter->QuadPart = monotonic_counter(); + unix_funcs->NtQueryPerformanceCounter( counter, NULL ); return TRUE; } @@ -1070,58 +1009,10 @@ NTSTATUS WINAPI RtlSetTimeZoneInformation( const RTL_TIME_ZONE_INFORMATION *tzin /*********************************************************************** * NtSetSystemTime [NTDLL.@] * ZwSetSystemTime [NTDLL.@] - * - * Set the system time. - * - * PARAMS - * NewTime [I] The time to set. - * OldTime [O] Optional destination for the previous system time. - * - * RETURNS - * Success: STATUS_SUCCESS. - * Failure: An NTSTATUS error code indicating the problem. */ -NTSTATUS WINAPI NtSetSystemTime(const LARGE_INTEGER *NewTime, LARGE_INTEGER *OldTime) +NTSTATUS WINAPI NtSetSystemTime(const LARGE_INTEGER *new, LARGE_INTEGER *old ) { - struct timeval tv; - time_t tm_t; - DWORD sec, oldsec; - LARGE_INTEGER tm; - - /* Return the old time if necessary */ - if (!OldTime) OldTime = &tm; - - NtQuerySystemTime( OldTime ); - if (!RtlTimeToSecondsSince1970( OldTime, &oldsec )) return STATUS_INVALID_PARAMETER; - if (!RtlTimeToSecondsSince1970( NewTime, &sec )) return STATUS_INVALID_PARAMETER; - - /* fake success if time didn't change */ - if (oldsec == sec) - return STATUS_SUCCESS; - - /* set the new time */ - tv.tv_sec = sec; - tv.tv_usec = 0; - -#ifdef HAVE_SETTIMEOFDAY - tm_t = sec; - if (!settimeofday(&tv, NULL)) /* 0 is OK, -1 is error */ - { - TRACE("OS time changed to %s\n", ctime(&tm_t)); - return STATUS_SUCCESS; - } - ERR("Cannot set time to %s, time adjustment %ld: %s\n", - ctime(&tm_t), (long)(sec-oldsec), strerror(errno)); - if (errno == EPERM) - return STATUS_PRIVILEGE_NOT_HELD; - else - return STATUS_INVALID_PARAMETER; -#else - tm_t = sec; - FIXME("setting time to %s not implemented for missing settimeofday\n", - ctime(&tm_t)); - return STATUS_NOT_IMPLEMENTED; -#endif + return unix_funcs->NtSetSystemTime( new, old ); } /*********************************************************************** diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index eac43ba42c4..da41805c6b6 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1018,8 +1018,10 @@ static struct unix_funcs unix_funcs = NtPulseEvent, NtQueryEvent, NtQueryMutant, + NtQueryPerformanceCounter, NtQuerySection, NtQuerySemaphore, + NtQuerySystemTime, NtQueryTimer, NtQueryVirtualMemory, NtQueueApcThread, @@ -1034,6 +1036,7 @@ static struct unix_funcs unix_funcs = NtSetContextThread, NtSetEvent, NtSetLdtEntries, + NtSetSystemTime, NtSetTimer, NtSignalAndWaitForSingleObject, NtSuspendThread, diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index 03b511881b7..e5eec38c5aa 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -59,6 +59,7 @@ # include # include # include +# include #endif #include "ntstatus.h" @@ -66,6 +67,7 @@ #define NONAMELESSUNION #include "windef.h" #include "winternl.h" +#include "ddk/wdm.h" #include "wine/server.h" #include "wine/debug.h" #include "unix_private.h" @@ -73,6 +75,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(sync); #define TICKSPERSEC 10000000 +#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)86400) +#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC) HANDLE keyed_event = 0; @@ -87,6 +91,34 @@ static RTL_CRITICAL_SECTION_DEBUG addr_section_debug = }; static RTL_CRITICAL_SECTION addr_section = { &addr_section_debug, -1, 0, 0, 0, 0 }; + +/* return a monotonic time counter, in Win32 ticks */ +static inline ULONGLONG monotonic_counter(void) +{ + struct timeval now; +#ifdef __APPLE__ + static mach_timebase_info_data_t timebase; + + if (!timebase.denom) mach_timebase_info( &timebase ); +#ifdef HAVE_MACH_CONTINUOUS_TIME + if (&mach_continuous_time != NULL) + return mach_continuous_time() * timebase.numer / timebase.denom / 100; +#endif + return mach_absolute_time() * timebase.numer / timebase.denom / 100; +#elif defined(HAVE_CLOCK_GETTIME) + struct timespec ts; +#ifdef CLOCK_MONOTONIC_RAW + if (!clock_gettime( CLOCK_MONOTONIC_RAW, &ts )) + return ts.tv_sec * (ULONGLONG)TICKSPERSEC + ts.tv_nsec / 100; +#endif + if (!clock_gettime( CLOCK_MONOTONIC, &ts )) + return ts.tv_sec * (ULONGLONG)TICKSPERSEC + ts.tv_nsec / 100; +#endif + gettimeofday( &now, 0 ); + return now.tv_sec * (ULONGLONG)TICKSPERSEC + now.tv_usec * 10 + TICKS_1601_TO_1970 - server_start_time; +} + + #ifdef __linux__ #define FUTEX_WAIT 0 @@ -906,6 +938,84 @@ NTSTATUS WINAPI NtDelayExecution( BOOLEAN alertable, const LARGE_INTEGER *timeou } +/****************************************************************************** + * NtQueryPerformanceCounter (NTDLL.@) + */ +NTSTATUS WINAPI NtQueryPerformanceCounter( LARGE_INTEGER *counter, LARGE_INTEGER *frequency ) +{ + counter->QuadPart = monotonic_counter(); + if (frequency) frequency->QuadPart = TICKSPERSEC; + return STATUS_SUCCESS; +} + + +/*********************************************************************** + * NtQuerySystemTime (NTDLL.@) + */ +NTSTATUS WINAPI NtQuerySystemTime( LARGE_INTEGER *time ) +{ +#ifdef HAVE_CLOCK_GETTIME + struct timespec ts; + static clockid_t clock_id = CLOCK_MONOTONIC; /* placeholder */ + + if (clock_id == CLOCK_MONOTONIC) + { +#ifdef CLOCK_REALTIME_COARSE + struct timespec res; + + /* Use CLOCK_REALTIME_COARSE if it has 1 ms or better resolution */ + if (!clock_getres( CLOCK_REALTIME_COARSE, &res ) && res.tv_sec == 0 && res.tv_nsec <= 1000000) + clock_id = CLOCK_REALTIME_COARSE; + else +#endif /* CLOCK_REALTIME_COARSE */ + clock_id = CLOCK_REALTIME; + } + + if (!clock_gettime( clock_id, &ts )) + { + time->QuadPart = ts.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970; + time->QuadPart += (ts.tv_nsec + 50) / 100; + } + else +#endif /* HAVE_CLOCK_GETTIME */ + { + struct timeval now; + + gettimeofday( &now, 0 ); + time->QuadPart = now.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970; + time->QuadPart += now.tv_usec * 10; + } + return STATUS_SUCCESS; +} + + +/*********************************************************************** + * NtSetSystemTime (NTDLL.@) + */ +NTSTATUS WINAPI NtSetSystemTime( const LARGE_INTEGER *new, LARGE_INTEGER *old ) +{ + LARGE_INTEGER now; + LONGLONG diff; + + NtQuerySystemTime( &now ); + if (old) *old = now; + diff = new->QuadPart - now.QuadPart; + if (diff > -TICKSPERSEC / 2 && diff < TICKSPERSEC / 2) return STATUS_SUCCESS; + ERR( "not allowed: difference %d ms\n", (int)(diff / 10000) ); + return STATUS_PRIVILEGE_NOT_HELD; +} + + +/****************************************************************************** + * NtGetTickCount (NTDLL.@) + */ +ULONG WINAPI NtGetTickCount(void) +{ + /* note: we ignore TickCountMultiplier */ + return user_shared_data->u.TickCount.LowPart; +} + + /****************************************************************************** * NtCreateKeyedEvent (NTDLL.@) */ diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 3e61111cba5..f056cc5ed0f 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -121,6 +121,7 @@ extern timeout_t server_start_time DECLSPEC_HIDDEN; extern sigset_t server_block_set DECLSPEC_HIDDEN; extern SIZE_T signal_stack_size DECLSPEC_HIDDEN; extern SIZE_T signal_stack_mask DECLSPEC_HIDDEN; +extern struct _KUSER_SHARED_DATA *user_shared_data DECLSPEC_HIDDEN; extern unsigned int server_call_unlocked( void *req_ptr ) DECLSPEC_HIDDEN; extern void server_enter_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 512cf12a742..0f886a3bb2e 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -161,7 +161,7 @@ static void *user_space_limit = (void *)0x7fff0000; static void *working_set_limit = (void *)0x7fff0000; #endif -static struct _KUSER_SHARED_DATA *user_shared_data = (void *)0x7ffe0000; +struct _KUSER_SHARED_DATA *user_shared_data = (void *)0x7ffe0000; SIZE_T signal_stack_size = 0; SIZE_T signal_stack_mask = 0; diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h index 80d3ce27601..07dc832635d 100644 --- a/dlls/ntdll/unixlib.h +++ b/dlls/ntdll/unixlib.h @@ -28,7 +28,7 @@ struct ldt_copy; struct msghdr; /* increment this when you change the function table */ -#define NTDLL_UNIXLIB_VERSION 37 +#define NTDLL_UNIXLIB_VERSION 38 struct unix_funcs { @@ -96,10 +96,12 @@ struct unix_funcs void *info, ULONG len, ULONG *ret_len ); NTSTATUS (WINAPI *NtQueryMutant)( HANDLE handle, MUTANT_INFORMATION_CLASS class, void *info, ULONG len, ULONG *ret_len ); + NTSTATUS (WINAPI *NtQueryPerformanceCounter)( LARGE_INTEGER *counter, LARGE_INTEGER *frequency ); NTSTATUS (WINAPI *NtQuerySection)( HANDLE handle, SECTION_INFORMATION_CLASS class, void *ptr, SIZE_T size, SIZE_T *ret_size ); NTSTATUS (WINAPI *NtQuerySemaphore)( HANDLE handle, SEMAPHORE_INFORMATION_CLASS class, void *info, ULONG len, ULONG *ret_len ); + NTSTATUS (WINAPI *NtQuerySystemTime)( LARGE_INTEGER *time ); NTSTATUS (WINAPI *NtQueryTimer)( HANDLE handle, TIMER_INFORMATION_CLASS class, void *info, ULONG len, ULONG *ret_len ); NTSTATUS (WINAPI *NtQueryVirtualMemory)( HANDLE process, LPCVOID addr, @@ -120,6 +122,7 @@ struct unix_funcs NTSTATUS (WINAPI *NtSetContextThread)( HANDLE handle, const CONTEXT *context ); NTSTATUS (WINAPI *NtSetEvent)( HANDLE handle, LONG *prev_state ); NTSTATUS (WINAPI *NtSetLdtEntries)( ULONG sel1, LDT_ENTRY entry1, ULONG sel2, LDT_ENTRY entry2 ); + NTSTATUS (WINAPI *NtSetSystemTime)( const LARGE_INTEGER *new, LARGE_INTEGER *old ); NTSTATUS (WINAPI *NtSetTimer)( HANDLE handle, const LARGE_INTEGER *when, PTIMER_APC_ROUTINE callback, void *arg, BOOLEAN resume, ULONG period, BOOLEAN *state );