ReactOS  0.4.14-dev-552-g2fad488
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;
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  }
1795  }
1796  if (dwState & NF_ROUND)
1797  *szOut-- = '1'; /* e.g. .6 > 1.0 */
1798  else if (!(dwState & NF_DIGITS_OUT) && lpFormat->LeadingZero)
1799  *szOut-- = '0'; /* Add leading 0 if we have no digits before the decimal point */
1800 
1801  /* Add any leading negative or currency sign */
1802  while (dwFmt & (CF_MINUS_LEFT|CF_CY_LEFT))
1803  {
1804  switch (dwFmt & (CF_MINUS_LEFT|CF_MINUS_BEFORE|CF_CY_LEFT))
1805  {
1806  case CF_MINUS_LEFT:
1808  while (lpszNeg >= lpszNegStart)
1809  *szOut-- = *lpszNeg--;
1810  dwFmt &= ~CF_MINUS_LEFT;
1811  break;
1812 
1813  case CF_CY_LEFT:
1816  if (dwFmt & CF_CY_SPACE)
1817  *szOut-- = ' ';
1818  while (lpszCy >= lpszCyStart)
1819  *szOut-- = *lpszCy--;
1820  dwFmt &= ~(CF_CY_LEFT|CF_MINUS_BEFORE);
1821  break;
1822  }
1823  }
1824  if (dwFmt & CF_PARENS)
1825  *szOut-- = '(';
1826  szOut++;
1827 
1828  iRet = strlenW(szOut) + 1;
1829  if (cchOut)
1830  {
1831  if (iRet <= cchOut)
1832  memcpy(lpCurrencyStr, szOut, iRet * sizeof(WCHAR));
1833  else
1834  {
1835  memcpy(lpCurrencyStr, szOut, cchOut * sizeof(WCHAR));
1836  lpCurrencyStr[cchOut - 1] = '\0';
1838  iRet = 0;
1839  }
1840  }
1841  return iRet;
1842 
1843 error:
1845  return 0;
1846 }
1847 
1848 #if _WIN32_WINNT >= 0x600
1849 /***********************************************************************
1850  * GetCurrencyFormatEx (KERNEL32.@)
1851  */
1852 int WINAPI GetCurrencyFormatEx(LPCWSTR localename, DWORD flags, LPCWSTR value,
1853  const CURRENCYFMTW *format, LPWSTR str, int len)
1854 {
1855  TRACE("(%s,0x%08x,%s,%p,%p,%d)\n", debugstr_w(localename), flags,
1856  debugstr_w(value), format, str, len);
1857 
1858  return GetCurrencyFormatW( LocaleNameToLCID(localename, 0), flags, value, format, str, len);
1859 }
1860 #endif
1861 
1862 
1863 /* FIXME: Everything below here needs to move somewhere else along with the
1864  * other EnumXXX functions, when a method for storing resources for
1865  * alternate calendars is determined.
1866  */
1867 
1872 };
1873 
1875  enum enum_callback_type type; /* callback kind */
1876  union {
1877  DATEFMT_ENUMPROCW callback; /* user callback pointer */
1880  } u;
1881  LCID lcid; /* locale of interest */
1884  BOOL unicode; /* A vs W callback type, only for regular and Ex callbacks */
1885 };
1886 
1887 /******************************************************************************
1888  * NLS_EnumDateFormats <internal>
1889  * Enumerates date formats for a specified locale.
1890  *
1891  * PARAMS
1892  * ctxt [I] enumeration context, see 'struct enumdateformats_context'
1893  *
1894  * RETURNS
1895  * Success: TRUE.
1896  * Failure: FALSE. Use GetLastError() to determine the cause.
1897  */
1899 {
1900  WCHAR bufW[256];
1901  char bufA[256];
1902  LCTYPE lctype;
1903  CALID cal_id;
1904  INT ret;
1905 
1906  if (!ctxt->u.callback)
1907  {
1909  return FALSE;
1910  }
1911 
1912  if (!GetLocaleInfoW(ctxt->lcid, LOCALE_ICALENDARTYPE|LOCALE_RETURN_NUMBER, (LPWSTR)&cal_id, sizeof(cal_id)/sizeof(WCHAR)))
1913  return FALSE;
1914 
1915  switch (ctxt->flags & ~LOCALE_USE_CP_ACP)
1916  {
1917  case 0:
1918  case DATE_SHORTDATE:
1919  lctype = LOCALE_SSHORTDATE;
1920  break;
1921  case DATE_LONGDATE:
1922  lctype = LOCALE_SLONGDATE;
1923  break;
1924  case DATE_YEARMONTH:
1925  lctype = LOCALE_SYEARMONTH;
1926  break;
1927  default:
1928  FIXME("Unknown date format (0x%08x)\n", ctxt->flags);
1930  return FALSE;
1931  }
1932 
1933  lctype |= ctxt->flags & LOCALE_USE_CP_ACP;
1934  if (ctxt->unicode)
1935  ret = GetLocaleInfoW(ctxt->lcid, lctype, bufW, ARRAY_SIZE(bufW));
1936  else
1937  ret = GetLocaleInfoA(ctxt->lcid, lctype, bufA, ARRAY_SIZE(bufA));
1938 
1939  if (ret)
1940  {
1941  switch (ctxt->type)
1942  {
1943  case CALLBACK_ENUMPROC:
1944  ctxt->u.callback(ctxt->unicode ? bufW : (WCHAR*)bufA);
1945  break;
1946  case CALLBACK_ENUMPROCEX:
1947  ctxt->u.callbackex(ctxt->unicode ? bufW : (WCHAR*)bufA, cal_id);
1948  break;
1949  case CALLBACK_ENUMPROCEXEX:
1950  ctxt->u.callbackexex(bufW, cal_id, ctxt->lParam);
1951  break;
1952  default:
1953  ;
1954  }
1955  }
1956 
1957  return TRUE;
1958 }
1959 
1960 /**************************************************************************
1961  * EnumDateFormatsExA (KERNEL32.@)
1962  *
1963  * FIXME: MSDN mentions only LOCALE_USE_CP_ACP, should we handle
1964  * LOCALE_NOUSEROVERRIDE here as well?
1965  */
1967 {
1968  struct enumdateformats_context ctxt;
1969 
1970  ctxt.type = CALLBACK_ENUMPROCEX;
1972  ctxt.lcid = lcid;
1973  ctxt.flags = flags;
1974  ctxt.unicode = FALSE;
1975 
1976  return NLS_EnumDateFormats(&ctxt);
1977 }
1978 
1979 /**************************************************************************
1980  * EnumDateFormatsExW (KERNEL32.@)
1981  */
1983 {
1984  struct enumdateformats_context ctxt;
1985 
1986  ctxt.type = CALLBACK_ENUMPROCEX;
1987  ctxt.u.callbackex = proc;
1988  ctxt.lcid = lcid;
1989  ctxt.flags = flags;
1990  ctxt.unicode = TRUE;
1991 
1992  return NLS_EnumDateFormats(&ctxt);
1993 }
1994 
1995 /**************************************************************************
1996  * EnumDateFormatsA (KERNEL32.@)
1997  *
1998  * FIXME: MSDN mentions only LOCALE_USE_CP_ACP, should we handle
1999  * LOCALE_NOUSEROVERRIDE here as well?
2000  */
2002 {
2003  struct enumdateformats_context ctxt;
2004 
2005  ctxt.type = CALLBACK_ENUMPROC;
2006  ctxt.u.callback = (DATEFMT_ENUMPROCW)proc;
2007  ctxt.lcid = lcid;
2008  ctxt.flags = flags;
2009  ctxt.unicode = FALSE;
2010 
2011  return NLS_EnumDateFormats(&ctxt);
2012 }
2013 
2014 /**************************************************************************
2015  * EnumDateFormatsW (KERNEL32.@)
2016  */
2018 {
2019  struct enumdateformats_context ctxt;
2020 
2021  ctxt.type = CALLBACK_ENUMPROC;
2022  ctxt.u.callback = proc;
2023  ctxt.lcid = lcid;
2024  ctxt.flags = flags;
2025  ctxt.unicode = TRUE;
2026 
2027  return NLS_EnumDateFormats(&ctxt);
2028 }
2029 
2030 #if _WIN32_WINNT >= 0x600
2031 /**************************************************************************
2032  * EnumDateFormatsExEx (KERNEL32.@)
2033  */
2034 BOOL WINAPI EnumDateFormatsExEx(DATEFMT_ENUMPROCEXEX proc, const WCHAR *locale, DWORD flags, LPARAM lParam)
2035 {
2036  struct enumdateformats_context ctxt;
2037 
2038  ctxt.type = CALLBACK_ENUMPROCEXEX;
2039  ctxt.u.callbackexex = proc;
2040  ctxt.lcid = LocaleNameToLCID(locale, 0);
2041  ctxt.flags = flags;
2042  ctxt.lParam = lParam;
2043  ctxt.unicode = TRUE;
2044 
2045  return NLS_EnumDateFormats(&ctxt);
2046 }
2047 #endif /* _WIN32_WINNT >= 0x600 */
2048 
2050  enum enum_callback_type type; /* callback kind */
2051  union {
2052  TIMEFMT_ENUMPROCW callback; /* user callback pointer */
2054  } u;
2055  LCID lcid; /* locale of interest */
2058  BOOL unicode; /* A vs W callback type, only for regular and Ex callbacks */
2059 };
2060 
2062 {
2063  WCHAR bufW[256];
2064  char bufA[256];
2065  LCTYPE lctype;
2066  INT ret;
2067 
2068  if (!ctxt->u.callback)
2069  {
2071  return FALSE;
2072  }
2073 
2074  switch (ctxt->flags & ~LOCALE_USE_CP_ACP)
2075  {
2076  case 0:
2077  lctype = LOCALE_STIMEFORMAT;
2078  break;
2079  case TIME_NOSECONDS:
2080  lctype = LOCALE_SSHORTTIME;
2081  break;
2082  default:
2083  FIXME("Unknown time format (%d)\n", ctxt->flags);
2085  return FALSE;
2086  }
2087 
2088  lctype |= ctxt->flags & LOCALE_USE_CP_ACP;
2089  if (ctxt->unicode)
2090  ret = GetLocaleInfoW(ctxt->lcid, lctype, bufW, ARRAY_SIZE(bufW));
2091  else
2092  ret = GetLocaleInfoA(ctxt->lcid, lctype, bufA, ARRAY_SIZE(bufA));
2093 
2094  if (ret)
2095  {
2096  switch (ctxt->type)
2097  {
2098  case CALLBACK_ENUMPROC:
2099  ctxt->u.callback(ctxt->unicode ? bufW : (WCHAR*)bufA);
2100  break;
2101  case CALLBACK_ENUMPROCEX:
2102  ctxt->u.callbackex(bufW, ctxt->lParam);
2103  break;
2104  default:
2105  ;
2106  }
2107  }
2108 
2109  return TRUE;
2110 }
2111 
2112 /**************************************************************************
2113  * EnumTimeFormatsA (KERNEL32.@)
2114  *
2115  * FIXME: MSDN mentions only LOCALE_USE_CP_ACP, should we handle
2116  * LOCALE_NOUSEROVERRIDE here as well?
2117  */
2119 {
2120  struct enumtimeformats_context ctxt;
2121 
2122  /* EnumTimeFormatsA doesn't support flags, EnumTimeFormatsW does. */
2123  if (flags & ~LOCALE_USE_CP_ACP)
2124  {
2126  return FALSE;
2127  }
2128 
2129  ctxt.type = CALLBACK_ENUMPROC;
2130  ctxt.u.callback = (TIMEFMT_ENUMPROCW)proc;
2131  ctxt.lcid = lcid;
2132  ctxt.flags = flags;
2133  ctxt.unicode = FALSE;
2134 
2135  return NLS_EnumTimeFormats(&ctxt);
2136 }
2137 
2138 /**************************************************************************
2139  * EnumTimeFormatsW (KERNEL32.@)
2140  */
2142 {
2143  struct enumtimeformats_context ctxt;
2144 
2145  ctxt.type = CALLBACK_ENUMPROC;
2146  ctxt.u.callback = proc;
2147  ctxt.lcid = lcid;
2148  ctxt.flags = flags;
2149  ctxt.unicode = TRUE;
2150 
2151  return NLS_EnumTimeFormats(&ctxt);
2152 }
2153 
2154 #if _WIN32_WINNT >= 0x600
2155 /**************************************************************************
2156  * EnumTimeFormatsEx (KERNEL32.@)
2157  */
2158 BOOL WINAPI EnumTimeFormatsEx(TIMEFMT_ENUMPROCEX proc, const WCHAR *locale, DWORD flags, LPARAM lParam)
2159 {
2160  struct enumtimeformats_context ctxt;
2161 
2162  ctxt.type = CALLBACK_ENUMPROCEX;
2163  ctxt.u.callbackex = proc;
2164  ctxt.lcid = LocaleNameToLCID(locale, 0);
2165  ctxt.flags = flags;
2166  ctxt.lParam = lParam;
2167  ctxt.unicode = TRUE;
2168 
2169  return NLS_EnumTimeFormats(&ctxt);
2170 }
2171 #endif /* _WIN32_WINNT >= 0x600 */
2172 
2174  enum enum_callback_type type; /* callback kind */
2175  union {
2176  CALINFO_ENUMPROCW callback; /* user callback pointer */
2179  } u;
2180  LCID lcid; /* locale of interest */
2181  CALID calendar; /* specific calendar or ENUM_ALL_CALENDARS */
2182  CALTYPE caltype; /* calendar information type */
2183  LPARAM lParam; /* user input parameter passed to callback, for ExEx case only */
2184  BOOL unicode; /* A vs W callback type, only for regular and Ex callbacks */
2185 };
2186 
2187 /******************************************************************************
2188  * NLS_EnumCalendarInfo <internal>
2189  * Enumerates calendar information for a specified locale.
2190  *
2191  * PARAMS
2192  * ctxt [I] enumeration context, see 'struct enumcalendar_context'
2193  *
2194  * RETURNS
2195  * Success: TRUE.
2196  * Failure: FALSE. Use GetLastError() to determine the cause.
2197  *
2198  * NOTES
2199  * When the ANSI version of this function is used with a Unicode-only LCID,
2200  * the call can succeed because the system uses the system code page.
2201  * However, characters that are undefined in the system code page appear
2202  * in the string as a question mark (?).
2203  *
2204  * TODO
2205  * The above note should be respected by GetCalendarInfoA.
2206  */
2208 {
2209  WCHAR *buf, *opt = NULL, *iter = NULL;
2210  CALID calendar = ctxt->calendar;
2211  BOOL ret = FALSE;
2212  int bufSz = 200; /* the size of the buffer */
2213 
2214  if (ctxt->u.callback == NULL)
2215  {
2217  return FALSE;
2218  }
2219 
2220  buf = HeapAlloc(GetProcessHeap(), 0, bufSz);
2221  if (buf == NULL)
2222  {
2224  return FALSE;
2225  }
2226 
2227  if (calendar == ENUM_ALL_CALENDARS)
2228  {
2229  int optSz = GetLocaleInfoW(ctxt->lcid, LOCALE_IOPTIONALCALENDAR, NULL, 0);
2230  if (optSz > 1)
2231  {
2232  opt = HeapAlloc(GetProcessHeap(), 0, optSz * sizeof(WCHAR));
2233  if (opt == NULL)
2234  {
2236  goto cleanup;
2237  }
2238  if (GetLocaleInfoW(ctxt->lcid, LOCALE_IOPTIONALCALENDAR, opt, optSz))
2239  iter = opt;
2240  }
2241  calendar = NLS_GetLocaleNumber(ctxt->lcid, LOCALE_ICALENDARTYPE);
2242  }
2243 
2244  while (TRUE) /* loop through calendars */
2245  {
2246  do /* loop until there's no error */
2247  {
2248  if (ctxt->caltype & CAL_RETURN_NUMBER)
2249  ret = GetCalendarInfoW(ctxt->lcid, calendar, ctxt->caltype, NULL, bufSz / sizeof(WCHAR), (LPDWORD)buf);
2250  else if (ctxt->unicode)
2251  ret = GetCalendarInfoW(ctxt->lcid, calendar, ctxt->caltype, buf, bufSz / sizeof(WCHAR), NULL);
2252  else ret = GetCalendarInfoA(ctxt->lcid, calendar, ctxt->caltype, (CHAR*)buf, bufSz / sizeof(CHAR), NULL);
2253 
2254  if (!ret)
2255  {
2257  { /* so resize it */
2258  int newSz;
2259  if (ctxt->unicode)
2260  newSz = GetCalendarInfoW(ctxt->lcid, calendar, ctxt->caltype, NULL, 0, NULL) * sizeof(WCHAR);
2261  else newSz = GetCalendarInfoA(ctxt->lcid, calendar, ctxt->caltype, NULL, 0, NULL) * sizeof(CHAR);
2262  if (bufSz >= newSz)
2263  {
2264  ERR("Buffer resizing disorder: was %d, requested %d.\n", bufSz, newSz);
2265  goto cleanup;
2266  }
2267  bufSz = newSz;
2268  WARN("Buffer too small; resizing to %d bytes.\n", bufSz);
2269  buf = HeapReAlloc(GetProcessHeap(), 0, buf, bufSz);
2270  if (buf == NULL)
2271  goto cleanup;
2272  } else goto cleanup;
2273  }
2274  } while (!ret);
2275 
2276  /* Here we are. We pass the buffer to the correct version of
2277  * the callback. Because it's not the same number of params,
2278  * we must check for Ex, but we don't care about Unicode
2279  * because the buffer is already in the correct format.
2280  */
2281  switch (ctxt->type)
2282  {
2283  case CALLBACK_ENUMPROC:
2284  ret = ctxt->u.callback(buf);
2285  break;
2286  case CALLBACK_ENUMPROCEX:
2287  ret = ctxt->u.callbackex(buf, calendar);
2288  break;
2289  case CALLBACK_ENUMPROCEXEX:
2290  ret = ctxt->u.callbackexex(buf, calendar, NULL, ctxt->lParam);
2291  break;
2292  default:
2293  ;
2294  }
2295 
2296  if (!ret) { /* the callback told to stop */
2297  ret = TRUE;
2298  break;
2299  }
2300 
2301  if ((iter == NULL) || (*iter == 0)) /* no more calendars */
2302  break;
2303 
2304  calendar = 0;
2305  while ((*iter >= '0') && (*iter <= '9'))
2306  calendar = calendar * 10 + *iter++ - '0';
2307 
2308  if (*iter++ != 0)
2309  {
2311  ret = FALSE;
2312  break;
2313  }
2314  }
2315 
2316 cleanup:
2317  HeapFree(GetProcessHeap(), 0, opt);
2318  HeapFree(GetProcessHeap(), 0, buf);
2319  return ret;
2320 }
2321 
2322 /******************************************************************************
2323  * EnumCalendarInfoA [KERNEL32.@]
2324  */
2326  CALID calendar,CALTYPE caltype )
2327 {
2328  struct enumcalendar_context ctxt;
2329 
2330  TRACE("(%p,0x%08x,0x%08x,0x%08x)\n", calinfoproc, locale, calendar, caltype);
2331 
2332  ctxt.type = CALLBACK_ENUMPROC;
2333  ctxt.u.callback = (CALINFO_ENUMPROCW)calinfoproc;
2334  ctxt.lcid = locale;
2335  ctxt.calendar = calendar;
2336  ctxt.caltype = caltype;
2337  ctxt.lParam = 0;
2338  ctxt.unicode = FALSE;
2339  return NLS_EnumCalendarInfo(&ctxt);
2340 }
2341 
2342 /******************************************************************************
2343  * EnumCalendarInfoW [KERNEL32.@]
2344  */
2347 {
2348  struct enumcalendar_context ctxt;
2349 
2350  TRACE("(%p,0x%08x,0x%08x,0x%08x)\n", calinfoproc, locale, calendar, caltype);
2351 
2352  ctxt.type = CALLBACK_ENUMPROC;
2353  ctxt.u.callback = calinfoproc;
2354  ctxt.lcid = locale;
2355  ctxt.calendar = calendar;
2356  ctxt.caltype = caltype;
2357  ctxt.lParam = 0;
2358  ctxt.unicode = TRUE;
2359  return NLS_EnumCalendarInfo(&ctxt);
2360 }
2361 
2362 /******************************************************************************
2363  * EnumCalendarInfoExA [KERNEL32.@]
2364  */
2367 {
2368  struct enumcalendar_context ctxt;
2369 
2370  TRACE("(%p,0x%08x,0x%08x,0x%08x)\n", calinfoproc, locale, calendar, caltype);
2371 
2372  ctxt.type = CALLBACK_ENUMPROCEX;
2373  ctxt.u.callbackex = (CALINFO_ENUMPROCEXW)calinfoproc;
2374  ctxt.lcid = locale;
2375  ctxt.calendar = calendar;
2376  ctxt.caltype = caltype;
2377  ctxt.lParam = 0;
2378  ctxt.unicode = FALSE;
2379  return NLS_EnumCalendarInfo(&ctxt);
2380 }
2381 
2382 /******************************************************************************
2383  * EnumCalendarInfoExW [KERNEL32.@]
2384  */
2387 {
2388  struct enumcalendar_context ctxt;
2389 
2390  TRACE("(%p,0x%08x,0x%08x,0x%08x)\n", calinfoproc, locale, calendar, caltype);
2391 
2392  ctxt.type = CALLBACK_ENUMPROCEX;
2393  ctxt.u.callbackex = calinfoproc;
2394  ctxt.lcid = locale;
2395  ctxt.calendar = calendar;
2396  ctxt.caltype = caltype;
2397  ctxt.lParam = 0;
2398  ctxt.unicode = TRUE;
2399  return NLS_EnumCalendarInfo(&ctxt);
2400 }
2401 
2402 #if _WIN32_WINNT >= 0x600
2403 /******************************************************************************
2404  * EnumCalendarInfoExEx [KERNEL32.@]
2405  */
2406 BOOL WINAPI EnumCalendarInfoExEx( CALINFO_ENUMPROCEXEX calinfoproc, LPCWSTR locale, CALID calendar,
2408 {
2409  struct enumcalendar_context ctxt;
2410 
2411  TRACE("(%p,%s,0x%08x,%p,0x%08x,0x%ld)\n", calinfoproc, debugstr_w(locale), calendar, reserved, caltype, lParam);
2412 
2413  ctxt.type = CALLBACK_ENUMPROCEXEX;
2414  ctxt.u.callbackexex = calinfoproc;
2415  ctxt.lcid = LocaleNameToLCID(locale, 0);
2416  ctxt.calendar = calendar;
2417  ctxt.caltype = caltype;
2418  ctxt.lParam = lParam;
2419  ctxt.unicode = TRUE;
2420  return NLS_EnumCalendarInfo(&ctxt);
2421 }
2422 #endif /* _WIN32_WINNT >= 0x600 */
2423 
2424 /*********************************************************************
2425  * GetCalendarInfoA (KERNEL32.@)
2426  *
2427  */
2429  LPSTR lpCalData, int cchData, LPDWORD lpValue)
2430 {
2431  int ret, cchDataW = cchData;
2432  LPWSTR lpCalDataW = NULL;
2433 #ifdef __REACTOS__
2434  DWORD cp = CP_ACP;
2435  if (!(CalType & CAL_USE_CP_ACP))
2436  {
2437  DWORD dwFlags = ((CalType & CAL_NOUSEROVERRIDE) ? LOCALE_NOUSEROVERRIDE : 0);
2439  if (!node)
2440  {
2442  return 0;
2443  }
2444  cp = node->dwCodePage;
2445  }
2446  if ((CalType & 0xFFFF) == CAL_SABBREVERASTRING)
2447  {
2448  /* NOTE: CAL_SABBREVERASTRING is not supported in GetCalendarInfoA */
2450  return 0;
2451  }
2452 #endif
2453 
2455  {
2457  return 0;
2458  }
2459 
2460  if (!cchData && !(CalType & CAL_RETURN_NUMBER))
2461  cchDataW = GetCalendarInfoW(lcid, Calendar, CalType, NULL, 0, NULL);
2462  if (!(lpCalDataW = HeapAlloc(GetProcessHeap(), 0, cchDataW*sizeof(WCHAR))))
2463  return 0;
2464 
2465  ret = GetCalendarInfoW(lcid, Calendar, CalType, lpCalDataW, cchDataW, lpValue);
2466  if(ret && lpCalDataW && lpCalData)
2467 #ifdef __REACTOS__
2468  ret = WideCharToMultiByte(cp, 0, lpCalDataW, -1, lpCalData, cchData, NULL, NULL);
2469 #else
2470  ret = WideCharToMultiByte(CP_ACP, 0, lpCalDataW, -1, lpCalData, cchData, NULL, NULL);
2471 #endif
2472  else if (CalType & CAL_RETURN_NUMBER)
2473  ret *= sizeof(WCHAR);
2474  HeapFree(GetProcessHeap(), 0, lpCalDataW);
2475 
2476  return ret;
2477 }
2478 
2479 /*********************************************************************
2480  * GetCalendarInfoW (KERNEL32.@)
2481  *
2482  */
2483 int WINAPI GetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType,
2484  LPWSTR lpCalData, int cchData, LPDWORD lpValue)
2485 {
2486  static const LCTYPE caltype_lctype_map[] = {
2487  0, /* not used */
2488  0, /* CAL_ICALINTVALUE */
2489  0, /* CAL_SCALNAME */
2490  0, /* CAL_IYEAROFFSETRANGE */
2491  0, /* CAL_SERASTRING */
2534  LOCALE_SYEARMONTH,
2535  0, /* CAL_ITWODIGITYEARMAX */
2536 #if (WINVER >= 0x0600) /* ReactOS */
2537  LOCALE_SSHORTESTDAYNAME1,
2538  LOCALE_SSHORTESTDAYNAME2,
2539  LOCALE_SSHORTESTDAYNAME3,
2540  LOCALE_SSHORTESTDAYNAME4,
2541  LOCALE_SSHORTESTDAYNAME5,
2542  LOCALE_SSHORTESTDAYNAME6,
2543  LOCALE_SSHORTESTDAYNAME7,
2544 #endif
2546  0, /* CAL_SABBREVERASTRING */
2547  };
2548  DWORD localeflags = 0;
2549  CALTYPE calinfo;
2550 
2551  if (CalType & CAL_NOUSEROVERRIDE)
2552  FIXME("flag CAL_NOUSEROVERRIDE used, not fully implemented\n");
2553  if (CalType & CAL_USE_CP_ACP)
2554  FIXME("flag CAL_USE_CP_ACP used, not fully implemented\n");
2555 
2556  if (CalType & CAL_RETURN_NUMBER) {
2557  if (!lpValue)
2558  {
2560  return 0;
2561  }
2562  if (lpCalData != NULL)
2563  WARN("lpCalData not NULL (%p) when it should!\n", lpCalData);
2564  if (cchData != 0)
2565  WARN("cchData not 0 (%d) when it should!\n", cchData);
2566  } else {
2567  if (lpValue != NULL)
2568  WARN("lpValue not NULL (%p) when it should!\n", lpValue);
2569  }
2570 
2571  /* FIXME: No verification is made yet wrt Locale
2572  * for the CALTYPES not requiring GetLocaleInfoA */
2573 
2574  calinfo = CalType & 0xffff;
2575 
2576 #ifdef __REACTOS__
2577  if (CalType & LOCALE_RETURN_GENITIVE_NAMES)
2578 #else
2579  if (CalType & CAL_RETURN_GENITIVE_NAMES)
2580 #endif
2581  localeflags |= LOCALE_RETURN_GENITIVE_NAMES;
2582 
2583  switch (calinfo) {
2584  case CAL_ICALINTVALUE:
2585 #ifdef __REACTOS__
2586  if (IS_LCID_JAPANESE(Locale))
2587  {
2588  if (CalType & CAL_RETURN_NUMBER)
2589  {
2590  *lpValue = CAL_JAPAN;
2591  return sizeof(DWORD) / sizeof(WCHAR);
2592  }
2593  else
2594  {
2595  static const WCHAR fmtW[] = {'%','u',0};
2596  WCHAR buffer[10];
2597  int ret = snprintfW( buffer, 10, fmtW, CAL_JAPAN ) + 1;
2598  if (!lpCalData) return ret;
2599  if (ret <= cchData)
2600  {
2601  strcpyW( lpCalData, buffer );
2602  return ret;
2603  }
2605  return 0;
2606  }
2607  }
2608 #endif
2609  if (CalType & CAL_RETURN_NUMBER)
2610  return GetLocaleInfoW(Locale, LOCALE_RETURN_NUMBER | LOCALE_ICALENDARTYPE,
2611  (LPWSTR)lpValue, 2);
2612  return GetLocaleInfoW(Locale, LOCALE_ICALENDARTYPE, lpCalData, cchData);
2613  case CAL_SCALNAME:
2614 #ifdef __REACTOS__
2615  if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
2616  {
2617  // Wareki
2618  lpCalData[0] = 0x548C;
2619  lpCalData[1] = 0x66A6;
2620  lpCalData[2] = 0;
2621  return 3;
2622  }
2623 #endif
2624  FIXME("Unimplemented caltype %d\n", calinfo);
2625  if (lpCalData) *lpCalData = 0;
2626  return 1;
2627  case CAL_IYEAROFFSETRANGE:
2628 #ifdef __REACTOS__
2629  if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
2630  {
2632  if (pEra)
2633  {
2634  if (CalType & CAL_RETURN_NUMBER)
2635  {
2636  *lpValue = pEra->wYear;
2637  return sizeof(DWORD) / sizeof(WCHAR);
2638  }
2639  else
2640  {
2641  static const WCHAR fmtW[] = {'%','u',0};
2642  WCHAR buffer[10];
2643  int ret = snprintfW( buffer, 10, fmtW, pEra->wYear ) + 1;
2644  if (!lpCalData) return ret;
2645  if (ret <= cchData)
2646  {
2647  strcpyW( lpCalData, buffer );
2648  return ret;
2649  }
2651  return 0;
2652  }
2653  }
2654  else
2655  {
2657  return 0;
2658  }
2659  }
2660 #endif
2661  FIXME("Unimplemented caltype %d\n", calinfo);
2662  return 0;
2663  case CAL_SERASTRING:
2664 #ifdef __REACTOS__
2665  if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
2666  {
2668  if (pEra)
2669  {
2670  RtlStringCchCopyW(lpCalData, cchData, pEra->szEraName);
2671  return strlenW(lpCalData) + 1;
2672  }
2673  else
2674  {
2676  return 0;
2677  }
2678  }
2679 #endif
2680  FIXME("Unimplemented caltype %d\n", calinfo);
2681  return 0;
2682  case CAL_SSHORTDATE:
2683  case CAL_SLONGDATE:
2684  case CAL_SDAYNAME1:
2685  case CAL_SDAYNAME2:
2686  case CAL_SDAYNAME3:
2687  case CAL_SDAYNAME4:
2688  case CAL_SDAYNAME5:
2689  case CAL_SDAYNAME6:
2690  case CAL_SDAYNAME7:
2691  case CAL_SABBREVDAYNAME1:
2692  case CAL_SABBREVDAYNAME2:
2693  case CAL_SABBREVDAYNAME3:
2694  case CAL_SABBREVDAYNAME4:
2695  case CAL_SABBREVDAYNAME5:
2696  case CAL_SABBREVDAYNAME6:
2697  case CAL_SABBREVDAYNAME7:
2698  case CAL_SMONTHNAME1:
2699  case CAL_SMONTHNAME2:
2700  case CAL_SMONTHNAME3:
2701  case CAL_SMONTHNAME4:
2702  case CAL_SMONTHNAME5:
2703  case CAL_SMONTHNAME6:
2704  case CAL_SMONTHNAME7:
2705  case CAL_SMONTHNAME8:
2706  case CAL_SMONTHNAME9:
2707  case CAL_SMONTHNAME10:
2708  case CAL_SMONTHNAME11:
2709  case CAL_SMONTHNAME12:
2710  case CAL_SMONTHNAME13:
2711  case CAL_SABBREVMONTHNAME1:
2712  case CAL_SABBREVMONTHNAME2:
2713  case CAL_SABBREVMONTHNAME3:
2714  case CAL_SABBREVMONTHNAME4:
2715  case CAL_SABBREVMONTHNAME5:
2716  case CAL_SABBREVMONTHNAME6:
2717  case CAL_SABBREVMONTHNAME7:
2718  case CAL_SABBREVMONTHNAME8:
2719  case CAL_SABBREVMONTHNAME9:
2724  case CAL_SYEARMONTH:
2725  return GetLocaleInfoW(Locale, caltype_lctype_map[calinfo] | localeflags, lpCalData, cchData);
2726  case CAL_ITWODIGITYEARMAX:
2727 #ifdef __REACTOS__
2728  if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
2729  {
2730  if (CalType & CAL_RETURN_NUMBER)
2731  {
2732  *lpValue = JAPANESE_MAX_TWODIGITYEAR;
2733  return sizeof(DWORD) / sizeof(WCHAR);
2734  }
2735  else
2736  {
2737  static const WCHAR fmtW[] = {'%','u',0};
2738  WCHAR buffer[10];
2739  int ret = snprintfW( buffer, 10, fmtW, JAPANESE_MAX_TWODIGITYEAR ) + 1;
2740  if (!lpCalData) return ret;
2741  if (ret <= cchData)
2742  {
2743  strcpyW( lpCalData, buffer );
2744  return ret;
2745  }
2747  return 0;
2748  }
2749  }
2750 #endif
2751  if (CalType & CAL_RETURN_NUMBER)
2752  {
2753  *lpValue = CALINFO_MAX_YEAR;
2754  return sizeof(DWORD) / sizeof(WCHAR);
2755  }
2756  else
2757  {
2758  static const WCHAR fmtW[] = {'%','u',0};
2759  WCHAR buffer[10];
2760  int ret = snprintfW( buffer, 10, fmtW, CALINFO_MAX_YEAR ) + 1;
2761  if (!lpCalData) return ret;
2762  if (ret <= cchData)
2763  {
2764  strcpyW( lpCalData, buffer );
2765  return ret;
2766  }
2768  return 0;
2769  }
2770  break;
2771 #ifdef __REACTOS__
2772  case CAL_SABBREVERASTRING:
2773  if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
2774  {
2776  if (pEra)
2777  {
2778  RtlStringCchCopyW(lpCalData, cchData, pEra->szEraAbbrev);
2779  return strlenW(lpCalData) + 1;
2780  }
2781  }
2783  return 0;
2784 #endif
2785  default:
2786  FIXME("Unknown caltype %d\n", calinfo);
2788  return 0;
2789  }
2790  return 0;
2791 }
2792 
2793 #if _WIN32_WINNT >= 0x600
2794 /*********************************************************************
2795  * GetCalendarInfoEx (KERNEL32.@)
2796  */
2797 int WINAPI GetCalendarInfoEx(LPCWSTR locale, CALID calendar, LPCWSTR lpReserved, CALTYPE caltype,
2798  LPWSTR data, int len, DWORD *value)
2799 {
2800  static int once;
2801 
2802  LCID lcid = LocaleNameToLCID(locale, 0);
2803  if (!once++)
2804  FIXME("(%s, %d, %p, 0x%08x, %p, %d, %p): semi-stub\n", debugstr_w(locale), calendar, lpReserved, caltype,
2805  data, len, value);
2807 }
2808 #endif
2809 
2810 /*********************************************************************
2811  * SetCalendarInfoA (KERNEL32.@)
2812  *
2813  */
2814 int WINAPI SetCalendarInfoA(LCID Locale, CALID Calendar, CALTYPE CalType, LPCSTR lpCalData)
2815 {
2816  FIXME("(%08x,%08x,%08x,%s): stub\n",
2817  Locale, Calendar, CalType, debugstr_a(lpCalData));
2818  return 0;
2819 }
2820 
2821 /*********************************************************************
2822  * SetCalendarInfoW (KERNEL32.@)
2823  *
2824  *
2825  */
2826 int WINAPI SetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType, LPCWSTR lpCalData)
2827 {
2828  FIXME("(%08x,%08x,%08x,%s): stub\n",
2829  Locale, Calendar, CalType, debugstr_w(lpCalData));
2830  return 0;
2831 }
BOOL(CALLBACK * CALINFO_ENUMPROCA)(LPSTR)
Definition: winnls.h:524
LPWSTR lpThousandSep
Definition: winnls.h:643
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
#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:2365
BOOL WINAPI EnumCalendarInfoExW(CALINFO_ENUMPROCEXW calinfoproc, LCID locale, CALID calendar, CALTYPE caltype)
Definition: lcformat.c:2385
#define LOCALE_SABBREVMONTHNAME12
Definition: winnls.h:115
BOOL WINAPI EnumDateFormatsA(DATEFMT_ENUMPROCA proc, LCID lcid, DWORD flags)
Definition: lcformat.c:2001
#define GetNegative(fmt)
Definition: lcformat.c:94
#define CAL_SABBREVMONTHNAME12
Definition: winnls.h:438
#define TRUE
Definition: types.h:120
#define snprintfW
Definition: unicode.h:60
BOOL WINAPI EnumTimeFormatsW(TIMEFMT_ENUMPROCW proc, LCID lcid, DWORD flags)
Definition: lcformat.c:2141
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:1982
#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:2814
#define WideCharToMultiByte
Definition: compat.h:101
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 enumdateformats_context::@446 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:878
#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:2118
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
CALINFO_ENUMPROCEXEX callbackexex
Definition: lcformat.c:2178
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:99
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
GLuint GLuint GLsizei count
Definition: gl.h:1545
WORD wDayOfWeek
Definition: winbase.h:879
#define DATE_SHORTDATE
Definition: winnls.h:193
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:1966
char CHAR
Definition: xmlstorage.h:175
#define WARN(fmt,...)
Definition: debug.h:111
#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:1059
#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:56
#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:1875
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:877
#define LOCALE_SABBREVMONTHNAME5
Definition: winnls.h:108
DWORD LCTYPE
Definition: winnls.h:514
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 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:1878
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:2345
#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:110
static BOOL NLS_EnumDateFormats(const struct enumdateformats_context *ctxt)
Definition: lcformat.c:1898
int WINAPI GetCalendarInfoA(LCID lcid, CALID Calendar, CALTYPE CalType, LPSTR lpCalData, int cchData, LPDWORD lpValue)
Definition: lcformat.c:2428
CALINFO_ENUMPROCW callback
Definition: lcformat.c:2176
#define CAL_SSHORTDATE
Definition: winnls.h:398
r reserved
Definition: btrfs.c:2865
#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:882
#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
smooth NULL
Definition: ftsmooth.c:416
enum enum_callback_type type
Definition: lcformat.c:2174
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:2325
BOOL WINAPI EnumDateFormatsW(DATEFMT_ENUMPROCW proc, LCID lcid, DWORD flags)
Definition: lcformat.c:2017
union enumtimeformats_context::@447 u
#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:403
#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:2826
#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
PCJAPANESE_ERA JapaneseEra_Find(const SYSTEMTIME *pst OPTIONAL)
Definition: japanese.c:236
#define WINAPI
Definition: msvc.h:8
#define CAL_SMONTHNAME6
Definition: winnls.h:419
union enumcalendar_context::@448 u
#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:1877
#define SetLastError(x)
Definition: compat.h:417
#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:883
#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:2053
#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:2061
#define CAL_SABBREVMONTHNAME1
Definition: winnls.h:427
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
#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:855
enum_callback_type
Definition: lcformat.c:1868
#define GET_LOCALE_STRING(str, type)
Definition: lcformat.c:170
#define CAL_SMONTHNAME5
Definition: winnls.h:418
#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:2207
#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:109
WINE_DEFAULT_DEBUG_CHANNEL(nls)
#define CAL_SABBREVMONTHNAME11
Definition: winnls.h:437
WORD wDay
Definition: winbase.h:880
#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
#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:401
#define DATE_LONGDATE
Definition: winnls.h:194
WORD wHour
Definition: winbase.h:881
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:1879
#define LOCALE_SMONTHNAME9
Definition: winnls.h:99
#define CAL_SDAYNAME1
Definition: winnls.h:400
WCHAR szShortPM[2]
Definition: lcformat.c:89
#define GetShortMonth(fmt, mth)
Definition: lcformat.c:106
#define LOCALE_SMONTHNAME12
Definition: winnls.h:102
#define MultiByteToWideChar
Definition: compat.h:100
#define CAL_SABBREVDAYNAME6
Definition: winnls.h:412
CALINFO_ENUMPROCEXW callbackex
Definition: lcformat.c:2177
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:57
#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:2052
#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:402
#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:2483
#define ERROR_BADDB
Definition: winerror.h:588
enum enum_callback_type type
Definition: lcformat.c:2050
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