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

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

Added debug macros

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