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.

2034 lines
49 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. init9x.c
  5. Abstract:
  6. Code that initializes all libraries used on the Win9x side of the upgrade.
  7. Author:
  8. Jim Schmidt (jimschm) 30-Dec-1997
  9. Revision History:
  10. marcw 21-Jul-1999 Examine the boot sector.
  11. marcw 15-Jul-1999 Added pSafeToUpgrade.
  12. ovidiut 08-Mar-1999 Add call to UndoChangedFileProps
  13. Jim Schmidt (jimschm) 30-Mar-1998 IsServerInstall
  14. --*/
  15. #include "pch.h"
  16. #include "n98boot.h"
  17. #include "init9xp.h"
  18. //
  19. // Process globals
  20. //
  21. BOOL g_Terminated = FALSE;
  22. HANDLE g_hHeap = NULL;
  23. HINSTANCE g_hInst = NULL;
  24. HWND g_ParentWnd = NULL;
  25. PRODUCTTYPE *g_ProductType;
  26. extern DWORD g_MasterSequencer;
  27. READ_DISK_SECTORS_PROC ReadDiskSectors;
  28. //
  29. // Paths
  30. //
  31. // Filled in DllMain
  32. TCHAR g_DllDir[MAX_TCHAR_PATH];
  33. TCHAR g_UpgradeSources[MAX_TCHAR_PATH];
  34. // Filled in Winnt32PlugInInit
  35. PTSTR g_TempDir;
  36. PTSTR g_Win9xSifDir;
  37. PTSTR g_TempDirWack;
  38. PTSTR g_WinDir;
  39. PTSTR g_WinDirWack;
  40. PTSTR g_WinDrive;
  41. PTSTR g_PlugInDir;
  42. PTSTR g_PlugInDirWack;
  43. PTSTR g_PlugInTempDir;
  44. PTSTR g_SystemDir;
  45. PTSTR g_SystemDirWack;
  46. PTSTR g_System32Dir;
  47. PTSTR g_System32DirWack;
  48. PTSTR g_ProgramFilesDir;
  49. PTSTR g_ProgramFilesDirWack;
  50. PTSTR g_ProgramFilesCommonDir;
  51. PTSTR g_Win95UpgInfFile;
  52. PTSTR g_RecycledDirWack;
  53. PTSTR g_ProfileDirNt;
  54. PTSTR g_ProfileDir;
  55. PTSTR g_ProfileDirWack;
  56. PTSTR g_CommonProfileDir;
  57. PTSTR g_DriversDir;
  58. PTSTR g_InfDir;
  59. PTSTR g_HelpDir;
  60. PTSTR g_HelpDirWack;
  61. PTSTR g_CatRootDir;
  62. PTSTR g_CatRootDirWack;
  63. PTSTR g_FontsDir;
  64. PTSTR g_ViewersDir;
  65. PTSTR g_ColorDir;
  66. PTSTR g_SharedDir;
  67. PTSTR g_SpoolDir;
  68. PTSTR g_SpoolDriversDir;
  69. PTSTR g_PrintProcDir;
  70. HINF g_Win95UpgInf = INVALID_HANDLE_VALUE;
  71. HINF g_TxtSetupSif = INVALID_HANDLE_VALUE;
  72. PCTSTR g_ProfileName = NULL;
  73. TCHAR g_Win95Name[MAX_TCHAR_PATH];
  74. INT g_TempDirWackChars;
  75. INT g_WinDirWackChars;
  76. INT g_HelpDirWackChars;
  77. INT g_CatRootDirWackChars;
  78. INT g_SystemDirWackChars;
  79. INT g_System32DirWackChars;
  80. INT g_ProgramFilesDirWackChars;
  81. INT g_PlugInDirWackChars;
  82. INT g_RecycledDirWackChars;
  83. INT g_ProfileDirWackChars;
  84. BOOL g_ToolMode = FALSE;
  85. //
  86. // HWND for use by migrate.dlls.
  87. //
  88. HWND g_pluginHwnd;
  89. //
  90. // Info from WINNT32
  91. //
  92. PCTSTR g_SourceDirectories[MAX_SOURCE_COUNT];
  93. DWORD g_SourceDirectoryCount;
  94. PCTSTR * g_SourceDirectoriesFromWinnt32;
  95. PDWORD g_SourceDirectoryCountFromWinnt32;
  96. PCTSTR g_OptionalDirectories[MAX_SOURCE_COUNT];
  97. DWORD g_OptionalDirectoryCount;
  98. PCTSTR * g_OptionalDirectoriesFromWinnt32;
  99. PDWORD g_OptionalDirectoryCountFromWinnt32;
  100. PCTSTR * g_UnattendScriptFile;
  101. PCTSTR * g_CmdLineOptions;
  102. BOOL * g_UnattendedFlagPtr;
  103. BOOL * g_CancelFlagPtr;
  104. BOOL * g_AbortFlagPtr;
  105. BOOL * g_UpgradeFlagPtr;
  106. BOOL * g_MakeLocalSourcePtr;
  107. BOOL * g_CdRomInstallPtr;
  108. BOOL * g_BlockOnNotEnoughSpace;
  109. PDWORD g_LocalSourceDrive;
  110. PLONGLONG g_LocalSourceSpace;
  111. PLONGLONG g_WinDirSpace;
  112. PCTSTR g_AdministratorStr;
  113. BOOL * g_ForceNTFSConversion;
  114. PUINT g_RamNeeded;
  115. PUINT g_RamAvailable;
  116. UINT * g_ProductFlavor;
  117. BOOL g_PersonalSKU;
  118. PDWORD g_SetupFlags;
  119. PTSTR g_DynamicUpdateLocalDir;
  120. PTSTR g_DynamicUpdateDrivers;
  121. BOOL * g_UnattendSwitchSpecified;
  122. //
  123. // Info for config.c
  124. //
  125. BOOL g_GoodDrive = FALSE; // cmdLine option: Skip Valid HDD check.
  126. BOOL g_NoFear = FALSE; // cmdLine option: Skip Beta 1 Warnings...
  127. POOLHANDLE g_UserOptionPool = NULL;
  128. BOOL g_UseSystemFont = FALSE; // force use of sys font for variable text
  129. BOOL g_Stress; // used for private stress options
  130. POOLHANDLE g_GlobalPool; // for globals that are allocated for the lifetime of the DLL
  131. //
  132. // PC-98 additions
  133. //
  134. //
  135. // Define and Globals for NEC98. These items are used to call 98ptn32.dll.
  136. //
  137. typedef int (CALLBACK WIN95_PLUGIN_98PTN32_GETBOOTDRIVE_PROTOTYPE)(void);
  138. typedef WIN95_PLUGIN_98PTN32_GETBOOTDRIVE_PROTOTYPE * PWIN95_PLUGIN_98PTN32_GETBOOTDRIVE;
  139. typedef BOOL (CALLBACK WIN95_PLUGIN_98PTN32_SETBOOTFLAG_PROTOTYPE)(int, WORD);
  140. typedef WIN95_PLUGIN_98PTN32_SETBOOTFLAG_PROTOTYPE * PWIN95_PLUGIN_98PTN32_SETBOOTFLAG;
  141. typedef BOOL (CALLBACK WIN95_PLUGIN_98PTN32_SETPTNNAME_PROTOTYPE)(int, WORD);
  142. typedef WIN95_PLUGIN_98PTN32_SETPTNNAME_PROTOTYPE * PWIN95_PLUGIN_98PTN32_SETPTNNAME;
  143. PWIN95_PLUGIN_98PTN32_SETBOOTFLAG SetBootFlag;
  144. PWIN95_PLUGIN_98PTN32_GETBOOTDRIVE GetBootDrive;
  145. PWIN95_PLUGIN_98PTN32_SETPTNNAME SetPtnName;
  146. #define WIN95_98PTN32_GETBOOTDRIVE TEXT("GetBootDriveLetter32")
  147. #define WIN95_98PTN32_SETBOOTFLAG TEXT("SetBootable95ptn32")
  148. #define WIN95_98PTN32_SETPTNNAME TEXT("SetPartitionName32")
  149. #define PC98_DLL_NAME TEXT("98PTN32.DLL")
  150. HINSTANCE g_Pc98ModuleHandle = NULL;
  151. #define SB_BOOTABLE 0x0001
  152. #define SB_UNBOOTABLE 0x0002
  153. #define MSK_BOOTABLE 0x000f
  154. #define SB_AUTO 0x0010
  155. #define MSK_AUTO 0x00f0
  156. #define WIN9X_DOS_NAME 0
  157. #define WINNT5_NAME 1
  158. BOOL IsServerInstall (VOID);
  159. VOID pCleanUpShellFolderTemp (VOID);
  160. //
  161. // The following macro expansion was designed to simplify library
  162. // maintenence. The library name in LIBLIST is used in two ways:
  163. // (1) the routine is automatically prototyped, and (2) an array
  164. // of function pointers is automatically created. Each function
  165. // listed in LIBLIST is called whenever the dll entry point is called.
  166. //
  167. // To add a new library to this DLL, follow these steps:
  168. //
  169. // 1. Make a directory and have the target built in win95upg\lib\i386.
  170. // Your new library must have an entry point declared like DllEntryPoint.
  171. // 2. Add the target library to the sources in win95upg\w95upg\dll\i386.
  172. // 3. Add your library's entry point name to the list below. It will
  173. // get called at load of w95upg.dll and at termination of w95upg.dll.
  174. //
  175. //
  176. // IMPORTANT: MigUtil_Entry *must* be first; other libs are dependent on its
  177. // initialization.
  178. //
  179. #define LIBLIST \
  180. LIBRARY_NAME(MigUtil_Entry) \
  181. LIBRARY_NAME(Win95Reg_Entry) \
  182. LIBRARY_NAME(MemDb_Entry) \
  183. LIBRARY_NAME(FileEnum_Entry) \
  184. LIBRARY_NAME(Common9x_Entry) \
  185. LIBRARY_NAME(MigApp_Entry) \
  186. LIBRARY_NAME(HwComp_Entry) \
  187. LIBRARY_NAME(BuildInf_Entry) \
  188. LIBRARY_NAME(SysMig_Entry) \
  189. LIBRARY_NAME(DosMig_Entry) \
  190. LIBRARY_NAME(UI_Entry) \
  191. LIBRARY_NAME(Ras_Entry) \
  192. LIBRARY_NAME(MigDll9x_Entry) \
  193. //
  194. // Declare prototype types
  195. //
  196. typedef BOOL (WINAPI INITROUTINE_PROTOTYPE)(HINSTANCE, DWORD, LPVOID);
  197. typedef INITROUTINE_PROTOTYPE * INITROUTINE;
  198. //
  199. // Declare the actual prototypes of the entry points
  200. //
  201. #define LIBRARY_NAME(x) INITROUTINE_PROTOTYPE x;
  202. LIBLIST
  203. #undef LIBRARY_NAME
  204. //
  205. // Declare an array of function pointers to the entry pointes
  206. //
  207. #define LIBRARY_NAME(x) x,
  208. static INITROUTINE g_InitRoutine[] = {LIBLIST /*,*/ NULL};
  209. #undef LIBRARY_NAME
  210. //
  211. // Declare variable to track number of libraries successfully loaded
  212. //
  213. static int g_LibCount = 0;
  214. //
  215. // Persistent strings buffer holds strings that we use for the
  216. // life of the DLL.
  217. //
  218. static PGROWBUFFER g_PersistentStrings;
  219. //
  220. // Implementation
  221. //
  222. BOOL
  223. FirstInitRoutine (
  224. HINSTANCE hInstance
  225. )
  226. /*++
  227. Routine Description:
  228. pFirstInitRoutine is the very first function called during the
  229. initialization of the DLL. It sets up globals such as the heap
  230. pointer and instance handle. This routine must be called before
  231. any library entry point is called.
  232. Arguments:
  233. hInstance - (OS-supplied) instance handle for the DLL
  234. Return Value:
  235. Returns TRUE if the global variables could be initialized, or FALSE
  236. if an error occurred.
  237. --*/
  238. {
  239. PTSTR p;
  240. //
  241. // Get the process heap & instance handle
  242. //
  243. if (g_ToolMode) {
  244. g_hHeap = GetProcessHeap ();
  245. }
  246. else {
  247. g_hHeap = HeapCreate(0, 0x20000, 0);
  248. if (!g_hHeap) {
  249. LOG ((LOG_ERROR, "Cannot create a private heap."));
  250. g_hHeap = GetProcessHeap();
  251. }
  252. }
  253. g_hInst = hInstance;
  254. //
  255. // No DLL_THREAD_ATTACH or DLL_THREAD_DETECH needed
  256. //
  257. DisableThreadLibraryCalls (hInstance);
  258. //
  259. // Init common controls
  260. //
  261. InitCommonControls();
  262. //
  263. // Get DLL path and strip directory
  264. //
  265. GetModuleFileName (hInstance, g_DllDir, MAX_TCHAR_PATH);
  266. p = _tcsrchr (g_DllDir, TEXT('\\'));
  267. MYASSERT (p);
  268. *p = 0;
  269. if (g_ToolMode) {
  270. StringCopy (g_UpgradeSources, g_DllDir);
  271. }
  272. return TRUE;
  273. }
  274. BOOL
  275. InitLibs (
  276. HINSTANCE hInstance,
  277. DWORD dwReason,
  278. PVOID lpReserved
  279. )
  280. /*++
  281. Routine Description:
  282. pInitLibs calls all library entry points in the g_InitRoutine array.
  283. If an entry point fails, all libraries are unloaded in reverse order
  284. and pInitLibs returns FALSE.
  285. Arguments:
  286. hInstance - (OS-supplied) instance handle for the DLL
  287. dwReason - (OS-supplied) indicates attach or detatch from process or
  288. thread -- in this case always DLL_PROCESS_ATTACH
  289. lpReserved - (OS-supplied) unused
  290. Return Value:
  291. Returns TRUE if all libraries successfully initialized, or FALSE if
  292. a library could not initialize. If TRUE is returned, pTerminateLibs
  293. must be called for the DLL_PROCESS_DETACH message.
  294. --*/
  295. {
  296. InitCommonControls();
  297. if(!pSetupInitializeUtils()) {
  298. return FALSE;
  299. }
  300. SET_RESETLOG();
  301. // Init each LIB
  302. for (g_LibCount = 0 ; g_InitRoutine[g_LibCount] != NULL ; g_LibCount++) {
  303. if (!g_InitRoutine[g_LibCount] (hInstance, dwReason, lpReserved)) {
  304. TerminateLibs (hInstance, DLL_PROCESS_DETACH, lpReserved);
  305. return FALSE;
  306. }
  307. }
  308. return TRUE;
  309. }
  310. BOOL
  311. FinalInitRoutine (
  312. VOID
  313. )
  314. /*++
  315. Routine Description:
  316. pFinalInitRoutine completes all initialization that requires completely
  317. initialized libraries.
  318. Arguments:
  319. none
  320. Return Value:
  321. TRUE if initialization completed successfully, or FALSE if an error occurred.
  322. --*/
  323. {
  324. TCHAR Buffer[MAX_TCHAR_PATH];
  325. PTSTR p;
  326. //
  327. // Load common message strings
  328. //
  329. g_PersistentStrings = CreateAllocTable();
  330. if (!g_PersistentStrings) {
  331. return FALSE;
  332. }
  333. // Get Administrator account name
  334. g_AdministratorStr = GetStringResourceEx (g_PersistentStrings, MSG_ADMINISTRATOR_ACCOUNT);
  335. if (!g_AdministratorStr) {
  336. g_AdministratorStr = S_EMPTY;
  337. }
  338. //
  339. // Obtain PC-98 helper routine addresses
  340. //
  341. if(ISPC98()){
  342. //
  343. // Generate directory of WINNT32
  344. //
  345. StringCopy (Buffer, g_UpgradeSources);
  346. p = _tcsrchr (Buffer, TEXT('\\'));
  347. MYASSERT (p);
  348. StringCopy (_tcsinc(p), PC98_DLL_NAME);
  349. //
  350. // Load library
  351. //
  352. g_Pc98ModuleHandle = LoadLibraryEx(
  353. Buffer,
  354. NULL,
  355. LOAD_WITH_ALTERED_SEARCH_PATH
  356. );
  357. if(!g_Pc98ModuleHandle){
  358. LOG ((LOG_ERROR, "Cannot load %s", Buffer));
  359. return FALSE;
  360. }
  361. //
  362. // Get entry points
  363. //
  364. (FARPROC)SetBootFlag = GetProcAddress (g_Pc98ModuleHandle, WIN95_98PTN32_SETBOOTFLAG);
  365. if(!SetBootFlag){
  366. LOG ((LOG_ERROR, "Cannot get %s address from %s", WIN95_98PTN32_SETBOOTFLAG, Buffer));
  367. return FALSE;
  368. }
  369. (FARPROC)GetBootDrive = GetProcAddress (g_Pc98ModuleHandle, WIN95_98PTN32_GETBOOTDRIVE);
  370. if(!GetBootDrive){
  371. LOG ((LOG_ERROR, "Cannot get %s address from %s", WIN95_98PTN32_GETBOOTDRIVE, Buffer));
  372. return FALSE;
  373. }
  374. (FARPROC)SetPtnName = GetProcAddress (g_Pc98ModuleHandle, WIN95_98PTN32_SETPTNNAME);
  375. if(!SetPtnName){
  376. LOG ((LOG_ERROR, "Cannot get %s address from %s", WIN95_98PTN32_SETPTNNAME, Buffer));
  377. return FALSE;
  378. }
  379. //
  380. // Update boot drive
  381. //
  382. DEBUGMSG_IF ((
  383. GetBootDrive() != g_BootDriveLetterA,
  384. DBG_VERBOSE,
  385. "Boot drive letter is %c:, different from A:",
  386. GetBootDrive()
  387. ));
  388. g_BootDriveLetterW = g_BootDriveLetterA = (char)GetBootDrive();
  389. *((PSTR) g_BootDrivePathA) = g_BootDriveLetterA;
  390. *((PWSTR) g_BootDrivePathW) = g_BootDriveLetterW;
  391. }
  392. //
  393. // Allocate a global pool
  394. //
  395. g_GlobalPool = PoolMemInitNamedPool ("Global Pool");
  396. //
  397. // Declare temporary memdb keys
  398. //
  399. #ifndef PRERELEASE
  400. if (!MemDbCreateTemporaryKey (MEMDB_TMP_HIVE)) {
  401. LOG((LOG_ERROR, TEXT("Cannot create temporary key!")));
  402. }
  403. #endif
  404. pCleanUpShellFolderTemp();
  405. return TRUE;
  406. }
  407. VOID
  408. pCleanUpShellFolderTemp (
  409. VOID
  410. )
  411. {
  412. DRIVELETTERS driveLetters;
  413. UINT u;
  414. TCHAR dir1[] = S_SHELL_TEMP_NORMAL_PATH;
  415. TCHAR dir2[] = S_SHELL_TEMP_LONG_PATH;
  416. InitializeDriveLetterStructure (&driveLetters);
  417. for (u = 0 ; u < NUMDRIVELETTERS ; u++) {
  418. if (driveLetters.Type[u] == DRIVE_FIXED) {
  419. dir1[0] = driveLetters.Letter[u];
  420. dir2[0] = driveLetters.Letter[u];
  421. RemoveCompleteDirectory (dir1);
  422. RemoveCompleteDirectory (dir2);
  423. }
  424. }
  425. }
  426. VOID
  427. FirstCleanupRoutine (
  428. VOID
  429. )
  430. /*++
  431. Routine Description:
  432. pFirstCleanupRoutine is called to perform any cleanup that requires
  433. libraries to still be loaded.
  434. Arguments:
  435. none
  436. Return Value:
  437. none
  438. --*/
  439. {
  440. g_Terminated = TRUE;
  441. //
  442. // Clean up drive structures
  443. //
  444. CleanUpAccessibleDrives();
  445. //
  446. // Clean up our fake NT environment block
  447. //
  448. TerminateNtEnvironment();
  449. CleanUp9xEnvironmentVariables();
  450. //
  451. // Free standard pools
  452. //
  453. if (g_GlobalPool) {
  454. PoolMemDestroyPool (g_GlobalPool);
  455. g_GlobalPool = NULL;
  456. }
  457. if (g_PersistentStrings) {
  458. DestroyAllocTable (g_PersistentStrings);
  459. g_PersistentStrings = NULL;
  460. }
  461. if (g_UserOptionPool) {
  462. PoolMemDestroyPool(g_UserOptionPool);
  463. g_UserOptionPool = NULL;
  464. }
  465. //
  466. // Close all files
  467. //
  468. CleanUpKnownGoodIconMap();
  469. if (g_Win95UpgInf != INVALID_HANDLE_VALUE) {
  470. InfCloseInfFile (g_Win95UpgInf);
  471. g_Win95UpgInf = INVALID_HANDLE_VALUE;
  472. }
  473. if (g_TxtSetupSif != INVALID_HANDLE_VALUE) {
  474. InfCloseInfFile (g_TxtSetupSif);
  475. g_TxtSetupSif = INVALID_HANDLE_VALUE;
  476. }
  477. CleanupMigDb();
  478. }
  479. VOID
  480. TerminateLibs (
  481. HINSTANCE hInstance,
  482. DWORD dwReason,
  483. LPVOID lpReserved
  484. )
  485. /*++
  486. Routine Description:
  487. TerminateLibs is called to unload all libraries in the reverse order
  488. that they were initialized. Each entry point of successfully
  489. initialized library is called.
  490. Arguments:
  491. hInstance - (OS-supplied) instance handle for the DLL
  492. dwReason - (OS-supplied) indicates attach or detatch from process or
  493. thread -- in this case always DLL_PROCESS_DETACH
  494. lpReserved - (OS-supplied) unused
  495. Return Value:
  496. none
  497. --*/
  498. {
  499. INT i;
  500. for (i = g_LibCount - 1 ; i >= 0 ; i--) {
  501. g_InitRoutine[i] (hInstance, dwReason, lpReserved);
  502. }
  503. g_LibCount = 0;
  504. pSetupUninitializeUtils();
  505. }
  506. VOID
  507. FinalCleanupRoutine (
  508. VOID
  509. )
  510. /*++
  511. Routine Description:
  512. FinalCleanupRoutine is after all library entry points have been
  513. called for cleanup. This routine cleans up all resources that a
  514. library will not clean up.
  515. Arguments:
  516. none
  517. Return Value:
  518. none
  519. --*/
  520. {
  521. }
  522. BOOL
  523. pSafeToUpgrade (
  524. VOID
  525. )
  526. /*++
  527. Routine Description:
  528. pSafeToUpgrade ensures that we are willing to upgrade the machine. If
  529. certain conditions exist (particularily other OSes on other partitions) we
  530. may inadvertantly destroy data used by the other Operating System.
  531. Arguments:
  532. None.
  533. Return Value:
  534. TRUE if we believe it is safe to upgrade the machine, FALSE otherwise.
  535. --*/
  536. {
  537. BOOL rUpgradeSafe = TRUE;
  538. //
  539. // ignore this check for now, allow machines that have multiple OSes installed to be upgraded
  540. // if they have another OS on the SAME drive, setup will stop at the report,
  541. // after disk analyze phase
  542. //
  543. #if 0
  544. PTSTR p;
  545. GROWBUFFER buf = GROWBUF_INIT;
  546. UINT size;
  547. MULTISZ_ENUM e;
  548. TCHAR winDriveMatch[20];
  549. PCTSTR group;
  550. PCTSTR message;
  551. BOOL ntBootSector = FALSE;
  552. BYTE bootSector[FAT_BOOT_SECTOR_SIZE];
  553. TCHAR cmpBuffer[6];
  554. UINT i;
  555. //
  556. // Look to see if there is an NT boot sector on the machine.
  557. //
  558. __try {
  559. if (ReadDiskSectors (
  560. *g_BootDrive,
  561. FAT_STARTING_SECTOR,
  562. FAT_BOOT_SECTOR_COUNT,
  563. FAT_BOOT_SECTOR_SIZE,
  564. bootSector
  565. )) {
  566. cmpBuffer[5] = 0;
  567. for (i = 0;i < FAT_BOOT_SECTOR_SIZE - 4; i++) {
  568. if (bootSector[i] == 'n' || bootSector[i] == 'N') {
  569. StringCopyByteCount (cmpBuffer, (PTSTR) (bootSector + i), 6);
  570. if (StringIMatch (cmpBuffer, TEXT("ntldr"))) {
  571. ntBootSector = TRUE;
  572. break;
  573. }
  574. }
  575. }
  576. }
  577. }
  578. __except (1) {
  579. ntBootSector = FALSE;
  580. }
  581. if (ntBootSector) {
  582. //
  583. // See if there is another OS listed in BOOT.ini.
  584. //
  585. p = JoinPaths (g_BootDrive, S_BOOTINI);
  586. size = 4096;
  587. GrowBuffer (&buf, size);
  588. *buf.Buf = 0;
  589. while (GetPrivateProfileSection (S_OPERATING_SYSTEMS, buf.Buf, 4096, p) == size -2) {
  590. size += 4096;
  591. GrowBuffer (&buf, size);
  592. }
  593. FreePathString (p);
  594. if (EnumFirstMultiSz (&e, buf.Buf)) {
  595. wsprintf (winDriveMatch, TEXT("%s\\"), g_WinDrive);
  596. do {
  597. p = (PTSTR) _tcschr (e.CurrentString, TEXT('='));
  598. if (p) {
  599. *p = 0;
  600. }
  601. if (!StringIMatchCharCount(winDriveMatch, e.CurrentString, 3)) {
  602. if (!g_ConfigOptions.IgnoreOtherOS) {
  603. g_OtherOsExists = TRUE;
  604. group = BuildMessageGroup (MSG_INSTALL_NOTES_ROOT, MSG_OTHER_OS_WARNING_SUBGROUP, NULL);
  605. message = GetStringResource (MSG_OTHER_OS_WARNING);
  606. if (message && group) {
  607. MsgMgr_ObjectMsg_Add (TEXT("*BootIniFound"), group, message);
  608. }
  609. FreeText (group);
  610. FreeStringResource (message);
  611. rUpgradeSafe = FALSE;
  612. //
  613. // Let the user know why they won't be upgrading today.
  614. //
  615. break;
  616. }
  617. }
  618. if (p) {
  619. *p = TEXT('=');
  620. }
  621. } while (EnumNextMultiSz (&e));
  622. }
  623. FreeGrowBuffer (&buf);
  624. }
  625. #endif
  626. return rUpgradeSafe;
  627. }
  628. BOOL
  629. pGetInfEntry (
  630. IN PCTSTR Section,
  631. IN PCTSTR Key,
  632. OUT PTSTR Buffer
  633. )
  634. /*++
  635. Routine Description:
  636. Given a section and key, pGetInfEntry gets a value from win95upg.inf.
  637. Arguments:
  638. Section - Specifies the section contianing Key
  639. Key - Specifies the key containing a value
  640. Buffer - Receives the value specified in win95upg.inf for Section and Key
  641. Return Value:
  642. TRUE if a value was obtained, or FALSE if the value does not exist.
  643. --*/
  644. {
  645. GetPrivateProfileString (
  646. Section,
  647. Key,
  648. S_EMPTY,
  649. Buffer,
  650. MAX_TCHAR_PATH,
  651. g_Win95UpgInfFile
  652. );
  653. Buffer[MAX_TCHAR_PATH-1] = 0;
  654. if (!(*Buffer)) {
  655. LOG ((
  656. LOG_ERROR,
  657. "Cannot obtain %s in [%s] in %s.",
  658. Key,
  659. Section,
  660. g_Win95UpgInfFile
  661. ));
  662. return FALSE;
  663. }
  664. return TRUE;
  665. }
  666. PTSTR
  667. pCreateDirectoryFromInf (
  668. IN PCTSTR Key,
  669. IN PCTSTR BaseDir,
  670. IN BOOL Empty
  671. )
  672. /*++
  673. Routine Description:
  674. pCreateDirectoryFromInf obtains a directory for the sequencer specified
  675. by Key. If Key is valid, the BaseDir is combined with the value stored
  676. in win95upg.inf to form a complete path. The path is created and the
  677. path string is returned to the caller.
  678. If g_ToolMode is TRUE, then we don't have an INF to read, and we make
  679. all the directories point to the name "Setup."
  680. Arguments:
  681. Key - Specifies the key (normally a number) that exists in the [Win95.Directories]
  682. section of win95upg.inf.
  683. BaseDir - Specifies the base directory to build the path from.
  684. Empty - TRUE if directory should be emptied, FALSE if it should be created
  685. if it does not already exist
  686. Return Value:
  687. A pointer to the path, or NULL if the specified key doesn't exist or the
  688. path could not be created.
  689. The caller must free a non-NULL return value with FreePathString.
  690. --*/
  691. {
  692. TCHAR FileName[MAX_TCHAR_PATH];
  693. PTSTR Buffer;
  694. BOOL b;
  695. LONG rc;
  696. if (g_ToolMode) {
  697. StringCopy (FileName, TEXT("Setup"));
  698. } else if (!pGetInfEntry (
  699. SECTION_MIGRATION_DIRECTORIES,
  700. Key,
  701. FileName
  702. )) {
  703. LOG ((LOG_ERROR, "%s does not exist in [%s] of %s",Key, SECTION_MIGRATION_DIRECTORIES, FileName));
  704. return FALSE;
  705. }
  706. Buffer = JoinPathsEx (g_GlobalPool, BaseDir, FileName);
  707. if (Empty) {
  708. b = CreateEmptyDirectory (Buffer);
  709. } else {
  710. b = MakeSurePathExists (Buffer, TRUE) == ERROR_SUCCESS;
  711. }
  712. if (!b) {
  713. rc = GetLastError();
  714. if (rc != ERROR_SUCCESS && rc != ERROR_ALREADY_EXISTS) {
  715. LOG ((LOG_ERROR, "Cannot create %s", Buffer));
  716. FreePathStringEx (g_GlobalPool, Buffer);
  717. return NULL;
  718. }
  719. }
  720. return Buffer;
  721. }
  722. BOOL
  723. pGetProductFlavor (
  724. VOID
  725. )
  726. {
  727. DWORD i;
  728. TCHAR buf[12];
  729. PTSTR path;
  730. DWORD count;
  731. DWORD rc = ERROR_INVALID_PARAMETER; // when *g_SourceDirectoryCountFromWinnt32 == 0
  732. BOOL b = FALSE;
  733. for (i = 0; i < *g_SourceDirectoryCountFromWinnt32; i++) {
  734. path = JoinPaths (g_SourceDirectoriesFromWinnt32[i], TEXT("dosnet.inf"));
  735. count = GetPrivateProfileString (
  736. TEXT("Miscellaneous"),
  737. S_PRODUCTTYPE,
  738. TEXT(""),
  739. buf,
  740. 12,
  741. path
  742. );
  743. rc = GetLastError ();
  744. FreePathString (path);
  745. if (count == 1 && buf[0] >= TEXT('0') && buf[0] <= TEXT('9')) {
  746. *g_ProductFlavor = buf[0] - TEXT('0');
  747. b = TRUE;
  748. break;
  749. }
  750. }
  751. if (!b && g_ToolMode) {
  752. b = TRUE;
  753. }
  754. SetLastError (rc);
  755. return b;
  756. }
  757. //
  758. // Exported functions called from WINNT32
  759. //
  760. DWORD
  761. Winnt32Init (
  762. IN PWINNT32_WIN9XUPG_INIT_INFORMATION_BLOCK Info
  763. )
  764. /*++
  765. Routine Description:
  766. Winnt32Init is called when WINNT32 first loads w95upg.dll, before
  767. any wizard pages are displayed. The structure supplies pointers to
  768. WINNT32's variables that will be filled with valid values as WINNT32
  769. runs.
  770. This routine copies the inbound values to our own private structures.
  771. We do not count on WINNT32 to maintain the Info structure after we
  772. return.
  773. In addition to obtaining the WINNT32 variable pointers, this routine
  774. generates all paths needed by the w95upg.dll to do its work.
  775. Arguments:
  776. Win9xInfo - Specifies the WINNT32 variables the upgrade module needs access
  777. to.
  778. Return Value:
  779. A Win32 status code indicating outcome.
  780. --*/
  781. {
  782. DWORD rc = ERROR_SUCCESS;
  783. PCTSTR TempStr = NULL;
  784. PCTSTR RegStr = NULL;
  785. PTSTR TempStr2;
  786. TCHAR TempPath[MAX_TCHAR_PATH];
  787. HKEY Key;
  788. PCTSTR RegData;
  789. HKEY h;
  790. INFSTRUCT is = INITINFSTRUCT_GROWBUFFER;
  791. UINT index;
  792. UINT index2;
  793. #if 0
  794. PDWORD data;
  795. #endif
  796. DEBUGMSG ((
  797. DBG_VERBOSE,
  798. "ProductType: %u\n"
  799. "BuildNumber: %u\n"
  800. "ProductVersion: %u\n"
  801. "Debug: %u\n"
  802. "PreRelease: %u\n"
  803. "UpdatesLocalDir: %s\n",
  804. *Info->BaseInfo->ProductType,
  805. Info->BaseInfo->BuildNumber,
  806. Info->BaseInfo->ProductVersion,
  807. Info->BaseInfo->Debug,
  808. Info->BaseInfo->PreRelease,
  809. Info->DynamicUpdateLocalDir ? Info->DynamicUpdateLocalDir : TEXT("<none>")
  810. ));
  811. __try {
  812. //
  813. // Open win95upg.inf in i386\winnt32\win9x
  814. //
  815. g_Win95UpgInfFile = JoinPathsEx (g_GlobalPool, g_UpgradeSources, STR_WIN95UPG_INF);
  816. g_Win95UpgInf = InfOpenInfFile (g_Win95UpgInfFile);
  817. if (g_Win95UpgInf == INVALID_HANDLE_VALUE) {
  818. if (!g_ToolMode) {
  819. LOG ((LOG_ERROR, "Cannot open %s", g_Win95UpgInfFile));
  820. rc = ERROR_FILE_NOT_FOUND;
  821. __leave;
  822. }
  823. }
  824. InitializeKnownGoodIconMap();
  825. MsgMgr_InitStringMap ();
  826. //
  827. // Get name of platform
  828. //
  829. if (ISWIN95_GOLDEN()) {
  830. TempStr = GetStringResource (MSG_CHICAGO);
  831. } else if (ISWIN95_OSR2()) {
  832. TempStr = GetStringResource (MSG_NASHVILLE);
  833. } else if (ISMEMPHIS()) {
  834. TempStr = GetStringResource (MSG_MEMPHIS);
  835. } else if (ISMILLENNIUM()) {
  836. TempStr = GetStringResource (MSG_MILLENNIUM);
  837. } else {
  838. //
  839. // We don't know what this is. We'll check the registry. If there isn't a name there, we'll
  840. // use an 'unknown' case name.
  841. //
  842. h = OpenRegKeyStr (TEXT("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion"));
  843. if (h && h != INVALID_HANDLE_VALUE) {
  844. RegStr = GetRegValueString (h, TEXT("ProductName"));
  845. CloseRegKey (h);
  846. }
  847. if (!RegStr) {
  848. TempStr = GetStringResource (MSG_UNKOWN_WINDOWS);
  849. }
  850. }
  851. if (!TempStr && !RegStr) {
  852. rc = GetLastError();
  853. __leave;
  854. }
  855. StringCopy (g_Win95Name, TempStr ? TempStr : RegStr);
  856. if (TempStr) {
  857. FreeStringResource (TempStr);
  858. }
  859. if (RegStr) {
  860. MemFree (g_hHeap, 0, RegStr);
  861. }
  862. MemDbSetValueEx (
  863. MEMDB_CATEGORY_STATE,
  864. MEMDB_ITEM_PLATFORM_NAME,
  865. g_Win95Name,
  866. NULL,
  867. 0,
  868. NULL
  869. );
  870. //
  871. // Get %WinDir%, with and without wack
  872. //
  873. if (!GetWindowsDirectory (TempPath, MAX_TCHAR_PATH)) {
  874. return GetLastError ();
  875. }
  876. g_WinDir = PoolMemDuplicateString (g_GlobalPool, TempPath);
  877. g_WinDirWack = JoinPathsEx (g_GlobalPool, g_WinDir, S_EMPTY);
  878. g_WinDirWackChars = CharCount (g_WinDirWack);
  879. g_InfDir = JoinPaths (g_WinDir, S_INFDIR);
  880. g_HelpDir = JoinPaths (g_WinDir, S_HELPDIR);
  881. g_HelpDirWack = JoinPaths (g_HelpDir, S_EMPTY);
  882. g_HelpDirWackChars = CharCount (g_HelpDirWack);
  883. g_CatRootDir = JoinPaths (g_WinDir, S_CATROOTDIR);
  884. g_CatRootDirWack = JoinPaths (g_CatRootDir, S_EMPTY);
  885. g_CatRootDirWackChars = CharCount (g_CatRootDirWack);
  886. g_FontsDir = JoinPaths (g_WinDir, S_FONTSDIR);
  887. g_SharedDir = g_WinDir;
  888. //
  889. // Get Windows drive
  890. //
  891. SplitPath (g_WinDir, &TempStr2, NULL, NULL, NULL);
  892. g_WinDrive = PoolMemDuplicateString (g_GlobalPool, TempStr2);
  893. FreePathString (TempStr2);
  894. //
  895. // Get user profile dir
  896. //
  897. g_ProfileDir = JoinPathsEx (g_GlobalPool, g_WinDir, S_PROFILES);
  898. g_ProfileDirWack = JoinPathsEx (g_GlobalPool, g_ProfileDir, S_EMPTY);
  899. g_ProfileDirWackChars = CharCount (g_ProfileDirWack);
  900. g_CommonProfileDir = JoinPathsEx (g_GlobalPool, g_WinDir, TEXT("All Users"));
  901. //
  902. // Get System dir, with and without wack
  903. //
  904. GetSystemDirectory(TempPath, MAX_TCHAR_PATH);
  905. g_SystemDir = PoolMemDuplicateString (g_GlobalPool, TempPath);
  906. g_SystemDirWack = JoinPathsEx (g_GlobalPool, g_SystemDir, S_EMPTY);
  907. g_SystemDirWackChars = CharCount (g_SystemDirWack);
  908. //
  909. // Get System32 dir
  910. //
  911. g_System32Dir = JoinPathsEx (g_GlobalPool, g_WinDir, STR_SYSTEM32);
  912. g_System32DirWack = JoinPathsEx (g_GlobalPool, g_System32Dir, S_EMPTY);
  913. g_System32DirWackChars = CharCount (g_System32DirWack);
  914. g_DriversDir = JoinPaths (g_System32Dir, S_DRIVERSDIR);
  915. g_ViewersDir = JoinPaths (g_System32Dir, S_VIEWERSDIR);
  916. g_SpoolDir = JoinPaths (g_System32Dir, S_SPOOLDIR);
  917. g_SpoolDriversDir = JoinPaths (g_SpoolDir, S_SPOOLDRIVERSDIR);
  918. g_ColorDir = JoinPaths (g_SpoolDriversDir,S_COLORDIR);
  919. g_PrintProcDir = JoinPaths (g_SpoolDir, S_PRINTPROCDIR);
  920. //
  921. // Get Program Files dir
  922. //
  923. g_ProgramFilesDir = NULL;
  924. g_ProgramFilesCommonDir = NULL;
  925. Key = OpenRegKeyStr (TEXT("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion"));
  926. if (Key) {
  927. RegData = GetRegValueString (Key, TEXT("ProgramFilesDir"));
  928. if (RegData) {
  929. g_ProgramFilesDir = PoolMemDuplicateString (g_GlobalPool, RegData);
  930. MemFree (g_hHeap, 0, RegData);
  931. }
  932. }
  933. if (!g_ProgramFilesDir) {
  934. TempStr = (PTSTR) GetStringResource (MSG_PROGRAM_FILES_DIR);
  935. MYASSERT (TempStr);
  936. g_ProgramFilesDir = PoolMemDuplicateString (g_GlobalPool, TempStr);
  937. MYASSERT (g_ProgramFilesDir);
  938. g_ProgramFilesDir[0] = g_SystemDir[0];
  939. FreeStringResource (TempStr);
  940. }
  941. DEBUGMSG ((DBG_VERBOSE, "Program Files Dir is %s", g_ProgramFilesDir));
  942. //
  943. // Get Program Files\Common Files dir
  944. //
  945. g_ProgramFilesDirWack = JoinPathsEx (g_GlobalPool, g_ProgramFilesDir, S_EMPTY);
  946. MYASSERT (g_ProgramFilesDirWack);
  947. g_ProgramFilesDirWackChars = CharCount (g_ProgramFilesDirWack);
  948. if (Key) {
  949. RegData = GetRegValueString (Key, TEXT("CommonFilesDir"));
  950. if (RegData) {
  951. g_ProgramFilesCommonDir = PoolMemDuplicateString (g_GlobalPool, RegData);
  952. MemFree (g_hHeap, 0, RegData);
  953. }
  954. }
  955. if (!g_ProgramFilesCommonDir) {
  956. TempStr = JoinPaths (g_ProgramFilesDir, S_COMMONDIR);
  957. g_ProgramFilesCommonDir = PoolMemDuplicateString (g_GlobalPool, TempStr);
  958. FreePathString (TempStr);
  959. }
  960. if (Key) {
  961. CloseRegKey (Key);
  962. }
  963. DEBUGMSG ((DBG_VERBOSE, "Common Program Files Dir is %s", g_ProgramFilesCommonDir));
  964. //
  965. // Create temporary directory path, with and without wack
  966. //
  967. g_TempDir = pCreateDirectoryFromInf (KEY_TEMP_BASE, g_WinDir, FALSE);
  968. if (!g_TempDir) {
  969. rc = GetLastError();
  970. __leave;
  971. }
  972. g_Win9xSifDir = JoinPathsEx (g_GlobalPool, g_TempDir,S_WIN9XSIF);
  973. g_TempDirWack = JoinPathsEx (g_GlobalPool, g_TempDir, S_EMPTY);
  974. g_TempDirWackChars = CharCount (g_TempDirWack);
  975. //
  976. // Build plugin dir, with and without wack
  977. //
  978. g_PlugInDir = PoolMemDuplicateString (g_GlobalPool, g_TempDir);
  979. g_PlugInDirWack = JoinPathsEx (g_GlobalPool, g_PlugInDir, S_EMPTY);
  980. g_PlugInDirWackChars = CharCount (g_PlugInDirWack);
  981. //
  982. // Create plugin temp dir, with and without wack.
  983. //
  984. g_PlugInTempDir = JoinPathsEx (g_GlobalPool, g_PlugInDir, TEXT("temp"));
  985. //
  986. // Create recycled dir, with wack
  987. //
  988. g_RecycledDirWack = JoinPathsEx (g_GlobalPool, g_WinDrive, TEXT("recycled\\"));
  989. g_RecycledDirWackChars = CharCount (g_RecycledDirWack);
  990. //
  991. // Copy WINNT32 settings to globals
  992. //
  993. // NOTE: If more args are added to WINNT32's Info struct, you should
  994. // adjust the InitToolMode code below to match.
  995. //
  996. //
  997. g_UnattendedFlagPtr = Info->BaseInfo->UnattendedFlag;
  998. g_CancelFlagPtr = Info->BaseInfo->CancelledFlag;
  999. g_AbortFlagPtr = Info->BaseInfo->AbortedFlag;
  1000. g_UpgradeFlagPtr = Info->BaseInfo->UpgradeFlag;
  1001. g_MakeLocalSourcePtr = Info->BaseInfo->LocalSourceModeFlag;
  1002. g_CdRomInstallPtr = Info->BaseInfo->CdRomInstallFlag;
  1003. g_UnattendScriptFile = Info->BaseInfo->UnattendedScriptFile;
  1004. g_CmdLineOptions = Info->BaseInfo->UpgradeOptions;
  1005. g_BlockOnNotEnoughSpace = Info->BaseInfo->NotEnoughSpaceBlockFlag;
  1006. g_LocalSourceDrive = Info->BaseInfo->LocalSourceDrive;
  1007. g_LocalSourceSpace = Info->BaseInfo->LocalSourceSpaceRequired;
  1008. g_ProductType = Info->BaseInfo->ProductType;
  1009. g_SourceDirectoryCountFromWinnt32 = Info->BaseInfo->SourceDirectoryCount;
  1010. g_SourceDirectoriesFromWinnt32 = Info->BaseInfo->SourceDirectories;
  1011. g_ForceNTFSConversion = Info->BaseInfo->ForceNTFSConversion;
  1012. g_Boot16 = Info->BaseInfo->Boot16;
  1013. g_UnattendSwitchSpecified = Info->BaseInfo->UnattendSwitchSpecified;
  1014. //
  1015. // ProductFlavor is not initialized at this point yet, but it will be below
  1016. //
  1017. g_ProductFlavor = Info->BaseInfo->ProductFlavor;
  1018. g_SetupFlags = Info->BaseInfo->SetupFlags;
  1019. g_WinDirSpace = Info->WinDirSpace;
  1020. g_RamNeeded = Info->RequiredMb;
  1021. g_RamAvailable = Info->AvailableMb;
  1022. g_OptionalDirectoryCountFromWinnt32 = Info->OptionalDirectoryCount;
  1023. g_OptionalDirectoriesFromWinnt32 = Info->OptionalDirectories;
  1024. g_UpginfsUpdated = Info->UpginfsUpdated;
  1025. ReadDiskSectors = Info->ReadDiskSectors;
  1026. if (!pGetProductFlavor ()) {
  1027. LOG ((LOG_ERROR, "Cannot get ProductType key from dosnet.inf"));
  1028. rc = GetLastError ();
  1029. __leave;
  1030. }
  1031. if (*g_ProductFlavor != PROFESSIONAL_PRODUCTTYPE && *g_ProductFlavor != PERSONAL_PRODUCTTYPE) {
  1032. *g_ProductType = NT_SERVER;
  1033. } else {
  1034. *g_ProductType = NT_WORKSTATION;
  1035. g_PersonalSKU = (*g_ProductFlavor == PERSONAL_PRODUCTTYPE);
  1036. }
  1037. if (IsServerInstall()) {
  1038. rc = ERROR_REQUEST_ABORTED;
  1039. __leave;
  1040. }
  1041. //
  1042. // NOTE: If more args are added to WINNT32's Info struct, you should
  1043. // adjust the InitToolMode code below to match.
  1044. //
  1045. if (Info->DynamicUpdateLocalDir && *Info->DynamicUpdateLocalDir) {
  1046. g_DynamicUpdateLocalDir = DuplicateTextEx (g_GlobalPool, Info->DynamicUpdateLocalDir, 0, NULL);
  1047. }
  1048. if (Info->DynamicUpdateDrivers && *Info->DynamicUpdateDrivers) {
  1049. g_DynamicUpdateDrivers = DuplicateTextEx (g_GlobalPool, Info->DynamicUpdateDrivers, 0, NULL);
  1050. }
  1051. g_UserOptionPool = PoolMemInitNamedPool ("User Options");
  1052. //
  1053. // Initialize Win9x environment table
  1054. //
  1055. Init9xEnvironmentVariables();
  1056. //
  1057. // Make sure that we really want to upgrade this machine.
  1058. //
  1059. if (!g_ToolMode && !pSafeToUpgrade ()) {
  1060. *Info->UpgradeFailureReason = REASON_UPGRADE_OTHER_OS_FOUND;
  1061. rc = ERROR_REQUEST_ABORTED;
  1062. __leave;
  1063. }
  1064. //
  1065. // winnt32 doesn't scrub the source directories for duplicates..We, however, do.
  1066. //
  1067. g_SourceDirectoryCount = 0;
  1068. for (index = 0 ; index < *g_SourceDirectoryCountFromWinnt32; index++) {
  1069. for (index2 = 0; index2 < g_SourceDirectoryCount; index2++) {
  1070. if (StringIMatch(
  1071. g_SourceDirectories[index2],
  1072. g_SourceDirectoriesFromWinnt32[index]
  1073. )) {
  1074. DEBUGMSG ((
  1075. DBG_WARNING,
  1076. "Duplicate Source Directory %s removed from list!!",
  1077. g_SourceDirectories[index2]
  1078. ));
  1079. break;
  1080. }
  1081. }
  1082. if (index2 == g_SourceDirectoryCount) {
  1083. //
  1084. // No matching directory found, add to list..
  1085. //
  1086. g_SourceDirectories[g_SourceDirectoryCount++] = g_SourceDirectoriesFromWinnt32[index];
  1087. }
  1088. }
  1089. //
  1090. // Do the samescrubbing with optional directories.
  1091. //
  1092. g_OptionalDirectoryCount = 0;
  1093. for (index = 0 ; index < *g_OptionalDirectoryCountFromWinnt32; index++) {
  1094. for (index2 = 0; index2 < g_OptionalDirectoryCount; index2++) {
  1095. if (StringIMatch(
  1096. g_OptionalDirectories[index2],
  1097. g_OptionalDirectoriesFromWinnt32[index]
  1098. )) {
  1099. DEBUGMSG ((
  1100. DBG_WARNING,
  1101. "Duplicate Optional Directory %s removed from list!!",
  1102. g_OptionalDirectories[index2]
  1103. ));
  1104. break;
  1105. }
  1106. }
  1107. if (index2 == g_OptionalDirectoryCount) {
  1108. //
  1109. // No matching directory found, add to list..
  1110. //
  1111. g_OptionalDirectories[g_OptionalDirectoryCount++] = g_OptionalDirectoriesFromWinnt32[index];
  1112. }
  1113. }
  1114. //
  1115. // block upgrades from Win95
  1116. //
  1117. if (!g_ToolMode && !ISATLEASTWIN98()) {
  1118. rc = ERROR_REQUEST_ABORTED;
  1119. ResourceMessageBox (NULL, MSG_PLATFORM_UPGRADE_UNSUPPORTED, MB_OK, NULL);
  1120. __leave;
  1121. }
  1122. rc = ERROR_SUCCESS;
  1123. }
  1124. __finally {
  1125. if (rc != ERROR_SUCCESS && rc != ERROR_REQUEST_ABORTED) {
  1126. if (g_Win95UpgInf != INVALID_HANDLE_VALUE) {
  1127. InfCloseInfFile (g_Win95UpgInf);
  1128. g_Win95UpgInf = INVALID_HANDLE_VALUE;
  1129. }
  1130. }
  1131. }
  1132. return rc;
  1133. }
  1134. BOOL
  1135. InitToolMode (
  1136. HINSTANCE Instance
  1137. )
  1138. /*++
  1139. Routine Description:
  1140. InitToolMode is called by Win9x-side tools (not by shipping setup code).
  1141. It initializes the libraries and simulates WINNT32 init.
  1142. Arguments:
  1143. None.
  1144. Return Value:
  1145. TRUE if init was successful, FALSE otherwise.
  1146. --*/
  1147. {
  1148. DWORD dwReason;
  1149. PVOID lpReserved;
  1150. WINNT32_PLUGIN_INIT_INFORMATION_BLOCK BaseInfo;
  1151. WINNT32_WIN9XUPG_INIT_INFORMATION_BLOCK InfoBlock;
  1152. static BOOL AlwaysFalseFlag = FALSE;
  1153. static BOOL AlwaysTrueFlag = TRUE;
  1154. static PRODUCTTYPE ProductType = NT_WORKSTATION;
  1155. static UINT SourceDirs = 1;
  1156. static PCTSTR SourceDirMultiSz = TEXT(".\0");
  1157. static UINT ProductFlavor = PERSONAL_PRODUCTTYPE;
  1158. static UINT AlwaysZero = 0;
  1159. g_ToolMode = TRUE;
  1160. //
  1161. // Simulate DllMain
  1162. //
  1163. dwReason = DLL_PROCESS_ATTACH;
  1164. lpReserved = NULL;
  1165. //
  1166. // Initialize DLL globals
  1167. //
  1168. if (!FirstInitRoutine (Instance)) {
  1169. return FALSE;
  1170. }
  1171. //
  1172. // Initialize all libraries
  1173. //
  1174. if (!InitLibs (Instance, dwReason, lpReserved)) {
  1175. return FALSE;
  1176. }
  1177. //
  1178. // Final initialization
  1179. //
  1180. if (!FinalInitRoutine ()) {
  1181. return FALSE;
  1182. }
  1183. //
  1184. // Simulate WINNT32 init
  1185. //
  1186. ZeroMemory (&BaseInfo, sizeof (BaseInfo));
  1187. ZeroMemory (&InfoBlock, sizeof (InfoBlock));
  1188. BaseInfo.UnattendedFlag = &AlwaysFalseFlag;
  1189. BaseInfo.CancelledFlag = &AlwaysFalseFlag;
  1190. BaseInfo.AbortedFlag = &AlwaysFalseFlag;
  1191. BaseInfo.UpgradeFlag = &AlwaysTrueFlag;
  1192. BaseInfo.LocalSourceModeFlag = &AlwaysFalseFlag;
  1193. BaseInfo.CdRomInstallFlag = &AlwaysFalseFlag;
  1194. BaseInfo.UnattendedScriptFile = NULL;
  1195. BaseInfo.UpgradeOptions = NULL;
  1196. BaseInfo.NotEnoughSpaceBlockFlag = &AlwaysFalseFlag;
  1197. BaseInfo.LocalSourceDrive = NULL;
  1198. BaseInfo.LocalSourceSpaceRequired = 0;
  1199. BaseInfo.ProductType = &ProductType;
  1200. BaseInfo.SourceDirectoryCount = &SourceDirs;
  1201. BaseInfo.SourceDirectories = &SourceDirMultiSz;
  1202. BaseInfo.ForceNTFSConversion = &AlwaysFalseFlag;
  1203. BaseInfo.Boot16 = &AlwaysFalseFlag;
  1204. BaseInfo.ProductFlavor = &ProductFlavor;
  1205. InfoBlock.BaseInfo = &BaseInfo;
  1206. InfoBlock.WinDirSpace = 0;
  1207. InfoBlock.RequiredMb = 0;
  1208. InfoBlock.AvailableMb = 0;
  1209. InfoBlock.OptionalDirectories = NULL;
  1210. InfoBlock.OptionalDirectoryCount = &AlwaysZero;
  1211. return ERROR_SUCCESS == Winnt32Init (&InfoBlock);
  1212. }
  1213. VOID
  1214. TerminateToolMode (
  1215. HINSTANCE Instance
  1216. )
  1217. {
  1218. DWORD dwReason;
  1219. PVOID lpReserved;
  1220. //
  1221. // Simulate DllMain
  1222. //
  1223. dwReason = DLL_PROCESS_DETACH;
  1224. lpReserved = NULL;
  1225. //
  1226. // Call the cleanup routine that requires library APIs
  1227. //
  1228. FirstCleanupRoutine();
  1229. //
  1230. // Clean up all libraries
  1231. //
  1232. TerminateLibs (Instance, dwReason, lpReserved);
  1233. //
  1234. // Do any remaining clean up
  1235. //
  1236. FinalCleanupRoutine();
  1237. }
  1238. DWORD
  1239. Winnt32WriteParamsWorker (
  1240. IN PCTSTR WinntSifFile
  1241. )
  1242. /*++
  1243. Routine Description:
  1244. Winnt32WriteParamsWorker is called just before WINNT32 begins to modify the
  1245. boot sector and copy files. Our job here is to take the specified
  1246. WINNT.SIF file, read it in, merge in our changes, and write it back
  1247. out.
  1248. Arguments:
  1249. WinntSifFile - Specifies path to WINNT.SIF. By this time, the WINNT.SIF
  1250. file has some values already set.
  1251. Return Value:
  1252. A Win32 status code indicating outcome.
  1253. --*/
  1254. {
  1255. static TCHAR SifBuf[MAX_TCHAR_PATH];
  1256. //
  1257. // This can take a while (especially writing the INF to disk.)
  1258. // Display a wait cursor.
  1259. //
  1260. TurnOnWaitCursor();
  1261. __try {
  1262. //
  1263. // We finally got the WINNT.SIF file location. Merge any
  1264. // settings that are already there, then save it to disk.
  1265. // If it saves OK, start using profile APIs.
  1266. //
  1267. if (!MergeInf (WinntSifFile))
  1268. return GetLastError();
  1269. if (!WriteInfToDisk (WinntSifFile))
  1270. return GetLastError();
  1271. StringCopy (SifBuf, WinntSifFile);
  1272. g_ProfileName = SifBuf;
  1273. if (!REPORTONLY()) {
  1274. //
  1275. // Go ahead and save ntsetup.dat at this time as well.. to ensure that we
  1276. // get rid of the BuildInf stuff.
  1277. //
  1278. MemDbSetValue (
  1279. MEMDB_CATEGORY_STATE TEXT("\\") MEMDB_ITEM_MASTER_SEQUENCER,
  1280. g_MasterSequencer
  1281. );
  1282. if (!MemDbSave (UI_GetMemDbDat())) {
  1283. return GetLastError();
  1284. }
  1285. }
  1286. #ifdef PRERELEASE
  1287. if (g_ConfigOptions.DevPause) {
  1288. OkBox (g_ParentWnd, (DWORD) TEXT("Developer Pause"));
  1289. }
  1290. #endif
  1291. }
  1292. __finally {
  1293. TurnOffWaitCursor();
  1294. }
  1295. return ERROR_SUCCESS;
  1296. }
  1297. VOID
  1298. Winnt32CleanupWorker (
  1299. VOID
  1300. )
  1301. /*++
  1302. Routine Description:
  1303. If the user cancels Setup, Winnt32Cleanup is called while WINNT32 is
  1304. displaying the wizard page "Setup is undoing changes it made to your
  1305. computer." We must stop all processing and clean up.
  1306. If WINNT32 completes all of its work, Winnt32Cleanup is called as
  1307. the process exists.
  1308. We get called even on fresh install, so we must verify we are upgrading.
  1309. Arguments:
  1310. none
  1311. Return Value:
  1312. none
  1313. --*/
  1314. {
  1315. HKEY Key;
  1316. TCHAR Path[MAX_TCHAR_PATH];
  1317. TCHAR src[MAX_PATH];
  1318. TCHAR dest[MAX_PATH];
  1319. DWORD attribs;
  1320. TCHAR drive[] = TEXT(":?");
  1321. UINT u;
  1322. DEBUGMSG ((DBG_VERBOSE, "Winnt32Cleanup initiated"));
  1323. TerminateWinntSifBuilder();
  1324. UI_Cleanup();
  1325. //
  1326. // If the cancel flag pointer is set, we must undo everything!!
  1327. //
  1328. if (CANCELLED()) {
  1329. DeleteDirectoryContents(g_PlugInTempDir);
  1330. RemoveDirectory(g_PlugInTempDir);
  1331. DeleteDirectoryContents(g_TempDir);
  1332. RemoveDirectory(g_TempDir);
  1333. //
  1334. // Enumerate all drives and try to delete user~tmp.@0?
  1335. //
  1336. pCleanUpShellFolderTemp();
  1337. //
  1338. // if some files were already affected, undo those modifications
  1339. //
  1340. UndoChangedFileProps ();
  1341. } else {
  1342. //
  1343. // Put boot.ini in uninstall image
  1344. //
  1345. if (g_BootDrivePath && g_TempDir) {
  1346. StringCopy (src, g_BootDrivePath);
  1347. StringCopy (AppendWack (src), S_BOOTINI);
  1348. StringCopy (dest, g_TempDir);
  1349. StringCopy (AppendWack (dest), TEXT("uninstall\\boot.ini"));
  1350. attribs = GetFileAttributes (src);
  1351. SetFileAttributes (src, FILE_ATTRIBUTE_NORMAL);
  1352. CopyFile (src, dest, FALSE);
  1353. SetFileAttributes (src, attribs);
  1354. StringCopy (src, g_BootDrivePath);
  1355. StringCopy (AppendWack (src), TEXT("$ldr$"));
  1356. StringCopy (dest, g_TempDir);
  1357. StringCopy (AppendWack (dest), TEXT("uninstall\\$ldr$"));
  1358. attribs = GetFileAttributes (src);
  1359. SetFileAttributes (src, FILE_ATTRIBUTE_NORMAL);
  1360. CopyFile (src, dest, FALSE);
  1361. SetFileAttributes (src, attribs);
  1362. if (g_ConfigOptions.EnableBackup) {
  1363. //
  1364. // Put autochk.exe in c:\$win_nt$.~bt\i386
  1365. //
  1366. StringCopy (dest, g_BootDrivePath);
  1367. StringCat (dest, TEXT("$win_nt$.~bt\\i386\\autochk.exe"));
  1368. MakeSurePathExists (dest, FALSE);
  1369. for (u = 0 ; u < g_SourceDirectoryCount ; u++) {
  1370. StringCopy (src, g_SourceDirectories[u]);
  1371. StringCopy (AppendWack (src), "autochk.exe");
  1372. if (DoesFileExist (src)) {
  1373. break;
  1374. }
  1375. }
  1376. if (u == g_SourceDirectoryCount) {
  1377. LOG ((LOG_WARNING, "autochk.exe not found in sources"));
  1378. } else {
  1379. if (!CopyFile (src, dest, FALSE)) {
  1380. LOG ((LOG_WARNING, "autochk.exe could not be copied from %s to %s; not fatal", src, dest));
  1381. }
  1382. }
  1383. }
  1384. } else {
  1385. MYASSERT (FALSE);
  1386. }
  1387. //
  1388. // Put cleanup code in Run key
  1389. //
  1390. Key = CreateRegKeyStr (TEXT("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunServicesOnce"));
  1391. MYASSERT (Key);
  1392. if (Key) {
  1393. wsprintf(
  1394. Path,
  1395. TEXT("\"%s\\migisol.exe\" -%c"),
  1396. g_TempDir,
  1397. g_ConfigOptions.EnableBackup? 'b': 'c'
  1398. );
  1399. if(g_ConfigOptions.EnableBackup){
  1400. drive[1] = g_BootDrivePath[0];
  1401. StringCat(Path, drive);
  1402. }
  1403. DEBUGMSG ((DBG_VERBOSE, Path));
  1404. if(ERROR_SUCCESS != RegSetValueEx (Key, TEXT("WINNT32"), 0, REG_SZ, (PBYTE) Path, SizeOfString (Path))){
  1405. DEBUGMSG ((DBG_ERROR, "RegSetValueEx is failed to setup RunServicesOnce with migisol.exe"));
  1406. }
  1407. CloseRegKey (Key);
  1408. }
  1409. }
  1410. SafeModeShutDown ();
  1411. DEBUGMSG ((DBG_VERBOSE, "Winnt32Cleanup completed"));
  1412. }
  1413. BOOL
  1414. Winnt32SetAutoBootWorker (
  1415. IN INT DrvLetter
  1416. )
  1417. /*++
  1418. Routine Description:
  1419. Winnt32SetAutoBootWorker is called by WINNT32 on both upgrade and fresh install
  1420. to modify the boot partition of a NEC PC-9800 Partition Control Table.
  1421. Arguments:
  1422. none
  1423. Return Value:
  1424. TRUE if the partition control table was updated, or FALSE if it wasn't,
  1425. or an error occurred.
  1426. --*/
  1427. {
  1428. INT Win95BootDrive;
  1429. INT rc = TRUE;
  1430. if(ISPC98()) {
  1431. if (!g_Pc98ModuleHandle) {
  1432. LOG ((LOG_ERROR, "PC98: External module not loaded! Can't update auto boot."));
  1433. return FALSE;
  1434. }
  1435. //
  1436. // Set the NT 5 drive as "Bootable" and "Auto boot"
  1437. //
  1438. if (!SetBootFlag (DrvLetter, SB_BOOTABLE | SB_AUTO)) {
  1439. LOG ((LOG_ERROR, "PC98: Unable to set target partition as BOOTABLE and AUTO."));
  1440. return FALSE;
  1441. }
  1442. DrvLetter = _totupper (DrvLetter);
  1443. Win95BootDrive = _totupper ((UINT) g_BootDriveLetter);
  1444. if ( Win95BootDrive != DrvLetter) {
  1445. if ( *g_Boot16 == BOOT16_YES ) {
  1446. //
  1447. // In this case, we do not create "MS-DOS" entry into BOOT.INI.
  1448. // Set partition name to Win95 boot drive and NT5 system drive, instead of NT5 Boot menu (boot.ini).
  1449. //
  1450. rc = SetPtnName (Win95BootDrive, WIN9X_DOS_NAME);
  1451. if (!rc) {
  1452. LOG ((LOG_ERROR, "PC98: Unable to set partition name into NEC98 boot menu. (WIN9X_DOS_NAME)"));
  1453. }
  1454. rc = SetPtnName (DrvLetter, WINNT5_NAME);
  1455. if (!rc) {
  1456. LOG ((LOG_ERROR, "PC98: Unable to set partition name into NEC98 boot menu. (WINNT5_NAME)"));
  1457. }
  1458. } else {
  1459. //
  1460. // Set to Win95 drive as "Unbootable"
  1461. //
  1462. rc = SetBootFlag (Win95BootDrive, SB_UNBOOTABLE);
  1463. if (!rc) {
  1464. LOG ((LOG_ERROR, "PC98: Unable to set target partition as UNBOOTABLE."));
  1465. }
  1466. }
  1467. }
  1468. return rc;
  1469. }
  1470. return FALSE;
  1471. }
  1472. BOOL
  1473. IsServerInstall (
  1474. VOID
  1475. )
  1476. /*++
  1477. Routine Description:
  1478. IsServerInstall checks win95upg.inf to see if ProductType is set to zero,
  1479. indicating workstation. If this test passes incorrectly, a test in
  1480. wizproc.c will catch the upgrade to server.
  1481. Arguments:
  1482. None.
  1483. Return Value:
  1484. TRUE if this win95upg.inf is for server.
  1485. --*/
  1486. {
  1487. PCTSTR ArgArray[1];
  1488. BOOL b;
  1489. if (g_ToolMode) {
  1490. return FALSE;
  1491. }
  1492. //
  1493. // Block upgrades of Server
  1494. //
  1495. b = FALSE;
  1496. if (*g_ProductFlavor != PROFESSIONAL_PRODUCTTYPE && *g_ProductFlavor != PERSONAL_PRODUCTTYPE) {
  1497. ArgArray[0] = g_Win95Name;
  1498. ResourceMessageBox (
  1499. g_ParentWnd,
  1500. MSG_SERVER_UPGRADE_UNSUPPORTED_INIT,
  1501. MB_OK|MB_ICONSTOP|MB_SETFOREGROUND,
  1502. ArgArray
  1503. );
  1504. b = TRUE;
  1505. }
  1506. return b;
  1507. }