Reactos
1/*
2 * Unit test suite for time functions
3 *
4 * Copyright 2004 Uwe Bonnes
5 * Copyright 2007 Dmitry Timoshkov
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#include "wine/test.h"
23#include "winbase.h"
24#include "winnls.h"
25#include "winternl.h"
26
27static BOOL (WINAPI *pTzSpecificLocalTimeToSystemTime)(LPTIME_ZONE_INFORMATION, LPSYSTEMTIME, LPSYSTEMTIME);
28static BOOL (WINAPI *pSystemTimeToTzSpecificLocalTime)(LPTIME_ZONE_INFORMATION, LPSYSTEMTIME, LPSYSTEMTIME);
29static BOOL (WINAPI *pGetSystemTimes)(LPFILETIME, LPFILETIME, LPFILETIME);
30static int (WINAPI *pGetCalendarInfoA)(LCID,CALID,CALTYPE,LPSTR,int,LPDWORD);
31static int (WINAPI *pGetCalendarInfoW)(LCID,CALID,CALTYPE,LPWSTR,int,LPDWORD);
32static DWORD (WINAPI *pGetDynamicTimeZoneInformation)(DYNAMIC_TIME_ZONE_INFORMATION*);
33static void (WINAPI *pGetSystemTimePreciseAsFileTime)(LPFILETIME);
34static BOOL (WINAPI *pGetTimeZoneInformationForYear)(USHORT, PDYNAMIC_TIME_ZONE_INFORMATION, LPTIME_ZONE_INFORMATION);
35static ULONG (WINAPI *pNtGetTickCount)(void);
36
37#define SECSPERMIN 60
38#define SECSPERDAY 86400
39/* 1601 to 1970 is 369 years plus 89 leap days */
40#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
41#define TICKSPERSEC 10000000
42#define TICKSPERMSEC 10000
43#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
44
45
46#define NEWYEAR_1980_HI 0x01a8e79f
47#define NEWYEAR_1980_LO 0xe1d58000
48
49#define MAYDAY_2002_HI 0x01c1f107
50#define MAYDAY_2002_LO 0xb82b6000
51
52#define ATIME_HI 0x1c2349b
53#define ATIME_LOW 0x580716b0
54
55#define LOCAL_ATIME_HI 0x01c23471
56#define LOCAL_ATIME_LOW 0x6f310eb0
57
58#define DOS_DATE(y,m,d) ( (((y)-1980)<<9) | ((m)<<5) | (d) )
59#define DOS_TIME(h,m,s) ( ((h)<<11) | ((m)<<5) | ((s)>>1) )
60
61
62#define SETUP_1980(st) \
63 (st).wYear = 1980; \
64 (st).wMonth = 1; \
65 (st).wDay = 1; \
66 (st).wHour = 0; \
67 (st).wMinute = 0; \
68 (st).wSecond = 0; \
69 (st).wMilliseconds = 0;
70
71#define SETUP_2002(st) \
72 (st).wYear = 2002; \
73 (st).wMonth = 5; \
74 (st).wDay = 1; \
75 (st).wHour = 12; \
76 (st).wMinute = 0; \
77 (st).wSecond = 0; \
78 (st).wMilliseconds = 0;
79
80#define SETUP_ATIME(st) \
81 (st).wYear = 2002; \
82 (st).wMonth = 7; \
83 (st).wDay = 26; \
84 (st).wHour = 11; \
85 (st).wMinute = 55; \
86 (st).wSecond = 32; \
87 (st).wMilliseconds = 123;
88
89#define SETUP_ZEROTIME(st) \
90 (st).wYear = 1601; \
91 (st).wMonth = 1; \
92 (st).wDay = 1; \
93 (st).wHour = 0; \
94 (st).wMinute = 0; \
95 (st).wSecond = 0; \
96 (st).wMilliseconds = 0;
97
98#define SETUP_EARLY(st) \
99 (st).wYear = 1600; \
100 (st).wMonth = 12; \
101 (st).wDay = 31; \
102 (st).wHour = 23; \
103 (st).wMinute = 59; \
104 (st).wSecond = 59; \
105 (st).wMilliseconds = 999;
106
107
108static void test_conversions(void)
109{
110 FILETIME ft;
111 SYSTEMTIME st;
112
113 memset(&ft,0,sizeof ft);
114
115 SetLastError(0xdeadbeef);
116 SETUP_EARLY(st)
117 ok (!SystemTimeToFileTime(&st, &ft), "Conversion succeeded EARLY\n");
118 ok (GetLastError() == ERROR_INVALID_PARAMETER ||
119 GetLastError() == 0xdeadbeef, /* win9x */
120 "EARLY should be INVALID\n");
121
122 SETUP_ZEROTIME(st)
123 ok (SystemTimeToFileTime(&st, &ft), "Conversion failed ZERO_TIME\n");
124 ok( (!((ft.dwHighDateTime != 0) || (ft.dwLowDateTime != 0))),
125 "Wrong time for ATIME: %08lx %08lx (correct %08x %08x)\n",
126 ft.dwLowDateTime, ft.dwHighDateTime, 0, 0);
127
128
129 SETUP_ATIME(st)
130 ok (SystemTimeToFileTime(&st,&ft), "Conversion Failed ATIME\n");
131 ok( (!((ft.dwHighDateTime != ATIME_HI) || (ft.dwLowDateTime!=ATIME_LOW))),
132 "Wrong time for ATIME: %08lx %08lx (correct %08x %08x)\n",
133 ft.dwLowDateTime, ft.dwHighDateTime, ATIME_LOW, ATIME_HI);
134
135
136 SETUP_2002(st)
137 ok (SystemTimeToFileTime(&st, &ft), "Conversion failed 2002\n");
138
139 ok( (!((ft.dwHighDateTime != MAYDAY_2002_HI) ||
140 (ft.dwLowDateTime!=MAYDAY_2002_LO))),
141 "Wrong time for 2002 %08lx %08lx (correct %08x %08x)\n", ft.dwLowDateTime,
142 ft.dwHighDateTime, MAYDAY_2002_LO, MAYDAY_2002_HI);
143
144
145 SETUP_1980(st)
146 ok((SystemTimeToFileTime(&st, &ft)), "Conversion failed 1980\n");
147
148 ok( (!((ft.dwHighDateTime!=NEWYEAR_1980_HI) ||
149 (ft.dwLowDateTime!=NEWYEAR_1980_LO))) ,
150 "Wrong time for 1980 %08lx %08lx (correct %08x %08x)\n", ft.dwLowDateTime,
151 ft.dwHighDateTime, NEWYEAR_1980_LO,NEWYEAR_1980_HI );
152
153 ok(DosDateTimeToFileTime(DOS_DATE(1980,1,1),DOS_TIME(0,0,0),&ft),
154 "DosDateTimeToFileTime() failed\n");
155
156 ok( (!((ft.dwHighDateTime!=NEWYEAR_1980_HI) ||
157 (ft.dwLowDateTime!=NEWYEAR_1980_LO))),
158 "Wrong time DosDateTimeToFileTime %08lx %08lx (correct %08x %08x)\n",
159 ft.dwHighDateTime, ft.dwLowDateTime, NEWYEAR_1980_HI, NEWYEAR_1980_LO);
160
161}
162
163static void test_invalid_arg(void)
164{
165 FILETIME ft;
166 SYSTEMTIME st;
167
168
169 /* Invalid argument checks */
170
171 memset(&ft,0,sizeof ft);
172 ok( DosDateTimeToFileTime(DOS_DATE(1980,1,1),DOS_TIME(0,0,0),&ft), /* this is 1 Jan 1980 00:00:00 */
173 "DosDateTimeToFileTime() failed\n");
174
175 ok( (ft.dwHighDateTime==NEWYEAR_1980_HI) && (ft.dwLowDateTime==NEWYEAR_1980_LO),
176 "filetime for 1/1/80 00:00:00 was %08lx %08lx\n", ft.dwHighDateTime, ft.dwLowDateTime);
177
178 /* now check SystemTimeToFileTime */
179 memset(&ft,0,sizeof ft);
180
181
182 /* try with a bad month */
183 SETUP_1980(st)
184 st.wMonth = 0;
185
186 ok( !SystemTimeToFileTime(&st, &ft), "bad month\n");
187
188 /* with a bad hour */
189 SETUP_1980(st)
190 st.wHour = 24;
191
192 ok( !SystemTimeToFileTime(&st, &ft), "bad hour\n");
193
194 /* with a bad minute */
195 SETUP_1980(st)
196 st.wMinute = 60;
197
198 ok( !SystemTimeToFileTime(&st, &ft), "bad minute\n");
199}
200
201static LONGLONG system_time_to_minutes(const SYSTEMTIME *st)
202{
203 BOOL ret;
204 FILETIME ft;
205 LONGLONG minutes;
206
207 SetLastError(0xdeadbeef);
208 ret = SystemTimeToFileTime(st, &ft);
209 ok(ret, "SystemTimeToFileTime error %lu\n", GetLastError());
210
211 minutes = ((LONGLONG)ft.dwHighDateTime << 32) + ft.dwLowDateTime;
212 minutes /= (LONGLONG)600000000; /* convert to minutes */
213 return minutes;
214}
215
216static LONG get_tz_bias(const TIME_ZONE_INFORMATION *tzinfo, DWORD tz_id)
217{
218 switch (tz_id)
219 {
220 case TIME_ZONE_ID_DAYLIGHT:
221 if (memcmp(&tzinfo->StandardDate, &tzinfo->DaylightDate, sizeof(tzinfo->DaylightDate)) != 0)
222 return tzinfo->DaylightBias;
223 /* fall through */
224
225 case TIME_ZONE_ID_STANDARD:
226 return tzinfo->StandardBias;
227
228 default:
229 trace("unknown time zone id %ld\n", tz_id);
230 /* fall through */
231 case TIME_ZONE_ID_UNKNOWN:
232 return 0;
233 }
234}
235
236static void test_GetTimeZoneInformation(void)
237{
238 char std_name[32], dlt_name[32];
239 TIME_ZONE_INFORMATION tzinfo, tzinfo1;
240 BOOL res;
241 DWORD tz_id;
242 SYSTEMTIME st, current, utc, local;
243 FILETIME l_ft, s_ft;
244 LONGLONG l_time, s_time;
245 LONG diff;
246
247 GetSystemTime(&st);
248 s_time = system_time_to_minutes(&st);
249
250 SetLastError(0xdeadbeef);
251 res = SystemTimeToFileTime(&st, &s_ft);
252 ok(res, "SystemTimeToFileTime error %lu\n", GetLastError());
253 SetLastError(0xdeadbeef);
254 res = FileTimeToLocalFileTime(&s_ft, &l_ft);
255 ok(res, "FileTimeToLocalFileTime error %lu\n", GetLastError());
256 SetLastError(0xdeadbeef);
257 res = FileTimeToSystemTime(&l_ft, &local);
258 ok(res, "FileTimeToSystemTime error %lu\n", GetLastError());
259 l_time = system_time_to_minutes(&local);
260
261 tz_id = GetTimeZoneInformation(&tzinfo);
262 ok(tz_id != TIME_ZONE_ID_INVALID, "GetTimeZoneInformation failed\n");
263
264 trace("tz_id %lu (%s)\n", tz_id,
265 tz_id == TIME_ZONE_ID_DAYLIGHT ? "TIME_ZONE_ID_DAYLIGHT" :
266 (tz_id == TIME_ZONE_ID_STANDARD ? "TIME_ZONE_ID_STANDARD" :
267 (tz_id == TIME_ZONE_ID_UNKNOWN ? "TIME_ZONE_ID_UNKNOWN" :
268 "TIME_ZONE_ID_INVALID")));
269
270 WideCharToMultiByte(CP_ACP, 0, tzinfo.StandardName, -1, std_name, sizeof(std_name), NULL, NULL);
271 WideCharToMultiByte(CP_ACP, 0, tzinfo.DaylightName, -1, dlt_name, sizeof(dlt_name), NULL, NULL);
272 trace("bias %ld, %s - %s\n", tzinfo.Bias, std_name, dlt_name);
273 trace("standard (d/m/y): %u/%02u/%04u day of week %u %u:%02u:%02u.%03u bias %ld\n",
274 tzinfo.StandardDate.wDay, tzinfo.StandardDate.wMonth,
275 tzinfo.StandardDate.wYear, tzinfo.StandardDate.wDayOfWeek,
276 tzinfo.StandardDate.wHour, tzinfo.StandardDate.wMinute,
277 tzinfo.StandardDate.wSecond, tzinfo.StandardDate.wMilliseconds,
278 tzinfo.StandardBias);
279 trace("daylight (d/m/y): %u/%02u/%04u day of week %u %u:%02u:%02u.%03u bias %ld\n",
280 tzinfo.DaylightDate.wDay, tzinfo.DaylightDate.wMonth,
281 tzinfo.DaylightDate.wYear, tzinfo.DaylightDate.wDayOfWeek,
282 tzinfo.DaylightDate.wHour, tzinfo.DaylightDate.wMinute,
283 tzinfo.DaylightDate.wSecond, tzinfo.DaylightDate.wMilliseconds,
284 tzinfo.DaylightBias);
285
286 diff = (LONG)(s_time - l_time);
287 ok(diff == tzinfo.Bias + get_tz_bias(&tzinfo, tz_id),
288 "system/local diff %ld != tz bias %ld\n",
289 diff, tzinfo.Bias + get_tz_bias(&tzinfo, tz_id));
290
291 ok(SetEnvironmentVariableA("TZ","GMT0") != 0,
292 "SetEnvironmentVariableA failed\n");
293 res = GetTimeZoneInformation(&tzinfo1);
294 ok(res != TIME_ZONE_ID_INVALID, "GetTimeZoneInformation failed\n");
295
296 ok(((tzinfo.Bias == tzinfo1.Bias) &&
297 (tzinfo.StandardBias == tzinfo1.StandardBias) &&
298 (tzinfo.DaylightBias == tzinfo1.DaylightBias)),
299 "Bias influenced by TZ variable\n");
300 ok(SetEnvironmentVariableA("TZ",NULL) != 0,
301 "SetEnvironmentVariableA failed\n");
302
303 if (!pSystemTimeToTzSpecificLocalTime)
304 {
305 win_skip("SystemTimeToTzSpecificLocalTime not available\n");
306 return;
307 }
308
309 diff = get_tz_bias(&tzinfo, tz_id);
310
311 utc = st;
312 SetLastError(0xdeadbeef);
313 res = pSystemTimeToTzSpecificLocalTime(&tzinfo, &utc, ¤t);
314 if (!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
315 {
316 win_skip("SystemTimeToTzSpecificLocalTime is not implemented\n");
317 return;
318 }
319
320 ok(res, "SystemTimeToTzSpecificLocalTime error %lu\n", GetLastError());
321 s_time = system_time_to_minutes(¤t);
322
323 tzinfo.StandardBias -= 123;
324 tzinfo.DaylightBias += 456;
325
326 res = pSystemTimeToTzSpecificLocalTime(&tzinfo, &utc, &local);
327 ok(res, "SystemTimeToTzSpecificLocalTime error %lu\n", GetLastError());
328 l_time = system_time_to_minutes(&local);
329 ok(l_time - s_time == diff - get_tz_bias(&tzinfo, tz_id), "got %ld, expected %ld\n",
330 (LONG)(l_time - s_time), diff - get_tz_bias(&tzinfo, tz_id));
331
332 /* pretend that there is no transition dates */
333 tzinfo.DaylightDate.wDay = 0;
334 tzinfo.DaylightDate.wMonth = 0;
335 tzinfo.DaylightDate.wYear = 0;
336 tzinfo.StandardDate.wDay = 0;
337 tzinfo.StandardDate.wMonth = 0;
338 tzinfo.StandardDate.wYear = 0;
339
340 res = pSystemTimeToTzSpecificLocalTime(&tzinfo, &utc, &local);
341 ok(res, "SystemTimeToTzSpecificLocalTime error %lu\n", GetLastError());
342 l_time = system_time_to_minutes(&local);
343 ok(l_time - s_time == diff, "got %ld, expected %ld\n",
344 (LONG)(l_time - s_time), diff);
345
346 /* test 23:01, 31st of December date */
347 memset(&tzinfo, 0, sizeof(tzinfo));
348 tzinfo.StandardDate.wMonth = 10;
349 tzinfo.StandardDate.wDay = 5;
350 tzinfo.StandardDate.wHour = 2;
351 tzinfo.StandardDate.wMinute = 0;
352 tzinfo.DaylightDate.wMonth = 4;
353 tzinfo.DaylightDate.wDay = 1;
354 tzinfo.DaylightDate.wHour = 2;
355 tzinfo.Bias = 0;
356 tzinfo.StandardBias = 0;
357 tzinfo.DaylightBias = -60;
358 utc.wYear = 2012;
359 utc.wMonth = 12;
360 utc.wDay = 31;
361 utc.wHour = 23;
362 utc.wMinute = 1;
363 res = pSystemTimeToTzSpecificLocalTime(&tzinfo, &utc, &local);
364 ok(res, "SystemTimeToTzSpecificLocalTime error %lu\n", GetLastError());
365 ok(local.wYear==2012 && local.wMonth==12 && local.wDay==31 && local.wHour==23 && local.wMinute==1,
366 "got (%d-%d-%d %02d:%02d), expected (2012-12-31 23:01)\n",
367 local.wYear, local.wMonth, local.wDay, local.wHour, local.wMinute);
368}
369
370static void test_FileTimeToSystemTime(void)
371{
372 FILETIME ft;
373 SYSTEMTIME st;
374 ULONGLONG time = (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
375 BOOL ret;
376
377 ft.dwHighDateTime = 0;
378 ft.dwLowDateTime = 0;
379 ret = FileTimeToSystemTime(&ft, &st);
380 ok( ret,
381 "FileTimeToSystemTime() failed with Error %ld\n",GetLastError());
382 ok(((st.wYear == 1601) && (st.wMonth == 1) && (st.wDay == 1) &&
383 (st.wHour == 0) && (st.wMinute == 0) && (st.wSecond == 0) &&
384 (st.wMilliseconds == 0)),
385 "Got Year %4d Month %2d Day %2d\n", st.wYear, st.wMonth, st.wDay);
386
387 ft.dwHighDateTime = (UINT)(time >> 32);
388 ft.dwLowDateTime = (UINT)time;
389 ret = FileTimeToSystemTime(&ft, &st);
390 ok( ret,
391 "FileTimeToSystemTime() failed with Error %ld\n",GetLastError());
392 ok(((st.wYear == 1970) && (st.wMonth == 1) && (st.wDay == 1) &&
393 (st.wHour == 0) && (st.wMinute == 0) && (st.wSecond == 1) &&
394 (st.wMilliseconds == 0)),
395 "Got Year %4d Month %2d Day %2d Hour %2d Min %2d Sec %2d mSec %3d\n",
396 st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond,
397 st.wMilliseconds);
398
399 ft.dwHighDateTime = -1;
400 ft.dwLowDateTime = -1;
401 SetLastError(0xdeadbeef);
402 ret = FileTimeToSystemTime(&ft, &st);
403 ok(!ret, "expected failure\n");
404 ok(GetLastError() == ERROR_INVALID_PARAMETER,
405 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
406}
407
408static void test_FileTimeToLocalFileTime(void)
409{
410 FILETIME ft, lft;
411 SYSTEMTIME st;
412 TIME_ZONE_INFORMATION tzinfo;
413 DWORD res = GetTimeZoneInformation(&tzinfo);
414 ULONGLONG time = (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970 +
415 (LONGLONG)(tzinfo.Bias +
416 ( res == TIME_ZONE_ID_STANDARD ? tzinfo.StandardBias :
417 ( res == TIME_ZONE_ID_DAYLIGHT ? tzinfo.DaylightBias : 0 ))) *
418 SECSPERMIN *TICKSPERSEC;
419 BOOL ret;
420
421 ok( res != TIME_ZONE_ID_INVALID , "GetTimeZoneInformation failed\n");
422 ft.dwHighDateTime = (UINT)(time >> 32);
423 ft.dwLowDateTime = (UINT)time;
424 ret = FileTimeToLocalFileTime(&ft, &lft);
425 ok( ret,
426 "FileTimeToLocalFileTime() failed with Error %ld\n",GetLastError());
427 FileTimeToSystemTime(&lft, &st);
428 ok(((st.wYear == 1970) && (st.wMonth == 1) && (st.wDay == 1) &&
429 (st.wHour == 0) && (st.wMinute == 0) && (st.wSecond == 1) &&
430 (st.wMilliseconds == 0)),
431 "Got Year %4d Month %2d Day %2d Hour %2d Min %2d Sec %2d mSec %3d\n",
432 st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond,
433 st.wMilliseconds);
434
435 ok(SetEnvironmentVariableA("TZ","GMT") != 0,
436 "SetEnvironmentVariableA failed\n");
437 ok(res != TIME_ZONE_ID_INVALID, "GetTimeZoneInformation failed\n");
438 ret = FileTimeToLocalFileTime(&ft, &lft);
439 ok( ret,
440 "FileTimeToLocalFileTime() failed with Error %ld\n",GetLastError());
441 FileTimeToSystemTime(&lft, &st);
442 ok(((st.wYear == 1970) && (st.wMonth == 1) && (st.wDay == 1) &&
443 (st.wHour == 0) && (st.wMinute == 0) && (st.wSecond == 1) &&
444 (st.wMilliseconds == 0)),
445 "Got Year %4d Month %2d Day %2d Hour %2d Min %2d Sec %2d mSec %3d\n",
446 st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond,
447 st.wMilliseconds);
448 ok(SetEnvironmentVariableA("TZ",NULL) != 0,
449 "SetEnvironmentVariableA failed\n");
450}
451
452typedef struct {
453 int nr; /* test case number for easier lookup */
454 TIME_ZONE_INFORMATION *ptz; /* ptr to timezone */
455 SYSTEMTIME slt; /* system/local time to convert */
456 WORD ehour; /* expected hour */
457} TZLT2ST_case;
458
459static void test_TzSpecificLocalTimeToSystemTime(void)
460{
461 TIME_ZONE_INFORMATION tzE, tzW, tzS;
462 SYSTEMTIME result;
463 int i, j, year;
464
465 if (!pTzSpecificLocalTimeToSystemTime || !pSystemTimeToTzSpecificLocalTime)
466 {
467 win_skip("TzSpecificLocalTimeToSystemTime or SystemTimeToTzSpecificLocalTime not available\n");
468 return;
469 }
470
471 ZeroMemory( &tzE, sizeof(tzE));
472 ZeroMemory( &tzW, sizeof(tzW));
473 ZeroMemory( &tzS, sizeof(tzS));
474 /* timezone Eastern hemisphere */
475 tzE.Bias=-600;
476 tzE.StandardBias=0;
477 tzE.DaylightBias=-60;
478 tzE.StandardDate.wMonth=10;
479 tzE.StandardDate.wDayOfWeek=0; /* Sunday */
480 tzE.StandardDate.wDay=5; /* last (Sunday) of the month */
481 tzE.StandardDate.wHour=3;
482 tzE.DaylightDate.wMonth=3;
483 tzE.DaylightDate.wDay=5;
484 tzE.DaylightDate.wHour=2;
485 /* timezone Western hemisphere */
486 tzW.Bias=240;
487 tzW.StandardBias=0;
488 tzW.DaylightBias=-60;
489 tzW.StandardDate.wMonth=10;
490 tzW.StandardDate.wDayOfWeek=0; /* Sunday */
491 tzW.StandardDate.wDay=4; /* 4th (Sunday) of the month */
492 tzW.StandardDate.wHour=2;
493 tzW.DaylightDate.wMonth=4;
494 tzW.DaylightDate.wDay=1;
495 tzW.DaylightDate.wHour=2;
496 /* timezone Southern hemisphere */
497 tzS.Bias=240;
498 tzS.StandardBias=0;
499 tzS.DaylightBias=-60;
500 tzS.StandardDate.wMonth=4;
501 tzS.StandardDate.wDayOfWeek=0; /*Sunday */
502 tzS.StandardDate.wDay=1; /* 1st (Sunday) of the month */
503 tzS.StandardDate.wHour=2;
504 tzS.DaylightDate.wMonth=10;
505 tzS.DaylightDate.wDay=4;
506 tzS.DaylightDate.wHour=2;
507 /*tests*/
508 /* TzSpecificLocalTimeToSystemTime */
509 { TZLT2ST_case cases[] = {
510 /* standard->daylight transition */
511 { 1, &tzE, {2004,3,-1,28,1,0,0,0}, 15 },
512 { 2, &tzE, {2004,3,-1,28,1,59,59,999}, 15},
513 { 3, &tzE, {2004,3,-1,28,2,0,0,0}, 15},
514 /* daylight->standard transition */
515 { 4, &tzE, {2004,10,-1,31,2,0,0,0} , 15 },
516 { 5, &tzE, {2004,10,-1,31,2,59,59,999}, 15 },
517 { 6, &tzE, {2004,10,-1,31,3,0,0,0}, 17 },
518 /* West and with fixed weekday of the month */
519 { 7, &tzW, {2004,4,-1,4,1,0,0,0}, 5},
520 { 8, &tzW, {2004,4,-1,4,1,59,59,999}, 5},
521 { 9, &tzW, {2004,4,-1,4,2,0,0,0}, 5},
522 { 10, &tzW, {2004,10,-1,24,1,0,0,0}, 4},
523 { 11, &tzW, {2004,10,-1,24,1,59,59,999}, 4},
524 { 12, &tzW, {2004,10,-1,24,2,0,0,0 }, 6},
525 /* and now South */
526 { 13, &tzS, {2004,4,-1,4,1,0,0,0}, 4},
527 { 14, &tzS, {2004,4,-1,4,1,59,59,999}, 4},
528 { 15, &tzS, {2004,4,-1,4,2,0,0,0}, 6},
529 { 16, &tzS, {2004,10,-1,24,1,0,0,0}, 5},
530 { 17, &tzS, {2004,10,-1,24,1,59,59,999}, 5},
531 { 18, &tzS, {2004,10,-1,24,2,0,0,0}, 5},
532 {0}
533 };
534 /* days of transitions to put into the cases array */
535 int yeardays[][6]=
536 {
537 {28,31,4,24,4,24} /* 1999 */
538 , {26,29,2,22,2,22} /* 2000 */
539 , {25,28,1,28,1,28} /* 2001 */
540 , {31,27,7,27,7,27} /* 2002 */
541 , {30,26,6,26,6,26} /* 2003 */
542 , {28,31,4,24,4,24} /* 2004 */
543 , {27,30,3,23,3,23} /* 2005 */
544 , {26,29,2,22,2,22} /* 2006 */
545 , {25,28,1,28,1,28} /* 2007 */
546 , {30,26,6,26,6,26} /* 2008 */
547 , {29,25,5,25,5,25} /* 2009 */
548 , {28,31,4,24,4,24} /* 2010 */
549 , {27,30,3,23,3,23} /* 2011 */
550 , {25,28,1,28,1,28} /* 2012 */
551 , {31,27,7,27,7,27} /* 2013 */
552 , {30,26,6,26,6,26} /* 2014 */
553 , {29,25,5,25,5,25} /* 2015 */
554 , {27,30,3,23,3,23} /* 2016 */
555 , {26,29,2,22,2,22} /* 2017 */
556 , {25,28,1,28,1,28} /* 2018 */
557 , {31,27,7,27,7,27} /* 2019 */
558 ,{0}
559 };
560 for( j=0 , year = 1999; yeardays[j][0] ; j++, year++) {
561 for (i=0; cases[i].nr; i++) {
562 if(i) cases[i].nr += 18;
563 cases[i].slt.wYear = year;
564 cases[i].slt.wDay = yeardays[j][i/3];
565 pTzSpecificLocalTimeToSystemTime( cases[i].ptz, &(cases[i].slt), &result);
566 ok( result.wHour == cases[i].ehour,
567 "Test TzSpecificLocalTimeToSystemTime #%d. Got %4d-%02d-%02d %02d:%02d. Expect hour = %02d\n",
568 cases[i].nr, result.wYear, result.wMonth, result.wDay,
569 result.wHour, result.wMinute, cases[i].ehour);
570 }
571 }
572 }
573 /* SystemTimeToTzSpecificLocalTime */
574 { TZLT2ST_case cases[] = {
575 /* standard->daylight transition */
576 { 1, &tzE, {2004,3,-1,27,15,0,0,0}, 1 },
577 { 2, &tzE, {2004,3,-1,27,15,59,59,999}, 1},
578 { 3, &tzE, {2004,3,-1,27,16,0,0,0}, 3},
579 /* daylight->standard transition */
580 { 4, &tzE, {2004,10,-1,30,15,0,0,0}, 2 },
581 { 5, &tzE, {2004,10,-1,30,15,59,59,999}, 2 },
582 { 6, &tzE, {2004,10,-1,30,16,0,0,0}, 2 },
583 /* West and with fixed weekday of the month */
584 { 7, &tzW, {2004,4,-1,4,5,0,0,0}, 1},
585 { 8, &tzW, {2004,4,-1,4,5,59,59,999}, 1},
586 { 9, &tzW, {2004,4,-1,4,6,0,0,0}, 3},
587 { 10, &tzW, {2004,10,-1,24,4,0,0,0}, 1},
588 { 11, &tzW, {2004,10,-1,24,4,59,59,999}, 1},
589 { 12, &tzW, {2004,10,-1,24,5,0,0,0 }, 1},
590 /* and now South */
591 { 13, &tzS, {2004,4,-1,4,4,0,0,0}, 1},
592 { 14, &tzS, {2004,4,-1,4,4,59,59,999}, 1},
593 { 15, &tzS, {2004,4,-1,4,5,0,0,0}, 1},
594 { 16, &tzS, {2004,10,-1,24,5,0,0,0}, 1},
595 { 17, &tzS, {2004,10,-1,24,5,59,59,999}, 1},
596 { 18, &tzS, {2004,10,-1,24,6,0,0,0}, 3},
597
598 {0}
599 };
600 /* days of transitions to put into the cases array */
601 int yeardays[][6]=
602 {
603 {27,30,4,24,4,24} /* 1999 */
604 , {25,28,2,22,2,22} /* 2000 */
605 , {24,27,1,28,1,28} /* 2001 */
606 , {30,26,7,27,7,27} /* 2002 */
607 , {29,25,6,26,6,26} /* 2003 */
608 , {27,30,4,24,4,24} /* 2004 */
609 , {26,29,3,23,3,23} /* 2005 */
610 , {25,28,2,22,2,22} /* 2006 */
611 , {24,27,1,28,1,28} /* 2007 */
612 , {29,25,6,26,6,26} /* 2008 */
613 , {28,24,5,25,5,25} /* 2009 */
614 , {27,30,4,24,4,24} /* 2010 */
615 , {26,29,3,23,3,23} /* 2011 */
616 , {24,27,1,28,1,28} /* 2012 */
617 , {30,26,7,27,7,27} /* 2013 */
618 , {29,25,6,26,6,26} /* 2014 */
619 , {28,24,5,25,5,25} /* 2015 */
620 , {26,29,3,23,3,23} /* 2016 */
621 , {25,28,2,22,2,22} /* 2017 */
622 , {24,27,1,28,1,28} /* 2018 */
623 , {30,26,7,27,7,27} /* 2019 */
624 , {0}
625 };
626 for( j=0 , year = 1999; yeardays[j][0] ; j++, year++) {
627 for (i=0; cases[i].nr; i++) {
628 if(i) cases[i].nr += 18;
629 cases[i].slt.wYear = year;
630 cases[i].slt.wDay = yeardays[j][i/3];
631 pSystemTimeToTzSpecificLocalTime( cases[i].ptz, &(cases[i].slt), &result);
632 ok( result.wHour == cases[i].ehour,
633 "Test SystemTimeToTzSpecificLocalTime #%d. Got %4d-%02d-%02d %02d:%02d. Expect hour = %02d\n",
634 cases[i].nr, result.wYear, result.wMonth, result.wDay,
635 result.wHour, result.wMinute, cases[i].ehour);
636 }
637 }
638
639 }
640}
641
642static void test_FileTimeToDosDateTime(void)
643{
644 FILETIME ft = { 0 };
645 WORD fatdate, fattime;
646 BOOL ret;
647
648 if (0)
649 {
650 /* Crashes */
651 FileTimeToDosDateTime(NULL, NULL, NULL);
652 }
653 /* Parameter checking */
654 SetLastError(0xdeadbeef);
655 ret = FileTimeToDosDateTime(&ft, NULL, NULL);
656 ok(!ret, "expected failure\n");
657 ok(GetLastError() == ERROR_INVALID_PARAMETER,
658 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
659
660 SetLastError(0xdeadbeef);
661 ret = FileTimeToDosDateTime(&ft, &fatdate, NULL);
662 ok(!ret, "expected failure\n");
663 ok(GetLastError() == ERROR_INVALID_PARAMETER,
664 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
665
666 SetLastError(0xdeadbeef);
667 ret = FileTimeToDosDateTime(&ft, NULL, &fattime);
668 ok(!ret, "expected failure\n");
669 ok(GetLastError() == ERROR_INVALID_PARAMETER,
670 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
671
672 SetLastError(0xdeadbeef);
673 ret = FileTimeToDosDateTime(&ft, &fatdate, &fattime);
674 ok(!ret, "expected failure\n");
675 ok(GetLastError() == ERROR_INVALID_PARAMETER,
676 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
677}
678
679static void test_GetCalendarInfo(void)
680{
681 char bufferA[20];
682 WCHAR bufferW[20];
683 DWORD val1, val2;
684 int i, j, ret, ret2;
685
686 if (!pGetCalendarInfoA || !pGetCalendarInfoW)
687 {
688 trace( "GetCalendarInfo missing\n" );
689 return;
690 }
691
692 ret = pGetCalendarInfoA( 0x0409, CAL_GREGORIAN, CAL_ITWODIGITYEARMAX | CAL_RETURN_NUMBER,
693 NULL, 0, &val1 );
694 ok( ret, "GetCalendarInfoA failed err %lu\n", GetLastError() );
695 ok( ret == sizeof(val1), "wrong size %u\n", ret );
696 ok( val1 >= 2000 && val1 < 2100, "wrong value %lu\n", val1 );
697
698 ret = pGetCalendarInfoW( 0x0409, CAL_GREGORIAN, CAL_ITWODIGITYEARMAX | CAL_RETURN_NUMBER,
699 NULL, 0, &val2 );
700 ok( ret, "GetCalendarInfoW failed err %lu\n", GetLastError() );
701 ok( ret == sizeof(val2)/sizeof(WCHAR), "wrong size %u\n", ret );
702 ok( val1 == val2, "A/W mismatch %lu/%lu\n", val1, val2 );
703
704 ret = pGetCalendarInfoA( 0x0409, CAL_GREGORIAN, CAL_ITWODIGITYEARMAX, bufferA, sizeof(bufferA), NULL );
705 ok( ret, "GetCalendarInfoA failed err %lu\n", GetLastError() );
706 ok( ret == 5, "wrong size %u\n", ret );
707 ok( atoi( bufferA ) == val1, "wrong value %s/%lu\n", bufferA, val1 );
708
709 ret = pGetCalendarInfoW( 0x0409, CAL_GREGORIAN, CAL_ITWODIGITYEARMAX, bufferW, ARRAY_SIZE(bufferW), NULL );
710 ok( ret, "GetCalendarInfoW failed err %lu\n", GetLastError() );
711 ok( ret == 5, "wrong size %u\n", ret );
712 memset( bufferA, 0x55, sizeof(bufferA) );
713 WideCharToMultiByte( CP_ACP, 0, bufferW, -1, bufferA, sizeof(bufferA), NULL, NULL );
714 ok( atoi( bufferA ) == val1, "wrong value %s/%lu\n", bufferA, val1 );
715
716 ret = pGetCalendarInfoA( 0x0409, CAL_GREGORIAN, CAL_ITWODIGITYEARMAX | CAL_RETURN_NUMBER,
717 NULL, 0, NULL );
718 ok( !ret, "GetCalendarInfoA succeeded\n" );
719 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() );
720
721 ret = pGetCalendarInfoA( 0x0409, CAL_GREGORIAN, CAL_ITWODIGITYEARMAX, NULL, 0, NULL );
722 ok( ret, "GetCalendarInfoA failed err %lu\n", GetLastError() );
723 ok( ret == 5, "wrong size %u\n", ret );
724
725 ret = pGetCalendarInfoW( 0x0409, CAL_GREGORIAN, CAL_ITWODIGITYEARMAX | CAL_RETURN_NUMBER,
726 NULL, 0, NULL );
727 ok( !ret, "GetCalendarInfoW succeeded\n" );
728 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() );
729
730 ret = pGetCalendarInfoW( 0x0409, CAL_GREGORIAN, CAL_ITWODIGITYEARMAX, NULL, 0, NULL );
731 ok( ret, "GetCalendarInfoW failed err %lu\n", GetLastError() );
732 ok( ret == 5, "wrong size %u\n", ret );
733
734 ret = pGetCalendarInfoA( LANG_SYSTEM_DEFAULT, CAL_GREGORIAN, CAL_SDAYNAME1,
735 bufferA, sizeof(bufferA), NULL);
736 ok( ret, "GetCalendarInfoA failed err %lu\n", GetLastError() );
737 ret2 = pGetCalendarInfoA( LANG_SYSTEM_DEFAULT, CAL_GREGORIAN, CAL_SDAYNAME1,
738 bufferA, 0, NULL);
739 ok( ret2, "GetCalendarInfoA failed err %lu\n", GetLastError() );
740 ok( ret == ret2, "got %d, expected %d\n", ret2, ret );
741
742 ret2 = pGetCalendarInfoW( LANG_SYSTEM_DEFAULT, CAL_GREGORIAN, CAL_SDAYNAME1,
743 bufferW, ARRAY_SIZE(bufferW), NULL);
744 ok( ret2, "GetCalendarInfoW failed err %lu\n", GetLastError() );
745 ret2 = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL );
746 ok( ret == ret2, "got %d, expected %d\n", ret, ret2 );
747
748#ifdef __REACTOS__
749 if (GetNTVersion() >= _WIN32_WINNT_VISTA) {
750#endif
751 for (i = CAL_GREGORIAN; i <= CAL_UMALQURA; i++)
752 {
753 WCHAR name[80];
754 ret = pGetCalendarInfoW( 0x0409, i, CAL_SCALNAME, name, ARRAY_SIZE(name), NULL);
755 for (j = CAL_ICALINTVALUE; j <= CAL_SRELATIVELONGDATE; j++)
756 {
757 ret2 = pGetCalendarInfoW( 0x0409, i, j, bufferW, ARRAY_SIZE(bufferW), NULL);
758 if (ret || j == CAL_ITWODIGITYEARMAX)
759#ifdef __REACTOS__
760 ok( ret2 || broken(j == CAL_SRELATIVELONGDATE) /* Win7 */ || broken(j == CAL_SMONTHDAY || j == CAL_SABBREVERASTRING), /* Vista */
761#else
762 ok( ret2 || broken(j == CAL_SRELATIVELONGDATE), /* win7 doesn't have this */
763#endif
764 "calendar %u %s value %02x failed\n", i, wine_dbgstr_w(name), j );
765 else
766 ok( !ret2, "calendar %u %s value %02x succeeded %s\n",
767 i, wine_dbgstr_w(name), j, wine_dbgstr_w(bufferW) );
768 }
769 }
770#ifdef __REACTOS__
771 }
772#endif
773}
774
775static void test_GetDynamicTimeZoneInformation(void)
776{
777 DYNAMIC_TIME_ZONE_INFORMATION dyninfo;
778 TIME_ZONE_INFORMATION tzinfo;
779 DWORD ret, ret2;
780
781#if defined(__REACTOS__) && DLL_EXPORT_VERSION >= 0x600
782 /* FIXME: GetDynamicTimeZoneInformation is a STUB on ReactOS */
783 if (is_reactos() || !pGetDynamicTimeZoneInformation)
784#else
785 if (!pGetDynamicTimeZoneInformation)
786#endif
787 {
788 win_skip("GetDynamicTimeZoneInformation() is not supported.\n");
789 return;
790 }
791
792 ret = pGetDynamicTimeZoneInformation(&dyninfo);
793 ret2 = GetTimeZoneInformation(&tzinfo);
794 ok(ret == ret2, "got %ld, %ld\n", ret, ret2);
795
796 ok(dyninfo.Bias == tzinfo.Bias, "got %ld, %ld\n", dyninfo.Bias, tzinfo.Bias);
797 ok(!lstrcmpW(dyninfo.StandardName, tzinfo.StandardName), "got std name %s, %s\n",
798 wine_dbgstr_w(dyninfo.StandardName), wine_dbgstr_w(tzinfo.StandardName));
799 ok(!memcmp(&dyninfo.StandardDate, &tzinfo.StandardDate, sizeof(dyninfo.StandardDate)), "got different StandardDate\n");
800 ok(dyninfo.StandardBias == tzinfo.StandardBias, "got %ld, %ld\n", dyninfo.StandardBias, tzinfo.StandardBias);
801 ok(!lstrcmpW(dyninfo.DaylightName, tzinfo.DaylightName), "got daylight name %s, %s\n",
802 wine_dbgstr_w(dyninfo.DaylightName), wine_dbgstr_w(tzinfo.DaylightName));
803 ok(!memcmp(&dyninfo.DaylightDate, &tzinfo.DaylightDate, sizeof(dyninfo.DaylightDate)), "got different DaylightDate\n");
804 ok(dyninfo.TimeZoneKeyName[0] != 0, "got empty tz keyname\n");
805 trace("Dyn TimeZoneKeyName %s\n", wine_dbgstr_w(dyninfo.TimeZoneKeyName));
806}
807
808static ULONGLONG get_longlong_time(FILETIME *time)
809{
810 ULARGE_INTEGER uli;
811 uli.u.LowPart = time->dwLowDateTime;
812 uli.u.HighPart = time->dwHighDateTime;
813 return uli.QuadPart;
814}
815
816static void test_GetSystemTimeAsFileTime(void)
817{
818 LARGE_INTEGER t1, t2, t3;
819 FILETIME ft;
820
821 NtQuerySystemTime( &t1 );
822 GetSystemTimeAsFileTime( &ft );
823 NtQuerySystemTime( &t3 );
824 t2.QuadPart = get_longlong_time( &ft );
825
826 ok(t1.QuadPart <= t2.QuadPart, "out of order %s %s\n", wine_dbgstr_longlong(t1.QuadPart), wine_dbgstr_longlong(t2.QuadPart));
827 ok(t2.QuadPart <= t3.QuadPart, "out of order %s %s\n", wine_dbgstr_longlong(t2.QuadPart), wine_dbgstr_longlong(t3.QuadPart));
828}
829
830static void test_GetSystemTimePreciseAsFileTime(void)
831{
832 FILETIME ft;
833 ULONGLONG time1, time2;
834 LONGLONG diff;
835
836 if (!pGetSystemTimePreciseAsFileTime)
837 {
838 win_skip("GetSystemTimePreciseAsFileTime() is not supported.\n");
839 return;
840 }
841
842 GetSystemTimeAsFileTime(&ft);
843 time1 = get_longlong_time(&ft);
844 pGetSystemTimePreciseAsFileTime(&ft);
845 time2 = get_longlong_time(&ft);
846 diff = time2 - time1;
847 if (diff < 0)
848 diff = -diff;
849 ok(diff < 1000000, "Difference between GetSystemTimeAsFileTime and GetSystemTimePreciseAsFileTime more than 100 ms\n");
850
851 pGetSystemTimePreciseAsFileTime(&ft);
852 time1 = get_longlong_time(&ft);
853 do {
854 pGetSystemTimePreciseAsFileTime(&ft);
855 time2 = get_longlong_time(&ft);
856 } while (time2 == time1);
857 diff = time2 - time1;
858 ok(diff < 10000 && diff > 0, "GetSystemTimePreciseAsFileTime incremented by more than 1 ms\n");
859}
860
861static void test_GetSystemTimes(void)
862{
863
864 FILETIME idletime, kerneltime, usertime;
865 int i;
866 ULARGE_INTEGER ul1, ul2, ul3;
867 SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi;
868 SYSTEM_BASIC_INFORMATION sbi;
869 ULONG ReturnLength;
870 ULARGE_INTEGER total_usertime, total_kerneltime, total_idletime;
871
872 if (!pGetSystemTimes)
873 {
874 win_skip("GetSystemTimes not available\n");
875 return;
876 }
877
878 ok( pGetSystemTimes(NULL, NULL, NULL), "GetSystemTimes failed unexpectedly\n" );
879
880 total_usertime.QuadPart = 0;
881 total_kerneltime.QuadPart = 0;
882 total_idletime.QuadPart = 0;
883 memset( &idletime, 0x11, sizeof(idletime) );
884 memset( &kerneltime, 0x11, sizeof(kerneltime) );
885 memset( &usertime, 0x11, sizeof(usertime) );
886 ok( pGetSystemTimes(&idletime, &kerneltime , &usertime),
887 "GetSystemTimes failed unexpectedly\n" );
888
889 ul1.LowPart = idletime.dwLowDateTime;
890 ul1.HighPart = idletime.dwHighDateTime;
891 ul2.LowPart = kerneltime.dwLowDateTime;
892 ul2.HighPart = kerneltime.dwHighDateTime;
893 ul3.LowPart = usertime.dwLowDateTime;
894 ul3.HighPart = usertime.dwHighDateTime;
895
896 ok( !NtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength),
897 "NtQuerySystemInformation failed\n" );
898 ok( sizeof(sbi) == ReturnLength, "Inconsistent length %ld\n", ReturnLength );
899
900 /* Check if we have some return values */
901 trace( "Number of Processors : %d\n", sbi.NumberOfProcessors );
902 ok( sbi.NumberOfProcessors > 0, "Expected more than 0 processors, got %d\n",
903 sbi.NumberOfProcessors );
904
905 sppi = HeapAlloc( GetProcessHeap(), 0,
906 sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * sbi.NumberOfProcessors);
907
908 ok( !NtQuerySystemInformation( SystemProcessorPerformanceInformation, sppi,
909 sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * sbi.NumberOfProcessors,
910 &ReturnLength),
911 "NtQuerySystemInformation failed\n" );
912
913 for (i = 0; i < sbi.NumberOfProcessors; i++)
914 {
915 total_usertime.QuadPart += sppi[i].UserTime.QuadPart;
916 total_kerneltime.QuadPart += sppi[i].KernelTime.QuadPart;
917 total_idletime.QuadPart += sppi[i].IdleTime.QuadPart;
918 }
919
920 ok( total_idletime.QuadPart - ul1.QuadPart < 10000000, "test idletime failed\n" );
921 ok( total_kerneltime.QuadPart - ul2.QuadPart < 10000000, "test kerneltime failed\n" );
922 ok( total_usertime.QuadPart - ul3.QuadPart < 10000000, "test usertime failed\n" );
923
924 HeapFree(GetProcessHeap(), 0, sppi);
925}
926
927static WORD day_of_month(const SYSTEMTIME* systemtime, WORD year)
928{
929 SYSTEMTIME first_of_month = {0};
930 FILETIME filetime;
931 WORD result;
932
933 if (systemtime->wYear != 0)
934 return systemtime->wDay;
935
936 if (systemtime->wMonth == 0)
937 return 0;
938
939 first_of_month.wYear = year;
940 first_of_month.wMonth = systemtime->wMonth;
941 first_of_month.wDay = 1;
942
943 /* round-trip conversion sets day of week field */
944 SystemTimeToFileTime(&first_of_month, &filetime);
945 FileTimeToSystemTime(&filetime, &first_of_month);
946
947 result = 1 + ((systemtime->wDayOfWeek - first_of_month.wDayOfWeek + 7) % 7) +
948 (7 * (systemtime->wDay - 1));
949
950 if (systemtime->wDay == 5)
951 {
952 /* make sure this isn't in the next month */
953 SYSTEMTIME result_date;
954
955 result_date = first_of_month;
956 result_date.wDay = result;
957
958 SystemTimeToFileTime(&result_date, &filetime);
959 FileTimeToSystemTime(&filetime, &result_date);
960
961 if (result_date.wDay != result)
962 result = 1 + ((systemtime->wDayOfWeek - first_of_month.wDayOfWeek + 7) % 7) +
963 (7 * (4 - 1));
964 }
965
966 return result;
967}
968
969static void test_GetTimeZoneInformationForYear(void)
970{
971 BOOL ret, broken_test = FALSE;
972 SYSTEMTIME systemtime;
973 TIME_ZONE_INFORMATION local_tzinfo, tzinfo, tzinfo2;
974 DYNAMIC_TIME_ZONE_INFORMATION dyn_tzinfo;
975 WORD std_day, dlt_day;
976 unsigned i;
977 static const struct
978 {
979 const WCHAR *tzname;
980 USHORT year;
981 LONG bias, std_bias, dlt_bias;
982 WORD std_month, std_day, dlt_month, dlt_day;
983 }
984 test_data[] =
985 {
986 { L"Greenland Standard Time", 2015, 180, 0, -60, 10, 24, 3, 28 },
987 { L"Greenland Standard Time", 2016, 180, 0, -60, 10, 29, 3, 26 },
988 { L"Greenland Standard Time", 2017, 180, 0, -60, 10, 28, 3, 25 },
989 { L"Easter Island Standard Time", 2014, 360, 0, -60, 4, 26, 9, 6 },
990 { L"Easter Island Standard Time", 2015, 300, 0, -60, 0, 0, 0, 0 },
991 { L"Easter Island Standard Time", 2016, 360, 0, -60, 5, 14, 8, 13 },
992 { L"Egypt Standard Time", 2013, -120, 0, -60, 0, 0, 0, 0 },
993 { L"Egypt Standard Time", 2014, -120, 0, -60, 9, 25, 5, 15 },
994 { L"Egypt Standard Time", 2015, -120, 0, -60, 0, 0, 0, 0 },
995 { L"Egypt Standard Time", 2016, -120, 0, -60, 0, 0, 0, 0 },
996 { L"Altai Standard Time", 2016, -420, 0, 60, 3, 27, 1, 1 },
997 { L"Altai Standard Time", 2017, -420, 0, -60, 0, 0, 0, 0 },
998 { L"Altai Standard Time", 2018, -420, 0, -60, 0, 0, 0, 0 },
999 };
1000
1001#if defined(__REACTOS__) && DLL_EXPORT_VERSION >= 0x600
1002 /* FIXME: GetTimeZoneInformationForYear and GetDynamicTimeZoneInformation are STUBS on ReactOS */
1003 if (is_reactos() || !pGetTimeZoneInformationForYear || !pGetDynamicTimeZoneInformation)
1004#else
1005 if (!pGetTimeZoneInformationForYear || !pGetDynamicTimeZoneInformation)
1006#endif
1007 {
1008 win_skip("GetTimeZoneInformationForYear not available\n");
1009 return;
1010 }
1011
1012 GetLocalTime(&systemtime);
1013
1014 GetTimeZoneInformation(&local_tzinfo);
1015
1016 ret = pGetTimeZoneInformationForYear(systemtime.wYear, NULL, &tzinfo);
1017 ok(ret == TRUE, "GetTimeZoneInformationForYear failed, err %lu\n", GetLastError());
1018 ok(tzinfo.Bias == local_tzinfo.Bias, "Expected Bias %ld, got %ld\n", local_tzinfo.Bias, tzinfo.Bias);
1019 ok(!lstrcmpW(tzinfo.StandardName, local_tzinfo.StandardName),
1020 "Expected StandardName %s, got %s\n", wine_dbgstr_w(local_tzinfo.StandardName), wine_dbgstr_w(tzinfo.StandardName));
1021 ok(!memcmp(&tzinfo.StandardDate, &local_tzinfo.StandardDate, sizeof(SYSTEMTIME)), "StandardDate does not match\n");
1022 ok(tzinfo.StandardBias == local_tzinfo.StandardBias, "Expected StandardBias %ld, got %ld\n", local_tzinfo.StandardBias, tzinfo.StandardBias);
1023 ok(!lstrcmpW(tzinfo.DaylightName, local_tzinfo.DaylightName),
1024 "Expected DaylightName %s, got %s\n", wine_dbgstr_w(local_tzinfo.DaylightName), wine_dbgstr_w(tzinfo.DaylightName));
1025 ok(!memcmp(&tzinfo.DaylightDate, &local_tzinfo.DaylightDate, sizeof(SYSTEMTIME)), "DaylightDate does not match\n");
1026 ok(tzinfo.DaylightBias == local_tzinfo.DaylightBias, "Expected DaylightBias %ld, got %ld\n", local_tzinfo.DaylightBias, tzinfo.DaylightBias);
1027
1028 pGetDynamicTimeZoneInformation(&dyn_tzinfo);
1029
1030 ret = pGetTimeZoneInformationForYear(systemtime.wYear, &dyn_tzinfo, &tzinfo);
1031 ok(ret == TRUE, "GetTimeZoneInformationForYear failed, err %lu\n", GetLastError());
1032 ok(tzinfo.Bias == local_tzinfo.Bias, "Expected Bias %ld, got %ld\n", local_tzinfo.Bias, tzinfo.Bias);
1033 ok(!lstrcmpW(tzinfo.StandardName, local_tzinfo.StandardName),
1034 "Expected StandardName %s, got %s\n", wine_dbgstr_w(local_tzinfo.StandardName), wine_dbgstr_w(tzinfo.StandardName));
1035 ok(!memcmp(&tzinfo.StandardDate, &local_tzinfo.StandardDate, sizeof(SYSTEMTIME)), "StandardDate does not match\n");
1036 ok(tzinfo.StandardBias == local_tzinfo.StandardBias, "Expected StandardBias %ld, got %ld\n", local_tzinfo.StandardBias, tzinfo.StandardBias);
1037 ok(!lstrcmpW(tzinfo.DaylightName, local_tzinfo.DaylightName),
1038 "Expected DaylightName %s, got %s\n", wine_dbgstr_w(local_tzinfo.DaylightName), wine_dbgstr_w(tzinfo.DaylightName));
1039 ok(!memcmp(&tzinfo.DaylightDate, &local_tzinfo.DaylightDate, sizeof(SYSTEMTIME)), "DaylightDate does not match\n");
1040 ok(tzinfo.DaylightBias == local_tzinfo.DaylightBias, "Expected DaylightBias %ld, got %ld\n", local_tzinfo.DaylightBias, tzinfo.DaylightBias);
1041
1042 memset(&dyn_tzinfo, 0xaa, sizeof(dyn_tzinfo));
1043 lstrcpyW(dyn_tzinfo.TimeZoneKeyName, L"Greenland Daylight Time");
1044 SetLastError(0xdeadbeef);
1045 ret = pGetTimeZoneInformationForYear(2015, &dyn_tzinfo, &tzinfo);
1046 if (ret)
1047 broken_test = TRUE;
1048 ok((ret == FALSE && GetLastError() == ERROR_FILE_NOT_FOUND) ||
1049 broken(broken_test) /* vista,7 */,
1050 "GetTimeZoneInformationForYear err %lu\n", GetLastError());
1051
1052 memset(&dyn_tzinfo, 0xaa, sizeof(dyn_tzinfo));
1053 lstrcpyW(dyn_tzinfo.TimeZoneKeyName, L"Altai Standard Time");
1054 SetLastError(0xdeadbeef);
1055 ret = pGetTimeZoneInformationForYear(2015, &dyn_tzinfo, &tzinfo);
1056 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
1057 broken_test = TRUE;
1058 ok(ret == TRUE || broken(broken_test) /* before 10 1809 */,
1059 "GetTimeZoneInformationForYear err %lu\n", GetLastError());
1060
1061 if (broken(broken_test))
1062 {
1063 win_skip("Old Windows version\n");
1064 return;
1065 }
1066
1067 for (i = 0; i < ARRAY_SIZE(test_data); i++)
1068 {
1069 memset(&dyn_tzinfo, 0xaa, sizeof(dyn_tzinfo));
1070 memset(&tzinfo, 0xbb, sizeof(tzinfo));
1071 lstrcpyW(dyn_tzinfo.TimeZoneKeyName, test_data[i].tzname);
1072 dyn_tzinfo.DynamicDaylightTimeDisabled = FALSE;
1073
1074 ret = pGetTimeZoneInformationForYear(test_data[i].year, &dyn_tzinfo, &tzinfo);
1075 ok(ret == TRUE, "GetTimeZoneInformationForYear failed, err %lu, for %s\n", GetLastError(), wine_dbgstr_w(test_data[i].tzname));
1076 if (!ret)
1077 continue;
1078 ok(tzinfo.Bias == test_data[i].bias, "Expected bias %ld, got %ld, for %s\n",
1079 test_data[i].bias, tzinfo.Bias, wine_dbgstr_w(test_data[i].tzname));
1080 ok(tzinfo.StandardDate.wMonth == test_data[i].std_month, "Expected standard month %d, got %d, for %s\n",
1081 test_data[i].std_month, tzinfo.StandardDate.wMonth, wine_dbgstr_w(test_data[i].tzname));
1082 std_day = day_of_month(&tzinfo.StandardDate, test_data[i].year);
1083 ok(std_day == test_data[i].std_day, "Expected standard day %d, got %d, for %s\n",
1084 test_data[i].std_day, std_day, wine_dbgstr_w(test_data[i].tzname));
1085 ok(tzinfo.StandardBias == test_data[i].std_bias, "Expected standard bias %ld, got %ld, for %s\n",
1086 test_data[i].std_bias, tzinfo.StandardBias, wine_dbgstr_w(test_data[i].tzname));
1087 ok(tzinfo.DaylightDate.wMonth == test_data[i].dlt_month, "Expected daylight month %d, got %d, for %s\n",
1088 test_data[i].dlt_month, tzinfo.DaylightDate.wMonth, wine_dbgstr_w(test_data[i].tzname));
1089 dlt_day = day_of_month(&tzinfo.DaylightDate, test_data[i].year);
1090 ok(dlt_day == test_data[i].dlt_day, "Expected daylight day %d, got %d, for %s\n",
1091 test_data[i].dlt_day, dlt_day, wine_dbgstr_w(test_data[i].tzname));
1092 ok(tzinfo.DaylightBias == test_data[i].dlt_bias, "Expected daylight bias %ld, got %ld, for %s\n",
1093 test_data[i].dlt_bias, tzinfo.DaylightBias, wine_dbgstr_w(test_data[i].tzname));
1094
1095 if (i > 0 && test_data[i-1].tzname == test_data[i].tzname)
1096 {
1097 ok(!lstrcmpW(tzinfo.StandardName, tzinfo2.StandardName),
1098 "Got differing StandardName values %s and %s\n",
1099 wine_dbgstr_w(tzinfo.StandardName), wine_dbgstr_w(tzinfo2.StandardName));
1100 ok(!lstrcmpW(tzinfo.DaylightName, tzinfo2.DaylightName),
1101 "Got differing DaylightName values %s and %s\n",
1102 wine_dbgstr_w(tzinfo.DaylightName), wine_dbgstr_w(tzinfo2.DaylightName));
1103 }
1104
1105 memcpy(&tzinfo2, &tzinfo, sizeof(tzinfo2));
1106 }
1107}
1108
1109static void test_GetTickCount(void)
1110{
1111 DWORD t1, t2, t3;
1112 int i = 0;
1113
1114 if (!pNtGetTickCount)
1115 {
1116 win_skip("NtGetTickCount not implemented\n");
1117 return;
1118 }
1119
1120 do
1121 {
1122 t1 = pNtGetTickCount();
1123 t2 = GetTickCount();
1124 t3 = pNtGetTickCount();
1125 } while(t3 < t1 && i++ < 1); /* allow for wrap, but only once */
1126
1127 ok(t1 <= t2, "out of order %ld %ld\n", t1, t2);
1128 ok(t2 <= t3, "out of order %ld %ld\n", t2, t3);
1129}
1130
1131BOOL (WINAPI *pQueryUnbiasedInterruptTime)(ULONGLONG *time);
1132BOOL (WINAPI *pRtlQueryUnbiasedInterruptTime)(ULONGLONG *time);
1133
1134static void test_QueryUnbiasedInterruptTime(void)
1135{
1136 ULONGLONG time;
1137 BOOL ret;
1138
1139 if (pQueryUnbiasedInterruptTime)
1140 {
1141 SetLastError( 0xdeadbeef );
1142 ret = pQueryUnbiasedInterruptTime( &time );
1143 ok( ret, "QueryUnbiasedInterruptTime failed err %lu\n", GetLastError() );
1144 SetLastError( 0xdeadbeef );
1145 ret = pQueryUnbiasedInterruptTime( NULL );
1146 ok( !ret, "QueryUnbiasedInterruptTime succeeded\n" );
1147 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() );
1148 }
1149 else win_skip( "QueryUnbiasedInterruptTime not supported\n" );
1150 if (pRtlQueryUnbiasedInterruptTime)
1151 {
1152 SetLastError( 0xdeadbeef );
1153 ret = pRtlQueryUnbiasedInterruptTime( &time );
1154 ok( ret, "RtlQueryUnbiasedInterruptTime failed err %lu\n", GetLastError() );
1155 SetLastError( 0xdeadbeef );
1156 ret = pRtlQueryUnbiasedInterruptTime( NULL );
1157 ok( !ret, "RtlQueryUnbiasedInterruptTime succeeded\n" );
1158 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() );
1159 }
1160 else win_skip( "RtlQueryUnbiasedInterruptTime not supported\n" );
1161}
1162
1163static void test_processor_idle_cycle_time(void)
1164{
1165#ifdef __REACTOS__
1166 skip("Cannot build test_processor_idle_cycle_time() until kernelbase is synced.\n");
1167#else
1168 unsigned int cpu_count = NtCurrentTeb()->Peb->NumberOfProcessors;
1169 ULONG64 buffer[64];
1170 ULONG size;
1171 DWORD err;
1172 BOOL bret;
1173
1174 SetLastError( 0xdeadbeef );
1175 size = 0;
1176 bret = QueryIdleProcessorCycleTime( &size, NULL );
1177 err = GetLastError();
1178 ok( bret == TRUE && err == 0xdeadbeef, "got %d, %ld.\n", bret, err );
1179 ok( size == cpu_count * sizeof(ULONG64), "got %lu.\n", size );
1180
1181 size = 4;
1182 memset( buffer, 0xcc, sizeof(buffer) );
1183 SetLastError( 0xdeadbeef );
1184 bret = QueryIdleProcessorCycleTime( &size, NULL );
1185 err = GetLastError();
1186 ok( bret == TRUE && err == 0xdeadbeef, "got %d, %ld.\n", bret, err );
1187 ok( size == 4, "got %lu.\n", size );
1188 ok( buffer[0] == 0xcccccccccccccccc, "got %#I64x.\n", buffer[0] );
1189
1190 size = sizeof(buffer);
1191 SetLastError( 0xdeadbeef );
1192 bret = QueryIdleProcessorCycleTime( &size, NULL );
1193 err = GetLastError();
1194 ok( bret == TRUE && err == 0xdeadbeef, "got %d, %ld.\n", bret, err );
1195 ok( size == sizeof(buffer), "got %lu.\n", size );
1196
1197 size = sizeof(buffer);
1198 SetLastError( 0xdeadbeef );
1199 bret = QueryIdleProcessorCycleTime( &size, buffer );
1200 err = GetLastError();
1201 ok( bret == TRUE && err == 0xdeadbeef, "got %d, %ld.\n", bret, err );
1202 ok( size == cpu_count * sizeof(ULONG64), "got %lu.\n", size );
1203
1204 SetLastError( 0xdeadbeef );
1205 size = 0;
1206 bret = QueryIdleProcessorCycleTimeEx( 0, &size, NULL );
1207 err = GetLastError();
1208 ok( bret == TRUE && err == 0xdeadbeef, "got %d, %ld.\n", bret, err );
1209 ok( size == cpu_count * sizeof(ULONG64), "got %lu.\n", size );
1210
1211 size = 4;
1212 SetLastError( 0xdeadbeef );
1213 bret = QueryIdleProcessorCycleTimeEx( 0, &size, NULL );
1214 err = GetLastError();
1215 ok( bret == TRUE && err == 0xdeadbeef, "got %d, %ld.\n", bret, err );
1216 ok( size == 4, "got %lu.\n", size );
1217
1218 size = sizeof(buffer);
1219 SetLastError( 0xdeadbeef );
1220 bret = QueryIdleProcessorCycleTimeEx( 0, &size, NULL );
1221 err = GetLastError();
1222 ok( bret == TRUE && err == 0xdeadbeef, "got %d, %ld.\n", bret, err );
1223 ok( size == sizeof(buffer), "got %lu.\n", size );
1224
1225 size = sizeof(buffer);
1226 SetLastError( 0xdeadbeef );
1227 bret = QueryIdleProcessorCycleTimeEx( 0, &size, buffer );
1228 err = GetLastError();
1229 ok( bret == TRUE && err == 0xdeadbeef, "got %d, %ld.\n", bret, err );
1230 ok( size == cpu_count * sizeof(ULONG64), "got %lu.\n", size );
1231#endif
1232}
1233
1234START_TEST(time)
1235{
1236 HMODULE hKernel = GetModuleHandleA("kernel32");
1237 HMODULE hntdll = GetModuleHandleA("ntdll");
1238 pTzSpecificLocalTimeToSystemTime = (void *)GetProcAddress(hKernel, "TzSpecificLocalTimeToSystemTime");
1239 pSystemTimeToTzSpecificLocalTime = (void *)GetProcAddress( hKernel, "SystemTimeToTzSpecificLocalTime");
1240 pGetSystemTimes = (void *)GetProcAddress( hKernel, "GetSystemTimes");
1241 pGetCalendarInfoA = (void *)GetProcAddress(hKernel, "GetCalendarInfoA");
1242 pGetCalendarInfoW = (void *)GetProcAddress(hKernel, "GetCalendarInfoW");
1243 pGetDynamicTimeZoneInformation = (void *)GetProcAddress(hKernel, "GetDynamicTimeZoneInformation");
1244 pGetSystemTimePreciseAsFileTime = (void *)GetProcAddress(hKernel, "GetSystemTimePreciseAsFileTime");
1245 pGetTimeZoneInformationForYear = (void *)GetProcAddress(hKernel, "GetTimeZoneInformationForYear");
1246 pQueryUnbiasedInterruptTime = (void *)GetProcAddress(hKernel, "QueryUnbiasedInterruptTime");
1247 pNtGetTickCount = (void *)GetProcAddress(hntdll, "NtGetTickCount");
1248 pRtlQueryUnbiasedInterruptTime = (void *)GetProcAddress(hntdll, "RtlQueryUnbiasedInterruptTime");
1249
1250 test_conversions();
1251 test_invalid_arg();
1252 test_GetTimeZoneInformation();
1253 test_FileTimeToSystemTime();
1254 test_FileTimeToLocalFileTime();
1255 test_TzSpecificLocalTimeToSystemTime();
1256 test_GetSystemTimes();
1257 test_FileTimeToDosDateTime();
1258 test_GetCalendarInfo();
1259 test_GetDynamicTimeZoneInformation();
1260 test_GetSystemTimeAsFileTime();
1261 test_GetSystemTimePreciseAsFileTime();
1262 test_GetTimeZoneInformationForYear();
1263 test_GetTickCount();
1264 test_QueryUnbiasedInterruptTime();
1265 test_processor_idle_cycle_time();
1266}