Fix gcc 4.0 warnings.
[wine] / dlls / ntdll / time.c
1 /*
2  * Nt time functions.
3  *
4  * RtlTimeToTimeFields, RtlTimeFieldsToTime and defines are taken from ReactOS and
5  * adapted to wine with special permissions of the author. This code is
6  * Copyright 2002 Rex Jolliff (rex@lvcablemodem.com)
7  *
8  * Copyright 1999 Juergen Schmied
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  */
24
25 #include "config.h"
26 #include "wine/port.h"
27
28 #include <stdarg.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <limits.h>
32 #include <time.h>
33 #ifdef HAVE_SYS_TIME_H
34 # include <sys/time.h>
35 #endif
36 #ifdef HAVE_UNISTD_H
37 # include <unistd.h>
38 #endif
39
40 #define NONAMELESSUNION
41 #define NONAMELESSSTRUCT
42 #include "windef.h"
43 #include "winternl.h"
44 #include "wine/unicode.h"
45 #include "wine/debug.h"
46 #include "ntdll_misc.h"
47
48 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
49
50 static RTL_CRITICAL_SECTION TIME_GetBias_section;
51 static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
52 {
53     0, 0, &TIME_GetBias_section,
54     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
55       0, 0, { 0, (DWORD)(__FILE__ ": TIME_GetBias_section") }
56 };
57 static RTL_CRITICAL_SECTION TIME_GetBias_section = { &critsect_debug, -1, 0, 0, 0, 0 };
58
59 /* TimeZone registry key values */
60 static const WCHAR TZInformationKeyW[] = { 'M','a','c','h','i','n','e','\\',
61  'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
62  'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','T','i','m','e','z',
63  'o','n','e','I','n','f','o','r','m','a','t','i','o','n', 0};
64 static const WCHAR TZStandardStartW[] = {
65   'S','t','a','n','d','a','r','d','s','t','a','r','t', 0};
66 static const WCHAR TZDaylightStartW[] = {
67   'D','a','y','l','i','g','h','t','s','t','a','r','t', 0};
68 static const WCHAR TZDaylightBiasW[] = {
69     'D','a','y','l','i','g','h','t','B','i','a','s', 0};
70 static const WCHAR TZStandardBiasW[] = {
71     'S','t','a','n','d','a','r','d','B','i','a','s', 0};
72 static const WCHAR TZBiasW[] = {'B','i','a','s', 0};
73 static const WCHAR TZDaylightNameW[] = {
74     'D','a','y','l','i','g','h','t','N','a','m','e', 0};
75 static const WCHAR TZStandardNameW[] = {
76     'S','t','a','n','d','a','r','d','N','a','m','e', 0};
77
78
79 #define SETTIME_MAX_ADJUST 120
80
81 /* This structure is used to store strings that represent all of the time zones
82  * in the world. (This is used to help GetTimeZoneInformation)
83  */
84 struct tagTZ_INFO
85 {
86     const char *psTZFromUnix;
87     WCHAR psTZWindows[32];
88     int bias;
89     int dst;
90 };
91
92 static const struct tagTZ_INFO TZ_INFO[] =
93 {
94    {"MHT",
95     {'D','a','t','e','l','i','n','e',' ','S','t','a','n','d','a','r','d',' ',
96      'T','i','m','e','\0'}, -720, 0},
97    {"SST",
98     {'S','a','m','o','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m',
99      'e','\0'}, 660, 0},
100    {"HST",
101     {'H','a','w','a','i','i','a','n',' ','S','t','a','n','d','a','r','d',' ',
102      'T','i','m','e','\0'}, 600, 0},
103    {"AKDT",
104     {'A','l','a','s','k','a','n',' ','S','t','a','n','d','a','r','d',' ','T',
105      'i','m','e','\0'}, 480, 1},
106    {"PST",
107     {'P','a','c','i','f','i','c',' ','S','t','a','n','d','a','r','d',' ','T',
108      'i','m','e','\0'}, 480, 0},
109    {"PDT",
110     {'P','a','c','i','f','i','c',' ','S','t','a','n','d','a','r','d',' ','T',
111      'i','m','e','\0'}, 420, 1},
112    {"MST",
113     {'U','S',' ','M','o','u','n','t','a','i','n',' ','S','t','a','n','d','a',
114      'r','d',' ','T','i','m','e','\0'}, 420, 0},
115    {"MDT",
116     {'M','o','u','n','t','a','i','n',' ','S','t','a','n','d','a','r','d',' ',
117      'T','i','m','e','\0'}, 360, 1},
118    {"CST",
119     {'C','e','n','t','r','a','l',' ','A','m','e','r','i','c','a',' ','S','t',
120      'a','n','d','a','r','d',' ','T','i','m','e','\0'}, 360, 0},
121    {"CDT",
122     {'C','e','n','t','r','a','l',' ','S','t','a','n','d','a','r','d',' ','T',
123      'i','m','e','\0'}, 300, 1},
124    {"COT",
125     {'S','A',' ','P','a','c','i','f','i','c',' ','S','t','a','n','d','a','r',
126      'd',' ','T','i','m','e','\0'}, 300, 0},
127    {"EDT",
128     {'E','a','s','t','e','r','n',' ','S','t','a','n','d','a','r','d',' ','T',
129      'i','m','e','\0'}, 240, 1},
130    {"EST",
131     {'U','S',' ','E','a','s','t','e','r','n',' ','S','t','a','n','d','a','r',
132      'd',' ','T','i','m','e','\0'}, 300, 0},
133    {"ECT",
134     {'E','a','s','t','e','r','n',' ','C','e','n','t','r','a','l',' ','S','t','a','n','d','a','r',
135      'd',' ','T','i','m','e','\0'}, 300, 0},
136    {"ADT",
137     {'A','t','l','a','n','t','i','c',' ','S','t','a','n','d','a','r','d',' ',
138      'T','i','m','e','\0'}, 180, 1},
139    {"VET",
140     {'S','A',' ','W','e','s','t','e','r','n',' ','S','t','a','n','d','a','r',
141      'd',' ','T','i','m','e','\0'}, 240, 0},
142    {"CLT",
143     {'P','a','c','i','f','i','c',' ','S','A',' ','S','t','a','n','d','a','r',
144      'd',' ','T','i','m','e','\0'}, 240, 0},
145    {"NDT",
146     {'N','e','w','f','o','u','n','d','l','a','n','d',' ','S','t','a','n','d',
147      'a','r','d',' ','T','i','m','e','\0'}, 150, 1},
148    {"BRT",
149     {'B','r','a','z','i','l','i','a','n',' ','S','t','a','n','d','a','r','d',
150      ' ','T','i','m','e','\0'}, 180, 0},
151    {"BRST",
152     {'B','r','a','z','i','l','i','a','n',' ','S','u','m','m','e','r',
153      ' ','T','i','m','e','\0'}, 120, 1},
154    {"ART",
155     {'S','A',' ','E','a','s','t','e','r','n',' ','S','t','a','n','d','a','r',
156      'd',' ','T','i','m','e','\0'}, 180, 0},
157    {"WGST",
158     {'G','r','e','e','n','l','a','n','d',' ','S','t','a','n','d','a','r','d',
159      ' ','T','i','m','e','\0'}, 120, 1},
160    {"GST",
161     {'M','i','d','-','A','t','l','a','n','t','i','c',' ','S','t','a','n','d',
162      'a','r','d',' ','T','i','m','e','\0'}, 120, 0},
163    {"AZOST",
164     {'A','z','o','r','e','s',' ','S','t','a','n','d','a','r','d',' ','T','i',
165      'm','e','\0'}, 0, 1},
166    {"CVT",
167     {'C','a','p','e',' ','V','e','r','d','e',' ','S','t','a','n','d','a','r',
168      'd',' ','T','i','m','e','\0'}, 60, 0},
169    {"WEST",
170     {'W','e','s','t','e','r','n',' ','E','u','r','o','p','e','a','n',' ','S','u','m','m','e','r',' ','T','i','m','e','\0'}, -60, 1},
171    {"WET",
172     {'G','r','e','e','n','w','i','c','h',' ','S','t','a','n','d','a','r','d',
173      ' ','T','i','m','e','\0'}, 0, 0},
174    {"BST",
175     {'G','M','T',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
176     -60, 1},
177    {"IST",
178     {'I','r','i','s','h',' ','S','u','m','m','e','r',' ','T','i','m','e','\0'},
179     -60, 1},
180    {"GMT",
181     {'G','M','T',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
182     0, 0},
183    {"UTC",
184     {'G','M','T',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
185     0, 0},
186    {"CET",
187     {'C','e','n','t','r','a','l',' ','E','u','r','o','p','e','a','n',' ',
188      'T','i','m','e','\0'}, -60, 0},
189    {"CEST",
190     {'C','e','n','t','r','a','l',' ','E','u','r','o','p','e',' ','S','t','a',
191      'n','d','a','r','d',' ','T','i','m','e','\0'}, -120, 1},
192    {"MET",
193     {'C','e','n','t','r','a','l',' ','E','u','r','o','p','e',' ','S','t','a',
194      'n','d','a','r','d',' ','T','i','m','e','\0'}, -60, 0},
195    {"MEST",
196     {'C','e','n','t','r','a','l',' ','E','u','r','o','p','e',' ','D','a','y',
197      'l','i','g','h','t',' ','T','i','m','e','\0'}, -120, 1},
198    {"WAT",
199     {'W','.',' ','C','e','n','t','r','a','l',' ','A','f','r','i','c','a',' ',
200      'S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, -60, 0},
201    {"EEST",
202     {'E','.',' ','E','u','r','o','p','e',' ','S','t','a','n','d','a','r','d',
203      ' ','T','i','m','e','\0'}, -180, 1},
204    {"EET",
205     {'E','g','y','p','t',' ','S','t','a','n','d','a','r','d',' ','T','i','m',
206      'e','\0'}, -120, 0},
207    {"CAT",
208     {'C','e','n','t','r','a','l',' ','A','f','r','i','c','a','n',' '
209     ,'T','i','m','e','\0'}, -120, 0},
210    {"SAST",
211     {'S','o','u','t','h',' ','A','f','r','i','c','a',' ','S','t','a','n','d',
212      'a','r','d',' ','T','i','m','e','\0'}, -120, 0},
213    {"IST",
214     {'I','s','r','a','e','l',' ','S','t','a','n','d','a','r','d',' ','T','i',
215      'm','e','\0'}, -120, 0},
216    {"MSK",
217     {'R','u','s','s','i','a','n',' ','S','t','a','n','d','a','r','d',' ','T',
218      'i','m','e','\0'}, -180, 0},
219    {"ADT",
220     {'A','r','a','b','i','c',' ','S','t','a','n','d','a','r','d',' ','T','i',
221      'm','e','\0'}, -240, 1},
222    {"AST",
223     {'A','r','a','b',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e',
224      '\0'}, -180, 0},
225    {"MSD",
226     {'R','u','s','s','i','a','n',' ','S','t','a','n','d','a','r','d',' ','T',
227      'i','m','e','\0'}, -240, 1},
228    {"EAT",
229     {'E','.',' ','A','f','r','i','c','a',' ','S','t','a','n','d','a','r','d',
230      ' ','T','i','m','e','\0'}, -180, 0},
231    {"IRST",
232     {'I','r','a','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e',
233      '\0'}, -270, 1},
234    {"GST",
235     {'A','r','a','b','i','a','n',' ','S','t','a','n','d','a','r','d',' ','T',
236      'i','m','e','\0'}, -240, 0},
237    {"AZST",
238     {'C','a','u','c','a','s','u','s',' ','S','t','a','n','d','a','r','d',' ',
239      'T','i','m','e','\0'}, -300, 1},
240    {"AFT",
241     {'A','f','g','h','a','n','i','s','t','a','n',' ','S','t','a','n','d','a',
242      'r','d',' ','T','i','m','e','\0'}, -270, 0},
243    {"SAMT",
244     {'S','a','m','a','r','a',' ','S','t','a','n','d','a','r','d',' ','T','i',
245      'm','e','\0'}, -270, 1},
246    {"YEKST",
247     {'E','k','a','t','e','r','i','n','b','u','r','g',' ','S','t','a','n','d',
248      'a','r','d',' ','T','i','m','e','\0'}, -360, 1},
249    {"PKT",
250     {'W','e','s','t',' ','A','s','i','a',' ','S','t','a','n','d','a','r','d',
251      ' ','T','i','m','e','\0'}, -300, 0},
252    {"IST",
253     {'I','n','d','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m',
254      'e','\0'}, -330, 0},
255    {"NPT",
256     {'N','e','p','a','l',' ','S','t','a','n','d','a','r','d',' ','T','i','m',
257      'e','\0'}, -345, 0},
258    {"ALMST",
259     {'N','.',' ','C','e','n','t','r','a','l',' ','A','s','i','a',' ','S','t',
260      'a','n','d','a','r','d',' ','T','i','m','e','\0'}, -420, 1},
261    {"BDT",
262     {'C','e','n','t','r','a','l',' ','A','s','i','a',' ','S','t','a','n','d',
263      'a','r','d',' ','T','i','m','e','\0'}, -360, 0},
264    {"LKT",
265     {'S','r','i',' ','L','a','n','k','a',' ','S','t','a','n','d','a','r','d',
266      ' ','T','i','m','e','\0'}, -360, 0},
267    {"MMT",
268     {'M','y','a','n','m','a','r',' ','S','t','a','n','d','a','r','d',' ','T',
269      'i','m','e','\0'}, -390, 0},
270    {"ICT",
271     {'S','E',' ','A','s','i','a',' ','S','t','a','n','d','a','r','d',' ','T',
272      'i','m','e','\0'}, -420, 0},
273    {"KRAST",
274     {'N','o','r','t','h',' ','A','s','i','a',' ','S','t','a','n','d','a','r',
275      'd',' ','T','i','m','e','\0'}, -480, 1},
276    {"CST",
277     {'C','h','i','n','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m',
278      'e','\0'}, -480, 0},
279    {"IRKST",
280     {'N','o','r','t','h',' ','A','s','i','a',' ','E','a','s','t',' ','S','t',
281      'a','n','d','a','r','d',' ','T','i','m','e','\0'}, -540, 1},
282    {"SGT",
283     {'M','a','l','a','y',' ','P','e','n','i','n','s','u','l','a',' ','S','t',
284      'a','n','d','a','r','d',' ','T','i','m','e','\0'}, -480, 0},
285    {"WST",
286     {'W','.',' ','A','u','s','t','r','a','l','i','a',' ','S','t','a','n','d',
287      'a','r','d',' ','T','i','m','e','\0'}, -480, 0},
288    {"JST",
289     {'T','o','k','y','o',' ','S','t','a','n','d','a','r','d',' ','T','i','m',
290      'e','\0'}, -540, 0},
291    {"KST",
292     {'K','o','r','e','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m',
293      'e','\0'}, -540, 0},
294    {"YAKST",
295     {'Y','a','k','u','t','s','k',' ','S','t','a','n','d','a','r','d',' ','T',
296      'i','m','e','\0'}, -600, 1},
297    {"CST",
298     {'C','e','n','.',' ','A','u','s','t','r','a','l','i','a',' ','S','t','a',
299      'n','d','a','r','d',' ','T','i','m','e','\0'}, -570, 0},
300    {"EST",
301     {'E','.',' ','A','u','s','t','r','a','l','i','a',' ','S','t','a','n','d',
302      'a','r','d',' ','T','i','m','e','\0'}, -600, 0},
303    {"EST",
304     {'E','.',' ','A','u','s','t','r','a','l','i','a',' ','S','t','a','n','d',
305      'a','r','d',' ','T','i','m','e','\0'}, -660, 1},
306    {"GST",
307     {'W','e','s','t',' ','P','a','c','i','f','i','c',' ','S','t','a','n','d',
308      'a','r','d',' ','T','i','m','e','\0'}, -600, 0},
309    {"VLAST",
310     {'V','l','a','d','i','v','o','s','t','o','k',' ','S','t','a','n','d','a',
311      'r','d',' ','T','i','m','e','\0'}, -660, 1},
312    {"MAGST",
313     {'C','e','n','t','r','a','l',' ','P','a','c','i','f','i','c',' ','S','t',
314      'a','n','d','a','r','d',' ','T','i','m','e','\0'}, -720, 1},
315    {"NZST",
316     {'N','e','w',' ','Z','e','a','l','a','n','d',' ','S','t','a','n','d','a',
317      'r','d',' ','T','i','m','e','\0'}, -720, 0},
318    {"NZDT",
319     {'N','e','w',' ','Z','e','a','l','a','n','d',' ','D','a','y','l','i','g',
320      'h','t',' ','T','i','m','e','\0'}, -780, 1},
321    {"FJT",
322     {'F','i','j','i',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e',
323      '\0'}, -720, 0},
324    {"TOT",
325     {'T','o','n','g','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m',
326      'e','\0'}, -780, 0},
327    {"NOVT",
328     {'N','o','v','o','s','i','b','i','r','s','k',' ','S','t','a','n','d','a',
329      'r','d',' ','T','i','m','e','\0'}, -360, 1},
330    {"ANAT",
331     {'A','n','a','d','y','r',' ','S','t','a','n','d','a','r','d',' ','T','i',
332      'm','e','\0'}, -720, 1},
333    {"HKT",
334     {'H','o','n','g',' ','K','o','n','g',' ','S','t','a','n','d','a','r','d',
335      ' ','T','i','m','e','\0'}, -480, 0},
336    {"UYT",
337     {'U','r','u','g','u','a','y','a','n',' ','T','i','m','e','\0'}, 180, 0}
338 };
339
340 #define TICKSPERSEC        10000000
341 #define TICKSPERMSEC       10000
342 #define SECSPERDAY         86400
343 #define SECSPERHOUR        3600
344 #define SECSPERMIN         60
345 #define MINSPERHOUR        60
346 #define HOURSPERDAY        24
347 #define EPOCHWEEKDAY       1  /* Jan 1, 1601 was Monday */
348 #define DAYSPERWEEK        7
349 #define EPOCHYEAR          1601
350 #define DAYSPERNORMALYEAR  365
351 #define DAYSPERLEAPYEAR    366
352 #define MONSPERYEAR        12
353 #define DAYSPERQUADRICENTENNIUM (365 * 400 + 97)
354 #define DAYSPERNORMALCENTURY (365 * 100 + 24)
355 #define DAYSPERNORMALQUADRENNIUM (365 * 4 + 1)
356
357 /* 1601 to 1970 is 369 years plus 89 leap days */
358 #define SECS_1601_TO_1970  ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
359 #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
360 /* 1601 to 1980 is 379 years plus 91 leap days */
361 #define SECS_1601_TO_1980  ((379 * 365 + 91) * (ULONGLONG)SECSPERDAY)
362 #define TICKS_1601_TO_1980 (SECS_1601_TO_1980 * TICKSPERSEC)
363 /* max ticks that can be represented as Unix time */
364 #define TICKS_1601_TO_UNIX_MAX ((SECS_1601_TO_1970 + INT_MAX) * TICKSPERSEC)
365
366
367 static const int MonthLengths[2][MONSPERYEAR] =
368 {
369         { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
370         { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
371 };
372
373 static inline int IsLeapYear(int Year)
374 {
375         return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0;
376 }
377
378 /***********************************************************************
379  *              NTDLL_get_server_timeout
380  *
381  * Convert a NTDLL timeout into a timeval struct to send to the server.
382  */
383 void NTDLL_get_server_timeout( abs_time_t *when, const LARGE_INTEGER *timeout )
384 {
385     UINT remainder;
386
387     if (!timeout)  /* infinite timeout */
388     {
389         when->sec = when->usec = 0;
390     }
391     else if (timeout->QuadPart <= 0)  /* relative timeout */
392     {
393         struct timeval tv;
394
395         if (-timeout->QuadPart > (LONGLONG)INT_MAX * TICKSPERSEC)
396             when->sec = when->usec = INT_MAX;
397         else
398         {
399             ULONG sec = RtlEnlargedUnsignedDivide( -timeout->QuadPart, TICKSPERSEC, &remainder );
400             gettimeofday( &tv, 0 );
401             when->sec = tv.tv_sec + sec;
402             if ((when->usec = tv.tv_usec + (remainder / 10)) >= 1000000)
403             {
404                 when->usec -= 1000000;
405                 when->sec++;
406             }
407             if (when->sec < tv.tv_sec)  /* overflow */
408                 when->sec = when->usec = INT_MAX;
409         }
410     }
411     else  /* absolute time */
412     {
413         if (timeout->QuadPart < TICKS_1601_TO_1970)
414             when->sec = when->usec = 0;
415         else if (timeout->QuadPart > TICKS_1601_TO_UNIX_MAX)
416             when->sec = when->usec = INT_MAX;
417         else
418         {
419             when->sec = RtlEnlargedUnsignedDivide( timeout->QuadPart - TICKS_1601_TO_1970,
420                                                    TICKSPERSEC, &remainder );
421             when->usec = remainder / 10;
422         }
423     }
424 }
425
426
427 /***********************************************************************
428  *              NTDLL_from_server_timeout
429  *
430  * Convert a timeval struct from the server into an NTDLL timeout.
431  */
432 void NTDLL_from_server_timeout( LARGE_INTEGER *timeout, const abs_time_t *when )
433 {
434     timeout->QuadPart = when->sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
435     timeout->QuadPart += when->usec * 10;
436 }
437
438
439 /******************************************************************************
440  *       RtlTimeToTimeFields [NTDLL.@]
441  *
442  * Convert a time into a TIME_FIELDS structure.
443  *
444  * PARAMS
445  *   liTime     [I] Time to convert.
446  *   TimeFields [O] Destination for the converted time.
447  *
448  * RETURNS
449  *   Nothing.
450  */
451 VOID WINAPI RtlTimeToTimeFields(
452         const LARGE_INTEGER *liTime,
453         PTIME_FIELDS TimeFields)
454 {
455         int SecondsInDay;
456         long int cleaps, years, yearday, months;
457         long int Days;
458         LONGLONG Time;
459
460         /* Extract millisecond from time and convert time into seconds */
461         TimeFields->Milliseconds =
462             (CSHORT) (( liTime->QuadPart % TICKSPERSEC) / TICKSPERMSEC);
463         Time = liTime->QuadPart / TICKSPERSEC;
464
465         /* The native version of RtlTimeToTimeFields does not take leap seconds
466          * into account */
467
468         /* Split the time into days and seconds within the day */
469         Days = Time / SECSPERDAY;
470         SecondsInDay = Time % SECSPERDAY;
471
472         /* compute time of day */
473         TimeFields->Hour = (CSHORT) (SecondsInDay / SECSPERHOUR);
474         SecondsInDay = SecondsInDay % SECSPERHOUR;
475         TimeFields->Minute = (CSHORT) (SecondsInDay / SECSPERMIN);
476         TimeFields->Second = (CSHORT) (SecondsInDay % SECSPERMIN);
477
478         /* compute day of week */
479         TimeFields->Weekday = (CSHORT) ((EPOCHWEEKDAY + Days) % DAYSPERWEEK);
480
481         /* compute year, month and day of month. */
482         cleaps=( 3 * ((4 * Days + 1227) / DAYSPERQUADRICENTENNIUM) + 3 ) / 4;
483         Days += 28188 + cleaps;
484         years = (20 * Days - 2442) / (5 * DAYSPERNORMALQUADRENNIUM);
485         yearday = Days - (years * DAYSPERNORMALQUADRENNIUM)/4;
486         months = (64 * yearday) / 1959;
487         /* the result is based on a year starting on March.
488          * To convert take 12 from Januari and Februari and
489          * increase the year by one. */
490         if( months < 14 ) {
491             TimeFields->Month = months - 1;
492             TimeFields->Year = years + 1524;
493         } else {
494             TimeFields->Month = months - 13;
495             TimeFields->Year = years + 1525;
496         }
497         /* calculation of day of month is based on the wonderful
498          * sequence of INT( n * 30.6): it reproduces the 
499          * 31-30-31-30-31-31 month lengths exactly for small n's */
500         TimeFields->Day = yearday - (1959 * months) / 64 ;
501         return;
502 }
503
504 /******************************************************************************
505  *       RtlTimeFieldsToTime [NTDLL.@]
506  *
507  * Convert a TIME_FIELDS structure into a time.
508  *
509  * PARAMS
510  *   ftTimeFields [I] TIME_FIELDS structure to convert.
511  *   Time         [O] Destination for the converted time.
512  *
513  * RETURNS
514  *   Success: TRUE.
515  *   Failure: FALSE.
516  */
517 BOOLEAN WINAPI RtlTimeFieldsToTime(
518         PTIME_FIELDS tfTimeFields,
519         PLARGE_INTEGER Time)
520 {
521         int month, year, cleaps, day;
522
523         /* FIXME: normalize the TIME_FIELDS structure here */
524         /* No, native just returns 0 (error) if the fields are not */
525         if( tfTimeFields->Milliseconds< 0 || tfTimeFields->Milliseconds > 999 ||
526                 tfTimeFields->Second < 0 || tfTimeFields->Second > 59 ||
527                 tfTimeFields->Minute < 0 || tfTimeFields->Minute > 59 ||
528                 tfTimeFields->Hour < 0 || tfTimeFields->Hour > 23 ||
529                 tfTimeFields->Month < 1 || tfTimeFields->Month > 12 ||
530                 tfTimeFields->Day < 1 ||
531                 tfTimeFields->Day > MonthLengths
532                     [ tfTimeFields->Month ==2 || IsLeapYear(tfTimeFields->Year)]
533                     [ tfTimeFields->Month - 1] ||
534                 tfTimeFields->Year < 1601 )
535             return FALSE;
536
537         /* now calculate a day count from the date
538          * First start counting years from March. This way the leap days
539          * are added at the end of the year, not somewhere in the middle.
540          * Formula's become so much less complicate that way.
541          * To convert: add 12 to the month numbers of Jan and Feb, and 
542          * take 1 from the year */
543         if(tfTimeFields->Month < 3) {
544             month = tfTimeFields->Month + 13;
545             year = tfTimeFields->Year - 1;
546         } else {
547             month = tfTimeFields->Month + 1;
548             year = tfTimeFields->Year;
549         }
550         cleaps = (3 * (year / 100) + 3) / 4;   /* nr of "century leap years"*/
551         day =  (36525 * year) / 100 - cleaps + /* year * dayperyr, corrected */
552                  (1959 * month) / 64 +         /* months * daypermonth */
553                  tfTimeFields->Day -          /* day of the month */
554                  584817 ;                      /* zero that on 1601-01-01 */
555         /* done */
556         
557         Time->QuadPart = (((((LONGLONG) day * HOURSPERDAY +
558             tfTimeFields->Hour) * MINSPERHOUR +
559             tfTimeFields->Minute) * SECSPERMIN +
560             tfTimeFields->Second ) * 1000 +
561             tfTimeFields->Milliseconds ) * TICKSPERMSEC;
562
563         return TRUE;
564 }
565
566 /***********************************************************************
567  *       TIME_GetBias [internal]
568  *
569  * Helper function calculates delta local time from UTC. 
570  *
571  * PARAMS
572  *   utc [I] The current utc time.
573  *   pdaylight [I] Local daylight.
574  *
575  * RETURNS
576  *   The bias for the current timezone.
577  */
578 static int TIME_GetBias(time_t utc, int *pdaylight)
579 {
580     struct tm *ptm;
581     static time_t last_utc;
582     static int last_bias;
583     static int last_daylight;
584     int ret;
585
586     RtlEnterCriticalSection( &TIME_GetBias_section );
587     if(utc == last_utc)
588     {
589         *pdaylight = last_daylight;
590         ret = last_bias;        
591     } else
592     {
593         ptm = localtime(&utc);
594         *pdaylight = last_daylight =
595             ptm->tm_isdst; /* daylight for local timezone */
596         ptm = gmtime(&utc);
597         ptm->tm_isdst = *pdaylight; /* use local daylight, not that of Greenwich */
598         last_utc = utc;
599         ret = last_bias = (int)(utc-mktime(ptm));
600     }
601     RtlLeaveCriticalSection( &TIME_GetBias_section );
602     return ret;
603 }
604
605 /******************************************************************************
606  *        RtlLocalTimeToSystemTime [NTDLL.@]
607  *
608  * Convert a local time into system time.
609  *
610  * PARAMS
611  *   LocalTime  [I] Local time to convert.
612  *   SystemTime [O] Destination for the converted time.
613  *
614  * RETURNS
615  *   Success: STATUS_SUCCESS.
616  *   Failure: An NTSTATUS error code indicating the problem.
617  */
618 NTSTATUS WINAPI RtlLocalTimeToSystemTime( const LARGE_INTEGER *LocalTime,
619                                           PLARGE_INTEGER SystemTime)
620 {
621     time_t gmt;
622     int bias, daylight;
623
624     TRACE("(%p, %p)\n", LocalTime, SystemTime);
625
626     gmt = time(NULL);
627     bias = TIME_GetBias(gmt, &daylight);
628
629     SystemTime->QuadPart = LocalTime->QuadPart - bias * (LONGLONG)TICKSPERSEC;
630     return STATUS_SUCCESS;
631 }
632
633 /******************************************************************************
634  *       RtlSystemTimeToLocalTime [NTDLL.@]
635  *
636  * Convert a system time into a local time.
637  *
638  * PARAMS
639  *   SystemTime [I] System time to convert.
640  *   LocalTime  [O] Destination for the converted time.
641  *
642  * RETURNS
643  *   Success: STATUS_SUCCESS.
644  *   Failure: An NTSTATUS error code indicating the problem.
645  */
646 NTSTATUS WINAPI RtlSystemTimeToLocalTime( const LARGE_INTEGER *SystemTime,
647                                           PLARGE_INTEGER LocalTime )
648 {
649     time_t gmt;
650     int bias, daylight;
651
652     TRACE("(%p, %p)\n", SystemTime, LocalTime);
653
654     gmt = time(NULL);
655     bias = TIME_GetBias(gmt, &daylight);
656
657     LocalTime->QuadPart = SystemTime->QuadPart + bias * (LONGLONG)TICKSPERSEC;
658     return STATUS_SUCCESS;
659 }
660
661 /******************************************************************************
662  *       RtlTimeToSecondsSince1970 [NTDLL.@]
663  *
664  * Convert a time into a count of seconds since 1970.
665  *
666  * PARAMS
667  *   Time    [I] Time to convert.
668  *   Seconds [O] Destination for the converted time.
669  *
670  * RETURNS
671  *   Success: TRUE.
672  *   Failure: FALSE, if the resulting value will not fit in a DWORD.
673  */
674 BOOLEAN WINAPI RtlTimeToSecondsSince1970( const LARGE_INTEGER *Time, LPDWORD Seconds )
675 {
676     ULONGLONG tmp = ((ULONGLONG)Time->u.HighPart << 32) | Time->u.LowPart;
677     tmp = RtlLargeIntegerDivide( tmp, TICKSPERSEC, NULL );
678     tmp -= SECS_1601_TO_1970;
679     if (tmp > 0xffffffff) return FALSE;
680     *Seconds = (DWORD)tmp;
681     return TRUE;
682 }
683
684 /******************************************************************************
685  *       RtlTimeToSecondsSince1980 [NTDLL.@]
686  *
687  * Convert a time into a count of seconds since 1980.
688  *
689  * PARAMS
690  *   Time    [I] Time to convert.
691  *   Seconds [O] Destination for the converted time.
692  *
693  * RETURNS
694  *   Success: TRUE.
695  *   Failure: FALSE, if the resulting value will not fit in a DWORD.
696  */
697 BOOLEAN WINAPI RtlTimeToSecondsSince1980( const LARGE_INTEGER *Time, LPDWORD Seconds )
698 {
699     ULONGLONG tmp = ((ULONGLONG)Time->u.HighPart << 32) | Time->u.LowPart;
700     tmp = RtlLargeIntegerDivide( tmp, TICKSPERSEC, NULL );
701     tmp -= SECS_1601_TO_1980;
702     if (tmp > 0xffffffff) return FALSE;
703     *Seconds = (DWORD)tmp;
704     return TRUE;
705 }
706
707 /******************************************************************************
708  *       RtlSecondsSince1970ToTime [NTDLL.@]
709  *
710  * Convert a count of seconds since 1970 to a time.
711  *
712  * PARAMS
713  *   Seconds [I] Time to convert.
714  *   Time    [O] Destination for the converted time.
715  *
716  * RETURNS
717  *   Nothing.
718  */
719 void WINAPI RtlSecondsSince1970ToTime( DWORD Seconds, LARGE_INTEGER *Time )
720 {
721     ULONGLONG secs = Seconds * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
722     Time->u.LowPart  = (DWORD)secs;
723     Time->u.HighPart = (DWORD)(secs >> 32);
724 }
725
726 /******************************************************************************
727  *       RtlSecondsSince1980ToTime [NTDLL.@]
728  *
729  * Convert a count of seconds since 1980 to a time.
730  *
731  * PARAMS
732  *   Seconds [I] Time to convert.
733  *   Time    [O] Destination for the converted time.
734  *
735  * RETURNS
736  *   Nothing.
737  */
738 void WINAPI RtlSecondsSince1980ToTime( DWORD Seconds, LARGE_INTEGER *Time )
739 {
740     ULONGLONG secs = Seconds * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1980;
741     Time->u.LowPart  = (DWORD)secs;
742     Time->u.HighPart = (DWORD)(secs >> 32);
743 }
744
745 /******************************************************************************
746  *       RtlTimeToElapsedTimeFields [NTDLL.@]
747  *
748  * Convert a time to a count of elapsed seconds.
749  *
750  * PARAMS
751  *   Time       [I] Time to convert.
752  *   TimeFields [O] Destination for the converted time.
753  *
754  * RETURNS
755  *   Nothing.
756  */
757 void WINAPI RtlTimeToElapsedTimeFields( const LARGE_INTEGER *Time, PTIME_FIELDS TimeFields )
758 {
759     LONGLONG time;
760     INT rem;
761
762     time = RtlExtendedLargeIntegerDivide( Time->QuadPart, TICKSPERSEC, &rem );
763     TimeFields->Milliseconds = rem / TICKSPERMSEC;
764
765     /* time is now in seconds */
766     TimeFields->Year  = 0;
767     TimeFields->Month = 0;
768     TimeFields->Day   = RtlExtendedLargeIntegerDivide( time, SECSPERDAY, &rem );
769
770     /* rem is now the remaining seconds in the last day */
771     TimeFields->Second = rem % 60;
772     rem /= 60;
773     TimeFields->Minute = rem % 60;
774     TimeFields->Hour = rem / 60;
775 }
776
777 /***********************************************************************
778  *       NtQuerySystemTime [NTDLL.@]
779  *       ZwQuerySystemTime [NTDLL.@]
780  *
781  * Get the current system time.
782  *
783  * PARAMS
784  *   Time [O] Destination for the current system time.
785  *
786  * RETURNS
787  *   Success: STATUS_SUCCESS.
788  *   Failure: An NTSTATUS error code indicating the problem.
789  */
790 NTSTATUS WINAPI NtQuerySystemTime( PLARGE_INTEGER Time )
791 {
792     struct timeval now;
793
794     gettimeofday( &now, 0 );
795     Time->QuadPart = now.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
796     Time->QuadPart += now.tv_usec * 10;
797     return STATUS_SUCCESS;
798 }
799
800 /******************************************************************************
801  *  NtQueryPerformanceCounter   [NTDLL.@]
802  *
803  *  Note: Windows uses a timer clocked at a multiple of 1193182 Hz. There is a
804  *  good number of applications that crash when the returned frequency is either
805  *  lower or higher then what Windows gives. Also too high counter values are
806  *  reported to give problems.
807  */
808 NTSTATUS WINAPI NtQueryPerformanceCounter( PLARGE_INTEGER Counter, PLARGE_INTEGER Frequency )
809 {
810     struct timeval now;
811
812     if (!Counter) return STATUS_ACCESS_VIOLATION;
813     gettimeofday( &now, 0 );
814     /* convert a counter that increments at a rate of 1 MHz
815      * to one of 1.193182 MHz, with some care for arithmetic
816      * overflow ( will not overflow for 5000 years ) and
817      * good accuracy ( 105/88 = 1.19318182) */
818     Counter->QuadPart = (((now.tv_sec - server_start_time) * (ULONGLONG)1000000 + now.tv_usec) * 105) / 88;
819     if (Frequency) Frequency->QuadPart = 1193182;
820     return STATUS_SUCCESS;
821 }
822
823 /***********************************************************************
824  *        TIME_GetTZAsStr [internal]
825  *
826  * Helper function that returns the given timezone as a string.
827  *
828  * PARAMS
829  *   utc [I] The current utc time.
830  *   bias [I] The bias of the current timezone.
831  *   dst [I] ??
832  *
833  * RETURNS
834  *   Timezone name.
835  *
836  * NOTES:
837  *   This could be done with a hash table instead of merely iterating through a
838  *   table, however with the small amount of entries (60 or so) I didn't think
839  *   it was worth it.
840  */
841 static const WCHAR* TIME_GetTZAsStr (time_t utc, int bias, int dst)
842 {
843    char psTZName[7];
844    struct tm *ptm = localtime(&utc);
845    unsigned int i;
846
847    if (!strftime (psTZName, 7, "%Z", ptm))
848       return (NULL);
849
850    for (i=0; i<(sizeof(TZ_INFO) / sizeof(struct tagTZ_INFO)); i++)
851    {
852       if ( strcmp(TZ_INFO[i].psTZFromUnix, psTZName) == 0 &&
853            TZ_INFO[i].bias == bias &&
854            TZ_INFO[i].dst == dst
855          )
856             return TZ_INFO[i].psTZWindows;
857    }
858    FIXME("Can't match system time zone name \"%s\", bias=%d and dst=%d "
859          "to an entry in TZ_INFO. Please add appropriate entry to "
860          "TZ_INFO and submit as patch to wine-patches\n",psTZName,bias,dst);
861    return NULL;
862 }
863
864 /***  TIME_GetTimeZoneInfoFromReg: helper for GetTimeZoneInformation ***/
865
866
867 static int TIME_GetTimeZoneInfoFromReg(RTL_TIME_ZONE_INFORMATION *tzinfo)
868 {
869     BYTE buf[90];
870     KEY_VALUE_PARTIAL_INFORMATION * KpInfo =
871         (KEY_VALUE_PARTIAL_INFORMATION *) buf;
872     HANDLE hkey;
873     DWORD size;
874     OBJECT_ATTRIBUTES attr;
875     UNICODE_STRING nameW;
876
877     attr.Length = sizeof(attr);
878     attr.RootDirectory = 0;
879     attr.ObjectName = &nameW;
880     attr.Attributes = 0;
881     attr.SecurityDescriptor = NULL;
882     attr.SecurityQualityOfService = NULL;
883     RtlInitUnicodeString( &nameW, TZInformationKeyW);
884     if (!NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr )) {
885
886 #define GTZIFR_N( valkey, tofield) \
887         RtlInitUnicodeString( &nameW, valkey );\
888         if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, KpInfo,\
889                     sizeof(buf), &size )) { \
890             if( size >= (sizeof((tofield)) + \
891                     offsetof(KEY_VALUE_PARTIAL_INFORMATION,Data))); { \
892                 memcpy(&(tofield), \
893                         KpInfo->Data, sizeof(tofield)); \
894             } \
895         }
896 #define GTZIFR_S( valkey, tofield) \
897         RtlInitUnicodeString( &nameW, valkey );\
898         if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, KpInfo,\
899                     sizeof(buf), &size )) { \
900             size_t len = (strlenW( (WCHAR*)KpInfo->Data ) + 1) * sizeof(WCHAR); \
901             if (len > sizeof(tofield)) len = sizeof(tofield); \
902             memcpy( tofield, KpInfo->Data, len ); \
903             tofield[(len/sizeof(WCHAR))-1] = 0; \
904         }
905
906         GTZIFR_N( TZStandardStartW,  tzinfo->StandardDate)
907         GTZIFR_N( TZDaylightStartW,  tzinfo->DaylightDate)
908         GTZIFR_N( TZBiasW,          tzinfo->Bias)
909         GTZIFR_N( TZStandardBiasW,  tzinfo->StandardBias)
910         GTZIFR_N( TZDaylightBiasW,  tzinfo->DaylightBias)
911         GTZIFR_S( TZStandardNameW, tzinfo->StandardName)
912         GTZIFR_S( TZDaylightNameW, tzinfo->DaylightName)
913
914 #undef GTZIFR_N
915 #undef GTZIFR_S
916         NtClose( hkey );
917         return 1;
918     }
919     return 0;
920 }
921
922 /***********************************************************************
923  *      RtlQueryTimeZoneInformation [NTDLL.@]
924  *
925  * Get information about the current timezone.
926  *
927  * PARAMS
928  *   tzinfo [O] Destination for the retrieved timezone info.
929  *
930  * RETURNS
931  *   Success: STATUS_SUCCESS.
932  *   Failure: An NTSTATUS error code indicating the problem.
933  */
934 NTSTATUS WINAPI RtlQueryTimeZoneInformation(RTL_TIME_ZONE_INFORMATION *tzinfo)
935 {
936     time_t gmt;
937     int bias, daylight;
938     const WCHAR *psTZ;
939
940     memset(tzinfo, 0, sizeof(RTL_TIME_ZONE_INFORMATION));
941
942     if( !TIME_GetTimeZoneInfoFromReg(tzinfo)) {
943
944         gmt = time(NULL);
945         bias = TIME_GetBias(gmt, &daylight);
946
947         tzinfo->Bias = -bias / 60;
948         tzinfo->StandardBias = 0;
949         tzinfo->DaylightBias = -60;
950         tzinfo->StandardName[0]='\0';
951         tzinfo->DaylightName[0]='\0';
952         psTZ = TIME_GetTZAsStr (gmt, (-bias/60), daylight);
953         if (psTZ) strcpyW( tzinfo->StandardName, psTZ );
954         }
955     return STATUS_SUCCESS;
956 }
957
958 /***********************************************************************
959  *       RtlSetTimeZoneInformation [NTDLL.@]
960  *
961  * Set the current time zone information.
962  *
963  * PARAMS
964  *   tzinfo [I] Timezone information to set.
965  *
966  * RETURNS
967  *   Success: STATUS_SUCCESS.
968  *   Failure: An NTSTATUS error code indicating the problem.
969  *
970  * BUGS
971  *   Uses the obsolete unix timezone structure and tz_dsttime member.
972  */
973 NTSTATUS WINAPI RtlSetTimeZoneInformation( const RTL_TIME_ZONE_INFORMATION *tzinfo )
974 {
975 #ifdef HAVE_SETTIMEOFDAY
976     struct timezone tz;
977
978     tz.tz_minuteswest = tzinfo->Bias;
979 #ifdef DST_NONE
980     tz.tz_dsttime = DST_NONE;
981 #else
982     tz.tz_dsttime = 0;
983 #endif
984     if(!settimeofday(NULL, &tz))
985         return STATUS_SUCCESS;
986 #endif
987     return STATUS_PRIVILEGE_NOT_HELD;
988 }
989
990 /***********************************************************************
991  *        NtSetSystemTime [NTDLL.@]
992  *        ZwSetSystemTime [NTDLL.@]
993  *
994  * Set the system time.
995  *
996  * PARAMS
997  *   NewTime [I] The time to set.
998  *   OldTime [O] Optional destination for the previous system time.
999  *
1000  * RETURNS
1001  *   Success: STATUS_SUCCESS.
1002  *   Failure: An NTSTATUS error code indicating the problem.
1003  */
1004 NTSTATUS WINAPI NtSetSystemTime(const LARGE_INTEGER *NewTime, LARGE_INTEGER *OldTime)
1005 {
1006     TIME_FIELDS tf;
1007     struct timeval tv;
1008     struct timezone tz;
1009     struct tm t;
1010     time_t sec, oldsec;
1011     int dst, bias;
1012     int err;
1013
1014     /* Return the old time if necessary */
1015     if(OldTime)
1016         NtQuerySystemTime(OldTime);
1017
1018     RtlTimeToTimeFields(NewTime, &tf);
1019
1020     /* call gettimeofday to get the current timezone */
1021     gettimeofday(&tv, &tz);
1022     oldsec = tv.tv_sec;
1023     /* get delta local time from utc */
1024     bias = TIME_GetBias(oldsec, &dst);
1025
1026     /* get the number of seconds */
1027     t.tm_sec = tf.Second;
1028     t.tm_min = tf.Minute;
1029     t.tm_hour = tf.Hour;
1030     t.tm_mday = tf.Day;
1031     t.tm_mon = tf.Month - 1;
1032     t.tm_year = tf.Year - 1900;
1033     t.tm_isdst = dst;
1034     sec = mktime (&t);
1035     /* correct for timezone and daylight */
1036     sec += bias;
1037
1038     /* set the new time */
1039     tv.tv_sec = sec;
1040     tv.tv_usec = tf.Milliseconds * 1000;
1041
1042     /* error and sanity check*/
1043     if(sec == (time_t)-1 || abs((int)(sec-oldsec)) > SETTIME_MAX_ADJUST) {
1044         err = 2;
1045     } else {
1046 #ifdef HAVE_SETTIMEOFDAY
1047         err = settimeofday(&tv, NULL); /* 0 is OK, -1 is error */
1048         if(err == 0)
1049             return STATUS_SUCCESS;
1050 #else
1051         err = 1;
1052 #endif
1053     }
1054
1055     ERR("Cannot set time to %d/%d/%d %d:%d:%d Time adjustment %ld %s\n",
1056             tf.Year, tf.Month, tf.Day, tf.Hour, tf.Minute, tf.Second,
1057             (long)(sec-oldsec),
1058             err == -1 ? "No Permission"
1059                       : sec == (time_t)-1 ? "" : "is too large." );
1060
1061     if(err == 2)
1062         return STATUS_INVALID_PARAMETER;
1063     else if(err == -1)
1064         return STATUS_PRIVILEGE_NOT_HELD;
1065     else
1066         return STATUS_NOT_IMPLEMENTED;
1067 }