[INTL]
[reactos.git] / reactos / dll / cpl / intl / generalp.c
index dcd9bab..aa1c660 100644 (file)
 #define SAMPLE_NUMBER   L"123456789"
 #define NO_FLAG         0
 
+#define NUM_SHEETS      4
+
+#define MAX_FIELD_DIG_SAMPLES       3
+
 typedef struct
 {
     LCTYPE lcType;
@@ -42,47 +46,14 @@ HWND hList;
 HWND hLocaleList, hGeoList;
 BOOL bSpain = FALSE;
 
-LOCALE_KEY_DATA LocaleKeyData[] =
+
+PWSTR szCurrencyGrouping[3] =
 {
-    {LOCALE_ICALENDARTYPE, L"iCalendarType"},
-    {LOCALE_ICOUNTRY, L"iCountry"},
-    {LOCALE_ICURRDIGITS, L"iCurrDigits"},
-    {LOCALE_ICURRENCY, L"iCurrency"},
-    {LOCALE_IDATE, L"iDate"},
-    {LOCALE_IDIGITS, L"iDigits"},
-    {LOCALE_IFIRSTDAYOFWEEK, L"iFirstDayOfWeek"},
-    {LOCALE_IFIRSTWEEKOFYEAR, L"iFirstWeekOfYear"},
-    {LOCALE_ILZERO, L"iLZero"},
-    {LOCALE_IMEASURE, L"iMeasure"},
-    {LOCALE_INEGCURR, L"iNegCurr"},
-    {LOCALE_INEGNUMBER, L"iNegNumber"},
-    {LOCALE_ITIME, L"iTime"},
-    {LOCALE_ITIMEMARKPOSN, L"iTimePrefix"},
-    {LOCALE_ITLZERO, L"iTLZero"},
-    {LOCALE_IDIGITSUBSTITUTION, L"NumShape"},
-    {LOCALE_S1159, L"s1159"},
-    {LOCALE_S2359, L"s2359"},
-    {LOCALE_SCOUNTRY, L"sCountry"},
-    {LOCALE_SCURRENCY, L"sCurrency"},
-    {LOCALE_SDATE, L"sDate"},
-    {LOCALE_SDECIMAL, L"sDecimal"},
-    {LOCALE_SGROUPING, L"sGrouping"},
-    {LOCALE_SABBREVLANGNAME, L"sLanguage"},
-    {LOCALE_SLIST, L"sList"},
-    {LOCALE_SLONGDATE, L"sLongDate"},
-    {LOCALE_SMONDECIMALSEP, L"sMonDecimalSep"},
-    {LOCALE_SMONGROUPING, L"sMonGrouping"},
-    {LOCALE_SMONTHOUSANDSEP, L"sMonThousandSep"},
-    {LOCALE_SNATIVEDIGITS, L"sNativeDigits"},
-    {LOCALE_SNEGATIVESIGN, L"sNegativeSign"},
-    {LOCALE_SPOSITIVESIGN, L"sPositiveSign"},
-    {LOCALE_SSHORTDATE, L"sShortDate"},
-    {LOCALE_STHOUSAND, L"sThousand"},
-    {LOCALE_STIME, L"sTime"},
-    {LOCALE_STIMEFORMAT, L"sTimeFormat"}
+    L"0;0",
+    L"3;0",
+    L"3;2;0"
 };
 
-
 static BOOL CALLBACK
 LocalesEnumProc(LPTSTR lpLocale)
 {
@@ -132,24 +103,6 @@ LocalesEnumProc(LPTSTR lpLocale)
 }
 
 
-PWSTR
-GetLocaleString(
-    PWSTR *pLocaleArray,
-    LCTYPE lcType)
-{
-    DWORD dwDataCount, i;
-
-    dwDataCount = sizeof(LocaleKeyData) / sizeof(LOCALE_KEY_DATA);
-    for (i = 0; i < dwDataCount; i++)
-    {
-        if (LocaleKeyData[i].lcType == lcType)
-            return pLocaleArray[i];
-    }
-
-    return NULL;
-}
-
-
 /* Update all locale samples */
 static
 VOID
@@ -160,34 +113,34 @@ UpdateLocaleSample(
     WCHAR OutBuffer[MAX_SAMPLES_STR_SIZE];
 
     /* Get number format sample */
-    GetNumberFormatW(pGlobalData->lcid, NO_FLAG, SAMPLE_NUMBER, NULL,
+    GetNumberFormatW(pGlobalData->UserLCID, NO_FLAG, SAMPLE_NUMBER, NULL,
                      OutBuffer, MAX_SAMPLES_STR_SIZE);
     SendDlgItemMessageW(hwndDlg, IDC_NUMSAMPLE_EDIT,
                         WM_SETTEXT, 0, (LPARAM)OutBuffer);
     ZeroMemory(OutBuffer, MAX_SAMPLES_STR_SIZE * sizeof(WCHAR));
 
     /* Get monetary format sample */
-    GetCurrencyFormatW(pGlobalData->lcid, NO_FLAG, SAMPLE_NUMBER, NULL,
+    GetCurrencyFormatW(pGlobalData->UserLCID, NO_FLAG, SAMPLE_NUMBER, NULL,
                        OutBuffer, MAX_SAMPLES_STR_SIZE);
     SendDlgItemMessageW(hwndDlg, IDC_MONEYSAMPLE_EDIT,
                         WM_SETTEXT, 0, (LPARAM)OutBuffer);
     ZeroMemory(OutBuffer, MAX_SAMPLES_STR_SIZE * sizeof(WCHAR));
 
     /* Get time format sample */
-    GetTimeFormatW(pGlobalData->lcid, NO_FLAG, NULL, NULL,
+    GetTimeFormatW(pGlobalData->UserLCID, NO_FLAG, NULL, NULL,
                    OutBuffer, MAX_SAMPLES_STR_SIZE);
     SendDlgItemMessageW(hwndDlg, IDC_TIMESAMPLE_EDIT,
                         WM_SETTEXT, 0, (LPARAM)OutBuffer);
     ZeroMemory(OutBuffer, MAX_SAMPLES_STR_SIZE * sizeof(WCHAR));
 
     /* Get short date format sample */
-    GetDateFormatW(pGlobalData->lcid, DATE_SHORTDATE, NULL, NULL,
+    GetDateFormatW(pGlobalData->UserLCID, DATE_SHORTDATE, NULL, NULL,
                    OutBuffer, MAX_SAMPLES_STR_SIZE);
     SendDlgItemMessageW(hwndDlg, IDC_SHORTTIMESAMPLE_EDIT,
                         WM_SETTEXT, 0, (LPARAM)OutBuffer);
 
     /* Get long date sample */
-    GetDateFormatW(pGlobalData->lcid, DATE_LONGDATE, NULL, NULL,
+    GetDateFormatW(pGlobalData->UserLCID, DATE_LONGDATE, NULL, NULL,
                    OutBuffer, MAX_SAMPLES_STR_SIZE);
     SendDlgItemMessageW(hwndDlg, IDC_FULLTIMESAMPLE_EDIT,
                         WM_SETTEXT, 0, (LPARAM)OutBuffer);
@@ -217,12 +170,11 @@ BOOL
 LoadCurrentLocale(
     PGLOBALDATA pGlobalData)
 {
-    WCHAR szValue[9];
+    WCHAR szBuffer[16];
     PWSTR ptr;
     HKEY hLocaleKey;
     DWORD ret;
     DWORD dwSize;
-    DWORD i;
 
     ret = RegOpenKeyExW(HKEY_CURRENT_USER,
                         L"Control Panel\\International",
@@ -235,48 +187,364 @@ LoadCurrentLocale(
         return FALSE;
     }
 
-    pGlobalData->dwLocaleCount = sizeof(LocaleKeyData) / sizeof(LOCALE_KEY_DATA);
+    dwSize = 9 * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"Locale",
+                     NULL,
+                     NULL,
+                     (PBYTE)szBuffer,
+                     &dwSize);
+    pGlobalData->UserLCID = (LCID)wcstoul(szBuffer, &ptr, 16);
+
+    /* Number */
+    dwSize = MAX_NUMDECIMALSEP * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"sDecimal",
+                     NULL,
+                     NULL,
+                     (PBYTE)pGlobalData->szNumDecimalSep,
+                     &dwSize);
+
+    dwSize = MAX_NUMTHOUSANDSEP * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"sThousand",
+                     NULL,
+                     NULL,
+                     (PBYTE)pGlobalData->szNumThousandSep,
+                     &dwSize);
+
+    dwSize = MAX_NUMNEGATIVESIGN * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"sNegativeSign",
+                     NULL,
+                     NULL,
+                     (PBYTE)pGlobalData->szNumNegativeSign,
+                     &dwSize);
 
-    pGlobalData->pLocaleArray = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
-                                          pGlobalData->dwLocaleCount * sizeof(PWSTR));
-    if (pGlobalData->pLocaleArray == NULL)
+    dwSize = MAX_NUMPOSITIVESIGN * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"sPositiveSign",
+                     NULL,
+                     NULL,
+                     (PBYTE)pGlobalData->szNumPositiveSign,
+                     &dwSize);
+
+    dwSize = MAX_NUMLISTSEP * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"sList",
+                     NULL,
+                     NULL,
+                     (PBYTE)pGlobalData->szNumListSep,
+                     &dwSize);
+
+    dwSize = MAX_NUMNATIVEDIGITS * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"sNativeDigits",
+                     NULL,
+                     NULL,
+                     (PBYTE)pGlobalData->szNumNativeDigits,
+                     &dwSize);
+
+    pGlobalData->nNumNegFormat = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"iNegNumber",
+                         NULL,
+                         NULL,
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
+        pGlobalData->nNumNegFormat = _wtoi(szBuffer);
+
+    pGlobalData->nNumDigits = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"iDigits",
+                         NULL,
+                         NULL,
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
+        pGlobalData->nNumDigits = _wtoi(szBuffer);
+
+    pGlobalData->nNumLeadingZero = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"iLZero",
+                         NULL,
+                         NULL,
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
+        pGlobalData->nNumLeadingZero = _wtoi(szBuffer);
+
+    pGlobalData->nNumMeasure = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"iMeasure",
+                         NULL,
+                         NULL,
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
+        pGlobalData->nNumMeasure = _wtoi(szBuffer);
+
+    pGlobalData->nNumShape = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"NumShape",
+                         NULL,
+                         NULL,
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
+        pGlobalData->nNumShape = _wtoi(szBuffer);
+
+    pGlobalData->nNumGrouping = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"sGrouping",
+                         NULL,
+                         NULL,
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
     {
-        RegCloseKey(hLocaleKey);
-        return FALSE;
+        pGlobalData->nNumGrouping = 0;
+        if (szBuffer[0] == L'3')
+        {
+            if ((szBuffer[1] == L';') &&
+                (szBuffer[2] == L'2'))
+                pGlobalData->nNumGrouping = 2;
+            else
+                pGlobalData->nNumGrouping = 1;
+        }
     }
 
-    dwSize = 9 * sizeof(WCHAR);
+    /* Currency */
+    dwSize = MAX_CURRSYMBOL * sizeof(WCHAR);
     RegQueryValueExW(hLocaleKey,
-                     L"Locale",
+                     L"sCurrency",
                      NULL,
                      NULL,
-                     (PBYTE)szValue,
+                     (PBYTE)pGlobalData->szCurrSymbol,
                      &dwSize);
-    pGlobalData->lcid = (LCID)wcstoul(szValue, &ptr, 16);
 
-    for (i = 0; i < pGlobalData->dwLocaleCount; i++)
-    {
-        RegQueryValueExW(hLocaleKey,
-                         LocaleKeyData[i].pKeyName,
-                         NULL,
+    dwSize = MAX_CURRDECIMALSEP * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"sMonDecimalSep",
+                     NULL,
+                     NULL,
+                     (PBYTE)pGlobalData->szCurrDecimalSep,
+                     &dwSize);
+
+    dwSize = MAX_CURRTHOUSANDSEP * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"sMonThousandSep",
+                     NULL,
+                     NULL,
+                     (PBYTE)pGlobalData->szCurrThousandSep,
+                     &dwSize);
+
+    pGlobalData->nCurrGrouping = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"sMonGrouping",
                          NULL,
                          NULL,
-                         &dwSize);
-        if (dwSize > 0)
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
+    {
+        pGlobalData->nCurrGrouping = 0;
+        if (szBuffer[0] == L'3')
         {
-            pGlobalData->pLocaleArray[i] = HeapAlloc(GetProcessHeap(), 0, dwSize);
-            if (pGlobalData->pLocaleArray[i])
-            {
-                RegQueryValueExW(hLocaleKey,
-                                 LocaleKeyData[i].pKeyName,
-                                 NULL,
-                                 NULL,
-                                 (LPVOID)pGlobalData->pLocaleArray[i],
-                                 &dwSize);
-            }
+            if ((szBuffer[1] == L';') &&
+                (szBuffer[2] == L'2'))
+                pGlobalData->nCurrGrouping = 2;
+            else
+                pGlobalData->nCurrGrouping = 1;
         }
     }
 
