/* * MLANG wrapper functions * Copyright (C) 2000 Microsoft Corporation */ #include "precomp.h" #include "mlang.h" #include "oleauto.h" #define CP_USERDEF 50000 #define CP_ISCII_MIN 57002 #define CP_ISCII_MAC 57011 #define IsISCII(cp) (((cp) >= CP_ISCII_MIN) && ((cp) <= CP_ISCII_MAC)) BOOL fInitializedCom; IMultiLanguage3 *pml3; BOOL FLoadMlang() { HRESULT hr; if (!fInitializedCom) { hr = CoInitialize(NULL); if (FAILED(hr)) { return(FALSE); } fInitializedCom = TRUE; } if (pml3 == NULL) { hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, &IID_IMultiLanguage3, (void **) &pml3); if (FAILED(hr)) { return(FALSE); } } return(TRUE); } BOOL FValidWin32CodePage(UINT cp) { switch (cp) { case 50220 : case 50221 : case 50222 : case 50225 : case 50227 : // case 50229 : case 52936 : // We don't use WCToMB or MBToWC for these because there are // bugs in C_IS2022.DLL and MLANG has built support. return(FALSE); } return(IsValidCodePage(cp)); } ConvertFromUnicodeMlang(UINT cp, BOOL fNoBestFit, BOOL fWriteEntities, LPCWSTR rgchUtf16, UINT cchUtf16, LPSTR rgchMbcs, UINT cchMbcs, BOOL* pfDefCharUsed) { DWORD dwMode; UINT cchSrc; UINT cchDst; DWORD dwFlags; HRESULT hr; if (!FLoadMlang()) { return(0); } dwMode = 0; cchSrc = cchUtf16; cchDst = cchMbcs; dwFlags = fWriteEntities ? MLCONVCHARF_NCR_ENTITIZE : MLCONVCHARF_USEDEFCHAR; if (fNoBestFit) { dwFlags |= MLCONVCHARF_NOBESTFITCHARS; } hr = pml3->lpVtbl->ConvertStringFromUnicodeEx(pml3, &dwMode, cp, (WCHAR *) rgchUtf16, &cchSrc, rgchMbcs, &cchDst, dwFlags, NULL); if (FAILED(hr)) { return(0); } if (pfDefCharUsed != NULL) { *pfDefCharUsed = (hr == S_FALSE); } return(cchDst); } UINT ConvertFromUnicode(UINT cp, BOOL fNoBestFit, BOOL fWriteEntities, LPCWSTR rgchUtf16, UINT cchUtf16, LPSTR rgchMbcs, UINT cchMbcs, BOOL* pfDefCharUsed) { UINT cch; if (cchUtf16 == 0) { return(0); } if (!fWriteEntities && FValidWin32CodePage(cp)) { cch = WideCharToMultiByte(cp, fNoBestFit ? WC_NO_BEST_FIT_CHARS : 0, rgchUtf16, cchUtf16, rgchMbcs, cchMbcs, NULL, pfDefCharUsed); if (cch != 0) { return(cch); } // We retry with MLANG even when WCToMB supports the code page // because there are code pages when WCToMB may not support all // the features of the API. I know this is the case for WCToMB // and the ISCII encodings. We try again just for robustness. } cch = ConvertFromUnicodeMlang(cp, fNoBestFit, fWriteEntities, rgchUtf16, cchUtf16, rgchMbcs, cchMbcs, pfDefCharUsed); #if DBG if (cch == 0) { DebugBreak(); } #endif return(cch); } UINT ConvertToUnicodeMlang(UINT cp, LPCSTR rgchMbcs, UINT cchMbcs, LPWSTR rgchUtf16, UINT cchUtf16) { DWORD dwMode; UINT cchSrc; UINT cchDst; HRESULT hr; if (!FLoadMlang()) { return(0); } dwMode = 0; cchSrc = cchMbcs; cchDst = cchUtf16; hr = pml3->lpVtbl->ConvertStringToUnicode(pml3, &dwMode, cp, (CHAR *) rgchMbcs, &cchSrc, rgchUtf16, &cchDst); if (FAILED(hr)) { return(0); } return(cchDst); } UINT ConvertToUnicode(UINT cp, LPCSTR rgchMbcs, UINT cchMbcs, LPWSTR rgchUtf16, UINT cchUtf16) { UINT cch; if (cchMbcs == 0) { return(0); } if (FValidWin32CodePage(cp)) { cch = MultiByteToWideChar(cp, 0, rgchMbcs, cchMbcs, rgchUtf16, cchUtf16); if (cch != 0) { return(cch); } // We retry with MLANG even when MBToWC supports the code page // because there are code pages when MBToWC may not support all // the features of the API. I know this is the case for WCToMB // and the ISCII encodings. We try again just for robustness. } cch = ConvertToUnicodeMlang(cp, rgchMbcs, cchMbcs, rgchUtf16, cchUtf16); #if DBG if (cch == 0) { DebugBreak(); } #endif return(cch); } BOOL FDetectEncodingA(LPCSTR rgch, UINT cch, UINT* pcp) { INT cb; DetectEncodingInfo dei; INT cdei; HRESULT hr; if (!FLoadMlang()) { return(0); } cb = (INT) cch; cdei = 1; hr = pml3->lpVtbl->DetectInputCodepage(pml3, 0, 0, (LPSTR) rgch, &cb, &dei, &cdei); if (hr != S_OK) { return(FALSE); } if (cdei == 0) { return(FALSE); } *pcp = dei.nCodePage; return(TRUE); } BOOL FLookupCodepageNameW(LPCWSTR rgchEncoding, UINT cch, UINT* pcp) { BSTR bstrEncoding; MIMECSETINFO mci; HRESULT hr; if (cch == 0) { return(FALSE); } if (rgchEncoding[0] == L'_') { // Don't allow internal MLANG encodings return(FALSE); } if (!FLoadMlang()) { return(FALSE); } bstrEncoding = SysAllocStringLen(rgchEncoding, cch); if (bstrEncoding == NULL) { return(FALSE); } hr = pml3->lpVtbl->GetCharsetInfo(pml3, bstrEncoding, &mci); SysFreeString(bstrEncoding); *pcp = mci.uiInternetEncoding; if (SUCCEEDED(hr)) { return(TRUE); } return(FALSE); } BOOL FLookupCodepageNameA(LPCSTR rgchEncoding, UINT cch, UINT* pcp) { WCHAR rgwchEncoding[MAX_MIMECSET_NAME]; UINT ich; if (cch > MAX_MIMECSET_NAME) { return(FALSE); } for (ich = 0; ich < cch; ich++) { // Assume input is ASCII or Latin-1 and zero extend each character rgwchEncoding[ich] = (WCHAR) (BYTE) rgchEncoding[ich]; } return(FLookupCodepageNameW(rgwchEncoding, cch, pcp)); } BOOL FSupportWriteEntities(UINT cp) { if (IsISCII(cp)) { return(FALSE); } return(TRUE); } BOOL FValidateCodepage(HWND hwnd, UINT cp) { HRESULT hr; if (IsValidCodePage(cp)) { return(TRUE); } if ((cp == CP_USERDEF) || (cp == CP_AUTO) || (cp == CP_MACCP) || (cp == CP_THREAD_ACP)) { return(FALSE); } if (!FLoadMlang()) { return(FALSE); } hr = pml3->lpVtbl->ValidateCodePage(pml3, cp, hwnd); if (SUCCEEDED(hr) && (hr != S_FALSE)) { return(TRUE); } return(FALSE); } void PopulateCodePages(HWND hWnd, BOOL fSelectEncoding, UINT cpSelect, UINT cpExtra) { IEnumCodePage *pecp; UINT msg_ADDSTRING; UINT msg_SETITEMDATA; UINT msg_GETCOUNT; UINT msg_GETITEMDATA; UINT msg_SETCURSEL; HRESULT hr; LRESULT lr; if (!FLoadMlang()) { return; } hr = pml3->lpVtbl->EnumCodePages(pml3, MIMECONTF_VALID_NLS | MIMECONTF_EXPORT, GetUserDefaultUILanguage(), &pecp); if (FAILED(hr)) { return; } msg_ADDSTRING = fSelectEncoding ? LB_ADDSTRING : CB_ADDSTRING; msg_SETITEMDATA = fSelectEncoding ? LB_SETITEMDATA : CB_SETITEMDATA; msg_GETCOUNT = fSelectEncoding ? LB_GETCOUNT : CB_GETCOUNT; msg_GETITEMDATA = fSelectEncoding ? LB_GETITEMDATA : CB_GETITEMDATA; msg_SETCURSEL = fSelectEncoding ? LB_SETCURSEL : CB_SETCURSEL; for (;;) { MIMECPINFO mci; ULONG c; hr = pecp->lpVtbl->Next(pecp, 1, &mci, &c); if (FAILED(hr)) { break; } if (c == 0) { break; } if (mci.uiCodePage == CP_USERDEF) { // Ignore "User Defined" continue; } if (!fSelectEncoding) { if (mci.uiCodePage == cpSelect) { } else if (mci.uiCodePage == cpExtra) { } else if (mci.uiCodePage == CP_UTF16) { } else if (mci.uiCodePage == 1252) { } else if (mci.uiCodePage == CP_UTF8) { } else if (mci.uiCodePage == g_cpDefault) { } else if (mci.uiCodePage == g_cpANSI) { // Don't filter ANSI codepage used by system } else if (mci.uiCodePage == g_cpOEM) { // Don't filter OEM codepage used by system } else if (mci.uiCodePage == g_cpUserLangANSI) { // Don't filter ANSI codepage associated with user's default UI language } else if (mci.uiCodePage == g_cpUserLangOEM) { // Don't filter OEM codepage associated with user's default UI language } else if (mci.uiCodePage == g_cpUserLocaleANSI) { // Don't filter ANSI codepage associated with user's default locale } else if (mci.uiCodePage == g_cpUserLocaleOEM) { // Don't filter OEM codepage associated with user's default locale } else if (mci.uiCodePage == g_cpKeyboardANSI) { // Don't filter ANSI codepage associated with the current active keyboard } else if (mci.uiCodePage == g_cpKeyboardOEM) { // Don't filter OEM codepage associated with the current active keyboard } else { continue; } } lr = SendDlgItemMessage(hWnd, IDC_CODEPAGE, msg_ADDSTRING, 0, (LPARAM) mci.wszDescription); if (lr < 0) { break; } SendDlgItemMessage(hWnd, IDC_CODEPAGE, msg_SETITEMDATA, (WPARAM) lr, (LPARAM) mci.uiCodePage); } pecp->lpVtbl->Release(pecp); lr = SendDlgItemMessage(hWnd, IDC_CODEPAGE, msg_GETCOUNT, 0, 0); while (--lr >= 0) { UINT cp = (UINT) SendDlgItemMessage(hWnd, IDC_CODEPAGE, msg_GETITEMDATA, (WPARAM) lr, 0); if (cp == cpSelect) { SendDlgItemMessage(hWnd, IDC_CODEPAGE, msg_SETCURSEL, (WPARAM) lr, 0); break; } } } void UnloadMlang() { if (pml3 != NULL) { pml3->lpVtbl->Release(pml3); pml3 = NULL; } if (fInitializedCom) { CoUninitialize(); fInitializedCom = FALSE; } }