Source code of Windows XP (NT5)
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.

1017 lines
27 KiB

  1. //////////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Main.cpp
  4. //
  5. // Microsoft CONFIDENTIAL
  6. //
  7. // Copyright (C) 1998, 1999 Microsoft Corporation. All rights reserved.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////////////////////
  10. //
  11. // Make sure to enable multi-threading and OLE2
  12. //
  13. #ifndef _MT
  14. #define _MT
  15. #endif
  16. #include <windows.h>
  17. #include <stdio.h>
  18. #include <process.h>
  19. #include <assert.h>
  20. #include <string.h>
  21. #include "Global.h"
  22. #include "RunOnce.h"
  23. #include "RegistryKey.h"
  24. //////////////////////////////////////////////////////////////////////////////////////////////
  25. //
  26. //////////////////////////////////////////////////////////////////////////////////////////////
  27. BOOL ExtractComponent(const DWORD dwIndex, LPCTSTR strPath)
  28. {
  29. BOOL fSuccess = FALSE;
  30. HRSRC hResourceInfo;
  31. HGLOBAL hResource;
  32. LPVOID lpResourceImage;
  33. HANDLE hFileHandle;
  34. DWORD dwBytesToWrite, dwBytesWritten;
  35. TCHAR strDestinationFilename[MAX_PATH];
  36. //
  37. // Build the destination filename
  38. //
  39. wsprintf(strDestinationFilename, TEXT("%s\\%s"), strPath, g_sComponentInfo[dwIndex].strFilename);
  40. //
  41. // Get the resource that contains the binary image of TestSample.exe
  42. //
  43. hResourceInfo = FindResource(g_hInstance, MAKEINTRESOURCE(g_sComponentInfo[dwIndex].dwResourceId), "BINARY");
  44. if (NULL != hResourceInfo)
  45. {
  46. hResource = LoadResource(g_hInstance, hResourceInfo);
  47. if (NULL != hResource)
  48. {
  49. dwBytesToWrite = SizeofResource(g_hInstance, hResourceInfo);
  50. if (0 < dwBytesToWrite)
  51. {
  52. lpResourceImage = LockResource(hResource);
  53. if (NULL != lpResourceImage)
  54. {
  55. //
  56. // Make sure to delete the existing file
  57. //
  58. if (FileExists(strDestinationFilename))
  59. {
  60. SetFileAttributes(strDestinationFilename, FILE_ATTRIBUTE_NORMAL);
  61. DeleteFile(strDestinationFilename);
  62. }
  63. //
  64. // Write it to a file
  65. //
  66. hFileHandle = CreateFile(strDestinationFilename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);
  67. if (INVALID_HANDLE_VALUE != hFileHandle)
  68. {
  69. //
  70. // Write the bits to the file
  71. //
  72. if (WriteFile(hFileHandle, lpResourceImage, dwBytesToWrite, &dwBytesWritten, NULL))
  73. {
  74. if (dwBytesToWrite == dwBytesWritten)
  75. {
  76. fSuccess = TRUE;
  77. }
  78. }
  79. //
  80. // Close the file
  81. //
  82. CloseHandle(hFileHandle);
  83. }
  84. }
  85. }
  86. }
  87. }
  88. return fSuccess;
  89. }
  90. //////////////////////////////////////////////////////////////////////////////////////////////
  91. //
  92. //////////////////////////////////////////////////////////////////////////////////////////////
  93. BOOL GetFileVersion(LPTSTR strFilename, VS_FIXEDFILEINFO * lpFileInfo)
  94. {
  95. BOOL fSuccess = FALSE;
  96. LPVOID lpVersion;
  97. LPVOID lpVersionInfo;
  98. UINT uSize;
  99. DWORD dwSize, dwEmpty;
  100. //
  101. // By default we zero out the lpFileInfo buffer
  102. //
  103. ZeroMemory(lpFileInfo, sizeof(VS_FIXEDFILEINFO));
  104. //
  105. // Go get the version info for that file
  106. //
  107. dwSize = GetFileVersionInfoSize((LPTSTR) strFilename, &dwEmpty);
  108. if (0 != dwSize)
  109. {
  110. lpVersion = new BYTE [dwSize];
  111. ZeroMemory(lpVersion, dwSize);
  112. if (NULL != lpVersion)
  113. {
  114. if (0 != GetFileVersionInfo(strFilename, 0, dwSize, lpVersion))
  115. {
  116. if (0 != VerQueryValue(lpVersion, TEXT("\\"), &lpVersionInfo, &uSize))
  117. {
  118. if (uSize == sizeof(VS_FIXEDFILEINFO))
  119. {
  120. //
  121. // Save the version information
  122. //
  123. CopyMemory(lpFileInfo, lpVersionInfo, sizeof(VS_FIXEDFILEINFO));
  124. //
  125. // delete the memory allocated to lpVersion
  126. //
  127. delete [] lpVersion;
  128. //
  129. // Everything was successful
  130. //
  131. fSuccess = TRUE;
  132. }
  133. }
  134. }
  135. }
  136. }
  137. return fSuccess;
  138. }
  139. //////////////////////////////////////////////////////////////////////////////////////////////
  140. //
  141. //////////////////////////////////////////////////////////////////////////////////////////////
  142. DWORD CompareFileVersions(VS_FIXEDFILEINFO * lpFileInfo1, VS_FIXEDFILEINFO * lpFileInfo2)
  143. {
  144. if (HIWORD(lpFileInfo1->dwFileVersionMS) > HIWORD(lpFileInfo2->dwFileVersionMS))
  145. {
  146. return COMPONENT_NEWER_VERSION;
  147. }
  148. if (HIWORD(lpFileInfo1->dwFileVersionMS) < HIWORD(lpFileInfo2->dwFileVersionMS))
  149. {
  150. return COMPONENT_OLDER_VERSION;
  151. }
  152. if (LOWORD(lpFileInfo1->dwFileVersionMS) > LOWORD(lpFileInfo2->dwFileVersionMS))
  153. {
  154. return COMPONENT_NEWER_VERSION;
  155. }
  156. if (LOWORD(lpFileInfo1->dwFileVersionMS) < LOWORD(lpFileInfo2->dwFileVersionMS))
  157. {
  158. return COMPONENT_OLDER_VERSION;
  159. }
  160. if (HIWORD(lpFileInfo1->dwFileVersionLS) > HIWORD(lpFileInfo2->dwFileVersionLS))
  161. {
  162. return COMPONENT_NEWER_VERSION;
  163. }
  164. if (HIWORD(lpFileInfo1->dwFileVersionLS) < HIWORD(lpFileInfo2->dwFileVersionLS))
  165. {
  166. return COMPONENT_OLDER_VERSION;
  167. }
  168. if (LOWORD(lpFileInfo1->dwFileVersionLS) > LOWORD(lpFileInfo2->dwFileVersionLS))
  169. {
  170. return COMPONENT_NEWER_VERSION;
  171. }
  172. if (LOWORD(lpFileInfo1->dwFileVersionLS) < LOWORD(lpFileInfo2->dwFileVersionLS))
  173. {
  174. return COMPONENT_OLDER_VERSION;
  175. }
  176. return COMPONENT_SAME_VERSION;
  177. }
  178. //////////////////////////////////////////////////////////////////////////////////////////////
  179. //
  180. //////////////////////////////////////////////////////////////////////////////////////////////
  181. DWORD CompareFiles(LPCTSTR strFile1, LPCTSTR strFile2)
  182. {
  183. HANDLE hFileHandle[2];
  184. HANDLE hFileMapping[2];
  185. LPVOID lpFileView[2];
  186. DWORD dwFileSize[2];
  187. DWORD dwReturnCode = 0xffffffff;
  188. //
  189. // Open strFile1
  190. //
  191. hFileHandle[0] = CreateFile(strFile1, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  192. if (INVALID_HANDLE_VALUE != hFileHandle[0])
  193. {
  194. //
  195. // Open strFile2
  196. //
  197. hFileHandle[1] = CreateFile(strFile2, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  198. if (INVALID_HANDLE_VALUE != hFileHandle[1])
  199. {
  200. //
  201. // Get the file size for both files. They should be the same in order for us to continue
  202. //
  203. dwFileSize[0] = GetFileSize(hFileHandle[0], NULL);
  204. dwFileSize[1] = GetFileSize(hFileHandle[1], NULL);
  205. if (dwFileSize[0] == dwFileSize[1])
  206. {
  207. //
  208. // Create a file mapping for hFileHandle[0]
  209. //
  210. hFileMapping[0] = CreateFileMapping(hFileHandle[0], NULL, PAGE_READONLY, 0, dwFileSize[0], NULL);
  211. if (NULL != hFileMapping[0])
  212. {
  213. //
  214. // Map a view of hFileMapping[0]
  215. //
  216. lpFileView[0] = MapViewOfFile(hFileMapping[0], FILE_MAP_READ, 0, 0, 0);
  217. if (NULL != lpFileView[0])
  218. {
  219. //
  220. // Create a file mapping for hFileHandle[1]
  221. //
  222. hFileMapping[1] = CreateFileMapping(hFileHandle[1], NULL, PAGE_READONLY, 0, dwFileSize[1], NULL);
  223. if (NULL != hFileMapping[1])
  224. {
  225. //
  226. // Map a view of hFileMapping[1]
  227. //
  228. lpFileView[1] = MapViewOfFile(hFileMapping[1], FILE_MAP_READ, 0, 0, 0);
  229. if (NULL != lpFileView[1])
  230. {
  231. //
  232. // Compare lpFileView[0] and lpFileView[1]
  233. //
  234. if (0 != memcmp(lpFileView[0], lpFileView[1], dwFileSize[0]))
  235. {
  236. dwReturnCode = COMPONENT_NOT_IDENTICAL;
  237. }
  238. else
  239. {
  240. dwReturnCode = 0;
  241. }
  242. //
  243. // Make sure to unmap the view of file for lpFileView[1]
  244. //
  245. UnmapViewOfFile(lpFileView[1]);
  246. }
  247. //
  248. // Make sure to release the mapping for hFileMapping[1]
  249. //
  250. CloseHandle(hFileMapping[1]);
  251. }
  252. //
  253. // Make sure to unmap the view of file for lpFileView[0]
  254. //
  255. UnmapViewOfFile(lpFileView[0]);
  256. }
  257. //
  258. // Make sure to release the mapping for hFileMapping[0]
  259. //
  260. CloseHandle(hFileMapping[0]);
  261. }
  262. }
  263. else
  264. {
  265. //
  266. // Files are not the same size
  267. //
  268. dwReturnCode = COMPONENT_NOT_IDENTICAL;
  269. }
  270. //
  271. // Make sure to close hFileHandle2
  272. //
  273. CloseHandle(hFileHandle[1]);
  274. }
  275. //
  276. // Make sure to close hFileHandle1
  277. //
  278. CloseHandle(hFileHandle[0]);
  279. }
  280. return dwReturnCode;
  281. }
  282. //////////////////////////////////////////////////////////////////////////////////////////////
  283. //
  284. //////////////////////////////////////////////////////////////////////////////////////////////
  285. BOOL RegisterComponent(LPCTSTR strFilename)
  286. {
  287. BOOL fSuccess = FALSE;
  288. HRESULT hResult;
  289. HINSTANCE hInstance;
  290. LPFNDLLREGISTERSERVER DllRegisterServer;
  291. hInstance = LoadLibrary(strFilename);
  292. if (hInstance)
  293. {
  294. DllRegisterServer = (LPFNDLLREGISTERSERVER) GetProcAddress(hInstance, "DllRegisterServer");
  295. if ((DllRegisterServer)&&(SUCCEEDED(DllRegisterServer())))
  296. {
  297. fSuccess = TRUE;
  298. }
  299. //
  300. // Make sure to free the library
  301. //
  302. FreeLibrary(hInstance);
  303. }
  304. return fSuccess;
  305. }
  306. //////////////////////////////////////////////////////////////////////////////////////////////
  307. //
  308. //////////////////////////////////////////////////////////////////////////////////////////////
  309. BOOL UnRegisterComponent(LPCTSTR strFilename)
  310. {
  311. BOOL fSuccess = FALSE;
  312. HRESULT hResult;
  313. HINSTANCE hInstance;
  314. LPFNDLLUNREGISTERSERVER DllUnregisterServer;
  315. hInstance = LoadLibrary(strFilename);
  316. if (hInstance)
  317. {
  318. DllUnregisterServer = (LPFNDLLREGISTERSERVER) GetProcAddress(hInstance, "DllUnregisterServer");
  319. if ((DllUnregisterServer)&&(SUCCEEDED(DllUnregisterServer())))
  320. {
  321. fSuccess = TRUE;
  322. }
  323. //
  324. // Make sure to free the library
  325. //
  326. FreeLibrary(hInstance);
  327. }
  328. return fSuccess;
  329. }
  330. //////////////////////////////////////////////////////////////////////////////////////////////
  331. //
  332. //////////////////////////////////////////////////////////////////////////////////////////////
  333. BOOL SetDebugMode(void)
  334. {
  335. BOOL fSuccess = FALSE;
  336. CRegistryKey oRegistryKey;
  337. TCHAR strValueName[MAX_PATH];
  338. DWORD dwValue, dwKeyDisposition;
  339. //
  340. // Do we want to run in debug mode ?
  341. //
  342. if (g_fInstallDebug)
  343. {
  344. //
  345. // Make sure our target registry key exists
  346. //
  347. if (S_OK != oRegistryKey.CheckForExistingKey(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\AppMan")))
  348. {
  349. oRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\AppMan"), 0, KEY_ALL_ACCESS, &dwKeyDisposition);
  350. }
  351. //
  352. // Open the target registry key
  353. //
  354. if (S_OK == oRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\AppMan"), KEY_ALL_ACCESS))
  355. {
  356. wsprintf(strValueName, TEXT("Debug"));
  357. dwValue = 0;
  358. if (S_OK == oRegistryKey.SetValue(strValueName, REG_DWORD, (LPBYTE) &dwValue, sizeof(dwValue)))
  359. {
  360. wsprintf(strValueName, TEXT("LoadDebugRuntime"));
  361. dwValue = 1;
  362. if (S_OK == oRegistryKey.SetValue(strValueName, REG_DWORD, (LPBYTE) &dwValue, sizeof(dwValue)))
  363. {
  364. fSuccess = TRUE;
  365. }
  366. }
  367. //
  368. // Make sure to close the registry
  369. //
  370. oRegistryKey.CloseKey();
  371. }
  372. }
  373. else
  374. {
  375. //
  376. // We do not want to run in debug mode. Make sure to delete the target registry key
  377. //
  378. if (S_OK == oRegistryKey.CheckForExistingKey(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\AppMan")))
  379. {
  380. if (S_OK == oRegistryKey.DeleteKey(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\AppMan")))
  381. {
  382. fSuccess = TRUE;
  383. }
  384. }
  385. }
  386. return fSuccess;
  387. }
  388. //////////////////////////////////////////////////////////////////////////////////////////////
  389. //
  390. //////////////////////////////////////////////////////////////////////////////////////////////
  391. LONG SetupAndLaunch(void)
  392. {
  393. LONG lReturnCode = -2;
  394. BOOL fReady = FALSE;
  395. STARTUPINFO sStartupInfo;
  396. PROCESS_INFORMATION sProcessInfo;
  397. DWORD dwIndex, dwReturnValue;
  398. TCHAR strTempPath[MAX_PATH];
  399. TCHAR strSystemPath[MAX_PATH];
  400. TCHAR strSourceFilename[MAX_PATH];
  401. TCHAR strDestinationFilename[MAX_PATH];
  402. TCHAR strCmdLine[MAX_PATH];
  403. VS_FIXEDFILEINFO sSourceFileInfo;
  404. VS_FIXEDFILEINFO sDestinationFileInfo;
  405. //
  406. // Where should the temporary files go
  407. //
  408. if (GetSystemDirectory(strSystemPath, MAX_PATH))
  409. {
  410. if (GetTempPath(MAX_PATH, strTempPath))
  411. {
  412. //
  413. // What is the source filename ?
  414. //
  415. if (GetModuleFileName(NULL, strSourceFilename, MAX_PATH))
  416. {
  417. //
  418. // Generate the path/filename pair for the destination of the setup bits
  419. //
  420. wsprintf(strDestinationFilename, TEXT("%s\\WAMSetup.exe"), strSystemPath);
  421. if (FileExists(strDestinationFilename))
  422. {
  423. SetFileAttributes(strDestinationFilename, FILE_ATTRIBUTE_NORMAL);
  424. if (DeleteFile(strDestinationFilename))
  425. {
  426. if (CopyFile(strSourceFilename, strDestinationFilename, FALSE))
  427. {
  428. fReady = TRUE;
  429. }
  430. }
  431. }
  432. else
  433. {
  434. //
  435. // There is no existing destination file. Just copy the source to the destination
  436. //
  437. if (CopyFile(strSourceFilename, strDestinationFilename, FALSE))
  438. {
  439. fReady = TRUE;
  440. }
  441. }
  442. }
  443. //
  444. // Did we successfully copy the setup executable to the system directory. Continue if so.
  445. //
  446. if (fReady)
  447. {
  448. //
  449. // Execute the temporary executable
  450. //
  451. ZeroMemory(&sStartupInfo, sizeof(sStartupInfo));
  452. sStartupInfo.cb = sizeof(sStartupInfo);
  453. ZeroMemory(&sProcessInfo, sizeof(PROCESS_INFORMATION));
  454. if (g_fInstallDebug)
  455. {
  456. wsprintf(strCmdLine, TEXT("""%s"" /DoInstall /Debug"), strDestinationFilename);
  457. }
  458. else
  459. {
  460. wsprintf(strCmdLine, TEXT("""%s"" /DoInstall"), strDestinationFilename);
  461. }
  462. if (CreateProcess(NULL, strCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &sStartupInfo, &sProcessInfo))
  463. {
  464. //
  465. // Wait for the process to end
  466. //
  467. WaitForSingleObject(sProcessInfo.hProcess, INFINITE);
  468. //
  469. // What was the return value ?
  470. //
  471. if (GetExitCodeProcess(sProcessInfo.hProcess, &dwReturnValue))
  472. {
  473. switch(dwReturnValue)
  474. {
  475. case _EXIT_SUCCESS
  476. : lReturnCode = 1;
  477. break;
  478. case _EXIT_SUCCESS_REBOOT
  479. : lReturnCode = 2;
  480. break;
  481. default
  482. : lReturnCode = -1;
  483. break;
  484. }
  485. }
  486. //
  487. // Close the process and thread handles created by CreateProcess()
  488. //
  489. CloseHandle(sProcessInfo.hThread);
  490. CloseHandle(sProcessInfo.hProcess);
  491. }
  492. }
  493. }
  494. }
  495. return lReturnCode;
  496. }
  497. //////////////////////////////////////////////////////////////////////////////////////////////
  498. //
  499. //////////////////////////////////////////////////////////////////////////////////////////////
  500. LONG DoInstall(void)
  501. {
  502. LONG lReturnCode = -1;
  503. BOOL fReady = TRUE;
  504. BOOL fRebootNeeded = FALSE;
  505. DWORD dwIndex;
  506. TCHAR strSystemPath[MAX_PATH];
  507. TCHAR strTempPath[MAX_PATH];
  508. TCHAR strSourceFilename[MAX_PATH];
  509. TCHAR strTargetFilename[MAX_PATH];
  510. TCHAR strAlternateTargetFilename[MAX_PATH];
  511. //
  512. // Get the system and temp path to start with
  513. //
  514. if (GetSystemDirectory(strSystemPath, MAX_PATH))
  515. {
  516. if (GetTempPath(MAX_PATH, strTempPath))
  517. {
  518. //
  519. // Extract the DLLs to a temporary directory
  520. //
  521. for (dwIndex = 0; dwIndex < COMPONENT_COUNT; dwIndex++)
  522. {
  523. if (g_dwOSVersion & g_sComponentInfo[dwIndex].dwTargetOS)
  524. {
  525. if ((FALSE == g_sComponentInfo[dwIndex].fDebugVersion)||(g_fInstallDebug))
  526. {
  527. if (!ExtractComponent(dwIndex, strTempPath))
  528. {
  529. fReady = FALSE;
  530. }
  531. }
  532. }
  533. }
  534. //
  535. // Continue on if the DLLS were properly extracted
  536. //
  537. if (fReady)
  538. {
  539. //
  540. // First we need to initialize the RunOnce process
  541. //
  542. if (InitializeRunOnce(TRUE))
  543. {
  544. //
  545. // Determine the status of the component
  546. //
  547. for (dwIndex = 0; dwIndex < COMPONENT_COUNT; dwIndex++)
  548. {
  549. if (g_dwOSVersion & g_sComponentInfo[dwIndex].dwTargetOS)
  550. {
  551. if ((FALSE == g_sComponentInfo[dwIndex].fDebugVersion)||(g_fInstallDebug))
  552. {
  553. //
  554. // What would be the target filename for component at dwIndex
  555. //
  556. wsprintf(strSourceFilename, TEXT("%s%s"), strTempPath, g_sComponentInfo[dwIndex].strFilename);
  557. wsprintf(strTargetFilename, TEXT("%s\\%s"), strSystemPath, g_sComponentInfo[dwIndex].strFilename);
  558. if (FileExists(strTargetFilename))
  559. {
  560. //
  561. // Flag the component as being on the system
  562. //
  563. g_sComponentInfo[dwIndex].dwStatus |= COMPONENT_ON_SYSTEM;
  564. //
  565. // Get the version of the component on the system
  566. //
  567. GetFileVersion(strTargetFilename, &g_sComponentInfo[dwIndex].sCurrentVersionInfo);
  568. GetFileVersion(strSourceFilename, &g_sComponentInfo[dwIndex].sTargetVersionInfo);
  569. //
  570. // Compare the component on the system and the target component
  571. //
  572. g_sComponentInfo[dwIndex].dwStatus |= CompareFileVersions(&g_sComponentInfo[dwIndex].sCurrentVersionInfo, &g_sComponentInfo[dwIndex].sTargetVersionInfo);
  573. //
  574. // If the two files are the same version, they should be identical. Check that fact
  575. //
  576. g_sComponentInfo[dwIndex].dwStatus |= CompareFiles(strTargetFilename, strSourceFilename);
  577. }
  578. }
  579. }
  580. }
  581. //
  582. // At first, we will try to copy each component to the system directory. Otherwise we
  583. // will copy the components to the system directory under temporary names.
  584. //
  585. for (dwIndex = 0; dwIndex < COMPONENT_COUNT; dwIndex++)
  586. {
  587. if (g_dwOSVersion & g_sComponentInfo[dwIndex].dwTargetOS)
  588. {
  589. if ((FALSE == g_sComponentInfo[dwIndex].fDebugVersion)||(g_fInstallDebug))
  590. {
  591. //
  592. // Determine whether or not the component should be updated before proceeding
  593. //
  594. if ((!(COMPONENT_ON_SYSTEM & g_sComponentInfo[dwIndex].dwStatus))||(COMPONENT_OLDER_VERSION & g_sComponentInfo[dwIndex].dwStatus)||((COMPONENT_NOT_IDENTICAL & g_sComponentInfo[dwIndex].dwStatus)&&(COMPONENT_SAME_VERSION & g_sComponentInfo[dwIndex].dwStatus)))
  595. {
  596. //
  597. // What will be the target filename
  598. //
  599. wsprintf(strSourceFilename, TEXT("%s%s"), strTempPath, g_sComponentInfo[dwIndex].strFilename);
  600. wsprintf(strTargetFilename, TEXT("%s\\%s"), strSystemPath, g_sComponentInfo[dwIndex].strFilename);
  601. if (!CopyFile(strSourceFilename, strTargetFilename, FALSE))
  602. {
  603. //
  604. // We will need to copy the DLL to a temporary directory
  605. //
  606. if ((GenerateUniqueFilename(strSystemPath, TEXT("dll"), strAlternateTargetFilename))&&(CopyFile(strSourceFilename, strAlternateTargetFilename, FALSE)))
  607. {
  608. SetRunOnceCleanupFile(strAlternateTargetFilename, strTargetFilename, g_sComponentInfo[dwIndex].fRegister);
  609. fRebootNeeded = TRUE;
  610. }
  611. else
  612. {
  613. break;
  614. }
  615. }
  616. //
  617. // Excellent, all we need to do is register the component if required
  618. //
  619. if (g_sComponentInfo[dwIndex].fRegister)
  620. {
  621. if (!RegisterComponent(strTargetFilename))
  622. {
  623. break;
  624. }
  625. }
  626. }
  627. }
  628. }
  629. }
  630. //
  631. // Did everything go as planned
  632. //
  633. if (COMPONENT_COUNT == dwIndex)
  634. {
  635. //
  636. // Finish off the DoInstall process
  637. //
  638. SetDebugMode();
  639. if (fRebootNeeded)
  640. {
  641. FinalizeRunOnce(TRUE);
  642. lReturnCode = 2;
  643. }
  644. else
  645. {
  646. FinalizeRunOnce(FALSE);
  647. lReturnCode = 1;
  648. }
  649. }
  650. }
  651. }
  652. //
  653. // Did we fail ?
  654. //
  655. if (-1 == lReturnCode)
  656. {
  657. FinalizeRunOnce(FALSE);
  658. }
  659. //
  660. // Delete the temporary DLLs
  661. //
  662. for (dwIndex = 0; dwIndex < COMPONENT_COUNT; dwIndex++)
  663. {
  664. if (g_dwOSVersion & g_sComponentInfo[dwIndex].dwTargetOS)
  665. {
  666. if ((FALSE == g_sComponentInfo[dwIndex].fDebugVersion)||(g_fInstallDebug))
  667. {
  668. wsprintf(strTargetFilename, TEXT("%s\\%s"), strTempPath, g_sComponentInfo[dwIndex].strFilename);
  669. SetFileAttributes(strTargetFilename, FILE_ATTRIBUTE_NORMAL);
  670. DeleteFile(strTargetFilename);
  671. }
  672. }
  673. }
  674. }
  675. }
  676. return lReturnCode;
  677. }
  678. //////////////////////////////////////////////////////////////////////////////////////////////
  679. //
  680. //////////////////////////////////////////////////////////////////////////////////////////////
  681. LONG DoCleanup(void)
  682. {
  683. LONG lReturnCode = 1;
  684. BOOL fSuccess;
  685. TCHAR strSourceFilename[MAX_PATH];
  686. TCHAR strDestinationFilename[MAX_PATH];
  687. //
  688. // First we need to initialize the RunOnce process
  689. //
  690. if (InitializeRunOnce(FALSE))
  691. {
  692. //
  693. // Get the components that do need to be registered
  694. //
  695. fSuccess = TRUE;
  696. while ((fSuccess)&&(GetRunOnceCleanupFile(strSourceFilename, MAX_PATH, strDestinationFilename, MAX_PATH, TRUE)))
  697. {
  698. //
  699. // By default we pretend that the operation will fail until proven otherwise
  700. //
  701. fSuccess = FALSE;
  702. //
  703. // Make sure the file attribute is set properly prior to deleting the destination file
  704. //
  705. SetFileAttributes(strDestinationFilename, FILE_ATTRIBUTE_NORMAL);
  706. if (UnRegisterComponent(strDestinationFilename))
  707. {
  708. if (CopyFile(strSourceFilename, strDestinationFilename, FALSE))
  709. {
  710. //
  711. // Redo the registration on the component
  712. //
  713. if (UnRegisterComponent(strSourceFilename))
  714. {
  715. SetFileAttributes(strSourceFilename, FILE_ATTRIBUTE_NORMAL);
  716. if (DeleteFile(strSourceFilename))
  717. {
  718. if (RegisterComponent(strDestinationFilename))
  719. {
  720. fSuccess = TRUE;
  721. }
  722. }
  723. }
  724. }
  725. else
  726. {
  727. //
  728. // We were unable to overwrite the destination component. Make sure to re-register it
  729. //
  730. RegisterComponent(strDestinationFilename);
  731. }
  732. }
  733. }
  734. //
  735. // If we were not successful, put the RunOnceCleanupFile back into the registry before exiting
  736. //
  737. if (!fSuccess)
  738. {
  739. SetRunOnceCleanupFile(strSourceFilename, strDestinationFilename, TRUE);
  740. FinalizeRunOnce(TRUE);
  741. lReturnCode = 2;
  742. }
  743. else
  744. {
  745. //
  746. // Get the components that do not need to be registered
  747. //
  748. while ((fSuccess)&&(GetRunOnceCleanupFile(strSourceFilename, MAX_PATH, strDestinationFilename, MAX_PATH, FALSE)))
  749. {
  750. //
  751. // By default we pretend that the operation will fail until proven otherwise
  752. //
  753. fSuccess = FALSE;
  754. //
  755. // Make sure the file attribute is set properly prior to deleting the destination file
  756. //
  757. SetFileAttributes(strDestinationFilename, FILE_ATTRIBUTE_NORMAL);
  758. if (CopyFile(strSourceFilename, strDestinationFilename, FALSE))
  759. {
  760. //
  761. // Redo the registration on the component
  762. //
  763. SetFileAttributes(strSourceFilename, FILE_ATTRIBUTE_NORMAL);
  764. if (DeleteFile(strSourceFilename))
  765. {
  766. fSuccess = TRUE;
  767. }
  768. }
  769. }
  770. if (!fSuccess)
  771. {
  772. SetRunOnceCleanupFile(strSourceFilename, strDestinationFilename, FALSE);
  773. FinalizeRunOnce(TRUE);
  774. lReturnCode = 2;
  775. }
  776. else
  777. {
  778. FinalizeRunOnce(FALSE);
  779. lReturnCode = 1;
  780. }
  781. }
  782. }
  783. return lReturnCode;
  784. }
  785. //////////////////////////////////////////////////////////////////////////////////////////////
  786. //
  787. //////////////////////////////////////////////////////////////////////////////////////////////
  788. int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR lpCommandLine, int nCmdShow)
  789. {
  790. //
  791. // Initialize some global variables
  792. //
  793. g_hInstance = hInstance;
  794. g_dwOSVersion = GetOSVersion();
  795. g_dwSuccessCode = 0;
  796. //
  797. // For now, we do not work in Win95
  798. //
  799. //if (OS_VERSION_WIN95 == g_dwOSVersion)
  800. //{
  801. // return -3;
  802. //}
  803. //
  804. // Cast the command line into uppercase
  805. //
  806. _strupr(lpCommandLine);
  807. //
  808. // Define whether or not we care about the DEBUG files
  809. //
  810. if (NULL != strstr((LPCSTR) lpCommandLine, "/DEBUG"))
  811. {
  812. g_fInstallDebug = TRUE;
  813. }
  814. else
  815. {
  816. g_fInstallDebug = FALSE;
  817. }
  818. //
  819. // Is the /DoInstall command line parameter on the command line
  820. //
  821. if (NULL != strstr((LPCSTR) lpCommandLine, "/DOINSTALL"))
  822. {
  823. //
  824. // Do the installation here
  825. //
  826. g_dwSuccessCode = (DWORD) DoInstall();
  827. }
  828. else if (NULL == strstr((LPCSTR) lpCommandLine, "/CLEANUP"))
  829. {
  830. //
  831. // Copy the executable to a temporary directory and restart it
  832. //
  833. g_dwSuccessCode = (DWORD) SetupAndLaunch();
  834. }
  835. else
  836. {
  837. //
  838. // Do the installation cleanup here. Please note that DoCleanup does not return errors.
  839. //
  840. g_dwSuccessCode = (DWORD) DoCleanup();
  841. }
  842. return (int) g_dwSuccessCode;
  843. }
  844. ///////////////////////////////////////////////////////////////////////////////////////////////////