Source code of Windows XP (NT5)
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.

555 lines
12 KiB

  1. /*
  2. * MLANG wrapper functions
  3. * Copyright (C) 2000 Microsoft Corporation
  4. */
  5. #include "precomp.h"
  6. #include "mlang.h"
  7. #include "oleauto.h"
  8. #define CP_USERDEF 50000
  9. #define CP_ISCII_MIN 57002
  10. #define CP_ISCII_MAC 57011
  11. #define IsISCII(cp) (((cp) >= CP_ISCII_MIN) && ((cp) <= CP_ISCII_MAC))
  12. BOOL fInitializedCom;
  13. IMultiLanguage3 *pml3;
  14. BOOL FLoadMlang()
  15. {
  16. HRESULT hr;
  17. if (!fInitializedCom)
  18. {
  19. hr = CoInitialize(NULL);
  20. if (FAILED(hr))
  21. {
  22. return(FALSE);
  23. }
  24. fInitializedCom = TRUE;
  25. }
  26. if (pml3 == NULL)
  27. {
  28. hr = CoCreateInstance(&CLSID_CMultiLanguage,
  29. NULL,
  30. CLSCTX_INPROC_SERVER,
  31. &IID_IMultiLanguage3,
  32. (void **) &pml3);
  33. if (FAILED(hr))
  34. {
  35. return(FALSE);
  36. }
  37. }
  38. return(TRUE);
  39. }
  40. BOOL FValidWin32CodePage(UINT cp)
  41. {
  42. switch (cp)
  43. {
  44. case 50220 :
  45. case 50221 :
  46. case 50222 :
  47. case 50225 :
  48. case 50227 :
  49. // case 50229 :
  50. case 52936 :
  51. // We don't use WCToMB or MBToWC for these because there are
  52. // bugs in C_IS2022.DLL and MLANG has built support.
  53. return(FALSE);
  54. }
  55. return(IsValidCodePage(cp));
  56. }
  57. ConvertFromUnicodeMlang(UINT cp, BOOL fNoBestFit, BOOL fWriteEntities, LPCWSTR rgchUtf16, UINT cchUtf16, LPSTR rgchMbcs, UINT cchMbcs, BOOL* pfDefCharUsed)
  58. {
  59. DWORD dwMode;
  60. UINT cchSrc;
  61. UINT cchDst;
  62. DWORD dwFlags;
  63. HRESULT hr;
  64. if (!FLoadMlang())
  65. {
  66. return(0);
  67. }
  68. dwMode = 0;
  69. cchSrc = cchUtf16;
  70. cchDst = cchMbcs;
  71. dwFlags = fWriteEntities ? MLCONVCHARF_NCR_ENTITIZE : MLCONVCHARF_USEDEFCHAR;
  72. if (fNoBestFit)
  73. {
  74. dwFlags |= MLCONVCHARF_NOBESTFITCHARS;
  75. }
  76. hr = pml3->lpVtbl->ConvertStringFromUnicodeEx(pml3,
  77. &dwMode,
  78. cp,
  79. (WCHAR *) rgchUtf16,
  80. &cchSrc,
  81. rgchMbcs,
  82. &cchDst,
  83. dwFlags,
  84. NULL);
  85. if (FAILED(hr))
  86. {
  87. return(0);
  88. }
  89. if (pfDefCharUsed != NULL)
  90. {
  91. *pfDefCharUsed = (hr == S_FALSE);
  92. }
  93. return(cchDst);
  94. }
  95. UINT ConvertFromUnicode(UINT cp, BOOL fNoBestFit, BOOL fWriteEntities, LPCWSTR rgchUtf16, UINT cchUtf16, LPSTR rgchMbcs, UINT cchMbcs, BOOL* pfDefCharUsed)
  96. {
  97. UINT cch;
  98. if (cchUtf16 == 0)
  99. {
  100. return(0);
  101. }
  102. if (!fWriteEntities && FValidWin32CodePage(cp))
  103. {
  104. cch = WideCharToMultiByte(cp,
  105. fNoBestFit ? WC_NO_BEST_FIT_CHARS : 0,
  106. rgchUtf16,
  107. cchUtf16,
  108. rgchMbcs,
  109. cchMbcs,
  110. NULL,
  111. pfDefCharUsed);
  112. if (cch != 0)
  113. {
  114. return(cch);
  115. }
  116. // We retry with MLANG even when WCToMB supports the code page
  117. // because there are code pages when WCToMB may not support all
  118. // the features of the API. I know this is the case for WCToMB
  119. // and the ISCII encodings. We try again just for robustness.
  120. }
  121. cch = ConvertFromUnicodeMlang(cp, fNoBestFit, fWriteEntities, rgchUtf16, cchUtf16, rgchMbcs, cchMbcs, pfDefCharUsed);
  122. #if DBG
  123. if (cch == 0)
  124. {
  125. DebugBreak();
  126. }
  127. #endif
  128. return(cch);
  129. }
  130. UINT ConvertToUnicodeMlang(UINT cp, LPCSTR rgchMbcs, UINT cchMbcs, LPWSTR rgchUtf16, UINT cchUtf16)
  131. {
  132. DWORD dwMode;
  133. UINT cchSrc;
  134. UINT cchDst;
  135. HRESULT hr;
  136. if (!FLoadMlang())
  137. {
  138. return(0);
  139. }
  140. dwMode = 0;
  141. cchSrc = cchMbcs;
  142. cchDst = cchUtf16;
  143. hr = pml3->lpVtbl->ConvertStringToUnicode(pml3,
  144. &dwMode,
  145. cp,
  146. (CHAR *) rgchMbcs,
  147. &cchSrc,
  148. rgchUtf16,
  149. &cchDst);
  150. if (FAILED(hr))
  151. {
  152. return(0);
  153. }
  154. return(cchDst);
  155. }
  156. UINT ConvertToUnicode(UINT cp, LPCSTR rgchMbcs, UINT cchMbcs, LPWSTR rgchUtf16, UINT cchUtf16)
  157. {
  158. UINT cch;
  159. if (cchMbcs == 0)
  160. {
  161. return(0);
  162. }
  163. if (FValidWin32CodePage(cp))
  164. {
  165. cch = MultiByteToWideChar(cp, 0, rgchMbcs, cchMbcs, rgchUtf16, cchUtf16);
  166. if (cch != 0)
  167. {
  168. return(cch);
  169. }
  170. // We retry with MLANG even when MBToWC supports the code page
  171. // because there are code pages when MBToWC may not support all
  172. // the features of the API. I know this is the case for WCToMB
  173. // and the ISCII encodings. We try again just for robustness.
  174. }
  175. cch = ConvertToUnicodeMlang(cp, rgchMbcs, cchMbcs, rgchUtf16, cchUtf16);
  176. #if DBG
  177. if (cch == 0)
  178. {
  179. DebugBreak();
  180. }
  181. #endif
  182. return(cch);
  183. }
  184. BOOL FDetectEncodingA(LPCSTR rgch, UINT cch, UINT* pcp)
  185. {
  186. INT cb;
  187. DetectEncodingInfo dei;
  188. INT cdei;
  189. HRESULT hr;
  190. if (!FLoadMlang())
  191. {
  192. return(0);
  193. }
  194. cb = (INT) cch;
  195. cdei = 1;
  196. hr = pml3->lpVtbl->DetectInputCodepage(pml3,
  197. 0,
  198. 0,
  199. (LPSTR) rgch,
  200. &cb,
  201. &dei,
  202. &cdei);
  203. if (hr != S_OK)
  204. {
  205. return(FALSE);
  206. }
  207. if (cdei == 0)
  208. {
  209. return(FALSE);
  210. }
  211. *pcp = dei.nCodePage;
  212. return(TRUE);
  213. }
  214. BOOL FLookupCodepageNameW(LPCWSTR rgchEncoding, UINT cch, UINT* pcp)
  215. {
  216. BSTR bstrEncoding;
  217. MIMECSETINFO mci;
  218. HRESULT hr;
  219. if (cch == 0)
  220. {
  221. return(FALSE);
  222. }
  223. if (rgchEncoding[0] == L'_')
  224. {
  225. // Don't allow internal MLANG encodings
  226. return(FALSE);
  227. }
  228. if (!FLoadMlang())
  229. {
  230. return(FALSE);
  231. }
  232. bstrEncoding = SysAllocStringLen(rgchEncoding, cch);
  233. if (bstrEncoding == NULL)
  234. {
  235. return(FALSE);
  236. }
  237. hr = pml3->lpVtbl->GetCharsetInfo(pml3, bstrEncoding, &mci);
  238. SysFreeString(bstrEncoding);
  239. *pcp = mci.uiInternetEncoding;
  240. if (SUCCEEDED(hr))
  241. {
  242. return(TRUE);
  243. }
  244. return(FALSE);
  245. }
  246. BOOL FLookupCodepageNameA(LPCSTR rgchEncoding, UINT cch, UINT* pcp)
  247. {
  248. WCHAR rgwchEncoding[MAX_MIMECSET_NAME];
  249. UINT ich;
  250. if (cch > MAX_MIMECSET_NAME)
  251. {
  252. return(FALSE);
  253. }
  254. for (ich = 0; ich < cch; ich++)
  255. {
  256. // Assume input is ASCII or Latin-1 and zero extend each character
  257. rgwchEncoding[ich] = (WCHAR) (BYTE) rgchEncoding[ich];
  258. }
  259. return(FLookupCodepageNameW(rgwchEncoding, cch, pcp));
  260. }
  261. BOOL FSupportWriteEntities(UINT cp)
  262. {
  263. if (IsISCII(cp))
  264. {
  265. return(FALSE);
  266. }
  267. return(TRUE);
  268. }
  269. BOOL FValidateCodepage(HWND hwnd, UINT cp)
  270. {
  271. HRESULT hr;
  272. if (IsValidCodePage(cp))
  273. {
  274. return(TRUE);
  275. }
  276. if ((cp == CP_USERDEF) || (cp == CP_AUTO) || (cp == CP_MACCP) || (cp == CP_THREAD_ACP))
  277. {
  278. return(FALSE);
  279. }
  280. if (!FLoadMlang())
  281. {
  282. return(FALSE);
  283. }
  284. hr = pml3->lpVtbl->ValidateCodePage(pml3, cp, hwnd);
  285. if (SUCCEEDED(hr) && (hr != S_FALSE))
  286. {
  287. return(TRUE);
  288. }
  289. return(FALSE);
  290. }
  291. void PopulateCodePages(HWND hWnd, BOOL fSelectEncoding, UINT cpSelect, UINT cpExtra)
  292. {
  293. IEnumCodePage *pecp;
  294. UINT msg_ADDSTRING;
  295. UINT msg_SETITEMDATA;
  296. UINT msg_GETCOUNT;
  297. UINT msg_GETITEMDATA;
  298. UINT msg_SETCURSEL;
  299. HRESULT hr;
  300. LRESULT lr;
  301. if (!FLoadMlang())
  302. {
  303. return;
  304. }
  305. hr = pml3->lpVtbl->EnumCodePages(pml3,
  306. MIMECONTF_VALID_NLS | MIMECONTF_EXPORT,
  307. GetUserDefaultUILanguage(),
  308. &pecp);
  309. if (FAILED(hr))
  310. {
  311. return;
  312. }
  313. msg_ADDSTRING = fSelectEncoding ? LB_ADDSTRING : CB_ADDSTRING;
  314. msg_SETITEMDATA = fSelectEncoding ? LB_SETITEMDATA : CB_SETITEMDATA;
  315. msg_GETCOUNT = fSelectEncoding ? LB_GETCOUNT : CB_GETCOUNT;
  316. msg_GETITEMDATA = fSelectEncoding ? LB_GETITEMDATA : CB_GETITEMDATA;
  317. msg_SETCURSEL = fSelectEncoding ? LB_SETCURSEL : CB_SETCURSEL;
  318. for (;;)
  319. {
  320. MIMECPINFO mci;
  321. ULONG c;
  322. hr = pecp->lpVtbl->Next(pecp, 1, &mci, &c);
  323. if (FAILED(hr))
  324. {
  325. break;
  326. }
  327. if (c == 0)
  328. {
  329. break;
  330. }
  331. if (mci.uiCodePage == CP_USERDEF)
  332. {
  333. // Ignore "User Defined"
  334. continue;
  335. }
  336. if (!fSelectEncoding)
  337. {
  338. if (mci.uiCodePage == cpSelect)
  339. {
  340. }
  341. else if (mci.uiCodePage == cpExtra)
  342. {
  343. }
  344. else if (mci.uiCodePage == CP_UTF16)
  345. {
  346. }
  347. else if (mci.uiCodePage == 1252)
  348. {
  349. }
  350. else if (mci.uiCodePage == CP_UTF8)
  351. {
  352. }
  353. else if (mci.uiCodePage == g_cpDefault)
  354. {
  355. }
  356. else if (mci.uiCodePage == g_cpANSI)
  357. {
  358. // Don't filter ANSI codepage used by system
  359. }
  360. else if (mci.uiCodePage == g_cpOEM)
  361. {
  362. // Don't filter OEM codepage used by system
  363. }
  364. else if (mci.uiCodePage == g_cpUserLangANSI)
  365. {
  366. // Don't filter ANSI codepage associated with user's default UI language
  367. }
  368. else if (mci.uiCodePage == g_cpUserLangOEM)
  369. {
  370. // Don't filter OEM codepage associated with user's default UI language
  371. }
  372. else if (mci.uiCodePage == g_cpUserLocaleANSI)
  373. {
  374. // Don't filter ANSI codepage associated with user's default locale
  375. }
  376. else if (mci.uiCodePage == g_cpUserLocaleOEM)
  377. {
  378. // Don't filter OEM codepage associated with user's default locale
  379. }
  380. else if (mci.uiCodePage == g_cpKeyboardANSI)
  381. {
  382. // Don't filter ANSI codepage associated with the current active keyboard
  383. }
  384. else if (mci.uiCodePage == g_cpKeyboardOEM)
  385. {
  386. // Don't filter OEM codepage associated with the current active keyboard
  387. }
  388. else
  389. {
  390. continue;
  391. }
  392. }
  393. lr = SendDlgItemMessage(hWnd, IDC_CODEPAGE, msg_ADDSTRING, 0, (LPARAM) mci.wszDescription);
  394. if (lr < 0)
  395. {
  396. break;
  397. }
  398. SendDlgItemMessage(hWnd, IDC_CODEPAGE, msg_SETITEMDATA, (WPARAM) lr, (LPARAM) mci.uiCodePage);
  399. }
  400. pecp->lpVtbl->Release(pecp);
  401. lr = SendDlgItemMessage(hWnd, IDC_CODEPAGE, msg_GETCOUNT, 0, 0);
  402. while (--lr >= 0)
  403. {
  404. UINT cp = (UINT) SendDlgItemMessage(hWnd, IDC_CODEPAGE, msg_GETITEMDATA, (WPARAM) lr, 0);
  405. if (cp == cpSelect)
  406. {
  407. SendDlgItemMessage(hWnd, IDC_CODEPAGE, msg_SETCURSEL, (WPARAM) lr, 0);
  408. break;
  409. }
  410. }
  411. }
  412. void UnloadMlang()
  413. {
  414. if (pml3 != NULL)
  415. {
  416. pml3->lpVtbl->Release(pml3);
  417. pml3 = NULL;
  418. }
  419. if (fInitializedCom)
  420. {
  421. CoUninitialize();
  422. fInitializedCom = FALSE;
  423. }
  424. }