Updated.
[wine] / dlls / kernel / time.c
1 /*
2  * Win32 kernel functions
3  *
4  * Copyright 1995 Martin von Loewis and Cameron Heide
5  */
6
7 #include <string.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <sys/time.h>
11 #include <sys/times.h>
12 #include "file.h"
13 #include "ntddk.h"
14 #include "winerror.h"
15 #include "winnls.h"
16 #include "debugtools.h"
17
18 DEFAULT_DEBUG_CHANNEL(win32);
19
20 /* maximum time adjustment in seconds for SetLocalTime and SetSystemTime */
21 #define SETTIME_MAX_ADJUST 120
22
23 /* TIME_GetBias: helper function calculates delta local time from UTC */
24 static int TIME_GetBias( time_t utc, int *pdaylight)
25 {
26     struct tm *ptm = localtime(&utc);
27     *pdaylight = ptm->tm_isdst; /* daylight for local timezone */
28     ptm = gmtime(&utc);
29     ptm->tm_isdst = *pdaylight; /* use local daylight, not that of Greenwich */
30     return (int)(utc-mktime(ptm));
31 }
32
33
34 /***********************************************************************
35  *              SetLocalTime            (KERNEL32.655)
36  *
37  *  Sets the local time using current time zone and daylight
38  *  savings settings.
39  *
40  * RETURNS
41  *
42  *  True if the time was set, false if the time was invalid or the
43  *  necessary permissions were not held.
44  */
45 BOOL WINAPI SetLocalTime(
46     const SYSTEMTIME *systime) /* [in] The desired local time. */
47 {
48     struct timeval tv;
49     struct tm t;
50     time_t sec;
51     time_t oldsec=time(NULL);
52     int err;
53
54     /* get the number of seconds */
55     t.tm_sec = systime->wSecond;
56     t.tm_min = systime->wMinute;
57     t.tm_hour = systime->wHour;
58     t.tm_mday = systime->wDay;
59     t.tm_mon = systime->wMonth - 1;
60     t.tm_year = systime->wYear - 1900;
61     t.tm_isdst = -1;
62     sec = mktime (&t);
63
64     /* set the new time */
65     tv.tv_sec = sec;
66     tv.tv_usec = systime->wMilliseconds * 1000;
67
68     /* error and sanity check*/
69     if( sec == (time_t)-1 || abs((int)(sec-oldsec)) > SETTIME_MAX_ADJUST ){
70         err = 1;
71         SetLastError(ERROR_INVALID_PARAMETER);
72     } else {
73         err=settimeofday(&tv, NULL); /* 0 is OK, -1 is error */
74         if(err == 0)
75             return TRUE;
76         SetLastError(ERROR_PRIVILEGE_NOT_HELD);
77     }
78     ERR("Cannot set time to %d/%d/%d %d:%d:%d Time adjustment %ld %s\n",
79             systime->wYear, systime->wMonth, systime->wDay, systime->wHour,
80             systime->wMinute, systime->wSecond,
81             sec-oldsec, err == -1 ? "No Permission" : 
82                 sec==(time_t)-1 ? "" : "is too large." );
83     return FALSE;
84 }
85
86
87 /***********************************************************************
88  *           GetSystemTimeAdjustment     (KERNEL32.407)
89  *
90  *  Indicates the period between clock interrupt and the amount the clock
91  *  is adjusted each interrupt so as to keep it insync with an external source.
92  *
93  * RETURNS
94  *
95  *  Always returns true.
96  *
97  * BUGS
98  *
99  *  Only the special case of disabled time adjustments is supported.
100  *  (also the signature is wrong it should have a return type of BOOL)
101  */
102 DWORD WINAPI GetSystemTimeAdjustment(
103     LPDWORD lpTimeAdjustment,         /* [out] The clock adjustment per interupt in 100's of nanoseconds. */
104     LPDWORD lpTimeIncrement,          /* [out] The time between clock interupts in 100's of nanoseconds. */
105     LPBOOL  lpTimeAdjustmentDisabled) /* [out] The clock synchonisation has been disabled. */
106 {
107     *lpTimeAdjustment = 0;
108     *lpTimeIncrement = 0;
109     *lpTimeAdjustmentDisabled = TRUE;
110     return TRUE;
111 }
112
113
114 /***********************************************************************
115  *              SetSystemTime            (KERNEL32.665)
116  *
117  *  Sets the system time (utc).
118  *
119  * RETURNS
120  *
121  *  True if the time was set, false if the time was invalid or the
122  *  necessary permissions were not held.
123  */
124 BOOL WINAPI SetSystemTime(
125     const SYSTEMTIME *systime) /* [in] The desired system time. */
126 {
127     struct timeval tv;
128     struct timezone tz;
129     struct tm t;
130     time_t sec, oldsec;
131     int dst, bias;
132     int err;
133
134     /* call gettimeofday to get the current timezone */
135     gettimeofday(&tv, &tz);
136     oldsec=tv.tv_sec;
137     /* get delta local time from utc */
138     bias=TIME_GetBias(oldsec,&dst);
139
140     /* get the number of seconds */
141     t.tm_sec = systime->wSecond;
142     t.tm_min = systime->wMinute;
143     t.tm_hour = systime->wHour;
144     t.tm_mday = systime->wDay;
145     t.tm_mon = systime->wMonth - 1;
146     t.tm_year = systime->wYear - 1900;
147     t.tm_isdst = dst;
148     sec = mktime (&t);
149     /* correct for timezone and daylight */
150     sec += bias;
151
152     /* set the new time */
153     tv.tv_sec = sec;
154     tv.tv_usec = systime->wMilliseconds * 1000;
155
156     /* error and sanity check*/
157     if( sec == (time_t)-1 || abs((int)(sec-oldsec)) > SETTIME_MAX_ADJUST ){
158         err = 1;
159         SetLastError(ERROR_INVALID_PARAMETER);
160     } else {
161         err=settimeofday(&tv, NULL); /* 0 is OK, -1 is error */
162         if(err == 0)
163             return TRUE;
164         SetLastError(ERROR_PRIVILEGE_NOT_HELD);
165     }
166     ERR("Cannot set time to %d/%d/%d %d:%d:%d Time adjustment %ld %s\n",
167             systime->wYear, systime->wMonth, systime->wDay, systime->wHour,
168             systime->wMinute, systime->wSecond,
169             sec-oldsec, err == -1 ? "No Permission" :
170                 sec==(time_t)-1 ? "" : "is too large." );
171     return FALSE;
172 }
173
174
175 /***********************************************************************
176  *              GetTimeZoneInformation  (KERNEL32.424)
177  *
178  *  Fills in the a time zone information structure with values based on
179  *  the current local time.
180  *
181  * RETURNS
182  *
183  *  The daylight savings time standard or TIME_ZONE_ID_INVALID if the call failed.
184  */
185 DWORD WINAPI GetTimeZoneInformation(
186     LPTIME_ZONE_INFORMATION tzinfo) /* [out] The time zone structure to be filled in. */
187 {
188     time_t gmt;
189     int bias, daylight;
190
191     memset(tzinfo, 0, sizeof(TIME_ZONE_INFORMATION));
192
193     gmt = time(NULL);
194     bias=TIME_GetBias(gmt,&daylight);
195
196     tzinfo->Bias = -bias / 60;
197     tzinfo->StandardBias = 0;
198     tzinfo->DaylightBias = -60;
199
200     return TIME_ZONE_ID_STANDARD;
201 }
202
203
204 /***********************************************************************
205  *              SetTimeZoneInformation  (KERNEL32.673)
206  *
207  *  Set the local time zone with values based on the time zone structure.
208  *
209  * RETURNS
210  *
211  *  True on successful setting of the time zone.
212  *
213  * BUGS
214  *
215  *  Use the obsolete unix timezone structure and tz_dsttime member.
216  */
217 BOOL WINAPI SetTimeZoneInformation(
218     const LPTIME_ZONE_INFORMATION tzinfo) /* [in] The new time zone. */
219 {
220     struct timezone tz;
221
222     tz.tz_minuteswest = tzinfo->Bias;
223 #ifdef DST_NONE
224     tz.tz_dsttime = DST_NONE;
225 #else
226     tz.tz_dsttime = 0;
227 #endif
228     return !settimeofday(NULL, &tz);
229 }
230
231
232 /***********************************************************************
233  *              SystemTimeToTzSpecificLocalTime  (KERNEL32.683)
234  *
235  *  Converts the system time (utc) to the local time in the specified time zone.
236  *
237  * RETURNS
238  *
239  *  Returns true when the local time was calculated.
240  *
241  * BUGS
242  *
243  *  Does not handle daylight savings time adjustments correctly.
244  */
245 BOOL WINAPI SystemTimeToTzSpecificLocalTime(
246     LPTIME_ZONE_INFORMATION lpTimeZoneInformation, /* [in] The desired time zone. */
247     LPSYSTEMTIME            lpUniversalTime,       /* [in] The utc time to base local time on. */
248     LPSYSTEMTIME            lpLocalTime)           /* [out] The local time in the time zone. */
249 {
250   FIXME(":stub\n");
251   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
252        return FALSE;
253 }
254
255
256 /***********************************************************************
257  *              GetSystemTimeAsFileTime  (KERNEL32.408)
258  *
259  *  Fills in a file time structure with the current time in UTC format.
260  */
261 VOID WINAPI GetSystemTimeAsFileTime(
262     LPFILETIME time) /* [out] The file time struct to be filled with the system time. */
263 {
264     NtQuerySystemTime( (LARGE_INTEGER *)time );
265 }
266
267
268 /*********************************************************************
269  *      TIME_ClockTimeToFileTime    (olorin@fandra.org, 20-Sep-1998)
270  *
271  *  Used by GetProcessTimes to convert clock_t into FILETIME.
272  *
273  *      Differences to UnixTimeToFileTime:
274  *          1) Divided by CLK_TCK
275  *          2) Time is relative. There is no 'starting date', so there is 
276  *             no need in offset correction, like in UnixTimeToFileTime
277  */
278 static void TIME_ClockTimeToFileTime(clock_t unix_time, LPFILETIME filetime)
279 {
280     LONGLONG secs = RtlEnlargedUnsignedMultiply( unix_time, 10000000 );
281     ((LARGE_INTEGER *)filetime)->QuadPart = RtlExtendedLargeIntegerDivide( secs, CLK_TCK, NULL );
282 }
283
284 /*********************************************************************
285  *      GetProcessTimes                         (KERNEL32.378)
286  *
287  *  Returns the user and kernel execution times of a process,
288  *  along with the creation and exit times if known.
289  *
290  *  olorin@fandra.org:
291  *  Would be nice to subtract the cpu time, used by Wine at startup.
292  *  Also, there is a need to separate times used by different applications.
293  *
294  * RETURNS
295  *
296  *  Always returns true.
297  *
298  * BUGS
299  *
300  *  lpCreationTime, lpExitTime are NOT INITIALIZED.
301  */
302 BOOL WINAPI GetProcessTimes(
303     HANDLE     hprocess,       /* [in] The process to be queried (obtained from PROCESS_QUERY_INFORMATION). */
304     LPFILETIME lpCreationTime, /* [out] The creation time of the process. */
305     LPFILETIME lpExitTime,     /* [out] The exit time of the process if exited. */
306     LPFILETIME lpKernelTime,   /* [out] The time spent in kernal routines in 100's of nanoseconds. */
307     LPFILETIME lpUserTime)     /* [out] The time spent in user routines in 100's of nanoseconds. */
308 {
309     struct tms tms;
310
311     times(&tms);
312     TIME_ClockTimeToFileTime(tms.tms_utime,lpUserTime);
313     TIME_ClockTimeToFileTime(tms.tms_stime,lpKernelTime);
314     return TRUE;
315 }
316
317 /*********************************************************************
318  *      GetCalendarInfoA                                (KERNEL32)
319  *
320  */
321 int WINAPI GetCalendarInfoA(LCID Locale, CALID Calendar, CALTYPE CalType,
322                             LPSTR lpCalData, int cchData, LPDWORD lpValue)
323 {
324     FIXME("(%08lx,%08lx,%08lx,%p,%d,%p): stub\n", 
325           Locale, Calendar, CalType, lpCalData, cchData, lpValue);
326     return 0;
327 }
328
329 /*********************************************************************
330  *      GetCalendarInfoW                                (KERNEL32)
331  *
332  */
333 int WINAPI GetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType,
334                             LPWSTR lpCalData, int cchData, LPDWORD lpValue)
335 {       
336     FIXME("(%08lx,%08lx,%08lx,%p,%d,%p): stub\n", 
337           Locale, Calendar, CalType, lpCalData, cchData, lpValue);
338     return 0;
339 }
340
341 /*********************************************************************
342  *      SetCalendarInfoA                                (KERNEL32)
343  *
344  */
345 int WINAPI      SetCalendarInfoA(LCID Locale, CALID Calendar, CALTYPE CalType, LPCSTR lpCalData)
346 {
347     FIXME("(%08lx,%08lx,%08lx,%s): stub\n", 
348           Locale, Calendar, CalType, debugstr_a(lpCalData));
349     return 0;
350 }
351
352 /*********************************************************************
353  *      SetCalendarInfoW                                (KERNEL32)
354  *
355  */
356 int WINAPI      SetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType, LPCWSTR lpCalData)
357 {
358     FIXME("(%08lx,%08lx,%08lx,%s): stub\n", 
359           Locale, Calendar, CalType, debugstr_w(lpCalData));
360     return 0;
361 }
362