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.

1323 lines
36 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 & Server 2003
  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. 04/19/2002 rparsons Install different catalogs for Server 2003 & XP.
  19. --*/
  20. #include "main.h"
  21. extern APPINFO g_ai;
  22. /*++
  23. Routine Description:
  24. Retrieve file version info from a file.
  25. The version is specified in the dwFileVersionMS and dwFileVersionLS fields
  26. of a VS_FIXEDFILEINFO, as filled in by the win32 version APIs.
  27. If the file is not a coff image or does not have version resources,
  28. the function fails.
  29. Arguments:
  30. pwszFileName - Supplies the full path of the file whose version
  31. data is desired.
  32. pdwlVersion - Receives the version stamp of the file.
  33. If the file is not a coff image or does not contain
  34. the appropriate version resource data, the function fails.
  35. Return Value:
  36. TRUE on success, FALSE otherwise.
  37. --*/
  38. BOOL
  39. GetVersionInfoFromImage(
  40. IN LPWSTR pwszFileName,
  41. OUT PDWORDLONG pdwlVersion
  42. )
  43. {
  44. UINT cchSize;
  45. DWORD cbSize, dwIgnored;
  46. BOOL bResult = FALSE;
  47. PVOID pVersionBlock = NULL;
  48. VS_FIXEDFILEINFO* pffi = NULL;
  49. if (!pwszFileName || !pdwlVersion) {
  50. DPF(dlError, "[GetVersionInfoFromImage] Invalid arguments");
  51. return FALSE;
  52. }
  53. cbSize = GetFileVersionInfoSize(pwszFileName, &dwIgnored);
  54. if (0 == cbSize) {
  55. DPF(dlError,
  56. "[GetVersionInfoFromImage] 0x%08X Failed to get version size",
  57. GetLastError());
  58. return FALSE;
  59. }
  60. //
  61. // Allocate memory block of sufficient size to hold version info block.
  62. //
  63. pVersionBlock = HeapAlloc(GetProcessHeap(),
  64. HEAP_ZERO_MEMORY,
  65. cbSize);
  66. if (!pVersionBlock) {
  67. DPF(dlError, "[GetVersionInfoFromImage] Unable to allocate memory");
  68. return FALSE;
  69. }
  70. //
  71. // Get the version block from the file.
  72. //
  73. if (!GetFileVersionInfo(pwszFileName,
  74. 0,
  75. cbSize,
  76. pVersionBlock)) {
  77. DPF(dlError,
  78. "[GetVersionInfoFromImage] 0x%08X Failed to get version info",
  79. GetLastError());
  80. goto exit;
  81. }
  82. //
  83. // Get fixed version info.
  84. //
  85. if (!VerQueryValue(pVersionBlock,
  86. L"\\",
  87. (LPVOID*)&pffi,
  88. &cchSize)) {
  89. DPF(dlError,
  90. "[GetVersionInfoFromImage] 0x%08X Failed to fixed version info",
  91. GetLastError());
  92. goto exit;
  93. }
  94. //
  95. // Return version to caller.
  96. //
  97. *pdwlVersion = (((DWORDLONG)pffi->dwFileVersionMS) << 32) +
  98. pffi->dwFileVersionLS;
  99. bResult = TRUE;
  100. exit:
  101. if (pVersionBlock) {
  102. HeapFree(GetProcessHeap(), 0, pVersionBlock);
  103. }
  104. return bResult;
  105. }
  106. /*++
  107. Routine Description:
  108. Initializes our data structures with information about
  109. the files that we're installing/uninstalling.
  110. Arguments:
  111. None.
  112. Return Value:
  113. TRUE on success, FALSE otherwise.
  114. --*/
  115. BOOL
  116. InitializeFileInfo(
  117. void
  118. )
  119. {
  120. UINT uCount = 0;
  121. HRESULT hr;
  122. //
  123. // Set up the information for each file.
  124. // I realize that a for loop seems much more suitable here,
  125. // but we have to match up the destination for each file.
  126. // Ideally, we would have a INF file to read from that tells
  127. // us where to install each file.
  128. // For now, copying and pasting is all we need to do.
  129. //
  130. hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName,
  131. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName),
  132. FILENAME_APPVERIF_EXE);
  133. if (FAILED(hr)) {
  134. DPF(dlError, "[InitializeFileInfo] Buffer too small (1)");
  135. return FALSE;
  136. }
  137. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName,
  138. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName),
  139. L"%ls\\"FILENAME_APPVERIF_EXE,
  140. g_ai.wszCurrentDir);
  141. if (FAILED(hr)) {
  142. DPF(dlError, "[InitializeFileInfo] Buffer too small (2)");
  143. return FALSE;
  144. }
  145. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName,
  146. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName),
  147. L"%ls\\"FILENAME_APPVERIF_EXE,
  148. g_ai.wszSysDir);
  149. if (FAILED(hr)) {
  150. DPF(dlError, "[InitializeFileInfo] Buffer too small (3)");
  151. return FALSE;
  152. }
  153. if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszSrcFileName,
  154. &g_ai.rgFileInfo[uCount].dwlSrcFileVersion)) {
  155. DPF(dlError,
  156. "[InitializeFileInfo] Failed to get version info for %ls",
  157. g_ai.rgFileInfo[uCount].wszSrcFileName);
  158. return FALSE;
  159. }
  160. if (GetFileAttributes(g_ai.rgFileInfo[uCount].wszDestFileName) != -1) {
  161. if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszDestFileName,
  162. &g_ai.rgFileInfo[uCount].dwlDestFileVersion)) {
  163. DPF(dlError,
  164. "[InitializeFileInfo] Failed to get version info for %ls",
  165. g_ai.rgFileInfo[uCount].wszDestFileName);
  166. return FALSE;
  167. }
  168. }
  169. uCount++;
  170. //
  171. // Next file.
  172. //
  173. hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName,
  174. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName),
  175. FILENAME_APPVERIF_EXE_PDB);
  176. if (FAILED(hr)) {
  177. DPF(dlError, "[InitializeFileInfo] Buffer too small (4)");
  178. return FALSE;
  179. }
  180. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName,
  181. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName),
  182. L"%ls\\"FILENAME_APPVERIF_EXE_PDB,
  183. g_ai.wszCurrentDir);
  184. if (FAILED(hr)) {
  185. DPF(dlError, "[InitializeFileInfo] Buffer too small (5)");
  186. return FALSE;
  187. }
  188. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName,
  189. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName),
  190. L"%ls\\"FILENAME_APPVERIF_EXE_PDB,
  191. g_ai.wszSysDir);
  192. if (FAILED(hr)) {
  193. DPF(dlError, "[InitializeFileInfo] Buffer too small (6)");
  194. return FALSE;
  195. }
  196. uCount++;
  197. //
  198. // Next file.
  199. //
  200. hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName,
  201. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName),
  202. FILENAME_APPVERIF_CHM);
  203. if (FAILED(hr)) {
  204. DPF(dlError, "[InitializeFileInfo] Buffer too small (7)");
  205. return FALSE;
  206. }
  207. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName,
  208. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName),
  209. L"%ls\\"FILENAME_APPVERIF_CHM,
  210. g_ai.wszCurrentDir);
  211. if (FAILED(hr)) {
  212. DPF(dlError, "[InitializeFileInfo] Buffer too small (8)");
  213. return FALSE;
  214. }
  215. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName,
  216. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName),
  217. L"%ls\\"FILENAME_APPVERIF_CHM,
  218. g_ai.wszSysDir);
  219. if (FAILED(hr)) {
  220. DPF(dlError, "[InitializeFileInfo] Buffer too small (9)");
  221. return FALSE;
  222. }
  223. uCount++;
  224. //
  225. // Next file.
  226. //
  227. hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName,
  228. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName),
  229. FILENAME_ACVERFYR_DLL);
  230. if (FAILED(hr)) {
  231. DPF(dlError, "[InitializeFileInfo] Buffer too small (10)");
  232. return FALSE;
  233. }
  234. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName,
  235. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName),
  236. L"%ls\\"FILENAME_ACVERFYR_DLL,
  237. g_ai.wszCurrentDir);
  238. if (FAILED(hr)) {
  239. DPF(dlError, "[InitializeFileInfo] Buffer too small (11)");
  240. return FALSE;
  241. }
  242. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName,
  243. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName),
  244. L"%ls\\AppPatch\\"FILENAME_ACVERFYR_DLL,
  245. g_ai.wszWinDir);
  246. if (FAILED(hr)) {
  247. DPF(dlError, "[InitializeFileInfo] Buffer too small (12)");
  248. return FALSE;
  249. }
  250. if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszSrcFileName,
  251. &g_ai.rgFileInfo[uCount].dwlSrcFileVersion)) {
  252. DPF(dlError,
  253. "[InitializeFileInfo] Failed to get version info for %ls",
  254. g_ai.rgFileInfo[uCount].wszSrcFileName);
  255. return FALSE;
  256. }
  257. if (GetFileAttributes(g_ai.rgFileInfo[uCount].wszDestFileName) != -1) {
  258. if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszDestFileName,
  259. &g_ai.rgFileInfo[uCount].dwlDestFileVersion)) {
  260. DPF(dlError,
  261. "[InitializeFileInfo] Failed to get version info for %ls",
  262. g_ai.rgFileInfo[uCount].wszDestFileName);
  263. return FALSE;
  264. }
  265. }
  266. uCount++;
  267. //
  268. // Next file.
  269. //
  270. hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName,
  271. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName),
  272. FILENAME_ACVERFYR_DLL_PDB);
  273. if (FAILED(hr)) {
  274. DPF(dlError, "[InitializeFileInfo] Buffer too small (13)");
  275. return FALSE;
  276. }
  277. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName,
  278. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName),
  279. L"%ls\\"FILENAME_ACVERFYR_DLL_PDB,
  280. g_ai.wszCurrentDir);
  281. if (FAILED(hr)) {
  282. DPF(dlError, "[InitializeFileInfo] Buffer too small (14)");
  283. return FALSE;
  284. }
  285. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName,
  286. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName),
  287. L"%ls\\AppPatch\\"FILENAME_ACVERFYR_DLL_PDB,
  288. g_ai.wszWinDir);
  289. if (FAILED(hr)) {
  290. DPF(dlError, "[InitializeFileInfo] Buffer too small (15)");
  291. return FALSE;
  292. }
  293. uCount++;
  294. //
  295. // Next file.
  296. //
  297. hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName,
  298. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName),
  299. FILENAME_ACVERFYR_DLL);
  300. if (FAILED(hr)) {
  301. DPF(dlError, "[InitializeFileInfo] Buffer too small (16)");
  302. return FALSE;
  303. }
  304. g_ai.rgFileInfo[uCount].bWin2KOnly = TRUE;
  305. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName,
  306. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName),
  307. L"%ls\\"FILENAME_ACVERFYR_DLL_W2K,
  308. g_ai.wszCurrentDir);
  309. if (FAILED(hr)) {
  310. DPF(dlError, "[InitializeFileInfo] Buffer too small (17)");
  311. return FALSE;
  312. }
  313. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName,
  314. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName),
  315. L"%ls\\AppPatch\\"FILENAME_ACVERFYR_DLL,
  316. g_ai.wszWinDir);
  317. if (FAILED(hr)) {
  318. DPF(dlError, "[InitializeFileInfo] Buffer too small (18)");
  319. return FALSE;
  320. }
  321. if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszSrcFileName,
  322. &g_ai.rgFileInfo[uCount].dwlSrcFileVersion)) {
  323. DPF(dlError,
  324. "[InitializeFileInfo] Failed to get version info for %ls",
  325. g_ai.rgFileInfo[uCount].wszSrcFileName);
  326. return FALSE;
  327. }
  328. if (GetFileAttributes(g_ai.rgFileInfo[uCount].wszDestFileName) != -1) {
  329. if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszDestFileName,
  330. &g_ai.rgFileInfo[uCount].dwlDestFileVersion)) {
  331. DPF(dlError,
  332. "[InitializeFileInfo] Failed to get version info for %ls",
  333. g_ai.rgFileInfo[uCount].wszDestFileName);
  334. return FALSE;
  335. }
  336. }
  337. uCount++;
  338. //
  339. // Next file.
  340. //
  341. hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName,
  342. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName),
  343. FILENAME_ACVERFYR_DLL_PDB);
  344. if (FAILED(hr)) {
  345. DPF(dlError, "[InitializeFileInfo] Buffer too small (19)");
  346. return FALSE;
  347. }
  348. g_ai.rgFileInfo[uCount].bWin2KOnly = TRUE;
  349. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName,
  350. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName),
  351. L"%ls\\"FILENAME_ACVERFYR_DLL_W2K_PDB,
  352. g_ai.wszCurrentDir);
  353. if (FAILED(hr)) {
  354. DPF(dlError, "[InitializeFileInfo] Buffer too small (20)");
  355. return FALSE;
  356. }
  357. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName,
  358. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName),
  359. L"%ls\\AppPatch\\"FILENAME_ACVERFYR_DLL_PDB,
  360. g_ai.wszWinDir);
  361. if (FAILED(hr)) {
  362. DPF(dlError, "[InitializeFileInfo] Buffer too small (21)");
  363. return FALSE;
  364. }
  365. uCount++;
  366. //
  367. // Next file.
  368. //
  369. hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName,
  370. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName),
  371. FILENAME_MSVCP60_DLL);
  372. if (FAILED(hr)) {
  373. DPF(dlError, "[InitializeFileInfo] Buffer too small (22)");
  374. return FALSE;
  375. }
  376. g_ai.rgFileInfo[uCount].bWin2KOnly = TRUE;
  377. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName,
  378. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName),
  379. L"%ls\\"FILENAME_MSVCP60_DLL,
  380. g_ai.wszCurrentDir);
  381. if (FAILED(hr)) {
  382. DPF(dlError, "[InitializeFileInfo] Buffer too small (23)");
  383. return FALSE;
  384. }
  385. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName,
  386. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName),
  387. L"%ls\\"FILENAME_MSVCP60_DLL,
  388. g_ai.wszWinDir);
  389. if (FAILED(hr)) {
  390. DPF(dlError, "[InitializeFileInfo] Buffer too small (24)");
  391. return FALSE;
  392. }
  393. if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszSrcFileName,
  394. &g_ai.rgFileInfo[uCount].dwlSrcFileVersion)) {
  395. DPF(dlError,
  396. "[InitializeFileInfo] Failed to get version info for %ls",
  397. g_ai.rgFileInfo[uCount].wszSrcFileName);
  398. return FALSE;
  399. }
  400. if (GetFileAttributes(g_ai.rgFileInfo[uCount].wszDestFileName) != -1) {
  401. if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszDestFileName,
  402. &g_ai.rgFileInfo[uCount].dwlDestFileVersion)) {
  403. DPF(dlError,
  404. "[InitializeFileInfo] Failed to get version info for %ls",
  405. g_ai.rgFileInfo[uCount].wszDestFileName);
  406. return FALSE;
  407. }
  408. }
  409. uCount++;
  410. //
  411. // Next file.
  412. //
  413. hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName,
  414. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName),
  415. FILENAME_SDBINST_EXE);
  416. if (FAILED(hr)) {
  417. DPF(dlError, "[InitializeFileInfo] Buffer too small (25)");
  418. return FALSE;
  419. }
  420. g_ai.rgFileInfo[uCount].bWin2KOnly = TRUE;
  421. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName,
  422. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName),
  423. L"%ls\\"FILENAME_SDBINST_EXE,
  424. g_ai.wszCurrentDir);
  425. if (FAILED(hr)) {
  426. DPF(dlError, "[InitializeFileInfo] Buffer too small (26)");
  427. return FALSE;
  428. }
  429. hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName,
  430. ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName),
  431. L"%ls\\"FILENAME_SDBINST_EXE,
  432. g_ai.wszSysDir);
  433. if (FAILED(hr)) {
  434. DPF(dlError, "[InitializeFileInfo] Buffer too small (27)");
  435. return FALSE;
  436. }
  437. if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszSrcFileName,
  438. &g_ai.rgFileInfo[uCount].dwlSrcFileVersion)) {
  439. DPF(dlError,
  440. "[InitializeFileInfo] Failed to get version info for %ls",
  441. g_ai.rgFileInfo[uCount].wszSrcFileName);
  442. return FALSE;
  443. }
  444. if (GetFileAttributes(g_ai.rgFileInfo[uCount].wszDestFileName) != -1) {
  445. if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszDestFileName,
  446. &g_ai.rgFileInfo[uCount].dwlDestFileVersion)) {
  447. DPF(dlError,
  448. "[InitializeFileInfo] Failed to get version info for %ls",
  449. g_ai.rgFileInfo[uCount].wszDestFileName);
  450. return FALSE;
  451. }
  452. }
  453. return TRUE;
  454. }
  455. /*++
  456. Routine Description:
  457. Determines if any of the files we have to offer
  458. are newer than ones already installed.
  459. Arguments:
  460. None.
  461. Return Value:
  462. TRUE if we have at least one new file to offer.
  463. FALSE if we don't have at least one new file to offer.
  464. --*/
  465. BOOL
  466. InstallCheckFileVersions(
  467. void
  468. )
  469. {
  470. UINT uCount;
  471. BOOL bReturn = FALSE;
  472. for (uCount = 0; uCount < NUM_FILES; uCount++) {
  473. if (g_ai.rgFileInfo[uCount].dwlSrcFileVersion >=
  474. g_ai.rgFileInfo[uCount].dwlDestFileVersion) {
  475. g_ai.rgFileInfo[uCount].bInstall = TRUE;
  476. bReturn = TRUE;
  477. }
  478. }
  479. return bReturn;
  480. }
  481. /*++
  482. Routine Description:
  483. Determines if we have a newer version of appverif.exe
  484. or acverfyr.dll to offer.
  485. Arguments:
  486. None.
  487. Return Value:
  488. TRUE if our version is newer than the one installed.
  489. or if there is no version installed.
  490. FALSE otherwise.
  491. --*/
  492. BOOL
  493. IsPkgAppVerifNewer(
  494. void
  495. )
  496. {
  497. //
  498. // Check appverif.exe first.
  499. //
  500. if (g_ai.rgFileInfo[0].dwlSrcFileVersion >=
  501. g_ai.rgFileInfo[0].dwlDestFileVersion) {
  502. return TRUE;
  503. }
  504. //
  505. // Check acverfyr.dll if appverif.exe didn't pan out.
  506. // Do this based on the platform.
  507. //
  508. if (g_ai.ePlatform == osWindowsXP || g_ai.ePlatform == osWindowsDotNet) {
  509. if (g_ai.rgFileInfo[1].dwlSrcFileVersion >=
  510. g_ai.rgFileInfo[1].dwlDestFileVersion) {
  511. return TRUE;
  512. }
  513. } else {
  514. if (g_ai.rgFileInfo[2].dwlSrcFileVersion >=
  515. g_ai.rgFileInfo[2].dwlDestFileVersion) {
  516. return TRUE;
  517. }
  518. }
  519. //
  520. // Perhaps we have a newer version of sdbinst to offer.
  521. //
  522. if (g_ai.ePlatform == osWindows2000) {
  523. if (g_ai.rgFileInfo[8].dwlSrcFileVersion >=
  524. g_ai.rgFileInfo[8].dwlDestFileVersion) {
  525. return TRUE;
  526. }
  527. }
  528. return FALSE;
  529. }
  530. /*++
  531. Routine Description:
  532. Performs a file copy, even if it's in use.
  533. Arguments:
  534. pwszSourceFileName - Name of the source file to copy.
  535. pwszDestFileName - Name of the destination file to replace.
  536. Return Value:
  537. TRUE on success, FALSE otherwise.
  538. --*/
  539. BOOL
  540. ForceCopy(
  541. IN LPCWSTR pwszSourceFileName,
  542. IN LPCWSTR pwszDestFileName
  543. )
  544. {
  545. WCHAR wszTempPath[MAX_PATH];
  546. WCHAR wszDelFileName[MAX_PATH];
  547. DWORD cchSize;
  548. if (!pwszSourceFileName || !pwszDestFileName) {
  549. DPF(dlError, "[ForceCopy] Invalid parameters");
  550. return FALSE;
  551. }
  552. DPF(dlInfo, "[ForceCopy] Source file: %ls", pwszSourceFileName);
  553. DPF(dlInfo, "[ForceCopy] Destination file: %ls", pwszDestFileName);
  554. if (!CopyFile(pwszSourceFileName, pwszDestFileName, FALSE)) {
  555. cchSize = GetTempPath(ARRAYSIZE(wszTempPath), wszTempPath);
  556. if (cchSize > ARRAYSIZE(wszTempPath) || cchSize == 0) {
  557. DPF(dlError, "[ForceCopy] Buffer for temp path is too small");
  558. return FALSE;
  559. }
  560. if (!GetTempFileName(wszTempPath, L"del", 0, wszDelFileName)) {
  561. DPF(dlError,
  562. "[ForceCopy] 0x%08X Failed to get temp file",
  563. GetLastError());
  564. return FALSE;
  565. }
  566. if (!MoveFileEx(pwszDestFileName,
  567. wszDelFileName,
  568. MOVEFILE_REPLACE_EXISTING)) {
  569. DPF(dlError,
  570. "[ForceCopy] 0x%08X Failed to replace file",
  571. GetLastError());
  572. return FALSE;
  573. }
  574. if (!MoveFileEx(wszDelFileName,
  575. NULL,
  576. MOVEFILE_DELAY_UNTIL_REBOOT)) {
  577. DPF(dlError,
  578. "[ForceCopy] 0x%08X Failed to delete file",
  579. GetLastError());
  580. return FALSE;
  581. }
  582. if (!CopyFile(pwszSourceFileName, pwszDestFileName, FALSE)) {
  583. DPF(dlError,
  584. "[ForceCopy] 0x%08X Failed to copy file",
  585. GetLastError());
  586. return FALSE;
  587. }
  588. }
  589. return TRUE;
  590. }
  591. /*++
  592. Routine Description:
  593. Prints a formatted string to the debugger.
  594. Arguments:
  595. dwDetail - Specifies the level of the information provided.
  596. pszFmt - The string to be displayed.
  597. ... - A va_list of insertion strings.
  598. Return Value:
  599. None.
  600. --*/
  601. void
  602. __cdecl
  603. DebugPrintfEx(
  604. IN DEBUGLEVEL dwDetail,
  605. IN LPSTR pszFmt,
  606. ...
  607. )
  608. {
  609. char szT[1024];
  610. va_list arglist;
  611. int len;
  612. va_start(arglist, pszFmt);
  613. //
  614. // Reserve one character for the potential '\n' that we may be adding.
  615. //
  616. StringCchVPrintfA(szT, sizeof(szT) - 1, pszFmt, arglist);
  617. va_end(arglist);
  618. //
  619. // Make sure we have a '\n' at the end of the string
  620. //
  621. len = strlen(szT);
  622. if (len > 0 && szT[len - 1] != '\n') {
  623. szT[len] = '\n';
  624. szT[len + 1] = 0;
  625. }
  626. switch (dwDetail) {
  627. case dlPrint:
  628. DbgPrint("[MSG ] ");
  629. break;
  630. case dlError:
  631. DbgPrint("[FAIL] ");
  632. break;
  633. case dlWarning:
  634. DbgPrint("[WARN] ");
  635. break;
  636. case dlInfo:
  637. DbgPrint("[INFO] ");
  638. break;
  639. default:
  640. DbgPrint("[XXXX] ");
  641. break;
  642. }
  643. DbgPrint("%s", szT);
  644. }
  645. /*++
  646. Routine Description:
  647. Initializes the installer. Sets up paths, version
  648. information, etc.
  649. Arguments:
  650. None.
  651. Return Value:
  652. TRUE on success.
  653. FALSE on failure.
  654. -1 if the operating system is not supported.
  655. --*/
  656. int
  657. InitializeInstaller(
  658. void
  659. )
  660. {
  661. OSVERSIONINFO osvi;
  662. WCHAR* pTemp = NULL;
  663. UINT cchSize;
  664. DWORD cchReturned;
  665. HRESULT hr;
  666. //
  667. // Find out what operating system we're running on.
  668. //
  669. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  670. if (!GetVersionEx(&osvi)) {
  671. DPF(dlError,
  672. "[InitializeInstaller] 0x%08X Failed to get OS version info",
  673. GetLastError());
  674. return FALSE;
  675. }
  676. //
  677. // No support for Win9x or NT4.
  678. //
  679. if (osvi.dwMajorVersion == 4) {
  680. DPF(dlInfo, "[InitializeInstaller] OS not supported");
  681. return -1;
  682. }
  683. if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) {
  684. g_ai.ePlatform = osWindows2000;
  685. } else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
  686. g_ai.ePlatform = osWindowsXP;
  687. } else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion >= 2) {
  688. g_ai.ePlatform = osWindowsDotNet;
  689. }
  690. //
  691. // Find out where we're running from.
  692. //
  693. g_ai.wszModuleName[ARRAYSIZE(g_ai.wszModuleName) - 1] = 0;
  694. cchReturned = GetModuleFileName(NULL,
  695. g_ai.wszModuleName,
  696. ARRAYSIZE(g_ai.wszModuleName));
  697. if (g_ai.wszModuleName[ARRAYSIZE(g_ai.wszModuleName) - 1] != 0 ||
  698. cchReturned == 0) {
  699. DPF(dlError,
  700. "[InitializeInstaller] 0x%08X Failed to get module file name",
  701. GetLastError());
  702. return FALSE;
  703. }
  704. //
  705. // Save away our current directory for later use.
  706. //
  707. hr = StringCchCopy(g_ai.wszCurrentDir,
  708. ARRAYSIZE(g_ai.wszCurrentDir),
  709. g_ai.wszModuleName);
  710. if (FAILED(hr)) {
  711. DPF(dlError, "[InitializeInstaller] 0x%08X String copy failed", hr);
  712. return FALSE;
  713. }
  714. pTemp = wcsrchr(g_ai.wszCurrentDir, '\\');
  715. if (pTemp) {
  716. *pTemp = 0;
  717. }
  718. //
  719. // Save away paths to the Windows & System32 directories for later use.
  720. //
  721. cchSize = GetSystemWindowsDirectory(g_ai.wszWinDir,
  722. ARRAYSIZE(g_ai.wszWinDir));
  723. if (cchSize > ARRAYSIZE(g_ai.wszWinDir) || cchSize == 0) {
  724. DPF(dlError,
  725. "[InitializeInstaller] 0x%08X Failed to get Windows directory",
  726. GetLastError());
  727. return FALSE;
  728. }
  729. cchSize = GetSystemDirectory(g_ai.wszSysDir, ARRAYSIZE(g_ai.wszSysDir));
  730. if (cchSize > ARRAYSIZE(g_ai.wszSysDir) || cchSize == 0) {
  731. DPF(dlError,
  732. "[InitializeInstaller] 0x%08X Failed to get system directory",
  733. GetLastError());
  734. return FALSE;
  735. }
  736. return TRUE;
  737. }
  738. /*++
  739. Routine Description:
  740. Launches the Application Verifier.
  741. Arguments:
  742. None.
  743. Return Value:
  744. None.
  745. --*/
  746. void
  747. InstallLaunchExe(
  748. void
  749. )
  750. {
  751. STARTUPINFO si;
  752. PROCESS_INFORMATION pi;
  753. WCHAR wszAppVerifExe[MAX_PATH];
  754. HRESULT hr;
  755. hr = StringCchPrintf(wszAppVerifExe,
  756. ARRAYSIZE(wszAppVerifExe),
  757. L"%ls\\"FILENAME_APPVERIF_EXE,
  758. g_ai.wszSysDir);
  759. if (FAILED(hr)) {
  760. DPF(dlError, "[InstallLaunchExe] Buffer too small");
  761. return;
  762. }
  763. ZeroMemory(&si, sizeof(STARTUPINFO));
  764. ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
  765. si.cb = sizeof(STARTUPINFO);
  766. if (!CreateProcess(wszAppVerifExe,
  767. NULL,
  768. NULL,
  769. NULL,
  770. FALSE,
  771. 0,
  772. NULL,
  773. NULL,
  774. &si,
  775. &pi)) {
  776. DPF(dlError,
  777. "[InstallLaunchExe] 0x%08X Failed to launch %ls",
  778. GetLastError(),
  779. wszAppVerifExe);
  780. return;
  781. }
  782. CloseHandle(pi.hProcess);
  783. CloseHandle(pi.hThread);
  784. }
  785. /*++
  786. Routine Description:
  787. Installs the catalog file.
  788. Arguments:
  789. pwszCatFileName - Name of the catalog file to install.
  790. Return Value:
  791. TRUE on success, FALSE otherwise.
  792. --*/
  793. BOOL
  794. InstallCatalogFile(
  795. IN LPWSTR pwszCatFileName
  796. )
  797. {
  798. HCATADMIN hCatAdmin;
  799. HCATINFO hCatInfo;
  800. GUID guidCatRoot;
  801. if (!pwszCatFileName) {
  802. DPF(dlError, "[InstallCatalogFile] Invalid parameter");
  803. return FALSE;
  804. }
  805. StringToGuid(L"{F750E6C3-38EE-11D1-85E5-00C04FC295EE}", &guidCatRoot);
  806. if (!CryptCATAdminAcquireContext(&hCatAdmin, &guidCatRoot, 0)) {
  807. DPF(dlError,
  808. "[InstallCatalogFile] 0x%08X Failed to acquire context",
  809. GetLastError());
  810. return FALSE;
  811. }
  812. hCatInfo = CryptCATAdminAddCatalog(hCatAdmin,
  813. pwszCatFileName,
  814. NULL,
  815. 0);
  816. if (hCatInfo) {
  817. CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0);
  818. CryptCATAdminReleaseContext(hCatAdmin, 0);
  819. return TRUE;
  820. }
  821. CryptCATAdminReleaseContext(hCatAdmin, 0);
  822. DPF(dlError,
  823. "[InstallCatalogFile] 0x%08X Failed to add catalog %ls",
  824. GetLastError(),
  825. pwszCatFileName);
  826. return FALSE;
  827. }
  828. /*++
  829. Routine Description:
  830. Installs a certificate into the certificate store.
  831. Arguments:
  832. None.
  833. Return Value:
  834. TRUE on success, FALSE otherwise.
  835. --*/
  836. BOOL
  837. InstallCertificateFile(
  838. void
  839. )
  840. {
  841. STARTUPINFO si;
  842. PROCESS_INFORMATION pi;
  843. WCHAR wszCertMgrName[MAX_PATH];
  844. WCHAR wszCertMgrCmdLine[MAX_PATH];
  845. HRESULT hr;
  846. ZeroMemory(&si, sizeof(STARTUPINFO));
  847. ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
  848. si.cb = sizeof(STARTUPINFO);
  849. //
  850. // Set up the path to certmgr.exe.
  851. //
  852. hr = StringCchPrintf(wszCertMgrName,
  853. ARRAYSIZE(wszCertMgrName),
  854. L"%ls\\"CERTMGR_EXE,
  855. g_ai.wszCurrentDir);
  856. if (FAILED(hr)) {
  857. DPF(dlError, "[InstallCertificateFile] Buffer too small (1)");
  858. return FALSE;
  859. }
  860. //
  861. // Set up the command-line for certmgr.exe.
  862. //
  863. hr = StringCchPrintf(wszCertMgrCmdLine,
  864. ARRAYSIZE(wszCertMgrCmdLine),
  865. L"%ls\\%ls %ls",
  866. g_ai.wszCurrentDir,
  867. CERTMGR_EXE,
  868. CERTMGR_CMD);
  869. if (FAILED(hr)) {
  870. DPF(dlError, "[InstallCertificateFile] Buffer too small (2)");
  871. return FALSE;
  872. }
  873. if (!CreateProcess(wszCertMgrName,
  874. wszCertMgrCmdLine,
  875. NULL,
  876. NULL,
  877. FALSE,
  878. CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS,
  879. NULL,
  880. NULL,
  881. &si,
  882. &pi)) {
  883. DPF(dlError,
  884. "[InstallCertificateFile] 0x%08X Failed to launch '%ls %ls'",
  885. GetLastError(),
  886. wszCertMgrName,
  887. wszCertMgrCmdLine);
  888. return FALSE;
  889. }
  890. CloseHandle(pi.hProcess);
  891. CloseHandle(pi.hThread);
  892. return TRUE;
  893. }
  894. /*++
  895. Routine Description:
  896. Performs the installation of the catalog file
  897. on Windows XP or Windows Server 2003.
  898. Arguments:
  899. None.
  900. Return Value:
  901. TRUE on success, FALSE otherwise.
  902. --*/
  903. BOOL
  904. PerformCatalogInstall(
  905. void
  906. )
  907. {
  908. WCHAR wszCatalog[MAX_PATH];
  909. HRESULT hr;
  910. if (g_ai.ePlatform == osWindowsXP) {
  911. hr = StringCchPrintf(wszCatalog,
  912. ARRAYSIZE(wszCatalog),
  913. L"%ls\\"FILENAME_DELTA_CAT_XP,
  914. g_ai.wszCurrentDir);
  915. } else if (g_ai.ePlatform == osWindowsDotNet) {
  916. hr = StringCchPrintf(wszCatalog,
  917. ARRAYSIZE(wszCatalog),
  918. L"%ls\\"FILENAME_DELTA_CAT_DOTNET,
  919. g_ai.wszCurrentDir);
  920. }
  921. if (FAILED(hr)) {
  922. DPF(dlError, "[PerformCatalogInstall] Buffer too small");
  923. return FALSE;
  924. }
  925. return (InstallCatalogFile(wszCatalog));
  926. }
  927. /*++
  928. Routine Description:
  929. Copies the files that we've determined are
  930. newer to their specified destination.
  931. Arguments:
  932. None.
  933. Return Value:
  934. TRUE on success, FALSE otherwise.
  935. --*/
  936. BOOL
  937. InstallCopyFiles(
  938. void
  939. )
  940. {
  941. UINT uCount;
  942. while (TRUE) {
  943. for (uCount = 0; uCount < NUM_FILES; uCount++) {
  944. if (g_ai.rgFileInfo[uCount].bInstall) {
  945. //
  946. // If we're on XP and the file is not specifically for
  947. // Windows 2000, copy it over.
  948. //
  949. if (g_ai.ePlatform != osWindows2000 &&
  950. g_ai.rgFileInfo[uCount].bWin2KOnly) {
  951. break;
  952. }
  953. if (!ForceCopy(g_ai.rgFileInfo[uCount].wszSrcFileName,
  954. g_ai.rgFileInfo[uCount].wszDestFileName)) {
  955. DPF(dlError,
  956. "[InstallCopyFiles] Failed to copy %ls to %ls",
  957. g_ai.rgFileInfo[uCount].wszSrcFileName,
  958. g_ai.rgFileInfo[uCount].wszDestFileName);
  959. return FALSE;
  960. }
  961. }
  962. }
  963. break;
  964. }
  965. return TRUE;
  966. }
  967. /*++
  968. Routine Description:
  969. Performs the installation. This is the main routine
  970. for the install.
  971. Arguments:
  972. hWndParent - Parent window handle for message boxes.
  973. Return Value:
  974. None.
  975. --*/
  976. void
  977. PerformInstallation(
  978. IN HWND hWndParent
  979. )
  980. {
  981. WCHAR wszError[MAX_PATH];
  982. SendMessage(g_ai.hWndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, NUM_PB_STEPS));
  983. SendMessage(g_ai.hWndProgress, PBM_SETSTEP, 1, 0);
  984. //
  985. // Initialize our structure with new files that need to be installed.
  986. // This should not fail because we've already performed a check and
  987. // it told us that we had new files to install.
  988. //
  989. if (!InstallCheckFileVersions()) {
  990. DPF(dlError, "[PerformInstallation] Failed to check file versions");
  991. goto InstallError;
  992. }
  993. //
  994. // If we're running on Windows XP or Server 2003, install a catalog file
  995. // and our certificate. We have different catalogs for XP versus Server 2003.
  996. //
  997. if (g_ai.ePlatform == osWindowsXP || g_ai.ePlatform == osWindowsDotNet) {
  998. if (!PerformCatalogInstall()) {
  999. DPF(dlError, "[PerformInstallation] Failed to install catalog");
  1000. goto InstallError;
  1001. }
  1002. SendMessage(g_ai.hWndProgress, PBM_STEPIT, 0, 0);
  1003. if (!InstallCertificateFile()) {
  1004. DPF(dlError, "[PerformInstallation] Failed to install certificate");
  1005. goto InstallError;
  1006. }
  1007. }
  1008. SendMessage(g_ai.hWndProgress, PBM_STEPIT, 0, 0);
  1009. if (!InstallCopyFiles()) {
  1010. DPF(dlError, "[PerformInstallation] Failed to copy files");
  1011. goto InstallError;
  1012. }
  1013. SendMessage(g_ai.hWndProgress, PBM_STEPIT, 0, 0);
  1014. DPF(dlInfo, "[PerformInstallation] Installation completed successfully");
  1015. g_ai.bInstallSuccess = TRUE;
  1016. //
  1017. // Install successful.
  1018. //
  1019. SendMessage(g_ai.hWndProgress, PBM_SETPOS, NUM_PB_STEPS, 0);
  1020. LoadString(g_ai.hInstance, IDS_INSTALL_COMPLETE, wszError, ARRAYSIZE(wszError));
  1021. SetDlgItemText(hWndParent, IDC_STATUS, wszError);
  1022. EnableWindow(GetDlgItem(hWndParent, IDOK), TRUE);
  1023. ShowWindow(GetDlgItem(hWndParent, IDC_LAUNCH), SW_SHOW);
  1024. return;
  1025. InstallError:
  1026. SendMessage(g_ai.hWndProgress, PBM_SETPOS, NUM_PB_STEPS, 0);
  1027. LoadString(g_ai.hInstance, IDS_INSTALL_FAILED, wszError, ARRAYSIZE(wszError));
  1028. SetDlgItemText(hWndParent, IDC_STATUS, wszError);
  1029. EnableWindow(GetDlgItem(hWndParent, IDCANCEL), TRUE);
  1030. }