+    pGlobalData->nCurrPosFormat = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"iCurrency",
+                         NULL,
+                         NULL,
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
+        pGlobalData->nCurrPosFormat = _wtoi(szBuffer);
+
+    pGlobalData->nCurrNegFormat = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"iNegCurr",
+                         NULL,
+                         NULL,
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
+        pGlobalData->nCurrNegFormat = _wtoi(szBuffer);
+
+    pGlobalData->nCurrDigits = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"iCurrDigits",
+                         NULL,
+                         NULL,
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
+        pGlobalData->nCurrDigits = _wtoi(szBuffer);
+
+    /* Time */
+    dwSize = MAX_TIMEFORMAT * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"sTimeFormat",
+                     NULL,
+                     NULL,
+                     (PBYTE)pGlobalData->szTimeFormat,
+                     &dwSize);
+
+    dwSize = MAX_TIMESEPARATOR * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"sTime",
+                     NULL,
+                     NULL,
+                     (PBYTE)pGlobalData->szTimeSep,
+                     &dwSize);
+
+    dwSize = MAX_TIMEAMSYMBOL * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"s1159",
+                     NULL,
+                     NULL,
+                     (PBYTE)pGlobalData->szTimeAM,
+                     &dwSize);
+
+    dwSize = MAX_TIMEPMSYMBOL * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"s2359",
+                     NULL,
+                     NULL,
+                     (PBYTE)pGlobalData->szTimePM,
+                     &dwSize);
+
+    pGlobalData->nTime = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"iTime",
+                         NULL,
+                         NULL,
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
+        pGlobalData->nTime = _wtoi(szBuffer);
+
+    pGlobalData->nTimePrefix = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"iTimePrefix",
+                         NULL,
+                         NULL,
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
+        pGlobalData->nTimePrefix = _wtoi(szBuffer);
+
+    pGlobalData->nTimeLeadingZero = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"iTLZero",
+                         NULL,
+                         NULL,
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
+        pGlobalData->nTimeLeadingZero = _wtoi(szBuffer);
+
+    /* Date */
+    dwSize = MAX_LONGDATEFORMAT * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"sLongDate",
+                     NULL,
+                     NULL,
+                     (PBYTE)pGlobalData->szLongDateFormat,
+                     &dwSize);
+
+    dwSize = MAX_SHORTDATEFORMAT * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"sShortDate",
+                     NULL,
+                     NULL,
+                     (PBYTE)pGlobalData->szShortDateFormat,
+                     &dwSize);
+
+    dwSize = MAX_DATESEPARATOR * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"sDate",
+                     NULL,
+                     NULL,
+                     (PBYTE)pGlobalData->szDateSep,
+                     &dwSize);
+
+    pGlobalData->nFirstDayOfWeek = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"iFirstDayOfWeek",
+                         NULL,
+                         NULL,
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
+        pGlobalData->nFirstDayOfWeek = _wtoi(szBuffer);
+
+    pGlobalData->nFirstWeekOfYear = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"iFirstWeekOfYear",
+                         NULL,
+                         NULL,
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
+        pGlobalData->nFirstWeekOfYear = _wtoi(szBuffer);
+
+    pGlobalData->nDate = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"iDate",
+                         NULL,
+                         NULL,
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
+        pGlobalData->nDate = _wtoi(szBuffer);
+
+    pGlobalData->nCalendarType = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"iCalendarType",
+                         NULL,
+                         NULL,
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
+        pGlobalData->nCalendarType = _wtoi(szBuffer);
+
+    /* Misc */
+    dwSize = MAX_MISCCOUNTRY * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"sCountry",
+                     NULL,
+                     NULL,
+                     (PBYTE)pGlobalData->szMiscCountry,
+                     &dwSize);
+
+    dwSize = MAX_MISCLANGUAGE * sizeof(WCHAR);
+    RegQueryValueExW(hLocaleKey,
+                     L"sLanguage",
+                     NULL,
+                     NULL,
+                     (PBYTE)pGlobalData->szMiscLanguage,
+                     &dwSize);
+
+    pGlobalData->nMiscCountry = 0;
+    dwSize = 16 * sizeof(WCHAR);
+    if (RegQueryValueExW(hLocaleKey,
+                         L"iCountry",
+                         NULL,
+                         NULL,
+                         (PBYTE)szBuffer,
+                         &dwSize) == ERROR_SUCCESS)
+        pGlobalData->nMiscCountry = _wtoi(szBuffer);
+
     RegCloseKey(hLocaleKey);
 
     return TRUE;
