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.

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