source: trunk/src/kernel32/time.cpp@ 4213

Last change on this file since 4213 was 4213, checked in by phaller, 25 years ago

.

File size: 20.0 KB
Line 
1/* $Id: time.cpp,v 1.12 2000-09-08 00:33:16 phaller Exp $ */
2
3/*
4 * Win32 time/date API functions
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1999 Christoph Bratschi (cbratschi@datacomm.ch)
8 *
9 * Copyright 1996 Alexandre Julliard
10 * Copyright 1995 Martin von Loewis
11 * Copyright 1998 David Lee Lambert
12
13 *
14 * Project Odin Software License can be found in LICENSE.TXT
15 */
16
17
18/*****************************************************************************
19 * Includes *
20 *****************************************************************************/
21
22#include <odin.h>
23#include <odinwrap.h>
24#include <os2sel.h>
25
26#include <os2win.h>
27
28#include <winnls.h>
29#include "winuser.h"
30#include <stdlib.h>
31#include <string.h>
32#include <stdio.h>
33#include "unicode.h"
34
35#define DBG_LOCALLOG DBG_time
36#include "dbglocal.h"
37
38/*****************************************************************************
39 * Defines *
40 *****************************************************************************/
41
42ODINDEBUGCHANNEL(KERNEL32-TIME)
43
44
45
46#define lstrcpynAtoW(unicode,ascii,asciilen) AsciiToUnicodeN(ascii,unicode,asciilen);
47
48#define WPRINTF_LEFTALIGN 0x0001 /* Align output on the left ('-' prefix) */
49#define WPRINTF_PREFIX_HEX 0x0002 /* Prefix hex with 0x ('#' prefix) */
50#define WPRINTF_ZEROPAD 0x0004 /* Pad with zeros ('0' prefix) */
51#define WPRINTF_LONG 0x0008 /* Long arg ('l' prefix) */
52#define WPRINTF_SHORT 0x0010 /* Short arg ('h' prefix) */
53#define WPRINTF_UPPER_HEX 0x0020 /* Upper-case hex ('X' specifier) */
54#define WPRINTF_WIDE 0x0040 /* Wide arg ('w' prefix) */
55
56typedef enum
57{
58 WPR_UNKNOWN,
59 WPR_CHAR,
60 WPR_WCHAR,
61 WPR_STRING,
62 WPR_WSTRING,
63 WPR_SIGNED,
64 WPR_UNSIGNED,
65 WPR_HEXA
66} WPRINTF_TYPE;
67
68typedef struct
69{
70 UINT flags;
71 UINT width;
72 UINT precision;
73 WPRINTF_TYPE type;
74} WPRINTF_FORMAT;
75
76typedef union {
77 WCHAR wchar_view;
78 CHAR char_view;
79 LPCSTR lpcstr_view;
80 LPCWSTR lpcwstr_view;
81 INT int_view;
82} WPRINTF_DATA;
83
84static const CHAR null_stringA[] = "(null)";
85static const WCHAR null_stringW[] = { '(', 'n', 'u', 'l', 'l', ')', 0 };
86
87//******************************************************************************
88//******************************************************************************
89VOID WIN32API GetLocalTime( LPSYSTEMTIME arg1)
90{
91/// dprintf(("KERNEL32: GetLocalTime\n"));
92 O32_GetLocalTime(arg1);
93}
94//******************************************************************************
95//******************************************************************************
96BOOL WIN32API SetLocalTime( const SYSTEMTIME * arg1)
97{
98 dprintf(("KERNEL32: SetLocalTime\n"));
99 return O32_SetLocalTime(arg1);
100}
101//******************************************************************************
102//******************************************************************************
103BOOL WIN32API FileTimeToDosDateTime(const FILETIME * arg1, LPWORD arg2, LPWORD arg3)
104{
105 dprintf(("KERNEL32: FileTimeToDosDateTime\n"));
106 return O32_FileTimeToDosDateTime(arg1, arg2, arg3);
107}
108//******************************************************************************
109//******************************************************************************
110BOOL WIN32API FileTimeToLocalFileTime(const FILETIME * arg1, LPFILETIME arg2)
111{
112 dprintf(("KERNEL32: FileTimeToLocalFileTime\n"));
113 return O32_FileTimeToLocalFileTime(arg1, arg2);
114}
115//******************************************************************************
116//******************************************************************************
117BOOL WIN32API LocalFileTimeToFileTime(const FILETIME * arg1, LPFILETIME arg2)
118{
119 dprintf(("KERNEL32: LocalFileTimeToFileTime\n"));
120 return O32_LocalFileTimeToFileTime(arg1, arg2);
121}
122//******************************************************************************
123//******************************************************************************
124BOOL WIN32API FileTimeToSystemTime(const FILETIME * arg1, LPSYSTEMTIME arg2)
125{
126 dprintf(("KERNEL32: FileTimeToSystemTime"));
127 return O32_FileTimeToSystemTime(arg1, arg2);
128}
129//******************************************************************************
130//******************************************************************************
131BOOL WIN32API DosDateTimeToFileTime( WORD arg1, WORD arg2, LPFILETIME arg3)
132{
133 dprintf(("KERNEL32: DosDateTimeToFileTime\n"));
134 return O32_DosDateTimeToFileTime(arg1, arg2, arg3);
135}
136//******************************************************************************
137//******************************************************************************
138DWORD WIN32API GetTimeZoneInformation( LPTIME_ZONE_INFORMATION arg1)
139{
140 dprintf(("KERNEL32: GetTimeZoneInformation\n"));
141 return O32_GetTimeZoneInformation(arg1);
142}
143//******************************************************************************
144//******************************************************************************
145DWORD WIN32API GetTickCount(void)
146{
147//// dprintf(("KERNEL32: GetTickCount\n"));
148 return O32_GetTickCount();
149}
150//******************************************************************************
151//******************************************************************************
152ODINPROCEDURE1(GetSystemTime,
153 LPSYSTEMTIME, arg1)
154{
155 O32_GetSystemTime(arg1);
156}
157//******************************************************************************
158//******************************************************************************
159BOOL WIN32API SystemTimeToFileTime( const SYSTEMTIME * arg1, LPFILETIME arg2)
160{
161 dprintf(("KERNEL32: OS2SystemTimeToFileTime\n"));
162 return O32_SystemTimeToFileTime(arg1, arg2);
163}
164//******************************************************************************
165//******************************************************************************
166BOOL WIN32API SystemTimeToTzSpecificLocalTime( LPTIME_ZONE_INFORMATION arg1, LPSYSTEMTIME arg2, LPSYSTEMTIME arg3)
167{
168 dprintf(("KERNEL32: OS2SystemTimeToTzSpecificLocalTime\n"));
169 return O32_SystemTimeToTzSpecificLocalTime(arg1, arg2, arg3);
170}
171//******************************************************************************
172//******************************************************************************
173BOOL WIN32API SetTimeZoneInformation( const LPTIME_ZONE_INFORMATION arg1)
174{
175 dprintf(("KERNEL32: OS2SetTimeZoneInformation\n"));
176 return O32_SetTimeZoneInformation(arg1);
177}
178//******************************************************************************
179//******************************************************************************
180BOOL WIN32API SetSystemTime(const SYSTEMTIME * arg1)
181{
182 dprintf(("KERNEL32: OS2SetSystemTime\n"));
183 return O32_SetSystemTime(arg1);
184}
185
186/***********************************************************************
187 * WPRINTF_ParseFormatA
188 *
189 * Parse a format specification. A format specification has the form:
190 *
191 * [-][#][0][width][.precision]type
192 *
193 * Return value is the length of the format specification in characters.
194 */
195static INT WPRINTF_ParseFormatA( LPCSTR format, WPRINTF_FORMAT *res )
196{
197 LPCSTR p = format;
198
199 res->flags = 0;
200 res->width = 0;
201 res->precision = 0;
202 if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
203 if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
204 if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
205 while ((*p >= '0') && (*p <= '9')) /* width field */
206 {
207 res->width = res->width * 10 + *p - '0';
208 p++;
209 }
210 if (*p == '.') /* precision field */
211 {
212 p++;
213 while ((*p >= '0') && (*p <= '9'))
214 {
215 res->precision = res->precision * 10 + *p - '0';
216 p++;
217 }
218 }
219 if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
220 else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
221 else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
222 switch(*p)
223 {
224 case 'c':
225 res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
226 break;
227 case 'C':
228 res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
229 break;
230 case 'd':
231 case 'i':
232 res->type = WPR_SIGNED;
233 break;
234 case 's':
235 res->type = (res->flags & (WPRINTF_LONG |WPRINTF_WIDE))
236 ? WPR_WSTRING : WPR_STRING;
237 break;
238 case 'S':
239 res->type = (res->flags & (WPRINTF_SHORT|WPRINTF_WIDE))
240 ? WPR_STRING : WPR_WSTRING;
241 break;
242 case 'u':
243 res->type = WPR_UNSIGNED;
244 break;
245 case 'X':
246 res->flags |= WPRINTF_UPPER_HEX;
247 /* fall through */
248 case 'x':
249 res->type = WPR_HEXA;
250 break;
251 default: /* unknown format char */
252 res->type = WPR_UNKNOWN;
253 p--; /* print format as normal char */
254 break;
255 }
256 return (INT)(p - format) + 1;
257}
258
259
260/***********************************************************************
261 * WPRINTF_ParseFormatW
262 *
263 * Parse a format specification. A format specification has the form:
264 *
265 * [-][#][0][width][.precision]type
266 *
267 * Return value is the length of the format specification in characters.
268 */
269static INT WPRINTF_ParseFormatW( LPCWSTR format, WPRINTF_FORMAT *res )
270{
271 LPCWSTR p = format;
272
273 res->flags = 0;
274 res->width = 0;
275 res->precision = 0;
276 if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
277 if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
278 if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
279 while ((*p >= '0') && (*p <= '9')) /* width field */
280 {
281 res->width = res->width * 10 + *p - '0';
282 p++;
283 }
284 if (*p == '.') /* precision field */
285 {
286 p++;
287 while ((*p >= '0') && (*p <= '9'))
288 {
289 res->precision = res->precision * 10 + *p - '0';
290 p++;
291 }
292 }
293 if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
294 else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
295 else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
296 switch((CHAR)*p)
297 {
298 case 'c':
299 res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
300 break;
301 case 'C':
302 res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
303 break;
304 case 'd':
305 case 'i':
306 res->type = WPR_SIGNED;
307 break;
308 case 's':
309 res->type = ((res->flags & WPRINTF_SHORT) && !(res->flags & WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING;
310 break;
311 case 'S':
312 res->type = (res->flags & (WPRINTF_LONG|WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING;
313 break;
314 case 'u':
315 res->type = WPR_UNSIGNED;
316 break;
317 case 'X':
318 res->flags |= WPRINTF_UPPER_HEX;
319 /* fall through */
320 case 'x':
321 res->type = WPR_HEXA;
322 break;
323 default:
324 res->type = WPR_UNKNOWN;
325 p--; /* print format as normal char */
326 break;
327 }
328 return (INT)(p - format) + 1;
329}
330
331
332/***********************************************************************
333 * WPRINTF_GetLen
334 */
335static UINT WPRINTF_GetLen( WPRINTF_FORMAT *format, WPRINTF_DATA *arg,
336 LPSTR number, UINT maxlen )
337{
338 UINT len;
339
340 if (format->flags & WPRINTF_LEFTALIGN) format->flags &= ~WPRINTF_ZEROPAD;
341 if (format->width > maxlen) format->width = maxlen;
342 switch(format->type)
343 {
344 case WPR_CHAR:
345 case WPR_WCHAR:
346 return (format->precision = 1);
347 case WPR_STRING:
348 if (!arg->lpcstr_view) arg->lpcstr_view = null_stringA;
349 for (len = 0; !format->precision || (len < format->precision); len++)
350 if (!*(arg->lpcstr_view + len)) break;
351 if (len > maxlen) len = maxlen;
352 return (format->precision = len);
353 case WPR_WSTRING:
354 if (!arg->lpcwstr_view) arg->lpcwstr_view = null_stringW;
355 for (len = 0; !format->precision || (len < format->precision); len++)
356 if (!*(arg->lpcwstr_view + len)) break;
357 if (len > maxlen) len = maxlen;
358 return (format->precision = len);
359 case WPR_SIGNED:
360 len = sprintf( number, "%d", arg->int_view );
361 break;
362 case WPR_UNSIGNED:
363 len = sprintf( number, "%u", (UINT)arg->int_view );
364 break;
365 case WPR_HEXA:
366 len = sprintf( number,
367 (format->flags & WPRINTF_UPPER_HEX) ? "%X" : "%x",
368 (UINT)arg->int_view);
369 if (format->flags & WPRINTF_PREFIX_HEX) len += 2;
370 break;
371 default:
372 return 0;
373 }
374 if (len > maxlen) len = maxlen;
375 if (format->precision < len) format->precision = len;
376 if (format->precision > maxlen) format->precision = maxlen;
377 if ((format->flags & WPRINTF_ZEROPAD) && (format->width > format->precision))
378 format->precision = format->width;
379 return len;
380}
381
382/***********************************************************************
383 * WPRINTF_ExtractVAPtr (Not a Windows API)
384 */
385static WPRINTF_DATA WPRINTF_ExtractVAPtr( WPRINTF_FORMAT *format, va_list* args )
386{
387 WPRINTF_DATA result;
388 switch(format->type)
389 {
390 case WPR_WCHAR:
391 result.wchar_view = va_arg( *args, WCHAR ); break;
392 case WPR_CHAR:
393 result.char_view = va_arg( *args, CHAR ); break;
394 case WPR_STRING:
395 result.lpcstr_view = va_arg( *args, LPCSTR); break;
396 case WPR_WSTRING:
397 result.lpcwstr_view = va_arg( *args, LPCWSTR); break;
398 case WPR_HEXA:
399 case WPR_SIGNED:
400 case WPR_UNSIGNED:
401 result.int_view = va_arg( *args, INT ); break;
402 default:
403 result.wchar_view = 0; break;
404 }
405 return result;
406}
407
408/***********************************************************************
409 * wvsnprintfA (Not a Windows API)
410 */
411INT WINAPI wvsnprintfA( LPSTR buffer, UINT maxlen, LPCSTR spec,
412 va_list args )
413{
414 WPRINTF_FORMAT format;
415 LPSTR p = buffer;
416 UINT i, len;
417 CHAR number[20];
418 WPRINTF_DATA argData;
419
420 while (*spec && (maxlen > 1))
421 {
422 if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
423 spec++;
424 if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
425 spec += WPRINTF_ParseFormatA( spec, &format );
426 argData = WPRINTF_ExtractVAPtr( &format, &args );
427 len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 );
428 if (!(format.flags & WPRINTF_LEFTALIGN))
429 for (i = format.precision; i < format.width; i++, maxlen--)
430 *p++ = ' ';
431 switch(format.type)
432 {
433 case WPR_WCHAR:
434 *p = argData.wchar_view;
435 if (*p != '\0') p++;
436 else if (format.width > 1) *p++ = ' ';
437 else len = 0;
438 break;
439 case WPR_CHAR:
440 *p = argData.char_view;
441 if (*p != '\0') p++;
442 else if (format.width > 1) *p++ = ' ';
443 else len = 0;
444 break;
445 case WPR_STRING:
446 memcpy( p, argData.lpcstr_view, len );
447 p += len;
448 break;
449 case WPR_WSTRING:
450 {
451 LPCWSTR ptr = argData.lpcwstr_view;
452 for (i = 0; i < len; i++) *p++ = (CHAR)*ptr++;
453 }
454 break;
455 case WPR_HEXA:
456 if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
457 {
458 *p++ = '0';
459 *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
460 maxlen -= 2;
461 len -= 2;
462 format.precision -= 2;
463 format.width -= 2;
464 }
465 /* fall through */
466 case WPR_SIGNED:
467 case WPR_UNSIGNED:
468 for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
469 memcpy( p, number, len );
470 p += len;
471 /* Go to the next arg */
472 break;
473 case WPR_UNKNOWN:
474 continue;
475 }
476 if (format.flags & WPRINTF_LEFTALIGN)
477 for (i = format.precision; i < format.width; i++, maxlen--)
478 *p++ = ' ';
479 maxlen -= len;
480 }
481 *p = 0;
482 //TRACE("%s\n",buffer);
483 return (maxlen > 1) ? (INT)(p - buffer) : -1;
484}
485
486
487/***********************************************************************
488 * wvsnprintfW (Not a Windows API)
489 */
490INT WINAPI wvsnprintfW( LPWSTR buffer, UINT maxlen, LPCWSTR spec,
491 va_list args )
492{
493 WPRINTF_FORMAT format;
494 LPWSTR p = buffer;
495 UINT i, len;
496 CHAR number[20];
497
498 while (*spec && (maxlen > 1))
499 {
500 if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
501 spec++;
502 if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
503 spec += WPRINTF_ParseFormatW( spec, &format );
504 len = WPRINTF_GetLen( &format, (WPRINTF_DATA*)args, number, maxlen - 1 );
505 if (!(format.flags & WPRINTF_LEFTALIGN))
506 for (i = format.precision; i < format.width; i++, maxlen--)
507 *p++ = ' ';
508 switch(format.type)
509 {
510 case WPR_WCHAR:
511 *p = va_arg( args, WCHAR );
512 if (*p != '\0') p++;
513 else if (format.width > 1) *p++ = ' ';
514 else len = 0;
515 break;
516 case WPR_CHAR:
517 *p = (WCHAR)va_arg( args, CHAR );
518 if (*p != '\0') p++;
519 else if (format.width > 1) *p++ = ' ';
520 else len = 0;
521 break;
522 case WPR_STRING:
523 {
524 LPCSTR ptr = va_arg( args, LPCSTR );
525 for (i = 0; i < len; i++) *p++ = (WCHAR)*ptr++;
526 }
527 break;
528 case WPR_WSTRING:
529 if (len) memcpy( p, va_arg( args, LPCWSTR ), len * sizeof(WCHAR) );
530 p += len;
531 break;
532 case WPR_HEXA:
533 if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
534 {
535 *p++ = '0';
536 *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
537 maxlen -= 2;
538 len -= 2;
539 format.precision -= 2;
540 format.width -= 2;
541 }
542 /* fall through */
543 case WPR_SIGNED:
544 case WPR_UNSIGNED:
545 for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
546 for (i = 0; i < len; i++) *p++ = (WCHAR)number[i];
547 (void)va_arg( args, INT ); /* Go to the next arg */
548 break;
549 case WPR_UNKNOWN:
550 continue;
551 }
552 if (format.flags & WPRINTF_LEFTALIGN)
553 for (i = format.precision; i < format.width; i++, maxlen--)
554 *p++ = ' ';
555 maxlen -= len;
556 }
557 *p = 0;
558 return (maxlen > 1) ? (INT)(p - buffer) : -1;
559}
560
561/***********************************************************************
562 * wsnprintfA (Not a Windows API)
563 */
564INT WINAPIV wsnprintfA( LPSTR buffer, UINT maxlen, LPCSTR spec, ... )
565{
566 va_list valist;
567 INT res;
568
569 va_start( valist, spec );
570 res = wvsnprintfA( buffer, maxlen, spec, valist );
571 va_end( valist );
572 return res;
573}
574
575/***********************************************************************
576 * wsnprintfW (Not a Windows API)
577 */
578INT WINAPIV wsnprintfW( LPWSTR buffer, UINT maxlen, LPCWSTR spec, ... )
579{
580 va_list valist;
581 INT res;
582
583 va_start( valist, spec );
584 res = wvsnprintfW( buffer, maxlen, spec, valist );
585 va_end( valist );
586 return res;
587}
588
589
590/*****************************************************************************
591 * Name : DWORD GetSystemTimeAsFileTime
592 * Purpose : The GetSystemTimeAsFileTime function obtains the current system
593 * date and time. The information is in Coordinated Universal Time (UTC) format.
594 * Parameters: LLPFILETIME lLPSYSTEMTIMEAsFileTime
595 * Variables :
596 * Result :
597 * Remark :
598 * Status : UNTESTED
599 *
600 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
601 *****************************************************************************/
602
603VOID WIN32API GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime)
604{
605 FILETIME ft; /* code sequence from WIN32.HLP */
606 SYSTEMTIME st;
607
608 dprintf(("KERNEL32: GetSystemTimeAsFileTime(%08xh)\n", lpSystemTimeAsFileTime));
609
610 GetSystemTime(&st);
611 SystemTimeToFileTime(&st, &ft);
612}
Note: See TracBrowser for help on using the repository browser.