#include "private.h" #include #ifdef UNIX /* Convert from little endian to big endian format */ #define CONVERTLONG(a,b,c,d) (((unsigned long )a) + \ ((unsigned long )b << 8) + \ ((unsigned long )c << 16) + \ ((unsigned long )d << 24)) #endif /* UNIX */ // // Globals // CMimeDatabaseReg *g_pMimeDatabaseReg = NULL; // // Globals // PRFC1766INFOA g_pRfc1766Reg = NULL; UINT g_cRfc1766Reg = 0, g_cMaxRfc1766 = 0; // // Functions // void CMimeDatabaseReg::BuildRfc1766Table(void) { HKEY hKey = NULL; DWORD dwIndex, dwType, cInfo, cbMaxValueLen, cbLCID, cb; TCHAR szLCID[8], sz[MAX_RFC1766_NAME + MAX_LOCALE_NAME + 1]; DebugMsg(DM_TRACE, TEXT("CRfc1766::BuildRfc1766Table called.")); EnterCriticalSection(&g_cs); if (NULL == g_pRfc1766Reg) { if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, REGSTR_KEY_MIME_DATABASE_RFC1766, 0, KEY_READ, &hKey)) { ASSERT(NULL != hKey); if (ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, 0, NULL, NULL, NULL, &cInfo, &cbMaxValueLen, NULL, NULL, NULL)) { g_pRfc1766Reg = (PRFC1766INFOA)LocalAlloc(LPTR, sizeof(RFC1766INFOA) * cInfo); if (NULL != g_pRfc1766Reg) { g_cRfc1766Reg = 0; g_cMaxRfc1766 = cInfo; dwIndex = 0; while (g_cRfc1766Reg < g_cMaxRfc1766) { LONG lRet; cbLCID = ARRAYSIZE(szLCID) - 2; cb = sizeof(sz); lRet = RegEnumValue(hKey, dwIndex++, szLCID + 2, &cbLCID, 0, &dwType, (LPBYTE)sz, &cb); if (ERROR_SUCCESS == lRet) { int iLCID; szLCID[0] = TEXT('0'); szLCID[1] = TEXT('x'); // StrToInt if (iLCID = HexToNum(szLCID + 2)) { g_pRfc1766Reg[g_cRfc1766Reg].lcid = (LCID)iLCID; if (REG_SZ == dwType) { TCHAR *psz = sz; while (*psz) { if (TEXT(';') == *psz) { *psz = TEXT('\0'); break; } psz = CharNext(psz); } lstrcpyn(g_pRfc1766Reg[g_cRfc1766Reg].szRfc1766, sz, MAX_RFC1766_NAME); lstrcpyn(g_pRfc1766Reg[g_cRfc1766Reg].szLocaleName, psz + 1, MAX_LOCALE_NAME); g_cRfc1766Reg++; } } } else if (ERROR_NO_MORE_ITEMS == lRet) break; } } } RegCloseKey(hKey); } } LeaveCriticalSection(&g_cs); } void CMimeDatabaseReg::FreeRfc1766Table(void) { DebugMsg(DM_TRACE, TEXT("CRfc1766::FreeRfc1766Table called.")); EnterCriticalSection(&g_cs); if (NULL != g_pRfc1766Reg) { LocalFree(g_pRfc1766Reg); g_pRfc1766Reg = NULL; g_cRfc1766Reg = g_cMaxRfc1766 = 0; } LeaveCriticalSection(&g_cs); } void CMimeDatabaseReg::EnsureRfc1766Table(void) { // Ensure g_pRfc1766 is initialized if (NULL == g_pRfc1766Reg) BuildRfc1766Table(); } STDAPI CMimeDatabaseReg::LcidToRfc1766A(LCID Locale, LPSTR pszRfc1766, int iMaxLength) { UINT i; HRESULT hr = E_INVALIDARG; EnsureRfc1766Table(); if (NULL != pszRfc1766 && 0 < iMaxLength) { for (i = 0; i < g_cRfc1766Reg; i++) { if (g_pRfc1766Reg[i].lcid == Locale) break; } if (i < g_cRfc1766Reg) { lstrcpyn(pszRfc1766, g_pRfc1766Reg[i].szRfc1766, iMaxLength); hr = S_OK; } else { TCHAR sz[MAX_RFC1766_NAME]; if (GetLocaleInfoA(Locale, LOCALE_SABBREVLANGNAME, sz, ARRAYSIZE(sz))) { CharLowerA(sz); if (!lstrcmpA(sz, TEXT("cht"))) lstrcpynA(pszRfc1766, TEXT("zh-cn"), iMaxLength); else if (!lstrcmpA(sz, TEXT("chs"))) lstrcpynA(pszRfc1766, TEXT("zh-tw"), iMaxLength); else if (!lstrcmpA(sz, TEXT("jpn"))) lstrcpynA(pszRfc1766, TEXT("ja"), iMaxLength); else { sz[2] = TEXT('\0'); lstrcpynA(pszRfc1766, sz, iMaxLength); } hr = S_OK; } else hr = E_FAIL; } } return hr; } STDAPI CMimeDatabaseReg::LcidToRfc1766W(LCID Locale, LPWSTR pwszRfc1766, int nChar) { HRESULT hr = E_INVALIDARG; if (NULL != pwszRfc1766 && 0 < nChar) { TCHAR sz[MAX_RFC1766_NAME]; hr = LcidToRfc1766A(Locale, (LPSTR)sz, ARRAYSIZE(sz)); if (S_OK == hr) { int i; for (i = 0; i < nChar - 1; i++) { pwszRfc1766[i] = (WCHAR)sz[i]; if (L'\0' == pwszRfc1766[i]) break; } if (i == nChar - 1) pwszRfc1766[i] = L'\0'; } } return hr; } STDAPI CMimeDatabaseReg::Rfc1766ToLcidA(PLCID pLocale, LPCSTR pszRfc1766) { UINT i; HRESULT hr = E_INVALIDARG; EnsureRfc1766Table(); if (NULL != pLocale && NULL != pszRfc1766) { for (i = 0; i < g_cRfc1766Reg; i++) { if (!lstrcmpi(g_pRfc1766Reg[i].szRfc1766, pszRfc1766)) break; } if (i < g_cRfc1766Reg) { *pLocale = g_pRfc1766Reg[i].lcid; hr = S_OK; } else { if (2 < lstrlen(pszRfc1766)) { TCHAR sz[3]; sz[0] = pszRfc1766[0]; sz[1] = pszRfc1766[1]; sz[2] = TEXT('\0'); for (i = 0; i < g_cRfc1766Reg; i++) { if (!lstrcmpi(g_pRfc1766Reg[i].szRfc1766, sz)) break; } if (i < g_cRfc1766Reg) { *pLocale = g_pRfc1766Reg[i].lcid; hr = S_FALSE; } else hr = E_FAIL; } else hr = E_FAIL; } } return hr; } STDAPI CMimeDatabaseReg::Rfc1766ToLcidW(PLCID pLocale, LPCWSTR pwszRfc1766) { HRESULT hr = E_INVALIDARG; if (NULL != pLocale && NULL != pwszRfc1766) { int i; TCHAR sz[MAX_RFC1766_NAME]; for (i = 0; i < MAX_RFC1766_NAME - 1; i++) { sz[i] = (TCHAR)pwszRfc1766[i]; if (TEXT('\0') == sz[i]) break; } if (i == MAX_RFC1766_NAME -1) sz[i] = TEXT('\0'); hr = Rfc1766ToLcidA(pLocale, (LPCSTR)sz); } return hr; } // // CMimeDatabase implementation // CMimeDatabaseReg::CMimeDatabaseReg() { DebugMsg(DM_TRACE, TEXT("constructor of CMimeDatabase 0x%08x"), this); _pCodePage = NULL; _cCodePage = _cMaxCodePage = 0; _pCharset = NULL; _cCharset = _cMaxCharset = 0; _fAllCPCached = FALSE; InitializeCriticalSection(&_cs); } CMimeDatabaseReg::~CMimeDatabaseReg() { DebugMsg(DM_TRACE, TEXT("destructor of CMimeDatabase 0x%08x"), this); FreeMimeDatabase(); DeleteCriticalSection(&_cs); } void CMimeDatabaseReg::BuildCodePageMimeDatabase(void) { HKEY hKey = NULL; DWORD cInfo, cbMaxSubKeyLen; DebugMsg(DM_TRACE, TEXT("CMimeDatabase::BuildCodePageMimeDatabase called.")); // Open CodePage Mime Database Key if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, REGSTR_KEY_MIME_DATABASE_CODEPAGE, 0, KEY_READ, &hKey)) { ASSERT(NULL != hKey); if (ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, 0, &cInfo, &cbMaxSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL)) { if (NULL == _pCodePage) { _pCodePage = (PMIMECPINFO)LocalAlloc(LPTR, sizeof(MIMECPINFO) * cInfo); if (NULL != _pCodePage) _cMaxCodePage = cInfo; } } RegCloseKey(hKey); hKey = NULL; } } void CMimeDatabaseReg::BuildCharsetMimeDatabase(void) { HKEY hKey = NULL; DWORD cInfo, cbMaxSubKeyLen; DebugMsg(DM_TRACE, TEXT("CMimeDatabase::BuildCharsetMimeDatabase called.")); // Open Charset Mime Database Key if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, REGSTR_KEY_MIME_DATABASE_CHARSET, 0, KEY_READ, &hKey)) { ASSERT(NULL != hKey); if (ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, 0, &cInfo, &cbMaxSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL)) { if (NULL == _pCharset) { _pCharset = (PMIMECSETINFO)LocalAlloc(LPTR, sizeof(MIMECSETINFO) * cInfo); if (NULL != _pCharset) _cMaxCharset = cInfo; } } RegCloseKey(hKey); hKey = NULL; } } void CMimeDatabaseReg::FreeMimeDatabase(void) { DebugMsg(DM_TRACE, TEXT("CMimeDatabase::FreeMimeDatabase called.")); EnterCriticalSection(&_cs); if (NULL != _pCodePage) { LocalFree(_pCodePage); _pCodePage = NULL; _cCodePage = _cMaxCodePage = 0; } if (NULL != _pCharset) { LocalFree(_pCharset); _pCharset = NULL; _cCharset = _cMaxCharset = 0; } LeaveCriticalSection(&_cs); FreeRfc1766Table(); } STDAPI CMimeDatabaseReg::EnumCodePageInfo(void) { HKEY hKey = NULL; DWORD dwIndex = 0; MIMECPINFO CPInfo; TCHAR szCodePage[15]; HRESULT hr = S_OK; DebugMsg(DM_TRACE, TEXT("CMimeDatabase::EnumCodePageInfo called.")); EnterCriticalSection(&_cs); if (FALSE == _fAllCPCached) { if (NULL == _pCodePage) BuildCodePageMimeDatabase(); if (_pCodePage) { // Open CodePage Mime Database Key if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, REGSTR_KEY_MIME_DATABASE_CODEPAGE, 0, KEY_READ, &hKey)) { ASSERT(NULL != hKey); while (ERROR_SUCCESS == RegEnumKey(hKey, dwIndex++, szCodePage, ARRAYSIZE(szCodePage))) { UINT uiCodePage = MLStrToInt(szCodePage); if (0 <= FindCodePageFromCache(uiCodePage)) continue; if (TRUE == FindCodePageFromRegistry(uiCodePage, &CPInfo)) { _pCodePage[_cCodePage] = CPInfo; _cCodePage++; } } _fAllCPCached = TRUE; RegCloseKey(hKey); hKey = NULL; } if (0 < _cCodePage) QSortCodePageInfo(0, _cCodePage-1); // Fill empty font face field base on its FamilyCodePage for (UINT i = 0; i < _cCodePage; i++) { UINT uiFamily; WCHAR wszFixed[MAX_MIMEFACE_NAME], wszProp[MAX_MIMEFACE_NAME]; uiFamily = 0; wszFixed[0] = wszProp[0] = TEXT('\0'); if (TEXT('\0') == _pCodePage[i].wszFixedWidthFont[0] || TEXT('\0') == _pCodePage[i].wszProportionalFont[0]) { if (uiFamily != _pCodePage[i].uiFamilyCodePage) { for (UINT j = 0; j < _cCodePage; j++) { if (_pCodePage[i].uiFamilyCodePage == _pCodePage[j].uiCodePage) { uiFamily = _pCodePage[j].uiCodePage; MLStrCpyNW(wszFixed, _pCodePage[j].wszFixedWidthFont, MAX_MIMEFACE_NAME); MLStrCpyNW(wszProp, _pCodePage[j].wszProportionalFont, MAX_MIMEFACE_NAME); break; } } } MLStrCpyNW(_pCodePage[i].wszFixedWidthFont, wszFixed, MAX_MIMEFACE_NAME); MLStrCpyNW(_pCodePage[i].wszProportionalFont, wszProp, MAX_MIMEFACE_NAME); } } } else { hr = E_OUTOFMEMORY; } } LeaveCriticalSection(&_cs); return hr; } STDAPI CMimeDatabaseReg::GetNumberOfCodePageInfo(UINT *pcCodePage) { EnterCriticalSection(&_cs); if (NULL == _pCodePage) BuildCodePageMimeDatabase(); *pcCodePage = _cMaxCodePage; LeaveCriticalSection(&_cs); return NOERROR; } STDAPI CMimeDatabaseReg::GetCodePageInfo(UINT uiCodePage, PMIMECPINFO pcpInfo) { int idx; HRESULT hr = E_FAIL; DebugMsg(DM_TRACE, TEXT("CMimeDatabase::GetCodePageInfo called.")); if (NULL != pcpInfo) { EnterCriticalSection(&_cs); if (NULL == _pCodePage) BuildCodePageMimeDatabase(); if (_pCodePage) { idx = FindCodePageFromCache(uiCodePage); if (0 > idx) { MIMECPINFO CPInfo = {0}; if (TRUE == FindCodePageFromRegistry(uiCodePage, &CPInfo)) { if (CPInfo.uiCodePage != CPInfo.uiFamilyCodePage) { idx = FindCodePageFromCache(CPInfo.uiFamilyCodePage); if (0 > idx) { MIMECPINFO FamilyCPInfo; if (TRUE == FindCodePageFromRegistry(CPInfo.uiFamilyCodePage, &FamilyCPInfo)) { idx = _cCodePage; _pCodePage[_cCodePage] = FamilyCPInfo; _cCodePage++; } } MLStrCpyNW(CPInfo.wszFixedWidthFont, _pCodePage[idx].wszFixedWidthFont, MAX_MIMEFACE_NAME); MLStrCpyNW(CPInfo.wszProportionalFont, _pCodePage[idx].wszProportionalFont, MAX_MIMEFACE_NAME); } _pCodePage[_cCodePage] = CPInfo; _cCodePage++; QSortCodePageInfo(0, _cCodePage-1); idx = FindCodePageFromCache(uiCodePage); } } if (0 <= idx) { *pcpInfo = _pCodePage[idx]; hr = S_OK; } LeaveCriticalSection(&_cs); } } return hr; } int CMimeDatabaseReg::FindCodePageFromCache(UINT uiCodePage) { UINT i; int iRet = -1; for (i = 0; i < _cCodePage; i++) { if (_pCodePage[i].uiCodePage == uiCodePage) { iRet = i; break; } } return iRet; } BOOL CMimeDatabaseReg::FindCodePageFromRegistry(UINT uiCodePage, PMIMECPINFO pcpInfo) { HKEY hKey; DWORD dw, cb; TCHAR szKey[256], sz[MAX_MIMECP_NAME]; BOOL fRet = FALSE; HRESULT hr = E_FAIL; //*STRSAFE* wsprintf(szKey, TEXT("%s\\%d"), REGSTR_KEY_MIME_DATABASE_CODEPAGE, uiCodePage); hr = StringCchPrintf(szKey , ARRAYSIZE(szKey), TEXT("%s\\%d"), REGSTR_KEY_MIME_DATABASE_CODEPAGE, uiCodePage); if (!SUCCEEDED(hr)) { return FALSE; } if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hKey)) { TCHAR *psz, *pszComma; CHARSETINFO rCharsetInfo; pcpInfo->uiCodePage = uiCodePage; cb = sizeof(dw); if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_FAMILY, 0, NULL, (LPBYTE)&dw, &cb)) pcpInfo->uiFamilyCodePage = (UINT)dw; else pcpInfo->uiFamilyCodePage = pcpInfo->uiCodePage; cb = sizeof(dw); if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_LEVEL, 0, NULL, (LPBYTE)&dw, &cb)) #ifdef UNIX { BYTE* px = (BYTE*)&dw; pcpInfo->dwFlags = CONVERTLONG(px[0], px[1], px[2], px[3]); } #else pcpInfo->dwFlags = dw; #endif /* UNIX */ else pcpInfo->dwFlags = 0; cb = sizeof(sz); if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_DESCRIPTION, NULL, NULL, (LPBYTE)sz, &cb)) MultiByteToWideChar(CP_ACP, 0, sz, -1, pcpInfo->wszDescription, ARRAYSIZE(pcpInfo->wszDescription)); else { TCHAR szDef[MAX_MIMECP_NAME]; HRESULT hr; LoadString(g_hInst, IDS_MIME_LANG_DEFAULT, szDef, ARRAYSIZE(szDef)); //*STRSAFE* wsprintf(sz, szDef, pcpInfo->uiCodePage); hr = StringCchPrintf(sz , ARRAYSIZE(sz), szDef, pcpInfo->uiCodePage); if (!SUCCEEDED(hr)) { RegCloseKey(hKey); return FALSE; } MultiByteToWideChar(CP_ACP, 0, sz, -1, pcpInfo->wszDescription, ARRAYSIZE(pcpInfo->wszDescription)); } cb = sizeof(sz); if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_FIXEDWIDTHFONT, NULL, NULL, (LPBYTE)sz, &cb)) { psz = sz; pszComma = MLStrChr(sz, TEXT(',')); if (NULL != pszComma) // If there are multiple font name { if (uiCodePage != g_uACP) psz = pszComma + 1; // Take right side(English) fontname for non-native codepage info else *pszComma = TEXT('\0'); // Take left side(DBCS) fontname for native codepage info } if (lstrlen(psz) >= MAX_MIMEFACE_NAME) psz[MAX_MIMEFACE_NAME-1] = TEXT('\0'); MultiByteToWideChar(CP_ACP, 0, psz, -1, pcpInfo->wszFixedWidthFont, ARRAYSIZE(pcpInfo->wszFixedWidthFont)); } else pcpInfo->wszFixedWidthFont[0] = L'\0'; cb = sizeof(sz); if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_PROPORTIONALFONT, NULL, NULL, (LPBYTE)sz, &cb)) { psz = sz; pszComma = MLStrChr(sz, TEXT(',')); if (NULL != pszComma) // If there are multiple font name { if (uiCodePage != g_uACP) psz = pszComma + 1; // Take right side(English) fontname for non-native codepage info else *pszComma = TEXT('\0'); // Take left side(DBCS) fontname for native codepage info } if (lstrlen(psz) >= MAX_MIMEFACE_NAME) psz[MAX_MIMEFACE_NAME-1] = TEXT('\0'); MultiByteToWideChar(CP_ACP, 0, psz, -1, pcpInfo->wszProportionalFont, ARRAYSIZE(pcpInfo->wszProportionalFont)); } else pcpInfo->wszProportionalFont[0] = L'\0'; cb = sizeof(sz); if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_BODYCHARSET, NULL, NULL, (LPBYTE)sz, &cb)) MultiByteToWideChar(CP_ACP, 0, sz, -1, pcpInfo->wszBodyCharset, ARRAYSIZE(pcpInfo->wszBodyCharset)); else pcpInfo->wszBodyCharset[0] = L'\0'; cb = sizeof(sz); if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_HEADERCHARSET, NULL, NULL, (LPBYTE)sz, &cb)) MultiByteToWideChar(CP_ACP, 0, sz, -1, pcpInfo->wszHeaderCharset, ARRAYSIZE(pcpInfo->wszHeaderCharset)); else MLStrCpyNW(pcpInfo->wszHeaderCharset, pcpInfo->wszBodyCharset, MAX_MIMECSET_NAME); cb = sizeof(sz); if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_WEBCHARSET, NULL, NULL, (LPBYTE)sz, &cb)) MultiByteToWideChar(CP_ACP, 0, sz, -1, pcpInfo->wszWebCharset, ARRAYSIZE(pcpInfo->wszWebCharset)); else MLStrCpyNW(pcpInfo->wszWebCharset, pcpInfo->wszBodyCharset, MAX_MIMECSET_NAME); cb = sizeof(sz); if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_PRIVCONVERTER, NULL, NULL, (LPBYTE)sz, &cb)) pcpInfo->dwFlags |= MIMECONTF_PRIVCONVERTER; if (0 != TranslateCharsetInfo(IntToPtr_(LPDWORD, pcpInfo->uiFamilyCodePage), &rCharsetInfo, TCI_SRCCODEPAGE)) pcpInfo->bGDICharset = (BYTE)rCharsetInfo.ciCharset; else pcpInfo->bGDICharset = DEFAULT_CHARSET; if (1200 == pcpInfo->uiFamilyCodePage || 50000 == pcpInfo->uiFamilyCodePage || TRUE == _IsValidCodePage(pcpInfo->uiFamilyCodePage)) // 50000 means user defined { if (TRUE == CheckFont(pcpInfo->bGDICharset)) { if (pcpInfo->uiCodePage == pcpInfo->uiFamilyCodePage || TRUE == _IsValidCodePage(pcpInfo->uiCodePage)) pcpInfo->dwFlags |= MIMECONTF_VALID|MIMECONTF_VALID; else if (S_OK == IsConvertINetStringAvailable(pcpInfo->uiCodePage, pcpInfo->uiFamilyCodePage)) pcpInfo->dwFlags |= MIMECONTF_VALID|MIMECONTF_VALID; } else { if (pcpInfo->uiCodePage == pcpInfo->uiFamilyCodePage || TRUE == _IsValidCodePage(pcpInfo->uiCodePage)) pcpInfo->dwFlags |= MIMECONTF_VALID_NLS; else if (S_OK == IsConvertINetStringAvailable(pcpInfo->uiCodePage, pcpInfo->uiFamilyCodePage)) pcpInfo->dwFlags |= MIMECONTF_VALID_NLS; } } RegCloseKey(hKey); fRet = TRUE; } return fRet; } STDAPI CMimeDatabaseReg::GetCodePageInfoWithIndex(UINT uidx, PMIMECPINFO pcpInfo) { HRESULT hr = NOERROR; DebugMsg(DM_TRACE, TEXT("CMimeDatabase::GetCodePageInfoWithIndex called.")); EnterCriticalSection(&_cs); if (NULL == _pCodePage) BuildCodePageMimeDatabase(); if (uidx < _cCodePage && _pCodePage) *pcpInfo = _pCodePage[uidx]; else hr = E_FAIL; LeaveCriticalSection(&_cs); return hr; } STDAPI CMimeDatabaseReg::GetCharsetInfo(BSTR Charset, PMIMECSETINFO pcsetInfo) { int idx; HRESULT hr = E_FAIL; DebugMsg(DM_TRACE, TEXT("CMimeDatabase::GetCharsetInfo called.")); if (NULL != pcsetInfo) { EnterCriticalSection(&_cs); if (NULL == _pCharset) BuildCharsetMimeDatabase(); if (_pCharset) { idx = FindCharsetFromCache(Charset); if (0 > idx) idx = FindCharsetFromRegistry(Charset, FALSE); if (0 <= idx) { *pcsetInfo = _pCharset[idx]; hr = S_OK; } } LeaveCriticalSection(&_cs); } return hr; } int CMimeDatabaseReg::FindCharsetFromCache(BSTR Charset) { int iStart, iEnd, iMiddle, iCmpResult, iRet = -1; iStart = 0; iEnd = _cCharset - 1; while (iStart <= iEnd) { iMiddle = (iStart + iEnd) / 2; iCmpResult = MLStrCmpIW(Charset, _pCharset[iMiddle].wszCharset); if (iCmpResult < 0) iEnd = iMiddle - 1; else if (iCmpResult > 0) iStart = iMiddle + 1; else { iRet = iMiddle; break; } } return iRet; } int CMimeDatabaseReg::FindCharsetFromRegistry(BSTR Charset, BOOL fFromAlias) { HKEY hKey; TCHAR szKey[256], szCharset[MAX_MIMECSET_NAME]; int iRet = -1; HRESULT hr = E_FAIL; WideCharToMultiByte(CP_ACP, 0, Charset, -1, szCharset, ARRAYSIZE(szCharset), NULL, NULL); //*STRSAFE* lstrcpy(szKey, REGSTR_KEY_MIME_DATABASE_CHARSET); hr = StringCchCopy(szKey , ARRAYSIZE(szKey), REGSTR_KEY_MIME_DATABASE_CHARSET); if (!SUCCEEDED(hr)) { return iRet; } //*STRSAFE* lstrcat(szKey, TEXT("\\")); hr = StringCchCat(szKey , ARRAYSIZE(szKey), TEXT("\\")); if (!SUCCEEDED(hr)) { return iRet; } //*STRSAFE* lstrcat(szKey, szCharset); hr = StringCchCat(szKey , ARRAYSIZE(szKey), szCharset); if (!SUCCEEDED(hr)) { return iRet; } if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hKey)) { DWORD cb, dw; TCHAR sz[MAX_MIMECSET_NAME]; WCHAR wsz[MAX_MIMECSET_NAME]; cb = sizeof(sz); if (FALSE == fFromAlias && ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_ALIASTO, NULL, NULL, (LPBYTE)sz, &cb)) { MultiByteToWideChar(CP_ACP, 0, sz, -1, wsz, ARRAYSIZE(wsz)); iRet = FindCharsetFromCache(wsz); if (0 > iRet) iRet = FindCharsetFromRegistry(wsz, TRUE); if (0 <= iRet) { MLStrCpyNW(_pCharset[_cCharset].wszCharset, Charset, MAX_MIMECSET_NAME); _pCharset[_cCharset].uiCodePage = _pCharset[iRet].uiCodePage; _pCharset[_cCharset].uiInternetEncoding = _pCharset[iRet].uiInternetEncoding; _cCharset++; QSortCharsetInfo(0, _cCharset-1); iRet = FindCharsetFromCache(Charset); } } else { MLStrCpyNW(_pCharset[_cCharset].wszCharset, Charset, MAX_MIMECSET_NAME); cb = sizeof(dw); if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_CODEPAGE, 0, NULL, (LPBYTE)&dw, &cb)) { _pCharset[_cCharset].uiCodePage = (UINT)dw; cb = sizeof(dw); if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_INETENCODING, 0, NULL, (LPBYTE)&dw, &cb)) { _pCharset[_cCharset].uiInternetEncoding = (UINT)dw; _cCharset++; QSortCharsetInfo(0, _cCharset-1); iRet = FindCharsetFromCache(Charset); } } } RegCloseKey(hKey); } return iRet; } BOOL CMimeDatabaseReg::CheckFont(BYTE bGDICharset) { BOOL fRet = FALSE; DebugMsg(DM_TRACE, TEXT("CMimeDatabase::CheckFont called.")); if (DEFAULT_CHARSET == bGDICharset) fRet = TRUE; else { HDC hDC; LOGFONT lf; HWND hWnd; hWnd = GetTopWindow(GetDesktopWindow()); hDC = GetDC(hWnd); if (NULL != hDC) { lf.lfFaceName[0] = TEXT('\0'); lf.lfPitchAndFamily = 0; lf.lfCharSet = bGDICharset; EnumFontFamiliesEx(hDC, &lf, (FONTENUMPROC)EnumFontFamExProc, (LPARAM)&fRet, 0); } ReleaseDC(hWnd, hDC); } return fRet; } void CMimeDatabaseReg::QSortCodePageInfo(LONG left, LONG right) { register LONG i, j; WCHAR k[MAX_MIMECP_NAME]; MIMECPINFO t; DebugMsg(DM_TRACE, TEXT("CMimeDatabase::QSortCodePageInfo called.")); i = left; j = right; StringCchCopyW(k, ARRAYSIZE(k), _pCodePage[(left + right) / 2].wszDescription); do { while(MLStrCmpIW(_pCodePage[i].wszDescription, k) < 0 && i < right) i++; while (MLStrCmpIW(_pCodePage[j].wszDescription, k) > 0 && j > left) j--; if (i <= j) { t = _pCodePage[i]; _pCodePage[i] = _pCodePage[j]; _pCodePage[j] = t; i++; j--; } } while (i <= j); if (left < j) QSortCodePageInfo(left, j); if (i < right) QSortCodePageInfo(i, right); } void CMimeDatabaseReg::QSortCharsetInfo(LONG left, LONG right) { register LONG i, j; WCHAR k[MAX_MIMECSET_NAME]; MIMECSETINFO t; DebugMsg(DM_TRACE, TEXT("CMimeDatabase::QSortCharsetInfo called.")); i = left; j = right; StringCchCopyW(k, ARRAYSIZE(k), _pCharset[(left + right) / 2].wszCharset); do { while(MLStrCmpIW(_pCharset[i].wszCharset, k) < 0 && i < right) i++; while (MLStrCmpIW(_pCharset[j].wszCharset, k) > 0 && j > left) j--; if (i <= j) { t = _pCharset[i]; _pCharset[i] = _pCharset[j]; _pCharset[j] = t; i++; j--; } } while (i <= j); if (left < j) QSortCharsetInfo(left, j); if (i < right) QSortCharsetInfo(i, right); } // validates all cps that are in the same // family of the given codepage STDAPI CMimeDatabaseReg::ValidateCP(UINT uiCodePage) { UINT i; if (NULL == _pCodePage) BuildCodePageMimeDatabase(); // // just look into already cached codepages // for (i = 0; i < _cCodePage; i++) { if (_pCodePage[i].uiFamilyCodePage == uiCodePage) _pCodePage[i].dwFlags |= MIMECONTF_VALID|MIMECONTF_VALID_NLS; } return S_OK; // never fail? }