@@ -284,57 +552,539 @@ LoadCurrentLocale(
 
 
 VOID
-FreeCurrentLocale(
-    PGLOBALDATA pGlobalData)
+SetNewLocale(
+    PGLOBALDATA pGlobalData,
+    LCID lcid)
 {
-    DWORD i;
-
-    if (pGlobalData == NULL || pGlobalData->pLocaleArray == NULL)
-        return;
+    WCHAR szBuffer[16];
+
+    pGlobalData->UserLCID = lcid;
+
+    /* Number */
+    GetLocaleInfo(lcid,
+                  LOCALE_SDECIMAL | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szNumDecimalSep,
+                  MAX_NUMDECIMALSEP * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_STHOUSAND | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szNumThousandSep,
+                  MAX_NUMTHOUSANDSEP * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_SNEGATIVESIGN | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szNumNegativeSign,
+                  MAX_NUMNEGATIVESIGN * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_SPOSITIVESIGN | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szNumPositiveSign,
+                  MAX_NUMPOSITIVESIGN * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_SLIST | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szNumListSep,
+                  MAX_NUMLISTSEP * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_SNATIVEDIGITS | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szNumNativeDigits,
+                  MAX_NUMNATIVEDIGITS * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_INEGNUMBER | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nNumNegFormat = _wtoi(szBuffer);
+
+    GetLocaleInfo(lcid,
+                  LOCALE_IDIGITS | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nNumDigits = _wtoi(szBuffer);
+
+    GetLocaleInfo(lcid,
+                  LOCALE_ILZERO | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nNumLeadingZero = _wtoi(szBuffer);
+
+    GetLocaleInfo(lcid,
+                  LOCALE_IMEASURE | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nNumMeasure = _wtoi(szBuffer);
+
+    GetLocaleInfo(lcid,
+                  LOCALE_IDIGITSUBSTITUTION | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nNumShape = _wtoi(szBuffer);
+
+    GetLocaleInfo(lcid,
+                  LOCALE_SGROUPING | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nNumGrouping = 0;
+    if (szBuffer[0] == L'3')
+    {
+        if ((szBuffer[1] == L';') &&
+            (szBuffer[2] == L'2'))
+            pGlobalData->nNumGrouping = 2;
+        else
+            pGlobalData->nNumGrouping = 1;
+    }
 
-    for (i = 0; i < pGlobalData->dwLocaleCount; i++)
+    /* Currency */
+    GetLocaleInfo(lcid,
+                  LOCALE_SCURRENCY | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szCurrSymbol,
+                  MAX_CURRSYMBOL * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_SMONDECIMALSEP | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szCurrDecimalSep,
+                  MAX_CURRDECIMALSEP * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_SMONTHOUSANDSEP | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szCurrThousandSep,
+                  MAX_CURRTHOUSANDSEP * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_SMONGROUPING | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nCurrGrouping = 0;
+    if (szBuffer[0] == L'3')
     {
-        if (pGlobalData->pLocaleArray[i])
-            HeapFree(GetProcessHeap(), 0, pGlobalData->pLocaleArray[i]);
+        if ((szBuffer[1] == L';') &&
+            (szBuffer[2] == L'2'))
+            pGlobalData->nCurrGrouping = 2;
+        else
+            pGlobalData->nCurrGrouping = 1;
     }
-    HeapFree(GetProcessHeap(), 0, pGlobalData->pLocaleArray);
-    pGlobalData->pLocaleArray = NULL;
+
+    GetLocaleInfo(lcid,
+                  LOCALE_ICURRENCY | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nCurrPosFormat = _wtoi(szBuffer);
+
+    GetLocaleInfo(lcid,
+                  LOCALE_INEGCURR | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nCurrNegFormat = _wtoi(szBuffer);
+
+    GetLocaleInfo(lcid,
+                  LOCALE_ICURRDIGITS | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nCurrDigits = _wtoi(szBuffer);
+
+    /* Time */
+    GetLocaleInfo(lcid,
+                  LOCALE_STIMEFORMAT | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szTimeFormat,
+                  MAX_TIMEFORMAT * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_STIME | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szTimeSep,
+                  MAX_TIMESEPARATOR * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_S1159 | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szTimeAM,
+                  MAX_TIMEAMSYMBOL * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_S2359 | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szTimePM,
+                  MAX_TIMEPMSYMBOL * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_ITIME | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nTime = _wtoi(szBuffer);
+
+    GetLocaleInfo(lcid,
+                  LOCALE_ITIMEMARKPOSN | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nTimePrefix = _wtoi(szBuffer);
+
+    GetLocaleInfo(lcid,
+                  LOCALE_ITLZERO | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nTimeLeadingZero = _wtoi(szBuffer);
+
+    /* Date */
+    GetLocaleInfo(lcid,
+                  LOCALE_SLONGDATE | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szLongDateFormat,
+                  MAX_LONGDATEFORMAT * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_SSHORTDATE | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szShortDateFormat,
+                  MAX_SHORTDATEFORMAT * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_SDATE | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szDateSep,
+                  MAX_DATESEPARATOR * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_IFIRSTDAYOFWEEK | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nFirstDayOfWeek = _wtoi(szBuffer);
+
+    GetLocaleInfo(lcid,
+                  LOCALE_IFIRSTWEEKOFYEAR | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nFirstWeekOfYear = _wtoi(szBuffer);
+
+    GetLocaleInfo(lcid,
+                  LOCALE_IDATE | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nDate = _wtoi(szBuffer);
+
+    GetLocaleInfo(lcid,
+                  LOCALE_ICALENDARTYPE | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nCalendarType = _wtoi(szBuffer);
+
+    /* Misc */
+    GetLocaleInfo(lcid,
+                  LOCALE_SCOUNTRY | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szMiscCountry,
+                  MAX_MISCCOUNTRY * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_SLANGUAGE | LOCALE_NOUSEROVERRIDE,
+                  pGlobalData->szMiscLanguage,
+                  MAX_MISCLANGUAGE * sizeof(WCHAR));
+
+    GetLocaleInfo(lcid,
+                  LOCALE_ICOUNTRY | LOCALE_NOUSEROVERRIDE,
+                  szBuffer,
+                  16 * sizeof(WCHAR));
+    pGlobalData->nMiscCountry = _wtoi(szBuffer);
 }
 
 
+static
 VOID
-SetNewLocale(
+SaveUserLocale(
     PGLOBALDATA pGlobalData,
-    LCID lcid)
+    HKEY hLocaleKey)
 {
-    DWORD i, dwSize;
-
-    pGlobalData->lcid = lcid;
-
-    for (i = 0; i < pGlobalData->dwLocaleCount; i++)
-    {
-        if (pGlobalData->pLocaleArray[i])
-        {
-            HeapFree(GetProcessHeap(), 0, pGlobalData->pLocaleArray[i]);
-            pGlobalData->pLocaleArray[i] = NULL;
-        }
-
-        dwSize = GetLocaleInfo(lcid,
-                               LocaleKeyData[i].lcType | LOCALE_NOUSEROVERRIDE,
-                               NULL,
-                               0);
-        if (dwSize > 0)
-        {
-            pGlobalData->pLocaleArray[i] = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(WCHAR));
-            if (pGlobalData->pLocaleArray[i])
-            {
-                GetLocaleInfo(lcid,
-                              LocaleKeyData[i].lcType | LOCALE_NOUSEROVERRIDE,
-                              pGlobalData->pLocaleArray[i],
-                              dwSize);
-            }
-        }
-    }
+    WCHAR szBuffer[16];
+
+    wsprintf(szBuffer, L"%08lx", (DWORD)pGlobalData->UserLCID);
+    RegSetValueExW(hLocaleKey,
+                   L"Locale",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szBuffer,
+                   (wcslen(szBuffer) + 1) * sizeof(WCHAR));
+
+    /* Number */
+    RegSetValueExW(hLocaleKey,
+                   L"sDecimal",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szNumDecimalSep,
+                   (wcslen(pGlobalData->szNumDecimalSep) + 1) * sizeof(WCHAR));
+
+    RegSetValueExW(hLocaleKey,
+                   L"sThousand",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szNumThousandSep,
+                   (wcslen(pGlobalData->szNumThousandSep) + 1) * sizeof(WCHAR));
+
+    RegSetValueExW(hLocaleKey,
+                   L"sNegativeSign",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szNumNegativeSign,
+                   (wcslen(pGlobalData->szNumNegativeSign) + 1) * sizeof(WCHAR));
+
+    RegSetValueExW(hLocaleKey,
+                   L"sPositiveSign",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szNumPositiveSign,
+                   (wcslen(pGlobalData->szNumPositiveSign) + 1) * sizeof(WCHAR));
+
+    RegSetValueExW(hLocaleKey,
+                   L"sGrouping",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szCurrencyGrouping[pGlobalData->nNumGrouping],
+                   (wcslen(szCurrencyGrouping[pGlobalData->nNumGrouping]) + 1) * sizeof(WCHAR));
+
+    RegSetValueExW(hLocaleKey,
+                   L"sList",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szNumListSep,
+                   (wcslen(pGlobalData->szNumListSep) + 1) * sizeof(WCHAR));
+
+    RegSetValueExW(hLocaleKey,
+                   L"sNativeDigits",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szNumNativeDigits,
+                   (wcslen(pGlobalData->szNumNativeDigits) + 1) * sizeof(WCHAR));
+
+    _itow(pGlobalData->nNumNegFormat,
+          szBuffer, DECIMAL_RADIX);
+    RegSetValueExW(hLocaleKey,
+                   L"iNegNumber",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szBuffer,
+                   (wcslen(szBuffer) + 1) * sizeof(WCHAR));
+
+    _itow(pGlobalData->nNumDigits,
+          szBuffer, DECIMAL_RADIX);
+    RegSetValueExW(hLocaleKey,
+                   L"iDigits",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szBuffer,
+                   (wcslen(szBuffer) + 1) * sizeof(WCHAR));
+
+    _itow(pGlobalData->nNumLeadingZero,
+          szBuffer, DECIMAL_RADIX);
+    RegSetValueExW(hLocaleKey,
+                   L"iLZero",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szBuffer,
+                   (wcslen(szBuffer) + 1) * sizeof(WCHAR));
+
+    _itow(pGlobalData->nNumMeasure,
+          szBuffer, DECIMAL_RADIX);
+    RegSetValueExW(hLocaleKey,
+                   L"iMeasure",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szBuffer,
+                   (wcslen(szBuffer) + 1) * sizeof(WCHAR));
+
+    _itow(pGlobalData->nNumShape,
+          szBuffer, DECIMAL_RADIX);
+    RegSetValueExW(hLocaleKey,
+                   L"NumShape",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szBuffer,
+                   (wcslen(szBuffer) + 1) * sizeof(WCHAR));
+
+    /* Currency */
+    RegSetValueExW(hLocaleKey,
+                   L"sCurrency",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szCurrSymbol,
+                   (wcslen(pGlobalData->szCurrSymbol) + 1) * sizeof(WCHAR));
+
+    RegSetValueExW(hLocaleKey,
+                   L"sMonDecimalSep",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szCurrDecimalSep,
+                   (wcslen(pGlobalData->szCurrDecimalSep) + 1) * sizeof(WCHAR));
+
+    RegSetValueExW(hLocaleKey,
+                   L"sMonThousandSep",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szCurrThousandSep,
+                   (wcslen(pGlobalData->szCurrThousandSep) + 1) * sizeof(WCHAR));
+
+    RegSetValueExW(hLocaleKey,
+                   L"sMonGrouping",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szCurrencyGrouping[pGlobalData->nCurrGrouping],
+                   (wcslen(szCurrencyGrouping[pGlobalData->nCurrGrouping]) + 1) * sizeof(WCHAR));
+
+    _itow(pGlobalData->nCurrPosFormat,
+          szBuffer, DECIMAL_RADIX);
+    RegSetValueExW(hLocaleKey,
+                   L"iCurrency",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szBuffer,
+                   (wcslen(szBuffer) + 1) * sizeof(WCHAR));
+
+    _itow(pGlobalData->nCurrNegFormat,
+          szBuffer, DECIMAL_RADIX);
+    RegSetValueExW(hLocaleKey,
+                   L"iNegCurr",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szBuffer,
+                   (wcslen(szBuffer) + 1) * sizeof(WCHAR));
+
+    _itow(pGlobalData->nCurrDigits,
+          szBuffer, DECIMAL_RADIX);
+    RegSetValueExW(hLocaleKey,
+                   L"iCurrDigits",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szBuffer,
+                   (wcslen(szBuffer) + 1) * sizeof(WCHAR));
+
+    /* Time */
+    RegSetValueExW(hLocaleKey,
+                   L"sTimeFormat",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szTimeFormat,
+                   (wcslen(pGlobalData->szTimeFormat) + 1) * sizeof(WCHAR));
+
+    RegSetValueExW(hLocaleKey,
+                   L"sTime",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szTimeSep,
+                   (wcslen(pGlobalData->szTimeSep) + 1) * sizeof(WCHAR));
+
+    RegSetValueExW(hLocaleKey,
+                   L"s1159",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szTimeAM,
+                   (wcslen(pGlobalData->szTimeAM) + 1) * sizeof(WCHAR));
+
+    RegSetValueExW(hLocaleKey,
+                   L"s2359",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szTimePM,
+                   (wcslen(pGlobalData->szTimePM) + 1) * sizeof(WCHAR));
+
+    _itow(pGlobalData->nTime,
+          szBuffer, DECIMAL_RADIX);
+    RegSetValueExW(hLocaleKey,
+                   L"iTime",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szBuffer,
+                   (wcslen(szBuffer) + 1) * sizeof(WCHAR));
+
+    _itow(pGlobalData->nTimePrefix,
+          szBuffer, DECIMAL_RADIX);
+    RegSetValueExW(hLocaleKey,
+                   L"iTimePrefix",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szBuffer,
+                   (wcslen(szBuffer) + 1) * sizeof(WCHAR));
+
+    _itow(pGlobalData->nTimeLeadingZero,
+          szBuffer, DECIMAL_RADIX);
+    RegSetValueExW(hLocaleKey,
+                   L"iTLZero",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szBuffer,
+                   (wcslen(szBuffer) + 1) * sizeof(WCHAR));
+
+    /* Date */
+    RegSetValueExW(hLocaleKey,
+                   L"sLongDate",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szLongDateFormat,
+                   (wcslen(pGlobalData->szLongDateFormat) + 1) * sizeof(WCHAR));
+
+    RegSetValueExW(hLocaleKey,
+                   L"sShortDate",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szShortDateFormat,
+                   (wcslen(pGlobalData->szShortDateFormat) + 1) * sizeof(WCHAR));
+
+    RegSetValueExW(hLocaleKey,
+                   L"sDate",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szDateSep,
+                   (wcslen(pGlobalData->szDateSep) + 1) * sizeof(WCHAR));
+
+    _itow(pGlobalData->nFirstDayOfWeek,
+          szBuffer, DECIMAL_RADIX);
+    RegSetValueExW(hLocaleKey,
+                   L"iFirstDayOfWeek",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szBuffer,
+                   (wcslen(szBuffer) + 1) * sizeof(WCHAR));
+
+    _itow(pGlobalData->nFirstWeekOfYear,
+          szBuffer, DECIMAL_RADIX);
+    RegSetValueExW(hLocaleKey,
+                   L"iFirstWeekOfYear",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szBuffer,
+                   (wcslen(szBuffer) + 1) * sizeof(WCHAR));
+
+    _itow(pGlobalData->nDate,
+          szBuffer, DECIMAL_RADIX);
+    RegSetValueExW(hLocaleKey,
+                   L"iDate",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szBuffer,
+                   (wcslen(szBuffer) + 1) * sizeof(WCHAR));
+
+    _itow(pGlobalData->nCalendarType,
+          szBuffer, DECIMAL_RADIX);
+    RegSetValueExW(hLocaleKey,
+                   L"iCalendarType",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szBuffer,
+                   (wcslen(szBuffer) + 1) * sizeof(WCHAR));
+
+    /* Misc */
+    RegSetValueExW(hLocaleKey,
+                   L"sCountry",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szMiscCountry,
+                   (wcslen(pGlobalData->szMiscCountry) + 1) * sizeof(WCHAR));
+
+    RegSetValueExW(hLocaleKey,
+                   L"sLanguage",
+                   0,
+                   REG_SZ,
+                   (PBYTE)pGlobalData->szMiscLanguage,
+                   (wcslen(pGlobalData->szMiscLanguage) + 1) * sizeof(WCHAR));
+
+    _itow(pGlobalData->nMiscCountry,
+          szBuffer, DECIMAL_RADIX);
+    RegSetValueExW(hLocaleKey,
+                   L"iCountry",
+                   0,
+                   REG_SZ,
+                   (PBYTE)szBuffer,
+                   (wcslen(szBuffer) + 1) * sizeof(WCHAR));
 }
 
 
@@ -343,14 +1093,8 @@ VOID
 SaveCurrentLocale(
     PGLOBALDATA pGlobalData)
 {
-    HKEY localeKey;
+    HKEY hLocaleKey;
     DWORD ret;
-    WCHAR value[9];
-    DWORD valuesize;
-    DWORD i;
-
-    wsprintf(value, L"%08x", (DWORD)pGlobalData->lcid);
-    valuesize = (wcslen(value) + 1) * sizeof(WCHAR);
 
     if (pGlobalData->bApplyToDefaultUser)
     {
@@ -358,69 +1102,39 @@ SaveCurrentLocale(
                             L".DEFAULT\\Control Panel\\International",
                             0,
                             KEY_WRITE,
-                            &localeKey);
+                            &hLocaleKey);
         if (ret != ERROR_SUCCESS)
         {
             PrintErrorMsgBox(IDS_ERROR_DEF_INT_KEY_REG);
             return;
         }
 
-        ret = RegSetValueExW(localeKey, L"Locale", 0, REG_SZ, (PBYTE)value, valuesize);
-        if (ret != ERROR_SUCCESS)
-        {
-            RegCloseKey(localeKey);
-            PrintErrorMsgBox(IDS_ERROR_INT_KEY_REG);
-            return;
-        }
-
-        for (i = 0; i < pGlobalData->dwLocaleCount; i++)
-        {
-            RegSetValueExW(localeKey,
-                           LocaleKeyData[i].pKeyName,
-                           0,
-                           REG_SZ,
-                           (PBYTE)pGlobalData->pLocaleArray[i],
-                           (wcslen(pGlobalData->pLocaleArray[i]) + 1) * sizeof(WCHAR));
-        }
+        SaveUserLocale(pGlobalData, hLocaleKey);
 
         /* Flush and close the locale key */
-        RegFlushKey(localeKey);
-        RegCloseKey(localeKey);
-    }
-
-    ret = RegOpenKeyExW(HKEY_CURRENT_USER, L"Control Panel\\International",
-                        0, KEY_READ | KEY_WRITE, &localeKey);
-    if (ret != ERROR_SUCCESS)
-    {
-        PrintErrorMsgBox(IDS_ERROR_INT_KEY_REG);
-        return;
+        RegFlushKey(hLocaleKey);
+        RegCloseKey(hLocaleKey);
     }
 
-    ret = RegSetValueExW(localeKey, L"Locale", 0, REG_SZ, (PBYTE)value, valuesize);
+    ret = RegOpenKeyExW(HKEY_CURRENT_USER,
+                        L"Control Panel\\International",
+                        0,
+                        KEY_WRITE,
+                        &hLocaleKey);
     if (ret != ERROR_SUCCESS)
     {
-        RegCloseKey(localeKey);
         PrintErrorMsgBox(IDS_ERROR_INT_KEY_REG);
         return;
     }
 
-    for (i = 0; i < pGlobalData->dwLocaleCount; i++)
-    {
-        RegSetValueExW(localeKey,
-                       LocaleKeyData[i].pKeyName,
-                       0,
-                       REG_SZ,
-                       (PBYTE)pGlobalData->pLocaleArray[i],
-                       (wcslen(pGlobalData->pLocaleArray[i]) + 1) * sizeof(WCHAR));
-    }
+    SaveUserLocale(pGlobalData, hLocaleKey);
 
     /* Flush and close the locale key */
-    RegFlushKey(localeKey);
-    RegCloseKey(localeKey);
+    RegFlushKey(hLocaleKey);
+    RegCloseKey(hLocaleKey);
 
     /* Set the new locale for the current process */
-    NtSetDefaultLocale(TRUE, pGlobalData->lcid);
-
+    NtSetDefaultLocale(TRUE, pGlobalData->UserLCID);
 }
 
 /* Location enumerate procedure */
@@ -576,6 +1290,62 @@ VerifyUnattendLCID(HWND hwndDlg)
 }
 
 
+static
+VOID
+InitPropSheetPage(
+    PROPSHEETPAGEW *psp,
+    WORD idDlg,
+    DLGPROC DlgProc,
+    PGLOBALDATA pGlobalData)
+{
+    ZeroMemory(psp, sizeof(PROPSHEETPAGEW));
+    psp->dwSize = sizeof(PROPSHEETPAGEW);
+    psp->dwFlags = PSP_DEFAULT;
+    psp->hInstance = hApplet;
+    psp->pszTemplate = MAKEINTRESOURCE(idDlg);
+    psp->pfnDlgProc = DlgProc;
+    psp->lParam = (LPARAM)pGlobalData;
+}
+
+
+INT_PTR
+APIENTRY
+CustomizeLocalePropertySheet(
+    HWND hwndDlg,
+    PGLOBALDATA pGlobalData)
+{
+    PROPSHEETPAGEW PsPage[NUM_SHEETS + 1];
+    PROPSHEETHEADERW psh;
+    WCHAR Caption[MAX_STR_SIZE];
+
+    LoadStringW(hApplet, IDS_CUSTOMIZE_TITLE, Caption, sizeof(Caption) / sizeof(TCHAR));
+
+    ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
+    psh.dwSize = sizeof(PROPSHEETHEADER);
+    psh.dwFlags =  PSH_PROPSHEETPAGE | PSH_USECALLBACK;
+    psh.hwndParent = hwndDlg;
+    psh.hInstance = hApplet;
+    psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_CPLICON));
+    psh.pszCaption = Caption;
+    psh.nPages = (sizeof(PsPage) / sizeof(PROPSHEETPAGE)) - 1;
+    psh.nStartPage = 0;
+    psh.ppsp = PsPage;
+
+    InitPropSheetPage(&PsPage[0], IDD_NUMBERSPAGE, NumbersPageProc, pGlobalData);
+    InitPropSheetPage(&PsPage[1], IDD_CURRENCYPAGE, CurrencyPageProc, pGlobalData);
+    InitPropSheetPage(&PsPage[2], IDD_TIMEPAGE, TimePageProc, pGlobalData);
+    InitPropSheetPage(&PsPage[3], IDD_DATEPAGE, DatePageProc, pGlobalData);
+
+    if (IsSortPageNeeded(pGlobalData->UserLCID))
+    {
+        psh.nPages++;
+        InitPropSheetPage(&PsPage[4], IDD_SORTPAGE, SortPageProc, pGlobalData);
+    }
+
+    return PropertySheetW(&psh);
+}
+
+
 /* Property page dialog callback */
 INT_PTR CALLBACK
 GeneralPageProc(HWND hwndDlg,
@@ -676,7 +1446,12 @@ GeneralPageProc(HWND hwndDlg,
                     break;
 
                 case IDC_SETUP_BUTTON:
-                    SetupApplet(GetParent(hwndDlg), pGlobalData);
+                    if (CustomizeLocalePropertySheet(GetParent(hwndDlg), pGlobalData) > 0)
+                    {
+                        UpdateLocaleSample(hwndDlg, pGlobalData);
+                        pGlobalData->fUserLocaleChanged = TRUE;
+                        PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
+                    }
                     break;
             }
             break;
@@ -704,17 +1479,10 @@ GeneralPageProc(HWND hwndDlg,
                         pGlobalData->fGeoIdChanged = FALSE;
                     }
 
-                    AddNewKbLayoutsByLcid(pGlobalData->lcid);
+                    AddNewKbLayoutsByLcid(pGlobalData->UserLCID);
                 }
             }
             break;
-
-        case WM_DESTROY:
-            if (pGlobalData)
-            {
-                FreeCurrentLocale(pGlobalData);
-            }
-            break;
     }
 
     return FALSE;