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

Windows Kernel

Development Platform:

Visual C++

  1. // Util.cpp : Helper functions and classes
  2. #include "private.h"
  3. #include "mlmain.h"
  4. #include <setupapi.h>
  5. #include <tchar.h>
  6. const CLSID CLSID_Japanese =  {0x76C19B30,0xF0C8,0x11cf,{0x87,0xCC,0x00,0x20,0xAF,0xEE,0xCF,0x20}};
  7. const CLSID CLSID_Korean   =  {0x76C19B31,0xF0C8,0x11cf,{0x87,0xCC,0x00,0x20,0xAF,0xEE,0xCF,0x20}};
  8. const CLSID CLSID_PanEuro  =  {0x76C19B32,0xF0C8,0x11cf,{0x87,0xCC,0x00,0x20,0xAF,0xEE,0xCF,0x20}};
  9. const CLSID CLSID_TradChinese = {0x76C19B33,0xF0C8,0x11cf,{0x87,0xCC,0x00,0x20,0xAF,0xEE,0xCF,0x20}};
  10. const CLSID CLSID_SimpChinese = {0x76C19B34,0xF0C8,0x11cf,{0x87,0xCC,0x00,0x20,0xAF,0xEE,0xCF,0x20}};
  11. const CLSID CLSID_Thai        = {0x76C19B35,0xF0C8,0x11cf,{0x87,0xCC,0x00,0x20,0xAF,0xEE,0xCF,0x20}};
  12. const CLSID CLSID_Hebrew      = {0x76C19B36,0xF0C8,0x11cf,{0x87,0xCC,0x00,0x20,0xAF,0xEE,0xCF,0x20}};
  13. const CLSID CLSID_Vietnamese  = {0x76C19B37,0xF0C8,0x11cf,{0x87,0xCC,0x00,0x20,0xAF,0xEE,0xCF,0x20}};
  14. const CLSID CLSID_Arabic      = {0x76C19B38,0xF0C8,0x11cf,{0x87,0xCC,0x00,0x20,0xAF,0xEE,0xCF,0x20}};
  15. const CLSID CLSID_Auto        = {0x76C19B50,0xF0C8,0x11cf,{0x87,0xCC,0x00,0x20,0xAF,0xEE,0xCF,0x20}};
  16. TCHAR szFonts[]=TEXT("fonts");
  17. static TCHAR s_szJaFont[] = TEXT("msgothic.ttf,msgothic.ttc");
  18. // a-ehuang: mail-Hyo Kyoung Kim-Kevin Gjerstad-9/14/98
  19. // OLD: static TCHAR s_szKorFont[] = TEXT("gulimche.ttf, gulim.ttf,gulim.ttc");
  20. static TCHAR s_szKorFont[] = TEXT("gulim.ttf,gulim.ttc,gulimche.ttf");
  21. // end-of-change
  22. static TCHAR s_szZhtFont[] = TEXT("mingliu.ttf,mingliu.ttc");
  23. static TCHAR s_szZhcFont[] = TEXT("mssong.ttf,simsun.ttc,mshei.ttf");
  24. static TCHAR s_szThaiFont[] = TEXT("angsa.ttf,angsa.ttf,angsab.ttf,angsai.ttf,angsaz.ttf,upcil.ttf,upcib.ttf,upcibi.ttf, cordia.ttf, cordiab.ttf, cordiai.ttf, coradiaz.ttf");
  25. static TCHAR s_szPeFont[] = TEXT("larial.ttf,larialbd.ttf,larialbi.ttf,lariali.ttf,lcour.ttf,lcourbd.ttf,lcourbi.ttf,lcouri.ttf,ltimes.ttf,ltimesbd.ttf,ltimesbi.ttf,ltimesi.ttf,symbol.ttf");
  26. static TCHAR s_szArFont[] = TEXT("andlso.ttf, artrbdo.ttf, artro.ttf, simpbdo.ttf, simpfxo.ttf, tradbdo.ttf, trado.ttf");
  27. static TCHAR s_szViFont[] = TEXT("VARIAL.TTF, VARIALBD.TTF, VARIALBI.TTF, VARIALI.TTF, VCOUR.TTF, VCOURBD.TTF, VCOURBI.TTF, VCOURI.TTF, VTIMES.TTF, VTIMESBD.TTF, VTIMESBI.TTF, VTIMESI.TTF");
  28. static TCHAR s_szIwFont[] = TEXT("DAVID.TTF, DAVIDBD.TTF, DAVIDTR.TTF, MRIAM.TTF, MRIAMC.TTF, MRIAMFX.TTF, MRIAMTR.TTF, ROD.TTF");
  29. #ifdef NEWMLSTR
  30. #include "util.h"
  31. /////////////////////////////////////////////////////////////////////////////
  32. // Helper functions
  33. HRESULT RegularizePosLen(long lStrLen, long* plPos, long* plLen)
  34. {
  35.     ASSERT_WRITE_PTR(plPos);
  36.     ASSERT_WRITE_PTR(plLen);
  37.     long lPos = *plPos;
  38.     long lLen = *plLen;
  39.     if (lPos < 0)
  40.         lPos = lStrLen;
  41.     else
  42.         lPos = min(lPos, lStrLen);
  43.     if (lLen < 0)
  44.         lLen = lStrLen - lPos;
  45.     else
  46.         lLen = min(lLen, lStrLen - lPos);
  47.     *plPos = lPos;
  48.     *plLen = lLen;
  49.     return S_OK;
  50. }
  51. HRESULT LocaleToCodePage(LCID locale, UINT* puCodePage)
  52. {
  53.     HRESULT hr = S_OK;
  54.     if (puCodePage)
  55.     {
  56.         TCHAR szCodePage[8];
  57.         if (::GetLocaleInfo(locale, LOCALE_IDEFAULTANSICODEPAGE, szCodePage, ARRAYSIZE(szCodePage)) > 0)
  58.             *puCodePage = _ttoi(szCodePage);
  59.         else
  60.             hr = E_FAIL; // NLS failed
  61.     }
  62.     return hr;
  63. }
  64. HRESULT StartEndConnection(IUnknown* const pUnkCPC, const IID* const piid, IUnknown* const pUnkSink, DWORD* const pdwCookie, DWORD dwCookie)
  65. {
  66.     ASSERT_READ_PTR(pUnkCPC);
  67.     ASSERT_READ_PTR(piid);
  68.     if (pdwCookie)
  69.         ASSERT_WRITE_PTR(pUnkSink);
  70.     ASSERT_READ_PTR_OR_NULL(pdwCookie);
  71.     HRESULT hr;
  72.     IConnectionPointContainer* pcpc;
  73.     if (SUCCEEDED(hr = pUnkCPC->QueryInterface(IID_IConnectionPointContainer, (void**)&pcpc)))
  74.     {
  75.         ASSERT_READ_PTR(pcpc);
  76.         IConnectionPoint* pcp;
  77.         if (SUCCEEDED(hr = pcpc->FindConnectionPoint(*piid, &pcp)))
  78.         {
  79.             ASSERT_READ_PTR(pcp);
  80.             if (pdwCookie)
  81.                 hr = pcp->Advise(pUnkSink, pdwCookie);
  82.             else
  83.                 hr = pcp->Unadvise(dwCookie);
  84.             pcp->Release();
  85.         }
  86.         pcpc->Release();
  87.     }
  88.     return hr;
  89. }
  90. /////////////////////////////////////////////////////////////////////////////
  91. // CMLAlloc
  92. CMLAlloc::CMLAlloc(void)
  93. {
  94.     if (FAILED(::CoGetMalloc(1, &m_pIMalloc)))
  95.         m_pIMalloc = NULL;
  96. }
  97. CMLAlloc::~CMLAlloc(void)
  98. {
  99.     if (m_pIMalloc)
  100.         m_pIMalloc->Release();
  101. }
  102. void* CMLAlloc::Alloc(ULONG cb)
  103. {
  104.     if (m_pIMalloc)
  105.         return m_pIMalloc->Alloc(cb);
  106.     else
  107.         return ::malloc(cb);
  108. }
  109. void* CMLAlloc::Realloc(void* pv, ULONG cb)
  110. {
  111.     if (m_pIMalloc)
  112.         return m_pIMalloc->Realloc(pv, cb);
  113.     else
  114.         return ::realloc(pv, cb);
  115. }
  116. void CMLAlloc::Free(void* pv)
  117. {
  118.     if (m_pIMalloc)
  119.         m_pIMalloc->Free(pv);
  120.     else
  121.         ::free(pv);
  122. }
  123. /////////////////////////////////////////////////////////////////////////////
  124. // CMLList
  125. HRESULT CMLList::Add(void** ppv)
  126. {
  127.     if (!m_pFree) // No free cell
  128.     {
  129.         // Determine new size of the buffer
  130.         const int cNewCell = (m_cbCell * m_cCell + m_cbIncrement + m_cbCell - 1) / m_cbCell;
  131.         ASSERT(cNewCell > m_cCell);
  132.         const long lNewSize = cNewCell * m_cbCell;
  133.         // Allocate the buffer
  134.         void *pNewBuf;
  135.         if (!m_pBuf)
  136.         {
  137.             pNewBuf = MemAlloc(lNewSize);
  138.         }
  139.         else
  140.         {
  141.             pNewBuf = MemRealloc((void*)m_pBuf, lNewSize);
  142.             ASSERT(m_pBuf == pNewBuf);
  143.         }
  144.         ASSERT_WRITE_BLOCK_OR_NULL((BYTE*)pNewBuf, lNewSize);
  145.         if (pNewBuf)
  146.         {
  147.             // Add new cells to free link
  148.             m_pFree = m_pBuf[m_cCell].m_pNext;
  149.             for (int iCell = m_cCell; iCell + 1 < cNewCell; iCell++)
  150.                 m_pBuf[iCell].m_pNext = &m_pBuf[iCell + 1];
  151.             m_pBuf[iCell].m_pNext = NULL;
  152.             m_pBuf = (CCell*)pNewBuf;
  153.             m_cCell = cNewCell;
  154.         }
  155.     }
  156.     if (m_pFree)
  157.     {
  158.         // Get a new element from free link
  159.         CCell* const pNewCell = m_pFree;
  160.         m_pFree = pNewCell->m_pNext;
  161.         *ppv = pNewCell;
  162.         return S_OK;
  163.     }
  164.     else
  165.     {
  166.         *ppv = NULL;
  167.         return E_OUTOFMEMORY;
  168.     }
  169. }
  170. HRESULT CMLList::Remove(void* pv)
  171. {
  172.     AssertPV(pv);
  173. #ifdef DEBUG
  174.     for (CCell* pWalk = m_pFree; pWalk && pWalk != pv; pWalk = pWalk->m_pNext)
  175.         ;
  176.     ASSERT(!pWalk); // pv is already in free link
  177. #endif
  178.     CCell* const pCell = (CCell* const)pv;
  179.     pCell->m_pNext = m_pFree;
  180.     m_pFree = pCell;
  181.     return S_OK;
  182. }
  183. /////////////////////////////////////////////////////////////////////////////
  184. // CMLListLru
  185. HRESULT CMLListLru::Add(void** ppv)
  186. {
  187.     HRESULT hr;
  188.     CCell* pCell;
  189.     
  190.     if (SUCCEEDED(hr = CMLList::Add((void**)&pCell)))
  191.     {
  192.         // Add the cell at the bottom of LRU link
  193.         for (CCell** ppCell = &m_pTop; *ppCell; ppCell = &(*ppCell)->m_pNext)
  194.             ;
  195.         *ppCell = pCell;
  196.         pCell->m_pNext = NULL;
  197.     }
  198.     *ppv = (void*)pCell;
  199.     return hr;
  200. }
  201. HRESULT CMLListLru::Remove(void* pv)
  202. {
  203.     AssertPV(pv);
  204.     // Look for previous cell of given
  205.     for (CCell** ppWalk = &m_pTop; *ppWalk != pv && *ppWalk; ppWalk = &(*ppWalk)->m_pNext)
  206.         ;
  207.     ASSERT(!*ppWalk); // Not found in LRU link
  208.     if (*ppWalk)
  209.     {
  210.         // Remove from LRU link
  211.         CCell* const pCell = *ppWalk;
  212.         *ppWalk = pCell->m_pNext;
  213.     }
  214.     // Add to free link
  215.     return CMLList::Remove(pv);
  216. }
  217. /////////////////////////////////////////////////////////////////////////////
  218. // CMLListFast
  219. HRESULT CMLListFast::Add(void** ppv)
  220. {
  221.     HRESULT hr;
  222.     CCell* pCell;
  223.     
  224.     if (SUCCEEDED(hr = CMLList::Add((void**)&pCell)))
  225.     {
  226.         // Add to top of double link
  227.         pCell->m_pNext = m_pTop;
  228.         CCell* const pPrev = m_pTop->m_pPrev;
  229.         pCell->m_pPrev = pPrev;
  230.         m_pTop = pCell;
  231.         pPrev->m_pNext = pCell;
  232.     }
  233.     *ppv = (void*)pCell;
  234.     return hr;
  235. }
  236. HRESULT CMLListFast::Remove(void* pv)
  237. {
  238.     AssertPV(pv);
  239.     // Remove from double link
  240.     CCell* const pCell = (CCell*)pv;
  241.     CCell* const pPrev = pCell->m_pPrev;
  242.     CCell* const pNext = (CCell*)pCell->m_pNext;
  243.     pPrev->m_pNext = pNext;
  244.     pNext->m_pPrev = pPrev;
  245.     // Add to free link
  246.     return CMLList::Remove(pv);
  247. }
  248. #endif // NEWMLSTR
  249. HRESULT 
  250. _FaultInIEFeature(HWND hwnd, uCLSSPEC *pclsspec, QUERYCONTEXT *pQ, DWORD dwFlags)
  251. {
  252.     HRESULT hr = E_FAIL;
  253.     typedef HRESULT (WINAPI *PFNJIT)(
  254.         HWND hwnd, 
  255.         uCLSSPEC *pclsspec, 
  256.         QUERYCONTEXT *pQ, 
  257.         DWORD dwFlags);
  258.     static PFNJIT  pfnJIT = NULL;
  259.     if (!pfnJIT && !g_hUrlMon)
  260.     {
  261.         g_hUrlMon = LoadLibrary(TEXT("urlmon.DLL"));
  262.         if (g_hUrlMon)
  263.             pfnJIT = (PFNJIT)GetProcAddress(g_hUrlMon, "FaultInIEFeature");
  264.     }
  265.     
  266.     if (pfnJIT)
  267.        hr = pfnJIT(hwnd, pclsspec, pQ, dwFlags);
  268.        
  269.     return hr;
  270. }
  271. HRESULT InstallIEFeature(HWND hWnd, CLSID *clsid, DWORD dwfIODControl)
  272. {
  273.    
  274.     HRESULT     hr  = REGDB_E_CLASSNOTREG;
  275.     uCLSSPEC    classpec;
  276.     DWORD       dwfIEF = 0;
  277.     
  278.     classpec.tyspec=TYSPEC_CLSID;
  279.     classpec.tagged_union.clsid=*clsid;
  280.     if (dwfIODControl & CPIOD_PEEK)
  281.         dwfIEF |= FIEF_FLAG_PEEK;
  282.     if (dwfIODControl & CPIOD_FORCE_PROMPT)
  283.         dwfIEF |= FIEF_FLAG_FORCE_JITUI;
  284.     hr = _FaultInIEFeature(hWnd, &classpec, NULL, dwfIEF);
  285.     if (hr != S_OK) {
  286.         hr = REGDB_E_CLASSNOTREG;
  287.     }
  288.     return hr;
  289. }
  290. HRESULT _GetJITClsIDForCodePage(UINT uiCP, CLSID *clsid)
  291. {
  292.     switch(uiCP)
  293.     {
  294.         case 932: // JA
  295.             *clsid = CLSID_Japanese;
  296.             break;
  297.         case 949: // KOR
  298.             *clsid = CLSID_Korean;
  299.             break;
  300.         case 950: // ZHT
  301.             *clsid = CLSID_TradChinese;
  302.             break;
  303.         case 936: // ZHC
  304.             *clsid = CLSID_SimpChinese;
  305.             break;
  306.         case 874:
  307.             *clsid = CLSID_Thai;
  308.             break;
  309.         case 1255:
  310.             *clsid = CLSID_Hebrew;
  311.             break;
  312.         case 1256:
  313.             *clsid = CLSID_Arabic;
  314.             break;
  315.         case 1258:
  316.             *clsid = CLSID_Vietnamese;
  317.             break;            
  318.         case 1250:    // PANEURO
  319.         case 1251: 
  320.         case 1253:
  321.         case 1254:
  322.         case 1257:
  323.             *clsid = CLSID_PanEuro;
  324.             break;
  325.         case 50001:
  326.             *clsid = CLSID_Auto;
  327.             break;
  328.         default:
  329.             return E_INVALIDARG;
  330.     }
  331.     
  332.     return S_OK;
  333. }
  334. // BUGBUG: how do we handle UTFs and HZ encodings?
  335. HRESULT _ValidateCPInfo(UINT uiCP)
  336. {
  337.     HRESULT hr = E_FAIL;
  338.     if (g_pMimeDatabase) // just a paranoid
  339.     {
  340.         switch(uiCP)
  341.         {
  342.             case 932: // JA
  343.             case 949: // KOR
  344.             case 874: // Thai
  345.             case 950: // ZHT
  346.             case 936: // ZHC
  347.             case 1255: // Hebrew
  348.             case 1256: // Arabic
  349.             case 1258: // Vietnamese
  350.             case 50001: // CP_AUTO
  351.                 // just validate what's given
  352.                 hr = g_pMimeDatabase->ValidateCP(uiCP);
  353.                 break;
  354.             case 1250:    // PANEURO
  355.             case 1251:
  356.             case 1253:
  357.             case 1254:
  358.             case 1257:
  359.                 // have to validate
  360.                 // all of these
  361.                 hr = g_pMimeDatabase->ValidateCP(1250);
  362.                 if (SUCCEEDED(hr))
  363.                     hr = g_pMimeDatabase->ValidateCP(1251);
  364.                 if (SUCCEEDED(hr))
  365.                     hr = g_pMimeDatabase->ValidateCP(1253);
  366.                 if (SUCCEEDED(hr))
  367.                     hr = g_pMimeDatabase->ValidateCP(1254);
  368.                 if (SUCCEEDED(hr))
  369.                     hr = g_pMimeDatabase->ValidateCP(1257);
  370.                 break;
  371.             default:
  372.                 return E_INVALIDARG;
  373.         }
  374.     }
  375.     return hr;
  376. }
  377. // assumes the corresponding fontfile name for now
  378. HRESULT _AddFontForCP(UINT uiCP)
  379. {
  380.    TCHAR szFontsPath[MAX_PATH];
  381.    LPTSTR szFontFile;
  382.    HRESULT hr = S_OK;
  383.    BOOL bAtLeastOneFontAdded = FALSE;
  384.    
  385.    switch(uiCP)
  386.    {
  387.         case 932: // JA
  388.             szFontFile = s_szJaFont;
  389.             break;
  390.         case 949: // KOR
  391.             szFontFile = s_szKorFont;
  392.             break;
  393.         case 950: // ZHT
  394.             szFontFile = s_szZhtFont;
  395.             break;
  396.         case 936: // ZHC
  397.             szFontFile = s_szZhcFont;
  398.             break;
  399.         case 874:
  400.             szFontFile = s_szThaiFont;
  401.             break; 
  402.         case 1255:
  403.             szFontFile = s_szIwFont;
  404.             break; 
  405.         case 1256:
  406.             szFontFile = s_szArFont;
  407.             break; 
  408.         case 1258:
  409.             szFontFile = s_szViFont;
  410.             break; 
  411.         case 1251:    // PANEURO
  412.         case 1253:
  413.         case 1254:
  414.         case 1257:
  415.             szFontFile = s_szPeFont;
  416.             break;
  417.         default:
  418.             hr = E_INVALIDARG;
  419.     } 
  420.    
  421.    // addfontresource, then broadcast WM_FONTCHANGE
  422.    if (SUCCEEDED(hr))
  423.    {      
  424.        if (MLGetWindowsDirectory(szFontsPath, ARRAYSIZE(szFontsPath)))
  425.        {
  426.            TCHAR  szFontFilePath[MAX_PATH];
  427.            LPTSTR psz, pszT;
  428.            MLPathCombine(szFontsPath, szFontsPath, szFonts);
  429.            for (psz = szFontFile; *psz; psz = pszT + 1)
  430.            {
  431.                pszT = MLStrChr(psz, TEXT(','));
  432.                if (pszT)
  433.                {
  434.                    *pszT=TEXT('');
  435.                }
  436.                MLPathCombine(szFontFilePath, szFontsPath, psz);
  437.                if (AddFontResource(szFontFilePath))
  438.                {
  439.                    bAtLeastOneFontAdded = TRUE;
  440.                }
  441.                if (!pszT)
  442.                   break;
  443.            }
  444.            if (!bAtLeastOneFontAdded)
  445.                hr = E_FAIL;
  446.        }
  447.        else
  448.            hr = E_FAIL;
  449.    }
  450.    // BUGBUG: WM_FONTCHANGE
  451.    return hr;
  452. }
  453. // Extend LoadString() to to _LoadStringExW() to take LangId parameter
  454. int _LoadStringExW(
  455.     HMODULE    hModule,
  456.     UINT      wID,
  457.     LPWSTR    lpBuffer,            // Unicode buffer
  458.     int       cchBufferMax,        // cch in Unicode buffer
  459.     WORD      wLangId)
  460. {
  461.     HRSRC hResInfo;
  462.     HANDLE hStringSeg;
  463.     LPWSTR lpsz;
  464.     int    cch;
  465.     
  466.     // Make sure the parms are valid.     
  467.     if (lpBuffer == NULL || cchBufferMax == 0) 
  468.     {
  469.         return 0;
  470.     }
  471.     cch = 0;
  472.     
  473.     // String Tables are broken up into 16 string segments.  Find the segment
  474.     // containing the string we are interested in.     
  475.     if (hResInfo = FindResourceExW(hModule, (LPCWSTR)RT_STRING,
  476.                                    (LPWSTR)((LONG)(((USHORT)wID >> 4) + 1)), wLangId)) 
  477.     {        
  478.         // Load that segment.        
  479.         hStringSeg = LoadResource(hModule, hResInfo);
  480.         
  481.         // Lock the resource.        
  482.         if (lpsz = (LPWSTR)LockResource(hStringSeg)) 
  483.         {            
  484.             // Move past the other strings in this segment.
  485.             // (16 strings in a segment -> & 0x0F)             
  486.             wID &= 0x0F;
  487.             while (TRUE) 
  488.             {
  489.                 cch = *((WORD *)lpsz++);   // PASCAL like string count
  490.                                             // first UTCHAR is count if TCHARs
  491.                 if (wID-- == 0) break;
  492.                 lpsz += cch;                // Step to start if next string
  493.              }
  494.             
  495.                             
  496.             // Account for the NULL                
  497.             cchBufferMax--;
  498.                 
  499.             // Don't copy more than the max allowed.                
  500.             if (cch > cchBufferMax)
  501.                 cch = cchBufferMax-1;
  502.                 
  503.             // Copy the string into the buffer.                
  504.             CopyMemory(lpBuffer, lpsz, cch*sizeof(WCHAR));
  505.             // Attach Null terminator.
  506.             lpBuffer[cch] = 0;
  507.         }
  508.     }
  509.     return cch;
  510. }
  511. typedef struct tagCPLGID
  512. {
  513.     UINT    uiCodepage;
  514.     TCHAR   szLgId[3];
  515. } CPLGID;
  516. const CPLGID CpLgId[] =
  517. {
  518.     {1252,  TEXT("1")},  // WESTERN EUROPE
  519.     {1250,  TEXT("2")},  // CENTRAL EUROPE
  520.     {1257,  TEXT("3")},  // BALTIC
  521.     {1253,  TEXT("4")},  // GREEK
  522.     {1251,  TEXT("5")},  // CYRILLIC
  523.     {1254,  TEXT("6")},  // TURKISH
  524.     {932,   TEXT("7")},  // JAPANESE
  525.     {949,   TEXT("8")},  // KOREAN
  526.     {950,   TEXT("9")},  // TRADITIONAL CHINESE
  527.     {936,  TEXT("10")},  // SIMPLIFIED CHINESE
  528.     {874,  TEXT("11")},  // THAI
  529.     {1255, TEXT("12")},  // HEBREW
  530.     {1256, TEXT("13")},  // ARABIC
  531.     {1258, TEXT("14")}   // VIETNAMESE
  532. };
  533. typedef BOOL (WINAPI *PFNISNTADMIN) ( DWORD dwReserved, DWORD *lpdwReserved );
  534. typedef INT (WINAPI *PFNSETUPPROMPTREBOOT) (
  535.         HSPFILEQ FileQueue,  // optional, handle to a file queue
  536.         HWND Owner,          // parent window of this dialog box
  537.         BOOL ScanOnly        // optional, do not prompt user
  538.         );
  539. typedef PSP_FILE_CALLBACK PFNSETUPDEFAULTQUEUECALLBACK;
  540. typedef VOID (WINAPI *PFNSETUPCLOSEINFFILE) (
  541.     HINF InfHandle
  542.     );
  543. typedef BOOL (WINAPI *PFNSETUPINSTALLFROMINFSECTION) (
  544.     HWND                Owner,
  545.     HINF                InfHandle,
  546.     LPCTSTR             SectionName,
  547.     UINT                Flags,
  548.     HKEY                RelativeKeyRoot,   OPTIONAL
  549.     LPCTSTR             SourceRootPath,    OPTIONAL
  550.     UINT                CopyFlags,
  551.     PSP_FILE_CALLBACK   MsgHandler,
  552.     PVOID               Context,
  553.     HDEVINFO            DeviceInfoSet,     OPTIONAL
  554.     PSP_DEVINFO_DATA    DeviceInfoData     OPTIONAL
  555.     );
  556. typedef HINF (WINAPI *PFNSETUPOPENINFFILE) (
  557.     LPCTSTR FileName,
  558.     LPCTSTR InfClass,    OPTIONAL
  559.     DWORD   InfStyle,
  560.     PUINT   ErrorLine    OPTIONAL
  561.     );
  562. typedef PVOID (WINAPI *PFNSETUPINITDEFAULTQUEUECALLBACK) (
  563.     IN HWND OwnerWindow
  564.     );
  565. typedef BOOL (WINAPI *PFNSETUPOPENAPPENDINFFILE) (
  566.   PCTSTR FileName, // optional, name of the file to append
  567.   HINF InfHandle,  // handle of the file to append to
  568.   PUINT ErrorLine  // optional, receives error information
  569. );
  570.  
  571. HRESULT IsNTLangpackAvailable(UINT uiCP)
  572. {
  573.     HRESULT hret = S_FALSE;
  574.     
  575.     for (int i=0; i < ARRAYSIZE(CpLgId); i++)
  576.     {
  577.         if (uiCP == CpLgId[i].uiCodepage)
  578.         {
  579.             hret = S_OK;
  580.             break;
  581.         }
  582.     }
  583.     return hret;
  584. }
  585. HRESULT _InstallNT5Langpack(HWND hwnd, UINT uiCP)
  586. {
  587.     HRESULT             hr = E_FAIL;
  588.     HINF                hIntlInf = NULL;
  589.     TCHAR               szIntlInf[MAX_PATH];
  590.     TCHAR               szIntlInfSection[MAX_PATH];
  591.     PVOID               QueueContext = NULL;   
  592.     HINSTANCE           hDllAdvPack = NULL;
  593.     HINSTANCE           hDllSetupApi = NULL;
  594.     PFNSETUPINSTALLFROMINFSECTION       lpfnSetupInstallFromInfSection = NULL;
  595.     PFNSETUPCLOSEINFFILE                lpfnSetupCloseInfFile = NULL;
  596.     PFNSETUPDEFAULTQUEUECALLBACK        lpfnSetupDefaultQueueCallback = NULL;
  597.     PFNSETUPOPENINFFILE                 lpfnSetupOpenInfFile = NULL;
  598.     PFNISNTADMIN                        lpfnIsNTAdmin = NULL;
  599.     PFNSETUPINITDEFAULTQUEUECALLBACK    lpfnSetupInitDefaultQueueCallback = NULL;
  600.     PFNSETUPOPENAPPENDINFFILE           lpfnSetupOpenAppendInfFile = NULL;
  601.     for (int i=0; i < ARRAYSIZE(CpLgId); i++)
  602.     {
  603.         if (uiCP == CpLgId[i].uiCodepage)
  604.         {
  605.             _tcscpy(szIntlInfSection, TEXT("LG_INSTALL_"));
  606.             _tcscat(szIntlInfSection, CpLgId[i].szLgId);
  607.             break;
  608.         }
  609.     }
  610.     if (i >= ARRAYSIZE(CpLgId))
  611.     {
  612.         goto LANGPACK_EXIT;
  613.     }
  614.     hDllAdvPack = LoadLibrary(TEXT("advpack.dll"));
  615.     hDllSetupApi = LoadLibrary(TEXT("setupapi.dll"));
  616.     if (!hDllAdvPack || !hDllSetupApi)
  617.     {
  618.         goto LANGPACK_EXIT;
  619.     }
  620.     lpfnIsNTAdmin = (PFNISNTADMIN) GetProcAddress( hDllAdvPack, "IsNTAdmin");
  621.     lpfnSetupCloseInfFile = (PFNSETUPCLOSEINFFILE) GetProcAddress( hDllSetupApi, "SetupCloseInfFile");
  622.     lpfnSetupInitDefaultQueueCallback = (PFNSETUPINITDEFAULTQUEUECALLBACK) GetProcAddress(hDllSetupApi, "SetupInitDefaultQueueCallback");
  623. #ifdef UNICODE
  624.     lpfnSetupOpenInfFile = (PFNSETUPOPENINFFILE) GetProcAddress( hDllSetupApi, "SetupOpenInfFileW"));
  625.     lpfnSetupInstallFromInfSection = (PFNSETUPINSTALLFROMINFSECTION) GetProcAddress( hDllSetupApi, "SetupInstallFromInfSectionW");
  626.     lpfnSetupDefaultQueueCallback = (PFNSETUPDEFAULTQUEUECALLBACK) GetProcAddress(hDllSetupApi, "SetupDefaultQueueCallbackW");
  627.     lpfnSetupOpenAppendInfFile = (PFNSETUPDEFAULTQUEUECALLBACK) GetProcAddress(hDllSetupApi, "SetupOpenAppendInfFileW");
  628. #else
  629.     lpfnSetupOpenInfFile = (PFNSETUPOPENINFFILE) GetProcAddress( hDllSetupApi, "SetupOpenInfFileA");
  630.     lpfnSetupInstallFromInfSection = (PFNSETUPINSTALLFROMINFSECTION) GetProcAddress( hDllSetupApi, "SetupInstallFromInfSectionA");
  631.     lpfnSetupDefaultQueueCallback = (PFNSETUPDEFAULTQUEUECALLBACK) GetProcAddress(hDllSetupApi, "SetupDefaultQueueCallbackA");
  632.     lpfnSetupOpenAppendInfFile = (PFNSETUPOPENAPPENDINFFILE) GetProcAddress(hDllSetupApi, "SetupOpenAppendInfFileA");
  633. #endif
  634.     if (!lpfnIsNTAdmin || !lpfnSetupOpenInfFile || !lpfnSetupCloseInfFile || !lpfnSetupDefaultQueueCallback 
  635.         || !lpfnSetupInstallFromInfSection || !lpfnSetupInitDefaultQueueCallback || !lpfnSetupOpenAppendInfFile)
  636.     {
  637.         goto LANGPACK_EXIT;
  638.     }
  639.     if (!lpfnIsNTAdmin(0, NULL))
  640.     {
  641.         WCHAR wszLangInstall[MAX_PATH];
  642.         WCHAR wszNoAdmin[1024];
  643.         LANGID LangId = GetNT5UILanguage();
  644.         // Fall back to English (US) if we don't have a specific language resource
  645.         if (!_LoadStringExW(g_hInst, IDS_LANGPACK_INSTALL, wszLangInstall, ARRAYSIZE(wszLangInstall), LangId) ||
  646.             !_LoadStringExW(g_hInst, IDS_NO_ADMIN, wszNoAdmin, ARRAYSIZE(wszNoAdmin), LangId))
  647.         {
  648.             LangId = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
  649.             _LoadStringExW(g_hInst, IDS_LANGPACK_INSTALL, wszLangInstall, ARRAYSIZE(wszLangInstall), LangId);
  650.             _LoadStringExW(g_hInst, IDS_NO_ADMIN, wszNoAdmin, ARRAYSIZE(wszNoAdmin), LangId);
  651.         }
  652.         MessageBoxW(hwnd, wszNoAdmin, wszLangInstall, MB_OK);
  653.         goto LANGPACK_EXIT;
  654.     }
  655.     QueueContext = lpfnSetupInitDefaultQueueCallback(hwnd);
  656.     MLGetWindowsDirectory(szIntlInf, MAX_PATH);
  657.     MLPathCombine(szIntlInf, szIntlInf, TEXT("inf\intl.inf"));
  658.     hIntlInf = lpfnSetupOpenInfFile(szIntlInf, NULL, INF_STYLE_WIN4, NULL);
  659.     if (!lpfnSetupOpenAppendInfFile(NULL, hIntlInf, NULL))
  660.     {
  661.         lpfnSetupCloseInfFile(hIntlInf);
  662.         goto LANGPACK_EXIT;
  663.     }
  664.     if (INVALID_HANDLE_VALUE != hIntlInf)
  665.     {
  666.         if (lpfnSetupInstallFromInfSection( hwnd,
  667.                                     hIntlInf,
  668.                                     szIntlInfSection,
  669.                                     SPINST_FILES,
  670.                                     NULL,
  671.                                     NULL,
  672.                                     SP_COPY_NEWER,
  673.                                     lpfnSetupDefaultQueueCallback,
  674.                                     QueueContext,
  675.                                     NULL,
  676.                                     NULL ))
  677.         {
  678.             if (lpfnSetupInstallFromInfSection( hwnd,
  679.                                     hIntlInf,
  680.                                     szIntlInfSection,
  681.                                     SPINST_ALL & ~SPINST_FILES,
  682.                                     NULL,
  683.                                     NULL,
  684.                                     0,
  685.                                     lpfnSetupDefaultQueueCallback,
  686.                                     QueueContext,
  687.                                     NULL,
  688.                                     NULL ))
  689.             {
  690.                 hr = S_OK;
  691.             }
  692.         }
  693.     
  694.         lpfnSetupCloseInfFile(hIntlInf);
  695.     }
  696. LANGPACK_EXIT:
  697.     if(hDllSetupApi)
  698.         FreeLibrary(hDllSetupApi);
  699.     if(hDllAdvPack)
  700.         FreeLibrary(hDllAdvPack);
  701.     return hr;
  702. }
  703. BOOL _IsValidCodePage(UINT uiCodePage)
  704. {
  705.     BOOL bRet;
  706.     if (50001 == uiCodePage)
  707.     {
  708.         HANDLE hFile = NULL;
  709.         TCHAR szSysDir[MAX_PATH];
  710.         if (GetSystemDirectory(szSysDir, MAX_PATH))
  711.         {
  712.             _tcscat(szSysDir, TEXT("\MLANG.DAT"));
  713.         }
  714.         if (INVALID_HANDLE_VALUE == (hFile = CreateFile(szSysDir, GENERIC_READ, FILE_SHARE_READ, NULL,
  715.                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)))
  716.         {
  717.             bRet = FALSE;
  718.         }
  719.         else
  720.         {
  721.             bRet = TRUE;
  722.             CloseHandle(hFile);
  723.         }
  724.     }
  725.     else
  726.     {
  727.         bRet = IsValidCodePage(uiCodePage);
  728.     }
  729.     return bRet;
  730. }
  731. WCHAR *MLStrCpyNW(WCHAR *strDest, const WCHAR *strSource, int nCount)
  732. {
  733.     return wcsncpy(strDest, strSource, nCount);
  734. }
  735. WCHAR *MLStrCpyW(WCHAR *strDest, const WCHAR *strSource)
  736. {
  737.     return wcscpy(strDest, strSource);
  738. }
  739. LPTSTR MLStrChr( const TCHAR *string, int c )
  740. {
  741.     return _tcschr(string, c);
  742. }
  743. LPTSTR MLStrCpyN(LPTSTR strDest, const LPTSTR strSource, UINT nCount)
  744. {
  745.     return _tcsncpy(strDest, strSource, nCount);
  746. }
  747. LPTSTR MLStrStr(const LPTSTR Str, const LPTSTR subStr)
  748. {
  749.     return _tcsstr(Str, subStr);
  750. }
  751. LPTSTR MLPathCombine(LPTSTR szPath, LPTSTR szPath1, LPTSTR szPath2)
  752. {
  753.     int len;
  754.     if (!szPath) 
  755.         return NULL;
  756.     if (szPath != szPath1)
  757.     {
  758.         _tcscpy(szPath, szPath1);
  759.     }
  760.     len = _tcslen(szPath1);
  761.     if (szPath[len-1] != TEXT('\'))
  762.     {
  763.         szPath[len++] = TEXT('\');
  764.         szPath[len] = 0;
  765.     }
  766.     return _tcscat(szPath, szPath2);
  767. }
  768. DWORD HexToNum(LPTSTR lpsz)
  769. {
  770.     DWORD   dw = 0L;
  771.     TCHAR   c;
  772.     while(*lpsz)
  773.     {
  774.         c = *lpsz++;
  775.         if (c >= TEXT('A') && c <= TEXT('F'))
  776.         {
  777.             c -= TEXT('A') - 0xa;
  778.         }
  779.         else if (c >= TEXT('0') && c <= TEXT('9'))
  780.         {
  781.             c -= TEXT('0');
  782.         }
  783.         else if (c >= TEXT('a') && c <= TEXT('f'))
  784.         {
  785.             c -= TEXT('a') - 0xa;
  786.         }
  787.         else
  788.         {
  789.             break;
  790.         }
  791.         dw *= 0x10;
  792.         dw += c;
  793.     }
  794.     return(dw);
  795. }
  796. // Following code is borrowed from shlwapi
  797. BOOL AnsiFromUnicode(
  798.      LPSTR * ppszAnsi,
  799.      LPCWSTR pwszWide,        // NULL to clean up
  800.      LPSTR pszBuf,
  801.      int cchBuf)
  802. {
  803.     BOOL bRet;
  804.     // Convert the string?
  805.     if (pwszWide)
  806.     {
  807.         // Yes; determine the converted string length
  808.         int cch;
  809.         LPSTR psz;
  810.         cch = WideCharToMultiByte(CP_ACP, 0, pwszWide, -1, NULL, 0, NULL, NULL);
  811.         // String too big, or is there no buffer?
  812.         if (cch > cchBuf || NULL == pszBuf)
  813.         {
  814.             // Yes; allocate space
  815.             cchBuf = cch + 1;
  816.             psz = (LPSTR)LocalAlloc(LPTR, CbFromCchA(cchBuf));
  817.         }
  818.         else
  819.         {
  820.             // No; use the provided buffer
  821.             ASSERT(pszBuf);
  822.             psz = pszBuf;
  823.         }
  824.         if (psz)
  825.         {
  826.             // Convert the string
  827.             cch = WideCharToMultiByte(CP_ACP, 0, pwszWide, -1, psz, cchBuf, NULL, NULL);
  828.             bRet = (0 < cch);
  829.         }
  830.         else
  831.         {
  832.             bRet = FALSE;
  833.         }
  834.         *ppszAnsi = psz;
  835.     }
  836.     else
  837.     {
  838.         // No; was this buffer allocated?
  839.         if (*ppszAnsi && pszBuf != *ppszAnsi)
  840.         {
  841.             // Yes; clean up
  842.             LocalFree((HLOCAL)*ppszAnsi);
  843.             *ppszAnsi = NULL;
  844.         }
  845.         bRet = TRUE;
  846.     }
  847.     return bRet;
  848. }
  849. int MLStrCmpI(IN LPCTSTR pwsz1, IN LPCTSTR pwsz2)
  850. {
  851. #ifdef UNICODE
  852.     return MLStrCmpIW(pwsz1, pwsz2);
  853. #else
  854.     return lstrcmpiA(pwsz1, pwsz2);
  855. #endif
  856. }
  857. int MLStrCmpNI(IN LPCTSTR pstr1, IN LPCTSTR pstr2, IN int count)
  858. {
  859. #ifdef UNICODE
  860.     return MLStrCmpNIW(pstr1, pstr2, count);
  861. #else
  862.     return MLStrCmpNIA(pstr1, pstr2, count);
  863. #endif
  864. }
  865. int MLStrCmpIW(
  866.     IN LPCWSTR pwsz1,
  867.     IN LPCWSTR pwsz2)
  868. {
  869.     int iRet;
  870.     
  871.     ASSERT(IS_VALID_STRING_PTRW(pwsz1, -1));
  872.     ASSERT(IS_VALID_STRING_PTRW(pwsz2, -1));
  873.     
  874.     if (g_bIsNT)
  875.     {        
  876.         iRet = CompareStringW(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), NORM_IGNORECASE, pwsz1, -1, pwsz2, -1) - CSTR_EQUAL;
  877.     }
  878.     else
  879.     {
  880.         CHAR sz1[512];
  881.         CHAR sz2[512];
  882.         LPSTR psz1;
  883.         LPSTR psz2;
  884.         iRet = -1;      // arbitrary on failure
  885.         if (pwsz1 && pwsz2)
  886.         {
  887.             if (AnsiFromUnicode(&psz1, pwsz1, sz1, SIZECHARS(sz1)))
  888.             {
  889.                 if (AnsiFromUnicode(&psz2, pwsz2, sz2, SIZECHARS(sz2)))
  890.                 {
  891.                     iRet = CompareStringA(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), NORM_IGNORECASE, psz1, -1, psz2, -1) - CSTR_EQUAL;
  892.                     AnsiFromUnicode(&psz2, NULL, sz2, 0);       // Free
  893.                 }
  894.                 AnsiFromUnicode(&psz1, NULL, sz1, 0);       // Free
  895.             }
  896.         }
  897.     }
  898.     return iRet;
  899. }
  900. #ifdef UNIX
  901. #ifdef BIG_ENDIAN
  902. #define READNATIVEWORD(x) MAKEWORD(*(char*)(x), *(char*)((char*)(x) + 1))
  903. #else 
  904. #define READNATIVEWORD(x) MAKEWORD(*(char*)((char*)(x) + 1), *(char*)(x))
  905. #endif
  906. #else
  907. #define READNATIVEWORD(x) (*(UNALIGNED WORD *)x)
  908. #endif
  909. int WINAPI MLStrToIntA(
  910.     LPCSTR lpSrc)
  911. {
  912.     int n = 0;
  913.     BOOL bNeg = FALSE;
  914.     if (*lpSrc == '-') {
  915.         bNeg = TRUE;
  916.         lpSrc++;
  917.     }
  918.     while (IS_DIGITA(*lpSrc)) {
  919.         n *= 10;
  920.         n += *lpSrc - '0';
  921.         lpSrc++;
  922.     }
  923.     return bNeg ? -n : n;
  924. }
  925. int WINAPI MLStrToIntW(
  926.     LPCWSTR lpSrc)
  927. {
  928.     int n = 0;
  929.     BOOL bNeg = FALSE;
  930.     if (*lpSrc == L'-') {
  931.         bNeg = TRUE;
  932.         lpSrc++;
  933.     }
  934.     while (IS_DIGITW(*lpSrc)) {
  935.         n *= 10;
  936.         n += *lpSrc - L'0';
  937.         lpSrc++;
  938.     }
  939.     return bNeg ? -n : n;
  940. }
  941. /*
  942.  * ChrCmpI - Case insensitive character comparison for DBCS
  943.  * Assumes   w1, wMatch are characters to be compared;
  944.  *           HIBYTE of wMatch is 0 if not a DBC
  945.  * Return    FALSE if match, TRUE if not
  946.  */
  947. BOOL ChrCmpIA(WORD w1, WORD wMatch)
  948. {
  949.     char sz1[3], sz2[3];
  950.     if (IsDBCSLeadByte(sz1[0] = LOBYTE(w1)))
  951.     {
  952.         sz1[1] = HIBYTE(w1);
  953.         sz1[2] = '';
  954.     }
  955.     else
  956.         sz1[1] = '';
  957. #if defined(MWBIG_ENDIAN)
  958.     sz2[0] = LOBYTE(wMatch);
  959.     sz2[1] = HIBYTE(wMatch);
  960. #else
  961.     *(WORD *)sz2 = wMatch;
  962. #endif
  963.     sz2[2] = '';
  964.     return lstrcmpiA(sz1, sz2);
  965. }
  966. BOOL ChrCmpIW(WCHAR w1, WCHAR wMatch)
  967. {
  968.     WCHAR sz1[2], sz2[2];
  969.     sz1[0] = w1;
  970.     sz1[1] = '';
  971.     sz2[0] = wMatch;
  972.     sz2[1] = '';
  973.     return lstrcmpiW(sz1, sz2);
  974. }
  975. /*
  976.  * StrCmpNI     - Compare n bytes, case insensitive
  977.  *
  978.  * returns   See lstrcmpi return values.
  979.  */
  980. int MLStrCmpNIA(LPCSTR lpStr1, LPCSTR lpStr2, int nChar)
  981. {
  982.     int i;
  983.     LPCSTR lpszEnd = lpStr1 + nChar;
  984.     for ( ; (lpszEnd > lpStr1) && (*lpStr1 || *lpStr2); (lpStr1 = AnsiNext(lpStr1)), (lpStr2 = AnsiNext(lpStr2))) {
  985.         WORD w1;
  986.         WORD w2;
  987.         // If either pointer is at the null terminator already,
  988.         // we want to copy just one byte to make sure we don't read 
  989.         // past the buffer (might be at a page boundary).
  990.         w1 = (*lpStr1) ? READNATIVEWORD(lpStr1) : 0;
  991.         w2 = (UINT)(IsDBCSLeadByte(*lpStr2)) ? (UINT)READNATIVEWORD(lpStr2) : (WORD)(BYTE)(*lpStr2);
  992.         i = ChrCmpIA(w1, w2);
  993.         if (i)
  994.             return i;
  995.     }
  996.     return 0;
  997. }
  998. int MLStrCmpNIW(LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar)
  999. {
  1000.     int i;
  1001.     LPCWSTR lpszEnd = lpStr1 + nChar;
  1002.     for ( ; (lpszEnd > lpStr1) && (*lpStr1 || *lpStr2); lpStr1++, lpStr2++) {
  1003.         i = ChrCmpIW(*lpStr1, *lpStr2);
  1004.         if (i) {
  1005.             return i;
  1006.         }
  1007.     }
  1008.     return 0;
  1009. }
  1010. HRESULT _IsCodePageInstallable(UINT uiCodePage)
  1011. {
  1012.     MIMECPINFO cpInfo;
  1013.     UINT       uiFamCp;
  1014.     HRESULT    hr;
  1015.     if (NULL != g_pMimeDatabase)
  1016.         hr = g_pMimeDatabase->GetCodePageInfo(uiCodePage, 0x409, &cpInfo);
  1017.     else
  1018.         hr = E_OUTOFMEMORY;
  1019.     if (FAILED(hr))
  1020.         return E_INVALIDARG;
  1021.     uiFamCp = cpInfo.uiFamilyCodePage;
  1022.     if (g_bIsNT5)
  1023.     {
  1024.         hr = IsNTLangpackAvailable(uiFamCp);
  1025.     }
  1026.     else
  1027.     {
  1028.         CLSID      clsid;
  1029.         // clsid is just used for place holder
  1030.         hr = _GetJITClsIDForCodePage(uiFamCp, &clsid);
  1031.     }
  1032.     return hr;
  1033. }
  1034. //
  1035. // CML2 specific utilities
  1036. //
  1037. //
  1038. // CMultiLanguage2::EnsureIEStatus()
  1039. //
  1040. // ensures CML2::m_pIEStat
  1041. //
  1042. HRESULT CMultiLanguage2::EnsureIEStatus(void)
  1043. {
  1044.     HRESULT hr = S_OK;
  1045.     // initialize IE status cache
  1046.     if (!m_pIEStat)
  1047.     {
  1048.         m_pIEStat = new CIEStatus();
  1049.         if (m_pIEStat)
  1050.         {
  1051.             hr = m_pIEStat->Init();
  1052.         }
  1053.     }
  1054.     return hr;
  1055. }
  1056. //
  1057. // CIEStatus::Init()
  1058. //
  1059. // initializes the IE status;
  1060. //
  1061. HRESULT CMultiLanguage2::CIEStatus::Init(void)
  1062. {
  1063.     HRESULT hr = S_OK;
  1064.     HKEY hkey;
  1065.     // Get JIT satus
  1066.     if (RegOpenKeyEx(HKEY_CURRENT_USER, 
  1067.                       REGSTR_PATH_MAIN,
  1068.                      0, KEY_READ, &hkey) == ERROR_SUCCESS) 
  1069.     {
  1070.         DWORD dwVal, dwType;
  1071.         DWORD dwSize = sizeof(dwVal);
  1072.         RegQueryValueEx(hkey, TEXT("nojitsetup"), 0, &dwType, (LPBYTE)&dwVal, &dwSize);
  1073.         RegCloseKey(hkey);
  1074.         if (dwType == REG_DWORD && dwSize == sizeof(dwVal))
  1075.         {
  1076.             if (dwVal > 0 ) 
  1077.                 _IEFlags.fJITDisabled = TRUE;
  1078.             else
  1079.                 _IEFlags.fJITDisabled = FALSE;
  1080.         }
  1081.     }
  1082.     else
  1083.         hr = E_FAIL;
  1084.     // any other status to get initialized
  1085.     // ...
  1086.     
  1087.     return hr;
  1088. }
  1089. #define NT5LPK_DLG_STRING "MLang.NT5LpkDlg"
  1090. //
  1091. // LangpackDlgProc()
  1092. //
  1093. // Message handler for the NT5 langpack dialog.
  1094. //
  1095. INT_PTR CALLBACK LangpackDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1096. {
  1097.     ASSERT(g_bIsNT5);
  1098.     switch (uMsg)
  1099.     {
  1100.         case WM_INITDIALOG:
  1101.             HWND hwndCheckBox;            
  1102.             RECT rc1, rc2;
  1103.             MIMECPINFO cpInfo;
  1104.             SetProp(hDlg, NT5LPK_DLG_STRING, (HANDLE)lParam);
  1105.     
  1106.             if ((NULL != g_pMimeDatabase) &&
  1107.                 SUCCEEDED(g_pMimeDatabase->GetCodePageInfo(HIWORD(lParam), GetNT5UILanguage(), &cpInfo)))
  1108.             {
  1109.                 for (int i=0; i<MAX_MIMECP_NAME && cpInfo.wszDescription[i]; i++)
  1110.                 {
  1111.                     if (cpInfo.wszDescription[i] == L'(')
  1112.                     {
  1113.                         cpInfo.wszDescription[i] = 0;
  1114.                         break;
  1115.                     }
  1116.                 }
  1117.                 // Use W version regardlessly since we're only running this on NT5             
  1118.                 SetDlgItemTextW(hDlg, IDC_STATIC_LANG, cpInfo.wszDescription);
  1119.             }
  1120.             
  1121.             // Center the dialog in the area of parent window
  1122.             if (GetWindowRect(GetParent(hDlg), &rc1) && GetWindowRect(hDlg, &rc2))
  1123.             {
  1124.                 MoveWindow(hDlg, (rc1.right+rc2.left+rc1.left-rc2.right)/2, (rc1.bottom+rc2.top+rc1.top-rc2.bottom)/2, rc2.right-rc2.left, rc2.bottom-rc2.top, FALSE);
  1125.             }            
  1126.             hwndCheckBox = GetDlgItem(hDlg, IDC_CHECK_LPK);
  1127.             // Set CheckBox state according to current registry setting
  1128.             PostMessage(hwndCheckBox, BM_SETCHECK, LOWORD(lParam)? BST_UNCHECKED:BST_CHECKED, 0);
  1129.             break;
  1130.         case WM_COMMAND:
  1131.             if (LOWORD(wParam) != IDC_CHECK_LPK)
  1132.             {
  1133.                 HKEY hkey;
  1134.                 DWORD dwInstallOut = (BST_CHECKED == SendMessage(GetDlgItem(hDlg, IDC_CHECK_LPK), BM_GETCHECK, 0, 0)? 0:1);
  1135.                 DWORD dwInstallIn = LOWORD(GetProp(hDlg, NT5LPK_DLG_STRING));
  1136.                 
  1137.                 if ((dwInstallOut != dwInstallIn) &&
  1138.                     ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, 
  1139.                          REGSTR_PATH_INTERNATIONAL,
  1140.                          NULL, KEY_READ|KEY_SET_VALUE, &hkey)) 
  1141.                 {
  1142.                     DWORD dwType = REG_DWORD;
  1143.                     DWORD dwSize = sizeof(DWORD);
  1144.                     RegSetValueEx(hkey, REG_KEY_NT5LPK, 0, REG_DWORD, (LPBYTE)&dwInstallOut, sizeof(dwInstallOut));
  1145.                     RegCloseKey(hkey);
  1146.                 }                
  1147.                 EndDialog(hDlg, LOWORD(wParam) == IDOK? 1: 0);
  1148.             }
  1149.             break;
  1150.         case WM_HELP:
  1151.             // Do we need help file for this simply dialog?
  1152.             // If needed, we can always add it at later time.
  1153.             break;
  1154.         default:
  1155.             return FALSE;
  1156.     }
  1157.     return TRUE;
  1158. }
  1159. // To get real Windows directory on Terminal Server, 
  1160. // Instead of using internal Kernel32 API GetSystemWindowsDirectory with LoadLibrary/GetProcAddress,
  1161. // We cast GetSystemDirectory return to Windows directory
  1162. UINT MLGetWindowsDirectory(
  1163.     LPTSTR lpBuffer,    // address of buffer for Windows directory
  1164.     UINT uSize          // size of directory buffer
  1165.     )
  1166. {
  1167.     UINT uLen;
  1168.     if (g_bIsNT)
  1169.     {        
  1170.         if (uLen = GetSystemDirectory(lpBuffer, uSize))
  1171.         {        
  1172.             if (lpBuffer[uLen-1] == TEXT('\'))
  1173.                 uLen--;
  1174.             while (uLen-- > 0)
  1175.             {
  1176.                 if (lpBuffer[uLen] == TEXT('\'))
  1177.                 {
  1178.                     lpBuffer[uLen] = NULL;                
  1179.                     break;
  1180.                 }
  1181.             }
  1182.         }
  1183.     }
  1184.     else    
  1185.         uLen = GetWindowsDirectory(lpBuffer, uSize);
  1186.     return uLen;
  1187. }
  1188. // To speed up basic ANSI string compare,
  1189. // We avoid using lstrcmpi in LOW-ASCII case
  1190. int LowAsciiStrCmpNIA(LPCSTR  lpstr1, LPCSTR lpstr2, int count)
  1191. {
  1192.     int delta;
  1193.     while (count-- > 0)
  1194.     {        
  1195.         delta = *lpstr1 - *lpstr2;
  1196.         if (delta && 
  1197.             !(IS_CHARA(*lpstr1) && IS_CHARA(*lpstr2) && (delta == 0x20 || delta == -0x20)))
  1198.             return delta;
  1199.         lpstr1++;
  1200.         lpstr2++;
  1201.     }
  1202.     return 0;
  1203. }
  1204. //
  1205. //  GetNT5UILanguage(void)
  1206. //
  1207. LANGID GetNT5UILanguage(void)
  1208. {
  1209.     if (g_bIsNT5)
  1210.     {
  1211.         static LANGID (CALLBACK* pfnGetUserDefaultUILanguage)(void) = NULL;
  1212.         if (pfnGetUserDefaultUILanguage == NULL)
  1213.         {
  1214.             HMODULE hmod = GetModuleHandle(TEXT("KERNEL32"));
  1215.             if (hmod)
  1216.                 pfnGetUserDefaultUILanguage = (LANGID (CALLBACK*)(void))GetProcAddress(hmod, "GetUserDefaultUILanguage");
  1217.         }
  1218.         if (pfnGetUserDefaultUILanguage)
  1219.             return pfnGetUserDefaultUILanguage();
  1220.     }
  1221.     return 0;
  1222. }