ReactOS  0.4.15-dev-1367-g07cc0b5
lcformat.c
Go to the documentation of this file.
1 /*
2  * Locale-dependent format handling
3  *
4  * Copyright 1995 Martin von Loewis
5  * Copyright 1998 David Lee Lambert
6  * Copyright 2000 Julio César Gázquez
7  * Copyright 2003 Jon Griffiths
8  * Copyright 2005 Dmitry Timoshkov
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
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #ifdef __REACTOS__
26 
27 #include <k32.h>
28 #include "japanese.h" /* Japanese eras */
29 
30 #define NDEBUG
31 #include <debug.h>
33 
34 #define CRITICAL_SECTION RTL_CRITICAL_SECTION
35 #define CRITICAL_SECTION_DEBUG RTL_CRITICAL_SECTION_DEBUG
36 #define CALINFO_MAX_YEAR 2029
37 
38 #define IS_LCID_JAPANESE(lcid) PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_JAPANESE
39 
40 #ifndef CAL_SABBREVERASTRING
41  #define CAL_SABBREVERASTRING 0x00000039
42 #endif
43 
44 #else /* __REACTOS__ */
45 
46 #include "config.h"
47 #include "wine/port.h"
48 
49 #include <string.h>
50 #include <stdarg.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 
54 #include "windef.h"
55 #include "winbase.h"
56 #include "wine/unicode.h"
57 #include "wine/debug.h"
58 #include "winternl.h"
59 
60 #include "kernel_private.h"
61 
63 
64 #endif /* __REACTOS__ */
65 
66 #define DATE_DATEVARSONLY 0x0100 /* only date stuff: yMdg */
67 #define TIME_TIMEVARSONLY 0x0200 /* only time stuff: hHmst */
68 
69 /* Since calculating the formatting data for each locale is time-consuming,
70  * we get the format data for each locale only once and cache it in memory.
71  * We cache both the system default and user overridden data, after converting
72  * them into the formats that the functions here expect. Since these functions
73  * will typically be called with only a small number of the total locales
74  * installed, the memory overhead is minimal while the speedup is significant.
75  *
76  * Our cache takes the form of a singly linked list, whose node is below:
77  */
78 #define NLS_NUM_CACHED_STRINGS 57
79 
80 typedef struct _NLS_FORMAT_NODE
81 {
82  LCID lcid; /* Locale Id */
83  DWORD dwFlags; /* 0 or LOCALE_NOUSEROVERRIDE */
84  DWORD dwCodePage; /* Default code page (if LOCALE_USE_ANSI_CP not given) */
85  NUMBERFMTW fmt; /* Default format for numbers */
86  CURRENCYFMTW cyfmt; /* Default format for currencies */
87  LPWSTR lppszStrings[NLS_NUM_CACHED_STRINGS]; /* Default formats,day/month names */
88  WCHAR szShortAM[2]; /* Short 'AM' marker */
89  WCHAR szShortPM[2]; /* Short 'PM' marker */
92 
93 /* Macros to get particular data strings from a format node */
94 #define GetNegative(fmt) fmt->lppszStrings[0]
95 #define GetLongDate(fmt) fmt->lppszStrings[1]
96 #define GetShortDate(fmt) fmt->lppszStrings[2]
97 #define GetTime(fmt) fmt->lppszStrings[3]
98 #define GetAM(fmt) fmt->lppszStrings[54]
99 #define GetPM(fmt) fmt->lppszStrings[55]
100 #define GetYearMonth(fmt) fmt->lppszStrings[56]
101 
102 #define GetLongDay(fmt,day) fmt->lppszStrings[4 + day]
103 #define GetShortDay(fmt,day) fmt->lppszStrings[11 + day]
104 #define GetLongMonth(fmt,mth) fmt->lppszStrings[18 + mth]
105 #define GetGenitiveMonth(fmt,mth) fmt->lppszStrings[30 + mth]
106 #define GetShortMonth(fmt,mth) fmt->lppszStrings[42 + mth]
107 
108 /* Write access to the cache is protected by this critical section */
111 {
112  0, 0, &NLS_FormatsCS,
115 #ifdef __REACTOS__
116  0, 0, 0
117 #else
118  0, 0, { (DWORD_PTR)(__FILE__ ": NLS_Formats") }
119 #endif
120 };
121 static CRITICAL_SECTION NLS_FormatsCS = { &NLS_FormatsCS_debug, -1, 0, 0, 0, 0 };
122 
123 /**************************************************************************
124  * NLS_GetLocaleNumber <internal>
125  *
126  * Get a numeric locale format value.
127  */
129 {
130  WCHAR szBuff[80];
131  DWORD dwVal = 0;
132 
133  szBuff[0] = '\0';
134  GetLocaleInfoW(lcid, dwFlags, szBuff, ARRAY_SIZE(szBuff));
135 
136  if (szBuff[0] && szBuff[1] == ';' && szBuff[2] != '0')
137  dwVal = (szBuff[0] - '0') * 10 + (szBuff[2] - '0');
138  else
139  {
140  const WCHAR* iter = szBuff;
141  dwVal = 0;
142  while(*iter >= '0' && *iter <= '9')
143  dwVal = dwVal * 10 + (*iter++ - '0');
144  }
145  return dwVal;
146 }
147 
148 /**************************************************************************
149  * NLS_GetLocaleString <internal>
150  *
151  * Get a string locale format value.
152  */
154 {
155  WCHAR szBuff[80], *str;
156  DWORD dwLen;
157 
158  szBuff[0] = '\0';
159  GetLocaleInfoW(lcid, dwFlags, szBuff, ARRAY_SIZE(szBuff));
160  dwLen = strlenW(szBuff) + 1;
161  str = HeapAlloc(GetProcessHeap(), 0, dwLen * sizeof(WCHAR));
162  if (str)
163  memcpy(str, szBuff, dwLen * sizeof(WCHAR));
164  return str;
165 }
166 
167 #define GET_LOCALE_NUMBER(num, type) num = NLS_GetLocaleNumber(lcid, type|dwFlags); \
168  TRACE( #type ": %d (%08x)\n", (DWORD)num, (DWORD)num)
169 
170 #define GET_LOCALE_STRING(str, type) str = NLS_GetLocaleString(lcid, type|dwFlags); \
171  TRACE( #type ": %s\n", debugstr_w(str))
172 
173 /**************************************************************************
174  * NLS_GetFormats <internal>
175  *
176  * Calculate (and cache) the number formats for a locale.
177  */
179 {
180  /* GetLocaleInfo() identifiers for cached formatting strings */
181  static const LCTYPE NLS_LocaleIndices[] = {
211  LOCALE_SYEARMONTH
212  };
213  static NLS_FORMAT_NODE *NLS_CachedFormats = NULL;
214  NLS_FORMAT_NODE *node = NLS_CachedFormats;
215 
217 
218  TRACE("(0x%04x,0x%08x)\n", lcid, dwFlags);
219 
220  /* See if we have already cached the locales number format */
221  while (node && (node->lcid != lcid || node->dwFlags != dwFlags) && node->next)
222  node = node->next;
223 
224  if (!node || node->lcid != lcid || node->dwFlags != dwFlags)
225  {
226  NLS_FORMAT_NODE *new_node;
227  DWORD i;
228 
229  TRACE("Creating new cache entry\n");
230 
231  if (!(new_node = HeapAlloc(GetProcessHeap(), 0, sizeof(NLS_FORMAT_NODE))))
232  return NULL;
233 
235 
236  /* Number Format */
237  new_node->lcid = lcid;
238  new_node->dwFlags = dwFlags;
239  new_node->next = NULL;
240 
244 
246  if (new_node->fmt.Grouping > 9 && new_node->fmt.Grouping != 32)
247  {
248  WARN("LOCALE_SGROUPING (%d) unhandled, please report!\n",
249  new_node->fmt.Grouping);
250  new_node->fmt.Grouping = 0;
251  }
252 
255 
256  /* Currency Format */
257  new_node->cyfmt.NumDigits = new_node->fmt.NumDigits;
258  new_node->cyfmt.LeadingZero = new_node->fmt.LeadingZero;
259 
261 
262  if (new_node->cyfmt.Grouping > 9)
263  {
264  WARN("LOCALE_SMONGROUPING (%d) unhandled, please report!\n",
265  new_node->cyfmt.Grouping);
266  new_node->cyfmt.Grouping = 0;
267  }
268 
270  if (new_node->cyfmt.NegativeOrder > 15)
271  {
272  WARN("LOCALE_INEGCURR (%d) unhandled, please report!\n",
273  new_node->cyfmt.NegativeOrder);
274  new_node->cyfmt.NegativeOrder = 0;
275  }
277  if (new_node->cyfmt.PositiveOrder > 3)
278  {
279  WARN("LOCALE_IPOSCURR (%d) unhandled,please report!\n",
280  new_node->cyfmt.PositiveOrder);
281  new_node->cyfmt.PositiveOrder = 0;
282  }
286 
287  /* Date/Time Format info, negative character, etc */
288  for (i = 0; i < ARRAY_SIZE(NLS_LocaleIndices); i++)
289  {
290  GET_LOCALE_STRING(new_node->lppszStrings[i], NLS_LocaleIndices[i]);
291  }
292  /* Save some memory if month genitive name is the same or not present */
293  for (i = 0; i < 12; i++)
294  {
295  if (strcmpW(GetLongMonth(new_node, i), GetGenitiveMonth(new_node, i)) == 0)
296  {
297  HeapFree(GetProcessHeap(), 0, GetGenitiveMonth(new_node, i));
298  GetGenitiveMonth(new_node, i) = NULL;
299  }
300  }
301 
302  new_node->szShortAM[0] = GetAM(new_node)[0]; new_node->szShortAM[1] = '\0';
303  new_node->szShortPM[0] = GetPM(new_node)[0]; new_node->szShortPM[1] = '\0';
304 
305  /* Now add the computed format to the cache */
307 
308  /* Search again: We may have raced to add the node */
309  node = NLS_CachedFormats;
310  while (node && (node->lcid != lcid || node->dwFlags != dwFlags) && node->next)
311  node = node->next;
312 
313  if (!node)
314  {
315  node = NLS_CachedFormats = new_node; /* Empty list */
316  new_node = NULL;
317  }
318  else if (node->lcid != lcid || node->dwFlags != dwFlags)
319  {
320  node->next = new_node; /* Not in the list, add to end */
321  node = new_node;
322  new_node = NULL;
323  }
324 
326 
327  if (new_node)
328  {
329  /* We raced and lost: The node was already added by another thread.
330  * node points to the currently cached node, so free new_node.
331  */
332  for (i = 0; i < ARRAY_SIZE(NLS_LocaleIndices); i++)
333  HeapFree(GetProcessHeap(), 0, new_node->lppszStrings[i]);
334  HeapFree(GetProcessHeap(), 0, new_node->fmt.lpDecimalSep);
335  HeapFree(GetProcessHeap(), 0, new_node->fmt.lpThousandSep);
336  HeapFree(GetProcessHeap(), 0, new_node->cyfmt.lpDecimalSep);
337  HeapFree(GetProcessHeap(), 0, new_node->cyfmt.lpThousandSep);
339  HeapFree(GetProcessHeap(), 0, new_node);
340  }
341  }
342  return node;
343 }
344 
345 /**************************************************************************
346  * NLS_IsUnicodeOnlyLcid <internal>
347  *
348  * Determine if a locale is Unicode only, and thus invalid in ASCII calls.
349  */
351 {
353 
354  switch (PRIMARYLANGID(lcid))
355  {
356  case LANG_ARMENIAN:
357  case LANG_DIVEHI:
358  case LANG_GEORGIAN:
359  case LANG_GUJARATI:
360  case LANG_HINDI:
361  case LANG_KANNADA:
362  case LANG_KONKANI:
363  case LANG_MARATHI:
364  case LANG_PUNJABI:
365  case LANG_SANSKRIT:
366  TRACE("lcid 0x%08x: langid 0x%4x is Unicode Only\n", lcid, PRIMARYLANGID(lcid));
367  return TRUE;
368  default:
369  return FALSE;
370  }
371 }
372 
373 /*
374  * Formatting of dates, times, numbers and currencies.
375  */
376 
377 #define IsLiteralMarker(p) (p == '\'')
378 #define IsDateFmtChar(p) (p == 'd'||p == 'M'||p == 'y'||p == 'g')
379 #define IsTimeFmtChar(p) (p == 'H'||p == 'h'||p == 'm'||p == 's'||p == 't')
380 
381 /* Only the following flags can be given if a date/time format is specified */
382 #ifdef __REACTOS__
383 #define DATE_FORMAT_FLAGS (DATE_DATEVARSONLY | DATE_USE_ALT_CALENDAR)
384 #else
385 #define DATE_FORMAT_FLAGS (DATE_DATEVARSONLY)
386 #endif
387 #define TIME_FORMAT_FLAGS (TIME_TIMEVARSONLY|TIME_FORCE24HOURFORMAT| \
388  TIME_NOMINUTESORSECONDS|TIME_NOSECONDS| \
389  TIME_NOTIMEMARKER)
390 
391 /******************************************************************************
392  * NLS_GetDateTimeFormatW <internal>
393  *
394  * Performs the formatting for GetDateFormatW/GetTimeFormatW.
395  *
396  * FIXME
397  * DATE_USE_ALT_CALENDAR - Requires GetCalendarInfo to work first.
398  * DATE_LTRREADING/DATE_RTLREADING - Not yet implemented.
399  */
401  const SYSTEMTIME* lpTime, LPCWSTR lpFormat,
402  LPWSTR lpStr, INT cchOut)
403 {
404  const NLS_FORMAT_NODE *node;
405  SYSTEMTIME st;
406  INT cchWritten = 0;
407  INT lastFormatPos = 0;
408  BOOL bSkipping = FALSE; /* Skipping text around marker? */
409  BOOL d_dd_formatted = FALSE; /* previous formatted part was for d or dd */
410 
411  /* Verify our arguments */
412  if ((cchOut && !lpStr) || !(node = NLS_GetFormats(lcid, dwFlags)))
413  goto invalid_parameter;
414 
416  {
417  if (lpFormat &&
420  {
421  goto invalid_flags;
422  }
423 
425  {
426  if ((dwFlags & (DATE_LTRREADING|DATE_RTLREADING)) == (DATE_LTRREADING|DATE_RTLREADING))
427  goto invalid_flags;
428  else if (dwFlags & (DATE_LTRREADING|DATE_RTLREADING))
429  FIXME("Unsupported flags: DATE_LTRREADING/DATE_RTLREADING\n");
430 
431  switch (dwFlags & (DATE_SHORTDATE|DATE_LONGDATE|DATE_YEARMONTH))
432  {
433  case 0:
434  break;
435  case DATE_SHORTDATE:
436  case DATE_LONGDATE:
437  case DATE_YEARMONTH:
438  if (lpFormat)
439  goto invalid_flags;
440  break;
441  default:
442  goto invalid_flags;
443  }
444  }
445  }
446 
447  if (!lpFormat)
448  {
449  /* Use the appropriate default format */
451  {
452  if (dwFlags & DATE_YEARMONTH)
454  else if (dwFlags & DATE_LONGDATE)
456  else
458  }
459  else
460  lpFormat = GetTime(node);
461  }
462 
463  if (!lpTime)
464  {
465  GetLocalTime(&st); /* Default to current time */
466  lpTime = &st;
467  }
468  else
469  {
471  {
472  FILETIME ftTmp;
473 
474  /* Verify the date and correct the D.O.W. if needed */
475  memset(&st, 0, sizeof(st));
476  st.wYear = lpTime->wYear;
477  st.wMonth = lpTime->wMonth;
478  st.wDay = lpTime->wDay;
479 
480  if (st.wDay > 31 || st.wMonth > 12 || !SystemTimeToFileTime(&st, &ftTmp))
481  goto invalid_parameter;
482 
483  FileTimeToSystemTime(&ftTmp, &st);
484  lpTime = &st;
485  }
486 
488  {
489  /* Verify the time */
490  if (lpTime->wHour > 24 || lpTime->wMinute > 59 || lpTime->wSecond > 59)
491  goto invalid_parameter;
492  }
493  }
494 
495  /* Format the output */
496  while (*lpFormat)
497  {
499  {
500  /* Start of a literal string */
501  lpFormat++;
502 
503  /* Loop until the end of the literal marker or end of the string */
504  while (*lpFormat)
505  {
507  {
508  lpFormat++;
509  if (!IsLiteralMarker(*lpFormat))
510  break; /* Terminating literal marker */
511  }
512 
513  if (!cchOut)
514  cchWritten++; /* Count size only */
515  else if (cchWritten >= cchOut)
516  goto overrun;
517  else if (!bSkipping)
518  {
519  lpStr[cchWritten] = *lpFormat;
520  cchWritten++;
521  }
522  lpFormat++;
523  }
524  }
525  else if ((dwFlags & DATE_DATEVARSONLY && IsDateFmtChar(*lpFormat)) ||
527  {
528  WCHAR buff[32], fmtChar;
529  LPCWSTR szAdd = NULL;
530  DWORD dwVal = 0;
531  int count = 0, dwLen;
532 
533  bSkipping = FALSE;
534 
535  fmtChar = *lpFormat;
536  while (*lpFormat == fmtChar)
537  {
538  count++;
539  lpFormat++;
540  }
541  buff[0] = '\0';
542 
543  if (fmtChar != 'M') d_dd_formatted = FALSE;
544  switch(fmtChar)
545  {
546  case 'd':
547  if (count >= 4)
548  szAdd = GetLongDay(node, (lpTime->wDayOfWeek + 6) % 7);
549  else if (count == 3)
550  szAdd = GetShortDay(node, (lpTime->wDayOfWeek + 6) % 7);
551  else
552  {
553  dwVal = lpTime->wDay;
554  szAdd = buff;
555  d_dd_formatted = TRUE;
556  }
557  break;
558 
559  case 'M':
560  if (count >= 4)
561  {
562  LPCWSTR genitive = GetGenitiveMonth(node, lpTime->wMonth - 1);
563  if (genitive)
564  {
565  if (d_dd_formatted)
566  {
567  szAdd = genitive;
568  break;
569  }
570  else
571  {
573  /* Look forward now, if next format pattern is for day genitive
574  name should be used */
575  while (*format)
576  {
577  /* Skip parts within markers */
578  if (IsLiteralMarker(*format))
579  {
580  ++format;
581  while (*format)
582  {
583  if (IsLiteralMarker(*format))
584  {
585  ++format;
586  if (!IsLiteralMarker(*format)) break;
587  }
588  }
589  }
590  if (*format != ' ') break;
591  ++format;
592  }
593  /* Only numeric day form matters */
594  if (*format == 'd')
595  {
596  INT dcount = 1;
597  while (*++format == 'd') dcount++;
598  if (dcount < 3)
599  {
600  szAdd = genitive;
601  break;
602  }
603  }
604  }
605  }
606  szAdd = GetLongMonth(node, lpTime->wMonth - 1);
607  }
608  else if (count == 3)
609  szAdd = GetShortMonth(node, lpTime->wMonth - 1);
610  else
611  {
612  dwVal = lpTime->wMonth;
613  szAdd = buff;
614  }
615  break;
616 
617  case 'y':
618 #ifdef __REACTOS__
619  if (IS_LCID_JAPANESE(lcid) && (dwFlags & DATE_USE_ALT_CALENDAR))
620  {
621  PCJAPANESE_ERA pEra = JapaneseEra_Find(lpTime);
622  if (pEra)
623  {
624  if (count >= 2)
625  {
626  count = 2;
627  }
628 
629  dwVal = lpTime->wYear - pEra->wYear + 1;
630 
631  if (dwVal == 1 && JapaneseEra_IsFirstYearGannen())
632  {
633  // Gan of 'Gannen'
634  buff[0] = 0x5143;
635  buff[1] = 0;
636  }
637  szAdd = buff;
638  break;
639  }
641  return 0;
642  }
643 #endif
644  if (count >= 4)
645  {
646  count = 4;
647  dwVal = lpTime->wYear;
648  }
649  else
650  {
651  count = count > 2 ? 2 : count;
652  dwVal = lpTime->wYear % 100;
653  }
654  szAdd = buff;
655  break;
656 
657  case 'g':
658 #ifdef __REACTOS__
659  if (IS_LCID_JAPANESE(lcid))
660  {
662  {
663  PCJAPANESE_ERA pEra = JapaneseEra_Find(lpTime);
664  if (pEra)
665  {
666  RtlStringCbCopyW(buff, sizeof(buff), pEra->szEraName);
667  szAdd = buff;
668  break;
669  }
671  return 0;
672  }
673  else
674  {
675  /* Seireki */
676  buff[0] = 0x897F;
677  buff[1] = 0x66A6;
678  buff[2] = 0;
679  szAdd = buff;
680  break;
681  }
682  }
683 #endif
684  if (count == 2)
685  {
686  /* FIXME: Our GetCalendarInfo() does not yet support CAL_SERASTRING.
687  * When it is fixed, this string should be cached in 'node'.
688  */
689  FIXME("Should be using GetCalendarInfo(CAL_SERASTRING), defaulting to 'AD'\n");
690  buff[0] = 'A'; buff[1] = 'D'; buff[2] = '\0';
691  }
692  else
693  {
694  buff[0] = 'g'; buff[1] = '\0'; /* Add a literal 'g' */
695  }
696  szAdd = buff;
697  break;
698 
699  case 'h':
701  {
702  count = count > 2 ? 2 : count;
703  dwVal = lpTime->wHour == 0 ? 12 : (lpTime->wHour - 1) % 12 + 1;
704  szAdd = buff;
705  break;
706  }
707  /* .. fall through if we are forced to output in 24 hour format */
708 
709  case 'H':
710  count = count > 2 ? 2 : count;
711  dwVal = lpTime->wHour;
712  szAdd = buff;
713  break;
714 
715  case 'm':
717  {
718  cchWritten = lastFormatPos; /* Skip */
719  bSkipping = TRUE;
720  }
721  else
722  {
723  count = count > 2 ? 2 : count;
724  dwVal = lpTime->wMinute;
725  szAdd = buff;
726  }
727  break;
728 
729  case 's':
731  {
732  cchWritten = lastFormatPos; /* Skip */
733  bSkipping = TRUE;
734  }
735  else
736  {
737  count = count > 2 ? 2 : count;
738  dwVal = lpTime->wSecond;
739  szAdd = buff;
740  }
741  break;
742 
743  case 't':
745  {
746  cchWritten = lastFormatPos; /* Skip */
747  bSkipping = TRUE;
748  }
749  else
750  {
751  if (count == 1)
752  szAdd = lpTime->wHour < 12 ? node->szShortAM : node->szShortPM;
753  else
754  szAdd = lpTime->wHour < 12 ? GetAM(node) : GetPM(node);
755  }
756  break;
757  }
758 
759  if (szAdd == buff && buff[0] == '\0')
760  {
761  static const WCHAR fmtW[] = {'%','.','*','d',0};
762  /* We have a numeric value to add */
763  snprintfW(buff, ARRAY_SIZE(buff), fmtW, count, dwVal);
764  }
765 
766  dwLen = szAdd ? strlenW(szAdd) : 0;
767 
768  if (cchOut && dwLen)
769  {
770  if (cchWritten + dwLen < cchOut)
771  memcpy(lpStr + cchWritten, szAdd, dwLen * sizeof(WCHAR));
772  else
773  {
774  memcpy(lpStr + cchWritten, szAdd, (cchOut - cchWritten) * sizeof(WCHAR));
775  goto overrun;
776  }
777  }
778  cchWritten += dwLen;
779  lastFormatPos = cchWritten; /* Save position of last output format text */
780  }
781  else
782  {
783  /* Literal character */
784  if (!cchOut)
785  cchWritten++; /* Count size only */
786  else if (cchWritten >= cchOut)
787  goto overrun;
788  else if (!bSkipping || *lpFormat == ' ')
789  {
790  lpStr[cchWritten] = *lpFormat;
791  cchWritten++;
792  }
793  lpFormat++;
794  }
795  }
796 
797  /* Final string terminator and sanity check */
798  if (cchOut)
799  {
800  if (cchWritten >= cchOut)
801  goto overrun;
802  else
803  lpStr[cchWritten] = '\0';
804  }
805  cchWritten++; /* Include terminating NUL */
806 
807  TRACE("returning length=%d, output=%s\n", cchWritten, debugstr_w(lpStr));
808  return cchWritten;
809 
810 overrun:
811  TRACE("returning 0, (ERROR_INSUFFICIENT_BUFFER)\n");
813  return 0;
814 
815 invalid_parameter:
817  return 0;
818 
819 invalid_flags:
821  return 0;
822 }
823 
824 /******************************************************************************
825  * NLS_GetDateTimeFormatA <internal>
826  *
827  * ASCII wrapper for GetDateFormatA/GetTimeFormatA.
828  */
830  const SYSTEMTIME* lpTime,
831  LPCSTR lpFormat, LPSTR lpStr, INT cchOut)
832 {
833  DWORD cp = CP_ACP;
834  WCHAR szFormat[128], szOut[128];
835  INT iRet;
836 
837  TRACE("(0x%04x,0x%08x,%p,%s,%p,%d)\n", lcid, dwFlags, lpTime,
838  debugstr_a(lpFormat), lpStr, cchOut);
839 
841  {
843  return 0;
844  }
845 
846  if (!(dwFlags & LOCALE_USE_CP_ACP))
847  {
849  if (!node)
850  {
852  return 0;
853  }
854 
855  cp = node->dwCodePage;
856  }
857 
858  if (lpFormat)
859  MultiByteToWideChar(cp, 0, lpFormat, -1, szFormat, ARRAY_SIZE(szFormat));
860 
861  if (cchOut > (int) ARRAY_SIZE(szOut))
862  cchOut = ARRAY_SIZE(szOut);
863 
864  szOut[0] = '\0';
865 
866  iRet = NLS_GetDateTimeFormatW(lcid, dwFlags, lpTime, lpFormat ? szFormat : NULL,
867  lpStr ? szOut : NULL, cchOut);
868 
869  if (lpStr)
870  {
871  if (szOut[0])
872  WideCharToMultiByte(cp, 0, szOut, iRet ? -1 : cchOut, lpStr, cchOut, 0, 0);
873  else if (cchOut && iRet)
874  *lpStr = '\0';
875  }
876  return iRet;
877 }
878 
879 /******************************************************************************
880  * GetDateFormatA [KERNEL32.@]
881  *
882  * Format a date for a given locale.
883  *
884  * PARAMS
885  * lcid [I] Locale to format for
886  * dwFlags [I] LOCALE_ and DATE_ flags from "winnls.h"
887  * lpTime [I] Date to format
888  * lpFormat [I] Format string, or NULL to use the system defaults
889  * lpDateStr [O] Destination for formatted string
890  * cchOut [I] Size of lpDateStr, or 0 to calculate the resulting size
891  *
892  * NOTES
893  * - If lpFormat is NULL, lpDateStr will be formatted according to the format
894  * details returned by GetLocaleInfoA() and modified by dwFlags.
895  * - lpFormat is a string of characters and formatting tokens. Any characters
896  * in the string are copied verbatim to lpDateStr, with tokens being replaced
897  * by the date values they represent.
898  * - The following tokens have special meanings in a date format string:
899  *| Token Meaning
900  *| ----- -------
901  *| d Single digit day of the month (no leading 0)
902  *| dd Double digit day of the month
903  *| ddd Short name for the day of the week
904  *| dddd Long name for the day of the week
905  *| M Single digit month of the year (no leading 0)
906  *| MM Double digit month of the year
907  *| MMM Short name for the month of the year
908  *| MMMM Long name for the month of the year
909  *| y Double digit year number (no leading 0)
910  *| yy Double digit year number
911  *| yyyy Four digit year number
912  *| gg Era string, for example 'AD'.
913  * - To output any literal character that could be misidentified as a token,
914  * enclose it in single quotes.
915  * - The Ascii version of this function fails if lcid is Unicode only.
916  *
917  * RETURNS
918  * Success: The number of character written to lpDateStr, or that would
919  * have been written, if cchOut is 0.
920  * Failure: 0. Use GetLastError() to determine the cause.
921  */
923  LPCSTR lpFormat, LPSTR lpDateStr, INT cchOut)
924 {
925  TRACE("(0x%04x,0x%08x,%p,%s,%p,%d)\n",lcid, dwFlags, lpTime,
926  debugstr_a(lpFormat), lpDateStr, cchOut);
927 
929  lpFormat, lpDateStr, cchOut);
930 }
931 
932 #if _WIN32_WINNT >= 0x600
933 /******************************************************************************
934  * GetDateFormatEx [KERNEL32.@]
935  *
936  * Format a date for a given locale.
937  *
938  * PARAMS
939  * localename [I] Locale to format for
940  * flags [I] LOCALE_ and DATE_ flags from "winnls.h"
941  * date [I] Date to format
942  * format [I] Format string, or NULL to use the locale defaults
943  * outbuf [O] Destination for formatted string
944  * bufsize [I] Size of outbuf, or 0 to calculate the resulting size
945  * calendar [I] Reserved, must be NULL
946  *
947  * See GetDateFormatA for notes.
948  *
949  * RETURNS
950  * Success: The number of characters written to outbuf, or that would have
951  * been written if bufsize is 0.
952  * Failure: 0. Use GetLastError() to determine the cause.
953  */
955  const SYSTEMTIME* date, LPCWSTR format,
956  LPWSTR outbuf, INT bufsize, LPCWSTR calendar)
957 {
958  TRACE("(%s,0x%08x,%p,%s,%p,%d,%s)\n", debugstr_w(localename), flags,
959  date, debugstr_w(format), outbuf, bufsize, debugstr_w(calendar));
960 
961  /* Parameter is currently reserved and Windows errors if set */
962  if (calendar != NULL)
963  {
965  return 0;
966  }
967 
968  return NLS_GetDateTimeFormatW(LocaleNameToLCID(localename, 0),
970  outbuf, bufsize);
971 }
972 #endif /* _WIN32_WINNT >= 0x600 */
973 
974 /******************************************************************************
975  * GetDateFormatW [KERNEL32.@]
976  *
977  * See GetDateFormatA.
978  */
980  LPCWSTR lpFormat, LPWSTR lpDateStr, INT cchOut)
981 {
982  TRACE("(0x%04x,0x%08x,%p,%s,%p,%d)\n", lcid, dwFlags, lpTime,
983  debugstr_w(lpFormat), lpDateStr, cchOut);
984 
986  lpFormat, lpDateStr, cchOut);
987 }
988 
989 /******************************************************************************
990  * GetTimeFormatA [KERNEL32.@]
991  *
992  * Format a time for a given locale.
993  *
994  * PARAMS
995  * lcid [I] Locale to format for
996  * dwFlags [I] LOCALE_ and TIME_ flags from "winnls.h"
997  * lpTime [I] Time to format
998  * lpFormat [I] Formatting overrides
999  * lpTimeStr [O] Destination for formatted string
1000  * cchOut [I] Size of lpTimeStr, or 0 to calculate the resulting size
1001  *
1002  * NOTES
1003  * - If lpFormat is NULL, lpszValue will be formatted according to the format
1004  * details returned by GetLocaleInfoA() and modified by dwFlags.
1005  * - lpFormat is a string of characters and formatting tokens. Any characters
1006  * in the string are copied verbatim to lpTimeStr, with tokens being replaced
1007  * by the time values they represent.
1008  * - The following tokens have special meanings in a time format string:
1009  *| Token Meaning
1010  *| ----- -------
1011  *| h Hours with no leading zero (12-hour clock)
1012  *| hh Hours with full two digits (12-hour clock)
1013  *| H Hours with no leading zero (24-hour clock)
1014  *| HH Hours with full two digits (24-hour clock)
1015  *| m Minutes with no leading zero
1016  *| mm Minutes with full two digits
1017  *| s Seconds with no leading zero
1018  *| ss Seconds with full two digits
1019  *| t Short time marker (e.g. "A" or "P")
1020  *| tt Long time marker (e.g. "AM", "PM")
1021  * - To output any literal character that could be misidentified as a token,
1022  * enclose it in single quotes.
1023  * - The Ascii version of this function fails if lcid is Unicode only.
1024  *
1025  * RETURNS
1026  * Success: The number of character written to lpTimeStr, or that would
1027  * have been written, if cchOut is 0.
1028  * Failure: 0. Use GetLastError() to determine the cause.
1029  */
1031  LPCSTR lpFormat, LPSTR lpTimeStr, INT cchOut)
1032 {
1033  TRACE("(0x%04x,0x%08x,%p,%s,%p,%d)\n",lcid, dwFlags, lpTime,
1034  debugstr_a(lpFormat), lpTimeStr, cchOut);
1035 
1037  lpFormat, lpTimeStr, cchOut);
1038 }
1039 
1040 #if _WIN32_WINNT >= 0x600
1041 /******************************************************************************
1042  * GetTimeFormatEx [KERNEL32.@]
1043  *
1044  * Format a date for a given locale.
1045  *
1046  * PARAMS
1047  * localename [I] Locale to format for
1048  * flags [I] LOCALE_ and TIME_ flags from "winnls.h"
1049  * time [I] Time to format
1050  * format [I] Formatting overrides
1051  * outbuf [O] Destination for formatted string
1052  * bufsize [I] Size of outbuf, or 0 to calculate the resulting size
1053  *
1054  * See GetTimeFormatA for notes.
1055  *
1056  * RETURNS
1057  * Success: The number of characters written to outbuf, or that would have
1058  * have been written if bufsize is 0.
1059  * Failure: 0. Use GetLastError() to determine the cause.
1060  */
1062  const SYSTEMTIME* time, LPCWSTR format,
1063  LPWSTR outbuf, INT bufsize)
1064 {
1065  TRACE("(%s,0x%08x,%p,%s,%p,%d)\n", debugstr_w(localename), flags, time,
1066  debugstr_w(format), outbuf, bufsize);
1067 
1068  return NLS_GetDateTimeFormatW(LocaleNameToLCID(localename, 0),
1070  outbuf, bufsize);
1071 }
1072 #endif /* _WIN32_WINNT >= 0x600 */
1073 
1074 /******************************************************************************
1075  * GetTimeFormatW [KERNEL32.@]
1076  *
1077  * See GetTimeFormatA.
1078  */
1080  LPCWSTR lpFormat, LPWSTR lpTimeStr, INT cchOut)
1081 {
1082  TRACE("(0x%04x,0x%08x,%p,%s,%p,%d)\n",lcid, dwFlags, lpTime,
1083  debugstr_w(lpFormat), lpTimeStr, cchOut);
1084 
1086  lpFormat, lpTimeStr, cchOut);
1087 }
1088 
1089 /**************************************************************************
1090  * GetNumberFormatA (KERNEL32.@)
1091  *
1092  * Format a number string for a given locale.
1093  *
1094  * PARAMS
1095  * lcid [I] Locale to format for
1096  * dwFlags [I] LOCALE_ flags from "winnls.h"
1097  * lpszValue [I] String to format
1098  * lpFormat [I] Formatting overrides
1099  * lpNumberStr [O] Destination for formatted string
1100  * cchOut [I] Size of lpNumberStr, or 0 to calculate the resulting size
1101  *
1102  * NOTES
1103  * - lpszValue can contain only '0' - '9', '-' and '.'.
1104  * - If lpFormat is non-NULL, dwFlags must be 0. In this case lpszValue will
1105  * be formatted according to the format details returned by GetLocaleInfoA().
1106  * - This function rounds the number string if the number of decimals exceeds the
1107  * locales normal number of decimal places.
1108  * - If cchOut is 0, this function does not write to lpNumberStr.
1109  * - The Ascii version of this function fails if lcid is Unicode only.
1110  *
1111  * RETURNS
1112  * Success: The number of character written to lpNumberStr, or that would
1113  * have been written, if cchOut is 0.
1114  * Failure: 0. Use GetLastError() to determine the cause.
1115  */
1117  LPCSTR lpszValue, const NUMBERFMTA *lpFormat,
1118  LPSTR lpNumberStr, int cchOut)
1119 {
1120  DWORD cp = CP_ACP;
1121  WCHAR szDec[8], szGrp[8], szIn[128], szOut[128];
1122  NUMBERFMTW fmt;
1123  const NUMBERFMTW *pfmt = NULL;
1124  INT iRet;
1125 
1126  TRACE("(0x%04x,0x%08x,%s,%p,%p,%d)\n", lcid, dwFlags, debugstr_a(lpszValue),
1127  lpFormat, lpNumberStr, cchOut);
1128 
1130  {
1132  return 0;
1133  }
1134 
1135  if (!(dwFlags & LOCALE_USE_CP_ACP))
1136  {
1138  if (!node)
1139  {
1141  return 0;
1142  }
1143 
1144  cp = node->dwCodePage;
1145  }
1146 
1147  if (lpFormat)
1148  {
1149  memcpy(&fmt, lpFormat, sizeof(fmt));
1150  pfmt = &fmt;
1151  if (lpFormat->lpDecimalSep)
1152  {
1153  MultiByteToWideChar(cp, 0, lpFormat->lpDecimalSep, -1, szDec, ARRAY_SIZE(szDec));
1154  fmt.lpDecimalSep = szDec;
1155  }
1156  if (lpFormat->lpThousandSep)
1157  {
1158  MultiByteToWideChar(cp, 0, lpFormat->lpThousandSep, -1, szGrp, ARRAY_SIZE(szGrp));
1159  fmt.lpThousandSep = szGrp;
1160  }
1161  }
1162 
1163  if (lpszValue)
1164  MultiByteToWideChar(cp, 0, lpszValue, -1, szIn, ARRAY_SIZE(szIn));
1165 
1166  if (cchOut > (int) ARRAY_SIZE(szOut))
1167  cchOut = ARRAY_SIZE(szOut);
1168 
1169  szOut[0] = '\0';
1170 
1171  iRet = GetNumberFormatW(lcid, dwFlags, lpszValue ? szIn : NULL, pfmt,
1172  lpNumberStr ? szOut : NULL, cchOut);
1173 
1174  if (szOut[0] && lpNumberStr)
1175  WideCharToMultiByte(cp, 0, szOut, -1, lpNumberStr, cchOut, 0, 0);
1176  return iRet;
1177 }
1178 
1179 /* Number parsing state flags */
1180 #define NF_ISNEGATIVE 0x1 /* '-' found */
1181 #define NF_ISREAL 0x2 /* '.' found */
1182 #define NF_DIGITS 0x4 /* '0'-'9' found */
1183 #define NF_DIGITS_OUT 0x8 /* Digits before the '.' found */
1184 #define NF_ROUND 0x10 /* Number needs to be rounded */
1185 
1186 /* Formatting options for Numbers */
1187 #define NLS_NEG_PARENS 0 /* "(1.1)" */
1188 #define NLS_NEG_LEFT 1 /* "-1.1" */
1189 #define NLS_NEG_LEFT_SPACE 2 /* "- 1.1" */
1190 #define NLS_NEG_RIGHT 3 /* "1.1-" */
1191 #define NLS_NEG_RIGHT_SPACE 4 /* "1.1 -" */
1192 
1193 /**************************************************************************
1194  * GetNumberFormatW (KERNEL32.@)
1195  *
1196  * See GetNumberFormatA.
1197  */
1199  LPCWSTR lpszValue, const NUMBERFMTW *lpFormat,
1200  LPWSTR lpNumberStr, int cchOut)
1201 {
1202  WCHAR szBuff[128], *szOut = szBuff + ARRAY_SIZE(szBuff) - 1;
1203  WCHAR szNegBuff[8];
1204  const WCHAR *lpszNeg = NULL, *lpszNegStart, *szSrc;
1205  DWORD dwState = 0, dwDecimals = 0, dwGroupCount = 0, dwCurrentGroupCount = 0;
1206  INT iRet;
1207 
1208  TRACE("(0x%04x,0x%08x,%s,%p,%p,%d)\n", lcid, dwFlags, debugstr_w(lpszValue),
1209  lpFormat, lpNumberStr, cchOut);
1210 
1211  if (!lpszValue || cchOut < 0 || (cchOut > 0 && !lpNumberStr) ||
1212  !IsValidLocale(lcid, 0) ||
1213  (lpFormat && (dwFlags || !lpFormat->lpDecimalSep || !lpFormat->lpThousandSep)))
1214  {
1215  goto error;
1216  }
1217 
1218  if (!lpFormat)
1219  {
1221 
1222  if (!node)
1223  goto error;
1224  lpFormat = &node->fmt;
1225  lpszNegStart = lpszNeg = GetNegative(node);
1226  }
1227  else
1228  {
1230  szNegBuff, ARRAY_SIZE(szNegBuff));
1231  lpszNegStart = lpszNeg = szNegBuff;
1232  }
1233  lpszNeg = lpszNeg + strlenW(lpszNeg) - 1;
1234 
1236 
1237  /* Format the number backwards into a temporary buffer */
1238 
1239  szSrc = lpszValue;
1240  *szOut-- = '\0';
1241 
1242  /* Check the number for validity */
1243  while (*szSrc)
1244  {
1245  if (*szSrc >= '0' && *szSrc <= '9')
1246  {
1247  dwState |= NF_DIGITS;
1248  if (dwState & NF_ISREAL)
1249  dwDecimals++;
1250  }
1251  else if (*szSrc == '-')
1252  {
1253  if (dwState)
1254  goto error; /* '-' not first character */
1255  dwState |= NF_ISNEGATIVE;
1256  }
1257  else if (*szSrc == '.')
1258  {
1259  if (dwState & NF_ISREAL)
1260  goto error; /* More than one '.' */
1261  dwState |= NF_ISREAL;
1262  }
1263  else
1264  goto error; /* Invalid char */
1265  szSrc++;
1266  }
1267  szSrc--; /* Point to last character */
1268 
1269  if (!(dwState & NF_DIGITS))
1270  goto error; /* No digits */
1271 
1272  /* Add any trailing negative sign */
1273  if (dwState & NF_ISNEGATIVE)
1274  {
1275  switch (lpFormat->NegativeOrder)
1276  {
1277  case NLS_NEG_PARENS:
1278  *szOut-- = ')';
1279  break;
1280  case NLS_NEG_RIGHT:
1281  case NLS_NEG_RIGHT_SPACE:
1282  while (lpszNeg >= lpszNegStart)
1283  *szOut-- = *lpszNeg--;
1284  if (lpFormat->NegativeOrder == NLS_NEG_RIGHT_SPACE)
1285  *szOut-- = ' ';
1286  break;
1287  }
1288  }
1289 
1290  /* Copy all digits up to the decimal point */
1291  if (!lpFormat->NumDigits)
1292  {
1293  if (dwState & NF_ISREAL)
1294  {
1295  while (*szSrc != '.') /* Don't write any decimals or a separator */
1296  {
1297  if (*szSrc >= '5' || (*szSrc == '4' && (dwState & NF_ROUND)))
1298  dwState |= NF_ROUND;
1299  else
1300  dwState &= ~NF_ROUND;
1301  szSrc--;
1302  }
1303  szSrc--;
1304  }
1305  }
1306  else
1307  {
1308  LPWSTR lpszDec = lpFormat->lpDecimalSep + strlenW(lpFormat->lpDecimalSep) - 1;
1309 
1310  if (dwDecimals <= lpFormat->NumDigits)
1311  {
1312  dwDecimals = lpFormat->NumDigits - dwDecimals;
1313  while (dwDecimals--)
1314  *szOut-- = '0'; /* Pad to correct number of dp */
1315  }
1316  else
1317  {
1318  dwDecimals -= lpFormat->NumDigits;
1319  /* Skip excess decimals, and determine if we have to round the number */
1320  while (dwDecimals--)
1321  {
1322  if (*szSrc >= '5' || (*szSrc == '4' && (dwState & NF_ROUND)))
1323  dwState |= NF_ROUND;
1324  else
1325  dwState &= ~NF_ROUND;
1326  szSrc--;
1327  }
1328  }
1329 
1330  if (dwState & NF_ISREAL)
1331  {
1332  while (*szSrc != '.')
1333  {
1334  if (dwState & NF_ROUND)
1335  {
1336  if (*szSrc == '9')
1337  *szOut-- = '0'; /* continue rounding */
1338  else
1339  {
1340  dwState &= ~NF_ROUND;
1341  *szOut-- = (*szSrc)+1;
1342  }
1343  szSrc--;
1344  }
1345  else
1346  *szOut-- = *szSrc--; /* Write existing decimals */
1347  }
1348  szSrc--; /* Skip '.' */
1349  }
1350 
1351  while (lpszDec >= lpFormat->lpDecimalSep)
1352  *szOut-- = *lpszDec--; /* Write decimal separator */
1353  }
1354 
1355  dwGroupCount = lpFormat->Grouping == 32 ? 3 : lpFormat->Grouping;
1356 
1357  /* Write the remaining whole number digits, including grouping chars */
1358  while (szSrc >= lpszValue && *szSrc >= '0' && *szSrc <= '9')
1359  {
1360  if (dwState & NF_ROUND)
1361  {
1362  if (*szSrc == '9')
1363  *szOut-- = '0'; /* continue rounding */
1364  else
1365  {
1366  dwState &= ~NF_ROUND;
1367  *szOut-- = (*szSrc)+1;
1368  }
1369  szSrc--;
1370  }
1371  else
1372  *szOut-- = *szSrc--;
1373 
1374  dwState |= NF_DIGITS_OUT;
1375  dwCurrentGroupCount++;
1376  if (szSrc >= lpszValue && dwCurrentGroupCount == dwGroupCount && *szSrc != '-')
1377  {
1378  LPWSTR lpszGrp = lpFormat->lpThousandSep + strlenW(lpFormat->lpThousandSep) - 1;
1379 
1380  while (lpszGrp >= lpFormat->lpThousandSep)
1381  *szOut-- = *lpszGrp--; /* Write grouping char */
1382 
1383  dwCurrentGroupCount = 0;
1384  if (lpFormat->Grouping == 32)
1385  dwGroupCount = 2; /* Indic grouping: 3 then 2 */
1386  }
1387  }
1388  if (dwState & NF_ROUND)
1389  {
1390  *szOut-- = '1'; /* e.g. .6 > 1.0 */
1391  }
1392  else if (!(dwState & NF_DIGITS_OUT) && lpFormat->LeadingZero)
1393  *szOut-- = '0'; /* Add leading 0 if we have no digits before the decimal point */
1394 
1395  /* Add any leading negative sign */
1396  if (dwState & NF_ISNEGATIVE)
1397  {
1398  switch (lpFormat->NegativeOrder)
1399  {
1400  case NLS_NEG_PARENS:
1401  *szOut-- = '(';
1402  break;
1403  case NLS_NEG_LEFT_SPACE:
1404  *szOut-- = ' ';
1405  /* Fall through */
1406  case NLS_NEG_LEFT:
1407  while (lpszNeg >= lpszNegStart)
1408  *szOut-- = *lpszNeg--;
1409  break;
1410  }
1411  }
1412  szOut++;
1413 
1414  iRet = strlenW(szOut) + 1;
1415  if (cchOut)
1416  {
1417  if (iRet <= cchOut)
1418  memcpy(lpNumberStr, szOut, iRet * sizeof(WCHAR));
1419  else
1420  {
1421  memcpy(lpNumberStr, szOut, cchOut * sizeof(WCHAR));
1422  lpNumberStr[cchOut - 1] = '\0';
1424  iRet = 0;
1425  }
1426  }
1427  return iRet;
1428 
1429 error:
1431  return 0;
1432 }
1433 
1434 #if _WIN32_WINNT >= 0x600
1435 /**************************************************************************
1436  * GetNumberFormatEx (KERNEL32.@)
1437  */
1438 INT WINAPI GetNumberFormatEx(LPCWSTR name, DWORD flags,
1439  LPCWSTR value, const NUMBERFMTW *format,
1440  LPWSTR number, int numout)
1441 {
1442  LCID lcid;
1443 
1444  TRACE("(%s,0x%08x,%s,%p,%p,%d)\n", debugstr_w(name), flags,
1445  debugstr_w(value), format, number, numout);
1446 
1447  lcid = LocaleNameToLCID(name, 0);
1448  if (!lcid)
1449  return 0;
1450 
1451  return GetNumberFormatW(lcid, flags, value, format, number, numout);
1452 }
1453 #endif /* _WIN32_WINNT >= 0x600 */
1454 
1455 /**************************************************************************
1456  * GetCurrencyFormatA (KERNEL32.@)
1457  *
1458  * Format a currency string for a given locale.
1459  *
1460  * PARAMS
1461  * lcid [I] Locale to format for
1462  * dwFlags [I] LOCALE_ flags from "winnls.h"
1463  * lpszValue [I] String to format
1464  * lpFormat [I] Formatting overrides
1465  * lpCurrencyStr [O] Destination for formatted string
1466  * cchOut [I] Size of lpCurrencyStr, or 0 to calculate the resulting size
1467  *
1468  * NOTES
1469  * - lpszValue can contain only '0' - '9', '-' and '.'.
1470  * - If lpFormat is non-NULL, dwFlags must be 0. In this case lpszValue will
1471  * be formatted according to the format details returned by GetLocaleInfoA().
1472  * - This function rounds the currency if the number of decimals exceeds the
1473  * locales number of currency decimal places.
1474  * - If cchOut is 0, this function does not write to lpCurrencyStr.
1475  * - The Ascii version of this function fails if lcid is Unicode only.
1476  *
1477  * RETURNS
1478  * Success: The number of character written to lpNumberStr, or that would
1479  * have been written, if cchOut is 0.
1480  * Failure: 0. Use GetLastError() to determine the cause.
1481  */
1483  LPCSTR lpszValue, const CURRENCYFMTA *lpFormat,
1484  LPSTR lpCurrencyStr, int cchOut)
1485 {
1486  DWORD cp = CP_ACP;
1487  WCHAR szDec[8], szGrp[8], szCy[8], szIn[128], szOut[128];
1488  CURRENCYFMTW fmt;
1489  const CURRENCYFMTW *pfmt = NULL;
1490  INT iRet;
1491 
1492  TRACE("(0x%04x,0x%08x,%s,%p,%p,%d)\n", lcid, dwFlags, debugstr_a(lpszValue),
1493  lpFormat, lpCurrencyStr, cchOut);
1494 
1496  {
1498  return 0;
1499  }
1500 
1501  if (!(dwFlags & LOCALE_USE_CP_ACP))
1502  {
1504  if (!node)
1505  {
1507  return 0;
1508  }
1509 
1510  cp = node->dwCodePage;
1511  }
1512 
1513  if (lpFormat)
1514  {
1515  memcpy(&fmt, lpFormat, sizeof(fmt));
1516  pfmt = &fmt;
1517  if (lpFormat->lpDecimalSep)
1518  {
1519  MultiByteToWideChar(cp, 0, lpFormat->lpDecimalSep, -1, szDec, ARRAY_SIZE(szDec));
1520  fmt.lpDecimalSep = szDec;
1521  }
1522  if (lpFormat->lpThousandSep)
1523  {
1524  MultiByteToWideChar(cp, 0, lpFormat->lpThousandSep, -1, szGrp, ARRAY_SIZE(szGrp));
1525  fmt.lpThousandSep = szGrp;
1526  }
1527  if (lpFormat->lpCurrencySymbol)
1528  {
1529  MultiByteToWideChar(cp, 0, lpFormat->lpCurrencySymbol, -1, szCy, ARRAY_SIZE(szCy));
1530  fmt.lpCurrencySymbol = szCy;
1531  }
1532  }
1533 
1534  if (lpszValue)
1535  MultiByteToWideChar(cp, 0, lpszValue, -1, szIn, ARRAY_SIZE(szIn));
1536 
1537  if (cchOut > (int) ARRAY_SIZE(szOut))
1538  cchOut = ARRAY_SIZE(szOut);
1539 
1540  szOut[0] = '\0';
1541 
1542  iRet = GetCurrencyFormatW(lcid, dwFlags, lpszValue ? szIn : NULL, pfmt,
1543  lpCurrencyStr ? szOut : NULL, cchOut);
1544 
1545  if (szOut[0] && lpCurrencyStr)
1546  WideCharToMultiByte(cp, 0, szOut, -1, lpCurrencyStr, cchOut, 0, 0);
1547  return iRet;
1548 }
1549 
1550 /* Formatting states for Currencies. We use flags to avoid code duplication. */
1551 #define CF_PARENS 0x1 /* Parentheses */
1552 #define CF_MINUS_LEFT 0x2 /* '-' to the left */
1553 #define CF_MINUS_RIGHT 0x4 /* '-' to the right */
1554 #define CF_MINUS_BEFORE 0x8 /* '-' before '$' */
1555 #define CF_CY_LEFT 0x10 /* '$' to the left */
1556 #define CF_CY_RIGHT 0x20 /* '$' to the right */
1557 #define CF_CY_SPACE 0x40 /* ' ' by '$' */
1558 
1559 /**************************************************************************
1560  * GetCurrencyFormatW (KERNEL32.@)
1561  *
1562  * See GetCurrencyFormatA.
1563  */
1565  LPCWSTR lpszValue, const CURRENCYFMTW *lpFormat,
1566  LPWSTR lpCurrencyStr, int cchOut)
1567 {
1568  static const BYTE NLS_NegCyFormats[16] =
1569  {
1570  CF_PARENS|CF_CY_LEFT, /* ($1.1) */
1572  CF_MINUS_LEFT|CF_CY_LEFT, /* $-1.1 */
1573  CF_MINUS_RIGHT|CF_CY_LEFT, /* $1.1- */
1574  CF_PARENS|CF_CY_RIGHT, /* (1.1$) */
1575  CF_MINUS_LEFT|CF_CY_RIGHT, /* -1.1$ */
1577  CF_MINUS_RIGHT|CF_CY_RIGHT, /* 1.1$- */
1578  CF_MINUS_LEFT|CF_CY_RIGHT|CF_CY_SPACE, /* -1.1 $ */
1580  CF_MINUS_RIGHT|CF_CY_RIGHT|CF_CY_SPACE, /* 1.1 $- */
1581  CF_MINUS_RIGHT|CF_CY_LEFT|CF_CY_SPACE, /* $ 1.1- */
1582  CF_MINUS_LEFT|CF_CY_LEFT|CF_CY_SPACE, /* $ -1.1 */
1584  CF_PARENS|CF_CY_LEFT|CF_CY_SPACE, /* ($ 1.1) */
1585  CF_PARENS|CF_CY_RIGHT|CF_CY_SPACE, /* (1.1 $) */
1586  };
1587  static const BYTE NLS_PosCyFormats[4] =
1588  {
1589  CF_CY_LEFT, /* $1.1 */
1590  CF_CY_RIGHT, /* 1.1$ */
1591  CF_CY_LEFT|CF_CY_SPACE, /* $ 1.1 */
1592  CF_CY_RIGHT|CF_CY_SPACE, /* 1.1 $ */
1593  };
1594  WCHAR szBuff[128], *szOut = szBuff + ARRAY_SIZE(szBuff) - 1;
1595  WCHAR szNegBuff[8];
1596  const WCHAR *lpszNeg = NULL, *lpszNegStart, *szSrc, *lpszCy, *lpszCyStart;
1597  DWORD dwState = 0, dwDecimals = 0, dwGroupCount = 0, dwCurrentGroupCount = 0, dwFmt;
1598  INT iRet;
1599 
1600  TRACE("(0x%04x,0x%08x,%s,%p,%p,%d)\n", lcid, dwFlags, debugstr_w(lpszValue),
1601  lpFormat, lpCurrencyStr, cchOut);
1602 
1603  if (!lpszValue || cchOut < 0 || (cchOut > 0 && !lpCurrencyStr) ||
1604  !IsValidLocale(lcid, 0) ||
1605  (lpFormat && (dwFlags || !lpFormat->lpDecimalSep || !lpFormat->lpThousandSep ||
1606  !lpFormat->lpCurrencySymbol || lpFormat->NegativeOrder > 15 ||
1607  lpFormat->PositiveOrder > 3)))
1608  {
1609  goto error;
1610  }
1611 
1612  if (!lpFormat)
1613  {
1615 
1616  if (!node)
1617  goto error;
1618 
1619  lpFormat = &node->cyfmt;
1620  lpszNegStart = lpszNeg = GetNegative(node);
1621  }
1622  else
1623  {
1625  szNegBuff, ARRAY_SIZE(szNegBuff));
1626  lpszNegStart = lpszNeg = szNegBuff;
1627  }
1629 
1630  lpszNeg = lpszNeg + strlenW(lpszNeg) - 1;
1631  lpszCyStart = lpFormat->lpCurrencySymbol;
1632  lpszCy = lpszCyStart + strlenW(lpszCyStart) - 1;
1633 
1634  /* Format the currency backwards into a temporary buffer */
1635 
1636  szSrc = lpszValue;
1637  *szOut-- = '\0';
1638 
1639  /* Check the number for validity */
1640  while (*szSrc)
1641  {
1642  if (*szSrc >= '0' && *szSrc <= '9')
1643  {
1644  dwState |= NF_DIGITS;
1645  if (dwState & NF_ISREAL)
1646  dwDecimals++;
1647  }
1648  else if (*szSrc == '-')
1649  {
1650  if (dwState)
1651  goto error; /* '-' not first character */
1652  dwState |= NF_ISNEGATIVE;
1653  }
1654  else if (*szSrc == '.')
1655  {
1656  if (dwState & NF_ISREAL)
1657  goto error; /* More than one '.' */
1658  dwState |= NF_ISREAL;
1659  }
1660  else
1661  goto error; /* Invalid char */
1662  szSrc++;
1663  }
1664  szSrc--; /* Point to last character */
1665 
1666  if (!(dwState & NF_DIGITS))
1667  goto error; /* No digits */
1668 
1669  if (dwState & NF_ISNEGATIVE)
1670  dwFmt = NLS_NegCyFormats[lpFormat->NegativeOrder];
1671  else
1672  dwFmt = NLS_PosCyFormats[lpFormat->PositiveOrder];
1673 
1674  /* Add any trailing negative or currency signs */
1675  if (dwFmt & CF_PARENS)
1676  *szOut-- = ')';
1677 
1678  while (dwFmt & (CF_MINUS_RIGHT|CF_CY_RIGHT))
1679  {
1680  switch (dwFmt & (CF_MINUS_RIGHT|CF_MINUS_BEFORE|CF_CY_RIGHT))
1681  {
1682  case CF_MINUS_RIGHT:
1684  while (lpszNeg >= lpszNegStart)
1685  *szOut-- = *lpszNeg--;
1686  dwFmt &= ~CF_MINUS_RIGHT;
1687  break;
1688 
1689  case CF_CY_RIGHT:
1692  while (lpszCy >= lpszCyStart)
1693  *szOut-- = *lpszCy--;
1694  if (dwFmt & CF_CY_SPACE)
1695  *szOut-- = ' ';
1696  dwFmt &= ~(CF_CY_RIGHT|CF_MINUS_BEFORE);
1697  break;
1698  }
1699  }
1700 
1701  /* Copy all digits up to the decimal point */
1702  if (!lpFormat->NumDigits)
1703  {
1704  if (dwState & NF_ISREAL)
1705  {
1706  while (*szSrc != '.') /* Don't write any decimals or a separator */
1707  {
1708  if (*szSrc >= '5' || (*szSrc == '4' && (dwState & NF_ROUND)))
1709  dwState |= NF_ROUND;
1710  else
1711  dwState &= ~NF_ROUND;
1712  szSrc--;
1713  }
1714  szSrc--;
1715  }
1716  }
1717  else
1718  {
1719  LPWSTR lpszDec = lpFormat->lpDecimalSep + strlenW(lpFormat->lpDecimalSep) - 1;
1720 
1721  if (dwDecimals <= lpFormat->NumDigits)
1722  {
1723  dwDecimals = lpFormat->NumDigits - dwDecimals;
1724  while (dwDecimals--)
1725  *szOut-- = '0'; /* Pad to correct number of dp */
1726  }
1727  else
1728  {
1729  dwDecimals -= lpFormat->NumDigits;
1730  /* Skip excess decimals, and determine if we have to round the number */
1731  while (dwDecimals--)
1732  {
1733  if (*szSrc >= '5' || (*szSrc == '4' && (dwState & NF_ROUND)))
1734  dwState |= NF_ROUND;
1735  else
1736  dwState &= ~NF_ROUND;
1737  szSrc--;
1738  }
1739  }
1740 
1741  if (dwState & NF_ISREAL)
1742  {
1743  while (*szSrc != '.')
1744  {
1745  if (dwState & NF_ROUND)
1746  {
1747  if (*szSrc == '9')
1748  *szOut-- = '0'; /* continue rounding */
1749  else
1750  {
1751  dwState &= ~NF_ROUND;
1752  *szOut-- = (*szSrc)+1;
1753  }
1754  szSrc--;
1755  }
1756  else
1757  *szOut-- = *szSrc--; /* Write existing decimals */
1758  }
1759  szSrc--; /* Skip '.' */
1760  }
1761  while (lpszDec >= lpFormat->lpDecimalSep)
1762  *szOut-- = *lpszDec--; /* Write decimal separator */
1763  }
1764 
1765  dwGroupCount = lpFormat->Grouping == 32 ? 3 : lpFormat->Grouping;
1766 
1767  /* Write the remaining whole number digits, including grouping chars */
1768  while (szSrc >= lpszValue && *szSrc >= '0' && *szSrc <= '9')
1769  {
1770  if (dwState & NF_ROUND)
1771  {
1772  if (*szSrc == '9')
1773  *szOut-- = '0'; /* continue rounding */
1774  else
1775  {
1776  dwState &= ~NF_ROUND;
1777  *szOut-- = (*szSrc)+1;
1778  }
1779  szSrc--;
1780  }
1781  else
1782  *szOut-- = *szSrc--;
1783 
1784  dwState |= NF_DIGITS_OUT;
1785  dwCurrentGroupCount++;
1786  if (szSrc >= lpszValue && dwCurrentGroupCount == dwGroupCount && *szSrc != '-')
1787  {
1788  LPWSTR lpszGrp = lpFormat->lpThousandSep + strlenW(lpFormat->lpThousandSep) - 1;
1789 
1790  while (lpszGrp >= lpFormat->lpThousandSep)
1791  *szOut-- = *lpszGrp--; /* Write grouping char */
1792 
1793  dwCurrentGroupCount = 0;
1794  if (lpFormat->Grouping == 32)
1795  dwGroupCount = 2; /* Indic grouping: 3 then 2 */
1796  }
1797  }
1798  if (dwState & NF_ROUND)
1799  *szOut-- = '1'; /* e.g. .6 > 1.0 */
1800  else if (!(dwState & NF_DIGITS_OUT) && lpFormat->LeadingZero)
1801  *szOut-- = '0'; /* Add leading 0 if we have no digits before the decimal point */
1802 
1803  /* Add any leading negative or currency sign */
1804  while (dwFmt & (CF_MINUS_LEFT|CF_CY_LEFT))
1805  {
1806  switch (dwFmt & (CF_MINUS_LEFT|CF_MINUS_BEFORE|CF_CY_LEFT))
1807  {
1808  case CF_MINUS_LEFT:
1810  while (lpszNeg >= lpszNegStart)
1811  *szOut-- = *lpszNeg--;
1812  dwFmt &= ~CF_MINUS_LEFT;
1813  break;
1814 
1815  case CF_CY_LEFT:
1818  if (dwFmt & CF_CY_SPACE)
1819  *szOut-- = ' ';
1820  while (lpszCy >= lpszCyStart)
1821  *szOut-- = *lpszCy--;
1822  dwFmt &= ~(CF_CY_LEFT|CF_MINUS_BEFORE);
1823  break;
1824  }
1825  }
1826  if (dwFmt & CF_PARENS)
1827  *szOut-- = '(';
1828  szOut++;
1829 
1830  iRet = strlenW(szOut) + 1;
1831  if (cchOut)
1832  {
1833  if (iRet <= cchOut)
1834  memcpy(lpCurrencyStr, szOut, iRet * sizeof(WCHAR));
1835  else
1836  {
1837  memcpy(lpCurrencyStr, szOut, cchOut * sizeof(WCHAR));
1838  lpCurrencyStr[cchOut - 1] = '\0';
1840  iRet = 0;
1841  }
1842  }
1843  return iRet;
1844 
1845 error:
1847  return 0;
1848 }
1849 
1850 #if _WIN32_WINNT >= 0x600
1851 /***********************************************************************
1852  * GetCurrencyFormatEx (KERNEL32.@)
1853  */
1854 int WINAPI GetCurrencyFormatEx(LPCWSTR localename, DWORD flags, LPCWSTR value,
1855  const CURRENCYFMTW *format, LPWSTR str, int len)
1856 {
1857  TRACE("(%s,0x%08x,%s,%p,%p,%d)\n", debugstr_w(localename), flags,
1858  debugstr_w(value), format, str, len);
1859 
1860  return GetCurrencyFormatW( LocaleNameToLCID(localename, 0), flags, value, format, str, len);
1861 }
1862 #endif
1863 
1864 
1865 /* FIXME: Everything below here needs to move somewhere else along with the
1866  * other EnumXXX functions, when a method for storing resources for
1867  * alternate calendars is determined.
1868  */
1869 
1874 };
1875 
1877  enum enum_callback_type type; /* callback kind */
1878  union {
1879  DATEFMT_ENUMPROCW callback; /* user callback pointer */
1882  } u;
1883  LCID lcid; /* locale of interest */
1886  BOOL unicode; /* A vs W callback type, only for regular and Ex callbacks */
1887 };
1888 
1889 /******************************************************************************
1890  * NLS_EnumDateFormats <internal>
1891  * Enumerates date formats for a specified locale.
1892  *
1893  * PARAMS
1894  * ctxt [I] enumeration context, see 'struct enumdateformats_context'
1895  *
1896  * RETURNS
1897  * Success: TRUE.
1898  * Failure: FALSE. Use GetLastError() to determine the cause.
1899  */
1901 {
1902  WCHAR bufW[256];
1903  char bufA[256];
1904  LCTYPE lctype;
1905  CALID cal_id;
1906  INT ret;
1907 
1908  if (!ctxt->u.callback)
1909  {
1911  return FALSE;
1912  }
1913 
1914  if (!GetLocaleInfoW(ctxt->lcid, LOCALE_ICALENDARTYPE|LOCALE_RETURN_NUMBER, (LPWSTR)&cal_id, sizeof(cal_id)/sizeof(WCHAR)))
1915  return FALSE;
1916 
1917  switch (ctxt->flags & ~LOCALE_USE_CP_ACP)
1918  {
1919  case 0:
1920  case DATE_SHORTDATE:
1921  lctype = LOCALE_SSHORTDATE;
1922  break;
1923  case DATE_LONGDATE:
1924  lctype = LOCALE_SLONGDATE;
1925  break;
1926  case DATE_YEARMONTH:
1927  lctype = LOCALE_SYEARMONTH;
1928  break;
1929  default:
1930  FIXME("Unknown date format (0x%08x)\n", ctxt->flags);
1932  return FALSE;
1933  }
1934 
1935  lctype |= ctxt->flags & LOCALE_USE_CP_ACP;
1936  if (ctxt->unicode)
1937  ret = GetLocaleInfoW(ctxt->lcid, lctype, bufW, ARRAY_SIZE(bufW));
1938  else
1939  ret = GetLocaleInfoA(ctxt->lcid, lctype, bufA, ARRAY_SIZE(bufA));
1940 
1941  if (ret)
1942  {
1943  switch (ctxt->type)
1944  {
1945  case CALLBACK_ENUMPROC:
1946  ctxt->u.callback(ctxt->unicode ? bufW : (WCHAR*)bufA);
1947  break;
1948  case CALLBACK_ENUMPROCEX:
1949  ctxt->u.callbackex(ctxt->unicode ? bufW : (WCHAR*)bufA, cal_id);
1950  break;
1951  case CALLBACK_ENUMPROCEXEX:
1952  ctxt->u.callbackexex(bufW, cal_id, ctxt->lParam);
1953  break;
1954  default:
1955  ;
1956  }
1957  }
1958 
1959  return TRUE;
1960 }
1961 
1962 /**************************************************************************
1963  * EnumDateFormatsExA (KERNEL32.@)
1964  *
1965  * FIXME: MSDN mentions only LOCALE_USE_CP_ACP, should we handle
1966  * LOCALE_NOUSEROVERRIDE here as well?
1967  */
1969 {
1970  struct enumdateformats_context ctxt;
1971 
1972  ctxt.type = CALLBACK_ENUMPROCEX;
1974  ctxt.lcid = lcid;
1975  ctxt.flags = flags;
1976  ctxt.unicode = FALSE;
1977 
1978  return NLS_EnumDateFormats(&ctxt);
1979 }
1980 
1981 /**************************************************************************
1982  * EnumDateFormatsExW (KERNEL32.@)
1983  */
1985 {
1986  struct enumdateformats_context ctxt;
1987 
1988  ctxt.type = CALLBACK_ENUMPROCEX;
1989  ctxt.u.callbackex = proc;
1990  ctxt.lcid = lcid;
1991  ctxt.flags = flags;
1992  ctxt.unicode = TRUE;
1993 
1994  return NLS_EnumDateFormats(&ctxt);
1995 }
1996 
1997 /**************************************************************************
1998  * EnumDateFormatsA (KERNEL32.@)
1999  *
2000  * FIXME: MSDN mentions only LOCALE_USE_CP_ACP, should we handle
2001  * LOCALE_NOUSEROVERRIDE here as well?
2002  */
2004 {
2005  struct enumdateformats_context ctxt;
2006 
2007  ctxt.type = CALLBACK_ENUMPROC;
2008  ctxt.u.callback = (DATEFMT_ENUMPROCW)proc;
2009  ctxt.lcid = lcid;
2010  ctxt.flags = flags;
2011  ctxt.unicode = FALSE;
2012 
2013  return NLS_EnumDateFormats(&ctxt);
2014 }
2015 
2016 /**************************************************************************
2017  * EnumDateFormatsW (KERNEL32.@)
2018  */
2020 {
2021  struct enumdateformats_context ctxt;
2022 
2023  ctxt.type = CALLBACK_ENUMPROC;
2024  ctxt.u.callback = proc;
2025  ctxt.lcid = lcid;
2026  ctxt.flags = flags;
2027  ctxt.unicode = TRUE;
2028 
2029  return NLS_EnumDateFormats(&ctxt);
2030 }
2031 
2032 #if _WIN32_WINNT >= 0x600
2033 /**************************************************************************
2034  * EnumDateFormatsExEx (KERNEL32.@)
2035  */
2036 BOOL WINAPI EnumDateFormatsExEx(DATEFMT_ENUMPROCEXEX proc, const WCHAR *locale, DWORD flags, LPARAM lParam)
2037 {
2038  struct enumdateformats_context ctxt;
2039 
2040  ctxt.type = CALLBACK_ENUMPROCEXEX;
2041  ctxt.u.callbackexex = proc;
2042  ctxt.lcid = LocaleNameToLCID(locale, 0);
2043  ctxt.flags = flags;
2044  ctxt.lParam = lParam;
2045  ctxt.unicode = TRUE;
2046 
2047  return NLS_EnumDateFormats(&ctxt);
2048 }
2049 #endif /* _WIN32_WINNT >= 0x600 */
2050 
2052  enum enum_callback_type type; /* callback kind */
2053  union {
2054  TIMEFMT_ENUMPROCW callback; /* user callback pointer */
2056  } u;
2057  LCID lcid; /* locale of interest */
2060  BOOL unicode; /* A vs W callback type, only for regular and Ex callbacks */
2061 };
2062 
2064 {
2065  WCHAR bufW[256];
2066  char bufA[256];
2067  LCTYPE lctype;
2068  INT ret;
2069 
2070  if (!ctxt->u.callback)
2071  {
2073  return FALSE;
2074  }
2075 
2076  switch (ctxt->flags & ~LOCALE_USE_CP_ACP)
2077  {
2078  case 0:
2079  lctype = LOCALE_STIMEFORMAT;
2080  break;
2081  case TIME_NOSECONDS:
2082  lctype = LOCALE_SSHORTTIME;
2083  break;
2084  default:
2085  FIXME("Unknown time format (%d)\n", ctxt->flags);
2087  return FALSE;
2088  }
2089 
2090  lctype |= ctxt->flags & LOCALE_USE_CP_ACP;
2091  if (ctxt->unicode)
2092  ret = GetLocaleInfoW(ctxt->lcid, lctype, bufW, ARRAY_SIZE(bufW));
2093  else
2094  ret = GetLocaleInfoA(ctxt->lcid, lctype, bufA, ARRAY_SIZE(bufA));
2095 
2096  if (ret)
2097  {
2098  switch (ctxt->type)
2099  {
2100  case CALLBACK_ENUMPROC:
2101  ctxt->u.callback(ctxt->unicode ? bufW : (WCHAR*)bufA);
2102  break;
2103  case CALLBACK_ENUMPROCEX:
2104  ctxt->u.callbackex(bufW, ctxt->lParam);
2105  break;
2106  default:
2107  ;
2108  }
2109  }
2110 
2111  return TRUE;
2112 }
2113 
2114 /**************************************************************************
2115  * EnumTimeFormatsA (KERNEL32.@)
2116  *
2117  * FIXME: MSDN mentions only LOCALE_USE_CP_ACP, should we handle
2118  * LOCALE_NOUSEROVERRIDE here as well?
2119  */
2121 {
2122  struct enumtimeformats_context ctxt;
2123 
2124  /* EnumTimeFormatsA doesn't support flags, EnumTimeFormatsW does. */
2125  if (flags & ~LOCALE_USE_CP_ACP)
2126  {
2128  return FALSE;
2129  }
2130 
2131  ctxt.type = CALLBACK_ENUMPROC;
2132  ctxt.u.callback = (TIMEFMT_ENUMPROCW)proc;
2133  ctxt.lcid = lcid;
2134  ctxt.flags = flags;
2135  ctxt.unicode = FALSE;
2136 
2137  return NLS_EnumTimeFormats(&ctxt);
2138 }
2139 
2140 /**************************************************************************
2141  * EnumTimeFormatsW (KERNEL32.@)
2142  */
2144 {
2145  struct enumtimeformats_context ctxt;
2146 
2147  ctxt.type = CALLBACK_ENUMPROC;
2148  ctxt.u.callback = proc;
2149  ctxt.lcid = lcid;
2150  ctxt.flags = flags;
2151  ctxt.unicode = TRUE;
2152 
2153  return NLS_EnumTimeFormats(&ctxt);
2154 }
2155 
2156 #if _WIN32_WINNT >= 0x600
2157 /**************************************************************************
2158  * EnumTimeFormatsEx (KERNEL32.@)
2159  */
2160 BOOL WINAPI EnumTimeFormatsEx(TIMEFMT_ENUMPROCEX proc, const WCHAR *locale, DWORD flags, LPARAM lParam)
2161 {
2162  struct enumtimeformats_context ctxt;
2163 
2164  ctxt.type = CALLBACK_ENUMPROCEX;
2165  ctxt.u.callbackex = proc;
2166  ctxt.lcid = LocaleNameToLCID(locale, 0);
2167  ctxt.flags = flags;
2168  ctxt.lParam = lParam;
2169  ctxt.unicode = TRUE;
2170 
2171  return NLS_EnumTimeFormats(&ctxt);
2172 }
2173 #endif /* _WIN32_WINNT >= 0x600 */
2174 
2176  enum enum_callback_type type; /* callback kind */
2177  union {
2178  CALINFO_ENUMPROCW callback; /* user callback pointer */
2181  } u;
2182  LCID lcid; /* locale of interest */
2183  CALID calendar; /* specific calendar or ENUM_ALL_CALENDARS */
2184  CALTYPE caltype; /* calendar information type */
2185  LPARAM lParam; /* user input parameter passed to callback, for ExEx case only */
2186  BOOL unicode; /* A vs W callback type, only for regular and Ex callbacks */
2187 };
2188 
2189 /******************************************************************************
2190  * NLS_EnumCalendarInfo <internal>
2191  * Enumerates calendar information for a specified locale.
2192  *
2193  * PARAMS
2194  * ctxt [I] enumeration context, see 'struct enumcalendar_context'
2195  *
2196  * RETURNS
2197  * Success: TRUE.
2198  * Failure: FALSE. Use GetLastError() to determine the cause.
2199  *
2200  * NOTES
2201  * When the ANSI version of this function is used with a Unicode-only LCID,
2202  * the call can succeed because the system uses the system code page.
2203  * However, characters that are undefined in the system code page appear
2204  * in the string as a question mark (?).
2205  *
2206  * TODO
2207  * The above note should be respected by GetCalendarInfoA.
2208  */
2210 {
2211  WCHAR *buf, *opt = NULL, *iter = NULL;
2212  CALID calendar = ctxt->calendar;
2213  BOOL ret = FALSE;
2214  int bufSz = 200; /* the size of the buffer */
2215 
2216  if (ctxt->u.callback == NULL)
2217  {
2219  return FALSE;
2220  }
2221 
2222  buf = HeapAlloc(GetProcessHeap(), 0, bufSz);
2223  if (buf == NULL)
2224  {
2226  return FALSE;
2227  }
2228 
2229  if (calendar == ENUM_ALL_CALENDARS)
2230  {
2231  int optSz = GetLocaleInfoW(ctxt->lcid, LOCALE_IOPTIONALCALENDAR, NULL, 0);
2232  if (optSz > 1)
2233  {
2234  opt = HeapAlloc(GetProcessHeap(), 0, optSz * sizeof(WCHAR));
2235  if (opt == NULL)
2236  {
2238  goto cleanup;
2239  }
2240  if (GetLocaleInfoW(ctxt->lcid, LOCALE_IOPTIONALCALENDAR, opt, optSz))
2241  iter = opt;
2242  }
2243  calendar = NLS_GetLocaleNumber(ctxt->lcid, LOCALE_ICALENDARTYPE);
2244  }
2245 
2246  while (TRUE) /* loop through calendars */
2247  {
2248  do /* loop until there's no error */
2249  {
2250  if (ctxt->caltype & CAL_RETURN_NUMBER)
2251  ret = GetCalendarInfoW(ctxt->lcid, calendar, ctxt->caltype, NULL, bufSz / sizeof(WCHAR), (LPDWORD)buf);
2252  else if (ctxt->unicode)
2253  ret = GetCalendarInfoW(ctxt->lcid, calendar, ctxt->caltype, buf, bufSz / sizeof(WCHAR), NULL);
2254  else ret = GetCalendarInfoA(ctxt->lcid, calendar, ctxt->caltype, (CHAR*)buf, bufSz / sizeof(CHAR), NULL);
2255 
2256  if (!ret)
2257  {
2259  { /* so resize it */
2260  int newSz;
2261  if (ctxt->unicode)
2262  newSz = GetCalendarInfoW(ctxt->lcid, calendar, ctxt->caltype, NULL, 0, NULL) * sizeof(WCHAR);
2263  else newSz = GetCalendarInfoA(ctxt->lcid, calendar, ctxt->caltype, NULL, 0, NULL) * sizeof(CHAR);
2264  if (bufSz >= newSz)
2265  {
2266  ERR("Buffer resizing disorder: was %d, requested %d.\n", bufSz, newSz);
2267  goto cleanup;
2268  }
2269  bufSz = newSz;
2270  WARN("Buffer too small; resizing to %d bytes.\n", bufSz);
2271  buf = HeapReAlloc(GetProcessHeap(), 0, buf, bufSz);
2272  if (buf == NULL)
2273  goto cleanup;
2274  } else goto cleanup;
2275  }
2276  } while (!ret);
2277 
2278  /* Here we are. We pass the buffer to the correct version of
2279  * the callback. Because it's not the same number of params,
2280  * we must check for Ex, but we don't care about Unicode
2281  * because the buffer is already in the correct format.
2282  */
2283  switch (ctxt->type)
2284  {
2285  case CALLBACK_ENUMPROC:
2286  ret = ctxt->u.callback(buf);
2287  break;
2288  case CALLBACK_ENUMPROCEX:
2289  ret = ctxt->u.callbackex(buf, calendar);
2290  break;
2291  case CALLBACK_ENUMPROCEXEX:
2292  ret = ctxt->u.callbackexex(buf, calendar, NULL, ctxt->lParam);
2293  break;
2294  default:
2295  ;
2296  }
2297 
2298  if (!ret) { /* the callback told to stop */
2299  ret = TRUE;
2300  break;
2301  }
2302 
2303  if ((iter == NULL) || (*iter == 0)) /* no more calendars */
2304  break;
2305 
2306  calendar = 0;
2307  while ((*iter >= '0') && (*iter <= '9'))
2308  calendar = calendar * 10 + *iter++ - '0';
2309 
2310  if (*iter++ != 0)
2311  {
2313  ret = FALSE;
2314  break;
2315  }
2316  }
2317 
2318 cleanup:
2319  HeapFree(GetProcessHeap(), 0, opt);
2320  HeapFree(GetProcessHeap(), 0, buf);
2321  return ret;
2322 }
2323 
2324 /******************************************************************************
2325  * EnumCalendarInfoA [KERNEL32.@]
2326  */
2328  CALID calendar,CALTYPE caltype )
2329 {
2330  struct enumcalendar_context ctxt;
2331 
2332  TRACE("(%p,0x%08x,0x%08x,0x%08x)\n", calinfoproc, locale, calendar, caltype);
2333 
2334  ctxt.type = CALLBACK_ENUMPROC;
2335  ctxt.u.callback = (CALINFO_ENUMPROCW)calinfoproc;
2336  ctxt.lcid = locale;
2337  ctxt.calendar = calendar;
2338  ctxt.caltype = caltype;
2339  ctxt.lParam = 0;
2340  ctxt.unicode = FALSE;
2341  return NLS_EnumCalendarInfo(&ctxt);
2342 }
2343 
2344 /******************************************************************************
2345  * EnumCalendarInfoW [KERNEL32.@]
2346  */
2349 {
2350  struct enumcalendar_context ctxt;
2351 
2352  TRACE("(%p,0x%08x,0x%08x,0x%08x)\n", calinfoproc, locale, calendar, caltype);
2353 
2354  ctxt.type = CALLBACK_ENUMPROC;
2355  ctxt.u.callback = calinfoproc;
2356  ctxt.lcid = locale;
2357  ctxt.calendar = calendar;
2358  ctxt.caltype = caltype;
2359  ctxt.lParam = 0;
2360  ctxt.unicode = TRUE;
2361  return NLS_EnumCalendarInfo(&ctxt);
2362 }
2363 
2364 /******************************************************************************
2365  * EnumCalendarInfoExA [KERNEL32.@]
2366  */
2369 {
2370  struct enumcalendar_context ctxt;
2371 
2372  TRACE("(%p,0x%08x,0x%08x,0x%08x)\n", calinfoproc, locale, calendar, caltype);
2373 
2374  ctxt.type = CALLBACK_ENUMPROCEX;
2375  ctxt.u.callbackex = (CALINFO_ENUMPROCEXW)calinfoproc;
2376  ctxt.lcid = locale;
2377  ctxt.calendar = calendar;
2378  ctxt.caltype = caltype;
2379  ctxt.lParam = 0;
2380  ctxt.unicode = FALSE;
2381  return NLS_EnumCalendarInfo(&ctxt);
2382 }
2383 
2384 /******************************************************************************
2385  * EnumCalendarInfoExW [KERNEL32.@]
2386  */
2389 {
2390  struct enumcalendar_context ctxt;
2391 
2392  TRACE("(%p,0x%08x,0x%08x,0x%08x)\n", calinfoproc, locale, calendar, caltype);
2393 
2394  ctxt.type = CALLBACK_ENUMPROCEX;
2395  ctxt.u.callbackex = calinfoproc;
2396  ctxt.lcid = locale;
2397  ctxt.calendar = calendar;
2398  ctxt.caltype = caltype;
2399  ctxt.lParam = 0;
2400  ctxt.unicode = TRUE;
2401  return NLS_EnumCalendarInfo(&ctxt);
2402 }
2403 
2404 #if _WIN32_WINNT >= 0x600
2405 /******************************************************************************
2406  * EnumCalendarInfoExEx [KERNEL32.@]
2407  */
2408 BOOL WINAPI EnumCalendarInfoExEx( CALINFO_ENUMPROCEXEX calinfoproc, LPCWSTR locale, CALID calendar,
2410 {
2411  struct enumcalendar_context ctxt;
2412 
2413  TRACE("(%p,%s,0x%08x,%p,0x%08x,0x%ld)\n", calinfoproc, debugstr_w(locale), calendar, reserved, caltype, lParam);
2414 
2415  ctxt.type = CALLBACK_ENUMPROCEXEX;
2416  ctxt.u.callbackexex = calinfoproc;
2417  ctxt.lcid = LocaleNameToLCID(locale, 0);
2418  ctxt.calendar = calendar;
2419  ctxt.caltype = caltype;
2420  ctxt.lParam = lParam;
2421  ctxt.unicode = TRUE;
2422  return NLS_EnumCalendarInfo(&ctxt);
2423 }
2424 #endif /* _WIN32_WINNT >= 0x600 */
2425 
2426 /*********************************************************************
2427  * GetCalendarInfoA (KERNEL32.@)
2428  *
2429  */
2431  LPSTR lpCalData, int cchData, LPDWORD lpValue)
2432 {
2433  int ret, cchDataW = cchData;
2434  LPWSTR lpCalDataW = NULL;
2435 #ifdef __REACTOS__
2436  DWORD cp = CP_ACP;
2437  if (!(CalType & CAL_USE_CP_ACP))
2438  {
2439  DWORD dwFlags = ((CalType & CAL_NOUSEROVERRIDE) ? LOCALE_NOUSEROVERRIDE : 0);
2441  if (!node)
2442  {
2444  return 0;
2445  }
2446  cp = node->dwCodePage;
2447  }
2448  if ((CalType & 0xFFFF) == CAL_SABBREVERASTRING)
2449  {
2450  /* NOTE: CAL_SABBREVERASTRING is not supported in GetCalendarInfoA */
2452  return 0;
2453  }
2454 #endif
2455 
2457  {
2459  return 0;
2460  }
2461 
2462  if (!cchData && !(CalType & CAL_RETURN_NUMBER))
2463  cchDataW = GetCalendarInfoW(lcid, Calendar, CalType, NULL, 0, NULL);
2464  if (!(lpCalDataW = HeapAlloc(GetProcessHeap(), 0, cchDataW*sizeof(WCHAR))))
2465  return 0;
2466 
2467  ret = GetCalendarInfoW(lcid, Calendar, CalType, lpCalDataW, cchDataW, lpValue);
2468  if(ret && lpCalDataW && lpCalData)
2469 #ifdef __REACTOS__
2470  ret = WideCharToMultiByte(cp, 0, lpCalDataW, -1, lpCalData, cchData, NULL, NULL);
2471 #else
2472  ret = WideCharToMultiByte(CP_ACP, 0, lpCalDataW, -1, lpCalData, cchData, NULL, NULL);
2473 #endif
2474  else if (CalType & CAL_RETURN_NUMBER)
2475  ret *= sizeof(WCHAR);
2476  HeapFree(GetProcessHeap(), 0, lpCalDataW);
2477 
2478  return ret;
2479 }
2480 
2481 /*********************************************************************
2482  * GetCalendarInfoW (KERNEL32.@)
2483  *
2484  */
2485 int WINAPI GetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType,
2486  LPWSTR lpCalData, int cchData, LPDWORD lpValue)
2487 {
2488  static const LCTYPE caltype_lctype_map[] = {
2489  0, /* not used */
2490  0, /* CAL_ICALINTVALUE */
2491  0, /* CAL_SCALNAME */
2492  0, /* CAL_IYEAROFFSETRANGE */
2493  0, /* CAL_SERASTRING */
2536  LOCALE_SYEARMONTH,
2537  0, /* CAL_ITWODIGITYEARMAX */
2538 #if (WINVER >= 0x0600) /* ReactOS */
2539  LOCALE_SSHORTESTDAYNAME1,
2540  LOCALE_SSHORTESTDAYNAME2,
2541  LOCALE_SSHORTESTDAYNAME3,
2542  LOCALE_SSHORTESTDAYNAME4,
2543  LOCALE_SSHORTESTDAYNAME5,
2544  LOCALE_SSHORTESTDAYNAME6,
2545  LOCALE_SSHORTESTDAYNAME7,
2546 #endif
2548  0, /* CAL_SABBREVERASTRING */
2549  };
2550  DWORD localeflags = 0;
2551  CALTYPE calinfo;
2552 
2553  if (CalType & CAL_NOUSEROVERRIDE)
2554  FIXME("flag CAL_NOUSEROVERRIDE used, not fully implemented\n");
2555  if (CalType & CAL_USE_CP_ACP)
2556  FIXME("flag CAL_USE_CP_ACP used, not fully implemented\n");
2557 
2558  if (CalType & CAL_RETURN_NUMBER) {
2559  if (!lpValue)
2560  {
2562  return 0;
2563  }
2564  if (lpCalData != NULL)
2565  WARN("lpCalData not NULL (%p) when it should!\n", lpCalData);
2566  if (cchData != 0)
2567  WARN("cchData not 0 (%d) when it should!\n", cchData);
2568  } else {
2569  if (lpValue != NULL)
2570  WARN("lpValue not NULL (%p) when it should!\n", lpValue);
2571  }
2572 
2573  /* FIXME: No verification is made yet wrt Locale
2574  * for the CALTYPES not requiring GetLocaleInfoA */
2575 
2576  calinfo = CalType & 0xffff;
2577 
2578 #ifdef __REACTOS__
2579  if (CalType & LOCALE_RETURN_GENITIVE_NAMES)
2580 #else
2581  if (CalType & CAL_RETURN_GENITIVE_NAMES)
2582 #endif
2583  localeflags |= LOCALE_RETURN_GENITIVE_NAMES;
2584 
2585  switch (calinfo) {
2586  case CAL_ICALINTVALUE:
2587 #ifdef __REACTOS__
2588  if (IS_LCID_JAPANESE(Locale))
2589  {
2590  if (CalType & CAL_RETURN_NUMBER)
2591  {
2592  *lpValue = CAL_JAPAN;
2593  return sizeof(DWORD) / sizeof(WCHAR);
2594  }
2595  else
2596  {
2597  static const WCHAR fmtW[] = {'%','u',0};
2598  WCHAR buffer[10];
2599  int ret = snprintfW( buffer, 10, fmtW, CAL_JAPAN ) + 1;
2600  if (!lpCalData) return ret;
2601  if (ret <= cchData)
2602  {
2603  strcpyW( lpCalData, buffer );
2604  return ret;
2605  }
2607  return 0;
2608  }
2609  }
2610 #endif
2611  if (CalType & CAL_RETURN_NUMBER)
2612  return GetLocaleInfoW(Locale, LOCALE_RETURN_NUMBER | LOCALE_ICALENDARTYPE,
2613  (LPWSTR)lpValue, 2);
2614  return GetLocaleInfoW(Locale, LOCALE_ICALENDARTYPE, lpCalData, cchData);
2615  case CAL_SCALNAME:
2616 #ifdef __REACTOS__
2617  if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
2618  {
2619  // Wareki
2620  lpCalData[0] = 0x548C;
2621  lpCalData[1] = 0x66A6;
2622  lpCalData[2] = 0;
2623  return 3;
2624  }
2625 #endif
2626  FIXME("Unimplemented caltype %d\n", calinfo);
2627  if (lpCalData) *lpCalData = 0;
2628  return 1;
2629  case CAL_IYEAROFFSETRANGE:
2630 #ifdef __REACTOS__
2631  if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
2632  {
2634  if (pEra)
2635  {
2636  if (CalType & CAL_RETURN_NUMBER)
2637  {
2638  *lpValue = pEra->wYear;
2639  return sizeof(DWORD) / sizeof(WCHAR);
2640  }
2641  else
2642  {
2643  static const WCHAR fmtW[] = {'%','u',0};
2644  WCHAR buffer[10];
2645  int ret = snprintfW( buffer, 10, fmtW, pEra->wYear ) + 1;
2646  if (!lpCalData) return ret;
2647  if (ret <= cchData)
2648  {
2649  strcpyW( lpCalData, buffer );
2650  return ret;
2651  }
2653  return 0;
2654  }
2655  }
2656  else
2657  {
2659  return 0;
2660  }
2661  }
2662 #endif
2663  FIXME("Unimplemented caltype %d\n", calinfo);
2664  return 0;
2665  case CAL_SERASTRING:
2666 #ifdef __REACTOS__
2667  if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
2668  {
2670  if (pEra)
2671  {
2672  RtlStringCchCopyW(lpCalData, cchData, pEra->szEraName);
2673  return strlenW(lpCalData) + 1;
2674  }
2675  else
2676  {
2678  return 0;
2679  }
2680  }
2681 #endif
2682  FIXME("Unimplemented caltype %d\n", calinfo);
2683  return 0;
2684  case CAL_SSHORTDATE:
2685  case CAL_SLONGDATE:
2686  case CAL_SDAYNAME1:
2687  case CAL_SDAYNAME2:
2688  case CAL_SDAYNAME3:
2689  case CAL_SDAYNAME4:
2690  case CAL_SDAYNAME5:
2691  case CAL_SDAYNAME6:
2692  case CAL_SDAYNAME7:
2693  case CAL_SABBREVDAYNAME1:
2694  case CAL_SABBREVDAYNAME2:
2695  case CAL_SABBREVDAYNAME3:
2696  case CAL_SABBREVDAYNAME4:
2697  case CAL_SABBREVDAYNAME5:
2698  case CAL_SABBREVDAYNAME6:
2699  case CAL_SABBREVDAYNAME7:
2700  case CAL_SMONTHNAME1:
2701  case CAL_SMONTHNAME2:
2702  case CAL_SMONTHNAME3:
2703  case CAL_SMONTHNAME4:
2704  case CAL_SMONTHNAME5:
2705  case CAL_SMONTHNAME6:
2706  case CAL_SMONTHNAME7:
2707  case CAL_SMONTHNAME8:
2708  case CAL_SMONTHNAME9:
2709  case CAL_SMONTHNAME10:
2710  case CAL_SMONTHNAME11:
2711  case CAL_SMONTHNAME12:
2712  case CAL_SMONTHNAME13:
2713  case CAL_SABBREVMONTHNAME1:
2714  case CAL_SABBREVMONTHNAME2:
2715  case CAL_SABBREVMONTHNAME3:
2716  case CAL_SABBREVMONTHNAME4:
2717  case CAL_SABBREVMONTHNAME5:
2718  case CAL_SABBREVMONTHNAME6:
2719  case CAL_SABBREVMONTHNAME7:
2720  case CAL_SABBREVMONTHNAME8:
2721  case CAL_SABBREVMONTHNAME9:
2726  case CAL_SYEARMONTH:
2727  return GetLocaleInfoW(Locale, caltype_lctype_map[calinfo] | localeflags, lpCalData, cchData);
2728  case CAL_ITWODIGITYEARMAX:
2729 #ifdef __REACTOS__
2730  if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
2731  {
2732  if (CalType & CAL_RETURN_NUMBER)
2733  {
2734  *lpValue = JAPANESE_MAX_TWODIGITYEAR;
2735  return sizeof(DWORD) / sizeof(WCHAR);
2736  }
2737  else
2738  {
2739  static const WCHAR fmtW[] = {'%','u',0};
2740  WCHAR buffer[10];
2741  int ret = snprintfW( buffer, 10, fmtW, JAPANESE_MAX_TWODIGITYEAR ) + 1;
2742  if (!lpCalData) return ret;
2743  if (ret <= cchData)
2744  {
2745  strcpyW( lpCalData, buffer );
2746  return ret;
2747  }
2749  return 0;
2750  }
2751  }
2752 #endif
2753  if (CalType & CAL_RETURN_NUMBER)
2754  {
2755  *lpValue = CALINFO_MAX_YEAR;
2756  return sizeof(DWORD) / sizeof(WCHAR);
2757  }
2758  else
2759  {
2760  static const WCHAR fmtW[] = {'%','u',0};
2761  WCHAR buffer[10];
2762  int ret = snprintfW( buffer, 10, fmtW, CALINFO_MAX_YEAR ) + 1;
2763  if (!lpCalData) return ret;
2764  if (ret <= cchData)
2765  {
2766  strcpyW( lpCalData, buffer );
2767  return ret;
2768  }
2770  return 0;
2771  }
2772  break;
2773 #ifdef __REACTOS__
2774  case CAL_SABBREVERASTRING:
2775  if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
2776  {
2778  if (pEra)
2779  {
2780  RtlStringCchCopyW(lpCalData, cchData, pEra->szEraAbbrev);
2781  return strlenW(lpCalData) + 1;
2782  }
2783  }
2785  return 0;
2786 #endif
2787  default:
2788  FIXME("Unknown caltype %d\n", calinfo);
2790  return 0;
2791  }
2792  return 0;
2793 }
2794 
2795 #if _WIN32_WINNT >= 0x600
2796 /*********************************************************************
2797  * GetCalendarInfoEx (KERNEL32.@)
2798  */
2799 int WINAPI GetCalendarInfoEx(LPCWSTR locale, CALID calendar, LPCWSTR lpReserved, CALTYPE caltype,
2800  LPWSTR data, int len, DWORD *value)
2801 {
2802  static int once;
2803 
2804  LCID lcid = LocaleNameToLCID(locale, 0);
2805  if (!once++)
2806  FIXME("(%s, %d, %p, 0x%08x, %p, %d, %p): semi-stub\n", debugstr_w(locale), calendar, lpReserved, caltype,
2807  data, len, value);
2809 }
2810 #endif
2811 
2812 /*********************************************************************
2813  * SetCalendarInfoA (KERNEL32.@)
2814  *
2815  */
2816 int WINAPI SetCalendarInfoA(LCID Locale, CALID Calendar, CALTYPE CalType, LPCSTR lpCalData)
2817 {
2818  FIXME("(%08x,%08x,%08x,%s): stub\n",
2819  Locale, Calendar, CalType, debugstr_a(lpCalData));
2820  return 0;
2821 }
2822 
2823 /*********************************************************************
2824  * SetCalendarInfoW (KERNEL32.@)
2825  *
2826  *
2827  */
2828 int WINAPI SetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType, LPCWSTR lpCalData)
2829 {
2830  FIXME("(%08x,%08x,%08x,%s): stub\n",
2831  Locale, Calendar, CalType, debugstr_w(lpCalData));
2832  return 0;
2833 }
BOOL(CALLBACK * CALINFO_ENUMPROCA)(LPSTR)
Definition: winnls.h:524
LPWSTR lpThousandSep
Definition: winnls.h:643
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define LOCALE_SGROUPING
Definition: winnls.h:44
NTSTRSAFEAPI RtlStringCbCopyW(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:174
#define GetShortDate(fmt)
Definition: lcformat.c:96
#define CAL_SDAYNAME6
Definition: winnls.h:405
#define CAL_SCALNAME
Definition: winnls.h:395
#define LOCALE_IDEFAULTANSICODEPAGE
Definition: winnls.h:38
BOOL WINAPI EnumCalendarInfoExA(CALINFO_ENUMPROCEXA calinfoproc, LCID locale, CALID calendar, CALTYPE caltype)
Definition: lcformat.c:2367
BOOL WINAPI EnumCalendarInfoExW(CALINFO_ENUMPROCEXW calinfoproc, LCID locale, CALID calendar, CALTYPE caltype)
Definition: lcformat.c:2387
#define LOCALE_SABBREVMONTHNAME12
Definition: winnls.h:115
BOOL WINAPI EnumDateFormatsA(DATEFMT_ENUMPROCA proc, LCID lcid, DWORD flags)
Definition: lcformat.c:2003
union enumdateformats_context::@455 u
#define GetNegative(fmt)
Definition: lcformat.c:94
#define CAL_SABBREVMONTHNAME12
Definition: winnls.h:438
#define snprintfW
Definition: unicode.h:60
BOOL WINAPI EnumTimeFormatsW(TIMEFMT_ENUMPROCW proc, LCID lcid, DWORD flags)
Definition: lcformat.c:2143
CURRENCYFMTW cyfmt
Definition: lcformat.c:86
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
#define LOCALE_SABBREVDAYNAME2
Definition: winnls.h:85
#define LOCALE_SABBREVMONTHNAME1
Definition: winnls.h:104
BOOL JapaneseEra_IsFirstYearGannen(void)
Definition: japanese.c:63
BOOL WINAPI EnumDateFormatsExW(DATEFMT_ENUMPROCEXW proc, LCID lcid, DWORD flags)
Definition: lcformat.c:1984
#define DWORD_PTR
Definition: treelist.c:76
#define NF_ROUND
Definition: lcformat.c:1184
#define LOCALE_SMONTHNAME5
Definition: winnls.h:95
int WINAPI SetCalendarInfoA(LCID Locale, CALID Calendar, CALTYPE CalType, LPCSTR lpCalData)
Definition: lcformat.c:2816
#define WideCharToMultiByte
Definition: compat.h:111
LPWSTR lpDecimalSep
Definition: winnls.h:642
#define error(str)
Definition: mkdosfs.c:1605
UINT PositiveOrder
Definition: winnls.h:615
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
union enumtimeformats_context::@456 u
#define NLS_NEG_RIGHT_SPACE
Definition: lcformat.c:1191
UINT Grouping
Definition: winnls.h:611
#define LOCALE_SABBREVMONTHNAME6
Definition: winnls.h:109
WORD wMonth
Definition: winbase.h:884
#define LOCALE_SMONTHNAME2
Definition: winnls.h:92
UINT NegativeOrder
Definition: winnls.h:614
BOOL WINAPI EnumTimeFormatsA(TIMEFMT_ENUMPROCA proc, LCID lcid, DWORD flags)
Definition: lcformat.c:2120
CALINFO_ENUMPROCEXEX callbackexex
Definition: lcformat.c:2180
#define TRUE
Definition: types.h:120
INT WINAPI GetDateFormatA(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCSTR lpFormat, LPSTR lpDateStr, INT cchOut)
Definition: lcformat.c:922
#define LOCALE_SABBREVDAYNAME4
Definition: winnls.h:87
#define LANG_HINDI
Definition: nls.h:68
UINT LeadingZero
Definition: winnls.h:610
#define CP_ACP
Definition: compat.h:109
INT WINAPI GetLocaleInfoA(LCID lcid, LCTYPE lctype, LPSTR buffer, INT len)
Definition: lang.c:1018
#define LOCALE_SABBREVDAYNAME7
Definition: winnls.h:90
#define LOCALE_SABBREVDAYNAME1
Definition: winnls.h:84
WORD wDayOfWeek
Definition: winbase.h:885
#define DATE_SHORTDATE
Definition: winnls.h:193
GLuint GLuint GLsizei count
Definition: gl.h:1545
INT WINAPI GetCurrencyFormatW(LCID lcid, DWORD dwFlags, LPCWSTR lpszValue, const CURRENCYFMTW *lpFormat, LPWSTR lpCurrencyStr, int cchOut)
Definition: lcformat.c:1564
BOOL WINAPI EnumDateFormatsExA(DATEFMT_ENUMPROCEXA proc, LCID lcid, DWORD flags)
Definition: lcformat.c:1968
char CHAR
Definition: xmlstorage.h:175
#define WARN(fmt,...)
Definition: debug.h:112
#define CAL_SMONTHNAME1
Definition: winnls.h:414
BOOL(CALLBACK * DATEFMT_ENUMPROCEXA)(LPSTR, CALID)
Definition: winnls.h:541
#define LOCALE_SMONTHNAME13
Definition: winnls.h:103
#define LOCALE_SDAYNAME2
Definition: winnls.h:78
#define LANG_DIVEHI
Definition: nls.h:50
#define TIME_TIMEVARSONLY
Definition: lcformat.c:67
const char * fmt
Definition: wsprintf.c:30
#define LOCALE_SMONTHNAME6
Definition: winnls.h:96
#define LOCALE_ICALENDARTYPE
Definition: winnls.h:73
#define LOCALE_ILZERO
Definition: winnls.h:46
void * next
Definition: dlist.c:360
UINT Grouping
Definition: winnls.h:641
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define GetGenitiveMonth(fmt, mth)
Definition: lcformat.c:105
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1044
#define CF_CY_RIGHT
Definition: lcformat.c:1556
#define LOCALE_SABBREVMONTHNAME7
Definition: winnls.h:110
GLuint buffer
Definition: glext.h:5915
int WINAPI GetDateFormatEx(LPCWSTR, DWORD, const SYSTEMTIME *, LPCWSTR, LPWSTR, int, LPCWSTR)
#define GetAM(fmt)
Definition: lcformat.c:98
#define IsLiteralMarker(p)
Definition: lcformat.c:377
DWORD LCID
Definition: nls.h:13
#define DATE_DATEVARSONLY
Definition: lcformat.c:66
static HANDLE proc()
Definition: pdb.c:32
#define CF_MINUS_BEFORE
Definition: lcformat.c:1554
LPWSTR lpThousandSep
Definition: winnls.h:613
__u16 time
Definition: mkdosfs.c:366
#define CAL_SERASTRING
Definition: winnls.h:397
GLenum GLuint GLsizei bufsize
Definition: glext.h:7473
char * LPSTR
Definition: xmlstorage.h:182
#define LOCALE_SABBREVMONTHNAME3
Definition: winnls.h:106
#define DWORD
Definition: nt_native.h:44
int32_t INT
Definition: typedefs.h:58
#define CAL_SMONTHNAME4
Definition: winnls.h:417
#define LOCALE_SMONTHNAME8
Definition: winnls.h:98
#define CAL_SDAYNAME3
Definition: winnls.h:402
#define LOCALE_RETURN_GENITIVE_NAMES
Definition: winnls.h:24
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
#define CAL_SABBREVMONTHNAME7
Definition: winnls.h:433
#define LOCALE_SABBREVMONTHNAME8
Definition: winnls.h:111
#define LOCALE_SCURRENCY
Definition: winnls.h:49
UINT NegativeOrder
Definition: winnls.h:644
int WINAPI GetTimeFormatEx(LPCWSTR, DWORD, const SYSTEMTIME *, LPCWSTR, LPWSTR, int)
#define CF_MINUS_LEFT
Definition: lcformat.c:1552
#define LOCALE_INEGNUMBER
Definition: winnls.h:47
#define LOCALE_SDAYNAME5
Definition: winnls.h:81
#define CAL_SABBREVDAYNAME2
Definition: winnls.h:408
static const NLS_FORMAT_NODE * NLS_GetFormats(LCID lcid, DWORD dwFlags)
Definition: lcformat.c:178
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: lang.c:1098
enum enum_callback_type type
Definition: lcformat.c:1877
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
struct node node
#define LOCALE_SDAYNAME1
Definition: winnls.h:77
#define LOCALE_SABBREVDAYNAME3
Definition: winnls.h:86
INT WINAPI GetTimeFormatA(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCSTR lpFormat, LPSTR lpTimeStr, INT cchOut)
Definition: lcformat.c:1030
#define CAL_SDAYNAME7
Definition: winnls.h:406
WORD wYear
Definition: winbase.h:883
#define LOCALE_SABBREVMONTHNAME5
Definition: winnls.h:108
DWORD LCTYPE
Definition: winnls.h:514
#define LOCALE_SMONTHNAME1
Definition: winnls.h:91
#define LOCALE_STHOUSAND
Definition: winnls.h:43
#define LOCALE_NOUSEROVERRIDE
Definition: winnls.h:19
DATEFMT_ENUMPROCEXW callbackex
Definition: lcformat.c:1880
#define FALSE
Definition: types.h:117
LCID WINAPI ConvertDefaultLocale(LCID lcid)
Definition: lang.c:1502
#define CAL_SABBREVDAYNAME3
Definition: winnls.h:409
Definition: _locale.h:75
#define CAL_SABBREVMONTHNAME10
Definition: winnls.h:436
unsigned int BOOL
Definition: ntddk_ex.h:94
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define CAL_SABBREVMONTHNAME4
Definition: winnls.h:430
#define NLS_NEG_LEFT_SPACE
Definition: lcformat.c:1189
#define LOCALE_SABBREVMONTHNAME10
Definition: winnls.h:113
static size_t double number
Definition: printf.c:69
#define LOCALE_SABBREVDAYNAME6
Definition: winnls.h:89
BOOL WINAPI EnumCalendarInfoW(CALINFO_ENUMPROCW calinfoproc, LCID locale, CALID calendar, CALTYPE caltype)
Definition: lcformat.c:2347
#define debugstr_w
Definition: kernel32.h:32
#define GetPM(fmt)
Definition: lcformat.c:99
UINT NumDigits
Definition: winnls.h:639
#define LOCALE_SLONGDATE
Definition: winnls.h:61
#define FIXME(fmt,...)
Definition: debug.h:111
static BOOL NLS_EnumDateFormats(const struct enumdateformats_context *ctxt)
Definition: lcformat.c:1900
int WINAPI GetCalendarInfoA(LCID lcid, CALID Calendar, CALTYPE CalType, LPSTR lpCalData, int cchData, LPDWORD lpValue)
Definition: lcformat.c:2430
CALINFO_ENUMPROCW callback
Definition: lcformat.c:2178
#define CAL_SSHORTDATE
Definition: winnls.h:398
r reserved
Definition: btrfs.c:2940
#define CAL_SABBREVMONTHNAME3
Definition: winnls.h:429
#define CAL_JAPAN
Definition: winnls.h:442
static CRITICAL_SECTION_DEBUG NLS_FormatsCS_debug
Definition: lcformat.c:110
#define GET_LOCALE_NUMBER(num, type)
Definition: lcformat.c:167
BOOL(CALLBACK * DATEFMT_ENUMPROCEXW)(LPWSTR, CALID)
Definition: winnls.h:542
#define CAL_SMONTHNAME13
Definition: winnls.h:426
#define CF_MINUS_RIGHT
Definition: lcformat.c:1553
const WCHAR * str
WORD wMinute
Definition: winbase.h:888
#define DEBUG_CHANNEL(args)
Definition: rdesktop.h:159
#define nls
Definition: kernel32.h:13
#define LOCALE_INEGCURR
Definition: winnls.h:57
#define LANG_KONKANI
Definition: nls.h:83
#define LOCALE_SABBREVMONTHNAME4
Definition: winnls.h:107
enum enum_callback_type type
Definition: lcformat.c:2176
static INT NLS_GetDateTimeFormatW(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCWSTR lpFormat, LPWSTR lpStr, INT cchOut)
Definition: lcformat.c:400
LONG_PTR LPARAM
Definition: windef.h:208
#define LOCALE_SMONTHNAME4
Definition: winnls.h:94
#define LOCALE_SABBREVMONTHNAME13
Definition: winnls.h:116
#define LOCALE_SDECIMAL
Definition: winnls.h:42
VOID WINAPI GetLocalTime(OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:286
const char * LPCSTR
Definition: xmlstorage.h:183
#define GetLongDate(fmt)
Definition: lcformat.c:95
struct _NLS_FORMAT_NODE * next
Definition: lcformat.c:90
BOOL(CALLBACK * CALINFO_ENUMPROCW)(LPWSTR)
Definition: winnls.h:525
#define IsTimeFmtChar(p)
Definition: lcformat.c:379
#define GetLongMonth(fmt, mth)
Definition: lcformat.c:104
WCHAR szShortAM[2]
Definition: lcformat.c:88
#define CAL_SABBREVDAYNAME1
Definition: winnls.h:407
#define NLS_NEG_RIGHT
Definition: lcformat.c:1190
#define NLS_NUM_CACHED_STRINGS
Definition: lcformat.c:78
BOOL(CALLBACK * DATEFMT_ENUMPROCEXEX)(LPWSTR, CALID, LPARAM)
Definition: winnls.h:522
INT WINAPI GetCurrencyFormatA(LCID lcid, DWORD dwFlags, LPCSTR lpszValue, const CURRENCYFMTA *lpFormat, LPSTR lpCurrencyStr, int cchOut)
Definition: lcformat.c:1482
#define LOCALE_SDAYNAME4
Definition: winnls.h:80
#define CAL_SMONTHNAME7
Definition: winnls.h:420
#define LOCALE_SSHORTTIME
Definition: winnls.h:160
#define LOCALE_ICURRENCY
Definition: winnls.h:56
#define LOCALE_SMONDECIMALSEP
Definition: winnls.h:51
#define GetShortDay(fmt, day)
Definition: lcformat.c:103
#define LOCALE_SMONTHNAME11
Definition: winnls.h:101
BOOL WINAPI EnumCalendarInfoA(CALINFO_ENUMPROCA calinfoproc, LCID locale, CALID calendar, CALTYPE caltype)
Definition: lcformat.c:2327
BOOL WINAPI EnumDateFormatsW(DATEFMT_ENUMPROCW proc, LCID lcid, DWORD flags)
Definition: lcformat.c:2019
#define ENUM_ALL_CALENDARS
Definition: winnls.h:192
#define TRACE(s)
Definition: solgame.cpp:4
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
#define GetProcessHeap()
Definition: compat.h:595
#define LOCALE_SDAYNAME3
Definition: winnls.h:79
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define NF_ISREAL
Definition: lcformat.c:1181
#define LOCALE_SMONTHOUSANDSEP
Definition: winnls.h:52
#define LOCALE_SMONTHNAME10
Definition: winnls.h:100
__wchar_t WCHAR
Definition: xmlstorage.h:180
int WINAPI SetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType, LPCWSTR lpCalData)
Definition: lcformat.c:2828
#define CAL_ICALINTVALUE
Definition: winnls.h:394
#define CAL_SDAYNAME2
Definition: winnls.h:401
BOOL(CALLBACK * TIMEFMT_ENUMPROCA)(LPSTR)
Definition: winnls.h:543
#define debugstr_a
Definition: kernel32.h:31
WCHAR szEraName[16]
Definition: japanese.h:14
#define GetLongDay(fmt, day)
Definition: lcformat.c:102
#define LANG_SANSKRIT
Definition: nls.h:115
BOOL NLS_IsUnicodeOnlyLcid(LCID lcid)
Definition: lcformat.c:350
#define LOCALE_SABBREVMONTHNAME2
Definition: winnls.h:105
union enumcalendar_context::@457 u
PCJAPANESE_ERA JapaneseEra_Find(const SYSTEMTIME *pst OPTIONAL)
Definition: japanese.c:236
#define WINAPI
Definition: msvc.h:6
#define CAL_SMONTHNAME6
Definition: winnls.h:419
#define TIME_NOMINUTESORSECONDS
Definition: winnls.h:274
#define CAL_SLONGDATE
Definition: winnls.h:399
unsigned long DWORD
Definition: ntddk_ex.h:95
DATEFMT_ENUMPROCW callback
Definition: lcformat.c:1879
#define SetLastError(x)
Definition: compat.h:611
#define CAL_IYEAROFFSETRANGE
Definition: winnls.h:396
#define JAPANESE_MAX_TWODIGITYEAR
Definition: japanese.h:7
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
DWORD CALTYPE
Definition: winnls.h:515
#define LOCALE_SDAYNAME7
Definition: winnls.h:83
GLbitfield flags
Definition: glext.h:7161
DWORD CALID
Definition: winnls.h:516
WORD wSecond
Definition: winbase.h:889
#define LOCALE_S1159
Definition: winnls.h:71
static DWORD NLS_GetLocaleNumber(LCID lcid, DWORD dwFlags)
Definition: lcformat.c:128
BOOL(CALLBACK * CALINFO_ENUMPROCEXW)(LPWSTR, CALID)
Definition: winnls.h:527
#define DATE_FORMAT_FLAGS
Definition: lcformat.c:385
TIMEFMT_ENUMPROCEX callbackex
Definition: lcformat.c:2055
#define CF_CY_LEFT
Definition: lcformat.c:1555
BOOL WINAPI IsValidLocale(LCID lcid, DWORD flags)
Definition: lang.c:1548
#define DATE_USE_ALT_CALENDAR
Definition: winnls.h:195
int ret
LPWSTR lpDecimalSep
Definition: winnls.h:612
#define CAL_SMONTHNAME12
Definition: winnls.h:425
#define CAL_SMONTHNAME11
Definition: winnls.h:424
#define LOCALE_SMONTHNAME3
Definition: winnls.h:93
#define LOCALE_SDAYNAME6
Definition: winnls.h:82
#define LOCALE_SNEGATIVESIGN
Definition: winnls.h:118
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
#define LOCALE_SSHORTDATE
Definition: winnls.h:60
#define LANG_KANNADA
Definition: nls.h:77
#define CAL_SABBREVDAYNAME4
Definition: winnls.h:410
static BOOL NLS_EnumTimeFormats(struct enumtimeformats_context *ctxt)
Definition: lcformat.c:2063
#define CAL_SABBREVMONTHNAME1
Definition: winnls.h:427
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
#define GetYearMonth(fmt)
Definition: lcformat.c:100
LPCWSTR lpFormat
Definition: trayclock.cpp:32
#define CAL_SABBREVMONTHNAME13
Definition: winnls.h:439
#define LOCALE_IDIGITS
Definition: winnls.h:45
#define NF_ISNEGATIVE
Definition: lcformat.c:1180
LIST_ENTRY ProcessLocksList
Definition: winbase.h:861
enum_callback_type
Definition: lcformat.c:1870
#define GET_LOCALE_STRING(str, type)
Definition: lcformat.c:170
#define CAL_SMONTHNAME5
Definition: winnls.h:418
unsigned char BYTE
Definition: xxhash.c:193
#define LOCALE_USE_CP_ACP
Definition: winnls.h:20
#define NLS_NEG_LEFT
Definition: lcformat.c:1188
struct _NLS_FORMAT_NODE NLS_FORMAT_NODE
INT WINAPI GetDateFormatW(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCWSTR lpFormat, LPWSTR lpDateStr, INT cchOut)
Definition: lcformat.c:979
NUMBERFMTW fmt
Definition: lcformat.c:85
static BOOL NLS_EnumCalendarInfo(const struct enumcalendar_context *ctxt)
Definition: lcformat.c:2209
#define LANG_MARATHI
Definition: nls.h:98
BOOL(CALLBACK * CALINFO_ENUMPROCEXA)(LPSTR, CALID)
Definition: winnls.h:526
BOOL(CALLBACK * CALINFO_ENUMPROCEXEX)(LPWSTR, CALID, LPWSTR, LPARAM)
Definition: winnls.h:521
LPWSTR lpCurrencySymbol
Definition: winnls.h:616
#define CAL_SMONTHNAME2
Definition: winnls.h:415
#define ERR(fmt,...)
Definition: debug.h:110
WINE_DEFAULT_DEBUG_CHANNEL(nls)
#define CAL_SABBREVMONTHNAME11
Definition: winnls.h:437
WORD wDay
Definition: winbase.h:886
#define CAL_SMONTHNAME10
Definition: winnls.h:423
static const wchar_t void * locale
Definition: printf.c:79
#define LOCALE_SABBREVMONTHNAME9
Definition: winnls.h:112
static INT NLS_GetDateTimeFormatA(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCSTR lpFormat, LPSTR lpStr, INT cchOut)
Definition: lcformat.c:829
BOOL WINAPI SystemTimeToFileTime(IN CONST SYSTEMTIME *lpSystemTime, OUT LPFILETIME lpFileTime)
Definition: time.c:158
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219
#define TIME_FORCE24HOURFORMAT
Definition: winnls.h:277
#define NLS_NEG_PARENS
Definition: lcformat.c:1187
#define LOCALE_SABBREVMONTHNAME11
Definition: winnls.h:114
BOOL(CALLBACK * TIMEFMT_ENUMPROCEX)(LPWSTR, LPARAM)
Definition: winnls.h:523
NTSTRSAFEAPI RtlStringCchCopyW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:127
#define LANG_PUNJABI
Definition: nls.h:109
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define CAL_SABBREVMONTHNAME6
Definition: winnls.h:432
BOOL(CALLBACK * TIMEFMT_ENUMPROCW)(LPWSTR)
Definition: winnls.h:544
#define LOCALE_SABBREVDAYNAME5
Definition: winnls.h:88
#define IsDateFmtChar(p)
Definition: lcformat.c:378
#define ARRAY_SIZE(a)
Definition: main.h:24
__u16 date
Definition: mkdosfs.c:366
#define HeapReAlloc
Definition: compat.h:593
#define DATE_LONGDATE
Definition: winnls.h:194
WORD wHour
Definition: winbase.h:887
INT WINAPI GetNumberFormatA(LCID lcid, DWORD dwFlags, LPCSTR lpszValue, const NUMBERFMTA *lpFormat, LPSTR lpNumberStr, int cchOut)
Definition: lcformat.c:1116
DATEFMT_ENUMPROCEXEX callbackexex
Definition: lcformat.c:1881
#define LOCALE_SMONTHNAME9
Definition: winnls.h:99
#define CAL_SDAYNAME1
Definition: winnls.h:400
WCHAR szShortPM[2]
Definition: lcformat.c:89
#define NULL
Definition: types.h:112
#define GetShortMonth(fmt, mth)
Definition: lcformat.c:106
#define LOCALE_SMONTHNAME12
Definition: winnls.h:102
#define MultiByteToWideChar
Definition: compat.h:110
#define CAL_SABBREVDAYNAME6
Definition: winnls.h:412
CALINFO_ENUMPROCEXW callbackex
Definition: lcformat.c:2179
UINT NumDigits
Definition: winnls.h:609
POINT cp
Definition: magnifier.c:59
Definition: name.c:38
DWORD dwCodePage
Definition: lcformat.c:84
WINE_UNICODE_INLINE int strcmpW(const WCHAR *str1, const WCHAR *str2)
Definition: unicode.h:229
#define LOCALE_SMONTHDAY
Definition: winnls.h:159
#define CF_CY_SPACE
Definition: lcformat.c:1557
static WCHAR * NLS_GetLocaleString(LCID lcid, DWORD dwFlags)
Definition: lcformat.c:153
uint32_t * LPDWORD
Definition: typedefs.h:59
#define LOCALE_SMONTHNAME7
Definition: winnls.h:97
#define CAL_SABBREVERASTRING
#define GetTime(fmt)
Definition: lcformat.c:97
#define CAL_SABBREVMONTHNAME5
Definition: winnls.h:431
UINT LeadingZero
Definition: winnls.h:640
#define CAL_SMONTHNAME3
Definition: winnls.h:416
#define LANG_ARMENIAN
Definition: nls.h:30
WCHAR szEraAbbrev[5]
Definition: japanese.h:15
char * cleanup(char *str)
Definition: wpickclick.c:99
#define CAL_SMONTHNAME8
Definition: winnls.h:421
#define TIME_NOSECONDS
Definition: winnls.h:275
static CRITICAL_SECTION NLS_FormatsCS
Definition: lcformat.c:109
#define CAL_SABBREVDAYNAME5
Definition: winnls.h:411
INT WINAPI GetNumberFormatW(LCID lcid, DWORD dwFlags, LPCWSTR lpszValue, const NUMBERFMTW *lpFormat, LPWSTR lpNumberStr, int cchOut)
Definition: lcformat.c:1198
#define NF_DIGITS
Definition: lcformat.c:1182
TIMEFMT_ENUMPROCW callback
Definition: lcformat.c:2054
#define LANG_GEORGIAN
Definition: nls.h:61
WCHAR * LPWSTR
Definition: xmlstorage.h:184
BOOL(CALLBACK * DATEFMT_ENUMPROCW)(LPWSTR)
Definition: winnls.h:540
#define NF_DIGITS_OUT
Definition: lcformat.c:1183
#define CAL_SABBREVMONTHNAME9
Definition: winnls.h:435
#define CAL_SABBREVDAYNAME7
Definition: winnls.h:413
INT WINAPI GetTimeFormatW(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCWSTR lpFormat, LPWSTR lpTimeStr, INT cchOut)
Definition: lcformat.c:1079
#define memset(x, y, z)
Definition: compat.h:39
BOOL(CALLBACK * DATEFMT_ENUMPROCA)(LPSTR)
Definition: winnls.h:539
#define CAL_SABBREVMONTHNAME2
Definition: winnls.h:428
#define CAL_SDAYNAME5
Definition: winnls.h:404
#define CHAR(Char)
#define LOCALE_IOPTIONALCALENDAR
Definition: winnls.h:74
LPWSTR lppszStrings[NLS_NUM_CACHED_STRINGS]
Definition: lcformat.c:87
#define LOCALE_S2359
Definition: winnls.h:72
#define LOCALE_STIMEFORMAT
Definition: winnls.h:62
LPARAM lParam
Definition: combotst.c:139
static unsigned char buff[32768]
Definition: fatten.c:17
Definition: dsound.c:943
WORD wYear
Definition: japanese.h:11
#define HeapFree(x, y, z)
Definition: compat.h:594
#define ERROR_INVALID_FLAGS
Definition: winerror.h:583
#define CF_PARENS
Definition: lcformat.c:1551
#define CAL_SMONTHNAME9
Definition: winnls.h:422
#define LANG_GUJARATI
Definition: nls.h:65
#define CAL_SABBREVMONTHNAME8
Definition: winnls.h:434
#define CAL_SDAYNAME4
Definition: winnls.h:403
#define TIME_NOTIMEMARKER
Definition: winnls.h:276
int WINAPI GetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType, LPWSTR lpCalData, int cchData, LPDWORD lpValue)
Definition: lcformat.c:2485
#define ERROR_BADDB
Definition: winerror.h:588
enum enum_callback_type type
Definition: lcformat.c:2052
Definition: dlist.c:348
#define PRIMARYLANGID(l)
Definition: nls.h:16
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define TIME_FORMAT_FLAGS
Definition: lcformat.c:387