1/* 2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23/* 24 * 25 * 26 * A simple tool to output all the installed locales on a Windows machine, and 27 * corresponding Java default locale/file.encoding using PrintDefaultLocale 28 * 29 * WARNING: This tool directly modifies the locale info in the Windows registry. 30 * It may not work with the Windows versions after Windows XP SP2. Also, 31 * if the test did not complete or was manually killed, you will need to reset 32 * the user default locale in the Control Panel manually. This executable has 33 * to be run with the "Administrator" privilege. 34 * 35 * Usage: "deflocale.exe <java launcher> PrintDefaultLocale 36 * 37 * How to compile: "cl -DUNICODE -D_UNICODE deflocale.c user32.lib advapi32.lib" 38 */ 39#include <windows.h> 40#include <stdio.h> 41#include <memory.h> 42 43wchar_t* launcher; 44wchar_t szBuffer[MAX_PATH]; 45LCID LCIDArray[1024]; 46int numLCIDs = 0; 47BOOL isWin7orUp = FALSE; 48 49// for Windows 7 50BOOL (WINAPI * pfnEnumSystemLocalesEx)(LPVOID, DWORD, LPARAM, LPVOID); 51BOOL (WINAPI * pfnEnumUILanguages)(LPVOID, DWORD, LPARAM); 52LCID (WINAPI * pfnLocaleNameToLCID)(LPCWSTR, DWORD); 53int (WINAPI * pfnLCIDToLocaleName)(LCID, LPWSTR, int, DWORD); 54wchar_t* LocaleNamesArray[1024]; 55wchar_t* UILangNamesArray[1024]; 56int numLocaleNames = 0; 57int numUILangNames = 0; 58 59void launchAndWait() { 60 STARTUPINFO si; 61 PROCESS_INFORMATION pi; 62 63 ZeroMemory(&si, sizeof(si)); 64 si.cb = sizeof(si); 65 ZeroMemory(&pi, sizeof(pi)); 66 if (CreateProcess(NULL, launcher, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)==0) { 67 wprintf(L"CreateProcess failed with the error code: %x\n", GetLastError()); 68 } 69 70 WaitForSingleObject( pi.hProcess, INFINITE ); 71} 72 73void testLocale(int anLCID, wchar_t* pName) { 74 HKEY hk; 75 76 if (pName != NULL && wcslen(pName) == 2) { 77 // ignore language only locale. 78 return; 79 } 80 81 wprintf(L"\n"); 82 wprintf(L"OS Locale (lcid: %x", anLCID); 83 if (pName != NULL) { 84 wprintf(L", name: %s", pName); 85 } 86 GetLocaleInfo(anLCID, LOCALE_SENGLANGUAGE, szBuffer, MAX_PATH); 87 wprintf(L"): %s (", szBuffer); 88 GetLocaleInfo(anLCID, LOCALE_SENGCOUNTRY, szBuffer, MAX_PATH); 89 wprintf(L"%s) - ", szBuffer); 90 GetLocaleInfo(anLCID, LOCALE_IDEFAULTANSICODEPAGE, szBuffer, MAX_PATH); 91 wprintf(L"%s\n", szBuffer); 92 fflush(0); 93 94 if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Control Panel\\International", 0, KEY_READ | KEY_WRITE, &hk) == ERROR_SUCCESS) { 95 wchar_t originalLocale[16]; 96 wchar_t testLocale[16]; 97 wchar_t* pKeyName; 98 DWORD cb = sizeof(originalLocale); 99 DWORD cbTest; 100 101 if (isWin7orUp) { 102 pKeyName = L"LocaleName"; 103 wcscpy(testLocale, pName); 104 cbTest = wcslen(pName) * sizeof(wchar_t); 105 } else { 106 pKeyName = L"Locale"; 107 swprintf(testLocale, L"%08x", anLCID); 108 cbTest = sizeof(wchar_t) * 8; 109 } 110 111 RegQueryValueEx(hk, pKeyName, 0, 0, (LPBYTE)originalLocale, &cb); 112 RegSetValueEx(hk, pKeyName, 0, REG_SZ, (LPBYTE)testLocale, cbTest ); 113 launchAndWait(); 114 RegSetValueEx(hk, pKeyName, 0, REG_SZ, (LPBYTE)originalLocale, cb); 115 RegCloseKey(hk); 116 } 117} 118 119void testUILang(wchar_t* pName) { 120 HKEY hk; 121 122 wprintf(L"\n"); 123 wprintf(L"OS UI Language (name: %s)\n", pName); 124 fflush(0); 125 126 if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Control Panel\\Desktop", 0, KEY_READ | KEY_WRITE, &hk) == ERROR_SUCCESS) { 127 wchar_t originalUILang[16]; 128 wchar_t testUILang[16]; 129 wchar_t* pKeyName; 130 DWORD cb = sizeof(originalUILang); 131 DWORD cbTest = wcslen(pName) * sizeof(wchar_t); 132 133 pKeyName = L"PreferredUILanguages"; 134 wcscpy(testUILang, pName); 135 cbTest = wcslen(pName) * sizeof(wchar_t); 136 137 RegQueryValueEx(hk, pKeyName, 0, 0, (LPBYTE)originalUILang, &cb); 138 RegSetValueEx(hk, pKeyName, 0, REG_SZ, (LPBYTE)testUILang, cbTest); 139 launchAndWait(); 140 RegSetValueEx(hk, pKeyName, 0, REG_SZ, (LPBYTE)originalUILang, cb); 141 RegCloseKey(hk); 142 } 143} 144 145BOOL CALLBACK EnumLocalesProc(LPWSTR lpLocaleStr) { 146 swscanf(lpLocaleStr, L"%08x", &LCIDArray[numLCIDs]); 147 numLCIDs ++; 148 149 return TRUE; 150} 151 152BOOL CALLBACK EnumLocalesProcEx(LPWSTR lpLocaleStr, DWORD flags, LPARAM lp) { 153 wchar_t* pName = malloc((wcslen(lpLocaleStr) + 1) * sizeof(wchar_t *)); 154 wcscpy(pName, lpLocaleStr); 155 LocaleNamesArray[numLocaleNames] = pName; 156 numLocaleNames ++; 157 158 return TRUE; 159} 160 161BOOL CALLBACK EnumUILanguagesProc(LPWSTR lpUILangStr, LPARAM lp) { 162 wchar_t* pName = malloc((wcslen(lpUILangStr) + 1) * sizeof(wchar_t *)); 163 wcscpy(pName, lpUILangStr); 164 UILangNamesArray[numUILangNames] = pName; 165 numUILangNames ++; 166 167 return TRUE; 168} 169 170int sortLCIDs(LCID * pLCID1, LCID * pLCID2) { 171 if (*pLCID1 < *pLCID2) return (-1); 172 if (*pLCID1 == *pLCID2) return 0; 173 return 1; 174} 175 176int sortLocaleNames(wchar_t** ppName1, wchar_t** ppName2) { 177 LCID l1 = pfnLocaleNameToLCID(*ppName1, 0); 178 LCID l2 = pfnLocaleNameToLCID(*ppName2, 0); 179 return sortLCIDs(&l1, &l2); 180} 181 182int main(int argc, char** argv) { 183 OSVERSIONINFO osvi; 184 LPWSTR commandline = GetCommandLine(); 185 int i; 186 187 osvi.dwOSVersionInfoSize = sizeof(osvi); 188 GetVersionEx(&osvi); 189 wprintf(L"# OSVersionInfo\n"); 190 wprintf(L"# MajorVersion: %d\n", osvi.dwMajorVersion); 191 wprintf(L"# MinorVersion: %d\n", osvi.dwMinorVersion); 192 wprintf(L"# BuildNumber: %d\n", osvi.dwBuildNumber); 193 wprintf(L"# CSDVersion: %s\n", osvi.szCSDVersion); 194 wprintf(L"\n"); 195 fflush(0); 196 197 launcher = wcschr(commandline, L' ')+1; 198 while (*launcher == L' ') { 199 launcher++; 200 } 201 202 isWin7orUp = (osvi.dwMajorVersion > 6) || 203 (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion >= 1); 204 205 if (!isWin7orUp) { 206 // Enumerate locales 207 EnumSystemLocales(EnumLocalesProc, LCID_INSTALLED); 208 209 // Sort LCIDs 210 qsort(LCIDArray, numLCIDs, sizeof(LCID), (void *)sortLCIDs); 211 } else { 212 // For Windows 7, use "LocaleName" registry key for the user locale 213 // as they seem to switch from "Locale". 214 HMODULE hmod = GetModuleHandle(L"kernel32"); 215 *(FARPROC*)&pfnEnumSystemLocalesEx = 216 GetProcAddress(hmod, "EnumSystemLocalesEx"); 217 *(FARPROC*)&pfnEnumUILanguages = 218 GetProcAddress(hmod, "EnumUILanguagesW"); 219 *(FARPROC*)&pfnLocaleNameToLCID = 220 GetProcAddress(hmod, "LocaleNameToLCID"); 221 *(FARPROC*)&pfnLCIDToLocaleName = 222 GetProcAddress(hmod, "LCIDToLocaleName"); 223 if (pfnEnumSystemLocalesEx != NULL && 224 pfnEnumUILanguages != NULL && 225 pfnLocaleNameToLCID != NULL && 226 pfnLCIDToLocaleName != NULL) { 227 // Enumerate locales 228 pfnEnumSystemLocalesEx(EnumLocalesProcEx, 229 1, // LOCALE_WINDOWS 230 (LPARAM)NULL, NULL); 231 // Enumerate UI Languages. 232 pfnEnumUILanguages(EnumUILanguagesProc, 233 0x8, // MUI_LANGUAGE_NAME 234 (LPARAM)NULL); 235 } else { 236 wprintf(L"Could not get needed entry points. quitting.\n"); 237 exit(-1); 238 } 239 240 // Sort LocaleNames 241 qsort(LocaleNamesArray, numLocaleNames, 242 sizeof(wchar_t*), (void *)sortLocaleNames); 243 qsort(UILangNamesArray, numUILangNames, 244 sizeof(wchar_t*), (void *)sortLocaleNames); 245 } 246 247 // Execute enumeration of Java default locales 248 if (isWin7orUp) { 249 for (i = 0; i < numLocaleNames; i ++) { 250 testLocale(pfnLocaleNameToLCID(LocaleNamesArray[i], 0), 251 LocaleNamesArray[i]); 252 } 253 for (i = 0; i < numUILangNames; i ++) { 254 testUILang(UILangNamesArray[i]); 255 } 256 } else { 257 for (i = 0; i < numLCIDs; i ++) { 258 testLocale(LCIDArray[i], NULL); 259 } 260 } 261} 262