Advertisement
bejiitas_wrath

Sample *.cpl file from Windows XP Control panel.

Oct 31st, 2023
958
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 58.94 KB | None | 0 0
  1. ///////////////////////////////////////////////////////////////////////
  2. //                     Microsoft Windows                             //
  3. //              Copyright(c) Microsoft Corp., 1995                   //
  4. ///////////////////////////////////////////////////////////////////////
  5. //
  6. // LANG.CPP - "Language" property page for InetCpl
  7. //
  8.  
  9. // HISTORY:
  10. //
  11. // 1/10/97  beomoh      created
  12. //
  13.  
  14. #include "inetcplp.h"
  15.  
  16. #include <tchar.h>
  17. #include <mlang.h>
  18. #include "psapi.h"
  19. #include "tlhelp32.h"
  20. #include "process.h"
  21. #include <mluisupp.h>
  22. #include <shdocvw.h>
  23.  
  24. #define ARRAYSIZE(a)        (sizeof(a)/sizeof(a[0]))
  25. #define FORMAT_STR          TEXT("%s [%s]")
  26. #define MAX_LIST_STRING_LEN MAX_LOCALE_NAME + MAX_RFC1766_NAME + 3
  27. #define MAX_ACCEPT_LANG_LEN 2048
  28.  
  29. #define CP_THAI     874
  30. #define CP_ARABIC   1256
  31. #define CP_HEBREW   1255
  32.  
  33. // used as the return value from setlang dialog
  34. #define RETURN_SETLANG_ENDLANGDIALOG    2
  35. #define RETURN_SETLANG_CLOSEDNORMAL     1
  36. #define RETURN_SETLANG_CANCELED         0
  37.  
  38. typedef HRESULT (* PCOINIT) (LPVOID);
  39. typedef VOID (* PCOUNINIT) (VOID);
  40. typedef VOID (* PCOMEMFREE) (LPVOID);
  41. typedef HRESULT (* PCOCREINST) (REFCLSID, LPUNKNOWN, DWORD,     REFIID, LPVOID * );
  42.  
  43. extern HMODULE hOLE32;
  44. extern PCOINIT pCoInitialize;
  45. extern PCOUNINIT pCoUninitialize;
  46. extern PCOMEMFREE pCoTaskMemFree;
  47. extern PCOCREINST pCoCreateInstance;
  48.  
  49. extern BOOL _StartOLE32();
  50.  
  51. class CUILangList;
  52. INT_PTR KickSetLang(HWND hDlg, CUILangList * pLangList);
  53.  
  54. static const TCHAR s_szResourceLocale[] = TEXT("ResourceLocale");
  55. // HKLM\Software\Microsoft\Internet Explorer\International used for url string
  56. static const TCHAR s_szUrlSPK[]
  57. = TEXT("http://www.microsoft.com/isapi/redir.dll?prd=ie&pver=6&ar=plugui&sba=install");
  58. static const TCHAR c_szInstall[]
  59. = TEXT("Software\\Microsoft\\Active Setup\\Installed Components\\{89820200-ECBD-11CF-8B85-00AA005B4383}");
  60. static const TCHAR c_szLocale[] = TEXT("Locale");
  61. static const TCHAR s_szLangPackPath[]   = TEXT("Software\\Microsoft\\Internet Explorer");
  62. static const TCHAR s_szVersion[] = TEXT("LPKInstalled");
  63.  
  64. typedef struct
  65. {
  66.     WORD wlangid;
  67.     BOOL fValid;
  68.     TCHAR szName[MAX_LOCALE_NAME];
  69. } LANGLIST;
  70.  
  71. static LANGLIST s_arryLangList[] =
  72. {
  73.     {0x0409, FALSE, {0}},
  74.     {0x0407, FALSE, {0}},
  75.     {0x0411, FALSE, {0}},
  76.     {0x0412, FALSE, {0}},
  77.     {0x0404, FALSE, {0}},
  78.     {0x0804, FALSE, {0}},
  79.     {0x040c, FALSE, {0}},
  80.     {0x0c0a, FALSE, {0}},
  81.     {0x0416, FALSE, {0}},
  82.     {0x0410, FALSE, {0}},
  83.     {0x0413, FALSE, {0}},
  84.     {0x041d, FALSE, {0}},
  85.     {0x0406, FALSE, {0}},
  86.     {0x040b, FALSE, {0}},
  87.     {0x040e, FALSE, {0}},
  88.     {0x0414, FALSE, {0}},
  89.     {0x0408, FALSE, {0}},
  90.     {0x0415, FALSE, {0}},
  91.     {0x0419, FALSE, {0}},
  92.     {0x0405, FALSE, {0}},
  93.     {0x0816, FALSE, {0}},
  94.     {0x041f, FALSE, {0}},
  95.     {0x041b, FALSE, {0}},
  96.     {0x0424, FALSE, {0}},
  97.     {0x0401, FALSE, {0}},
  98.     {0x040d, FALSE, {0}},
  99.     {0x042d, FALSE, {0}},
  100.     {0x040f, FALSE, {0}},
  101. };
  102.  
  103. //
  104. //  ISO639 ID table
  105. //
  106. typedef struct tagISO639
  107. {
  108.     LPCTSTR ISO639;
  109.     LANGID LangID;
  110. }   ISO639, *LPISO639;
  111.  
  112. const ISO639 c_ISO639[] =
  113. {
  114.     { TEXT("EN"), 0x0409 },
  115.     { TEXT("DE"), 0x0407 },
  116.     { TEXT("JA"), 0x0411 },
  117.     { TEXT("KO"), 0x0412 },
  118.     { TEXT("TW"), 0x0404 },
  119.     { TEXT("CN"), 0x0804 },
  120.     { TEXT("FR"), 0x040C },
  121.     { TEXT("ES"), 0x0C0A },
  122.     { TEXT("BR"), 0x0416 },
  123.     { TEXT("IT"), 0x0410 },
  124.     { TEXT("NL"), 0x0413 },
  125.     { TEXT("SV"), 0x041D },
  126.     { TEXT("DA"), 0x0406 },
  127.     { TEXT("FI"), 0x040B },
  128.     { TEXT("HU"), 0x040E },
  129.     { TEXT("NO"), 0x0414 },
  130.     { TEXT("EL"), 0x0408 },
  131.     { TEXT("PL"), 0x0415 },
  132.     { TEXT("RU"), 0x0419 },
  133.     { TEXT("CS"), 0x0405 },
  134.     { TEXT("PT"), 0x0816 },
  135.     { TEXT("TR"), 0x041F },
  136.     { TEXT("SK"), 0x041B },
  137.     { TEXT("SL"), 0x0424 },
  138.     { TEXT("AR"), 0x0401 },
  139.     { TEXT("HE"), 0x040D },
  140.     { TEXT("EU"), 0x042D },
  141.     { TEXT("IS"), 0x040F },
  142. };
  143.  
  144. // GetInstallLanguage
  145. //
  146. // synopsis - borrowed this function from shlwapi. we can remove this
  147. //            once we have it exported from shlwapi.dll
  148. //
  149. LANGID GetInstallLanguage(void)
  150. {
  151.     static LANGID LangID = 0;
  152.     TCHAR szISO639[3];
  153.     DWORD cb;
  154.  
  155.     if (0 == LangID)
  156.     {
  157.         cb = sizeof(szISO639);
  158.         if (ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE, c_szInstall, c_szLocale, NULL, szISO639, &cb))
  159.         {
  160.             int i;
  161.  
  162.             for (i = 0; i < ARRAYSIZE(c_ISO639); i++)
  163.             {
  164.                 if (!StrCmpNI(szISO639, c_ISO639[i].ISO639, ARRAYSIZE(szISO639)))
  165.                 {
  166.                     LangID = c_ISO639[i].LangID;
  167.                     break;
  168.                 }
  169.             }
  170.         }
  171.     }
  172.     return LangID;
  173. }
  174.  
  175. // CUILangList
  176. //
  177. // maintains the list of UI languages for user to choose
  178. //
  179. class CUILangList
  180. {
  181. public:
  182.     CUILangList() {_iLangIdx = -1; lang = s_arryLangList;
  183.                    _nLangList = ARRAYSIZE(s_arryLangList);
  184.                    _fOffice9Installed = -1;};
  185.    
  186.     void    ValidateLangList();
  187.     BOOL    IsValidLang(int idx) { return (idx < _nLangList) ? lang[idx].fValid: FALSE; };
  188.     int     GetCurrentLangIdx();
  189.     void    SetCurrentLangIdx(int idx);
  190.     LPCTSTR GetCurrentLangName();
  191.     LPCTSTR GetLangNameOfIdx(int idx);
  192.     WORD    GetLangIdOfIdx(int idx) { return (idx < _nLangList) ? lang[idx].wlangid:0; };
  193.     UINT    GetIds(int idx);
  194.     int     GetListSize() {return _nLangList;};
  195.     BOOL    IsOffice9Installed();
  196.     static  HRESULT GetLangList(HWND hdlg, CUILangList ** ppLangList);
  197.     static  HRESULT RemoveLangList(HWND hdlg);
  198. private:
  199.     int _iLangIdx;
  200.     int _nLangList;
  201.     int _fOffice9Installed;
  202.     LANGLIST *lang;
  203. };
  204.  
  205. // CShutDownProcInfo
  206. //
  207. // manages information about processes we want
  208. // to shutdown/restart.
  209. //
  210. typedef enum
  211. {
  212.     PS_UNKNOWN=0,
  213.     PS_CANDIDATE,
  214.     PS_TO_BE_SHUTDOWN,
  215.     PS_IGNORE,
  216.     PS_SHUTDOWN_OK,
  217.     PS_WAITING,
  218.     PS_TO_BE_SHUTDOWN_WITH_NO_RELAUNCH,
  219.     PS_SHUTDOWN_OK_NO_RELAUNCH_NEEDED,
  220. } PROCSTATE;
  221.  
  222. class CShutDownProcInfo : public CProcessInfo
  223. {
  224. public:
  225.     CShutDownProcInfo(HWND hdlgParent);
  226.     ~CShutDownProcInfo();
  227.     HRESULT EnsureProcList();
  228.     HRESULT IncreaseProcList();
  229.     HRESULT NotifyShutDownToFolks(int *nProccess);
  230.     HRESULT AddToProcList(HWND hwndShutDown);
  231.     HRESULT WaitForOneProcess(int iProc);
  232.     HRESULT WaitForFolksShutDown();
  233.     HRESULT GetRestartAppPath(LPTSTR szPath, int cchPath, int iProc);
  234.     HRESULT RestartFolks();
  235.     static DWORD CALLBACK ShutDownThreadProc(void *pv);
  236. protected:
  237.     typedef struct
  238.     {
  239.         DWORD dwPID;
  240.         TCHAR szExeName[32];
  241.         PROCSTATE State;
  242.     } PROCLIST;
  243.     PROCLIST *_pProcList;
  244.     int _nAlloced;
  245.     int _iProcList;
  246.     HWND _hdlgParent;
  247.     BOOL _fAllShutDown;
  248. };
  249. // this always fills '0' to empty digits
  250. // caller has to make sure sz has cdigit+1 of buffer
  251. void IntToHex(OUT LPTSTR sz, IN int cdigit, IN int value)
  252. {
  253.     int i, idigit;
  254.  
  255.     if (sz && value > 0 && cdigit > 0)
  256.     {
  257.         // nul terminate the buffer
  258.         sz[cdigit] = TEXT('\0');
  259.        
  260.         for (i = cdigit-1; i >= 0; i--, value /= 16)
  261.         {
  262.             idigit = value%16;
  263.             if (idigit < 10)
  264.                 sz[i] = (TCHAR)idigit + TEXT('0');
  265.             else
  266.                 sz[i] = (TCHAR)idigit - 10 + TEXT('A');
  267.         }
  268.     }
  269. }
  270.  
  271. // set valid flags for the lang list
  272. // very expensive so expects to be called only once in a session
  273. // from CUILangList::GetLangList
  274. //
  275. #define MAX_SATELLITEPACKS 30 // 30 must be a practical number for satellite packs
  276. void CUILangList::ValidateLangList()
  277. {
  278.     HKEY hKey;
  279.     HRESULT hr;
  280.     TCHAR szValueName[32];
  281.     WORD aryValidLang[MAX_SATELLITEPACKS +1+1] = {0}; // +1 for install lang,
  282.                                                       // +1 for terminator
  283.  
  284.     int  nMaxValidLang = ARRAYSIZE(aryValidLang)-1;   // -1 for terminator
  285.     WORD *pwValid = aryValidLang;
  286.    
  287.     // make the install language always valid
  288.     *pwValid = GetInstallLanguage();
  289.     if (*pwValid != 0)
  290.     {
  291.        *(pwValid+1) = 0; // terminator
  292.        pwValid++;
  293.        nMaxValidLang--;
  294.     }
  295.  
  296.     if (ERROR_SUCCESS ==
  297.     RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_INTERNATIONAL, NULL, KEY_READ, &hKey))
  298.     {
  299.         int i = 0;
  300.         do {
  301.             // see if the value has a match in the list
  302.             DWORD dwType;
  303.             DWORD cb = ARRAYSIZE(szValueName)-2;
  304.  
  305.             hr = SHEnumValue(hKey, i++, szValueName+2, &cb, &dwType, NULL, NULL);
  306.             if (SUCCEEDED(hr) && dwType == REG_SZ)
  307.             {
  308.                 UINT uiInstalled ;
  309.  
  310.                 szValueName[0] = TEXT('0');
  311.                 szValueName[1] = TEXT('x');
  312.                 StrToIntEx(szValueName, STIF_SUPPORT_HEX, (LPINT)&uiInstalled);
  313.                 if (uiInstalled > 0)
  314.                 {
  315.                     *pwValid     = (unsigned short) uiInstalled;
  316.                     *(pwValid+1) = 0; // terminator
  317.                     pwValid++;
  318.                 }
  319.             }
  320.         } while(hr == ERROR_SUCCESS && i < nMaxValidLang);
  321.         RegCloseKey(hKey);
  322.     }
  323.  
  324.     // this assumes we can use StrChrW to search a value in
  325.     // a word array, it also assumes we never have 0 as a langid
  326.     //
  327.     Assert(sizeof(WORD) == sizeof(WCHAR)); // unix?
  328.  
  329.     int nValidLang = (int)(pwValid-aryValidLang);
  330.     for(int idx = 0; idx < GetListSize(); idx++ )
  331.     {
  332.         // abusing the string function but this is a fast way
  333.         if (StrChrW((WCHAR *)aryValidLang, (WCHAR)lang[idx].wlangid))
  334.         {
  335.             lang[idx].fValid = TRUE;
  336.             if(--nValidLang <= 0)
  337.                 break;
  338.         }
  339.     }
  340. }
  341.  
  342. static const TCHAR s_szPropLangList[] = TEXT("langlist");
  343. HRESULT CUILangList::GetLangList(HWND hdlg, CUILangList ** ppLangList)
  344. {
  345.     HRESULT hr=S_OK;
  346.    
  347.     CUILangList *pLangList = (CUILangList *)GetProp(hdlg, s_szPropLangList);
  348.     if (!pLangList)
  349.     {
  350.         pLangList = new CUILangList();
  351.         if (pLangList)
  352.         {
  353.             pLangList->ValidateLangList();
  354.             SetProp(hdlg, s_szPropLangList, (HANDLE)pLangList);
  355.         }
  356.         else
  357.             hr = E_FAIL;
  358.     }
  359.    
  360.     ASSERT(ppLangList);
  361.     if (ppLangList)
  362.         *ppLangList = pLangList;
  363.    
  364.     return hr;
  365. }
  366.  
  367. HRESULT CUILangList::RemoveLangList(HWND hdlg)
  368. {
  369.     HRESULT hr = S_OK;
  370.     CUILangList *pLangList = (CUILangList *)GetProp(hdlg, s_szPropLangList);
  371.  
  372.     if (pLangList)
  373.     {
  374.         delete pLangList;
  375.         RemoveProp(hdlg, s_szPropLangList);    
  376.     }
  377.     else
  378.         hr = S_FALSE;
  379.  
  380.     return hr;
  381. }
  382.  
  383. void CUILangList::SetCurrentLangIdx(int idx)
  384. {
  385.     TCHAR sz[4+1];
  386.     if (idx != _iLangIdx)
  387.     {
  388.         // the resource id is always 4 digit
  389.         IntToHex(sz, 4, lang[idx].wlangid);
  390.         SHSetValue(HKEY_CURRENT_USER, REGSTR_PATH_INTERNATIONAL,
  391.                    s_szResourceLocale, REG_SZ, (void *)sz, sizeof(sz));
  392.         _iLangIdx = idx;
  393.     }
  394. }
  395. // returns idx to the lang array
  396. int CUILangList::GetCurrentLangIdx()
  397. {
  398.     // show the current selection
  399.     TCHAR sz[64];
  400.     DWORD dwType;
  401.     int   isel;
  402.    
  403.     // see if it's cached already
  404.     if (_iLangIdx == -1)
  405.     {
  406.         // We basically wants what we've set in the registry,
  407.         // but if Office9 is installed we'll show whatever
  408.         // Office sets, and we can't change the Office setting anyway
  409.         // MLGetUILanguage returns Office's setting if its there
  410.         // Also I suppose we want to show NT5's UI language here
  411.         //
  412.         if (IsOffice9Installed() || IsOS(OS_WIN2000ORGREATER))
  413.             isel = INETCPL_GetUILanguage();
  414.         else
  415.         {
  416.             DWORD dwcbData = sizeof(sz);
  417.  
  418.             HRESULT hr =  SHGetValue(HKEY_CURRENT_USER, REGSTR_PATH_INTERNATIONAL,
  419.                                   s_szResourceLocale, &dwType, (void *)&sz[2], &dwcbData);
  420.                    
  421.             if (hr == ERROR_SUCCESS && dwType == REG_SZ)
  422.             {
  423.                 sz[0] = TEXT('0');
  424.                 sz[1] = TEXT('x');
  425.                 StrToIntEx(sz, STIF_SUPPORT_HEX, (LPINT)&isel);
  426.             }
  427.             else
  428.             {
  429.                 isel = GetInstallLanguage();
  430.             }
  431.         }
  432.        
  433.         for(int i = 0; i < GetListSize(); i++ )
  434.         {
  435.             if (isel == lang[i].wlangid)
  436.             {
  437.                 _iLangIdx = i;
  438.                 break;
  439.             }
  440.         }
  441.            
  442.         // english for error case
  443.         if (_iLangIdx < 0)
  444.             _iLangIdx = 0;
  445.     }
  446.     return _iLangIdx;
  447. }
  448.  
  449. LPCTSTR CUILangList::GetLangNameOfIdx(int idx)
  450. {
  451.     LPCTSTR pszRet = NULL;
  452.     IMultiLanguage2 *pML2;
  453.     HRESULT hr;
  454.     RFC1766INFO Rfc1766Info={0};
  455.  
  456.     if(!hOLE32)
  457.     {
  458.         if(!_StartOLE32())
  459.         {
  460.             ASSERT(FALSE);
  461.             return NULL;
  462.         }
  463.     }
  464.     hr = pCoInitialize(NULL);
  465.  
  466.     if (FAILED(hr))
  467.         return NULL;
  468.  
  469.     hr = pCoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, IID_IMultiLanguage2, (LPVOID *) &pML2);
  470.  
  471.     if (SUCCEEDED(hr))
  472.     {
  473.         if (idx >= 0)
  474.         {
  475.             if (!lang[idx].szName[0])
  476.             {
  477.                 pML2->GetRfc1766Info(lang[idx].wlangid, INETCPL_GetUILanguage(), &Rfc1766Info);
  478.                 StrCpyNW(lang[idx].szName, Rfc1766Info.wszLocaleName, ARRAYSIZE(lang[0].szName));            
  479.             }
  480.             pszRet = lang[idx].szName;        
  481.         }
  482.         pML2->Release();
  483.     }
  484.  
  485.     pCoUninitialize();
  486.     return pszRet;
  487. }
  488.  
  489. LPCTSTR CUILangList::GetCurrentLangName()
  490. {
  491.     int idx = GetCurrentLangIdx();
  492.     return GetLangNameOfIdx(idx);
  493. }
  494.  
  495. BOOL CUILangList::IsOffice9Installed()
  496. {
  497.     DWORD dwVersion;
  498.     DWORD cb = sizeof(dwVersion);
  499.     if (_fOffice9Installed < 0)
  500.     {
  501.         _fOffice9Installed ++;
  502.         if (ERROR_SUCCESS ==
  503.             SHGetValue(HKEY_LOCAL_MACHINE, s_szLangPackPath, s_szVersion, NULL, &dwVersion, &cb)
  504.           && dwVersion > 0) // magic number - christw tells me so
  505.             _fOffice9Installed ++;
  506.     }
  507.     return (BOOL)_fOffice9Installed;
  508. }
  509.  
  510. void InitCurrentUILang(HWND hDlg)
  511. {
  512.     BOOL fChanged = FALSE;
  513.     CUILangList *pLangList;  
  514.     LPCTSTR pszLangSel = NULL;
  515.     HRESULT hr;
  516.    
  517.     hr = CUILangList::GetLangList(hDlg, &pLangList);
  518.    
  519.     if (SUCCEEDED(hr))
  520.         pszLangSel = pLangList->GetCurrentLangName();
  521.    
  522.     if (pszLangSel)
  523.     {
  524.         TCHAR szBig[1024], szSmall[256];
  525.  
  526.         GetDlgItemText(hDlg, IDC_LANG_CURSEL, szBig, ARRAYSIZE(szBig));
  527.         if (szBig[0])
  528.             fChanged = (StrStr(szBig, pszLangSel) == NULL);
  529.  
  530.         if (MLLoadString((fChanged)? IDS_LANG_FUTUREUSE: IDS_LANG_CURRENTUSE, szSmall, ARRAYSIZE(szSmall)) > 0)
  531.         {
  532.             wnsprintf(szBig, ARRAYSIZE(szBig), szSmall, pszLangSel);
  533.             Static_SetText(GetDlgItem(hDlg, IDC_LANG_CURSEL), szBig);
  534.         }
  535.     }
  536. }
  537.  
  538.  
  539. //
  540. // FillAcceptListBox()
  541. //
  542. // Fills the accept language listbox with names of selected language
  543. //
  544. void FillAcceptListBox(IN HWND hDlg)
  545. {
  546.     IMultiLanguage2 *pML2;
  547.     HRESULT hr;
  548.     HKEY hKey;
  549.     DWORD cb;
  550.     TCHAR sz[MAX_LIST_STRING_LEN], szBuf[MAX_ACCEPT_LANG_LEN], *p1, *p2, *p3;
  551.     HWND hwndList = GetDlgItem(hDlg, IDC_LANG_ACCEPT_LIST);
  552.  
  553.     if(!hOLE32)
  554.     {
  555.         if(!_StartOLE32())
  556.         {
  557.             ASSERT(FALSE);
  558.             return;
  559.         }
  560.     }
  561.     hr = pCoInitialize(NULL);
  562.     if (FAILED(hr))
  563.         return;
  564.  
  565.     hr = pCoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, IID_IMultiLanguage2, (LPVOID *) &pML2);
  566.     if (SUCCEEDED(hr))
  567.     {
  568.         if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_INTERNATIONAL, NULL, NULL, NULL, KEY_SET_VALUE|KEY_READ, NULL, &hKey, NULL))
  569.         {
  570.             LCID lcid;
  571.             RFC1766INFO Rfc1766Info;
  572.             TCHAR sz1[MAX_LIST_STRING_LEN], sz2[MAX_RFC1766_NAME];
  573.  
  574.             cb = sizeof(szBuf);
  575.             if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGSTR_VAL_ACCEPT_LANGUAGE, NULL, NULL, (LPBYTE)szBuf, &cb))
  576.             {
  577.                 p1 = p2 = szBuf;
  578.                 while (NULL != *p1)
  579.                 {
  580.                     WCHAR wsz[MAX_LIST_STRING_LEN];
  581.                     BOOL bEnd = FALSE;
  582.  
  583.                     while (TEXT(',') != *p2 && NULL != *p2)
  584.                         p2 = CharNext(p2);
  585.                     if (NULL != *p2)
  586.                         *p2 = NULL;
  587.                     else
  588.                         bEnd = TRUE;
  589.                     p3 = p1;
  590.                     while (TEXT(';') != *p3 && NULL != *p3)
  591.                         p3 = CharNext(p3);
  592.                     if (NULL != *p3)
  593.                         *p3 = NULL;
  594. #ifdef UNICODE
  595.                     StrCpyN(wsz, p1, ARRAYSIZE(wsz));
  596. #else
  597.                     MultiByteToWideChar(CP_ACP, 0, p1, -1, wsz, MAX_RFC1766_NAME);
  598. #endif
  599.                     hr = pML2->GetLcidFromRfc1766(&lcid, wsz);
  600.                     if (SUCCEEDED(hr))
  601.                     {
  602.                         hr = pML2->GetRfc1766Info(lcid, INETCPL_GetUILanguage(), &Rfc1766Info);
  603.                         if (SUCCEEDED(hr))
  604.                         {
  605. #ifdef UNICODE
  606.                             StrCpyN(sz1, Rfc1766Info.wszLocaleName, ARRAYSIZE(sz1));
  607. #else
  608.                             WideCharToMultiByte(CP_ACP, 0, Rfc1766Info.wszLocaleName, -1, sz1, MAX_LIST_STRING_LEN, NULL, NULL);
  609. #endif
  610.                             wnsprintf(sz, ARRAYSIZE(sz), FORMAT_STR, sz1, p1);
  611.                         }
  612.                     }
  613.                     else
  614.                     {
  615.                         MLLoadString(IDS_USER_DEFINED, sz1, ARRAYSIZE(sz1));
  616.                         wnsprintf(sz, ARRAYSIZE(sz), FORMAT_STR, sz1, p1);
  617.                     }
  618.                     ListBox_AddString(hwndList, sz);
  619.                     if (TRUE == bEnd)
  620.                         p1 = p2;
  621.                     else
  622.                         p1 = p2 = p2 + 1;
  623.                 }
  624.             }
  625.             else
  626.             {
  627.                 lcid = GetUserDefaultLCID();
  628.  
  629.                 hr = pML2->GetRfc1766Info(lcid, INETCPL_GetUILanguage(), &Rfc1766Info);
  630.                 if (SUCCEEDED(hr))
  631.                 {
  632. #ifdef UNICODE
  633.                     StrCpyN(sz1, Rfc1766Info.wszLocaleName,  ARRAYSIZE(sz1));
  634.                     StrCpyN(sz2, Rfc1766Info.wszRfc1766,  ARRAYSIZE(sz2));
  635. #else
  636.                     WideCharToMultiByte(CP_ACP, 0, Rfc1766Info.wszLocaleName, -1, sz1, MAX_LIST_STRING_LEN, NULL, NULL);
  637.                     WideCharToMultiByte(CP_ACP, 0, Rfc1766Info.wszRfc1766, -1, sz2, MAX_RFC1766_NAME, NULL, NULL);
  638. #endif
  639.                     wnsprintf(sz, ARRAYSIZE(sz), FORMAT_STR, sz1, sz2);
  640.                     ListBox_AddString(hwndList, sz);
  641.                 }
  642.             }
  643.             RegCloseKey(hKey);
  644.         }
  645.         pML2->Release();
  646.     }
  647.     pCoUninitialize();
  648. }
  649.  
  650. //
  651. // LanguageDlgInit()
  652. //
  653. // Initializes the Language dialog.
  654. //
  655. BOOL LanguageDlgInit(IN HWND hDlg)
  656. {
  657.     if (!hDlg)
  658.         return FALSE;   // nothing to initialize
  659.  
  660.     FillAcceptListBox(hDlg);
  661.  
  662.     EnableWindow(GetDlgItem(hDlg, IDC_LANG_REMOVE_BUTTON), FALSE);
  663.     EnableWindow(GetDlgItem(hDlg, IDC_LANG_MOVE_UP_BUTTON), FALSE);
  664.     EnableWindow(GetDlgItem(hDlg, IDC_LANG_MOVE_DOWN_BUTTON), FALSE);
  665.     EnableWindow(GetDlgItem(hDlg, IDC_LANG_ADD_BUTTON), !g_restrict.fInternational);
  666.    
  667.     // On NT5, we use NT5's MUI feature instead of IE5 plugui
  668.     if (IsOS(OS_WIN2000ORGREATER))
  669.         ShowWindow(GetDlgItem(hDlg, IDC_LANG_UI_PREF), SW_HIDE);
  670.     else
  671.     {
  672.         UINT uiACP = GetACP();
  673.  
  674.         // We don't support PlugUI on these platforms
  675.         if (uiACP == CP_ARABIC || uiACP == CP_HEBREW || uiACP == CP_THAI)
  676.             ShowWindow(GetDlgItem(hDlg, IDC_LANG_UI_PREF), SW_HIDE);
  677.         else
  678.             EnableWindow(GetDlgItem(hDlg, IDC_LANG_UI_PREF), !g_restrict.fInternational);
  679.     }
  680.  
  681.     // show the current UI lang
  682.     InitCurrentUILang(hDlg);
  683.    
  684.     // everything ok
  685.     return TRUE;
  686. }
  687.  
  688. //
  689. // SaveLanguageData()
  690. //
  691. // Save the new language settings into regestry
  692. //
  693. void SaveLanguageData(IN HWND hDlg)
  694. {
  695.     HKEY hKey;
  696.     DWORD dw;
  697.     int i, iNumItems, iQ, n;
  698.     TCHAR szBuf[MAX_ACCEPT_LANG_LEN];
  699.  
  700.     if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_INTERNATIONAL, NULL, NULL, NULL, KEY_WRITE, NULL, &hKey, &dw ))
  701.     {
  702.         HWND hwndList = GetDlgItem(hDlg, IDC_LANG_ACCEPT_LIST);
  703.  
  704.         iNumItems = ListBox_GetCount(hwndList);
  705.  
  706.         for (n = 1, iQ = 10; iQ < iNumItems; iQ *= 10, n++)
  707.             ;
  708.  
  709.         szBuf[0] = NULL;
  710.         for (i = 0; i < iNumItems; i++)
  711.         {
  712.             TCHAR sz[MAX_LIST_STRING_LEN], *p1, *p2;
  713.  
  714.             ListBox_GetText(hwndList, i, sz);
  715.             p1 = sz;
  716.             // We can assume safely there is '[' and ']' in this string.
  717.             while (TEXT('[') != *p1)
  718.                 p1 = CharNext(p1);
  719.             p1 = p2 = p1 + 1;
  720.             while (TEXT(']') != *p2)
  721.                 p2 = CharNext(p2);
  722.             *p2 = NULL;
  723.             if (0 == i)
  724.                 StrCpyN(szBuf, p1, ARRAYSIZE(szBuf));
  725.             else
  726.             {
  727.                 TCHAR szF[MAX_ACCEPT_LANG_LEN], szQ[MAX_ACCEPT_LANG_LEN];
  728.  
  729.                 int len = lstrlen(szBuf);
  730.                 StrCpyN(szBuf + len, TEXT(","), ARRAYSIZE(szBuf) - len);
  731.                 len++;
  732.                 StrCpyN(szBuf + len, p1, ARRAYSIZE(szBuf) - len);
  733.                 wnsprintf(szF, ARRAYSIZE(szF), TEXT(";q=0.%%0%dd"), n);
  734.                 wnsprintf(szQ, ARRAYSIZE(szQ), szF, ((iNumItems - i) * iQ + (iNumItems / 2)) / iNumItems);
  735.                 len = lstrlen(szBuf);
  736.                 StrCpyN(szBuf + len , szQ, ARRAYSIZE(szBuf) - len);
  737.             }
  738.         }
  739.         RegSetValueEx(hKey, REGSTR_VAL_ACCEPT_LANGUAGE, NULL, REG_SZ, (LPBYTE)szBuf, (lstrlen(szBuf)+1)*sizeof(TCHAR));
  740.         RegCloseKey(hKey);
  741.     }
  742. }
  743.  
  744. // MoveUpDownListItem()
  745. //
  746. // Move selected list item up or down
  747. //
  748. void MoveUpDownListItem(HWND hDlg, HWND hwndList, BOOL bUp)
  749. {
  750.     int i, iNumItems;
  751.     TCHAR sz[MAX_LIST_STRING_LEN];
  752.  
  753.     i = ListBox_GetCurSel(hwndList);
  754.     iNumItems = ListBox_GetCount(hwndList);
  755.     ListBox_GetText(hwndList, i, sz);
  756.     ListBox_DeleteString(hwndList, i);
  757.  
  758.     i += (bUp)? -1: 1;
  759.     if (i < 0)
  760.         i = 0;
  761.     else if (i >= iNumItems)
  762.         i = iNumItems - 1;
  763.     ListBox_InsertString(hwndList, i, sz);
  764.     ListBox_SetSel(hwndList, TRUE, i);
  765.     ListBox_SetCurSel(hwndList, i);
  766.  
  767.     EnableWindow(GetDlgItem(hDlg, IDC_LANG_MOVE_UP_BUTTON), i != 0);
  768.     EnableWindow(GetDlgItem(hDlg, IDC_LANG_MOVE_DOWN_BUTTON), i < iNumItems - 1);
  769.  
  770.     if (NULL == GetFocus()) // This prevent keyboard access disable
  771.         SetFocus(hwndList);
  772. }
  773.  
  774.  
  775. //
  776. // FillLanguageListBox()
  777. //
  778. // Fills the language listbox with the names of available languages
  779. //
  780. BOOL FillLanguageListBox(IN HWND hDlg)
  781. {
  782.     IMultiLanguage2 *pML2;
  783.     HRESULT hr;
  784.     TCHAR sz[MAX_LIST_STRING_LEN], sz1[MAX_LOCALE_NAME], sz2[MAX_RFC1766_NAME];
  785.     HWND hwndEdit = GetDlgItem(hDlg, IDC_LANG_USER_DEFINED_EDIT);
  786.     HWND hwndList = GetDlgItem(hDlg, IDC_LANG_AVAILABLE_LIST);
  787.     HWND hwndAccept = GetDlgItem(GetParent(hDlg), IDC_LANG_ACCEPT_LIST);
  788.    
  789.     SendMessage(hwndEdit, EM_SETLIMITTEXT, 16, 0L); // Set Limit text as 16 characters
  790.  
  791.     if(!hOLE32)
  792.     {
  793.         if(!_StartOLE32())
  794.         {
  795.             ASSERT(FALSE);
  796.             return FALSE;
  797.         }
  798.     }
  799.     hr = pCoInitialize(NULL);
  800.     if (FAILED(hr))
  801.         return FALSE;
  802.  
  803.     hr = pCoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, IID_IMultiLanguage2, (LPVOID *) &pML2);
  804.     if (SUCCEEDED(hr))
  805.     {
  806.         IEnumRfc1766 *pEnumRfc1766;
  807.         RFC1766INFO Rfc1766Info;
  808.  
  809.         if (SUCCEEDED(pML2->EnumRfc1766(INETCPL_GetUILanguage(), &pEnumRfc1766)))
  810.         {
  811.             while (S_OK == pEnumRfc1766->Next(1, &Rfc1766Info, NULL))
  812.             {
  813. #ifdef UNICODE
  814.                 StrCpyN(sz1, Rfc1766Info.wszLocaleName, ARRAYSIZE(sz1));
  815.                 StrCpyN(sz2, Rfc1766Info.wszRfc1766,  ARRAYSIZE(sz2));
  816. #else
  817.                 WideCharToMultiByte(CP_ACP, 0, Rfc1766Info.wszLocaleName, -1, sz1, MAX_LOCALE_NAME, NULL, NULL);
  818.                 WideCharToMultiByte(CP_ACP, 0, Rfc1766Info.wszRfc1766, -1, sz2, MAX_RFC1766_NAME, NULL, NULL);
  819. #endif
  820.                 wnsprintf(sz, ARRAYSIZE(sz), FORMAT_STR, sz1, sz2);
  821.                 if (LB_ERR == ListBox_FindStringExact(hwndAccept, -1, sz))
  822.                     ListBox_AddString(hwndList, sz);
  823.             }
  824.             pEnumRfc1766->Release();
  825.         }
  826.         pML2->Release();
  827.     }
  828.     pCoUninitialize();
  829.    
  830.     // everything ok
  831.     return TRUE;
  832. }
  833.  
  834. //
  835. // AddLanguage()
  836. //
  837. // Add selected language to accept language listbox.
  838. //
  839. void AddLanguage(IN HWND hDlg)
  840. {
  841.     int i, j, *pItems, iNumItems, iIndex;
  842.     TCHAR sz[MAX_LIST_STRING_LEN];
  843.     HWND hdlgParent = GetParent(hDlg);
  844.     HWND hwndFrom = GetDlgItem(hDlg, IDC_LANG_AVAILABLE_LIST);
  845.     HWND hwndTo = GetDlgItem(hdlgParent, IDC_LANG_ACCEPT_LIST);
  846.  
  847.     i = ListBox_GetSelCount(hwndFrom);
  848.     if (0 < i && (pItems = (PINT)LocalAlloc(LPTR, sizeof(int)*i)))
  849.     {
  850.         ListBox_GetSelItems(hwndFrom, i, pItems);
  851.         for (j = 0; j < i; j++)
  852.         {
  853.             ListBox_GetText(hwndFrom, pItems[j], sz);
  854.             ListBox_AddString(hwndTo, sz);
  855.         }
  856.         LocalFree(pItems);
  857.     }
  858.     if (GetWindowTextLength(GetDlgItem(hDlg, IDC_LANG_USER_DEFINED_EDIT)))
  859.     {
  860.         TCHAR *p, sz1[MAX_LIST_STRING_LEN], sz2[MAX_LIST_STRING_LEN];
  861.         BOOL fValid = TRUE;
  862.  
  863.         GetWindowText(GetDlgItem(hDlg, IDC_LANG_USER_DEFINED_EDIT), sz2, ARRAYSIZE(sz2));
  864.         p = sz2;
  865.         while (NULL != *p && TRUE == fValid)
  866.         {
  867.             switch (*p)
  868.             {
  869.                 // Invalid characters for user-defined string
  870.                 case TEXT(','):
  871.                 case TEXT(';'):
  872.                 case TEXT('['):
  873.                 case TEXT(']'):
  874.                 case TEXT('='):
  875.                     fValid = FALSE;
  876.                     break;
  877.  
  878.                 default:
  879.                     p = CharNext(p);
  880.             }
  881.         }
  882.         if (FALSE == fValid)
  883.         {
  884.             TCHAR szTitle[256], szErr[1024];
  885.  
  886.             MLLoadShellLangString(IDS_USER_DEFINED_ERR, szErr, ARRAYSIZE(szErr));
  887.             GetWindowText(hDlg, szTitle, ARRAYSIZE(szTitle));
  888.             MessageBox(hDlg, szErr, szTitle, MB_OK | MB_ICONHAND);
  889.         }
  890.         else
  891.         {
  892.             MLLoadString(IDS_USER_DEFINED, sz1, ARRAYSIZE(sz1));
  893.             wnsprintf(sz, ARRAYSIZE(sz), FORMAT_STR, sz1, sz2);
  894.             ListBox_AddString(hwndTo, sz);
  895.         }
  896.     }
  897.     iIndex = ListBox_GetCurSel(hwndTo);
  898.     if (LB_ERR != iIndex)
  899.     {
  900.         iNumItems = ListBox_GetCount(hwndTo);
  901.         EnableWindow(GetDlgItem(hdlgParent, IDC_LANG_REMOVE_BUTTON), iNumItems > 0);
  902.         EnableWindow(GetDlgItem(hdlgParent, IDC_LANG_MOVE_UP_BUTTON), iIndex > 0);
  903.         EnableWindow(GetDlgItem(hdlgParent, IDC_LANG_MOVE_DOWN_BUTTON), iIndex < iNumItems - 1);
  904.     }
  905. }
  906.  
  907. int ComboBoxEx_AddString(IN HWND hwndCtl, IN LPCTSTR sz)
  908. {
  909.     COMBOBOXEXITEM cbexItem = {0};
  910.    
  911.     int csz = _tcslen(sz);
  912.  
  913.     cbexItem.mask = CBEIF_TEXT;
  914.     cbexItem.pszText = (LPTSTR)sz;
  915.     cbexItem.cchTextMax = csz;
  916.    
  917.     // sort the string based on the current locale
  918.     // we don't bother to use binary search because
  919.     // the list is up to 25 item
  920.     TCHAR szItem[MAX_LOCALE_NAME];
  921.     int i, itemCount = ComboBox_GetCount(hwndCtl);
  922.     for (i = 0; i < itemCount; i++)
  923.     {
  924.         ComboBox_GetLBText(hwndCtl, i, szItem);
  925.         if (CompareString(INETCPL_GetUILanguage(),
  926.                           0,
  927.                           sz,
  928.                           csz,
  929.                           szItem,
  930.                           ARRAYSIZE(szItem)) == CSTR_LESS_THAN)
  931.         {
  932.             break;
  933.         }
  934.     }
  935.     cbexItem.iItem = i;
  936.    
  937.     SendMessage(hwndCtl, CBEM_INSERTITEM, (WPARAM)0, (LPARAM)(LPVOID)&cbexItem);
  938.     return i;
  939. }
  940.  
  941. BOOL FillUILangListBox(IN HWND hDlg, CUILangList *pLangList)
  942. {
  943.     HWND hwndCombo = GetDlgItem(hDlg, IDC_COMBO_UILANG);
  944.     BOOL bNT5 = IsOS(OS_WIN2000ORGREATER);
  945.     DWORD dwAcp = GetACP();
  946.     LPCTSTR pszLangName;
  947.    
  948.     if (!pLangList)
  949.         return FALSE;
  950.  
  951.     // fill the list up.
  952.     for (int i = 0; i < pLangList->GetListSize(); i++)
  953.     {
  954.         if (!pLangList->IsValidLang(i))
  955.             continue;
  956.  
  957.         if (!bNT5)
  958.         {
  959.             LANGID lid = pLangList->GetLangIdOfIdx(i);
  960.  
  961.             if (dwAcp == CP_THAI || dwAcp == CP_ARABIC || dwAcp == CP_HEBREW)
  962.             {
  963.                 // do not support cross codepage PlugUI
  964.                 // on Thai or Middle East platform(Arabic/Hebrew)
  965.                 static DWORD dwDefCP = 0;
  966.  
  967.                 if (dwDefCP == 0)
  968.                 {
  969.                     TCHAR szLcData[6+1]; // +2 for '0x' +1 for terminator
  970.  
  971.                     GetLocaleInfo( MAKELCID(lid, SUBLANG_NEUTRAL),
  972.                         LOCALE_IDEFAULTANSICODEPAGE, szLcData, ARRAYSIZE(szLcData));
  973.                                        
  974.                     dwDefCP = StrToInt(szLcData);
  975.                 }
  976.                 if (dwDefCP != dwAcp && lid != 0x0409 && lid != GetInstallLanguage())
  977.                     continue;
  978.             }
  979.             else
  980.             {
  981.                 // skip Arabic and Hebrew on non-supporting platform
  982.                 if (lid == 0x401 || lid == 0x40d)
  983.                     continue;
  984.             }
  985.         }
  986.  
  987.         pszLangName = pLangList->GetLangNameOfIdx(i);
  988.  
  989.         // ComboBox_FindStringExact has problems to handle DBCS Unicode characters
  990.         if (pszLangName)
  991.         {
  992.             int ipos = ComboBoxEx_AddString(hwndCombo, pszLangName);
  993.             if (ipos >= 0)
  994.             {
  995.                 ComboBox_SetItemData(hwndCombo, ipos, i);
  996.             }
  997.         }
  998.     }
  999.  
  1000.     // show the current selection
  1001.     int iLangIdx = pLangList->GetCurrentLangIdx();
  1002.     if (iLangIdx >= 0)
  1003.     {
  1004.         int iCBPos;
  1005.         int iCBSize = ComboBox_GetCount(hwndCombo);
  1006.         for (iCBPos = 0; iCBPos < iCBSize; iCBPos++)
  1007.         {
  1008.             if (iLangIdx == ComboBox_GetItemData(hwndCombo, iCBPos))
  1009.                 break;
  1010.         }
  1011.  
  1012.         if (iCBPos < iCBSize)
  1013.             ComboBox_SetCurSel(hwndCombo, iCBPos);
  1014.     }
  1015.     return TRUE;
  1016. }
  1017.  
  1018. //
  1019. // Shutdown/reboot procedures implementation
  1020. //
  1021. // synopsis: CShutDownInfo class implements the method and the process list
  1022. //           which handle the sequence.
  1023. //           s_arryClsNames[] holds the list of target application
  1024. //           ChangeLanguage() (global) triggers the sequence being called from
  1025. //           LangChangeDlgProc().
  1026. //
  1027. static const LPTSTR s_arryClsNames[] =  
  1028. {
  1029.     TEXT("IEFrame"),                       // browser instance
  1030.     TEXT("ThorBrowserWndClass"),           // OE
  1031.     TEXT("HH Parent"),                     // Html Help
  1032.     TEXT("MPWClass"),                      //
  1033.     TEXT("Outlook Express Browser Class"), // OE
  1034.     TEXT("ATH_Note"),                      // OE?
  1035.     TEXT("WABBrowseView"),                 // WAB
  1036.     TEXT("Afx:400000:8:10008:0:900d6"),
  1037.     TEXT("Media Player 2"),
  1038.     TEXT("FrontPageExpressWindow"),
  1039.     TEXT("MSBLUIManager"),                 // Messenger
  1040. };
  1041.  
  1042. //
  1043. // CShutDownInfo
  1044. // class methods implementation
  1045. //
  1046. #define SHUTDOWN_TIMEOUT 2000 // 2 sec
  1047. #define RELAUNCH_TIMEOUT 1000 // 1 sec
  1048. CShutDownProcInfo::CShutDownProcInfo(HWND hDlg)
  1049. {
  1050.     _pProcList = NULL;
  1051.     _nAlloced = 0;
  1052.     _iProcList = 0;
  1053.     _hdlgParent = hDlg;
  1054.     _fAllShutDown = FALSE;
  1055. }
  1056.  
  1057. CShutDownProcInfo::~CShutDownProcInfo()
  1058. {
  1059.     if (_pProcList)
  1060.         LocalFree(_pProcList);
  1061. }
  1062.  
  1063.  
  1064. HRESULT CShutDownProcInfo::EnsureProcList()
  1065. {
  1066.     HRESULT hr = S_OK;
  1067.     if (!_pProcList)
  1068.     {
  1069.         // alloc mem for practical # of processes
  1070.         _nAlloced = ARRAYSIZE(s_arryClsNames);
  1071.         _pProcList = (PROCLIST *)LocalAlloc(LPTR, sizeof(PROCLIST)*_nAlloced);
  1072.     }
  1073.     if (!_pProcList)
  1074.     {
  1075.         _nAlloced = 0;
  1076.         hr = E_FAIL;
  1077.     }
  1078.  
  1079.     return hr;
  1080. }
  1081. HRESULT CShutDownProcInfo::IncreaseProcList()
  1082. {
  1083.     HRESULT hr = S_OK;
  1084.     PROCLIST * pl = NULL;
  1085.     // realloc mem every so often
  1086.     if (_iProcList+1 > _nAlloced)
  1087.     {
  1088.         pl = (PROCLIST *)LocalReAlloc(_pProcList, sizeof(PROCLIST)*(ARRAYSIZE(s_arryClsNames)+_nAlloced),
  1089.                                       LMEM_MOVEABLE | LMEM_ZEROINIT);
  1090.         if (pl)
  1091.         {
  1092.             _nAlloced += ARRAYSIZE(s_arryClsNames);
  1093.             _pProcList =  pl;
  1094.         }
  1095.         else
  1096.            hr = E_FAIL;
  1097.     }
  1098.  
  1099.     if (hr == S_OK)
  1100.         _iProcList++;
  1101.  
  1102.     return hr;
  1103. }
  1104. // CShutDownProcInfo::AddToProcList()
  1105. //
  1106. // synopsis: Get process info from given window handle
  1107. //           store it for shutdown procedure
  1108. //
  1109. //
  1110. //
  1111. HRESULT CShutDownProcInfo::AddToProcList(HWND hwnd)
  1112. {
  1113.     HRESULT hr = S_OK;
  1114.  
  1115.     hr = EnsureProcList();
  1116.     if (SUCCEEDED(hr) && hwnd)
  1117.     {
  1118.         DWORD dwPID;
  1119.         BOOL  fFoundDup = FALSE;
  1120.  
  1121.         GetWindowThreadProcessId(hwnd, &dwPID);
  1122.        
  1123.         // check to see if we already have the PID in the list
  1124.         for (int i=0; i < _iProcList; i++)
  1125.         {
  1126.             if (_pProcList[i].dwPID == dwPID)
  1127.             {
  1128.                 fFoundDup = TRUE;
  1129.                 break;
  1130.             }
  1131.         }
  1132.  
  1133.         // add proccess info only if we don't have it already
  1134.         if (!fFoundDup)
  1135.         {
  1136.             hr = IncreaseProcList();
  1137.             if (SUCCEEDED(hr))
  1138.             {
  1139.                 int iCur = _iProcList-1;
  1140.  
  1141.                 GetExeNameFromPID(dwPID,
  1142.                     _pProcList[iCur].szExeName,
  1143.                     ARRAYSIZE(_pProcList[iCur].szExeName));
  1144.  
  1145.                 _pProcList[iCur].dwPID = dwPID;
  1146.                 _pProcList[iCur].State = PS_UNKNOWN;
  1147.             }
  1148.         }
  1149.     }
  1150.     return hr;    
  1151. }
  1152.  
  1153. // CShutDownProcInfo::WaitForOneProcess
  1154. //
  1155. // synopsis: ensures the given process
  1156. //           has terminated
  1157. //
  1158. //
  1159. HRESULT CShutDownProcInfo::WaitForOneProcess(int iProc)
  1160. {
  1161.     HRESULT hr = S_OK;
  1162.     if (iProc < _iProcList && _pProcList[iProc].State != PS_SHUTDOWN_OK)
  1163.     {
  1164.         DWORD dwProcessFlags = PROCESS_ALL_ACCESS |
  1165.                                (_fNT ? SYNCHRONIZE : 0 );
  1166.  
  1167.         HANDLE hProc = OpenProcess(dwProcessFlags,
  1168.                                    FALSE,    
  1169.                                    _pProcList[iProc].dwPID);
  1170.  
  1171.         // pressume it has terminated, get it marked so
  1172.         _pProcList[iProc].State = PS_SHUTDOWN_OK;
  1173.  
  1174.         if (hProc)
  1175.         {
  1176.             // if the proccess in query is still alive,
  1177.             // we'll wait with time out here
  1178.             //
  1179.             DWORD dwRet = WaitForSingleObject (hProc, SHUTDOWN_TIMEOUT);
  1180.             if (dwRet == WAIT_TIMEOUT)
  1181.             {
  1182.                 _pProcList[iProc].State = PS_WAITING;
  1183.             }
  1184.            
  1185.             CloseHandle(hProc);
  1186.         }
  1187.     }
  1188.     return hr;
  1189. }
  1190.  
  1191. // CShutDownProcInfo::WaitForFolksShutDown
  1192. //
  1193. // synopsis: ensure the nominated processes terminate. If anyone
  1194. //           doesn't want to terminate, wait for her retrying a couple of
  1195. //           times and note her name so we can show it to the user.
  1196. //          
  1197. //
  1198. #define MAXSHUTDOWNTRY 10
  1199. HRESULT CShutDownProcInfo::WaitForFolksShutDown()
  1200. {
  1201.     HRESULT hr = S_OK;
  1202.     int    iTry = 0;
  1203.     do
  1204.     {
  1205.         // pressume all will be fine
  1206.         _fAllShutDown = TRUE;
  1207.         // waiting loop
  1208.         for (int i = 0; i < _iProcList; i++)
  1209.         {
  1210.             WaitForOneProcess(i);
  1211.             if (_pProcList[i].State != PS_SHUTDOWN_OK)
  1212.                 _fAllShutDown = FALSE;
  1213.         }
  1214.     }
  1215.     while( !_fAllShutDown && iTry++ < MAXSHUTDOWNTRY  );
  1216.     // FEATURE: here we should put up a dialog
  1217.     //         to ask user if they want to wait
  1218.     //         for the apps
  1219.  
  1220.     return hr;
  1221. }
  1222.  
  1223. // CShutDownProcInfo::NotifyShutDownToFolks
  1224. //
  1225. // synopsis: send POI_OFFICE_COMMAND to possible candidates on the desktop
  1226. //           if a candidate replies with valid value, save the proccess
  1227. //           information for the later restart procedure.
  1228. //
  1229. HRESULT CShutDownProcInfo::NotifyShutDownToFolks(int *pnProcess)
  1230. {
  1231.     HWND hwndShutDown, hwndAfter;
  1232.     PLUGUI_QUERY pq;
  1233.     HRESULT hr = S_OK;
  1234.     int     nProcToShutDown = 0;
  1235.  
  1236.     for (int i = 0; i < ARRAYSIZE(s_arryClsNames); i++)
  1237.     {
  1238.         hwndAfter = NULL;
  1239.         while (hwndShutDown = FindWindowEx(NULL, hwndAfter, s_arryClsNames[i], NULL))
  1240.         {
  1241.             pq.uQueryVal = (UINT)SendMessage(hwndShutDown, PUI_OFFICE_COMMAND, PLUGUI_CMD_QUERY, 0);
  1242.             if (pq.uQueryVal)
  1243.             {
  1244.                 if(pq.PlugUIInfo.uMajorVersion == OFFICE_VERSION_9)
  1245.                 {
  1246.                     PostMessage(hwndShutDown, PUI_OFFICE_COMMAND, (WPARAM)PLUGUI_CMD_SHUTDOWN, 0);
  1247.  
  1248.                     // store the information about the process which this window belongs to
  1249.                     // we only need to remember non OLE processes here for re-starting.
  1250.                     if (!pq.PlugUIInfo.uOleServer)
  1251.                     {
  1252.                         AddToProcList(hwndShutDown);
  1253.                         nProcToShutDown ++;
  1254.                     }
  1255.                 }
  1256.             }
  1257.             hwndAfter = hwndShutDown;
  1258.         }
  1259.     }
  1260.     if (!nProcToShutDown)
  1261.         hr = S_FALSE;
  1262.  
  1263.     if (pnProcess)
  1264.         *pnProcess = nProcToShutDown;
  1265.  
  1266.     return hr;
  1267. }
  1268.  
  1269. const TCHAR c_szRegAppPaths[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\");
  1270. HRESULT CShutDownProcInfo::GetRestartAppPath(LPTSTR szPath, int cchPath, int iProc)
  1271. {
  1272.     HRESULT hr = S_OK;
  1273.     TCHAR szAppPath[MAX_PATH];
  1274.     TCHAR szRegKey[MAX_PATH];
  1275.  
  1276.     ASSERT(szPath && cchPath > 0);
  1277.  
  1278.     if (iProc < _iProcList)
  1279.     {
  1280.         _tcscpy(szRegKey, c_szRegAppPaths);
  1281.         _tcscat(szRegKey, _pProcList[iProc].szExeName);
  1282.        
  1283.         DWORD cb = sizeof(szAppPath);
  1284.         if (ERROR_SUCCESS != SHGetValue(HKEY_LOCAL_MACHINE, szRegKey, NULL, NULL, szAppPath, &cb))
  1285.         {
  1286.             szPath[0] = TEXT('0');
  1287.             hr = E_FAIL;
  1288.         }
  1289.         else
  1290.             _tcsncpy(szPath, szAppPath, cchPath);
  1291.     }
  1292.     return hr;
  1293. }
  1294.  
  1295. HRESULT CShutDownProcInfo::RestartFolks()
  1296. {
  1297.     PROCESS_INFORMATION pi;
  1298.     for (int i = 0; i < _iProcList; i++)
  1299.     {
  1300.         STARTUPINFO si = {0};
  1301.         si.cb = sizeof(si);
  1302.         if (_pProcList[i].State == PS_SHUTDOWN_OK)
  1303.         {
  1304.             TCHAR szAppPath[MAX_PATH];    
  1305.             HRESULT hr = GetRestartAppPath(szAppPath, ARRAYSIZE(szAppPath), i);
  1306.             if (hr == S_OK)
  1307.             {
  1308.                 BOOL fLaunchedOK =
  1309.                 CreateProcess (szAppPath,               // name of app to launch
  1310.                                 NULL,                   // lpCmdLine
  1311.                                 NULL,                   // lpProcessAttributes
  1312.                                 NULL,                   // lpThreadAttributes
  1313.                                 TRUE,                   // bInheritHandles
  1314.                                 NORMAL_PRIORITY_CLASS,  // dwCreationFlags
  1315.                                 NULL,                   // lpEnvironment
  1316.                                 NULL,                   // lpCurrentDirectory
  1317.                                 &si,                    // lpStartupInfo
  1318.                                 &pi);                   // lpProcessInformation
  1319.  
  1320.                 if (fLaunchedOK)
  1321.                 {
  1322.                     DWORD dwRet = WaitForInputIdle (pi.hProcess,
  1323.                                                     RELAUNCH_TIMEOUT);
  1324.                     CloseHandle(pi.hProcess);
  1325.                     CloseHandle(pi.hThread);
  1326.                 }
  1327.             }
  1328.         }
  1329.     }
  1330.     return S_OK;
  1331. }
  1332.  
  1333.  
  1334.  
  1335. //
  1336. //   CShutDownProcInfo::ShutDownThreadProc
  1337. //
  1338. //   synopsis: launched from changelang dialog so the dialog
  1339. //             wouldn't get blocked when we're waiting for our apps
  1340. //             to shutdown/restart. this is a static proc
  1341. //             so we should be able to delete the class instance
  1342. //             in this proc.
  1343. //
  1344. DWORD CALLBACK CShutDownProcInfo::ShutDownThreadProc(void *pv)
  1345. {
  1346.     CShutDownProcInfo *pspi = (CShutDownProcInfo *)pv;
  1347.    
  1348.     if (pspi)
  1349.     {
  1350.         HRESULT hr;
  1351.         int     nToShutDown;
  1352.         // send PUI_OFFICE_COMMAND to corresponding folks...
  1353.         hr = pspi->NotifyShutDownToFolks(&nToShutDown);
  1354.  
  1355.         // and wait until all processes shutdown
  1356.         if (SUCCEEDED(hr) && nToShutDown > 0)
  1357.         {
  1358.             hr = pspi->WaitForFolksShutDown();
  1359.  
  1360.             // then restart here
  1361.             if (SUCCEEDED(hr))
  1362.                pspi->RestartFolks();
  1363.         }
  1364.    
  1365.         // now the parent dialog should go away
  1366.         int iret = (nToShutDown > 0) ?
  1367.                    RETURN_SETLANG_ENDLANGDIALOG: RETURN_SETLANG_CLOSEDNORMAL;
  1368.        
  1369.         EndDialog(pspi->_hdlgParent, iret);
  1370.    
  1371.         // delete this class instance
  1372.         delete pspi;
  1373.     }
  1374.     return 0;
  1375. }
  1376.  
  1377. void OpenSatelliteDownloadUrl(HWND hDlg)
  1378. {
  1379.     // get the default Url from registry
  1380.     TCHAR szSatelliteUrl[INTERNET_MAX_URL_LENGTH];
  1381.  
  1382.     // reg api needs size in byte
  1383.     DWORD dwType, dwcbData = sizeof(szSatelliteUrl);
  1384.    
  1385.     DWORD dwRet =  SHGetValue(HKEY_LOCAL_MACHINE, REGSTR_PATH_INTERNATIONAL,
  1386.                              NULL, &dwType, (void *)szSatelliteUrl, &dwcbData);
  1387.     if (dwRet != ERROR_SUCCESS || !szSatelliteUrl[0])
  1388.     {
  1389.        // use the hard coded Url instead
  1390.        _tcscpy(szSatelliteUrl, s_szUrlSPK);
  1391.     }
  1392.  
  1393.     if(!hOLE32)
  1394.     {
  1395.         if(!_StartOLE32())
  1396.         {
  1397.             ASSERT(FALSE);
  1398.             return;
  1399.         }
  1400.     }
  1401.  
  1402.     HRESULT hr = pCoInitialize(NULL);
  1403.     if (SUCCEEDED(hr))
  1404.     {
  1405.         NavToUrlUsingIE(szSatelliteUrl, TRUE);
  1406.         pCoUninitialize();
  1407.     }
  1408. }
  1409.  
  1410. INT_PTR CALLBACK LangMsgDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1411. {
  1412.     switch (uMsg)
  1413.     {
  1414.         case WM_COMMAND:
  1415.         {
  1416.             switch (GET_WM_COMMAND_ID(wParam, lParam))
  1417.             {
  1418.                 case IDYES:
  1419.                 case IDNO:
  1420.                 case IDOK:
  1421.                 case IDCANCEL:
  1422.                     EndDialog(hDlg, GET_WM_COMMAND_ID(wParam, lParam));
  1423.                     break;
  1424.             }
  1425.             return TRUE;
  1426.         }
  1427.  
  1428.         case WM_HELP:           // F1
  1429.             ResWinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, IDS_HELPFILE,
  1430.                 HELP_WM_HELP, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
  1431.             break;
  1432.  
  1433.         case WM_CONTEXTMENU:    // right mouse click
  1434.             ResWinHelp( (HWND) wParam, IDS_HELPFILE,
  1435.                 HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);        
  1436.             break;
  1437.     }
  1438.     return FALSE;
  1439. }
  1440.  
  1441. BOOL ChangeLanguage(IN HWND hDlg, CUILangList *pLangList)
  1442. {
  1443.     HWND hwndCombo = GetDlgItem(hDlg, IDC_COMBO_UILANG);
  1444.     int iSel = ComboBox_GetCurSel(hwndCombo);
  1445.     INT_PTR idxSel = 0;
  1446.     int idxCur;
  1447.    
  1448.     if (iSel != CB_ERR)
  1449.         idxSel = ComboBox_GetItemData(hwndCombo, iSel);
  1450.  
  1451.     if ( idxSel != CB_ERR
  1452.         && idxSel < pLangList->GetListSize())
  1453.     {
  1454.         idxCur = pLangList->GetCurrentLangIdx();
  1455.  
  1456.         if (idxCur != idxSel)
  1457.         {
  1458.             INT_PTR iRet = DialogBox(MLGetHinst(), MAKEINTRESOURCE(IDD_LANG_WARNING), hDlg, LangMsgDlgProc);
  1459.  
  1460.             if (IDCANCEL != iRet)
  1461.             {
  1462.                 pLangList->SetCurrentLangIdx((int)idxSel);
  1463.  
  1464.                 if (IDYES == iRet)
  1465.                 {
  1466.                     CShutDownProcInfo  *pspi = new CShutDownProcInfo(hDlg);
  1467.                     if (!SHCreateThread(pspi->ShutDownThreadProc, (void *)pspi, 0, NULL))
  1468.                         delete pspi;
  1469.  
  1470.                     // returning TRUE to indicate that we do shutdown/restart
  1471.                     return TRUE;
  1472.                 }
  1473.                 else
  1474.                 {
  1475.                     DialogBox(MLGetHinst(), MAKEINTRESOURCE(IDD_LANG_INFO), hDlg, LangMsgDlgProc);
  1476.                 }
  1477.             }
  1478.         }
  1479.     }
  1480.     // returning FALSE to indicate that we haven't changed the language
  1481.     return FALSE;
  1482. }
  1483.  
  1484. //
  1485. // LangChangeDlgProc()
  1486. //
  1487. // Message handler for the "Change Language" subdialog.
  1488. //
  1489. INT_PTR CALLBACK LangChangeDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1490. {
  1491.     CUILangList *pLangList;
  1492.     switch (uMsg)
  1493.     {
  1494.         case WM_INITDIALOG:
  1495.             CUILangList::GetLangList(GetParent(hDlg), &pLangList);
  1496.             return FillUILangListBox(hDlg, pLangList);
  1497.    
  1498.         case WM_DESTROY:
  1499.             break;
  1500.  
  1501.         case WM_COMMAND:
  1502.             switch(GET_WM_COMMAND_ID(wParam, lParam))
  1503.             {
  1504.                 case IDC_LANG_ADDSPK:
  1505.                     // open url from resource
  1506.                     OpenSatelliteDownloadUrl(hDlg);
  1507.                     EndDialog(hDlg, RETURN_SETLANG_ENDLANGDIALOG);
  1508.                     break;
  1509.                 case IDOK:
  1510.                     if(!SUCCEEDED(CUILangList::GetLangList(GetParent(hDlg), &pLangList))
  1511.                       || !ChangeLanguage(hDlg, pLangList))
  1512.                       EndDialog(hDlg, 0);
  1513.  
  1514.                     // EndDialog() is called in separate thread
  1515.                     // when shutdown/restart is done
  1516.                     //
  1517.                     break;
  1518.  
  1519.                 case IDCANCEL:
  1520.                     EndDialog(hDlg, 0);
  1521.                     break;
  1522.             }
  1523.             break;
  1524.  
  1525.         case WM_HELP:           // F1
  1526.             ResWinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, IDS_HELPFILE,
  1527.                 HELP_WM_HELP, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
  1528.             break;
  1529.  
  1530.         case WM_CONTEXTMENU:    // right mouse click
  1531.             ResWinHelp( (HWND) wParam, IDS_HELPFILE,
  1532.                 HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);        
  1533.             break;
  1534.  
  1535.         default:
  1536.             return FALSE;
  1537.     }
  1538.     return TRUE;
  1539. }
  1540.  
  1541. //
  1542. // LangAddDlgProc()
  1543. //
  1544. // Message handler for the "Add Language" subdialog.
  1545. //
  1546. INT_PTR CALLBACK LangAddDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1547. {
  1548.     switch (uMsg)
  1549.     {
  1550.         case WM_INITDIALOG:
  1551.             return FillLanguageListBox(hDlg);
  1552.    
  1553.         case WM_DESTROY:
  1554.             break;
  1555.  
  1556.         case WM_COMMAND:
  1557.             switch(GET_WM_COMMAND_ID(wParam, lParam))
  1558.             {
  1559.                 case IDOK:
  1560.                     AddLanguage(hDlg);
  1561.                     EndDialog(hDlg, 0);
  1562.                     break;
  1563.  
  1564.                 case IDCANCEL:
  1565.                     EndDialog(hDlg, 0);
  1566.                     break;
  1567.             }
  1568.             break;
  1569.  
  1570.         case WM_HELP:           // F1
  1571.             ResWinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, IDS_HELPFILE,
  1572.                 HELP_WM_HELP, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
  1573.             break;
  1574.  
  1575.         case WM_CONTEXTMENU:    // right mouse click
  1576.             ResWinHelp( (HWND) wParam, IDS_HELPFILE,
  1577.                 HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);        
  1578.             break;
  1579.  
  1580.         default:
  1581.             return FALSE;
  1582.     }
  1583.     return TRUE;
  1584. }
  1585.  
  1586. // put any cleanup procedures for language dialog here
  1587. void LangDlgCleanup(HWND hDlg)
  1588. {
  1589.     // also delete and remove the instance of
  1590.     // UI language list from window prop
  1591.     CUILangList::RemoveLangList(hDlg);
  1592. }
  1593. //
  1594. // LanguageDlgProc()
  1595. //
  1596. // Message handler for the "Language Preference" subdialog.
  1597. //
  1598. INT_PTR CALLBACK LanguageDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1599. {
  1600.     CUILangList *pLangList;
  1601.     switch (uMsg)
  1602.     {
  1603.         case WM_INITDIALOG:
  1604.             return LanguageDlgInit(hDlg);
  1605.    
  1606.         case WM_DESTROY:
  1607.             LangDlgCleanup(hDlg);
  1608.             break;
  1609.  
  1610.         case WM_COMMAND:
  1611.             switch(GET_WM_COMMAND_ID(wParam, lParam))
  1612.             {
  1613.                 HWND hwndList;
  1614.                 int iIndex, iNumItems;
  1615.                 INT_PTR iret;
  1616.  
  1617.                 case IDOK:
  1618.                     SaveLanguageData(hDlg);
  1619.                     EndDialog(hDlg, 0);
  1620.                     break;
  1621.  
  1622.                 case IDCANCEL:
  1623.                     EndDialog(hDlg, 0);
  1624.                     break;
  1625.  
  1626.                 case IDC_LANG_ADD_BUTTON:
  1627.                     DialogBox(MLGetHinst(), MAKEINTRESOURCE(IDD_LANG_ADD), hDlg, LangAddDlgProc);
  1628.                     break;
  1629.  
  1630.                 case IDC_LANG_UI_PREF:
  1631.                     CUILangList::GetLangList(hDlg, &pLangList);
  1632.                     iret = KickSetLang(hDlg, pLangList);
  1633.                     if (iret == RETURN_SETLANG_ENDLANGDIALOG)
  1634.                     {
  1635.                         // we're outa job
  1636.                         EndDialog(hDlg, 0);
  1637.                     }
  1638.                     else
  1639.                     {
  1640.                         InitCurrentUILang(hDlg);
  1641.                     }
  1642.                     break;
  1643.  
  1644.                 case IDC_LANG_REMOVE_BUTTON:
  1645.                     hwndList = GetDlgItem(hDlg, IDC_LANG_ACCEPT_LIST);
  1646.                     iIndex = ListBox_GetCurSel(hwndList);
  1647.                     ListBox_DeleteString(hwndList, iIndex);
  1648.                     iNumItems = ListBox_GetCount(hwndList);
  1649.                     if (iNumItems == iIndex)
  1650.                         iIndex--;
  1651.                     ListBox_SetCurSel(hwndList, iIndex);
  1652.                     EnableWindow(GetDlgItem(hDlg, IDC_LANG_REMOVE_BUTTON), (iNumItems > 0) && !g_restrict.fInternational);
  1653.                     EnableWindow(GetDlgItem(hDlg, IDC_LANG_MOVE_UP_BUTTON), (iIndex > 0) && !g_restrict.fInternational);
  1654.                     EnableWindow(GetDlgItem(hDlg, IDC_LANG_MOVE_DOWN_BUTTON), (iIndex < iNumItems - 1) && !g_restrict.fInternational);
  1655.  
  1656.                     if (NULL == GetFocus()) // This prevent keyboard access disable
  1657.                         SetFocus(hwndList);
  1658.                     break;
  1659.  
  1660.                 case IDC_LANG_ACCEPT_LIST:
  1661.                     hwndList = GetDlgItem(hDlg, IDC_LANG_ACCEPT_LIST);
  1662.                     iIndex = ListBox_GetCurSel(hwndList);
  1663.                     if (0 <= iIndex)
  1664.                     {
  1665.                         iNumItems = ListBox_GetCount(hwndList);
  1666.                         EnableWindow(GetDlgItem(hDlg, IDC_LANG_REMOVE_BUTTON), (iNumItems > 0) && !g_restrict.fInternational);
  1667.                         EnableWindow(GetDlgItem(hDlg, IDC_LANG_MOVE_UP_BUTTON), (iIndex > 0) && !g_restrict.fInternational);
  1668.                         EnableWindow(GetDlgItem(hDlg, IDC_LANG_MOVE_DOWN_BUTTON), (iIndex < iNumItems - 1) && !g_restrict.fInternational);
  1669.                     }
  1670.                     break;
  1671.  
  1672.                 case IDC_LANG_MOVE_UP_BUTTON:
  1673.                     MoveUpDownListItem(hDlg, GetDlgItem(hDlg, IDC_LANG_ACCEPT_LIST), TRUE);
  1674.                     break;
  1675.  
  1676.                 case IDC_LANG_MOVE_DOWN_BUTTON:
  1677.                     MoveUpDownListItem(hDlg, GetDlgItem(hDlg, IDC_LANG_ACCEPT_LIST), FALSE);
  1678.                     break;
  1679.             }
  1680.             break;
  1681.  
  1682.         case WM_HELP:           // F1
  1683.             ResWinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, IDS_HELPFILE,
  1684.                 HELP_WM_HELP, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
  1685.             break;
  1686.  
  1687.         case WM_CONTEXTMENU:    // right mouse click
  1688.             ResWinHelp( (HWND) wParam, IDS_HELPFILE,
  1689.                 HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);        
  1690.             break;
  1691.  
  1692.         default:
  1693.             return FALSE;
  1694.     }
  1695.     return TRUE;
  1696. }
  1697.  
  1698.  
  1699. //
  1700. // KickLanguageDialog
  1701. //
  1702. // synopsis : used for launching Language Preference sub dialog.
  1703. //            we need to launch the dialogbox as a separate process if inetcpl is
  1704. //            invoked from Tools->Internet options.
  1705. //            The reason: we shutdown every browser instances on desktop
  1706. //                        user chooses different UI language than the current,
  1707. //                        including the browser that launched inetcpl.
  1708. //
  1709. static const TCHAR  s_szRunDll32[] = TEXT("RunDll32.exe");
  1710. static const TCHAR  s_szKickLangDialog[] = TEXT(" inetcpl.cpl,OpenLanguageDialog");
  1711. void KickLanguageDialog(HWND hDlg)
  1712. {
  1713.     // 1: here we want to check to see if inetcpl was launched
  1714.     //         as a rundll32 process already, which would happen if user
  1715.     //         clicks on it at control panel folder
  1716.     //
  1717.     //
  1718.     BOOL fLaunchedOnBrowser = FALSE;
  1719.    
  1720.     // this tells me whether we got invoked from Tools->Internet Options...
  1721.     if (g_szCurrentURL[0])
  1722.     {
  1723.         fLaunchedOnBrowser = TRUE;
  1724.     }
  1725.    
  1726.     if (fLaunchedOnBrowser)
  1727.     {
  1728.         TCHAR szCommandLine[MAX_PATH];
  1729.         TCHAR szTitle[MAX_PATH];
  1730.  
  1731.         HWND hwndParent = GetParent(hDlg);
  1732.        
  1733.         StrCpy(szCommandLine, s_szRunDll32);
  1734.         StrCat(szCommandLine, s_szKickLangDialog);
  1735.        
  1736.         if (GetWindowText(hwndParent, szTitle, ARRAYSIZE(szTitle)) > 0)
  1737.         {
  1738.             StrCat(szCommandLine, TEXT(" "));
  1739.             StrCat(szCommandLine, szTitle);
  1740.         }
  1741.        
  1742. #ifdef USE_CREATE_PROCESS
  1743.         PROCESS_INFORMATION pi;
  1744.         STARTUPINFO si = {0};
  1745.  
  1746.         si.cb = sizeof(si);
  1747.         BOOL fLaunchedOK =
  1748.         CreateProcess (szCommandLine,          // name of app to launch
  1749.                        NULL,                   // lpCmdLine
  1750.                        NULL,                   // lpProcessAttributes
  1751.                        NULL,                   // lpThreadAttributes
  1752.                        TRUE,                   // bInheritHandles
  1753.                        NORMAL_PRIORITY_CLASS,  // dwCreationFlags
  1754.                        NULL,                   // lpEnvironment
  1755.                        NULL,                   // lpCurrentDirectory
  1756.                        &si,                    // lpStartupInfo
  1757.                        &pi);                   // lpProcessInformation
  1758. #else
  1759.         char szAnsiPath[MAX_PATH];
  1760.         SHUnicodeToAnsi(szCommandLine, szAnsiPath, ARRAYSIZE(szAnsiPath));
  1761.         WinExec(szAnsiPath, SW_SHOWNORMAL);
  1762. #endif
  1763.     }
  1764.     else
  1765.     {
  1766.         DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_LANG), hDlg, LanguageDlgProc, NULL);
  1767.     }
  1768. }
  1769.  
  1770. //
  1771. // KickSetLang
  1772. //
  1773. // synopsis : tries to find setlang.exe of Office9 first, if found it'll be kicked
  1774. //            if not, it uses our own setlang dialog.
  1775. //
  1776. //
  1777. static const TCHAR s_szOfficeInstallRoot[] = TEXT("Software\\Microsoft\\Office\\9.0\\Common\\InstallRoot");
  1778. static const TCHAR s_szOffice10InstallRoot[] = TEXT("Software\\Microsoft\\Shared");
  1779. static const TCHAR s_szPath[] = TEXT("Path");
  1780. static const TCHAR s_szOffice10Path[] = TEXT("OfficeSetLangInstallLocation");
  1781. static const TCHAR s_szSetLangExe[] = TEXT("setlang.exe");
  1782.  
  1783. INT_PTR KickSetLang(HWND hDlg, CUILangList *pLangList)
  1784. {
  1785.     BOOL fOfficeSetLangInstalled = FALSE;
  1786.     INT_PTR iret;
  1787.    
  1788.     TCHAR szSetLangPath[MAX_PATH];    
  1789.    
  1790.     //  deleting the key this way makes the key invalid for this process
  1791.     //  this way the inetcpl doesnt get bogus cached values
  1792.     SHDeleteKey(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\ShellNoRoam\\MUICache"));
  1793.  
  1794.     // try to get Office's setlang path
  1795.     if(pLangList && pLangList->IsOffice9Installed())
  1796.     {
  1797.         DWORD cb = sizeof(szSetLangPath);
  1798.         DWORD dwRet = SHGetValue(HKEY_LOCAL_MACHINE, s_szOffice10InstallRoot, s_szOffice10Path, NULL, szSetLangPath, &cb);
  1799.  
  1800.         // fall back to Office9 langpack setting if Office10 langpack setting isn't there
  1801.         if (ERROR_SUCCESS != dwRet)
  1802.         {
  1803.             cb = sizeof(szSetLangPath);            
  1804.             dwRet = SHGetValue(HKEY_LOCAL_MACHINE, s_szOfficeInstallRoot, s_szPath, NULL, szSetLangPath, &cb);
  1805.         }
  1806.  
  1807.         if (ERROR_SUCCESS == dwRet)
  1808.         {
  1809.             // If last character is a backslash
  1810.             if (szSetLangPath[lstrlen(szSetLangPath)-1] == TEXT('\\'))
  1811.             {
  1812.                 // Then concatenate the exe name
  1813.                 //
  1814.                 StrCat(szSetLangPath, s_szSetLangExe);
  1815.             }
  1816.             if (PathFileExists(szSetLangPath) == TRUE)
  1817.                 fOfficeSetLangInstalled = TRUE;
  1818.         }
  1819.     }
  1820.    
  1821.     if (fOfficeSetLangInstalled)
  1822.     {
  1823.         PROCESS_INFORMATION pi;
  1824.         STARTUPINFO si = {0};
  1825.  
  1826.         si.cb = sizeof(si);
  1827.         BOOL fLaunchedOK = CreateProcess(
  1828.                               szSetLangPath,     // name of app to launch
  1829.                                        NULL,     // lpCmdLine
  1830.                                        NULL,     // lpProcessAttributes
  1831.                                        NULL,     // lpThreadAttributes
  1832.                                        TRUE,     // bInheritHandles
  1833.                       NORMAL_PRIORITY_CLASS,     // dwCreationFlags
  1834.                                        NULL,     // lpEnvironment
  1835.                                        NULL,     // lpCurrentDirectory
  1836.                                        &si,      // lpStartupInfo
  1837.                                        &pi);     // lpProcessInformation
  1838.         // just wait a while
  1839.         if (fLaunchedOK)
  1840.         {
  1841.             WaitForInputIdle (pi.hProcess, RELAUNCH_TIMEOUT);
  1842.             CloseHandle(pi.hProcess);
  1843.             CloseHandle(pi.hThread);
  1844.         }
  1845.         iret = RETURN_SETLANG_ENDLANGDIALOG;
  1846.     }
  1847.     else
  1848.     {
  1849.         iret = DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_LANG_CHANGE), hDlg, LangChangeDlgProc, NULL);
  1850.     }
  1851.  
  1852.     return iret;
  1853. }
  1854.  
  1855. //
  1856. // entry point for rundll32
  1857. // NOTE: the following function was written intentionally as non-Unicode
  1858. //       mainly because we don't have Wide wrapper mechanism for rundll32
  1859. //       function on win95
  1860. //
  1861. extern void GetRestrictFlags(RESTRICT_FLAGS *pRestrict);
  1862. void CALLBACK OpenLanguageDialog(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
  1863. {
  1864.     // hinst is ignored because we set it at our LibMain()
  1865.     INITCOMMONCONTROLSEX icex;
  1866.  
  1867.     GetRestrictFlags(&g_restrict);
  1868.     icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
  1869.     icex.dwICC  = ICC_USEREX_CLASSES|ICC_NATIVEFNTCTL_CLASS;
  1870.     InitCommonControlsEx(&icex);
  1871.    
  1872.     if (lpszCmdLine && *lpszCmdLine)
  1873.     {
  1874.         HWND hwndParent = FindWindowA(NULL, lpszCmdLine);
  1875.         if (hwndParent)
  1876.             hwnd = hwndParent;
  1877.     }
  1878.     DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_LANG), hwnd, LanguageDlgProc, NULL);
  1879. }
  1880.  
  1881. // MLGetUILanguage in shlwapi returns current MUI language regardless version.
  1882. // MUI architecture doesn't display string correctly when main dll and satellite
  1883. // pack versions are mismatched.
  1884. // A good example is IE version upgrade without upgrading satellite.
  1885. // So here is more clever way to get the MUI language.
  1886. //
  1887. // 1. Get MLGetUILangauge from shlwapi
  1888. // 2. Compare it with current installed language.
  1889. // 3. if those are different, try to get resource dll.
  1890. // 4. if the resource dll is not in correct path just return current installed
  1891. //    language.
  1892. // 5. Or return the langid of MLGetUILanguage.
  1893. LANGID INETCPL_GetUILanguage()
  1894. {
  1895.     HINSTANCE hMLInst;
  1896.     TCHAR szPath[MAX_PATH], szMUI[16];
  1897.     LANGID lidUI = MLGetUILanguage();
  1898.  
  1899.     if (IsOS(OS_WIN2000ORGREATER))
  1900.         return lidUI;
  1901.  
  1902.     if (lidUI != GetInstallLanguage())
  1903.     {
  1904.         hMLInst = MLGetHinst();
  1905.         if (GetModuleFileName(hMLInst, szPath, ARRAYSIZE(szPath)))
  1906.         {
  1907.             IntToHex(szMUI, 4, lidUI);
  1908.             if (StrStrI(szPath, szMUI) == NULL)
  1909.                 lidUI = GetInstallLanguage();
  1910.         }
  1911.     }
  1912.  
  1913.     return lidUI;
  1914. }
  1915.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement