blob: 4d29c336ca171232f37bcd1a352e1234ab2403f2 [file] [log] [blame]
Juergen Schmied026d9db1999-03-09 17:47:51 +00001/*
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +00002 * Nt time functions.
Juergen Schmied026d9db1999-03-09 17:47:51 +00003 *
Vincent Béron9a624912002-05-31 23:06:46 +00004 * RtlTimeToTimeFields, RtlTimeFieldsToTime and defines are taken from ReactOS and
Jon Griffiths08922852003-08-19 00:56:34 +00005 * adapted to wine with special permissions of the author. This code is
6 * Copyright 2002 Rex Jolliff (rex@lvcablemodem.com)
Vincent Béron9a624912002-05-31 23:06:46 +00007 *
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00008 * 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
Jonathan Ernst360a3f92006-05-18 14:49:52 +020022 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Juergen Schmied026d9db1999-03-09 17:47:51 +000023 */
24
Patrik Stridvalld016f812002-08-17 00:43:16 +000025#include "config.h"
Patrik Stridvall51e6c0c2002-08-31 19:04:14 +000026#include "wine/port.h"
Patrik Stridvalld016f812002-08-17 00:43:16 +000027
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000028#include <stdarg.h>
Vincent Béronea966aa2002-11-27 20:14:45 +000029#include <stdlib.h>
Dmitry Timoshkova1886622007-07-29 21:31:00 +090030#include <errno.h>
David Luyer26cd7a11999-03-25 15:57:35 +000031#include <string.h>
Alexandre Julliard25b23a02004-09-07 23:01:34 +000032#include <limits.h>
Alexandre Julliardd76f9f92000-10-01 01:40:42 +000033#include <time.h>
Patrik Stridvalld016f812002-08-17 00:43:16 +000034#ifdef HAVE_SYS_TIME_H
35# include <sys/time.h>
36#endif
37#ifdef HAVE_UNISTD_H
38# include <unistd.h>
39#endif
Dimitrie O. Paun297f3d82003-01-07 20:36:20 +000040
41#define NONAMELESSUNION
42#define NONAMELESSSTRUCT
Ge van Geldorp1a1583a2005-11-28 17:32:54 +010043#include "ntstatus.h"
44#define WIN32_NO_STATUS
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000045#include "windef.h"
Patrik Stridvall9c1de6d2002-09-12 22:07:02 +000046#include "winternl.h"
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +000047#include "wine/unicode.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000048#include "wine/debug.h"
Alexandre Julliard462172a2003-04-02 22:48:59 +000049#include "ntdll_misc.h"
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000050
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000051WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
Juergen Schmied026d9db1999-03-09 17:47:51 +000052
Mike McCormack6b636e32005-06-25 18:00:57 +000053static RTL_CRITICAL_SECTION TIME_GetBias_section;
54static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
Huw Davies67e2d6c2004-02-27 00:43:20 +000055{
56 0, 0, &TIME_GetBias_section,
57 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
Alexandre Julliard20a1a202005-09-09 10:19:44 +000058 0, 0, { (DWORD_PTR)(__FILE__ ": TIME_GetBias_section") }
Huw Davies67e2d6c2004-02-27 00:43:20 +000059};
Mike McCormack6b636e32005-06-25 18:00:57 +000060static RTL_CRITICAL_SECTION TIME_GetBias_section = { &critsect_debug, -1, 0, 0, 0, 0 };
Huw Davies67e2d6c2004-02-27 00:43:20 +000061
Rein Klazesc5c93d12004-10-18 21:19:28 +000062/* TimeZone registry key values */
63static const WCHAR TZInformationKeyW[] = { 'M','a','c','h','i','n','e','\\',
64 'S','Y','S','T','E','M','\\','C','u','r','r','e','n','t','C','o','n','t','r',
65 'o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','T','i','m','e','z',
66 'o','n','e','I','n','f','o','r','m','a','t','i','o','n', 0};
67static const WCHAR TZStandardStartW[] = {
68 'S','t','a','n','d','a','r','d','s','t','a','r','t', 0};
69static const WCHAR TZDaylightStartW[] = {
70 'D','a','y','l','i','g','h','t','s','t','a','r','t', 0};
71static const WCHAR TZDaylightBiasW[] = {
72 'D','a','y','l','i','g','h','t','B','i','a','s', 0};
73static const WCHAR TZStandardBiasW[] = {
74 'S','t','a','n','d','a','r','d','B','i','a','s', 0};
75static const WCHAR TZBiasW[] = {'B','i','a','s', 0};
76static const WCHAR TZDaylightNameW[] = {
77 'D','a','y','l','i','g','h','t','N','a','m','e', 0};
78static const WCHAR TZStandardNameW[] = {
79 'S','t','a','n','d','a','r','d','N','a','m','e', 0};
80
Huw Davies67e2d6c2004-02-27 00:43:20 +000081
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +000082#define SETTIME_MAX_ADJUST 120
83
84/* This structure is used to store strings that represent all of the time zones
85 * in the world. (This is used to help GetTimeZoneInformation)
86 */
87struct tagTZ_INFO
88{
89 const char *psTZFromUnix;
90 WCHAR psTZWindows[32];
91 int bias;
92 int dst;
93};
94
95static const struct tagTZ_INFO TZ_INFO[] =
96{
97 {"MHT",
98 {'D','a','t','e','l','i','n','e',' ','S','t','a','n','d','a','r','d',' ',
99 'T','i','m','e','\0'}, -720, 0},
100 {"SST",
101 {'S','a','m','o','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m',
102 'e','\0'}, 660, 0},
103 {"HST",
104 {'H','a','w','a','i','i','a','n',' ','S','t','a','n','d','a','r','d',' ',
105 'T','i','m','e','\0'}, 600, 0},
Mike McCormack5b405512005-11-08 10:57:50 +0000106 {"AKST",
107 {'A','l','a','s','k','a','n',' ','S','t','a','n','d','a','r','d',' ',
108 'T','i','m','e',0}, 540, 0 },
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000109 {"AKDT",
110 {'A','l','a','s','k','a','n',' ','S','t','a','n','d','a','r','d',' ','T',
111 'i','m','e','\0'}, 480, 1},
Roger Olson30782222004-11-02 05:22:01 +0000112 {"PST",
113 {'P','a','c','i','f','i','c',' ','S','t','a','n','d','a','r','d',' ','T',
114 'i','m','e','\0'}, 480, 0},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000115 {"PDT",
116 {'P','a','c','i','f','i','c',' ','S','t','a','n','d','a','r','d',' ','T',
117 'i','m','e','\0'}, 420, 1},
118 {"MST",
119 {'U','S',' ','M','o','u','n','t','a','i','n',' ','S','t','a','n','d','a',
120 'r','d',' ','T','i','m','e','\0'}, 420, 0},
121 {"MDT",
122 {'M','o','u','n','t','a','i','n',' ','S','t','a','n','d','a','r','d',' ',
123 'T','i','m','e','\0'}, 360, 1},
124 {"CST",
125 {'C','e','n','t','r','a','l',' ','A','m','e','r','i','c','a',' ','S','t',
126 'a','n','d','a','r','d',' ','T','i','m','e','\0'}, 360, 0},
127 {"CDT",
128 {'C','e','n','t','r','a','l',' ','S','t','a','n','d','a','r','d',' ','T',
129 'i','m','e','\0'}, 300, 1},
130 {"COT",
131 {'S','A',' ','P','a','c','i','f','i','c',' ','S','t','a','n','d','a','r',
132 'd',' ','T','i','m','e','\0'}, 300, 0},
Mike McCormack5b405512005-11-08 10:57:50 +0000133 {"PET",
134 {'S','A',' ','P','a','c','i','f','i','c',' ','S','t','a','n','d','a','r',
135 'd',' ','T','i','m','e',0}, 300, 0 },
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000136 {"EDT",
137 {'E','a','s','t','e','r','n',' ','S','t','a','n','d','a','r','d',' ','T',
138 'i','m','e','\0'}, 240, 1},
139 {"EST",
140 {'U','S',' ','E','a','s','t','e','r','n',' ','S','t','a','n','d','a','r',
141 'd',' ','T','i','m','e','\0'}, 300, 0},
Alex Villacís Lasso3cea3a52005-03-14 10:04:30 +0000142 {"ECT",
143 {'E','a','s','t','e','r','n',' ','C','e','n','t','r','a','l',' ','S','t','a','n','d','a','r',
144 'd',' ','T','i','m','e','\0'}, 300, 0},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000145 {"ADT",
146 {'A','t','l','a','n','t','i','c',' ','S','t','a','n','d','a','r','d',' ',
147 'T','i','m','e','\0'}, 180, 1},
148 {"VET",
149 {'S','A',' ','W','e','s','t','e','r','n',' ','S','t','a','n','d','a','r',
150 'd',' ','T','i','m','e','\0'}, 240, 0},
151 {"CLT",
152 {'P','a','c','i','f','i','c',' ','S','A',' ','S','t','a','n','d','a','r',
153 'd',' ','T','i','m','e','\0'}, 240, 0},
Mike McCormack5b405512005-11-08 10:57:50 +0000154 {"CLST",
155 {'P','a','c','i','f','i','c',' ','S','A',' ','S','t','a','n','d','a','r',
156 'd',' ','T','i','m','e',0}, 180, 1},
157 {"AST",
158 {'A','t','l','a','n','t','i','c',' ','S','t','a','n','d','a','r','d',' ',
159 'T','i','m','e',0}, 240, 0 },
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000160 {"NDT",
161 {'N','e','w','f','o','u','n','d','l','a','n','d',' ','S','t','a','n','d',
162 'a','r','d',' ','T','i','m','e','\0'}, 150, 1},
Mike McCormack5b405512005-11-08 10:57:50 +0000163 {"NST",
164 {'N','e','w','f','o','u','n','d','l','a','n','d',' ','S','t','a','n','d',
165 'a','r','d',' ','T','i','m','e',0}, 210, 0 },
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000166 {"BRT",
Marcelo Duarte37bc4412005-02-14 11:03:05 +0000167 {'B','r','a','z','i','l','i','a','n',' ','S','t','a','n','d','a','r','d',
168 ' ','T','i','m','e','\0'}, 180, 0},
Tony Lambregts5f0e5542005-01-06 19:35:35 +0000169 {"BRST",
Marcelo Duarte37bc4412005-02-14 11:03:05 +0000170 {'B','r','a','z','i','l','i','a','n',' ','S','u','m','m','e','r',
171 ' ','T','i','m','e','\0'}, 120, 1},
Julio E. Gonzalez P5b987382007-07-04 20:52:29 -0400172 {"PYT",
173 {'P','a','r','a','g','u','a','y','a','n',' ',
174 'S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, 240, 0},
175 {"PYST",
176 {'P','a','r','a','g','u','a','y','a','n',' ','S','u','m','m','e','r',
177 ' ','T','i','m','e','\0'}, 180, 1},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000178 {"ART",
179 {'S','A',' ','E','a','s','t','e','r','n',' ','S','t','a','n','d','a','r',
180 'd',' ','T','i','m','e','\0'}, 180, 0},
181 {"WGST",
182 {'G','r','e','e','n','l','a','n','d',' ','S','t','a','n','d','a','r','d',
183 ' ','T','i','m','e','\0'}, 120, 1},
184 {"GST",
185 {'M','i','d','-','A','t','l','a','n','t','i','c',' ','S','t','a','n','d',
186 'a','r','d',' ','T','i','m','e','\0'}, 120, 0},
Mike McCormack5b405512005-11-08 10:57:50 +0000187 {"AZOT",
188 {'A','z','o','r','e','s',' ','S','t','a','n','d','a','r','d',' ','T','i',
189 'm','e',0}, 60, 0},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000190 {"AZOST",
191 {'A','z','o','r','e','s',' ','S','t','a','n','d','a','r','d',' ','T','i',
192 'm','e','\0'}, 0, 1},
193 {"CVT",
194 {'C','a','p','e',' ','V','e','r','d','e',' ','S','t','a','n','d','a','r',
195 'd',' ','T','i','m','e','\0'}, 60, 0},
Francois Gougetee7f5eb2005-05-07 14:50:56 +0000196 {"WEST",
197 {'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},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000198 {"WET",
199 {'G','r','e','e','n','w','i','c','h',' ','S','t','a','n','d','a','r','d',
200 ' ','T','i','m','e','\0'}, 0, 0},
201 {"BST",
202 {'G','M','T',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
203 -60, 1},
Juan Lang5e1b4182005-05-10 08:25:30 +0000204 {"IST",
205 {'I','r','i','s','h',' ','S','u','m','m','e','r',' ','T','i','m','e','\0'},
206 -60, 1},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000207 {"GMT",
208 {'G','M','T',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
209 0, 0},
Filip Navara63c63592004-10-04 19:29:16 +0000210 {"UTC",
211 {'G','M','T',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
212 0, 0},
Michael Jung82297522004-11-02 05:28:01 +0000213 {"CET",
214 {'C','e','n','t','r','a','l',' ','E','u','r','o','p','e','a','n',' ',
215 'T','i','m','e','\0'}, -60, 0},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000216 {"CEST",
217 {'C','e','n','t','r','a','l',' ','E','u','r','o','p','e',' ','S','t','a',
218 'n','d','a','r','d',' ','T','i','m','e','\0'}, -120, 1},
Uwe Bonnesd3499082004-09-06 21:26:37 +0000219 {"MET",
220 {'C','e','n','t','r','a','l',' ','E','u','r','o','p','e',' ','S','t','a',
221 'n','d','a','r','d',' ','T','i','m','e','\0'}, -60, 0},
222 {"MEST",
223 {'C','e','n','t','r','a','l',' ','E','u','r','o','p','e',' ','D','a','y',
224 'l','i','g','h','t',' ','T','i','m','e','\0'}, -120, 1},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000225 {"WAT",
226 {'W','.',' ','C','e','n','t','r','a','l',' ','A','f','r','i','c','a',' ',
227 'S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'}, -60, 0},
228 {"EEST",
229 {'E','.',' ','E','u','r','o','p','e',' ','S','t','a','n','d','a','r','d',
230 ' ','T','i','m','e','\0'}, -180, 1},
231 {"EET",
232 {'E','g','y','p','t',' ','S','t','a','n','d','a','r','d',' ','T','i','m',
233 'e','\0'}, -120, 0},
234 {"CAT",
Stewart Allen7cb55432004-12-06 11:39:34 +0000235 {'C','e','n','t','r','a','l',' ','A','f','r','i','c','a','n',' '
236 ,'T','i','m','e','\0'}, -120, 0},
237 {"SAST",
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000238 {'S','o','u','t','h',' ','A','f','r','i','c','a',' ','S','t','a','n','d',
239 'a','r','d',' ','T','i','m','e','\0'}, -120, 0},
240 {"IST",
241 {'I','s','r','a','e','l',' ','S','t','a','n','d','a','r','d',' ','T','i',
242 'm','e','\0'}, -120, 0},
Erez Volk14a32752007-05-15 20:43:51 +0300243 {"IDT",
244 {'I','s','r','a','e','l',' ','S','t','a','n','d','a','r','d',' ','T','i',
245 'm','e','\0'}, -180, 1},
Vitaly Lipatov4c801af2004-11-02 19:25:05 +0000246 {"MSK",
247 {'R','u','s','s','i','a','n',' ','S','t','a','n','d','a','r','d',' ','T',
248 'i','m','e','\0'}, -180, 0},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000249 {"ADT",
250 {'A','r','a','b','i','c',' ','S','t','a','n','d','a','r','d',' ','T','i',
251 'm','e','\0'}, -240, 1},
252 {"AST",
253 {'A','r','a','b',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e',
254 '\0'}, -180, 0},
255 {"MSD",
256 {'R','u','s','s','i','a','n',' ','S','t','a','n','d','a','r','d',' ','T',
257 'i','m','e','\0'}, -240, 1},
258 {"EAT",
259 {'E','.',' ','A','f','r','i','c','a',' ','S','t','a','n','d','a','r','d',
260 ' ','T','i','m','e','\0'}, -180, 0},
261 {"IRST",
262 {'I','r','a','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e',
Mike McCormack5b405512005-11-08 10:57:50 +0000263 0},-210, 0 },
264 {"IRST",
265 {'I','r','a','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e',
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000266 '\0'}, -270, 1},
267 {"GST",
268 {'A','r','a','b','i','a','n',' ','S','t','a','n','d','a','r','d',' ','T',
269 'i','m','e','\0'}, -240, 0},
Mike McCormack5b405512005-11-08 10:57:50 +0000270 {"AZT",
271 {'C','a','u','c','a','s','u','s',' ','S','t','a','n','d','a','r','d',' ',
272 'T','i','m','e',0}, -240, 0 },
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000273 {"AZST",
274 {'C','a','u','c','a','s','u','s',' ','S','t','a','n','d','a','r','d',' ',
275 'T','i','m','e','\0'}, -300, 1},
276 {"AFT",
277 {'A','f','g','h','a','n','i','s','t','a','n',' ','S','t','a','n','d','a',
278 'r','d',' ','T','i','m','e','\0'}, -270, 0},
Tony Lambregtse1ff586d2005-01-20 10:52:57 +0000279 {"SAMT",
280 {'S','a','m','a','r','a',' ','S','t','a','n','d','a','r','d',' ','T','i',
Konstantin Kondratyukb7c38b02007-07-24 08:57:55 +0400281 'm','e','(','W','i','n','t','e','r',')','\0'}, -240, 0},
282 {"SAMST",
283 {'S','a','m','a','r','a',' ','D','a','y','l','i','g','h','t',' ','T','i',
284 'm','e','(','S','u','m','m','e','r',')','\0'}, -300, 1},
Sergei Butakov4f53d5a2006-02-07 16:51:51 +0100285 {"YEKT",
286 {'U','r','a','l','s',' ','S','t','a','n','d','a','r','d',
287 ' ','T','i','m','e',' ','(','W','i','n','t','e','r',')','\0'}, -300, 0},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000288 {"YEKST",
Sergei Butakov4f53d5a2006-02-07 16:51:51 +0100289 {'U','r','a','l','s',' ','D','a','y','l','i','g','h','t',
290 ' ','T','i','m','e',' ','(','S','u','m','m','e','r',')','\0'}, -360, 1},
Konstantin Kondratyuk4f976742007-02-08 17:13:13 +0300291 {"OMST",
292 {'O','m','s','k',' ','S','t','a','n','d','a','r','d',
293 ' ','T','i','m','e',' ','(','W','i','n','t','e','r',')','\0'}, -360, 0},
294 {"OMSST",
295 {'O','m','s','k',' ','D','a','y','l','i','g','h','t',
296 ' ','T','i','m','e',' ','(','S','u','m','m','e','r',')','\0'}, -420, 1},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000297 {"PKT",
298 {'W','e','s','t',' ','A','s','i','a',' ','S','t','a','n','d','a','r','d',
299 ' ','T','i','m','e','\0'}, -300, 0},
300 {"IST",
301 {'I','n','d','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m',
302 'e','\0'}, -330, 0},
303 {"NPT",
304 {'N','e','p','a','l',' ','S','t','a','n','d','a','r','d',' ','T','i','m',
305 'e','\0'}, -345, 0},
306 {"ALMST",
307 {'N','.',' ','C','e','n','t','r','a','l',' ','A','s','i','a',' ','S','t',
308 'a','n','d','a','r','d',' ','T','i','m','e','\0'}, -420, 1},
309 {"BDT",
310 {'C','e','n','t','r','a','l',' ','A','s','i','a',' ','S','t','a','n','d',
311 'a','r','d',' ','T','i','m','e','\0'}, -360, 0},
312 {"LKT",
313 {'S','r','i',' ','L','a','n','k','a',' ','S','t','a','n','d','a','r','d',
314 ' ','T','i','m','e','\0'}, -360, 0},
315 {"MMT",
316 {'M','y','a','n','m','a','r',' ','S','t','a','n','d','a','r','d',' ','T',
317 'i','m','e','\0'}, -390, 0},
318 {"ICT",
319 {'S','E',' ','A','s','i','a',' ','S','t','a','n','d','a','r','d',' ','T',
320 'i','m','e','\0'}, -420, 0},
Mike McCormack5b405512005-11-08 10:57:50 +0000321 {"KRAT",
322 {'N','o','r','t','h',' ','A','s','i','a',' ','S','t','a','n','d','a','r',
323 'd',' ','T','i','m','e',0}, -420, 0},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000324 {"KRAST",
325 {'N','o','r','t','h',' ','A','s','i','a',' ','S','t','a','n','d','a','r',
326 'd',' ','T','i','m','e','\0'}, -480, 1},
Mike McCormack5b405512005-11-08 10:57:50 +0000327 {"IRKT",
328 {'N','o','r','t','h',' ','A','s','i','a',' ','E','a','s','t',' ','S','t',
329 'a','n','d','a','r','d',' ','T','i','m','e',0}, -480, 0},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000330 {"CST",
331 {'C','h','i','n','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m',
332 'e','\0'}, -480, 0},
333 {"IRKST",
334 {'N','o','r','t','h',' ','A','s','i','a',' ','E','a','s','t',' ','S','t',
335 'a','n','d','a','r','d',' ','T','i','m','e','\0'}, -540, 1},
336 {"SGT",
337 {'M','a','l','a','y',' ','P','e','n','i','n','s','u','l','a',' ','S','t',
338 'a','n','d','a','r','d',' ','T','i','m','e','\0'}, -480, 0},
339 {"WST",
340 {'W','.',' ','A','u','s','t','r','a','l','i','a',' ','S','t','a','n','d',
341 'a','r','d',' ','T','i','m','e','\0'}, -480, 0},
Harry McNallyca2c9872007-01-10 20:49:53 +0900342 {"WST",
343 {'W','.',' ','A','u','s','t','r','a','l','i','a',' ','S','u','m','m','e',
344 'r',' ','T','i','m','e','\0'}, -540, 1},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000345 {"JST",
346 {'T','o','k','y','o',' ','S','t','a','n','d','a','r','d',' ','T','i','m',
347 'e','\0'}, -540, 0},
348 {"KST",
349 {'K','o','r','e','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m',
350 'e','\0'}, -540, 0},
351 {"YAKST",
352 {'Y','a','k','u','t','s','k',' ','S','t','a','n','d','a','r','d',' ','T',
353 'i','m','e','\0'}, -600, 1},
354 {"CST",
355 {'C','e','n','.',' ','A','u','s','t','r','a','l','i','a',' ','S','t','a',
356 'n','d','a','r','d',' ','T','i','m','e','\0'}, -570, 0},
Kieran Clancyd1c74582005-11-03 13:21:23 +0000357 {"CST",
358 {'C','e','n','.',' ','A','u','s','t','r','a','l','i','a',' ','D','a','y',
359 'l','i','g','h','t',' ','T','i','m','e','\0'}, -630, 1},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000360 {"EST",
361 {'E','.',' ','A','u','s','t','r','a','l','i','a',' ','S','t','a','n','d',
362 'a','r','d',' ','T','i','m','e','\0'}, -600, 0},
Troy Rollo418853e2005-01-27 11:11:54 +0000363 {"EST",
364 {'E','.',' ','A','u','s','t','r','a','l','i','a',' ','S','t','a','n','d',
365 'a','r','d',' ','T','i','m','e','\0'}, -660, 1},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000366 {"GST",
367 {'W','e','s','t',' ','P','a','c','i','f','i','c',' ','S','t','a','n','d',
368 'a','r','d',' ','T','i','m','e','\0'}, -600, 0},
Mike McCormack5b405512005-11-08 10:57:50 +0000369 {"VLAT",
370 {'V','l','a','d','i','v','o','s','t','o','k',' ','S','t','a','n','d','a',
371 'r','d',' ','T','i','m','e',0}, -600, 0 },
372 {"ChST",
373 {'W','e','s','t',' ','P','a','c','i','f','i','c',' ','S','t','a','n','d',
374 'a','r','d',' ','T','i','m','e',0}, -600, 0},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000375 {"VLAST",
376 {'V','l','a','d','i','v','o','s','t','o','k',' ','S','t','a','n','d','a',
377 'r','d',' ','T','i','m','e','\0'}, -660, 1},
Mike McCormack5b405512005-11-08 10:57:50 +0000378 {"MAGT",
379 {'C','e','n','t','r','a','l',' ','P','a','c','i','f','i','c',' ','S','t',
380 'a','n','d','a','r','d',' ','T','i','m','e',0}, -660, 0},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000381 {"MAGST",
382 {'C','e','n','t','r','a','l',' ','P','a','c','i','f','i','c',' ','S','t',
383 'a','n','d','a','r','d',' ','T','i','m','e','\0'}, -720, 1},
384 {"NZST",
385 {'N','e','w',' ','Z','e','a','l','a','n','d',' ','S','t','a','n','d','a',
386 'r','d',' ','T','i','m','e','\0'}, -720, 0},
Darryl Dixonaef6fe32005-02-22 14:49:59 +0000387 {"NZDT",
388 {'N','e','w',' ','Z','e','a','l','a','n','d',' ','D','a','y','l','i','g',
389 'h','t',' ','T','i','m','e','\0'}, -780, 1},
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000390 {"FJT",
391 {'F','i','j','i',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e',
392 '\0'}, -720, 0},
393 {"TOT",
394 {'T','o','n','g','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m',
Alexander Yaworskyed923452004-11-21 15:34:28 +0000395 'e','\0'}, -780, 0},
396 {"NOVT",
Mike McCormack5b405512005-11-08 10:57:50 +0000397 {'N','.',' ','C','e','n','t','r','a','l',' ','A','s','i','a',' ','S','t',
398 'a','n','d','a','r','d',' ','T','i','m','e',0 }, -360, 0},
399 {"NOVT",
Alexander Yaworskyed923452004-11-21 15:34:28 +0000400 {'N','o','v','o','s','i','b','i','r','s','k',' ','S','t','a','n','d','a',
Rustam Chernotkach1283bd92005-03-22 18:17:31 +0000401 'r','d',' ','T','i','m','e','\0'}, -360, 1},
402 {"ANAT",
403 {'A','n','a','d','y','r',' ','S','t','a','n','d','a','r','d',' ','T','i',
Ivan Wongbf8f93d2005-05-04 09:45:48 +0000404 'm','e','\0'}, -720, 1},
405 {"HKT",
406 {'H','o','n','g',' ','K','o','n','g',' ','S','t','a','n','d','a','r','d',
Gabriel Gambettafd62fcf2005-05-12 09:54:39 +0000407 ' ','T','i','m','e','\0'}, -480, 0},
408 {"UYT",
Vijay Kiran Kamujubb53d092005-09-26 09:55:59 +0000409 {'U','r','u','g','u','a','y','a','n',' ','T','i','m','e','\0'}, 180, 0},
Gabriel Gambettacc578af2007-03-25 14:33:20 -0300410 {"UYST",
411 {'U','r','u','g','u','a','y','a','n',' ','S','u','m','m','e','r',' ','T',
412 'i','m','e','\0'}, 120, 1},
Vijay Kiran Kamujubb53d092005-09-26 09:55:59 +0000413 {"MYT",
414 {'M','a','l','a','y','s','i','a','n',' ','T','i','m','e','\0'}, -480, 0},
Vijay Kiran Kamujue573caf2005-10-10 18:03:56 +0000415 {"PHT",
416 {'P','h','i','l','i','p','p','i','n','e',' ','T','i','m','e','\0'}, -480, 0},
Vijay Kiran Kamujubb53d092005-09-26 09:55:59 +0000417 {"NOVST",
418 {'N','o','v','o','s','i','b','i','r','s','k',' ','S','u','m','m','e','r',
Alexey Markachev160f1c32007-04-26 13:03:55 +0400419 ' ','T','i','m','e','\0'}, -420, 1},
Lei Zhang9ee4d852007-07-29 22:01:56 -0700420 {"BOT",
421 {'B','o','l','i','v','i','a','n',' ','T','i','m','e','\0'}, 240, 0},
Vijay Kiran Kamujuee87f032006-06-23 12:42:05 -0400422 {"UZT",
423 {'U','z','b','e','k','i','s','t','h','a','n',' ','T','i','m','e','\0'}, -300, 0}
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000424};
425
Juergen Schmied026d9db1999-03-09 17:47:51 +0000426#define TICKSPERSEC 10000000
427#define TICKSPERMSEC 10000
428#define SECSPERDAY 86400
429#define SECSPERHOUR 3600
430#define SECSPERMIN 60
431#define MINSPERHOUR 60
432#define HOURSPERDAY 24
Alexandre Julliarddcc3afd2002-12-13 20:53:04 +0000433#define EPOCHWEEKDAY 1 /* Jan 1, 1601 was Monday */
Juergen Schmied026d9db1999-03-09 17:47:51 +0000434#define DAYSPERWEEK 7
435#define EPOCHYEAR 1601
436#define DAYSPERNORMALYEAR 365
437#define DAYSPERLEAPYEAR 366
438#define MONSPERYEAR 12
Huw Davies166faa42004-02-24 01:01:27 +0000439#define DAYSPERQUADRICENTENNIUM (365 * 400 + 97)
440#define DAYSPERNORMALCENTURY (365 * 100 + 24)
441#define DAYSPERNORMALQUADRENNIUM (365 * 4 + 1)
Juergen Schmied026d9db1999-03-09 17:47:51 +0000442
Alexandre Julliardd76f9f92000-10-01 01:40:42 +0000443/* 1601 to 1970 is 369 years plus 89 leap days */
Alexandre Julliardfbef57c2003-03-31 01:37:04 +0000444#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
445#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
Alexandre Julliardd76f9f92000-10-01 01:40:42 +0000446/* 1601 to 1980 is 379 years plus 91 leap days */
Alexandre Julliardfbef57c2003-03-31 01:37:04 +0000447#define SECS_1601_TO_1980 ((379 * 365 + 91) * (ULONGLONG)SECSPERDAY)
448#define TICKS_1601_TO_1980 (SECS_1601_TO_1980 * TICKSPERSEC)
Alexandre Julliard25b23a02004-09-07 23:01:34 +0000449/* max ticks that can be represented as Unix time */
450#define TICKS_1601_TO_UNIX_MAX ((SECS_1601_TO_1970 + INT_MAX) * TICKSPERSEC)
Alexandre Julliardd76f9f92000-10-01 01:40:42 +0000451
452
Juergen Schmied026d9db1999-03-09 17:47:51 +0000453static const int MonthLengths[2][MONSPERYEAR] =
454{
455 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
456 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
457};
458
Patrik Stridvall896889f1999-05-08 12:50:36 +0000459static inline int IsLeapYear(int Year)
Juergen Schmied026d9db1999-03-09 17:47:51 +0000460{
461 return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0;
462}
463
Juergen Schmied026d9db1999-03-09 17:47:51 +0000464/******************************************************************************
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000465 * RtlTimeToTimeFields [NTDLL.@]
Juergen Schmied026d9db1999-03-09 17:47:51 +0000466 *
Jon Griffiths08922852003-08-19 00:56:34 +0000467 * Convert a time into a TIME_FIELDS structure.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000468 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000469 * PARAMS
Jon Griffiths08922852003-08-19 00:56:34 +0000470 * liTime [I] Time to convert.
471 * TimeFields [O] Destination for the converted time.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000472 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000473 * RETURNS
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000474 * Nothing.
Juergen Schmied026d9db1999-03-09 17:47:51 +0000475 */
Juergen Schmied026d9db1999-03-09 17:47:51 +0000476VOID WINAPI RtlTimeToTimeFields(
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000477 const LARGE_INTEGER *liTime,
Juergen Schmied026d9db1999-03-09 17:47:51 +0000478 PTIME_FIELDS TimeFields)
479{
Rein Klazesdceae022004-11-06 03:53:53 +0000480 int SecondsInDay;
481 long int cleaps, years, yearday, months;
Juergen Schmied026d9db1999-03-09 17:47:51 +0000482 long int Days;
Rein Klazesdceae022004-11-06 03:53:53 +0000483 LONGLONG Time;
Juergen Schmied026d9db1999-03-09 17:47:51 +0000484
485 /* Extract millisecond from time and convert time into seconds */
Rein Klazesdceae022004-11-06 03:53:53 +0000486 TimeFields->Milliseconds =
487 (CSHORT) (( liTime->QuadPart % TICKSPERSEC) / TICKSPERMSEC);
488 Time = liTime->QuadPart / TICKSPERSEC;
Juergen Schmied026d9db1999-03-09 17:47:51 +0000489
György 'Nog' Jeney39433b92002-11-06 21:57:23 +0000490 /* The native version of RtlTimeToTimeFields does not take leap seconds
491 * into account */
Juergen Schmied026d9db1999-03-09 17:47:51 +0000492
493 /* Split the time into days and seconds within the day */
494 Days = Time / SECSPERDAY;
495 SecondsInDay = Time % SECSPERDAY;
496
Juergen Schmied026d9db1999-03-09 17:47:51 +0000497 /* compute time of day */
498 TimeFields->Hour = (CSHORT) (SecondsInDay / SECSPERHOUR);
499 SecondsInDay = SecondsInDay % SECSPERHOUR;
500 TimeFields->Minute = (CSHORT) (SecondsInDay / SECSPERMIN);
501 TimeFields->Second = (CSHORT) (SecondsInDay % SECSPERMIN);
502
Juergen Schmied026d9db1999-03-09 17:47:51 +0000503 /* compute day of week */
504 TimeFields->Weekday = (CSHORT) ((EPOCHWEEKDAY + Days) % DAYSPERWEEK);
505
Rein Klazesdceae022004-11-06 03:53:53 +0000506 /* compute year, month and day of month. */
507 cleaps=( 3 * ((4 * Days + 1227) / DAYSPERQUADRICENTENNIUM) + 3 ) / 4;
508 Days += 28188 + cleaps;
509 years = (20 * Days - 2442) / (5 * DAYSPERNORMALQUADRENNIUM);
510 yearday = Days - (years * DAYSPERNORMALQUADRENNIUM)/4;
511 months = (64 * yearday) / 1959;
512 /* the result is based on a year starting on March.
513 * To convert take 12 from Januari and Februari and
514 * increase the year by one. */
515 if( months < 14 ) {
516 TimeFields->Month = months - 1;
517 TimeFields->Year = years + 1524;
518 } else {
519 TimeFields->Month = months - 13;
520 TimeFields->Year = years + 1525;
521 }
522 /* calculation of day of month is based on the wonderful
523 * sequence of INT( n * 30.6): it reproduces the
524 * 31-30-31-30-31-31 month lengths exactly for small n's */
525 TimeFields->Day = yearday - (1959 * months) / 64 ;
526 return;
Juergen Schmied026d9db1999-03-09 17:47:51 +0000527}
György 'Nog' Jeney39433b92002-11-06 21:57:23 +0000528
Juergen Schmied026d9db1999-03-09 17:47:51 +0000529/******************************************************************************
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000530 * RtlTimeFieldsToTime [NTDLL.@]
Juergen Schmied026d9db1999-03-09 17:47:51 +0000531 *
Jon Griffiths08922852003-08-19 00:56:34 +0000532 * Convert a TIME_FIELDS structure into a time.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000533 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000534 * PARAMS
Jon Griffiths08922852003-08-19 00:56:34 +0000535 * ftTimeFields [I] TIME_FIELDS structure to convert.
536 * Time [O] Destination for the converted time.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000537 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000538 * RETURNS
Jon Griffiths08922852003-08-19 00:56:34 +0000539 * Success: TRUE.
540 * Failure: FALSE.
Juergen Schmied026d9db1999-03-09 17:47:51 +0000541 */
542BOOLEAN WINAPI RtlTimeFieldsToTime(
543 PTIME_FIELDS tfTimeFields,
544 PLARGE_INTEGER Time)
545{
Rein Klazesdceae022004-11-06 03:53:53 +0000546 int month, year, cleaps, day;
Juergen Schmied026d9db1999-03-09 17:47:51 +0000547
548 /* FIXME: normalize the TIME_FIELDS structure here */
Rein Klazesdceae022004-11-06 03:53:53 +0000549 /* No, native just returns 0 (error) if the fields are not */
550 if( tfTimeFields->Milliseconds< 0 || tfTimeFields->Milliseconds > 999 ||
551 tfTimeFields->Second < 0 || tfTimeFields->Second > 59 ||
552 tfTimeFields->Minute < 0 || tfTimeFields->Minute > 59 ||
553 tfTimeFields->Hour < 0 || tfTimeFields->Hour > 23 ||
554 tfTimeFields->Month < 1 || tfTimeFields->Month > 12 ||
555 tfTimeFields->Day < 1 ||
556 tfTimeFields->Day > MonthLengths
557 [ tfTimeFields->Month ==2 || IsLeapYear(tfTimeFields->Year)]
558 [ tfTimeFields->Month - 1] ||
559 tfTimeFields->Year < 1601 )
560 return FALSE;
Juergen Schmied026d9db1999-03-09 17:47:51 +0000561
Rein Klazesdceae022004-11-06 03:53:53 +0000562 /* now calculate a day count from the date
563 * First start counting years from March. This way the leap days
564 * are added at the end of the year, not somewhere in the middle.
565 * Formula's become so much less complicate that way.
566 * To convert: add 12 to the month numbers of Jan and Feb, and
567 * take 1 from the year */
568 if(tfTimeFields->Month < 3) {
569 month = tfTimeFields->Month + 13;
570 year = tfTimeFields->Year - 1;
571 } else {
572 month = tfTimeFields->Month + 1;
573 year = tfTimeFields->Year;
574 }
575 cleaps = (3 * (year / 100) + 3) / 4; /* nr of "century leap years"*/
576 day = (36525 * year) / 100 - cleaps + /* year * dayperyr, corrected */
577 (1959 * month) / 64 + /* months * daypermonth */
578 tfTimeFields->Day - /* day of the month */
579 584817 ; /* zero that on 1601-01-01 */
580 /* done */
581
582 Time->QuadPart = (((((LONGLONG) day * HOURSPERDAY +
583 tfTimeFields->Hour) * MINSPERHOUR +
584 tfTimeFields->Minute) * SECSPERMIN +
585 tfTimeFields->Second ) * 1000 +
586 tfTimeFields->Milliseconds ) * TICKSPERMSEC;
Juergen Schmied026d9db1999-03-09 17:47:51 +0000587
Rein Klazesdceae022004-11-06 03:53:53 +0000588 return TRUE;
Juergen Schmied026d9db1999-03-09 17:47:51 +0000589}
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000590
Huw Davies64ed8482004-02-26 05:26:34 +0000591/***********************************************************************
592 * TIME_GetBias [internal]
593 *
594 * Helper function calculates delta local time from UTC.
595 *
596 * PARAMS
597 * utc [I] The current utc time.
598 * pdaylight [I] Local daylight.
599 *
600 * RETURNS
601 * The bias for the current timezone.
602 */
603static int TIME_GetBias(time_t utc, int *pdaylight)
604{
Huw Davies67e2d6c2004-02-27 00:43:20 +0000605 struct tm *ptm;
606 static time_t last_utc;
607 static int last_bias;
Rein Klazes50403092004-03-01 21:23:18 +0000608 static int last_daylight;
Huw Davies67e2d6c2004-02-27 00:43:20 +0000609 int ret;
610
611 RtlEnterCriticalSection( &TIME_GetBias_section );
Dmitry Timoshkov6119f492007-07-29 21:33:23 +0900612 if (utc != last_utc)
Huw Davies67e2d6c2004-02-27 00:43:20 +0000613 {
614 ptm = localtime(&utc);
Dmitry Timoshkov6119f492007-07-29 21:33:23 +0900615 last_daylight = ptm->tm_isdst; /* daylight for local timezone */
Huw Davies67e2d6c2004-02-27 00:43:20 +0000616 ptm = gmtime(&utc);
Dmitry Timoshkov6119f492007-07-29 21:33:23 +0900617 ptm->tm_isdst = last_daylight; /* use local daylight, not that of Greenwich */
Huw Davies67e2d6c2004-02-27 00:43:20 +0000618 last_utc = utc;
Dmitry Timoshkov6119f492007-07-29 21:33:23 +0900619 last_bias = (int)(utc - mktime(ptm));
Huw Davies67e2d6c2004-02-27 00:43:20 +0000620 }
Dmitry Timoshkov6119f492007-07-29 21:33:23 +0900621
622 *pdaylight = last_daylight;
623 ret = last_bias;
624
Huw Davies67e2d6c2004-02-27 00:43:20 +0000625 RtlLeaveCriticalSection( &TIME_GetBias_section );
626 return ret;
Huw Davies64ed8482004-02-26 05:26:34 +0000627}
628
György 'Nog' Jeney4d6ba252002-12-11 00:19:56 +0000629/******************************************************************************
630 * RtlLocalTimeToSystemTime [NTDLL.@]
631 *
Jon Griffiths08922852003-08-19 00:56:34 +0000632 * Convert a local time into system time.
György 'Nog' Jeney4d6ba252002-12-11 00:19:56 +0000633 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000634 * PARAMS
Jon Griffiths08922852003-08-19 00:56:34 +0000635 * LocalTime [I] Local time to convert.
636 * SystemTime [O] Destination for the converted time.
György 'Nog' Jeney4d6ba252002-12-11 00:19:56 +0000637 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000638 * RETURNS
Jon Griffiths08922852003-08-19 00:56:34 +0000639 * Success: STATUS_SUCCESS.
640 * Failure: An NTSTATUS error code indicating the problem.
György 'Nog' Jeney4d6ba252002-12-11 00:19:56 +0000641 */
642NTSTATUS WINAPI RtlLocalTimeToSystemTime( const LARGE_INTEGER *LocalTime,
643 PLARGE_INTEGER SystemTime)
644{
Huw Davies64ed8482004-02-26 05:26:34 +0000645 time_t gmt;
646 int bias, daylight;
György 'Nog' Jeney4d6ba252002-12-11 00:19:56 +0000647
648 TRACE("(%p, %p)\n", LocalTime, SystemTime);
649
Huw Davies64ed8482004-02-26 05:26:34 +0000650 gmt = time(NULL);
651 bias = TIME_GetBias(gmt, &daylight);
652
Robert Shearmanabf2de22005-02-08 12:13:36 +0000653 SystemTime->QuadPart = LocalTime->QuadPart - bias * (LONGLONG)TICKSPERSEC;
György 'Nog' Jeney4d6ba252002-12-11 00:19:56 +0000654 return STATUS_SUCCESS;
655}
Juergen Schmied026d9db1999-03-09 17:47:51 +0000656
657/******************************************************************************
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000658 * RtlSystemTimeToLocalTime [NTDLL.@]
659 *
Jon Griffiths08922852003-08-19 00:56:34 +0000660 * Convert a system time into a local time.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000661 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000662 * PARAMS
663 * SystemTime [I] System time to convert.
Jon Griffiths08922852003-08-19 00:56:34 +0000664 * LocalTime [O] Destination for the converted time.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000665 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000666 * RETURNS
Jon Griffiths08922852003-08-19 00:56:34 +0000667 * Success: STATUS_SUCCESS.
668 * Failure: An NTSTATUS error code indicating the problem.
Juergen Schmied026d9db1999-03-09 17:47:51 +0000669 */
György 'Nog' Jeney4d6ba252002-12-11 00:19:56 +0000670NTSTATUS WINAPI RtlSystemTimeToLocalTime( const LARGE_INTEGER *SystemTime,
671 PLARGE_INTEGER LocalTime )
Juergen Schmied026d9db1999-03-09 17:47:51 +0000672{
Huw Davies64ed8482004-02-26 05:26:34 +0000673 time_t gmt;
674 int bias, daylight;
Juergen Schmied026d9db1999-03-09 17:47:51 +0000675
György 'Nog' Jeney4d6ba252002-12-11 00:19:56 +0000676 TRACE("(%p, %p)\n", SystemTime, LocalTime);
677
Huw Davies64ed8482004-02-26 05:26:34 +0000678 gmt = time(NULL);
679 bias = TIME_GetBias(gmt, &daylight);
680
Robert Shearmanabf2de22005-02-08 12:13:36 +0000681 LocalTime->QuadPart = SystemTime->QuadPart + bias * (LONGLONG)TICKSPERSEC;
György 'Nog' Jeney4d6ba252002-12-11 00:19:56 +0000682 return STATUS_SUCCESS;
Juergen Schmied026d9db1999-03-09 17:47:51 +0000683}
Juergen Schmied026d9db1999-03-09 17:47:51 +0000684
685/******************************************************************************
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000686 * RtlTimeToSecondsSince1970 [NTDLL.@]
687 *
Jon Griffiths08922852003-08-19 00:56:34 +0000688 * Convert a time into a count of seconds since 1970.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000689 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000690 * PARAMS
Jon Griffiths08922852003-08-19 00:56:34 +0000691 * Time [I] Time to convert.
692 * Seconds [O] Destination for the converted time.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000693 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000694 * RETURNS
Jon Griffiths08922852003-08-19 00:56:34 +0000695 * Success: TRUE.
696 * Failure: FALSE, if the resulting value will not fit in a DWORD.
Juergen Schmied026d9db1999-03-09 17:47:51 +0000697 */
Jon Griffiths08922852003-08-19 00:56:34 +0000698BOOLEAN WINAPI RtlTimeToSecondsSince1970( const LARGE_INTEGER *Time, LPDWORD Seconds )
Juergen Schmied026d9db1999-03-09 17:47:51 +0000699{
Ge van Geldorp399901e2004-01-23 01:51:33 +0000700 ULONGLONG tmp = ((ULONGLONG)Time->u.HighPart << 32) | Time->u.LowPart;
Robert Shearmanabf2de22005-02-08 12:13:36 +0000701 tmp = RtlLargeIntegerDivide( tmp, TICKSPERSEC, NULL );
Alexandre Julliardd76f9f92000-10-01 01:40:42 +0000702 tmp -= SECS_1601_TO_1970;
703 if (tmp > 0xffffffff) return FALSE;
Jon Griffiths08922852003-08-19 00:56:34 +0000704 *Seconds = (DWORD)tmp;
Alexandre Julliard0aa6cc22000-07-29 21:56:59 +0000705 return TRUE;
706}
707
708/******************************************************************************
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000709 * RtlTimeToSecondsSince1980 [NTDLL.@]
710 *
Jon Griffiths08922852003-08-19 00:56:34 +0000711 * Convert a time into a count of seconds since 1980.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000712 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000713 * PARAMS
Jon Griffiths08922852003-08-19 00:56:34 +0000714 * Time [I] Time to convert.
715 * Seconds [O] Destination for the converted time.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000716 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000717 * RETURNS
Jon Griffiths08922852003-08-19 00:56:34 +0000718 * Success: TRUE.
719 * Failure: FALSE, if the resulting value will not fit in a DWORD.
Alexandre Julliard0aa6cc22000-07-29 21:56:59 +0000720 */
Jon Griffiths08922852003-08-19 00:56:34 +0000721BOOLEAN WINAPI RtlTimeToSecondsSince1980( const LARGE_INTEGER *Time, LPDWORD Seconds )
Alexandre Julliard0aa6cc22000-07-29 21:56:59 +0000722{
Ge van Geldorp399901e2004-01-23 01:51:33 +0000723 ULONGLONG tmp = ((ULONGLONG)Time->u.HighPart << 32) | Time->u.LowPart;
Robert Shearmanabf2de22005-02-08 12:13:36 +0000724 tmp = RtlLargeIntegerDivide( tmp, TICKSPERSEC, NULL );
Alexandre Julliardfbef57c2003-03-31 01:37:04 +0000725 tmp -= SECS_1601_TO_1980;
Alexandre Julliardd76f9f92000-10-01 01:40:42 +0000726 if (tmp > 0xffffffff) return FALSE;
Jon Griffiths08922852003-08-19 00:56:34 +0000727 *Seconds = (DWORD)tmp;
Alexandre Julliard0aa6cc22000-07-29 21:56:59 +0000728 return TRUE;
729}
730
731/******************************************************************************
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000732 * RtlSecondsSince1970ToTime [NTDLL.@]
733 *
Jon Griffiths08922852003-08-19 00:56:34 +0000734 * Convert a count of seconds since 1970 to a time.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000735 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000736 * PARAMS
Jon Griffiths08922852003-08-19 00:56:34 +0000737 * Seconds [I] Time to convert.
738 * Time [O] Destination for the converted time.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000739 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000740 * RETURNS
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000741 * Nothing.
Alexandre Julliard0aa6cc22000-07-29 21:56:59 +0000742 */
Jon Griffiths08922852003-08-19 00:56:34 +0000743void WINAPI RtlSecondsSince1970ToTime( DWORD Seconds, LARGE_INTEGER *Time )
Alexandre Julliard0aa6cc22000-07-29 21:56:59 +0000744{
Jon Griffiths08922852003-08-19 00:56:34 +0000745 ULONGLONG secs = Seconds * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
Ge van Geldorp399901e2004-01-23 01:51:33 +0000746 Time->u.LowPart = (DWORD)secs;
747 Time->u.HighPart = (DWORD)(secs >> 32);
Alexandre Julliard0aa6cc22000-07-29 21:56:59 +0000748}
749
750/******************************************************************************
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000751 * RtlSecondsSince1980ToTime [NTDLL.@]
752 *
Jon Griffiths08922852003-08-19 00:56:34 +0000753 * Convert a count of seconds since 1980 to a time.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000754 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000755 * PARAMS
Jon Griffiths08922852003-08-19 00:56:34 +0000756 * Seconds [I] Time to convert.
757 * Time [O] Destination for the converted time.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000758 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000759 * RETURNS
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000760 * Nothing.
Alexandre Julliard0aa6cc22000-07-29 21:56:59 +0000761 */
Jon Griffiths08922852003-08-19 00:56:34 +0000762void WINAPI RtlSecondsSince1980ToTime( DWORD Seconds, LARGE_INTEGER *Time )
Alexandre Julliard0aa6cc22000-07-29 21:56:59 +0000763{
Jon Griffiths08922852003-08-19 00:56:34 +0000764 ULONGLONG secs = Seconds * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1980;
Ge van Geldorp399901e2004-01-23 01:51:33 +0000765 Time->u.LowPart = (DWORD)secs;
766 Time->u.HighPart = (DWORD)(secs >> 32);
Juergen Schmied026d9db1999-03-09 17:47:51 +0000767}
768
769/******************************************************************************
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000770 * RtlTimeToElapsedTimeFields [NTDLL.@]
771 *
Jon Griffiths08922852003-08-19 00:56:34 +0000772 * Convert a time to a count of elapsed seconds.
773 *
774 * PARAMS
775 * Time [I] Time to convert.
776 * TimeFields [O] Destination for the converted time.
777 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000778 * RETURNS
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000779 * Nothing.
Juergen Schmied026d9db1999-03-09 17:47:51 +0000780 */
Alexandre Julliarda16ed902002-12-18 02:31:33 +0000781void WINAPI RtlTimeToElapsedTimeFields( const LARGE_INTEGER *Time, PTIME_FIELDS TimeFields )
Juergen Schmied026d9db1999-03-09 17:47:51 +0000782{
Alexandre Julliarda16ed902002-12-18 02:31:33 +0000783 LONGLONG time;
Mike McCormackb5bd4a12005-09-02 14:47:36 +0000784 INT rem;
Alexandre Julliarda16ed902002-12-18 02:31:33 +0000785
786 time = RtlExtendedLargeIntegerDivide( Time->QuadPart, TICKSPERSEC, &rem );
787 TimeFields->Milliseconds = rem / TICKSPERMSEC;
788
789 /* time is now in seconds */
790 TimeFields->Year = 0;
791 TimeFields->Month = 0;
792 TimeFields->Day = RtlExtendedLargeIntegerDivide( time, SECSPERDAY, &rem );
793
794 /* rem is now the remaining seconds in the last day */
795 TimeFields->Second = rem % 60;
796 rem /= 60;
797 TimeFields->Minute = rem % 60;
798 TimeFields->Hour = rem / 60;
Juergen Schmied026d9db1999-03-09 17:47:51 +0000799}
Alexandre Julliardd76f9f92000-10-01 01:40:42 +0000800
801/***********************************************************************
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000802 * NtQuerySystemTime [NTDLL.@]
803 * ZwQuerySystemTime [NTDLL.@]
804 *
Jon Griffiths08922852003-08-19 00:56:34 +0000805 * Get the current system time.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000806 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000807 * PARAMS
Jon Griffiths08922852003-08-19 00:56:34 +0000808 * Time [O] Destination for the current system time.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000809 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000810 * RETURNS
Jon Griffiths08922852003-08-19 00:56:34 +0000811 * Success: STATUS_SUCCESS.
812 * Failure: An NTSTATUS error code indicating the problem.
Alexandre Julliardd76f9f92000-10-01 01:40:42 +0000813 */
Jon Griffiths08922852003-08-19 00:56:34 +0000814NTSTATUS WINAPI NtQuerySystemTime( PLARGE_INTEGER Time )
Alexandre Julliardd76f9f92000-10-01 01:40:42 +0000815{
Alexandre Julliardd76f9f92000-10-01 01:40:42 +0000816 struct timeval now;
817
818 gettimeofday( &now, 0 );
Jon Griffiths08922852003-08-19 00:56:34 +0000819 Time->QuadPart = now.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
820 Time->QuadPart += now.tv_usec * 10;
Patrik Stridvall9c1de6d2002-09-12 22:07:02 +0000821 return STATUS_SUCCESS;
Alexandre Julliardd76f9f92000-10-01 01:40:42 +0000822}
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000823
Alexandre Julliard9ad56282005-07-14 10:32:46 +0000824/******************************************************************************
825 * NtQueryPerformanceCounter [NTDLL.@]
826 *
827 * Note: Windows uses a timer clocked at a multiple of 1193182 Hz. There is a
828 * good number of applications that crash when the returned frequency is either
Francois Gougetebadbd42007-08-09 10:42:59 +0200829 * lower or higher than what Windows gives. Also too high counter values are
Alexandre Julliard9ad56282005-07-14 10:32:46 +0000830 * reported to give problems.
831 */
832NTSTATUS WINAPI NtQueryPerformanceCounter( PLARGE_INTEGER Counter, PLARGE_INTEGER Frequency )
833{
Alexandre Julliardaaf477f2007-04-17 20:08:59 +0200834 LARGE_INTEGER now;
Alexandre Julliard9ad56282005-07-14 10:32:46 +0000835
836 if (!Counter) return STATUS_ACCESS_VIOLATION;
Alexandre Julliardaaf477f2007-04-17 20:08:59 +0200837
838 /* convert a counter that increments at a rate of 10 MHz
Alexandre Julliard9ad56282005-07-14 10:32:46 +0000839 * to one of 1.193182 MHz, with some care for arithmetic
Alexandre Julliardaaf477f2007-04-17 20:08:59 +0200840 * overflow and good accuracy (21/176 = 0.11931818) */
841 NtQuerySystemTime( &now );
842 Counter->QuadPart = ((now.QuadPart - server_start_time) * 21) / 176;
Alexandre Julliard9ad56282005-07-14 10:32:46 +0000843 if (Frequency) Frequency->QuadPart = 1193182;
844 return STATUS_SUCCESS;
845}
846
Jacek Caban2333c802006-04-19 21:21:52 +0200847
848/******************************************************************************
849 * NtGetTickCount (NTDLL.@)
850 * ZwGetTickCount (NTDLL.@)
851 */
852ULONG WINAPI NtGetTickCount(void)
853{
Alexandre Julliardaaf477f2007-04-17 20:08:59 +0200854 LARGE_INTEGER now;
Jacek Caban2333c802006-04-19 21:21:52 +0200855
Alexandre Julliardaaf477f2007-04-17 20:08:59 +0200856 NtQuerySystemTime( &now );
857 return (now.QuadPart - server_start_time) / 10000;
Jacek Caban2333c802006-04-19 21:21:52 +0200858}
859
860
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000861/***********************************************************************
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000862 * TIME_GetTZAsStr [internal]
863 *
864 * Helper function that returns the given timezone as a string.
865 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000866 * PARAMS
867 * utc [I] The current utc time.
868 * bias [I] The bias of the current timezone.
869 * dst [I] ??
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000870 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000871 * RETURNS
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000872 * Timezone name.
873 *
874 * NOTES:
875 * This could be done with a hash table instead of merely iterating through a
876 * table, however with the small amount of entries (60 or so) I didn't think
877 * it was worth it.
878 */
879static const WCHAR* TIME_GetTZAsStr (time_t utc, int bias, int dst)
880{
881 char psTZName[7];
882 struct tm *ptm = localtime(&utc);
Hans Leidekkera9b4a472004-08-13 23:53:44 +0000883 unsigned int i;
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000884
885 if (!strftime (psTZName, 7, "%Z", ptm))
Dmitry Timoshkova1886622007-07-29 21:31:00 +0900886 {
887 WARN("strftime error %d\n", errno);
888 return NULL;
889 }
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000890
891 for (i=0; i<(sizeof(TZ_INFO) / sizeof(struct tagTZ_INFO)); i++)
892 {
893 if ( strcmp(TZ_INFO[i].psTZFromUnix, psTZName) == 0 &&
894 TZ_INFO[i].bias == bias &&
895 TZ_INFO[i].dst == dst
896 )
897 return TZ_INFO[i].psTZWindows;
898 }
Marcelo Duarte37bc4412005-02-14 11:03:05 +0000899 FIXME("Can't match system time zone name \"%s\", bias=%d and dst=%d "
900 "to an entry in TZ_INFO. Please add appropriate entry to "
901 "TZ_INFO and submit as patch to wine-patches\n",psTZName,bias,dst);
Jon Griffiths08922852003-08-19 00:56:34 +0000902 return NULL;
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000903}
904
Rein Klazesc5c93d12004-10-18 21:19:28 +0000905/*** TIME_GetTimeZoneInfoFromReg: helper for GetTimeZoneInformation ***/
906
907
Mike McCormack78911f32005-06-20 18:37:17 +0000908static int TIME_GetTimeZoneInfoFromReg(RTL_TIME_ZONE_INFORMATION *tzinfo)
Rein Klazesc5c93d12004-10-18 21:19:28 +0000909{
910 BYTE buf[90];
911 KEY_VALUE_PARTIAL_INFORMATION * KpInfo =
912 (KEY_VALUE_PARTIAL_INFORMATION *) buf;
Mike McCormack5b2d5fd2005-06-17 13:58:33 +0000913 HANDLE hkey;
Rein Klazesc5c93d12004-10-18 21:19:28 +0000914 DWORD size;
915 OBJECT_ATTRIBUTES attr;
916 UNICODE_STRING nameW;
917
918 attr.Length = sizeof(attr);
919 attr.RootDirectory = 0;
920 attr.ObjectName = &nameW;
921 attr.Attributes = 0;
922 attr.SecurityDescriptor = NULL;
923 attr.SecurityQualityOfService = NULL;
924 RtlInitUnicodeString( &nameW, TZInformationKeyW);
925 if (!NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr )) {
926
927#define GTZIFR_N( valkey, tofield) \
928 RtlInitUnicodeString( &nameW, valkey );\
929 if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, KpInfo,\
930 sizeof(buf), &size )) { \
931 if( size >= (sizeof((tofield)) + \
Mike McCormackc818a4e2005-09-21 09:46:28 +0000932 offsetof(KEY_VALUE_PARTIAL_INFORMATION,Data))) { \
Rein Klazesc5c93d12004-10-18 21:19:28 +0000933 memcpy(&(tofield), \
934 KpInfo->Data, sizeof(tofield)); \
935 } \
936 }
937#define GTZIFR_S( valkey, tofield) \
938 RtlInitUnicodeString( &nameW, valkey );\
939 if (!NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, KpInfo,\
940 sizeof(buf), &size )) { \
Alexandre Julliardb9654572005-04-21 17:18:50 +0000941 size_t len = (strlenW( (WCHAR*)KpInfo->Data ) + 1) * sizeof(WCHAR); \
942 if (len > sizeof(tofield)) len = sizeof(tofield); \
943 memcpy( tofield, KpInfo->Data, len ); \
944 tofield[(len/sizeof(WCHAR))-1] = 0; \
Rein Klazesc5c93d12004-10-18 21:19:28 +0000945 }
Alexandre Julliardb9654572005-04-21 17:18:50 +0000946
Rein Klazesc5c93d12004-10-18 21:19:28 +0000947 GTZIFR_N( TZStandardStartW, tzinfo->StandardDate)
948 GTZIFR_N( TZDaylightStartW, tzinfo->DaylightDate)
949 GTZIFR_N( TZBiasW, tzinfo->Bias)
950 GTZIFR_N( TZStandardBiasW, tzinfo->StandardBias)
951 GTZIFR_N( TZDaylightBiasW, tzinfo->DaylightBias)
952 GTZIFR_S( TZStandardNameW, tzinfo->StandardName)
953 GTZIFR_S( TZDaylightNameW, tzinfo->DaylightName)
954
955#undef GTZIFR_N
956#undef GTZIFR_S
957 NtClose( hkey );
958 return 1;
959 }
960 return 0;
961}
962
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000963/***********************************************************************
964 * RtlQueryTimeZoneInformation [NTDLL.@]
965 *
Jon Griffiths08922852003-08-19 00:56:34 +0000966 * Get information about the current timezone.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000967 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000968 * PARAMS
Jon Griffiths08922852003-08-19 00:56:34 +0000969 * tzinfo [O] Destination for the retrieved timezone info.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000970 *
Jon Griffithscd4234a2003-03-18 18:35:48 +0000971 * RETURNS
Jon Griffiths08922852003-08-19 00:56:34 +0000972 * Success: STATUS_SUCCESS.
973 * Failure: An NTSTATUS error code indicating the problem.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000974 */
Mike McCormack78911f32005-06-20 18:37:17 +0000975NTSTATUS WINAPI RtlQueryTimeZoneInformation(RTL_TIME_ZONE_INFORMATION *tzinfo)
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000976{
977 time_t gmt;
978 int bias, daylight;
979 const WCHAR *psTZ;
980
Mike McCormack78911f32005-06-20 18:37:17 +0000981 memset(tzinfo, 0, sizeof(RTL_TIME_ZONE_INFORMATION));
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000982
Dmitry Timoshkova1886622007-07-29 21:31:00 +0900983 if( !TIME_GetTimeZoneInfoFromReg(tzinfo))
984 {
985 WARN("TIME_GetTimeZoneInfoFromReg failed\n");
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000986
Rein Klazesc5c93d12004-10-18 21:19:28 +0000987 gmt = time(NULL);
988 bias = TIME_GetBias(gmt, &daylight);
Dmitry Timoshkova1886622007-07-29 21:31:00 +0900989 TRACE("bias %d, daylight %d\n", -bias/60, daylight);
Rein Klazesc5c93d12004-10-18 21:19:28 +0000990
991 tzinfo->Bias = -bias / 60;
992 tzinfo->StandardBias = 0;
993 tzinfo->DaylightBias = -60;
994 tzinfo->StandardName[0]='\0';
995 tzinfo->DaylightName[0]='\0';
996 psTZ = TIME_GetTZAsStr (gmt, (-bias/60), daylight);
997 if (psTZ) strcpyW( tzinfo->StandardName, psTZ );
998 }
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +0000999 return STATUS_SUCCESS;
1000}
1001
1002/***********************************************************************
1003 * RtlSetTimeZoneInformation [NTDLL.@]
1004 *
Jon Griffiths08922852003-08-19 00:56:34 +00001005 * Set the current time zone information.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +00001006 *
Jon Griffithscd4234a2003-03-18 18:35:48 +00001007 * PARAMS
Jon Griffiths08922852003-08-19 00:56:34 +00001008 * tzinfo [I] Timezone information to set.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +00001009 *
Jon Griffithscd4234a2003-03-18 18:35:48 +00001010 * RETURNS
Jon Griffiths08922852003-08-19 00:56:34 +00001011 * Success: STATUS_SUCCESS.
1012 * Failure: An NTSTATUS error code indicating the problem.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +00001013 *
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +00001014 */
Mike McCormack78911f32005-06-20 18:37:17 +00001015NTSTATUS WINAPI RtlSetTimeZoneInformation( const RTL_TIME_ZONE_INFORMATION *tzinfo )
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +00001016{
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +00001017 return STATUS_PRIVILEGE_NOT_HELD;
1018}
1019
1020/***********************************************************************
1021 * NtSetSystemTime [NTDLL.@]
1022 * ZwSetSystemTime [NTDLL.@]
1023 *
Jon Griffiths08922852003-08-19 00:56:34 +00001024 * Set the system time.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +00001025 *
Jon Griffiths08922852003-08-19 00:56:34 +00001026 * PARAMS
1027 * NewTime [I] The time to set.
1028 * OldTime [O] Optional destination for the previous system time.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +00001029 *
Jon Griffithscd4234a2003-03-18 18:35:48 +00001030 * RETURNS
Jon Griffiths08922852003-08-19 00:56:34 +00001031 * Success: STATUS_SUCCESS.
1032 * Failure: An NTSTATUS error code indicating the problem.
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +00001033 */
1034NTSTATUS WINAPI NtSetSystemTime(const LARGE_INTEGER *NewTime, LARGE_INTEGER *OldTime)
1035{
1036 TIME_FIELDS tf;
1037 struct timeval tv;
1038 struct timezone tz;
1039 struct tm t;
1040 time_t sec, oldsec;
1041 int dst, bias;
1042 int err;
1043
1044 /* Return the old time if necessary */
1045 if(OldTime)
1046 NtQuerySystemTime(OldTime);
1047
1048 RtlTimeToTimeFields(NewTime, &tf);
1049
1050 /* call gettimeofday to get the current timezone */
1051 gettimeofday(&tv, &tz);
1052 oldsec = tv.tv_sec;
1053 /* get delta local time from utc */
1054 bias = TIME_GetBias(oldsec, &dst);
1055
1056 /* get the number of seconds */
1057 t.tm_sec = tf.Second;
1058 t.tm_min = tf.Minute;
1059 t.tm_hour = tf.Hour;
1060 t.tm_mday = tf.Day;
1061 t.tm_mon = tf.Month - 1;
1062 t.tm_year = tf.Year - 1900;
1063 t.tm_isdst = dst;
1064 sec = mktime (&t);
1065 /* correct for timezone and daylight */
1066 sec += bias;
1067
1068 /* set the new time */
1069 tv.tv_sec = sec;
1070 tv.tv_usec = tf.Milliseconds * 1000;
1071
1072 /* error and sanity check*/
1073 if(sec == (time_t)-1 || abs((int)(sec-oldsec)) > SETTIME_MAX_ADJUST) {
1074 err = 2;
1075 } else {
1076#ifdef HAVE_SETTIMEOFDAY
1077 err = settimeofday(&tv, NULL); /* 0 is OK, -1 is error */
1078 if(err == 0)
1079 return STATUS_SUCCESS;
1080#else
1081 err = 1;
1082#endif
1083 }
1084
1085 ERR("Cannot set time to %d/%d/%d %d:%d:%d Time adjustment %ld %s\n",
1086 tf.Year, tf.Month, tf.Day, tf.Hour, tf.Minute, tf.Second,
Gerald Pfeiferaa0f3792003-10-02 04:29:30 +00001087 (long)(sec-oldsec),
1088 err == -1 ? "No Permission"
1089 : sec == (time_t)-1 ? "" : "is too large." );
György 'Nog' Jeney6f3015b2002-11-25 01:12:39 +00001090
1091 if(err == 2)
1092 return STATUS_INVALID_PARAMETER;
1093 else if(err == -1)
1094 return STATUS_PRIVILEGE_NOT_HELD;
1095 else
1096 return STATUS_NOT_IMPLEMENTED;
1097}