Added regedit unit test, a couple minor changes to regedit.
[wine] / dlls / kernel / time.c
1 /*
2  * Win32 kernel functions
3  *
4  * Copyright 1995 Martin von Loewis and Cameron Heide
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <string.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <sys/time.h>
27 #include <sys/times.h>
28 #include "file.h"
29 #include "ntddk.h"
30 #include "winerror.h"
31 #include "winnls.h"
32 #include "wine/unicode.h"
33 #include "wine/debug.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(win32);
36
37 /* maximum time adjustment in seconds for SetLocalTime and SetSystemTime */
38 #define SETTIME_MAX_ADJUST 120
39 #define CALINFO_MAX_YEAR 2029
40
41
42 /* This structure is used to store strings that represent all of the time zones
43    in the world. (This is used to help GetTimeZoneInformation)
44 */
45 struct tagTZ_INFO
46 {
47     const char *psTZFromUnix;
48     WCHAR psTZWindows[32];
49     int bias;
50     int dst;
51 };
52
53 static const struct tagTZ_INFO TZ_INFO[] =
54 {
55    {"MHT",
56     {'D','a','t','e','l','i','n','e',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
57     -720, 0},
58    {"SST",
59     {'S','a','m','o','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
60     660, 0},
61    {"HST",
62     {'H','a','w','a','i','i','a','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
63     600, 0},
64    {"AKDT",
65     {'A','l','a','s','k','a','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
66     480, 1},
67    {"PDT",
68     {'P','a','c','i','f','i','c',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
69     420, 1},
70    {"MST",
71     {'U','S',' ','M','o','u','n','t','a','i','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
72     420, 0},
73    {"MDT",
74     {'M','o','u','n','t','a','i','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
75     360, 1},
76    {"CST",
77     {'C','e','n','t','r','a','l',' ','A','m','e','r','i','c','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
78     360, 0},
79    {"CDT",
80     {'C','e','n','t','r','a','l',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
81     300, 1},
82    {"COT",
83     {'S','A',' ','P','a','c','i','f','i','c',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
84     300, 0},
85    {"EDT",
86     {'E','a','s','t','e','r','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
87      240, 1},
88    {"EST",
89     {'U','S',' ','E','a','s','t','e','r','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
90     300, 0},
91    {"ADT",
92     {'A','t','l','a','n','t','i','c',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
93     180, 1},
94    {"VET",
95     {'S','A',' ','W','e','s','t','e','r','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
96      240, 0},
97    {"CLT",
98     {'P','a','c','i','f','i','c',' ','S','A',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
99      240, 0},
100    {"NDT",
101     {'N','e','w','f','o','u','n','d','l','a','n','d',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
102     150, 1},
103    {"BRT",
104     {'E','.',' ','S','o','u','t','h',' ','A','m','e','r','i','c','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
105     180, 0},
106    {"ART",
107     {'S','A',' ','E','a','s','t','e','r','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
108     180, 0},
109    {"WGST",
110     {'G','r','e','e','n','l','a','n','d',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
111     120, 1},
112    {"GST",
113     {'M','i','d','-','A','t','l','a','n','t','i','c',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
114     120, 0},
115    {"AZOST",
116     {'A','z','o','r','e','s',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
117     0, 1},
118    {"CVT",
119     {'C','a','p','e',' ','V','e','r','d','e',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
120     60, 0},
121    {"WET",
122     {'G','r','e','e','n','w','i','c','h',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
123     0, 0},
124    {"BST",
125     {'G','M','T',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
126     -60, 1},
127    {"GMT",
128     {'G','M','T',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
129     0, 0},
130    {"CEST",
131     {'C','e','n','t','r','a','l',' ','E','u','r','o','p','e',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
132     -120, 1},
133    {"WAT",
134     {'W','.',' ','C','e','n','t','r','a','l',' ','A','f','r','i','c','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
135     -60, 0},
136    {"EEST",
137     {'E','.',' ','E','u','r','o','p','e',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
138     -180, 1},
139    {"EET",
140     {'E','g','y','p','t',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
141     -120, 0},
142    {"CAT",
143     {'S','o','u','t','h',' ','A','f','r','i','c','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
144     -120, 0},
145    {"IST",
146     {'I','s','r','a','e','l',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
147     -120, 0},
148    {"ADT",
149     {'A','r','a','b','i','c',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
150     -240, 1},
151    {"AST",
152     {'A','r','a','b',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
153     -180, 0},
154    {"MSD",
155     {'R','u','s','s','i','a','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
156     -240, 1},
157    {"EAT",
158     {'E','.',' ','A','f','r','i','c','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
159     -180, 0},
160    {"IRST",
161     {'I','r','a','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
162     -270, 1},
163    {"GST",
164     {'A','r','a','b','i','a','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
165     -240, 0},
166    {"AZST",
167     {'C','a','u','c','a','s','u','s',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
168     -300, 1},
169    {"AFT",
170     {'A','f','g','h','a','n','i','s','t','a','n',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
171     -270, 0},
172    {"YEKST",
173     {'E','k','a','t','e','r','i','n','b','u','r','g',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
174     -360, 1},
175    {"PKT",
176     {'W','e','s','t',' ','A','s','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
177     -300, 0},
178    {"IST",
179     {'I','n','d','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
180     -330, 0},
181    {"NPT",
182     {'N','e','p','a','l',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
183     -345, 0},
184    {"ALMST",
185     {'N','.',' ','C','e','n','t','r','a','l',' ','A','s','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
186     -420, 1},
187    {"BDT",
188     {'C','e','n','t','r','a','l',' ','A','s','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
189     -360, 0},
190    {"LKT",
191     {'S','r','i',' ','L','a','n','k','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
192     -360, 0},
193    {"MMT",
194     {'M','y','a','n','m','a','r',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
195     -390, 0},
196    {"ICT",
197     {'S','E',' ','A','s','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
198     -420, 0},
199    {"KRAST",
200     {'N','o','r','t','h',' ','A','s','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
201     -480, 1},
202    {"CST",
203     {'C','h','i','n','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
204     -480, 0},
205    {"IRKST",
206     {'N','o','r','t','h',' ','A','s','i','a',' ','E','a','s','t',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
207     -540, 1},
208    {"SGT",
209     {'M','a','l','a','y',' ','P','e','n','i','n','s','u','l','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
210     -480, 0},
211    {"WST",
212     {'W','.',' ','A','u','s','t','r','a','l','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
213     -480, 0},
214    {"JST",
215     {'T','o','k','y','o',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
216     -540, 0},
217    {"KST",
218     {'K','o','r','e','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
219     -540, 0},
220    {"YAKST",
221     {'Y','a','k','u','t','s','k',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
222     -600, 1},
223    {"CST",
224     {'C','e','n','.',' ','A','u','s','t','r','a','l','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
225     -570, 0},
226    {"EST",
227     {'E','.',' ','A','u','s','t','r','a','l','i','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
228     -600, 0},
229    {"GST",
230     {'W','e','s','t',' ','P','a','c','i','f','i','c',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
231     -600, 0},
232    {"VLAST",
233     {'V','l','a','d','i','v','o','s','t','o','k',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
234     -660, 1},
235    {"MAGST",
236     {'C','e','n','t','r','a','l',' ','P','a','c','i','f','i','c',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
237     -720, 1},
238    {"NZST",
239     {'N','e','w',' ','Z','e','a','l','a','n','d',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
240     -720, 0},
241    {"FJT",
242     {'F','i','j','i',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
243     -720, 0},
244    {"TOT",
245     {'T','o','n','g','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e','\0'},
246     -780, 0}
247 };
248
249 /* TIME_GetTZAsStr: helper function that returns the given timezone as a string.
250    This could be done with a hash table instead of merely iterating through
251    a table, however with the small amount of entries (60 or so) I didn't think
252    it was worth it. */
253 static const WCHAR* TIME_GetTZAsStr (time_t utc, int bias, int dst)
254 {
255    char psTZName[7];
256    struct tm *ptm = localtime(&utc);
257    int i;
258
259    if (!strftime (psTZName, 7, "%Z", ptm))
260       return (NULL);
261
262    for (i=0; i<(sizeof(TZ_INFO) / sizeof(struct tagTZ_INFO)); i++)
263    {
264       if ( strcmp(TZ_INFO[i].psTZFromUnix, psTZName) == 0 &&
265            TZ_INFO[i].bias == bias &&
266            TZ_INFO[i].dst == dst
267          )
268             return TZ_INFO[i].psTZWindows;
269    }
270
271    return (NULL);
272 }
273
274
275 /* TIME_GetBias: helper function calculates delta local time from UTC */
276 static int TIME_GetBias( time_t utc, int *pdaylight)
277 {
278     struct tm *ptm = localtime(&utc);
279     *pdaylight = ptm->tm_isdst; /* daylight for local timezone */
280     ptm = gmtime(&utc);
281     ptm->tm_isdst = *pdaylight; /* use local daylight, not that of Greenwich */
282     return (int)(utc-mktime(ptm));
283 }
284
285
286 /***********************************************************************
287  *              SetLocalTime            (KERNEL32.@)
288  *
289  *  Sets the local time using current time zone and daylight
290  *  savings settings.
291  *
292  * RETURNS
293  *
294  *  True if the time was set, false if the time was invalid or the
295  *  necessary permissions were not held.
296  */
297 BOOL WINAPI SetLocalTime(
298     const SYSTEMTIME *systime) /* [in] The desired local time. */
299 {
300     struct timeval tv;
301     struct tm t;
302     time_t sec;
303     time_t oldsec=time(NULL);
304     int err;
305
306     /* get the number of seconds */
307     t.tm_sec = systime->wSecond;
308     t.tm_min = systime->wMinute;
309     t.tm_hour = systime->wHour;
310     t.tm_mday = systime->wDay;
311     t.tm_mon = systime->wMonth - 1;
312     t.tm_year = systime->wYear - 1900;
313     t.tm_isdst = -1;
314     sec = mktime (&t);
315
316     /* set the new time */
317     tv.tv_sec = sec;
318     tv.tv_usec = systime->wMilliseconds * 1000;
319
320     /* error and sanity check*/
321     if( sec == (time_t)-1 || abs((int)(sec-oldsec)) > SETTIME_MAX_ADJUST ){
322         err = 1;
323         SetLastError(ERROR_INVALID_PARAMETER);
324     } else {
325 #ifdef HAVE_SETTIMEOFDAY
326         err=settimeofday(&tv, NULL); /* 0 is OK, -1 is error */
327         if(err == 0)
328             return TRUE;
329         SetLastError(ERROR_PRIVILEGE_NOT_HELD);
330 #else
331         err = 1;
332         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
333 #endif
334     }
335     ERR("Cannot set time to %d/%d/%d %d:%d:%d Time adjustment %ld %s\n",
336             systime->wYear, systime->wMonth, systime->wDay, systime->wHour,
337             systime->wMinute, systime->wSecond,
338             sec-oldsec, err == -1 ? "No Permission" :
339                 sec==(time_t)-1 ? "" : "is too large." );
340     return FALSE;
341 }
342
343
344 /***********************************************************************
345  *           GetSystemTimeAdjustment     (KERNEL32.@)
346  *
347  *  Indicates the period between clock interrupt and the amount the clock
348  *  is adjusted each interrupt so as to keep it insync with an external source.
349  *
350  * RETURNS
351  *
352  *  Always returns true.
353  *
354  * BUGS
355  *
356  *  Only the special case of disabled time adjustments is supported.
357  */
358 BOOL WINAPI GetSystemTimeAdjustment(
359     PDWORD lpTimeAdjustment,         /* [out] The clock adjustment per interupt in 100's of nanoseconds. */
360     PDWORD lpTimeIncrement,          /* [out] The time between clock interupts in 100's of nanoseconds. */
361     PBOOL  lpTimeAdjustmentDisabled) /* [out] The clock synchonisation has been disabled. */
362 {
363     *lpTimeAdjustment = 0;
364     *lpTimeIncrement = 0;
365     *lpTimeAdjustmentDisabled = TRUE;
366     return TRUE;
367 }
368
369
370 /***********************************************************************
371  *              SetSystemTime            (KERNEL32.@)
372  *
373  *  Sets the system time (utc).
374  *
375  * RETURNS
376  *
377  *  True if the time was set, false if the time was invalid or the
378  *  necessary permissions were not held.
379  */
380 BOOL WINAPI SetSystemTime(
381     const SYSTEMTIME *systime) /* [in] The desired system time. */
382 {
383     struct timeval tv;
384     struct timezone tz;
385     struct tm t;
386     time_t sec, oldsec;
387     int dst, bias;
388     int err;
389
390     /* call gettimeofday to get the current timezone */
391     gettimeofday(&tv, &tz);
392     oldsec=tv.tv_sec;
393     /* get delta local time from utc */
394     bias=TIME_GetBias(oldsec,&dst);
395
396     /* get the number of seconds */
397     t.tm_sec = systime->wSecond;
398     t.tm_min = systime->wMinute;
399     t.tm_hour = systime->wHour;
400     t.tm_mday = systime->wDay;
401     t.tm_mon = systime->wMonth - 1;
402     t.tm_year = systime->wYear - 1900;
403     t.tm_isdst = dst;
404     sec = mktime (&t);
405     /* correct for timezone and daylight */
406     sec += bias;
407
408     /* set the new time */
409     tv.tv_sec = sec;
410     tv.tv_usec = systime->wMilliseconds * 1000;
411
412     /* error and sanity check*/
413     if( sec == (time_t)-1 || abs((int)(sec-oldsec)) > SETTIME_MAX_ADJUST ){
414         err = 1;
415         SetLastError(ERROR_INVALID_PARAMETER);
416     } else {
417 #ifdef HAVE_SETTIMEOFDAY
418         err=settimeofday(&tv, NULL); /* 0 is OK, -1 is error */
419         if(err == 0)
420             return TRUE;
421         SetLastError(ERROR_PRIVILEGE_NOT_HELD);
422 #else
423         err = 1;
424         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
425 #endif
426     }
427     ERR("Cannot set time to %d/%d/%d %d:%d:%d Time adjustment %ld %s\n",
428             systime->wYear, systime->wMonth, systime->wDay, systime->wHour,
429             systime->wMinute, systime->wSecond,
430             sec-oldsec, err == -1 ? "No Permission" :
431                 sec==(time_t)-1 ? "" : "is too large." );
432     return FALSE;
433 }
434
435
436 /***********************************************************************
437  *              GetTimeZoneInformation  (KERNEL32.@)
438  *
439  *  Fills in the a time zone information structure with values based on
440  *  the current local time.
441  *
442  * RETURNS
443  *
444  *  The daylight savings time standard or TIME_ZONE_ID_INVALID if the call failed.
445  */
446 DWORD WINAPI GetTimeZoneInformation(
447     LPTIME_ZONE_INFORMATION tzinfo) /* [out] The time zone structure to be filled in. */
448 {
449     time_t gmt;
450     int bias, daylight;
451     const WCHAR *psTZ;
452
453
454     memset(tzinfo, 0, sizeof(TIME_ZONE_INFORMATION));
455
456     gmt = time(NULL);
457     bias=TIME_GetBias(gmt,&daylight);
458
459     tzinfo->Bias = -bias / 60;
460     tzinfo->StandardBias = 0;
461     tzinfo->DaylightBias = -60;
462     psTZ = TIME_GetTZAsStr (gmt, (-bias/60), daylight);
463     if (psTZ) strcpyW( tzinfo->StandardName, psTZ );
464     return TIME_ZONE_ID_STANDARD;
465 }
466
467
468 /***********************************************************************
469  *              SetTimeZoneInformation  (KERNEL32.@)
470  *
471  *  Set the local time zone with values based on the time zone structure.
472  *
473  * RETURNS
474  *
475  *  True on successful setting of the time zone.
476  *
477  * BUGS
478  *
479  *  Use the obsolete unix timezone structure and tz_dsttime member.
480  */
481 BOOL WINAPI SetTimeZoneInformation(
482     const LPTIME_ZONE_INFORMATION tzinfo) /* [in] The new time zone. */
483 {
484     struct timezone tz;
485
486     tz.tz_minuteswest = tzinfo->Bias;
487 #ifdef DST_NONE
488     tz.tz_dsttime = DST_NONE;
489 #else
490     tz.tz_dsttime = 0;
491 #endif
492     return !settimeofday(NULL, &tz);
493 }
494
495
496 /***********************************************************************
497  *              SystemTimeToTzSpecificLocalTime  (KERNEL32.@)
498  *
499  *  Converts the system time (utc) to the local time in the specified time zone.
500  *
501  * RETURNS
502  *
503  *  Returns true when the local time was calculated.
504  *
505  * BUGS
506  *
507  *  Does not handle daylight savings time adjustments correctly.
508  */
509 BOOL WINAPI SystemTimeToTzSpecificLocalTime(
510     LPTIME_ZONE_INFORMATION lpTimeZoneInformation, /* [in] The desired time zone. */
511     LPSYSTEMTIME            lpUniversalTime,       /* [in] The utc time to base local time on. */
512     LPSYSTEMTIME            lpLocalTime)           /* [out] The local time in the time zone. */
513 {
514   FIXME(":stub\n");
515   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
516        return FALSE;
517 }
518
519
520 /***********************************************************************
521  *              GetSystemTimeAsFileTime  (KERNEL32.@)
522  *
523  *  Fills in a file time structure with the current time in UTC format.
524  */
525 VOID WINAPI GetSystemTimeAsFileTime(
526     LPFILETIME time) /* [out] The file time struct to be filled with the system time. */
527 {
528     NtQuerySystemTime( (LARGE_INTEGER *)time );
529 }
530
531
532 /*********************************************************************
533  *      TIME_ClockTimeToFileTime    (olorin@fandra.org, 20-Sep-1998)
534  *
535  *  Used by GetProcessTimes to convert clock_t into FILETIME.
536  *
537  *      Differences to UnixTimeToFileTime:
538  *          1) Divided by CLK_TCK
539  *          2) Time is relative. There is no 'starting date', so there is
540  *             no need in offset correction, like in UnixTimeToFileTime
541  */
542 static void TIME_ClockTimeToFileTime(clock_t unix_time, LPFILETIME filetime)
543 {
544     ULONGLONG secs = RtlEnlargedUnsignedMultiply( unix_time, 10000000 );
545     secs = RtlExtendedLargeIntegerDivide( secs, CLK_TCK, NULL );
546     filetime->dwLowDateTime  = (DWORD)secs;
547     filetime->dwHighDateTime = (DWORD)(secs >> 32);
548 }
549
550 /*********************************************************************
551  *      GetProcessTimes                         (KERNEL32.@)
552  *
553  *  Returns the user and kernel execution times of a process,
554  *  along with the creation and exit times if known.
555  *
556  *  olorin@fandra.org:
557  *  Would be nice to subtract the cpu time, used by Wine at startup.
558  *  Also, there is a need to separate times used by different applications.
559  *
560  * RETURNS
561  *
562  *  Always returns true.
563  *
564  * BUGS
565  *
566  *  lpCreationTime, lpExitTime are NOT INITIALIZED.
567  */
568 BOOL WINAPI GetProcessTimes(
569     HANDLE     hprocess,       /* [in] The process to be queried (obtained from PROCESS_QUERY_INFORMATION). */
570     LPFILETIME lpCreationTime, /* [out] The creation time of the process. */
571     LPFILETIME lpExitTime,     /* [out] The exit time of the process if exited. */
572     LPFILETIME lpKernelTime,   /* [out] The time spent in kernal routines in 100's of nanoseconds. */
573     LPFILETIME lpUserTime)     /* [out] The time spent in user routines in 100's of nanoseconds. */
574 {
575     struct tms tms;
576
577     times(&tms);
578     TIME_ClockTimeToFileTime(tms.tms_utime,lpUserTime);
579     TIME_ClockTimeToFileTime(tms.tms_stime,lpKernelTime);
580     return TRUE;
581 }
582
583 /*********************************************************************
584  *      GetCalendarInfoA                                (KERNEL32.@)
585  *
586  */
587 int WINAPI GetCalendarInfoA(LCID Locale, CALID Calendar, CALTYPE CalType,
588                             LPSTR lpCalData, int cchData, LPDWORD lpValue)
589 {
590     int ret;
591     LPWSTR lpCalDataW = NULL;
592
593     FIXME("(%08lx,%08lx,%08lx,%p,%d,%p): quarter-stub\n",
594           Locale, Calendar, CalType, lpCalData, cchData, lpValue);
595     /* FIXME: Should verify if Locale is allowable in ANSI, as per MSDN */
596
597     if(cchData)
598       if(!(lpCalDataW = HeapAlloc(GetProcessHeap(), 0, cchData*sizeof(WCHAR)))) return 0;
599
600     ret = GetCalendarInfoW(Locale, Calendar, CalType, lpCalDataW, cchData, lpValue);
601     if(ret && lpCalDataW && lpCalData)
602       WideCharToMultiByte(CP_ACP, 0, lpCalDataW, cchData, lpCalData, cchData, NULL, NULL);
603     if(lpCalDataW)
604       HeapFree(GetProcessHeap(), 0, lpCalDataW);
605
606     return ret;
607 }
608
609 /*********************************************************************
610  *      GetCalendarInfoW                                (KERNEL32.@)
611  *
612  */
613 int WINAPI GetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType,
614                             LPWSTR lpCalData, int cchData, LPDWORD lpValue)
615 {
616     FIXME("(%08lx,%08lx,%08lx,%p,%d,%p): quarter-stub\n",
617           Locale, Calendar, CalType, lpCalData, cchData, lpValue);
618
619     if (CalType & CAL_NOUSEROVERRIDE)
620         FIXME("flag CAL_NOUSEROVERRIDE used, not fully implemented\n");
621     if (CalType & CAL_USE_CP_ACP)
622         FIXME("flag CAL_USE_CP_ACP used, not fully implemented\n");
623
624     if (CalType & CAL_RETURN_NUMBER) {
625         if (lpCalData != NULL)
626             WARN("lpCalData not NULL (%p) when it should!\n", lpCalData);
627         if (cchData != 0)
628             WARN("cchData not 0 (%d) when it should!\n", cchData);
629     } else {
630         if (lpValue != NULL)
631             WARN("lpValue not NULL (%p) when it should!\n", lpValue);
632     }
633
634     /* FIXME: No verification is made yet wrt Locale
635      * for the CALTYPES not requiring GetLocaleInfoA */
636     switch (CalType & ~(CAL_NOUSEROVERRIDE|CAL_RETURN_NUMBER|CAL_USE_CP_ACP)) {
637         case CAL_ICALINTVALUE:
638             FIXME("Unimplemented caltype %ld\n", CalType & 0xffff);
639             return E_FAIL;
640         case CAL_SCALNAME:
641             FIXME("Unimplemented caltype %ld\n", CalType & 0xffff);
642             return E_FAIL;
643         case CAL_IYEAROFFSETRANGE:
644             FIXME("Unimplemented caltype %ld\n", CalType & 0xffff);
645             return E_FAIL;
646         case CAL_SERASTRING:
647             FIXME("Unimplemented caltype %ld\n", CalType & 0xffff);
648             return E_FAIL;
649         case CAL_SSHORTDATE:
650             return GetLocaleInfoW(Locale, LOCALE_SSHORTDATE, lpCalData, cchData);
651         case CAL_SLONGDATE:
652             return GetLocaleInfoW(Locale, LOCALE_SLONGDATE, lpCalData, cchData);
653         case CAL_SDAYNAME1:
654             return GetLocaleInfoW(Locale, LOCALE_SDAYNAME1, lpCalData, cchData);
655         case CAL_SDAYNAME2:
656             return GetLocaleInfoW(Locale, LOCALE_SDAYNAME2, lpCalData, cchData);
657         case CAL_SDAYNAME3:
658             return GetLocaleInfoW(Locale, LOCALE_SDAYNAME3, lpCalData, cchData);
659         case CAL_SDAYNAME4:
660             return GetLocaleInfoW(Locale, LOCALE_SDAYNAME4, lpCalData, cchData);
661         case CAL_SDAYNAME5:
662             return GetLocaleInfoW(Locale, LOCALE_SDAYNAME5, lpCalData, cchData);
663         case CAL_SDAYNAME6:
664             return GetLocaleInfoW(Locale, LOCALE_SDAYNAME6, lpCalData, cchData);
665         case CAL_SDAYNAME7:
666             return GetLocaleInfoW(Locale, LOCALE_SDAYNAME7, lpCalData, cchData);
667         case CAL_SABBREVDAYNAME1:
668             return GetLocaleInfoW(Locale, LOCALE_SABBREVDAYNAME1, lpCalData, cchData);
669         case CAL_SABBREVDAYNAME2:
670             return GetLocaleInfoW(Locale, LOCALE_SABBREVDAYNAME2, lpCalData, cchData);
671         case CAL_SABBREVDAYNAME3:
672             return GetLocaleInfoW(Locale, LOCALE_SABBREVDAYNAME3, lpCalData, cchData);
673         case CAL_SABBREVDAYNAME4:
674             return GetLocaleInfoW(Locale, LOCALE_SABBREVDAYNAME4, lpCalData, cchData);
675         case CAL_SABBREVDAYNAME5:
676             return GetLocaleInfoW(Locale, LOCALE_SABBREVDAYNAME5, lpCalData, cchData);
677         case CAL_SABBREVDAYNAME6:
678             return GetLocaleInfoW(Locale, LOCALE_SABBREVDAYNAME6, lpCalData, cchData);
679         case CAL_SABBREVDAYNAME7:
680             return GetLocaleInfoW(Locale, LOCALE_SABBREVDAYNAME7, lpCalData, cchData);
681         case CAL_SMONTHNAME1:
682             return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME1, lpCalData, cchData);
683         case CAL_SMONTHNAME2:
684             return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME2, lpCalData, cchData);
685         case CAL_SMONTHNAME3:
686             return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME3, lpCalData, cchData);
687         case CAL_SMONTHNAME4:
688             return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME4, lpCalData, cchData);
689         case CAL_SMONTHNAME5:
690             return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME5, lpCalData, cchData);
691         case CAL_SMONTHNAME6:
692             return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME6, lpCalData, cchData);
693         case CAL_SMONTHNAME7:
694             return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME7, lpCalData, cchData);
695         case CAL_SMONTHNAME8:
696             return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME8, lpCalData, cchData);
697         case CAL_SMONTHNAME9:
698             return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME9, lpCalData, cchData);
699         case CAL_SMONTHNAME10:
700             return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME10, lpCalData, cchData);
701         case CAL_SMONTHNAME11:
702             return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME11, lpCalData, cchData);
703         case CAL_SMONTHNAME12:
704             return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME12, lpCalData, cchData);
705         case CAL_SMONTHNAME13:
706             return GetLocaleInfoW(Locale, LOCALE_SMONTHNAME13, lpCalData, cchData);
707         case CAL_SABBREVMONTHNAME1:
708             return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME1, lpCalData, cchData);
709         case CAL_SABBREVMONTHNAME2:
710             return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME2, lpCalData, cchData);
711         case CAL_SABBREVMONTHNAME3:
712             return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME3, lpCalData, cchData);
713         case CAL_SABBREVMONTHNAME4:
714             return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME4, lpCalData, cchData);
715         case CAL_SABBREVMONTHNAME5:
716             return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME5, lpCalData, cchData);
717         case CAL_SABBREVMONTHNAME6:
718             return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME6, lpCalData, cchData);
719         case CAL_SABBREVMONTHNAME7:
720             return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME7, lpCalData, cchData);
721         case CAL_SABBREVMONTHNAME8:
722             return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME8, lpCalData, cchData);
723         case CAL_SABBREVMONTHNAME9:
724             return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME9, lpCalData, cchData);
725         case CAL_SABBREVMONTHNAME10:
726             return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME10, lpCalData, cchData);
727         case CAL_SABBREVMONTHNAME11:
728             return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME11, lpCalData, cchData);
729         case CAL_SABBREVMONTHNAME12:
730             return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME12, lpCalData, cchData);
731         case CAL_SABBREVMONTHNAME13:
732             return GetLocaleInfoW(Locale, LOCALE_SABBREVMONTHNAME13, lpCalData, cchData);
733         case CAL_SYEARMONTH:
734             return GetLocaleInfoW(Locale, LOCALE_SYEARMONTH, lpCalData, cchData);
735         case CAL_ITWODIGITYEARMAX:
736             if (lpValue) *lpValue = CALINFO_MAX_YEAR;
737             break;
738         default: MESSAGE("Unknown caltype %ld\n",CalType & 0xffff);
739                  return E_FAIL;
740     }
741     return 0;
742 }
743
744 /*********************************************************************
745  *      SetCalendarInfoA                                (KERNEL32.@)
746  *
747  */
748 int WINAPI      SetCalendarInfoA(LCID Locale, CALID Calendar, CALTYPE CalType, LPCSTR lpCalData)
749 {
750     FIXME("(%08lx,%08lx,%08lx,%s): stub\n",
751           Locale, Calendar, CalType, debugstr_a(lpCalData));
752     return 0;
753 }
754
755 /*********************************************************************
756  *      SetCalendarInfoW                                (KERNEL32.@)
757  *
758  */
759 int WINAPI      SetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType, LPCWSTR lpCalData)
760 {
761     FIXME("(%08lx,%08lx,%08lx,%s): stub\n",
762           Locale, Calendar, CalType, debugstr_w(lpCalData));
763     return 0;
764 }
765