ntdll: Improve the Nt{Query,Set}TimerResolution() stubs.
[wine.git] / dlls / ntdll / tests / time.c
blobf75b159f441a19a7e3e3d50b644702b453dc7fc8
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 #define NONAMELESSUNION
22 #define NONAMELESSSTRUCT
23 #include "ntdll_test.h"
24 #include "ddk/wdm.h"
25 #include "intrin.h"
27 #define TICKSPERSEC 10000000
28 #define TICKSPERMSEC 10000
29 #define SECSPERDAY 86400
31 static VOID (WINAPI *pRtlTimeToTimeFields)( const LARGE_INTEGER *liTime, PTIME_FIELDS TimeFields) ;
32 static VOID (WINAPI *pRtlTimeFieldsToTime)( PTIME_FIELDS TimeFields, PLARGE_INTEGER Time) ;
33 static NTSTATUS (WINAPI *pNtQueryPerformanceCounter)( LARGE_INTEGER *counter, LARGE_INTEGER *frequency );
34 static NTSTATUS (WINAPI *pNtQuerySystemInformation)( SYSTEM_INFORMATION_CLASS class,
35 void *info, ULONG size, ULONG *ret_size );
36 static NTSTATUS (WINAPI *pRtlQueryTimeZoneInformation)( RTL_TIME_ZONE_INFORMATION *);
37 static NTSTATUS (WINAPI *pRtlQueryDynamicTimeZoneInformation)( RTL_DYNAMIC_TIME_ZONE_INFORMATION *);
38 static BOOL (WINAPI *pRtlQueryUnbiasedInterruptTime)( ULONGLONG *time );
40 static BOOL (WINAPI *pRtlQueryPerformanceCounter)(LARGE_INTEGER*);
41 static BOOL (WINAPI *pRtlQueryPerformanceFrequency)(LARGE_INTEGER*);
43 static const int MonthLengths[2][12] =
45 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
46 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
49 static inline BOOL IsLeapYear(int Year)
51 return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0);
54 /* start time of the tests */
55 static TIME_FIELDS tftest = {1889,12,31,23,59,59,0,0};
57 static void test_pRtlTimeToTimeFields(void)
59 LARGE_INTEGER litime , liresult;
60 TIME_FIELDS tfresult;
61 int i=0;
62 litime.QuadPart = ((ULONGLONG)0x0144017a << 32) | 0xf0b0a980;
63 while( tftest.Year < 2110 ) {
64 /* test at the last second of the month */
65 pRtlTimeToTimeFields( &litime, &tfresult);
66 ok( tfresult.Year == tftest.Year && tfresult.Month == tftest.Month &&
67 tfresult.Day == tftest.Day && tfresult.Hour == tftest.Hour &&
68 tfresult.Minute == tftest.Minute && tfresult.Second == tftest.Second,
69 "#%d expected: %d-%d-%d %d:%d:%d got: %d-%d-%d %d:%d:%d\n", ++i,
70 tftest.Year, tftest.Month, tftest.Day,
71 tftest.Hour, tftest.Minute,tftest.Second,
72 tfresult.Year, tfresult.Month, tfresult.Day,
73 tfresult.Hour, tfresult.Minute, tfresult.Second);
74 /* test the inverse */
75 pRtlTimeFieldsToTime( &tfresult, &liresult);
76 ok( liresult.QuadPart == litime.QuadPart," TimeFieldsToTime failed on %d-%d-%d %d:%d:%d. Error is %d ticks\n",
77 tfresult.Year, tfresult.Month, tfresult.Day,
78 tfresult.Hour, tfresult.Minute, tfresult.Second,
79 (int) (liresult.QuadPart - litime.QuadPart) );
80 /* one second later is beginning of next month */
81 litime.QuadPart += TICKSPERSEC ;
82 pRtlTimeToTimeFields( &litime, &tfresult);
83 ok( tfresult.Year == tftest.Year + (tftest.Month ==12) &&
84 tfresult.Month == tftest.Month % 12 + 1 &&
85 tfresult.Day == 1 && tfresult.Hour == 0 &&
86 tfresult.Minute == 0 && tfresult.Second == 0,
87 "#%d expected: %d-%d-%d %d:%d:%d got: %d-%d-%d %d:%d:%d\n", ++i,
88 tftest.Year + (tftest.Month ==12),
89 tftest.Month % 12 + 1, 1, 0, 0, 0,
90 tfresult.Year, tfresult.Month, tfresult.Day,
91 tfresult.Hour, tfresult.Minute, tfresult.Second);
92 /* test the inverse */
93 pRtlTimeFieldsToTime( &tfresult, &liresult);
94 ok( liresult.QuadPart == litime.QuadPart," TimeFieldsToTime failed on %d-%d-%d %d:%d:%d. Error is %d ticks\n",
95 tfresult.Year, tfresult.Month, tfresult.Day,
96 tfresult.Hour, tfresult.Minute, tfresult.Second,
97 (int) (liresult.QuadPart - litime.QuadPart) );
98 /* advance to the end of the month */
99 litime.QuadPart -= TICKSPERSEC ;
100 if( tftest.Month == 12) {
101 tftest.Month = 1;
102 tftest.Year += 1;
103 } else
104 tftest.Month += 1;
105 tftest.Day = MonthLengths[IsLeapYear(tftest.Year)][tftest.Month - 1];
106 litime.QuadPart += (LONGLONG) tftest.Day * TICKSPERSEC * SECSPERDAY;
110 static void test_NtQueryPerformanceCounter(void)
112 LARGE_INTEGER counter, frequency;
113 NTSTATUS status;
115 status = pNtQueryPerformanceCounter(NULL, NULL);
116 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
117 status = pNtQueryPerformanceCounter(NULL, &frequency);
118 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
119 status = pNtQueryPerformanceCounter(&counter, (void *)0xdeadbee0);
120 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
121 status = pNtQueryPerformanceCounter((void *)0xdeadbee0, &frequency);
122 ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
124 status = pNtQueryPerformanceCounter(&counter, NULL);
125 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
126 status = pNtQueryPerformanceCounter(&counter, &frequency);
127 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
130 #if defined(__i386__) || defined(__x86_64__)
132 struct hypervisor_shared_data
134 UINT64 unknown;
135 UINT64 QpcMultiplier;
136 UINT64 QpcBias;
139 /* 128-bit multiply a by b and return the high 64 bits, same as __umulh */
140 static UINT64 multiply_tsc(UINT64 a, UINT64 b)
142 UINT64 ah = a >> 32, al = (UINT32)a, bh = b >> 32, bl = (UINT32)b, m;
143 m = (ah * bl) + (bh * al) + ((al * bl) >> 32);
144 return (ah * bh) + (m >> 32);
147 static void test_RtlQueryPerformanceCounter(void)
149 struct hypervisor_shared_data *hsd;
150 KSHARED_USER_DATA *usd = (void *)0x7ffe0000;
151 LARGE_INTEGER frequency, counter;
152 NTSTATUS status;
153 UINT64 tsc0, tsc1;
154 ULONG len;
155 BOOL ret;
157 if (!pRtlQueryPerformanceCounter || !pRtlQueryPerformanceFrequency)
159 win_skip( "RtlQueryPerformanceCounter/Frequency not available, skipping tests\n" );
160 return;
163 if (!(usd->u3.s.QpcBypassEnabled & SHARED_GLOBAL_FLAGS_QPC_BYPASS_ENABLED))
165 todo_wine win_skip("QpcBypassEnabled is not set, skipping tests\n");
166 return;
169 if ((usd->u3.s.QpcBypassEnabled & SHARED_GLOBAL_FLAGS_QPC_BYPASS_USE_HV_PAGE))
171 ok( usd->u3.s.QpcBypassEnabled == (SHARED_GLOBAL_FLAGS_QPC_BYPASS_ENABLED|SHARED_GLOBAL_FLAGS_QPC_BYPASS_USE_HV_PAGE|SHARED_GLOBAL_FLAGS_QPC_BYPASS_USE_RDTSCP),
172 "unexpected QpcBypassEnabled %x, expected 0x83\n", usd->u3.s.QpcBypassEnabled );
173 ok( usd->QpcFrequency == 10000000, "unexpected QpcFrequency %I64d, expected 10000000\n", usd->QpcFrequency );
174 ok( !usd->u3.s.QpcShift, "unexpected QpcShift %d, expected 0\n", usd->u3.s.QpcShift );
176 hsd = NULL;
177 status = pNtQuerySystemInformation( SystemHypervisorSharedPageInformation, &hsd, sizeof(void *), &len );
178 ok( !status, "NtQuerySystemInformation returned %x\n", status );
179 ok( len == sizeof(void *), "unexpected SystemHypervisorSharedPageInformation length %u\n", len );
180 ok( !!hsd, "unexpected SystemHypervisorSharedPageInformation address %p\n", hsd );
182 tsc0 = __rdtsc();
183 ret = pRtlQueryPerformanceCounter( &counter );
184 tsc1 = __rdtsc();
185 ok( ret, "RtlQueryPerformanceCounter failed\n" );
187 tsc0 = multiply_tsc(tsc0, hsd->QpcMultiplier) + hsd->QpcBias + usd->QpcBias;
188 tsc1 = multiply_tsc(tsc1, hsd->QpcMultiplier) + hsd->QpcBias + usd->QpcBias;
190 ok( tsc0 <= counter.QuadPart, "rdtscp %I64d and RtlQueryPerformanceCounter %I64d are out of order\n", tsc0, counter.QuadPart );
191 ok( counter.QuadPart <= tsc1, "RtlQueryPerformanceCounter %I64d and rdtscp %I64d are out of order\n", counter.QuadPart, tsc1 );
193 else
195 ok( usd->u3.s.QpcShift == 10, "unexpected QpcShift %d, expected 10\n", usd->u3.s.QpcShift );
197 tsc0 = __rdtsc();
198 ret = pRtlQueryPerformanceCounter( &counter );
199 tsc1 = __rdtsc();
200 ok( ret, "RtlQueryPerformanceCounter failed\n" );
202 tsc0 += usd->QpcBias;
203 tsc0 >>= usd->u3.s.QpcShift;
204 tsc1 += usd->QpcBias;
205 tsc1 >>= usd->u3.s.QpcShift;
207 ok( tsc0 <= counter.QuadPart, "rdtscp %I64d and RtlQueryPerformanceCounter %I64d are out of order\n", tsc0, counter.QuadPart );
208 ok( counter.QuadPart <= tsc1, "RtlQueryPerformanceCounter %I64d and rdtscp %I64d are out of order\n", counter.QuadPart, tsc1 );
211 ret = pRtlQueryPerformanceFrequency( &frequency );
212 ok( ret, "RtlQueryPerformanceFrequency failed\n" );
213 ok( frequency.QuadPart == usd->QpcFrequency,
214 "RtlQueryPerformanceFrequency returned %I64d, expected USD QpcFrequency %I64d\n",
215 frequency.QuadPart, usd->QpcFrequency );
217 #endif
219 #define CHECK_CURRENT_TIMER(expected) \
220 do { \
221 ok(status == STATUS_SUCCESS, "NtSetTimerResolution failed %x\n", status); \
222 ok(cur2 == (expected), "expected new timer resolution %u, got %u\n", (expected), cur2); \
223 min2 = min + 10; \
224 cur2 = min2 + 1; \
225 max2 = cur2 + 1; \
226 status = NtQueryTimerResolution(&min2, &max2, &cur2); \
227 ok(status == STATUS_SUCCESS, "NtQueryTimerResolution() failed %x\n", status); \
228 ok(min2 == min, "NtQueryTimerResolution() expected min=%u, got %u\n", min, min2); \
229 ok(max2 == max, "NtQueryTimerResolution() expected max=%u, got %u\n", max, max2); \
230 ok(cur2 == expected, "NtQueryTimerResolution() expected timer resolution %u, got %u\n", (expected), 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 (%x)\n", status);
252 ok(min == 156250 /* 1/64s HPET */ || min == 156001 /* RTC */,
253 "unexpected minimum timer resolution %u\n", min);
254 ok(0 < max, "invalid maximum timer resolution, should be 0 < %u\n", max);
255 ok(max <= cur && cur <= min, "invalid timer resolutions, should be %u <= %u <= %u\n", max, cur, min);
257 status = NtSetTimerResolution(0, FALSE, NULL);
258 ok(status == STATUS_ACCESS_VIOLATION, "NtSetTimerResolution(,,NULL) success\n");
260 /* Nothing happens if that pointer is not good */
261 status = NtSetTimerResolution(cur - 1, TRUE, NULL);
262 ok(status == STATUS_ACCESS_VIOLATION, "NtSetTimerResolution() failed %x\n", status);
264 min2 = min + 1;
265 cur2 = min2 + 1;
266 max2 = cur2 + 1;
267 status = NtQueryTimerResolution(&min2, &max2, &cur2);
268 ok(status == STATUS_SUCCESS, "NtQueryTimerResolution() failed (%x)\n", status);
269 ok(min2 == min, "NtQueryTimerResolution() expected min=%u, got %u\n", min, min2);
270 ok(max2 == max, "NtQueryTimerResolution() expected max=%u, got %u\n", max, max2);
271 ok(cur2 == cur, "NtQueryTimerResolution() expected timer resolution %u, got %u\n", cur, cur2);
273 /* 'fails' until the first valid timer resolution request */
274 cur2 = 7654321;
275 status = NtSetTimerResolution(0, FALSE, &cur2);
276 ok(status == STATUS_TIMER_RESOLUTION_NOT_SET, "NtSetTimerResolution() failed %x\n", status);
277 /* and returns the current timer resolution */
278 ok(cur2 == cur, "expected requested timer resolution %u, got %u\n", cur, cur2);
281 cur2 = 7654321;
282 status = NtSetTimerResolution(max - 1, TRUE, &cur2);
283 CHECK_CURRENT_TIMER(max);
285 /* Rescinds our timer resolution request */
286 cur2 = 7654321;
287 status = NtSetTimerResolution(0, FALSE, &cur2);
288 ok(status == STATUS_SUCCESS, "NtSetTimerResolution() failed %x\n", status);
289 /* -> the timer resolution was reset to its initial value */
290 ok(cur2 == cur, "expected requested timer resolution %u, got %u\n", min, cur2);
292 cur2 = 7654321;
293 status = NtSetTimerResolution(0, FALSE, &cur2);
294 ok(status == STATUS_TIMER_RESOLUTION_NOT_SET, "NtSetTimerResolution() failed %x\n", status);
295 ok(cur2 == cur, "expected requested timer resolution %u, got %u\n", cur, cur2);
297 cur2 = 7654321;
298 status = NtSetTimerResolution(min + 1, TRUE, &cur2);
299 ok(status == STATUS_SUCCESS, "NtSetTimerResolution() failed %x\n", status);
300 /* This works because:
301 * - Either cur is the minimum (15.6 ms) resolution already, i.e. the
302 * closest valid value 'set' is rounded to.
303 * - Or some other application requested a higher timer resolution, cur,
304 * and any attempt to lower the resolution has no effect until that
305 * request is rescinded (hopefully after this test is done).
307 CHECK_CURRENT_TIMER(cur);
309 /* The requested resolution may (win7) or may not be rounded */
310 cur2 = 7654321;
311 set = max < cur ? cur - 1 : max;
312 status = NtSetTimerResolution(set, TRUE, &cur2);
313 ok(status == STATUS_SUCCESS, "NtSetTimerResolution() failed %x\n", status);
314 ok(cur2 <= set, "expected new timer resolution %u <= %u\n", cur2, set);
315 trace("timer resolution: %u(max) <= %u(cur) <= %u(prev) <= %u(min)\n", max, cur2, cur, min);
317 cur2 = 7654321;
318 status = NtSetTimerResolution(cur + 1, TRUE, &cur2);
319 CHECK_CURRENT_TIMER(cur); /* see min + 1 test */
321 /* Cleanup by rescinding the last request */
322 cur2 = 7654321;
323 status = NtSetTimerResolution(0, FALSE, &cur2);
324 ok(status == STATUS_SUCCESS, "NtSetTimerResolution() failed %x\n", status);
325 ok(cur2 == cur, "expected requested timer resolution %u, got %u\n", set, cur2);
328 static void test_RtlQueryTimeZoneInformation(void)
330 RTL_DYNAMIC_TIME_ZONE_INFORMATION tzinfo, tzinfo2;
331 NTSTATUS status;
332 ULONG len;
334 /* test RtlQueryTimeZoneInformation returns an indirect string,
335 e.g. @tzres.dll,-32 (Vista or later) */
336 if (!pRtlQueryTimeZoneInformation || !pRtlQueryDynamicTimeZoneInformation)
338 win_skip("Time zone name tests require Vista or later\n");
339 return;
342 memset(&tzinfo, 0xcc, sizeof(tzinfo));
343 status = pRtlQueryDynamicTimeZoneInformation(&tzinfo);
344 ok(status == STATUS_SUCCESS,
345 "RtlQueryDynamicTimeZoneInformation failed, got %08x\n", status);
346 ok(tzinfo.StandardName[0] == '@' ||
347 broken(tzinfo.StandardName[0]), /* some win10 2004 */
348 "standard time zone name isn't an indirect string, got %s\n",
349 wine_dbgstr_w(tzinfo.StandardName));
350 ok(tzinfo.DaylightName[0] == '@' ||
351 broken(tzinfo.DaylightName[0]), /* some win10 2004 */
352 "daylight time zone name isn't an indirect string, got %s\n",
353 wine_dbgstr_w(tzinfo.DaylightName));
355 memset(&tzinfo2, 0xcc, sizeof(tzinfo2));
356 status = pNtQuerySystemInformation( SystemDynamicTimeZoneInformation, &tzinfo2, sizeof(tzinfo2), &len );
357 ok( !status, "NtQuerySystemInformation failed %x\n", status );
358 ok( len == sizeof(tzinfo2), "wrong len %u\n", len );
359 ok( !memcmp( &tzinfo, &tzinfo2, sizeof(tzinfo2) ), "tz data is different\n" );
361 memset(&tzinfo, 0xcc, sizeof(tzinfo));
362 status = pRtlQueryTimeZoneInformation((RTL_TIME_ZONE_INFORMATION *)&tzinfo);
363 ok(status == STATUS_SUCCESS,
364 "RtlQueryTimeZoneInformation failed, got %08x\n", status);
365 ok(tzinfo.StandardName[0] == '@' ||
366 broken(tzinfo.StandardName[0]), /* some win10 2004 */
367 "standard time zone name isn't an indirect string, got %s\n",
368 wine_dbgstr_w(tzinfo.StandardName));
369 ok(tzinfo.DaylightName[0] == '@' ||
370 broken(tzinfo.DaylightName[0]), /* some win10 2004 */
371 "daylight time zone name isn't an indirect string, got %s\n",
372 wine_dbgstr_w(tzinfo.DaylightName));
374 memset(&tzinfo, 0xcc, sizeof(tzinfo));
375 status = pRtlQueryTimeZoneInformation((RTL_TIME_ZONE_INFORMATION *)&tzinfo);
376 ok(status == STATUS_SUCCESS,
377 "RtlQueryTimeZoneInformation failed, got %08x\n", status);
378 ok(tzinfo.StandardName[0] == '@' ||
379 broken(tzinfo.StandardName[0]), /* some win10 2004 */
380 "standard time zone name isn't an indirect string, got %s\n",
381 wine_dbgstr_w(tzinfo.StandardName));
382 ok(tzinfo.DaylightName[0] == '@' ||
383 broken(tzinfo.DaylightName[0]), /* some win10 2004 */
384 "daylight time zone name isn't an indirect string, got %s\n",
385 wine_dbgstr_w(tzinfo.DaylightName));
387 memset(&tzinfo2, 0xcc, sizeof(tzinfo2));
388 status = pNtQuerySystemInformation( SystemCurrentTimeZoneInformation, &tzinfo2,
389 sizeof(RTL_TIME_ZONE_INFORMATION), &len );
390 ok( !status, "NtQuerySystemInformation failed %x\n", status );
391 ok( len == sizeof(RTL_TIME_ZONE_INFORMATION), "wrong len %u\n", len );
392 ok( !memcmp( &tzinfo, &tzinfo2, sizeof(RTL_TIME_ZONE_INFORMATION) ), "tz data is different\n" );
395 static ULONGLONG read_ksystem_time(volatile KSYSTEM_TIME *time)
397 ULONGLONG high, low;
400 high = time->High1Time;
401 low = time->LowPart;
403 while (high != time->High2Time);
404 return high << 32 | low;
407 static void test_user_shared_data_time(void)
409 KSHARED_USER_DATA *user_shared_data = (void *)0x7ffe0000;
410 ULONGLONG t1, t2, t3;
411 int i = 0;
413 i = 0;
416 t1 = GetTickCount();
417 if (user_shared_data->NtMajorVersion <= 5 && user_shared_data->NtMinorVersion <= 1)
418 t2 = (DWORD)((*(volatile ULONG*)&user_shared_data->TickCountLowDeprecated * (ULONG64)user_shared_data->TickCountMultiplier) >> 24);
419 else
420 t2 = (DWORD)((read_ksystem_time(&user_shared_data->u.TickCount) * user_shared_data->TickCountMultiplier) >> 24);
421 t3 = GetTickCount();
422 } while(t3 < t1 && i++ < 1); /* allow for wrap, but only once */
424 ok(t1 <= t2, "USD TickCount / GetTickCount are out of order: %s %s\n",
425 wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2));
426 ok(t2 <= t3, "USD TickCount / GetTickCount are out of order: %s %s\n",
427 wine_dbgstr_longlong(t2), wine_dbgstr_longlong(t3));
429 i = 0;
432 LARGE_INTEGER system_time;
433 NtQuerySystemTime(&system_time);
434 t1 = system_time.QuadPart;
435 t2 = read_ksystem_time(&user_shared_data->SystemTime);
436 NtQuerySystemTime(&system_time);
437 t3 = system_time.QuadPart;
438 } while(t3 < t1 && i++ < 1); /* allow for wrap, but only once */
440 /* FIXME: not always in order, but should be close */
441 todo_wine_if(t1 > t2 && t1 - t2 < 50 * TICKSPERMSEC)
442 ok(t1 <= t2, "USD SystemTime / NtQuerySystemTime are out of order %s %s\n",
443 wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2));
444 ok(t2 <= t3, "USD SystemTime / NtQuerySystemTime are out of order %s %s\n",
445 wine_dbgstr_longlong(t2), wine_dbgstr_longlong(t3));
447 if (!pRtlQueryUnbiasedInterruptTime)
448 win_skip("skipping RtlQueryUnbiasedInterruptTime tests\n");
449 else
451 i = 0;
454 pRtlQueryUnbiasedInterruptTime(&t1);
455 t2 = read_ksystem_time(&user_shared_data->InterruptTime) - user_shared_data->InterruptTimeBias;
456 pRtlQueryUnbiasedInterruptTime(&t3);
457 } while(t3 < t1 && i++ < 1); /* allow for wrap, but only once */
459 ok(t1 <= t2, "USD InterruptTime / RtlQueryUnbiasedInterruptTime are out of order %s %s\n",
460 wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2));
461 ok(t2 <= t3, "USD InterruptTime / RtlQueryUnbiasedInterruptTime are out of order %s %s\n",
462 wine_dbgstr_longlong(t2), wine_dbgstr_longlong(t3));
466 START_TEST(time)
468 HMODULE mod = GetModuleHandleA("ntdll.dll");
469 pRtlTimeToTimeFields = (void *)GetProcAddress(mod,"RtlTimeToTimeFields");
470 pRtlTimeFieldsToTime = (void *)GetProcAddress(mod,"RtlTimeFieldsToTime");
471 pNtQueryPerformanceCounter = (void *)GetProcAddress(mod, "NtQueryPerformanceCounter");
472 pNtQuerySystemInformation = (void *)GetProcAddress(mod, "NtQuerySystemInformation");
473 pRtlQueryTimeZoneInformation =
474 (void *)GetProcAddress(mod, "RtlQueryTimeZoneInformation");
475 pRtlQueryDynamicTimeZoneInformation =
476 (void *)GetProcAddress(mod, "RtlQueryDynamicTimeZoneInformation");
477 pRtlQueryUnbiasedInterruptTime = (void *)GetProcAddress(mod, "RtlQueryUnbiasedInterruptTime");
478 pRtlQueryPerformanceCounter = (void *)GetProcAddress(mod, "RtlQueryPerformanceCounter");
479 pRtlQueryPerformanceFrequency = (void *)GetProcAddress(mod, "RtlQueryPerformanceFrequency");
481 if (pRtlTimeToTimeFields && pRtlTimeFieldsToTime)
482 test_pRtlTimeToTimeFields();
483 else
484 win_skip("Required time conversion functions are not available\n");
485 test_NtQueryPerformanceCounter();
486 test_RtlQueryTimeZoneInformation();
487 test_user_shared_data_time();
488 #if defined(__i386__) || defined(__x86_64__)
489 test_RtlQueryPerformanceCounter();
490 #endif
491 test_TimerResolution();