dmsynth: Remove DECLSPEC_HIDDEN usage.
[wine.git] / dlls / ntdll / tests / time.c
blob7b8a3a5fa5dd959e3ff5f3392896e0948d0f68e8
1 /*
2 * Unit test suite for ntdll time functions
4 * Copyright 2004 Rein Klazes
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "ntdll_test.h"
22 #include "ddk/wdm.h"
23 #include "intrin.h"
25 #define TICKSPERSEC 10000000
26 #define TICKSPERMSEC 10000
27 #define SECSPERDAY 86400
29 static VOID (WINAPI *pRtlTimeToTimeFields)( const LARGE_INTEGER *liTime, PTIME_FIELDS TimeFields) ;
30 static VOID (WINAPI *pRtlTimeFieldsToTime)( PTIME_FIELDS TimeFields, PLARGE_INTEGER Time) ;
31 static NTSTATUS (WINAPI *pNtQueryPerformanceCounter)( LARGE_INTEGER *counter, LARGE_INTEGER *frequency );
32 static NTSTATUS (WINAPI *pNtQuerySystemInformation)( SYSTEM_INFORMATION_CLASS class,
33 void *info, ULONG size, ULONG *ret_size );
34 static NTSTATUS (WINAPI *pRtlQueryTimeZoneInformation)( RTL_TIME_ZONE_INFORMATION *);
35 static NTSTATUS (WINAPI *pRtlQueryDynamicTimeZoneInformation)( RTL_DYNAMIC_TIME_ZONE_INFORMATION *);
36 static BOOL (WINAPI *pRtlQueryUnbiasedInterruptTime)( ULONGLONG *time );
38 static BOOL (WINAPI *pRtlQueryPerformanceCounter)(LARGE_INTEGER*);
39 static BOOL (WINAPI *pRtlQueryPerformanceFrequency)(LARGE_INTEGER*);
41 static const int MonthLengths[2][12] =
43 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
44 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
47 static inline BOOL IsLeapYear(int Year)
49 return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0);
52 /* start time of the tests */
53 static TIME_FIELDS tftest = {1889,12,31,23,59,59,0,0};
55 static void test_pRtlTimeToTimeFields(void)
57 LARGE_INTEGER litime , liresult;
58 TIME_FIELDS tfresult;
59 int i=0;
60 litime.QuadPart = ((ULONGLONG)0x0144017a << 32) | 0xf0b0a980;
61 while( tftest.Year < 2110 ) {
62 /* test at the last second of the month */
63 pRtlTimeToTimeFields( &litime, &tfresult);
64 ok( tfresult.Year == tftest.Year && tfresult.Month == tftest.Month &&
65 tfresult.Day == tftest.Day && tfresult.Hour == tftest.Hour &&
66 tfresult.Minute == tftest.Minute && tfresult.Second == tftest.Second,
67 "#%d expected: %d-%d-%d %d:%d:%d got: %d-%d-%d %d:%d:%d\n", ++i,
68 tftest.Year, tftest.Month, tftest.Day,
69 tftest.Hour, tftest.Minute,tftest.Second,
70 tfresult.Year, tfresult.Month, tfresult.Day,
71 tfresult.Hour, tfresult.Minute, tfresult.Second);
72 /* test the inverse */
73 pRtlTimeFieldsToTime( &tfresult, &liresult);
74 ok( liresult.QuadPart == litime.QuadPart," TimeFieldsToTime failed on %d-%d-%d %d:%d:%d. Error is %d ticks\n",
75 tfresult.Year, tfresult.Month, tfresult.Day,
76 tfresult.Hour, tfresult.Minute, tfresult.Second,
77 (int) (liresult.QuadPart - litime.QuadPart) );
78 /* one second later is beginning of next month */
79 litime.QuadPart += TICKSPERSEC ;
80 pRtlTimeToTimeFields( &litime, &tfresult);
81 ok( tfresult.Year == tftest.Year + (tftest.Month ==12) &&
82 tfresult.Month == tftest.Month % 12 + 1 &&
83 tfresult.Day == 1 && tfresult.Hour == 0 &&
84 tfresult.Minute == 0 && tfresult.Second == 0,
85 "#%d expected: %d-%d-%d %d:%d:%d got: %d-%d-%d %d:%d:%d\n", ++i,
86 tftest.Year + (tftest.Month ==12),
87 tftest.Month % 12 + 1, 1, 0, 0, 0,
88 tfresult.Year, tfresult.Month, tfresult.Day,
89 tfresult.Hour, tfresult.Minute, tfresult.Second);
90 /* test the inverse */
91 pRtlTimeFieldsToTime( &tfresult, &liresult);
92 ok( liresult.QuadPart == litime.QuadPart," TimeFieldsToTime failed on %d-%d-%d %d:%d:%d. Error is %d ticks\n",
93 tfresult.Year, tfresult.Month, tfresult.Day,
94 tfresult.Hour, tfresult.Minute, tfresult.Second,
95 (int) (liresult.QuadPart - litime.QuadPart) );
96 /* advance to the end of the month */
97 litime.QuadPart -= TICKSPERSEC ;
98 if( tftest.Month == 12) {
99 tftest.Month = 1;
100 tftest.Year += 1;
101 } else
102 tftest.Month += 1;
103 tftest.Day = MonthLengths[IsLeapYear(tftest.Year)][tftest.Month - 1];
104 litime.QuadPart += (LONGLONG) tftest.Day * TICKSPERSEC * SECSPERDAY;
108 static void test_NtQueryPerformanceCounter(void)
110 LARGE_INTEGER counter, frequency;
111 NTSTATUS status;
113 status = pNtQueryPerformanceCounter(NULL, NULL);
114 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08lx\n", status);
115 status = pNtQueryPerformanceCounter(NULL, &frequency);
116 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08lx\n", status);
117 status = pNtQueryPerformanceCounter(&counter, (void *)0xdeadbee0);
118 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08lx\n", status);
119 status = pNtQueryPerformanceCounter((void *)0xdeadbee0, &frequency);
120 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08lx\n", status);
122 status = pNtQueryPerformanceCounter(&counter, NULL);
123 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
124 status = pNtQueryPerformanceCounter(&counter, &frequency);
125 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08lx\n", status);
128 #if defined(__i386__) || defined(__x86_64__)
130 struct hypervisor_shared_data
132 UINT64 unknown;
133 UINT64 QpcMultiplier;
134 UINT64 QpcBias;
137 /* 128-bit multiply a by b and return the high 64 bits, same as __umulh */
138 static UINT64 multiply_tsc(UINT64 a, UINT64 b)
140 UINT64 ah = a >> 32, al = (UINT32)a, bh = b >> 32, bl = (UINT32)b, m;
141 m = (ah * bl) + (bh * al) + ((al * bl) >> 32);
142 return (ah * bh) + (m >> 32);
145 static void test_RtlQueryPerformanceCounter(void)
147 struct hypervisor_shared_data *hsd;
148 KSHARED_USER_DATA *usd = (void *)0x7ffe0000;
149 LARGE_INTEGER frequency, counter;
150 NTSTATUS status;
151 UINT64 tsc0, tsc1;
152 ULONG len;
153 BOOL ret;
155 if (!pRtlQueryPerformanceCounter || !pRtlQueryPerformanceFrequency)
157 win_skip( "RtlQueryPerformanceCounter/Frequency not available, skipping tests\n" );
158 return;
161 if (!(usd->QpcBypassEnabled & SHARED_GLOBAL_FLAGS_QPC_BYPASS_ENABLED))
163 todo_wine win_skip("QpcBypassEnabled is not set, skipping tests\n");
164 return;
167 if ((usd->QpcBypassEnabled & SHARED_GLOBAL_FLAGS_QPC_BYPASS_USE_HV_PAGE))
169 ok( usd->QpcBypassEnabled == (SHARED_GLOBAL_FLAGS_QPC_BYPASS_ENABLED|SHARED_GLOBAL_FLAGS_QPC_BYPASS_USE_HV_PAGE|SHARED_GLOBAL_FLAGS_QPC_BYPASS_USE_RDTSCP),
170 "unexpected QpcBypassEnabled %x, expected 0x83\n", usd->QpcBypassEnabled );
171 ok( usd->QpcFrequency == 10000000, "unexpected QpcFrequency %I64d, expected 10000000\n", usd->QpcFrequency );
172 ok( !usd->QpcShift, "unexpected QpcShift %d, expected 0\n", usd->QpcShift );
174 hsd = NULL;
175 status = pNtQuerySystemInformation( SystemHypervisorSharedPageInformation, &hsd, sizeof(void *), &len );
176 ok( !status, "NtQuerySystemInformation returned %lx\n", status );
177 ok( len == sizeof(void *), "unexpected SystemHypervisorSharedPageInformation length %lu\n", len );
178 ok( !!hsd, "unexpected SystemHypervisorSharedPageInformation address %p\n", hsd );
180 tsc0 = __rdtsc();
181 ret = pRtlQueryPerformanceCounter( &counter );
182 tsc1 = __rdtsc();
183 ok( ret, "RtlQueryPerformanceCounter failed\n" );
185 tsc0 = multiply_tsc(tsc0, hsd->QpcMultiplier) + hsd->QpcBias + usd->QpcBias;
186 tsc1 = multiply_tsc(tsc1, hsd->QpcMultiplier) + hsd->QpcBias + usd->QpcBias;
188 ok( tsc0 <= counter.QuadPart, "rdtscp %I64d and RtlQueryPerformanceCounter %I64d are out of order\n", tsc0, counter.QuadPart );
189 ok( counter.QuadPart <= tsc1, "RtlQueryPerformanceCounter %I64d and rdtscp %I64d are out of order\n", counter.QuadPart, tsc1 );
191 else
193 ok( usd->QpcShift == 10, "unexpected QpcShift %d, expected 10\n", usd->QpcShift );
195 tsc0 = __rdtsc();
196 ret = pRtlQueryPerformanceCounter( &counter );
197 tsc1 = __rdtsc();
198 ok( ret, "RtlQueryPerformanceCounter failed\n" );
200 tsc0 += usd->QpcBias;
201 tsc0 >>= usd->QpcShift;
202 tsc1 += usd->QpcBias;
203 tsc1 >>= usd->QpcShift;
205 ok( tsc0 <= counter.QuadPart, "rdtscp %I64d and RtlQueryPerformanceCounter %I64d are out of order\n", tsc0, counter.QuadPart );
206 ok( counter.QuadPart <= tsc1, "RtlQueryPerformanceCounter %I64d and rdtscp %I64d are out of order\n", counter.QuadPart, tsc1 );
209 ret = pRtlQueryPerformanceFrequency( &frequency );
210 ok( ret, "RtlQueryPerformanceFrequency failed\n" );
211 ok( frequency.QuadPart == usd->QpcFrequency,
212 "RtlQueryPerformanceFrequency returned %I64d, expected USD QpcFrequency %I64d\n",
213 frequency.QuadPart, usd->QpcFrequency );
215 #endif
217 #define TIMER_LEEWAY 10
218 #define CHECK_CURRENT_TIMER(expected) \
219 do { \
220 ok(status == STATUS_SUCCESS, "NtSetTimerResolution failed %lx\n", status); \
221 ok(cur2 == (expected) || broken(abs((int)((expected) - cur2)) <= TIMER_LEEWAY), "expected new timer resolution %lu, got %lu\n", (expected), cur2); \
222 set = cur2; \
223 min2 = min + 20000; \
224 cur2 = min2 + 1; \
225 max2 = cur2 + 1; \
226 status = NtQueryTimerResolution(&min2, &max2, &cur2); \
227 ok(status == STATUS_SUCCESS, "NtQueryTimerResolution() failed %lx\n", status); \
228 ok(min2 == min, "NtQueryTimerResolution() expected min=%lu, got %lu\n", min, min2); \
229 ok(max2 == max, "NtQueryTimerResolution() expected max=%lu, got %lu\n", max, max2); \
230 ok(cur2 == set, "NtQueryTimerResolution() expected timer resolution %lu, got %lu\n", set, cur2); \
231 } while (0)
233 static void test_TimerResolution(void)
235 ULONG min, max, cur, min2, max2, cur2, set;
236 NTSTATUS status;
238 status = NtQueryTimerResolution(NULL, &max, &cur);
239 ok(status == STATUS_ACCESS_VIOLATION, "NtQueryTimerResolution(NULL,,) success\n");
241 status = NtQueryTimerResolution(&min, NULL, &cur);
242 ok(status == STATUS_ACCESS_VIOLATION, "NtQueryTimerResolution(,NULL,) success\n");
244 status = NtQueryTimerResolution(&min, &max, NULL);
245 ok(status == STATUS_ACCESS_VIOLATION, "NtQueryTimerResolution(,,NULL) success\n");
247 min = 212121;
248 cur = min + 1;
249 max = cur + 1;
250 status = NtQueryTimerResolution(&min, &max, &cur);
251 ok(status == STATUS_SUCCESS, "NtQueryTimerResolution() failed (%lx)\n", status);
252 ok(min == 156250 /* 1/64s HPET */ || min == 156001 /* RTC */,
253 "unexpected minimum timer resolution %lu\n", min);
254 ok(0 < max, "invalid maximum timer resolution, should be 0 < %lu\n", max);
255 ok(max <= cur || broken(max - TIMER_LEEWAY <= cur), "invalid timer resolutions, should be %lu <= %lu\n", max, cur);
256 ok(cur <= min || broken(cur <= min + TIMER_LEEWAY), "invalid timer resolutions, should be %lu <= %lu\n", cur, min);
258 status = NtSetTimerResolution(0, FALSE, NULL);
259 ok(status == STATUS_ACCESS_VIOLATION, "NtSetTimerResolution(,,NULL) success\n");
261 /* Nothing happens if that pointer is not good */
262 status = NtSetTimerResolution(cur - 1, TRUE, NULL);
263 ok(status == STATUS_ACCESS_VIOLATION, "NtSetTimerResolution() failed %lx\n", status);
265 min2 = min + 10000;
266 cur2 = min2 + 1;
267 max2 = cur2 + 1;
268 status = NtQueryTimerResolution(&min2, &max2, &cur2);
269 ok(status == STATUS_SUCCESS, "NtQueryTimerResolution() failed (%lx)\n", status);
270 ok(min2 == min, "NtQueryTimerResolution() expected min=%lu, got %lu\n", min, min2);
271 ok(max2 == max, "NtQueryTimerResolution() expected max=%lu, got %lu\n", max, max2);
272 ok(cur2 == cur, "NtQueryTimerResolution() expected timer resolution %lu, got %lu\n", cur, cur2);
274 /* 'fails' until the first valid timer resolution request */
275 cur2 = 7654321;
276 status = NtSetTimerResolution(0, FALSE, &cur2);
277 ok(status == STATUS_TIMER_RESOLUTION_NOT_SET, "NtSetTimerResolution() failed %lx\n", status);
278 /* and returns the current timer resolution */
279 ok(cur2 == cur, "expected requested timer resolution %lu, got %lu\n", cur, cur2);
282 cur2 = 7654321;
283 status = NtSetTimerResolution(max - 1, TRUE, &cur2);
284 CHECK_CURRENT_TIMER(max);
286 /* Rescinds our timer resolution request */
287 cur2 = 7654321;
288 status = NtSetTimerResolution(0, FALSE, &cur2);
289 ok(status == STATUS_SUCCESS, "NtSetTimerResolution() failed %lx\n", status);
290 /* -> the timer resolution was reset to its initial value */
291 ok(cur2 == cur, "expected requested timer resolution %lu, got %lu\n", min, cur2);
293 cur2 = 7654321;
294 status = NtSetTimerResolution(0, FALSE, &cur2);
295 ok(status == STATUS_TIMER_RESOLUTION_NOT_SET, "NtSetTimerResolution() failed %lx\n", status);
296 ok(cur2 == cur, "expected requested timer resolution %lu, got %lu\n", cur, cur2);
298 cur2 = 7654321;
299 status = NtSetTimerResolution(min + 1, TRUE, &cur2);
300 ok(status == STATUS_SUCCESS, "NtSetTimerResolution() failed %lx\n", status);
301 /* This works because:
302 * - Either cur is the minimum (15.6 ms) resolution already, i.e. the
303 * closest valid value 'set' is rounded to.
304 * - Or some other application requested a higher timer resolution, cur,
305 * and any attempt to lower the resolution has no effect until that
306 * request is rescinded (hopefully after this test is done).
308 CHECK_CURRENT_TIMER(cur);
310 /* The requested resolution may (win7) or may not be rounded */
311 cur2 = 7654321;
312 set = max < cur ? cur - 1 : max;
313 status = NtSetTimerResolution(set, TRUE, &cur2);
314 ok(status == STATUS_SUCCESS, "NtSetTimerResolution() failed %lx\n", status);
315 ok(cur2 <= set || broken(cur2 <= set + TIMER_LEEWAY), "expected new timer resolution %lu <= %lu\n", cur2, set);
316 trace("timer resolution: %lu(max) <= %lu(cur) <= %lu(prev) <= %lu(min)\n", max, cur2, cur, min);
318 cur2 = 7654321;
319 status = NtSetTimerResolution(cur + 1, TRUE, &cur2);
320 CHECK_CURRENT_TIMER(cur); /* see min + 1 test */
322 /* Cleanup by rescinding the last request */
323 cur2 = 7654321;
324 status = NtSetTimerResolution(0, FALSE, &cur2);
325 ok(status == STATUS_SUCCESS, "NtSetTimerResolution() failed %lx\n", status);
326 ok(cur2 == cur, "expected requested timer resolution %lu, got %lu\n", set, cur2);
329 static void test_RtlQueryTimeZoneInformation(void)
331 RTL_DYNAMIC_TIME_ZONE_INFORMATION tzinfo, tzinfo2;
332 NTSTATUS status;
333 ULONG len;
335 /* test RtlQueryTimeZoneInformation returns an indirect string,
336 e.g. @tzres.dll,-32 (Vista or later) */
337 if (!pRtlQueryTimeZoneInformation || !pRtlQueryDynamicTimeZoneInformation)
339 win_skip("Time zone name tests require Vista or later\n");
340 return;
343 memset(&tzinfo, 0xcc, sizeof(tzinfo));
344 status = pRtlQueryDynamicTimeZoneInformation(&tzinfo);
345 ok(status == STATUS_SUCCESS,
346 "RtlQueryDynamicTimeZoneInformation failed, got %08lx\n", status);
347 ok(tzinfo.StandardName[0] == '@' ||
348 broken(tzinfo.StandardName[0]), /* some win10 2004 */
349 "standard time zone name isn't an indirect string, got %s\n",
350 wine_dbgstr_w(tzinfo.StandardName));
351 ok(tzinfo.DaylightName[0] == '@' ||
352 broken(tzinfo.DaylightName[0]), /* some win10 2004 */
353 "daylight time zone name isn't an indirect string, got %s\n",
354 wine_dbgstr_w(tzinfo.DaylightName));
356 memset(&tzinfo2, 0xcc, sizeof(tzinfo2));
357 status = pNtQuerySystemInformation( SystemDynamicTimeZoneInformation, &tzinfo2, sizeof(tzinfo2), &len );
358 ok( !status, "NtQuerySystemInformation failed %lx\n", status );
359 ok( len == sizeof(tzinfo2), "wrong len %lu\n", len );
360 ok( !memcmp( &tzinfo, &tzinfo2, sizeof(tzinfo2) ), "tz data is different\n" );
362 memset(&tzinfo, 0xcc, sizeof(tzinfo));
363 status = pRtlQueryTimeZoneInformation((RTL_TIME_ZONE_INFORMATION *)&tzinfo);
364 ok(status == STATUS_SUCCESS,
365 "RtlQueryTimeZoneInformation failed, got %08lx\n", status);
366 ok(tzinfo.StandardName[0] == '@' ||
367 broken(tzinfo.StandardName[0]), /* some win10 2004 */
368 "standard time zone name isn't an indirect string, got %s\n",
369 wine_dbgstr_w(tzinfo.StandardName));
370 ok(tzinfo.DaylightName[0] == '@' ||
371 broken(tzinfo.DaylightName[0]), /* some win10 2004 */
372 "daylight time zone name isn't an indirect string, got %s\n",
373 wine_dbgstr_w(tzinfo.DaylightName));
375 memset(&tzinfo, 0xcc, sizeof(tzinfo));
376 status = pRtlQueryTimeZoneInformation((RTL_TIME_ZONE_INFORMATION *)&tzinfo);
377 ok(status == STATUS_SUCCESS,
378 "RtlQueryTimeZoneInformation failed, got %08lx\n", status);
379 ok(tzinfo.StandardName[0] == '@' ||
380 broken(tzinfo.StandardName[0]), /* some win10 2004 */
381 "standard time zone name isn't an indirect string, got %s\n",
382 wine_dbgstr_w(tzinfo.StandardName));
383 ok(tzinfo.DaylightName[0] == '@' ||
384 broken(tzinfo.DaylightName[0]), /* some win10 2004 */
385 "daylight time zone name isn't an indirect string, got %s\n",
386 wine_dbgstr_w(tzinfo.DaylightName));
388 memset(&tzinfo2, 0xcc, sizeof(tzinfo2));
389 status = pNtQuerySystemInformation( SystemCurrentTimeZoneInformation, &tzinfo2,
390 sizeof(RTL_TIME_ZONE_INFORMATION), &len );
391 ok( !status, "NtQuerySystemInformation failed %lx\n", status );
392 ok( len == sizeof(RTL_TIME_ZONE_INFORMATION), "wrong len %lu\n", len );
393 ok( !memcmp( &tzinfo, &tzinfo2, sizeof(RTL_TIME_ZONE_INFORMATION) ), "tz data is different\n" );
396 static ULONGLONG read_ksystem_time(volatile KSYSTEM_TIME *time)
398 ULONGLONG high, low;
401 high = time->High1Time;
402 low = time->LowPart;
404 while (high != time->High2Time);
405 return high << 32 | low;
408 static void test_user_shared_data_time(void)
410 KSHARED_USER_DATA *user_shared_data = (void *)0x7ffe0000;
411 SYSTEM_TIMEOFDAY_INFORMATION timeofday;
412 ULONGLONG t1, t2, t3;
413 NTSTATUS status;
414 int i = 0;
416 i = 0;
419 t1 = GetTickCount();
420 if (user_shared_data->NtMajorVersion <= 5 && user_shared_data->NtMinorVersion <= 1)
421 t2 = (DWORD)((*(volatile ULONG*)&user_shared_data->TickCountLowDeprecated * (ULONG64)user_shared_data->TickCountMultiplier) >> 24);
422 else
423 t2 = (DWORD)((read_ksystem_time(&user_shared_data->TickCount) * user_shared_data->TickCountMultiplier) >> 24);
424 t3 = GetTickCount();
425 } while(t3 < t1 && i++ < 1); /* allow for wrap, but only once */
427 ok(t1 <= t2, "USD TickCount / GetTickCount are out of order: %s %s\n",
428 wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2));
429 ok(t2 <= t3, "USD TickCount / GetTickCount are out of order: %s %s\n",
430 wine_dbgstr_longlong(t2), wine_dbgstr_longlong(t3));
432 i = 0;
435 LARGE_INTEGER system_time;
436 NtQuerySystemTime(&system_time);
437 t1 = system_time.QuadPart;
438 t2 = read_ksystem_time(&user_shared_data->SystemTime);
439 NtQuerySystemTime(&system_time);
440 t3 = system_time.QuadPart;
441 } while(t3 < t1 && i++ < 1); /* allow for wrap, but only once */
443 /* FIXME: not always in order, but should be close */
444 todo_wine_if(t1 > t2 && t1 - t2 < 50 * TICKSPERMSEC)
445 ok(t1 <= t2, "USD SystemTime / NtQuerySystemTime are out of order %s %s\n",
446 wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2));
447 ok(t2 <= t3, "USD SystemTime / NtQuerySystemTime are out of order %s %s\n",
448 wine_dbgstr_longlong(t2), wine_dbgstr_longlong(t3));
450 if (!pRtlQueryUnbiasedInterruptTime)
451 win_skip("skipping RtlQueryUnbiasedInterruptTime tests\n");
452 else
454 i = 0;
457 pRtlQueryUnbiasedInterruptTime(&t1);
458 t2 = read_ksystem_time(&user_shared_data->InterruptTime) - user_shared_data->InterruptTimeBias;
459 pRtlQueryUnbiasedInterruptTime(&t3);
460 } while(t3 < t1 && i++ < 1); /* allow for wrap, but only once */
462 ok(t1 <= t2, "USD InterruptTime / RtlQueryUnbiasedInterruptTime are out of order %s %s\n",
463 wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2));
464 ok(t2 <= t3, "USD InterruptTime / RtlQueryUnbiasedInterruptTime are out of order %s %s\n",
465 wine_dbgstr_longlong(t2), wine_dbgstr_longlong(t3));
468 t1 = read_ksystem_time(&user_shared_data->TimeZoneBias);
469 status = NtQuerySystemInformation(SystemTimeOfDayInformation, &timeofday, sizeof(timeofday), NULL);
470 ok(!status, "failed to query time of day, status %#lx\n", status);
471 ok(timeofday.TimeZoneBias.QuadPart == t1, "got USD bias %I64u, ntdll bias %I64u\n",
472 t1, timeofday.TimeZoneBias.QuadPart);
475 START_TEST(time)
477 HMODULE mod = GetModuleHandleA("ntdll.dll");
478 pRtlTimeToTimeFields = (void *)GetProcAddress(mod,"RtlTimeToTimeFields");
479 pRtlTimeFieldsToTime = (void *)GetProcAddress(mod,"RtlTimeFieldsToTime");
480 pNtQueryPerformanceCounter = (void *)GetProcAddress(mod, "NtQueryPerformanceCounter");
481 pNtQuerySystemInformation = (void *)GetProcAddress(mod, "NtQuerySystemInformation");
482 pRtlQueryTimeZoneInformation =
483 (void *)GetProcAddress(mod, "RtlQueryTimeZoneInformation");
484 pRtlQueryDynamicTimeZoneInformation =
485 (void *)GetProcAddress(mod, "RtlQueryDynamicTimeZoneInformation");
486 pRtlQueryUnbiasedInterruptTime = (void *)GetProcAddress(mod, "RtlQueryUnbiasedInterruptTime");
487 pRtlQueryPerformanceCounter = (void *)GetProcAddress(mod, "RtlQueryPerformanceCounter");
488 pRtlQueryPerformanceFrequency = (void *)GetProcAddress(mod, "RtlQueryPerformanceFrequency");
490 if (pRtlTimeToTimeFields && pRtlTimeFieldsToTime)
491 test_pRtlTimeToTimeFields();
492 else
493 win_skip("Required time conversion functions are not available\n");
494 test_NtQueryPerformanceCounter();
495 test_RtlQueryTimeZoneInformation();
496 test_user_shared_data_time();
497 #if defined(__i386__) || defined(__x86_64__)
498 test_RtlQueryPerformanceCounter();
499 #endif
500 test_TimerResolution();