Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5553 lines
175 KiB

  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. // MUISetup.cpp
  4. //
  5. // This file contains the WinMain() and the UI handling of MUISetup.
  6. //
  7. // MUISetup is compiled as an Unicode application.
  8. //
  9. ////////////////////////////////////////////////////////////////////////////
  10. #include <nt.h>
  11. #include <ntrtl.h>
  12. #include <nturtl.h>
  13. #include <userenv.h>
  14. #include <shellapi.h>
  15. #include <regstr.h>
  16. #include <wmistr.h>
  17. #include <wmiumkm.h>
  18. #include <setupapi.h>
  19. #include <shlwapi.h>
  20. #include "sxsapi.h"
  21. #include "muisetup.h"
  22. #define STRSAFE_LIB
  23. #include <strsafe.h>
  24. //
  25. // Context Help IDs
  26. //
  27. //
  28. // Context Help Ids.
  29. //
  30. STDAPI_(BOOL) IsUserAnAdmin();
  31. static int aMuisetupHelpIds[] =
  32. {
  33. 207, IDH_COMM_GROUPBOX, // Group Box
  34. IDC_LIST1, IDH_MUISETUP_UILANGUAGE_LIST, // UI Language ListView
  35. IDC_DEF_UI_LANG_COMBO, IDH_MUISETUP_UILANGUAGECOMBO, // UI ComboBox selection
  36. IDC_CHECK_LOCALE, IDH_MUISETUP_CHECKLOCALE, // Match system locale with UI language
  37. IDC_CHECK_UIFONT, IDH_MUISETUP_MATCHUIFONT, // Match system locale with UI language
  38. 0, 0
  39. };
  40. //
  41. // Global variables
  42. //
  43. BOOL g_bMatchUIFont;
  44. // Store the special directories listed under [Directories] in mui.inf
  45. TCHAR DirNames[MFL][MAX_PATH],DirNames_ie[MFL][MAX_PATH];
  46. TCHAR szWindowsDir[MAX_PATH];
  47. // The FOLDER where MUISetup.exe is executed.
  48. TCHAR g_szMUISetupFolder[MAX_PATH];
  49. // The FULL PATH for MUISetup.exe.
  50. TCHAR g_szMuisetupPath[MAX_PATH];
  51. // The full path where MUI.inf is located.
  52. TCHAR g_szMUIInfoFilePath[MAX_PATH];
  53. TCHAR g_szVolumeName[MAX_PATH],g_szVolumeRoot[MAX_PATH];
  54. TCHAR g_szMUIHelpFilePath[MAX_PATH],g_szPlatformPath[16],g_szCDLabel[MAX_PATH];
  55. // Windows directory
  56. TCHAR g_szWinDir[MAX_PATH];
  57. TCHAR g_AddLanguages[BUFFER_SIZE];
  58. HANDLE ghMutex = NULL;
  59. HINSTANCE ghInstance;
  60. HWND ghProgDialog; // The progress dialog showed during installation/uninstallation.
  61. HWND ghProgress; // The progress bar in the progress dialog
  62. LANGID gUserUILangId, gSystemUILangId;
  63. BOOL gbIsWorkStation,gbIsServer,gbIsAdvanceServer,gbIsDataCenter,gbIsDomainController;
  64. HINSTANCE g_hUserEnvDll = NULL;
  65. HMODULE g_hAdvPackDll = NULL;
  66. HMODULE g_hSxSDll = NULL;
  67. DWORD g_dwVolumeSerialNo;
  68. BOOL g_InstallCancelled,g_IECopyError,g_bRemoveDefaultUI,g_bRemoveUserUI,g_bCmdMatchLocale,g_bCmdMatchUIFont, g_bReboot;
  69. UILANGUAGEGROUP g_UILanguageGroup;
  70. int g_cdnumber;
  71. // Number of MUI languges to insatll
  72. int gNumLanguages,gNumLanguages_Install,gNumLanguages_Uninstall;
  73. // Flag to indicate whether a language group is found for the locale or not.
  74. BOOL gFoundLangGroup;
  75. LGRPID gLangGroup;
  76. LCID gLCID;
  77. // The language groups installed in the system.
  78. LGRPID gLanguageGroups[32] ;
  79. int gNumLanguageGroups;
  80. PFILERENAME_TABLE g_pFileRenameTable;
  81. int g_nFileRename;
  82. PTYPENOTFALLBACK_TABLE g_pNotFallBackTable;
  83. int g_nNotFallBack;
  84. BOOL g_bSilent=FALSE; // indicate that muisetup should need no user interaction
  85. BOOL g_bNoUI=FALSE; // indicate that muisetup should install with no UI displayed and no user interaction
  86. BOOL g_bRunFromOSSetup=FALSE; // indicated that muisetup is called as part of NT setup/upgrade
  87. BOOL g_bLipLanguages;
  88. BOOL g_bLipAllowSwitch;
  89. //
  90. // Required pfns
  91. //
  92. pfnNtSetDefaultUILanguage gpfnNtSetDefaultUILanguage;
  93. pfnGetUserDefaultUILanguage gpfnGetUserDefaultUILanguage;
  94. pfnGetSystemDefaultUILanguage gpfnGetSystemDefaultUILanguage;
  95. pfnIsValidLanguageGroup gpfnIsValidLanguageGroup;
  96. pfnEnumLanguageGroupLocalesW gpfnEnumLanguageGroupLocalesW;
  97. pfnEnumSystemLanguageGroupsW gpfnEnumSystemLanguageGroupsW;
  98. pfnRtlAdjustPrivilege gpfnRtlAdjustPrivilege;
  99. pfnProcessIdToSessionId gpfnProcessIdToSessionId;
  100. pfnGetDefaultUserProfileDirectoryW gpfnGetDefaultUserProfileDirectoryW = NULL;
  101. pfnLaunchINFSection gpfnLaunchINFSection = NULL;
  102. PSXS_INSTALL_W gpfnSxsInstallW = NULL;
  103. PSXS_UNINSTALL_ASSEMBLYW gpfnSxsUninstallW = NULL;
  104. //
  105. // GetWindowsDirectory stuff
  106. //
  107. UINT WINAPI NT4_GetWindowsDir(LPWSTR pBuf, UINT uSize)
  108. {
  109. return GetWindowsDirectoryW(pBuf, uSize);
  110. }
  111. //
  112. // shlwapi StrToIntEx doesn't work for us
  113. //
  114. DWORD HexStrToInt(LPTSTR lpsz)
  115. {
  116. DWORD dw = 0L;
  117. TCHAR c;
  118. if (! lpsz)
  119. {
  120. return dw;
  121. }
  122. while(*lpsz)
  123. {
  124. c = *lpsz++;
  125. if (c >= TEXT('A') && c <= TEXT('F'))
  126. {
  127. c -= TEXT('A') - 0xa;
  128. }
  129. else if (c >= TEXT('0') && c <= TEXT('9'))
  130. {
  131. c -= TEXT('0');
  132. }
  133. else if (c >= TEXT('a') && c <= TEXT('f'))
  134. {
  135. c -= TEXT('a') - 0xa;
  136. }
  137. else
  138. {
  139. break;
  140. }
  141. dw *= 0x10;
  142. dw += c;
  143. }
  144. return(dw);
  145. }
  146. UINT (WINAPI *pfnGetWindowsDir)(LPWSTR pBuf, UINT uSize) = NT4_GetWindowsDir;
  147. void InitGetWindowsDirectoryPFN(HMODULE hMod)
  148. {
  149. pfnGetWindowsDir = (UINT (WINAPI *) (LPWSTR pBuf, UINT uSize)) GetProcAddress(hMod, "GetSystemWindowsDirectoryW");
  150. if (!pfnGetWindowsDir)
  151. {
  152. pfnGetWindowsDir = NT4_GetWindowsDir;
  153. }
  154. }
  155. ////////////////////////////////////////////////////////////////////////////
  156. //
  157. // GetLanguageDisplayName
  158. //
  159. // Get the display name (in the form of "Language (Region)") for the specified
  160. // language ID.
  161. //
  162. // Parameters:
  163. // [IN] langID Language ID
  164. // [OUT] lpBuffer the buffer to receive the display name.
  165. // [IN] nBufferSize the size of buffer, in TCHAR.
  166. //
  167. // Return Values:
  168. // TRUE if succeed. FALSE if the buffer is not big enough.
  169. //
  170. //
  171. // 01-11-2001 YSLin Created.
  172. //
  173. ////////////////////////////////////////////////////////////////////////////
  174. BOOL GetLanguageDisplayName(LANGID langID, LPTSTR lpBuffer, int nBufferSize)
  175. {
  176. TCHAR lpLangName[BUFFER_SIZE];
  177. TCHAR lpRegionName[BUFFER_SIZE];
  178. int nCharCount = 0;
  179. HRESULT hresult = S_OK;
  180. nCharCount = GetLocaleInfo(langID, LOCALE_SENGLANGUAGE, lpLangName, ARRAYSIZE(lpLangName)-1);
  181. nCharCount += GetLocaleInfo(langID, LOCALE_SENGCOUNTRY , lpRegionName, ARRAYSIZE(lpRegionName)-1);
  182. nCharCount += 3;
  183. if (nCharCount > nBufferSize)
  184. {
  185. if (nBufferSize)
  186. //*STRSAFE* lstrcpy(lpBuffer, TEXT(""));
  187. hresult = StringCchCopy(lpBuffer , nBufferSize, TEXT(""));
  188. if (!SUCCEEDED(hresult))
  189. {
  190. return FALSE;
  191. }
  192. return (FALSE);
  193. }
  194. //*STRSAFE* wsprintf(lpBuffer, TEXT("%s (%s)"), lpLangName, lpRegionName);
  195. hresult = StringCchPrintf(lpBuffer , nBufferSize, TEXT("%s (%s)"), lpLangName, lpRegionName);
  196. if (!SUCCEEDED(hresult))
  197. {
  198. return FALSE;
  199. }
  200. return (TRUE);
  201. }
  202. //
  203. // Our Message Box
  204. //
  205. int DoMessageBox(HWND hwndParent, UINT uIdString, UINT uIdCaption, UINT uType)
  206. {
  207. TCHAR szString[MAX_PATH+MAX_PATH];
  208. TCHAR szCaption[MAX_PATH];
  209. szString[0] = szCaption[0] = TEXT('\0');
  210. if (uIdString)
  211. LoadString(NULL, uIdString, szString, MAX_PATH+MAX_PATH-1);
  212. if (uIdCaption)
  213. LoadString(NULL, uIdCaption, szCaption, MAX_PATH-1);
  214. return MESSAGEBOX(hwndParent, szString, szCaption, uType);
  215. }
  216. ////////////////////////////////////////////////////////////////////////////
  217. //
  218. // DoMessageBoxFromResource
  219. //
  220. // Load a format string from resource, and format the string using the
  221. // specified arguments. Display a message box using the formatted string.
  222. //
  223. // Parameters:
  224. //
  225. // Return Values:
  226. // The return value from MessageBox.
  227. //
  228. // Remarks:
  229. // The length of the formatted string is limited by BUFFER_SIZE.
  230. //
  231. // 08-07-2000 YSLin Created.
  232. //
  233. ////////////////////////////////////////////////////////////////////////////
  234. int DoMessageBoxFromResource(HWND hwndParent, HMODULE hInstance, UINT uIdString, LONG_PTR* lppArgs, UINT uIdCaption, UINT uType)
  235. {
  236. TCHAR szString[BUFFER_SIZE];
  237. TCHAR szCaption[BUFFER_SIZE];
  238. szString[0] = szCaption[0] = TEXT('\0');
  239. if (uIdCaption)
  240. LoadString(hInstance, uIdCaption, szCaption, MAX_PATH-1);
  241. FormatStringFromResource(szString, sizeof(szString)/sizeof(TCHAR), hInstance, uIdString, lppArgs);
  242. return (MESSAGEBOX(hwndParent, szString, szCaption, uType));
  243. }
  244. BOOL IsMatchingPlatform(void)
  245. {
  246. BOOL bx86Image = FALSE;
  247. BOOL bRet = TRUE;
  248. TCHAR szWOW64Path[MAX_PATH];
  249. #ifdef _X86_
  250. bx86Image = TRUE;
  251. #endif
  252. if (GetSystemWow64Directory(szWOW64Path, ARRAYSIZE(szWOW64Path)) &&
  253. bx86Image)
  254. bRet = FALSE;
  255. return bRet;
  256. }
  257. //
  258. // Program Entry Point
  259. //
  260. INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)
  261. {
  262. int result = 0;
  263. BOOL bForwardCall=FALSE;
  264. TCHAR lpCommandLine[BUFFER_SIZE+1];
  265. HMODULE hMod;
  266. int error,nNumArgs=0,i;
  267. LONG_PTR lppArgs[3];
  268. LPWSTR *pszArgv=NULL;
  269. HRESULT hresult;
  270. if (!IsUserAnAdmin())
  271. {
  272. //
  273. // "You must have administrator right to run muisetup.\n\n"
  274. // "If you want to switch your UI language, please use the regional option from control panel."
  275. //
  276. LogFormattedMessage(ghInstance, IDS_ADMIN_L, NULL);
  277. DoMessageBox(NULL, IDS_ADMIN, IDS_MAIN_TITLE, MB_OK);
  278. return result;
  279. }
  280. //
  281. // Bail out if image doesn't match the running platform
  282. //
  283. if (!IsMatchingPlatform())
  284. {
  285. DoMessageBox(NULL, IDS_WRONG_IMAGE, IDS_MAIN_TITLE, MB_OK | MB_DEFBUTTON1);
  286. return result;
  287. }
  288. ghInstance = hInstance;
  289. //
  290. // Let make sure this NT5, and let's initialize all our pfns
  291. //
  292. if (!InitializePFNs())
  293. {
  294. //
  295. // Not an NT5 system. The following should be ANSI to work on Win9x.
  296. //
  297. CHAR szString[MAX_PATH];
  298. CHAR szCaption[MAX_PATH];
  299. LoadStringA(NULL, IDS_ERROR_NT5_ONLY, szString, MAX_PATH-1);
  300. LoadStringA(NULL, IDS_MAIN_TITLE, szCaption, MAX_PATH-1);
  301. MessageBoxA(NULL, szString, szCaption, MB_OK | MB_ICONINFORMATION);
  302. result = 1;
  303. goto Exit;
  304. }
  305. //
  306. // Check if the program has already been running ?
  307. //
  308. if (CheckMultipleInstances())
  309. {
  310. result = 1;
  311. goto Exit;
  312. }
  313. //
  314. // Initialize any global vars
  315. //
  316. InitGlobals();
  317. //
  318. // Check if I'm launching from previous version of muisetup
  319. //
  320. // I.E. muisetup /$_transfer_$ path_of_MUI_installation_files
  321. //
  322. pszArgv = CommandLineToArgvW((LPCWSTR) GetCommandLineW(), &nNumArgs);
  323. lpCommandLine[0]=TEXT('\0');
  324. if (pszArgv)
  325. {
  326. for (i=1; i<nNumArgs;i++)
  327. {
  328. if (!_tcsicmp(pszArgv[i],MUISETUP_FORWARDCALL_TAG) && ((i+1) < nNumArgs) )
  329. {
  330. Set_SourcePath_FromForward(pszArgv[i+1]);
  331. bForwardCall=TRUE;
  332. i++;
  333. }
  334. else
  335. {
  336. //*STRSAFE* _tcscat(lpCommandLine,pszArgv[i]);
  337. hresult = StringCchCat(lpCommandLine , ARRAYSIZE(lpCommandLine), pszArgv[i]);
  338. if (!SUCCEEDED(hresult))
  339. {
  340. result = 1;
  341. goto Exit;
  342. }
  343. //*STRSAFE* _tcscat(lpCommandLine,TEXT(" "));
  344. hresult = StringCchCat(lpCommandLine , ARRAYSIZE(lpCommandLine), TEXT(" "));
  345. if (!SUCCEEDED(hresult))
  346. {
  347. result = 1;
  348. goto Exit;
  349. }
  350. }
  351. }
  352. }
  353. //
  354. // Check if there is a new version of muisetup.exe at %windir%\mui
  355. //
  356. // If it's the case, transfer all the control to it
  357. //
  358. if (!bForwardCall)
  359. {
  360. if ( MUIShouldSwitchToNewVersion(lpCommandLine) )
  361. {
  362. result = 0;
  363. goto Exit;;
  364. }
  365. }
  366. InitCommonControls();
  367. BeginLog();
  368. //
  369. // Block the installation of Personal and Professional
  370. // NOTE: this is here for only the .NET server release, re-enable pro sku after this.
  371. //
  372. #ifdef MUI_MAGIC
  373. if (CheckProductType(MUI_IS_WIN2K_PERSONAL) || CheckProductType(MUI_IS_WIN2K_PRO))
  374. #else
  375. if (CheckProductType(MUI_IS_WIN2K_PERSONAL))
  376. #endif
  377. {
  378. //
  379. // "Windows XP MultiLanguage Version cannot be installed on this platform."
  380. //
  381. DoMessageBox(NULL, IDS_ERROR_NT5_ONLY, IDS_MAIN_TITLE, MB_OK | MB_DEFBUTTON1);
  382. result = 1;
  383. goto Exit;
  384. }
  385. //
  386. // Check to see if a command line has been used
  387. //
  388. if(lpCommandLine && NextCommandTag(lpCommandLine))
  389. {
  390. lppArgs[0] = (LONG_PTR)lpCommandLine;
  391. LogFormattedMessage(NULL, IDS_COMMAND_LOG, lppArgs);
  392. LogMessage(TEXT("")); //Add a carriage return and newline
  393. ParseCommandLine(lpCommandLine);
  394. }
  395. else
  396. {
  397. //
  398. // MUI version needs to match OS version
  399. //
  400. if (!checkversion(TRUE))
  401. {
  402. DoMessageBox(NULL, IDS_WRONG_VERSION, IDS_MAIN_TITLE, MB_OK | MB_DEFBUTTON1);
  403. result = 1;
  404. goto Exit;
  405. }
  406. if (WelcomeDialog(0))
  407. {
  408. DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG_MAIN), 0, DialogFunc);
  409. }
  410. result = 1;
  411. }
  412. Exit:
  413. //
  414. // Cleanup
  415. //
  416. if ( pszArgv)
  417. {
  418. GlobalFree((HGLOBAL) pszArgv);
  419. }
  420. Muisetup_Cleanup();
  421. return result;
  422. }
  423. ////////////////////////////////////////////////////////////////////////////////////
  424. //
  425. // CheckMultipleInstances
  426. //
  427. // Checks if another instance is running, and if so, it switches to it.
  428. //
  429. ////////////////////////////////////////////////////////////////////////////////////
  430. BOOL CheckMultipleInstances(void)
  431. {
  432. ghMutex = CreateMutex(NULL, TRUE, TEXT("Muisetup_Mutex"));
  433. if (ghMutex && (GetLastError() == ERROR_ALREADY_EXISTS))
  434. {
  435. const int idsTitles[] = {IDS_MAIN_TITLE, IDS_INSTALL_TITLE, IDS_PROG_TITLE_2, IDS_PROG_TITLE_3, IDS_UNINSTALL_TITLE};
  436. HWND hWnd;
  437. TCHAR szTitle[MAX_PATH];
  438. int i;
  439. //
  440. // Find the running instance by searching possible Window titles
  441. //
  442. for (i=0; i<ARRAYSIZE(idsTitles); i++)
  443. {
  444. LoadString(NULL, idsTitles[i], szTitle, MAX_PATH-1);
  445. hWnd = FindWindow(NULL,szTitle);
  446. if (hWnd && IsWindow(hWnd))
  447. {
  448. if (IsIconic(hWnd))
  449. ShowWindow(hWnd, SW_RESTORE);
  450. SetForegroundWindow(hWnd);
  451. break;
  452. }
  453. }
  454. //
  455. // Always bail out if there is another running instance
  456. //
  457. return TRUE;
  458. }
  459. return FALSE;
  460. }
  461. ////////////////////////////////////////////////////////////////////////////////////
  462. //
  463. // InitializePFNs
  464. //
  465. // Initialize NT5 specific pfns
  466. //
  467. ////////////////////////////////////////////////////////////////////////////////////
  468. BOOL InitializePFNs()
  469. {
  470. HMODULE hModule;
  471. SYSTEM_INFO SystemInfo;
  472. LONG_PTR lppArgs[2];
  473. HRESULT hresult;
  474. //
  475. // Determine platform
  476. //
  477. GetSystemInfo( &SystemInfo );
  478. if (SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL ||
  479. SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ||
  480. SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
  481. {
  482. #if defined(_AMD64_)
  483. //*STRSAFE* _tcscpy(g_szPlatformPath, TEXT("amd64\\"));
  484. hresult = StringCchCopy(g_szPlatformPath , ARRAYSIZE(g_szPlatformPath), TEXT("amd64\\"));
  485. if (!SUCCEEDED(hresult))
  486. {
  487. return FALSE;
  488. }
  489. #elif defined(_IA64_)
  490. //*STRSAFE* _tcscpy(g_szPlatformPath, TEXT("ia64\\"));
  491. hresult = StringCchCopy(g_szPlatformPath , ARRAYSIZE(g_szPlatformPath), TEXT("ia64\\"));
  492. if (!SUCCEEDED(hresult))
  493. {
  494. return FALSE;
  495. }
  496. #else
  497. //*STRSAFE* _tcscpy(g_szPlatformPath, TEXT("i386\\"));
  498. hresult = StringCchCopy(g_szPlatformPath , ARRAYSIZE(g_szPlatformPath), TEXT("i386\\"));
  499. if (!SUCCEEDED(hresult))
  500. {
  501. return FALSE;
  502. }
  503. #endif
  504. }
  505. else
  506. {
  507. // This is NOT supported yet
  508. return FALSE;
  509. }
  510. //
  511. // Let's bring ntdll!NtSetDefaultUILanguage
  512. //
  513. hModule = GetModuleHandle(TEXT("ntdll.dll"));
  514. if (!hModule)
  515. return FALSE;
  516. gpfnNtSetDefaultUILanguage =
  517. (pfnNtSetDefaultUILanguage)GetProcAddress(hModule,
  518. "NtSetDefaultUILanguage");
  519. if (!gpfnNtSetDefaultUILanguage)
  520. return FALSE;
  521. gpfnRtlAdjustPrivilege =
  522. (pfnRtlAdjustPrivilege)GetProcAddress(hModule,
  523. "RtlAdjustPrivilege");
  524. if (!gpfnRtlAdjustPrivilege)
  525. return FALSE;
  526. //
  527. // Let's get out from kernel32.dll :
  528. // - GetUserDefaultUILanguage
  529. // - GetSystemDefaultUILanguage
  530. // - EnumLanguageGroupLocalesW
  531. //
  532. hModule = GetModuleHandle(TEXT("kernel32.dll"));
  533. if (!hModule)
  534. return FALSE;
  535. gpfnGetUserDefaultUILanguage =
  536. (pfnGetUserDefaultUILanguage)GetProcAddress(hModule,
  537. "GetUserDefaultUILanguage");
  538. if (!gpfnGetUserDefaultUILanguage)
  539. return FALSE;
  540. gpfnGetSystemDefaultUILanguage =
  541. (pfnGetSystemDefaultUILanguage)GetProcAddress(hModule,
  542. "GetSystemDefaultUILanguage");
  543. if (!gpfnGetSystemDefaultUILanguage)
  544. return FALSE;
  545. gpfnIsValidLanguageGroup =
  546. (pfnIsValidLanguageGroup)GetProcAddress(hModule,
  547. "IsValidLanguageGroup");
  548. if (!gpfnIsValidLanguageGroup)
  549. return FALSE;
  550. gpfnEnumLanguageGroupLocalesW =
  551. (pfnEnumLanguageGroupLocalesW)GetProcAddress(hModule,
  552. "EnumLanguageGroupLocalesW");
  553. if (!gpfnEnumLanguageGroupLocalesW)
  554. return FALSE;
  555. gpfnEnumSystemLanguageGroupsW =
  556. (pfnEnumSystemLanguageGroupsW)GetProcAddress(hModule,
  557. "EnumSystemLanguageGroupsW");
  558. if (!gpfnEnumSystemLanguageGroupsW)
  559. return FALSE;
  560. gpfnProcessIdToSessionId =
  561. (pfnProcessIdToSessionId) GetProcAddress(hModule,
  562. "ProcessIdToSessionId");
  563. //
  564. // Initialize the pfnGetWindowsDirectory
  565. //
  566. InitGetWindowsDirectoryPFN(hModule);
  567. //
  568. // Try to load userenv.dll
  569. //
  570. g_hUserEnvDll = LoadLibrary(TEXT("userenv.dll"));
  571. if (g_hUserEnvDll)
  572. {
  573. gpfnGetDefaultUserProfileDirectoryW =
  574. (pfnGetDefaultUserProfileDirectoryW)GetProcAddress(g_hUserEnvDll,
  575. "GetDefaultUserProfileDirectoryW");
  576. }
  577. else
  578. {
  579. LogFormattedMessage(ghInstance, IDS_LOAD_USERENV_L, NULL);
  580. return (FALSE);
  581. }
  582. g_hAdvPackDll = LoadLibrary(TEXT("AdvPack.dll"));
  583. if (g_hAdvPackDll == NULL)
  584. {
  585. LogFormattedMessage(ghInstance, IDS_LOAD_ADVPACK_L, NULL);
  586. return (FALSE);
  587. }
  588. gpfnLaunchINFSection = (pfnLaunchINFSection)GetProcAddress(g_hAdvPackDll, "LaunchINFSection");
  589. if (gpfnLaunchINFSection == NULL)
  590. {
  591. lppArgs[0] = (LONG_PTR)TEXT("LaunchINFSection");
  592. LogFormattedMessage(ghInstance, IDS_LOAD_ADVPACK_API_L, lppArgs);
  593. return (FALSE);
  594. }
  595. g_hSxSDll = LoadLibrary(TEXT("SxS.dll"));
  596. if (g_hSxSDll)
  597. {
  598. gpfnSxsInstallW = (PSXS_INSTALL_W)GetProcAddress(g_hSxSDll, SXS_INSTALL_W);
  599. gpfnSxsUninstallW = (PSXS_UNINSTALL_ASSEMBLYW)GetProcAddress(g_hSxSDll, SXS_UNINSTALL_ASSEMBLYW);
  600. }
  601. else
  602. {
  603. LogFormattedMessage(ghInstance, IDS_LOAD_SXS_L, NULL);
  604. return (FALSE);
  605. }
  606. return TRUE;
  607. }
  608. ////////////////////////////////////////////////////////////////////////////////////
  609. //
  610. // Find the path of execution file and set path for MUI.INF
  611. //
  612. //
  613. ////////////////////////////////////////////////////////////////////////////////////
  614. void SetSourcePath(LPTSTR lpszPreviousMUIPath)
  615. {
  616. UINT_PTR cb;
  617. LPTSTR lpszPath,lpszNext=NULL;
  618. TCHAR szHelpPath[MAX_PATH+1],szHelpFile[MAX_PATH+1];
  619. HRESULT hresult;
  620. if (!lpszPreviousMUIPath)
  621. {
  622. g_szMUISetupFolder[0]=TEXT('\0');
  623. cb = GetModuleFileName (ghInstance, g_szMuisetupPath, MAX_PATH);
  624. //*STRSAFE* _tcscpy(g_szMUISetupFolder,g_szMuisetupPath);
  625. hresult = StringCchCopy(g_szMUISetupFolder , ARRAYSIZE(g_szMUISetupFolder), g_szMuisetupPath);
  626. if (!SUCCEEDED(hresult))
  627. {
  628. return;
  629. }
  630. //
  631. // Get folder for MUISetup.
  632. //
  633. lpszPath = g_szMUISetupFolder;
  634. while ( (lpszNext=_tcschr(lpszPath,TEXT('\\'))) )
  635. {
  636. lpszPath = lpszNext+1;
  637. }
  638. *lpszPath=TEXT('\0');
  639. }
  640. else
  641. {
  642. //*STRSAFE* _tcscpy(g_szMUISetupFolder,lpszPreviousMUIPath);
  643. hresult = StringCchCopy(g_szMUISetupFolder , ARRAYSIZE(g_szMUISetupFolder), lpszPreviousMUIPath);
  644. if (!SUCCEEDED(hresult))
  645. {
  646. return ;
  647. }
  648. }
  649. //*STRSAFE* _tcscpy(g_szMUIInfoFilePath,g_szMUISetupFolder);
  650. hresult = StringCchCopy(g_szMUIInfoFilePath , ARRAYSIZE(g_szMUIInfoFilePath), g_szMUISetupFolder);
  651. if (!SUCCEEDED(hresult))
  652. {
  653. return;
  654. }
  655. //*STRSAFE* _tcscat(g_szMUIInfoFilePath,MUIINFFILENAME);
  656. hresult = StringCchCat(g_szMUIInfoFilePath , ARRAYSIZE(g_szMUIInfoFilePath), MUIINFFILENAME);
  657. if (!SUCCEEDED(hresult))
  658. {
  659. return ;
  660. }
  661. //
  662. // Check the location of help file
  663. //
  664. //*STRSAFE* _tcscpy(szHelpPath,g_szMUISetupFolder);
  665. hresult = StringCchCopy(szHelpPath , ARRAYSIZE(szHelpPath), g_szMUISetupFolder);
  666. if (!SUCCEEDED(hresult))
  667. {
  668. return ;
  669. }
  670. LoadString(NULL, IDS_HELPFILE,szHelpFile,MAX_PATH);
  671. //*STRSAFE* _tcscat(szHelpPath,szHelpFile);
  672. hresult = StringCchCat(szHelpPath , ARRAYSIZE(szHelpPath), szHelpFile);
  673. if (!SUCCEEDED(hresult))
  674. {
  675. return;
  676. }
  677. if (!FileExists(szHelpPath))
  678. {
  679. pfnGetWindowsDir(szHelpPath, MAX_PATH);
  680. //*STRSAFE* _tcscat(szHelpPath, TEXT("\\"));
  681. hresult = StringCchCat(szHelpPath , ARRAYSIZE(szHelpPath), TEXT("\\"));
  682. if (!SUCCEEDED(hresult))
  683. {
  684. return ;
  685. }
  686. //*STRSAFE* _tcscat(szHelpPath,HELPDIR); // HELP\MUI
  687. hresult = StringCchCat(szHelpPath , ARRAYSIZE(szHelpPath), HELPDIR);
  688. if (!SUCCEEDED(hresult))
  689. {
  690. return ;
  691. }
  692. //*STRSAFE* _tcscat(szHelpPath, TEXT("\\"));
  693. hresult = StringCchCat(szHelpPath , ARRAYSIZE(szHelpPath), TEXT("\\"));
  694. if (!SUCCEEDED(hresult))
  695. {
  696. return ;
  697. }
  698. //*STRSAFE* _tcscat(szHelpPath,szHelpFile);
  699. hresult = StringCchCat(szHelpPath , ARRAYSIZE(szHelpPath), szHelpFile);
  700. if (!SUCCEEDED(hresult))
  701. {
  702. return ;
  703. }
  704. if (FileExists(szHelpPath))
  705. {
  706. //*STRSAFE* _tcscpy(g_szMUIHelpFilePath,szHelpPath);
  707. hresult = StringCchCopy(g_szMUIHelpFilePath , ARRAYSIZE(g_szMUIHelpFilePath), szHelpPath);
  708. if (!SUCCEEDED(hresult))
  709. {
  710. return ;
  711. }
  712. }
  713. }
  714. else
  715. {
  716. //*STRSAFE* _tcscpy(g_szMUIHelpFilePath,szHelpPath);
  717. hresult = StringCchCopy(g_szMUIHelpFilePath , ARRAYSIZE(g_szMUIHelpFilePath), szHelpPath);
  718. if (!SUCCEEDED(hresult))
  719. {
  720. return ;
  721. }
  722. }
  723. if(g_szMUIInfoFilePath[1] == TEXT(':'))
  724. {
  725. _tcsncpy(g_szVolumeRoot,g_szMUIInfoFilePath,3);
  726. g_szVolumeRoot[3]=TEXT('\0');
  727. GetVolumeInformation(g_szVolumeRoot, g_szVolumeName, sizeof(g_szVolumeName)/sizeof(TCHAR),
  728. &g_dwVolumeSerialNo, 0, 0, 0, 0);
  729. }
  730. if (!GetPrivateProfileString( MUI_CDLAYOUT_SECTION,
  731. MUI_CDLABEL,
  732. TEXT(""),
  733. g_szCDLabel,
  734. MAX_PATH-1,
  735. g_szMUIInfoFilePath))
  736. {
  737. LoadString(NULL, IDS_CHANGE_CDROM, g_szCDLabel, MAX_PATH-1);
  738. }
  739. }
  740. //
  741. // Set MUI installation source path from the instance that transfer control to this instance
  742. //
  743. void Set_SourcePath_FromForward(LPCTSTR lpszPath)
  744. {
  745. TCHAR szMUIPath[MAX_PATH+1];
  746. int nidx=0;
  747. if (!lpszPath)
  748. {
  749. return;
  750. }
  751. while (*lpszPath)
  752. {
  753. if (*lpszPath == MUI_FILLER_CHAR)
  754. {
  755. szMUIPath[nidx++]=TEXT(' ');
  756. }
  757. else
  758. {
  759. szMUIPath[nidx++]=*lpszPath;
  760. }
  761. lpszPath++;
  762. }
  763. szMUIPath[nidx]=TEXT('\0');
  764. SetSourcePath(szMUIPath);
  765. }
  766. //
  767. // Check if the version of current instance is older than that in %windir%\mui.
  768. // If it's the case, then we transfer control to %windir%\mui\muisetup.
  769. //
  770. BOOL MUIShouldSwitchToNewVersion(LPTSTR lpszCommandLine)
  771. {
  772. BOOL bResult=FALSE;
  773. TCHAR szTarget[ MAX_PATH+1 ];
  774. HRESULT hresult;
  775. ULONG ulHandle,ulBytes;
  776. pfnGetWindowsDir(szTarget, MAX_PATH); //%windir% //
  777. //*STRSAFE* _tcscat(szTarget, TEXT("\\"));
  778. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("\\"));
  779. if (!SUCCEEDED(hresult))
  780. {
  781. return bResult;
  782. }
  783. //*STRSAFE* _tcscat(szTarget, MUIDIR); // \MUI //
  784. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), MUIDIR);
  785. if (!SUCCEEDED(hresult))
  786. {
  787. return bResult;
  788. }
  789. //*STRSAFE* _tcscat(szTarget, TEXT("\\"));
  790. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("\\"));
  791. if (!SUCCEEDED(hresult))
  792. {
  793. return bResult;
  794. }
  795. //*STRSAFE* _tcscat(szTarget,MUISETUP_EXECUTION_FILENAME);
  796. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), MUISETUP_EXECUTION_FILENAME);
  797. if (!SUCCEEDED(hresult))
  798. {
  799. return bResult;
  800. }
  801. //
  802. // If %windir%\mui\muisetup.exe doesn't exist or current muisetup.exe is launched from %windir%\mui then
  803. // do nothing
  804. //
  805. if (!FileExists(szTarget) || !_tcsicmp(szTarget,g_szMuisetupPath))
  806. {
  807. return bResult;
  808. }
  809. //
  810. // If %windir%mui\muisetup.exe is not a execuatble then do nothing
  811. //
  812. ulBytes = GetFileVersionInfoSize( szTarget, &ulHandle );
  813. if ( ulBytes == 0 )
  814. return bResult;
  815. //
  816. // Compare the version stamp
  817. //
  818. // if version of g_szMuisetupPath (cuurent process) < %windir%\mui\muisetup
  819. // then switch control to it
  820. //
  821. if (CompareMuisetupVersion(g_szMuisetupPath,szTarget))
  822. {
  823. bResult = TRUE;
  824. MUI_TransferControlToNewVersion(szTarget,lpszCommandLine);
  825. }
  826. return bResult;
  827. }
  828. ////////////////////////////////////////////////////////////////////////////////////
  829. //
  830. // MUI_TransferControlToNewVersion
  831. //
  832. // Call %windir%\mui\muisetup.exe /$_transfer_$ mui_installation_file_path command_line
  833. //
  834. ////////////////////////////////////////////////////////////////////////////////////
  835. BOOL MUI_TransferControlToNewVersion(LPTSTR lpszExecutable,LPTSTR lpszCommandLine)
  836. {
  837. STARTUPINFO si;
  838. PROCESS_INFORMATION pi;
  839. TCHAR szAppName[BUFFER_SIZE],szDropPath[MAX_PATH];
  840. int nIdx,nLen;
  841. BOOL bResult=FALSE;
  842. HRESULT hresult;
  843. if (!lpszExecutable)
  844. {
  845. return bResult;
  846. }
  847. nLen=_tcslen(g_szMUISetupFolder);
  848. for (nIdx=0; nIdx <nLen ; nIdx++)
  849. {
  850. if (g_szMUISetupFolder[nIdx]==TEXT(' '))
  851. {
  852. szDropPath[nIdx]=MUI_FILLER_CHAR;
  853. }
  854. else
  855. {
  856. szDropPath[nIdx]=g_szMUISetupFolder[nIdx];
  857. }
  858. }
  859. szDropPath[nIdx]=TEXT('\0');
  860. //*STRSAFE* wsprintf(szAppName,TEXT("%s %s %s %s"),lpszExecutable,MUISETUP_FORWARDCALL_TAG,szDropPath,lpszCommandLine);
  861. hresult = StringCchPrintf(szAppName , ARRAYSIZE(szAppName), TEXT("%s %s %s %s"),lpszExecutable,MUISETUP_FORWARDCALL_TAG,szDropPath,lpszCommandLine);
  862. if (!SUCCEEDED(hresult))
  863. {
  864. return bResult;
  865. }
  866. //
  867. // Run the process
  868. //
  869. memset( &si, 0x00, sizeof(si));
  870. si.cb = sizeof(STARTUPINFO);
  871. if (!CreateProcess(NULL,
  872. szAppName,
  873. NULL,
  874. NULL,
  875. FALSE,
  876. 0L,
  877. NULL, NULL,
  878. &si,
  879. &pi) )
  880. return bResult;
  881. bResult =TRUE;
  882. return bResult;
  883. }
  884. ////////////////////////////////////////////////////////////////////////////////////
  885. //
  886. // CheckVolumeChange
  887. //
  888. // Make sure that MUI CD-ROM is put in the CD drive.
  889. //
  890. ////////////////////////////////////////////////////////////////////////////////////
  891. BOOL CheckVolumeChange()
  892. {
  893. BOOL bResult = FALSE;
  894. TCHAR szVolumeName[MAX_PATH],szCaption[MAX_PATH+1],szMsg[MAX_PATH+1],szMsg00[MAX_PATH+1],szMsg01[MAX_PATH+1];
  895. DWORD dwVolumeSerialNo;
  896. BOOL bInit=TRUE;
  897. LONG_PTR lppArgs[3];
  898. if( *g_szVolumeName &&
  899. GetVolumeInformation(g_szVolumeRoot, szVolumeName, ARRAYSIZE(szVolumeName),
  900. &dwVolumeSerialNo, 0, 0, 0, 0) )
  901. {
  902. while( lstrcmp(szVolumeName,g_szVolumeName) || (dwVolumeSerialNo != g_dwVolumeSerialNo) )
  903. {
  904. if (bInit)
  905. {
  906. szCaption[0]=szMsg00[0]=szMsg01[0]=TEXT('\0');
  907. LoadString(NULL, IDS_MAIN_TITLE, szCaption, MAX_PATH);
  908. lppArgs[0] = (LONG_PTR)g_szCDLabel;
  909. lppArgs[1] = (LONG_PTR)g_cdnumber;
  910. FormatStringFromResource(szMsg, ARRAYSIZE(szMsg), ghInstance, IDS_CHANGE_CDROM2, lppArgs);
  911. bInit=FALSE;
  912. }
  913. if (MESSAGEBOX(NULL, szMsg,szCaption, MB_YESNO | MB_ICONQUESTION) == IDNO)
  914. {
  915. return TRUE;
  916. }
  917. GetVolumeInformation(g_szVolumeRoot, szVolumeName, ARRAYSIZE(szVolumeName),
  918. &dwVolumeSerialNo, 0, 0, 0, 0);
  919. }
  920. }
  921. return bResult;
  922. }
  923. ////////////////////////////////////////////////////////////////////////////////////
  924. //
  925. // InitGlobals
  926. //
  927. // Initialize global variables
  928. //
  929. ////////////////////////////////////////////////////////////////////////////////////
  930. void InitGlobals(void)
  931. {
  932. // User UI Language Id
  933. gUserUILangId = gpfnGetUserDefaultUILanguage();
  934. gSystemUILangId = gpfnGetSystemDefaultUILanguage();
  935. // System Windows directory
  936. szWindowsDir[0] = TEXT('\0');
  937. pfnGetWindowsDir(szWindowsDir, MAX_PATH);
  938. // Does this have admin privliges ?
  939. gbIsWorkStation=CheckProductType(MUI_IS_WIN2K_PRO);
  940. gbIsServer= CheckProductType(MUI_IS_WIN2K_SERVER);
  941. gbIsAdvanceServer= (CheckProductType(MUI_IS_WIN2K_ADV_SERVER_OR_DATACENTER) || CheckProductType(MUI_IS_WIN2K_ENTERPRISE));
  942. gbIsDataCenter=(CheckProductType(MUI_IS_WIN2K_DATACENTER) || CheckProductType(MUI_IS_WIN2K_DC_DATACENTER));
  943. gbIsDomainController=CheckProductType(MUI_IS_WIN2K_DC);
  944. if (gbIsDomainController)
  945. {
  946. if ( (!gbIsWorkStation) && (!gbIsServer) && (!gbIsAdvanceServer))
  947. {
  948. gbIsServer=TRUE;
  949. }
  950. }
  951. // Fill in system supported language groups
  952. gpfnEnumSystemLanguageGroupsW(EnumLanguageGroupsProc, LGRPID_SUPPORTED, 0);
  953. pfnGetWindowsDir(g_szWinDir, sizeof(g_szWinDir));
  954. g_AddLanguages[0]=TEXT('\0');
  955. g_szVolumeName[0]=TEXT('\0');
  956. g_szVolumeRoot[0]=TEXT('\0');
  957. g_szMUIHelpFilePath[0]=TEXT('\0');
  958. g_szCDLabel[0]=TEXT('\0');
  959. g_dwVolumeSerialNo = 0;
  960. gNumLanguages=0;
  961. gNumLanguages_Install=0;
  962. gNumLanguages_Uninstall=0;
  963. g_InstallCancelled = FALSE;
  964. g_bRemoveDefaultUI=FALSE;
  965. g_cdnumber=0;
  966. g_pFileRenameTable=NULL;
  967. g_nFileRename=0;
  968. g_pNotFallBackTable=NULL;
  969. g_nNotFallBack=0;
  970. // Detect source path for installation
  971. SetSourcePath(NULL);
  972. // Initialize the context for diamond FDI
  973. Muisetup_InitDiamond();
  974. // Get all installed UI languages
  975. MUIGetAllInstalledUILanguages();
  976. }
  977. BOOL CALLBACK EnumLanguageGroupsProc(
  978. LGRPID LanguageGroup, // language group identifier
  979. LPTSTR lpLanguageGroupString, // pointer to language group identifier string
  980. LPTSTR lpLanguageGroupNameString, // pointer to language group name string
  981. DWORD dwFlags, // flags
  982. LONG_PTR lParam) // user-supplied parameter
  983. {
  984. gLanguageGroups[gNumLanguageGroups] = LanguageGroup;
  985. gNumLanguageGroups++;
  986. return TRUE;
  987. }
  988. ////////////////////////////////////////////////////////////////////////////////////
  989. //
  990. // Muisetup_Cleanup
  991. //
  992. // Muisetup cleanup code.
  993. //
  994. ////////////////////////////////////////////////////////////////////////////////////
  995. void Muisetup_Cleanup()
  996. {
  997. //
  998. // Free userenv.dll, if needed
  999. //
  1000. if (g_hUserEnvDll)
  1001. {
  1002. FreeLibrary(g_hUserEnvDll);
  1003. }
  1004. if (g_hAdvPackDll)
  1005. {
  1006. FreeLibrary(g_hAdvPackDll);
  1007. }
  1008. if (g_hSxSDll)
  1009. {
  1010. FreeLibrary(g_hSxSDll);
  1011. }
  1012. if (ghMutex)
  1013. {
  1014. CloseHandle(ghMutex);
  1015. }
  1016. // Free/release diamond DLL
  1017. Muisetup_FreeDiamond();
  1018. return;
  1019. }
  1020. ////////////////////////////////////////////////////////////////////////////////////
  1021. //
  1022. // OpenMuiKey
  1023. //
  1024. // Opens the Registry Key where installed languages are stored
  1025. //
  1026. ////////////////////////////////////////////////////////////////////////////////////
  1027. HKEY OpenMuiKey(REGSAM samDesired)
  1028. {
  1029. DWORD dwDisposition;
  1030. HKEY hKey;
  1031. TCHAR lpSubKey[BUFFER_SIZE];
  1032. HRESULT hresult;
  1033. //*STRSAFE* _tcscpy(lpSubKey, REG_MUI_PATH);
  1034. hresult = StringCchCopy(lpSubKey , ARRAYSIZE(lpSubKey), REG_MUI_PATH);
  1035. if (!SUCCEEDED(hresult))
  1036. {
  1037. return NULL;
  1038. }
  1039. if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  1040. lpSubKey,
  1041. 0,
  1042. NULL,
  1043. REG_OPTION_NON_VOLATILE,
  1044. samDesired,
  1045. NULL,
  1046. &hKey,
  1047. &dwDisposition) != ERROR_SUCCESS)
  1048. {
  1049. hKey = NULL;
  1050. }
  1051. return hKey;
  1052. }
  1053. void DialogCleanUp(HWND hwndDlg)
  1054. {
  1055. HWND hList = GetDlgItem(hwndDlg, IDC_LIST1);
  1056. int iCount = ListView_GetItemCount(hList);
  1057. LVITEM lvItem;
  1058. PMUILANGINFO pMuiLangInfo;
  1059. while (iCount--)
  1060. {
  1061. lvItem.mask = LVIF_PARAM;
  1062. lvItem.iItem = iCount;
  1063. lvItem.iSubItem = 0;
  1064. lvItem.state = 0;
  1065. lvItem.stateMask = 0;
  1066. lvItem.pszText = 0;
  1067. lvItem.cchTextMax = 0;
  1068. lvItem.iImage = 0;
  1069. lvItem.lParam = 0;
  1070. ListView_GetItem(hList, &lvItem);
  1071. pMuiLangInfo = (PMUILANGINFO)lvItem.lParam;
  1072. if (pMuiLangInfo)
  1073. {
  1074. if (pMuiLangInfo->lpszLcid)
  1075. LocalFree(pMuiLangInfo->lpszLcid);
  1076. LocalFree(pMuiLangInfo);
  1077. }
  1078. }
  1079. }
  1080. ////////////////////////////////////////////////////////////////////////////////////
  1081. //
  1082. // DialogFunc
  1083. //
  1084. // Callback function for main dialog (102)
  1085. //
  1086. ////////////////////////////////////////////////////////////////////////////////////
  1087. INT_PTR CALLBACK DialogFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1088. {
  1089. switch(uMsg)
  1090. {
  1091. case WM_INITDIALOG:
  1092. SendMessage(hwndDlg, WM_SETICON , (WPARAM)ICON_BIG, (LPARAM)LoadIcon(ghInstance,MAKEINTRESOURCE(MUI_ICON)));
  1093. SendMessage(hwndDlg, WM_SETICON , (WPARAM)ICON_SMALL, (LPARAM)LoadIcon(ghInstance,MAKEINTRESOURCE(MUI_ICON)));
  1094. InitializeInstallDialog(hwndDlg, uMsg, wParam, lParam);
  1095. return TRUE;
  1096. case WM_HELP:
  1097. {
  1098. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  1099. g_szMUIHelpFilePath,
  1100. HELP_WM_HELP,
  1101. (DWORD_PTR)(LPTSTR)aMuisetupHelpIds );
  1102. break;
  1103. }
  1104. case WM_CONTEXTMENU: // right mouse click
  1105. {
  1106. WinHelp( (HWND)wParam,
  1107. g_szMUIHelpFilePath,
  1108. HELP_CONTEXTMENU,
  1109. (DWORD_PTR)(LPTSTR)aMuisetupHelpIds );
  1110. break;
  1111. }
  1112. case WM_COMMAND:
  1113. switch (LOWORD(wParam))
  1114. {
  1115. case IDOK:
  1116. EnableWindow(hwndDlg, FALSE);
  1117. if (StartGUISetup(hwndDlg))
  1118. {
  1119. EndDialog(hwndDlg, 0);
  1120. }
  1121. else
  1122. {
  1123. EnableWindow(hwndDlg, TRUE);
  1124. SetFocus(hwndDlg);
  1125. }
  1126. return TRUE;
  1127. case IDCANCEL:
  1128. EndDialog(hwndDlg, 0);
  1129. return TRUE;
  1130. case IDC_DEF_UI_LANG_COMBO:
  1131. switch(HIWORD(wParam))
  1132. {
  1133. case CBN_SELCHANGE:
  1134. UpdateCombo(hwndDlg);
  1135. return TRUE;
  1136. default:
  1137. break;
  1138. }
  1139. break;
  1140. case IDC_CHECK_LOCALE:
  1141. if (BST_CHECKED == IsDlgButtonChecked( hwndDlg, IDC_CHECK_LOCALE))
  1142. {
  1143. EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK_UIFONT), TRUE);
  1144. }
  1145. else
  1146. {
  1147. CheckDlgButton(hwndDlg, IDC_CHECK_UIFONT, BST_UNCHECKED);
  1148. EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK_UIFONT), FALSE);
  1149. }
  1150. break;
  1151. }
  1152. //
  1153. // End of WM_COMMAND case
  1154. //
  1155. break;
  1156. case WM_NOTIFY:
  1157. switch (((NMHDR *)lParam)->code)
  1158. {
  1159. case(NM_CUSTOMDRAW):
  1160. ListViewCustomDraw(hwndDlg, (LPNMLVCUSTOMDRAW)lParam);
  1161. return TRUE;
  1162. break;
  1163. case (LVN_ITEMCHANGING):
  1164. return ListViewChanging( hwndDlg,
  1165. IDC_LIST1,
  1166. (NM_LISTVIEW *)lParam);
  1167. break;
  1168. case (LVN_ITEMCHANGED) :
  1169. ListViewChanged( hwndDlg,
  1170. IDC_LIST1,
  1171. (NM_LISTVIEW *)lParam );
  1172. break;
  1173. default:
  1174. return FALSE;
  1175. }
  1176. break;
  1177. case WM_CLOSE:
  1178. EndDialog(hwndDlg, 0);
  1179. return TRUE;
  1180. case WM_DESTROY:
  1181. DialogCleanUp(hwndDlg);
  1182. return TRUE;
  1183. default:
  1184. return FALSE;
  1185. }
  1186. return TRUE;
  1187. }
  1188. ////////////////////////////////////////////////////////////////////////////////////
  1189. //
  1190. // ListViewChanging
  1191. //
  1192. // Processing for a LVN_ITEMCHANGING message
  1193. //
  1194. ////////////////////////////////////////////////////////////////////////////////////
  1195. BOOL ListViewChanging(HWND hDlg, int iID, NM_LISTVIEW *pLV)
  1196. {
  1197. HWND hwndLV = GetDlgItem(hDlg, iID);
  1198. PMUILANGINFO pMuiLangInfo;
  1199. //
  1200. // Make sure it's a state change message
  1201. //
  1202. if ((!(pLV->uChanged & LVIF_STATE)) || ((pLV->uNewState & 0x3000) == 0))
  1203. return FALSE;
  1204. //
  1205. // Don't let the System Default be unchecked
  1206. //
  1207. GetMuiLangInfoFromListView(hwndLV, pLV->iItem, &pMuiLangInfo);
  1208. if (MAKELCID(gSystemUILangId, SORT_DEFAULT) == pMuiLangInfo->lcid)
  1209. return TRUE;
  1210. return FALSE;
  1211. }
  1212. ////////////////////////////////////////////////////////////////////////////////////
  1213. //
  1214. // ListViewChanged
  1215. //
  1216. // Processing for a LVN_ITEMCHANGED message
  1217. //
  1218. ////////////////////////////////////////////////////////////////////////////////////
  1219. BOOL ListViewChanged(HWND hDlg, int iID, NM_LISTVIEW *pLV)
  1220. {
  1221. HWND hwndLV = GetDlgItem(hDlg, iID);
  1222. PMUILANGINFO pMuiLangInfo;
  1223. int iCount;
  1224. BOOL bChecked;
  1225. //
  1226. // Make sure it's a state change message.
  1227. //
  1228. if ((!(pLV->uChanged & LVIF_STATE)) ||
  1229. ((pLV->uNewState & 0x3000) == 0))
  1230. {
  1231. return (FALSE);
  1232. }
  1233. //
  1234. // Get the state of the check box for the currently selected item.
  1235. //
  1236. bChecked = ListView_GetCheckState(hwndLV, pLV->iItem) ? TRUE : FALSE;
  1237. //
  1238. // Don't let the System Default or the current user UI language be unchecked
  1239. //
  1240. GetMuiLangInfoFromListView(hwndLV, pLV->iItem, &pMuiLangInfo);
  1241. if (MAKELCID(gSystemUILangId, SORT_DEFAULT) == pMuiLangInfo->lcid)
  1242. {
  1243. //
  1244. // Set Default check state
  1245. //
  1246. if (bChecked == FALSE)
  1247. {
  1248. ListView_SetCheckState( hwndLV,
  1249. pLV->iItem,
  1250. TRUE );
  1251. }
  1252. return FALSE;
  1253. }
  1254. //
  1255. // Deselect all items.
  1256. //
  1257. iCount = ListView_GetItemCount(hwndLV);
  1258. while (iCount > 0)
  1259. {
  1260. iCount--;
  1261. ListView_SetItemState( hwndLV,
  1262. iCount,
  1263. 0,
  1264. LVIS_FOCUSED | LVIS_SELECTED );
  1265. }
  1266. //
  1267. // Make sure this item is selected.
  1268. //
  1269. ListView_SetItemState( hwndLV,
  1270. pLV->iItem,
  1271. LVIS_FOCUSED | LVIS_SELECTED,
  1272. LVIS_FOCUSED | LVIS_SELECTED );
  1273. //
  1274. // Update the combo box
  1275. //
  1276. PostMessage( hDlg,
  1277. WM_COMMAND,
  1278. MAKEWPARAM(IDC_DEF_UI_LANG_COMBO, CBN_SELCHANGE),
  1279. 0L);
  1280. //
  1281. // Return success.
  1282. //
  1283. return (TRUE);
  1284. }
  1285. ////////////////////////////////////////////////////////////////////////////////////
  1286. //
  1287. // ListViewCustomDraw
  1288. //
  1289. // Processing for list view WM_CUSTOMDRAW notification.
  1290. //
  1291. ////////////////////////////////////////////////////////////////////////////////////
  1292. void ListViewCustomDraw(HWND hDlg, LPNMLVCUSTOMDRAW pDraw)
  1293. {
  1294. HWND hwndLV = GetDlgItem(hDlg, IDC_LIST1);
  1295. PMUILANGINFO pMuiLangInfo;
  1296. //
  1297. // Tell the list view to notify me of item draws.
  1298. //
  1299. if (pDraw->nmcd.dwDrawStage == CDDS_PREPAINT)
  1300. {
  1301. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, CDRF_NOTIFYITEMDRAW);
  1302. return;
  1303. }
  1304. //
  1305. // Handle the Item Prepaint.
  1306. //
  1307. if (pDraw->nmcd.dwDrawStage & CDDS_ITEMPREPAINT)
  1308. {
  1309. //
  1310. // Check to see if the item being drawn is the system default or
  1311. // the current active ui language
  1312. //
  1313. GetMuiLangInfoFromListView(hwndLV, (int)pDraw->nmcd.dwItemSpec, &pMuiLangInfo);
  1314. if (MAKELCID(gSystemUILangId, SORT_DEFAULT) == pMuiLangInfo->lcid)
  1315. {
  1316. pDraw->clrText = (GetSysColor(COLOR_GRAYTEXT));
  1317. }
  1318. }
  1319. //
  1320. // Do the default action.
  1321. //
  1322. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, CDRF_DODEFAULT);
  1323. }
  1324. ////////////////////////////////////////////////////////////////////////////////////
  1325. //
  1326. // StartGUISetup
  1327. //
  1328. // Creates dialog with progress bar for installation
  1329. //
  1330. ////////////////////////////////////////////////////////////////////////////////////
  1331. BOOL StartGUISetup(HWND hwndDlg)
  1332. {
  1333. LONG_PTR lppArgs[3];
  1334. ULONG ulParam[2];
  1335. TCHAR lpMessage[BUFFER_SIZE];
  1336. TCHAR szBuf[BUFFER_SIZE];
  1337. INT64 ulSizeNeed,ulSizeAvailable;
  1338. BOOL success;
  1339. HWND hList;
  1340. HWND hCombo;
  1341. int iIndex;
  1342. TCHAR lpAddLanguages[BUFFER_SIZE];
  1343. TCHAR lpRemoveLanguages[BUFFER_SIZE];
  1344. TCHAR lpDefaultUILang[BUFFER_SIZE];
  1345. TCHAR szPostParameter[BUFFER_SIZE];
  1346. int installLangCount; // The number of MUI languages to be installed
  1347. int uninstallLangCount; // The number of MUI langauges to be uninstalled.
  1348. LANGID langID;
  1349. HRESULT hresult;
  1350. INSTALL_LANG_GROUP installLangGroup;
  1351. //
  1352. // (0) Check available disk space
  1353. //
  1354. if(!IsSpaceEnough(hwndDlg,&ulSizeNeed,&ulSizeAvailable))
  1355. {
  1356. ulParam[0] = (ULONG) (ulSizeNeed/1024);
  1357. ulParam[1] = (ULONG) (ulSizeAvailable/1024);
  1358. LoadString(ghInstance, IDS_DISKSPACE_NOTENOUGH, lpMessage, ARRAYSIZE(lpMessage)-1);
  1359. LoadString(ghInstance, IDS_ERROR_DISKSPACE, szBuf, ARRAYSIZE(szBuf)-1);
  1360. FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  1361. lpMessage,
  1362. 0,
  1363. 0,
  1364. lpMessage,
  1365. ARRAYSIZE(lpMessage)-1,
  1366. (va_list *)ulParam);
  1367. LogMessage(lpMessage);
  1368. MESSAGEBOX(NULL, lpMessage, szBuf, MB_OK | MB_DEFBUTTON1 | MB_ICONWARNING);
  1369. //
  1370. // Let User has another chance to reselect
  1371. //
  1372. return FALSE;
  1373. }
  1374. installLangGroup.bFontLinkRegistryTouched = FALSE;
  1375. installLangGroup.NotDeleted = 0;
  1376. //
  1377. // (1) Install Language Group First
  1378. //
  1379. ConvertMUILangToLangGroup(hwndDlg, &installLangGroup);
  1380. hList=GetDlgItem(hwndDlg, IDC_LIST1);
  1381. hCombo=GetDlgItem(hwndDlg, IDC_DEF_UI_LANG_COMBO);
  1382. installLangCount = EnumSelectedLanguages(hList, lpAddLanguages);
  1383. memmove(g_AddLanguages,lpAddLanguages,ARRAYSIZE(lpAddLanguages));
  1384. uninstallLangCount = EnumUnselectedLanguages(hList, lpRemoveLanguages);
  1385. //
  1386. // Let's read the user's UI language selection,
  1387. // and then call the kernel to update the registry.
  1388. //
  1389. hList = GetDlgItem(hwndDlg, IDC_LIST1);
  1390. hCombo = GetDlgItem(hwndDlg, IDC_DEF_UI_LANG_COMBO);
  1391. iIndex = (int)SendMessage(hCombo, CB_GETCURSEL, 0, 0);
  1392. if (iIndex == CB_ERR)
  1393. {
  1394. return FALSE;
  1395. }
  1396. langID = LANGIDFROMLCID((LCID) SendMessage(hCombo, CB_GETITEMDATA, iIndex, 0L));
  1397. //*STRSAFE* wsprintf(lpDefaultUILang, TEXT("%X"), langID);
  1398. hresult = StringCchPrintf(lpDefaultUILang , ARRAYSIZE(lpDefaultUILang), TEXT("%X"), langID);
  1399. if (!SUCCEEDED(hresult))
  1400. {
  1401. return FALSE;
  1402. }
  1403. DEBUGMSGBOX(NULL, TEXT("About to do setup"), NULL, MB_OK);
  1404. success = DoSetup(
  1405. hwndDlg,
  1406. uninstallLangCount, lpRemoveLanguages,
  1407. installLangGroup,
  1408. installLangCount, lpAddLanguages,
  1409. g_bLipLanguages? lpAddLanguages:lpDefaultUILang,
  1410. TRUE, TRUE, TRUE);
  1411. return (success);
  1412. }
  1413. ////////////////////////////////////////////////////////////////////////////////////
  1414. //
  1415. // ProgressDialogFunc
  1416. //
  1417. // Callback function for progresss dialog
  1418. //
  1419. ////////////////////////////////////////////////////////////////////////////////////
  1420. INT_PTR CALLBACK ProgressDialogFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1421. {
  1422. switch(uMsg)
  1423. {
  1424. case WM_INITDIALOG:
  1425. return TRUE;
  1426. case WM_COMMAND:
  1427. switch (LOWORD(wParam))
  1428. {
  1429. case IDCANCEL:
  1430. EndDialog(hwndDlg, 0);
  1431. return TRUE;
  1432. }
  1433. break;
  1434. case WM_CLOSE:
  1435. EndDialog(hwndDlg, 0);
  1436. return TRUE;
  1437. case WM_DESTROY:
  1438. EndDialog(hwndDlg, 0);
  1439. return TRUE;
  1440. default:
  1441. return FALSE;
  1442. }
  1443. return TRUE;
  1444. }
  1445. ////////////////////////////////////////////////////////////////////////////////////
  1446. //
  1447. // InitializeInstallDialog
  1448. //
  1449. // Sets contents of list view and combo box in installation dialog
  1450. //
  1451. ////////////////////////////////////////////////////////////////////////////////////
  1452. BOOL InitializeInstallDialog(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1453. {
  1454. HWND hList, hCombo;
  1455. PTSTR lpLanguages;
  1456. TCHAR tchBuffer[BUFFER_SIZE];
  1457. TCHAR lpDefaultSystemLanguage[BUFFER_SIZE],lpUILanguage[BUFFER_SIZE];
  1458. TCHAR lpMessage[BUFFER_SIZE];
  1459. int iIndex;
  1460. int iChkIndex,iCnt,iMUIDirectories=0;
  1461. HRESULT hresult;
  1462. lpLanguages = tchBuffer;
  1463. SetWindowTitleFromResource(hwndDlg, IDS_MAIN_TITLE);
  1464. hList = GetDlgItem(hwndDlg, IDC_LIST1);
  1465. hCombo=GetDlgItem(hwndDlg, IDC_DEF_UI_LANG_COMBO);
  1466. InitializeListView(hList);
  1467. //
  1468. // Insert the default system language in the list view
  1469. //
  1470. //*STRSAFE* _stprintf(lpDefaultSystemLanguage, TEXT("%04x"), gSystemUILangId);
  1471. hresult = StringCchPrintf(lpDefaultSystemLanguage , ARRAYSIZE(lpDefaultSystemLanguage), TEXT("%04x"), gSystemUILangId);
  1472. if (!SUCCEEDED(hresult))
  1473. {
  1474. return FALSE;
  1475. }
  1476. iIndex=InsertLanguageInListView(hList, lpDefaultSystemLanguage, TRUE);
  1477. //
  1478. // Insert the languages in MUI.INF in the list view
  1479. //
  1480. if ( ( (iMUIDirectories =EnumLanguages(lpLanguages)) == 0) && (g_UILanguageGroup.iCount == 0 ) )
  1481. {
  1482. //
  1483. // No languages found in MUI.INF
  1484. //
  1485. LoadString(ghInstance, IDS_NO_LANG_L, lpMessage, ARRAYSIZE(lpMessage)-1);
  1486. LogMessage(lpMessage);
  1487. return FALSE;
  1488. }
  1489. while (*lpLanguages != TEXT('\0'))
  1490. {
  1491. if (CheckLanguageIsQualified(lpLanguages))
  1492. {
  1493. InsertLanguageInListView(hList, lpLanguages, FALSE);
  1494. }
  1495. lpLanguages = _tcschr(lpLanguages, '\0');
  1496. lpLanguages++;
  1497. }
  1498. //
  1499. // We should also check all installed UI languages
  1500. //
  1501. for (iCnt=0; iCnt<g_UILanguageGroup.iCount; iCnt++)
  1502. {
  1503. if (!GetLcidItemIndexFromListView(hList, g_UILanguageGroup.lcid[iCnt], &iChkIndex))
  1504. {
  1505. //*STRSAFE* _stprintf(lpUILanguage, TEXT("%04x"), g_UILanguageGroup.lcid[iCnt]);
  1506. hresult = StringCchPrintf(lpUILanguage , ARRAYSIZE(lpUILanguage), TEXT("%04x"), g_UILanguageGroup.lcid[iCnt]);
  1507. if (!SUCCEEDED(hresult))
  1508. {
  1509. return FALSE;
  1510. }
  1511. if (CheckLanguageIsQualified(lpUILanguage))
  1512. {
  1513. InsertLanguageInListView(hList, lpUILanguage, FALSE);
  1514. }
  1515. }
  1516. }
  1517. //
  1518. // Let's detect which language groups are installed
  1519. //
  1520. DetectLanguageGroups(hwndDlg);
  1521. SelectInstalledLanguages(hList);
  1522. SetDefault(hCombo);
  1523. //
  1524. // Deselect all items.
  1525. //
  1526. iIndex = ListView_GetItemCount(hList);
  1527. while (iIndex > 0)
  1528. {
  1529. iIndex--;
  1530. ListView_SetItemState( hList,
  1531. iIndex,
  1532. 0,
  1533. LVIS_FOCUSED | LVIS_SELECTED );
  1534. }
  1535. //
  1536. // Select the first one in the list.
  1537. //
  1538. ListView_SetItemState( hList,
  1539. 0,
  1540. LVIS_FOCUSED | LVIS_SELECTED,
  1541. LVIS_FOCUSED | LVIS_SELECTED );
  1542. //
  1543. // Match system locale with the default UI language
  1544. //
  1545. if (CheckMUIRegSetting(MUI_MATCH_LOCALE))
  1546. {
  1547. CheckDlgButton(hwndDlg, IDC_CHECK_LOCALE, BST_CHECKED);
  1548. //
  1549. // Match UI font with the default UI language
  1550. //
  1551. if (g_bMatchUIFont = CheckMUIRegSetting(MUI_MATCH_UIFONT))
  1552. {
  1553. CheckDlgButton(hwndDlg, IDC_CHECK_UIFONT, BST_CHECKED);
  1554. }
  1555. }
  1556. else
  1557. {
  1558. SetMUIRegSetting(MUI_MATCH_UIFONT, FALSE);
  1559. EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK_UIFONT), FALSE);
  1560. }
  1561. return TRUE;
  1562. }
  1563. ////////////////////////////////////////////////////////////////////////////////////
  1564. //
  1565. // CheckForUsingCountryName
  1566. //
  1567. // Fetch MUIINF file if the selected UI lang needs to be displayed as a language
  1568. // name or a country name.
  1569. //
  1570. ////////////////////////////////////////////////////////////////////////////////////
  1571. BOOL CheckForUsingCountryName(PMUILANGINFO pMuiLangInfo)
  1572. {
  1573. TCHAR szSource[MAX_PATH];
  1574. szSource[0] = TEXT('\0');
  1575. //
  1576. // Try check if there is a value for it under [UseCountryName]
  1577. //
  1578. GetPrivateProfileString( MUI_COUNTRYNAME_SECTION,
  1579. pMuiLangInfo->lpszLcid,
  1580. TEXT(""),
  1581. szSource,
  1582. MAX_PATH,
  1583. g_szMUIInfoFilePath);
  1584. if (szSource[0] == TEXT('1'))
  1585. {
  1586. return (TRUE);
  1587. }
  1588. return (FALSE);
  1589. }
  1590. ////////////////////////////////////////////////////////////////////////////////////
  1591. //
  1592. // GetDisplayName
  1593. //
  1594. // Fetch MUIINF file if the selected UI lang needs to be displayed using the
  1595. // name specified in [LanguageDisplayName] section of mui.inf.
  1596. // Otherwise, get the display name according to the values in [UseCountryName].
  1597. // If the value for the specified LCID is 1, use the country name. Otherwise,
  1598. // use the locale name.
  1599. //
  1600. ////////////////////////////////////////////////////////////////////////////////////
  1601. BOOL GetDisplayName(PMUILANGINFO pMuiLangInfo)
  1602. {
  1603. //
  1604. // Try check if there is a customized display name for the specified LCID under [LanguageDisplayName].
  1605. //
  1606. pMuiLangInfo->szDisplayName[0] = L'\0';
  1607. if (pMuiLangInfo->lpszLcid)
  1608. {
  1609. GetPrivateProfileString( MUI_DISPLAYNAME_SECTION,
  1610. pMuiLangInfo->lpszLcid,
  1611. TEXT(""),
  1612. pMuiLangInfo->szDisplayName,
  1613. MAX_PATH,
  1614. g_szMUIInfoFilePath);
  1615. }
  1616. if (pMuiLangInfo->szDisplayName[0] == L'\0')
  1617. {
  1618. //
  1619. // There is no entry in [LanguageDisplayName]. Use the country name or locale name.
  1620. //
  1621. Muisetup_GetLocaleLanguageInfo( pMuiLangInfo->lcid,
  1622. pMuiLangInfo->szDisplayName,
  1623. ARRAYSIZE(pMuiLangInfo->szDisplayName)-1,
  1624. CheckForUsingCountryName(pMuiLangInfo));
  1625. }
  1626. return TRUE;
  1627. }
  1628. ////////////////////////////////////////////////////////////////////////////////////
  1629. //
  1630. // GetLanguageGroupDisplayName
  1631. // Get language group display name for MUI install/uninstall dialog
  1632. //
  1633. ////////////////////////////////////////////////////////////////////////////////////
  1634. BOOL GetLanguageGroupDisplayName(LANGID LangId, LPTSTR lpBuffer, int nSize)
  1635. {
  1636. BOOL bRet = FALSE;
  1637. MUILANGINFO MuiLangInfo = {0};
  1638. HRESULT hresult;
  1639. if ( (!lpBuffer) || (nSize == 0))
  1640. {
  1641. return bRet;
  1642. }
  1643. MuiLangInfo.lcid = MAKELCID(LangId, SORT_DEFAULT);
  1644. MuiLangInfo.lgrpid = GetLanguageGroup(MuiLangInfo.lcid);
  1645. if (GetDisplayName(&MuiLangInfo) &&
  1646. nSize >= lstrlen(MuiLangInfo.szDisplayName))
  1647. {
  1648. //*STRSAFE* lstrcpy(lpBuffer, MuiLangInfo.szDisplayName);
  1649. hresult = StringCchCopy(lpBuffer , nSize, MuiLangInfo.szDisplayName);
  1650. if (!SUCCEEDED(hresult))
  1651. {
  1652. return bRet;
  1653. }
  1654. bRet = TRUE;
  1655. }
  1656. return bRet;
  1657. }
  1658. ////////////////////////////////////////////////////////////////////////////////////
  1659. //
  1660. // Get UI, IE and LPK files size for the lcid
  1661. //
  1662. ////////////////////////////////////////////////////////////////////////////////////
  1663. BOOL GetUIFileSize(PMUILANGINFO pMuiLangInfo)
  1664. {
  1665. TCHAR szSize[MAX_PATH];
  1666. int nCD;
  1667. pMuiLangInfo->ulUISize = 0;
  1668. pMuiLangInfo->ulLPKSize = 0;
  1669. #if defined(_IA64_)
  1670. BOOL bIA64 = TRUE;
  1671. #else
  1672. BOOL bIA64 = FALSE;
  1673. #endif
  1674. if (!pMuiLangInfo)
  1675. {
  1676. return FALSE;
  1677. }
  1678. szSize[0] = TEXT('\0');
  1679. //
  1680. // Try to get UI files size under [FileSize_UI]
  1681. //
  1682. if (GetPrivateProfileString( bIA64? MUI_UIFILESIZE_SECTION_IA64 : MUI_UIFILESIZE_SECTION,
  1683. pMuiLangInfo->lpszLcid,
  1684. TEXT(""),
  1685. szSize,
  1686. MAX_PATH,
  1687. g_szMUIInfoFilePath))
  1688. {
  1689. pMuiLangInfo->ulUISize =_wtoi64(szSize);
  1690. }
  1691. szSize[0] = TEXT('\0');
  1692. //
  1693. // Try to get LPK files size under [FileSize_LPK]
  1694. //
  1695. if (GetPrivateProfileString( bIA64? MUI_LPKFILESIZE_SECTION_IA64 : MUI_LPKFILESIZE_SECTION,
  1696. pMuiLangInfo->lpszLcid,
  1697. TEXT(""),
  1698. szSize,
  1699. MAX_PATH,
  1700. g_szMUIInfoFilePath))
  1701. {
  1702. pMuiLangInfo->ulLPKSize =_wtoi64(szSize);
  1703. }
  1704. //
  1705. // Try to get CD # under [CD_LAYOUT]
  1706. //
  1707. nCD=GetPrivateProfileInt(bIA64? MUI_CDLAYOUT_SECTION_IA64 : MUI_CDLAYOUT_SECTION,
  1708. pMuiLangInfo->lpszLcid,
  1709. 0,
  1710. g_szMUIInfoFilePath);
  1711. if (nCD)
  1712. {
  1713. pMuiLangInfo->cd_number = nCD;
  1714. if (g_cdnumber == 0)
  1715. {
  1716. g_cdnumber = pMuiLangInfo->cd_number;
  1717. }
  1718. }
  1719. else
  1720. {
  1721. pMuiLangInfo->cd_number = DEFAULT_CD_NUMBER;
  1722. }
  1723. return TRUE;
  1724. }
  1725. BOOL GetUIFileSize_commandline(LPTSTR lpszLcid, INT64 *ulUISize,INT64 *ulLPKSize)
  1726. {
  1727. TCHAR szSize[MAX_PATH];
  1728. *ulUISize = 0;
  1729. *ulLPKSize = 0;
  1730. #if defined(_IA64_)
  1731. BOOL bIA64 = TRUE;
  1732. #else
  1733. BOOL bIA64 = FALSE;
  1734. #endif
  1735. if ( (!lpszLcid) || (!ulUISize) || (!ulLPKSize))
  1736. {
  1737. return FALSE;
  1738. }
  1739. szSize[0] = TEXT('\0');
  1740. //
  1741. // Try to get UI files size under [FileSize_UI]
  1742. //
  1743. if (GetPrivateProfileString( bIA64? MUI_UIFILESIZE_SECTION_IA64 : MUI_UIFILESIZE_SECTION,
  1744. lpszLcid,
  1745. TEXT(""),
  1746. szSize,
  1747. MAX_PATH,
  1748. g_szMUIInfoFilePath))
  1749. {
  1750. *ulUISize =_wtoi64(szSize);
  1751. }
  1752. szSize[0] = TEXT('\0');
  1753. //
  1754. // Try to get LPK files size under [FileSize_LPK]
  1755. //
  1756. if (GetPrivateProfileString( bIA64? MUI_LPKFILESIZE_SECTION_IA64 : MUI_LPKFILESIZE_SECTION,
  1757. lpszLcid,
  1758. TEXT(""),
  1759. szSize,
  1760. MAX_PATH,
  1761. g_szMUIInfoFilePath))
  1762. {
  1763. *ulLPKSize =_wtoi64(szSize);
  1764. }
  1765. // Try to get CD # under [CD_LAYOUT]
  1766. //
  1767. if (g_cdnumber == 0)
  1768. {
  1769. g_cdnumber=GetPrivateProfileInt( bIA64? MUI_CDLAYOUT_SECTION_IA64 : MUI_CDLAYOUT_SECTION,
  1770. lpszLcid,
  1771. 0,
  1772. g_szMUIInfoFilePath);
  1773. }
  1774. return TRUE;
  1775. }
  1776. ////////////////////////////////////////////////////////////////////////////////////
  1777. //
  1778. // InitializeListView
  1779. //
  1780. // Gets the list view ready for inserting items
  1781. //
  1782. ////////////////////////////////////////////////////////////////////////////////////
  1783. BOOL InitializeListView(HWND hList)
  1784. {
  1785. DWORD dwExStyle;
  1786. LV_COLUMN Column;
  1787. RECT Rect;
  1788. GetClientRect(hList, &Rect);
  1789. Column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
  1790. Column.fmt = LVCFMT_LEFT;
  1791. Column.cx = Rect.right - GetSystemMetrics(SM_CYHSCROLL);
  1792. Column.pszText = NULL;
  1793. Column.cchTextMax = 0;
  1794. Column.iSubItem = 0;
  1795. ListView_InsertColumn(hList, 0, &Column);
  1796. dwExStyle = ListView_GetExtendedListViewStyle(hList);
  1797. ListView_SetExtendedListViewStyle(hList, dwExStyle | LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
  1798. return TRUE;
  1799. }
  1800. ////////////////////////////////////////////////////////////////////////////////////
  1801. //
  1802. //
  1803. // Check if specified language can install on the target machine.
  1804. // I.E. Arabic, Turkish, Greek and Hebrew MUI can only install on NT Workstation;
  1805. // They are not allowed on NT Server
  1806. //
  1807. ////////////////////////////////////////////////////////////////////////////////////
  1808. BOOL CheckLanguageIsQualified(LPTSTR lpLanguage)
  1809. {
  1810. #ifdef XCHECK_LANGUAGE_FOR_PLATFORM
  1811. BOOL bResult = FALSE;
  1812. LANGID LgLang;
  1813. if (!lpLanguage)
  1814. {
  1815. return bResult;
  1816. }
  1817. LgLang = (LANGID)_tcstol(lpLanguage, NULL, 16);
  1818. LgLang = PRIMARYLANGID(LgLang);
  1819. if(gbIsAdvanceServer)
  1820. {
  1821. if (LgLang == LANG_GERMAN || LgLang == LANG_FRENCH || LgLang == LANG_SPANISH ||
  1822. LgLang == LANG_JAPANESE || LgLang == LANG_KOREAN || LgLang == LANG_CHINESE)
  1823. {
  1824. bResult = TRUE;
  1825. }
  1826. }
  1827. else if(gbIsServer)
  1828. {
  1829. if (LgLang == LANG_GERMAN || LgLang == LANG_FRENCH || LgLang == LANG_SPANISH ||
  1830. LgLang == LANG_JAPANESE || LgLang == LANG_KOREAN || LgLang == LANG_CHINESE ||
  1831. LgLang == LANG_SWEDISH || LgLang == LANG_ITALIAN || LgLang == LANG_DUTCH ||
  1832. LgLang == LANG_PORTUGUESE || LgLang == LANG_CZECH || LgLang == LANG_HUNGARIAN ||
  1833. LgLang == LANG_POLISH || LgLang == LANG_RUSSIAN || LgLang == LANG_TURKISH)
  1834. {
  1835. bResult = TRUE;
  1836. }
  1837. }
  1838. else if(gbIsWorkStation)
  1839. {
  1840. bResult = TRUE;
  1841. }
  1842. return bResult;
  1843. #else
  1844. return TRUE;
  1845. #endif
  1846. }
  1847. ////////////////////////////////////////////////////////////////////////////////////
  1848. //
  1849. // InsertLanguageInListView
  1850. //
  1851. // Returns the index of the item in the list view after inserting it.
  1852. //
  1853. ////////////////////////////////////////////////////////////////////////////////////
  1854. int InsertLanguageInListView(HWND hList, LPTSTR lpLanguage, BOOL bCheckState)
  1855. {
  1856. LANGID LgLang;
  1857. LV_ITEM lvItem;
  1858. PMUILANGINFO pMuiLangInfo;
  1859. int iIndex;
  1860. HRESULT hresult;
  1861. if (!lpLanguage)
  1862. {
  1863. return -1;
  1864. }
  1865. lvItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
  1866. lvItem.iItem = 0;
  1867. lvItem.iSubItem = 0;
  1868. lvItem.state = 0;
  1869. lvItem.stateMask = LVIS_STATEIMAGEMASK;
  1870. lvItem.cchTextMax = 0;
  1871. lvItem.iImage = 0;
  1872. //
  1873. // Allocate enough space to hold pszLcid and MUILANGINFO
  1874. //
  1875. pMuiLangInfo = (PMUILANGINFO) LocalAlloc(LPTR, sizeof(MUILANGINFO));
  1876. if (pMuiLangInfo == NULL)
  1877. {
  1878. ExitFromOutOfMemory();
  1879. }
  1880. else
  1881. {
  1882. pMuiLangInfo->lpszLcid = (LPTSTR) LocalAlloc(LMEM_FIXED, (_tcslen(lpLanguage) + 1) * sizeof(TCHAR));
  1883. }
  1884. if (pMuiLangInfo->lpszLcid == NULL)
  1885. {
  1886. ExitFromOutOfMemory();
  1887. }
  1888. else
  1889. {
  1890. //
  1891. // Init pszLcid
  1892. //
  1893. lvItem.lParam = (LPARAM)pMuiLangInfo;
  1894. //*STRSAFE* _tcscpy((LPTSTR)pMuiLangInfo->lpszLcid, lpLanguage);
  1895. hresult = StringCchCopy((LPTSTR)pMuiLangInfo->lpszLcid ,_tcslen(lpLanguage) + 1 , lpLanguage);
  1896. if (!SUCCEEDED(hresult))
  1897. {
  1898. return -1;
  1899. }
  1900. }
  1901. //
  1902. // Init lcid
  1903. //
  1904. LgLang = (LANGID)_tcstol(lpLanguage, NULL, 16);
  1905. pMuiLangInfo->lcid = MAKELCID(LgLang, SORT_DEFAULT);
  1906. if (pMuiLangInfo->szDisplayName[0] == L'\0')
  1907. {
  1908. GetDisplayName(pMuiLangInfo);
  1909. }
  1910. lvItem.pszText = pMuiLangInfo->szDisplayName;
  1911. GetUIFileSize(pMuiLangInfo);
  1912. iIndex = ListView_InsertItem(hList, &lvItem);
  1913. if (iIndex >= 0)
  1914. {
  1915. ListView_SetCheckState(hList, iIndex, bCheckState);
  1916. }
  1917. return iIndex;
  1918. }
  1919. ////////////////////////////////////////////////////////////////////////////////////
  1920. //
  1921. // GetMuiLangInfoFromListView
  1922. //
  1923. // Get the MuiLangInfo of the corresponding ListView Item
  1924. //
  1925. ////////////////////////////////////////////////////////////////////////////////////
  1926. BOOL GetMuiLangInfoFromListView(HWND hList, int i, PMUILANGINFO *ppMuiLangInfo)
  1927. {
  1928. LVITEM lvItem;
  1929. if (!ppMuiLangInfo)
  1930. {
  1931. return FALSE;
  1932. }
  1933. //
  1934. // Check if Language Group is installed
  1935. //
  1936. lvItem.mask = LVIF_PARAM;
  1937. lvItem.iItem = i;
  1938. lvItem.iSubItem = 0;
  1939. lvItem.state = 0;
  1940. lvItem.stateMask = 0;
  1941. lvItem.pszText = 0;
  1942. lvItem.cchTextMax = 0;
  1943. lvItem.iImage = 0;
  1944. lvItem.lParam = 0;
  1945. ListView_GetItem(hList, &lvItem);
  1946. *ppMuiLangInfo = (PMUILANGINFO)lvItem.lParam;
  1947. return TRUE;
  1948. }
  1949. ////////////////////////////////////////////////////////////////////////////////////
  1950. //
  1951. // Muisetup_GetLocaleLanguageInfo
  1952. //
  1953. // Read the locale info of the language or country name.
  1954. //
  1955. ////////////////////////////////////////////////////////////////////////////////////
  1956. int Muisetup_GetLocaleLanguageInfo(LCID lcid, PTSTR pBuf, int iLen, BOOL fUseCountryName)
  1957. {
  1958. TCHAR tchBuf[ MAX_PATH ] ;
  1959. int iRet;
  1960. HRESULT hresult;
  1961. if ( (!pBuf) || (iLen == 0))
  1962. {
  1963. return 0;
  1964. }
  1965. //
  1966. // If this is either 0x0404 or 0x0804, then mark them specially
  1967. //
  1968. if (0x0404 == lcid)
  1969. {
  1970. iRet = LoadString(ghInstance, IDS_MUI_CHT, pBuf, iLen);
  1971. }
  1972. else if (0x0804 == lcid)
  1973. {
  1974. iRet = LoadString(ghInstance, IDS_MUI_CHS, pBuf, iLen);
  1975. }
  1976. else
  1977. {
  1978. iRet = GetLocaleInfo( lcid,
  1979. LOCALE_SENGLANGUAGE,
  1980. pBuf,
  1981. iLen);
  1982. if (fUseCountryName)
  1983. {
  1984. iRet = GetLocaleInfo( lcid,
  1985. LOCALE_SENGCOUNTRY,
  1986. tchBuf,
  1987. (sizeof(tchBuf)/sizeof(TCHAR)));
  1988. if (iRet)
  1989. {
  1990. //*STRSAFE* _tcscat(pBuf, TEXT(" ("));
  1991. hresult = StringCchCat(pBuf , iLen, TEXT(" ("));
  1992. if (!SUCCEEDED(hresult))
  1993. {
  1994. return 0;
  1995. }
  1996. //*STRSAFE* _tcscat(pBuf, tchBuf);
  1997. hresult = StringCchCat(pBuf , iLen, tchBuf);
  1998. if (!SUCCEEDED(hresult))
  1999. {
  2000. return 0;
  2001. }
  2002. //*STRSAFE* _tcscat(pBuf, TEXT(")"));
  2003. hresult = StringCchCat(pBuf , iLen, TEXT(")"));
  2004. if (!SUCCEEDED(hresult))
  2005. {
  2006. return 0;
  2007. }
  2008. }
  2009. }
  2010. }
  2011. return iRet;
  2012. }
  2013. ////////////////////////////////////////////////////////////////////////////////////
  2014. //
  2015. // GetLcidFromComboBox
  2016. //
  2017. // Retreives the index of the combo box item that corresponds to this UI Language
  2018. //
  2019. ////////////////////////////////////////////////////////////////////////////////////
  2020. BOOL GetLcidFromComboBox(HWND hCombo, LCID lcid, int *piIndex)
  2021. {
  2022. LCID ItemLcid;
  2023. int i;
  2024. int iCount = (int)SendMessage(hCombo, CB_GETCOUNT, 0L, 0L);
  2025. if (!piIndex)
  2026. {
  2027. return FALSE;
  2028. }
  2029. if (CB_ERR != iCount)
  2030. {
  2031. i = 0;
  2032. while (i < iCount)
  2033. {
  2034. ItemLcid = (LCID)SendMessage(hCombo, CB_GETITEMDATA, (WPARAM)i, (LPARAM)0);
  2035. if ((CB_ERR != ItemLcid) && (ItemLcid == lcid))
  2036. {
  2037. *piIndex = i;
  2038. return TRUE;
  2039. }
  2040. i++;
  2041. }
  2042. }
  2043. return FALSE;
  2044. }
  2045. ////////////////////////////////////////////////////////////////////////////////////
  2046. //
  2047. // GetMuiLangInfoFromListView
  2048. //
  2049. // Retreives the index of the listview item that corresponds to this UI Language
  2050. //
  2051. ////////////////////////////////////////////////////////////////////////////////////
  2052. BOOL GetLcidItemIndexFromListView(HWND hList, LCID lcid, int *piIndex)
  2053. {
  2054. int iCount = ListView_GetItemCount(hList);
  2055. int i;
  2056. PMUILANGINFO pMuiLangInfo;
  2057. LVITEM lvItem;
  2058. if (!piIndex)
  2059. {
  2060. return FALSE;
  2061. }
  2062. i = 0;
  2063. while (i < iCount)
  2064. {
  2065. //
  2066. // Check if Language Group is installed
  2067. //
  2068. lvItem.mask = LVIF_PARAM;
  2069. lvItem.iItem = i;
  2070. lvItem.iSubItem = 0;
  2071. lvItem.state = 0;
  2072. lvItem.stateMask = 0;
  2073. lvItem.pszText = 0;
  2074. lvItem.cchTextMax = 0;
  2075. lvItem.iImage = 0;
  2076. lvItem.lParam = 0;
  2077. ListView_GetItem(hList, &lvItem);
  2078. pMuiLangInfo = (PMUILANGINFO)lvItem.lParam;
  2079. if (pMuiLangInfo->lcid == lcid)
  2080. {
  2081. *piIndex = i;
  2082. return TRUE;
  2083. }
  2084. i++;
  2085. }
  2086. return FALSE;
  2087. }
  2088. ////////////////////////////////////////////////////////////////////////////////////
  2089. //
  2090. // SelectInstalledLanguages
  2091. //
  2092. // Sets the list view check state for insalled languages
  2093. //
  2094. // TODO: We should perhaps use the MSI to check for installed packages instead...
  2095. ////////////////////////////////////////////////////////////////////////////////////
  2096. BOOL SelectInstalledLanguages(HWND hList)
  2097. {
  2098. DWORD dwData;
  2099. DWORD dwIndex;
  2100. DWORD dwValue;
  2101. HKEY hKey;
  2102. LANGID LgLang;
  2103. LONG rc;
  2104. TCHAR lpItemString[BUFFER_SIZE];
  2105. TCHAR szData[BUFFER_SIZE];
  2106. TCHAR szValue[BUFFER_SIZE];
  2107. int iIndex;
  2108. int nLvIndex;
  2109. if (hKey = OpenMuiKey(KEY_READ))
  2110. {
  2111. dwIndex = 0;
  2112. rc = ERROR_SUCCESS;
  2113. iIndex = ListView_GetItemCount(hList);
  2114. while(rc==ERROR_SUCCESS)
  2115. {
  2116. dwValue=sizeof(szValue)/sizeof(TCHAR);
  2117. szValue[0]=TEXT('\0');
  2118. dwData = sizeof(szData);
  2119. szData[0] = TEXT('\0');
  2120. DWORD dwType;
  2121. rc = RegEnumValue(hKey, dwIndex, szValue, &dwValue, 0, &dwType, (LPBYTE)szData, &dwData);
  2122. if (rc == ERROR_SUCCESS)
  2123. {
  2124. if (dwType != REG_SZ)
  2125. {
  2126. dwIndex++;
  2127. continue;
  2128. }
  2129. LgLang=(WORD)_tcstol(szValue, NULL, 16);
  2130. if (GetLcidItemIndexFromListView(hList, MAKELCID(LgLang, SORT_DEFAULT), &nLvIndex))
  2131. {
  2132. ListView_SetCheckState(hList, nLvIndex, TRUE);
  2133. }
  2134. }
  2135. dwIndex++;
  2136. }
  2137. RegCloseKey(hKey);
  2138. return TRUE;
  2139. }
  2140. return FALSE;
  2141. }
  2142. ////////////////////////////////////////////////////////////////////////////////////
  2143. //
  2144. // UpdateCombo
  2145. //
  2146. // Updates the combo box to correspond to the languages selected in the list view
  2147. //
  2148. ////////////////////////////////////////////////////////////////////////////////////
  2149. BOOL UpdateCombo(HWND hwndDlg)
  2150. {
  2151. BOOL bDefaultSet=FALSE;
  2152. HWND hCombo;
  2153. HWND hList;
  2154. TCHAR lpBuffer[BUFFER_SIZE];
  2155. TCHAR lpSystemDefault[BUFFER_SIZE];
  2156. int i;
  2157. int iIndex;
  2158. int iLbIndex;
  2159. int iListIndex;
  2160. WPARAM iPrevDefault;
  2161. LCID lcidPrev;
  2162. PMUILANGINFO pMuiLangInfo;
  2163. hList = GetDlgItem(hwndDlg, IDC_LIST1);
  2164. hCombo = GetDlgItem(hwndDlg, IDC_DEF_UI_LANG_COMBO);
  2165. //
  2166. // If the Previous Default is still selected, keep it as the default
  2167. //
  2168. iPrevDefault = SendMessage(hCombo, CB_GETCURSEL, 0, 0);
  2169. if (iPrevDefault == CB_ERR)
  2170. return FALSE;
  2171. lcidPrev = (LCID) SendMessage(hCombo, CB_GETITEMDATA, (WPARAM)iPrevDefault, 0);
  2172. //
  2173. // Get the text of the currently selected default
  2174. //
  2175. GetLcidItemIndexFromListView(hList, lcidPrev, &iLbIndex);
  2176. SendMessage(hCombo, CB_RESETCONTENT, 0, 0);
  2177. iIndex = ListView_GetItemCount(hList);
  2178. iListIndex = 0;
  2179. //
  2180. // See if we can preserve the default.
  2181. //
  2182. i = 0;
  2183. while (i < iIndex)
  2184. {
  2185. if (ListView_GetCheckState(hList, i))
  2186. {
  2187. ListView_GetItemText(hList, i, 0, lpBuffer, ARRAYSIZE(lpBuffer)-1);
  2188. iListIndex = (int) SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)(LPTSTR)lpBuffer);
  2189. if (CB_ERR != iListIndex)
  2190. {
  2191. GetMuiLangInfoFromListView(hList, i, &pMuiLangInfo);
  2192. SendMessage(hCombo, CB_SETITEMDATA, iListIndex, (LPARAM)(LCID)pMuiLangInfo->lcid);
  2193. if (pMuiLangInfo->lcid == lcidPrev)
  2194. {
  2195. SendMessage(hCombo, CB_SETCURSEL, (WPARAM)iListIndex, 0);
  2196. bDefaultSet = TRUE;
  2197. }
  2198. }
  2199. }
  2200. i++;
  2201. }
  2202. //
  2203. // If no default, force the system default.
  2204. //
  2205. if (!bDefaultSet)
  2206. {
  2207. lcidPrev = MAKELCID(gSystemUILangId, SORT_DEFAULT);
  2208. if (!GetLcidFromComboBox(hCombo, lcidPrev, &iIndex))
  2209. {
  2210. GetLocaleInfo(lcidPrev,
  2211. LOCALE_SENGLANGUAGE,
  2212. lpSystemDefault,
  2213. ARRAYSIZE(lpSystemDefault)-1);
  2214. iIndex = (int) SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)lpSystemDefault);
  2215. SendMessage(hCombo, CB_SETITEMDATA, (WPARAM)iIndex, (LPARAM)(LCID)lcidPrev);
  2216. }
  2217. SendMessage(hCombo, CB_SETCURSEL, (WPARAM)iIndex, 0);
  2218. }
  2219. return TRUE;
  2220. }
  2221. ////////////////////////////////////////////////////////////////////////////////////
  2222. //
  2223. // SetDefault
  2224. //
  2225. // Sets the default user setting in the combo box
  2226. //
  2227. ////////////////////////////////////////////////////////////////////////////////////
  2228. BOOL SetDefault(HWND hCombo)
  2229. {
  2230. int iIndex;
  2231. TCHAR lpBuffer[BUFFER_SIZE];
  2232. LCID lcid = MAKELCID(GetDotDefaultUILanguage(), SORT_DEFAULT);
  2233. GetLocaleInfo(lcid,
  2234. LOCALE_SENGLANGUAGE,
  2235. lpBuffer,
  2236. ARRAYSIZE(lpBuffer)-1);
  2237. iIndex = (int)SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)lpBuffer);
  2238. if (CB_ERR != iIndex)
  2239. {
  2240. SendMessage(hCombo, CB_SETITEMDATA, (WPARAM)iIndex, (LPARAM)(DWORD) lcid);
  2241. SendMessage(hCombo, CB_SETCURSEL, (WPARAM)iIndex, 0);
  2242. }
  2243. return TRUE;
  2244. }
  2245. ////////////////////////////////////////////////////////////////////////////////////
  2246. //
  2247. // SetUserDefaultLanguage
  2248. //
  2249. // Sets the default language in the registry
  2250. //
  2251. ////////////////////////////////////////////////////////////////////////////////////
  2252. BOOL SetUserDefaultLanguage(LANGID langID, BOOL bApplyCurrentUser, BOOL bApplyAllUsers)
  2253. {
  2254. TCHAR szCommands[BUFFER_SIZE];
  2255. TCHAR szBuf[BUFFER_SIZE];
  2256. BOOL success;
  2257. LONG_PTR lppArgs[2];
  2258. HRESULT hresult;
  2259. //
  2260. // Set the UI language now
  2261. //
  2262. // status = gpfnNtSetDefaultUILanguage(LANGIDFROMLCID(langID));
  2263. szCommands[0] = TEXT('\0');
  2264. if (bApplyCurrentUser)
  2265. {
  2266. // E.g. MUILanguage = "0411".
  2267. //*STRSAFE* wsprintf(szCommands, TEXT("MUILanguage=\"%x\"\n"), langID);
  2268. hresult = StringCchPrintf(szCommands , ARRAYSIZE(szCommands), TEXT("MUILanguage=\"%x\"\n"), langID);
  2269. if (!SUCCEEDED(hresult))
  2270. {
  2271. return FALSE;
  2272. }
  2273. }
  2274. if (bApplyAllUsers)
  2275. {
  2276. //*STRSAFE* wsprintf(szBuf, TEXT("MUILanguage_DefaultUser = \"%x\""), langID);
  2277. hresult = StringCchPrintf(szBuf , ARRAYSIZE(szBuf), TEXT("MUILanguage_DefaultUser = \"%x\""), langID);
  2278. if (!SUCCEEDED(hresult))
  2279. {
  2280. return FALSE;
  2281. }
  2282. //*STRSAFE* _tcscat(szCommands, szBuf);
  2283. hresult = StringCchCat(szCommands , ARRAYSIZE(szCommands), szBuf);
  2284. if (!SUCCEEDED(hresult))
  2285. {
  2286. return FALSE;
  2287. }
  2288. }
  2289. success = RunRegionalOptionsApplet(szCommands);
  2290. lppArgs[0] = langID;
  2291. if (success)
  2292. {
  2293. if (bApplyCurrentUser)
  2294. {
  2295. LogFormattedMessage(NULL, IDS_SET_UILANG_CURRENT, lppArgs);
  2296. }
  2297. if (bApplyAllUsers)
  2298. {
  2299. LogFormattedMessage(NULL, IDS_SET_UILANG_ALLUSERS, lppArgs);
  2300. }
  2301. } else
  2302. {
  2303. if (bApplyCurrentUser)
  2304. {
  2305. LogFormattedMessage(NULL, IDS_ERROR_SET_UILANG_CURRENT, lppArgs);
  2306. }
  2307. if (bApplyAllUsers)
  2308. {
  2309. LogFormattedMessage(NULL, IDS_ERROR_SET_UILANG_ALLUSERS, lppArgs);
  2310. }
  2311. }
  2312. return (success);
  2313. }
  2314. ////////////////////////////////////////////////////////////////////////////////////
  2315. //
  2316. // GetDotDefaultUILanguage
  2317. //
  2318. // Retrieve the UI language stored in the HKCU\.Default.
  2319. // This is the default UI language for new users.
  2320. //
  2321. ////////////////////////////////////////////////////////////////////////////////////
  2322. LANGID GetDotDefaultUILanguage()
  2323. {
  2324. HKEY hKey;
  2325. DWORD dwKeyType;
  2326. DWORD dwSize;
  2327. BOOL success = FALSE;
  2328. TCHAR szBuffer[BUFFER_SIZE];
  2329. LANGID langID;
  2330. //
  2331. // Get the value in .DEFAULT.
  2332. //
  2333. if (RegOpenKeyEx( HKEY_USERS,
  2334. TEXT(".DEFAULT\\Control Panel\\Desktop"),
  2335. 0L,
  2336. KEY_READ,
  2337. &hKey ) == ERROR_SUCCESS)
  2338. {
  2339. dwSize = sizeof(szBuffer);
  2340. if (RegQueryValueEx( hKey,
  2341. TEXT("MultiUILanguageId"),
  2342. 0L,
  2343. &dwKeyType,
  2344. (LPBYTE)szBuffer,
  2345. &dwSize) == ERROR_SUCCESS)
  2346. {
  2347. if (dwKeyType == REG_SZ)
  2348. {
  2349. langID = (LANGID)_tcstol(szBuffer, NULL, 16);
  2350. success = TRUE;
  2351. }
  2352. }
  2353. RegCloseKey(hKey);
  2354. }
  2355. // here, check to see if the key is actually meaningful, if not, return SystemDefaultUILanguage
  2356. if (success && (!IsInstalled(szBuffer)))
  2357. {
  2358. success = FALSE;
  2359. }
  2360. if (!success)
  2361. {
  2362. langID = GetSystemDefaultUILanguage();
  2363. }
  2364. return (langID);
  2365. }
  2366. ////////////////////////////////////////////////////////////////////////////////////
  2367. //
  2368. // CheckLangGroupCommandLine
  2369. //
  2370. // Command line version of CheckSupport
  2371. //
  2372. ////////////////////////////////////////////////////////////////////////////////////
  2373. BOOL CheckLangGroupCommandLine(PINSTALL_LANG_GROUP pInstallLangGroup, LPTSTR lpArg)
  2374. {
  2375. int i = 0;
  2376. int iArg;
  2377. LGRPID lgrpid;
  2378. if ( (!pInstallLangGroup) || (!lpArg))
  2379. {
  2380. return FALSE;
  2381. }
  2382. iArg = _tcstol(lpArg, NULL, 16);
  2383. //
  2384. // See if the lang group for this MUI lang is installed or not
  2385. //
  2386. lgrpid = GetLanguageGroup(MAKELCID(iArg, SORT_DEFAULT));
  2387. if (AddMUILangGroup(pInstallLangGroup, lgrpid))
  2388. {
  2389. return TRUE;
  2390. }
  2391. return FALSE;
  2392. }
  2393. ////////////////////////////////////////////////////////////////////////////////////
  2394. //
  2395. // SetWindowTitleFromResource
  2396. //
  2397. // Set the window title using the specified resource string ID.
  2398. //
  2399. ////////////////////////////////////////////////////////////////////////////////////
  2400. void SetWindowTitleFromResource(HWND hwnd, int resourceID)
  2401. {
  2402. TCHAR szBuffer[BUFFER_SIZE];
  2403. LoadString(NULL, resourceID, szBuffer, sizeof(szBuffer)/sizeof(TCHAR));
  2404. SetWindowText(hwnd, szBuffer);
  2405. }
  2406. BOOL RemoveFileReadOnlyAttribute(LPTSTR lpszFileName)
  2407. {
  2408. BOOL bResult = FALSE;
  2409. DWORD dwAttrib;
  2410. if (! lpszFileName)
  2411. {
  2412. return bResult;
  2413. }
  2414. dwAttrib = GetFileAttributes (lpszFileName);
  2415. if ( dwAttrib & FILE_ATTRIBUTE_READONLY )
  2416. {
  2417. dwAttrib &= ~FILE_ATTRIBUTE_READONLY;
  2418. SetFileAttributes (lpszFileName, dwAttrib);
  2419. bResult=TRUE;
  2420. }
  2421. return bResult;
  2422. }
  2423. BOOL MUI_DeleteFile(LPTSTR lpszFileName)
  2424. {
  2425. if (!lpszFileName)
  2426. {
  2427. return FALSE;
  2428. }
  2429. RemoveFileReadOnlyAttribute(lpszFileName);
  2430. return DeleteFile(lpszFileName);
  2431. }
  2432. BOOL DeleteSideBySideMUIAssemblyIfExisted(LPTSTR Languages, TCHAR pszLogFile[BUFFER_SIZE])
  2433. {
  2434. HRESULT hresult;
  2435. if (!Languages)
  2436. {
  2437. return FALSE;
  2438. }
  2439. //*STRSAFE* lstrcpy(pszLogFile, g_szWinDir); // c:\windows
  2440. hresult = StringCchCopy(pszLogFile , BUFFER_SIZE, g_szWinDir);
  2441. if (!SUCCEEDED(hresult))
  2442. {
  2443. return FALSE;
  2444. }
  2445. //*STRSAFE* lstrcat(pszLogFile, MUISETUP_PATH_SEPARATOR); // c:\windows
  2446. hresult = StringCchCat(pszLogFile , BUFFER_SIZE, MUISETUP_PATH_SEPARATOR);
  2447. if (!SUCCEEDED(hresult))
  2448. {
  2449. return FALSE;
  2450. }
  2451. //*STRSAFE* lstrcat(pszLogFile, MUIDIR); // c:\windows\mui
  2452. hresult = StringCchCat(pszLogFile , BUFFER_SIZE, MUIDIR);
  2453. if (!SUCCEEDED(hresult))
  2454. {
  2455. return FALSE;
  2456. }
  2457. //*STRSAFE* lstrcat(pszLogFile, MUISETUP_PATH_SEPARATOR); // c:\windows\mui
  2458. hresult = StringCchCat(pszLogFile , BUFFER_SIZE, MUISETUP_PATH_SEPARATOR);
  2459. if (!SUCCEEDED(hresult))
  2460. {
  2461. return FALSE;
  2462. }
  2463. //*STRSAFE* lstrcat(pszLogFile, MUISETUP_ASSEMBLY_INSTALLATION_LOG_FILENAME); // c:\windows\mui\muisetup.log.
  2464. hresult = StringCchCat(pszLogFile , BUFFER_SIZE, MUISETUP_ASSEMBLY_INSTALLATION_LOG_FILENAME);
  2465. if (!SUCCEEDED(hresult))
  2466. {
  2467. return FALSE;
  2468. }
  2469. //*STRSAFE* lstrcat(pszLogFile, Languages); // c:\windows\mui\muisetup.log.1234
  2470. hresult = StringCchCat(pszLogFile , BUFFER_SIZE, Languages);
  2471. if (!SUCCEEDED(hresult))
  2472. {
  2473. return FALSE;
  2474. }
  2475. if (GetFileAttributes(pszLogFile) != 0xFFFFFFFF) // existed
  2476. {
  2477. // open it and delete assemblies in the list
  2478. SXS_UNINSTALLW UninstallData = {sizeof(UninstallData)};
  2479. UninstallData.dwFlags = SXS_UNINSTALL_FLAG_USE_INSTALL_LOG;
  2480. UninstallData.lpInstallLogFile = pszLogFile;
  2481. return gpfnSxsUninstallW(&UninstallData,NULL);
  2482. }else
  2483. return TRUE;
  2484. }
  2485. ////////////////////////////////////////////////////////////////////////////////////
  2486. //
  2487. // InstallSelected
  2488. //
  2489. // Install the languages specified
  2490. //
  2491. // Return:
  2492. // TURE if the operation succeeds. Otherwise FALSE.
  2493. //
  2494. ////////////////////////////////////////////////////////////////////////////////////
  2495. BOOL InstallSelected(LPTSTR Languages, BOOL *lpbFontLinkRegistryTouched)
  2496. {
  2497. TCHAR lpMessage[BUFFER_SIZE];
  2498. if (!Languages)
  2499. {
  2500. return FALSE;
  2501. }
  2502. //
  2503. // Next step is to create a list of install directories from layout
  2504. // the directories are listed in the [Directories] section of MUI.INF
  2505. //
  2506. if (!EnumDirectories())
  2507. {
  2508. //
  2509. // "LOG: Error reading directory list."
  2510. //
  2511. LoadString(ghInstance, IDS_DIRECTORY_L, lpMessage, ARRAYSIZE(lpMessage)-1);
  2512. LogMessage(lpMessage);
  2513. return (FALSE);
  2514. }
  2515. EnumFileRename();
  2516. EnumTypeNotFallback();
  2517. //
  2518. // Copy the common files
  2519. //
  2520. if (Languages)
  2521. {
  2522. //
  2523. // Copy MUI files for the selected languages.
  2524. //
  2525. #ifdef MUI_MAGIC
  2526. if (!g_bNoUI)
  2527. {
  2528. SetWindowTitleFromResource(ghProgDialog, IDS_INSTALL_TITLE);
  2529. }
  2530. #endif
  2531. if (!CopyFiles(ghProgDialog, Languages))
  2532. {
  2533. //
  2534. // "LOG: Error copying files."
  2535. //
  2536. // stop install if copy fails
  2537. //
  2538. LoadString(ghInstance, IDS_COPY_L, lpMessage, ARRAYSIZE(lpMessage)-1);
  2539. LogMessage(lpMessage);
  2540. #ifndef IGNORE_COPY_ERRORS
  2541. gNumLanguages_Install = 0;
  2542. return (FALSE);
  2543. #endif
  2544. }
  2545. #ifndef MUI_MAGIC
  2546. CopyRemoveMuiItself(TRUE);
  2547. #endif
  2548. }
  2549. #ifndef MUI_MAGIC
  2550. //
  2551. // register MUI as installed in registry
  2552. //
  2553. if (!UpdateRegistry(Languages,lpbFontLinkRegistryTouched))
  2554. {
  2555. //
  2556. // LOG: Error updating registry
  2557. //
  2558. LoadString(ghInstance, IDS_REGISTRY_L, lpMessage, ARRAYSIZE(lpMessage)-1);
  2559. LogMessage(lpMessage);
  2560. return (FALSE);
  2561. }
  2562. if (!InstallExternalComponents(Languages))
  2563. {
  2564. return (FALSE);
  2565. }
  2566. #endif
  2567. return (TRUE);
  2568. }
  2569. ////////////////////////////////////////////////////////////////////////////////////
  2570. //
  2571. // UninstallSelected
  2572. //
  2573. // Uninstall the languages specified
  2574. //
  2575. // Return:
  2576. // TRUE if the operation succeeds. Otherwise FALSE.
  2577. //
  2578. ////////////////////////////////////////////////////////////////////////////////////
  2579. BOOL UninstallSelected(LPTSTR Languages,int *lpNotDeleted)
  2580. {
  2581. TCHAR lpMessage[BUFFER_SIZE];
  2582. BOOL bResult = TRUE;
  2583. HRESULT hresult;
  2584. if (!Languages)
  2585. {
  2586. return FALSE;
  2587. }
  2588. //
  2589. // Next step is to create a list of install directories
  2590. // the directories are listed in the [Directories] section
  2591. //
  2592. //
  2593. // this enumerates the directories and fills the array DirNames
  2594. //
  2595. if (!EnumDirectories())
  2596. {
  2597. //
  2598. // "LOG: Error reading directory list."
  2599. //
  2600. LoadString(ghInstance, IDS_DIRECTORY_L, lpMessage, ARRAYSIZE(lpMessage)-1);
  2601. LogMessage(lpMessage);
  2602. return (FALSE);
  2603. }
  2604. #ifndef MUI_MAGIC
  2605. UninstallExternalComponents(Languages);
  2606. if (!g_bNoUI)
  2607. {
  2608. SetWindowTitleFromResource(ghProgDialog, IDS_UNINSTALL_TITLE);
  2609. }
  2610. #endif
  2611. //
  2612. // Copy the common files
  2613. //
  2614. if (!DeleteFiles(Languages,lpNotDeleted))
  2615. {
  2616. //
  2617. // "LOG: Error deleting files"
  2618. //
  2619. LoadString(ghInstance, IDS_DELETE_L, lpMessage, ARRAYSIZE(lpMessage)-1);
  2620. LogMessage(lpMessage);
  2621. bResult = FALSE; // even though something failed, we will continue to try to uninstall the product here so upgrade uninstallation will continue clean up
  2622. }
  2623. //
  2624. // register MUI as installed in registry, the function logs messages already, so we don't need to log another one here.
  2625. //
  2626. UninstallUpdateRegistry(Languages);
  2627. //
  2628. // Delete sxs Assembly
  2629. //
  2630. if (gpfnSxsUninstallW)
  2631. {
  2632. TCHAR pszLogFile[BUFFER_SIZE];
  2633. if ( ! DeleteSideBySideMUIAssemblyIfExisted(Languages, pszLogFile))
  2634. {
  2635. TCHAR errInfo[BUFFER_SIZE];
  2636. //*STRSAFE* swprintf(errInfo, TEXT("Assembly UnInstallation of %s failed"), pszLogFile);
  2637. hresult = StringCchPrintf(errInfo , ARRAYSIZE(errInfo), TEXT("Assembly UnInstallation of %s failed"), pszLogFile);
  2638. if (!SUCCEEDED(hresult))
  2639. {
  2640. return FALSE;
  2641. }
  2642. OutputDebugString(errInfo);
  2643. }
  2644. }
  2645. return (bResult);
  2646. }
  2647. ////////////////////////////////////////////////////////////////////////////////////
  2648. //
  2649. // UninstallUpdateRegistry
  2650. //
  2651. // Update the Registry to account for languages that have been uninstalled
  2652. //
  2653. ////////////////////////////////////////////////////////////////////////////////////
  2654. BOOL UninstallUpdateRegistry(LPTSTR Languages)
  2655. {
  2656. LPTSTR Language;
  2657. HKEY hKeyMUI = 0;
  2658. HKEY hKeyFileVersions = 0;
  2659. DWORD dwDisp;
  2660. BOOL bRet = TRUE;
  2661. TCHAR tcMessage[BUFFER_SIZE];
  2662. if (!Languages)
  2663. {
  2664. return FALSE;
  2665. }
  2666. if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  2667. REG_MUI_PATH,
  2668. 0,
  2669. TEXT("REG_SZ"),
  2670. REG_OPTION_NON_VOLATILE ,
  2671. KEY_ALL_ACCESS,
  2672. NULL,
  2673. &hKeyMUI,
  2674. &dwDisp) != ERROR_SUCCESS)
  2675. {
  2676. bRet = FALSE;
  2677. goto Exit;
  2678. }
  2679. if (RegCreateKeyEx( HKEY_CURRENT_USER,
  2680. REG_FILEVERSION_PATH,
  2681. 0,
  2682. TEXT("REG_SZ"),
  2683. REG_OPTION_NON_VOLATILE ,
  2684. KEY_ALL_ACCESS,
  2685. NULL,
  2686. &hKeyFileVersions,
  2687. &dwDisp) != ERROR_SUCCESS)
  2688. {
  2689. bRet = FALSE;
  2690. goto Exit;
  2691. }
  2692. Language = Languages;
  2693. while (*Language)
  2694. {
  2695. //
  2696. // Don't remove system UI language for registry
  2697. //
  2698. if (HexStrToInt(Language) != gSystemUILangId)
  2699. {
  2700. //
  2701. // Delete UI Language key, subkeys and values.
  2702. //
  2703. if (RegDeleteValue(hKeyMUI, Language) != ERROR_SUCCESS)
  2704. {
  2705. bRet = FALSE;
  2706. }
  2707. if (DeleteRegTree(hKeyFileVersions, Language) != ERROR_SUCCESS)
  2708. {
  2709. bRet = FALSE;
  2710. }
  2711. }
  2712. //
  2713. // Attempt to delete the Windows installer regkey entry if we are in OS upgrade setup
  2714. //
  2715. if (TRUE == g_bRunFromOSSetup)
  2716. {
  2717. DeleteMSIRegSettings(Language);
  2718. }
  2719. while (*Language++) // go to the next language and repeat
  2720. {
  2721. }
  2722. } // of while (*Language)
  2723. //
  2724. // Delete Match UI Font and Match locale Key
  2725. //
  2726. DeleteMUIRegSetting();
  2727. Exit:
  2728. //
  2729. // Clean up
  2730. //
  2731. if (hKeyMUI)
  2732. RegCloseKey(hKeyMUI);
  2733. if (hKeyFileVersions)
  2734. RegCloseKey(hKeyFileVersions);
  2735. return bRet;
  2736. }
  2737. ////////////////////////////////////////////////////////////////////////////////////
  2738. //
  2739. // EnumSelectedLanguages
  2740. //
  2741. // Enumerate the languages marked for installation
  2742. //
  2743. // Return:
  2744. // The total number of MUI languages to be added.
  2745. //
  2746. ////////////////////////////////////////////////////////////////////////////////////
  2747. int EnumSelectedLanguages(HWND hList, LPTSTR lpAddLanguages)
  2748. {
  2749. TCHAR szBuffer[BUFFER_SIZE];
  2750. TCHAR *p;
  2751. LPTSTR lpszLcid;
  2752. int iIndex;
  2753. int i = 0;
  2754. PMUILANGINFO pMuiLangInfo;
  2755. int installLangCount = 0;
  2756. iIndex = ListView_GetItemCount(hList);
  2757. HRESULT hresult;
  2758. if (!lpAddLanguages)
  2759. {
  2760. return 0;
  2761. }
  2762. *lpAddLanguages=TEXT('\0');
  2763. while(i<iIndex)
  2764. {
  2765. if(ListView_GetCheckState(hList, i))
  2766. {
  2767. GetMuiLangInfoFromListView(hList, i, &pMuiLangInfo);
  2768. lpszLcid = pMuiLangInfo->lpszLcid;
  2769. if (!IsInstalled(lpszLcid) && HaveFiles(lpszLcid))
  2770. {
  2771. //*STRSAFE* _tcscat(lpAddLanguages, lpszLcid);
  2772. hresult = StringCchCat(lpAddLanguages , BUFFER_SIZE, lpszLcid);
  2773. if (!SUCCEEDED(hresult))
  2774. {
  2775. return 0;
  2776. }
  2777. //*STRSAFE* _tcscat(lpAddLanguages, TEXT("*"));
  2778. hresult = StringCchCat(lpAddLanguages , BUFFER_SIZE, TEXT("*"));
  2779. if (!SUCCEEDED(hresult))
  2780. {
  2781. return 0;
  2782. }
  2783. //
  2784. // Count how many languages are being installed/uninstalled for the progress bar
  2785. //
  2786. gNumLanguages++;
  2787. gNumLanguages_Install++;
  2788. installLangCount++;
  2789. }
  2790. }
  2791. i++;
  2792. }
  2793. p = lpAddLanguages;
  2794. while (p=_tcschr(p, TEXT('*')))
  2795. {
  2796. *p=TEXT('\0');
  2797. p++;
  2798. }
  2799. return (installLangCount);
  2800. }
  2801. ////////////////////////////////////////////////////////////////////////////////////
  2802. //
  2803. // EnumUnselectedLanguages
  2804. //
  2805. // Enumerate the languages marked for removal
  2806. //
  2807. // Return:
  2808. // The total number of MUI languages to be added.
  2809. //
  2810. ////////////////////////////////////////////////////////////////////////////////////
  2811. int EnumUnselectedLanguages(HWND hList, LPTSTR lpRemoveLanguages)
  2812. {
  2813. LPTSTR p;
  2814. TCHAR szBuffer[BUFFER_SIZE];
  2815. LPTSTR lpszLcid;
  2816. int iIndex;
  2817. int i = 0;
  2818. PMUILANGINFO pMuiLangInfo;
  2819. int uninstallLangCount = 0;
  2820. HRESULT hresult;
  2821. iIndex = ListView_GetItemCount(hList);
  2822. if (!lpRemoveLanguages)
  2823. {
  2824. return 0;
  2825. }
  2826. *lpRemoveLanguages=TEXT('\0');
  2827. g_bRemoveDefaultUI=FALSE;
  2828. while (i < iIndex)
  2829. {
  2830. if (!ListView_GetCheckState(hList, i))
  2831. {
  2832. GetMuiLangInfoFromListView(hList, i, &pMuiLangInfo);
  2833. lpszLcid = pMuiLangInfo->lpszLcid;
  2834. if (IsInstalled(lpszLcid))
  2835. {
  2836. //*STRSAFE* _tcscat(lpRemoveLanguages, lpszLcid);
  2837. hresult = StringCchCat(lpRemoveLanguages , BUFFER_SIZE, lpszLcid);
  2838. if (!SUCCEEDED(hresult))
  2839. {
  2840. return 0;
  2841. }
  2842. //*STRSAFE* _tcscat(lpRemoveLanguages, TEXT("*"));
  2843. hresult = StringCchCat(lpRemoveLanguages , BUFFER_SIZE, TEXT("*"));
  2844. if (!SUCCEEDED(hresult))
  2845. {
  2846. return 0;
  2847. }
  2848. if (GetDotDefaultUILanguage() == pMuiLangInfo->lcid)
  2849. {
  2850. g_bRemoveDefaultUI=TRUE;
  2851. }
  2852. if (GetUserDefaultUILanguage() == pMuiLangInfo->lcid)
  2853. {
  2854. g_bRemoveUserUI = TRUE;
  2855. }
  2856. //
  2857. // Count how many languages are being installed/uninstalled for the progress bar
  2858. //
  2859. gNumLanguages++;
  2860. gNumLanguages_Uninstall++;
  2861. uninstallLangCount++;
  2862. }
  2863. }
  2864. i++;
  2865. }
  2866. p = lpRemoveLanguages;
  2867. while (p=_tcschr(p, TEXT('*')))
  2868. {
  2869. *p = TEXT('\0');
  2870. p++;
  2871. }
  2872. return (uninstallLangCount);
  2873. }
  2874. ////////////////////////////////////////////////////////////////////////////////////
  2875. //
  2876. // SkipBlanks
  2877. //
  2878. // Skips spaces and tabs in string. Returns pointer to next character
  2879. //
  2880. ////////////////////////////////////////////////////////////////////////////////////
  2881. PTCHAR SkipBlanks(PTCHAR pszText)
  2882. {
  2883. if (!pszText)
  2884. {
  2885. return NULL;
  2886. }
  2887. while (*pszText==TEXT(' ') || *pszText==TEXT('\t'))
  2888. {
  2889. pszText++;
  2890. }
  2891. return pszText;
  2892. }
  2893. ////////////////////////////////////////////////////////////////////////////////////
  2894. //
  2895. // NextCommandTag
  2896. //
  2897. // pointing to next command tag (TEXT('-') or TEXT('/')
  2898. //
  2899. ////////////////////////////////////////////////////////////////////////////////////
  2900. LPTSTR NextCommandTag(LPTSTR lpcmd)
  2901. {
  2902. LPTSTR p=NULL;
  2903. if(!lpcmd)
  2904. {
  2905. return (p);
  2906. }
  2907. while(*lpcmd)
  2908. {
  2909. if ((*lpcmd == TEXT('-')) || (*lpcmd == TEXT('/')))
  2910. {
  2911. // Skip to the character after the '-','/'.
  2912. p = lpcmd + 1;
  2913. break;
  2914. }
  2915. lpcmd++;
  2916. }
  2917. return (p);
  2918. }
  2919. ////////////////////////////////////////////////////////////////////////////////////
  2920. //
  2921. // IsInInstallList
  2922. //
  2923. // Check if a target is in the string list
  2924. //
  2925. // Structure of string list:
  2926. //
  2927. // <string 1><NULL><string 2><NULL>......<string n><NULL><NULL>
  2928. //
  2929. ////////////////////////////////////////////////////////////////////////////////////
  2930. BOOL IsInInstallList(LPTSTR lpList,LPTSTR lpTarget)
  2931. {
  2932. BOOL bResult=FALSE;
  2933. if (!lpList || !lpTarget)
  2934. return bResult;
  2935. while (*lpList)
  2936. {
  2937. if (!_tcsicmp(lpList,lpTarget))
  2938. {
  2939. bResult=TRUE;
  2940. break;
  2941. }
  2942. while (*lpList++) // move to next
  2943. {
  2944. }
  2945. }
  2946. return bResult;
  2947. }
  2948. ////////////////////////////////////////////////////////////////////////////////////
  2949. //
  2950. // CreateProgressDialog
  2951. //
  2952. // Globals affected:
  2953. // ghProgDialog
  2954. // ghProgress
  2955. //
  2956. ////////////////////////////////////////////////////////////////////////////////////
  2957. void CreateProgressDialog(HWND hwnd)
  2958. {
  2959. ghProgDialog = CreateDialog(ghInstance,
  2960. MAKEINTRESOURCE(IDD_DIALOG_INSTALL_PROGRESS),
  2961. hwnd,
  2962. ProgressDialogFunc);
  2963. ghProgress = GetDlgItem(ghProgDialog, IDC_PROGRESS1);
  2964. }
  2965. ////////////////////////////////////////////////////////////////////////////////////
  2966. //
  2967. // CheckLanguageGroupInstalled
  2968. // Check if the Language groups for specified languages is installed correctly.
  2969. //
  2970. // Parameters:
  2971. // [IN] lpLanguages The double-null-terminated string which contains the hex LCID
  2972. // strings to be checked.
  2973. // Return:
  2974. // TURE if all the required language packs are installed in the system. Otherwise, FALSE is
  2975. // returned.
  2976. //
  2977. // CheckLanguageGroupInstalled
  2978. // Check if the Language groups for specified languages is installed correctly.
  2979. //
  2980. // Parameters:
  2981. // [IN] lpLanguages The double-null-terminated string which contains the hex LCID
  2982. // strings to be checked.
  2983. // Return:
  2984. // TURE if all the required language packs are installed in the system. Otherwise, FALSE is
  2985. // returned.
  2986. //
  2987. // Remarks:
  2988. // 01-18-2001 YSLin Created.
  2989. ////////////////////////////////////////////////////////////////////////////////////
  2990. BOOL CheckLanguageGroupInstalled(LPTSTR lpLanguages)
  2991. {
  2992. LANGID langID;
  2993. LGRPID lgrpID;
  2994. if (!lpLanguages)
  2995. {
  2996. return FALSE;
  2997. }
  2998. while (*lpLanguages != TEXT('\0'))
  2999. {
  3000. langID = (LANGID)TransNum(lpLanguages);
  3001. lgrpID = GetLanguageGroup(langID);
  3002. if (!gpfnIsValidLanguageGroup(lgrpID, LGRPID_INSTALLED))
  3003. {
  3004. return (FALSE);
  3005. }
  3006. // Go to the null character.
  3007. lpLanguages = _tcschr(lpLanguages, TEXT('\0'));
  3008. // Skip to next char after the null character.
  3009. lpLanguages++;
  3010. }
  3011. return (TRUE);
  3012. }
  3013. ////////////////////////////////////////////////////////////////////////////////////
  3014. //
  3015. // DoSetup
  3016. //
  3017. // Parameters:
  3018. // hwnd The hwnd of the MUISetup main dialog. Pass null if the muisetup is run from command line.
  3019. // UnistallLangCount The number of languages to be uninstalled.
  3020. // lpUninstall The double-null-terminated string which contains the hex LCID strings for the
  3021. // languages to be uninstalled.
  3022. // installLangGroup
  3023. // InstallLangCount The number of languages to be installed.
  3024. // lpInstall The double-null-terminated string which contains the hex LCID strings for the
  3025. // languages to be installed.
  3026. // lpDefaultUILang The language to be set as system default UI language. Pass NULL if the system default
  3027. // UI language is not changed.
  3028. // fAllowReboot The flag to indicate if this function should check if reboot is necessary.
  3029. // bInteractive TRUE if run in interactive mode, or FALSE if run in silent mode.
  3030. // bDisplayUI TRUE if UI is desired, FALSE if UI is to be suppressed
  3031. //
  3032. //
  3033. // Return:
  3034. // TRUE if installation is successful. Otherwise FALSE.
  3035. //
  3036. // Notes:
  3037. // This functions serves as the entry point of the real installation process, shared by both the GUI setup
  3038. // and the command line mode setup.
  3039. //
  3040. // There are several steps in doing MUI setup.
  3041. // 1. Uninstall the selected MUI languages.
  3042. // 2. Install the necessary language packs according to the selected MUI languges(if any).
  3043. // 3. Install the selected MUI languages.
  3044. // 4. Change the default UI language.
  3045. // 5. Check for rebooting.
  3046. //
  3047. // Please note that to save space, we do the uninstallation first, then do the installation.
  3048. ////////////////////////////////////////////////////////////////////////////////////
  3049. BOOL DoSetup(
  3050. HWND hwnd,
  3051. int UninstallLangCount, LPTSTR lpUninstall,
  3052. INSTALL_LANG_GROUP installLangGroup,
  3053. int InstallLangCount, LPTSTR lpInstall,
  3054. LPTSTR lpDefaultUILang,
  3055. BOOL fAllowReboot, BOOL bInteractive, BOOL bDisplayUI)
  3056. {
  3057. LONG_PTR lppArgs[3];
  3058. TCHAR lpMessage[BUFFER_SIZE];
  3059. TCHAR lpForceUILang[BUFFER_SIZE];
  3060. TCHAR lpTemp[BUFFER_SIZE];
  3061. TCHAR lpTemp2[BUFFER_SIZE];
  3062. LANGID defaultLangID;
  3063. HCURSOR hCurSave;
  3064. int NotDeleted;
  3065. BOOL bDefaultUIChanged = FALSE;
  3066. BOOL bErrorOccurred = FALSE;
  3067. LANGID lidSys = GetSystemDefaultLangID();
  3068. BOOL isReboot;
  3069. ghProgDialog = NULL;
  3070. ghProgress = NULL;
  3071. HRESULT hresult;
  3072. if ( (! lpUninstall) || (!lpInstall) )
  3073. {
  3074. return FALSE;
  3075. }
  3076. hCurSave=SetCursor(LoadCursor(NULL, IDC_WAIT));
  3077. if(UninstallLangCount > 0)
  3078. {
  3079. #ifndef MUI_MAGIC
  3080. if (bDisplayUI)
  3081. {
  3082. CreateProgressDialog(hwnd);
  3083. SendMessage(ghProgress, PBM_SETRANGE, (WPARAM)(int)0, (LPARAM)MAKELPARAM(0, UninstallLangCount * INSTALLED_FILES));
  3084. SendMessage(ghProgress, PBM_SETPOS, (WPARAM)0, 0);
  3085. SetWindowTitleFromResource(ghProgDialog, IDS_UNINSTALL_TITLE);
  3086. }
  3087. #endif
  3088. //
  3089. // Uninstall MUI languages
  3090. //
  3091. if (!UninstallSelected(lpUninstall, &NotDeleted))
  3092. {
  3093. #ifndef MUI_MAGIC
  3094. if (bDisplayUI)
  3095. {
  3096. DestroyWindow(ghProgDialog);
  3097. ghProgDialog = NULL;
  3098. }
  3099. #endif
  3100. // prompt a messagebox about uninstallation error
  3101. if (bDisplayUI)
  3102. {
  3103. DoMessageBoxFromResource(hwnd, ghInstance, IDS_ERROR_UNINSTALL_LANG, lppArgs, IDS_MAIN_TITLE, MB_OK);
  3104. SetCursor(hCurSave);
  3105. }
  3106. bErrorOccurred = TRUE;
  3107. goto PostSetup;
  3108. }
  3109. #ifndef MUI_MAGIC
  3110. if (bDisplayUI)
  3111. {
  3112. SendMessage(ghProgress, PBM_SETPOS, (WPARAM)(UninstallLangCount * INSTALLED_FILES), 0);
  3113. }
  3114. #endif
  3115. }
  3116. if(InstallLangCount > 0)
  3117. {
  3118. #ifndef MUI_MAGIC
  3119. //
  3120. // Install Language Group First
  3121. //
  3122. if (!InstallLanguageGroups(&installLangGroup))
  3123. {
  3124. if (bDisplayUI)
  3125. {
  3126. DestroyWindow(ghProgDialog);
  3127. ghProgDialog = NULL;
  3128. }
  3129. if (bDisplayUI)
  3130. {
  3131. SetCursor(hCurSave);
  3132. }
  3133. bErrorOccurred = TRUE;
  3134. goto PostSetup;
  3135. }
  3136. //
  3137. // Check if language group in installLangGroup is installed correctly
  3138. //
  3139. if (!CheckLanguageGroupInstalled(lpInstall))
  3140. {
  3141. LogFormattedMessage(NULL, IDS_LG_NOT_INSTALL_L, NULL);
  3142. if (bDisplayUI || bInteractive)
  3143. {
  3144. DoMessageBox(NULL, IDS_LG_NOT_INSTALL, IDS_MAIN_TITLE, MB_OK);
  3145. }
  3146. return (FALSE);
  3147. }
  3148. #endif
  3149. //
  3150. // Make sure MUI CD-ROM is put in the CD-ROM drive.
  3151. //
  3152. if(CheckVolumeChange())
  3153. {
  3154. if (bDisplayUI)
  3155. {
  3156. #ifndef MUI_MAGIC
  3157. DestroyWindow(ghProgDialog);
  3158. ghProgDialog = NULL;
  3159. #endif
  3160. SetCursor(hCurSave);
  3161. }
  3162. return (FALSE);
  3163. }
  3164. #ifndef MUI_MAGIC
  3165. if (bDisplayUI)
  3166. {
  3167. if (ghProgDialog == NULL)
  3168. {
  3169. CreateProgressDialog(hwnd);
  3170. }
  3171. SendMessage(ghProgress, PBM_SETRANGE, (WPARAM)(int)0, (LPARAM)MAKELPARAM(0, InstallLangCount * INSTALLED_FILES));
  3172. SendMessage(ghProgress, PBM_SETPOS, (WPARAM)0, 0);
  3173. SetWindowTitleFromResource(ghProgDialog, IDS_INSTALL_TITLE);
  3174. }
  3175. #endif
  3176. if (!InstallSelected(lpInstall,&installLangGroup.bFontLinkRegistryTouched))
  3177. {
  3178. if (bDisplayUI)
  3179. {
  3180. DoMessageBoxFromResource(hwnd, ghInstance, IDS_ERROR_INSTALL_LANG, lppArgs, IDS_MAIN_TITLE, MB_OK);
  3181. #ifndef MUI_MAGIC
  3182. DestroyWindow(ghProgDialog);
  3183. ghProgDialog = NULL;
  3184. #endif
  3185. SetCursor(hCurSave);
  3186. }
  3187. bErrorOccurred = TRUE;
  3188. goto PostSetup;
  3189. }
  3190. #ifndef MUI_MAGIC
  3191. if (bDisplayUI)
  3192. {
  3193. SendMessage(ghProgress, PBM_SETPOS, (WPARAM)((UninstallLangCount+InstallLangCount) * INSTALLED_FILES), 0);
  3194. }
  3195. #endif
  3196. }
  3197. if (bDisplayUI)
  3198. {
  3199. #ifndef MUI_MAGIC
  3200. DestroyWindow(ghProgDialog);
  3201. ghProgDialog = NULL;
  3202. #endif
  3203. SetCursor(hCurSave);
  3204. }
  3205. if (UninstallLangCount + InstallLangCount > 0)
  3206. {
  3207. //
  3208. // "Installation Complete"
  3209. // "Installation was completed successfully."
  3210. //
  3211. if (bInteractive || bDisplayUI)
  3212. {
  3213. DoMessageBox(hwnd, InstallLangCount > 0 ? IDS_MUISETUP_SUCCESS : IDS_MUISETUP_UNINSTALL_SUCCESS, IDS_MAIN_TITLE, MB_OK | MB_DEFBUTTON1);
  3214. }
  3215. }
  3216. //
  3217. // In command line mode, if "/D" is specified, we should ask user to confirm making default UI language change.
  3218. // In command line mode, if "/D" is NOT specified, we should NOT try to change the default UI language.
  3219. // In command line mode, if "/D" & "/S" are specified, we will NOT ask user's confirmation.
  3220. // In GUI mode, we always ask user to confirm making default UI language change.
  3221. //
  3222. //
  3223. // Special case:
  3224. // If the current default UI language is going to be removed and user doesn't choose a new UI language,
  3225. // we will force to set the default UI language to be the system UI language.
  3226. //
  3227. if(g_bRemoveDefaultUI)
  3228. {
  3229. //
  3230. // Delete shell cache for the current user
  3231. //
  3232. SHDeleteKey(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\ShellNoRoam\\MUICache"));
  3233. }
  3234. if (lpDefaultUILang)
  3235. {
  3236. defaultLangID = (LANGID)_tcstol(lpDefaultUILang, NULL, 16);
  3237. if (IsInstalled(lpDefaultUILang))
  3238. {
  3239. //
  3240. // If the assigned UI language ID (defaultLangID) is already the default user UI language,
  3241. // we don't do anything. Otherwise, change the default user UI langauge.
  3242. //
  3243. if (defaultLangID != GetDotDefaultUILanguage())
  3244. {
  3245. if (SetUserDefaultLanguage(defaultLangID, FALSE, TRUE))
  3246. {
  3247. bDefaultUIChanged = TRUE;
  3248. } else
  3249. {
  3250. if (bInteractive)
  3251. {
  3252. DoMessageBox(hwnd, IDS_DEFAULT_USER_ERROR, IDS_MAIN_TITLE, (MB_OK | MB_ICONEXCLAMATION));
  3253. }
  3254. }
  3255. } else
  3256. {
  3257. // Do nothing here. I leave this here intentionally to highlight that
  3258. // we don't do antying if the specified defaultLangID is already the default UI language.
  3259. }
  3260. //
  3261. // Make sure registry is set correctly
  3262. //
  3263. if(BST_CHECKED == IsDlgButtonChecked( hwnd, IDC_CHECK_LOCALE ))
  3264. {
  3265. SetMUIRegSetting(MUI_MATCH_LOCALE, TRUE);
  3266. SetMUIRegSetting(MUI_MATCH_UIFONT, BST_CHECKED == IsDlgButtonChecked(hwnd, IDC_CHECK_UIFONT));
  3267. }
  3268. else
  3269. {
  3270. SetMUIRegSetting(MUI_MATCH_LOCALE, FALSE);
  3271. SetMUIRegSetting(MUI_MATCH_UIFONT, FALSE);
  3272. }
  3273. //
  3274. // Notify intl.cpl if we have system locale or UI font setting change
  3275. //
  3276. if ((BST_CHECKED == IsDlgButtonChecked( hwnd, IDC_CHECK_LOCALE) || g_bCmdMatchLocale || g_bLipLanguages) &&
  3277. defaultLangID != lidSys)
  3278. {
  3279. TCHAR szCommands[BUFFER_SIZE];
  3280. //
  3281. // Invoke intl.cpl to change system locale to match the default UI language
  3282. //
  3283. //*STRSAFE* wsprintf(szCommands, TEXT("SystemLocale = \"%x\""), defaultLangID);
  3284. hresult = StringCchPrintf(szCommands , ARRAYSIZE(szCommands), TEXT("SystemLocale = \"%x\""), defaultLangID);
  3285. if (!SUCCEEDED(hresult))
  3286. {
  3287. return FALSE;
  3288. }
  3289. //
  3290. // Always reboot if system locale is changed
  3291. //
  3292. if (RunRegionalOptionsApplet(szCommands))
  3293. {
  3294. g_bReboot = TRUE;
  3295. }
  3296. }
  3297. else if (g_bMatchUIFont != (BST_CHECKED == IsDlgButtonChecked(hwnd, IDC_CHECK_UIFONT)) ||
  3298. g_bCmdMatchUIFont)
  3299. {
  3300. TCHAR szCommands[BUFFER_SIZE];
  3301. //
  3302. // We're not really changing system locale here, it is used to invoke intl.cpl for font setting changes
  3303. //
  3304. //*STRSAFE* wsprintf(szCommands, TEXT("SystemLocale = \"%x\""), lidSys);
  3305. hresult = StringCchPrintf(szCommands , ARRAYSIZE(szCommands), TEXT("SystemLocale = \"%x\""), lidSys);
  3306. if (!SUCCEEDED(hresult))
  3307. {
  3308. return FALSE;
  3309. }
  3310. if (RunRegionalOptionsApplet(szCommands) && defaultLangID == MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT))
  3311. {
  3312. // Don't prompt for reboot, intl.cpl will cause muisetup to lose focus if we do so.
  3313. // Need to fix this in XP server release
  3314. g_bReboot = TRUE;
  3315. }
  3316. }
  3317. //
  3318. // Change user locale for LIP languages
  3319. //
  3320. if (g_bLipLanguages)
  3321. {
  3322. TCHAR szCommands[BUFFER_SIZE];
  3323. //
  3324. // Invoke intl.cpl to change system locale to match the default UI language
  3325. //
  3326. //*STRSAFE* wsprintf(szCommands, TEXT("UserLocale = \"%x\"\x0d\x0aUserLocale_DefaultUser = \"%x\"\x0d\x0aMUILanguage=\"%x\""), defaultLangID, defaultLangID, defaultLangID);
  3327. hresult = StringCchPrintf(szCommands , ARRAYSIZE(szCommands), TEXT("UserLocale = \"%x\"\x0d\x0aUserLocale_DefaultUser = \"%x\"\x0d\x0aMUILanguage=\"%x\""), defaultLangID, defaultLangID, defaultLangID);
  3328. if (!SUCCEEDED(hresult))
  3329. {
  3330. return FALSE;
  3331. }
  3332. if (RunRegionalOptionsApplet(szCommands) && defaultLangID == MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT))
  3333. {
  3334. // Don't prompt for reboot, intl.cpl will cause muisetup to loose focus if we do so.
  3335. // Need to fix this in XP server release
  3336. g_bReboot = TRUE;
  3337. }
  3338. }
  3339. } else
  3340. {
  3341. //
  3342. // "ERROR: %1 was not set as the default. It is not installed.\r\nNo default UI language change."
  3343. //
  3344. lppArgs[0] = (LONG_PTR)lpDefaultUILang;
  3345. LogFormattedMessage(NULL, IDS_DEFAULT_L, lppArgs);
  3346. return (FALSE);
  3347. }
  3348. }
  3349. PostSetup:
  3350. //
  3351. // Check for reboot, and if we are allowed to do so.
  3352. //
  3353. if (fAllowReboot)
  3354. {
  3355. //
  3356. // Check if we need to reboot?
  3357. //
  3358. if (!CheckForReboot(hwnd, &installLangGroup))
  3359. {
  3360. //
  3361. // Check if we recommend a reboot?
  3362. //
  3363. if ((bInteractive || bDisplayUI) && bDefaultUIChanged)
  3364. {
  3365. GetLanguageDisplayName(defaultLangID, lpTemp, ARRAYSIZE(lpTemp)-1);
  3366. lppArgs[0] = (LONG_PTR)lpTemp;
  3367. if (lidSys == defaultLangID)
  3368. {
  3369. if (bDisplayUI)
  3370. {
  3371. isReboot = (DoMessageBoxFromResource(hwnd, ghInstance, IDS_CHANGE_UI_NEED_RBOOT, lppArgs, IDS_MAIN_TITLE, MB_YESNO) == IDYES);
  3372. }
  3373. else
  3374. {
  3375. isReboot = TRUE;
  3376. }
  3377. } else
  3378. {
  3379. GetLanguageDisplayName(lidSys, lpTemp2, ARRAYSIZE(lpTemp2)-1);
  3380. lppArgs[1] = (LONG_PTR)lpTemp2;
  3381. if (bDisplayUI)
  3382. {
  3383. isReboot = (DoMessageBoxFromResource(hwnd, ghInstance, IDS_CHANGE_UI_NEED_RBOOT_SYSTEM_LCID, lppArgs, IDS_MAIN_TITLE, MB_YESNO) == IDYES);
  3384. }
  3385. else
  3386. {
  3387. isReboot = TRUE;
  3388. }
  3389. }
  3390. if (isReboot)
  3391. {
  3392. Muisetup_RebootTheSystem();
  3393. }
  3394. }
  3395. }
  3396. }
  3397. if (bErrorOccurred)
  3398. return (FALSE);
  3399. return (TRUE);
  3400. }
  3401. int ParseUninstallLangs(LPTSTR p, LPTSTR lpUninstall, int cchUninstall, INT64* pulUISize, INT64* pulLPKSize, INT64* pulSpaceNeed, BOOL* pbLogError)
  3402. {
  3403. int iCopied;
  3404. TCHAR lpBuffer[BUFFER_SIZE];
  3405. LONG_PTR lppArgs[2];
  3406. int cLanguagesToUnInstall = 0;
  3407. LANGID LgId;
  3408. LPTSTR pU = lpUninstall;
  3409. if ((!p) || (! lpUninstall) || (!pulUISize) || (!pulLPKSize) || (!pulSpaceNeed) || (!pbLogError))
  3410. {
  3411. return FALSE;
  3412. }
  3413. p = SkipBlanks(p);
  3414. if (!p)
  3415. return FALSE;
  3416. iCopied = 0;
  3417. while((*p != TEXT('-')) && (*p != TEXT('/')) && (*p != TEXT('\0')))
  3418. {
  3419. iCopied = CopyArgument(lpBuffer, p);
  3420. if(!HaveFiles(lpBuffer, FALSE))
  3421. {
  3422. //
  3423. // "LOG: %1 was not installed. It is not listed in MUI.INF."
  3424. //
  3425. lppArgs[0] = (LONG_PTR)lpBuffer;
  3426. LogFormattedMessage(NULL, IDS_NOT_LISTED_L, lppArgs);
  3427. *pbLogError = TRUE;
  3428. } else if (!IsInstalled(lpBuffer))
  3429. {
  3430. //
  3431. // "LOG: %1 was not uninstalled, because it is not installed. "
  3432. //
  3433. lppArgs[0] = (LONG_PTR)lpBuffer;
  3434. LogFormattedMessage(NULL, IDS_IS_NOT_INSTALLED_L, lppArgs);
  3435. *pbLogError = TRUE;
  3436. } else if (!IsInInstallList(lpUninstall,lpBuffer))
  3437. {
  3438. iCopied = CopyArgument(pU, p);
  3439. //
  3440. // Check if we are going to remove the current UI language
  3441. //
  3442. LgId = (LANGID)_tcstol(pU, NULL, 16);
  3443. if (LgId == GetDotDefaultUILanguage())
  3444. {
  3445. g_bRemoveDefaultUI = TRUE;
  3446. }
  3447. if (LgId == GetUserDefaultUILanguage())
  3448. {
  3449. g_bRemoveUserUI = TRUE;
  3450. }
  3451. //
  3452. // Calculate the space required
  3453. //
  3454. GetUIFileSize_commandline(lpBuffer, pulUISize,pulLPKSize);
  3455. *pulSpaceNeed-=*pulUISize;
  3456. pU += iCopied;
  3457. pU++; //skip over NULL
  3458. cLanguagesToUnInstall++;
  3459. }
  3460. p += iCopied;
  3461. p = SkipBlanks(p);
  3462. }
  3463. //
  3464. // Uninstall all MUI languages if there is no language argument after /U
  3465. //
  3466. if (iCopied == 0)
  3467. {
  3468. cLanguagesToUnInstall = GetInstalledMUILanguages(lpUninstall, cchUninstall);
  3469. if (cLanguagesToUnInstall == 0)
  3470. {
  3471. LogFormattedMessage(ghInstance, IDS_NO_MUI_LANG, NULL);
  3472. *pbLogError = TRUE;
  3473. }
  3474. else
  3475. {
  3476. if (0x0409 != GetDotDefaultUILanguage())
  3477. {
  3478. g_bRemoveDefaultUI = TRUE;
  3479. }
  3480. if (0x0409 != GetUserDefaultUILanguage())
  3481. {
  3482. g_bRemoveUserUI = TRUE;
  3483. }
  3484. }
  3485. }
  3486. else
  3487. {
  3488. *pU=TEXT('\0');
  3489. }
  3490. return (cLanguagesToUnInstall);
  3491. }
  3492. ////////////////////////////////////////////////////////////////////////////
  3493. //
  3494. // GetCDNameFromLang
  3495. //
  3496. // Given a langange ID (in hex string), return the CD name where the language
  3497. // installation folder exist.
  3498. // This can also be used to check if the language is supported MUI language.
  3499. //
  3500. // Parameters:
  3501. // [IN] lpLangName the language to be installed in hex string.
  3502. // [OUT] lpCDName the number of the CD (e.g. "2" or "3").
  3503. // [IN] nCDNameSize the size of lpCDName, in TCHAR.
  3504. //
  3505. // Return Values:
  3506. // TRUE if lpLangName is a supported MUI language. lpCDName will contain
  3507. // the name of the CD.
  3508. // FALSE if the language ID is not a supported langauge. lpCDNAme will be
  3509. // empty string.
  3510. //
  3511. // Remarks:
  3512. //
  3513. // 01-01-2001 YSLin Created.
  3514. //
  3515. ////////////////////////////////////////////////////////////////////////////
  3516. BOOL GetCDNameFromLang(LPTSTR lpLangName, LPTSTR lpCDName, int nCDNameSize)
  3517. {
  3518. if (!GetPrivateProfileString(
  3519. MUI_CDLAYOUT_SECTION,
  3520. lpLangName,
  3521. TEXT(""),
  3522. lpCDName,
  3523. nCDNameSize,
  3524. g_szMUIInfoFilePath))
  3525. {
  3526. return (FALSE);
  3527. }
  3528. return (TRUE);
  3529. }
  3530. ////////////////////////////////////////////////////////////////////////////////////
  3531. //
  3532. // ParseCommandLine
  3533. //
  3534. // Runs installation functions with command line specifications
  3535. //
  3536. ////////////////////////////////////////////////////////////////////////////////////
  3537. BOOL ParseCommandLine(LPTSTR lpCommandLine)
  3538. {
  3539. BOOL bSetDefaultUI=FALSE; // Specify if the /D switch is used to change the user default UI language.
  3540. BOOL bInstall=FALSE;
  3541. BOOL bLogError=FALSE;
  3542. BOOL bFELangpackAdded=FALSE;
  3543. BOOL bResult = FALSE;
  3544. DWORD dwDisp;
  3545. LANGID LgId;
  3546. TCHAR lpBuffer[BUFFER_SIZE];
  3547. TCHAR lpDefault[BUFFER_SIZE];
  3548. TCHAR lpDefaultText[MAX_PATH];
  3549. TCHAR lpInstall[BUFFER_SIZE];
  3550. TCHAR lpMessage[BUFFER_SIZE];
  3551. TCHAR lpUninstall[BUFFER_SIZE];
  3552. TCHAR lpSystemDefault[BUFFER_SIZE];
  3553. TCHAR lpTemp[BUFFER_SIZE];
  3554. TCHAR szWinDir[MAX_PATH];
  3555. INSTALL_LANG_GROUP installLangGroup;
  3556. LONG_PTR lppArgs[4];
  3557. PTCHAR pI;
  3558. PTCHAR pD;
  3559. PTCHAR p;
  3560. BOOL fAllowReboot = TRUE;
  3561. int cLanguagesToInstall = 0L;
  3562. int cLanguagesToUnInstall = 0L;
  3563. int iCopied;
  3564. TCHAR chOpt;
  3565. INT64 ulSpaceNeed=0,ulSpaceAvailable=0,ulUISize=0,ulLPKSize=0;
  3566. ULONG ulParam[2];
  3567. ULARGE_INTEGER ulgiFreeBytesAvailableToCaller;
  3568. ULARGE_INTEGER ulgiTotalNumberOfBytes;
  3569. BOOL bHasLangArgs = FALSE;
  3570. BOOL bHelpDisplayed=FALSE;
  3571. //PREFAST TCHAR lpCDName[BUFFER_SIZE];
  3572. LPTSTR lpCDName=NULL;
  3573. if (!lpCommandLine)
  3574. {
  3575. return FALSE;
  3576. }
  3577. //
  3578. // Allocate space for Heap variable
  3579. //
  3580. lpCDName = new TCHAR[BUFFER_SIZE];
  3581. if (! lpCDName)
  3582. {
  3583. goto exit_ParseCommandLine;
  3584. }
  3585. //
  3586. // Initialize Lang-Groups to install
  3587. //
  3588. installLangGroup.iCount = 0L;
  3589. installLangGroup.NotDeleted = 0L;
  3590. installLangGroup.bFontLinkRegistryTouched = FALSE;
  3591. lpInstall[0] = TEXT('\0');
  3592. lpUninstall[0] = TEXT('\0');
  3593. lpDefault[0] = TEXT('\0');
  3594. pI = lpInstall;
  3595. pD = lpDefault;
  3596. p = lpCommandLine;
  3597. CharLower(p);
  3598. while(p=NextCommandTag(p))
  3599. {
  3600. chOpt = *p++;
  3601. switch (chOpt)
  3602. {
  3603. case '?':
  3604. case 'h':
  3605. if (!bHelpDisplayed)
  3606. {
  3607. DisplayHelpWindow();
  3608. bHelpDisplayed=TRUE;
  3609. }
  3610. // if we encountered a help switch, after displaying the window, we just exit
  3611. bResult = TRUE;
  3612. goto exit_ParseCommandLine;
  3613. // p = SkipBlanks(p);
  3614. break;
  3615. case 'i':
  3616. if (!FileExists(g_szMUIInfoFilePath))
  3617. {
  3618. //
  3619. // "The file MUI.INF cannot be found."
  3620. //
  3621. DoMessageBox(NULL, IDS_NO_MUI_FILE, IDS_MAIN_TITLE, MB_OK | MB_DEFBUTTON1);
  3622. break;
  3623. }
  3624. //
  3625. // MUI version needs to match OS version
  3626. //
  3627. if (!checkversion(TRUE))
  3628. {
  3629. DoMessageBox(NULL, IDS_WRONG_VERSION, IDS_MAIN_TITLE, MB_OK | MB_DEFBUTTON1);
  3630. break;
  3631. }
  3632. p = SkipBlanks(p);
  3633. while ((*p != TEXT('-')) && (*p != TEXT('/')) && (*p != TEXT('\0')))
  3634. {
  3635. bHasLangArgs = TRUE;
  3636. iCopied=CopyArgument(lpBuffer, p);
  3637. if (!IsInstalled(lpBuffer) &&
  3638. CheckLanguageIsQualified(lpBuffer) &&
  3639. HaveFiles(lpBuffer) && (!IsInInstallList(lpInstall,lpBuffer)) )
  3640. {
  3641. //
  3642. // Calculate the space required
  3643. //
  3644. GetUIFileSize_commandline(lpBuffer, &ulUISize,&ulLPKSize);
  3645. ulSpaceNeed+=ulUISize;
  3646. if(CheckLangGroupCommandLine(&installLangGroup, lpBuffer))
  3647. {
  3648. if (IS_FE_LANGPACK(_tcstol(lpBuffer, NULL, 16)))
  3649. {
  3650. if (!bFELangpackAdded)
  3651. {
  3652. ulSpaceNeed+=ulLPKSize;
  3653. bFELangpackAdded = TRUE;
  3654. }
  3655. }else
  3656. {
  3657. ulSpaceNeed+=ulLPKSize;
  3658. }
  3659. }
  3660. AddExtraLangGroupsFromINF(lpBuffer, &installLangGroup);
  3661. iCopied=CopyArgument(pI, p);
  3662. pI += iCopied;
  3663. pI++; //skip over NULL
  3664. bInstall = TRUE;
  3665. cLanguagesToInstall++;
  3666. }
  3667. else
  3668. {
  3669. lppArgs[0]=(LONG_PTR)lpBuffer;
  3670. if(IsInstalled(lpBuffer)|| IsInInstallList(lpInstall,lpBuffer))
  3671. {
  3672. // "LOG: %1 was not installed, because it is already installed. "
  3673. LogFormattedMessage(ghInstance, IDS_IS_INSTALLED_L, lppArgs);
  3674. }
  3675. if(!HaveFiles(lpBuffer))
  3676. {
  3677. if (!GetCDNameFromLang(lpBuffer, lpCDName, ARRAYSIZE(lpCDName)))
  3678. {
  3679. // lpBuffer is not a supported MUI language.
  3680. // "LOG: %1 was not installed, because it is not listed in MUI.INF. Please check if it is a valid UI language ID."
  3681. LogFormattedMessage(ghInstance, IDS_NOT_LISTED_L, lppArgs);
  3682. } else
  3683. {
  3684. // lpBuffer is a supported MUI language, ask user to change CD and
  3685. // rerun setup.
  3686. LoadString(ghInstance, IDS_CHANGE_CDROM, lpTemp, ARRAYSIZE(lpTemp)-1);
  3687. lppArgs[1] = (LONG_PTR)lpTemp;
  3688. lppArgs[2] = (LONG_PTR)lpCDName;
  3689. // "ERROR: %1 was not installed, because it is located in %2 %3. Please insert that CD and rerun MUISetup."
  3690. LogFormattedMessage(ghInstance, IDS_LANG_IN_ANOTHER_CD_L, lppArgs);
  3691. }
  3692. }
  3693. if(!CheckLanguageIsQualified(lpBuffer))
  3694. {
  3695. // "LOG: %1 was not installed, because it cannot be installed on this platform\n"
  3696. LogFormattedMessage(ghInstance, IDS_NOT_QUALIFIED_L, lppArgs);
  3697. }
  3698. bLogError = TRUE;
  3699. }
  3700. p += iCopied;
  3701. p = SkipBlanks(p);
  3702. }
  3703. if (!bHasLangArgs)
  3704. {
  3705. lppArgs[0] = (LONG_PTR)TEXT("/I");
  3706. FormatStringFromResource(lpMessage, sizeof(lpMessage)/sizeof(TCHAR), ghInstance, IDS_ERROR_NO_LANG_ARG, lppArgs);
  3707. LogMessage(lpMessage);
  3708. bLogError = TRUE;
  3709. }
  3710. *pI = TEXT('\0');
  3711. break;
  3712. case 'u':
  3713. if (!checkversion(FALSE))
  3714. {
  3715. DoMessageBox(NULL, IDS_WRONG_VERSION, IDS_MAIN_TITLE, MB_OK | MB_DEFBUTTON1);
  3716. break;
  3717. }
  3718. cLanguagesToUnInstall = ParseUninstallLangs(p, lpUninstall, ARRAYSIZE(lpUninstall), &ulUISize, &ulLPKSize, &ulSpaceNeed, &bLogError);
  3719. break;
  3720. case 'd':
  3721. if (!checkversion(FALSE))
  3722. {
  3723. DoMessageBox(NULL, IDS_WRONG_VERSION, IDS_MAIN_TITLE, MB_OK | MB_DEFBUTTON1);
  3724. break;
  3725. }
  3726. bSetDefaultUI = TRUE;
  3727. p = SkipBlanks(p);
  3728. if (CopyArgument(lpDefault, p) == 0)
  3729. {
  3730. lppArgs[0] = (LONG_PTR)TEXT("/D");
  3731. FormatStringFromResource(lpMessage, sizeof(lpMessage)/sizeof(TCHAR),
  3732. ghInstance, IDS_ERROR_NO_LANG_ARG, lppArgs);
  3733. LogMessage(lpMessage);
  3734. bLogError = FALSE;
  3735. }
  3736. break;
  3737. case 'r':
  3738. fAllowReboot = FALSE;
  3739. break;
  3740. case 's' :
  3741. g_bSilent = TRUE;
  3742. // check if desktop is interactive or not, if not, hide all UI
  3743. if (FALSE == IsWindowVisible(GetDesktopWindow()))
  3744. {
  3745. g_bNoUI = TRUE;
  3746. }
  3747. break;
  3748. case 't' :
  3749. // use this switch to totally suppress all the possible UI that can be popped up by muisetup and the processes it
  3750. // launches.
  3751. g_bSilent = TRUE;
  3752. g_bNoUI = TRUE;
  3753. break;
  3754. case 'l':
  3755. g_bCmdMatchLocale = TRUE;
  3756. break;
  3757. case 'f':
  3758. g_bCmdMatchUIFont = TRUE;
  3759. break;
  3760. case 'o':
  3761. g_bRunFromOSSetup = TRUE;
  3762. break;
  3763. default:
  3764. // if we encounter an invalid switch at any stage, treat it the same as help and quit afterwards
  3765. if (!bHelpDisplayed)
  3766. {
  3767. DisplayHelpWindow();
  3768. bHelpDisplayed=TRUE;
  3769. }
  3770. // if we encountered a help switch, after displaying the window, we just exit
  3771. bResult = TRUE;
  3772. goto exit_ParseCommandLine;
  3773. break;
  3774. }
  3775. }
  3776. //
  3777. // UI Font depends on system locale
  3778. //
  3779. if (!g_bCmdMatchLocale && g_bCmdMatchUIFont)
  3780. {
  3781. g_bCmdMatchUIFont = FALSE;
  3782. }
  3783. //
  3784. // Check the disk space
  3785. //
  3786. //
  3787. pfnGetWindowsDir( szWinDir, MAX_PATH);
  3788. szWinDir[3]=TEXT('\0');
  3789. if (GetDiskFreeSpaceEx(szWinDir,
  3790. &ulgiFreeBytesAvailableToCaller,
  3791. &ulgiTotalNumberOfBytes,
  3792. NULL))
  3793. {
  3794. ulSpaceAvailable= ulgiFreeBytesAvailableToCaller.QuadPart;
  3795. if ( ulSpaceAvailable < ulSpaceNeed )
  3796. {
  3797. ulParam[0] = (ULONG) (ulSpaceNeed/1024);
  3798. ulParam[1] = (ULONG) (ulSpaceAvailable/1024);
  3799. LoadString(ghInstance, IDS_DISKSPACE_NOTENOUGH, lpMessage, ARRAYSIZE(lpMessage)-1);
  3800. LoadString(ghInstance, IDS_ERROR_DISKSPACE, lpTemp, ARRAYSIZE(lpTemp)-1);
  3801. FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  3802. lpMessage,
  3803. 0,
  3804. 0,
  3805. lpMessage,
  3806. ARRAYSIZE(lpMessage)-1,
  3807. (va_list *) ulParam);
  3808. LogMessage(lpMessage);
  3809. bLogError = TRUE;
  3810. MESSAGEBOX(NULL, lpMessage, lpTemp, MB_OK | MB_DEFBUTTON1 | MB_ICONWARNING);
  3811. bInstall = FALSE;
  3812. cLanguagesToUnInstall = 0;
  3813. }
  3814. }
  3815. if (!bLogError)
  3816. {
  3817. //
  3818. // Let's set the default UI language
  3819. //
  3820. if (!DoSetup(
  3821. NULL,
  3822. cLanguagesToUnInstall, lpUninstall,
  3823. installLangGroup,
  3824. cLanguagesToInstall, lpInstall,
  3825. (bSetDefaultUI ? lpDefault : NULL),
  3826. fAllowReboot, !g_bSilent, !g_bNoUI))
  3827. {
  3828. bLogError = TRUE;
  3829. }
  3830. }
  3831. if (bLogError && !g_bSilent && !g_bNoUI)
  3832. {
  3833. //
  3834. // "Installation Error"
  3835. // "One or more errors occurred during installation.
  3836. // Please see %1\muisetup.log for more information."
  3837. //
  3838. lppArgs[0] = (LONG_PTR)szWindowsDir;
  3839. DoMessageBoxFromResource(NULL, ghInstance, IDS_ERROR, lppArgs, IDS_ERROR_T, MB_OK | MB_DEFBUTTON1 | MB_ICONWARNING);
  3840. }
  3841. bResult = TRUE;
  3842. exit_ParseCommandLine:
  3843. if (lpCDName)
  3844. {
  3845. delete [] lpCDName;
  3846. }
  3847. return bResult;
  3848. }
  3849. ////////////////////////////////////////////////////////////////////////////////////
  3850. //
  3851. // DisplayHelpWindow
  3852. //
  3853. // Displays help window for command line version
  3854. //
  3855. ////////////////////////////////////////////////////////////////////////////////////
  3856. void DisplayHelpWindow()
  3857. {
  3858. STARTUPINFO si;
  3859. PROCESS_INFORMATION pi = {0};
  3860. TCHAR Appname[MAX_PATH+MAX_PATH+1],szFilePath[MAX_PATH+1];
  3861. HRESULT hresult;
  3862. int nLen;
  3863. szFilePath[0] = UNICODE_NULL;
  3864. if (!pfnGetWindowsDir(szFilePath, MAX_PATH))
  3865. {
  3866. return;
  3867. }
  3868. nLen = lstrlen(szFilePath);
  3869. if (szFilePath[nLen-1] != TEXT('\\'))
  3870. {
  3871. hresult = StringCchCat(szFilePath , ARRAYSIZE(szFilePath), TEXT("\\"));
  3872. if (!SUCCEEDED(hresult))
  3873. {
  3874. return;
  3875. }
  3876. }
  3877. hresult = StringCchCat(szFilePath , ARRAYSIZE(szFilePath), WINHELP32PATH);
  3878. if (!SUCCEEDED(hresult))
  3879. {
  3880. return ;
  3881. }
  3882. if (FileExists(g_szMUIHelpFilePath))
  3883. {
  3884. //*STRSAFE* wsprintf(Appname,TEXT("\"%s\" -n%d %s"),szFilePath,IDH_MUISETUP_COMMANDLINE,g_szMUIHelpFilePath);
  3885. hresult = StringCchPrintf(Appname , ARRAYSIZE(Appname), TEXT("\"%s\" -n%d %s"),szFilePath, IDH_MUISETUP_COMMANDLINE,g_szMUIHelpFilePath);
  3886. if (!SUCCEEDED(hresult))
  3887. {
  3888. return;
  3889. }
  3890. memset( &si, 0x00, sizeof(si));
  3891. si.cb = sizeof(STARTUPINFO);
  3892. if (!CreateProcess(NULL,
  3893. Appname,
  3894. NULL,
  3895. NULL,
  3896. FALSE,
  3897. 0L,
  3898. NULL, NULL,
  3899. &si,
  3900. &pi) )
  3901. return;
  3902. WaitForSingleObject(pi.hProcess, INFINITE);
  3903. //
  3904. // Close Handle
  3905. //
  3906. CloseHandle( pi.hProcess );
  3907. CloseHandle( pi.hThread );
  3908. }
  3909. else
  3910. {
  3911. //////////////////////////////////////////////
  3912. // MessageBox should be changed to Dialog
  3913. //////////////////////////////////////////////
  3914. DoMessageBox(NULL, IDS_HELP, IDS_HELP_T, MB_OK | MB_DEFBUTTON1);
  3915. }
  3916. }
  3917. ////////////////////////////////////////////////////////////////////////////////////
  3918. //
  3919. // CopyArgument
  3920. //
  3921. // Copies command line argument pointed to by src to dest
  3922. //
  3923. ////////////////////////////////////////////////////////////////////////////////////
  3924. int CopyArgument(LPTSTR dest, LPTSTR src)
  3925. {
  3926. int i=0;
  3927. if ((!dest) || (!src))
  3928. {
  3929. return i;
  3930. }
  3931. while(*src!=TEXT(' ') && *src!=TEXT('\0'))
  3932. {
  3933. *dest=*src;
  3934. dest++;
  3935. src++;
  3936. i++;
  3937. }
  3938. *dest = TEXT('\0');
  3939. return i;
  3940. }
  3941. ////////////////////////////////////////////////////////////////////////////////////
  3942. //
  3943. // IsInstalled
  3944. //
  3945. // Checks to see if lpArg is a language installed in the registry
  3946. //
  3947. ////////////////////////////////////////////////////////////////////////////////////
  3948. BOOL IsInstalled(LPTSTR lpArg)
  3949. {
  3950. HKEY hKey;
  3951. DWORD dwData;
  3952. DWORD dwIndex;
  3953. DWORD dwValue;
  3954. TCHAR lpData[BUFFER_SIZE];
  3955. TCHAR lpValue[BUFFER_SIZE];
  3956. int rc;
  3957. int iArg;
  3958. if (!lpArg)
  3959. {
  3960. return FALSE;
  3961. }
  3962. hKey=OpenMuiKey(KEY_READ);
  3963. if (hKey == NULL)
  3964. {
  3965. return (FALSE);
  3966. }
  3967. dwIndex=0;
  3968. rc=ERROR_SUCCESS;
  3969. iArg=_tcstol(lpArg, NULL, 16);
  3970. if (iArg == gSystemUILangId)
  3971. {
  3972. RegCloseKey(hKey);
  3973. return (TRUE);
  3974. }
  3975. while(rc==ERROR_SUCCESS)
  3976. {
  3977. dwValue=sizeof(lpValue)/sizeof(TCHAR);
  3978. lpValue[0]=TEXT('\0');
  3979. dwData=sizeof(lpData);
  3980. lpData[0]=TEXT('\0');
  3981. DWORD dwType;
  3982. rc=RegEnumValue(hKey, dwIndex, lpValue, &dwValue, 0, &dwType, (LPBYTE)lpData, &dwData);
  3983. if(rc==ERROR_SUCCESS)
  3984. {
  3985. if (dwType != REG_SZ)
  3986. {
  3987. dwIndex++;
  3988. continue;
  3989. }
  3990. if(_tcstol(lpValue, NULL, 16)==iArg)
  3991. {
  3992. RegCloseKey(hKey);
  3993. return TRUE;
  3994. }
  3995. }
  3996. dwIndex++;
  3997. }
  3998. RegCloseKey(hKey);
  3999. return FALSE;
  4000. }
  4001. ////////////////////////////////////////////////////////////////////////////////////
  4002. //
  4003. // GetInstalledMUILanguages
  4004. //
  4005. // Get installed MUI languages, dump it to lpUninstall buffer in a MULTI_SZ format
  4006. //
  4007. ////////////////////////////////////////////////////////////////////////////////////
  4008. DWORD GetInstalledMUILanguages(LPTSTR lpUninstall, int cch)
  4009. {
  4010. HKEY hKey;
  4011. DWORD dwIndex = 0;
  4012. DWORD dwCount = 0;
  4013. DWORD dwValue = cch;
  4014. DWORD dwType = 0;
  4015. if (!lpUninstall)
  4016. {
  4017. return dwCount;
  4018. }
  4019. if (hKey = OpenMuiKey(KEY_READ))
  4020. {
  4021. while(ERROR_NO_MORE_ITEMS != RegEnumValue(hKey, dwIndex++, lpUninstall, &dwValue, 0, &dwType, NULL, NULL) &&
  4022. cch > 0)
  4023. {
  4024. if (dwType != REG_SZ)
  4025. continue;
  4026. if (_tcstol(lpUninstall, NULL, 16) != gSystemUILangId)
  4027. {
  4028. //
  4029. // Count in NULL
  4030. //
  4031. dwValue++;
  4032. lpUninstall += dwValue;
  4033. cch -= dwValue;
  4034. dwCount++;
  4035. }
  4036. dwValue = cch;
  4037. }
  4038. RegCloseKey(hKey);
  4039. *lpUninstall = TEXT('\0');
  4040. }
  4041. return dwCount;
  4042. }
  4043. ////////////////////////////////////////////////////////////////////////////////////
  4044. //
  4045. // HaveFiles
  4046. //
  4047. // Checks that the language in lpBuffer is in MUI.INF
  4048. //
  4049. ////////////////////////////////////////////////////////////////////////////////////
  4050. BOOL HaveFiles(LPTSTR lpBuffer, BOOL bCheckDir)
  4051. {
  4052. LPTSTR lpLanguages = NULL;
  4053. TCHAR lpMessage[BUFFER_SIZE];
  4054. TCHAR tchBuffer[BUFFER_SIZE];
  4055. if (!lpBuffer)
  4056. {
  4057. return FALSE;
  4058. }
  4059. lpLanguages = tchBuffer;
  4060. if (EnumLanguages(lpLanguages, bCheckDir) == 0)
  4061. {
  4062. //
  4063. // "LOG: No languages found in MUI.INF"
  4064. //
  4065. LoadString(ghInstance, IDS_NO_LANG_L, lpMessage, ARRAYSIZE(lpMessage)-1);
  4066. LogMessage(lpMessage);
  4067. return FALSE;
  4068. }
  4069. if(!lpLanguages)
  4070. return FALSE;
  4071. while (*lpLanguages != TEXT('\0'))
  4072. {
  4073. if (_tcscmp(lpBuffer, lpLanguages) == 0)
  4074. {
  4075. return TRUE;
  4076. }
  4077. lpLanguages = _tcschr(lpLanguages, '\0');
  4078. lpLanguages++;
  4079. }
  4080. return FALSE;
  4081. }
  4082. ////////////////////////////////////////////////////////////////////////////////////
  4083. //
  4084. // OpenLogFile
  4085. //
  4086. // Opens the setup log for writing
  4087. //
  4088. ////////////////////////////////////////////////////////////////////////////////////
  4089. HANDLE OpenLogFile()
  4090. {
  4091. DWORD dwSize;
  4092. DWORD dwUnicodeHeader;
  4093. HANDLE hFile;
  4094. SECURITY_ATTRIBUTES SecurityAttributes;
  4095. TCHAR lpPath[BUFFER_SIZE];
  4096. int error;
  4097. HRESULT hresult;
  4098. pfnGetWindowsDir(lpPath, MAX_PATH);
  4099. error=GetLastError();
  4100. //*STRSAFE* _tcscat(lpPath, LOG_FILE);
  4101. hresult = StringCchCat(lpPath , ARRAYSIZE(lpPath), LOG_FILE);
  4102. if (!SUCCEEDED(hresult))
  4103. {
  4104. return NULL;
  4105. }
  4106. SecurityAttributes.nLength=sizeof(SecurityAttributes);
  4107. SecurityAttributes.lpSecurityDescriptor=NULL;
  4108. SecurityAttributes.bInheritHandle=FALSE;
  4109. hFile=CreateFile(
  4110. lpPath,
  4111. GENERIC_WRITE,
  4112. 0,
  4113. &SecurityAttributes,
  4114. OPEN_ALWAYS,
  4115. FILE_ATTRIBUTE_NORMAL,
  4116. NULL);
  4117. #ifdef UNICODE
  4118. //
  4119. // If the file did not already exist, add the unicode header
  4120. //
  4121. if(GetLastError()==0)
  4122. {
  4123. dwUnicodeHeader=0xFEFF;
  4124. WriteFile(hFile, &dwUnicodeHeader, 2, &dwSize, NULL);
  4125. }
  4126. #endif
  4127. error=GetLastError();
  4128. return hFile;
  4129. }
  4130. ////////////////////////////////////////////////////////////////////////////////////
  4131. //
  4132. // LogMessage
  4133. //
  4134. // Writes lpMessage to the setup log
  4135. //
  4136. ////////////////////////////////////////////////////////////////////////////////////
  4137. BOOL LogMessage(LPCTSTR lpMessage)
  4138. {
  4139. DWORD dwBytesWritten;
  4140. HANDLE hFile;
  4141. if (!lpMessage)
  4142. {
  4143. return FALSE;
  4144. }
  4145. hFile=OpenLogFile();
  4146. if(hFile==INVALID_HANDLE_VALUE)
  4147. {
  4148. return FALSE;
  4149. }
  4150. SetFilePointer(hFile, 0, NULL, FILE_END);
  4151. WriteFile(
  4152. hFile,
  4153. lpMessage,
  4154. _tcslen(lpMessage) * sizeof(TCHAR),
  4155. &dwBytesWritten,
  4156. NULL);
  4157. SetFilePointer(hFile, 0, NULL, FILE_END);
  4158. WriteFile(
  4159. hFile,
  4160. TEXT("\r\n"),
  4161. _tcslen(TEXT("\r\n")) * sizeof(TCHAR),
  4162. &dwBytesWritten,
  4163. NULL);
  4164. CloseHandle(hFile);
  4165. return TRUE;
  4166. }
  4167. ////////////////////////////////////////////////////////////////////////////////////
  4168. //
  4169. // LogFormattedMessage
  4170. //
  4171. // Writes a formatted lpMessage to the setup log
  4172. //
  4173. ////////////////////////////////////////////////////////////////////////////////////
  4174. BOOL LogFormattedMessage(HINSTANCE hInstance, int messageID, LONG_PTR* lppArgs)
  4175. {
  4176. TCHAR szBuffer[BUFFER_SIZE];
  4177. LoadString(hInstance, messageID, szBuffer, ARRAYSIZE(szBuffer));
  4178. if (lppArgs == NULL)
  4179. {
  4180. return (LogMessage(szBuffer));
  4181. }
  4182. FormatMessage(
  4183. FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  4184. szBuffer,
  4185. 0,
  4186. 0,
  4187. szBuffer,
  4188. sizeof(szBuffer) / sizeof(TCHAR),
  4189. (va_list *)lppArgs);
  4190. return (LogMessage(szBuffer));
  4191. }
  4192. ////////////////////////////////////////////////////////////////////////////
  4193. //
  4194. // FormatStringFromResource
  4195. //
  4196. // Format a string using the format specified in the resource and the
  4197. // specified arguments.
  4198. //
  4199. // Parameters:
  4200. //
  4201. // Return Values:
  4202. // the formatted string.
  4203. //
  4204. // Remarks:
  4205. //
  4206. // 08-07-2000 YSLin Created.
  4207. //
  4208. ////////////////////////////////////////////////////////////////////////////
  4209. LPTSTR FormatStringFromResource(LPTSTR pszBuffer, UINT bufferSize, HMODULE hInstance, int messageID, LONG_PTR* lppArgs)
  4210. {
  4211. TCHAR szFormatStr[BUFFER_SIZE];
  4212. LoadString(hInstance, messageID, szFormatStr, ARRAYSIZE(szFormatStr)-1);
  4213. if (!lppArgs)
  4214. {
  4215. LogMessage(szFormatStr);
  4216. return NULL;
  4217. }
  4218. FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  4219. szFormatStr,
  4220. 0,
  4221. 0,
  4222. pszBuffer,
  4223. bufferSize ,
  4224. (va_list *)lppArgs);
  4225. return (pszBuffer);
  4226. }
  4227. ////////////////////////////////////////////////////////////////////////////////////
  4228. //
  4229. // BeginLog
  4230. //
  4231. // Writes a header to the setup log
  4232. //
  4233. ////////////////////////////////////////////////////////////////////////////////////
  4234. void BeginLog(void)
  4235. {
  4236. TCHAR lpMessage[BUFFER_SIZE];
  4237. SYSTEMTIME stSysTime;
  4238. HRESULT hresult;
  4239. //
  4240. // "**********************************************************
  4241. // Language Module Installation Log
  4242. // **********************************************************" (LOG)
  4243. //
  4244. LoadString(ghInstance, IDS_LOG_HEAD, lpMessage, ARRAYSIZE(lpMessage)-1);
  4245. LogMessage(lpMessage);
  4246. // Also log the time the mui installation is started.
  4247. GetLocalTime(&stSysTime);
  4248. //*STRSAFE* wsprintf(lpMessage, TEXT("Muisetup.exe started on day %2d/%2d/%4d at time %2d:%2d:%2d"),
  4249. //*STRSAFE* stSysTime.wMonth,
  4250. //*STRSAFE* stSysTime.wDay,
  4251. //*STRSAFE* stSysTime.wYear,
  4252. //*STRSAFE* stSysTime.wHour,
  4253. //*STRSAFE* stSysTime.wMinute,
  4254. //*STRSAFE* stSysTime.wSecond
  4255. //);
  4256. hresult = StringCchPrintf(lpMessage , ARRAYSIZE(lpMessage) , TEXT("Muisetup.exe started on day %2d/%2d/%4d at time %2d:%2d:%2d"),
  4257. stSysTime.wMonth,
  4258. stSysTime.wDay,
  4259. stSysTime.wYear,
  4260. stSysTime.wHour,
  4261. stSysTime.wMinute,
  4262. stSysTime.wSecond
  4263. );
  4264. if (!SUCCEEDED(hresult))
  4265. {
  4266. return;
  4267. }
  4268. LogMessage(lpMessage);
  4269. }
  4270. ////////////////////////////////////////////////////////////////////////////////////
  4271. //
  4272. // GetLanguageGroup
  4273. //
  4274. // Retreive the Language Group of this locale.
  4275. //
  4276. ////////////////////////////////////////////////////////////////////////////////////
  4277. LGRPID GetLanguageGroup(LCID lcid)
  4278. {
  4279. int i;
  4280. gLangGroup = LGRPID_WESTERN_EUROPE;
  4281. gFoundLangGroup = FALSE;
  4282. gLCID = lcid;
  4283. for (i=0 ; i<gNumLanguageGroups; i++)
  4284. {
  4285. // The globals gLangGroup and gFoundLangGroup is used in the callback function
  4286. // EnumLanguageGroupLocalesProc.
  4287. gpfnEnumLanguageGroupLocalesW(EnumLanguageGroupLocalesProc, gLanguageGroups[i], 0L, 0L);
  4288. //
  4289. // If we found it, then break now
  4290. //
  4291. if (gFoundLangGroup)
  4292. break;
  4293. }
  4294. return gLangGroup;
  4295. }
  4296. BOOL EnumLanguageGroupLocalesProc(
  4297. LGRPID langGroupId,
  4298. LCID lcid,
  4299. LPTSTR lpszLocale,
  4300. LONG_PTR lParam)
  4301. {
  4302. if (lcid == gLCID)
  4303. {
  4304. gLangGroup = langGroupId;
  4305. gFoundLangGroup = TRUE;
  4306. // stop iterating
  4307. return FALSE;
  4308. }
  4309. // next iteration
  4310. return TRUE;
  4311. }
  4312. ////////////////////////////////////////////////////////////////////////////////////
  4313. //
  4314. // DetectLanguageGroups
  4315. //
  4316. // Detect language groups installed.
  4317. //
  4318. ////////////////////////////////////////////////////////////////////////////////////
  4319. BOOL DetectLanguageGroups(HWND hwndDlg)
  4320. {
  4321. int i;
  4322. HWND hwndList = GetDlgItem(hwndDlg, IDC_LIST1);
  4323. HWND hwndProgress, hwndStatus,hProgDlg;
  4324. int iCount = ListView_GetItemCount(hwndList);
  4325. LVITEM lvItem;
  4326. PMUILANGINFO pMuiLangInfo;
  4327. TCHAR szBuf[MAX_PATH], szStatus[MAX_PATH];
  4328. PVOID ppArgs[1];
  4329. hProgDlg = CreateDialog(ghInstance,
  4330. MAKEINTRESOURCE(IDD_DIALOG_INSTALL_PROGRESS),
  4331. hwndDlg,
  4332. ProgressDialogFunc);
  4333. hwndProgress = GetDlgItem(hProgDlg, IDC_PROGRESS1);
  4334. hwndStatus = GetDlgItem(hProgDlg, IDC_STATUS);
  4335. //
  4336. // Reflect that we doing something on the UI
  4337. //
  4338. LoadString(ghInstance, IDS_INSTALLLANGGROUP, szBuf, MAX_PATH-1);
  4339. SetWindowText(hProgDlg, szBuf);
  4340. SendMessage(hwndProgress, PBM_SETRANGE, (WPARAM)(int)0, (LPARAM)MAKELPARAM(0, iCount));
  4341. SendMessage(hwndProgress, PBM_SETPOS, (WPARAM)(int)(0), 0);
  4342. SetWindowText(hwndStatus, TEXT(""));
  4343. i = 0;
  4344. while (i < iCount)
  4345. {
  4346. //
  4347. // Check if Language Group is installed
  4348. //
  4349. lvItem.mask = LVIF_PARAM;
  4350. lvItem.iItem = i;
  4351. lvItem.iSubItem = 0;
  4352. lvItem.state = 0;
  4353. lvItem.stateMask = 0;
  4354. lvItem.pszText = 0;
  4355. lvItem.cchTextMax = 0;
  4356. lvItem.iImage = 0;
  4357. lvItem.lParam = 0;
  4358. ListView_GetItem(hwndList, &lvItem);
  4359. pMuiLangInfo = (PMUILANGINFO)lvItem.lParam;
  4360. SendMessage(hwndProgress, PBM_SETPOS, (WPARAM)(int)i+1, 0L);
  4361. LoadString(ghInstance, IDS_CHECK_LANG_GROUP, szStatus, MAX_PATH-1);
  4362. if (pMuiLangInfo->szDisplayName[0] == L'\0')
  4363. {
  4364. GetDisplayName(pMuiLangInfo);
  4365. }
  4366. ppArgs[0] = pMuiLangInfo->szDisplayName;
  4367. FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  4368. szStatus,
  4369. 0,
  4370. 0,
  4371. szStatus,
  4372. MAX_PATH-1,
  4373. (va_list *)ppArgs);
  4374. SetWindowText(hwndStatus, szStatus);
  4375. pMuiLangInfo->lgrpid = GetLanguageGroup(pMuiLangInfo->lcid);
  4376. i++;
  4377. };
  4378. SendMessage(hwndProgress, PBM_SETPOS, (WPARAM)(int)i+1, 0L);
  4379. DestroyWindow(hProgDlg);
  4380. return TRUE;
  4381. }
  4382. ////////////////////////////////////////////////////////////////////////////////////
  4383. //
  4384. // AddExtraLangGroupsFromINF
  4385. //
  4386. // Look at the [LanguagePack] section to see if we need to install extra
  4387. // language packs for the language specified in lpszLcid.
  4388. //
  4389. // This is basically used to support pseudo localized build.
  4390. //
  4391. // Parameter:
  4392. // lpszLcid the LCID of UI language to be installed in string form.
  4393. // pInstallLangGroup points to a strcutre which stores language groups to be installed.
  4394. //
  4395. // Remarks:
  4396. //
  4397. // 10-11-2000 YSLin Created.
  4398. ////////////////////////////////////////////////////////////////////////////////////
  4399. BOOL AddExtraLangGroupsFromINF(LPTSTR lpszLcid, PINSTALL_LANG_GROUP pInstallLangGroup)
  4400. {
  4401. WCHAR szBuffer[BUFFER_SIZE];
  4402. HINF hInf;
  4403. INFCONTEXT InfContext;
  4404. LONG_PTR lppArgs[2];
  4405. int LangGroup;
  4406. int i;
  4407. HRESULT hresult;
  4408. if (!pInstallLangGroup)
  4409. {
  4410. return FALSE;
  4411. }
  4412. hInf = SetupOpenInfFile(g_szMUIInfoFilePath, NULL, INF_STYLE_WIN4, NULL);
  4413. if (hInf == INVALID_HANDLE_VALUE)
  4414. {
  4415. //*STRSAFE* _stprintf(szBuffer, TEXT("%d"), GetLastError());
  4416. hresult = StringCchPrintf(szBuffer , ARRAYSIZE(szBuffer), TEXT("%d"), GetLastError());
  4417. if (!SUCCEEDED(hresult))
  4418. {
  4419. return FALSE;
  4420. }
  4421. lppArgs[0] = (LONG_PTR)szBuffer;
  4422. lppArgs[1] = (LONG_PTR)g_szMUIInfoFilePath;
  4423. LogFormattedMessage(ghInstance, IDS_NO_READ_L, lppArgs);
  4424. return (FALSE);
  4425. }
  4426. if (SetupFindFirstLine(hInf, MUI_LANGPACK_SECTION, lpszLcid, &InfContext))
  4427. {
  4428. i = 1;
  4429. while (SetupGetIntField(&InfContext, i++, &LangGroup))
  4430. {
  4431. AddMUILangGroup(pInstallLangGroup, LangGroup);
  4432. }
  4433. }
  4434. SetupCloseInfFile(hInf);
  4435. return (TRUE);
  4436. }
  4437. ////////////////////////////////////////////////////////////////////////////////////
  4438. //
  4439. // ConvertMUILangToLangGroup
  4440. //
  4441. // Generate Lang-Group IDs for the selected items in the listview,
  4442. // in preparation to pass them to InstallLanguageGroups(...)
  4443. ////////////////////////////////////////////////////////////////////////////////////
  4444. BOOL ConvertMUILangToLangGroup(HWND hwndDlg, PINSTALL_LANG_GROUP pInstallLangGroup)
  4445. {
  4446. int i;
  4447. LVITEM lvItem;
  4448. HWND hwndList = GetDlgItem(hwndDlg, IDC_LIST1);
  4449. int iCount = ListView_GetItemCount(hwndList);
  4450. PMUILANGINFO pMuiLangInfo;
  4451. if (!pInstallLangGroup)
  4452. {
  4453. return FALSE;
  4454. }
  4455. //
  4456. // Initialize to "No lang-groups to install"
  4457. //
  4458. pInstallLangGroup->iCount = 0L;
  4459. i = 0;
  4460. while (i < iCount)
  4461. {
  4462. if (ListView_GetCheckState(hwndList, i))
  4463. {
  4464. //
  4465. // Check if Language Group is installed
  4466. //
  4467. lvItem.mask = LVIF_PARAM;
  4468. lvItem.iItem = i;
  4469. lvItem.iSubItem = 0;
  4470. lvItem.state = 0;
  4471. lvItem.stateMask = 0;
  4472. lvItem.pszText = 0;
  4473. lvItem.cchTextMax = 0;
  4474. lvItem.iImage = 0;
  4475. lvItem.lParam = 0;
  4476. ListView_GetItem(hwndList, &lvItem);
  4477. pMuiLangInfo = (PMUILANGINFO)lvItem.lParam;
  4478. //
  4479. // Make sure there are no redundant elements
  4480. //
  4481. AddMUILangGroup(pInstallLangGroup, pMuiLangInfo->lgrpid);
  4482. //
  4483. // Add extra language groups specified in [LangPack] section of mui.inf
  4484. // This is used to support Pesudo Localized Build.
  4485. //
  4486. AddExtraLangGroupsFromINF(pMuiLangInfo->lpszLcid, pInstallLangGroup);
  4487. }
  4488. i++;
  4489. };
  4490. return TRUE;
  4491. }
  4492. ////////////////////////////////////////////////////////////////////////////////////
  4493. //
  4494. // AddMUILangGroup
  4495. //
  4496. // Add a language a group to INSTALL_LANG_GROUP. Takes care of duplicates.
  4497. ////////////////////////////////////////////////////////////////////////////////////
  4498. BOOL AddMUILangGroup(PINSTALL_LANG_GROUP pInstallLangGroup, LGRPID lgrpid)
  4499. {
  4500. int j = 0L;
  4501. BOOL bFound = FALSE;
  4502. if (!pInstallLangGroup)
  4503. {
  4504. return FALSE;
  4505. }
  4506. //
  4507. // Check if it is installed by default
  4508. //
  4509. if (gpfnIsValidLanguageGroup(lgrpid, LGRPID_INSTALLED))
  4510. {
  4511. return FALSE;
  4512. }
  4513. while (j < pInstallLangGroup->iCount)
  4514. {
  4515. if (pInstallLangGroup->lgrpid[j] == lgrpid)
  4516. {
  4517. bFound = TRUE;
  4518. }
  4519. j++;
  4520. }
  4521. if (!bFound)
  4522. {
  4523. pInstallLangGroup->lgrpid[j] = lgrpid;
  4524. pInstallLangGroup->iCount++;
  4525. return TRUE;
  4526. }
  4527. return FALSE;
  4528. }
  4529. ////////////////////////////////////////////////////////////////////////////////////
  4530. //
  4531. // RunRegionalOptionsApplet
  4532. //
  4533. // Run the Regional Option silent mode installation using the specified pCommands.
  4534. //
  4535. // This function will create the "[RegigionalSettings]" string, so there is no need
  4536. // to supply that in pCommands.
  4537. //
  4538. ////////////////////////////////////////////////////////////////////////////////////
  4539. BOOL RunRegionalOptionsApplet(LPTSTR pCommands)
  4540. {
  4541. HANDLE hFile;
  4542. TCHAR szFilePath[MAX_PATH], szCmdLine[MAX_PATH];
  4543. DWORD dwNumWritten = 0L;
  4544. STARTUPINFO si;
  4545. PROCESS_INFORMATION pi = {0};
  4546. int i;
  4547. LONG_PTR lppArgs[3];
  4548. HRESULT hresult;
  4549. TCHAR szRunDllPath[MAX_PATH];
  4550. TCHAR szSection[MAX_PATH] = TEXT("[RegionalSettings]\r\n");
  4551. if (!pCommands)
  4552. {
  4553. return FALSE;
  4554. }
  4555. //
  4556. // prepare the file for un-attended mode setup
  4557. //
  4558. szFilePath[0] = UNICODE_NULL;
  4559. if (!pfnGetWindowsDir(szFilePath, MAX_PATH-1))
  4560. {
  4561. return FALSE;
  4562. }
  4563. i = lstrlen(szFilePath);
  4564. if (szFilePath[i-1] != TEXT('\\'))
  4565. {
  4566. //*STRSAFE* lstrcat(szFilePath, TEXT("\\"));
  4567. hresult = StringCchCat(szFilePath , ARRAYSIZE(szFilePath), TEXT("\\"));
  4568. if (!SUCCEEDED(hresult))
  4569. {
  4570. return FALSE;
  4571. }
  4572. }
  4573. hresult = StringCchCopy(szRunDllPath , ARRAYSIZE(szRunDllPath), szFilePath);
  4574. if (!SUCCEEDED(hresult))
  4575. {
  4576. return FALSE;
  4577. }
  4578. //*STRSAFE* lstrcat(szFilePath, MUI_LANG_GROUP_FILE);
  4579. hresult = StringCchCat(szFilePath , ARRAYSIZE(szFilePath), MUI_LANG_GROUP_FILE);
  4580. if (!SUCCEEDED(hresult))
  4581. {
  4582. return FALSE;
  4583. }
  4584. hresult = StringCchCat(szRunDllPath , ARRAYSIZE(szRunDllPath), RUNDLLNAME);
  4585. if (!SUCCEEDED(hresult))
  4586. {
  4587. return FALSE;
  4588. }
  4589. hFile = CreateFile(szFilePath,
  4590. GENERIC_WRITE,
  4591. 0L,
  4592. NULL,
  4593. CREATE_ALWAYS,
  4594. FILE_ATTRIBUTE_NORMAL,
  4595. NULL);
  4596. if (INVALID_HANDLE_VALUE == hFile)
  4597. {
  4598. lppArgs[0] = (LONG_PTR)szFilePath;
  4599. LogFormattedMessage(ghInstance, IDS_ERROR_FILE_CREATE, lppArgs);
  4600. return FALSE;
  4601. }
  4602. WriteFile(hFile,
  4603. szSection,
  4604. (lstrlen(szSection) * sizeof(TCHAR)),
  4605. &dwNumWritten,
  4606. NULL);
  4607. if (dwNumWritten != (lstrlen(szSection) * sizeof(TCHAR)))
  4608. {
  4609. lppArgs[0] = (LONG_PTR)szFilePath;
  4610. LogFormattedMessage(ghInstance, IDS_ERROR_FILE_CREATE, lppArgs);
  4611. CloseHandle(hFile);
  4612. return FALSE;
  4613. }
  4614. WriteFile(hFile,
  4615. pCommands,
  4616. (lstrlen(pCommands) * sizeof(TCHAR)),
  4617. &dwNumWritten,
  4618. NULL);
  4619. if (dwNumWritten != (lstrlen(pCommands) * sizeof(TCHAR)))
  4620. {
  4621. #if SAMER_DBG
  4622. OutputDebugString(TEXT("Unable to write to Language Groups to muilang.txt\n"));
  4623. #endif
  4624. CloseHandle(hFile);
  4625. return (FALSE);
  4626. }
  4627. CloseHandle(hFile);
  4628. //
  4629. // Call the control panel regional-options applet, and wait for it to complete
  4630. //
  4631. //*STRSAFE* lstrcpy(szCmdLine, TEXT("rundll32 shell32,Control_RunDLL intl.cpl,, /f:\""));
  4632. hresult=StringCchPrintf(szCmdLine,ARRAYSIZE(szCmdLine),TEXT("\"%s\" shell32,Control_RunDLL intl.cpl,, /f:\""),szRunDllPath);
  4633. if (!SUCCEEDED(hresult))
  4634. {
  4635. DeleteFile(szFilePath);
  4636. return FALSE;
  4637. }
  4638. //*STRSAFE* lstrcat(szCmdLine, szFilePath);
  4639. hresult = StringCchCat(szCmdLine , ARRAYSIZE(szCmdLine), szFilePath);
  4640. if (!SUCCEEDED(hresult))
  4641. {
  4642. DeleteFile(szFilePath);
  4643. return FALSE;
  4644. }
  4645. // only pop up progress bar UI if we are showing UI "/g" param for intl.cpl dictates this
  4646. // also add a /D so that intl.cpl will not prompt for a source dialog if no UI is to be shown
  4647. if (!g_bNoUI)
  4648. {
  4649. //*STRSAFE* lstrcat(szCmdLine, TEXT("\"/g "f));
  4650. hresult = StringCchCat(szCmdLine , ARRAYSIZE(szCmdLine), TEXT("\" /g"));
  4651. if (!SUCCEEDED(hresult))
  4652. {
  4653. DeleteFile(szFilePath);
  4654. return FALSE;
  4655. }
  4656. }
  4657. else
  4658. {
  4659. #ifdef MUI_MAGIC
  4660. //*STRSAFE* lstrcat(szCmdLine, TEXT("\" /D"));
  4661. hresult = StringCchCat(szCmdLine , ARRAYSIZE(szCmdLine), TEXT("\" /D "));
  4662. // hresult = StringCchCat(szCmdLine , ARRAYSIZE(szCmdLine), TEXT("\" "));
  4663. if (!SUCCEEDED(hresult))
  4664. {
  4665. DeleteFile(szFilePath);
  4666. return FALSE;
  4667. }
  4668. #else
  4669. //*STRSAFE* lstrcat(szCmdLine, TEXT("\" /D"));
  4670. hresult = StringCchCat(szCmdLine , ARRAYSIZE(szCmdLine), TEXT("\" "));
  4671. // hresult = StringCchCat(szCmdLine , ARRAYSIZE(szCmdLine), TEXT("\" "));
  4672. if (!SUCCEEDED(hresult))
  4673. {
  4674. DeleteFile(szFilePath);
  4675. return FALSE;
  4676. }
  4677. #endif
  4678. }
  4679. // intl.cpl matches the UI font if /t is specified on the command line
  4680. if (g_bCmdMatchUIFont)
  4681. {
  4682. //*STRSAFE* lstrcat(szCmdLine, TEXT("/t "));
  4683. hresult = StringCchCat(szCmdLine , ARRAYSIZE(szCmdLine), TEXT("/t "));
  4684. if (!SUCCEEDED(hresult))
  4685. {
  4686. DeleteFile(szFilePath);
  4687. return FALSE;
  4688. }
  4689. }
  4690. memset( &si, 0x00, sizeof(si));
  4691. si.cb = sizeof(STARTUPINFO);
  4692. if (!CreateProcess(NULL,
  4693. szCmdLine,
  4694. NULL,
  4695. NULL,
  4696. FALSE,
  4697. 0L,
  4698. NULL,
  4699. NULL,
  4700. &si,
  4701. &pi))
  4702. {
  4703. lppArgs[0] = (LONG_PTR)szCmdLine;
  4704. LogFormattedMessage(ghInstance, IDS_ERROR_LAUNCH_INTLCPL, lppArgs);
  4705. DeleteFile(szFilePath);
  4706. return FALSE;
  4707. }
  4708. //
  4709. // Wait forever till intl.cpl terminates.
  4710. //
  4711. WaitForSingleObject(pi.hProcess, INFINITE);
  4712. //
  4713. // Close Handle
  4714. //
  4715. CloseHandle( pi.hProcess );
  4716. CloseHandle( pi.hThread );
  4717. //
  4718. // Delete the File
  4719. //
  4720. DeleteFile(szFilePath);
  4721. return (TRUE);
  4722. }
  4723. ////////////////////////////////////////////////////////////////////////////////////
  4724. //
  4725. // InstallLanguageGroups
  4726. //
  4727. // Checks whether a language group is needed to be installed or not. If
  4728. // any lang-group needs to be installed, then the routine will invoke
  4729. // the Regional-Options applet in unattended mode setup.
  4730. //
  4731. // Return:
  4732. // TURE if the operation succeeds. Otherwise FALSE.
  4733. //
  4734. ////////////////////////////////////////////////////////////////////////////////////
  4735. BOOL InstallLanguageGroups(PINSTALL_LANG_GROUP pInstallLangGroup)
  4736. {
  4737. TCHAR pCommands[MAX_PATH];
  4738. int i, iCount = pInstallLangGroup->iCount;
  4739. BOOL bFirstTime=FALSE;
  4740. HRESULT hresult;
  4741. if (!pInstallLangGroup)
  4742. {
  4743. return FALSE;
  4744. }
  4745. //
  4746. // If nothing to do, then just return
  4747. //
  4748. if (0L == iCount)
  4749. {
  4750. return TRUE;
  4751. }
  4752. i = 0;
  4753. while (i < iCount)
  4754. {
  4755. if (!gpfnIsValidLanguageGroup(pInstallLangGroup->lgrpid[i], LGRPID_INSTALLED))
  4756. {
  4757. if (!bFirstTime)
  4758. {
  4759. bFirstTime = TRUE;
  4760. //*STRSAFE* wsprintf(pCommands, TEXT("LanguageGroup = %d\0"), pInstallLangGroup->lgrpid[i]);
  4761. hresult = StringCchPrintf(pCommands , ARRAYSIZE(pCommands), TEXT("LanguageGroup = %d\0"), pInstallLangGroup->lgrpid[i]);
  4762. if (!SUCCEEDED(hresult))
  4763. {
  4764. return FALSE;
  4765. }
  4766. }
  4767. else
  4768. {
  4769. //*STRSAFE* wsprintf(&pCommands[lstrlen(pCommands)], TEXT(",%d\0"), pInstallLangGroup->lgrpid[i]);
  4770. hresult = StringCchPrintf(&pCommands[lstrlen(pCommands)] , ARRAYSIZE(pCommands) -lstrlen(pCommands) , TEXT(",%d\0"), pInstallLangGroup->lgrpid[i]);
  4771. if (!SUCCEEDED(hresult))
  4772. {
  4773. return FALSE;
  4774. }
  4775. }
  4776. }
  4777. i++;
  4778. };
  4779. if (!bFirstTime)
  4780. {
  4781. //
  4782. // There is no language group to be added.
  4783. return (FALSE);
  4784. }
  4785. return (RunRegionalOptionsApplet(pCommands));
  4786. }
  4787. ////////////////////////////////////////////////////////////////////////////
  4788. //
  4789. // Muisetup_RebootTheSystem
  4790. //
  4791. // This routine enables all privileges in the token, calls ExitWindowsEx
  4792. // to reboot the system, and then resets all of the privileges to their
  4793. // old state.
  4794. //
  4795. ////////////////////////////////////////////////////////////////////////////
  4796. void Muisetup_RebootTheSystem(void)
  4797. {
  4798. HANDLE Token = NULL;
  4799. ULONG ReturnLength, Index;
  4800. PTOKEN_PRIVILEGES NewState = NULL;
  4801. PTOKEN_PRIVILEGES OldState = NULL;
  4802. BOOL Result;
  4803. Result = OpenProcessToken( GetCurrentProcess(),
  4804. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  4805. &Token );
  4806. if (Result)
  4807. {
  4808. ReturnLength = 4096;
  4809. NewState = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, ReturnLength);
  4810. OldState = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, ReturnLength);
  4811. Result = (BOOL)((NewState != NULL) && (OldState != NULL));
  4812. if (Result)
  4813. {
  4814. Result = GetTokenInformation( Token, // TokenHandle
  4815. TokenPrivileges, // TokenInformationClass
  4816. NewState, // TokenInformation
  4817. ReturnLength, // TokenInformationLength
  4818. &ReturnLength ); // ReturnLength
  4819. if (Result)
  4820. {
  4821. //
  4822. // Set the state settings so that all privileges are enabled...
  4823. //
  4824. if (NewState->PrivilegeCount > 0)
  4825. {
  4826. for (Index = 0; Index < NewState->PrivilegeCount; Index++)
  4827. {
  4828. NewState->Privileges[Index].Attributes = SE_PRIVILEGE_ENABLED;
  4829. }
  4830. }
  4831. Result = AdjustTokenPrivileges( Token, // TokenHandle
  4832. FALSE, // DisableAllPrivileges
  4833. NewState, // NewState
  4834. ReturnLength, // BufferLength
  4835. OldState, // PreviousState
  4836. &ReturnLength ); // ReturnLength
  4837. if (Result)
  4838. {
  4839. ExitWindowsEx(EWX_REBOOT, SHTDN_REASON_FLAG_PLANNED | SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_RECONFIG);
  4840. AdjustTokenPrivileges( Token,
  4841. FALSE,
  4842. OldState,
  4843. 0,
  4844. NULL,
  4845. NULL );
  4846. }
  4847. }
  4848. }
  4849. }
  4850. if (NewState != NULL)
  4851. {
  4852. LocalFree(NewState);
  4853. }
  4854. if (OldState != NULL)
  4855. {
  4856. LocalFree(OldState);
  4857. }
  4858. if (Token != NULL)
  4859. {
  4860. CloseHandle(Token);
  4861. }
  4862. }
  4863. ////////////////////////////////////////////////////////////////////////////
  4864. //
  4865. // CheckForReboot
  4866. //
  4867. // Check if we need to reboot the system, if a lang group is installed
  4868. //
  4869. // Return:
  4870. // TRUE if we need user to reboot, otherwise FALSE.
  4871. //
  4872. ////////////////////////////////////////////////////////////////////////////
  4873. BOOL CheckForReboot(HWND hwnd, PINSTALL_LANG_GROUP pInstallLangGroup)
  4874. {
  4875. int nIDS,nMask=MB_YESNO | MB_ICONQUESTION;
  4876. if (!pInstallLangGroup)
  4877. {
  4878. return FALSE;
  4879. }
  4880. if (pInstallLangGroup->iCount || pInstallLangGroup->bFontLinkRegistryTouched || pInstallLangGroup->NotDeleted
  4881. || g_bRemoveDefaultUI || g_bRemoveUserUI || g_bReboot)
  4882. {
  4883. if (g_bRemoveUserUI)
  4884. {
  4885. nIDS=IDS_MUST_REBOOT_STRING1;
  4886. nMask=MB_YESNO | MB_ICONWARNING;
  4887. }
  4888. else if (g_bRemoveDefaultUI)
  4889. {
  4890. nMask=MB_YESNO | MB_ICONWARNING;
  4891. nIDS=IDS_MUST_REBOOT_STRING2;
  4892. }
  4893. else
  4894. {
  4895. nIDS=IDS_REBOOT_STRING;
  4896. }
  4897. SetForegroundWindow(hwnd); // muisetup lost focus when it show reboot dialog so we force it as foreground window.
  4898. if (DoMessageBox(hwnd, nIDS, IDS_MAIN_TITLE, nMask) == IDYES)
  4899. {
  4900. Muisetup_RebootTheSystem();
  4901. }
  4902. return (TRUE);
  4903. }
  4904. return (FALSE);
  4905. }
  4906. ////////////////////////////////////////////////////////////////////////////
  4907. //
  4908. // Following code are stolen from intl.cpl
  4909. //
  4910. // We want to enumulate all installed UI languages
  4911. //
  4912. ////////////////////////////////////////////////////////////////////////////
  4913. DWORD_PTR TransNum(
  4914. LPTSTR lpsz)
  4915. {
  4916. DWORD dw = 0L;
  4917. TCHAR c;
  4918. if (!lpsz)
  4919. {
  4920. return dw;
  4921. }
  4922. while (*lpsz)
  4923. {
  4924. c = *lpsz++;
  4925. if (c >= TEXT('A') && c <= TEXT('F'))
  4926. {
  4927. c -= TEXT('A') - 0xa;
  4928. }
  4929. else if (c >= TEXT('0') && c <= TEXT('9'))
  4930. {
  4931. c -= TEXT('0');
  4932. }
  4933. else if (c >= TEXT('a') && c <= TEXT('f'))
  4934. {
  4935. c -= TEXT('a') - 0xa;
  4936. }
  4937. else
  4938. {
  4939. break;
  4940. }
  4941. dw *= 0x10;
  4942. dw += c;
  4943. }
  4944. return (dw);
  4945. }
  4946. BOOL MUIGetAllInstalledUILanguages()
  4947. {
  4948. pfnEnumUILanguages fnEnumUILanguages;
  4949. BOOL result = TRUE;
  4950. HINSTANCE hKernel32;
  4951. //
  4952. // Enumerate the installed UI languages.
  4953. //
  4954. g_UILanguageGroup.iCount = 0L;
  4955. hKernel32 = LoadLibrary(TEXT("kernel32.dll"));
  4956. fnEnumUILanguages = (pfnEnumUILanguages)GetProcAddress(hKernel32, "EnumUILanguagesW");
  4957. if (fnEnumUILanguages == NULL)
  4958. {
  4959. result = FALSE;
  4960. } else
  4961. {
  4962. fnEnumUILanguages(Region_EnumUILanguagesProc, 0, (LONG_PTR)&g_UILanguageGroup);
  4963. }
  4964. FreeLibrary(hKernel32);
  4965. return (result);
  4966. }
  4967. BOOL CALLBACK Region_EnumUILanguagesProc(
  4968. LPWSTR pwszUILanguage,
  4969. LONG_PTR lParam)
  4970. {
  4971. int Ctr = 0;
  4972. LGRPID lgrp;
  4973. PUILANGUAGEGROUP pUILangGroup = (PUILANGUAGEGROUP)lParam;
  4974. if ( (!pwszUILanguage) || (!pUILangGroup))
  4975. {
  4976. return FALSE;
  4977. }
  4978. LCID UILanguage = (LCID)TransNum( pwszUILanguage );
  4979. if (UILanguage)
  4980. {
  4981. while (Ctr < pUILangGroup->iCount)
  4982. {
  4983. if (pUILangGroup->lcid[Ctr] == UILanguage)
  4984. {
  4985. break;
  4986. }
  4987. Ctr++;
  4988. }
  4989. //
  4990. // Theoritically, we won't go over 64 language groups!
  4991. //
  4992. if ((Ctr == pUILangGroup->iCount) && (Ctr < MAX_UI_LANG_GROUPS))
  4993. {
  4994. pUILangGroup->lcid[Ctr] = UILanguage;
  4995. pUILangGroup->iCount++;
  4996. }
  4997. }
  4998. return (TRUE);
  4999. }
  5000. BOOL IsSpaceEnough(HWND hwndDlg,INT64 *ulSizeNeed,INT64 *ulSizeAvailable)
  5001. {
  5002. HWND hList;
  5003. LGRPID lgrpid[MAX_MUI_LANGUAGES];
  5004. LPTSTR lpszLcid;
  5005. int iIndex;
  5006. int i = 0;
  5007. int iCount=0,iArrayIndex=0;
  5008. PMUILANGINFO pMuiLangInfo;
  5009. BOOL bChked,bResult=TRUE;
  5010. INT64 ulTotalBytesRequired=0,ulSpaceAvailable;
  5011. TCHAR szWinDir[MAX_PATH];
  5012. BOOL bFELangpackAdded = FALSE;
  5013. ULARGE_INTEGER ulgiFreeBytesAvailableToCaller;
  5014. ULARGE_INTEGER ulgiTotalNumberOfBytes;
  5015. if ((!ulSizeNeed) || (!ulSizeAvailable))
  5016. {
  5017. return FALSE;
  5018. }
  5019. *ulSizeNeed=0;
  5020. *ulSizeAvailable=0;
  5021. hList=GetDlgItem(hwndDlg, IDC_LIST1);
  5022. iIndex = ListView_GetItemCount(hList);
  5023. while(i<iIndex)
  5024. {
  5025. bChked=ListView_GetCheckState(hList, i);
  5026. GetMuiLangInfoFromListView(hList, i, &pMuiLangInfo);
  5027. lpszLcid = pMuiLangInfo->lpszLcid;
  5028. //
  5029. // Install required
  5030. //
  5031. if (bChked && !IsInstalled(lpszLcid) && HaveFiles(lpszLcid))
  5032. {
  5033. if (!gpfnIsValidLanguageGroup(pMuiLangInfo->lgrpid, LGRPID_INSTALLED))
  5034. {
  5035. for(iArrayIndex=0;iArrayIndex < iCount;iArrayIndex++)
  5036. {
  5037. if (lgrpid[iArrayIndex]==pMuiLangInfo->lgrpid)
  5038. break;
  5039. }
  5040. if(iArrayIndex == iCount)
  5041. {
  5042. if (IS_FE_LANGPACK(pMuiLangInfo->lcid))
  5043. {
  5044. if (!bFELangpackAdded)
  5045. {
  5046. ulTotalBytesRequired+=pMuiLangInfo->ulLPKSize;
  5047. bFELangpackAdded = TRUE;
  5048. }
  5049. }
  5050. else
  5051. {
  5052. ulTotalBytesRequired+=pMuiLangInfo->ulLPKSize;
  5053. }
  5054. lgrpid[iCount]= pMuiLangInfo->lgrpid;
  5055. iCount++;
  5056. }
  5057. }
  5058. ulTotalBytesRequired+=pMuiLangInfo->ulUISize;
  5059. }
  5060. // Uninstall required
  5061. if (!bChked && IsInstalled(lpszLcid))
  5062. {
  5063. ulTotalBytesRequired-=pMuiLangInfo->ulUISize;
  5064. }
  5065. i++;
  5066. }
  5067. //
  5068. // Let's check available disk space of system drive
  5069. //
  5070. pfnGetWindowsDir( szWinDir, MAX_PATH);
  5071. szWinDir[3]=TEXT('\0');
  5072. if (GetDiskFreeSpaceEx(szWinDir,
  5073. &ulgiFreeBytesAvailableToCaller,
  5074. &ulgiTotalNumberOfBytes,
  5075. NULL))
  5076. {
  5077. ulSpaceAvailable= ulgiFreeBytesAvailableToCaller.QuadPart;
  5078. if ( ulSpaceAvailable < ulTotalBytesRequired )
  5079. {
  5080. *ulSizeNeed =ulTotalBytesRequired;
  5081. *ulSizeAvailable=ulSpaceAvailable;
  5082. bResult=FALSE;
  5083. }
  5084. }
  5085. return bResult;
  5086. }
  5087. void ExitFromOutOfMemory()
  5088. {
  5089. LONG_PTR lppArgs[1];
  5090. lppArgs[0] = (LONG_PTR)GetLastError();
  5091. DoMessageBox(NULL, IDS_OUT_OF_MEMORY, IDS_MAIN_TITLE, MB_ICONEXCLAMATION | MB_OK);
  5092. LogFormattedMessage(ghInstance, IDS_OUT_OF_MEMORY_L, lppArgs);
  5093. ExitProcess(1);
  5094. }
  5095. ////////////////////////////////////////////////////////////////////////////
  5096. //
  5097. // Call the kernel to notify it that a new language is being added or
  5098. // removed
  5099. //
  5100. ////////////////////////////////////////////////////////////////////////////
  5101. void NotifyKernel(
  5102. LPTSTR LangList,
  5103. ULONG Flags
  5104. )
  5105. {
  5106. HANDLE Handle;
  5107. WMILANGUAGECHANGE LanguageChange;
  5108. ULONG ReturnSize;
  5109. BOOL IoctlSuccess;
  5110. HRESULT hresult;
  5111. if ((LangList != NULL) &&
  5112. (*LangList != 0))
  5113. {
  5114. Handle = CreateFile(WMIAdminDeviceName,
  5115. GENERIC_READ | GENERIC_WRITE,
  5116. 0,
  5117. NULL,
  5118. OPEN_EXISTING,
  5119. FILE_ATTRIBUTE_NORMAL,
  5120. NULL);
  5121. if (Handle != INVALID_HANDLE_VALUE)
  5122. {
  5123. while (*LangList != 0)
  5124. {
  5125. memset(&LanguageChange, 0, sizeof(LanguageChange));
  5126. //*STRSAFE* _tcscpy(LanguageChange.Language, LangList);
  5127. hresult = StringCchCopy(LanguageChange.Language , MAX_LANGUAGE_SIZE, LangList);
  5128. if (!SUCCEEDED(hresult))
  5129. {
  5130. CloseHandle(Handle);
  5131. return ;
  5132. }
  5133. LanguageChange.Flags = Flags;
  5134. IoctlSuccess = DeviceIoControl(Handle,
  5135. IOCTL_WMI_NOTIFY_LANGUAGE_CHANGE,
  5136. &LanguageChange,
  5137. sizeof(LanguageChange),
  5138. NULL,
  5139. 0,
  5140. &ReturnSize,
  5141. NULL);
  5142. #if ALANWAR_DBG
  5143. {
  5144. WCHAR Buf[256];
  5145. //*STRSAFE* wsprintf(Buf, L"MUISetup: Notify Lang change -> %d for %ws\n", GetLastError(), LangList);
  5146. hresult = StringCchPrintfW(Buf , ARRAYSIZE(Buf), L"MUISetup: Notify Lang change -> %d for %ws\n", GetLastError(), LangList);
  5147. if (!SUCCEEDED(hresult))
  5148. {
  5149. CloseHandle(Handle);
  5150. return ;
  5151. }
  5152. OutputDebugStringW(Buf);
  5153. }
  5154. #endif
  5155. while (*LangList++ != 0) ;
  5156. }
  5157. CloseHandle(Handle);
  5158. }
  5159. }
  5160. }
  5161. //
  5162. // Query MUI registry setting
  5163. //
  5164. BOOL CheckMUIRegSetting(DWORD dwFlag)
  5165. {
  5166. BOOL bRet = FALSE;
  5167. HKEY hKey;
  5168. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_MUI_SETTING, 0, KEY_READ, &hKey))
  5169. {
  5170. DWORD dwValue;
  5171. DWORD dwSize = sizeof(dwValue);
  5172. DWORD dwType;
  5173. if (ERROR_SUCCESS ==
  5174. RegQueryValueEx(hKey,
  5175. (dwFlag & MUI_MATCH_UIFONT)? REGSTR_VALUE_MATCH_UIFONT : REGSTR_VALUE_MATCH_LOCALE,
  5176. 0, &dwType, (LPBYTE)&dwValue, &dwSize))
  5177. {
  5178. bRet = (BOOL) dwValue;
  5179. }
  5180. RegCloseKey(hKey);
  5181. }
  5182. return bRet;
  5183. }
  5184. //
  5185. // Set MUI registry setting
  5186. //
  5187. BOOL SetMUIRegSetting(DWORD dwFlag, BOOL bEnable)
  5188. {
  5189. BOOL bRet = FALSE;
  5190. HKEY hKey;
  5191. if (ERROR_SUCCESS ==
  5192. RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_MUI_SETTING, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,NULL, &hKey, NULL))
  5193. {
  5194. DWORD dwValue = (DWORD) bEnable;
  5195. if (ERROR_SUCCESS ==
  5196. RegSetValueEx(hKey,
  5197. (dwFlag & MUI_MATCH_UIFONT)? REGSTR_VALUE_MATCH_UIFONT : REGSTR_VALUE_MATCH_LOCALE,
  5198. 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD)))
  5199. {
  5200. bRet = TRUE;
  5201. }
  5202. RegCloseKey(hKey);
  5203. }
  5204. return bRet;
  5205. }
  5206. //
  5207. // Delete MUI registry setting
  5208. //
  5209. BOOL DeleteMUIRegSetting()
  5210. {
  5211. BOOL bRet = TRUE;
  5212. HKEY hKey;
  5213. TCHAR tcMessage[BUFFER_SIZE];
  5214. if (ERROR_SUCCESS ==RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_MUI_SETTING, 0, KEY_ALL_ACCESS, &hKey))
  5215. {
  5216. DWORD dwValue;
  5217. DWORD dwSize = sizeof(dwValue);
  5218. DWORD dwType;
  5219. if (ERROR_SUCCESS ==
  5220. RegQueryValueEx(hKey,
  5221. REGSTR_VALUE_MATCH_UIFONT,
  5222. 0, &dwType, (LPBYTE)&dwValue, &dwSize))
  5223. {
  5224. if (RegDeleteValue(hKey, REGSTR_VALUE_MATCH_UIFONT) != ERROR_SUCCESS)
  5225. {
  5226. wnsprintf(tcMessage, ARRAYSIZE(tcMessage) ,TEXT("MuiSetup: DeleteMUIRegSetting: WARNING - Failed to delete regkey HKLM\\%s regvalue %s"), REGSTR_MUI_SETTING,REGSTR_VALUE_MATCH_UIFONT);
  5227. LogMessage(tcMessage);
  5228. bRet = FALSE;
  5229. }
  5230. }
  5231. dwSize = sizeof(dwValue);
  5232. if (ERROR_SUCCESS ==
  5233. RegQueryValueEx(hKey,
  5234. REGSTR_VALUE_MATCH_LOCALE,
  5235. 0, &dwType, (LPBYTE)&dwValue, &dwSize))
  5236. {
  5237. if (RegDeleteValue(hKey, REGSTR_VALUE_MATCH_LOCALE) != ERROR_SUCCESS)
  5238. {
  5239. wnsprintf(tcMessage, ARRAYSIZE(tcMessage) ,TEXT("MuiSetup: DeleteMUIRegSetting: WARNING - Failed to delete regkey HKLM\\%s regvalue %s"), REGSTR_MUI_SETTING,REGSTR_VALUE_MATCH_LOCALE);
  5240. LogMessage(tcMessage);
  5241. bRet = FALSE;
  5242. }
  5243. }
  5244. RegCloseKey(hKey);
  5245. }
  5246. return bRet;
  5247. }
  5248. ////////////////////////////////////////////////////////////////////////////
  5249. //
  5250. // DeleteRegTree
  5251. //
  5252. // This deletes all subkeys under a specific key.
  5253. //
  5254. // Note: The code makes no attempt to check or recover from partial
  5255. // deletions.
  5256. //
  5257. // A registry key that is opened by an application can be deleted
  5258. // without error by another application. This is by design.
  5259. //
  5260. ////////////////////////////////////////////////////////////////////////////
  5261. DWORD DeleteRegTree(
  5262. HKEY hStartKey,
  5263. LPTSTR pKeyName)
  5264. {
  5265. DWORD dwRtn, dwSubKeyLength;
  5266. LPTSTR pSubKey = NULL;
  5267. TCHAR szSubKey[REGSTR_MAX_VALUE_LENGTH]; // (256) this should be dynamic.
  5268. HKEY hKey;
  5269. //
  5270. // Do not allow NULL or empty key name.
  5271. //
  5272. if (pKeyName && lstrlen(pKeyName))
  5273. {
  5274. if ((dwRtn = RegOpenKeyEx( hStartKey,
  5275. pKeyName,
  5276. 0,
  5277. KEY_ENUMERATE_SUB_KEYS | DELETE,
  5278. &hKey )) == ERROR_SUCCESS)
  5279. {
  5280. while (dwRtn == ERROR_SUCCESS)
  5281. {
  5282. dwSubKeyLength = REGSTR_MAX_VALUE_LENGTH;
  5283. dwRtn = RegEnumKeyEx( hKey,
  5284. 0, // always index zero
  5285. szSubKey,
  5286. &dwSubKeyLength,
  5287. NULL,
  5288. NULL,
  5289. NULL,
  5290. NULL );
  5291. if (dwRtn == ERROR_NO_MORE_ITEMS)
  5292. {
  5293. dwRtn = RegDeleteKey(hStartKey, pKeyName);
  5294. break;
  5295. }
  5296. else if (dwRtn == ERROR_SUCCESS)
  5297. {
  5298. dwRtn = DeleteRegTree(hKey, szSubKey);
  5299. }
  5300. }
  5301. RegCloseKey(hKey);
  5302. }
  5303. else if (dwRtn == ERROR_FILE_NOT_FOUND)
  5304. {
  5305. dwRtn = ERROR_SUCCESS;
  5306. }
  5307. }
  5308. else
  5309. {
  5310. dwRtn = ERROR_BADKEY;
  5311. }
  5312. return (dwRtn);
  5313. }
  5314. ////////////////////////////////////////////////////////////////////////////////////
  5315. //
  5316. // InstallExternalComponents
  5317. //
  5318. //
  5319. // Return:
  5320. // TURE if the operation succeeds. Otherwise FALSE.
  5321. //
  5322. ////////////////////////////////////////////////////////////////////////////////////
  5323. BOOL InstallExternalComponents(LPTSTR Languages)
  5324. {
  5325. BOOL bRet = TRUE;
  5326. TCHAR lpMessage[BUFFER_SIZE];
  5327. if (! Languages)
  5328. {
  5329. return FALSE;
  5330. }
  5331. //
  5332. // call WBEM API to mofcompile MUI MFL's for each language
  5333. //
  5334. if (!MofCompileLanguages(Languages))
  5335. {
  5336. //
  5337. // LOG: Error mofcompiling
  5338. //
  5339. LoadString(ghInstance, IDS_MOFCOMPILE_L, lpMessage, ARRAYSIZE(lpMessage)-1);
  5340. LogMessage(lpMessage);
  5341. bRet = FALSE;
  5342. }
  5343. if (bRet)
  5344. {
  5345. //
  5346. // Inform kernel that new languages have been added
  5347. //
  5348. NotifyKernel(Languages,
  5349. WMILANGUAGECHANGE_FLAG_ADDED);
  5350. }
  5351. return bRet;
  5352. }
  5353. ////////////////////////////////////////////////////////////////////////////////////
  5354. //
  5355. // UninstallExternalComponents
  5356. //
  5357. ////////////////////////////////////////////////////////////////////////////////////
  5358. VOID UninstallExternalComponents(LPTSTR Languages)
  5359. {
  5360. if (!Languages)
  5361. {
  5362. return ;
  5363. }
  5364. //
  5365. // Inform kernel that new languages have been added
  5366. //
  5367. NotifyKernel(Languages,
  5368. WMILANGUAGECHANGE_FLAG_REMOVED);
  5369. }