Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1457 lines
46 KiB

  1. //=======================================================================
  2. //
  3. // Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
  4. //
  5. // File: osdet.cpp
  6. //
  7. // Description:
  8. //
  9. // Ported to lib from V3 SLM DLL sources
  10. //
  11. //=======================================================================
  12. #include <windows.h>
  13. #include <wuiutest.h>
  14. #include <tchar.h>
  15. #include <osdet.h>
  16. #include <logging.h>
  17. #include <iucommon.h>
  18. #include "wusafefn.h"
  19. #include<MISTSAFE.h>
  20. // Forwared Declarations
  21. static LANGID CorrectGetSystemDefaultLangID(BOOL& bIsNT4, BOOL& bIsW95);
  22. static LANGID CorrectGetUserDefaultLangID(BOOL& bIsNT4, BOOL& bIsW95);
  23. static WORD CorrectGetACP(void);
  24. static WORD CorrectGetOEMCP(void);
  25. static LANGID MapLangID(LANGID langid);
  26. static bool FIsNECMachine();
  27. static int aton(LPCTSTR ptr);
  28. static int atoh(LPCTSTR ptr);
  29. //
  30. // Constants and defines
  31. //
  32. const LANGID LANGID_ENGLISH = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); // 0x0409
  33. const LANGID LANGID_GREEK = MAKELANGID(LANG_GREEK, SUBLANG_DEFAULT); // 0x0408
  34. const LANGID LANGID_JAPANESE = MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT); // 0x0411
  35. const LANGID LANGID_ARABIC = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA); // 0x0401
  36. const LANGID LANGID_HEBREW = MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT); // 0x040D
  37. const LANGID LANGID_THAI = MAKELANGID(LANG_THAI, SUBLANG_DEFAULT); // 0x041E
  38. const TCHAR Win98_REGPATH_MACHLCID[] = _T("Control Panel\\Desktop\\ResourceLocale");
  39. const TCHAR REGPATH_CODEPAGE[] = _T("SYSTEM\\CurrentControlSet\\Control\\Nls\\CodePage");
  40. const TCHAR REGKEY_OEMCP[] = _T("OEMCP");
  41. const TCHAR REGKEY_ACP[] = _T("ACP");
  42. const TCHAR REGKEY_LOCALE[] = _T("Locale");
  43. const TCHAR REGKEY_IE[] = _T("Software\\Microsoft\\Internet Explorer");
  44. const TCHAR REGKEY_VERSION[] = _T("Version");
  45. const TCHAR REGKEY_CP_INTERNATIONAL[] = _T(".DEFAULT\\Control Panel\\International");
  46. const TCHAR REGKEY_CP_RESOURCELOCAL[] = _T("Control Panel\\Desktop\\ResourceLocale");
  47. const TCHAR KERNEL32_DLL[] = _T("kernel32.dll");
  48. const WORD CODEPAGE_ARABIC = 1256;
  49. const WORD CODEPAGE_HEBREW = 1255;
  50. const WORD CODEPAGE_THAI = 874;
  51. const WORD CODEPAGE_GREEK_MS = 737;
  52. const WORD CODEPAGE_GREEK_IBM = 869;
  53. // ISO code for Greek OS's on Windows 98 ONLY.
  54. const TCHAR ISOCODE_GREEK_MS[] = _T("el_MS");
  55. const TCHAR ISOCODE_GREEK_IBM[] = _T("el_IBM");
  56. // Registry keys to determine NEC machines
  57. const TCHAR NT5_REGPATH_MACHTYPE[] = _T("HARDWARE\\DESCRIPTION\\System");
  58. const TCHAR NT5_REGKEY_MACHTYPE[] = _T("Identifier");
  59. const TCHAR REGVAL_MACHTYPE_AT[] = _T("AT/AT COMPATIBLE");
  60. const TCHAR REGVAL_MACHTYPE_NEC[] = _T("NEC PC-98");
  61. const TCHAR REGVAL_GREEK_IBM[] = _T("869");
  62. // Platform strings
  63. const TCHAR SZ_PLAT_WIN95[] = _T("w95");
  64. const TCHAR SZ_PLAT_WIN98[] = _T("w98");
  65. const TCHAR SZ_PLAT_WINME[] = _T("mil");
  66. const TCHAR SZ_PLAT_NT4[] = _T("NT4");
  67. const TCHAR SZ_PLAT_W2K[] = _T("W2k");
  68. const TCHAR SZ_PLAT_WHISTLER[] = _T("Whi");
  69. const TCHAR SZ_PLAT_UNKNOWN[] = _T("unk");
  70. #define LOOKUP_OEMID(keybdid) HIBYTE(LOWORD((keybdid)))
  71. #define PC98_KEYBOARD_ID 0x0D
  72. //
  73. // Globals
  74. //
  75. //
  76. // We derive this from WINVER >= 0x0500 section of winnls.h
  77. //
  78. typedef LANGID (WINAPI * PFN_GetUserDefaultUILanguage) (void);
  79. typedef LANGID (WINAPI * PFN_GetSystemDefaultUILanguage) (void);
  80. typedef struct
  81. {
  82. LANGID langidUser;
  83. TCHAR * pszISOCode;
  84. } USER_LANGID;
  85. typedef struct
  86. {
  87. LANGID langidMachine;
  88. TCHAR * pszDefaultISOCode;
  89. int cElems;
  90. const USER_LANGID * grLangidUser;
  91. } MACH_LANGID;
  92. // We give a Japanese NEC machine its own ISO code.
  93. #define LANGID_JAPANESE 0x0411
  94. #define ISOCODE_NEC _T("nec")
  95. #define ISOCODE_EN _T("en")
  96. #define grsize(langid) (sizeof(gr##langid) / sizeof(USER_LANGID))
  97. // These are all the user langids associated with a particular machine.
  98. // NTRAID#NTBUG9-220063-2000/12/13-waltw 220063 IU: Specify mappings between GetSystemDefaultUILanguage LANGID and ISO/639/1988
  99. // From Industry Update XML Schema.doc
  100. // 3.1 Language Codes
  101. // The languages are defined by ISO 639. They are represented by lowercase 2 letter symbols such as "en" for English, "fr" for French etc.
  102. //
  103. // 3.2 Country Codes
  104. // The country codes are defined in ISO 3166-1, using the Alpha-2 representation (two letter symbols).
  105. //
  106. // 3.3 Representation in Industry Update
  107. // Industry Update uses the RFC 1766 standard to manage the representation of language+locale symbols.
  108. // 3.3.1 Simple Case - Language Alone
  109. // When no regional flavor is considered for a language, or when it pertains to the "standard" version of the language, such as Portuguese as spoken in Portugal, it uses a straight ISO 639 symbol:
  110. // en, fr, de
  111. //
  112. // 3.3.2 Regional Variants
  113. // Managed by the RFCThe lowercase version of the Alpha-2 ISO 3166-1 country (or region) code is hyphenated to the language code, e.g. en-us, en-ca, fr-be, fr-ca, zh-hk, zh-tw�
  114. const USER_LANGID gr0404[] = {{0x0804,_T("zh-CN")},{0x1004,_T("zh-CN")}};
  115. const USER_LANGID gr0407[] = {{0x0c07,_T("de-AT")},{0x0807,_T("de-CH")}};
  116. const USER_LANGID gr0409[] = {{0x1c09,_T("en-ZA")},{0x0809,_T("en-GB")},{0x0c09,_T("en-AU")},{0x1009,_T("en-CA")},
  117. {0x1409,_T("en-NZ")},{0x1809,_T("en-IE")}};
  118. const USER_LANGID gr040c[] = {{0x080c,_T("fr-BE")},{0x0c0c,_T("fr-CA")},{0x100c,_T("fr-CH")}};
  119. const USER_LANGID gr0410[] = {{0x0810,_T("it-CH")}};
  120. const USER_LANGID gr0413[] = {{0x0813,_T("nl-BE")}};
  121. const USER_LANGID gr0416[] = {{0x0816,_T("pt")}};
  122. const USER_LANGID gr080a[] = {{0x040a,_T("es")},{0x080a,_T("es-MX")},{0x200a,_T("es-VE")},{0x240a,_T("es-CO")},
  123. {0x280a,_T("es-PE")},{0x2c0a,_T("es-AR")},{0x300a,_T("es-EC")},{0x340a,_T("es-CL")}};
  124. const USER_LANGID gr0c0a[] = {{0x040a,_T("es")},{0x080a,_T("es-MX")},{0x200a,_T("es-VE")},{0x240a,_T("es-CO")},
  125. {0x280a,_T("es-PE")},{0x2c0a,_T("es-AR")},{0x300a,_T("es-EC")},{0x340a,_T("es-CL")}};
  126. // These are all the machine langids. If there isn't an associated array of user langids, then
  127. // the user langid is irrelevant, and the default ISO language code should be used. If there is
  128. // an associated array of user langids, then it should be searched first and the specific langid used.
  129. // If no match is found in the user langids, then the default langid is used.
  130. const MACH_LANGID grLangids[] = {
  131. { 0x0401, _T("ar"), 0, NULL },
  132. { 0x0403, _T("ca"), 0, NULL },
  133. { 0x0404, _T("zh-TW"), grsize(0404), gr0404 },
  134. { 0x0405, _T("cs"), 0, NULL },
  135. { 0x0406, _T("da"), 0, NULL },
  136. { 0x0407, _T("de"), grsize(0407), gr0407 },
  137. { 0x0408, _T("el"), 0, NULL },
  138. { 0x0409, _T("en"), grsize(0409), gr0409 },
  139. { 0x040b, _T("fi"), 0, NULL },
  140. { 0x040c, _T("fr"), grsize(040c), gr040c },
  141. { 0x040d, _T("iw"), 0, NULL },
  142. { 0x040e, _T("hu"), 0, NULL },
  143. { 0x0410, _T("it"), grsize(0410), gr0410 },
  144. { 0x0411, _T("ja"), 0, NULL },
  145. { 0x0412, _T("ko"), 0, NULL },
  146. { 0x0413, _T("nl"), grsize(0413), gr0413 },
  147. { 0x0414, _T("no"), 0, NULL },
  148. { 0x0415, _T("pl"), 0, NULL },
  149. { 0x0416, _T("pt-BR"), grsize(0416), gr0416 },
  150. { 0x0419, _T("ru"), 0, NULL },
  151. { 0x041b, _T("sk"), 0, NULL },
  152. { 0x041d, _T("sv"), 0, NULL },
  153. { 0x041e, _T("th"), 0, NULL },
  154. { 0x041f, _T("tr"), 0, NULL },
  155. { 0x0424, _T("sl"), 0, NULL },
  156. { 0x042d, _T("eu"), 0, NULL },
  157. { 0x0804, _T("zh-CN"), 0, NULL },
  158. { 0x080a, _T("es"), grsize(080a), gr080a },
  159. { 0x0816, _T("pt"), 0, NULL },
  160. { 0x0c0a, _T("es"), grsize(0c0a), gr0c0a }
  161. };
  162. #define cLangids (sizeof(grLangids) / sizeof(MACH_LANGID))
  163. static LANGID MapLangID(LANGID langid)
  164. {
  165. switch (PRIMARYLANGID(langid))
  166. {
  167. case LANG_ARABIC:
  168. langid = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA);
  169. break;
  170. case LANG_CHINESE:
  171. if (SUBLANGID(langid) != SUBLANG_CHINESE_TRADITIONAL)
  172. langid = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED);
  173. break;
  174. case LANG_DUTCH:
  175. langid = MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH);
  176. break;
  177. case LANG_GERMAN:
  178. langid = MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN);
  179. break;
  180. case LANG_ENGLISH:
  181. if (SUBLANGID(langid) != SUBLANG_ENGLISH_UK)
  182. langid = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
  183. break;
  184. case LANG_FRENCH:
  185. langid = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH);
  186. break;
  187. case LANG_ITALIAN:
  188. langid = MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN);
  189. break;
  190. case LANG_KOREAN:
  191. langid = MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN);
  192. break;
  193. case LANG_NORWEGIAN:
  194. langid = MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL);
  195. break;
  196. case LANG_PORTUGUESE:
  197. // We support both SUBLANG_PORTUGUESE and SUBLANG_PORTUGUESE_BRAZILIAN
  198. break;
  199. case LANG_SPANISH:
  200. langid = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH);
  201. break;
  202. case LANG_SWEDISH:
  203. langid = MAKELANGID(LANG_SWEDISH, SUBLANG_SWEDISH);
  204. break;
  205. };
  206. return langid;
  207. }
  208. // return user language ID
  209. LANGID WINAPI GetUserLangID()
  210. {
  211. LOG_Block("GetUserLangID");
  212. #ifdef __WUIUTEST
  213. // language spoofing
  214. HKEY hKey;
  215. DWORD dwLangID = 0;
  216. int error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WUIUTEST, 0, KEY_READ, &hKey);
  217. if (ERROR_SUCCESS == error)
  218. {
  219. DWORD dwSize = sizeof(dwLangID);
  220. error = RegQueryValueEx(hKey, REGVAL_USER_LANGID, 0, 0, (LPBYTE)&dwLangID, &dwSize);
  221. RegCloseKey(hKey);
  222. if (ERROR_SUCCESS == error)
  223. {
  224. return (WORD) dwLangID;
  225. }
  226. }
  227. #endif
  228. WORD wCodePage = 0;
  229. BOOL bIsNT4 = FALSE;
  230. BOOL bIsW95 = FALSE;
  231. //
  232. // get base language id
  233. //
  234. LANGID langidCurrent = CorrectGetUserDefaultLangID(bIsNT4, bIsW95); // Passed by reference
  235. //
  236. // // special handling for languages
  237. // //
  238. // switch (langidCurrent)
  239. // {
  240. // case LANGID_ENGLISH:
  241. //
  242. // // enabled langauges
  243. // wCodePage = CorrectGetACP();
  244. // if (CODEPAGE_ARABIC != wCodePage &&
  245. // CODEPAGE_HEBREW != wCodePage &&
  246. // CODEPAGE_THAI != wCodePage)
  247. // {
  248. // wCodePage = 0;
  249. // }
  250. // break;
  251. //
  252. // case LANGID_GREEK:
  253. //
  254. // // Greek IBM?
  255. // wCodePage = CorrectGetOEMCP();
  256. // if (wCodePage != CODEPAGE_GREEK_IBM)
  257. // {
  258. // // if its not Greek IBM we assume its MS. The language code for Greek MS does not include
  259. // // the code page
  260. // wCodePage = 0;
  261. // }
  262. // break;
  263. //
  264. // case LANGID_JAPANESE:
  265. //
  266. // if (FIsNECMachine())
  267. // {
  268. // wCodePage = 1;
  269. // }
  270. //
  271. // break;
  272. //
  273. // default:
  274. //
  275. // map language to the ones we support
  276. //
  277. langidCurrent = MapLangID(langidCurrent);
  278. // break;
  279. // }
  280. //
  281. // Special treatment of NT4 and W95 languages.
  282. // On NT4, Enabled Arabic, Thai, and Hebrew systems report as fully localized but we want to map them to Enabled
  283. // On W95, Enabled Thai is reported as Thai but we want to map to Enabled Thai
  284. //
  285. if (bIsNT4)
  286. {
  287. // NT4
  288. switch (langidCurrent)
  289. {
  290. case LANGID_ARABIC:
  291. langidCurrent = LANGID_ENGLISH;
  292. break;
  293. case LANGID_HEBREW:
  294. langidCurrent = LANGID_ENGLISH;
  295. break;
  296. case LANGID_THAI:
  297. langidCurrent = LANGID_ENGLISH;
  298. break;
  299. }
  300. }
  301. else if (bIsW95)
  302. {
  303. // W95 - only tweek Thai
  304. if (langidCurrent == LANGID_THAI)
  305. {
  306. // wCodePage = CODEPAGE_THAI;
  307. langidCurrent = LANGID_ENGLISH;
  308. }
  309. }
  310. LOG_Driver(_T("Returning 0x%04x"), langidCurrent);
  311. return langidCurrent;
  312. }
  313. // return system language ID
  314. LANGID WINAPI GetSystemLangID()
  315. {
  316. LOG_Block("GetSystemLangID");
  317. #ifdef __WUIUTEST
  318. // language spoofing
  319. HKEY hKey;
  320. DWORD dwLangID = 0;
  321. int error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WUIUTEST, 0, KEY_READ, &hKey);
  322. if (ERROR_SUCCESS == error)
  323. {
  324. DWORD dwSize = sizeof(dwLangID);
  325. error = RegQueryValueEx(hKey, REGVAL_OS_LANGID, 0, 0, (LPBYTE)&dwLangID, &dwSize);
  326. RegCloseKey(hKey);
  327. if (ERROR_SUCCESS == error)
  328. {
  329. return (WORD) dwLangID;
  330. }
  331. }
  332. #endif
  333. WORD wCodePage = 0;
  334. BOOL bIsNT4 = FALSE;
  335. BOOL bIsW95 = FALSE;
  336. //
  337. // get base language id
  338. //
  339. LANGID langidCurrent = CorrectGetSystemDefaultLangID(bIsNT4, bIsW95); // Passed by reference
  340. //
  341. // // special handling for languages
  342. // //
  343. // switch (langidCurrent)
  344. // {
  345. // case LANGID_ENGLISH:
  346. //
  347. // // enabled langauges
  348. // wCodePage = CorrectGetACP();
  349. // if (CODEPAGE_ARABIC != wCodePage &&
  350. // CODEPAGE_HEBREW != wCodePage &&
  351. // CODEPAGE_THAI != wCodePage)
  352. // {
  353. // wCodePage = 0;
  354. // }
  355. // break;
  356. //
  357. // case LANGID_GREEK:
  358. //
  359. // // Greek IBM?
  360. // wCodePage = CorrectGetOEMCP();
  361. // if (wCodePage != CODEPAGE_GREEK_IBM)
  362. // {
  363. // // if its not Greek IBM we assume its MS. The language code for Greek MS does not include
  364. // // the code page
  365. // wCodePage = 0;
  366. // }
  367. // break;
  368. //
  369. // case LANGID_JAPANESE:
  370. //
  371. // if (FIsNECMachine())
  372. // {
  373. // wCodePage = 1;
  374. // }
  375. //
  376. // break;
  377. //
  378. // default:
  379. //
  380. // map language to the ones we support
  381. //
  382. langidCurrent = MapLangID(langidCurrent);
  383. // break;
  384. // }
  385. //
  386. // Special treatment of NT4 and W95 languages.
  387. // On NT4, Enabled Arabic, Thai, and Hebrew systems report as fully localized but we want to map them to Enabled
  388. // On W95, Enabled Thai is reported as Thai but we want to map to Enabled Thai
  389. //
  390. if (bIsNT4)
  391. {
  392. // NT4
  393. switch (langidCurrent)
  394. {
  395. case LANGID_ARABIC:
  396. langidCurrent = LANGID_ENGLISH;
  397. break;
  398. case LANGID_HEBREW:
  399. langidCurrent = LANGID_ENGLISH;
  400. break;
  401. case LANGID_THAI:
  402. langidCurrent = LANGID_ENGLISH;
  403. break;
  404. }
  405. }
  406. else if (bIsW95)
  407. {
  408. // W95
  409. if (langidCurrent == LANGID_THAI)
  410. {
  411. // wCodePage = CODEPAGE_THAI;
  412. langidCurrent = LANGID_ENGLISH;
  413. }
  414. }
  415. LOG_Driver(_T("Returning 0x%04x"), langidCurrent);
  416. return langidCurrent;
  417. }
  418. HRESULT WINAPI DetectClientIUPlatform(PIU_PLATFORM_INFO pIuPlatformInfo)
  419. {
  420. LOG_Block("DetectClientIUPlatform");
  421. HRESULT hr = S_OK;
  422. if (!pIuPlatformInfo)
  423. {
  424. LOG_ErrorMsg(E_INVALIDARG);
  425. return E_INVALIDARG;
  426. }
  427. ZeroMemory(pIuPlatformInfo, sizeof(IU_PLATFORM_INFO));
  428. OSVERSIONINFO osverinfo;
  429. osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  430. if ( !GetVersionEx(&osverinfo) )
  431. {
  432. LOG_ErrorMsg(GetLastError());
  433. return HRESULT_FROM_WIN32(GetLastError());
  434. }
  435. #ifdef __WUIUTEST
  436. // platform spoofing
  437. HKEY hKey;
  438. int error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WUIUTEST, 0, KEY_READ, &hKey);
  439. if (ERROR_SUCCESS == error)
  440. {
  441. DWORD dwSize = sizeof(DWORD);
  442. RegQueryValueEx(hKey, REGVAL_MAJORVER, 0, 0, (LPBYTE)&osverinfo.dwMajorVersion, &dwSize);
  443. RegQueryValueEx(hKey, REGVAL_MINORVER, 0, 0, (LPBYTE)&osverinfo.dwMinorVersion, &dwSize);
  444. RegQueryValueEx(hKey, REGVAL_BLDNUMBER, 0, 0, (LPBYTE)&osverinfo.dwBuildNumber, &dwSize);
  445. RegQueryValueEx(hKey, REGVAL_PLATFORMID, 0, 0, (LPBYTE)&osverinfo.dwPlatformId, &dwSize);
  446. int cchValueSize;
  447. (void) SafeRegQueryStringValueCch(hKey, REGVAL_SZCSDVER, osverinfo.szCSDVersion, ARRAYSIZE(osverinfo.szCSDVersion), &cchValueSize);
  448. RegCloseKey(hKey);
  449. }
  450. #endif
  451. if ( VER_PLATFORM_WIN32_WINDOWS == osverinfo.dwPlatformId
  452. || ( VER_PLATFORM_WIN32_NT == osverinfo.dwPlatformId && 5 > osverinfo.dwMajorVersion ) )
  453. {
  454. //
  455. // We're on a Win9x platform or NT < 5.0 (Win2K) - just copy OSVERSIONINFO
  456. //
  457. memcpy(&pIuPlatformInfo->osVersionInfoEx, &osverinfo, sizeof(OSVERSIONINFO));
  458. //
  459. // For Win9x platforms, remove redundant Major/Minor info from high word of build
  460. //
  461. if (VER_PLATFORM_WIN32_WINDOWS == osverinfo.dwPlatformId)
  462. {
  463. pIuPlatformInfo->osVersionInfoEx.dwBuildNumber = (0x0000FFFF & pIuPlatformInfo->osVersionInfoEx.dwBuildNumber);
  464. }
  465. }
  466. else
  467. {
  468. //
  469. // We're on Win2K or greater, get and copy OSVERSIONINFOEX
  470. //
  471. OSVERSIONINFOEX osverinfoex;
  472. osverinfoex.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  473. if ( !GetVersionEx((OSVERSIONINFO*)&osverinfoex) )
  474. {
  475. LOG_ErrorMsg(GetLastError());
  476. return HRESULT_FROM_WIN32(GetLastError());
  477. }
  478. memcpy(&pIuPlatformInfo->osVersionInfoEx, &osverinfoex, sizeof(OSVERSIONINFOEX));
  479. }
  480. //
  481. // Fill in the OEM BSTRs
  482. //
  483. if (FAILED(hr = GetOemBstrs(pIuPlatformInfo->bstrOEMManufacturer, pIuPlatformInfo->bstrOEMModel, pIuPlatformInfo->bstrOEMSupportURL)))
  484. {
  485. goto FreeBSTRsAndReturnError;
  486. }
  487. //
  488. // Fill in pIuPlatformInfo->fIsAdministrator
  489. //
  490. pIuPlatformInfo->fIsAdministrator = IsAdministrator();
  491. return S_OK;
  492. FreeBSTRsAndReturnError:
  493. SafeSysFreeString(pIuPlatformInfo->bstrOEMManufacturer);
  494. SafeSysFreeString(pIuPlatformInfo->bstrOEMModel);
  495. SafeSysFreeString(pIuPlatformInfo->bstrOEMSupportURL);
  496. return hr;
  497. }
  498. static int atoh(LPCTSTR ptr)
  499. {
  500. int i = 0;
  501. //skip 0x if present
  502. if ( ptr[0] == '0' && (ptr[1] == 'x' || ptr[1] == 'X') )
  503. ptr += 2;
  504. for(;;) // until break
  505. {
  506. TCHAR ch = *ptr;
  507. if ('0' <= ch && ch <= '9')
  508. ch -= '0';
  509. else if ('a' <= ch && ch <= 'f')
  510. ch -= ('a' - 10);
  511. else if ('A' <= ch && ch <= 'F')
  512. ch -= ('A' - 10);
  513. else
  514. break;
  515. i = 16 * i + (int)ch;
  516. ptr++;
  517. }
  518. return i;
  519. }
  520. static int aton(LPCTSTR ptr)
  521. {
  522. int i = 0;
  523. while ('0' <= *ptr && *ptr <= '9')
  524. {
  525. i = 10 * i + (int)(*ptr - '0');
  526. ptr ++;
  527. }
  528. return i;
  529. }
  530. static LANGID CorrectGetSystemDefaultLangID(BOOL& bIsNT4, BOOL& bIsW95)
  531. {
  532. LOG_Block("CorrectGetSystemDefaultLangID");
  533. LANGID langidMachine = LANGID_ENGLISH; // default is english
  534. bIsNT4 = FALSE;
  535. bIsW95 = FALSE;
  536. TCHAR szMachineLCID[MAX_PATH];
  537. OSVERSIONINFO osverinfo;
  538. osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  539. if ( GetVersionEx(&osverinfo) )
  540. {
  541. if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
  542. {
  543. //
  544. if (5 == osverinfo.dwMajorVersion)
  545. {
  546. // langidMachine = GetSystemDefaultLangID();
  547. typedef LANGID (WINAPI *PFN_GetSystemDefaultUILanguage)(void);
  548. //
  549. //kernel32.dll will always be loaded in process
  550. //
  551. HMODULE hLibModule = GetModuleHandle(KERNEL32_DLL);
  552. if (hLibModule)
  553. {
  554. PFN_GetSystemDefaultUILanguage fpnGetSystemDefaultUILanguage =
  555. (PFN_GetSystemDefaultUILanguage)GetProcAddress(hLibModule, "GetSystemDefaultUILanguage");
  556. if (NULL != fpnGetSystemDefaultUILanguage)
  557. {
  558. langidMachine = fpnGetSystemDefaultUILanguage();
  559. if (0 == langidMachine)
  560. {
  561. LOG_Driver(_T("GetSystemDefaultUILanguage() returned 0, setting langidMachine back to LANGID_ENGLISH"));
  562. langidMachine = LANGID_ENGLISH;
  563. }
  564. }
  565. }
  566. }
  567. else
  568. {
  569. // Get the OS lang from the registry to correct NT4 bug in
  570. // GetSystemDefaultLangID -- it returns the UI lang and
  571. // the UI bits get installed (incorrect) as opposed to the actual OS
  572. // lang bits.
  573. HKEY hKey;
  574. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_USERS, REGKEY_CP_INTERNATIONAL, 0, KEY_QUERY_VALUE, &hKey))
  575. {
  576. int cchValueSize = ARRAYSIZE(szMachineLCID);
  577. if (SUCCEEDED(SafeRegQueryStringValueCch(hKey, REGKEY_LOCALE, szMachineLCID, cchValueSize, &cchValueSize)))
  578. {
  579. langidMachine = LANGIDFROMLCID(atoh(szMachineLCID));
  580. }
  581. else
  582. {
  583. LOG_Driver(_T("Failed to get langid from \"Locale\" registry value - defaults to LANGID_ENGLISH"));
  584. }
  585. RegCloseKey(hKey);
  586. }
  587. else
  588. {
  589. LOG_Driver(_T("Failed to open \"HKCU\\.DEFAULT\\Control Panel\\International\" - defaults to LANGID_ENGLISH"));
  590. }
  591. }
  592. if (osverinfo.dwMajorVersion == 4) // NT 4
  593. {
  594. bIsNT4 = TRUE;
  595. }
  596. }
  597. else
  598. {
  599. //
  600. // hack around a problem introduced in Win95 and still existing
  601. // in Win98 whereby the System Langid is the same as the User Langid.
  602. // We must look in the registry to get the real value.
  603. //
  604. HKEY hKey;
  605. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REGKEY_CP_RESOURCELOCAL, 0, KEY_QUERY_VALUE, &hKey))
  606. {
  607. int cchValueSize = ARRAYSIZE(szMachineLCID);
  608. if (SUCCEEDED(SafeRegQueryStringValueCch(hKey, NULL, szMachineLCID, cchValueSize, &cchValueSize)))
  609. {
  610. langidMachine = LANGIDFROMLCID(atoh(szMachineLCID));
  611. }
  612. else
  613. {
  614. LOG_Driver(_T("Failed to get (Default) from \"HKCU\\Control Panel\\Desktop\\ResourceLocale\" - defaults to LANGID_ENGLISH"));
  615. }
  616. RegCloseKey(hKey);
  617. }
  618. else
  619. {
  620. LOG_Driver(_T("Failed to open \"HKCU\\Control Panel\\Desktop\\ResourceLocale\" - defaults to LANGID_ENGLISH"));
  621. }
  622. if ((osverinfo.dwMajorVersion == 4) && (osverinfo.dwMinorVersion <= 0)) // Windows 95
  623. {
  624. bIsW95 = TRUE;
  625. }
  626. }
  627. }
  628. return langidMachine;
  629. }
  630. static LANGID CorrectGetUserDefaultLangID(BOOL& bIsNT4, BOOL& bIsW95)
  631. {
  632. LOG_Block("CorrectGetUserDefaultLangID");
  633. LANGID langidMachine = LANGID_ENGLISH; // default is english
  634. bIsNT4 = FALSE;
  635. bIsW95 = FALSE;
  636. TCHAR szMachineLCID[MAX_PATH];
  637. OSVERSIONINFO osverinfo;
  638. osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  639. if ( GetVersionEx(&osverinfo) )
  640. {
  641. if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
  642. {
  643. //
  644. // We shouldn't be using this function from NT, so just default to LANGID_ENGLISH
  645. // and log a message. This function will hopefully go away when we port to downlevel OS's
  646. //
  647. LOG_ErrorMsg(E_INVALIDARG);
  648. }
  649. else
  650. {
  651. //
  652. // hack around a problem introduced in Win95 and still existing
  653. // in Win98 whereby the System Langid is the same as the User Langid.
  654. // We must look in the registry to get the real value.
  655. //
  656. HKEY hKey;
  657. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REGKEY_CP_INTERNATIONAL, 0, KEY_QUERY_VALUE, &hKey))
  658. {
  659. int cchValueSize = ARRAYSIZE(szMachineLCID);
  660. if (SUCCEEDED(SafeRegQueryStringValueCch(hKey, NULL, szMachineLCID, cchValueSize, &cchValueSize)))
  661. {
  662. langidMachine = LANGIDFROMLCID(atoh(szMachineLCID));
  663. }
  664. else
  665. {
  666. LOG_Driver(_T("Failed to get (Default) from \"HKCU\\Control Panel\\Desktop\\ResourceLocale\" - defaults to LANGID_ENGLISH"));
  667. }
  668. RegCloseKey(hKey);
  669. }
  670. else
  671. {
  672. LOG_Driver(_T("Failed to open \"HKCU\\Control Panel\\Desktop\\ResourceLocale\" - defaults to LANGID_ENGLISH"));
  673. }
  674. if ((osverinfo.dwMajorVersion == 4) && (osverinfo.dwMinorVersion <= 0)) // Windows 95
  675. {
  676. bIsW95 = TRUE;
  677. }
  678. }
  679. }
  680. return langidMachine;
  681. }
  682. static WORD CorrectGetACP(void)
  683. {
  684. LOG_Block("CorrectGetACP");
  685. WORD wCodePage = 0;
  686. HKEY hKey;
  687. if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGPATH_CODEPAGE, 0, KEY_QUERY_VALUE, &hKey))
  688. {
  689. TCHAR szCodePage[MAX_PATH];
  690. int cchValueSize = ARRAYSIZE(szCodePage);
  691. if (SUCCEEDED(SafeRegQueryStringValueCch(hKey, REGKEY_ACP, szCodePage, cchValueSize, &cchValueSize)))
  692. {
  693. wCodePage = (WORD)aton(szCodePage);
  694. }
  695. else
  696. {
  697. LOG_Driver(_T("Failed SafeRegQueryStringValueCch in CorrectGetACP - defaulting to code page 0"));
  698. }
  699. RegCloseKey(hKey);
  700. }
  701. else
  702. {
  703. LOG_Driver(_T("Failed RegOpenKeyEx in CorrectGetACP - defaulting to code page 0"));
  704. }
  705. return wCodePage;
  706. }
  707. static WORD CorrectGetOEMCP(void)
  708. {
  709. LOG_Block("CorrectGetOEMCP");
  710. WORD wCodePage = 0;
  711. HKEY hKey;
  712. if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGPATH_CODEPAGE, 0, KEY_QUERY_VALUE, &hKey))
  713. {
  714. TCHAR szCodePage[MAX_PATH];
  715. int cchValueSize = ARRAYSIZE(szCodePage);
  716. if (SUCCEEDED(SafeRegQueryStringValueCch(hKey, REGKEY_OEMCP, szCodePage, cchValueSize, &cchValueSize)))
  717. {
  718. wCodePage = (WORD)aton(szCodePage);
  719. }
  720. else
  721. {
  722. LOG_Driver(_T("Failed SafeRegQueryStringValueCch in CorrectGetOEMCP - defaulting to code page 0"));
  723. }
  724. RegCloseKey(hKey);
  725. }
  726. else
  727. {
  728. LOG_Driver(_T("Failed RegOpenKeyEx in CorrectGetOEMCP - defaulting to code page 0"));
  729. }
  730. return wCodePage;
  731. }
  732. static bool FIsNECMachine()
  733. {
  734. LOG_Block("FIsNECMachine");
  735. bool fNEC = false;
  736. OSVERSIONINFO osverinfo;
  737. LONG lErr;
  738. osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  739. if (GetVersionEx(&osverinfo))
  740. {
  741. if (osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
  742. {
  743. HKEY hKey;
  744. TCHAR tszMachineType[50];
  745. int cchValueSize;
  746. if (ERROR_SUCCESS == (lErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  747. NT5_REGPATH_MACHTYPE,
  748. 0,
  749. KEY_QUERY_VALUE,
  750. &hKey)))
  751. {
  752. cchValueSize = ARRAYSIZE(tszMachineType);
  753. if (SUCCEEDED(SafeRegQueryStringValueCch(hKey,
  754. NT5_REGKEY_MACHTYPE,
  755. tszMachineType,
  756. cchValueSize,
  757. &cchValueSize)))
  758. {
  759. if (lstrcmp(tszMachineType, REGVAL_MACHTYPE_NEC) == 0)
  760. {
  761. fNEC = true;
  762. }
  763. }
  764. else
  765. {
  766. LOG_ErrorMsg(lErr);
  767. LOG_Driver(_T("Failed SafeRegQueryStringValueCch in FIsNECMachine - defaulting to fNEC = false"));
  768. }
  769. RegCloseKey(hKey);
  770. }
  771. else
  772. {
  773. LOG_ErrorMsg(lErr);
  774. LOG_Driver(_T("Failed RegOpenKeyEx in FIsNECMachine - defaulting to fNEC = false"));
  775. }
  776. }
  777. else // enOSWin98
  778. {
  779. // All NEC machines have NEC keyboards for Win98. NEC
  780. // machine detection is based on this.
  781. if (LOOKUP_OEMID(GetKeyboardType(1)) == PC98_KEYBOARD_ID)
  782. {
  783. fNEC = true;
  784. }
  785. else
  786. {
  787. LOG_Driver(_T("LOOKUP_OEMID(GetKeyboardType(1)) == PC98_KEYBOARD_ID was FALSE: defaulting to fNEC = false"));
  788. }
  789. }
  790. }
  791. return fNEC;
  792. }
  793. //
  794. // NOTES: If you pass in a NULL pointer you'll get it right back.
  795. // dwcBuffLen is in characters, not bytes.
  796. //
  797. LPTSTR GetIdentPlatformString(LPTSTR pszPlatformBuff, DWORD dwcBuffLen)
  798. {
  799. HRESULT hr=S_OK;
  800. LOG_Block("GetIdentPlatformString");
  801. if (NULL == pszPlatformBuff || 1 > dwcBuffLen)
  802. {
  803. LOG_ErrorMsg(E_INVALIDARG);
  804. return pszPlatformBuff;
  805. }
  806. LPTSTR szOSNamePtr = (LPTSTR) SZ_PLAT_UNKNOWN;
  807. OSVERSIONINFO osverinfo;
  808. osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  809. if (GetVersionEx(&osverinfo))
  810. {
  811. if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
  812. {
  813. // ADD CHECK FOR NEPTUNE HERE!!!!!
  814. if ( osverinfo.dwMinorVersion >= 90) // Millenium
  815. {
  816. szOSNamePtr = (LPTSTR) SZ_PLAT_WINME;
  817. }
  818. else if (osverinfo.dwMinorVersion > 0 && osverinfo.dwMinorVersion < 90) // Windows 98
  819. {
  820. szOSNamePtr = (LPTSTR) SZ_PLAT_WIN98;
  821. }
  822. else // Windows 95
  823. {
  824. szOSNamePtr = (LPTSTR) SZ_PLAT_WIN95;
  825. }
  826. }
  827. else // osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT
  828. {
  829. if ( osverinfo.dwMajorVersion == 4 ) // NT 4
  830. {
  831. szOSNamePtr = (LPTSTR) SZ_PLAT_NT4;
  832. }
  833. else if (osverinfo.dwMajorVersion == 5) // NT 5
  834. {
  835. if (0 == osverinfo.dwMinorVersion)
  836. {
  837. szOSNamePtr = (LPTSTR) SZ_PLAT_W2K;
  838. }
  839. else if (1 <= osverinfo.dwMinorVersion)
  840. {
  841. szOSNamePtr = (LPTSTR) SZ_PLAT_WHISTLER;
  842. }
  843. }
  844. }
  845. }
  846. if(lstrlen(szOSNamePtr) + 1 > (int) dwcBuffLen)
  847. {
  848. pszPlatformBuff[0] = 0;
  849. }
  850. else
  851. {
  852. //The length is validated above. So this function cannot possibly fail
  853. hr=StringCchCopyEx(pszPlatformBuff,dwcBuffLen,szOSNamePtr,NULL,NULL,MISTSAFE_STRING_FLAGS);
  854. if(FAILED(hr))
  855. pszPlatformBuff[0] = 0;
  856. }
  857. return pszPlatformBuff;
  858. }
  859. //
  860. // GetIdentLocaleString and related functions ported from Drizzle Utils
  861. //
  862. /////////////////////////////////////////////////////////////////////////////
  863. // DistinguishGreekOSs
  864. // Append additional code to distinguish the Greek OS version.
  865. //
  866. // Parameters:
  867. // pszISOCodeOut-
  868. // Greek-specific ISO code is appended to this parameter.
  869. /////////////////////////////////////////////////////////////////////////////
  870. void DistinguishGreekOSs(const TCHAR*& pszISOCodeOut /* out */)
  871. {
  872. LOG_Block("DistinguishGreekOSs");
  873. //
  874. // Default ISO code to Greek OS (MS).
  875. //
  876. pszISOCodeOut = ISOCODE_GREEK_MS;
  877. //
  878. // Determine from the registry which version of Greek OS. There are
  879. // two versions of the Greek OS.
  880. //
  881. HKEY hKey;
  882. DWORD type;
  883. TCHAR tszOSType[50];
  884. int cchValueSize;
  885. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  886. REGPATH_CODEPAGE,
  887. 0,
  888. KEY_QUERY_VALUE,
  889. &hKey) == ERROR_SUCCESS)
  890. {
  891. cchValueSize = ARRAYSIZE(tszOSType);
  892. if (SUCCEEDED(SafeRegQueryStringValueCch(hKey,
  893. REGKEY_OEMCP,
  894. tszOSType,
  895. cchValueSize,
  896. &cchValueSize)))
  897. {
  898. if (0 == lstrcmp(tszOSType, REGVAL_GREEK_IBM))
  899. {
  900. // Greek2
  901. pszISOCodeOut = ISOCODE_GREEK_IBM;
  902. }
  903. }
  904. RegCloseKey(hKey);
  905. }
  906. }
  907. /////////////////////////////////////////////////////////////////////////////
  908. // HandleExceptionCases
  909. // Take care of a few exception cases (i.e. Greek OS).
  910. //
  911. // Parameters:
  912. // langidMachine-
  913. // Contains a language id for the current OS.
  914. //
  915. // pszISOCode-
  916. // Points to a valid language id string for the current OS.
  917. /////////////////////////////////////////////////////////////////////////////
  918. inline void HandleExceptionCases(const LANGID& langidMachine, /* in */
  919. const TCHAR*& pszISOCode /* out */)
  920. {
  921. LOG_Block("HandleExceptionCases");
  922. // NEC machines are treated as having their own langid.
  923. // See if we have a Japanese machine, then check if it
  924. // is NEC.
  925. if (LANGID_JAPANESE == langidMachine)
  926. {
  927. if (FIsNECMachine())
  928. {
  929. pszISOCode = ISOCODE_NEC;
  930. }
  931. return;
  932. }
  933. // Windows 98 has two versions of Greek OS distinguished
  934. // only by a key in the registry.
  935. if(LANGID_GREEK == langidMachine)
  936. {
  937. OSVERSIONINFO osverinfo;
  938. osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  939. if (! GetVersionEx(&osverinfo))
  940. {
  941. return;
  942. }
  943. if (osverinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  944. {
  945. if (osverinfo.dwMinorVersion > 0)
  946. {
  947. DistinguishGreekOSs(pszISOCode);
  948. }
  949. return;
  950. }
  951. }
  952. }
  953. /////////////////////////////////////////////////////////////////////////////
  954. // langidCorrectGetSystemDefaultLangID
  955. // Make this return what GetSystemDefaultLangID should have returned
  956. // under Win98.
  957. //
  958. // Parameters:
  959. //
  960. // Comments :
  961. /////////////////////////////////////////////////////////////////////////////
  962. LANGID langidCorrectGetSystemDefaultLangID(void)
  963. {
  964. LOG_Block("langidCorrectGetSystemDefaultLangID");
  965. LANGID langidMachine = LANGID_ENGLISH; // default is english
  966. OSVERSIONINFO osverinfo;
  967. osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  968. if ( GetVersionEx(&osverinfo) )
  969. {
  970. if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
  971. {
  972. langidMachine = GetSystemDefaultLangID();
  973. }
  974. else
  975. {
  976. // hack around a problem introduced in Win95 and still existing
  977. // in Win98 whereby the System Langid is the same as the User Langid.
  978. // We must look in the registry to get the real value.
  979. HKEY hKey;
  980. // determine if we should log transmissions
  981. if ( RegOpenKeyEx( HKEY_CURRENT_USER,
  982. Win98_REGPATH_MACHLCID,
  983. 0,
  984. KEY_QUERY_VALUE,
  985. &hKey) == ERROR_SUCCESS )
  986. {
  987. TCHAR tszMachineLCID[MAX_PATH];
  988. int cchValueSize = ARRAYSIZE(tszMachineLCID);
  989. if (SUCCEEDED(SafeRegQueryStringValueCch(hKey, NULL, tszMachineLCID, cchValueSize, &cchValueSize))
  990. || SUCCEEDED(StringCchCopyEx(tszMachineLCID,ARRAYSIZE(tszMachineLCID),_T("00000409"),NULL,NULL,MISTSAFE_STRING_FLAGS)))
  991. {
  992. // Now convert to hexadecimal.
  993. langidMachine = LANGIDFROMLCID(atoh(tszMachineLCID));
  994. }
  995. RegCloseKey(hKey);
  996. }
  997. }
  998. }
  999. return langidMachine;
  1000. }
  1001. //
  1002. // NOTES: If you pass in a NULL pointer you'll get it right back.
  1003. // dwcBuffLen is in characters, not bytes.
  1004. //
  1005. LPTSTR GetIdentLocaleString(LPTSTR pszISOCode, DWORD dwcBuffLen)
  1006. {
  1007. LOG_Block("GetIdentLocaleString");
  1008. HRESULT hr=S_OK;
  1009. if (NULL == pszISOCode || 1 > dwcBuffLen)
  1010. {
  1011. LOG_ErrorMsg(E_INVALIDARG);
  1012. return pszISOCode;
  1013. }
  1014. // if we don't find any matching machine langids, we go to the english page.
  1015. LPTSTR pszISOCodePtr = ISOCODE_EN;
  1016. // First get the system and user LCID.
  1017. LANGID langidMachine = langidCorrectGetSystemDefaultLangID();
  1018. // First, locate the machine langid in the table.
  1019. for ( int iMachine = 0; iMachine < cLangids; iMachine++ )
  1020. {
  1021. if ( grLangids[iMachine].langidMachine == langidMachine )
  1022. {
  1023. // set the default langid in case we don't find a matching user langid.
  1024. pszISOCodePtr = grLangids[iMachine].pszDefaultISOCode;
  1025. // Found the machine langid, now lookup the user langid
  1026. if ( grLangids[iMachine].cElems != 0 )
  1027. {
  1028. LANGID langidUser = GetUserDefaultLangID();
  1029. // We check for specific user langids
  1030. for ( int iUser = 0; iUser < grLangids[iMachine].cElems; iUser++ )
  1031. {
  1032. if ( grLangids[iMachine].grLangidUser[iUser].langidUser == langidUser )
  1033. {
  1034. pszISOCodePtr = grLangids[iMachine].grLangidUser[iUser].pszISOCode;
  1035. break;
  1036. }
  1037. }
  1038. }
  1039. break;
  1040. }
  1041. }
  1042. // Take care of a few exceptions.
  1043. // HandleExceptionCases(langidMachine, pszISOCodePtr);
  1044. if(lstrlen(pszISOCodePtr) + 1 > (int) dwcBuffLen)
  1045. {
  1046. pszISOCode[0] = 0;
  1047. }
  1048. else
  1049. {
  1050. hr=StringCchCopyEx(pszISOCode,dwcBuffLen,pszISOCodePtr,NULL,NULL,MISTSAFE_STRING_FLAGS);
  1051. //cannot possibly fail since length is already validated
  1052. if(FAILED(hr))
  1053. {
  1054. pszISOCode[0] = 0;
  1055. }
  1056. }
  1057. return pszISOCode;
  1058. }
  1059. BOOL LookupLocaleStringFromLCID(LCID lcid, LPTSTR pszISOCode, DWORD cchISOCode)
  1060. {
  1061. LOG_Block("LookupLocaleStringFromLCID");
  1062. TCHAR szCountry[MAX_PATH];
  1063. BOOL fRet = FALSE;
  1064. if (GetLocaleInfo(lcid, LOCALE_SISO639LANGNAME,
  1065. pszISOCode, cchISOCode) == FALSE)
  1066. {
  1067. LOG_ErrorMsg(GetLastError());
  1068. goto done;
  1069. }
  1070. szCountry[0] = _T('-');
  1071. if (GetLocaleInfo(lcid, LOCALE_SISO3166CTRYNAME,
  1072. szCountry + 1, ARRAYSIZE(szCountry) - 1) == FALSE)
  1073. {
  1074. LOG_ErrorMsg(GetLastError());
  1075. goto done;
  1076. }
  1077. else
  1078. {
  1079. HRESULT hr;
  1080. hr = StringCchCatEx(pszISOCode, cchISOCode, szCountry,
  1081. NULL, NULL, MISTSAFE_STRING_FLAGS);
  1082. if (FAILED(hr))
  1083. {
  1084. SetLastError(HRESULT_CODE(hr));
  1085. LOG_ErrorMsg(hr);
  1086. pszISOCode[0] = _T('\0');
  1087. goto done;
  1088. }
  1089. }
  1090. fRet = TRUE;
  1091. done:
  1092. return fRet;
  1093. }
  1094. //
  1095. // NOTES: If you pass in a NULL pointer you'll get it right back.
  1096. // dwcBuffLen is in characters, not bytes.
  1097. //
  1098. LPTSTR LookupLocaleString(LPTSTR pszISOCode, DWORD dwcBuffLen, BOOL fIsUser)
  1099. {
  1100. LOG_Block("LookupLocaleString");
  1101. TCHAR szCtryName[MAX_PATH];
  1102. LANGID langid = 0;
  1103. LCID lcid = 0;
  1104. PFN_GetUserDefaultUILanguage pfnGetUserDefaultUILanguage = NULL;
  1105. PFN_GetSystemDefaultUILanguage pfnGetSystemDefaultUILanguage = NULL;
  1106. HMODULE hModule = NULL;
  1107. HRESULT hr=S_OK;
  1108. if (NULL == pszISOCode)
  1109. {
  1110. LOG_ErrorMsg(ERROR_INVALID_PARAMETER);
  1111. return NULL;
  1112. }
  1113. //
  1114. // If we hit an error, return a "Error" string
  1115. //
  1116. const TCHAR szError[] = _T("Error");
  1117. if (lstrlen(szError) < (int) dwcBuffLen)
  1118. {
  1119. hr=StringCchCopyEx(pszISOCode,dwcBuffLen,szError,NULL,NULL,MISTSAFE_STRING_FLAGS);
  1120. //This should not ideally happen
  1121. if(FAILED(hr))
  1122. {
  1123. LOG_ErrorMsg(HRESULT_CODE(hr));
  1124. pszISOCode[0] = 0;
  1125. goto CleanUp;
  1126. }
  1127. }
  1128. else
  1129. {
  1130. pszISOCode[0] = 0;
  1131. }
  1132. OSVERSIONINFO osverinfo;
  1133. osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  1134. if ( GetVersionEx(&osverinfo) )
  1135. {
  1136. if ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT && 5 <= osverinfo.dwMajorVersion)
  1137. {
  1138. //
  1139. // Windows 2000 and greater (Windows XP)
  1140. //
  1141. //kernel32.dll will always be loaded in process
  1142. //
  1143. hModule = GetModuleHandle(KERNEL32_DLL);
  1144. if (NULL == hModule)
  1145. {
  1146. LOG_ErrorMsg(GetLastError());
  1147. goto CleanUp;
  1148. }
  1149. if (TRUE == fIsUser)
  1150. {
  1151. //
  1152. // We want the MUI language rather than the LOCALE_USER_DEFAULT and we are >= Win2k
  1153. //
  1154. pfnGetUserDefaultUILanguage = (PFN_GetUserDefaultUILanguage) GetProcAddress(hModule, "GetUserDefaultUILanguage");
  1155. if (NULL == pfnGetUserDefaultUILanguage)
  1156. {
  1157. LOG_ErrorMsg(GetLastError());
  1158. goto CleanUp;
  1159. }
  1160. langid = pfnGetUserDefaultUILanguage();
  1161. if (0 == langid)
  1162. {
  1163. LOG_ErrorMsg(E_FAIL);
  1164. goto CleanUp;
  1165. }
  1166. lcid = MAKELCID(langid, SORT_DEFAULT);
  1167. }
  1168. else
  1169. {
  1170. pfnGetSystemDefaultUILanguage = (PFN_GetSystemDefaultUILanguage) GetProcAddress(hModule, "GetSystemDefaultUILanguage");
  1171. if (NULL == pfnGetSystemDefaultUILanguage)
  1172. {
  1173. LOG_ErrorMsg(GetLastError());
  1174. goto CleanUp;
  1175. }
  1176. langid = pfnGetSystemDefaultUILanguage();
  1177. if (0 == langid)
  1178. {
  1179. LOG_ErrorMsg(E_FAIL);
  1180. goto CleanUp;
  1181. }
  1182. lcid = MAKELCID(langid, SORT_DEFAULT);
  1183. }
  1184. if (FALSE == fIsUser && FIsNECMachine())
  1185. {
  1186. //
  1187. // 523660 Website is not distinguishing the JA_NEC and JA machine types
  1188. //
  1189. // For context="OS", special case NEC machines and just return "nec" for <language/>
  1190. //
  1191. lstrcpyn(pszISOCode, _T("nec"), (int) dwcBuffLen);
  1192. }
  1193. else
  1194. {
  1195. // don't check for error return because the previous code didn't
  1196. LookupLocaleStringFromLCID(lcid, pszISOCode, dwcBuffLen);
  1197. }
  1198. }
  1199. else
  1200. {
  1201. //
  1202. // Use methods ported from V3 to get local strings
  1203. //
  1204. // if we don't find any matching machine langids, we go to the english page.
  1205. LPTSTR pszISOCodePtr = ISOCODE_EN;
  1206. // First get the system or user LCID.
  1207. LANGID langidMachine = fIsUser ? GetUserLangID() : GetSystemLangID();
  1208. // First, locate the machine langid in the table.
  1209. for ( int iMachine = 0; iMachine < cLangids; iMachine++ )
  1210. {
  1211. if ( grLangids[iMachine].langidMachine == langidMachine )
  1212. {
  1213. // set the default langid in case we don't find a matching user langid.
  1214. pszISOCodePtr = grLangids[iMachine].pszDefaultISOCode;
  1215. // Found the machine langid, now lookup the user langid
  1216. if ( grLangids[iMachine].cElems != 0 )
  1217. {
  1218. LANGID langidUser = fIsUser ? GetUserDefaultLangID() : GetSystemDefaultLangID();
  1219. // We check for specific user langids
  1220. for ( int iUser = 0; iUser < grLangids[iMachine].cElems; iUser++ )
  1221. {
  1222. if ( grLangids[iMachine].grLangidUser[iUser].langidUser == langidUser )
  1223. {
  1224. pszISOCodePtr = grLangids[iMachine].grLangidUser[iUser].pszISOCode;
  1225. break;
  1226. }
  1227. }
  1228. }
  1229. break;
  1230. }
  1231. }
  1232. // Take care of a few exceptions.
  1233. // HandleExceptionCases(langidMachine, pszISOCodePtr);
  1234. if(lstrlen(pszISOCodePtr) < (int) dwcBuffLen)
  1235. {
  1236. hr=StringCchCopyEx(pszISOCode,dwcBuffLen,pszISOCodePtr,NULL,NULL,MISTSAFE_STRING_FLAGS);
  1237. if(FAILED(hr))
  1238. {
  1239. LOG_ErrorMsg(HRESULT_CODE(hr));
  1240. pszISOCode[0] = 0;
  1241. goto CleanUp;
  1242. }
  1243. }
  1244. }
  1245. }
  1246. else
  1247. {
  1248. LOG_ErrorMsg(GetLastError());
  1249. }
  1250. CleanUp:
  1251. return pszISOCode;
  1252. }