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"
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
;
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) {
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
;
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
133 UINT64 QpcMultiplier
;
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
;
155 if (!pRtlQueryPerformanceCounter
|| !pRtlQueryPerformanceFrequency
)
157 win_skip( "RtlQueryPerformanceCounter/Frequency not available, skipping tests\n" );
161 if (!(usd
->QpcBypassEnabled
& SHARED_GLOBAL_FLAGS_QPC_BYPASS_ENABLED
))
163 todo_wine
win_skip("QpcBypassEnabled is not set, skipping tests\n");
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
);
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
);
181 ret
= pRtlQueryPerformanceCounter( &counter
);
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
);
193 ok( usd
->QpcShift
== 10, "unexpected QpcShift %d, expected 10\n", usd
->QpcShift
);
196 ret
= pRtlQueryPerformanceCounter( &counter
);
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
);
217 #define TIMER_LEEWAY 10
218 #define CHECK_CURRENT_TIMER(expected) \
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); \
223 min2 = min + 20000; \
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); \
233 static void test_TimerResolution(void)
235 ULONG min
, max
, cur
, min2
, max2
, cur2
, set
;
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");
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
);
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 */
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
);
283 status
= NtSetTimerResolution(max
- 1, TRUE
, &cur2
);
284 CHECK_CURRENT_TIMER(max
);
286 /* Rescinds our timer resolution request */
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
);
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
);
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 */
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
);
319 status
= NtSetTimerResolution(cur
+ 1, TRUE
, &cur2
);
320 CHECK_CURRENT_TIMER(cur
); /* see min + 1 test */
322 /* Cleanup by rescinding the last request */
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
;
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");
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
)
401 high
= time
->High1Time
;
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
;
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);
423 t2
= (DWORD
)((read_ksystem_time(&user_shared_data
->TickCount
) * user_shared_data
->TickCountMultiplier
) >> 24);
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
));
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");
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
);
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();
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();
500 test_TimerResolution();