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.

4074 lines
135 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include <shlwapi.h>
  5. #include <shlwapip.h> // For SHRegisterValidateTemplate()
  6. #include "muisetup.h"
  7. #include "stdlib.h"
  8. #include "tchar.h"
  9. #include <setupapi.h>
  10. #include <syssetup.h>
  11. #include "lzexpand.h"
  12. #include <sxsapi.h>
  13. #include <Msi.h> // for Msi invocation API
  14. #ifdef _IA64_
  15. #include "msiguids64.h"
  16. #else
  17. #include "msiguids.h"
  18. #endif
  19. #define STRSAFE_LIB
  20. #include <strsafe.h>
  21. #define SHRVT_REGISTER 0x00000001
  22. #define DEFAULT_INSTALL_SECTION TEXT("DefaultInstall")
  23. #define DEFAULT_UNINSTALL_SECTION TEXT("DefaultUninstall")
  24. // GLOBAL variables
  25. MUIMSIREGINFO g_MuiMsiRegs[REG_MUI_MSI_COUNT] = {
  26. {HKEY_LOCAL_MACHINE, REGSTR_HKLM_MUI_MSI1, NORMAL_GUID},
  27. {HKEY_LOCAL_MACHINE, REGSTR_HKLM_MUI_MSI2, REVERSED_GUID},
  28. {HKEY_LOCAL_MACHINE, REGSTR_HKLM_MUI_MSI3, REVERSED_GUID},
  29. {HKEY_CLASSES_ROOT, REGSTR_HKR_MUI_MSI4, REVERSED_GUID},
  30. {HKEY_CLASSES_ROOT, REGSTR_HKR_MUI_MSI5, REVERSED_GUID}
  31. };
  32. extern TCHAR DirNames[MFL][MAX_PATH],DirNames_ie[MFL][MAX_PATH];
  33. LPTSTR g_szSpecialFiles[] = {
  34. TEXT("hhctrlui.dll"),
  35. };
  36. extern BOOL g_bReboot;
  37. extern BOOL g_bSilent;
  38. extern BOOL g_bNoUI;
  39. extern BOOL g_bLipLanguages;
  40. extern BOOL g_bLipAllowSwitch;
  41. extern BOOL g_bRunFromOSSetup;
  42. extern TCHAR g_szCDLabel[MAX_PATH];
  43. extern int g_cdnumber;;
  44. void debug(char *printout);
  45. ////////////////////////////////////////////////////////////////////////////
  46. //
  47. // ConstructMSIGUID
  48. //
  49. // This function will reverse the character orders in each section of a
  50. // string guild (separated by the - char) and write the result to the
  51. // output. The output string will also have all the - characters
  52. // removed as well.
  53. //
  54. ////////////////////////////////////////////////////////////////////////////
  55. BOOL ConstructMSIGUID(LPTSTR szGuid, LPTSTR szOutput)
  56. {
  57. BOOL bResult = TRUE;
  58. INT i, j;
  59. INT iSegments1[3] = {8, 4, 4}; // number of char in each segments of a guid string
  60. INT iSegments2[5] = {4, 12}; // number of char in each segments of a guid string
  61. TCHAR *tcDest = szOutput;
  62. TCHAR *tcSource = szGuid+1; // we increment by one to skip the opening '{' char
  63. if ((NULL == szGuid) || (NULL == szOutput))
  64. {
  65. return FALSE;
  66. }
  67. else
  68. {
  69. for (i = 0; i < 3; i++)
  70. {
  71. // copy the size of the segment into the output buffer
  72. _tcsncpy(tcDest, tcSource, iSegments1[i]);
  73. // add a null to the end of the dest
  74. *(tcDest+iSegments1[i]) = NULL;
  75. // reverse the section we just copied into the output buffer
  76. _tcsrev(tcDest);
  77. // skip ahead, for source, we add one more so we don't copy the '-' char
  78. tcDest += iSegments1[i];
  79. tcSource += (iSegments1[i] + 1);
  80. }
  81. for (i = 0; i < 2; i++)
  82. {
  83. j = iSegments2[i];
  84. // here in each segment, we swap every second char in the segment, eg. 1a3f becomes a1f3
  85. while (j > 0)
  86. {
  87. // copy the size of the segment into the output buffer, swapping the source chars
  88. tcDest[0] = tcSource[1];
  89. tcDest[1] = tcSource[0];
  90. tcDest[2] = NULL;
  91. j-=2;
  92. tcDest += 2;
  93. tcSource += 2;
  94. }
  95. // for source, we add one more so we don't copy the '-' char
  96. tcSource++;
  97. }
  98. }
  99. return TRUE;
  100. }
  101. ////////////////////////////////////////////////////////////////////////////
  102. //
  103. // DeleteMSIRegSettings
  104. //
  105. // This function will atempt to manually remove enough MSI registry
  106. // keys from the system so that a specific MUI language is shown as
  107. // not installed on the system.
  108. //
  109. // Note that this is a hack right now as, during OS setup, the windows
  110. // installer service is not available and so we cannot find a way
  111. // to uninstall MUI during that time using the windows installer service.
  112. //
  113. ////////////////////////////////////////////////////////////////////////////
  114. void DeleteMSIRegSettings(LPTSTR Language)
  115. {
  116. TCHAR tcMessage[BUFFER_SIZE];
  117. BOOL bFound = FALSE;
  118. TCHAR szProductCode[GUIDLENGTH]; // stores a GUID in string format
  119. TCHAR szReversed[GUIDLENGTH-4]; // this is essentially the guild string reversed and without the dashes
  120. HKEY hkReg = NULL;
  121. DWORD dwDisp = 0;
  122. int i;
  123. if (NULL == Language)
  124. {
  125. return;
  126. }
  127. // look up the MSI product code for the
  128. bFound = GetMSIProductCode(Language, szProductCode, ARRAYSIZE(szProductCode));
  129. // construct the reversed guid string key
  130. ConstructMSIGUID(szProductCode, szReversed);
  131. if (TRUE == bFound)
  132. {
  133. for (i=0; i<REG_MUI_MSI_COUNT; i++)
  134. {
  135. if (RegOpenKeyEx(g_MuiMsiRegs[i].hkRegRoot,
  136. g_MuiMsiRegs[i].szRegString,
  137. 0,
  138. KEY_ALL_ACCESS,
  139. &hkReg) == ERROR_SUCCESS)
  140. {
  141. if (g_MuiMsiRegs[i].RegType == NORMAL_GUID)
  142. {
  143. DeleteRegTree(hkReg, szProductCode);
  144. }
  145. else
  146. {
  147. DeleteRegTree(hkReg, szReversed);
  148. }
  149. RegCloseKey(hkReg);
  150. }
  151. }
  152. }
  153. else
  154. {
  155. wnsprintf(tcMessage, ARRAYSIZE(tcMessage), TEXT("MuiSetup: DeleteMSIRegSettings: product code for language %s is not found."), Language);
  156. LogMessage(tcMessage);
  157. }
  158. }
  159. ////////////////////////////////////////////////////////////////////////////////////
  160. //
  161. // GetMSIProductCode
  162. //
  163. // This function returns the product code for a specific mui language
  164. // after copying it into the supplied destination buffer.
  165. //
  166. ////////////////////////////////////////////////////////////////////////////////////
  167. BOOL GetMSIProductCode(LPTSTR szLanguage, LPTSTR szProductCode, UINT uiBufSize)
  168. {
  169. HRESULT hresult = S_OK;
  170. int i;
  171. BOOL bResult = FALSE;
  172. TCHAR tcMessage[BUFFER_SIZE];
  173. if ((NULL == szLanguage) || (NULL == szProductCode) || (uiBufSize <= 0))
  174. {
  175. wnsprintf(tcMessage, ARRAYSIZE(tcMessage) ,TEXT("MuiSetup: GetMSIProductCode: WARNING - input parameter invalid."));
  176. LogMessage(tcMessage);
  177. bResult = FALSE;
  178. }
  179. else
  180. {
  181. for (i = 0; i < NUM_PRODUCTS; i++)
  182. {
  183. if (lstrcmpi(szLanguage, g_mpProducts[i].szLanguage) == 0)
  184. {
  185. //*STRSAFE* lstrcpy(szProductCode, g_mpProducts[i].szProductGUID);
  186. hresult = StringCchCopy(szProductCode , uiBufSize, g_mpProducts[i].szProductGUID);
  187. if (!SUCCEEDED(hresult))
  188. {
  189. wnsprintf(tcMessage, ARRAYSIZE(tcMessage) ,TEXT("MuiSetup: GetMSIProductCode: WARNING - failed to copy product code to output buffer."));
  190. LogMessage(tcMessage);
  191. bResult = FALSE;
  192. }
  193. else
  194. {
  195. bResult = TRUE;
  196. }
  197. break;
  198. }
  199. }
  200. }
  201. if (FALSE == bResult)
  202. {
  203. wnsprintf(tcMessage, ARRAYSIZE(tcMessage) ,TEXT("MuiSetup: GetMSIProductCode: WARNING - failed to find the MSI product code for langauge %s."), szLanguage);
  204. LogMessage(tcMessage);
  205. }
  206. return bResult;
  207. }
  208. ////////////////////////////////////////////////////////////////////////////////////
  209. //
  210. // EnumLanguages
  211. //
  212. // Enumerate the languages in the [Languages] section of MUI.INF. And check for the language
  213. // folders in the CD-ROM.
  214. // Languages is an OUT parameter, which will store the languages which has language folder
  215. // in the CD-ROM.
  216. //
  217. ////////////////////////////////////////////////////////////////////////////////////
  218. int EnumLanguages(LPTSTR Languages, BOOL bCheckDir)
  219. {
  220. DWORD dwErr;
  221. LPTSTR Language;
  222. LONG_PTR lppArgs[2];
  223. TCHAR szInffile[MAX_PATH];
  224. int iLanguages = 0;
  225. TCHAR LipLanguages[128] = {0};
  226. HRESULT hresult;
  227. if (!Languages)
  228. {
  229. return (-1);
  230. }
  231. //
  232. // MUI.INF should be in the same directory in which the installer was
  233. // started
  234. //
  235. //*STRSAFE* _tcscpy(szInffile, g_szMUIInfoFilePath);
  236. hresult = StringCchCopy(szInffile , ARRAYSIZE(szInffile), g_szMUIInfoFilePath);
  237. if (!SUCCEEDED(hresult))
  238. {
  239. return (-1);
  240. }
  241. //
  242. // find out how many languages we can install
  243. //
  244. *Languages = TEXT('\0');
  245. if (!GetPrivateProfileString( MUI_LANGUAGES_SECTION,
  246. NULL,
  247. TEXT("NOLANG"),
  248. Languages,
  249. BUFFER_SIZE,
  250. szInffile))
  251. {
  252. //
  253. // "LOG: Unable to read MUI.INF - rc == %1"
  254. //
  255. lppArgs[0] = (LONG_PTR)GetLastError();
  256. lppArgs[1] = (LONG_PTR)g_szMUIInfoFilePath;
  257. LogFormattedMessage(ghInstance, IDS_NO_READ_L, lppArgs);
  258. return(-1);
  259. }
  260. if (bCheckDir)
  261. {
  262. CheckLanguageDirectoryExist(Languages);
  263. }
  264. Language = Languages;
  265. //
  266. // Count the number of languages which exist in the CD-ROM,
  267. // and return that value.
  268. //
  269. while (*Language)
  270. {
  271. iLanguages++;
  272. while (*Language++)
  273. {
  274. }
  275. }
  276. if (iLanguages == 1 &&
  277. GetPrivateProfileSection( MUI_LIP_LANGUAGES_SECTION,
  278. LipLanguages,
  279. ARRAYSIZE(LipLanguages),
  280. szInffile))
  281. {
  282. g_bLipLanguages = TRUE;
  283. }
  284. if (g_bLipLanguages &&
  285. GetPrivateProfileSection( MUI_LIP_ALLOW_SWITCH_SECTION,
  286. LipLanguages,
  287. ARRAYSIZE(LipLanguages),
  288. szInffile))
  289. {
  290. g_bLipAllowSwitch = TRUE;
  291. }
  292. return(iLanguages);
  293. }
  294. BOOL CheckLanguageDirectoryExist(LPTSTR Languages)
  295. {
  296. TCHAR szBuffer[BUFFER_SIZE];
  297. TCHAR szSource[ MAX_PATH ];
  298. TCHAR szTemp [ MAX_PATH ];
  299. LPTSTR lpCur,lpBuffer;
  300. HANDLE hFile;
  301. WIN32_FIND_DATA FindFileData;
  302. int nSize;
  303. HRESULT hresult;
  304. if (!Languages)
  305. {
  306. return FALSE;
  307. }
  308. memcpy(szBuffer,Languages,BUFFER_SIZE);
  309. lpCur=Languages;
  310. lpBuffer=szBuffer;
  311. nSize=BUFFER_SIZE;
  312. while (*lpBuffer)
  313. {
  314. GetPrivateProfileString( MUI_LANGUAGES_SECTION,
  315. lpBuffer,
  316. TEXT("DEFAULT"),
  317. szSource,
  318. (sizeof(szSource)/sizeof(TCHAR)),
  319. g_szMUIInfoFilePath );
  320. #ifndef MUI_MAGIC
  321. //*STRSAFE* _tcscpy(szTemp,g_szMUISetupFolder);
  322. hresult = StringCchCopy(szTemp , ARRAYSIZE(szTemp), g_szMUISetupFolder);
  323. if (!SUCCEEDED(hresult))
  324. {
  325. return FALSE;
  326. }
  327. //*STRSAFE* _tcscat(szTemp,szSource);
  328. hresult = StringCchCat(szTemp , ARRAYSIZE(szTemp), szSource);
  329. if (!SUCCEEDED(hresult))
  330. {
  331. return FALSE;
  332. }
  333. //*STRSAFE* _tcscat(szTemp,TEXT("\\"));
  334. hresult = StringCchCat(szTemp , ARRAYSIZE(szTemp), TEXT("\\"));
  335. if (!SUCCEEDED(hresult))
  336. {
  337. return FALSE;
  338. }
  339. //*STRSAFE* _tcscat(szTemp,g_szPlatformPath); // i386 or alpha
  340. hresult = StringCchCat(szTemp , ARRAYSIZE(szTemp), g_szPlatformPath);
  341. if (!SUCCEEDED(hresult))
  342. {
  343. return FALSE;
  344. }
  345. //*STRSAFE* _tcscat(szTemp,TEXT("*.*"));
  346. hresult = StringCchCat(szTemp , ARRAYSIZE(szTemp), TEXT("*.*"));
  347. if (!SUCCEEDED(hresult))
  348. {
  349. return FALSE;
  350. }
  351. hFile = FindFirstFile( szTemp, &FindFileData );
  352. if (INVALID_HANDLE_VALUE != hFile )
  353. {
  354. if (FindNextFile( hFile, &FindFileData ) &&
  355. FindNextFile( hFile, &FindFileData ) )
  356. {
  357. //*STRSAFE* _tcscpy(lpCur,lpBuffer);
  358. hresult = StringCchCopy(lpCur , nSize, lpBuffer);
  359. if (!SUCCEEDED(hresult))
  360. {
  361. FindClose(hFile);
  362. return FALSE;
  363. }
  364. lpCur+=(_tcslen(lpBuffer)+1);
  365. nSize -= (_tcslen(lpBuffer)+1);
  366. }
  367. FindClose(hFile);
  368. }
  369. #else
  370. // kenhsu - here, we check for the specific msi file that is required for installation of the language, e.g. for jpn, it's 0411.msi
  371. // the file is located at CDRoot\jpn.mui\platform\msi
  372. //*STRSAFE* _tcscpy(szTemp,g_szMUISetupFolder);
  373. hresult = StringCchCopy(szTemp , ARRAYSIZE(szTemp), g_szMUISetupFolder);
  374. if (!SUCCEEDED(hresult))
  375. {
  376. return FALSE;
  377. }
  378. //*STRSAFE* _tcscat(szTemp,lpBuffer);
  379. hresult = StringCchCat(szTemp , ARRAYSIZE(szTemp), lpBuffer);
  380. if (!SUCCEEDED(hresult))
  381. {
  382. return FALSE;
  383. }
  384. //*STRSAFE* _tcscat(szTemp,TEXT(".msi"));
  385. hresult = StringCchCat(szTemp , ARRAYSIZE(szTemp), TEXT(".msi"));
  386. if (!SUCCEEDED(hresult))
  387. {
  388. return FALSE;
  389. }
  390. hFile = FindFirstFile( szTemp, &FindFileData );
  391. if (INVALID_HANDLE_VALUE != hFile )
  392. {
  393. //*STRSAFE* _tcscpy(lpCur,lpBuffer);
  394. hresult = StringCchCopy(lpCur , nSize, lpBuffer);
  395. if (!SUCCEEDED(hresult))
  396. {
  397. FindClose(hFile);
  398. return FALSE;
  399. }
  400. lpCur+=(_tcslen(lpBuffer)+1);
  401. nSize -= (_tcslen(lpBuffer)+1);
  402. FindClose(hFile);
  403. }
  404. #endif
  405. while (*lpBuffer++)
  406. {
  407. }
  408. }
  409. *lpCur=TEXT('\0');
  410. return TRUE;
  411. }
  412. ////////////////////////////////////////////////////////////////////////////////////
  413. //
  414. // checkversion
  415. //
  416. // Checks the NT version and build, and system ui language
  417. //
  418. ////////////////////////////////////////////////////////////////////////////////////
  419. BOOL checkversion(BOOL bMatchBuildNumber)
  420. {
  421. TCHAR buffer[20];
  422. TCHAR build[20];
  423. OSVERSIONINFO verinfo;
  424. LANGID rcLang;
  425. TCHAR lpMessage[BUFFER_SIZE];
  426. HRESULT hresult;
  427. DWORD dwDummy = 0;
  428. DWORD dwBufSize = 0;
  429. UINT uiLen = 0;
  430. BYTE *pbBuffer = NULL;
  431. VS_FIXEDFILEINFO *pvsFileInfo;
  432. BOOL bResult = TRUE;
  433. //
  434. // get the os version structure
  435. //
  436. verinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  437. if (!GetVersionEx( &verinfo))
  438. {
  439. bResult = FALSE;
  440. goto Exit;
  441. }
  442. //
  443. // get the file version structure
  444. //
  445. if (!FileExists(g_szMuisetupPath))
  446. {
  447. bResult = FALSE;
  448. goto Exit;
  449. }
  450. dwBufSize = GetFileVersionInfoSize(g_szMuisetupPath, &dwDummy);
  451. if (dwBufSize > 0)
  452. {
  453. //
  454. // allocate enough buffer to store the file version info
  455. //
  456. pbBuffer = (BYTE*) LocalAlloc(LMEM_FIXED, dwBufSize+1);
  457. if (NULL == pbBuffer)
  458. {
  459. bResult = FALSE;
  460. goto Exit;
  461. }
  462. else
  463. {
  464. //
  465. // Get the file version info
  466. //
  467. if (!GetFileVersionInfo(g_szMuisetupPath, dwDummy, dwBufSize, pbBuffer))
  468. {
  469. bResult = FALSE;
  470. goto Exit;
  471. }
  472. else
  473. {
  474. //
  475. // get the version from the file version info using VerQueryValue
  476. //
  477. if (!VerQueryValue(pbBuffer, TEXT("\\"), (LPVOID *) &pvsFileInfo, &uiLen))
  478. {
  479. bResult = FALSE;
  480. goto Exit;
  481. }
  482. }
  483. }
  484. }
  485. else
  486. {
  487. bResult = FALSE;
  488. goto Exit;
  489. }
  490. //
  491. // make sure muisetup.exe file version matches os version
  492. //
  493. if ((verinfo.dwMajorVersion != HIWORD(pvsFileInfo->dwFileVersionMS)) || (verinfo.dwMinorVersion != LOWORD(pvsFileInfo->dwFileVersionMS)))
  494. {
  495. debug("DBG: muisetup.exe file version does not match the OS version.\r\n");
  496. bResult = FALSE;
  497. goto Exit;
  498. }
  499. rcLang = (LANGID) gpfnGetSystemDefaultUILanguage();
  500. //
  501. // need to convert decimal to hex, LANGID to chr.
  502. //
  503. hresult = StringCchPrintf(buffer, ARRAYSIZE(buffer),TEXT("00000%X") , rcLang);
  504. if (!SUCCEEDED(hresult))
  505. {
  506. bResult = FALSE;
  507. goto Exit;
  508. }
  509. if (_tcscmp(buffer, TEXT("00000409")))
  510. {
  511. bResult = FALSE;
  512. goto Exit;
  513. }
  514. //
  515. // also make sure version build number matches between os and muisetup
  516. //
  517. if (bMatchBuildNumber)
  518. {
  519. if (LOWORD(verinfo.dwBuildNumber) == HIWORD(pvsFileInfo->dwFileVersionLS))
  520. {
  521. bResult = TRUE;
  522. }
  523. else
  524. {
  525. bResult = FALSE;
  526. }
  527. }
  528. Exit:
  529. if (pbBuffer)
  530. {
  531. LocalFree(pbBuffer);
  532. }
  533. return bResult;
  534. }
  535. ////////////////////////////////////////////////////////////////////////////////////
  536. //
  537. // File Exists
  538. //
  539. // Returns TRUE if the file exists, FALSE if it does not.
  540. //
  541. ////////////////////////////////////////////////////////////////////////////////////
  542. BOOL FileExists(LPTSTR szFile)
  543. {
  544. HANDLE hFile;
  545. WIN32_FIND_DATA FindFileData;
  546. if (!szFile)
  547. {
  548. return FALSE;
  549. }
  550. hFile = FindFirstFile( szFile, &FindFileData );
  551. if (hFile == INVALID_HANDLE_VALUE)
  552. {
  553. return FALSE;
  554. }
  555. FindClose( hFile );
  556. return TRUE;
  557. }
  558. ////////////////////////////////////////////////////////////////////////////////////
  559. //
  560. // EnumDirectories
  561. //
  562. // Enumerates the directories listed in MUI.INF
  563. //
  564. ////////////////////////////////////////////////////////////////////////////////////
  565. BOOL EnumDirectories()
  566. {
  567. DWORD dwErr;
  568. LPTSTR Directories, Directory, TempDir;
  569. TCHAR lpError[BUFFER_SIZE];
  570. TCHAR lpMessage[BUFFER_SIZE];
  571. LONG_PTR lppArgs[3];
  572. int Dirnumber = 0;
  573. HRESULT hresult;
  574. Directories = (LPTSTR) LocalAlloc( 0, (DIRNUMBER * MAX_PATH * sizeof(TCHAR)) );
  575. if (Directories == NULL)
  576. {
  577. ExitFromOutOfMemory();
  578. }
  579. TempDir = (LPTSTR) LocalAlloc( 0, (MAX_PATH * sizeof(TCHAR)) );
  580. if (TempDir == NULL)
  581. {
  582. LocalFree(Directories);
  583. ExitFromOutOfMemory();
  584. }
  585. else
  586. {
  587. *Directories = TEXT('\0');
  588. }
  589. //
  590. // Copy all key names into Directories.
  591. //
  592. if (!GetPrivateProfileString( TEXT("Directories"),
  593. NULL,
  594. TEXT("DEFAULT"),
  595. Directories,
  596. (DIRNUMBER * MAX_PATH),
  597. g_szMUIInfoFilePath ))
  598. {
  599. //
  600. // "LOG: Unable to read - rc == %1"
  601. //
  602. lppArgs[0] = (LONG_PTR)GetLastError();
  603. lppArgs[1] = (LONG_PTR)g_szMUIInfoFilePath;
  604. LogFormattedMessage(ghInstance, IDS_NO_READ_L, lppArgs);
  605. LocalFree( TempDir );
  606. LocalFree( Directories );
  607. return FALSE;
  608. }
  609. Directory = Directories;
  610. //
  611. // In case we don't find anything, we go to the fallback directory
  612. //
  613. //*STRSAFE* _tcscpy(DirNames[0], TEXT("FALLBACK"));
  614. hresult = StringCchCopy(DirNames[0] , MAX_PATH, TEXT("FALLBACK"));
  615. if (!SUCCEEDED(hresult))
  616. {
  617. LocalFree( TempDir );
  618. LocalFree( Directories );
  619. return FALSE;
  620. }
  621. while (*Directory)
  622. {
  623. if (!GetPrivateProfileString( TEXT("Directories"),
  624. Directory,
  625. TEXT("\\DEFAULT"),
  626. TempDir,
  627. MAX_PATH,
  628. g_szMUIInfoFilePath))
  629. {
  630. //
  631. // "LOG: Unable to read - rc == %1"
  632. //
  633. lppArgs[0] = (LONG_PTR)GetLastError();
  634. lppArgs[1] = (LONG_PTR)g_szMUIInfoFilePath;
  635. LogFormattedMessage(ghInstance, IDS_NO_READ_L, lppArgs);
  636. LocalFree( TempDir );
  637. LocalFree( Directories );
  638. return FALSE;
  639. }
  640. //*STRSAFE* _tcscpy(DirNames[++Dirnumber], TempDir);
  641. hresult = StringCchCopy(DirNames[++Dirnumber] , MAX_PATH, TempDir);
  642. if (!SUCCEEDED(hresult))
  643. {
  644. LocalFree( TempDir );
  645. LocalFree( Directories );
  646. return FALSE;
  647. }
  648. // Move to the beginning of next key name.
  649. while (*Directory++)
  650. {
  651. }
  652. }
  653. LocalFree( TempDir );
  654. LocalFree( Directories );
  655. return TRUE;
  656. }
  657. ////////////////////////////////////////////////////////////////////////////////////
  658. //
  659. // EnumFileRename
  660. //
  661. // Enumerates the [File_Layout] section listed in MUI.INF
  662. //
  663. ////////////////////////////////////////////////////////////////////////////////////
  664. BOOL EnumFileRename()
  665. {
  666. DWORD dwErr;
  667. LPTSTR Directories, Directory, TempDir,lpszNext;
  668. TCHAR szPlatform[MAX_PATH+1],szTargetPlatform[MAX_PATH+1];
  669. LONG_PTR lppArgs[1];
  670. int Dirnumber = 0,nIdx=0;
  671. HRESULT hresult;
  672. Directories = (LPTSTR) LocalAlloc( 0, (FILERENAMENUMBER * (MAX_PATH+1) * sizeof(TCHAR)) );
  673. if (!Directories)
  674. {
  675. return FALSE;
  676. }
  677. TempDir = (LPTSTR) LocalAlloc( 0, ( (MAX_PATH+1) * sizeof(TCHAR)) );
  678. if (!TempDir)
  679. {
  680. LocalFree(Directories);
  681. return FALSE;
  682. }
  683. if (gbIsAdvanceServer)
  684. {
  685. //*STRSAFE* _tcscpy(szTargetPlatform,PLATFORMNAME_AS);
  686. hresult = StringCchCopy(szTargetPlatform , ARRAYSIZE(szTargetPlatform), PLATFORMNAME_AS);
  687. if (!SUCCEEDED(hresult))
  688. {
  689. LocalFree( TempDir );
  690. LocalFree( Directories );
  691. return FALSE;
  692. }
  693. }
  694. else if (gbIsServer)
  695. {
  696. //*STRSAFE* _tcscpy(szTargetPlatform,PLATFORMNAME_SRV);
  697. hresult = StringCchCopy(szTargetPlatform , ARRAYSIZE(szTargetPlatform), PLATFORMNAME_SRV);
  698. if (!SUCCEEDED(hresult))
  699. {
  700. LocalFree( TempDir );
  701. LocalFree( Directories );
  702. return FALSE;
  703. }
  704. }
  705. else if (gbIsWorkStation)
  706. {
  707. //*STRSAFE* _tcscpy(szTargetPlatform,PLATFORMNAME_PRO);
  708. hresult = StringCchCopy(szTargetPlatform , ARRAYSIZE(szTargetPlatform), PLATFORMNAME_PRO);
  709. if (!SUCCEEDED(hresult))
  710. {
  711. LocalFree( TempDir );
  712. LocalFree( Directories );
  713. return FALSE;
  714. }
  715. }
  716. else if ( gbIsDataCenter)
  717. {
  718. //*STRSAFE* _tcscpy(szTargetPlatform,PLATFORMNAME_DTC);
  719. hresult = StringCchCopy(szTargetPlatform , ARRAYSIZE(szTargetPlatform), PLATFORMNAME_DTC);
  720. if (!SUCCEEDED(hresult))
  721. {
  722. LocalFree( TempDir );
  723. LocalFree( Directories );
  724. return FALSE;
  725. }
  726. }
  727. else
  728. {
  729. //*STRSAFE* _tcscpy(szTargetPlatform,PLATFORMNAME_PRO);
  730. hresult = StringCchCopy(szTargetPlatform , ARRAYSIZE(szTargetPlatform), PLATFORMNAME_PRO);
  731. if (!SUCCEEDED(hresult))
  732. {
  733. LocalFree( TempDir );
  734. LocalFree( Directories );
  735. return FALSE;
  736. }
  737. }
  738. *Directories = TEXT('\0');
  739. if (!GetPrivateProfileString( MUI_FILELAYOUT_SECTION,
  740. NULL,
  741. TEXT(""),
  742. Directories,
  743. (FILERENAMENUMBER * MAX_PATH),
  744. g_szMUIInfoFilePath ))
  745. {
  746. LocalFree( TempDir );
  747. LocalFree( Directories );
  748. return FALSE;
  749. }
  750. Directory = Directories;
  751. //
  752. // Calculate # of entries in this section
  753. //
  754. while (*Directory)
  755. {
  756. if (!GetPrivateProfileString( MUI_FILELAYOUT_SECTION,
  757. Directory,
  758. TEXT(""),
  759. TempDir,
  760. MAX_PATH,
  761. g_szMUIInfoFilePath))
  762. {
  763. LocalFree( TempDir );
  764. LocalFree( Directories );
  765. return FALSE;
  766. }
  767. //
  768. // Check if platform ID field in this entry
  769. //
  770. // Source_file_name=Destination_file_name,P,S,A
  771. //
  772. lpszNext=TempDir;
  773. while ( (lpszNext=_tcschr(lpszNext,TEXT(','))) )
  774. {
  775. lpszNext++;
  776. nIdx=0;
  777. szPlatform[0]=TEXT('\0');
  778. while ( (*lpszNext != TEXT('\0')) && (*lpszNext != TEXT(',')))
  779. {
  780. if (*lpszNext != TEXT(' '))
  781. {
  782. szPlatform[nIdx++]=*lpszNext;
  783. }
  784. lpszNext++;
  785. }
  786. szPlatform[nIdx]=TEXT('\0');
  787. if (!_tcsicmp(szPlatform,szTargetPlatform))
  788. {
  789. Dirnumber++;
  790. break;
  791. }
  792. }
  793. while (*Directory++)
  794. {
  795. }
  796. }
  797. //
  798. // Allocte Space for Rename Table
  799. //
  800. g_pFileRenameTable=(PFILERENAME_TABLE)LocalAlloc( 0, Dirnumber * sizeof(FILERENAME_TABLE) );
  801. if (!g_pFileRenameTable)
  802. {
  803. LocalFree( TempDir );
  804. LocalFree( Directories );
  805. return FALSE;
  806. }
  807. g_nFileRename=0;
  808. Directory = Directories;
  809. //
  810. // Create Reanme Table
  811. //
  812. while (*Directory)
  813. {
  814. if (!GetPrivateProfileString( MUI_FILELAYOUT_SECTION,
  815. Directory,
  816. TEXT(""),
  817. TempDir,
  818. MAX_PATH,
  819. g_szMUIInfoFilePath))
  820. {
  821. LocalFree(g_pFileRenameTable);
  822. LocalFree( TempDir );
  823. LocalFree( Directories );
  824. return FALSE;
  825. }
  826. //
  827. // Check if platform ID field in this entry
  828. //
  829. // Source_file_name=Destination_file_name,P,S,A
  830. //
  831. lpszNext=TempDir;
  832. while ( lpszNext =_tcschr(lpszNext,TEXT(',')))
  833. {
  834. lpszNext++;
  835. nIdx=0;
  836. szPlatform[0]=TEXT('\0');
  837. while ( (*lpszNext != TEXT('\0')) && (*lpszNext != TEXT(',')))
  838. {
  839. if (*lpszNext != TEXT(' '))
  840. {
  841. szPlatform[nIdx++]=*lpszNext;
  842. }
  843. lpszNext++;
  844. }
  845. szPlatform[nIdx]=TEXT('\0');
  846. if (!_tcsicmp(szPlatform,szTargetPlatform) )
  847. {
  848. //
  849. // Insert this entry into rename table pointed by g_pFileRenameTable
  850. //
  851. //*STRSAFE* _tcscpy(g_pFileRenameTable[g_nFileRename].szSource,Directory);
  852. hresult = StringCchCopy(g_pFileRenameTable[g_nFileRename].szSource , MAX_PATH+1, Directory);
  853. if (!SUCCEEDED(hresult))
  854. {
  855. LocalFree( TempDir );
  856. LocalFree( Directories );
  857. return FALSE;
  858. }
  859. lpszNext=TempDir;
  860. nIdx=0;
  861. g_pFileRenameTable[g_nFileRename].szDest[0]=TEXT('\0');
  862. while ( (*lpszNext != TEXT('\0')) && (*lpszNext != TEXT(',')) && (*lpszNext != TEXT(' ')) )
  863. {
  864. g_pFileRenameTable[g_nFileRename].szDest[nIdx++]=*lpszNext;
  865. lpszNext++;
  866. }
  867. g_pFileRenameTable[g_nFileRename].szDest[nIdx]=TEXT('\0');
  868. g_nFileRename++;
  869. break;
  870. }
  871. }
  872. while (*Directory++)
  873. {
  874. }
  875. }
  876. LocalFree( TempDir );
  877. LocalFree( Directories );
  878. return TRUE;
  879. }
  880. ////////////////////////////////////////////////////////////////////////////////////
  881. //
  882. // EnumTypeNotFallback
  883. //
  884. // Enumerates the [FileType_NoFallback] section listed in MUI.INF
  885. //
  886. ////////////////////////////////////////////////////////////////////////////////////
  887. BOOL EnumTypeNotFallback()
  888. {
  889. LPTSTR Directories, Directory, TempDir,lpszNext;
  890. int Dirnumber = 0,nIdx=0;
  891. Directories = (LPTSTR) LocalAlloc( 0, (NOTFALLBACKNUMBER * (MAX_PATH+1) * sizeof(TCHAR)) );
  892. if (!Directories)
  893. {
  894. return FALSE;
  895. }
  896. TempDir = (LPTSTR) LocalAlloc( 0, ( (MAX_PATH+1) * sizeof(TCHAR)) );
  897. if (!TempDir)
  898. {
  899. LocalFree(Directories);
  900. return FALSE;
  901. }
  902. *Directories = TEXT('\0');
  903. if (!GetPrivateProfileString( MUI_NOFALLBACK_SECTION,
  904. NULL,
  905. TEXT(""),
  906. Directories,
  907. (NOTFALLBACKNUMBER * MAX_PATH),
  908. g_szMUIInfoFilePath ))
  909. {
  910. LocalFree( TempDir );
  911. LocalFree( Directories );
  912. return FALSE;
  913. }
  914. Directory = Directories;
  915. //
  916. // Calculate # of entries in this section
  917. //
  918. while (*Directory)
  919. {
  920. if (!GetPrivateProfileString( MUI_NOFALLBACK_SECTION,
  921. Directory,
  922. TEXT(""),
  923. TempDir,
  924. MAX_PATH,
  925. g_szMUIInfoFilePath))
  926. {
  927. LocalFree( TempDir );
  928. LocalFree( Directories );
  929. return FALSE;
  930. }
  931. Dirnumber++;
  932. while (*Directory++)
  933. {
  934. }
  935. }
  936. //
  937. // Allocte Space for
  938. //
  939. g_pNotFallBackTable=(PTYPENOTFALLBACK_TABLE)LocalAlloc( 0, Dirnumber * sizeof(TYPENOTFALLBACK_TABLE) );
  940. if (!g_pNotFallBackTable)
  941. {
  942. LocalFree( TempDir );
  943. LocalFree( Directories );
  944. return FALSE;
  945. }
  946. g_nNotFallBack=0;
  947. Directory = Directories;
  948. //
  949. // Create NoFallBack Table
  950. //
  951. while (*Directory)
  952. {
  953. if (!GetPrivateProfileString( MUI_NOFALLBACK_SECTION,
  954. Directory,
  955. TEXT(""),
  956. TempDir,
  957. MAX_PATH,
  958. g_szMUIInfoFilePath))
  959. {
  960. LocalFree(g_pNotFallBackTable);
  961. LocalFree( TempDir );
  962. LocalFree( Directories );
  963. return FALSE;
  964. }
  965. //
  966. //
  967. //
  968. lpszNext=TempDir;
  969. nIdx=0;
  970. g_pNotFallBackTable[g_nNotFallBack].szSource[0]=TEXT('\0');
  971. while ( (*lpszNext != TEXT('\0')) && (*lpszNext != TEXT(',')) && (*lpszNext != TEXT(' ')) )
  972. {
  973. g_pNotFallBackTable[g_nNotFallBack].szSource[nIdx++]=*lpszNext;
  974. lpszNext++;
  975. }
  976. g_pNotFallBackTable[g_nNotFallBack].szSource[nIdx]=TEXT('\0');
  977. g_nNotFallBack++;
  978. while (*Directory++)
  979. {
  980. }
  981. }
  982. LocalFree( TempDir );
  983. LocalFree( Directories );
  984. return TRUE;
  985. }
  986. //
  987. // Check if a given file should be renamed by searching Rename Table
  988. //
  989. BOOL IsFileBeRenamed(LPTSTR lpszSrc,LPTSTR lpszDest)
  990. {
  991. int nIdx;
  992. BOOL bResult=FALSE;
  993. HRESULT hresult;
  994. if (!lpszSrc)
  995. return bResult;
  996. for (nIdx=0; nIdx < g_nFileRename; nIdx++)
  997. {
  998. LPTSTR pMUI = StrStrI(lpszSrc,g_pFileRenameTable[nIdx].szSource);
  999. if (pMUI == lpszSrc)
  1000. {
  1001. pMUI += lstrlen(g_pFileRenameTable[nIdx].szSource);
  1002. //*PREFAST * if (!*pMUI || !lstrcmpi(pMUI, TEXT(".MUI")))
  1003. if (! *pMUI || (CompareString(LOCALE_INVARIANT,NORM_IGNORECASE,pMUI,-1,TEXT(".MUI"),-1) == 2) )
  1004. {
  1005. //*STRSAFE* lstrcpy(lpszDest,g_pFileRenameTable[nIdx].szDest);
  1006. hresult = StringCchCopy(lpszDest , MAX_PATH, g_pFileRenameTable[nIdx].szDest);
  1007. if (!SUCCEEDED(hresult))
  1008. {
  1009. return FALSE;
  1010. }
  1011. //*STRSAFE* lstrcat(lpszDest, pMUI);
  1012. hresult = StringCchCat(lpszDest , MAX_PATH, pMUI);
  1013. if (!SUCCEEDED(hresult))
  1014. {
  1015. return FALSE;
  1016. }
  1017. bResult=TRUE;
  1018. break;
  1019. }
  1020. }
  1021. }
  1022. return bResult;
  1023. }
  1024. //
  1025. // Check if a given file matches szDest field of rename table.
  1026. // If it the case then we won't install this file
  1027. //
  1028. BOOL IsFileInRenameTable(LPTSTR lpszSrc)
  1029. {
  1030. int nIdx;
  1031. BOOL bResult=FALSE;
  1032. if (!lpszSrc)
  1033. return bResult;
  1034. for (nIdx=0; nIdx < g_nFileRename; nIdx++)
  1035. {
  1036. LPTSTR pMUI = StrStrI(lpszSrc,g_pFileRenameTable[nIdx].szDest);
  1037. if (pMUI == lpszSrc)
  1038. {
  1039. pMUI += lstrlen(g_pFileRenameTable[nIdx].szDest);
  1040. //*PREFAST* if (!*pMUI || !lstrcmpi(pMUI, TEXT(".MUI")))
  1041. if (! *pMUI || (CompareString(LOCALE_INVARIANT,NORM_IGNORECASE,pMUI,-1,TEXT(".MUI"),-1) == 2) )
  1042. {
  1043. bResult=TRUE;
  1044. break;
  1045. }
  1046. }
  1047. }
  1048. return bResult;
  1049. }
  1050. //
  1051. // Check if the file type of a given file belongs to the category "Do not Fallback"
  1052. //
  1053. BOOL IsDoNotFallBack(LPTSTR lpszFileName)
  1054. {
  1055. BOOL bResult = FALSE;
  1056. int iLen,nIdx;
  1057. if (!lpszFileName)
  1058. {
  1059. return bResult;
  1060. }
  1061. iLen = _tcslen(lpszFileName);
  1062. if (iLen > 4)
  1063. {
  1064. for (nIdx=0; nIdx < g_nNotFallBack ; nIdx++)
  1065. {
  1066. if (!_tcsicmp(&lpszFileName[iLen - 4],g_pNotFallBackTable[nIdx].szSource))
  1067. {
  1068. bResult = TRUE;
  1069. break;
  1070. }
  1071. }
  1072. }
  1073. return bResult;
  1074. }
  1075. ////////////////////////////////////////////////////////////////////////////////////
  1076. //
  1077. // Muisetup_CheckForExpandedFile
  1078. //
  1079. // Retreives the original filename, in case the file is compressed.
  1080. //
  1081. ////////////////////////////////////////////////////////////////////////////////////
  1082. BOOL Muisetup_CheckForExpandedFile(
  1083. PTSTR pszPathName,
  1084. PTSTR pszFileName,
  1085. PTSTR pszOriginalFileName,
  1086. PDIAMOND_PACKET pDiamond)
  1087. {
  1088. TCHAR szCompressedFileName[ MAX_PATH ];
  1089. TCHAR szOut[ MAX_PATH ];
  1090. PTSTR pszTemp, pszDelimiter;
  1091. BOOL bIsCompressed;
  1092. int iLen=0;
  1093. HRESULT hresult;
  1094. if ( (!pszPathName) || (!pszFileName) || (!pszOriginalFileName) || (!pDiamond))
  1095. {
  1096. return FALSE;
  1097. }
  1098. // Initializations
  1099. bIsCompressed = FALSE;
  1100. szOut[ 0 ] = szCompressedFileName[ 0 ] = TEXT('\0');
  1101. //
  1102. // Get the real name
  1103. //
  1104. //*STRSAFE* _tcscpy(szCompressedFileName, pszPathName);
  1105. hresult = StringCchCopy(szCompressedFileName , ARRAYSIZE(szCompressedFileName), pszPathName);
  1106. if (!SUCCEEDED(hresult))
  1107. {
  1108. return FALSE;
  1109. }
  1110. //*STRSAFE* _tcscat(szCompressedFileName, pszFileName);
  1111. hresult = StringCchCat(szCompressedFileName , ARRAYSIZE(szCompressedFileName), pszFileName);
  1112. if (!SUCCEEDED(hresult))
  1113. {
  1114. return FALSE;
  1115. }
  1116. if (Muisetup_IsDiamondFile( szCompressedFileName,
  1117. pszOriginalFileName,
  1118. MAX_PATH,
  1119. pDiamond ))
  1120. {
  1121. return TRUE;
  1122. }
  1123. if (GetExpandedName(szCompressedFileName, szOut) == TRUE)
  1124. {
  1125. pszDelimiter = pszTemp = szOut;
  1126. while (*pszTemp)
  1127. {
  1128. if ((*pszTemp == TEXT('\\')) ||
  1129. (*pszTemp == TEXT('/')))
  1130. {
  1131. pszDelimiter = pszTemp;
  1132. }
  1133. pszTemp++;
  1134. }
  1135. if (*pszDelimiter == TEXT('\\') ||
  1136. *pszDelimiter == TEXT('/'))
  1137. {
  1138. pszDelimiter++;
  1139. }
  1140. if (_tcsicmp(pszDelimiter, pszFileName) != 0)
  1141. {
  1142. bIsCompressed = TRUE;
  1143. //*STRSAFE* _tcscpy(pszOriginalFileName, pszDelimiter);
  1144. hresult = StringCchCopy(pszOriginalFileName , MAX_PATH, pszDelimiter);
  1145. if (!SUCCEEDED(hresult))
  1146. {
  1147. return FALSE;
  1148. }
  1149. }
  1150. }
  1151. if (!bIsCompressed)
  1152. {
  1153. //*STRSAFE* _tcscpy(pszOriginalFileName, pszFileName);
  1154. hresult = StringCchCopy(pszOriginalFileName , MAX_PATH, pszFileName);
  1155. if (!SUCCEEDED(hresult))
  1156. {
  1157. return FALSE;
  1158. }
  1159. //
  1160. // If muisetup is launched through [GUIRunOnce] command line mode,
  1161. // W2K uncompresses all mui files and leave the name as xxxxxx.xxx.mu_
  1162. // We should cover this situation by changing the name to xxxxxx.xxx.mui
  1163. iLen = _tcslen(pszOriginalFileName);
  1164. if (iLen > 4)
  1165. {
  1166. if (_tcsicmp(&pszOriginalFileName[iLen - 4], TEXT(".mu_")) == 0)
  1167. {
  1168. pszOriginalFileName[iLen-1]=TEXT('i');
  1169. }
  1170. }
  1171. }
  1172. return TRUE;
  1173. }
  1174. ////////////////////////////////////////////////////////////////////////////////////
  1175. //
  1176. // Muisetup_CopyFile
  1177. //
  1178. // Copy file, and expand it if necessary.
  1179. //
  1180. ////////////////////////////////////////////////////////////////////////////////////
  1181. BOOL Muisetup_CopyFile(
  1182. PCTSTR pszCopyFrom,
  1183. PTSTR pszCopyTo,
  1184. PDIAMOND_PACKET pDiamond,
  1185. PTSTR pOriginalName)
  1186. {
  1187. OFSTRUCT ofs;
  1188. INT hfFrom, hfTo;
  1189. BOOL bRet = FALSE;
  1190. HRESULT hresult;
  1191. if ( (!pszCopyFrom) || (!pszCopyTo) || (!pDiamond) )
  1192. {
  1193. return FALSE;
  1194. }
  1195. //
  1196. // Check if diamond can handle it
  1197. //
  1198. bRet = Muisetup_CopyDiamondFile( pDiamond,
  1199. pszCopyTo );
  1200. if (bRet)
  1201. {
  1202. //
  1203. // Diamond copy won't rename file for us
  1204. //
  1205. if (pOriginalName)
  1206. {
  1207. WCHAR wszPath[MAX_PATH];
  1208. //
  1209. // Diamond is ANSI
  1210. //
  1211. if (MultiByteToWideChar(1252, 0, pDiamond->szDestFilePath, -1, wszPath, ARRAYSIZE(wszPath)))
  1212. {
  1213. //*STRSAFE* StrCat(wszPath, pOriginalName);
  1214. hresult = StringCchCat(wszPath , ARRAYSIZE(wszPath), pOriginalName);
  1215. if (!SUCCEEDED(hresult))
  1216. {
  1217. return FALSE;
  1218. }
  1219. MoveFileEx(wszPath,pszCopyTo,MOVEFILE_REPLACE_EXISTING);
  1220. }
  1221. }
  1222. return bRet;
  1223. }
  1224. hfFrom = LZOpenFile( (PTSTR) pszCopyFrom,
  1225. &ofs,
  1226. OF_READ );
  1227. if (hfFrom < 0)
  1228. {
  1229. return FALSE;
  1230. }
  1231. hfTo = LZOpenFile( (PTSTR) pszCopyTo,
  1232. &ofs,
  1233. OF_CREATE | OF_WRITE);
  1234. if (hfTo < 0)
  1235. {
  1236. LZClose(hfFrom);
  1237. return FALSE;
  1238. }
  1239. bRet = TRUE;
  1240. if (LZCopy(hfFrom, hfTo) < 0)
  1241. {
  1242. bRet = FALSE;
  1243. }
  1244. LZClose(hfFrom);
  1245. LZClose(hfTo);
  1246. return bRet;
  1247. }
  1248. ////////////////////////////////////////////////////////////////////////////////////
  1249. //
  1250. // InstallComponentsMUIFiles
  1251. //
  1252. // Parameters:
  1253. // pszLangSourceDir The sub-directory name for a specific lanuage in the MUI CD-ROM.
  1254. // E.g. "jpn.MUI"
  1255. // pszLanguage The LCID for the specific language. E.g. "0404".
  1256. // isInstall TRUE if you are going to install the MUI files for the component. FALSE
  1257. // if you are going to uninstall.
  1258. // [OUT] pbCanceled TRUE if the operation is canceled.
  1259. // [OUT] pbError TURE if error happens.
  1260. //
  1261. // Return:
  1262. // TRUE if success. Otherwise FALSE.
  1263. //
  1264. // Note:
  1265. // For the language resources stored in pszLangSourceDir, this function will enumerate
  1266. // the compoents listed in the [Components]
  1267. // (the real section is put in MUI_COMPONENTS_SECTION) section, and execute the INF file
  1268. // listed in every entry in
  1269. // the [Components] section.
  1270. //
  1271. ////////////////////////////////////////////////////////////////////////////////////
  1272. BOOL InstallComponentsMUIFiles(PTSTR pszLangSourceDir, PTSTR pszLanguage, BOOL isInstall)
  1273. {
  1274. BOOL result = TRUE;
  1275. TCHAR szComponentName[BUFFER_SIZE];
  1276. TCHAR CompDir[BUFFER_SIZE];
  1277. TCHAR CompINFFile[BUFFER_SIZE];
  1278. TCHAR CompInstallSection[BUFFER_SIZE];
  1279. TCHAR CompUninstallSection[BUFFER_SIZE];
  1280. TCHAR szCompInfFullPath[MAX_PATH];
  1281. LONG_PTR lppArgs[2];
  1282. INFCONTEXT InfContext;
  1283. HRESULT hresult;
  1284. TCHAR szBuffer[BUFFER_SIZE];
  1285. if ((TRUE == isInstall) && (!pszLangSourceDir))
  1286. {
  1287. return FALSE;
  1288. }
  1289. HINF hInf = SetupOpenInfFile(g_szMUIInfoFilePath, NULL, INF_STYLE_WIN4, NULL);
  1290. if (hInf == INVALID_HANDLE_VALUE)
  1291. {
  1292. //*STRSAFE* _stprintf(szBuffer, TEXT("%d"), GetLastError());
  1293. hresult = StringCchPrintf(szBuffer , ARRAYSIZE(szBuffer), TEXT("%d"), GetLastError());
  1294. if (!SUCCEEDED(hresult))
  1295. {
  1296. return FALSE;
  1297. }
  1298. lppArgs[0] = (LONG_PTR)szBuffer;
  1299. lppArgs[1] = (LONG_PTR)g_szMUIInfoFilePath;
  1300. LogFormattedMessage(ghInstance, IDS_NO_READ_L, lppArgs);
  1301. return (FALSE);
  1302. }
  1303. //
  1304. // Get the first comopnent to be installed.
  1305. //
  1306. if (SetupFindFirstLine(hInf, MUI_COMPONENTS_SECTION, NULL, &InfContext))
  1307. {
  1308. do
  1309. {
  1310. if (!SetupGetStringField(&InfContext, 0, szComponentName, ARRAYSIZE(szComponentName), NULL))
  1311. {
  1312. lppArgs[0]=(LONG_PTR)szComponentName;
  1313. LogFormattedMessage(ghInstance, IDS_COMP_MISSING_NAME_L, lppArgs);
  1314. continue;
  1315. }
  1316. if (!SetupGetStringField(&InfContext, 1, CompDir, ARRAYSIZE(CompDir), NULL))
  1317. {
  1318. //
  1319. // "LOG: MUI files for component %1 was not installed because of missing component direcotry.\n"
  1320. //
  1321. lppArgs[0]=(LONG_PTR)szComponentName;
  1322. LogFormattedMessage(ghInstance, IDS_COMP_MISSING_DIR_L, lppArgs);
  1323. continue;
  1324. }
  1325. if (!SetupGetStringField(&InfContext, 2, CompINFFile, ARRAYSIZE(CompINFFile), NULL))
  1326. {
  1327. //
  1328. // "LOG: MUI files for component %1 were not installed because of missing component INF filename.\n"
  1329. //
  1330. lppArgs[0]=(LONG_PTR)szComponentName;
  1331. LogFormattedMessage(ghInstance, IDS_COMP_MISSING_INF_L, lppArgs);
  1332. continue;
  1333. }
  1334. if (!SetupGetStringField(&InfContext, 3, CompInstallSection, ARRAYSIZE(CompInstallSection), NULL))
  1335. {
  1336. //*STRSAFE* _tcscpy(CompInstallSection, DEFAULT_INSTALL_SECTION);
  1337. hresult = StringCchCopy(CompInstallSection , ARRAYSIZE(CompInstallSection), DEFAULT_INSTALL_SECTION);
  1338. if (!SUCCEEDED(hresult))
  1339. {
  1340. SetupCloseInfFile(hInf);
  1341. return FALSE;
  1342. }
  1343. }
  1344. if (!SetupGetStringField(&InfContext, 4, CompUninstallSection, ARRAYSIZE(CompUninstallSection), NULL))
  1345. {
  1346. //*STRSAFE* _tcscpy(CompUninstallSection, DEFAULT_UNINSTALL_SECTION);
  1347. hresult = StringCchCopy(CompUninstallSection , ARRAYSIZE(CompUninstallSection), DEFAULT_UNINSTALL_SECTION);
  1348. if (!SUCCEEDED(hresult))
  1349. {
  1350. SetupCloseInfFile(hInf);
  1351. return FALSE;
  1352. }
  1353. }
  1354. //
  1355. // Establish the correct path for component INF file.
  1356. //
  1357. if (isInstall)
  1358. {
  1359. //
  1360. // For installation, we execute the INFs in the language directory of the CD-ROM (e.g.
  1361. // g:\jpn.mui\i386\ie5\ie5ui.inf
  1362. //
  1363. //*STRSAFE* _stprintf(szCompInfFullPath, TEXT("%s%s\\%s%s\\%s"), g_szMUISetupFolder, pszLangSourceDir, g_szPlatformPath, CompDir, CompINFFile);
  1364. hresult = StringCchPrintf(szCompInfFullPath, ARRAYSIZE(szCompInfFullPath), TEXT("%s%s\\%s%s\\%s"), g_szMUISetupFolder, pszLangSourceDir, g_szPlatformPath, CompDir, CompINFFile);
  1365. if (!SUCCEEDED(hresult))
  1366. {
  1367. SetupCloseInfFile(hInf);
  1368. return FALSE;
  1369. }
  1370. if (!ExecuteComponentINF(NULL, szComponentName, szCompInfFullPath, CompInstallSection, TRUE))
  1371. {
  1372. if (!g_bNoUI)
  1373. {
  1374. if (DoMessageBox(NULL, IDS_CANCEL_INSTALLATION, IDS_MAIN_TITLE, MB_YESNO) == IDNO)
  1375. {
  1376. result = FALSE;
  1377. break;
  1378. }
  1379. }
  1380. }
  1381. } else
  1382. {
  1383. //
  1384. // For uninstallation, we execute the INFs in the \winnt\mui\fallback directory to remove component files.
  1385. //
  1386. //*STRSAFE* _stprintf(szCompInfFullPath, TEXT("%s%s\\%s\\%s"), g_szWinDir, FALLBACKDIR, pszLanguage, CompINFFile) ;
  1387. hresult = StringCchPrintf(szCompInfFullPath , ARRAYSIZE(szCompInfFullPath), TEXT("%s%s\\%s\\%s"), g_szWinDir, FALLBACKDIR, pszLanguage, CompINFFile);
  1388. if (!SUCCEEDED(hresult))
  1389. {
  1390. SetupCloseInfFile(hInf);
  1391. return FALSE;
  1392. }
  1393. if (!ExecuteComponentINF(NULL, szComponentName, szCompInfFullPath, CompUninstallSection, FALSE) && result)
  1394. {
  1395. result = FALSE;
  1396. }
  1397. }
  1398. //
  1399. // Install the next component.
  1400. //
  1401. } while (SetupFindNextLine(&InfContext, &InfContext));
  1402. }
  1403. SetupCloseInfFile(hInf);
  1404. return (result);
  1405. }
  1406. ////////////////////////////////////////////////////////////////////////////////////
  1407. //
  1408. // CopyFiles
  1409. //
  1410. // Copies the specified files to the appropriate directories
  1411. //
  1412. // Parameters:
  1413. // [in] languages: contain the hex string for the languages to be installed. There could be more than one language.
  1414. // [out] lpbCopyCancelled: if the copy operation has been cancelled.
  1415. //
  1416. // Notes:
  1417. // This function first look at the [Languages] section in the INF file to find out the
  1418. // source directory (in the CD-ROM) for the language to be installed.
  1419. // From that directory, do:
  1420. // 1. install the MUI files for the components listed in the [Components] section,
  1421. // 2. Enumarate every file in that direcotry to:
  1422. // Check if the same file exists in directories in DirNames. If yes, this means we have to copy
  1423. // the mui file to that particular direcotry. Otherwise, copy the file to the FALLBACK directory.
  1424. //
  1425. ////////////////////////////////////////////////////////////////////////////////////
  1426. BOOL CopyFiles(HWND hWnd, LPTSTR Languages)
  1427. {
  1428. LPTSTR Language;
  1429. HANDLE hFile;
  1430. HWND hStatic;
  1431. TCHAR lpStatus[ BUFFER_SIZE ];
  1432. TCHAR lpLangText[ BUFFER_SIZE ];
  1433. TCHAR szSource[ MAX_PATH ] = {0}; // The source directory for a particular language
  1434. TCHAR szTarget[ MAX_PATH ];
  1435. TCHAR szTemp[ MAX_PATH ];
  1436. TCHAR szOriginalFileName[ MAX_PATH ];
  1437. TCHAR szFileNameBeforeRenamed[ MAX_PATH], szFileNameCopied[MAX_PATH];
  1438. TCHAR szFileRenamed[MAX_PATH];
  1439. DIAMOND_PACKET diamond;
  1440. BOOL CreateFailure = FALSE;
  1441. BOOL CopyOK=TRUE;
  1442. BOOL bFileWithNoMuiExt=FALSE;
  1443. BOOL FileCopied = FALSE;
  1444. BOOL bSpecialDirectory=FALSE;
  1445. BOOL bRename=FALSE;
  1446. WIN32_FIND_DATA FindFileData;
  1447. int FoundMore = 1;
  1448. int Dirnum = 0;
  1449. int iLen;
  1450. int NotDeleted = 0;
  1451. int i;
  1452. TCHAR dir[_MAX_DIR];
  1453. TCHAR fname[_MAX_FNAME];
  1454. TCHAR ext[_MAX_EXT];
  1455. LONG_PTR lppArgs[3];
  1456. HRESULT hresult;
  1457. MSG msg;
  1458. if (!Languages)
  1459. {
  1460. return FALSE;
  1461. }
  1462. //
  1463. // we need to try to copy for each language to be installed the file
  1464. //
  1465. Language = Languages;
  1466. #ifndef MUI_MAGIC
  1467. if (!g_bNoUI)
  1468. {
  1469. hStatic = GetDlgItem(ghProgDialog, IDC_STATUS);
  1470. }
  1471. while (*Language)
  1472. {
  1473. //
  1474. // Find the directory in which the sourcefile for given language should be
  1475. //
  1476. GetPrivateProfileString( MUI_LANGUAGES_SECTION,
  1477. Language,
  1478. TEXT("DEFAULT"),
  1479. szSource,
  1480. (sizeof(szSource)/sizeof(TCHAR)),
  1481. g_szMUIInfoFilePath );
  1482. //
  1483. // Install Fusion MUI assemblies
  1484. //
  1485. if (gpfnSxsInstallW)
  1486. {
  1487. TCHAR pszLogFile[BUFFER_SIZE];
  1488. if ( !DeleteSideBySideMUIAssemblyIfExisted(Language, pszLogFile))
  1489. {
  1490. TCHAR errInfo[BUFFER_SIZE];
  1491. //*STRSAFE* swprintf(errInfo, TEXT("Uninstall existing assemblies based on %s before new installation failed\n"), pszLogFile);
  1492. hresult = StringCchPrintf(errInfo , ARRAYSIZE(errInfo), TEXT("Uninstall existing assemblies based on %s before new installation failed\n"), pszLogFile);
  1493. if (!SUCCEEDED(hresult))
  1494. {
  1495. return FALSE;
  1496. }
  1497. OutputDebugString(errInfo);
  1498. }
  1499. if (GetFileAttributes(pszLogFile) != 0xFFFFFFFF)
  1500. {
  1501. DeleteFile(pszLogFile); // no use anyway
  1502. }
  1503. TCHAR szFusionAssemblyPath[BUFFER_SIZE];
  1504. PathCombine(szFusionAssemblyPath, g_szMUISetupFolder, szSource);
  1505. PathAppend(szFusionAssemblyPath, g_szPlatformPath);
  1506. PathAppend(szFusionAssemblyPath, TEXT("ASMS"));
  1507. SXS_INSTALLW SxsInstallInfo = {sizeof(SxsInstallInfo)};
  1508. SXS_INSTALL_REFERENCEW Reference = {sizeof(Reference)};
  1509. Reference.guidScheme = SXS_INSTALL_REFERENCE_SCHEME_OPAQUESTRING;
  1510. Reference.lpIdentifier = MUISETUP_ASSEMBLY_INSTALLATION_REFERENCE_IDENTIFIER;
  1511. SxsInstallInfo.dwFlags = SXS_INSTALL_FLAG_REPLACE_EXISTING |
  1512. SXS_INSTALL_FLAG_REFERENCE_VALID |
  1513. SXS_INSTALL_FLAG_CODEBASE_URL_VALID |
  1514. SXS_INSTALL_FLAG_LOG_FILE_NAME_VALID |
  1515. SXS_INSTALL_FLAG_FROM_DIRECTORY_RECURSIVE;
  1516. SxsInstallInfo.lpReference = &Reference;
  1517. SxsInstallInfo.lpLogFileName = pszLogFile;
  1518. SxsInstallInfo.lpManifestPath = szFusionAssemblyPath;
  1519. SxsInstallInfo.lpCodebaseURL = SxsInstallInfo.lpManifestPath;
  1520. if ( !gpfnSxsInstallW(&SxsInstallInfo))
  1521. {
  1522. TCHAR errInfo[BUFFER_SIZE];
  1523. //*STRSAFE* swprintf(errInfo, TEXT("Assembly Installation of %s failed. Please refer Eventlog for more information"), szFusionAssemblyPath);
  1524. hresult = StringCchPrintf(errInfo , ARRAYSIZE(errInfo), TEXT("Assembly Installation of %s failed. Please refer Eventlog for more information"), szFusionAssemblyPath);
  1525. if (!SUCCEEDED(hresult))
  1526. {
  1527. return FALSE;
  1528. }
  1529. OutputDebugString(errInfo);
  1530. }
  1531. }
  1532. GetLanguageGroupDisplayName((LANGID)_tcstol(Language, NULL, 16), lpLangText, ARRAYSIZE(lpLangText)-1);
  1533. lppArgs[0] = (LONG_PTR)lpLangText;
  1534. //
  1535. // Try installing component satellite DLLs
  1536. //
  1537. if (!g_bNoUI)
  1538. {
  1539. FormatStringFromResource(lpStatus, sizeof(lpStatus)/sizeof(TCHAR), ghInstance, IDS_INSTALLING_COMP_MUI, lppArgs);
  1540. SetWindowText(hStatic, lpStatus);
  1541. }
  1542. if (!InstallComponentsMUIFiles(szSource, NULL, TRUE))
  1543. {
  1544. #ifndef IGNORE_COPY_ERRORS
  1545. DeleteFiles(Languages,&NotDeleted);
  1546. return FALSE;
  1547. #endif
  1548. }
  1549. //
  1550. // Output what is being installed on the progress dialog box
  1551. //
  1552. if (!g_bNoUI)
  1553. {
  1554. LoadString(ghInstance, IDS_INSTALLING, lpStatus, ARRAYSIZE(lpStatus)-1);
  1555. FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  1556. lpStatus,
  1557. 0,
  1558. 0,
  1559. lpStatus,
  1560. ARRAYSIZE(lpStatus)-1,
  1561. (va_list *)lppArgs);
  1562. SetWindowText(hStatic, lpStatus);
  1563. }
  1564. //
  1565. // find first file in language subdirectory
  1566. //
  1567. //*STRSAFE* _tcscpy(szTemp,szSource);
  1568. hresult = StringCchCopy(szTemp , ARRAYSIZE(szTemp), szSource);
  1569. if (!SUCCEEDED(hresult))
  1570. {
  1571. return FALSE;
  1572. }
  1573. // szSource = g_szMUISetupFolder\szSource\tchPlatfromPath
  1574. // e.g. szSource = "g_szMUISetupFolder\JPN.MUI\i386\"
  1575. //*STRSAFE* _tcscpy(szSource,g_szMUISetupFolder);
  1576. hresult = StringCchCopy(szSource , ARRAYSIZE(szSource), g_szMUISetupFolder);
  1577. if (!SUCCEEDED(hresult))
  1578. {
  1579. return FALSE;
  1580. }
  1581. //*STRSAFE* _tcscat(szSource,szTemp);
  1582. hresult = StringCchCat(szSource , ARRAYSIZE(szSource), szTemp);
  1583. if (!SUCCEEDED(hresult))
  1584. {
  1585. return FALSE;
  1586. }
  1587. //*STRSAFE* _tcscat(szSource, TEXT("\\"));
  1588. hresult = StringCchCat(szSource , ARRAYSIZE(szSource), TEXT("\\"));
  1589. if (!SUCCEEDED(hresult))
  1590. {
  1591. return FALSE;
  1592. }
  1593. //*STRSAFE* _tcscat(szSource, g_szPlatformPath); // i386 or alpha
  1594. hresult = StringCchCat(szSource , ARRAYSIZE(szSource), g_szPlatformPath);
  1595. if (!SUCCEEDED(hresult))
  1596. {
  1597. return FALSE;
  1598. }
  1599. // szTemp = szSource + "*.*"
  1600. // e.g. szTemp = "g_szMUISetupFolder\JPN.MUI\i386\*.*"
  1601. //*STRSAFE* _tcscpy(szTemp,szSource);
  1602. hresult = StringCchCopy(szTemp , ARRAYSIZE(szTemp), szSource);
  1603. if (!SUCCEEDED(hresult))
  1604. {
  1605. return FALSE;
  1606. }
  1607. //*STRSAFE* _tcscat(szTemp,TEXT("*.*"));
  1608. hresult = StringCchCat(szTemp , ARRAYSIZE(szTemp), TEXT("*.*"));
  1609. if (!SUCCEEDED(hresult))
  1610. {
  1611. return FALSE;
  1612. }
  1613. FoundMore = 1; // reset foundmore for next language.
  1614. hFile = FindFirstFile( szTemp, &FindFileData );
  1615. if (INVALID_HANDLE_VALUE == hFile)
  1616. return FALSE;
  1617. //*STRSAFE* _tcscpy(szTemp, TEXT(""));
  1618. hresult = StringCchCopy(szTemp , ARRAYSIZE(szTemp), TEXT(""));
  1619. if (!SUCCEEDED(hresult))
  1620. {
  1621. FindClose(hFile);
  1622. return FALSE;
  1623. }
  1624. while (FoundMore)
  1625. {
  1626. CreateFailure=FALSE;
  1627. FileCopied=FALSE;
  1628. if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  1629. {
  1630. //
  1631. // Reset diamond stuff for the new file
  1632. //
  1633. Muisetup_DiamondReset(&diamond);
  1634. //
  1635. // Check if it's a compressed file or not
  1636. //
  1637. Muisetup_CheckForExpandedFile( szSource,
  1638. FindFileData.cFileName,
  1639. szOriginalFileName,
  1640. &diamond );
  1641. if (IsFileBeRenamed(szOriginalFileName,szFileRenamed))
  1642. {
  1643. //*STRSAFE* _tcscpy(szFileNameBeforeRenamed,szOriginalFileName);
  1644. hresult = StringCchCopy(szFileNameBeforeRenamed , ARRAYSIZE(szFileNameBeforeRenamed), szOriginalFileName);
  1645. if (!SUCCEEDED(hresult))
  1646. {
  1647. FindClose(hFile);
  1648. return FALSE;
  1649. }
  1650. //*STRSAFE* _tcscpy(szOriginalFileName,szFileRenamed);
  1651. hresult = StringCchCopy(szOriginalFileName , ARRAYSIZE(szOriginalFileName), szFileRenamed);
  1652. if (!SUCCEEDED(hresult))
  1653. {
  1654. FindClose(hFile);
  1655. return FALSE;
  1656. }
  1657. bRename=TRUE;
  1658. }
  1659. else if (IsFileInRenameTable(szOriginalFileName))
  1660. {
  1661. // Skip this file because a file be renamed/to be renamed with the same name.
  1662. // Fix bug#:443196
  1663. FoundMore = FindNextFile( hFile, &FindFileData );
  1664. continue;
  1665. }
  1666. else
  1667. {
  1668. bRename=FALSE;
  1669. }
  1670. // e.g. szTemp = "shell32.dll"
  1671. //*STRSAFE* _tcscpy(szTemp, szOriginalFileName); //////////////
  1672. hresult = StringCchCopy(szTemp , ARRAYSIZE(szTemp), szOriginalFileName);
  1673. if (!SUCCEEDED(hresult))
  1674. {
  1675. FindClose(hFile);
  1676. return FALSE;
  1677. }
  1678. FileCopied=FALSE;
  1679. for (Dirnum=1; (_tcslen(DirNames[Dirnum])>0); Dirnum++ )
  1680. {
  1681. //
  1682. // see where this file has to go
  1683. //
  1684. pfnGetWindowsDir( szTarget, MAX_PATH);
  1685. // e.g. szTarget = "c:\winnt\system32\wbem"
  1686. //*STRSAFE* _tcscat(szTarget, DirNames[Dirnum]);
  1687. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), DirNames[Dirnum]);
  1688. if (!SUCCEEDED(hresult))
  1689. {
  1690. FindClose(hFile);
  1691. return FALSE;
  1692. }
  1693. if (_tcscmp(DirNames[Dirnum], TEXT("\\")))
  1694. {
  1695. //*STRSAFE* _tcscat(szTarget, TEXT("\\"));
  1696. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("\\"));
  1697. if (!SUCCEEDED(hresult))
  1698. {
  1699. FindClose(hFile);
  1700. return FALSE;
  1701. }
  1702. }
  1703. bFileWithNoMuiExt = FALSE;
  1704. //*STRSAFE* _tcscpy(szTemp, szOriginalFileName); //remove .mui if it's .mui ////////
  1705. hresult = StringCchCopy(szTemp , ARRAYSIZE(szTemp), szOriginalFileName);
  1706. if (!SUCCEEDED(hresult))
  1707. {
  1708. FindClose(hFile);
  1709. return FALSE;
  1710. }
  1711. iLen = _tcslen(szTemp);
  1712. if (iLen > 4)
  1713. {
  1714. if (_tcsicmp(&szTemp[iLen - 4], TEXT(".mui")) == 0)
  1715. {
  1716. *(szTemp + iLen - 4) = 0;
  1717. }
  1718. else
  1719. {
  1720. bFileWithNoMuiExt = TRUE;
  1721. }
  1722. }
  1723. //*STRSAFE* _tcscat(szTarget, szTemp);
  1724. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), szTemp);
  1725. if (!SUCCEEDED(hresult))
  1726. {
  1727. FindClose(hFile);
  1728. return FALSE;
  1729. }
  1730. //
  1731. // Check the file with the same name (with the .mui extension) exist in the
  1732. // system directory. If yes, this means that we need to copy the mui file.
  1733. //
  1734. if (FileExists(szTarget))
  1735. {
  1736. //
  1737. // need to copy this file to the directory
  1738. //
  1739. FileCopied = TRUE;
  1740. //
  1741. // copy filename in szTemp and directory in szTarget
  1742. //
  1743. _tsplitpath( szTarget, szTemp, dir, fname, ext );
  1744. //*STRSAFE* _tcscpy(szTarget, szTemp); // drive name
  1745. hresult = StringCchCopy(szTarget , ARRAYSIZE(szTarget), szTemp);
  1746. if (!SUCCEEDED(hresult))
  1747. {
  1748. FindClose(hFile);
  1749. return FALSE;
  1750. }
  1751. //*STRSAFE* _tcscat(szTarget, dir); // directory name
  1752. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), dir);
  1753. if (!SUCCEEDED(hresult))
  1754. {
  1755. FindClose(hFile);
  1756. return FALSE;
  1757. }
  1758. //
  1759. //now szTarget = Directory, szTemp = filename
  1760. //
  1761. //*STRSAFE* _tcscat(szTarget, MUIDIR); // append MUI to directory
  1762. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), MUIDIR);
  1763. if (!SUCCEEDED(hresult))
  1764. {
  1765. FindClose(hFile);
  1766. return FALSE;
  1767. }
  1768. if (!MakeDir(szTarget)) // if the MUI dir doesn't exist yet, create it.
  1769. {
  1770. MakeDirFailed(szTarget);
  1771. CreateFailure = TRUE;
  1772. }
  1773. //*STRSAFE* _tcscat(szTarget, TEXT("\\"));
  1774. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("\\"));
  1775. if (!SUCCEEDED(hresult))
  1776. {
  1777. FindClose(hFile);
  1778. return FALSE;
  1779. }
  1780. //*STRSAFE* _tcscat(szTarget, Language); // add Language Identifier (from MUI.INF, e.g., 0407)
  1781. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), Language);
  1782. if (!SUCCEEDED(hresult))
  1783. {
  1784. FindClose(hFile);
  1785. return FALSE;
  1786. }
  1787. if (!FileExists(szTarget)) // if the directory doesn't exist yet
  1788. {
  1789. if (!MakeDir(szTarget)) // if the LANGID dir doesn't exist yet, create it.
  1790. {
  1791. MakeDirFailed(szTarget);
  1792. CreateFailure=TRUE;
  1793. }
  1794. }
  1795. //*STRSAFE* _tcscat(szTarget, TEXT("\\")); // append \ /
  1796. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("\\"));
  1797. if (!SUCCEEDED(hresult))
  1798. {
  1799. FindClose(hFile);
  1800. return FALSE;
  1801. }
  1802. if (bRename)
  1803. {
  1804. //*STRSAFE* _tcscpy(szFileNameCopied,szTarget);
  1805. hresult = StringCchCopy(szFileNameCopied , ARRAYSIZE(szFileNameCopied), szTarget);
  1806. if (!SUCCEEDED(hresult))
  1807. {
  1808. FindClose(hFile);
  1809. return FALSE;
  1810. }
  1811. //*STRSAFE* _tcscat(szFileNameCopied,szFileNameBeforeRenamed);
  1812. hresult = StringCchCat(szFileNameCopied , ARRAYSIZE(szFileNameCopied), szFileNameBeforeRenamed);
  1813. if (!SUCCEEDED(hresult))
  1814. {
  1815. FindClose(hFile);
  1816. return FALSE;
  1817. }
  1818. }
  1819. //*STRSAFE* _tcscat(szTarget, szOriginalFileName); // append filename
  1820. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), szOriginalFileName);
  1821. if (!SUCCEEDED(hresult))
  1822. {
  1823. FindClose(hFile);
  1824. return FALSE;
  1825. }
  1826. //*STRSAFE* _tcscpy(szTemp, szSource);
  1827. hresult = StringCchCopy(szTemp , ARRAYSIZE(szTemp), szSource);
  1828. if (!SUCCEEDED(hresult))
  1829. {
  1830. FindClose(hFile);
  1831. return FALSE;
  1832. }
  1833. //*STRSAFE* _tcscat(szTemp, FindFileData.cFileName);
  1834. hresult = StringCchCat(szTemp , ARRAYSIZE(szTemp), FindFileData.cFileName);
  1835. if (!SUCCEEDED(hresult))
  1836. {
  1837. FindClose(hFile);
  1838. return FALSE;
  1839. }
  1840. if (!CreateFailure)
  1841. {
  1842. if (!Muisetup_CopyFile(szTemp, szTarget, &diamond, bRename? szFileNameBeforeRenamed:NULL))
  1843. {
  1844. CopyFileFailed(szTarget,0);
  1845. CreateFailure = TRUE;
  1846. CopyOK = FALSE;
  1847. }
  1848. else
  1849. {
  1850. if (!g_bNoUI)
  1851. {
  1852. SendMessage(ghProgress, PBM_DELTAPOS, (WPARAM)(1), 0);
  1853. }
  1854. //
  1855. // Diamond decompression doesn't rename correctly
  1856. //
  1857. /*
  1858. if (bRename)
  1859. {
  1860. MoveFileEx(szFileNameCopied,szTarget,MOVEFILE_REPLACE_EXISTING);
  1861. }
  1862. */
  1863. }
  1864. }
  1865. } // if fileexists
  1866. } // of for
  1867. //
  1868. // the file was not found in any of the known MUI targets -> fallback.
  1869. // Simple hack for FAXUI.DLL to be copied to the fallback directory as well.
  1870. //
  1871. bSpecialDirectory=FALSE;
  1872. for (i = 0; i < ARRAYSIZE(g_szSpecialFiles); i++)
  1873. {
  1874. if (_tcsicmp(szOriginalFileName, g_szSpecialFiles[i]) == 0)
  1875. {
  1876. bSpecialDirectory=TRUE;
  1877. }
  1878. }
  1879. if ( ( (FileCopied != TRUE) && (!IsDoNotFallBack(szOriginalFileName))) ||
  1880. (_tcsicmp(szOriginalFileName, TEXT("faxui.dll.mui")) == 0) )
  1881. {
  1882. pfnGetWindowsDir(szTarget, MAX_PATH); //%windir% //
  1883. //*STRSAFE* _tcscat(szTarget, TEXT("\\"));
  1884. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("\\"));
  1885. if (!SUCCEEDED(hresult))
  1886. {
  1887. FindClose(hFile);
  1888. return FALSE;
  1889. }
  1890. //
  1891. // If the file couldn't be found in any of the above, and it's extension
  1892. // doesn't contain .mui, then copy it to %windir%\system32
  1893. // szTemp holds the filename.
  1894. //
  1895. if (bSpecialDirectory)
  1896. {
  1897. // e.g. szTarget = "c:\winnt\system32\";
  1898. //*STRSAFE* _tcscat(szTarget, TEXT("system32\\"));
  1899. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("system32\\"));
  1900. if (!SUCCEEDED(hresult))
  1901. {
  1902. FindClose(hFile);
  1903. return FALSE;
  1904. }
  1905. }
  1906. // e.g. szTarget = "c:\winnt\system32\MUI" (when bSpecialDirectory = TRUE) or "c:\winnt\MUI"
  1907. //*STRSAFE* _tcscat(szTarget, MUIDIR); // \MUI //
  1908. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), MUIDIR);
  1909. if (!SUCCEEDED(hresult))
  1910. {
  1911. FindClose(hFile);
  1912. return FALSE;
  1913. }
  1914. if (!MakeDir(szTarget)) // if the MUI dir doesn't exist yet, create it.
  1915. {
  1916. MakeDirFailed(szTarget);
  1917. CreateFailure = TRUE;
  1918. }
  1919. if (!bSpecialDirectory)
  1920. {
  1921. // e.g. szTarget = "C:\winnt\MUI\FALLBACK"
  1922. //*STRSAFE* _tcscat(szTarget, TEXT("\\"));
  1923. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("\\"));
  1924. if (!SUCCEEDED(hresult))
  1925. {
  1926. FindClose(hFile);
  1927. return FALSE;
  1928. }
  1929. //*STRSAFE* _tcscat(szTarget, TEXT("FALLBACK")); // FALLBACK
  1930. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("FALLBACK"));
  1931. if (!SUCCEEDED(hresult))
  1932. {
  1933. FindClose(hFile);
  1934. return FALSE;
  1935. }
  1936. if (!MakeDir(szTarget)) // if the MUI dir doesn't exist yet, create it.
  1937. {
  1938. MakeDirFailed(szTarget);
  1939. CreateFailure = TRUE;
  1940. }
  1941. }
  1942. //*STRSAFE* _tcscat(szTarget, TEXT("\\")); // \ //
  1943. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("\\"));
  1944. if (!SUCCEEDED(hresult))
  1945. {
  1946. FindClose(hFile);
  1947. return FALSE;
  1948. }
  1949. // e.g. szTarget = "c:\winnt\system32\MUI\0411" (when bSpecialDirectory = TRUE) or "c:\winnt\MUI\FALLBACK\0411"
  1950. //*STRSAFE* _tcscat(szTarget, Language); // add Language Identifier (from MUI.INF, e.g., 0407)
  1951. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), Language);
  1952. if (!SUCCEEDED(hresult))
  1953. {
  1954. FindClose(hFile);
  1955. return FALSE;
  1956. }
  1957. if (!MakeDir(szTarget)) // if the MUI dir doesn't exist yet, create it.
  1958. {
  1959. MakeDirFailed(szTarget);
  1960. CreateFailure = TRUE;
  1961. }
  1962. //*STRSAFE* _tcscat(szTarget, TEXT("\\")); // \ //
  1963. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("\\"));
  1964. if (!SUCCEEDED(hresult))
  1965. {
  1966. FindClose(hFile);
  1967. return FALSE;
  1968. }
  1969. //*STRSAFE* _tcscat(szTarget, szOriginalFileName); // filename
  1970. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), szOriginalFileName);
  1971. if (!SUCCEEDED(hresult))
  1972. {
  1973. FindClose(hFile);
  1974. return FALSE;
  1975. }
  1976. //*STRSAFE* _tcscpy(szTemp, szSource);
  1977. hresult = StringCchCopy(szTemp , ARRAYSIZE(szTemp), szSource);
  1978. if (!SUCCEEDED(hresult))
  1979. {
  1980. FindClose(hFile);
  1981. return FALSE;
  1982. }
  1983. //*STRSAFE* _tcscat(szTemp, FindFileData.cFileName);
  1984. hresult = StringCchCat(szTemp , ARRAYSIZE(szTemp), FindFileData.cFileName);
  1985. if (!SUCCEEDED(hresult))
  1986. {
  1987. FindClose(hFile);
  1988. return FALSE;
  1989. }
  1990. if (!CreateFailure)
  1991. {
  1992. if (!Muisetup_CopyFile(szTemp, szTarget, &diamond, bRename? szFileNameBeforeRenamed:NULL))
  1993. {
  1994. CopyFileFailed(szTarget,0);
  1995. CopyOK = FALSE;
  1996. }
  1997. else
  1998. {
  1999. if (!g_bNoUI)
  2000. {
  2001. SendMessage(ghProgress, PBM_DELTAPOS, (WPARAM)(1), 0);
  2002. }
  2003. }
  2004. }
  2005. if (CreateFailure == TRUE)
  2006. {
  2007. CopyOK=FALSE;
  2008. }
  2009. } // fallback case
  2010. } // of file not dir
  2011. FoundMore = FindNextFile( hFile, &FindFileData );
  2012. if (!g_bNoUI)
  2013. {
  2014. //
  2015. // Since this is a lengthy operation, we should
  2016. // peek and dispatch window messages here so
  2017. // that MUISetup dialog could repaint itself.
  2018. //
  2019. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  2020. {
  2021. if (msg.message == WM_QUIT)
  2022. {
  2023. return (FALSE);
  2024. }
  2025. TranslateMessage(&msg);
  2026. DispatchMessage(&msg);
  2027. }
  2028. }
  2029. } // of while
  2030. FindClose(hFile);
  2031. lppArgs[0] = (LONG_PTR)Language;
  2032. LogFormattedMessage(NULL, IDS_LANG_INSTALLED, lppArgs);
  2033. while (*Language++) // go to the next language and repeat
  2034. {
  2035. }
  2036. } // of while (*Language)
  2037. #ifndef IGNORE_COPY_ERRORS
  2038. if (!CopyOK)
  2039. {
  2040. // in silent mode, always just fail without prompting for user input
  2041. if (!g_bNoUI)
  2042. {
  2043. if (DoMessageBox(NULL, IDS_CANCEL_INSTALLATION, IDS_MAIN_TITLE, MB_YESNO) == IDNO)
  2044. {
  2045. DeleteFiles(Languages,&NotDeleted);
  2046. }
  2047. else
  2048. {
  2049. CopyOK = TRUE;
  2050. }
  2051. }
  2052. }
  2053. #endif
  2054. return CopyOK;
  2055. #else
  2056. TCHAR szMSIPath[MAX_PATH];
  2057. TCHAR szCmdLine[BUFFER_SIZE];
  2058. UINT uiMSIError = ERROR_SUCCESS;
  2059. TCHAR lpPath[BUFFER_SIZE] = {0};
  2060. TCHAR szCaption[MAX_PATH+1],szMsg[MAX_PATH+1];
  2061. BOOL bFileExist = FALSE;
  2062. UINT uiPrevMode = 0;
  2063. // kenhsu - in this codebranch here we include the code for MSI invocation instead of copying the files ourselves
  2064. // we will invoke the msi packages for installation one by one for each of the languages contained in the
  2065. // languages variable.
  2066. // Initialize MSI UI level (use Basic UI level if in GUI mode, otherwise, use no UI).
  2067. if (g_bNoUI)
  2068. {
  2069. MsiSetInternalUI((INSTALLUILEVEL)(INSTALLUILEVEL_NONE), NULL);
  2070. }
  2071. else
  2072. {
  2073. MsiSetInternalUI((INSTALLUILEVEL)(INSTALLUILEVEL_BASIC | INSTALLUILEVEL_PROGRESSONLY), NULL);
  2074. }
  2075. if (GetSystemWindowsDirectory(lpPath, MAX_PATH))
  2076. {
  2077. //*STRSAFE* _tcscat(lpPath, MSILOG_FILE);
  2078. hresult = StringCchCat(lpPath , ARRAYSIZE(lpPath), MSILOG_FILE);
  2079. if (!SUCCEEDED(hresult))
  2080. {
  2081. return FALSE;
  2082. }
  2083. MsiEnableLog(INSTALLLOGMODE_FATALEXIT |
  2084. INSTALLLOGMODE_ERROR |
  2085. INSTALLLOGMODE_WARNING |
  2086. INSTALLLOGMODE_INFO |
  2087. INSTALLLOGMODE_OUTOFDISKSPACE |
  2088. INSTALLLOGMODE_ACTIONSTART |
  2089. INSTALLLOGMODE_ACTIONDATA |
  2090. INSTALLLOGMODE_PROPERTYDUMP,
  2091. lpPath,
  2092. INSTALLLOGATTRIBUTES_APPEND | INSTALLLOGATTRIBUTES_FLUSHEACHLINE);
  2093. }
  2094. else
  2095. {
  2096. DEBUGMSGBOX(NULL, TEXT("Error getting windows directory, MSI logging has been disabled."), NULL, MB_OK);
  2097. MsiEnableLog(0, NULL, INSTALLLOGATTRIBUTES_APPEND);
  2098. }
  2099. while (*Language)
  2100. {
  2101. //*STRSAFE* _tcscpy(szMSIPath,g_szMUISetupFolder);
  2102. hresult = StringCchCopy(szMSIPath , ARRAYSIZE(szMSIPath), g_szMUISetupFolder);
  2103. if (!SUCCEEDED(hresult))
  2104. {
  2105. return FALSE;
  2106. }
  2107. //*STRSAFE* _tcscat(szMSIPath,Language);
  2108. hresult = StringCchCat(szMSIPath , ARRAYSIZE(szMSIPath), Language);
  2109. if (!SUCCEEDED(hresult))
  2110. {
  2111. return FALSE;
  2112. }
  2113. //*STRSAFE* _tcscat(szMSIPath,TEXT(".msi"));
  2114. hresult = StringCchCat(szMSIPath , ARRAYSIZE(szMSIPath), TEXT(".msi"));
  2115. if (!SUCCEEDED(hresult))
  2116. {
  2117. return FALSE;
  2118. }
  2119. //
  2120. // if we can't find files or media is missing, treat as error
  2121. //
  2122. uiPrevMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  2123. //
  2124. // First check to see if the MSI package is still located at the same place, since the user
  2125. // could have removed the CD, either intentionally or to install langpack for a MUI language
  2126. //
  2127. bFileExist = FileExists(szMSIPath);
  2128. while (!bFileExist)
  2129. {
  2130. if (g_bNoUI)
  2131. {
  2132. //
  2133. // log an error and fail the installation
  2134. //
  2135. lppArgs[0] = (LONG_PTR)szMSIPath;
  2136. LogFormattedMessage(ghInstance, IDS_CHANGE_CDROM3, lppArgs);
  2137. SetErrorMode(uiPrevMode);
  2138. return FALSE;
  2139. }
  2140. else
  2141. {
  2142. //
  2143. // prompt the user to reinsert the MUI CD so installation can continue, if user
  2144. // click cancel, cancel and fail the installation.
  2145. //
  2146. szCaption[0]=szMsg[0]=TEXT('\0');
  2147. LoadString(NULL, IDS_MAIN_TITLE, szCaption, MAX_PATH);
  2148. lppArgs[0] = (LONG_PTR)g_szCDLabel;
  2149. lppArgs[1] = (LONG_PTR)g_cdnumber;
  2150. FormatStringFromResource(szMsg, ARRAYSIZE(szMsg), ghInstance, IDS_CHANGE_CDROM2, lppArgs);
  2151. if (MESSAGEBOX(NULL, szMsg,szCaption, MB_YESNO | MB_ICONQUESTION) == IDNO)
  2152. {
  2153. lppArgs[0] = (LONG_PTR)szMSIPath;
  2154. LogFormattedMessage(ghInstance, IDS_CHANGE_CDROM3, lppArgs);
  2155. SetErrorMode(uiPrevMode);
  2156. return FALSE;
  2157. }
  2158. }
  2159. bFileExist = FileExists(szMSIPath);
  2160. }
  2161. SetErrorMode(uiPrevMode);
  2162. //
  2163. // Get the language display name in case we need to log it
  2164. //
  2165. GetPrivateProfileString( MUI_LANGUAGES_SECTION,
  2166. Language,
  2167. TEXT("DEFAULT"),
  2168. szSource,
  2169. (sizeof(szSource)/sizeof(TCHAR)),
  2170. g_szMUIInfoFilePath );
  2171. GetLanguageGroupDisplayName((LANGID)_tcstol(Language, NULL, 16), lpLangText, ARRAYSIZE(lpLangText)-1);
  2172. // invoke the MSI to do the installation - we do not set current user UI language and default user UI language here
  2173. //*STRSAFE* lstrcpy(szCmdLine, TEXT("CANCELBUTTON=\"Disable\" REBOOT=\"ReallySuppress\" CURRENTUSER=\"\" DEFAULTUSER=\"\""));
  2174. hresult = StringCchCopy(szCmdLine , ARRAYSIZE(szCmdLine), TEXT("CANCELBUTTON=\"Disable\" REBOOT=\"ReallySuppress\" CURRENTUSER=\"\" DEFAULTUSER=\"\""));
  2175. if (!SUCCEEDED(hresult))
  2176. {
  2177. return FALSE;
  2178. }
  2179. uiMSIError = MsiInstallProduct(szMSIPath, szCmdLine);
  2180. if ((ERROR_SUCCESS != uiMSIError) && (ERROR_SUCCESS_REBOOT_INITIATED != uiMSIError) && ((ERROR_SUCCESS_REBOOT_REQUIRED != uiMSIError)))
  2181. {
  2182. // log a message here indicating something went wrong
  2183. lppArgs[0] = (LONG_PTR) lpLangText;
  2184. lppArgs[1] = (LONG_PTR) szMSIPath;
  2185. lppArgs[2] = (LONG_PTR) uiMSIError;
  2186. LogFormattedMessage(NULL, IDS_ERROR_INSTALL_LANGMSI, lppArgs);
  2187. #ifdef MUI_DEBUG
  2188. TCHAR errorMsg[1024];
  2189. //*STRSAFE* wsprintf(errorMsg, TEXT("MSI Install failed, MSI path is %s, error is %d, language is %s"), szMSIPath, uiMSIError, lpLangText);
  2190. hresult = StringCchPrintf(errorMsg , ARRAYSIZE(errorMsg), TEXT("MSI Install failed, MSI path is %s, error is %d, language is %s"), szMSIPath, uiMSIError, lpLangText);
  2191. if (!SUCCEEDED(hresult))
  2192. {
  2193. return FALSE;
  2194. }
  2195. DEBUGMSGBOX(NULL, errorMsg, NULL, MB_OK);
  2196. #endif
  2197. CopyOK = FALSE;
  2198. }
  2199. else
  2200. {
  2201. lppArgs[0] = (LONG_PTR)Language;
  2202. LogFormattedMessage(NULL, IDS_LANG_INSTALLED, lppArgs);
  2203. }
  2204. if ((ERROR_SUCCESS_REBOOT_INITIATED == uiMSIError) || ((ERROR_SUCCESS_REBOOT_REQUIRED == uiMSIError)))
  2205. {
  2206. g_bReboot = TRUE;
  2207. }
  2208. while (*Language++) // go to the next language and repeat
  2209. {
  2210. }
  2211. } // of while (*Language)
  2212. return CopyOK;
  2213. #endif
  2214. }
  2215. ////////////////////////////////////////////////////////////////////////////////////
  2216. //
  2217. // Copy or remove muisetup related files
  2218. // Help file : %windir%\help
  2219. // Other files : %windir%\mui
  2220. //
  2221. ////////////////////////////////////////////////////////////////////////////////////
  2222. BOOL CopyRemoveMuiItself(BOOL bInstall)
  2223. {
  2224. //
  2225. // MUISETUP files need to be copied from MUI CD
  2226. //
  2227. TCHAR *TargetFiles[] = {
  2228. TEXT("muisetup.exe"),
  2229. TEXT("mui.inf"),
  2230. TEXT("eula.txt"),
  2231. TEXT("readme.txt"),
  2232. TEXT("relnotes.htm")
  2233. };
  2234. TCHAR szTargetPath[MAX_PATH+1], szTargetFile[MAX_PATH+1];
  2235. TCHAR szSrcFile[MAX_PATH+1];
  2236. TCHAR szHelpFile[MAX_PATH+1];
  2237. BOOL bRet = FALSE;
  2238. int i;
  2239. PathCombine(szTargetPath, g_szWinDir, MUIDIR);
  2240. if (MakeDir(szTargetPath))
  2241. {
  2242. //
  2243. // Copy over MUISETUP related files
  2244. //
  2245. for (i=0; i<ARRAYSIZE(TargetFiles); i++)
  2246. {
  2247. PathCombine(szTargetFile, szTargetPath, TargetFiles[i]);
  2248. PathCombine(szSrcFile, g_szMUISetupFolder, TargetFiles[i]);
  2249. if (bInstall)
  2250. {
  2251. RemoveFileReadOnlyAttribute(szTargetFile);
  2252. CopyFile(szSrcFile,szTargetFile,FALSE);
  2253. RemoveFileReadOnlyAttribute(szTargetFile);
  2254. }
  2255. else
  2256. {
  2257. if (FileExists(szTargetFile) &&
  2258. !MUI_DeleteFile(szTargetFile))
  2259. {
  2260. MoveFileEx(szTargetFile, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  2261. }
  2262. }
  2263. }
  2264. //
  2265. // Copy over muisetup help file
  2266. //
  2267. LoadString(NULL, IDS_HELPFILE,szHelpFile,MAX_PATH);
  2268. PathCombine(szTargetFile, g_szWinDir, HELPDIR);
  2269. PathAppend(szTargetFile, szHelpFile);
  2270. PathCombine(szSrcFile, g_szMUISetupFolder, szHelpFile);
  2271. if (bInstall)
  2272. {
  2273. RemoveFileReadOnlyAttribute(szTargetFile);
  2274. CopyFile(szSrcFile,szTargetFile,FALSE);
  2275. RemoveFileReadOnlyAttribute(szTargetFile);
  2276. }
  2277. else
  2278. {
  2279. if (FileExists(szTargetFile) &&
  2280. !MUI_DeleteFile(szTargetFile))
  2281. {
  2282. MoveFileEx(szTargetFile, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  2283. }
  2284. }
  2285. bRet = TRUE;
  2286. }
  2287. return bRet;
  2288. }
  2289. BOOL CompareMuisetupVersion(LPTSTR pszSrc,LPTSTR pszTarget)
  2290. {
  2291. BOOL bResult=TRUE;
  2292. ULONG ulHandle,ulHandle1,ulBytes,ulBytes1;
  2293. PVOID pvoidBuffer=NULL,pvoidBuffer1=NULL;
  2294. VS_FIXEDFILEINFO *lpvsInfo,*lpvsInfo1;
  2295. UINT unLen;
  2296. if ( (!pszSrc) || (!pszTarget))
  2297. {
  2298. bResult = FALSE;
  2299. goto endcompare;
  2300. }
  2301. ulBytes = GetFileVersionInfoSize( pszSrc, &ulHandle );
  2302. if ( ulBytes == 0 )
  2303. goto endcompare;
  2304. ulBytes1 = GetFileVersionInfoSize( pszTarget,&ulHandle1 );
  2305. if ( ulBytes1 == 0 )
  2306. goto endcompare;
  2307. pvoidBuffer=LocalAlloc(LMEM_FIXED,ulBytes+1);
  2308. if (!pvoidBuffer)
  2309. goto endcompare;
  2310. pvoidBuffer1=LocalAlloc(LMEM_FIXED,ulBytes1+1);
  2311. if (!pvoidBuffer1)
  2312. goto endcompare;
  2313. if ( !GetFileVersionInfo( pszSrc, ulHandle, ulBytes, pvoidBuffer ) )
  2314. goto endcompare;
  2315. if ( !GetFileVersionInfo( pszTarget, ulHandle1, ulBytes1, pvoidBuffer1 ) )
  2316. goto endcompare;
  2317. // Get fixed info block
  2318. if ( !VerQueryValue( pvoidBuffer,_T("\\"),(LPVOID *)&lpvsInfo ,&unLen ) )
  2319. goto endcompare;
  2320. if ( !VerQueryValue( pvoidBuffer1,_T("\\"),(LPVOID *)&lpvsInfo1,&unLen ) )
  2321. goto endcompare;
  2322. bResult = FALSE;
  2323. //
  2324. // We do nothing if major release version is different
  2325. //
  2326. // I.E We won't copy a new muisetup.exe over a old one if major release version of them are different
  2327. //
  2328. if ( (lpvsInfo->dwFileVersionMS == lpvsInfo1->dwFileVersionMS) &&
  2329. (lpvsInfo->dwFileVersionLS < lpvsInfo1->dwFileVersionLS))
  2330. {
  2331. bResult = TRUE;
  2332. }
  2333. endcompare:
  2334. if(pvoidBuffer)
  2335. LocalFree(pvoidBuffer);
  2336. if(pvoidBuffer1)
  2337. LocalFree(pvoidBuffer1);
  2338. return bResult;
  2339. }
  2340. BOOL IsAllLanguageRemoved(LPTSTR Language)
  2341. {
  2342. int mask[MAX_UI_LANG_GROUPS],nIdx;
  2343. LCID SystemUILangId,lgCheck;
  2344. BOOL bResult=FALSE;
  2345. if (! Language)
  2346. {
  2347. return FALSE;
  2348. }
  2349. if (gNumLanguages_Install > 0)
  2350. return bResult;
  2351. SystemUILangId=(LCID) gSystemUILangId;
  2352. for ( nIdx=0; nIdx<g_UILanguageGroup.iCount;nIdx++)
  2353. {
  2354. if ( gSystemUILangId == g_UILanguageGroup.lcid[nIdx])
  2355. {
  2356. mask[nIdx]=1;
  2357. }
  2358. else
  2359. {
  2360. mask[nIdx]=0;
  2361. }
  2362. }
  2363. while (*Language)
  2364. {
  2365. lgCheck = (LCID)_tcstol(Language,NULL,16);
  2366. for ( nIdx=0; nIdx<g_UILanguageGroup.iCount;nIdx++)
  2367. {
  2368. if ( lgCheck == g_UILanguageGroup.lcid[nIdx])
  2369. {
  2370. mask[nIdx]=1;
  2371. break;
  2372. }
  2373. }
  2374. while (*Language++)
  2375. {
  2376. }
  2377. }
  2378. bResult=TRUE;
  2379. for ( nIdx=0; nIdx<g_UILanguageGroup.iCount;nIdx++)
  2380. {
  2381. if ( mask[nIdx] == 0)
  2382. {
  2383. bResult = FALSE;
  2384. break;
  2385. }
  2386. }
  2387. return bResult;
  2388. }
  2389. void DoRemoveFiles(LPTSTR szDirToDelete, int* pnNotDeleted)
  2390. {
  2391. // File wildcard pattern.
  2392. TCHAR szTarget[MAX_PATH];
  2393. // File to be deleted.
  2394. TCHAR szFileName[MAX_PATH];
  2395. // Sub-directory name
  2396. TCHAR szSubDirName[MAX_PATH];
  2397. int FoundMore = 1;
  2398. HANDLE hFile;
  2399. WIN32_FIND_DATA FindFileData;
  2400. MSG msg;
  2401. HRESULT hresult;
  2402. if ((!szDirToDelete) || (!pnNotDeleted))
  2403. {
  2404. return;
  2405. }
  2406. // e.g. szTarget = "c:\winnt\system32\Wbem\MUI\0404\*.*"
  2407. //*STRSAFE* _stprintf(szTarget, TEXT("%s\\*.*"), szDirToDelete);
  2408. hresult = StringCchPrintf(szTarget , ARRAYSIZE(szTarget), TEXT("%s\\*.*"), szDirToDelete);
  2409. if (!SUCCEEDED(hresult))
  2410. {
  2411. return;
  2412. }
  2413. hFile = FindFirstFile(szTarget, &FindFileData);
  2414. while (FoundMore)
  2415. {
  2416. if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  2417. {
  2418. //*STRSAFE* _tcscpy(szFileName, szDirToDelete);
  2419. hresult = StringCchCopy(szFileName , ARRAYSIZE(szFileName), szDirToDelete);
  2420. if (!SUCCEEDED(hresult))
  2421. {
  2422. FindClose(hFile);
  2423. return;
  2424. }
  2425. //*STRSAFE* _tcscat(szFileName, TEXT("\\"));
  2426. hresult = StringCchCat(szFileName , ARRAYSIZE(szFileName), TEXT("\\"));
  2427. if (!SUCCEEDED(hresult))
  2428. {
  2429. FindClose(hFile);
  2430. return;
  2431. }
  2432. //*STRSAFE* _tcscat(szFileName, FindFileData.cFileName);
  2433. hresult = StringCchCat(szFileName , ARRAYSIZE(szFileName), FindFileData.cFileName);
  2434. if (!SUCCEEDED(hresult))
  2435. {
  2436. FindClose(hFile);
  2437. return;
  2438. }
  2439. if (FileExists(szFileName))
  2440. {
  2441. // We should check if the said file is actually deleted
  2442. // If it's not the case, then we should post a defered deletion
  2443. //
  2444. if (!MUI_DeleteFile(szFileName))
  2445. {
  2446. (*pnNotDeleted)++;
  2447. MoveFileEx(szFileName, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  2448. }
  2449. }
  2450. SendMessage(ghProgress, PBM_DELTAPOS, (WPARAM)(1), 0);
  2451. } else
  2452. {
  2453. if (_tcscmp(FindFileData.cFileName, TEXT(".")) != 0 && _tcscmp(FindFileData.cFileName, TEXT("..")) != 0)
  2454. {
  2455. //*STRSAFE* _stprintf(szSubDirName, TEXT("%s\\%s"), szDirToDelete, FindFileData.cFileName);
  2456. hresult = StringCchPrintf(szSubDirName , ARRAYSIZE(szSubDirName), TEXT("%s\\%s"), szDirToDelete, FindFileData.cFileName);
  2457. if (!SUCCEEDED(hresult))
  2458. {
  2459. FindClose(hFile);
  2460. return ;
  2461. }
  2462. DoRemoveFiles(szSubDirName, pnNotDeleted);
  2463. }
  2464. }
  2465. //
  2466. // Since this is a lengthy operation, we should
  2467. // peek and dispatch window messages here so
  2468. // that MUISetup dialog could repaint itself.
  2469. //
  2470. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  2471. {
  2472. if (msg.message == WM_QUIT)
  2473. {
  2474. FindClose(hFile);
  2475. return;
  2476. }
  2477. TranslateMessage(&msg);
  2478. DispatchMessage(&msg);
  2479. }
  2480. FoundMore = FindNextFile( hFile, &FindFileData );
  2481. }
  2482. FindClose(hFile);
  2483. //
  2484. // If the directory is not empty, then we should post a defered deletion
  2485. // for the directory
  2486. //
  2487. if (!RemoveDirectory(szDirToDelete))
  2488. {
  2489. MoveFileEx(szDirToDelete, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  2490. }
  2491. }
  2492. BOOL DeleteFilesClassic(LPTSTR Language, int *lpNotDeleted)
  2493. {
  2494. TCHAR lpLangText[BUFFER_SIZE];
  2495. LONG_PTR lppArgs[3];
  2496. TCHAR lpStatus[BUFFER_SIZE];
  2497. HWND hStatic;
  2498. int Dirnum = 0;
  2499. TCHAR szTarget[MAX_PATH];
  2500. LPTSTR Langchk;
  2501. TCHAR szMuiDir[MAX_PATH];
  2502. TCHAR szFallbackDir[MAX_PATH];
  2503. HRESULT hresult;
  2504. if ((!Language) || (!lpNotDeleted))
  2505. {
  2506. return FALSE;
  2507. }
  2508. #ifndef MUI_MAGIC
  2509. if (!g_bNoUI)
  2510. {
  2511. hStatic = GetDlgItem(ghProgDialog, IDC_STATUS);
  2512. }
  2513. #endif
  2514. Langchk = Language;
  2515. *lpNotDeleted = 0;
  2516. GetLanguageGroupDisplayName((LANGID)_tcstol(Language, NULL, 16), lpLangText, ARRAYSIZE(lpLangText)-1);
  2517. lppArgs[0]= (LONG_PTR)lpLangText;
  2518. #ifndef MUI_MAGIC
  2519. //
  2520. // Output what is being uninstalled on the progress dialog box
  2521. //
  2522. if (!g_bNoUI)
  2523. {
  2524. FormatStringFromResource(lpStatus, sizeof(lpStatus)/sizeof(TCHAR), ghInstance, IDS_UNINSTALLING, lppArgs);
  2525. SetWindowText(hStatic, lpStatus);
  2526. }
  2527. #endif
  2528. //
  2529. // Remove all files under special directories (those directories listed under [Directories] in mui.inf.
  2530. //
  2531. for (Dirnum=1; (_tcslen(DirNames[Dirnum])>0); Dirnum++ )
  2532. {
  2533. // szTarget = "c:\winnt"
  2534. //*STRSAFE* _tcscpy(szTarget, g_szWinDir);
  2535. hresult = StringCchCopy(szTarget , ARRAYSIZE(szTarget), g_szWinDir);
  2536. if (!SUCCEEDED(hresult))
  2537. {
  2538. return FALSE;
  2539. }
  2540. // e.g. szTarget = "c:\winnt\system32\Wbem"
  2541. //*STRSAFE* _tcscat(szTarget, DirNames[Dirnum]);
  2542. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), DirNames[Dirnum]);
  2543. if (!SUCCEEDED(hresult))
  2544. {
  2545. return FALSE;
  2546. }
  2547. if (_tcscmp(DirNames[Dirnum], TEXT("\\")))
  2548. {
  2549. // e.g. szTarget = "c:\winnt\system32\Wbem\"
  2550. //*STRSAFE* _tcscat(szTarget, TEXT("\\"));
  2551. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("\\"));
  2552. if (!SUCCEEDED(hresult))
  2553. {
  2554. return FALSE;
  2555. }
  2556. }
  2557. // e.g. szTarget = "c:\winnt\system32\Wbem\MUI"
  2558. //*STRSAFE* _tcscat(szTarget, MUIDIR);
  2559. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), MUIDIR);
  2560. if (!SUCCEEDED(hresult))
  2561. {
  2562. return FALSE;
  2563. }
  2564. // e.g. szTarget = "c:\winnt\system32\Wbem\MUI\0404"
  2565. //*STRSAFE* _tcscat(szTarget, TEXT("\\"));
  2566. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("\\"));
  2567. if (!SUCCEEDED(hresult))
  2568. {
  2569. return FALSE;
  2570. }
  2571. //*STRSAFE* _tcscat(szTarget, Language);
  2572. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), Language);
  2573. if (!SUCCEEDED(hresult))
  2574. {
  2575. return FALSE;
  2576. }
  2577. DoRemoveFiles(szTarget, lpNotDeleted);
  2578. }
  2579. // Uninstall Component MUI Files.
  2580. // Note that we should do this before removing all files under FALLBACK directory,
  2581. // since we store compoent INF files under the FALLBACK directory.
  2582. InstallComponentsMUIFiles(NULL, Language, FALSE);
  2583. //
  2584. // Remove all files under FALLBACK directory.
  2585. //
  2586. // E.g. szTarget = "c:\winnt\mui"
  2587. //*STRSAFE* _tcscpy(szTarget, g_szWinDir);
  2588. hresult = StringCchCopy(szTarget , ARRAYSIZE(szTarget), g_szWinDir);
  2589. if (!SUCCEEDED(hresult))
  2590. {
  2591. return FALSE;
  2592. }
  2593. //*STRSAFE* _tcscat(szTarget, TEXT("\\"));
  2594. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("\\"));
  2595. if (!SUCCEEDED(hresult))
  2596. {
  2597. return FALSE;
  2598. }
  2599. //*STRSAFE* _tcscat(szTarget, MUIDIR);
  2600. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), MUIDIR);
  2601. if (!SUCCEEDED(hresult))
  2602. {
  2603. return FALSE;
  2604. }
  2605. //*STRSAFE* _tcscpy(szMuiDir, szTarget);
  2606. hresult = StringCchCopy(szMuiDir , ARRAYSIZE(szMuiDir), szTarget);
  2607. if (!SUCCEEDED(hresult))
  2608. {
  2609. return FALSE;
  2610. }
  2611. // E.g. szTarget = "c:\winnt\mui\FALLBACK"
  2612. //*STRSAFE* _tcscat(szTarget, TEXT("\\"));
  2613. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("\\"));
  2614. if (!SUCCEEDED(hresult))
  2615. {
  2616. return FALSE;
  2617. }
  2618. //*STRSAFE* _tcscat(szTarget, TEXT("FALLBACK"));
  2619. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("FALLBACK"));
  2620. if (!SUCCEEDED(hresult))
  2621. {
  2622. return FALSE;
  2623. }
  2624. //*STRSAFE* _tcscpy(szFallbackDir, szTarget);
  2625. hresult = StringCchCopy(szFallbackDir , ARRAYSIZE(szFallbackDir), szTarget);
  2626. if (!SUCCEEDED(hresult))
  2627. {
  2628. return FALSE;
  2629. }
  2630. //*STRSAFE* _tcscat(szTarget, TEXT("\\"));
  2631. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), TEXT("\\"));
  2632. if (!SUCCEEDED(hresult))
  2633. {
  2634. return FALSE;
  2635. }
  2636. // E.g. szTarget = "c:\winnt\mui\FALLBACK\0404"
  2637. //*STRSAFE* _tcscat(szTarget, Language);
  2638. hresult = StringCchCat(szTarget , ARRAYSIZE(szTarget), Language);
  2639. if (!SUCCEEDED(hresult))
  2640. {
  2641. return FALSE;
  2642. }
  2643. DoRemoveFiles(szTarget, lpNotDeleted);
  2644. //
  2645. // Remove files listed in g_SpecialFiles
  2646. //
  2647. // e.g. szTarget = "c:\winnt\system32\mui\0411"
  2648. //*STRSAFE* wsprintf(szTarget, L"%s\\system32\\%s\\%s", g_szWinDir, MUIDIR, Language);
  2649. hresult = StringCchPrintf(szTarget , ARRAYSIZE(szTarget), TEXT("%s\\system32\\%s\\%s"), g_szWinDir, MUIDIR, Language);
  2650. if (!SUCCEEDED(hresult))
  2651. {
  2652. return FALSE;
  2653. }
  2654. DoRemoveFiles(szTarget, lpNotDeleted);
  2655. lppArgs[0] = (LONG_PTR)Language;
  2656. LogFormattedMessage(NULL, IDS_LANG_UNINSTALLED, lppArgs);
  2657. return TRUE;
  2658. }
  2659. ////////////////////////////////////////////////////////////////////////////////////
  2660. //
  2661. // DeleteFiles
  2662. //
  2663. // Deletes MUI files for the languages specified
  2664. //
  2665. // Parameters:
  2666. // [IN] Languages: a double-null terminated string which contains languages
  2667. // to be processed.
  2668. // [OUT] lpNotDeleted: The number of files to be deleted after reboot.
  2669. //
  2670. ////////////////////////////////////////////////////////////////////////////////////
  2671. BOOL DeleteFiles(LPTSTR Languages, int *lpNotDeleted)
  2672. {
  2673. LPTSTR Language,Langchk;
  2674. HWND hStatic;
  2675. TCHAR lpLangText[BUFFER_SIZE];
  2676. //TCHAR szTarget[MAX_PATH];
  2677. TCHAR szMuiDir[MAX_PATH];
  2678. TCHAR szFallbackDir[MAX_PATH];
  2679. BOOL bSuccess = TRUE;
  2680. LONG_PTR lppArgs[3];
  2681. int i;
  2682. HRESULT hresult;
  2683. if ((!Languages) || (!lpNotDeleted))
  2684. {
  2685. return FALSE;
  2686. }
  2687. Language = Langchk = Languages;
  2688. *lpNotDeleted = 0;
  2689. #ifndef MUI_MAGIC
  2690. if (!g_bNoUI)
  2691. {
  2692. hStatic = GetDlgItem(ghProgDialog, IDC_STATUS);
  2693. }
  2694. while (*Language)
  2695. {
  2696. if (!DeleteFilesClassic(Language, lpNotDeleted))
  2697. {
  2698. bSuccess = FALSE;
  2699. }
  2700. while (*Language++) // go to the next language and repeat
  2701. {
  2702. }
  2703. } // of while (*Language)
  2704. //
  2705. // Removes Fallback directory if all languages have been uninstalled.
  2706. //
  2707. if (!RemoveDirectory(szFallbackDir))
  2708. {
  2709. MoveFileEx(szFallbackDir, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  2710. }
  2711. //
  2712. // Removes MUI directory if all languages have been uninstalled and Fallback
  2713. // directory has been removed.
  2714. //
  2715. if (IsAllLanguageRemoved(Langchk))
  2716. {
  2717. CopyRemoveMuiItself(FALSE);
  2718. }
  2719. if (!RemoveDirectory(szMuiDir))
  2720. {
  2721. MoveFileEx(szMuiDir, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  2722. }
  2723. return bSuccess;
  2724. #else
  2725. UINT uiMSIError = ERROR_SUCCESS;
  2726. BOOL bFound = FALSE;
  2727. TCHAR lpPath[BUFFER_SIZE] = {0};
  2728. TCHAR szString[256];
  2729. // kenhsu - in this codebranch here we include the code for MSI invocation instead of copying the files ourselves
  2730. // we will invoke the msi packages for installation one by one for each of the languages contained in the
  2731. // languages variable.
  2732. // Initialize MSI UI level (use Basic UI level if in GUI mode, otherwise, use no UI).
  2733. if (g_bNoUI)
  2734. {
  2735. MsiSetInternalUI((INSTALLUILEVEL)(INSTALLUILEVEL_NONE), NULL);
  2736. }
  2737. else
  2738. {
  2739. MsiSetInternalUI((INSTALLUILEVEL)(INSTALLUILEVEL_BASIC | INSTALLUILEVEL_PROGRESSONLY), NULL);
  2740. }
  2741. if (GetSystemWindowsDirectory(lpPath, MAX_PATH))
  2742. {
  2743. //*STRSAFE* _tcscat(lpPath, MSILOG_FILE);
  2744. hresult = StringCchCat(lpPath , ARRAYSIZE(lpPath), MSILOG_FILE);
  2745. if (!SUCCEEDED(hresult))
  2746. {
  2747. return FALSE;
  2748. }
  2749. MsiEnableLog(INSTALLLOGMODE_FATALEXIT |
  2750. INSTALLLOGMODE_ERROR |
  2751. INSTALLLOGMODE_WARNING |
  2752. INSTALLLOGMODE_INFO |
  2753. INSTALLLOGMODE_OUTOFDISKSPACE |
  2754. INSTALLLOGMODE_ACTIONSTART |
  2755. INSTALLLOGMODE_ACTIONDATA |
  2756. INSTALLLOGMODE_PROPERTYDUMP,
  2757. lpPath,
  2758. INSTALLLOGATTRIBUTES_APPEND | INSTALLLOGATTRIBUTES_FLUSHEACHLINE);
  2759. }
  2760. else
  2761. {
  2762. DEBUGMSGBOX(NULL, TEXT("Error getting windows directory, MSI logging has been disabled."), NULL, MB_OK);
  2763. MsiEnableLog(0, NULL, INSTALLLOGATTRIBUTES_APPEND);
  2764. }
  2765. while (*Language)
  2766. {
  2767. TCHAR szProductCode[GUIDLENGTH] = { 0 };
  2768. GetLanguageGroupDisplayName((LANGID)_tcstol(Language, NULL, 16), lpLangText, ARRAYSIZE(lpLangText)-1);
  2769. // Get the product code here
  2770. bFound = GetMSIProductCode(Language, szProductCode, ARRAYSIZE(szProductCode));
  2771. #ifdef MUI_DEBUG
  2772. //*STRSAFE* wsprintf(szString, TEXT("lpLangText is: %s, szProductGUID is %s, Language is %s"), lpLangText, szProductCode, Language);
  2773. hresult = StringCchPrintf(szString , ARRAYSIZE(szString), TEXT("lpLangText is: %s, szProductGUID is %s, Language is %s"), lpLangText, szProductCode, Language);
  2774. if (!SUCCEEDED(hresult))
  2775. {
  2776. return FALSE;
  2777. }
  2778. DEBUGMSGBOX(NULL, szString, TEXT("DEBUG MESSAGE"), MB_OK);
  2779. #endif
  2780. if (TRUE == bFound)
  2781. {
  2782. INSTALLSTATE isProductState = MsiQueryProductState(szProductCode);
  2783. // debug code remove later
  2784. switch (isProductState)
  2785. {
  2786. case INSTALLSTATE_ABSENT:
  2787. //*STRSAFE* wsprintf(szString, TEXT("Installed state for language %s (lcid: %s, product code: %s) is INSTALLSTATE_ABSENT"), lpLangText, Language, szProductCode);
  2788. hresult = StringCchPrintf(szString , ARRAYSIZE(szString), TEXT("Installed state for language %s (lcid: %s, product code: %s) is INSTALLSTATE_ABSENT"), lpLangText, Language, szProductCode);
  2789. if (!SUCCEEDED(hresult))
  2790. {
  2791. return FALSE;
  2792. }
  2793. break;
  2794. case INSTALLSTATE_ADVERTISED:
  2795. //*STRSAFE* wsprintf(szString, TEXT("Installed state for language %s (lcid: %s, product code: %s) is INSTALLSTATE_ADVERTISED"), lpLangText, Language, szProductCode);
  2796. hresult = StringCchPrintf(szString , ARRAYSIZE(szString), TEXT("Installed state for language %s (lcid: %s, product code: %s) is INSTALLSTATE_ADVERTISED"), lpLangText, Language, szProductCode);
  2797. if (!SUCCEEDED(hresult))
  2798. {
  2799. return FALSE;
  2800. }
  2801. break;
  2802. case INSTALLSTATE_DEFAULT:
  2803. //*STRSAFE* wsprintf(szString, TEXT("Installed state for language %s (lcid: %s, product code: %s) is INSTALLSTATE_DEFAULT"), lpLangText, Language, szProductCode);
  2804. hresult = StringCchPrintf(szString , ARRAYSIZE(szString), TEXT("Installed state for language %s (lcid: %s, product code: %s) is INSTALLSTATE_DEFAULT"), lpLangText, Language, szProductCode);
  2805. if (!SUCCEEDED(hresult))
  2806. {
  2807. return FALSE;
  2808. }
  2809. break;
  2810. case INSTALLSTATE_INVALIDARG:
  2811. //*STRSAFE* wsprintf(szString, TEXT("Installed state for language %s (lcid: %s, product code: %s) is INSTALLSTATE_INVALIDARG"), lpLangText, Language, szProductCode);
  2812. hresult = StringCchPrintf(szString , ARRAYSIZE(szString), TEXT("Installed state for language %s (lcid: %s, product code: %s) is INSTALLSTATE_INVALIDARG"), lpLangText, Language, szProductCode);
  2813. if (!SUCCEEDED(hresult))
  2814. {
  2815. return FALSE;
  2816. }
  2817. break;
  2818. case INSTALLSTATE_UNKNOWN:
  2819. default:
  2820. //*STRSAFE* wsprintf(szString, TEXT("Installed state for language %s (lcid: %s, product code: %s) is INSTALLSTATE_UNKNOWN or an unknown value."), lpLangText, Language, szProductCode);
  2821. hresult = StringCchPrintf(szString , ARRAYSIZE(szString), TEXT("Installed state for language %s (lcid: %s, product code: %s) is INSTALLSTATE_UNKNOWN or an unknown value."), lpLangText, Language, szProductCode);
  2822. if (!SUCCEEDED(hresult))
  2823. {
  2824. return FALSE;
  2825. }
  2826. break;
  2827. }
  2828. LogMessage(szString);
  2829. // check here to see if the product is actually installed using MSI
  2830. if (INSTALLSTATE_DEFAULT == isProductState)
  2831. {
  2832. LogMessage(TEXT("MUI Installed using Windows Installer"));
  2833. // invoke the MSI to do the installation by configuring the product to an install state of 'absent'
  2834. uiMSIError = MsiConfigureProductEx(szProductCode, INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, TEXT("CANCELBUTTON=\"Disable\" REBOOT=\"ReallySuppress\""));
  2835. switch (uiMSIError)
  2836. {
  2837. case ERROR_SUCCESS:
  2838. case ERROR_SUCCESS_REBOOT_INITIATED:
  2839. case ERROR_SUCCESS_REBOOT_REQUIRED:
  2840. lppArgs[0] = (LONG_PTR)Language;
  2841. LogFormattedMessage(NULL, IDS_LANG_UNINSTALLED, lppArgs);
  2842. if ((ERROR_SUCCESS_REBOOT_INITIATED == uiMSIError) || ((ERROR_SUCCESS_REBOOT_REQUIRED == uiMSIError)))
  2843. {
  2844. g_bReboot = TRUE;
  2845. }
  2846. break;
  2847. default:
  2848. if (TRUE == g_bRunFromOSSetup)
  2849. {
  2850. LogFormattedMessage(NULL, IDS_NTOS_SETUP_MSI_ERROR, NULL);
  2851. // we are in OS setup, and MSI service is not available, we will manually remove the files
  2852. // we will also need to clear the registry keys for the installer logs
  2853. if (!DeleteFilesClassic(Language, lpNotDeleted))
  2854. {
  2855. // log a message here indicating something went wrong
  2856. lppArgs[0] = (LONG_PTR) Language;
  2857. lppArgs[1] = (LONG_PTR) szProductCode;
  2858. lppArgs[2] = (LONG_PTR) uiMSIError;
  2859. LogFormattedMessage(NULL, IDS_ERROR_UNINSTALL_LANGMSI, lppArgs);
  2860. bSuccess = FALSE;
  2861. }
  2862. }
  2863. else
  2864. {
  2865. // log a message here indicating something went wrong
  2866. lppArgs[0] = (LONG_PTR) Language;
  2867. lppArgs[1] = (LONG_PTR) szProductCode;
  2868. lppArgs[2] = (LONG_PTR) uiMSIError;
  2869. LogFormattedMessage(NULL, IDS_ERROR_UNINSTALL_LANGMSI, lppArgs);
  2870. bSuccess = FALSE;
  2871. }
  2872. break;
  2873. }
  2874. }
  2875. else
  2876. {
  2877. // this is a classic installation - we will try to remove it manually
  2878. LogFormattedMessage(NULL, IDS_MUI_OLD_SETUP, NULL);
  2879. if (!DeleteFilesClassic(Language, lpNotDeleted))
  2880. {
  2881. // log a message here indicating something went wrong
  2882. lppArgs[0] = (LONG_PTR) Language;
  2883. lppArgs[1] = (LONG_PTR) szProductCode;
  2884. lppArgs[2] = (LONG_PTR) uiMSIError;
  2885. LogFormattedMessage(NULL, IDS_ERROR_UNINSTALL_LANGMSI, lppArgs);
  2886. bSuccess = FALSE;
  2887. }
  2888. }
  2889. }
  2890. else
  2891. {
  2892. // log a message here indicating language is not installed (which should not happen really)
  2893. lppArgs[0] = (LONG_PTR) Language;
  2894. LogFormattedMessage(NULL, IDS_IS_NOT_INSTALLED_L, lppArgs);
  2895. bSuccess = FALSE;
  2896. }
  2897. while (*Language++) // go to the next language and repeat
  2898. {
  2899. }
  2900. } // of while (*Language)
  2901. return bSuccess;
  2902. #endif
  2903. }
  2904. ////////////////////////////////////////////////////////////////////////////////////
  2905. //
  2906. // MZStrLen
  2907. //
  2908. // Calculate the length of MULTI_SZ string
  2909. //
  2910. // the length is in bytes and includes extra terminal NULL, so the length >= 1 (TCHAR)
  2911. //
  2912. ////////////////////////////////////////////////////////////////////////////////////
  2913. UINT MZStrLen(LPTSTR lpszStr)
  2914. {
  2915. UINT i=0;
  2916. if (!lpszStr)
  2917. {
  2918. return i;
  2919. }
  2920. while (lpszStr && *lpszStr)
  2921. {
  2922. i += ((lstrlen(lpszStr)+1) * sizeof(TCHAR));
  2923. lpszStr += (lstrlen(lpszStr)+1);
  2924. }
  2925. //
  2926. // extra NULL
  2927. //
  2928. i += sizeof(TCHAR);
  2929. return i;
  2930. }
  2931. ////////////////////////////////////////////////////////////////////////////////////
  2932. //
  2933. // SetFontLinkValue
  2934. //
  2935. // Set necessary font link value into registry
  2936. //
  2937. // lpszLinkInfo = "Target","Link1","Link2",....
  2938. //
  2939. ////////////////////////////////////////////////////////////////////////////////////
  2940. BOOL SetFontLinkValue (LPTSTR lpszLinkInfo,BOOL *lpbFontLinkRegistryTouched)
  2941. {
  2942. const TCHAR szDeli[] = TEXT("\\\\");
  2943. TCHAR szStrBuf[FONTLINK_BUF_SIZE];
  2944. TCHAR szRegDataStr[FONTLINK_BUF_SIZE];
  2945. LPTSTR lpszDstStr,lpszSrcStr;
  2946. LPTSTR lpszFontName;
  2947. LPTSTR lpszTok;
  2948. DWORD dwType;
  2949. DWORD cbData;
  2950. HKEY hKey;
  2951. LONG rc;
  2952. BOOL bRet = FALSE;
  2953. HRESULT hresult;
  2954. int nSize;
  2955. if ((!lpszLinkInfo) || (!lpbFontLinkRegistryTouched))
  2956. {
  2957. bRet = FALSE;
  2958. goto Exit1;
  2959. }
  2960. lpszSrcStr = szStrBuf;
  2961. lpszTok = _tcstok(lpszLinkInfo,szDeli);
  2962. while (lpszTok)
  2963. {
  2964. //*STRSAFE* lstrcpy(lpszSrcStr,lpszTok);
  2965. hresult = StringCchCopy(lpszSrcStr , ARRAYSIZE(szStrBuf), lpszTok);
  2966. if (!SUCCEEDED(hresult))
  2967. {
  2968. bRet = FALSE;
  2969. goto Exit1;
  2970. }
  2971. lpszSrcStr += (lstrlen(lpszTok) + 1);
  2972. lpszTok = _tcstok(NULL,szDeli);
  2973. }
  2974. *lpszSrcStr = TEXT('\0');
  2975. //
  2976. // first token is base font name
  2977. //
  2978. lpszSrcStr = lpszFontName = szStrBuf;
  2979. if (! *lpszFontName)
  2980. {
  2981. //
  2982. // there is no link info needs to be processed
  2983. //
  2984. bRet = FALSE;
  2985. goto Exit1;
  2986. }
  2987. //
  2988. // point to first linked font
  2989. //
  2990. lpszSrcStr += (lstrlen(lpszSrcStr) + 1);
  2991. if (! *lpszSrcStr)
  2992. {
  2993. //
  2994. // no linked font
  2995. //
  2996. bRet = FALSE;
  2997. goto Exit1;
  2998. }
  2999. rc = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  3000. TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink"),
  3001. 0L,
  3002. NULL,
  3003. REG_OPTION_NON_VOLATILE,
  3004. KEY_READ | KEY_WRITE,
  3005. NULL,
  3006. &hKey,
  3007. NULL);
  3008. if (rc != ERROR_SUCCESS)
  3009. {
  3010. bRet = FALSE;
  3011. goto Exit1;
  3012. }
  3013. cbData = sizeof(szRegDataStr);
  3014. rc = RegQueryValueEx(hKey,
  3015. lpszFontName,
  3016. NULL,
  3017. &dwType,
  3018. (LPBYTE) szRegDataStr,
  3019. &cbData);
  3020. if (rc != ERROR_SUCCESS)
  3021. {
  3022. //
  3023. // case 1, this font's font link hasn't been set yet, or something wrong in old value
  3024. //
  3025. lpszDstStr = lpszSrcStr;
  3026. }
  3027. else
  3028. {
  3029. //
  3030. // case 2, this font's font link list has been there
  3031. //
  3032. // we need check if new font is defined in font list or not.
  3033. //
  3034. while (*lpszSrcStr)
  3035. {
  3036. lpszDstStr = szRegDataStr;
  3037. nSize = ARRAYSIZE(szRegDataStr);
  3038. while (*lpszDstStr)
  3039. {
  3040. if (lstrcmpi(lpszSrcStr,lpszDstStr) == 0)
  3041. {
  3042. break;
  3043. }
  3044. lpszDstStr += (lstrlen(lpszDstStr) + 1);
  3045. nSize -= (lstrlen(lpszDstStr) + 1);
  3046. }
  3047. if (! *lpszDstStr)
  3048. {
  3049. //
  3050. // the font is not in original linke font list then
  3051. //
  3052. // append to end of list
  3053. //
  3054. //
  3055. // make sure this is a safe copy
  3056. //
  3057. if (lpszDstStr+(lstrlen(lpszSrcStr)+2) < szRegDataStr+FONTLINK_BUF_SIZE)
  3058. {
  3059. //*STRSAFE* lstrcpy(lpszDstStr,lpszSrcStr);
  3060. hresult = StringCchCopy(lpszDstStr , nSize, lpszSrcStr);
  3061. if (!SUCCEEDED(hresult))
  3062. {
  3063. bRet = FALSE;
  3064. goto Exit2;
  3065. }
  3066. lpszDstStr += (lstrlen(lpszDstStr) + 1);
  3067. *lpszDstStr = TEXT('\0');
  3068. }
  3069. }
  3070. lpszSrcStr += (lstrlen(lpszSrcStr) + 1);
  3071. }
  3072. lpszDstStr = szRegDataStr;
  3073. }
  3074. //
  3075. // in this step,lpszDstStr is new font link list
  3076. //
  3077. rc = RegSetValueEx( hKey,
  3078. lpszFontName,
  3079. 0L,
  3080. REG_MULTI_SZ,
  3081. (LPBYTE)lpszDstStr,
  3082. MZStrLen(lpszDstStr));
  3083. if (rc != ERROR_SUCCESS)
  3084. {
  3085. goto Exit2;
  3086. }
  3087. bRet = TRUE;
  3088. *lpbFontLinkRegistryTouched = TRUE;
  3089. Exit2:
  3090. RegCloseKey(hKey);
  3091. Exit1:
  3092. return bRet;
  3093. }
  3094. ////////////////////////////////////////////////////////////////////////////////////
  3095. //
  3096. // MofCompileLanguages
  3097. //
  3098. // Call the WBEM API to mofcompile the MFL's for each language
  3099. //
  3100. ////////////////////////////////////////////////////////////////////////////////////
  3101. BOOL MofCompileLanguages(LPTSTR Languages)
  3102. {
  3103. pfnMUI_InstallMFLFiles pfnMUIInstall = NULL;
  3104. TCHAR buffer[5];
  3105. LPTSTR Language = Languages;
  3106. TCHAR lpMessage[BUFFER_SIZE];
  3107. LONG_PTR lppArgs[1];
  3108. HMODULE hWbemUpgradeDll = NULL;
  3109. TCHAR szDllPath[MAX_PATH];
  3110. HRESULT hresult;
  3111. if (!Languages)
  3112. {
  3113. return FALSE;
  3114. }
  3115. //
  3116. // Load the WBEM upgrade DLL from system wbem folder
  3117. //
  3118. if (GetSystemDirectory(szDllPath, ARRAYSIZE(szDllPath)) &&
  3119. PathAppend(szDllPath, TEXT("wbem\\wbemupgd.dll")))
  3120. {
  3121. hWbemUpgradeDll = LoadLibrary(szDllPath);
  3122. }
  3123. //
  3124. // Fall back to system default path if previous loading fails
  3125. //
  3126. if (!hWbemUpgradeDll)
  3127. {
  3128. hWbemUpgradeDll = LoadLibrary(TEXT("WBEMUPGD.DLL"));
  3129. if (!hWbemUpgradeDll)
  3130. {
  3131. return FALSE;
  3132. }
  3133. }
  3134. //
  3135. // Hook function pointer
  3136. //
  3137. pfnMUIInstall = (pfnMUI_InstallMFLFiles)GetProcAddress(hWbemUpgradeDll, "MUI_InstallMFLFiles");
  3138. if (pfnMUIInstall == NULL)
  3139. {
  3140. FreeLibrary(hWbemUpgradeDll);
  3141. return FALSE;
  3142. }
  3143. // process each language
  3144. while (*Language)
  3145. {
  3146. //*STRSAFE* _tcscpy(buffer, Language);
  3147. hresult = StringCchCopy(buffer , ARRAYSIZE(buffer), Language);
  3148. if (!SUCCEEDED(hresult))
  3149. {
  3150. FreeLibrary(hWbemUpgradeDll);
  3151. return FALSE;
  3152. }
  3153. if (!pfnMUIInstall(buffer))
  3154. {
  3155. // log error for this language
  3156. LoadString(ghInstance, IDS_MOFCOMPILE_LANG_L, lpMessage, ARRAYSIZE(lpMessage)-1);
  3157. lppArgs[0] = (LONG_PTR)buffer;
  3158. FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  3159. lpMessage,
  3160. 0,
  3161. 0,
  3162. lpMessage,
  3163. ARRAYSIZE(lpMessage)-1,
  3164. (va_list *)lppArgs);
  3165. LogMessage(lpMessage);
  3166. }
  3167. while (*Language++) // go to the next language and repeat
  3168. {
  3169. }
  3170. } // of while (*Language)
  3171. FreeLibrary(hWbemUpgradeDll);
  3172. return TRUE;
  3173. }
  3174. ////////////////////////////////////////////////////////////////////////////////////
  3175. //
  3176. // UpdateRegistry
  3177. //
  3178. // Update the Registry to account for languages that have been installed
  3179. //
  3180. ////////////////////////////////////////////////////////////////////////////////////
  3181. BOOL UpdateRegistry(LPTSTR Languages,BOOL *lpbFontLinkRegistryTouched)
  3182. {
  3183. TCHAR szRegPath[MAX_PATH];
  3184. TCHAR szValue[] = TEXT("1");
  3185. LPTSTR Language;
  3186. DWORD dwErr;
  3187. HKEY hkey;
  3188. DWORD dwDisp;
  3189. HRESULT hresult;
  3190. if ((!Languages) || (!lpbFontLinkRegistryTouched))
  3191. {
  3192. return FALSE;
  3193. }
  3194. //*STRSAFE* _tcscpy(szRegPath, TEXT("SYSTEM\\CurrentControlSet\\Control\\Nls\\MUILanguages"));
  3195. hresult = StringCchCopy(szRegPath , ARRAYSIZE(szRegPath), TEXT("SYSTEM\\CurrentControlSet\\Control\\Nls\\MUILanguages"));
  3196. if (!SUCCEEDED(hresult))
  3197. {
  3198. return FALSE;
  3199. }
  3200. dwErr = RegCreateKeyEx( HKEY_LOCAL_MACHINE, // handle of an open key
  3201. szRegPath, // address of subkey name
  3202. 0, // reserved
  3203. TEXT("REG_SZ"), // address of class string
  3204. REG_OPTION_NON_VOLATILE , // special options flag
  3205. KEY_ALL_ACCESS, // desired security access
  3206. NULL,
  3207. &hkey, // address of szRegPath for opened handle
  3208. &dwDisp // address of disposition value szRegPath
  3209. );
  3210. if (dwErr != ERROR_SUCCESS)
  3211. {
  3212. return FALSE;
  3213. }
  3214. Language = Languages;
  3215. if (!g_bLipLanguages || g_bLipAllowSwitch) {
  3216. //*STRSAFE* lstrcpy(szRegPath, TEXT("0409"));
  3217. hresult = StringCchCopy(szRegPath , ARRAYSIZE(szRegPath), TEXT("0409"));
  3218. if (!SUCCEEDED(hresult))
  3219. {
  3220. RegCloseKey(hkey);
  3221. return FALSE;
  3222. }
  3223. dwErr = RegSetValueEx( hkey,
  3224. szRegPath,
  3225. 0,
  3226. REG_SZ,
  3227. (const BYTE *)szValue,
  3228. (lstrlen(szValue) + 1) * sizeof(TCHAR));
  3229. }
  3230. while (*Language)
  3231. {
  3232. TCHAR szFontLinkVal[FONTLINK_BUF_SIZE];
  3233. DWORD dwNum;
  3234. //*STRSAFE* lstrcpy(szRegPath, Language);
  3235. hresult = StringCchCopy(szRegPath , ARRAYSIZE(szRegPath), Language);
  3236. if (!SUCCEEDED(hresult))
  3237. {
  3238. RegCloseKey(hkey);
  3239. return FALSE;
  3240. }
  3241. dwErr = RegSetValueEx( hkey,
  3242. szRegPath,
  3243. 0,
  3244. REG_SZ,
  3245. (const BYTE *)szValue,
  3246. (lstrlen(szValue) + 1)*sizeof(TCHAR));
  3247. if (dwErr != ERROR_SUCCESS)
  3248. {
  3249. RegCloseKey(hkey);
  3250. return FALSE;
  3251. }
  3252. dwNum = GetPrivateProfileString(TEXT("FontLink"),
  3253. szRegPath,
  3254. TEXT(""),
  3255. szFontLinkVal,
  3256. (sizeof(szFontLinkVal)/sizeof(TCHAR)),
  3257. g_szMUIInfoFilePath);
  3258. if (dwNum)
  3259. {
  3260. SetFontLinkValue(szFontLinkVal,lpbFontLinkRegistryTouched);
  3261. }
  3262. while (*Language++); // go to the next language and repeat
  3263. } // of while (*Language)
  3264. RegCloseKey(hkey);
  3265. return TRUE;
  3266. }
  3267. void debug(char *printout)
  3268. {
  3269. #ifdef _DEBUG
  3270. fprintf(stderr, "%s", printout);
  3271. #endif
  3272. }
  3273. ////////////////////////////////////////////////////////////////////////////////////
  3274. //
  3275. // MakeDir
  3276. //
  3277. // Create the directory if it does not already exist
  3278. //
  3279. ////////////////////////////////////////////////////////////////////////////////////
  3280. BOOL MakeDir(LPTSTR szTarget)
  3281. {
  3282. TCHAR lpMessage[BUFFER_SIZE];
  3283. LONG_PTR lppArgs[1];
  3284. if (!szTarget)
  3285. {
  3286. return FALSE;
  3287. }
  3288. if (!FileExists(szTarget)) // if the directory doesn't exist yet
  3289. {
  3290. if (!CreateDirectory( szTarget, NULL)) // create it
  3291. {
  3292. //
  3293. // "LOG: Error creating directory %1"
  3294. //
  3295. LoadString(ghInstance, IDS_CREATEDIR_L, lpMessage, ARRAYSIZE(lpMessage)-1);
  3296. lppArgs[0]=(LONG_PTR)szTarget;
  3297. FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  3298. lpMessage,
  3299. 0,
  3300. 0,
  3301. lpMessage,
  3302. ARRAYSIZE(lpMessage)-1,
  3303. (va_list *)lppArgs);
  3304. LogMessage(lpMessage);
  3305. FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
  3306. NULL,
  3307. GetLastError(),
  3308. 0,
  3309. lpMessage,
  3310. ARRAYSIZE(lpMessage)-1,
  3311. NULL);
  3312. LogMessage(lpMessage);
  3313. return FALSE;
  3314. }
  3315. }
  3316. return TRUE;
  3317. }
  3318. ////////////////////////////////////////////////////////////////////////////////////
  3319. //
  3320. // MakeDirFailed
  3321. //
  3322. // Write message to log file that MakeDir failed.
  3323. //
  3324. ////////////////////////////////////////////////////////////////////////////////////
  3325. BOOL MakeDirFailed(LPTSTR lpDirectory)
  3326. {
  3327. LONG_PTR lppArgs[1];
  3328. if (!lpDirectory)
  3329. {
  3330. return FALSE;
  3331. }
  3332. //
  3333. // "LOG: MakeDir has failed: %1"
  3334. //
  3335. lppArgs[0]=(LONG_PTR)lpDirectory;
  3336. LogFormattedMessage(NULL, IDS_MAKEDIR_L, lppArgs);
  3337. return TRUE;
  3338. }
  3339. ////////////////////////////////////////////////////////////////////////////////////
  3340. //
  3341. // CopyFileFailed
  3342. // Write message to log file that CopyFile failed.
  3343. //
  3344. ////////////////////////////////////////////////////////////////////////////////////
  3345. BOOL CopyFileFailed(LPTSTR lpFile,DWORD dwErrorCode)
  3346. {
  3347. TCHAR lpMessage[BUFFER_SIZE];
  3348. LONG_PTR lppArgs[1];
  3349. DWORD MessageID;
  3350. if (!lpFile)
  3351. {
  3352. return FALSE;
  3353. }
  3354. if ( dwErrorCode)
  3355. {
  3356. MessageID = dwErrorCode;
  3357. }
  3358. else
  3359. {
  3360. MessageID = GetLastError();
  3361. }
  3362. //
  3363. // "LOG: CopyFile has failed: %1"
  3364. //
  3365. LoadString(ghInstance, IDS_COPYFILE_L, lpMessage, ARRAYSIZE(lpMessage)-1);
  3366. lppArgs[0]=(LONG_PTR)lpFile;
  3367. FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  3368. lpMessage,
  3369. 0,
  3370. 0,
  3371. lpMessage,
  3372. ARRAYSIZE(lpMessage)-1,
  3373. (va_list *)lppArgs);
  3374. LogMessage(lpMessage);
  3375. FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,
  3376. NULL,
  3377. MessageID,
  3378. 0,
  3379. lpMessage,
  3380. ARRAYSIZE(lpMessage)-1,
  3381. NULL);
  3382. LogMessage(lpMessage);
  3383. return TRUE;
  3384. }
  3385. ////////////////////////////////////////////////////////////////////////////
  3386. //
  3387. // Muisetup_InitInf
  3388. //
  3389. // Parameters:
  3390. //
  3391. // [OUT] phInf the handle to the INF file opened.
  3392. // [OUT] pFileQueue the file queue created in this function.
  3393. // [OUT] pQueueContext the context used by the default queue callback routine included with the Setup API.
  3394. //
  3395. ////////////////////////////////////////////////////////////////////////////
  3396. BOOL Muisetup_InitInf(
  3397. HWND hDlg,
  3398. LPTSTR pszInf,
  3399. HINF *phInf,
  3400. HSPFILEQ *pFileQueue,
  3401. PVOID *pQueueContext)
  3402. {
  3403. if ((! pszInf) || (!pFileQueue) || (!pQueueContext))
  3404. {
  3405. return FALSE;
  3406. }
  3407. //
  3408. // Open the Inf file.
  3409. //
  3410. *phInf = SetupOpenInfFile(pszInf, NULL, INF_STYLE_WIN4, NULL);
  3411. if (*phInf == INVALID_HANDLE_VALUE)
  3412. {
  3413. return FALSE;
  3414. }
  3415. //
  3416. // Create a setup file queue and initialize default setup
  3417. // copy queue callback context.
  3418. //
  3419. *pFileQueue = SetupOpenFileQueue();
  3420. if ((!*pFileQueue) || (*pFileQueue == INVALID_HANDLE_VALUE))
  3421. {
  3422. SetupCloseInfFile(*phInf);
  3423. return FALSE;
  3424. }
  3425. *pQueueContext = SetupInitDefaultQueueCallback(hDlg);
  3426. if (!*pQueueContext)
  3427. {
  3428. SetupCloseFileQueue(*pFileQueue);
  3429. SetupCloseInfFile(*phInf);
  3430. return FALSE;
  3431. }
  3432. //
  3433. // Return success.
  3434. //
  3435. return TRUE;
  3436. }
  3437. ////////////////////////////////////////////////////////////////////////////
  3438. //
  3439. // Muisetup_CloseInf
  3440. //
  3441. ////////////////////////////////////////////////////////////////////////////
  3442. BOOL Muisetup_CloseInf(
  3443. HINF hInf,
  3444. HSPFILEQ FileQueue,
  3445. PVOID QueueContext)
  3446. {
  3447. if (!QueueContext)
  3448. {
  3449. return FALSE;
  3450. }
  3451. //
  3452. // Terminate the Queue.
  3453. //
  3454. SetupTermDefaultQueueCallback(QueueContext);
  3455. //
  3456. // Close the file queue.
  3457. //
  3458. SetupCloseFileQueue(FileQueue);
  3459. //
  3460. // Close the Inf file.
  3461. //
  3462. SetupCloseInfFile(hInf);
  3463. return TRUE;
  3464. }
  3465. ////////////////////////////////////////////////////////////////////////////////////
  3466. //
  3467. // ExecuteComponentINF
  3468. //
  3469. // Installs component MUI files, by running the specified INF file.
  3470. //
  3471. // Parameters:
  3472. // pComponentName the name of the component (e.g. "ie5")
  3473. // pComponentInfFile: the full path of the component INF file.
  3474. // pInstallSection the section in the component INF file to be executed. (e.g "DefaultInstall" or "Uninstall")
  3475. //
  3476. ////////////////////////////////////////////////////////////////////////////////////
  3477. BOOL ExecuteComponentINF(
  3478. HWND hDlg, PTSTR pComponentName, PTSTR pComponentInfFile, PTSTR pInstallSection, BOOL bInstall)
  3479. {
  3480. int iLen;
  3481. TCHAR tchCommandParam[BUFFER_SIZE];
  3482. CHAR chCommandParam[BUFFER_SIZE*sizeof(TCHAR)];
  3483. HINF hCompInf; // the handle to the component INF file.
  3484. HSPFILEQ FileQueue;
  3485. PVOID QueueContext;
  3486. BOOL bRet = TRUE;
  3487. DWORD dwResult;
  3488. LONG_PTR lppArgs[3];
  3489. TCHAR szBuffer[BUFFER_SIZE];
  3490. HRESULT hresult;
  3491. if ((!pComponentName) || (!pComponentInfFile) || (!pInstallSection))
  3492. {
  3493. return FALSE;
  3494. }
  3495. //
  3496. // Advpack LaunchINFSection() command line format:
  3497. // INF file, INF section, flags, reboot string
  3498. // 'N' or 'n' in reboot string means no reboot message popup.
  3499. //
  3500. //*STRSAFE* wsprintf(tchCommandParam, TEXT("%s,%s,0,n"), pComponentInfFile, pInstallSection);
  3501. if (g_bNoUI)
  3502. {
  3503. hresult = StringCchPrintf(tchCommandParam , ARRAYSIZE(tchCommandParam), TEXT("%s,%s,1,n"), pComponentInfFile, pInstallSection);
  3504. }
  3505. else
  3506. {
  3507. hresult = StringCchPrintf(tchCommandParam , ARRAYSIZE(tchCommandParam), TEXT("%s,%s,0,n"), pComponentInfFile, pInstallSection);
  3508. }
  3509. if (!SUCCEEDED(hresult))
  3510. {
  3511. return FALSE;
  3512. }
  3513. WideCharToMultiByte(CP_ACP, 0, tchCommandParam, -1, chCommandParam, sizeof(chCommandParam), NULL, NULL);
  3514. if (FileExists(pComponentInfFile))
  3515. {
  3516. // gpfnLaunchINFSection won't be NULL since InitializePFNs() already verifies that.
  3517. if ((gpfnLaunchINFSection)(hDlg, ghInstance, chCommandParam, g_bNoUI? SW_HIDE : SW_SHOW) != S_OK)
  3518. {
  3519. if (!g_bNoUI)
  3520. {
  3521. lppArgs[0] = (LONG_PTR)pComponentName;
  3522. DoMessageBoxFromResource(hDlg, ghInstance, bInstall? IDS_ERROR_INSTALL_COMP_UI : IDS_ERROR_UNINSTALL_COMP_UI, lppArgs, IDS_ERROR_T, MB_OK);
  3523. }
  3524. else
  3525. {
  3526. lppArgs[0] = (LONG_PTR)pComponentName;
  3527. LogFormattedMessage(ghInstance, bInstall? IDS_ERROR_INSTALL_COMP_UI : IDS_ERROR_UNINSTALL_COMP_UI, lppArgs);
  3528. }
  3529. return (FALSE);
  3530. }
  3531. }
  3532. return (TRUE);
  3533. }
  3534. ////////////////////////////////////////////////////////////////////////////////////
  3535. //
  3536. // CheckProductType
  3537. //
  3538. // Check product type of W2K
  3539. //
  3540. ////////////////////////////////////////////////////////////////////////////////////
  3541. BOOL CheckProductType(INT_PTR nType)
  3542. {
  3543. OSVERSIONINFOEX verinfo;
  3544. INT64 dwConditionMask=0;
  3545. BOOL bResult=FALSE;
  3546. DWORD dwTypeMask = VER_PRODUCT_TYPE;
  3547. memset(&verinfo,0,sizeof(verinfo));
  3548. verinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  3549. VER_SET_CONDITION(dwConditionMask,VER_PRODUCT_TYPE,VER_EQUAL);
  3550. switch (nType)
  3551. {
  3552. // W2K Professional
  3553. case MUI_IS_WIN2K_PRO:
  3554. verinfo.wProductType=VER_NT_WORKSTATION;
  3555. break;
  3556. // W2K Server
  3557. case MUI_IS_WIN2K_SERVER:
  3558. verinfo.wProductType=VER_NT_SERVER;
  3559. break;
  3560. // W2K Advanced Server or Data Center
  3561. case MUI_IS_WIN2K_ADV_SERVER_OR_DATACENTER:
  3562. verinfo.wProductType=VER_NT_SERVER;
  3563. verinfo.wSuiteMask =VER_SUITE_ENTERPRISE;
  3564. VER_SET_CONDITION(dwConditionMask,VER_SUITENAME,VER_OR);
  3565. dwTypeMask = VER_PRODUCT_TYPE | VER_SUITENAME;
  3566. break;
  3567. // W2k Data Center
  3568. case MUI_IS_WIN2K_DATACENTER:
  3569. verinfo.wProductType=VER_NT_SERVER;
  3570. verinfo.wSuiteMask =VER_SUITE_DATACENTER;
  3571. VER_SET_CONDITION(dwConditionMask,VER_SUITENAME,VER_OR);
  3572. dwTypeMask = VER_PRODUCT_TYPE | VER_SUITENAME;
  3573. break;
  3574. // W2K Domain Controller
  3575. case MUI_IS_WIN2K_DC:
  3576. verinfo.wProductType=VER_NT_DOMAIN_CONTROLLER;
  3577. break;
  3578. case MUI_IS_WIN2K_ENTERPRISE:
  3579. verinfo.wProductType=VER_NT_DOMAIN_CONTROLLER;
  3580. verinfo.wSuiteMask =VER_SUITE_ENTERPRISE;
  3581. VER_SET_CONDITION(dwConditionMask,VER_SUITENAME,VER_OR);
  3582. dwTypeMask = VER_PRODUCT_TYPE | VER_SUITENAME;
  3583. break;
  3584. case MUI_IS_WIN2K_DC_DATACENTER:
  3585. verinfo.wProductType=VER_NT_DOMAIN_CONTROLLER;
  3586. verinfo.wSuiteMask =VER_SUITE_DATACENTER;
  3587. VER_SET_CONDITION(dwConditionMask,VER_SUITENAME,VER_OR);
  3588. dwTypeMask = VER_PRODUCT_TYPE | VER_SUITENAME;
  3589. break;
  3590. // Whistler Personal
  3591. case MUI_IS_WIN2K_PERSONAL:
  3592. verinfo.wProductType=VER_NT_WORKSTATION;
  3593. verinfo.wSuiteMask =VER_SUITE_PERSONAL;
  3594. VER_SET_CONDITION(dwConditionMask,VER_SUITENAME,VER_AND);
  3595. dwTypeMask = VER_PRODUCT_TYPE | VER_SUITENAME;
  3596. break;
  3597. default:
  3598. verinfo.wProductType=VER_NT_WORKSTATION;
  3599. break;
  3600. }
  3601. return (VerifyVersionInfo(&verinfo,dwTypeMask,dwConditionMask));
  3602. }