/* * 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 PrintDefaultLocale * * How to compile: "cl -DUNICODE -D_UNICODE deflocale.c user32.lib advapi32.lib" */ #include #include #include 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); } } }