mimereg.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 29k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. #include "private.h"
  2. #ifdef UNIX
  3. /* Convert from little endian to big endian format */
  4. #define CONVERTLONG(a,b,c,d) (((unsigned long )a) + 
  5.                            ((unsigned long )b << 8) + 
  6.                            ((unsigned long )c << 16) + 
  7.                            ((unsigned long )d << 24))
  8. #endif /* UNIX */
  9. //
  10. //  Globals
  11. //
  12. CMimeDatabaseReg *g_pMimeDatabaseReg = NULL;
  13. //
  14. //  Globals
  15. //
  16. PRFC1766INFOA   g_pRfc1766Reg = NULL;
  17. UINT            g_cRfc1766Reg = 0, g_cMaxRfc1766 = 0;
  18. //
  19. //  Functions
  20. //
  21. void CMimeDatabaseReg::BuildRfc1766Table(void)
  22. {
  23.     HKEY hKey = NULL;
  24.     DWORD dwIndex, dwType, cInfo, cbMaxValueLen, cbLCID, cb;
  25.     TCHAR szLCID[8], sz[MAX_RFC1766_NAME +  MAX_LOCALE_NAME + 1];
  26.     DebugMsg(DM_TRACE, TEXT("CRfc1766::BuildRfc1766Table called."));
  27.     EnterCriticalSection(&g_cs);
  28.     if (NULL == g_pRfc1766Reg)
  29.     {
  30.         if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, REGSTR_KEY_MIME_DATABASE_RFC1766, 0, KEY_READ, &hKey))
  31.         {
  32.             ASSERT(NULL != hKey);
  33.             if (ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, 0, NULL, NULL, NULL, &cInfo, &cbMaxValueLen, NULL, NULL, NULL))
  34.             {
  35.                 g_pRfc1766Reg = (PRFC1766INFOA)LocalAlloc(LPTR, sizeof(RFC1766INFOA) * cInfo);
  36.                 if (NULL != g_pRfc1766Reg)
  37.                 {
  38.                     g_cRfc1766Reg = 0;
  39.                     g_cMaxRfc1766 = cInfo;
  40.                     dwIndex = 0;
  41.                     while (g_cRfc1766Reg < g_cMaxRfc1766)
  42.                     {
  43.                         LONG lRet;
  44.                         cbLCID = ARRAYSIZE(szLCID) - 2;
  45.                         cb = sizeof(sz);
  46.                         lRet = RegEnumValue(hKey, dwIndex++, szLCID + 2, &cbLCID, 0, &dwType, (LPBYTE)sz, &cb);
  47.                         if (ERROR_SUCCESS == lRet)
  48.                         {
  49.                             int iLCID;
  50.                             szLCID[0] = TEXT('0');
  51.                             szLCID[1] = TEXT('x');
  52.                             // BUGBUG: We'd better have private function for this instead of using SHLWAPI becuase 16-bit doesn't have SHLWAPI
  53.                             // if (TRUE == StrToIntEx(szLCID, STIF_SUPPORT_HEX, &iLCID))
  54.                             if (iLCID = HexToNum(szLCID + 2))
  55.                             {
  56.                                 g_pRfc1766Reg[g_cRfc1766Reg].lcid = (LCID)iLCID;
  57.                                 if (REG_SZ == dwType)
  58.                                 {
  59.                                     TCHAR *psz = sz;
  60.                                     while (*psz)
  61.                                     {
  62.                                         if (TEXT(';') == *psz)
  63.                                         {
  64.                                             *psz = TEXT('');
  65.                                             break;
  66.                                         }
  67.                                         psz = CharNext(psz);
  68.                                     }
  69.                                     lstrcpyn(g_pRfc1766Reg[g_cRfc1766Reg].szRfc1766, sz, MAX_RFC1766_NAME);
  70.                                     lstrcpyn(g_pRfc1766Reg[g_cRfc1766Reg].szLocaleName, psz + 1, MAX_LOCALE_NAME);
  71.                                     g_cRfc1766Reg++;
  72.                                 }
  73.                             }
  74.                         }
  75.                         else if (ERROR_NO_MORE_ITEMS == lRet)
  76.                             break;
  77.                     }
  78.                 }
  79.             }
  80.             RegCloseKey(hKey);
  81.         }
  82.     }
  83.     LeaveCriticalSection(&g_cs);
  84. }
  85. void CMimeDatabaseReg::FreeRfc1766Table(void)
  86. {
  87.     DebugMsg(DM_TRACE, TEXT("CRfc1766::FreeRfc1766Table called."));
  88.     EnterCriticalSection(&g_cs);
  89.     if (NULL != g_pRfc1766Reg)
  90.     {
  91.         LocalFree(g_pRfc1766Reg);
  92.         g_pRfc1766Reg = NULL;
  93.         g_cRfc1766Reg = g_cMaxRfc1766 = 0;
  94.     }
  95.     LeaveCriticalSection(&g_cs);
  96. }
  97. void CMimeDatabaseReg::EnsureRfc1766Table(void)
  98. {
  99.     // Ensure g_pRfc1766 is initialized
  100.     if (NULL == g_pRfc1766Reg)
  101.         BuildRfc1766Table();
  102. }
  103. STDAPI CMimeDatabaseReg::LcidToRfc1766A(LCID Locale, LPSTR pszRfc1766, int iMaxLength)
  104. {
  105.     UINT i;
  106.     HRESULT hr = E_INVALIDARG;
  107.     EnsureRfc1766Table();
  108.     if (NULL != pszRfc1766 && 0 < iMaxLength)
  109.     {
  110.         for (i = 0; i < g_cRfc1766Reg; i++)
  111.         {
  112.             if (g_pRfc1766Reg[i].lcid == Locale)
  113.                 break;
  114.         }
  115.         if (i < g_cRfc1766Reg)
  116.         {
  117.             lstrcpyn(pszRfc1766, g_pRfc1766Reg[i].szRfc1766, iMaxLength);
  118.             hr = S_OK;
  119.         }
  120.         else
  121.         {
  122.             TCHAR sz[MAX_RFC1766_NAME];
  123.             if (GetLocaleInfoA(Locale, LOCALE_SABBREVLANGNAME, sz, ARRAYSIZE(sz)))
  124.             {
  125.                 CharLowerA(sz);
  126.                 if (!lstrcmpA(sz, TEXT("cht")))
  127.                     lstrcpynA(pszRfc1766, TEXT("zh-cn"), iMaxLength);
  128.                 else if (!lstrcmpA(sz, TEXT("chs")))
  129.                     lstrcpynA(pszRfc1766, TEXT("zh-tw"), iMaxLength);
  130.                 else if (!lstrcmpA(sz, TEXT("jpn")))
  131.                     lstrcpynA(pszRfc1766, TEXT("ja"), iMaxLength);
  132.                 else
  133.                 {
  134.                     sz[2] = TEXT('');
  135.                     lstrcpynA(pszRfc1766, sz, iMaxLength);
  136.                 }
  137.                 hr = S_OK;
  138.             }
  139.             else
  140.                 hr = E_FAIL;
  141.         }
  142.     }
  143.     return hr;
  144. }    
  145. STDAPI CMimeDatabaseReg::LcidToRfc1766W(LCID Locale, LPWSTR pwszRfc1766, int nChar)
  146. {
  147.     HRESULT hr = E_INVALIDARG;
  148.     if (NULL != pwszRfc1766 && 0 < nChar)
  149.     {
  150.         TCHAR sz[MAX_RFC1766_NAME];
  151.         hr = LcidToRfc1766A(Locale, (LPSTR)sz, ARRAYSIZE(sz));
  152.         if (S_OK == hr)
  153.         {
  154.             int i;
  155.             for (i = 0; i < nChar - 1; i++)
  156.             {
  157.                 pwszRfc1766[i] = (WCHAR)sz[i];
  158.                 if (L'' == pwszRfc1766[i])
  159.                     break;
  160.             }
  161.             if (i == nChar - 1)
  162.                 pwszRfc1766[i] = L'';            
  163.         }
  164.     }
  165.     return hr;
  166. }    
  167. STDAPI CMimeDatabaseReg::Rfc1766ToLcidA(PLCID pLocale, LPCSTR pszRfc1766)
  168. {
  169.     UINT i;
  170.     HRESULT hr = E_INVALIDARG;
  171.     EnsureRfc1766Table();
  172.     if (NULL != pLocale && NULL != pszRfc1766)
  173.     {
  174.         for (i = 0; i < g_cRfc1766Reg; i++)
  175.         {
  176.             if (!lstrcmpi(g_pRfc1766Reg[i].szRfc1766, pszRfc1766))
  177.                 break;
  178.         }
  179.         if (i < g_cRfc1766Reg)
  180.         {
  181.             *pLocale = g_pRfc1766Reg[i].lcid;
  182.             hr = S_OK;
  183.         }
  184.         else
  185.         {
  186.             if (2 < lstrlen(pszRfc1766))
  187.             {
  188.                 TCHAR sz[3];
  189.                 sz[0] = pszRfc1766[0];
  190.                 sz[1] = pszRfc1766[1];
  191.                 sz[2] = TEXT('');
  192.                 for (i = 0; i < g_cRfc1766Reg; i++)
  193.                 {
  194.                     if (!lstrcmpi(g_pRfc1766Reg[i].szRfc1766, sz))
  195.                         break;                
  196.                 }
  197.                 if (i < g_cRfc1766Reg)
  198.                 {
  199.                     *pLocale = g_pRfc1766Reg[i].lcid;
  200.                     hr = S_FALSE;
  201.                 }
  202.                 else
  203.                     hr = E_FAIL;
  204.             }
  205.             else
  206.                 hr = E_FAIL;
  207.         }
  208.     }
  209.     return hr;
  210. }
  211. STDAPI CMimeDatabaseReg::Rfc1766ToLcidW(PLCID pLocale, LPCWSTR pwszRfc1766)
  212. {
  213.     HRESULT hr = E_INVALIDARG;
  214.     if (NULL != pLocale && NULL != pwszRfc1766)
  215.     {
  216.         int i;
  217.         TCHAR sz[MAX_RFC1766_NAME];
  218.         for (i = 0; i < MAX_RFC1766_NAME - 1; i++)
  219.         {
  220.             sz[i] = (TCHAR)pwszRfc1766[i];
  221.             if (TEXT('') == sz[i])
  222.                 break;
  223.         }
  224.         if (i == MAX_RFC1766_NAME -1)
  225.             sz[i] = TEXT('');
  226.         hr = Rfc1766ToLcidA(pLocale, (LPCSTR)sz);
  227.     }
  228.     return hr;
  229. }
  230. //
  231. //  CMimeDatabase implementation
  232. //
  233. CMimeDatabaseReg::CMimeDatabaseReg()
  234. {
  235.     DebugMsg(DM_TRACE, TEXT("constructor of CMimeDatabase 0x%08x"), this);
  236.     _pCodePage = NULL;
  237.     _cCodePage = _cMaxCodePage = 0;
  238.     _pCharset = NULL;
  239.     _cCharset = _cMaxCharset = 0;
  240.     _fAllCPCached = FALSE;
  241.     InitializeCriticalSection(&_cs);
  242. }
  243. CMimeDatabaseReg::~CMimeDatabaseReg()
  244. {
  245.     DebugMsg(DM_TRACE, TEXT("destructor of CMimeDatabase 0x%08x"), this);
  246.     FreeMimeDatabase();
  247.     DeleteCriticalSection(&_cs);
  248. }
  249. void CMimeDatabaseReg::BuildCodePageMimeDatabase(void)
  250. {
  251.     HKEY hKey = NULL;
  252.     DWORD cInfo, cbMaxSubKeyLen;
  253.     DebugMsg(DM_TRACE, TEXT("CMimeDatabase::BuildCodePageMimeDatabase called."));
  254.     // Open CodePage Mime Database Key
  255.     if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, REGSTR_KEY_MIME_DATABASE_CODEPAGE, 0, KEY_READ, &hKey))
  256.     {
  257.         ASSERT(NULL != hKey);
  258.         if (ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, 0, &cInfo, &cbMaxSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL))
  259.         {
  260.             if (NULL == _pCodePage)
  261.             {
  262.                 _pCodePage = (PMIMECPINFO)LocalAlloc(LPTR, sizeof(MIMECPINFO) * cInfo);
  263.                 if (NULL != _pCodePage)
  264.                     _cMaxCodePage = cInfo;
  265.             }
  266.         }
  267.         RegCloseKey(hKey);
  268.         hKey = NULL;
  269.     }
  270. }
  271. void CMimeDatabaseReg::BuildCharsetMimeDatabase(void)
  272. {
  273.     HKEY hKey = NULL;
  274.     DWORD cInfo, cbMaxSubKeyLen;
  275.     DebugMsg(DM_TRACE, TEXT("CMimeDatabase::BuildCharsetMimeDatabase called."));
  276.     // Open Charset Mime Database Key
  277.     if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, REGSTR_KEY_MIME_DATABASE_CHARSET, 0, KEY_READ, &hKey))
  278.     {
  279.         ASSERT(NULL != hKey);
  280.         if (ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, 0, &cInfo, &cbMaxSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL))
  281.         {
  282.             if (NULL == _pCharset)
  283.             {
  284.                 _pCharset = (PMIMECSETINFO)LocalAlloc(LPTR, sizeof(MIMECSETINFO) * cInfo);
  285.                 if (NULL != _pCharset)
  286.                     _cMaxCharset = cInfo;
  287.             }
  288.         }
  289.         RegCloseKey(hKey);
  290.         hKey = NULL;
  291.     }
  292. }
  293. void CMimeDatabaseReg::FreeMimeDatabase(void)
  294. {
  295.     DebugMsg(DM_TRACE, TEXT("CMimeDatabase::FreeMimeDatabase called."));
  296.     EnterCriticalSection(&_cs);
  297.     if (NULL != _pCodePage)
  298.     {
  299.         LocalFree(_pCodePage);
  300.         _pCodePage = NULL;
  301.         _cCodePage = _cMaxCodePage = 0;
  302.     }
  303.     if (NULL != _pCharset)
  304.     {
  305.         LocalFree(_pCharset);
  306.         _pCharset = NULL;
  307.         _cCharset = _cMaxCharset = 0;
  308.     }
  309.     LeaveCriticalSection(&_cs);
  310.     FreeRfc1766Table();
  311. }
  312. STDAPI CMimeDatabaseReg::EnumCodePageInfo(void)
  313. {
  314.     HKEY hKey = NULL;
  315.     DWORD dwIndex = 0;
  316.     MIMECPINFO CPInfo;
  317.     TCHAR szCodePage[15];
  318.     HRESULT hr = S_OK;
  319.     DebugMsg(DM_TRACE, TEXT("CMimeDatabase::EnumCodePageInfo called."));
  320.     EnterCriticalSection(&_cs);
  321.     if (FALSE == _fAllCPCached)
  322.     {
  323.         if (NULL == _pCodePage)
  324.             BuildCodePageMimeDatabase();
  325.         if (_pCodePage)
  326.         {
  327.             // Open CodePage Mime Database Key
  328.             if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, REGSTR_KEY_MIME_DATABASE_CODEPAGE, 0, KEY_READ, &hKey))
  329.             {
  330.                 ASSERT(NULL != hKey);
  331.                 while (ERROR_SUCCESS == RegEnumKey(hKey, dwIndex++, szCodePage, ARRAYSIZE(szCodePage)))
  332.                 {
  333.                     UINT uiCodePage = MLStrToInt(szCodePage);
  334.     
  335.                     if (0 <= FindCodePageFromCache(uiCodePage))
  336.                         continue;
  337.                     if (TRUE == FindCodePageFromRegistry(uiCodePage, &CPInfo))
  338.                     {
  339.                         _pCodePage[_cCodePage] = CPInfo;
  340.                         _cCodePage++;
  341.                     }
  342.                 }
  343.                 _fAllCPCached = TRUE;
  344.                 RegCloseKey(hKey);
  345.                 hKey = NULL;
  346.             }
  347.             if (0 < _cCodePage)
  348.                 QSortCodePageInfo(0, _cCodePage-1);
  349.             // Fill empty font face field base on its FamilyCodePage
  350.             for (UINT i = 0; i < _cCodePage; i++)
  351.             {
  352.                 UINT uiFamily;
  353.                 WCHAR wszFixed[MAX_MIMEFACE_NAME], wszProp[MAX_MIMEFACE_NAME];
  354.                 uiFamily = 0;
  355.                 wszFixed[0] = wszProp[0] = TEXT('');
  356.                 if (TEXT('') == _pCodePage[i].wszFixedWidthFont[0] || TEXT('') == _pCodePage[i].wszProportionalFont[0])
  357.                 {
  358.                     if (uiFamily != _pCodePage[i].uiFamilyCodePage)
  359.                     {
  360.                         for (UINT j = 0; j < _cCodePage; j++)
  361.                         {
  362.                             if (_pCodePage[i].uiFamilyCodePage == _pCodePage[j].uiCodePage)
  363.                             {
  364.                                 uiFamily = _pCodePage[j].uiCodePage;
  365.                                 MLStrCpyNW(wszFixed, _pCodePage[j].wszFixedWidthFont, MAX_MIMEFACE_NAME);
  366.                                 MLStrCpyNW(wszProp, _pCodePage[j].wszProportionalFont, MAX_MIMEFACE_NAME);
  367.                                 break;
  368.                             }
  369.                         }                
  370.                     }
  371.                     MLStrCpyNW(_pCodePage[i].wszFixedWidthFont, wszFixed, MAX_MIMEFACE_NAME);
  372.                     MLStrCpyNW(_pCodePage[i].wszProportionalFont, wszProp, MAX_MIMEFACE_NAME);
  373.                 }
  374.             }
  375.         }
  376.         else
  377.         {
  378.             hr = E_OUTOFMEMORY;
  379.         }
  380.     }
  381.     LeaveCriticalSection(&_cs);
  382.     return hr;
  383. }
  384. STDAPI CMimeDatabaseReg::GetNumberOfCodePageInfo(UINT *pcCodePage)
  385. {
  386.     EnterCriticalSection(&_cs);
  387.     if (NULL == _pCodePage)
  388.         BuildCodePageMimeDatabase();
  389.     *pcCodePage = _cMaxCodePage;
  390.     LeaveCriticalSection(&_cs);
  391.     return NOERROR;
  392. }
  393. STDAPI CMimeDatabaseReg::GetCodePageInfo(UINT uiCodePage, PMIMECPINFO pcpInfo)
  394. {
  395.     int idx;
  396.     HRESULT hr = E_FAIL;
  397.     DebugMsg(DM_TRACE, TEXT("CMimeDatabase::GetCodePageInfo called."));
  398.     if (NULL != pcpInfo)
  399.     {
  400.         EnterCriticalSection(&_cs);
  401.         if (NULL == _pCodePage)
  402.             BuildCodePageMimeDatabase();
  403.         if (_pCodePage)
  404.         {
  405.             idx = FindCodePageFromCache(uiCodePage);
  406.             if (0 > idx)
  407.             {
  408.                 MIMECPINFO CPInfo = {0};
  409.                 if (TRUE == FindCodePageFromRegistry(uiCodePage, &CPInfo))
  410.                 {
  411.                     if (CPInfo.uiCodePage != CPInfo.uiFamilyCodePage)
  412.                     {
  413.                         idx = FindCodePageFromCache(CPInfo.uiFamilyCodePage);
  414.                         if (0 > idx)
  415.                         {
  416.                             MIMECPINFO FamilyCPInfo;
  417.                             if (TRUE == FindCodePageFromRegistry(CPInfo.uiFamilyCodePage, &FamilyCPInfo))
  418.                             {
  419.                                 idx = _cCodePage;
  420.                                 _pCodePage[_cCodePage] = FamilyCPInfo;
  421.                                 _cCodePage++;
  422.                             }
  423.                         }
  424.                         MLStrCpyNW(CPInfo.wszFixedWidthFont, _pCodePage[idx].wszFixedWidthFont, MAX_MIMEFACE_NAME);
  425.                         MLStrCpyNW(CPInfo.wszProportionalFont, _pCodePage[idx].wszProportionalFont, MAX_MIMEFACE_NAME);
  426.                     }
  427.                     _pCodePage[_cCodePage] = CPInfo;
  428.                     _cCodePage++;
  429.                     QSortCodePageInfo(0, _cCodePage-1);
  430.                     idx = FindCodePageFromCache(uiCodePage);
  431.                 }
  432.             }
  433.             if (0 <= idx)
  434.             {
  435.                 *pcpInfo = _pCodePage[idx];
  436.                 hr = S_OK;
  437.             }
  438.             LeaveCriticalSection(&_cs);
  439.         }
  440.     }
  441.     return hr;
  442. }
  443. int CMimeDatabaseReg::FindCodePageFromCache(UINT uiCodePage)
  444. {
  445.     UINT i;
  446.     int iRet = -1;
  447.     for (i = 0; i < _cCodePage; i++)
  448.     {
  449.         if (_pCodePage[i].uiCodePage == uiCodePage)
  450.         {
  451.             iRet = i;
  452.             break;
  453.         }
  454.     }
  455.     return iRet;
  456. }
  457. BOOL CMimeDatabaseReg::FindCodePageFromRegistry(UINT uiCodePage, PMIMECPINFO pcpInfo)
  458. {
  459.     HKEY hKey;
  460.     DWORD dw, cb;
  461.     TCHAR szKey[256],  sz[MAX_MIMECP_NAME];
  462.     BOOL fRet = FALSE;
  463.     static UINT s_uiCP = GetACP();
  464.     wsprintf(szKey, TEXT("%s\%d"), REGSTR_KEY_MIME_DATABASE_CODEPAGE, uiCodePage);
  465.     if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hKey))
  466.     {
  467.         TCHAR *psz, *pszComma;
  468.         CHARSETINFO rCharsetInfo;
  469.         pcpInfo->uiCodePage = uiCodePage;
  470.         cb = sizeof(dw);
  471.         if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_FAMILY, 0, NULL, (LPBYTE)&dw, &cb))
  472.             pcpInfo->uiFamilyCodePage = (UINT)dw;
  473.         else
  474.             pcpInfo->uiFamilyCodePage = pcpInfo->uiCodePage;
  475.         cb = sizeof(dw);
  476.         if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_LEVEL, 0, NULL, (LPBYTE)&dw, &cb))
  477. #ifdef UNIX
  478.         {
  479.            BYTE* px = (BYTE*)&dw;
  480.            pcpInfo->dwFlags = CONVERTLONG(px[0], px[1], px[2], px[3]);
  481.         }
  482. #else
  483.             pcpInfo->dwFlags = dw;
  484. #endif /* UNIX */
  485.         else
  486.             pcpInfo->dwFlags = 0;
  487.         cb = sizeof(sz);
  488.         if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_DESCRIPTION, NULL, NULL, (LPBYTE)sz, &cb))
  489.             MultiByteToWideChar(CP_ACP, 0, sz, -1, pcpInfo->wszDescription, ARRAYSIZE(pcpInfo->wszDescription));
  490.         else
  491.         {
  492.             TCHAR szDef[MAX_MIMECP_NAME];
  493.             LoadString(g_hInst, IDS_MIME_LANG_DEFAULT, szDef, ARRAYSIZE(szDef));
  494.             wsprintf(sz, szDef, pcpInfo->uiCodePage);
  495.             MultiByteToWideChar(CP_ACP, 0, sz, -1, pcpInfo->wszDescription, ARRAYSIZE(pcpInfo->wszDescription));
  496.         }
  497.         cb = sizeof(sz);
  498.         if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_FIXEDWIDTHFONT, NULL, NULL, (LPBYTE)sz, &cb))
  499.         {
  500.             psz = sz;
  501.             pszComma =  MLStrChr(sz, TEXT(','));
  502.             if (NULL != pszComma)               // If there are multiple font name
  503.             {
  504.                 if (uiCodePage != s_uiCP)
  505.                     psz = pszComma + 1;         // Take right side(English) fontname for non-native codepage info
  506.                 else
  507.                     *pszComma = TEXT('');     // Take left side(DBCS) fontname for native codepage info
  508.             }
  509.             if (lstrlen(psz) >= MAX_MIMEFACE_NAME)
  510.                 psz[MAX_MIMEFACE_NAME-1] = TEXT('');
  511.             MultiByteToWideChar(CP_ACP, 0, psz, -1, pcpInfo->wszFixedWidthFont, ARRAYSIZE(pcpInfo->wszFixedWidthFont));
  512.         }
  513.         else
  514.             pcpInfo->wszFixedWidthFont[0] = L'';
  515.         cb = sizeof(sz);
  516.         if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_PROPORTIONALFONT, NULL, NULL, (LPBYTE)sz, &cb))
  517.         {
  518.             psz = sz;
  519.             pszComma = MLStrChr(sz, TEXT(','));
  520.             if (NULL != pszComma)               // If there are multiple font name
  521.             {
  522.                 if (uiCodePage != s_uiCP)
  523.                     psz = pszComma + 1;         // Take right side(English) fontname for non-native codepage info
  524.                 else
  525.                     *pszComma = TEXT('');     // Take left side(DBCS) fontname for native codepage info
  526.             }
  527.             if (lstrlen(psz) >= MAX_MIMEFACE_NAME)
  528.                 psz[MAX_MIMEFACE_NAME-1] = TEXT('');
  529.             MultiByteToWideChar(CP_ACP, 0, psz, -1, pcpInfo->wszProportionalFont, ARRAYSIZE(pcpInfo->wszProportionalFont));
  530.         }
  531.         else
  532.             pcpInfo->wszProportionalFont[0] = L'';
  533.         cb = sizeof(sz);
  534.         if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_BODYCHARSET, NULL, NULL, (LPBYTE)sz, &cb))
  535.             MultiByteToWideChar(CP_ACP, 0, sz, -1, pcpInfo->wszBodyCharset, ARRAYSIZE(pcpInfo->wszBodyCharset));
  536.         else
  537.             pcpInfo->wszBodyCharset[0] = L'';
  538.         cb = sizeof(sz);
  539.         if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_HEADERCHARSET, NULL, NULL, (LPBYTE)sz, &cb))
  540.             MultiByteToWideChar(CP_ACP, 0, sz, -1, pcpInfo->wszHeaderCharset, ARRAYSIZE(pcpInfo->wszHeaderCharset));
  541.         else
  542.             MLStrCpyNW(pcpInfo->wszHeaderCharset, pcpInfo->wszBodyCharset, MAX_MIMECSET_NAME);
  543.         cb = sizeof(sz);
  544.         if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_WEBCHARSET, NULL, NULL, (LPBYTE)sz, &cb))
  545.             MultiByteToWideChar(CP_ACP, 0, sz, -1, pcpInfo->wszWebCharset, ARRAYSIZE(pcpInfo->wszWebCharset));
  546.         else
  547.             MLStrCpyNW(pcpInfo->wszWebCharset, pcpInfo->wszBodyCharset, MAX_MIMECSET_NAME);
  548.         cb = sizeof(sz);
  549.         if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_PRIVCONVERTER, NULL, NULL, (LPBYTE)sz, &cb))
  550.             pcpInfo->dwFlags |= MIMECONTF_PRIVCONVERTER;
  551.         if (0 != TranslateCharsetInfo((LPDWORD)pcpInfo->uiFamilyCodePage, &rCharsetInfo, TCI_SRCCODEPAGE))
  552.             pcpInfo->bGDICharset = (BYTE)rCharsetInfo.ciCharset;
  553.         else
  554.             pcpInfo->bGDICharset = DEFAULT_CHARSET;
  555.         if (1200 == pcpInfo->uiFamilyCodePage || 50000 == pcpInfo->uiFamilyCodePage || TRUE == _IsValidCodePage(pcpInfo->uiFamilyCodePage)) // 50000 means user defined
  556.         {
  557.             if (TRUE == CheckFont(pcpInfo->bGDICharset))
  558.             {
  559.                 if (pcpInfo->uiCodePage == pcpInfo->uiFamilyCodePage || TRUE == _IsValidCodePage(pcpInfo->uiCodePage))
  560.                     pcpInfo->dwFlags |= MIMECONTF_VALID|MIMECONTF_VALID;
  561.                 else if (S_OK == IsConvertINetStringAvailable(pcpInfo->uiCodePage, pcpInfo->uiFamilyCodePage))
  562.                     pcpInfo->dwFlags |= MIMECONTF_VALID|MIMECONTF_VALID;
  563.             }
  564.             else
  565.             {
  566.                 if (pcpInfo->uiCodePage == pcpInfo->uiFamilyCodePage || TRUE == _IsValidCodePage(pcpInfo->uiCodePage))
  567.                     pcpInfo->dwFlags |= MIMECONTF_VALID_NLS;
  568.                 else if (S_OK == IsConvertINetStringAvailable(pcpInfo->uiCodePage, pcpInfo->uiFamilyCodePage))
  569.                     pcpInfo->dwFlags |= MIMECONTF_VALID_NLS;
  570.             }
  571.         }
  572.         RegCloseKey(hKey);
  573.         fRet = TRUE;
  574.     }
  575.     return fRet;
  576. }
  577. STDAPI CMimeDatabaseReg::GetCodePageInfoWithIndex(UINT uidx, PMIMECPINFO pcpInfo)
  578. {
  579.     HRESULT hr = NOERROR;
  580.     DebugMsg(DM_TRACE, TEXT("CMimeDatabase::GetCodePageInfoWithIndex called."));
  581.     EnterCriticalSection(&_cs);
  582.     if (NULL == _pCodePage)
  583.         BuildCodePageMimeDatabase();
  584.     if (uidx < _cCodePage && _pCodePage)
  585.         *pcpInfo = _pCodePage[uidx];
  586.     else
  587.         hr = E_FAIL;
  588.     LeaveCriticalSection(&_cs);
  589.     return hr;
  590. }
  591. STDAPI CMimeDatabaseReg::GetCharsetInfo(BSTR Charset, PMIMECSETINFO pcsetInfo)
  592. {
  593.     int idx;
  594.     HRESULT hr = E_FAIL;
  595.     DebugMsg(DM_TRACE, TEXT("CMimeDatabase::GetCharsetInfo called."));
  596.     if (NULL != pcsetInfo)
  597.     {
  598.         EnterCriticalSection(&_cs);
  599.         if (NULL == _pCharset)
  600.             BuildCharsetMimeDatabase();
  601.         if (_pCharset)
  602.         {
  603.             idx = FindCharsetFromCache(Charset);
  604.             if (0 > idx)
  605.                 idx = FindCharsetFromRegistry(Charset, FALSE);
  606.             if (0 <= idx)
  607.             {
  608.                 *pcsetInfo = _pCharset[idx];
  609.                 hr = S_OK;
  610.             }
  611.         }
  612.         LeaveCriticalSection(&_cs);
  613.     }
  614.     return hr;
  615. }
  616. int CMimeDatabaseReg::FindCharsetFromCache(BSTR Charset)
  617. {
  618.     int iStart, iEnd, iMiddle, iCmpResult, iRet = -1;
  619.     iStart = 0;
  620.     iEnd = _cCharset - 1;
  621.     while (iStart <= iEnd)
  622.     {
  623.         iMiddle = (iStart + iEnd) / 2;
  624.         iCmpResult = MLStrCmpIW(Charset, _pCharset[iMiddle].wszCharset);
  625.         if (iCmpResult < 0)
  626.             iEnd = iMiddle - 1;
  627.         else if (iCmpResult > 0)
  628.             iStart = iMiddle + 1;
  629.         else
  630.         {
  631.             iRet = iMiddle;
  632.             break;
  633.         }
  634.     }
  635.     return iRet;
  636. }
  637. int CMimeDatabaseReg::FindCharsetFromRegistry(BSTR Charset, BOOL fFromAlias)
  638. {
  639.     HKEY hKey;
  640.     TCHAR szKey[256], szCharset[MAX_MIMECSET_NAME];
  641.     int iRet = -1;
  642.     WideCharToMultiByte(CP_ACP, 0, Charset, -1, szCharset, ARRAYSIZE(szCharset), NULL, NULL);
  643.     lstrcpy(szKey, REGSTR_KEY_MIME_DATABASE_CHARSET);
  644.     lstrcat(szKey, TEXT("\"));
  645.     lstrcat(szKey, szCharset);
  646.     if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hKey))
  647.     {
  648.         DWORD cb, dw;
  649.         TCHAR sz[MAX_MIMECSET_NAME];
  650.         WCHAR wsz[MAX_MIMECSET_NAME];
  651.         cb = sizeof(sz);
  652.         if (FALSE == fFromAlias && ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_ALIASTO, NULL, NULL, (LPBYTE)sz, &cb))
  653.         {
  654.             MultiByteToWideChar(CP_ACP, 0, sz, -1, wsz, ARRAYSIZE(wsz));
  655.             iRet = FindCharsetFromCache(wsz);
  656.             if (0 > iRet)
  657.                 iRet = FindCharsetFromRegistry(wsz, TRUE);
  658.             if (0 <= iRet)
  659.             {
  660.                 MLStrCpyNW(_pCharset[_cCharset].wszCharset, Charset, MAX_MIMECSET_NAME);
  661.                 _pCharset[_cCharset].uiCodePage = _pCharset[iRet].uiCodePage;
  662.                 _pCharset[_cCharset].uiInternetEncoding = _pCharset[iRet].uiInternetEncoding;
  663.                 _cCharset++;
  664.                 QSortCharsetInfo(0, _cCharset-1);
  665.                 iRet = FindCharsetFromCache(Charset);
  666.             }
  667.         }
  668.         else
  669.         {
  670.             MLStrCpyNW(_pCharset[_cCharset].wszCharset, Charset, MAX_MIMECSET_NAME);
  671.             cb = sizeof(dw);
  672.             if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_CODEPAGE, 0, NULL, (LPBYTE)&dw, &cb))
  673.             {
  674.                 _pCharset[_cCharset].uiCodePage = (UINT)dw;
  675.                 cb = sizeof(dw);
  676.                 if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_INETENCODING, 0, NULL, (LPBYTE)&dw, &cb))
  677.                 {
  678.                     _pCharset[_cCharset].uiInternetEncoding = (UINT)dw;
  679.                     _cCharset++;
  680.                     QSortCharsetInfo(0, _cCharset-1);
  681.                     iRet = FindCharsetFromCache(Charset);
  682.                 }
  683.             }
  684.         }
  685.         RegCloseKey(hKey);
  686.     }
  687.     return iRet;
  688. }
  689. BOOL CMimeDatabaseReg::CheckFont(BYTE bGDICharset)
  690. {
  691.     BOOL fRet = FALSE;
  692.     DebugMsg(DM_TRACE, TEXT("CMimeDatabase::CheckFont called."));
  693.     if (DEFAULT_CHARSET == bGDICharset)
  694.         fRet = TRUE;
  695.     else
  696.     {
  697.         HDC     hDC;
  698.         LOGFONT lf;
  699.         HWND    hWnd;
  700.         hWnd = GetTopWindow(GetDesktopWindow());
  701.         hDC = GetDC(hWnd);
  702.         if (NULL != hDC)
  703.         {
  704.             lf.lfFaceName[0] = TEXT('');
  705.             lf.lfPitchAndFamily = 0;
  706.             lf.lfCharSet = bGDICharset;
  707.             EnumFontFamiliesEx(hDC, &lf, (FONTENUMPROC)EnumFontFamExProc, (LPARAM)&fRet, 0);
  708.         }
  709.         ReleaseDC(hWnd, hDC);
  710.     }
  711.     return fRet;
  712. }
  713. void CMimeDatabaseReg::QSortCodePageInfo(LONG left, LONG right)
  714. {
  715.     register LONG i, j;
  716.     WCHAR k[MAX_MIMECP_NAME];
  717.     MIMECPINFO t;
  718.     DebugMsg(DM_TRACE, TEXT("CMimeDatabase::QSortCodePageInfo called."));
  719.     i = left;
  720.     j = right;
  721.     MLStrCpyW(k, _pCodePage[(left + right) / 2].wszDescription);
  722.     do  
  723.     {
  724.         while(MLStrCmpIW(_pCodePage[i].wszDescription, k) < 0 && i < right)
  725.             i++;
  726.         while (MLStrCmpIW(_pCodePage[j].wszDescription, k) > 0 && j > left)
  727.             j--;
  728.         if (i <= j)
  729.         {
  730.             t = _pCodePage[i];
  731.             _pCodePage[i] = _pCodePage[j];
  732.             _pCodePage[j] = t;
  733.             i++; j--;
  734.         }
  735.     } while (i <= j);
  736.     if (left < j)
  737.         QSortCodePageInfo(left, j);
  738.     if (i < right)
  739.         QSortCodePageInfo(i, right);
  740. }
  741. void CMimeDatabaseReg::QSortCharsetInfo(LONG left, LONG right)
  742. {
  743.     register LONG i, j;
  744.     WCHAR k[MAX_MIMECSET_NAME];
  745.     MIMECSETINFO t;
  746.     DebugMsg(DM_TRACE, TEXT("CMimeDatabase::QSortCharsetInfo called."));
  747.     i = left;
  748.     j = right;
  749.     MLStrCpyW(k, _pCharset[(left + right) / 2].wszCharset);
  750.     do  
  751.     {
  752.         while(MLStrCmpIW(_pCharset[i].wszCharset, k) < 0 && i < right)
  753.             i++;
  754.         while (MLStrCmpIW(_pCharset[j].wszCharset, k) > 0 && j > left)
  755.             j--;
  756.         if (i <= j)
  757.         {
  758.             t = _pCharset[i];
  759.             _pCharset[i] = _pCharset[j];
  760.             _pCharset[j] = t;
  761.             i++; j--;
  762.         }
  763.     } while (i <= j);
  764.     if (left < j)
  765.         QSortCharsetInfo(left, j);
  766.     if (i < right)
  767.         QSortCharsetInfo(i, right);
  768. }
  769. // validates all cps that are in the same
  770. // family of the given codepage
  771. STDAPI CMimeDatabaseReg::ValidateCP(UINT uiCodePage)
  772. {
  773.     UINT i;
  774.     if (NULL == _pCodePage)
  775.         BuildCodePageMimeDatabase();
  776.     //
  777.     // just look into already cached codepages
  778.     // 
  779.     for (i = 0; i < _cCodePage; i++)
  780.     {
  781.         if (_pCodePage[i].uiFamilyCodePage == uiCodePage)
  782.             _pCodePage[i].dwFlags |=  MIMECONTF_VALID|MIMECONTF_VALID_NLS;
  783.     }
  784.         
  785.     return S_OK; // never fail?
  786. }