| /* |
| * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| /* |
| * |
| * |
| * A simple tool to output all the installed locales on a Windows machine, and |
| * corresponding Java default locale/file.encoding using PrintDefaultLocale |
| * |
| * WARNING: This tool directly modifies the locale info in the Windows registry. |
| * It may not work with the Windows versions after Windows XP SP2. Also, |
| * if the test did not complete or was manually killed, you will need to reset |
| * the user default locale in the Control Panel manually. This executable has |
| * to be run with the "Administrator" privilege. |
| * |
| * Usage: "deflocale.exe <java launcher> PrintDefaultLocale |
| * |
| * How to compile: "cl -DUNICODE -D_UNICODE deflocale.c user32.lib advapi32.lib" |
| */ |
| #include <windows.h> |
| #include <stdio.h> |
| #include <memory.h> |
| |
| wchar_t* launcher; |
| wchar_t szBuffer[MAX_PATH]; |
| LCID LCIDArray[1024]; |
| int numLCIDs = 0; |
| BOOL isWin7orUp = FALSE; |
| |
| // for Windows 7 |
| BOOL (WINAPI * pfnEnumSystemLocalesEx)(LPVOID, DWORD, LPARAM, LPVOID); |
| BOOL (WINAPI * pfnEnumUILanguages)(LPVOID, DWORD, LPARAM); |
| LCID (WINAPI * pfnLocaleNameToLCID)(LPCWSTR, DWORD); |
| int (WINAPI * pfnLCIDToLocaleName)(LCID, LPWSTR, int, DWORD); |
| wchar_t* LocaleNamesArray[1024]; |
| wchar_t* UILangNamesArray[1024]; |
| int numLocaleNames = 0; |
| int numUILangNames = 0; |
| |
| void launchAndWait() { |
| STARTUPINFO si; |
| PROCESS_INFORMATION pi; |
| |
| ZeroMemory(&si, sizeof(si)); |
| si.cb = sizeof(si); |
| ZeroMemory(&pi, sizeof(pi)); |
| if (CreateProcess(NULL, launcher, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)==0) { |
| wprintf(L"CreateProcess failed with the error code: %x\n", GetLastError()); |
| } |
| |
| WaitForSingleObject( pi.hProcess, INFINITE ); |
| } |
| |
| void testLocale(int anLCID, wchar_t* pName) { |
| HKEY hk; |
| |
| if (pName != NULL && wcslen(pName) == 2) { |
| // ignore language only locale. |
| return; |
| } |
| |
| wprintf(L"\n"); |
| wprintf(L"OS Locale (lcid: %x", anLCID); |
| if (pName != NULL) { |
| wprintf(L", name: %s", pName); |
| } |
| GetLocaleInfo(anLCID, LOCALE_SENGLANGUAGE, szBuffer, MAX_PATH); |
| wprintf(L"): %s (", szBuffer); |
| GetLocaleInfo(anLCID, LOCALE_SENGCOUNTRY, szBuffer, MAX_PATH); |
| wprintf(L"%s) - ", szBuffer); |
| GetLocaleInfo(anLCID, LOCALE_IDEFAULTANSICODEPAGE, szBuffer, MAX_PATH); |
| wprintf(L"%s\n", szBuffer); |
| fflush(0); |
| |
| if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Control Panel\\International", 0, KEY_READ | KEY_WRITE, &hk) == ERROR_SUCCESS) { |
| wchar_t originalLocale[16]; |
| wchar_t testLocale[16]; |
| wchar_t* pKeyName; |
| DWORD cb = sizeof(originalLocale); |
| DWORD cbTest; |
| |
| if (isWin7orUp) { |
| pKeyName = L"LocaleName"; |
| wcscpy(testLocale, pName); |
| cbTest = wcslen(pName) * sizeof(wchar_t); |
| } else { |
| pKeyName = L"Locale"; |
| swprintf(testLocale, L"%08x", anLCID); |
| cbTest = sizeof(wchar_t) * 8; |
| } |
| |
| RegQueryValueEx(hk, pKeyName, 0, 0, (LPBYTE)originalLocale, &cb); |
| RegSetValueEx(hk, pKeyName, 0, REG_SZ, (LPBYTE)testLocale, cbTest ); |
| launchAndWait(); |
| RegSetValueEx(hk, pKeyName, 0, REG_SZ, (LPBYTE)originalLocale, cb); |
| RegCloseKey(hk); |
| } |
| } |
| |
| void testUILang(wchar_t* pName) { |
| HKEY hk; |
| |
| wprintf(L"\n"); |
| wprintf(L"OS UI Language (name: %s)\n", pName); |
| fflush(0); |
| |
| if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Control Panel\\Desktop", 0, KEY_READ | KEY_WRITE, &hk) == ERROR_SUCCESS) { |
| wchar_t originalUILang[16]; |
| wchar_t testUILang[16]; |
| wchar_t* pKeyName; |
| DWORD cb = sizeof(originalUILang); |
| DWORD cbTest = wcslen(pName) * sizeof(wchar_t); |
| |
| pKeyName = L"PreferredUILanguages"; |
| wcscpy(testUILang, pName); |
| cbTest = wcslen(pName) * sizeof(wchar_t); |
| |
| RegQueryValueEx(hk, pKeyName, 0, 0, (LPBYTE)originalUILang, &cb); |
| RegSetValueEx(hk, pKeyName, 0, REG_SZ, (LPBYTE)testUILang, cbTest); |
| launchAndWait(); |
| RegSetValueEx(hk, pKeyName, 0, REG_SZ, (LPBYTE)originalUILang, cb); |
| RegCloseKey(hk); |
| } |
| } |
| |
| BOOL CALLBACK EnumLocalesProc(LPWSTR lpLocaleStr) { |
| swscanf(lpLocaleStr, L"%08x", &LCIDArray[numLCIDs]); |
| numLCIDs ++; |
| |
| return TRUE; |
| } |
| |
| BOOL CALLBACK EnumLocalesProcEx(LPWSTR lpLocaleStr, DWORD flags, LPARAM lp) { |
| wchar_t* pName = malloc((wcslen(lpLocaleStr) + 1) * sizeof(wchar_t *)); |
| wcscpy(pName, lpLocaleStr); |
| LocaleNamesArray[numLocaleNames] = pName; |
| numLocaleNames ++; |
| |
| return TRUE; |
| } |
| |
| BOOL CALLBACK EnumUILanguagesProc(LPWSTR lpUILangStr, LPARAM lp) { |
| wchar_t* pName = malloc((wcslen(lpUILangStr) + 1) * sizeof(wchar_t *)); |
| wcscpy(pName, lpUILangStr); |
| UILangNamesArray[numUILangNames] = pName; |
| numUILangNames ++; |
| |
| return TRUE; |
| } |
| |
| int sortLCIDs(LCID * pLCID1, LCID * pLCID2) { |
| if (*pLCID1 < *pLCID2) return (-1); |
| if (*pLCID1 == *pLCID2) return 0; |
| return 1; |
| } |
| |
| int sortLocaleNames(wchar_t** ppName1, wchar_t** ppName2) { |
| LCID l1 = pfnLocaleNameToLCID(*ppName1, 0); |
| LCID l2 = pfnLocaleNameToLCID(*ppName2, 0); |
| return sortLCIDs(&l1, &l2); |
| } |
| |
| int main(int argc, char** argv) { |
| OSVERSIONINFO osvi; |
| LPWSTR commandline = GetCommandLine(); |
| int i; |
| |
| osvi.dwOSVersionInfoSize = sizeof(osvi); |
| GetVersionEx(&osvi); |
| wprintf(L"# OSVersionInfo\n"); |
| wprintf(L"# MajorVersion: %d\n", osvi.dwMajorVersion); |
| wprintf(L"# MinorVersion: %d\n", osvi.dwMinorVersion); |
| wprintf(L"# BuildNumber: %d\n", osvi.dwBuildNumber); |
| wprintf(L"# CSDVersion: %s\n", osvi.szCSDVersion); |
| wprintf(L"\n"); |
| fflush(0); |
| |
| launcher = wcschr(commandline, L' ')+1; |
| while (*launcher == L' ') { |
| launcher++; |
| } |
| |
| isWin7orUp = (osvi.dwMajorVersion > 6) || |
| (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion >= 1); |
| |
| if (!isWin7orUp) { |
| // Enumerate locales |
| EnumSystemLocales(EnumLocalesProc, LCID_INSTALLED); |
| |
| // Sort LCIDs |
| qsort(LCIDArray, numLCIDs, sizeof(LCID), (void *)sortLCIDs); |
| } else { |
| // For Windows 7, use "LocaleName" registry key for the user locale |
| // as they seem to switch from "Locale". |
| HMODULE hmod = GetModuleHandle(L"kernel32"); |
| *(FARPROC*)&pfnEnumSystemLocalesEx = |
| GetProcAddress(hmod, "EnumSystemLocalesEx"); |
| *(FARPROC*)&pfnEnumUILanguages = |
| GetProcAddress(hmod, "EnumUILanguagesW"); |
| *(FARPROC*)&pfnLocaleNameToLCID = |
| GetProcAddress(hmod, "LocaleNameToLCID"); |
| *(FARPROC*)&pfnLCIDToLocaleName = |
| GetProcAddress(hmod, "LCIDToLocaleName"); |
| if (pfnEnumSystemLocalesEx != NULL && |
| pfnEnumUILanguages != NULL && |
| pfnLocaleNameToLCID != NULL && |
| pfnLCIDToLocaleName != NULL) { |
| // Enumerate locales |
| pfnEnumSystemLocalesEx(EnumLocalesProcEx, |
| 1, // LOCALE_WINDOWS |
| (LPARAM)NULL, NULL); |
| // Enumerate UI Languages. |
| pfnEnumUILanguages(EnumUILanguagesProc, |
| 0x8, // MUI_LANGUAGE_NAME |
| (LPARAM)NULL); |
| } else { |
| wprintf(L"Could not get needed entry points. quitting.\n"); |
| exit(-1); |
| } |
| |
| // Sort LocaleNames |
| qsort(LocaleNamesArray, numLocaleNames, |
| sizeof(wchar_t*), (void *)sortLocaleNames); |
| qsort(UILangNamesArray, numUILangNames, |
| sizeof(wchar_t*), (void *)sortLocaleNames); |
| } |
| |
| // Execute enumeration of Java default locales |
| if (isWin7orUp) { |
| for (i = 0; i < numLocaleNames; i ++) { |
| testLocale(pfnLocaleNameToLCID(LocaleNamesArray[i], 0), |
| LocaleNamesArray[i]); |
| } |
| for (i = 0; i < numUILangNames; i ++) { |
| testUILang(UILangNamesArray[i]); |
| } |
| } else { |
| for (i = 0; i < numLCIDs; i ++) { |
| testLocale(LCIDArray[i], NULL); |
| } |
| } |
| } |