xref: /reactos/dll/cpl/intl/generalp.c (revision 8a978a17)
1 /*
2  *  ReactOS
3  *  Copyright (C) 2004, 2005 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License along
16  *  with this program; if not, write to the Free Software Foundation, Inc.,
17  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 /*
20  * PROJECT:         ReactOS International Control Panel
21  * FILE:            dll/cpl/intl/generalp.c
22  * PURPOSE:         General property page
23  * PROGRAMMER:      Eric Kohl
24  *                  Klemens Friedl
25  *                  Aleksey Bragin
26  */
27 
28 #include "intl.h"
29 
30 #include <debug.h>
31 
32 #define SAMPLE_NUMBER   L"123456789"
33 
34 #define NUM_SHEETS      4
35 
36 #define MAX_FIELD_DIG_SAMPLES       3
37 
38 
39 HWND hList;
40 HWND hLocaleList, hGeoList;
41 BOOL isSpain = FALSE;
42 
43 GROUPINGDATA
44 GroupingFormats[MAX_GROUPINGFORMATS] =
45 {
46     {0, L"0;0"},
47     {3, L"3;0"},
48     {32, L"3;2;0"}
49 };
50 
51 static BOOL CALLBACK
52 GeneralPropertyPageLocalesEnumProc(LPTSTR lpLocale)
53 {
54     LCID lcid;
55     WCHAR lang[255];
56     INT index;
57     BOOL bNoShow = FALSE;
58 
59     lcid = wcstoul(lpLocale, NULL, 16);
60 
61     /* Display only languages with installed support */
62     if (!IsValidLocale(lcid, LCID_INSTALLED))
63         return TRUE;
64 
65     if (lcid == MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH), SORT_DEFAULT) ||
66         lcid == MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT))
67     {
68         if (isSpain == FALSE)
69         {
70             LoadStringW(hApplet, IDS_SPAIN, lang, 255);
71             isSpain = TRUE;
72         }
73         else
74         {
75             bNoShow = TRUE;
76         }
77     }
78     else
79     {
80         GetLocaleInfoW(lcid, LOCALE_SLANGUAGE, lang, sizeof(lang)/sizeof(WCHAR));
81     }
82 
83     if (bNoShow == FALSE)
84     {
85     index = SendMessageW(hList,
86                          CB_ADDSTRING,
87                          0,
88                          (LPARAM)lang);
89 
90     SendMessageW(hList,
91                  CB_SETITEMDATA,
92                  index,
93                  (LPARAM)lcid);
94     }
95 
96     return TRUE;
97 }
98 
99 
100 /* Update all locale samples */
101 static
102 VOID
103 UpdateLocaleSample(
104     HWND hwndDlg,
105     PGLOBALDATA pGlobalData)
106 {
107     WCHAR OutBuffer[MAX_SAMPLES_STR_SIZE];
108     NUMBERFMT NumberFormat;
109     CURRENCYFMTW CurrencyFormat;
110 
111     NumberFormat.NumDigits = pGlobalData->nNumDigits;
112     NumberFormat.LeadingZero = pGlobalData->nNumLeadingZero;
113     NumberFormat.Grouping = GroupingFormats[pGlobalData->nNumGrouping].nInteger;
114     NumberFormat.lpDecimalSep = pGlobalData->szNumDecimalSep;
115     NumberFormat.lpThousandSep = pGlobalData->szNumThousandSep;
116     NumberFormat.NegativeOrder = pGlobalData->nNumNegFormat;
117 
118     CurrencyFormat.NumDigits = pGlobalData->nCurrDigits;
119     CurrencyFormat.LeadingZero = pGlobalData->nNumLeadingZero;
120     CurrencyFormat.Grouping = GroupingFormats[pGlobalData->nCurrGrouping].nInteger;
121     CurrencyFormat.lpDecimalSep = pGlobalData->szCurrDecimalSep;
122     CurrencyFormat.lpThousandSep = pGlobalData->szCurrThousandSep;
123     CurrencyFormat.NegativeOrder = pGlobalData->nCurrNegFormat;
124     CurrencyFormat.PositiveOrder = pGlobalData->nCurrPosFormat;
125     CurrencyFormat.lpCurrencySymbol = pGlobalData->szCurrSymbol;
126 
127     /* Get number format sample */
128     GetNumberFormatW(pGlobalData->UserLCID, 0, SAMPLE_NUMBER,
129                      &NumberFormat,
130                      OutBuffer, MAX_SAMPLES_STR_SIZE);
131     SendDlgItemMessageW(hwndDlg, IDC_NUMSAMPLE_EDIT,
132                         WM_SETTEXT, 0, (LPARAM)OutBuffer);
133     ZeroMemory(OutBuffer, MAX_SAMPLES_STR_SIZE * sizeof(WCHAR));
134 
135     /* Get monetary format sample */
136     GetCurrencyFormatW(pGlobalData->UserLCID, 0, SAMPLE_NUMBER,
137                        &CurrencyFormat,
138                        OutBuffer, MAX_SAMPLES_STR_SIZE);
139     SendDlgItemMessageW(hwndDlg, IDC_MONEYSAMPLE_EDIT,
140                         WM_SETTEXT, 0, (LPARAM)OutBuffer);
141     ZeroMemory(OutBuffer, MAX_SAMPLES_STR_SIZE * sizeof(WCHAR));
142 
143     /* Get time format sample */
144     GetTimeFormatW(pGlobalData->UserLCID, 0, NULL,
145                    pGlobalData->szTimeFormat,
146                    OutBuffer, MAX_SAMPLES_STR_SIZE);
147     SendDlgItemMessageW(hwndDlg, IDC_TIMESAMPLE_EDIT,
148                         WM_SETTEXT, 0, (LPARAM)OutBuffer);
149     ZeroMemory(OutBuffer, MAX_SAMPLES_STR_SIZE * sizeof(WCHAR));
150 
151     /* Get short date format sample */
152     GetDateFormatW(pGlobalData->UserLCID, 0, NULL,
153                    pGlobalData->szShortDateFormat,
154                    OutBuffer, MAX_SAMPLES_STR_SIZE);
155     SendDlgItemMessageW(hwndDlg, IDC_SHORTTIMESAMPLE_EDIT,
156                         WM_SETTEXT, 0, (LPARAM)OutBuffer);
157 
158     /* Get long date sample */
159     GetDateFormatW(pGlobalData->UserLCID, 0, NULL,
160                    pGlobalData->szLongDateFormat,
161                    OutBuffer, MAX_SAMPLES_STR_SIZE);
162     SendDlgItemMessageW(hwndDlg, IDC_FULLTIMESAMPLE_EDIT,
163                         WM_SETTEXT, 0, (LPARAM)OutBuffer);
164 }
165 
166 static VOID
167 CreateLanguagesList(HWND hwnd)
168 {
169     WCHAR langSel[255];
170 
171     hList = hwnd;
172     isSpain = FALSE;
173     EnumSystemLocalesW(GeneralPropertyPageLocalesEnumProc, LCID_SUPPORTED);
174 
175     /* Select current locale */
176     /* or should it be System and not user? */
177     GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_SLANGUAGE, langSel, sizeof(langSel)/sizeof(WCHAR));
178 
179     SendMessageW(hList,
180                  CB_SELECTSTRING,
181                  -1,
182                  (LPARAM)langSel);
183 }
184 
185 
186 BOOL
187 LoadCurrentLocale(
188     PGLOBALDATA pGlobalData)
189 {
190     WCHAR szBuffer[16];
191     PWSTR ptr;
192     HKEY hLocaleKey;
193     DWORD ret;
194     DWORD dwSize;
195 
196     ret = RegOpenKeyExW(HKEY_CURRENT_USER,
197                         L"Control Panel\\International",
198                         0,
199                         KEY_READ,
200                         &hLocaleKey);
201     if (ret != ERROR_SUCCESS)
202     {
203         PrintErrorMsgBox(IDS_ERROR_INT_KEY_REG);
204         return FALSE;
205     }
206 
207     dwSize = 9 * sizeof(WCHAR);
208     RegQueryValueExW(hLocaleKey,
209                      L"Locale",
210                      NULL,
211                      NULL,
212                      (PBYTE)szBuffer,
213                      &dwSize);
214     pGlobalData->UserLCID = (LCID)wcstoul(szBuffer, &ptr, 16);
215 
216     /* Number */
217     dwSize = MAX_NUMDECIMALSEP * sizeof(WCHAR);
218     RegQueryValueExW(hLocaleKey,
219                      L"sDecimal",
220                      NULL,
221                      NULL,
222                      (PBYTE)pGlobalData->szNumDecimalSep,
223                      &dwSize);
224 
225     dwSize = MAX_NUMTHOUSANDSEP * sizeof(WCHAR);
226     RegQueryValueExW(hLocaleKey,
227                      L"sThousand",
228                      NULL,
229                      NULL,
230                      (PBYTE)pGlobalData->szNumThousandSep,
231                      &dwSize);
232 
233     dwSize = MAX_NUMNEGATIVESIGN * sizeof(WCHAR);
234     RegQueryValueExW(hLocaleKey,
235                      L"sNegativeSign",
236                      NULL,
237                      NULL,
238                      (PBYTE)pGlobalData->szNumNegativeSign,
239                      &dwSize);
240 
241     dwSize = MAX_NUMPOSITIVESIGN * sizeof(WCHAR);
242     RegQueryValueExW(hLocaleKey,
243                      L"sPositiveSign",
244                      NULL,
245                      NULL,
246                      (PBYTE)pGlobalData->szNumPositiveSign,
247                      &dwSize);
248 
249     dwSize = MAX_NUMLISTSEP * sizeof(WCHAR);
250     RegQueryValueExW(hLocaleKey,
251                      L"sList",
252                      NULL,
253                      NULL,
254                      (PBYTE)pGlobalData->szNumListSep,
255                      &dwSize);
256 
257     dwSize = MAX_NUMNATIVEDIGITS * sizeof(WCHAR);
258     RegQueryValueExW(hLocaleKey,
259                      L"sNativeDigits",
260                      NULL,
261                      NULL,
262                      (PBYTE)pGlobalData->szNumNativeDigits,
263                      &dwSize);
264 
265     pGlobalData->nNumNegFormat = 0;
266     dwSize = 16 * sizeof(WCHAR);
267     if (RegQueryValueExW(hLocaleKey,
268                          L"iNegNumber",
269                          NULL,
270                          NULL,
271                          (PBYTE)szBuffer,
272                          &dwSize) == ERROR_SUCCESS)
273         pGlobalData->nNumNegFormat = _wtoi(szBuffer);
274 
275     pGlobalData->nNumDigits = 0;
276     dwSize = 16 * sizeof(WCHAR);
277     if (RegQueryValueExW(hLocaleKey,
278                          L"iDigits",
279                          NULL,
280                          NULL,
281                          (PBYTE)szBuffer,
282                          &dwSize) == ERROR_SUCCESS)
283         pGlobalData->nNumDigits = _wtoi(szBuffer);
284 
285     pGlobalData->nNumLeadingZero = 0;
286     dwSize = 16 * sizeof(WCHAR);
287     if (RegQueryValueExW(hLocaleKey,
288                          L"iLZero",
289                          NULL,
290                          NULL,
291                          (PBYTE)szBuffer,
292                          &dwSize) == ERROR_SUCCESS)
293         pGlobalData->nNumLeadingZero = _wtoi(szBuffer);
294 
295     pGlobalData->nNumMeasure = 0;
296     dwSize = 16 * sizeof(WCHAR);
297     if (RegQueryValueExW(hLocaleKey,
298                          L"iMeasure",
299                          NULL,
300                          NULL,
301                          (PBYTE)szBuffer,
302                          &dwSize) == ERROR_SUCCESS)
303         pGlobalData->nNumMeasure = _wtoi(szBuffer);
304 
305     pGlobalData->nNumShape = 0;
306     dwSize = 16 * sizeof(WCHAR);
307     if (RegQueryValueExW(hLocaleKey,
308                          L"NumShape",
309                          NULL,
310                          NULL,
311                          (PBYTE)szBuffer,
312                          &dwSize) == ERROR_SUCCESS)
313         pGlobalData->nNumShape = _wtoi(szBuffer);
314 
315     pGlobalData->nNumGrouping = 0;
316     dwSize = 16 * sizeof(WCHAR);
317     if (RegQueryValueExW(hLocaleKey,
318                          L"sGrouping",
319                          NULL,
320                          NULL,
321                          (PBYTE)szBuffer,
322                          &dwSize) == ERROR_SUCCESS)
323     {
324         pGlobalData->nNumGrouping = 0;
325         if (szBuffer[0] == L'3')
326         {
327             if ((szBuffer[1] == L';') &&
328                 (szBuffer[2] == L'2'))
329                 pGlobalData->nNumGrouping = 2;
330             else
331                 pGlobalData->nNumGrouping = 1;
332         }
333     }
334 
335     /* Currency */
336     dwSize = MAX_CURRSYMBOL * sizeof(WCHAR);
337     RegQueryValueExW(hLocaleKey,
338                      L"sCurrency",
339                      NULL,
340                      NULL,
341                      (PBYTE)pGlobalData->szCurrSymbol,
342                      &dwSize);
343 
344     dwSize = MAX_CURRDECIMALSEP * sizeof(WCHAR);
345     RegQueryValueExW(hLocaleKey,
346                      L"sMonDecimalSep",
347                      NULL,
348                      NULL,
349                      (PBYTE)pGlobalData->szCurrDecimalSep,
350                      &dwSize);
351 
352     dwSize = MAX_CURRTHOUSANDSEP * sizeof(WCHAR);
353     RegQueryValueExW(hLocaleKey,
354                      L"sMonThousandSep",
355                      NULL,
356                      NULL,
357                      (PBYTE)pGlobalData->szCurrThousandSep,
358                      &dwSize);
359 
360     pGlobalData->nCurrGrouping = 0;
361     dwSize = 16 * sizeof(WCHAR);
362     if (RegQueryValueExW(hLocaleKey,
363                          L"sMonGrouping",
364                          NULL,
365                          NULL,
366                          (PBYTE)szBuffer,
367                          &dwSize) == ERROR_SUCCESS)
368     {
369         pGlobalData->nCurrGrouping = 0;
370         if (szBuffer[0] == L'3')
371         {
372             if ((szBuffer[1] == L';') &&
373                 (szBuffer[2] == L'2'))
374                 pGlobalData->nCurrGrouping = 2;
375             else
376                 pGlobalData->nCurrGrouping = 1;
377         }
378     }
379 
380     pGlobalData->nCurrPosFormat = 0;
381     dwSize = 16 * sizeof(WCHAR);
382     if (RegQueryValueExW(hLocaleKey,
383                          L"iCurrency",
384                          NULL,
385                          NULL,
386                          (PBYTE)szBuffer,
387                          &dwSize) == ERROR_SUCCESS)
388         pGlobalData->nCurrPosFormat = _wtoi(szBuffer);
389 
390     pGlobalData->nCurrNegFormat = 0;
391     dwSize = 16 * sizeof(WCHAR);
392     if (RegQueryValueExW(hLocaleKey,
393                          L"iNegCurr",
394                          NULL,
395                          NULL,
396                          (PBYTE)szBuffer,
397                          &dwSize) == ERROR_SUCCESS)
398         pGlobalData->nCurrNegFormat = _wtoi(szBuffer);
399 
400     pGlobalData->nCurrDigits = 0;
401     dwSize = 16 * sizeof(WCHAR);
402     if (RegQueryValueExW(hLocaleKey,
403                          L"iCurrDigits",
404                          NULL,
405                          NULL,
406                          (PBYTE)szBuffer,
407                          &dwSize) == ERROR_SUCCESS)
408         pGlobalData->nCurrDigits = _wtoi(szBuffer);
409 
410     /* Time */
411     dwSize = MAX_TIMEFORMAT * sizeof(WCHAR);
412     RegQueryValueExW(hLocaleKey,
413                      L"sTimeFormat",
414                      NULL,
415                      NULL,
416                      (PBYTE)pGlobalData->szTimeFormat,
417                      &dwSize);
418 
419     dwSize = MAX_TIMESEPARATOR * sizeof(WCHAR);
420     RegQueryValueExW(hLocaleKey,
421                      L"sTime",
422                      NULL,
423                      NULL,
424                      (PBYTE)pGlobalData->szTimeSep,
425                      &dwSize);
426 
427     dwSize = MAX_TIMEAMSYMBOL * sizeof(WCHAR);
428     RegQueryValueExW(hLocaleKey,
429                      L"s1159",
430                      NULL,
431                      NULL,
432                      (PBYTE)pGlobalData->szTimeAM,
433                      &dwSize);
434 
435     dwSize = MAX_TIMEPMSYMBOL * sizeof(WCHAR);
436     RegQueryValueExW(hLocaleKey,
437                      L"s2359",
438                      NULL,
439                      NULL,
440                      (PBYTE)pGlobalData->szTimePM,
441                      &dwSize);
442 
443     pGlobalData->nTime = 0;
444     dwSize = 16 * sizeof(WCHAR);
445     if (RegQueryValueExW(hLocaleKey,
446                          L"iTime",
447                          NULL,
448                          NULL,
449                          (PBYTE)szBuffer,
450                          &dwSize) == ERROR_SUCCESS)
451         pGlobalData->nTime = _wtoi(szBuffer);
452 
453     pGlobalData->nTimePrefix = 0;
454     dwSize = 16 * sizeof(WCHAR);
455     if (RegQueryValueExW(hLocaleKey,
456                          L"iTimePrefix",
457                          NULL,
458                          NULL,
459                          (PBYTE)szBuffer,
460                          &dwSize) == ERROR_SUCCESS)
461         pGlobalData->nTimePrefix = _wtoi(szBuffer);
462 
463     pGlobalData->nTimeLeadingZero = 0;
464     dwSize = 16 * sizeof(WCHAR);
465     if (RegQueryValueExW(hLocaleKey,
466                          L"iTLZero",
467                          NULL,
468                          NULL,
469                          (PBYTE)szBuffer,
470                          &dwSize) == ERROR_SUCCESS)
471         pGlobalData->nTimeLeadingZero = _wtoi(szBuffer);
472 
473     /* Date */
474     dwSize = MAX_LONGDATEFORMAT * sizeof(WCHAR);
475     RegQueryValueExW(hLocaleKey,
476                      L"sLongDate",
477                      NULL,
478                      NULL,
479                      (PBYTE)pGlobalData->szLongDateFormat,
480                      &dwSize);
481 
482     dwSize = MAX_SHORTDATEFORMAT * sizeof(WCHAR);
483     RegQueryValueExW(hLocaleKey,
484                      L"sShortDate",
485                      NULL,
486                      NULL,
487                      (PBYTE)pGlobalData->szShortDateFormat,
488                      &dwSize);
489 
490     dwSize = MAX_DATESEPARATOR * sizeof(WCHAR);
491     RegQueryValueExW(hLocaleKey,
492                      L"sDate",
493                      NULL,
494                      NULL,
495                      (PBYTE)pGlobalData->szDateSep,
496                      &dwSize);
497 
498     pGlobalData->nFirstDayOfWeek = 0;
499     dwSize = 16 * sizeof(WCHAR);
500     if (RegQueryValueExW(hLocaleKey,
501                          L"iFirstDayOfWeek",
502                          NULL,
503                          NULL,
504                          (PBYTE)szBuffer,
505                          &dwSize) == ERROR_SUCCESS)
506         pGlobalData->nFirstDayOfWeek = _wtoi(szBuffer);
507 
508     pGlobalData->nFirstWeekOfYear = 0;
509     dwSize = 16 * sizeof(WCHAR);
510     if (RegQueryValueExW(hLocaleKey,
511                          L"iFirstWeekOfYear",
512                          NULL,
513                          NULL,
514                          (PBYTE)szBuffer,
515                          &dwSize) == ERROR_SUCCESS)
516         pGlobalData->nFirstWeekOfYear = _wtoi(szBuffer);
517 
518     pGlobalData->nDate = 0;
519     dwSize = 16 * sizeof(WCHAR);
520     if (RegQueryValueExW(hLocaleKey,
521                          L"iDate",
522                          NULL,
523                          NULL,
524                          (PBYTE)szBuffer,
525                          &dwSize) == ERROR_SUCCESS)
526         pGlobalData->nDate = _wtoi(szBuffer);
527 
528     pGlobalData->nCalendarType = 0;
529     dwSize = 16 * sizeof(WCHAR);
530     if (RegQueryValueExW(hLocaleKey,
531                          L"iCalendarType",
532                          NULL,
533                          NULL,
534                          (PBYTE)szBuffer,
535                          &dwSize) == ERROR_SUCCESS)
536         pGlobalData->nCalendarType = _wtoi(szBuffer);
537 
538     /* Misc */
539     dwSize = MAX_MISCCOUNTRY * sizeof(WCHAR);
540     RegQueryValueExW(hLocaleKey,
541                      L"sCountry",
542                      NULL,
543                      NULL,
544                      (PBYTE)pGlobalData->szMiscCountry,
545                      &dwSize);
546 
547     dwSize = MAX_MISCLANGUAGE * sizeof(WCHAR);
548     RegQueryValueExW(hLocaleKey,
549                      L"sLanguage",
550                      NULL,
551                      NULL,
552                      (PBYTE)pGlobalData->szMiscLanguage,
553                      &dwSize);
554 
555     pGlobalData->nMiscCountry = 0;
556     dwSize = 16 * sizeof(WCHAR);
557     if (RegQueryValueExW(hLocaleKey,
558                          L"iCountry",
559                          NULL,
560                          NULL,
561                          (PBYTE)szBuffer,
562                          &dwSize) == ERROR_SUCCESS)
563         pGlobalData->nMiscCountry = _wtoi(szBuffer);
564 
565     RegCloseKey(hLocaleKey);
566 
567     return TRUE;
568 }
569 
570 
571 VOID
572 SetNewLocale(
573     PGLOBALDATA pGlobalData,
574     LCID lcid)
575 {
576     WCHAR szBuffer[16];
577 
578     pGlobalData->UserLCID = lcid;
579 
580     /* Number */
581     GetLocaleInfo(lcid,
582                   LOCALE_SDECIMAL | LOCALE_NOUSEROVERRIDE,
583                   pGlobalData->szNumDecimalSep,
584                   MAX_NUMDECIMALSEP);
585 
586     GetLocaleInfo(lcid,
587                   LOCALE_STHOUSAND | LOCALE_NOUSEROVERRIDE,
588                   pGlobalData->szNumThousandSep,
589                   MAX_NUMTHOUSANDSEP);
590 
591     GetLocaleInfo(lcid,
592                   LOCALE_SNEGATIVESIGN | LOCALE_NOUSEROVERRIDE,
593                   pGlobalData->szNumNegativeSign,
594                   MAX_NUMNEGATIVESIGN);
595 
596     GetLocaleInfo(lcid,
597                   LOCALE_SPOSITIVESIGN | LOCALE_NOUSEROVERRIDE,
598                   pGlobalData->szNumPositiveSign,
599                   MAX_NUMPOSITIVESIGN);
600 
601     GetLocaleInfo(lcid,
602                   LOCALE_SLIST | LOCALE_NOUSEROVERRIDE,
603                   pGlobalData->szNumListSep,
604                   MAX_NUMLISTSEP);
605 
606     GetLocaleInfo(lcid,
607                   LOCALE_SNATIVEDIGITS | LOCALE_NOUSEROVERRIDE,
608                   pGlobalData->szNumNativeDigits,
609                   MAX_NUMNATIVEDIGITS);
610 
611     GetLocaleInfo(lcid,
612                   LOCALE_INEGNUMBER | LOCALE_NOUSEROVERRIDE,
613                   szBuffer,
614                   sizeof(szBuffer) / sizeof(WCHAR));
615     pGlobalData->nNumNegFormat = _wtoi(szBuffer);
616 
617     GetLocaleInfo(lcid,
618                   LOCALE_IDIGITS | LOCALE_NOUSEROVERRIDE,
619                   szBuffer,
620                   sizeof(szBuffer) / sizeof(WCHAR));
621     pGlobalData->nNumDigits = _wtoi(szBuffer);
622 
623     GetLocaleInfo(lcid,
624                   LOCALE_ILZERO | LOCALE_NOUSEROVERRIDE,
625                   szBuffer,
626                   sizeof(szBuffer) / sizeof(WCHAR));
627     pGlobalData->nNumLeadingZero = _wtoi(szBuffer);
628 
629     GetLocaleInfo(lcid,
630                   LOCALE_IMEASURE | LOCALE_NOUSEROVERRIDE,
631                   szBuffer,
632                   sizeof(szBuffer) / sizeof(WCHAR));
633     pGlobalData->nNumMeasure = _wtoi(szBuffer);
634 
635     GetLocaleInfo(lcid,
636                   LOCALE_IDIGITSUBSTITUTION | LOCALE_NOUSEROVERRIDE,
637                   szBuffer,
638                   sizeof(szBuffer) / sizeof(WCHAR));
639     pGlobalData->nNumShape = _wtoi(szBuffer);
640 
641     GetLocaleInfo(lcid,
642                   LOCALE_SGROUPING | LOCALE_NOUSEROVERRIDE,
643                   szBuffer,
644                   sizeof(szBuffer) / sizeof(WCHAR));
645     pGlobalData->nNumGrouping = 0;
646     if (szBuffer[0] == L'3')
647     {
648         if ((szBuffer[1] == L';') &&
649             (szBuffer[2] == L'2'))
650             pGlobalData->nNumGrouping = 2;
651         else
652             pGlobalData->nNumGrouping = 1;
653     }
654 
655     /* Currency */
656     GetLocaleInfo(lcid,
657                   LOCALE_SCURRENCY | LOCALE_NOUSEROVERRIDE,
658                   pGlobalData->szCurrSymbol,
659                   MAX_CURRSYMBOL);
660 
661     GetLocaleInfo(lcid,
662                   LOCALE_SMONDECIMALSEP | LOCALE_NOUSEROVERRIDE,
663                   pGlobalData->szCurrDecimalSep,
664                   MAX_CURRDECIMALSEP);
665 
666     GetLocaleInfo(lcid,
667                   LOCALE_SMONTHOUSANDSEP | LOCALE_NOUSEROVERRIDE,
668                   pGlobalData->szCurrThousandSep,
669                   MAX_CURRTHOUSANDSEP);
670 
671     GetLocaleInfo(lcid,
672                   LOCALE_SMONGROUPING | LOCALE_NOUSEROVERRIDE,
673                   szBuffer,
674                   sizeof(szBuffer) / sizeof(WCHAR));
675     pGlobalData->nCurrGrouping = 0;
676     if (szBuffer[0] == L'3')
677     {
678         if ((szBuffer[1] == L';') &&
679             (szBuffer[2] == L'2'))
680             pGlobalData->nCurrGrouping = 2;
681         else
682             pGlobalData->nCurrGrouping = 1;
683     }
684 
685     GetLocaleInfo(lcid,
686                   LOCALE_ICURRENCY | LOCALE_NOUSEROVERRIDE,
687                   szBuffer,
688                   sizeof(szBuffer) / sizeof(WCHAR));
689     pGlobalData->nCurrPosFormat = _wtoi(szBuffer);
690 
691     GetLocaleInfo(lcid,
692                   LOCALE_INEGCURR | LOCALE_NOUSEROVERRIDE,
693                   szBuffer,
694                   sizeof(szBuffer) / sizeof(WCHAR));
695     pGlobalData->nCurrNegFormat = _wtoi(szBuffer);
696 
697     GetLocaleInfo(lcid,
698                   LOCALE_ICURRDIGITS | LOCALE_NOUSEROVERRIDE,
699                   szBuffer,
700                   sizeof(szBuffer) / sizeof(WCHAR));
701     pGlobalData->nCurrDigits = _wtoi(szBuffer);
702 
703     /* Time */
704     GetLocaleInfo(lcid,
705                   LOCALE_STIMEFORMAT | LOCALE_NOUSEROVERRIDE,
706                   pGlobalData->szTimeFormat,
707                   MAX_TIMEFORMAT);
708 
709     GetLocaleInfo(lcid,
710                   LOCALE_STIME | LOCALE_NOUSEROVERRIDE,
711                   pGlobalData->szTimeSep,
712                   MAX_TIMESEPARATOR);
713 
714     GetLocaleInfo(lcid,
715                   LOCALE_S1159 | LOCALE_NOUSEROVERRIDE,
716                   pGlobalData->szTimeAM,
717                   MAX_TIMEAMSYMBOL);
718 
719     GetLocaleInfo(lcid,
720                   LOCALE_S2359 | LOCALE_NOUSEROVERRIDE,
721                   pGlobalData->szTimePM,
722                   MAX_TIMEPMSYMBOL);
723 
724     GetLocaleInfo(lcid,
725                   LOCALE_ITIME | LOCALE_NOUSEROVERRIDE,
726                   szBuffer,
727                   sizeof(szBuffer) / sizeof(WCHAR));
728     pGlobalData->nTime = _wtoi(szBuffer);
729 
730     GetLocaleInfo(lcid,
731                   LOCALE_ITIMEMARKPOSN | LOCALE_NOUSEROVERRIDE,
732                   szBuffer,
733                   sizeof(szBuffer) / sizeof(WCHAR));
734     pGlobalData->nTimePrefix = _wtoi(szBuffer);
735 
736     GetLocaleInfo(lcid,
737                   LOCALE_ITLZERO | LOCALE_NOUSEROVERRIDE,
738                   szBuffer,
739                   sizeof(szBuffer) / sizeof(WCHAR));
740     pGlobalData->nTimeLeadingZero = _wtoi(szBuffer);
741 
742     /* Date */
743     GetLocaleInfo(lcid,
744                   LOCALE_SLONGDATE | LOCALE_NOUSEROVERRIDE,
745                   pGlobalData->szLongDateFormat,
746                   MAX_LONGDATEFORMAT);
747 
748     GetLocaleInfo(lcid,
749                   LOCALE_SSHORTDATE | LOCALE_NOUSEROVERRIDE,
750                   pGlobalData->szShortDateFormat,
751                   MAX_SHORTDATEFORMAT);
752 
753     GetLocaleInfo(lcid,
754                   LOCALE_SDATE | LOCALE_NOUSEROVERRIDE,
755                   pGlobalData->szDateSep,
756                   MAX_DATESEPARATOR);
757 
758     GetLocaleInfo(lcid,
759                   LOCALE_IFIRSTDAYOFWEEK | LOCALE_NOUSEROVERRIDE,
760                   szBuffer,
761                   sizeof(szBuffer) / sizeof(WCHAR));
762     pGlobalData->nFirstDayOfWeek = _wtoi(szBuffer);
763 
764     GetLocaleInfo(lcid,
765                   LOCALE_IFIRSTWEEKOFYEAR | LOCALE_NOUSEROVERRIDE,
766                   szBuffer,
767                   sizeof(szBuffer) / sizeof(WCHAR));
768     pGlobalData->nFirstWeekOfYear = _wtoi(szBuffer);
769 
770     GetLocaleInfo(lcid,
771                   LOCALE_IDATE | LOCALE_NOUSEROVERRIDE,
772                   szBuffer,
773                   sizeof(szBuffer) / sizeof(WCHAR));
774     pGlobalData->nDate = _wtoi(szBuffer);
775 
776     GetLocaleInfo(lcid,
777                   LOCALE_ICALENDARTYPE | LOCALE_NOUSEROVERRIDE,
778                   szBuffer,
779                   sizeof(szBuffer) / sizeof(WCHAR));
780     pGlobalData->nCalendarType = _wtoi(szBuffer);
781 
782     /* Misc */
783     GetLocaleInfo(lcid,
784                   LOCALE_SCOUNTRY | LOCALE_NOUSEROVERRIDE,
785                   pGlobalData->szMiscCountry,
786                   MAX_MISCCOUNTRY);
787 
788     GetLocaleInfo(lcid,
789                   LOCALE_SLANGUAGE | LOCALE_NOUSEROVERRIDE,
790                   pGlobalData->szMiscLanguage,
791                   MAX_MISCLANGUAGE);
792 
793     GetLocaleInfo(lcid,
794                   LOCALE_ICOUNTRY | LOCALE_NOUSEROVERRIDE,
795                   szBuffer,
796                   sizeof(szBuffer) / sizeof(WCHAR));
797     pGlobalData->nMiscCountry = _wtoi(szBuffer);
798 }
799 
800 
801 static
802 VOID
803 SaveUserLocale(
804     PGLOBALDATA pGlobalData,
805     HKEY hLocaleKey)
806 {
807     WCHAR szBuffer[16];
808 
809     wsprintf(szBuffer, L"%08lx", (DWORD)pGlobalData->UserLCID);
810     RegSetValueExW(hLocaleKey,
811                    L"Locale",
812                    0,
813                    REG_SZ,
814                    (PBYTE)szBuffer,
815                    (wcslen(szBuffer) + 1) * sizeof(WCHAR));
816 
817     /* Number */
818     RegSetValueExW(hLocaleKey,
819                    L"sDecimal",
820                    0,
821                    REG_SZ,
822                    (PBYTE)pGlobalData->szNumDecimalSep,
823                    (wcslen(pGlobalData->szNumDecimalSep) + 1) * sizeof(WCHAR));
824 
825     RegSetValueExW(hLocaleKey,
826                    L"sThousand",
827                    0,
828                    REG_SZ,
829                    (PBYTE)pGlobalData->szNumThousandSep,
830                    (wcslen(pGlobalData->szNumThousandSep) + 1) * sizeof(WCHAR));
831 
832     RegSetValueExW(hLocaleKey,
833                    L"sNegativeSign",
834                    0,
835                    REG_SZ,
836                    (PBYTE)pGlobalData->szNumNegativeSign,
837                    (wcslen(pGlobalData->szNumNegativeSign) + 1) * sizeof(WCHAR));
838 
839     RegSetValueExW(hLocaleKey,
840                    L"sPositiveSign",
841                    0,
842                    REG_SZ,
843                    (PBYTE)pGlobalData->szNumPositiveSign,
844                    (wcslen(pGlobalData->szNumPositiveSign) + 1) * sizeof(WCHAR));
845 
846     RegSetValueExW(hLocaleKey,
847                    L"sGrouping",
848                    0,
849                    REG_SZ,
850                    (PBYTE)GroupingFormats[pGlobalData->nNumGrouping].pszString,
851                    (wcslen(GroupingFormats[pGlobalData->nNumGrouping].pszString) + 1) * sizeof(WCHAR));
852 
853     RegSetValueExW(hLocaleKey,
854                    L"sList",
855                    0,
856                    REG_SZ,
857                    (PBYTE)pGlobalData->szNumListSep,
858                    (wcslen(pGlobalData->szNumListSep) + 1) * sizeof(WCHAR));
859 
860     RegSetValueExW(hLocaleKey,
861                    L"sNativeDigits",
862                    0,
863                    REG_SZ,
864                    (PBYTE)pGlobalData->szNumNativeDigits,
865                    (wcslen(pGlobalData->szNumNativeDigits) + 1) * sizeof(WCHAR));
866 
867     _itow(pGlobalData->nNumNegFormat,
868           szBuffer, DECIMAL_RADIX);
869     RegSetValueExW(hLocaleKey,
870                    L"iNegNumber",
871                    0,
872                    REG_SZ,
873                    (PBYTE)szBuffer,
874                    (wcslen(szBuffer) + 1) * sizeof(WCHAR));
875 
876     _itow(pGlobalData->nNumDigits,
877           szBuffer, DECIMAL_RADIX);
878     RegSetValueExW(hLocaleKey,
879                    L"iDigits",
880                    0,
881                    REG_SZ,
882                    (PBYTE)szBuffer,
883                    (wcslen(szBuffer) + 1) * sizeof(WCHAR));
884 
885     _itow(pGlobalData->nNumLeadingZero,
886           szBuffer, DECIMAL_RADIX);
887     RegSetValueExW(hLocaleKey,
888                    L"iLZero",
889                    0,
890                    REG_SZ,
891                    (PBYTE)szBuffer,
892                    (wcslen(szBuffer) + 1) * sizeof(WCHAR));
893 
894     _itow(pGlobalData->nNumMeasure,
895           szBuffer, DECIMAL_RADIX);
896     RegSetValueExW(hLocaleKey,
897                    L"iMeasure",
898                    0,
899                    REG_SZ,
900                    (PBYTE)szBuffer,
901                    (wcslen(szBuffer) + 1) * sizeof(WCHAR));
902 
903     _itow(pGlobalData->nNumShape,
904           szBuffer, DECIMAL_RADIX);
905     RegSetValueExW(hLocaleKey,
906                    L"NumShape",
907                    0,
908                    REG_SZ,
909                    (PBYTE)szBuffer,
910                    (wcslen(szBuffer) + 1) * sizeof(WCHAR));
911 
912     /* Currency */
913     RegSetValueExW(hLocaleKey,
914                    L"sCurrency",
915                    0,
916                    REG_SZ,
917                    (PBYTE)pGlobalData->szCurrSymbol,
918                    (wcslen(pGlobalData->szCurrSymbol) + 1) * sizeof(WCHAR));
919 
920     RegSetValueExW(hLocaleKey,
921                    L"sMonDecimalSep",
922                    0,
923                    REG_SZ,
924                    (PBYTE)pGlobalData->szCurrDecimalSep,
925                    (wcslen(pGlobalData->szCurrDecimalSep) + 1) * sizeof(WCHAR));
926 
927     RegSetValueExW(hLocaleKey,
928                    L"sMonThousandSep",
929                    0,
930                    REG_SZ,
931                    (PBYTE)pGlobalData->szCurrThousandSep,
932                    (wcslen(pGlobalData->szCurrThousandSep) + 1) * sizeof(WCHAR));
933 
934     RegSetValueExW(hLocaleKey,
935                    L"sMonGrouping",
936                    0,
937                    REG_SZ,
938                    (PBYTE)GroupingFormats[pGlobalData->nCurrGrouping].pszString,
939                    (wcslen(GroupingFormats[pGlobalData->nCurrGrouping].pszString) + 1) * sizeof(WCHAR));
940 
941     _itow(pGlobalData->nCurrPosFormat,
942           szBuffer, DECIMAL_RADIX);
943     RegSetValueExW(hLocaleKey,
944                    L"iCurrency",
945                    0,
946                    REG_SZ,
947                    (PBYTE)szBuffer,
948                    (wcslen(szBuffer) + 1) * sizeof(WCHAR));
949 
950     _itow(pGlobalData->nCurrNegFormat,
951           szBuffer, DECIMAL_RADIX);
952     RegSetValueExW(hLocaleKey,
953                    L"iNegCurr",
954                    0,
955                    REG_SZ,
956                    (PBYTE)szBuffer,
957                    (wcslen(szBuffer) + 1) * sizeof(WCHAR));
958 
959     _itow(pGlobalData->nCurrDigits,
960           szBuffer, DECIMAL_RADIX);
961     RegSetValueExW(hLocaleKey,
962                    L"iCurrDigits",
963                    0,
964                    REG_SZ,
965                    (PBYTE)szBuffer,
966                    (wcslen(szBuffer) + 1) * sizeof(WCHAR));
967 
968     /* Time */
969     RegSetValueExW(hLocaleKey,
970                    L"sTimeFormat",
971                    0,
972                    REG_SZ,
973                    (PBYTE)pGlobalData->szTimeFormat,
974                    (wcslen(pGlobalData->szTimeFormat) + 1) * sizeof(WCHAR));
975 
976     RegSetValueExW(hLocaleKey,
977                    L"sTime",
978                    0,
979                    REG_SZ,
980                    (PBYTE)pGlobalData->szTimeSep,
981                    (wcslen(pGlobalData->szTimeSep) + 1) * sizeof(WCHAR));
982 
983     RegSetValueExW(hLocaleKey,
984                    L"s1159",
985                    0,
986                    REG_SZ,
987                    (PBYTE)pGlobalData->szTimeAM,
988                    (wcslen(pGlobalData->szTimeAM) + 1) * sizeof(WCHAR));
989 
990     RegSetValueExW(hLocaleKey,
991                    L"s2359",
992                    0,
993                    REG_SZ,
994                    (PBYTE)pGlobalData->szTimePM,
995                    (wcslen(pGlobalData->szTimePM) + 1) * sizeof(WCHAR));
996 
997     _itow(pGlobalData->nTime,
998           szBuffer, DECIMAL_RADIX);
999     RegSetValueExW(hLocaleKey,
1000                    L"iTime",
1001                    0,
1002                    REG_SZ,
1003                    (PBYTE)szBuffer,
1004                    (wcslen(szBuffer) + 1) * sizeof(WCHAR));
1005 
1006     _itow(pGlobalData->nTimePrefix,
1007           szBuffer, DECIMAL_RADIX);
1008     RegSetValueExW(hLocaleKey,
1009                    L"iTimePrefix",
1010                    0,
1011                    REG_SZ,
1012                    (PBYTE)szBuffer,
1013                    (wcslen(szBuffer) + 1) * sizeof(WCHAR));
1014 
1015     _itow(pGlobalData->nTimeLeadingZero,
1016           szBuffer, DECIMAL_RADIX);
1017     RegSetValueExW(hLocaleKey,
1018                    L"iTLZero",
1019                    0,
1020                    REG_SZ,
1021                    (PBYTE)szBuffer,
1022                    (wcslen(szBuffer) + 1) * sizeof(WCHAR));
1023 
1024     /* Date */
1025     RegSetValueExW(hLocaleKey,
1026                    L"sLongDate",
1027                    0,
1028                    REG_SZ,
1029                    (PBYTE)pGlobalData->szLongDateFormat,
1030                    (wcslen(pGlobalData->szLongDateFormat) + 1) * sizeof(WCHAR));
1031 
1032     RegSetValueExW(hLocaleKey,
1033                    L"sShortDate",
1034                    0,
1035                    REG_SZ,
1036                    (PBYTE)pGlobalData->szShortDateFormat,
1037                    (wcslen(pGlobalData->szShortDateFormat) + 1) * sizeof(WCHAR));
1038 
1039     RegSetValueExW(hLocaleKey,
1040                    L"sDate",
1041                    0,
1042                    REG_SZ,
1043                    (PBYTE)pGlobalData->szDateSep,
1044                    (wcslen(pGlobalData->szDateSep) + 1) * sizeof(WCHAR));
1045 
1046     _itow(pGlobalData->nFirstDayOfWeek,
1047           szBuffer, DECIMAL_RADIX);
1048     RegSetValueExW(hLocaleKey,
1049                    L"iFirstDayOfWeek",
1050                    0,
1051                    REG_SZ,
1052                    (PBYTE)szBuffer,
1053                    (wcslen(szBuffer) + 1) * sizeof(WCHAR));
1054 
1055     _itow(pGlobalData->nFirstWeekOfYear,
1056           szBuffer, DECIMAL_RADIX);
1057     RegSetValueExW(hLocaleKey,
1058                    L"iFirstWeekOfYear",
1059                    0,
1060                    REG_SZ,
1061                    (PBYTE)szBuffer,
1062                    (wcslen(szBuffer) + 1) * sizeof(WCHAR));
1063 
1064     _itow(pGlobalData->nDate,
1065           szBuffer, DECIMAL_RADIX);
1066     RegSetValueExW(hLocaleKey,
1067                    L"iDate",
1068                    0,
1069                    REG_SZ,
1070                    (PBYTE)szBuffer,
1071                    (wcslen(szBuffer) + 1) * sizeof(WCHAR));
1072 
1073     _itow(pGlobalData->nCalendarType,
1074           szBuffer, DECIMAL_RADIX);
1075     RegSetValueExW(hLocaleKey,
1076                    L"iCalendarType",
1077                    0,
1078                    REG_SZ,
1079                    (PBYTE)szBuffer,
1080                    (wcslen(szBuffer) + 1) * sizeof(WCHAR));
1081 
1082     /* Misc */
1083     RegSetValueExW(hLocaleKey,
1084                    L"sCountry",
1085                    0,
1086                    REG_SZ,
1087                    (PBYTE)pGlobalData->szMiscCountry,
1088                    (wcslen(pGlobalData->szMiscCountry) + 1) * sizeof(WCHAR));
1089 
1090     RegSetValueExW(hLocaleKey,
1091                    L"sLanguage",
1092                    0,
1093                    REG_SZ,
1094                    (PBYTE)pGlobalData->szMiscLanguage,
1095                    (wcslen(pGlobalData->szMiscLanguage) + 1) * sizeof(WCHAR));
1096 
1097     _itow(pGlobalData->nMiscCountry,
1098           szBuffer, DECIMAL_RADIX);
1099     RegSetValueExW(hLocaleKey,
1100                    L"iCountry",
1101                    0,
1102                    REG_SZ,
1103                    (PBYTE)szBuffer,
1104                    (wcslen(szBuffer) + 1) * sizeof(WCHAR));
1105 }
1106 
1107 
1108 /* Sets new locale */
1109 VOID
1110 SaveCurrentLocale(
1111     PGLOBALDATA pGlobalData)
1112 {
1113     HKEY hLocaleKey;
1114     DWORD ret;
1115 
1116     if (pGlobalData->bApplyToDefaultUser)
1117     {
1118         ret = RegOpenKeyExW(HKEY_USERS,
1119                             L".DEFAULT\\Control Panel\\International",
1120                             0,
1121                             KEY_WRITE,
1122                             &hLocaleKey);
1123         if (ret != ERROR_SUCCESS)
1124         {
1125             PrintErrorMsgBox(IDS_ERROR_DEF_INT_KEY_REG);
1126             return;
1127         }
1128 
1129         SaveUserLocale(pGlobalData, hLocaleKey);
1130 
1131         /* Flush and close the locale key */
1132         RegFlushKey(hLocaleKey);
1133         RegCloseKey(hLocaleKey);
1134     }
1135 
1136     ret = RegOpenKeyExW(HKEY_CURRENT_USER,
1137                         L"Control Panel\\International",
1138                         0,
1139                         KEY_WRITE,
1140                         &hLocaleKey);
1141     if (ret != ERROR_SUCCESS)
1142     {
1143         PrintErrorMsgBox(IDS_ERROR_INT_KEY_REG);
1144         return;
1145     }
1146 
1147     SaveUserLocale(pGlobalData, hLocaleKey);
1148 
1149     /* Flush and close the locale key */
1150     RegFlushKey(hLocaleKey);
1151     RegCloseKey(hLocaleKey);
1152 
1153     /* Set the new locale for the current process */
1154     NtSetDefaultLocale(TRUE, pGlobalData->UserLCID);
1155 }
1156 
1157 /* Location enumerate procedure */
1158 BOOL
1159 CALLBACK
1160 LocationsEnumProc(GEOID gId)
1161 {
1162     WCHAR loc[MAX_STR_SIZE];
1163     INT index;
1164 
1165     if (GetGeoInfoW(gId, GEO_FRIENDLYNAME, loc, MAX_STR_SIZE, LANG_SYSTEM_DEFAULT) == 0)
1166         return TRUE;
1167 
1168     index = (INT)SendMessageW(hGeoList,
1169                               CB_ADDSTRING,
1170                               0,
1171                               (LPARAM)loc);
1172 
1173     SendMessageW(hGeoList,
1174                  CB_SETITEMDATA,
1175                  index,
1176                  (LPARAM)gId);
1177 
1178     return TRUE;
1179 }
1180 
1181 /* Enumerate all system locations identifiers */
1182 static
1183 GEOID
1184 CreateLocationsList(HWND hWnd)
1185 {
1186     GEOID userGeoID;
1187     WCHAR loc[MAX_STR_SIZE];
1188 
1189     hGeoList = hWnd;
1190 
1191     EnumSystemGeoID(GEOCLASS_NATION, 0, LocationsEnumProc);
1192 
1193     /* Select current location */
1194     userGeoID = GetUserGeoID(GEOCLASS_NATION);
1195     GetGeoInfoW(userGeoID,
1196                 GEO_FRIENDLYNAME,
1197                 loc,
1198                 MAX_STR_SIZE,
1199                 LANG_SYSTEM_DEFAULT);
1200 
1201     SendMessageW(hGeoList,
1202                  CB_SELECTSTRING,
1203                  (WPARAM) -1,
1204                  (LPARAM)loc);
1205 
1206     return userGeoID;
1207 }
1208 
1209 VOID
1210 SaveGeoID(
1211     PGLOBALDATA pGlobalData)
1212 {
1213     HKEY hGeoKey;
1214     WCHAR value[15];
1215     DWORD valuesize;
1216     DWORD ret;
1217 
1218     wsprintf(value, L"%lu", (DWORD)pGlobalData->geoid);
1219     valuesize = (wcslen(value) + 1) * sizeof(WCHAR);
1220 
1221     if (pGlobalData->bApplyToDefaultUser)
1222     {
1223         ret = RegOpenKeyExW(HKEY_USERS,
1224                             L".DEFAULT\\Control Panel\\International\\Geo",
1225                             0,
1226                             KEY_WRITE,
1227                             &hGeoKey);
1228         if (ret != ERROR_SUCCESS)
1229         {
1230             PrintErrorMsgBox(IDS_ERROR_DEF_INT_KEY_REG);
1231             return;
1232         }
1233 
1234         ret = RegSetValueExW(hGeoKey,
1235                              L"Nation",
1236                              0,
1237                              REG_SZ,
1238                              (PBYTE)value,
1239                              valuesize);
1240 
1241         RegFlushKey(hGeoKey);
1242         RegCloseKey(hGeoKey);
1243 
1244         if (ret != ERROR_SUCCESS)
1245         {
1246             PrintErrorMsgBox(IDS_ERROR_INT_KEY_REG);
1247             return;
1248         }
1249     }
1250 
1251     ret = RegOpenKeyExW(HKEY_CURRENT_USER,
1252                         L"Control Panel\\International\\Geo",
1253                         0,
1254                         KEY_WRITE,
1255                         &hGeoKey);
1256     if (ret != ERROR_SUCCESS)
1257     {
1258         PrintErrorMsgBox(IDS_ERROR_INT_KEY_REG);
1259         return;
1260     }
1261 
1262     ret = RegSetValueExW(hGeoKey,
1263                          L"Nation",
1264                          0,
1265                          REG_SZ,
1266                          (PBYTE)value,
1267                          valuesize);
1268 
1269     RegFlushKey(hGeoKey);
1270     RegCloseKey(hGeoKey);
1271 
1272     if (ret != ERROR_SUCCESS)
1273     {
1274         PrintErrorMsgBox(IDS_ERROR_INT_KEY_REG);
1275         return;
1276     }
1277 }
1278 
1279 DWORD
1280 VerifyUnattendLCID(HWND hwndDlg)
1281 {
1282     LRESULT lCount, lIndex, lResult;
1283 
1284     lCount = SendMessage(hList, CB_GETCOUNT, (WPARAM)0, (LPARAM)0);
1285     if (lCount == CB_ERR)
1286     {
1287         return 0;
1288     }
1289 
1290     for (lIndex = 0; lIndex < lCount; lIndex++)
1291     {
1292         lResult = SendMessage(hList, CB_GETITEMDATA, (WPARAM)lIndex, (LPARAM)0);
1293         if (lResult == CB_ERR)
1294         {
1295             continue;
1296         }
1297 
1298         if (lResult == (LRESULT)UnattendLCID)
1299         {
1300             SendMessage(hList, CB_SETCURSEL, (WPARAM)lIndex, (LPARAM)0);
1301             PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1302             return 1;
1303         }
1304     }
1305 
1306     return 0;
1307 }
1308 
1309 
1310 static
1311 VOID
1312 InitPropSheetPage(
1313     PROPSHEETPAGEW *psp,
1314     WORD idDlg,
1315     DLGPROC DlgProc,
1316     PGLOBALDATA pGlobalData)
1317 {
1318     ZeroMemory(psp, sizeof(PROPSHEETPAGEW));
1319     psp->dwSize = sizeof(PROPSHEETPAGEW);
1320     psp->dwFlags = PSP_DEFAULT;
1321     psp->hInstance = hApplet;
1322     psp->pszTemplate = MAKEINTRESOURCE(idDlg);
1323     psp->pfnDlgProc = DlgProc;
1324     psp->lParam = (LPARAM)pGlobalData;
1325 }
1326 
1327 static int CALLBACK
1328 PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam)
1329 {
1330     // NOTE: This callback is needed to set large icon correctly.
1331     HICON hIcon;
1332     switch (uMsg)
1333     {
1334         case PSCB_INITIALIZED:
1335         {
1336             hIcon = LoadIconW(hApplet, MAKEINTRESOURCEW(IDC_CPLICON));
1337             SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
1338             break;
1339         }
1340     }
1341     return 0;
1342 }
1343 
1344 INT_PTR
1345 APIENTRY
1346 CustomizeLocalePropertySheet(
1347     HWND hwndDlg,
1348     PGLOBALDATA pGlobalData)
1349 {
1350     PROPSHEETPAGEW PsPage[NUM_SHEETS + 1];
1351     PROPSHEETHEADERW psh;
1352     WCHAR Caption[MAX_STR_SIZE];
1353 
1354     LoadStringW(hApplet, IDS_CUSTOMIZE_TITLE, Caption, sizeof(Caption) / sizeof(TCHAR));
1355 
1356     ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
1357     psh.dwSize = sizeof(PROPSHEETHEADER);
1358     psh.dwFlags =  PSH_PROPSHEETPAGE | PSH_USEICONID | PSH_USECALLBACK;
1359     psh.hwndParent = hwndDlg;
1360     psh.hInstance = hApplet;
1361     psh.pszIcon = MAKEINTRESOURCE(IDC_CPLICON);
1362     psh.pszCaption = Caption;
1363     psh.nPages = (sizeof(PsPage) / sizeof(PROPSHEETPAGE)) - 1;
1364     psh.nStartPage = 0;
1365     psh.ppsp = PsPage;
1366     psh.pfnCallback = PropSheetProc;
1367 
1368     InitPropSheetPage(&PsPage[0], IDD_NUMBERSPAGE, NumbersPageProc, pGlobalData);
1369     InitPropSheetPage(&PsPage[1], IDD_CURRENCYPAGE, CurrencyPageProc, pGlobalData);
1370     InitPropSheetPage(&PsPage[2], IDD_TIMEPAGE, TimePageProc, pGlobalData);
1371     InitPropSheetPage(&PsPage[3], IDD_DATEPAGE, DatePageProc, pGlobalData);
1372 
1373     if (IsSortPageNeeded(pGlobalData->UserLCID))
1374     {
1375         psh.nPages++;
1376         InitPropSheetPage(&PsPage[4], IDD_SORTPAGE, SortPageProc, pGlobalData);
1377     }
1378 
1379     return PropertySheetW(&psh);
1380 }
1381 
1382 
1383 /* Property page dialog callback */
1384 INT_PTR CALLBACK
1385 GeneralPageProc(HWND hwndDlg,
1386                 UINT uMsg,
1387                 WPARAM wParam,
1388                 LPARAM lParam)
1389 {
1390     PGLOBALDATA pGlobalData;
1391 
1392     pGlobalData = (PGLOBALDATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
1393 
1394     switch (uMsg)
1395     {
1396         case WM_INITDIALOG:
1397             pGlobalData = (PGLOBALDATA)((LPPROPSHEETPAGE)lParam)->lParam;
1398             SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
1399 
1400             if (pGlobalData)
1401             {
1402                 LoadCurrentLocale(pGlobalData);
1403 
1404                 CreateLanguagesList(GetDlgItem(hwndDlg, IDC_LANGUAGELIST));
1405                 UpdateLocaleSample(hwndDlg, pGlobalData);
1406                 pGlobalData->geoid = CreateLocationsList(GetDlgItem(hwndDlg, IDC_LOCATION_COMBO));
1407                 if (IsUnattendedSetupEnabled)
1408                 {
1409                     if (VerifyUnattendLCID(hwndDlg))
1410                     {
1411                         SetNewLocale(pGlobalData, UnattendLCID);
1412                         SaveCurrentLocale(pGlobalData);
1413                         PostQuitMessage(0);
1414                     }
1415                     else
1416                     {
1417                         DPRINT1("VerifyUnattendLCID failed\n");
1418                     }
1419                     return TRUE;
1420                 }
1421             }
1422             break;
1423 
1424         case WM_COMMAND:
1425             switch (LOWORD(wParam))
1426             {
1427                 case IDC_LANGUAGELIST:
1428                     if (HIWORD(wParam) == CBN_SELCHANGE)
1429                     {
1430                         LCID NewLcid;
1431                         INT iCurSel;
1432 
1433                         iCurSel = SendMessage(hList,
1434                                               CB_GETCURSEL,
1435                                               0,
1436                                               0);
1437                         if (iCurSel == CB_ERR)
1438                             break;
1439 
1440                         NewLcid = SendMessage(hList,
1441                                               CB_GETITEMDATA,
1442                                               iCurSel,
1443                                               0);
1444                         if (NewLcid == (LCID)CB_ERR)
1445                             break;
1446 
1447                         SetNewLocale(pGlobalData, NewLcid);
1448                         UpdateLocaleSample(hwndDlg, pGlobalData);
1449                         pGlobalData->bUserLocaleChanged = TRUE;
1450 
1451                         PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1452                     }
1453                     break;
1454 
1455                 case IDC_LOCATION_COMBO:
1456                     if (HIWORD(wParam) == CBN_SELCHANGE)
1457                     {
1458                         GEOID NewGeoID;
1459                         INT iCurSel;
1460 
1461                         iCurSel = SendMessage(GetDlgItem(hwndDlg, IDC_LOCATION_COMBO),
1462                                               CB_GETCURSEL,
1463                                               0,
1464                                               0);
1465                         if (iCurSel == CB_ERR)
1466                             break;
1467 
1468                         NewGeoID = SendMessage(GetDlgItem(hwndDlg, IDC_LOCATION_COMBO),
1469                                                CB_GETITEMDATA,
1470                                                iCurSel,
1471                                                0);
1472                         if (NewGeoID == (GEOID)CB_ERR)
1473                             break;
1474 
1475                         pGlobalData->geoid = NewGeoID;
1476                         pGlobalData->bGeoIdChanged = TRUE;
1477 
1478                         PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1479                     }
1480                     break;
1481 
1482                 case IDC_SETUP_BUTTON:
1483                     if (CustomizeLocalePropertySheet(GetParent(hwndDlg), pGlobalData) > 0)
1484                     {
1485                         UpdateLocaleSample(hwndDlg, pGlobalData);
1486                         pGlobalData->bUserLocaleChanged = TRUE;
1487                         PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1488                     }
1489                     break;
1490             }
1491             break;
1492 
1493         case WM_NOTIFY:
1494             if (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY)
1495             {
1496                 /* Apply changes */
1497                 PropSheet_UnChanged(GetParent(hwndDlg), hwndDlg);
1498 
1499                 /* Set new locale */
1500                 if (pGlobalData->bUserLocaleChanged == TRUE)
1501                 {
1502                     SaveCurrentLocale(pGlobalData);
1503                     pGlobalData->bUserLocaleChanged = FALSE;
1504                 }
1505 
1506                 /* Set new GEO ID */
1507                 if (pGlobalData->bGeoIdChanged == TRUE)
1508                 {
1509                     SaveGeoID(pGlobalData);
1510                     pGlobalData->bGeoIdChanged = FALSE;
1511                 }
1512 
1513                 AddNewKbLayoutsByLcid(pGlobalData->UserLCID);
1514 
1515                 /* Post WM_WININICHANGE messages to system */
1516                 PostMessageW(HWND_BROADCAST, WM_WININICHANGE, 0, (LPARAM)L"intl");
1517             }
1518             break;
1519     }
1520 
1521     return FALSE;
1522 }
1523 
1524 /* EOF */
1525