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.

1605 lines
39 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. #include <stdio.h>
  4. BOOL
  5. LoadInfs(
  6. IN HWND hdlg
  7. );
  8. BOOL
  9. BuildCopyList(
  10. IN HWND hdlg
  11. );
  12. BOOL
  13. LoadAndRunMigrationDlls (
  14. HWND hDlg
  15. );
  16. BOOL
  17. ProcessCompatibilityData(
  18. HWND hDlg
  19. );
  20. DWORD
  21. ProcessCompatibilitySection(
  22. LPVOID InfHandle,
  23. LPTSTR SectionName
  24. );
  25. DWORD
  26. InspectAndLoadThread(
  27. IN PVOID ThreadParam
  28. )
  29. {
  30. HWND hdlg;
  31. BOOL b;
  32. //
  33. // Thread parameter is the handle of the page in the wizard.
  34. //
  35. hdlg = ThreadParam;
  36. b = FALSE;
  37. //
  38. // If we're running the upgrade checker, fixup the title
  39. // right away.
  40. //
  41. if (CheckUpgradeOnly) {
  42. FixUpWizardTitle(GetParent(hdlg));
  43. PropSheet_SetTitle(GetParent(hdlg),0,UIntToPtr( IDS_APPTITLE_CHECKUPGRADE ));
  44. }
  45. //
  46. // Step 1: delete existing local sources.
  47. //
  48. CleanUpOldLocalSources(hdlg);
  49. #ifdef _X86_ //NEC98
  50. //
  51. // If NEC98, Backup NT4 files
  52. // boot.ini, NTLDR, NTDETECT
  53. //
  54. if (IsNEC98() && Floppyless)
  55. {
  56. SaveRestoreBootFiles_NEC98(NEC98SAVEBOOTFILES);
  57. }
  58. #endif //NEC98
  59. //
  60. // Step 2: inspect for HPFS, etc.
  61. //
  62. if(!InspectFilesystems(hdlg)) {
  63. Cancelled = TRUE;
  64. } else {
  65. //
  66. // Step 3: load inf(s).
  67. //
  68. if(LoadInfs(hdlg)) {
  69. //
  70. // Put in an "|| CheckUpgradeOnly" on these
  71. // function calls because if we're really only
  72. // checking the ability to upgrade, we want
  73. // to continue even if one of these guys fails.
  74. //
  75. //
  76. // Step 4: Check memory resources.
  77. //
  78. if( EnoughMemory( hdlg, FALSE ) || CheckUpgradeOnly ) {
  79. //
  80. // check for services to disable
  81. //
  82. ProcessCompatibilityData(hdlg);
  83. #if defined(UNICODE) && defined(_X86_)
  84. //
  85. // Run Migration DLLs.
  86. //
  87. LoadAndRunMigrationDlls (hdlg);
  88. #endif
  89. //
  90. // migrate any important data in boot.ini (like the countdown)
  91. //
  92. if (Upgrade) {
  93. if (IsArc()) {
  94. MigrateBootVarData();
  95. } else {
  96. #ifdef _X86_
  97. MigrateBootIniData();
  98. #endif
  99. }
  100. }
  101. //
  102. // Step 5: build the master file copy list.
  103. //
  104. if(CheckUpgradeOnly || BuildCopyList(hdlg)) {
  105. //
  106. // Step 6: look for a valid local source and check disk space.
  107. //
  108. if(FindLocalSourceAndCheckSpace(hdlg, FALSE, 0) || CheckUpgradeOnly) {
  109. //
  110. // Step 7:
  111. //
  112. // At this point we actually know everything we need to know
  113. // in order to pass parameters to text mode setup.
  114. //
  115. if( CheckUpgradeOnly ) {
  116. b = TRUE;
  117. } else {
  118. b = WriteParametersFile(hdlg);
  119. if (IsArc()) {
  120. #ifdef UNICODE // Always true for ARC, never true for Win9x upgrade
  121. if(b) {
  122. TCHAR Text[128];
  123. LoadString(hInst,IDS_SETTING_NVRAM,Text,sizeof(Text)/sizeof(TCHAR));
  124. SendMessage(hdlg,WMX_SETPROGRESSTEXT,0,(LPARAM)Text);
  125. b = SetUpNvRam(hdlg);
  126. }
  127. #endif // UNICODE
  128. } // if (IsArc())
  129. }
  130. #ifdef UNICODE
  131. if( b && Upgrade
  132. #ifdef _X86_
  133. && Floppyless
  134. #endif
  135. ) {
  136. //
  137. // Do the migration of unsupported NT drivers.
  138. // We can ignore the return code, since the fuction will inform the user if
  139. // migration could not be done.
  140. //
  141. MigrateUnsupportedNTDrivers( hdlg, TxtsetupSif );
  142. }
  143. #endif // UNICODE
  144. }
  145. }
  146. if(!b) {
  147. UnloadInfFile(MainInf);
  148. MainInf = NULL;
  149. if(TxtsetupSif) {
  150. UnloadInfFile(TxtsetupSif);
  151. TxtsetupSif = NULL;
  152. }
  153. }
  154. }
  155. }
  156. }
  157. PostMessage(hdlg,WMX_INSPECTRESULT,(CheckUpgradeOnly ? TRUE : b),0);
  158. return(0);
  159. }
  160. #if defined(UNICODE) && defined(_X86_)
  161. LIST_ENTRY g_HandledData;
  162. TCHAR g_MigDllAnswerFilePath[MAX_PATH];
  163. DWORD GlobalCompFlags;
  164. UINT g_MigDllIndex = 0;
  165. #define HANDLED_REGISTRY 1
  166. #define HANDLED_FILE 2
  167. #define HANDLED_SERVICE 3
  168. typedef struct {
  169. LIST_ENTRY ListEntry;
  170. LONG Type;
  171. PCTSTR RegKey;
  172. PCTSTR RegValue;
  173. PCTSTR File;
  174. PCTSTR Service;
  175. } HANDLED_DATA, *PHANDLED_DATA;
  176. BOOL
  177. ResolveHandledIncompatibilities (
  178. VOID
  179. )
  180. {
  181. //
  182. // At this point, all incompatibilities that will exist in the list are in place.
  183. // we can now compare this with our list of handled data and remove
  184. // anything a migration dll is taking care of.
  185. //
  186. PLIST_ENTRY nextHandled;
  187. PLIST_ENTRY nextCompData;
  188. PHANDLED_DATA handledData;
  189. PCOMPATIBILITY_DATA compData;
  190. BOOL remove;
  191. nextHandled = g_HandledData.Flink;
  192. if (!nextHandled) {
  193. return TRUE;
  194. }
  195. while ((ULONG_PTR)nextHandled != (ULONG_PTR)&g_HandledData) {
  196. handledData = CONTAINING_RECORD (nextHandled, HANDLED_DATA, ListEntry);
  197. nextHandled = handledData->ListEntry.Flink;
  198. nextCompData = CompatibilityData.Flink;
  199. if (!nextCompData) {
  200. return TRUE;
  201. }
  202. while ((ULONG_PTR)nextCompData != (ULONG_PTR)&CompatibilityData) {
  203. compData = CONTAINING_RECORD (nextCompData, COMPATIBILITY_DATA, ListEntry);
  204. nextCompData = compData->ListEntry.Flink;
  205. remove = FALSE;
  206. if (handledData->Type == HANDLED_REGISTRY && compData->RegKey && *compData->RegKey) {
  207. if (!lstrcmpi (compData->RegKey, handledData->RegKey)) {
  208. if (!handledData->RegValue || !lstrcmpi (compData->RegValue, handledData->RegValue)) {
  209. remove = TRUE;
  210. }
  211. }
  212. }
  213. if (handledData->Type == HANDLED_SERVICE && compData->ServiceName && *compData->ServiceName) {
  214. if (!lstrcmpi (compData->ServiceName, handledData->Service)) {
  215. remove = TRUE;
  216. }
  217. }
  218. if (handledData->Type == HANDLED_FILE && compData->FileName && *compData->FileName) {
  219. if (!lstrcmpi (compData->FileName, handledData->File)) {
  220. remove = TRUE;
  221. }
  222. }
  223. //
  224. // Migration dll has handled something. Remove it from the compatibility list.
  225. //
  226. if (remove) {
  227. RemoveEntryList (&compData->ListEntry);
  228. }
  229. }
  230. }
  231. return TRUE;
  232. }
  233. BOOL
  234. CallMigDllEntryPoints (
  235. PMIGDLLENUM Enum
  236. )
  237. {
  238. MIGRATIONDLL dll;
  239. LONG rc;
  240. if (!MigDllOpen (&dll, Enum->Properties->DllPath, GATHERMODE, FALSE, SOURCEOS_WINNT)) {
  241. return FALSE;
  242. }
  243. __try {
  244. rc = ERROR_SUCCESS;
  245. if (!MigDllInitializeSrc (
  246. &dll,
  247. Enum->Properties->WorkingDirectory,
  248. NativeSourcePaths[0],
  249. Enum->Properties->SourceMedia,
  250. NULL,
  251. 0
  252. )) {
  253. rc = GetLastError ();
  254. }
  255. if (rc != ERROR_SUCCESS) {
  256. return FALSE;
  257. }
  258. if (!MigDllGatherSystemSettings (
  259. &dll,
  260. g_MigDllAnswerFilePath,
  261. NULL,
  262. 0
  263. )) {
  264. rc = GetLastError ();
  265. }
  266. if (rc != ERROR_SUCCESS) {
  267. return FALSE;
  268. }
  269. }
  270. __finally {
  271. MigDllClose (&dll);
  272. }
  273. return TRUE;
  274. }
  275. BOOL
  276. ParseMigrateInf (
  277. PCWSTR MigInfPath
  278. )
  279. {
  280. PVOID migInf = NULL;
  281. LONG lineCount;
  282. LONG i;
  283. PCTSTR type;
  284. PHANDLED_DATA data;
  285. PCTSTR regKey;
  286. PCTSTR regValue;
  287. PCTSTR file;
  288. PCTSTR service;
  289. if (LoadInfFile (MigInfPath, FALSE, &migInf) != ERROR_SUCCESS) {
  290. return FALSE;
  291. }
  292. __try {
  293. //
  294. // Add any compatibility items to the list.
  295. //
  296. if( !CompatibilityData.Flink ) {
  297. InitializeListHead( &CompatibilityData );
  298. }
  299. GlobalCompFlags = COMPFLAG_STOPINSTALL;
  300. CompatibilityCount += ProcessCompatibilitySection (migInf, TEXT("ServicesToStopInstallation") );
  301. if (CompatibilityCount) {
  302. IncompatibilityStopsInstallation = TRUE;
  303. }
  304. GlobalCompFlags = 0;
  305. CompatibilityCount += ProcessCompatibilitySection (migInf, TEXT("ServicesToDisable") );
  306. //
  307. // Add Handled compatibility items to the list.
  308. //
  309. lineCount = InfGetSectionLineCount (migInf, TEXT("Handled"));
  310. if (lineCount && lineCount != -1) {
  311. for (i=0; i < lineCount; i++) {
  312. type = InfGetFieldByIndex (migInf, TEXT("Handled"), i, 0);
  313. if (!type) {
  314. continue;
  315. }
  316. if (!lstrcmpi (type, TEXT("Registry"))) {
  317. regKey = InfGetFieldByIndex (migInf, TEXT("Handled"), i, 1);
  318. regValue = InfGetFieldByIndex (migInf, TEXT("Handled"), i, 2);
  319. if (regKey && *regKey) {
  320. data = (PHANDLED_DATA) MALLOC (sizeof(HANDLED_DATA));
  321. if (data == NULL) {
  322. return FALSE;
  323. }
  324. ZeroMemory (data, sizeof (HANDLED_DATA));
  325. data->Type = HANDLED_REGISTRY;
  326. data->RegKey = regKey;
  327. data->RegValue = regValue;
  328. InsertTailList (&g_HandledData, &data->ListEntry);
  329. }
  330. }
  331. else if (!lstrcmpi (type, TEXT("File"))) {
  332. file = InfGetFieldByIndex (migInf, TEXT("Handled"), i, 1);
  333. if (file && *file) {
  334. data = (PHANDLED_DATA) MALLOC (sizeof(HANDLED_DATA));
  335. if (data == NULL) {
  336. return FALSE;
  337. }
  338. ZeroMemory (data, sizeof (HANDLED_DATA));
  339. data->Type = HANDLED_FILE;
  340. data->File = file;
  341. InsertTailList (&g_HandledData, &data->ListEntry);
  342. }
  343. }
  344. else if (!lstrcmpi (type, TEXT("Service"))) {
  345. service = InfGetFieldByIndex (migInf, TEXT("Handled"), i, 1);
  346. if (service && *service) {
  347. data = (PHANDLED_DATA) MALLOC (sizeof(HANDLED_DATA));
  348. if (data == NULL) {
  349. return FALSE;
  350. }
  351. ZeroMemory (data, sizeof (HANDLED_DATA));
  352. data->Type = HANDLED_SERVICE;
  353. data->Service = service;
  354. InsertTailList (&g_HandledData, &data->ListEntry);
  355. }
  356. }
  357. }
  358. }
  359. }
  360. __finally {
  361. UnloadInfFile (migInf);
  362. }
  363. return TRUE;
  364. }
  365. VOID
  366. SearchDirForMigDlls (
  367. PCTSTR SearchDir,
  368. PCTSTR BaseDir,
  369. DLLLIST List
  370. )
  371. {
  372. HANDLE findHandle;
  373. WIN32_FIND_DATA findData;
  374. MIGRATIONDLL dll;
  375. WCHAR path[MAX_PATH];
  376. PWSTR p;
  377. WCHAR searchPath[MAX_PATH];
  378. PMIGRATIONINFO migInfo;
  379. PMIGDLLPROPERTIES dllProps = NULL;
  380. WCHAR workingDir[MAX_PATH];
  381. lstrcpy (searchPath, SearchDir);
  382. ConcatenatePaths (searchPath, TEXT("*"), MAX_PATH);
  383. findHandle = FindFirstFile (searchPath, &findData);
  384. if (findHandle != INVALID_HANDLE_VALUE) {
  385. lstrcpy (path, SearchDir);
  386. p = _tcschr (path, 0);
  387. if (p) {
  388. do {
  389. if (!lstrcmpi (findData.cFileName, TEXT("migrate.dll"))) {
  390. *p = 0;
  391. ConcatenatePaths (path, findData.cFileName, MAX_PATH);
  392. if (!MigDllOpen (&dll, path, GATHERMODE, FALSE, SOURCEOS_WINNT)) {
  393. continue;
  394. }
  395. if (!MigDllQueryMigrationInfo (&dll, TEXT("c:\\"), &migInfo)) {
  396. MigDllClose (&dll);
  397. continue;
  398. }
  399. if (migInfo->SourceOs == OS_WINDOWS9X || migInfo->TargetOs != OS_WINDOWSWHISTLER) {
  400. continue;
  401. }
  402. //
  403. // Do we already have a version of this migration dll?
  404. //
  405. dllProps = MigDllFindDllInList (List, migInfo->StaticProductIdentifier);
  406. if (dllProps && dllProps->Info.DllVersion >= migInfo->DllVersion) {
  407. MigDllClose (&dll);
  408. continue;
  409. }
  410. else if (dllProps) {
  411. MigDllRemoveDllFromList (List, migInfo->StaticProductIdentifier);
  412. }
  413. //
  414. // Move dll locally.
  415. //
  416. wsprintf (workingDir, TEXT("%s\\mig%u"), BaseDir, g_MigDllIndex);
  417. g_MigDllIndex++;
  418. MigDllMoveDllLocally (&dll, workingDir);
  419. //
  420. // Add the dll to the list.
  421. //
  422. MigDllAddDllToList (List, &dll);
  423. MigDllClose (&dll);
  424. }
  425. else if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && *findData.cFileName != TEXT('.')) {
  426. *p = 0;
  427. ConcatenatePaths (path, findData.cFileName, MAX_PATH);
  428. SearchDirForMigDlls (path, BaseDir, List);
  429. }
  430. } while (FindNextFile (findHandle, &findData));
  431. }
  432. FindClose (findHandle);
  433. }
  434. }
  435. #endif // UNICODE
  436. #if defined(UNICODE) && defined(_X86_)
  437. BOOL
  438. LoadAndRunMigrationDlls (
  439. HWND hDlg
  440. )
  441. {
  442. HKEY regKey = NULL;
  443. DWORD index;
  444. DWORD nameSize;
  445. DWORD valueSize;
  446. DWORD type;
  447. TCHAR valueName[MAX_PATH];
  448. TCHAR value[MAX_PATH];
  449. TCHAR baseDir[MAX_PATH];
  450. TCHAR workingDir[MAX_PATH];
  451. PTSTR p;
  452. LONG rc;
  453. DLLLIST list = NULL;
  454. MIGRATIONDLL dll;
  455. PMIGDLLPROPERTIES dllProps = NULL;
  456. MIGDLLENUM e;
  457. PMIGRATIONINFO migInfo;
  458. TCHAR migInfPath[MAX_PATH];
  459. HANDLE migInf;
  460. TCHAR searchDir[MAX_PATH];
  461. TCHAR tempDir[MAX_PATH];
  462. *g_MigDllAnswerFilePath = 0;
  463. //
  464. // NT Upgrades only.
  465. //
  466. if (!ISNT() || !Upgrade) {
  467. return TRUE;
  468. }
  469. /*NTBUG9:394164
  470. //
  471. // Win2k > Upgrades only.
  472. //
  473. if (BuildNumber <= NT40) {
  474. return TRUE;
  475. }
  476. */
  477. __try {
  478. if (!MigDllInit ()) {
  479. return TRUE;
  480. }
  481. list = MigDllCreateList ();
  482. if (!list) {
  483. return TRUE;
  484. }
  485. InitializeListHead (&g_HandledData);
  486. MyGetWindowsDirectory (baseDir, MAX_PATH);
  487. ConcatenatePaths (baseDir, TEXT("Setup"), MAX_PATH);
  488. lstrcpy (g_MigDllAnswerFilePath, baseDir);
  489. lstrcpy (tempDir, baseDir);
  490. ConcatenatePaths (g_MigDllAnswerFilePath, TEXT("migdll.txt"), MAX_PATH);
  491. if(ActualParamFile[0]){
  492. CopyFile(ActualParamFile, g_MigDllAnswerFilePath, FALSE);
  493. }
  494. //
  495. // Scan registry for migration dlls and load them.
  496. //
  497. if (RegOpenKeyEx (
  498. HKEY_LOCAL_MACHINE,
  499. S_REGKEY_MIGRATION_DLLS_WINNT,
  500. 0,
  501. KEY_READ | KEY_WRITE,
  502. &regKey
  503. ) == ERROR_SUCCESS) {
  504. //
  505. // Enumerate Values.
  506. //
  507. index = 0;
  508. do {
  509. nameSize = MAX_PATH;
  510. valueSize = MAX_PATH * sizeof (TCHAR);
  511. rc = RegEnumValue (
  512. regKey,
  513. index,
  514. valueName,
  515. &nameSize,
  516. NULL,
  517. &type,
  518. (PBYTE) value,
  519. &valueSize
  520. );
  521. index++;
  522. if (rc == ERROR_MORE_DATA) {
  523. continue;
  524. }
  525. if (rc == ERROR_NO_MORE_ITEMS) {
  526. break;
  527. }
  528. if (rc != ERROR_SUCCESS) {
  529. return TRUE;
  530. }
  531. if (!MigDllOpen (&dll, value, GATHERMODE, FALSE, SOURCEOS_WINNT)) {
  532. continue;
  533. }
  534. if (!MigDllQueryMigrationInfo (&dll, tempDir, &migInfo)) {
  535. MigDllClose (&dll);
  536. continue;
  537. }
  538. if (migInfo->SourceOs == OS_WINDOWS9X || migInfo->TargetOs != OS_WINDOWSWHISTLER) {
  539. continue;
  540. }
  541. //
  542. // Do we already have a version of this migration dll?
  543. //
  544. dllProps = MigDllFindDllInList (list, migInfo->StaticProductIdentifier);
  545. if (dllProps && dllProps->Info.DllVersion >= migInfo->DllVersion) {
  546. MigDllClose (&dll);
  547. continue;
  548. }
  549. else {
  550. MigDllRemoveDllFromList (list, migInfo->StaticProductIdentifier);
  551. }
  552. //
  553. // Move dll locally.
  554. //
  555. wsprintf (workingDir, TEXT("%s\\mig%u"), baseDir, g_MigDllIndex);
  556. g_MigDllIndex++;
  557. MigDllMoveDllLocally (&dll, workingDir);
  558. //
  559. // Add the dll to the list.
  560. //
  561. MigDllAddDllToList (list, &dll);
  562. MigDllClose (&dll);
  563. } while (1);
  564. }
  565. //
  566. // Now, look for dlls shipped with the source.
  567. //
  568. GetModuleFileName (NULL, searchDir, MAX_PATH);
  569. p = _tcsrchr (searchDir, TEXT('\\'));
  570. if (p) {
  571. p++;
  572. lstrcpy (p, TEXT("WINNTMIG"));
  573. }
  574. SearchDirForMigDlls (searchDir, baseDir, list);
  575. //
  576. // All dlls are now in the list. Lets run them.
  577. //
  578. ConcatenatePaths (baseDir, TEXT("dlls.inf"), MAX_PATH);
  579. if (MigDllEnumFirst (&e, list)) {
  580. WritePrivateProfileString (
  581. TEXT("Version"),
  582. TEXT("Signature"),
  583. TEXT("\"$Windows NT$\""),
  584. baseDir
  585. );
  586. do {
  587. wsprintf (migInfPath, TEXT("%s\\migrate.inf"), e.Properties->WorkingDirectory);
  588. migInf = CreateFile (
  589. migInfPath,
  590. GENERIC_READ | GENERIC_WRITE,
  591. 0,
  592. NULL,
  593. CREATE_ALWAYS,
  594. FILE_ATTRIBUTE_NORMAL,
  595. NULL
  596. );
  597. if (migInf == INVALID_HANDLE_VALUE) {
  598. continue;
  599. }
  600. CloseHandle (migInf);
  601. WritePrivateProfileString (
  602. TEXT("Version"),
  603. TEXT("Signature"),
  604. TEXT("\"$Windows NT$\""),
  605. migInfPath
  606. );
  607. if (!CallMigDllEntryPoints (&e)) {
  608. MigDllRemoveDllInEnumFromList (list, &e);
  609. }
  610. else {
  611. ParseMigrateInf (migInfPath);
  612. WritePrivateProfileString (
  613. TEXT("DllsToLoad"),
  614. e.Properties->Info.StaticProductIdentifier,
  615. e.Properties->DllPath,
  616. baseDir
  617. );
  618. }
  619. } while (MigDllEnumNext (&e));
  620. WritePrivateProfileString (NULL, NULL, NULL, baseDir);
  621. //
  622. // Get rid of compatibility messages handled by migration dlls.
  623. //
  624. ResolveHandledIncompatibilities ();
  625. }
  626. }
  627. __finally {
  628. if (regKey) {
  629. RegCloseKey (regKey);
  630. }
  631. if (list) {
  632. MigDllFreeList (list);
  633. }
  634. }
  635. return TRUE;
  636. }
  637. #endif
  638. VOID
  639. CleanUpOldLocalSources(
  640. IN HWND hdlg
  641. )
  642. /*++
  643. Routine Description:
  644. Locate and delete old local source trees. All local fixed drives
  645. are scanned for \$win_nt$.~ls, and if present, delnoded.
  646. On x86, we also check the system partition for \$win_nt$.~bt
  647. and give it the same treatment.
  648. Arguments:
  649. Return Value:
  650. --*/
  651. {
  652. TCHAR Drive;
  653. TCHAR Text[250];
  654. TCHAR Filename[128];
  655. LoadString(hInst,IDS_INSPECTING,Text,sizeof(Text)/sizeof(TCHAR));
  656. SendMessage(hdlg,WMX_SETPROGRESSTEXT,0,(LPARAM)Text);
  657. for(Drive=TEXT('A'); Drive<=TEXT('Z'); Drive++) {
  658. if(MyGetDriveType(Drive) != DRIVE_FIXED) {
  659. continue;
  660. }
  661. Filename[0] = Drive;
  662. Filename[1] = TEXT(':');
  663. Filename[2] = 0;
  664. ConcatenatePaths(Filename,LOCAL_SOURCE_DIR,sizeof(Filename)/sizeof(TCHAR));
  665. if(FileExists(Filename, NULL)) {
  666. LoadString(hInst,IDS_REMOVING_OLD_TEMPFILES,Text,sizeof(Text)/sizeof(TCHAR));
  667. SendMessage(hdlg,WMX_SETPROGRESSTEXT,0,(LPARAM)Text);
  668. MyDelnode(Filename);
  669. LoadString(hInst,IDS_INSPECTING,Text,sizeof(Text)/sizeof(TCHAR));
  670. SendMessage(hdlg,WMX_SETPROGRESSTEXT,0,(LPARAM)Text);
  671. }
  672. }
  673. if (!IsArc()) {
  674. #ifdef _X86_
  675. MYASSERT (SystemPartitionDriveLetter);
  676. Filename[0] = SystemPartitionDriveLetter;
  677. Filename[1] = TEXT(':');
  678. Filename[2] = TEXT('\\');
  679. lstrcpy(Filename+3,LOCAL_BOOT_DIR);
  680. LoadString(hInst,IDS_REMOVING_OLD_TEMPFILES,Text,sizeof(Text)/sizeof(TCHAR));
  681. SendMessage(hdlg,WMX_SETPROGRESSTEXT,0,(LPARAM)Text);
  682. MyDelnode(Filename);
  683. //
  684. // Clean up backup directory, if it exists.
  685. //
  686. if(IsNEC98() && Floppyless) {
  687. Filename[0] = SystemPartitionDriveLetter;
  688. Filename[1] = TEXT(':');
  689. Filename[2] = TEXT('\\');
  690. lstrcpy(Filename+3,LOCAL_BACKUP_DIR);
  691. MyDelnode(Filename);
  692. }
  693. #endif // _X86_
  694. } // if (!IsArc())
  695. }
  696. BOOL
  697. InspectSources(
  698. HWND ParentWnd
  699. )
  700. /*++
  701. Routine Description:
  702. Check all sources given to ensure that they contain a valid
  703. windows NT distribution. We do this simply by looking for
  704. DOSNET.INF on each source.
  705. Arguments:
  706. ParentWnd - Specifies the handle of the parent window for any
  707. error messages.
  708. Return Value:
  709. None.
  710. --*/
  711. {
  712. UINT i,j;
  713. TCHAR Filename[MAX_PATH];
  714. TCHAR Text[512];
  715. UINT OriginalCount;
  716. HCURSOR OldCursor;
  717. BOOL b = TRUE;
  718. OldCursor = SetCursor (LoadCursor (NULL, IDC_WAIT));
  719. OriginalCount = SourceCount;
  720. //
  721. // if we have a good alternate path then there
  722. // is no need to verify the source paths
  723. //
  724. if (AlternateSourcePath[0]) {
  725. lstrcpy(Filename,AlternateSourcePath);
  726. ConcatenatePaths(Filename,InfName,MAX_PATH);
  727. if(FileExists (Filename, NULL)) {
  728. SetCursor (OldCursor);
  729. return TRUE;
  730. }
  731. }
  732. //
  733. // verify each path
  734. //
  735. for (i=0; i<SourceCount; ) {
  736. lstrcpy(Filename,NativeSourcePaths[i]);
  737. ConcatenatePaths(Filename,InfName,MAX_PATH);
  738. if(!FileExists (Filename, NULL)) {
  739. //
  740. // Source doesn't exist or isn't valid.
  741. // Adjust the list.
  742. //
  743. for(j=i+1; j<SourceCount; j++) {
  744. lstrcpy(NativeSourcePaths[j-1],NativeSourcePaths[j]);
  745. lstrcpy(SourcePaths[j-1],SourcePaths[j]);
  746. }
  747. SourceCount--;
  748. } else {
  749. i++;
  750. }
  751. }
  752. if (!SourceCount) {
  753. //
  754. // No sources are valid.
  755. //
  756. MessageBoxFromMessage(
  757. ParentWnd,
  758. (OriginalCount == 1) ? MSG_INVALID_SOURCE : MSG_INVALID_SOURCES,
  759. FALSE,
  760. AppTitleStringId,
  761. MB_OK | MB_ICONWARNING | MB_TASKMODAL,
  762. NativeSourcePaths[0]
  763. );
  764. //
  765. // Set it to look like one source that is the empty string,
  766. // so logic elsewhere will work correctly without special casing.
  767. //
  768. SourceCount = 1;
  769. NativeSourcePaths[0][0] = 0;
  770. SourcePaths[0][0] = 0;
  771. b = FALSE;
  772. }
  773. SetCursor (OldCursor);
  774. return b;
  775. }
  776. BOOL
  777. LoadInfs(
  778. IN HWND hdlg
  779. )
  780. /*++
  781. Routine Description:
  782. Load dosnet.inf from source 0. If upgrading and we're running
  783. on NT then also load txtsetup.sif. If running on NT, load ntcompat.inf
  784. Arguments:
  785. hdlg - supplies handle of dialog to which progress messages
  786. should be directed.
  787. Return Value:
  788. Boolean value indicating outcome. If FALSE then the user
  789. will have been informed.
  790. --*/
  791. {
  792. BOOL b;
  793. LPCTSTR p;
  794. TCHAR szPath[MAX_PATH];
  795. if (!MainInf) {
  796. b = LoadInfWorker(hdlg,InfName,&MainInf, TRUE);
  797. if(!b) {
  798. MessageBoxFromMessage(
  799. NULL,
  800. MSG_INVALID_INF_FILE,
  801. FALSE,
  802. AppTitleStringId,
  803. MB_OK | MB_ICONINFORMATION | MB_TASKMODAL,
  804. InfName
  805. );
  806. DebugLog( Winnt32LogError, TEXT("ERROR: Could not load dosnet.inf!"), 0);
  807. goto c0;
  808. }
  809. } else {
  810. b = TRUE;
  811. }
  812. if(p = InfGetFieldByKey(MainInf,TEXT("Miscellaneous"),TEXT("ProductType"),0)) {
  813. ProductFlavor = _tcstoul(p,NULL,10);
  814. Server = (ProductFlavor != PROFESSIONAL_PRODUCTTYPE && ProductFlavor != PERSONAL_PRODUCTTYPE);
  815. UpgradeProductType = Server ? NT_SERVER : NT_WORKSTATION;
  816. if( CheckUpgradeOnly ) {
  817. AppTitleStringId = IDS_APPTITLE_CHECKUPGRADE;
  818. } else if( ProductFlavor == PROFESSIONAL_PRODUCTTYPE ) {
  819. AppTitleStringId = IDS_APPTITLE_WKS;
  820. } else if( ProductFlavor == SERVER_PRODUCTTYPE ) {
  821. AppTitleStringId = IDS_APPTITLE_SRV;
  822. } else if( ProductFlavor == ADVANCEDSERVER_PRODUCTTYPE ) {
  823. AppTitleStringId = IDS_APPTITLE_ASRV;
  824. } else if( ProductFlavor == DATACENTER_PRODUCTTYPE ) {
  825. AppTitleStringId = IDS_APPTITLE_DAT;
  826. } else if( ProductFlavor == BLADESERVER_PRODUCTTYPE ) {
  827. AppTitleStringId = IDS_APPTITLE_BLADE;
  828. }
  829. // AppTitleStringId = Server ? IDS_APPTITLE_SRV : IDS_APPTITLE_WKS;
  830. FixUpWizardTitle(GetParent(hdlg));
  831. PropSheet_SetTitle(GetParent(hdlg),0,UIntToPtr( AppTitleStringId ));
  832. }
  833. if(Upgrade && ISNT()) {
  834. //
  835. // If upgrading NT, pull in txtsetup.sif.
  836. //
  837. b = LoadInfWorker(hdlg,TEXTMODE_INF,&TxtsetupSif, FALSE);
  838. if(!b) {
  839. MessageBoxFromMessage(
  840. NULL,
  841. MSG_INVALID_INF_FILE,
  842. FALSE,
  843. AppTitleStringId,
  844. MB_OK | MB_ICONINFORMATION | MB_TASKMODAL,
  845. TEXTMODE_INF
  846. );
  847. TxtsetupSif = NULL;
  848. DebugLog( Winnt32LogError, TEXT("ERROR: Could not load txtsetup.sif!"), 0);
  849. goto c1;
  850. }
  851. }
  852. if( ISNT()) {
  853. b = FindPathToWinnt32File(NTCOMPAT_INF, szPath, MAX_PATH);
  854. if(!b) {
  855. NtcompatInf = NULL;
  856. DebugLog( Winnt32LogError, TEXT("ERROR: Could not find ntcompat.inf!"), 0);
  857. goto c2;
  858. }
  859. if(LoadInfFile( szPath,TRUE, &NtcompatInf) != NO_ERROR) {
  860. MessageBoxFromMessage(
  861. NULL,
  862. MSG_INVALID_INF_FILE,
  863. FALSE,
  864. AppTitleStringId,
  865. MB_OK | MB_ICONINFORMATION | MB_TASKMODAL,
  866. szPath
  867. );
  868. b = FALSE;
  869. NtcompatInf = NULL;
  870. DebugLog( Winnt32LogError, TEXT("ERROR: Could not load ntcompat.inf!"), 0);
  871. goto c2;
  872. }
  873. DebugLog (Winnt32LogInformation, TEXT("NTCOMPAT: Using %1"), 0, szPath);
  874. }
  875. return(b);
  876. c2:
  877. if( TxtsetupSif) {
  878. UnloadInfFile(TxtsetupSif);
  879. TxtsetupSif = NULL;
  880. }
  881. c1:
  882. UnloadInfFile(MainInf);
  883. MainInf = NULL;
  884. c0:
  885. return(b);
  886. }
  887. BOOL
  888. BuildCopyList(
  889. IN HWND hdlg
  890. )
  891. {
  892. TCHAR Text[256];
  893. LoadString(hInst,IDS_BUILDING_COPY_LIST,Text,sizeof(Text)/sizeof(TCHAR));
  894. SendMessage(hdlg,WMX_SETPROGRESSTEXT,0,(LPARAM)Text);
  895. SaveLanguageDirs();
  896. return(BuildCopyListWorker(hdlg));
  897. }
  898. BOOL
  899. FindLocalSourceAndCheckSpace(
  900. IN HWND hdlg,
  901. IN BOOL QuickTest,
  902. IN LONGLONG AdditionalPadding
  903. )
  904. {
  905. TCHAR Text[256];
  906. if (!QuickTest) {
  907. LoadString(hInst,IDS_CHECKING_SPACE,Text,sizeof(Text)/sizeof(TCHAR));
  908. SendMessage(hdlg,WMX_SETPROGRESSTEXT,0,(LPARAM)Text);
  909. }
  910. return FindLocalSourceAndCheckSpaceWorker(hdlg, QuickTest, AdditionalPadding);
  911. }
  912. BOOL
  913. EnoughMemory(
  914. IN HWND hdlg,
  915. IN BOOL QuickTest
  916. )
  917. {
  918. LPCTSTR p;
  919. MEMORYSTATUS MemoryStatus;
  920. DWORD RequiredMemory;
  921. SIZE_T RequiredMB, AvailableMB;
  922. TCHAR buffer[64];
  923. UpgRequiredMb = 0;
  924. UpgAvailableMb = 0;
  925. //
  926. // Load the minimum memory requirements from the inf
  927. //
  928. if(GetMainInfValue (TEXT("Miscellaneous"),TEXT("MinimumMemory"), 0, buffer, 64)) {
  929. RequiredMemory = _tcstoul(buffer,NULL,10);
  930. //
  931. // Got it. Now figure out how much we've got.
  932. //
  933. GlobalMemoryStatus( &MemoryStatus );
  934. //
  935. // Convert to MB, rounding up to nearest 4MB boundary...
  936. //
  937. RequiredMB = ((RequiredMemory + ((4*1024*1024)-1)) >> 22) << 2;
  938. AvailableMB = ((MemoryStatus.dwTotalPhys + ((4*1024*1024)-1)) >> 22) << 2;
  939. //
  940. // Allow for UMA machine which may reservce 8MB for video
  941. //
  942. if( AvailableMB < (RequiredMB-8) ) {
  943. if (!QuickTest) {
  944. UpgRequiredMb = (DWORD)RequiredMB;
  945. UpgAvailableMb = (DWORD)AvailableMB;
  946. //
  947. // Fail.
  948. //
  949. DebugLog( Winnt32LogInformation,
  950. NULL,
  951. MSG_NOT_ENOUGH_MEMORY,
  952. AvailableMB,
  953. RequiredMB );
  954. SendMessage(hdlg,WMX_ERRORMESSAGEUP,TRUE,0);
  955. MessageBoxFromMessage(
  956. hdlg,
  957. MSG_NOT_ENOUGH_MEMORY,
  958. FALSE,
  959. AppTitleStringId,
  960. MB_OK | MB_ICONWARNING,
  961. AvailableMB,
  962. RequiredMB );
  963. SendMessage(hdlg,WMX_ERRORMESSAGEUP,FALSE,0);
  964. }
  965. return( FALSE );
  966. } else {
  967. if (!QuickTest) {
  968. TCHAR Buffer[MAX_PATH];
  969. _stprintf( Buffer, TEXT("Detected %dMB of RAM.\n"), AvailableMB );
  970. DebugLog( Winnt32LogInformation,
  971. Buffer,
  972. 0 );
  973. }
  974. }
  975. }
  976. return( TRUE );
  977. }
  978. BOOL
  979. LoadInfWorker(
  980. IN HWND hdlg,
  981. IN LPCTSTR FilenamePart,
  982. OUT PVOID *InfHandle,
  983. IN BOOL Winnt32File
  984. )
  985. {
  986. DWORD d;
  987. UINT u;
  988. UINT Id;
  989. TCHAR infPath[MAX_PATH];
  990. TCHAR FormatString[128];
  991. TCHAR Text[MAX_PATH+128];
  992. BOOL b;
  993. LoadString(hInst,IDS_LOADINGINF,Text,sizeof(Text)/sizeof(TCHAR));
  994. SendMessage(hdlg,WMX_SETPROGRESSTEXT,0,(LPARAM)Text);
  995. //
  996. // use standard searching algorithm to get to the right INF
  997. //
  998. if (Winnt32File) {
  999. b = FindPathToWinnt32File (FilenamePart, infPath, MAX_PATH);
  1000. } else {
  1001. b = FindPathToInstallationFile (FilenamePart, infPath, MAX_PATH);
  1002. }
  1003. if (b) {
  1004. d = LoadInfFile(infPath,TRUE,InfHandle);
  1005. if (d == NO_ERROR) {
  1006. return TRUE;
  1007. }
  1008. } else {
  1009. d = ERROR_FILE_NOT_FOUND;
  1010. }
  1011. switch(d) {
  1012. case NO_ERROR:
  1013. Id = 0;
  1014. break;
  1015. case ERROR_NOT_ENOUGH_MEMORY:
  1016. Id = MSG_OUT_OF_MEMORY;
  1017. break;
  1018. case ERROR_READ_FAULT:
  1019. //
  1020. // I/O error.
  1021. //
  1022. Id = MSG_CANT_LOAD_INF_IO;
  1023. break;
  1024. case ERROR_INVALID_DATA:
  1025. Id = MSG_CANT_LOAD_INF_SYNTAXERR;
  1026. break;
  1027. default:
  1028. Id = MSG_CANT_LOAD_INF_GENERIC;
  1029. break;
  1030. }
  1031. if(Id) {
  1032. SendMessage(hdlg,WMX_ERRORMESSAGEUP,TRUE,0);
  1033. MessageBoxFromMessage(
  1034. hdlg,
  1035. Id,
  1036. FALSE,
  1037. AppTitleStringId,
  1038. MB_OK | MB_ICONERROR | MB_TASKMODAL,
  1039. infPath
  1040. );
  1041. SendMessage(hdlg,WMX_ERRORMESSAGEUP,FALSE,0);
  1042. return(FALSE);
  1043. }
  1044. return(TRUE);
  1045. }
  1046. BOOL
  1047. WriteFileToLog(
  1048. const PTCHAR pszFileMetaName,
  1049. const PTCHAR pszActualFileName
  1050. )
  1051. {
  1052. HANDLE hActualFile = INVALID_HANDLE_VALUE;
  1053. BOOL fResult = FALSE;
  1054. DWORD cbBootIniSize, cbReadBootIniSize;
  1055. PUCHAR pszBuffer = NULL;
  1056. PTCHAR pszActualBuffer = NULL;
  1057. //
  1058. // Open the boot.ini file, get its size, convert it to the proper
  1059. // string type internally, and then log it out.
  1060. //
  1061. hActualFile = CreateFile(
  1062. pszActualFileName,
  1063. GENERIC_READ,
  1064. FILE_SHARE_READ,
  1065. NULL,
  1066. OPEN_EXISTING,
  1067. 0,
  1068. NULL);
  1069. if ( hActualFile == INVALID_HANDLE_VALUE )
  1070. goto Exit;
  1071. cbBootIniSize = GetFileSize( hActualFile, NULL );
  1072. //
  1073. // Buffer we'll be reading the boot.ini into
  1074. //
  1075. if ((pszBuffer = MALLOC(cbBootIniSize)) == NULL) {
  1076. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1077. goto Exit;
  1078. }
  1079. if ( !ReadFile( hActualFile, pszBuffer, cbBootIniSize, &cbReadBootIniSize, NULL ) )
  1080. goto Exit;
  1081. //
  1082. // Ensure that we read as much as we really wanted.
  1083. //
  1084. if ( cbBootIniSize != cbReadBootIniSize ) {
  1085. DebugLog( Winnt32LogError,
  1086. TEXT("Error: %1 unable to be read entirely.\n"),
  1087. 0,
  1088. pszFileMetaName);
  1089. goto Exit;
  1090. }
  1091. #ifdef UNICODE
  1092. pszActualBuffer = MALLOC( (cbBootIniSize + 3) * sizeof(TCHAR) );
  1093. MultiByteToWideChar(
  1094. CP_ACP,
  1095. 0,
  1096. pszBuffer,
  1097. cbBootIniSize,
  1098. pszActualBuffer,
  1099. cbBootIniSize );
  1100. #else
  1101. pszActualBuffer = pszBuffer;
  1102. #endif
  1103. pszActualBuffer[cbBootIniSize] = 0;
  1104. //
  1105. // And write it out
  1106. //
  1107. DebugLog(
  1108. Winnt32LogInformation,
  1109. TEXT("%1 ----\n%2\n---- (from %3)\n"),
  1110. 0,
  1111. pszFileMetaName,
  1112. pszActualBuffer,
  1113. pszActualFileName);
  1114. fResult = TRUE;
  1115. SetLastError(ERROR_SUCCESS);
  1116. Exit:
  1117. if ( hActualFile != INVALID_HANDLE_VALUE )
  1118. {
  1119. CloseHandle( hActualFile );
  1120. hActualFile = INVALID_HANDLE_VALUE;
  1121. }
  1122. #ifdef UNICODE
  1123. if ( pszActualBuffer != NULL )
  1124. #else
  1125. if ( ( pszActualBuffer != pszBuffer ) && ( pszActualBuffer != NULL ) )
  1126. #endif
  1127. {
  1128. FREE(pszActualBuffer);
  1129. pszActualBuffer = NULL;
  1130. }
  1131. if ( pszBuffer != NULL ) {
  1132. FREE(pszBuffer);
  1133. pszBuffer = NULL;
  1134. }
  1135. return fResult;
  1136. }
  1137. BOOL
  1138. InspectFilesystems(
  1139. IN HWND hdlg
  1140. )
  1141. {
  1142. TCHAR DriveRoot[4];
  1143. BOOL b;
  1144. TCHAR VolumeName[MAX_PATH];
  1145. DWORD SerialNumber;
  1146. DWORD MaxComponent;
  1147. BOOL Bogus[26];
  1148. TCHAR Filesystem[100];
  1149. TCHAR Drive;
  1150. DWORD Flags;
  1151. int i;
  1152. DriveRoot[1] = TEXT(':');
  1153. DriveRoot[2] = TEXT('\\');
  1154. DriveRoot[3] = 0;
  1155. ZeroMemory(Bogus,sizeof(Bogus));
  1156. for(Drive=TEXT('A'); Drive<=TEXT('Z'); Drive++) {
  1157. if(MyGetDriveType(Drive) != DRIVE_FIXED) {
  1158. continue;
  1159. }
  1160. DriveRoot[0] = Drive;
  1161. b = GetVolumeInformation(
  1162. DriveRoot,
  1163. VolumeName,MAX_PATH,
  1164. &SerialNumber,
  1165. &MaxComponent,
  1166. &Flags,
  1167. Filesystem,
  1168. sizeof(Filesystem)/sizeof(TCHAR)
  1169. );
  1170. if(b) {
  1171. //
  1172. // On NT, we want to warn about HPFS.
  1173. // On Win9x, we want to warn about doublespace/drivespace.
  1174. //
  1175. if(ISNT()) {
  1176. if(!lstrcmpi(Filesystem,TEXT("HPFS"))) {
  1177. Bogus[Drive-TEXT('A')] = TRUE;
  1178. }
  1179. } else {
  1180. if(Flags & FS_VOL_IS_COMPRESSED) {
  1181. Bogus[Drive-TEXT('A')] = TRUE;
  1182. }
  1183. }
  1184. }
  1185. }
  1186. #ifdef _X86_
  1187. if(ISNT()) {
  1188. TCHAR BootIniName[16];
  1189. DWORD dwAttributes;
  1190. //
  1191. // Disallow HPFS system partition. If someone figured out how
  1192. // to get an HPFS system partition on an ARC machine, more power
  1193. // to 'em.
  1194. //
  1195. MYASSERT (SystemPartitionDriveLetter);
  1196. if(SystemPartitionDriveLetter && Bogus[SystemPartitionDriveLetter-TEXT('A')]) {
  1197. MessageBoxFromMessage(
  1198. hdlg,
  1199. MSG_SYSPART_IS_HPFS,
  1200. FALSE,
  1201. AppTitleStringId,
  1202. MB_OK | MB_ICONERROR | MB_TASKMODAL,
  1203. SystemPartitionDriveLetter
  1204. );
  1205. return(FALSE);
  1206. }
  1207. /*
  1208. If we're upgrading NT, then log the existing boot.ini to the
  1209. logfiles for this pass. However, if that failed, then there
  1210. was something wrong - a missing boot.ini during an upgrade
  1211. is really a bad thing that should be snipped in the bud before
  1212. we go much further and copy files down, change system state,
  1213. etc.
  1214. */
  1215. #ifdef PRERELEASE
  1216. if (Upgrade)
  1217. {
  1218. _stprintf(BootIniName, TEXT("%c:\\BOOT.INI"), SystemPartitionDriveLetter);
  1219. if ( !WriteFileToLog( TEXT("Boot configuration file while inspecting filesystems"), BootIniName ) )
  1220. {
  1221. MessageBoxFromMessage(
  1222. hdlg,
  1223. MSG_UPGRADE_INSPECTION_MISSING_BOOT_INI,
  1224. FALSE,
  1225. AppTitleStringId,
  1226. MB_OK | MB_ICONERROR | MB_TASKMODAL,
  1227. BootIniName );
  1228. return FALSE;
  1229. }
  1230. }
  1231. #endif
  1232. }
  1233. #endif
  1234. //
  1235. // User cannot upgrade a system on an HPFS/DriveSpace drive
  1236. //
  1237. MyGetWindowsDirectory(VolumeName,MAX_PATH);
  1238. if(Upgrade && Bogus[VolumeName[0]-TEXT('A')]) {
  1239. MessageBoxFromMessage(
  1240. hdlg,
  1241. ISNT() ? MSG_SYSTEM_ON_HPFS : MSG_SYSTEM_ON_CVF,
  1242. FALSE,
  1243. AppTitleStringId,
  1244. MB_OK | MB_ICONERROR | MB_TASKMODAL
  1245. );
  1246. return(FALSE);
  1247. }
  1248. //
  1249. // General case, HPFS data partition/compressed drive.
  1250. //
  1251. for(b=FALSE,Drive=0; !b && (Drive<26); Drive++) {
  1252. if(Bogus[Drive]) {
  1253. b = TRUE;
  1254. }
  1255. }
  1256. if(b) {
  1257. i = MessageBoxFromMessage(
  1258. hdlg,
  1259. ISNT() ? MSG_HPFS_DRIVES_EXIST : MSG_CVFS_EXIST,
  1260. FALSE,
  1261. AppTitleStringId,
  1262. MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL
  1263. );
  1264. if(i == IDNO) {
  1265. return(FALSE);
  1266. }
  1267. }
  1268. return(TRUE);
  1269. }