Added stub for RegisterServiceCtrlHandlerEx{A,W}.
[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, { (DWORD_PTR)(__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    {"MYT",
339     {'M','a','l','a','y','s','i','a','n',' ','T','i','m','e','\0'}, -480, 0},
340    {"PHT",
341     {'P','h','i','l','i','p','p','i','n','e',' ','T','i','m','e','\0'}, -480, 0},
342    {"NOVST",
343     {'N','o','v','o','s','i','b','i','r','s','k',' ','S','u','m','m','e','r',
344      ' ','T','i','m','e','\0'}, -480, 1}
345 };
346
347 #define TICKSPERSEC        10000000
348 #define TICKSPERMSEC       10000
349 #define SECSPERDAY         86400
350 #define SECSPERHOUR        3600
351 #define SECSPERMIN         60
352 #define MINSPERHOUR        60
353 #define HOURSPERDAY        24
354 #define EPOCHWEEKDAY       1  /* Jan 1, 1601 was Monday */
355 #define DAYSPERWEEK        7
356 #define EPOCHYEAR          1601
357 #define DAYSPERNORMALYEAR  365
358 #define DAYSPERLEAPYEAR    366
359 #define MONSPERYEAR        12
360 #define DAYSPERQUADRICENTENNIUM (365 * 400 + 97)
361 #define DAYSPERNORMALCENTURY (365 * 100 + 24)
362 #define DAYSPERNORMALQUADRENNIUM (365 * 4 + 1)
363
364 /* 1601 to 1970 is 369 years plus 89 leap days */
365 #define SECS_1601_TO_1970  ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
366 #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
367 /* 1601 to 1980 is 379 years plus 91 leap days */
368 #define SECS_1601_TO_1980  ((379 * 365 + 91) * (ULONGLONG)SECSPERDAY)
369 #define TICKS_1601_TO_1980 (SECS_1601_TO_1980 * TICKSPERSEC)
370 /* max ticks that can be represented as Unix time */
371 #define TICKS_1601_TO_UNIX_MAX ((SECS_1601_TO_1970 + INT_MAX) * TICKSPERSEC)
372
373
374 static const int MonthLengths[2][MONSPERYEAR] =
375 {
376         { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
377         { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
378 };
379
380 static inline int IsLeapYear(int Year)
381 {
382         return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0;
383 }
384
385 /***********************************************************************
386  *              NTDLL_get_server_timeout
387  *
388  * Convert a NTDLL timeout into a timeval struct to send to the server.
389  */
390 void NTDLL_get_server_timeout( abs_time_t *when, const LARGE_INTEGER *timeout )
391 {
392     UINT remainder;
393
394     if (!timeout)  /* infinite timeout */
395     {
396         when->sec = when->usec = 0;
397     }
398     else if (timeout->QuadPart <= 0)  /* relative timeout */
399     {
400         struct timeval tv;
401
402         if (-timeout->QuadPart > (LONGLONG)INT_MAX * TICKSPERSEC)
403             when->sec = when->usec = INT_MAX;
404         else
405         {
406             ULONG sec = RtlEnlargedUnsignedDivide( -timeout->QuadPart, TICKSPERSEC, &remainder );
407             gettimeofday( &tv, 0 );
408             when->sec = tv.tv_sec + sec;
409             if ((when->usec = tv.tv_usec + (remainder / 10)) >= 1000000)
410             {
411                 when->usec -= 1000000;
412                 when->sec++;
413             }
414             if (when->sec < tv.tv_sec)  /* overflow */
415                 when->sec = when->usec = INT_MAX;
416         }
417     }
418     else  /* absolute time */
419     {
420         if (timeout->QuadPart < TICKS_1601_TO_1970)
421             when->sec = when->usec = 0;
422         else if (timeout->QuadPart > TICKS_1601_TO_UNIX_MAX)
423             when->sec = when->usec = INT_MAX;
424         else
425         {
426             when->sec = RtlEnlargedUnsignedDivide( timeout->QuadPart - TICKS_1601_TO_1970,
427                                                    TICKSPERSEC, &remainder );
428             when->usec = remainder / 10;
429         }
430     }
431 }
432
433
434 /***********************************************************************
435  *              NTDLL_from_server_timeout
436  *
437  * Convert a timeval struct from the server into an NTDLL timeout.
438  */
439 void NTDLL_from_server_timeout( LARGE_INTEGER *timeout, const abs_time_t *when )
440 {
441     timeout->QuadPart = when->sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
442     timeout->QuadPart += when->usec * 10;
443 }
444
445
446 /******************************************************************************
447  *       RtlTimeToTimeFields [NTDLL.@]
448  *
449  * Convert a time into a TIME_FIELDS structure.
450  *
451  * PARAMS
452  *   liTime     [I] Time to convert.
453  *   TimeFields [O] Destination for the converted time.
454  *
455  * RETURNS
456  *   Nothing.
457  */
458 VOID WINAPI RtlTimeToTimeFields(
459         const LARGE_INTEGER *liTime,
460         PTIME_FIELDS TimeFields)
461 {
462         int SecondsInDay;
463         long int cleaps, years, yearday, months;
464         long int Days;
465         LONGLONG Time;
466
467         /* Extract millisecond from time and convert time into seconds */
468         TimeFields->Milliseconds =
469             (CSHORT) (( liTime->QuadPart % TICKSPERSEC) / TICKSPERMSEC);
470         Time = liTime->QuadPart / TICKSPERSEC;
471
472         /* The native version of RtlTimeToTimeFields does not take leap seconds
473          * into account */
474
475         /* Split the time into days and seconds within the day */
476         Days = Time / SECSPERDAY;
477         SecondsInDay = Time % SECSPERDAY;
478
479         /* compute time of day */
480         TimeFields->Hour = (CSHORT) (SecondsInDay / SECSPERHOUR);
481         SecondsInDay = SecondsInDay % SECSPERHOUR;
482         TimeFields->Minute = (CSHORT) (SecondsInDay / SECSPERMIN);
483         TimeFields->Second = (CSHORT) (SecondsInDay % SECSPERMIN);
484
485         /* compute day of week */
486         TimeFields->Weekday = (CSHORT) ((EPOCHWEEKDAY + Days) % DAYSPERWEEK);
487
488         /* compute year, month and day of month. */
489         cleaps=( 3 * ((4 * Days + 1227) / DAYSPERQUADRICENTENNIUM) + 3 ) / 4;
490         Days += 28188 + cleaps;
491         years = (20 * Days - 2442) / (5 * DAYSPERNORMALQUADRENNIUM);
492         yearday = Days - (years * DAYSPERNORMALQUADRENNIUM)/4;
493         months = (64 * yearday) / 1959;
494         /* the result is based on a year starting on March.
495          * To convert take 12 from Januari and Februari and
496          * increase the year by one. */
497         if( months < 14 ) {
498             TimeFields->Month = months - 1;
499             TimeFields->Year = years + 1524;
500         } else {
501             TimeFields->Month = months - 13;
502             TimeFields->Year = years + 1525;
503         }
504         /* calculation of day of month is based on the wonderful
505          * sequence of INT( n * 30.6): it reproduces the 
506          * 31-30-31-30-31-31 month lengths exactly for small n's */
507         TimeFields->Day = yearday - (1959 * months) / 64 ;
508         return;
509 }
510
511 /******************************************************************************
512  *       RtlTimeFieldsToTime [NTDLL.@]
513  *
514  * Convert a TIME_FIELDS structure into a time.
515  *
516  * PARAMS
517  *   ftTimeFields [I] TIME_FIELDS structure to convert.
518  *   Time         [O] Destination for the converted time.
519  *
520  * RETURNS
521  *   Success: TRUE.
522  *   Failure: FALSE.
523  */
524 BOOLEAN WINAPI RtlTimeFieldsToTime(
525         PTIME_FIELDS tfTimeFields,
526         PLARGE_INTEGER Time)
527 {
528         int month, year, cleaps, day;
529
530         /* FIXME: normalize the TIME_FIELDS structure here */
531         /* No, native just returns 0 (error) if the fields are not */
532         if( tfTimeFields->Milliseconds< 0 || tfTimeFields->Milliseconds > 999 ||
533                 tfTimeFields->Second < 0 || tfTimeFields->Second > 59 ||
534                 tfTimeFields->Minute < 0 || tfTimeFields->Minute > 59 ||
535                 tfTimeFields->Hour < 0 || tfTimeFields->Hour > 23 ||
536                 tfTimeFields->Month < 1 || tfTimeFields->Month > 12 ||
537                 tfTimeFields->Day < 1 ||
538                 tfTimeFields->Day > MonthLengths
539                     [ tfTimeFields->Month ==2 || IsLeapYear(tfTimeFields->Year)]
540                     [ tfTimeFields->Month - 1] ||
541                 tfTimeFields->Year < 1601 )
542             return FALSE;
543
544         /* now calculate a day count from the date
545          * First start counting years from March. This way the leap days
546          * are added at the end of the year, not somewhere in the middle.
547          * Formula's become so much less complicate that way.
548          * To convert: add 12 to the month numbers of Jan and Feb, and 
549          * take 1 from the year */
550         if(tfTimeFields->Month < 3) {
551             month = tfTimeFields->Month + 13;
552             year = tfTimeFields->Year - 1;
553         } else {
554             month = tfTimeFields->Month + 1;
555             year = tfTimeFields->Year;
556         }
557         cleaps = (3 * (year / 100) + 3) / 4;   /* nr of "century leap years"*/
558         day =  (36525 * year) / 100 - cleaps + /* year * dayperyr, corrected */
559                  (1959 * month) / 64 +         /* months * daypermonth */
560                  tfTimeFields->Day -          /* day of the month */
561                  584817 ;                      /* zero that on 1601-01-01 */
562         /* done */
563         
564         Time->QuadPart = (((((LONGLONG) day * HOURSPERDAY +
565             tfTimeFields->Hour) * MINSPERHOUR +
566             tfTimeFields->Minute) * SECSPERMIN +
567             tfTimeFields->Second ) * 1000 +
568             tfTimeFields->Milliseconds ) * TICKSPERMSEC;
569
570         return TRUE;
571 }
572
573 /***********************************************************************
574  *       TIME_GetBias [internal]
575  *
576  * Helper function calculates delta local time from UTC. 
577  *
578  * PARAMS
579  *   utc [I] The current utc time.
580  *   pdaylight [I] Local daylight.
581  *
582  * RETURNS
583  *   The bias for the current timezone.
584  */
585 static int TIME_GetBias(time_t utc, int *pdaylight)
586 {
587     struct tm *ptm;
588     static time_t last_utc;
589     static int last_bias;
590     static int last_daylight;
591     int ret;
592
593     RtlEnterCriticalSection( &TIME_GetBias_section );
594     if(utc == last_utc)
595     {
596         *pdaylight = last_daylight;
597         ret = last_bias;        
598     } else
599     {
600         ptm = localtime(&utc);
601         *pdaylight = last_daylight =
602             ptm->tm_isdst; /* daylight for local timezone */
603         ptm = gmtime(&utc);
604         ptm->tm_isdst = *pdaylight; /* use local daylight, not that of Greenwich */
605         last_utc = utc;
606         ret = last_bias = (int)(utc-mktime(ptm));
607     }
608     RtlLeaveCriticalSection( &TIME_GetBias_section );
609     return ret;
610 }
611
612 /******************************************************************************
613  *        RtlLocalTimeToSystemTime [NTDLL.@]
614  *
615  * Convert a local time into system time.
616  *
617  * PARAMS
618  *   LocalTime  [I] Local time to convert.
619  *   SystemTime [O] Destination for the converted time.
620  *
621  * RETURNS
622  *   Success: STATUS_SUCCESS.
623  *   Failure: An NTSTATUS error code indicating the problem.
624  */
625 NTSTATUS WINAPI RtlLocalTimeToSystemTime( const LARGE_INTEGER *LocalTime,
626                                           PLARGE_INTEGER SystemTime)
627 {
628     time_t gmt;
629     int bias, daylight;
630
631     TRACE("(%p, %p)\n", LocalTime, SystemTime);
632
633     gmt = time(NULL);
634     bias = TIME_GetBias(gmt, &daylight);
635
636     SystemTime->QuadPart = LocalTime->QuadPart - bias * (LONGLONG)TICKSPERSEC;
637     return STATUS_SUCCESS;
638 }
639
640 /******************************************************************************
641  *       RtlSystemTimeToLocalTime [NTDLL.@]
642  *
643  * Convert a system time into a local time.
644  *
645  * PARAMS
646  *   SystemTime [I] System time to convert.
647  *   LocalTime  [O] Destination for the converted time.
648  *
649  * RETURNS
650  *   Success: STATUS_SUCCESS.
651  *   Failure: An NTSTATUS error code indicating the problem.
652  */
653 NTSTATUS WINAPI RtlSystemTimeToLocalTime( const LARGE_INTEGER *SystemTime,
654                                           PLARGE_INTEGER LocalTime )
655 {
656     time_t gmt;
657     int bias, daylight;
658
659     TRACE("(%p, %p)\n", SystemTime, LocalTime);
660
661     gmt = time(NULL);
662     bias = TIME_GetBias(gmt, &daylight);
663
664     LocalTime->QuadPart = SystemTime->QuadPart + bias * (LONGLONG)TICKSPERSEC;
665     return STATUS_SUCCESS;
666 }
667
668 /******************************************************************************
669  *       RtlTimeToSecondsSince1970 [NTDLL.@]
670  *
671  * Convert a time into a count of seconds since 1970.
672  *
673  * PARAMS
674  *   Time    [I] Time to convert.
675  *   Seconds [O] Destination for the converted time.
676  *
677  * RETURNS
678  *   Success: TRUE.
679  *   Failure: FALSE, if the resulting value will not fit in a DWORD.
680  */
681 BOOLEAN WINAPI RtlTimeToSecondsSince1970( const LARGE_INTEGER *Time, LPDWORD Seconds )
682 {
683     ULONGLONG tmp = ((ULONGLONG)Time->u.HighPart << 32) | Time->u.LowPart;
684     tmp = RtlLargeIntegerDivide( tmp, TICKSPERSEC, NULL );
685     tmp -= SECS_1601_TO_1970;
686     if (tmp > 0xffffffff) return FALSE;
687     *Seconds = (DWORD)tmp;
688     return TRUE;
689 }
690
691 /******************************************************************************
692  *       RtlTimeToSecondsSince1980 [NTDLL.@]
693  *
694  * Convert a time into a count of seconds since 1980.
695  *
696  * PARAMS
697  *   Time    [I] Time to convert.
698  *   Seconds [O] Destination for the converted time.
699  *
700  * RETURNS
701  *   Success: TRUE.
702  *   Failure: FALSE, if the resulting value will not fit in a DWORD.
703  */
704 BOOLEAN WINAPI RtlTimeToSecondsSince1980( const LARGE_INTEGER *Time, LPDWORD Seconds )
705 {
706     ULONGLONG tmp = ((ULONGLONG)Time->u.HighPart << 32) | Time->u.LowPart;
707     tmp = RtlLargeIntegerDivide( tmp, TICKSPERSEC, NULL );
708     tmp -= SECS_1601_TO_1980;
709     if (tmp > 0xffffffff) return FALSE;
710     *Seconds = (DWORD)tmp;
711     return TRUE;
712 }
713
714 /******************************************************************************
715  *       RtlSecondsSince1970ToTime [NTDLL.@]
716  *
717  * Convert a count of seconds since 1970 to a time.
718  *
719  * PARAMS
720  *   Seconds [I] Time to convert.
721  *   Time    [O] Destination for the converted time.
722  *
723  * RETURNS
724  *   Nothing.
725  */
726 void WINAPI RtlSecondsSince1970ToTime( DWORD Seconds, LARGE_INTEGER *Time )
727 {
728     ULONGLONG secs = Seconds * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
729     Time->u.LowPart  = (DWORD)secs;
730     Time->u.HighPart = (DWORD)(secs >> 32);
731 }
732
733 /******************************************************************************
734  *       RtlSecondsSince1980ToTime [NTDLL.@]
735  *
736  * Convert a count of seconds since 1980 to a time.
737  *
738  * PARAMS
739  *   Seconds [I] Time to convert.
740  *   Time    [O] Destination for the converted time.
741  *
742  * RETURNS
743  *   Nothing.
744  */
745 void WINAPI RtlSecondsSince1980ToTime( DWORD Seconds, LARGE_INTEGER *Time )
746 {
747     ULONGLONG secs = Seconds * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1980;
748     Time->u.LowPart  = (DWORD)secs;
749     Time->u.HighPart = (DWORD)(secs >> 32);
750 }
751
752 /******************************************************************************
753  *       RtlTimeToElapsedTimeFields [NTDLL.@]
754  *
755  * Convert a time to a count of elapsed seconds.
756  *
757  * PARAMS
758  *   Time       [I] Time to convert.
759  *   TimeFields [O] Destination for the converted time.
760  *
761  * RETURNS
762  *   Nothing.
763  */
764 void WINAPI RtlTimeToElapsedTimeFields( const LARGE_INTEGER *Time, PTIME_FIELDS TimeFields )
765 {
766     LONGLONG time;
767     INT rem;
768
769     time = RtlExtendedLargeIntegerDivide( Time->QuadPart, TICKSPERSEC, &rem );
770     TimeFields->Milliseconds = rem / TICKSPERMSEC;
771
772     /* time is now in seconds */
773     TimeFields->Year  = 0;
774     TimeFields->Month = 0;
775     TimeFields->Day   = RtlExtendedLargeIntegerDivide( time, SECSPERDAY, &rem );
776
777     /* rem is now the remaining seconds in the last day */
778     TimeFields->Second = rem % 60;
779     rem /= 60;
780     TimeFields->Minute = rem % 60;
781     TimeFields->Hour = rem / 60;
782 }
783
784 /***********************************************************************
785  *       NtQuerySystemTime [NTDLL.@]
786  *       ZwQuerySystemTime [NTDLL.@]
787  *
788  * Get the current system time.
789  *
790  * PARAMS
791  *   Time [O] Destination for the current system time.
792  *
793  * RETURNS
794  *   Success: STATUS_SUCCESS.
795  *   Failure: An NTSTATUS error code indicating the problem.
796  */
797 NTSTATUS WINAPI NtQuerySystemTime( PLARGE_INTEGER Time )
798 {
799     struct timeval now;
800
801     gettimeofday( &now, 0 );
802     Time->QuadPart = now.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
803     Time->QuadPart += now.tv_usec * 10;
804     return STATUS_SUCCESS;
805 }
806
807 /******************************************************************************
808  *  NtQueryPerformanceCounter   [NTDLL.@]
809  *
810  *  Note: Windows uses a timer clocked at a multiple of 1193182 Hz. There is a
811  *  good number of applications that crash when the returned frequency is either
812  *  lower or higher then what Windows gives. Also too high counter values are
813  *  reported to give problems.
814  */
815 NTSTATUS WINAPI NtQueryPerformanceCounter( PLARGE_INTEGER Counter, PLARGE_INTEGER Frequency )
816 {
817     struct timeval now;
818
819     if (!Counter) return STATUS_ACCESS_VIOLATION;
820     gettimeofday( &now, 0 );
821     /* convert a counter that increments at a rate of 1 MHz
822      * to one of 1.193182 MHz, with some care for arithmetic
823      * overflow ( will not overflow for 5000 years ) and
824      * good accuracy ( 105/88 = 1.19318182) */
825     Counter->QuadPart = (((now.tv_sec - server_start_time) * (ULONGLONG)1000000 + now.tv_usec) * 105) / 88;
826     if (Frequency) Frequency->QuadPart = 1193182;
827     return STATUS_SUCCESS;
828 }
829
830 /***********************************************************************
831  *        TIME_GetTZAsStr [internal]
832  *
833  * Helper function that returns the given timezone as a string.
834  *
835  * PARAMS
836  *   utc [I] The current utc time.
837  *   bias [I] The bias of the current timezone.
838  *   dst [I] ??
839  *
840  * RETURNS
841  *   Timezone name.
842  *
843  * NOTES:
844  *   This could be done with a hash table instead of merely iterating through a
845  *   table, however with the small amount of entries (60 or so) I didn't think
846  *   it was worth it.
847  */
848 static const WCHAR* TIME_GetTZAsStr (time_t utc, int bias, int dst)
849 {
850    char psTZName[7];
851    struct tm *ptm = localtime(&utc);
852    unsigned int i;
853
854    if (!strftime (psTZName, 7, "%Z", ptm))
855       return (NULL);
856
857    for (i=0; i<(sizeof(TZ_INFO) / sizeof(struct tagTZ_INFO)); i++)
858    {
859       if ( strcmp(TZ_INFO[i].psTZFromUnix, psTZName) == 0 &&
860            TZ_INFO[i].bias == bias &&
861            TZ_INFO[i].dst == dst
862          )
863             return TZ_INFO[i].psTZWindows;
864    }
865    FIXME("Can't match system time zone name \"%s\", bias=%d and dst=%d "
866          "to an entry in TZ_INFO. Please add appropriate entry to "
867          "TZ_INFO and submit as patch to wine-patches\n",psTZName,bias,dst);
868    return NULL;
869 }
870
871 /***  TIME_GetTimeZoneInfoFromReg: helper for GetTimeZoneInformation ***/
872
873
874 static int TIME_GetTimeZoneInfoFromReg(RTL_TIME_ZONE_INFORMATION *tzinfo)
875 {
876     BYTE buf[90];
877     KEY_VALUE_PARTIAL_INFORMATION * KpInfo =
878         (KEY_VALUE_PARTIAL_INFORMATION *) buf;
879     HANDLE hkey;
880     DWORD size;
881     OBJECT_ATTRIBUTES attr;
882     UNICODE_STRING nameW;
883
884     attr.Length = sizeof(attr);
885     attr.RootDirectory = 0;
886     attr.ObjectName = &nameW;
887     attr.Attributes = 0;
888     attr.SecurityDescriptor = NULL;
889     attr.SecurityQualityOfService = NULL;
890     RtlInitUnicodeString( &nameW, TZInformationKeyW);
891     if (!NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr )) {
892
893 #define GTZIFR_N( valkey, tofield) \
894         RtlInitUnicodeString( &nameW, valkey );\
895         if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, KpInfo,\
896                     sizeof(buf), &size )) { \
897             if( size >= (sizeof((tofield)) + \
898                     offsetof(KEY_VALUE_PARTIAL_INFORMATION,Data))) { \
899                 memcpy(&(tofield), \
900                         KpInfo->Data, sizeof(tofield)); \
901             } \
902         }
903 #define GTZIFR_S( valkey, tofield) \
904         RtlInitUnicodeString( &nameW, valkey );\
905         if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, KpInfo,\
906                     sizeof(buf), &size )) { \
907             size_t len = (strlenW( (WCHAR*)KpInfo->Data ) + 1) * sizeof(WCHAR); \
908             if (len > sizeof(tofield)) len = sizeof(tofield); \
909             memcpy( tofield, KpInfo->Data, len ); \
910             tofield[(len/sizeof(WCHAR))-1] = 0; \
911         }
912
913         GTZIFR_N( TZStandardStartW,  tzinfo->StandardDate)
914         GTZIFR_N( TZDaylightStartW,  tzinfo->DaylightDate)
915         GTZIFR_N( TZBiasW,          tzinfo->Bias)
916         GTZIFR_N( TZStandardBiasW,  tzinfo->StandardBias)
917         GTZIFR_N( TZDaylightBiasW,  tzinfo->DaylightBias)
918         GTZIFR_S( TZStandardNameW, tzinfo->StandardName)
919         GTZIFR_S( TZDaylightNameW, tzinfo->DaylightName)
920
921 #undef GTZIFR_N
922 #undef GTZIFR_S
923         NtClose( hkey );
924         return 1;
925     }
926     return 0;
927 }
928
929 /***********************************************************************
930  *      RtlQueryTimeZoneInformation [NTDLL.@]
931  *
932  * Get information about the current timezone.
933  *
934  * PARAMS
935  *   tzinfo [O] Destination for the retrieved timezone info.
936  *
937  * RETURNS
938  *   Success: STATUS_SUCCESS.
939  *   Failure: An NTSTATUS error code indicating the problem.
940  */
941 NTSTATUS WINAPI RtlQueryTimeZoneInformation(RTL_TIME_ZONE_INFORMATION *tzinfo)
942 {
943     time_t gmt;
944     int bias, daylight;
945     const WCHAR *psTZ;
946
947     memset(tzinfo, 0, sizeof(RTL_TIME_ZONE_INFORMATION));
948
949     if( !TIME_GetTimeZoneInfoFromReg(tzinfo)) {
950
951         gmt = time(NULL);
952         bias = TIME_GetBias(gmt, &daylight);
953
954         tzinfo->Bias = -bias / 60;
955         tzinfo->StandardBias = 0;
956         tzinfo->DaylightBias = -60;
957         tzinfo->StandardName[0]='\0';
958         tzinfo->DaylightName[0]='\0';
959         psTZ = TIME_GetTZAsStr (gmt, (-bias/60), daylight);
960         if (psTZ) strcpyW( tzinfo->StandardName, psTZ );
961         }
962     return STATUS_SUCCESS;
963 }
964
965 /***********************************************************************
966  *       RtlSetTimeZoneInformation [NTDLL.@]
967  *
968  * Set the current time zone information.
969  *
970  * PARAMS
971  *   tzinfo [I] Timezone information to set.
972  *
973  * RETURNS
974  *   Success: STATUS_SUCCESS.
975  *   Failure: An NTSTATUS error code indicating the problem.
976  *
977  * BUGS
978  *   Uses the obsolete unix timezone structure and tz_dsttime member.
979  */
980 NTSTATUS WINAPI RtlSetTimeZoneInformation( const RTL_TIME_ZONE_INFORMATION *tzinfo )
981 {
982 #ifdef HAVE_SETTIMEOFDAY
983     struct timezone tz;
984
985     tz.tz_minuteswest = tzinfo->Bias;
986 #ifdef DST_NONE
987     tz.tz_dsttime = DST_NONE;
988 #else
989     tz.tz_dsttime = 0;
990 #endif
991     if(!settimeofday(NULL, &tz))
992         return STATUS_SUCCESS;
993 #endif
994     return STATUS_PRIVILEGE_NOT_HELD;
995 }
996
997 /***********************************************************************
998  *        NtSetSystemTime [NTDLL.@]
999  *        ZwSetSystemTime [NTDLL.@]
1000  *
1001  * Set the system time.
1002  *
1003  * PARAMS
1004  *   NewTime [I] The time to set.
1005  *   OldTime [O] Optional destination for the previous system time.
1006  *
1007  * RETURNS
1008  *   Success: STATUS_SUCCESS.
1009  *   Failure: An NTSTATUS error code indicating the problem.
1010  */
1011 NTSTATUS WINAPI NtSetSystemTime(const LARGE_INTEGER *NewTime, LARGE_INTEGER *OldTime)
1012 {
1013     TIME_FIELDS tf;
1014     struct timeval tv;
1015     struct timezone tz;
1016     struct tm t;
1017     time_t sec, oldsec;
1018     int dst, bias;
1019     int err;
1020
1021     /* Return the old time if necessary */
1022     if(OldTime)
1023         NtQuerySystemTime(OldTime);
1024
1025     RtlTimeToTimeFields(NewTime, &tf);
1026
1027     /* call gettimeofday to get the current timezone */
1028     gettimeofday(&tv, &tz);
1029     oldsec = tv.tv_sec;
1030     /* get delta local time from utc */
1031     bias = TIME_GetBias(oldsec, &dst);
1032
1033     /* get the number of seconds */
1034     t.tm_sec = tf.Second;
1035     t.tm_min = tf.Minute;
1036     t.tm_hour = tf.Hour;
1037     t.tm_mday = tf.Day;
1038     t.tm_mon = tf.Month - 1;
1039     t.tm_year = tf.Year - 1900;
1040     t.tm_isdst = dst;
1041     sec = mktime (&t);
1042     /* correct for timezone and daylight */
1043     sec += bias;
1044
1045     /* set the new time */
1046     tv.tv_sec = sec;
1047     tv.tv_usec = tf.Milliseconds * 1000;
1048
1049     /* error and sanity check*/
1050     if(sec == (time_t)-1 || abs((int)(sec-oldsec)) > SETTIME_MAX_ADJUST) {
1051         err = 2;
1052     } else {
1053 #ifdef HAVE_SETTIMEOFDAY
1054         err = settimeofday(&tv, NULL); /* 0 is OK, -1 is error */
1055         if(err == 0)
1056             return STATUS_SUCCESS;
1057 #else
1058         err = 1;
1059 #endif
1060     }
1061
1062     ERR("Cannot set time to %d/%d/%d %d:%d:%d Time adjustment %ld %s\n",
1063             tf.Year, tf.Month, tf.Day, tf.Hour, tf.Minute, tf.Second,
1064             (long)(sec-oldsec),
1065             err == -1 ? "No Permission"
1066                       : sec == (time_t)-1 ? "" : "is too large." );
1067
1068     if(err == 2)
1069         return STATUS_INVALID_PARAMETER;
1070     else if(err == -1)
1071         return STATUS_PRIVILEGE_NOT_HELD;
1072     else
1073         return STATUS_NOT_IMPLEMENTED;
1074 }