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.

979 lines
25 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. Fns.cpp
  5. Abstract:
  6. Contains all of the functions used by the
  7. application.
  8. Notes:
  9. Unicode only - Windows 2000 & XP
  10. History:
  11. 01/02/2002 rparsons Created
  12. 01/08/2002 rparsons Restructured a bit to add some
  13. required functionality
  14. 01/10/2002 rparsons Change wsprintf to snwprintf
  15. 01/18/2002 rparsons Major changes - made more installer like
  16. 02/15/2002 rparsons Install SDBInst on W2K.
  17. Include strsafe.
  18. --*/
  19. #include "main.h"
  20. extern APPINFO g_ai;
  21. /*++
  22. Routine Description:
  23. Retrieve file version info from a file.
  24. The version is specified in the dwFileVersionMS and dwFileVersionLS fields
  25. of a VS_FIXEDFILEINFO, as filled in by the win32 version APIs.
  26. If the file is not a coff image or does not have version resources,
  27. the function fails.
  28. Arguments:
  29. pwszFileName - Supplies the full path of the file whose version
  30. data is desired.
  31. pdwlVersion - Receives the version stamp of the file.
  32. If the file is not a coff image or does not contain
  33. the appropriate version resource data, the function fails.
  34. Return Value:
  35. TRUE on success, FALSE otherwise.
  36. --*/
  37. BOOL
  38. GetVersionInfoFromImage(
  39. IN LPWSTR pwszFileName,
  40. OUT PDWORDLONG pdwlVersion
  41. )
  42. {
  43. UINT cchSize;
  44. DWORD cbSize, dwIgnored;
  45. BOOL bResult = FALSE;
  46. PVOID pVersionBlock = NULL;
  47. VS_FIXEDFILEINFO* pffi = NULL;
  48. if (!pwszFileName || !pdwlVersion) {
  49. DPF(dlError, "[GetVersionInfoFromImage] Invalid arguments");
  50. return FALSE;
  51. }
  52. cbSize = GetFileVersionInfoSize(pwszFileName, &dwIgnored);
  53. if (0 == cbSize) {
  54. DPF(dlError,
  55. "[GetVersionInfoFromImage] 0x%08X Failed to get version size",
  56. GetLastError());
  57. return FALSE;
  58. }
  59. //
  60. // Allocate memory block of sufficient size to hold version info block.
  61. //
  62. pVersionBlock = HeapAlloc(GetProcessHeap(),
  63. HEAP_ZERO_MEMORY,
  64. cbSize);
  65. if (!pVersionBlock) {
  66. DPF(dlError, "[GetVersionInfoFromImage] Unable to allocate memory");
  67. return FALSE;
  68. }
  69. //
  70. // Get the version block from the file.
  71. //
  72. if (!GetFileVersionInfo(pwszFileName,
  73. 0,
  74. cbSize,
  75. pVersionBlock)) {
  76. DPF(dlError,
  77. "[GetVersionInfoFromImage] 0x%08X Failed to get version info",
  78. GetLastError());
  79. goto exit;
  80. }
  81. //
  82. // Get fixed version info.
  83. //
  84. if (!VerQueryValue(pVersionBlock,
  85. L"\\",
  86. (LPVOID*)&pffi,
  87. &cchSize)) {
  88. DPF(dlError,
  89. "[GetVersionInfoFromImage] 0x%08X Failed to fixed version info",
  90. GetLastError());
  91. goto exit;
  92. }
  93. //
  94. // Return version to caller.
  95. //
  96. *pdwlVersion = (((DWORDLONG)pffi->dwFileVersionMS) << 32) +
  97. pffi->dwFileVersionLS;
  98. bResult = TRUE;
  99. exit:
  100. if (pVersionBlock) {
  101. HeapFree(GetProcessHeap(), 0, pVersionBlock);
  102. }
  103. return bResult;
  104. }
  105. /*++
  106. Routine Description:
  107. Initializes our data structures with information about
  108. the files that we're installing/uninstalling.
  109. Arguments:
  110. None.
  111. Return Value:
  112. TRUE on success, FALSE otherwise.
  113. --*/
  114. BOOL
  115. InitializeFileInfo(
  116. void
  117. )
  118. {
  119. UINT uCount = 0;
  120. HRESULT hr;
  121. //
  122. // Set up the information for each file.
  123. // I realize that a for loop seems much more suitable here,
  124. // but we have to match up the destination for each file.
  125. // Ideally, we would have a INF file to read from that tells
  126. // us where to install each file.
  127. // For now, copying and pasting is all we need to do.
  128. //
  129. hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName,
  130. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName),
  131. FILENAME_APPVERIF_EXE);
  132. if (FAILED(hr)) {
  133. DPF(dlError, "[InitializeFileInfo] Buffer too small (1)");
  134. return FALSE;
  135. }
  136. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName,
  137. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName),
  138. L"%ls\\"FILENAME_APPVERIF_EXE,
  139. g_ai.wszCurrentDir);
  140. if (FAILED(hr)) {
  141. DPF(dlError, "[InitializeFileInfo] Buffer too small (2)");
  142. return FALSE;
  143. }
  144. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName,
  145. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName),
  146. L"%ls\\"FILENAME_APPVERIF_EXE,
  147. g_ai.wszSysDir);
  148. if (FAILED(hr)) {
  149. DPF(dlError, "[InitializeFileInfo] Buffer too small (3)");
  150. return FALSE;
  151. }
  152. if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszSrcFileName,
  153. &g_ai.rgFileInfo[uCount].dwlSrcFileVersion)) {
  154. DPF(dlError,
  155. "[InitializeFileInfo] Failed to get version info for %ls",
  156. g_ai.rgFileInfo[uCount].wszSrcFileName);
  157. return FALSE;
  158. }
  159. if (GetFileAttributes(g_ai.rgFileInfo[uCount].wszDestFileName) != -1) {
  160. if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszDestFileName,
  161. &g_ai.rgFileInfo[uCount].dwlDestFileVersion)) {
  162. DPF(dlError,
  163. "[InitializeFileInfo] Failed to get version info for %ls",
  164. g_ai.rgFileInfo[uCount].wszDestFileName);
  165. return FALSE;
  166. }
  167. }
  168. uCount++;
  169. //
  170. // Next file.
  171. //
  172. hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName,
  173. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName),
  174. FILENAME_APPVERIF_EXE_PDB);
  175. if (FAILED(hr)) {
  176. DPF(dlError, "[InitializeFileInfo] Buffer too small (4)");
  177. return FALSE;
  178. }
  179. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName,
  180. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName),
  181. L"%ls\\"FILENAME_APPVERIF_EXE_PDB,
  182. g_ai.wszCurrentDir);
  183. if (FAILED(hr)) {
  184. DPF(dlError, "[InitializeFileInfo] Buffer too small (5)");
  185. return FALSE;
  186. }
  187. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName,
  188. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName),
  189. L"%ls\\"FILENAME_APPVERIF_EXE_PDB,
  190. g_ai.wszSysDir);
  191. if (FAILED(hr)) {
  192. DPF(dlError, "[InitializeFileInfo] Buffer too small (6)");
  193. return FALSE;
  194. }
  195. uCount++;
  196. //
  197. // Next file.
  198. //
  199. hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName,
  200. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName),
  201. FILENAME_APPVERIF_CHM);
  202. if (FAILED(hr)) {
  203. DPF(dlError, "[InitializeFileInfo] Buffer too small (7)");
  204. return FALSE;
  205. }
  206. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName,
  207. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName),
  208. L"%ls\\"FILENAME_APPVERIF_CHM,
  209. g_ai.wszCurrentDir);
  210. if (FAILED(hr)) {
  211. DPF(dlError, "[InitializeFileInfo] Buffer too small (8)");
  212. return FALSE;
  213. }
  214. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName,
  215. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName),
  216. L"%ls\\"FILENAME_APPVERIF_CHM,
  217. g_ai.wszSysDir);
  218. if (FAILED(hr)) {
  219. DPF(dlError, "[InitializeFileInfo] Buffer too small (9)");
  220. return FALSE;
  221. }
  222. uCount++;
  223. //
  224. // Next file.
  225. //
  226. hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName,
  227. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName),
  228. FILENAME_ACVERFYR_DLL);
  229. if (FAILED(hr)) {
  230. DPF(dlError, "[InitializeFileInfo] Buffer too small (10)");
  231. return FALSE;
  232. }
  233. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName,
  234. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName),
  235. L"%ls\\"FILENAME_ACVERFYR_DLL,
  236. g_ai.wszCurrentDir);
  237. if (FAILED(hr)) {
  238. DPF(dlError, "[InitializeFileInfo] Buffer too small (11)");
  239. return FALSE;
  240. }
  241. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName,
  242. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName),
  243. L"%ls\\AppPatch\\IA64\\"FILENAME_ACVERFYR_DLL,
  244. g_ai.wszWinDir);
  245. if (FAILED(hr)) {
  246. DPF(dlError, "[InitializeFileInfo] Buffer too small (12)");
  247. return FALSE;
  248. }
  249. if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszSrcFileName,
  250. &g_ai.rgFileInfo[uCount].dwlSrcFileVersion)) {
  251. DPF(dlError,
  252. "[InitializeFileInfo] Failed to get version info for %ls",
  253. g_ai.rgFileInfo[uCount].wszSrcFileName);
  254. return FALSE;
  255. }
  256. if (GetFileAttributes(g_ai.rgFileInfo[uCount].wszDestFileName) != -1) {
  257. if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszDestFileName,
  258. &g_ai.rgFileInfo[uCount].dwlDestFileVersion)) {
  259. DPF(dlError,
  260. "[InitializeFileInfo] Failed to get version info for %ls",
  261. g_ai.rgFileInfo[uCount].wszDestFileName);
  262. return FALSE;
  263. }
  264. }
  265. uCount++;
  266. //
  267. // Next file.
  268. //
  269. hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName,
  270. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName),
  271. FILENAME_ACVERFYR_DLL_PDB);
  272. if (FAILED(hr)) {
  273. DPF(dlError, "[InitializeFileInfo] Buffer too small (13)");
  274. return FALSE;
  275. }
  276. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName,
  277. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName),
  278. L"%ls\\"FILENAME_ACVERFYR_DLL_PDB,
  279. g_ai.wszCurrentDir);
  280. if (FAILED(hr)) {
  281. DPF(dlError, "[InitializeFileInfo] Buffer too small (14)");
  282. return FALSE;
  283. }
  284. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName,
  285. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName),
  286. L"%ls\\AppPatch\\ia64\\"FILENAME_ACVERFYR_DLL_PDB,
  287. g_ai.wszWinDir);
  288. if (FAILED(hr)) {
  289. DPF(dlError, "[InitializeFileInfo] Buffer too small (15)");
  290. return FALSE;
  291. }
  292. uCount++;
  293. //
  294. // Next file.
  295. //
  296. hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName,
  297. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName),
  298. FILENAME_SYSMAIN_SDB);
  299. if (FAILED(hr)) {
  300. DPF(dlError, "[InitializeFileInfo] Buffer too small (13)");
  301. return FALSE;
  302. }
  303. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName,
  304. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName),
  305. L"%ls\\"FILENAME_SYSMAIN_SDB,
  306. g_ai.wszCurrentDir);
  307. if (FAILED(hr)) {
  308. DPF(dlError, "[InitializeFileInfo] Buffer too small (14)");
  309. return FALSE;
  310. }
  311. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName,
  312. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName),
  313. L"%ls\\AppPatch\\ia64\\"FILENAME_SYSMAIN_SDB,
  314. g_ai.wszWinDir);
  315. if (FAILED(hr)) {
  316. DPF(dlError, "[InitializeFileInfo] Buffer too small (15)");
  317. return FALSE;
  318. }
  319. return TRUE;
  320. }
  321. /*++
  322. Routine Description:
  323. Determines if any of the files we have to offer
  324. are newer than ones already installed.
  325. Arguments:
  326. None.
  327. Return Value:
  328. TRUE if we have at least one new file to offer.
  329. FALSE if we don't have at least one new file to offer.
  330. --*/
  331. BOOL
  332. InstallCheckFileVersions(
  333. void
  334. )
  335. {
  336. UINT uCount;
  337. BOOL bReturn = FALSE;
  338. for (uCount = 0; uCount < NUM_FILES; uCount++) {
  339. if (g_ai.rgFileInfo[uCount].dwlSrcFileVersion >=
  340. g_ai.rgFileInfo[uCount].dwlDestFileVersion) {
  341. g_ai.rgFileInfo[uCount].bInstall = TRUE;
  342. bReturn = TRUE;
  343. }
  344. }
  345. return bReturn;
  346. }
  347. /*++
  348. Routine Description:
  349. Determines if we have a newer version of appverif.exe
  350. or acverfyr.dll to offer.
  351. Arguments:
  352. None.
  353. Return Value:
  354. TRUE if our version is newer than the one installed.
  355. or if there is no version installed.
  356. FALSE otherwise.
  357. --*/
  358. BOOL
  359. IsPkgAppVerifNewer(
  360. void
  361. )
  362. {
  363. //
  364. // Check appverif.exe first.
  365. //
  366. if (g_ai.rgFileInfo[0].dwlSrcFileVersion >=
  367. g_ai.rgFileInfo[0].dwlDestFileVersion) {
  368. return TRUE;
  369. }
  370. //
  371. // Check acverfyr.dll if appverif.exe didn't pan out.
  372. // Do this based on the platform.
  373. //
  374. if (g_ai.rgFileInfo[1].dwlSrcFileVersion >=
  375. g_ai.rgFileInfo[1].dwlDestFileVersion) {
  376. return TRUE;
  377. }
  378. return FALSE;
  379. }
  380. /*++
  381. Routine Description:
  382. Performs a file copy, even if it's in use.
  383. Arguments:
  384. pwszSourceFileName - Name of the source file to copy.
  385. pwszDestFileName - Name of the destination file to replace.
  386. Return Value:
  387. TRUE on success, FALSE otherwise.
  388. --*/
  389. BOOL
  390. ForceCopy(
  391. IN LPCWSTR pwszSourceFileName,
  392. IN LPCWSTR pwszDestFileName
  393. )
  394. {
  395. WCHAR wszTempPath[MAX_PATH];
  396. WCHAR wszDelFileName[MAX_PATH];
  397. DWORD cchSize;
  398. if (!pwszSourceFileName || !pwszDestFileName) {
  399. DPF(dlError, "[ForceCopy] Invalid parameters");
  400. return FALSE;
  401. }
  402. DPF(dlInfo, "[ForceCopy] Source file: %ls", pwszSourceFileName);
  403. DPF(dlInfo, "[ForceCopy] Destination file: %ls", pwszDestFileName);
  404. if (!CopyFile(pwszSourceFileName, pwszDestFileName, FALSE)) {
  405. cchSize = GetTempPath(ARRAYSIZE(wszTempPath), wszTempPath);
  406. if (cchSize > ARRAYSIZE(wszTempPath) || cchSize == 0) {
  407. DPF(dlError, "[ForceCopy] Buffer for temp path is too small");
  408. return FALSE;
  409. }
  410. if (!GetTempFileName(wszTempPath, L"del", 0, wszDelFileName)) {
  411. DPF(dlError,
  412. "[ForceCopy] 0x%08X Failed to get temp file",
  413. GetLastError());
  414. return FALSE;
  415. }
  416. if (!MoveFileEx(pwszDestFileName,
  417. wszDelFileName,
  418. MOVEFILE_REPLACE_EXISTING)) {
  419. DPF(dlError,
  420. "[ForceCopy] 0x%08X Failed to replace file",
  421. GetLastError());
  422. return FALSE;
  423. }
  424. if (!MoveFileEx(wszDelFileName,
  425. NULL,
  426. MOVEFILE_DELAY_UNTIL_REBOOT)) {
  427. DPF(dlError,
  428. "[ForceCopy] 0x%08X Failed to delete file",
  429. GetLastError());
  430. return FALSE;
  431. }
  432. if (!CopyFile(pwszSourceFileName, pwszDestFileName, FALSE)) {
  433. DPF(dlError,
  434. "[ForceCopy] 0x%08X Failed to copy file",
  435. GetLastError());
  436. return FALSE;
  437. }
  438. }
  439. return TRUE;
  440. }
  441. /*++
  442. Routine Description:
  443. Prints a formatted string to the debugger.
  444. Arguments:
  445. dwDetail - Specifies the level of the information provided.
  446. pszFmt - The string to be displayed.
  447. ... - A va_list of insertion strings.
  448. Return Value:
  449. None.
  450. --*/
  451. void
  452. __cdecl
  453. DebugPrintfEx(
  454. IN DEBUGLEVEL dwDetail,
  455. IN LPSTR pszFmt,
  456. ...
  457. )
  458. {
  459. char szT[1024];
  460. va_list arglist;
  461. int len;
  462. va_start(arglist, pszFmt);
  463. //
  464. // Reserve one character for the potential '\n' that we may be adding.
  465. //
  466. StringCchVPrintfA(szT, sizeof(szT) - 1, pszFmt, arglist);
  467. va_end(arglist);
  468. //
  469. // Make sure we have a '\n' at the end of the string
  470. //
  471. len = strlen(szT);
  472. if (len > 0 && szT[len - 1] != '\n') {
  473. szT[len] = '\n';
  474. szT[len + 1] = 0;
  475. }
  476. switch (dwDetail) {
  477. case dlPrint:
  478. DbgPrint("[MSG ] ");
  479. break;
  480. case dlError:
  481. DbgPrint("[FAIL] ");
  482. break;
  483. case dlWarning:
  484. DbgPrint("[WARN] ");
  485. break;
  486. case dlInfo:
  487. DbgPrint("[INFO] ");
  488. break;
  489. default:
  490. DbgPrint("[XXXX] ");
  491. break;
  492. }
  493. DbgPrint("%s", szT);
  494. }
  495. /*++
  496. Routine Description:
  497. Initializes the installer. Sets up paths, version
  498. information, etc.
  499. Arguments:
  500. None.
  501. Return Value:
  502. TRUE on success.
  503. FALSE on failure.
  504. -1 if the operating system is not supported.
  505. --*/
  506. int
  507. InitializeInstaller(
  508. void
  509. )
  510. {
  511. OSVERSIONINFO osvi;
  512. WCHAR* pTemp = NULL;
  513. UINT cchSize;
  514. DWORD cchReturned;
  515. HRESULT hr;
  516. //
  517. // Find out what operating system we're running on.
  518. //
  519. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  520. if (!GetVersionEx(&osvi)) {
  521. DPF(dlError,
  522. "[InitializeInstaller] 0x%08X Failed to get OS version info",
  523. GetLastError());
  524. return FALSE;
  525. }
  526. //
  527. // Check for supported OS.
  528. //
  529. if (osvi.dwMajorVersion < 5 ||
  530. osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) {
  531. DPF(dlInfo, "[InitializeInstaller] OS not supported");
  532. return -1;
  533. }
  534. //
  535. // Find out where we're running from.
  536. //
  537. g_ai.wszModuleName[ARRAYSIZE(g_ai.wszModuleName) - 1] = 0;
  538. cchReturned = GetModuleFileName(NULL,
  539. g_ai.wszModuleName,
  540. ARRAYSIZE(g_ai.wszModuleName));
  541. if (g_ai.wszModuleName[ARRAYSIZE(g_ai.wszModuleName) - 1] != 0 ||
  542. cchReturned == 0) {
  543. DPF(dlError,
  544. "[InitializeInstaller] 0x%08X Failed to get module file name",
  545. GetLastError());
  546. return FALSE;
  547. }
  548. //
  549. // Save away our current directory for later use.
  550. //
  551. hr = StringCchCopy(g_ai.wszCurrentDir,
  552. ARRAYSIZE(g_ai.wszCurrentDir),
  553. g_ai.wszModuleName);
  554. if (FAILED(hr)) {
  555. DPF(dlError, "[InitializeInstaller] 0x%08X String copy failed", hr);
  556. return FALSE;
  557. }
  558. pTemp = wcsrchr(g_ai.wszCurrentDir, '\\');
  559. if (pTemp) {
  560. *pTemp = 0;
  561. }
  562. //
  563. // Save away paths to the Windows & System32 directories for later use.
  564. //
  565. cchSize = GetSystemWindowsDirectory(g_ai.wszWinDir,
  566. ARRAYSIZE(g_ai.wszWinDir));
  567. if (cchSize > ARRAYSIZE(g_ai.wszWinDir) || cchSize == 0) {
  568. DPF(dlError,
  569. "[InitializeInstaller] 0x%08X Failed to get Windows directory",
  570. GetLastError());
  571. return FALSE;
  572. }
  573. cchSize = GetSystemDirectory(g_ai.wszSysDir, ARRAYSIZE(g_ai.wszSysDir));
  574. if (cchSize > ARRAYSIZE(g_ai.wszSysDir) || cchSize == 0) {
  575. DPF(dlError,
  576. "[InitializeInstaller] 0x%08X Failed to get system directory",
  577. GetLastError());
  578. return FALSE;
  579. }
  580. return TRUE;
  581. }
  582. /*++
  583. Routine Description:
  584. Launches the Application Verifier.
  585. Arguments:
  586. None.
  587. Return Value:
  588. None.
  589. --*/
  590. void
  591. InstallLaunchExe(
  592. void
  593. )
  594. {
  595. STARTUPINFO si;
  596. PROCESS_INFORMATION pi;
  597. WCHAR wszAppVerifExe[MAX_PATH];
  598. HRESULT hr;
  599. hr = StringCchPrintf(wszAppVerifExe,
  600. ARRAYSIZE(wszAppVerifExe),
  601. L"%ls\\"FILENAME_APPVERIF_EXE,
  602. g_ai.wszSysDir);
  603. if (FAILED(hr)) {
  604. DPF(dlError, "[InstallLaunchExe] Buffer too small");
  605. return;
  606. }
  607. ZeroMemory(&si, sizeof(STARTUPINFO));
  608. ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
  609. si.cb = sizeof(STARTUPINFO);
  610. if (!CreateProcess(wszAppVerifExe,
  611. NULL,
  612. NULL,
  613. NULL,
  614. FALSE,
  615. 0,
  616. NULL,
  617. NULL,
  618. &si,
  619. &pi)) {
  620. DPF(dlError,
  621. "[InstallLaunchExe] 0x%08X Failed to launch %ls",
  622. GetLastError(),
  623. wszAppVerifExe);
  624. return;
  625. }
  626. CloseHandle(pi.hProcess);
  627. CloseHandle(pi.hThread);
  628. }
  629. /*++
  630. Routine Description:
  631. Installs the catalog file.
  632. Arguments:
  633. pwszCatFileName - Name of the catalog file to install.
  634. Return Value:
  635. TRUE on success, FALSE otherwise.
  636. --*/
  637. BOOL
  638. InstallCatalogFile(
  639. IN LPWSTR pwszCatFileName
  640. )
  641. {
  642. HCATADMIN hCatAdmin;
  643. HCATINFO hCatInfo;
  644. GUID guidCatRoot;
  645. if (!pwszCatFileName) {
  646. DPF(dlError, "[InstallCatalogFile] Invalid parameter");
  647. return FALSE;
  648. }
  649. StringToGuid(L"{F750E6C3-38EE-11D1-85E5-00C04FC295EE}", &guidCatRoot);
  650. if (!CryptCATAdminAcquireContext(&hCatAdmin, &guidCatRoot, 0)) {
  651. DPF(dlError,
  652. "[InstallCatalogFile] 0x%08X Failed to acquire context",
  653. GetLastError());
  654. return FALSE;
  655. }
  656. hCatInfo = CryptCATAdminAddCatalog(hCatAdmin,
  657. pwszCatFileName,
  658. NULL,
  659. 0);
  660. if (hCatInfo) {
  661. CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0);
  662. CryptCATAdminReleaseContext(hCatAdmin, 0);
  663. return TRUE;
  664. }
  665. CryptCATAdminReleaseContext(hCatAdmin, 0);
  666. DPF(dlError,
  667. "[InstallCatalogFile] 0x%08X Failed to add catalog %ls",
  668. GetLastError(),
  669. pwszCatFileName);
  670. return FALSE;
  671. }
  672. /*++
  673. Routine Description:
  674. Copies the files that we've determined are
  675. newer to their specified destination.
  676. Arguments:
  677. None.
  678. Return Value:
  679. TRUE on success, FALSE otherwise.
  680. --*/
  681. BOOL
  682. InstallCopyFiles(
  683. void
  684. )
  685. {
  686. UINT uCount;
  687. while (TRUE) {
  688. for (uCount = 0; uCount < NUM_FILES; uCount++) {
  689. if (g_ai.rgFileInfo[uCount].bInstall) {
  690. if (!ForceCopy(g_ai.rgFileInfo[uCount].wszSrcFileName,
  691. g_ai.rgFileInfo[uCount].wszDestFileName)) {
  692. DPF(dlError,
  693. "[InstallCopyFiles] Failed to copy %ls to %ls",
  694. g_ai.rgFileInfo[uCount].wszSrcFileName,
  695. g_ai.rgFileInfo[uCount].wszDestFileName);
  696. return FALSE;
  697. }
  698. }
  699. }
  700. break;
  701. }
  702. return TRUE;
  703. }
  704. /*++
  705. Routine Description:
  706. Performs the installation. This is the main routine
  707. for the install.
  708. Arguments:
  709. hWndParent - Parent window handle for message boxes.
  710. Return Value:
  711. None.
  712. --*/
  713. void
  714. PerformInstallation(
  715. IN HWND hWndParent
  716. )
  717. {
  718. WCHAR wszError[MAX_PATH];
  719. SendMessage(g_ai.hWndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, NUM_PB_STEPS));
  720. SendMessage(g_ai.hWndProgress, PBM_SETSTEP, 1, 0);
  721. //
  722. // Initialize our structure with new files that need to be installed.
  723. // This should not fail because we've already performed a check and
  724. // it told us that we had new files to install.
  725. //
  726. if (!InstallCheckFileVersions()) {
  727. DPF(dlError, "[PerformInstallation] Failed to check file versions");
  728. goto InstallError;
  729. }
  730. SendMessage(g_ai.hWndProgress, PBM_STEPIT, 0, 0);
  731. if (!InstallCopyFiles()) {
  732. DPF(dlError, "[PerformInstallation] Failed to copy files");
  733. goto InstallError;
  734. }
  735. SendMessage(g_ai.hWndProgress, PBM_STEPIT, 0, 0);
  736. DPF(dlInfo, "[PerformInstallation] Installation completed successfully");
  737. g_ai.bInstallSuccess = TRUE;
  738. //
  739. // Install successful.
  740. //
  741. SendMessage(g_ai.hWndProgress, PBM_SETPOS, NUM_PB_STEPS, 0);
  742. LoadString(g_ai.hInstance, IDS_INSTALL_COMPLETE, wszError, ARRAYSIZE(wszError));
  743. SetDlgItemText(hWndParent, IDC_STATUS, wszError);
  744. EnableWindow(GetDlgItem(hWndParent, IDOK), TRUE);
  745. ShowWindow(GetDlgItem(hWndParent, IDC_LAUNCH), SW_SHOW);
  746. return;
  747. InstallError:
  748. SendMessage(g_ai.hWndProgress, PBM_SETPOS, NUM_PB_STEPS, 0);
  749. LoadString(g_ai.hInstance, IDS_INSTALL_FAILED, wszError, ARRAYSIZE(wszError));
  750. SetDlgItemText(hWndParent, IDC_STATUS, wszError);
  751. EnableWindow(GetDlgItem(hWndParent, IDCANCEL), TRUE);
  752. }