windows-nt/Source/XPSP1/NT/shell/ext/mlang/mimereg.cpp
2020-09-26 16:20:57 +08:00

879 lines
28 KiB
C++

#include "private.h"
#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;
wsprintf(szKey, TEXT("%s\\%d"), REGSTR_KEY_MIME_DATABASE_CODEPAGE, uiCodePage);
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];
LoadString(g_hInst, IDS_MIME_LANG_DEFAULT, szDef, ARRAYSIZE(szDef));
wsprintf(sz, szDef, pcpInfo->uiCodePage);
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;
WideCharToMultiByte(CP_ACP, 0, Charset, -1, szCharset, ARRAYSIZE(szCharset), NULL, NULL);
lstrcpy(szKey, REGSTR_KEY_MIME_DATABASE_CHARSET);
lstrcat(szKey, TEXT("\\"));
lstrcat(szKey, szCharset);
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;
MLStrCpyW(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;
MLStrCpyW(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?
}