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.

2201 lines
67 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. Spntupg.c
  5. Abstract:
  6. initializing and maintaining list of nts to upgrade
  7. Author:
  8. Sunil Pai (sunilp) 10-Nov-1993
  9. Revision History:
  10. --*/
  11. #include "spprecmp.h"
  12. #pragma hdrstop
  13. //
  14. // Major/minor version numbers of the system we're upgrading *from*
  15. // if upgrading.
  16. //
  17. ULONG OldMajorVersion,OldMinorVersion;
  18. //**************************************************************
  19. // S E L E C T I N G N T T O U P G R A D E S T U F F
  20. //**************************************************************
  21. #define MENU_LEFT_X 3
  22. #define MENU_WIDTH (VideoVars.ScreenWidth-(2*MENU_LEFT_X))
  23. #define MENU_INDENT 4
  24. VOID
  25. pSpStepUpValidate(
  26. VOID //IN BOOLEAN Server
  27. );
  28. BOOLEAN
  29. SpGetStepUpMode(
  30. IN PWSTR PidExtraData,
  31. BOOLEAN *StepUpMode
  32. );
  33. BOOLEAN
  34. pSpGetCurrentInstallVariation(
  35. IN PWSTR szPid20,
  36. OUT LPDWORD CurrentInstallVariation
  37. );
  38. VOID
  39. SpGetUpgDriveLetter(
  40. IN WCHAR DriveLetter,
  41. IN PWCHAR Buffer,
  42. IN ULONG BufferSize,
  43. IN BOOL AddColon
  44. );
  45. VOID
  46. SpCantFindBuildToUpgrade(
  47. VOID
  48. );
  49. #ifdef _X86_
  50. BOOLEAN
  51. SpIsWin9xMsdosSys(
  52. IN PDISK_REGION Region,
  53. OUT PSTR* Win9xPath
  54. );
  55. #endif
  56. VOID
  57. SpGetFileVersion(
  58. IN PVOID ImageBase,
  59. OUT PULONGLONG Version
  60. );
  61. ENUMUPGRADETYPE
  62. SpFindNtToUpgrade(
  63. IN PVOID SifHandle,
  64. OUT PDISK_REGION *TargetRegion,
  65. OUT PWSTR *TargetPath,
  66. OUT PDISK_REGION *SystemPartitionRegion,
  67. OUT PWSTR *SystemPartitionDirectory
  68. )
  69. /*++
  70. Routine Description:
  71. This goes through the list of NTs on the system and finds out which are
  72. upgradeable. Presents the information to the user and selects if he
  73. wishes to upgrade an installed NT / install a fresh NT into the same
  74. directory / select a different location for Windows NT.
  75. If the chosen target is too full user is offered to exit setup to create
  76. space/ choose new target.
  77. Arguments:
  78. SifHandle: Handle the txtsetup.sif
  79. TargetRegion: Variable to receive the partition of the Windows NT to install
  80. NULL if not chosen. Caller should not free.
  81. TargetPath: Variable to receive the target path of Windows NT. NULL if
  82. not decided. Caller can free.
  83. SystemPartitionRegion:
  84. Variable to receive the system partition of the Windows NT
  85. NULL if not chosen. Caller should not free.
  86. Return Value:
  87. UpgradeFull: If user chooses to upgrade an NT
  88. UpgradeInstallFresh: If user chooses to install fresh into an existing NT
  89. tree.
  90. DontUpgrade: If user chooses to cancel upgrade and choose a fresh
  91. tree for installation
  92. --*/
  93. {
  94. ENUMUPGRADETYPE UpgradeType;
  95. UPG_PROGRESS_TYPE UpgradeProgressValue;
  96. NTSTATUS NtStatus;
  97. ULONG i,j;
  98. ULONG UpgradeBootSets;
  99. ULONG PidIndex;
  100. PSP_BOOT_ENTRY BootEntry;
  101. PSP_BOOT_ENTRY ChosenBootEntry;
  102. PSP_BOOT_ENTRY MatchedSet = NULL;
  103. ULONG UpgradeOnlyBootSets;
  104. PVOID p;
  105. PWSTR Pid;
  106. ULONG TotalSizeOfFilesOnOsWinnt = 0;
  107. PWSTR UniqueIdFromSif;
  108. PWSTR UniqueIdFromReg;
  109. BOOLEAN Compliant;
  110. BOOLEAN WindowsUpgrade;
  111. BOOLEAN ComplianceChecked;
  112. PWSTR EulaComplete;
  113. DWORD Version = 0, BuildNumber = 0;
  114. DetermineSourceVersionInfo(&Version, &BuildNumber);
  115. //
  116. // If we know we're upgrading NT (chosen during winnt32) then fetch the
  117. // unique id from the parameters file. This will be used later to
  118. // find the system to be upgraded.
  119. //
  120. UniqueIdFromSif = NULL;
  121. p = SpGetSectionKeyIndex(WinntSifHandle,SIF_DATA,WINNT_D_NTUPGRADE_W,0);
  122. if(p && !_wcsicmp(p,WINNT_A_YES_W)) {
  123. UniqueIdFromSif = SpGetSectionKeyIndex(WinntSifHandle,SIF_DATA,SIF_UNIQUEID,0);
  124. if(!UniqueIdFromSif) {
  125. SpFatalSifError(WinntSifHandle,SIF_DATA,SIF_UNIQUEID,0,0);
  126. }
  127. }
  128. //
  129. // Go through all boot sets, looking for upgradeable ones.
  130. //
  131. SpDetermineUniqueAndPresentBootEntries();
  132. UpgradeBootSets = 0;
  133. UpgradeOnlyBootSets = 0;
  134. PidIndex = 0;
  135. for(BootEntry = SpBootEntries; BootEntry != NULL; BootEntry = BootEntry->Next) {
  136. //
  137. // The set's upgradeable flag might already be 0, such as it if was
  138. // a duplicate entry in boot.ini/nv-ram.
  139. // After we've checked for this reset the upgradeable flag for this
  140. // boot set to FALSE in preparation for validating upgreadeability below.
  141. //
  142. if (!BootEntry->Processable) {
  143. continue;
  144. }
  145. BootEntry->Processable = FALSE;
  146. Pid = NULL;
  147. BootEntry->LangId = -1;
  148. //
  149. // Determine various things about the build identified by the
  150. // current boot set (product type -- srv, wks, etc; version and
  151. // build numbers, upgrade progress value, unique id winnt32 put
  152. // in there if any, etc).
  153. //
  154. // Based on the information, we will update the UpgradeableList and
  155. // initialize FailedUpgradeList.
  156. //
  157. NtStatus = SpDetermineProduct(
  158. BootEntry->OsPartitionDiskRegion,
  159. BootEntry->OsDirectory,
  160. &BootEntry->ProductType,
  161. &BootEntry->MajorVersion,
  162. &BootEntry->MinorVersion,
  163. &BootEntry->BuildNumber,
  164. &BootEntry->ProductSuiteMask,
  165. &UpgradeProgressValue,
  166. &UniqueIdFromReg,
  167. &Pid,
  168. NULL, // ignore eval variation flag
  169. &BootEntry->LangId,
  170. &BootEntry->ServicePack
  171. );
  172. if(!NT_SUCCESS(NtStatus)) {
  173. continue;
  174. }
  175. //
  176. // Determine if this installation matches the one we're supposed
  177. // to upgrade (the one the user ran winnt32 on). If this is
  178. // a winnt32 based installation, there is no need to do a
  179. // compliance test as this was already completed during winnt32.
  180. //
  181. if(UniqueIdFromReg) {
  182. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: SpFindNtToUpgrade: BootEntry = %p, RegId = %S, UniqueId = %S\n", BootEntry, UniqueIdFromReg, UniqueIdFromSif));
  183. if(UniqueIdFromSif && (MatchedSet == NULL)
  184. && !wcscmp(UniqueIdFromSif,UniqueIdFromReg)) {
  185. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: SpFindNtToUpgrade: found a match!\n"));
  186. MatchedSet = BootEntry;
  187. BootEntry->Processable = TRUE;
  188. }
  189. SpMemFree(UniqueIdFromReg);
  190. UniqueIdFromReg = NULL;
  191. }
  192. if (BootEntry->Processable == FALSE) {
  193. //
  194. // this is set to TRUE if this is the build we ran winnt32 upgrade
  195. // from -- in all other cases we need to do a compliance test
  196. // to determine if this is a valid build to upgrade
  197. //
  198. Compliant = pSpIsCompliant( Version,
  199. BuildNumber,
  200. BootEntry->OsPartitionDiskRegion,
  201. BootEntry->OsDirectory,
  202. &BootEntry->UpgradeOnlyCompliance );
  203. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: SpFindNtToUpgrade says UpgradeableList[%p] compliance test is %s, upgrade only : %s\n",
  204. BootEntry,
  205. Compliant ? "TRUE" : "FALSE" ,
  206. BootEntry->UpgradeOnlyCompliance ? "TRUE" : "FALSE"
  207. ));
  208. BootEntry->Processable = Compliant;
  209. if (BootEntry->UpgradeOnlyCompliance) {
  210. UpgradeOnlyBootSets++;
  211. }
  212. }
  213. if(BootEntry->Processable) {
  214. UpgradeBootSets++;
  215. //
  216. // Save the Pid only if it is Pid20
  217. //
  218. if(wcslen(Pid) == 20) {
  219. BootEntry->Pid20Array = Pid;
  220. } else {
  221. SpMemFree(Pid);
  222. }
  223. } else {
  224. SpMemFree(Pid);
  225. }
  226. BootEntry->FailedUpgrade = (UpgradeProgressValue == UpgradeInProgress);
  227. }
  228. //
  229. // Winnt32 displays the EULA which signifies that compliance checking has been
  230. // completed
  231. //
  232. EulaComplete = SpGetSectionKeyIndex(WinntSifHandle, SIF_DATA,WINNT_D_EULADONE_W, 0);
  233. if(EulaComplete && SpStringToLong(EulaComplete, NULL, 10)) {
  234. ComplianceChecked = TRUE;
  235. } else {
  236. ComplianceChecked = FALSE;
  237. }
  238. //
  239. // don't try to validate if we are upgrading a Win3.X or Win9X installation
  240. //
  241. #ifdef _X86_
  242. WindowsUpgrade = SpIsWindowsUpgrade(WinntSifHandle);
  243. #else
  244. WindowsUpgrade = FALSE;
  245. #endif // _X86_
  246. //
  247. // In step-up mode, we need to ensure that the user has a qualifiying product.
  248. //
  249. //
  250. // If we couldn't find it on the machine, go perform additional validation
  251. // steps.
  252. //
  253. if(StepUpMode && !UpgradeBootSets && !WindowsUpgrade && !ComplianceChecked) {
  254. pSpStepUpValidate();
  255. }
  256. //
  257. // If we are supposed to be upgrading NT then make sure we found
  258. // the system we're supposed to upgrade.
  259. //
  260. if(UniqueIdFromSif) {
  261. if(MatchedSet == NULL) {
  262. SpCantFindBuildToUpgrade();
  263. }
  264. ChosenBootEntry = MatchedSet;
  265. UpgradeType = UpgradeFull;
  266. OldMajorVersion = ChosenBootEntry->MajorVersion;
  267. OldMinorVersion = ChosenBootEntry->MinorVersion;
  268. #if !defined(_AMD64_) && !defined(_X86_)
  269. //
  270. // On non-x86 platforms, especially alpha machines that in general
  271. // have small system partitions (~3 MB), we compute the size
  272. // of the files on \os\winnt (ie osloader.exe and hal.dll),
  273. // and consider this size as available disk space. We can do this
  274. // since these files will be overwritten by the new ones.
  275. // This fixes the problem that we see on Alpha, when the system
  276. // partition is too full.
  277. //
  278. SpFindSizeOfFilesInOsWinnt(
  279. SifHandle,
  280. ChosenBootEntry->LoaderPartitionDiskRegion,
  281. &TotalSizeOfFilesOnOsWinnt
  282. );
  283. //
  284. // Transform the size into KB
  285. //
  286. TotalSizeOfFilesOnOsWinnt /= 1024;
  287. #endif // !defined(_AMD64_) && !defined(_X86_)
  288. //
  289. // If a previous upgrade attempt on this build failed
  290. // (say the power went out in the middle) then we will try to
  291. // upgrade it again. We can't offer to install a fresh build
  292. // because we're not sure we can reliably complete it
  293. // (for example winnt32.exe might copy down only a subset of files
  294. // across the net when it knows the user ios upgrading and so
  295. // initial install could fail because of missing files, etc).
  296. //
  297. // If the disk is too full then the user is hosed. Tell him and exit.
  298. //
  299. if(ChosenBootEntry->FailedUpgrade) {
  300. SppResumingFailedUpgrade(
  301. ChosenBootEntry->OsPartitionDiskRegion,
  302. ChosenBootEntry->OsDirectory,
  303. ChosenBootEntry->FriendlyName,
  304. FALSE
  305. );
  306. }
  307. } else {
  308. //
  309. // Not upgrading. However for PSS we allow the user to upgrade a build
  310. // "in place" as a sort of emergency repair thing. The build has to be
  311. // the same build number as the one we're installing.
  312. //
  313. UpgradeType = DontUpgrade;
  314. //
  315. // Also, if the user is upgrading Windows 95 or we're in unattended mode
  316. // then we don't ask the user anything.
  317. //
  318. p = SpGetSectionKeyIndex(WinntSifHandle,SIF_DATA,WINNT_D_WIN95UPGRADE_W,0);
  319. if(!UnattendedOperation && (!p || _wcsicmp(p,WINNT_A_YES_W))) {
  320. //
  321. // Eliminate from the upgradeable list those builds which
  322. // don't match.
  323. //
  324. j = 0;
  325. for(BootEntry = SpBootEntries; BootEntry != NULL; BootEntry = BootEntry->Next) {
  326. if(BootEntry->Processable) {
  327. if (!SpDoBuildsMatch(
  328. SifHandle,
  329. BootEntry->BuildNumber,
  330. BootEntry->ProductType,
  331. BootEntry->ProductSuiteMask,
  332. AdvancedServer,
  333. SuiteType,
  334. BootEntry->LangId)) {
  335. BootEntry->Processable = FALSE;
  336. j++;
  337. }
  338. }
  339. }
  340. UpgradeBootSets -= j;
  341. if(UpgradeBootSets) {
  342. //
  343. // Find out if the user wants to "upgrade" one of these.
  344. //
  345. UpgradeType = SppSelectNTToRepairByUpgrade(
  346. &ChosenBootEntry
  347. );
  348. #if !defined(_AMD64_) && !defined(_X86_)
  349. SpFindSizeOfFilesInOsWinnt(
  350. SifHandle,
  351. ChosenBootEntry->LoaderPartitionDiskRegion,
  352. &TotalSizeOfFilesOnOsWinnt
  353. );
  354. TotalSizeOfFilesOnOsWinnt /= 1024;
  355. #endif // !defined(_AMD64_) && !defined(_X86_)
  356. if(UpgradeType == UpgradeFull) {
  357. //
  358. // Check for resume case and inform user.
  359. //
  360. if(ChosenBootEntry->FailedUpgrade) {
  361. //
  362. // If user cancelled then lets try to do a
  363. // clean install
  364. //
  365. if (!SppResumingFailedUpgrade(
  366. ChosenBootEntry->OsPartitionDiskRegion,
  367. ChosenBootEntry->OsDirectory,
  368. ChosenBootEntry->FriendlyName,
  369. TRUE
  370. )) {
  371. UpgradeType = DontUpgrade;
  372. }
  373. } else {
  374. //
  375. // Everything is OK.
  376. //
  377. OldMajorVersion = ChosenBootEntry->MajorVersion;
  378. OldMinorVersion = ChosenBootEntry->MinorVersion;
  379. }
  380. }
  381. }
  382. }
  383. }
  384. //
  385. // Depending on upgrade selection made do the setup needed before
  386. // we do the upgrade
  387. //
  388. if(UpgradeType == UpgradeFull) {
  389. PWSTR p1,p2,p3;
  390. //
  391. // Set the upgrade status to upgrading in the current system hive
  392. //
  393. SpSetUpgradeStatus(
  394. ChosenBootEntry->OsPartitionDiskRegion,
  395. ChosenBootEntry->OsDirectory,
  396. UpgradeInProgress
  397. );
  398. //
  399. // Return the region we are installing onto
  400. //
  401. *TargetRegion = ChosenBootEntry->OsPartitionDiskRegion;
  402. *TargetPath = SpDupStringW(ChosenBootEntry->OsDirectory);
  403. *SystemPartitionRegion = ChosenBootEntry->LoaderPartitionDiskRegion;
  404. StandardServerUpgrade = ( AdvancedServer &&
  405. ( ChosenBootEntry->ProductType == NtProductWinNt ) ||
  406. ( ChosenBootEntry->ProductType == NtProductServer )
  407. );
  408. //
  409. // Process the osloader variable to extract the system partition path.
  410. // The var could be of the form ...partition(1)\os\nt\... or
  411. // ...partition(1)os\nt\...
  412. // So we search forward for the first \ and then backwards for
  413. // the closest ) to find the start of the directory. We then
  414. // search backwards in the resulting string for the last \ to find
  415. // the end of the directory.
  416. //
  417. p1 = ChosenBootEntry->LoaderFile;
  418. p2 = wcsrchr(p1, L'\\');
  419. if (p2 == NULL) {
  420. p2 = p1;
  421. }
  422. i = (ULONG)(p2 - p1);
  423. if(i == 0) {
  424. *SystemPartitionDirectory = SpDupStringW(L"");
  425. } else {
  426. p2 = p3 = SpMemAlloc((i+2)*sizeof(WCHAR));
  427. ASSERT(p3);
  428. if(*p1 != L'\\') {
  429. *p3++ = L'\\';
  430. }
  431. wcsncpy(p3, p1, i);
  432. p3[i] = 0;
  433. *SystemPartitionDirectory = p2;
  434. }
  435. }
  436. //
  437. // Clean up and return,
  438. //
  439. CLEAR_CLIENT_SCREEN();
  440. return(UpgradeType);
  441. }
  442. BOOLEAN
  443. pSpGetCdInstallType(
  444. IN PWSTR PathToCd,
  445. OUT PULONG CdInstallType,
  446. OUT PULONG CdInstallVersion
  447. )
  448. {
  449. #define BuildMatch(_filename_,_type_,_ver_) \
  450. FileName = _filename_; \
  451. b = SpNFilesExist(PathToCd,&FileName,1,FALSE); \
  452. if (b) { \
  453. *CdInstallType = _type_; \
  454. *CdInstallVersion = _ver_; \
  455. } \
  456. //return(TRUE); \
  457. BOOLEAN b;
  458. //
  459. // Directories that are present on all known NT CD-ROM's.
  460. //
  461. //
  462. // ISSUE:2000/27/07:vijayj: this code seems really busted. In looking at a handful of cd's, none
  463. // of the nt cd's seem to conform to these rules listed
  464. // also looks like there might be "per architecture" tag files as well.
  465. //
  466. //Check for both dirs to exist? Definitely nt4 has these. Some pre RTM w2k cds have them
  467. PWSTR ListAllPreNT5[] = { L"alpha", L"i386" };
  468. //wk2 RTM , whistler and nt4 have thse two dirs. They differ by tag file.
  469. PWSTR ListAllNT5[] = { L"i386", L"support" };
  470. PWSTR ListAllNec98[] = { L"pc98",L"support" }; //NEC98
  471. PWSTR ListAllEntNT4[] = { L"alpha", L"i386", L"SP3" };
  472. //
  473. // Directories which must be present if a CD is a 3.51 or a 4.0 CD-ROM,
  474. // workstation or server. Note that the ppc directory distinguishes
  475. // 3.51 from 3.5.
  476. //
  477. PWSTR List351_40[] = { L"mips", L"ppc" };
  478. //
  479. // directories which must be present if a CD is a win95 or win98 cd-rom.
  480. //
  481. PWSTR ListWin95[] = { L"win95", L"drivers" };
  482. PWSTR ListWin98[] = { L"win98", L"drivers" };
  483. PWSTR ListWinME[] = { L"win9x", L"drivers" };
  484. PWSTR FileName;
  485. //
  486. // check for NT4 enterprise
  487. //
  488. b = SpNFilesExist(
  489. PathToCd,
  490. ListAllEntNT4,
  491. sizeof(ListAllEntNT4)/sizeof(ListAllEntNT4[0]),
  492. TRUE
  493. );
  494. if (b) {
  495. BuildMatch(L"cdrom_s.40", COMPLIANCE_INSTALLTYPE_NTSE, 400);
  496. if (b) {
  497. return(TRUE);
  498. }
  499. }
  500. //
  501. // check for various subsets of NT < NT5
  502. //
  503. b = SpNFilesExist(
  504. PathToCd,
  505. (!IsNEC_98) ? ListAllPreNT5 : ListAllNec98, //NEC98
  506. (!IsNEC_98) ? sizeof(ListAllPreNT5)/sizeof(ListAllPreNT5[0]) : sizeof(ListAllNec98)/sizeof(ListAllNec98[0]), //NEC98
  507. TRUE
  508. );
  509. if(b) {
  510. //
  511. // hydra (terminal server) is a special case (since it does not
  512. // have mips and ppc directory).
  513. //
  514. BuildMatch(L"cdrom_ts.40", COMPLIANCE_INSTALLTYPE_NTS, 400);
  515. if (b) {
  516. return TRUE;
  517. }
  518. //
  519. // OK, it could be an NT CD of some kind, but it could be
  520. // 3.1, 3.5, 3.51, 4.0. It could also be
  521. // server or workstation. Narrow down to 3.51/4.0.
  522. //
  523. b = SpNFilesExist(PathToCd,List351_40,
  524. sizeof(List351_40)/sizeof(List351_40[0]),TRUE);
  525. if(b) {
  526. //
  527. // If we get here, we know it can only be either 3.51 or 4.0.
  528. // Look for 3.51.
  529. //
  530. BuildMatch(L"cdrom.s", COMPLIANCE_INSTALLTYPE_NTS, 351);
  531. if (b) {
  532. return(TRUE);
  533. }
  534. BuildMatch(L"cdrom.w", COMPLIANCE_INSTALLTYPE_NTW, 351);
  535. if (b) {
  536. return(TRUE);
  537. }
  538. //
  539. // Look for 4.0.
  540. //
  541. BuildMatch(L"cdrom_s.40", COMPLIANCE_INSTALLTYPE_NTS, 400);
  542. if (b) {
  543. return(TRUE);
  544. }
  545. BuildMatch(L"cdrom_w.40", COMPLIANCE_INSTALLTYPE_NTW, 400);
  546. if (b) {
  547. return(TRUE);
  548. }
  549. } else {
  550. //
  551. // Find out if its one of the NT 4.0 service pack CDs
  552. //
  553. BuildMatch(L"cdrom_s.40", COMPLIANCE_INSTALLTYPE_NTS, 400);
  554. if (b) {
  555. return(TRUE);
  556. }
  557. BuildMatch(L"cdrom_w.40", COMPLIANCE_INSTALLTYPE_NTW, 400);
  558. if (b) {
  559. return(TRUE);
  560. }
  561. //
  562. // Not 3.51 or 4.0. Check for 5.0 beta 1 and beta2
  563. //
  564. //How is this possible to be 5.0 unless alpha dir exists on cd.
  565. //
  566. // Post beta 1 the tag files changed to support per architecture tags
  567. // but beta 2 still has alpha directories
  568. //
  569. // We could possibly just check to see if cdrom_w.50 isn't
  570. // there, but the NT3.1 CD would then pass so we need to
  571. // check explicitly for the 5.0 beta CDs.
  572. //
  573. BuildMatch(L"cdrom_s.5b1", COMPLIANCE_INSTALLTYPE_NTS, 500);
  574. if (b) {
  575. return(FALSE); //eval
  576. }
  577. BuildMatch(L"cdrom_w.5b1", COMPLIANCE_INSTALLTYPE_NTW, 500);
  578. if (b) {
  579. return(FALSE); //eval
  580. }
  581. BuildMatch(L"cdrom_s.5b2", COMPLIANCE_INSTALLTYPE_NTS, 500);
  582. if (b) {
  583. return(FALSE); //eval
  584. }
  585. BuildMatch(L"cdrom_w.5b2", COMPLIANCE_INSTALLTYPE_NTW, 500);
  586. if (b) {
  587. return(FALSE); //eval
  588. }
  589. BuildMatch(L"cdrom_s.5b3", COMPLIANCE_INSTALLTYPE_NTS, 500);
  590. if (b) {
  591. return(FALSE); //eval
  592. }
  593. BuildMatch(L"cdrom_w.5b3", COMPLIANCE_INSTALLTYPE_NTW, 500);
  594. if (b) {
  595. return(FALSE); //eval
  596. }
  597. BuildMatch(L"cdrom_is.5b2", COMPLIANCE_INSTALLTYPE_NTS, 500);
  598. if (b) {
  599. return(FALSE); //eval
  600. }
  601. BuildMatch(L"cdrom_iw.5b2", COMPLIANCE_INSTALLTYPE_NTW, 500);
  602. if (b) {
  603. return(FALSE); //eval
  604. }
  605. BuildMatch(L"cdrom_ie.5b2", COMPLIANCE_INSTALLTYPE_NTSE, 500);
  606. if (b) {
  607. return(FALSE); //eval
  608. }
  609. //Do we need to check for eval nt5.1 here? No since alpha dir doesnt exist on the cds.
  610. //
  611. // if we made it this far, it must be nt 3.1/3.5
  612. //
  613. // we just mark the version as 3.5 since we don't allow upgradescd o
  614. // from either type of install.
  615. //
  616. *CdInstallType = COMPLIANCE_INSTALLTYPE_NTW;
  617. *CdInstallVersion = 350;
  618. return(TRUE);
  619. }
  620. }
  621. //
  622. // look for various nt5 beta cds.
  623. // // Could also be nt5.1 since cd also contains same dir.
  624. //
  625. // note that we don't check 5.0 retail since that would allow the retail CD to
  626. // validate itself, which defeats the purpose entirely.
  627. //
  628. // Post NT5 beta 1 the tag files changed to support per architecture tags so we have
  629. // a massive ifdef below
  630. //
  631. //
  632. b = SpNFilesExist(
  633. PathToCd,
  634. ListAllNT5,
  635. sizeof(ListAllNT5)/sizeof(ListAllNT5[0]),
  636. TRUE
  637. );
  638. if (b) {
  639. //
  640. // we might have some flavour of NT5 beta cd, but we're not sure which one
  641. //
  642. BuildMatch(L"cdrom_s.5b1", COMPLIANCE_INSTALLTYPE_NTS, 500);
  643. if (b) {
  644. return(FALSE); //eval
  645. }
  646. BuildMatch(L"cdrom_w.5b1", COMPLIANCE_INSTALLTYPE_NTW, 500);
  647. if (b) {
  648. return(FALSE); //eval
  649. }
  650. BuildMatch(L"cdrom_is.5b2", COMPLIANCE_INSTALLTYPE_NTS, 500);
  651. if (b) {
  652. return(FALSE); //eval
  653. }
  654. BuildMatch(L"cdrom_iw.5b2", COMPLIANCE_INSTALLTYPE_NTW, 500);
  655. if (b) {
  656. return(FALSE); //eval
  657. }
  658. BuildMatch(L"cdrom_ie.5b2", COMPLIANCE_INSTALLTYPE_NTSE, 500);
  659. if (b) {
  660. return(FALSE); //eval
  661. }
  662. BuildMatch(L"cdrom_is.5b3", COMPLIANCE_INSTALLTYPE_NTS, 500);
  663. if (b) {
  664. return(FALSE); //eval
  665. }
  666. BuildMatch(L"cdrom_iw.5b3", COMPLIANCE_INSTALLTYPE_NTW, 500);
  667. if (b) {
  668. return(FALSE); //eval
  669. }
  670. BuildMatch(L"cdrom_ie.5b3", COMPLIANCE_INSTALLTYPE_NTSE, 500);
  671. if (b) {
  672. return(FALSE); //eval
  673. }
  674. BuildMatch(L"cdrom_nt.51", COMPLIANCE_INSTALLTYPE_NTW, 501);
  675. if (b) {
  676. return(FALSE); //pre beta1 whistler
  677. }
  678. BuildMatch(L"wen51.b1", COMPLIANCE_INSTALLTYPE_NTW, 501);
  679. if (b) {
  680. return(FALSE); //beta 1 whistler
  681. }
  682. BuildMatch(L"win51.b2", COMPLIANCE_INSTALLTYPE_NTW, 501);
  683. if (b) {
  684. return(FALSE); //beta 1 whistler
  685. }
  686. BuildMatch(L"win51.rc1", COMPLIANCE_INSTALLTYPE_NTW, 501);
  687. if (b) {
  688. return(FALSE); //rc1 whistler
  689. }
  690. }
  691. //
  692. // check for win95
  693. //
  694. b = SpNFilesExist(PathToCd, ListWin95, sizeof(ListWin95)/sizeof(ListWin95[0]),TRUE );
  695. if (b) {
  696. *CdInstallType = COMPLIANCE_INSTALLTYPE_WIN9X;
  697. *CdInstallVersion = 950;
  698. return TRUE;
  699. }
  700. //
  701. // check for win98
  702. //
  703. b = SpNFilesExist(PathToCd, ListWin98, sizeof(ListWin98)/sizeof(ListWin98[0]),TRUE );
  704. if (b) {
  705. *CdInstallType = COMPLIANCE_INSTALLTYPE_WIN9X;
  706. *CdInstallVersion = 1998;
  707. return TRUE;
  708. }
  709. //
  710. // check for winME
  711. //
  712. b = SpNFilesExist(PathToCd, ListWinME, sizeof(ListWinME)/sizeof(ListWinME[0]),TRUE );
  713. if (b) {
  714. *CdInstallType = COMPLIANCE_INSTALLTYPE_WIN9X;
  715. *CdInstallVersion = 3000;
  716. return TRUE;
  717. }
  718. //At this point we have rejected w2k beta cds. However we need to reject wk2 eval cds.
  719. //We should accept w2k stepup media so the next check is only for 5.1
  720. //Need to accept nt5.1 eval cds.!!Ask rajj to verify.
  721. // Need to reject nt5.1 step-up cds.
  722. // Need to reject nt5.1 rtm cds? Looks like we accept RTM FPP?
  723. //
  724. // could be NT 5.1 CD-ROM (make sure its not eval media)
  725. //
  726. if (!b) { //check is not needed.
  727. NTSTATUS Status;
  728. CCMEDIA MediaObj;
  729. WCHAR InfDir[MAX_PATH];
  730. wcscpy(InfDir, PathToCd);
  731. SpConcatenatePaths(InfDir, (IsNEC_98 ? ListAllNec98[0] : ListAllNT5[0]));
  732. Status = SpGetMediaDetails(InfDir, &MediaObj);
  733. if (NT_SUCCESS(Status)) {
  734. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "Type=%lx, Variation=%lx, Version=%lx, Build=%lx, SetupMedia=%s\n",
  735. MediaObj.SourceType, MediaObj.SourceVariation, MediaObj.Version,
  736. MediaObj.BuildNumber,
  737. (MediaObj.StepUpMedia ? L"True" : L"False")));
  738. if( (MediaObj.Version == 500) &&
  739. (MediaObj.SourceVariation != COMPLIANCE_INSTALLVAR_EVAL) &&
  740. (MediaObj.BuildNumber == 2195)) {
  741. *CdInstallType = MediaObj.SourceType;
  742. *CdInstallVersion = MediaObj.Version;
  743. return TRUE;
  744. }
  745. // At this point we should be current media 5.1
  746. if( MediaObj.Version == 501 ) {
  747. if( MediaObj.SourceVariation != COMPLIANCE_INSTALLVAR_EVAL) {
  748. if( MediaObj.StepUpMedia == FALSE) {
  749. *CdInstallType = MediaObj.SourceType;
  750. *CdInstallVersion = MediaObj.Version;
  751. return TRUE;
  752. } else {
  753. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "pSpGetCdInstallType: SpGetMediaDetails succeeded but STEPUP media"
  754. " cannot be used for validation\n", Status));
  755. }
  756. } else {
  757. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "pSpGetCdInstallType: SpGetMediaDetails succeeded but Eval media\n",
  758. Status));
  759. }
  760. } else {
  761. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "pSpGetCdInstallType: SpGetMediaDetails succeeded but unrecognized version\n",
  762. Status));
  763. }
  764. } else {
  765. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "pSpGetCdInstallType: SpGetMediaDetails failed with %lx error code\n",
  766. Status));
  767. }
  768. }
  769. //
  770. // not any system CD that we know about
  771. //
  772. return(FALSE);
  773. }
  774. VOID
  775. pSpStepUpValidate(
  776. VOID
  777. )
  778. {
  779. ULONG CdCount;
  780. ULONG i;
  781. BOOLEAN b;
  782. ULONG Prompt,SecondaryPrompt;
  783. ULONG ValidKeys[3] = { ASCI_CR, KEY_F3, 0 };
  784. LARGE_INTEGER DelayTime;
  785. PWSTR FileName;
  786. ULONG SourceSkuId;
  787. ULONG DontCare;
  788. ULONG CdInstallType;
  789. ULONG CdInstallVersion;
  790. //
  791. // Directories that are present on all known NT CD-ROM's.
  792. //
  793. PWSTR ListAll[] = { L"alpha", L"i386" };
  794. PWSTR ListAllNec98[] = { L"pc98",L"support" }; //NEC98
  795. //
  796. // Directories which must be present if a CD is a 3.51 or a 4.0 CD-ROM,
  797. // workstation or server. Note that the ppc directory distinguishes
  798. // 3.51 from 3.5.
  799. //
  800. PWSTR List351_40[] = { L"mips", L"ppc" };
  801. PWSTR ListWin95[] = { L"win95", L"autorun" };
  802. PWSTR ListWin98[] = { L"win98", L"autorun" };
  803. SourceSkuId = DetermineSourceProduct(&DontCare,NULL);
  804. Prompt = SP_SCRN_STEP_UP_NO_QUALIFY;
  805. switch (SourceSkuId) {
  806. case COMPLIANCE_SKU_NTW32U:
  807. SecondaryPrompt = SP_SCRN_STEP_UP_PROMPT_WKS;
  808. break;
  809. case COMPLIANCE_SKU_NTSU:
  810. SecondaryPrompt = SP_SCRN_STEP_UP_PROMPT_SRV;
  811. break;
  812. case COMPLIANCE_SKU_NTSEU:
  813. SecondaryPrompt = SP_SCRN_STEP_UP_PROMPT_ENT;
  814. break;
  815. default:
  816. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "setup: Unexpected SKU %x, defaulting to workstation\n", SourceSkuId));
  817. SecondaryPrompt = SP_SCRN_STEP_UP_PROMPT_WKS;
  818. break;
  819. }
  820. #if 0
  821. //
  822. // ntw upgrade is a special case because you have either win95 or an old NTW to
  823. // upgrade from
  824. //
  825. // might have to prompt for floppies
  826. //
  827. if (SourceSkuId == COMPLIANCE_SKU_NTWU) {
  828. }
  829. //
  830. // See if there is a CD-ROM drive. If not we can't continue.
  831. //
  832. else
  833. #endif
  834. if(CdCount = IoGetConfigurationInformation()->CdRomCount) {
  835. while(1) {
  836. //
  837. // Tell the user what's going on. This screen also contains
  838. // a prompt to insert a qualifying CD-ROM.
  839. //
  840. while(1) {
  841. SpStartScreen(Prompt,3,HEADER_HEIGHT+1,FALSE,FALSE,DEFAULT_ATTRIBUTE);
  842. SpContinueScreen(
  843. SecondaryPrompt,
  844. 3,
  845. 1,
  846. FALSE,
  847. DEFAULT_ATTRIBUTE
  848. );
  849. SpContinueScreen(SP_SCRN_STEP_UP_INSTRUCTIONS,3,1,FALSE,DEFAULT_ATTRIBUTE);
  850. SpDisplayStatusOptions(
  851. DEFAULT_STATUS_ATTRIBUTE,
  852. SP_STAT_ENTER_EQUALS_CONTINUE,
  853. SP_STAT_F3_EQUALS_EXIT,
  854. 0
  855. );
  856. if(SpWaitValidKey(ValidKeys,NULL,NULL) == KEY_F3) {
  857. SpConfirmExit();
  858. } else {
  859. break;
  860. }
  861. }
  862. CLEAR_CLIENT_SCREEN();
  863. SpDisplayStatusText(SP_STAT_PLEASE_WAIT,DEFAULT_STATUS_ATTRIBUTE);
  864. //
  865. // Wait 5 sec for the CD to become ready
  866. //
  867. DelayTime.HighPart = -1;
  868. DelayTime.LowPart = (ULONG)(-50000000);
  869. KeDelayExecutionThread(KernelMode,FALSE,&DelayTime);
  870. //
  871. // Check for relevent files/dirs on each CD-ROM drive.
  872. //
  873. for(i=0; i<CdCount; i++) {
  874. swprintf(TemporaryBuffer,L"\\Device\\Cdrom%u",i);
  875. if (pSpGetCdInstallType(TemporaryBuffer, &CdInstallType, &CdInstallVersion) ) {
  876. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "cd type : %x cd version : %d\n", CdInstallType, CdInstallVersion ));
  877. switch (SourceSkuId) {
  878. case COMPLIANCE_SKU_NTWPU:
  879. case COMPLIANCE_SKU_NTW32U:
  880. if ( (CdInstallType == COMPLIANCE_INSTALLTYPE_WIN9X) ||
  881. ( ((CdInstallType == COMPLIANCE_INSTALLTYPE_NTW) ||
  882. (CdInstallType == COMPLIANCE_INSTALLTYPE_NTWP)) &&
  883. (CdInstallVersion > 350)) ) {
  884. return;
  885. }
  886. break;
  887. case COMPLIANCE_SKU_NTSU:
  888. if ( (CdInstallType == COMPLIANCE_INSTALLTYPE_NTS) &&
  889. (CdInstallVersion > 350) ) {
  890. return;
  891. }
  892. break;
  893. case COMPLIANCE_SKU_NTSEU:
  894. if (CdInstallType == COMPLIANCE_INSTALLTYPE_NTSE) {
  895. return;
  896. }
  897. break;
  898. default:
  899. return;
  900. }
  901. }
  902. }
  903. Prompt = SP_SCRN_STEP_UP_BAD_CD;
  904. }
  905. }
  906. SpStartScreen(
  907. SP_SCRN_STEP_UP_FATAL,
  908. 3,
  909. HEADER_HEIGHT+1,
  910. FALSE,
  911. FALSE,
  912. DEFAULT_ATTRIBUTE
  913. );
  914. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,SP_STAT_F3_EQUALS_EXIT,0);
  915. SpInputDrain();
  916. while(SpInputGetKeypress() != KEY_F3);
  917. SpDone(0,FALSE,FALSE);
  918. }
  919. BOOLEAN
  920. SppResumingFailedUpgrade(
  921. IN PDISK_REGION Region,
  922. IN LPCWSTR OsLoadFileName,
  923. IN LPCWSTR LoadIdentifier,
  924. IN BOOLEAN AllowCancel
  925. )
  926. /*++
  927. Routine Description:
  928. Simple routine to inform the user that setup noticed that the build
  929. chosen for upgrade had been upgraded before, but the upgrade attempt
  930. failed. The user can continue or exit. If he continues the build will be
  931. upgraded (again).
  932. Arguments:
  933. Region - supplies region containing the build being upgraded
  934. OsLoadFileName - supplies ARC OSLOADFILENAME var for the build (ie, sysroot)
  935. LoadIdentifier - supplies ARC LOADIDENTIFIER for the build (ie, human-
  936. readable description).
  937. AllowCancel - Indicates whether user can cancel out of this or not
  938. Return Value:
  939. TRUE, if the user wants to continue and attempt to upgrade again else
  940. FALSE.
  941. --*/
  942. {
  943. ULONG ValidKeys[] = { KEY_F3, ASCI_CR, 0, 0 };
  944. ULONG c;
  945. DRIVELTR_STRING UpgDriveLetter;
  946. ULONG MsgId;
  947. ULONG EscStatusId;
  948. BOOLEAN AllowUpgrade = TRUE;
  949. ASSERT(Region->PartitionedSpace);
  950. ASSERT(wcslen(OsLoadFileName) >= 2);
  951. SpGetUpgDriveLetter(Region->DriveLetter,
  952. UpgDriveLetter,
  953. sizeof(UpgDriveLetter),
  954. FALSE);
  955. if (AllowCancel) {
  956. ValidKeys[2] = ASCI_ESC;
  957. MsgId = SP_SCRN_WINNT_FAILED_UPGRADE_ESC;
  958. EscStatusId = SP_STAT_ESC_EQUALS_CLEAN_INSTALL;
  959. } else {
  960. MsgId = SP_SCRN_WINNT_FAILED_UPGRADE;
  961. EscStatusId = 0;
  962. }
  963. do {
  964. SpStartScreen(
  965. MsgId,
  966. 3,
  967. HEADER_HEIGHT+1,
  968. FALSE,
  969. FALSE,
  970. DEFAULT_ATTRIBUTE,
  971. UpgDriveLetter,
  972. OsLoadFileName,
  973. LoadIdentifier
  974. );
  975. SpDisplayStatusOptions(
  976. DEFAULT_STATUS_ATTRIBUTE,
  977. SP_STAT_F3_EQUALS_EXIT,
  978. SP_STAT_ENTER_EQUALS_UPGRADE,
  979. EscStatusId,
  980. 0
  981. );
  982. c = SpWaitValidKey(ValidKeys, NULL, NULL);
  983. switch (c) {
  984. case KEY_F3:
  985. SpConfirmExit();
  986. break;
  987. case ASCI_ESC:
  988. AllowUpgrade = FALSE;
  989. break;
  990. default:
  991. break;
  992. }
  993. } while (c == KEY_F3);
  994. return AllowUpgrade;
  995. }
  996. #define MAX_INT_STRING 30
  997. VOID
  998. SppUpgradeDiskFull(
  999. IN PDISK_REGION OsRegion,
  1000. IN LPCWSTR OsLoadFileName,
  1001. IN LPCWSTR LoadIdentifier,
  1002. IN PDISK_REGION SysPartRegion,
  1003. IN ULONG MinOsFree,
  1004. IN ULONG MinSysFree,
  1005. IN BOOLEAN Fatal
  1006. )
  1007. /*++
  1008. Routine Description:
  1009. Inform the user that the nt tree chosen for upgrade can't be upgraded
  1010. because the partition is too full.
  1011. Arguments:
  1012. OsRegion - supplies region containing the nt tree.
  1013. OsLoadFileName - supplies ARC OSLOADFILENAME var for the build (ie, sysroot)
  1014. LoadIdentifier - supplies ARC LOADIDENTIFIER for the build (ie, human-
  1015. readable description).
  1016. SysPartRegion - supplies the region that is the ARC system partition
  1017. for the build being upgraded
  1018. MinOsFree - supplies the size in KB of the minimum amount of free space
  1019. we require before attempting upgrade
  1020. MinSysFree - supplies the size in KB of the minimum amount of free space
  1021. we require on the system partition before attempting upgrade.
  1022. Fatal - if TRUE then the only option is exit. If FALSE then this routine
  1023. can return to its caller.
  1024. Return Value:
  1025. None. MAY NOT RETURN, depending on Fatal.
  1026. --*/
  1027. {
  1028. ULONG ValidKeys[] = { KEY_F3,0,0 };
  1029. PWCHAR Drive1, Drive2;
  1030. DRIVELTR_STRING OsRgnDrive, OsRgnDriveFull, SysRgnDriveFull;
  1031. WCHAR Drive1Free[MAX_INT_STRING], Drive1FreeNeeded[MAX_INT_STRING];
  1032. WCHAR Drive2Free[MAX_INT_STRING], Drive2FreeNeeded[MAX_INT_STRING];
  1033. BOOLEAN FirstDefined = FALSE, SecondDefined = FALSE;
  1034. ASSERT(OsRegion->PartitionedSpace);
  1035. ASSERT(SysPartRegion->PartitionedSpace);
  1036. ASSERT(wcslen(OsLoadFileName) >= 2);
  1037. SpGetUpgDriveLetter(OsRegion->DriveLetter,OsRgnDrive,sizeof(OsRgnDrive),FALSE);
  1038. if((OsRegion == SysPartRegion) || (OsRegion->FreeSpaceKB < MinOsFree)) {
  1039. //
  1040. // Then we'll be needing the full (colon added) version of
  1041. // the drive letter
  1042. //
  1043. SpGetUpgDriveLetter(OsRegion->DriveLetter,OsRgnDriveFull,sizeof(OsRgnDrive),TRUE);
  1044. }
  1045. if(OsRegion == SysPartRegion) {
  1046. Drive1 = OsRgnDriveFull;
  1047. swprintf(Drive1Free,L"%d",OsRegion->FreeSpaceKB);
  1048. swprintf(Drive1FreeNeeded,L"%d",MinOsFree);
  1049. FirstDefined = TRUE;
  1050. } else {
  1051. if(SysPartRegion->FreeSpaceKB < MinSysFree) {
  1052. SpGetUpgDriveLetter(SysPartRegion->DriveLetter,SysRgnDriveFull,sizeof(SysRgnDriveFull),TRUE);
  1053. Drive1 = SysRgnDriveFull;
  1054. swprintf(Drive1Free,L"%d",SysPartRegion->FreeSpaceKB);
  1055. swprintf(Drive1FreeNeeded,L"%d",MinSysFree);
  1056. FirstDefined = TRUE;
  1057. }
  1058. if(OsRegion->FreeSpaceKB < MinOsFree) {
  1059. if(!FirstDefined) {
  1060. Drive1 = OsRgnDriveFull;
  1061. swprintf(Drive1Free,L"%d",OsRegion->FreeSpaceKB);
  1062. swprintf(Drive1FreeNeeded,L"%d",MinOsFree);
  1063. FirstDefined = TRUE;
  1064. } else {
  1065. Drive2 = OsRgnDriveFull;
  1066. swprintf(Drive2Free,L"%d",OsRegion->FreeSpaceKB);
  1067. swprintf(Drive2FreeNeeded,L"%d",MinOsFree);
  1068. SecondDefined = TRUE;
  1069. }
  1070. }
  1071. }
  1072. if(!Fatal) {
  1073. ValidKeys[1] = ASCI_CR;
  1074. }
  1075. while(1) {
  1076. SpStartScreen(
  1077. Fatal ? SP_SCRN_WINNT_DRIVE_FULL_FATAL : SP_SCRN_WINNT_DRIVE_FULL,
  1078. 3,
  1079. HEADER_HEIGHT+1,
  1080. FALSE,
  1081. FALSE,
  1082. DEFAULT_ATTRIBUTE,
  1083. OsRgnDrive,
  1084. OsLoadFileName,
  1085. LoadIdentifier,
  1086. FirstDefined ? Drive1 : L"",
  1087. FirstDefined ? Drive1FreeNeeded : L"",
  1088. FirstDefined ? Drive1Free : L"",
  1089. SecondDefined ? Drive2 : L"",
  1090. SecondDefined ? Drive2FreeNeeded : L"",
  1091. SecondDefined ? Drive2Free : L""
  1092. );
  1093. SpDisplayStatusOptions(
  1094. DEFAULT_STATUS_ATTRIBUTE,
  1095. SP_STAT_F3_EQUALS_EXIT,
  1096. Fatal ? 0 : SP_STAT_ENTER_EQUALS_CONTINUE,
  1097. 0
  1098. );
  1099. if(SpWaitValidKey(ValidKeys,NULL,NULL) == KEY_F3) {
  1100. if(Fatal) {
  1101. SpDone(0,FALSE,TRUE);
  1102. } else {
  1103. SpConfirmExit();
  1104. }
  1105. } else {
  1106. //
  1107. // User hit CR in non-fatal case
  1108. //
  1109. return;
  1110. }
  1111. }
  1112. }
  1113. ENUMUPGRADETYPE
  1114. SppSelectNTToRepairByUpgrade(
  1115. OUT PSP_BOOT_ENTRY *BootEntryChosen
  1116. )
  1117. {
  1118. PVOID Menu;
  1119. ULONG MenuTopY;
  1120. ULONG ValidKeys[] = { KEY_F3,ASCI_ESC,0 };
  1121. ULONG Mnemonics[] = {MnemonicRepair,0 };
  1122. ULONG Keypress;
  1123. PSP_BOOT_ENTRY BootEntry,FirstUpgradeSet;
  1124. BOOL bDone;
  1125. ENUMUPGRADETYPE ret;
  1126. //
  1127. // Build up array of drive letters for all menu options
  1128. //
  1129. for(BootEntry = SpBootEntries; BootEntry != NULL; BootEntry = BootEntry->Next) {
  1130. if (BootEntry->Processable) {
  1131. SpGetUpgDriveLetter(
  1132. BootEntry->OsPartitionDiskRegion->DriveLetter,
  1133. BootEntry->DriveLetterString,
  1134. sizeof(DRIVELTR_STRING),
  1135. FALSE
  1136. );
  1137. }
  1138. }
  1139. bDone = FALSE;
  1140. while(!bDone) {
  1141. //
  1142. // Display the text that goes above the menu on the partitioning screen.
  1143. //
  1144. SpDisplayScreen(SP_SCRN_WINNT_REPAIR_BY_UPGRADE,3,CLIENT_TOP+1);
  1145. //
  1146. // Calculate menu placement. Leave one blank line
  1147. // and one line for a frame.
  1148. //
  1149. MenuTopY = NextMessageTopLine+2;
  1150. //
  1151. // Create a menu.
  1152. //
  1153. Menu = SpMnCreate(
  1154. MENU_LEFT_X,
  1155. MenuTopY,
  1156. MENU_WIDTH,
  1157. VideoVars.ScreenHeight-MenuTopY-2-STATUS_HEIGHT
  1158. );
  1159. ASSERT(Menu);
  1160. //
  1161. // Build up a menu of partitions and free spaces.
  1162. //
  1163. FirstUpgradeSet = NULL;
  1164. for(BootEntry = SpBootEntries; BootEntry != NULL; BootEntry = BootEntry->Next) {
  1165. if(BootEntry->Processable) {
  1166. swprintf(
  1167. TemporaryBuffer,
  1168. L"%ws:%ws %ws",
  1169. BootEntry->DriveLetterString,
  1170. BootEntry->OsDirectory,
  1171. BootEntry->FriendlyName
  1172. );
  1173. SpMnAddItem(
  1174. Menu,
  1175. TemporaryBuffer,
  1176. MENU_LEFT_X+MENU_INDENT,
  1177. MENU_WIDTH-(2*MENU_INDENT),
  1178. TRUE,
  1179. (ULONG_PTR)BootEntry
  1180. );
  1181. if(FirstUpgradeSet == NULL) {
  1182. FirstUpgradeSet = BootEntry;
  1183. }
  1184. }
  1185. }
  1186. //
  1187. // Initialize the status line.
  1188. //
  1189. SpDisplayStatusOptions(
  1190. DEFAULT_STATUS_ATTRIBUTE,
  1191. SP_STAT_F3_EQUALS_EXIT,
  1192. SP_STAT_R_EQUALS_REPAIR,
  1193. SP_STAT_ESC_EQUALS_NO_REPAIR,
  1194. 0
  1195. );
  1196. //
  1197. // Display the menu
  1198. //
  1199. SpMnDisplay(
  1200. Menu,
  1201. (ULONG_PTR)FirstUpgradeSet,
  1202. TRUE,
  1203. ValidKeys,
  1204. Mnemonics,
  1205. NULL,
  1206. NULL,
  1207. &Keypress,
  1208. (PULONG_PTR)BootEntryChosen
  1209. );
  1210. //
  1211. // Now act on the user's selection.
  1212. //
  1213. switch(Keypress) {
  1214. case KEY_F3:
  1215. SpConfirmExit();
  1216. break;
  1217. case ASCI_ESC:
  1218. ret = DontUpgrade;
  1219. bDone = TRUE;
  1220. break;
  1221. default:
  1222. //
  1223. // Must be r=repair
  1224. //
  1225. ret = UpgradeFull;
  1226. bDone = TRUE;
  1227. break;
  1228. }
  1229. SpMnDestroy(Menu);
  1230. }
  1231. return(ret);
  1232. }
  1233. VOID
  1234. SpGetUpgDriveLetter(
  1235. IN WCHAR DriveLetter,
  1236. IN PWCHAR Buffer,
  1237. IN ULONG BufferSize,
  1238. IN BOOL AddColon
  1239. )
  1240. /*++
  1241. Routine Description:
  1242. This returns a unicode string containing the drive letter specified by
  1243. DriveLetter (if nonzero). If DriveLetter is 0, then we assume that we
  1244. are looking at a mirrored partition, and retrieve a localized string of
  1245. the form '(Mirror)'. If 'AddColon' is TRUE, then drive letters get a
  1246. colon appended (eg, "C:").
  1247. Arguments:
  1248. DriveLetter: Unicode drive letter, or 0 to denote a mirrored partition.
  1249. Buffer: Buffer to receive the unicode string
  1250. BufferSize: Size of the buffer.
  1251. AddColon: Boolean specifying whether colon should be added (has no
  1252. effect if DriveLetter is 0).
  1253. Returns:
  1254. Buffer contains the formatted Unicode string.
  1255. --*/
  1256. {
  1257. if(DriveLetter) {
  1258. if(BufferSize >= 2) {
  1259. *(Buffer++) = DriveLetter;
  1260. if(AddColon && BufferSize >= 3) {
  1261. *(Buffer++) = L':';
  1262. }
  1263. }
  1264. *Buffer = 0;
  1265. } else {
  1266. SpFormatMessage(Buffer, BufferSize, SP_UPG_MIRROR_DRIVELETTER);
  1267. }
  1268. }
  1269. BOOLEAN
  1270. SppWarnUpgradeWorkstationToServer(
  1271. IN ULONG MsgId
  1272. )
  1273. /*++
  1274. Routine Description:
  1275. Inform a user that that the installation that he/she selected to upgrade
  1276. is an NT Workstation, and that after the upgrade it will become a
  1277. Standard Server.
  1278. The user has the option to upgrade this or specify that he wants to
  1279. install Windows NT fresh.
  1280. Arguments:
  1281. MsgId - Screen to be displayed to the user.
  1282. Return Value:
  1283. BOOLEAN - Returns TRUE if the user wants to continue the upgrade, or
  1284. FALSE if the user wants to select another system to upgrade or
  1285. install fress.
  1286. --*/
  1287. {
  1288. ULONG ValidKeys[] = { ASCI_CR, ASCI_ESC, 0 };
  1289. ULONG c;
  1290. while(1) {
  1291. SpStartScreen(
  1292. MsgId,
  1293. 3,
  1294. HEADER_HEIGHT+1,
  1295. FALSE,
  1296. FALSE,
  1297. DEFAULT_ATTRIBUTE
  1298. );
  1299. SpDisplayStatusOptions(
  1300. DEFAULT_STATUS_ATTRIBUTE,
  1301. SP_STAT_ENTER_EQUALS_CONTINUE,
  1302. SP_STAT_ESC_EQUALS_CANCEL,
  1303. 0
  1304. );
  1305. switch(c=SpWaitValidKey(ValidKeys,NULL,NULL)) {
  1306. case KEY_F3:
  1307. SpConfirmExit();
  1308. break;
  1309. case ASCI_ESC:
  1310. return( FALSE );
  1311. case ASCI_CR:
  1312. return(TRUE);
  1313. default:
  1314. break;
  1315. }
  1316. }
  1317. }
  1318. VOID
  1319. SpCantFindBuildToUpgrade(
  1320. VOID
  1321. )
  1322. /*++
  1323. Routine Description:
  1324. Inform the user that we were unable to locate the build from which
  1325. he initiated unattended installation via winnt32.
  1326. This is a fatal condition.
  1327. Arguments:
  1328. None.
  1329. Return Value:
  1330. Does not return.
  1331. --*/
  1332. {
  1333. ULONG ValidKeys[2] = { KEY_F3, 0 };
  1334. CLEAR_CLIENT_SCREEN();
  1335. SpDisplayScreen(SP_SCRN_CANT_FIND_UPGRADE,3,HEADER_HEIGHT+1);
  1336. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,SP_STAT_F3_EQUALS_EXIT,0);
  1337. SpWaitValidKey(ValidKeys,NULL,NULL);
  1338. SpDone(0,FALSE,FALSE);
  1339. }
  1340. void
  1341. SpUpgradeToNT50FileSystems(
  1342. PVOID SifHandle,
  1343. PDISK_REGION SystemPartitionRegion,
  1344. PDISK_REGION NTPartitionRegion,
  1345. PWSTR SetupSourceDevicePath,
  1346. PWSTR DirectoryOnSetupSource
  1347. )
  1348. /*++
  1349. Routine Description:
  1350. Perform any necessary upgrades of the file systems
  1351. for the NT40 to NT50 upgrade case.
  1352. Arguments:
  1353. SystemPartitionRegion - Pointer to the structure that describes the
  1354. system partition.
  1355. NTPartitionRegion - Pointer to the structure that describes the
  1356. NT partition.
  1357. SetupSourceDevicePath - NT device path where autochk.exe is located
  1358. DirectoryOnSourceDevice - Local source directory.
  1359. Return Value:
  1360. None.
  1361. --*/
  1362. {
  1363. NTSTATUS Status;
  1364. PDISK_REGION Region;
  1365. PUCHAR Win9xPath;
  1366. ULONG i,j,k;
  1367. PSP_BOOT_ENTRY BootEntry;
  1368. PWSTR NtPath;
  1369. BOOLEAN DoConvert = TRUE;
  1370. OBJECT_ATTRIBUTES Obja;
  1371. IO_STATUS_BLOCK IoStatusBlock;
  1372. PVOID ImageBase;
  1373. HANDLE SectionHandle;
  1374. ULONGLONG SourceVersion;
  1375. HANDLE SourceHandle;
  1376. UNICODE_STRING UnicodeString;
  1377. BOOLEAN IssueWarning = FALSE;
  1378. WCHAR SourceFile[MAX_PATH];
  1379. PWSTR MediaShortName;
  1380. PWSTR MediaDirectory;
  1381. UCHAR SysId;
  1382. #if defined(REMOTE_BOOT)
  1383. //
  1384. // If this is a remote boot installation, do not try to convert -- the
  1385. // NT partition in this case is on the remote boot server.
  1386. //
  1387. if (RemoteBootSetup && !RemoteInstallSetup) {
  1388. ConvertNtVolumeToNtfs = FALSE;
  1389. return;
  1390. }
  1391. #endif // defined(REMOTE_BOOT)
  1392. SpDetermineUniqueAndPresentBootEntries();
  1393. for(BootEntry = SpBootEntries; BootEntry != NULL; BootEntry = BootEntry->Next) {
  1394. if (!BootEntry->Processable) {
  1395. continue;
  1396. }
  1397. BootEntry->Processable = FALSE;
  1398. wcscpy( TemporaryBuffer, BootEntry->OsPartitionNtName );
  1399. SpConcatenatePaths( TemporaryBuffer, BootEntry->OsDirectory );
  1400. SpConcatenatePaths( TemporaryBuffer, L"\\system32\\ntoskrnl.exe" );
  1401. INIT_OBJA( &Obja, &UnicodeString, TemporaryBuffer );
  1402. Status = ZwCreateFile(
  1403. &SourceHandle,
  1404. FILE_GENERIC_READ,
  1405. &Obja,
  1406. &IoStatusBlock,
  1407. NULL,
  1408. 0,
  1409. 0,
  1410. FILE_OPEN,
  1411. FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
  1412. NULL,
  1413. 0
  1414. );
  1415. if (NT_SUCCESS(Status)) {
  1416. Status = SpMapEntireFile( SourceHandle, &SectionHandle, &ImageBase, FALSE );
  1417. if (NT_SUCCESS(Status)) {
  1418. SpGetFileVersion( ImageBase, &BootEntry->KernelVersion );
  1419. BootEntry->Processable = TRUE;
  1420. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL,
  1421. "SETUP: SpUpgradeToNT50FileSystems: Kernel %p: NT%d.%d(Build %d) %d\n",
  1422. BootEntry,
  1423. (USHORT)(BootEntry->KernelVersion>>48),
  1424. (USHORT)(BootEntry->KernelVersion>>32),
  1425. (USHORT)(BootEntry->KernelVersion>>16),
  1426. (USHORT)(BootEntry->KernelVersion)));
  1427. SpUnmapFile( SectionHandle, ImageBase );
  1428. } else {
  1429. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpUpgradeToNT50FileSystems() could not map kernel image [%ws], %lx\n", TemporaryBuffer, Status ));
  1430. }
  1431. ZwClose(SourceHandle);
  1432. } else {
  1433. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpUpgradeToNT50FileSystems() corrupt boot config [%ws], %lx\n", TemporaryBuffer, Status ));
  1434. }
  1435. }
  1436. //
  1437. // count the number of "real" entries
  1438. //
  1439. k = 0;
  1440. for(BootEntry = SpBootEntries; BootEntry != NULL; BootEntry = BootEntry->Next) {
  1441. if (BootEntry->Processable) {
  1442. k += 1;
  1443. }
  1444. }
  1445. //
  1446. // check to see if a warning is necessary.
  1447. //
  1448. // If we're doing an upgrade, and there's only 1
  1449. // boot set, then we don't need a warning. However,
  1450. // if we're doing a clean install and there's at least
  1451. // 1 boot set, then warn (given the existing OS is
  1452. // old enough).
  1453. //
  1454. if( ( ((NTUpgrade == UpgradeFull) && (k > 1)) ||
  1455. ((NTUpgrade == DontUpgrade) && (k > 0)) ) &&
  1456. ( !UnattendedOperation ) && (!SpDrEnabled())) {
  1457. for(BootEntry = SpBootEntries; BootEntry != NULL && IssueWarning == FALSE; BootEntry = BootEntry->Next) {
  1458. if (!BootEntry->Processable || (BootEntry->KernelVersion == 0)) {
  1459. //
  1460. // bogus boot entry
  1461. //
  1462. } else if ((BootEntry->KernelVersion >> 48) < 4) {
  1463. IssueWarning = TRUE;
  1464. } else if ((BootEntry->KernelVersion >> 48) == 4 && (BootEntry->KernelVersion & 0xffff) <= 4) {
  1465. IssueWarning = TRUE;
  1466. }
  1467. }
  1468. }
  1469. // If there's any existing NT4.0 with servicepack less than 5 then warn.
  1470. if( k > 0) {
  1471. for(BootEntry = SpBootEntries; BootEntry != NULL && IssueWarning == FALSE; BootEntry = BootEntry->Next) {
  1472. if (!BootEntry->Processable || (BootEntry->KernelVersion == 0)) {
  1473. //
  1474. // bogus boot entry
  1475. //
  1476. } else if (BootEntry->MajorVersion == 4 && BootEntry->MinorVersion == 0 && BootEntry->BuildNumber == 1381 && BootEntry->ServicePack < 500) {
  1477. IssueWarning = TRUE;
  1478. }
  1479. }
  1480. }
  1481. if (IssueWarning) {
  1482. ULONG WarnKeys[] = { KEY_F3, 0 };
  1483. ULONG MnemonicKeys[] = { MnemonicContinueSetup, 0 };
  1484. while (IssueWarning) {
  1485. SpDisplayScreen(SP_SCRN_FSWARN,3,CLIENT_TOP+1);
  1486. SpDisplayStatusOptions(
  1487. DEFAULT_STATUS_ATTRIBUTE,
  1488. SP_STAT_C_EQUALS_CONTINUE_SETUP,
  1489. SP_STAT_F3_EQUALS_EXIT,
  1490. 0
  1491. );
  1492. SpInputDrain();
  1493. switch(SpWaitValidKey(WarnKeys,NULL,MnemonicKeys)) {
  1494. case KEY_F3:
  1495. SpConfirmExit();
  1496. return;
  1497. default:
  1498. IssueWarning = FALSE;
  1499. break;
  1500. }
  1501. }
  1502. }
  1503. #if 0
  1504. //
  1505. // now lets upgrade any nt40+sp3 ntfs file systems
  1506. //
  1507. MediaShortName = SpLookUpValueForFile(
  1508. SifHandle,
  1509. L"ntfs40.sys",
  1510. INDEX_WHICHMEDIA,
  1511. TRUE
  1512. );
  1513. SpGetSourceMediaInfo( SifHandle, MediaShortName, NULL, NULL, &MediaDirectory );
  1514. wcscpy( SourceFile, SetupSourceDevicePath );
  1515. SpConcatenatePaths( SourceFile, DirectoryOnSetupSource );
  1516. SpConcatenatePaths( SourceFile, MediaDirectory );
  1517. SpConcatenatePaths( SourceFile, L"ntfs40.sys" );
  1518. //
  1519. // Initialize the diamond decompression engine.
  1520. // This needs to be done, because SpCopyFileUsingNames() uses
  1521. // the decompression engine.
  1522. //
  1523. SpdInitialize();
  1524. for(BootEntry = SpBootEntries; BootEntry != NULL; BootEntry = BootEntry->Next) {
  1525. if (BootEntry->Processable &&
  1526. ((BootEntry->KernelVersion >> 48) == 4) &&
  1527. ((BootEntry->KernelVersion & 0xffff) == 4)) {
  1528. wcscpy( TemporaryBuffer, BootEntry->OsPartitionNtName );
  1529. SpConcatenatePaths( TemporaryBuffer, BootEntry->OsDirectory );
  1530. SpConcatenatePaths( TemporaryBuffer, L"\\system32\\drivers\\ntfs.sys" );
  1531. Status = SpCopyFileUsingNames(
  1532. SourceFile,
  1533. TemporaryBuffer,
  1534. 0,
  1535. COPY_NOVERSIONCHECK
  1536. );
  1537. if (!NT_SUCCESS(Status)) {
  1538. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpUpgradeToNT50FileSystems() could not copy nt40 ntfs.sys driver, %lx\n", Status ));
  1539. }
  1540. SpMemFree(NtPath);
  1541. }
  1542. }
  1543. // Terminate diamond
  1544. SpdTerminate();
  1545. #endif
  1546. return;
  1547. }
  1548. BOOLEAN
  1549. SpDoBuildsMatch(
  1550. IN PVOID SifHandle,
  1551. ULONG TestBuildNum,
  1552. NT_PRODUCT_TYPE TestBuildType,
  1553. ULONG TestBuildSuiteMask,
  1554. BOOLEAN CurrentProductIsServer,
  1555. ULONG CurrentSuiteMask,
  1556. IN LCID LangId
  1557. )
  1558. /*++
  1559. Routine Description:
  1560. Checks if the current build the user is installing matches the build we're
  1561. checking against.
  1562. We check:
  1563. 1. do the build numbers match?
  1564. 2. do the build types match? (nt server and nt professional don't match)
  1565. 3. do the product suites match? (nt advanced server vs. data center)
  1566. Arguments:
  1567. SifHandle - Handle to txtsetup.sif to find the source language
  1568. TestBuildNum - The build number of the build we're checking against
  1569. TestBuildType - The type of build we're checking against
  1570. TestBuildSuiteMask - Type of product suite as mask we're checking against
  1571. CurrentProductIsServer - If TRUE, the current build is NT Server
  1572. CurrentSuiteMask - Type of suite mask
  1573. LangId - System Language Id of the installation to check. If -1, Lang Id
  1574. check is ignored.
  1575. Return Value:
  1576. BOOLEAN - Returns TRUE if the builds match.
  1577. --*/
  1578. {
  1579. #define PRODUCTSUITES_TO_MATCH (( VER_SUITE_SMALLBUSINESS \
  1580. | VER_SUITE_ENTERPRISE \
  1581. | VER_SUITE_BACKOFFICE \
  1582. | VER_SUITE_COMMUNICATIONS \
  1583. | VER_SUITE_SMALLBUSINESS_RESTRICTED \
  1584. | VER_SUITE_EMBEDDEDNT \
  1585. | VER_SUITE_DATACENTER \
  1586. | VER_SUITE_PERSONAL))
  1587. BOOLEAN retval;
  1588. LANGID DefLangId = -1;
  1589. DWORD Version = 0, BuildNumber = 0;
  1590. if (!DetermineSourceVersionInfo(&Version, &BuildNumber)) {
  1591. retval = FALSE;
  1592. goto exit;
  1593. }
  1594. if(TestBuildNum != BuildNumber) {
  1595. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL,
  1596. "SETUP: SpDoBuildsMatch() has build mismatch, %d != %d\n",
  1597. TestBuildNum, BuildNumber));
  1598. retval = FALSE;
  1599. goto exit;
  1600. }
  1601. //
  1602. // build number test passed. now check for server vs. professional
  1603. //
  1604. if (((TestBuildType == NtProductWinNt) && CurrentProductIsServer) ||
  1605. ((TestBuildType == NtProductServer) && !CurrentProductIsServer)) {
  1606. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL,
  1607. "SETUP: SpDoBuildsMatch() has server/professional mismatch\n" ));
  1608. retval = FALSE;
  1609. goto exit;
  1610. }
  1611. //
  1612. // now check product suites.
  1613. // note that we don't check for all product suites, only
  1614. // suites that have their own SKU
  1615. //
  1616. if ((CurrentSuiteMask & PRODUCTSUITES_TO_MATCH) != (TestBuildSuiteMask & PRODUCTSUITES_TO_MATCH)) {
  1617. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL,
  1618. "SETUP: SpDoBuildsMatch() has suite mismatch (dest = %x) (source = %x\n",
  1619. TestBuildSuiteMask,CurrentSuiteMask ));
  1620. retval = FALSE;
  1621. goto exit;
  1622. }
  1623. //
  1624. // language IDs should also match (if requested)
  1625. //
  1626. if (LangId != -1) {
  1627. PWSTR LangIdStr = SpGetSectionKeyIndex(SifHandle, SIF_NLS, SIF_DEFAULTLAYOUT, 0);
  1628. PWSTR EndChar;
  1629. if (LangIdStr)
  1630. DefLangId = (LANGID)SpStringToLong(LangIdStr, &EndChar, 16);
  1631. //
  1632. // note : currently we are only interested in primary language IDs
  1633. //
  1634. retval = (PRIMARYLANGID(DefLangId) == PRIMARYLANGID(LangId)) ? TRUE : FALSE;
  1635. goto exit;
  1636. }
  1637. retval = TRUE;
  1638. exit:
  1639. return(retval);
  1640. }
  1641. NTSTATUS
  1642. SpGetMediaDetails(
  1643. IN PWSTR CdInfDirPath,
  1644. OUT PCCMEDIA MediaObj
  1645. )
  1646. /*++
  1647. Routine Description:
  1648. Gets the details of the current CD in CCMEDIA structure
  1649. Arguments:
  1650. CdInfDirPath - The path to the inf directories on CD-ROM drive
  1651. MediaObj - The pointer to the media object in which the details
  1652. are returned
  1653. Return Value:
  1654. Returns STATUS_SUCCESS if success otherwise appropriate status error code.
  1655. --*/
  1656. {
  1657. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  1658. WCHAR DosNetPath[MAX_PATH];
  1659. WCHAR SetuppIniPath[MAX_PATH];
  1660. PVOID SetuppIniHandle = 0;
  1661. PVOID DosNetHandle = 0;
  1662. ULONG ErrorLine = 0;
  1663. WCHAR Pid[32] = {0};
  1664. WCHAR PidData[256] = {0};
  1665. PWSTR TempPtr;
  1666. BOOLEAN UpgradeMode = FALSE;
  1667. DWORD Type = COMPLIANCE_INSTALLTYPE_UNKNOWN;
  1668. DWORD Variation = COMPLIANCE_INSTALLVAR_UNKNOWN;
  1669. DWORD Version = 0, BuildNumber = 0;
  1670. if (CdInfDirPath && MediaObj) {
  1671. BOOLEAN VersionDetected = FALSE;
  1672. wcscpy(DosNetPath, CdInfDirPath);
  1673. wcscpy(SetuppIniPath, CdInfDirPath);
  1674. SpConcatenatePaths(DosNetPath, L"dosnet.inf");
  1675. SpConcatenatePaths(SetuppIniPath, L"setupp.ini");
  1676. //
  1677. // load setupp.ini file and parse it
  1678. //
  1679. Status = SpLoadSetupTextFile(
  1680. SetuppIniPath,
  1681. NULL, // No image already in memory
  1682. 0, // Image size is empty
  1683. &SetuppIniHandle,
  1684. &ErrorLine,
  1685. TRUE,
  1686. FALSE
  1687. );
  1688. if(NT_SUCCESS(Status)) {
  1689. Status = STATUS_FILE_INVALID;
  1690. //
  1691. // get the PID
  1692. //
  1693. TempPtr = SpGetSectionKeyIndex(SetuppIniHandle, L"Pid", L"Pid", 0);
  1694. if (TempPtr) {
  1695. wcscpy(Pid, TempPtr);
  1696. //
  1697. // get PID ExtraData
  1698. //
  1699. TempPtr = SpGetSectionKeyIndex(SetuppIniHandle, L"Pid", L"ExtraData", 0);
  1700. if (TempPtr) {
  1701. wcscpy(PidData, TempPtr);
  1702. //
  1703. // Get stepup mode & install variation based on PID
  1704. //
  1705. if (SpGetStepUpMode(PidData, &UpgradeMode) &&
  1706. pSpGetCurrentInstallVariation(Pid, &Variation)) {
  1707. Status = STATUS_SUCCESS;
  1708. } else {
  1709. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SpGetMediaDetails: Could "
  1710. "not find StepUp mode or variation of install CD\n"));
  1711. }
  1712. } else {
  1713. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SpGetMediaDetails: Could not get "
  1714. "PidExtraData from Setupp.ini\n"));
  1715. }
  1716. } else {
  1717. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SpGetMediaDetails: Could not get Pid from Setupp.ini\n"));
  1718. }
  1719. } else {
  1720. //
  1721. // Silently fail if unable to read setupp.ini
  1722. //
  1723. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SpGetMediaDetails: Unable to read setupp.ini. "
  1724. "Status = %lx \n", Status));
  1725. }
  1726. if (SetuppIniHandle)
  1727. SpFreeTextFile(SetuppIniHandle);
  1728. if (NT_SUCCESS(Status)) {
  1729. //
  1730. // load and parse dosnet.inf
  1731. //
  1732. Status = SpLoadSetupTextFile(
  1733. DosNetPath,
  1734. NULL, // No image already in memory
  1735. 0, // Image size is empty
  1736. &DosNetHandle,
  1737. &ErrorLine,
  1738. TRUE,
  1739. FALSE
  1740. );
  1741. if (NT_SUCCESS(Status)) {
  1742. Status = STATUS_FILE_INVALID;
  1743. //
  1744. // get ProductType from Miscellaneous section
  1745. //
  1746. TempPtr = SpGetSectionKeyIndex(DosNetHandle, L"Miscellaneous",
  1747. L"ProductType", 0);
  1748. if (TempPtr) {
  1749. UNICODE_STRING UnicodeStr;
  1750. ULONG Value = -1;
  1751. RtlInitUnicodeString(&UnicodeStr, TempPtr);
  1752. Status = RtlUnicodeStringToInteger(&UnicodeStr, 10, &Value);
  1753. switch (Value) {
  1754. case 0:
  1755. Type = COMPLIANCE_INSTALLTYPE_NTW;
  1756. break;
  1757. case 1:
  1758. Type = COMPLIANCE_INSTALLTYPE_NTS;
  1759. break;
  1760. case 2:
  1761. Type = COMPLIANCE_INSTALLTYPE_NTSE;
  1762. break;
  1763. case 3:
  1764. Type = COMPLIANCE_INSTALLTYPE_NTSDTC;
  1765. break;
  1766. case 4:
  1767. Type = COMPLIANCE_INSTALLTYPE_NTWP;
  1768. break;
  1769. default:
  1770. break;
  1771. }
  1772. //
  1773. // Get the version also off from driverver in dosnet.inf
  1774. //
  1775. TempPtr = SpGetSectionKeyIndex(DosNetHandle, L"Version",
  1776. L"DriverVer", 1);
  1777. if (TempPtr) {
  1778. if (NT_SUCCESS(SpGetVersionFromStr(TempPtr,
  1779. &Version, &BuildNumber))) {
  1780. VersionDetected = TRUE;
  1781. }
  1782. Status = STATUS_SUCCESS;
  1783. }
  1784. if (Type != COMPLIANCE_INSTALLTYPE_UNKNOWN) {
  1785. Status = STATUS_SUCCESS;
  1786. } else {
  1787. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SpGetMediaDetails: Could not get product type"
  1788. " from dosnet.inf\n"));
  1789. }
  1790. } else {
  1791. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SpGetMediaDetails: "
  1792. "Could not get ProductType from dosnet.inf\n"));
  1793. }
  1794. } else {
  1795. //
  1796. // Silently fail if unable to read dosnet.inf
  1797. //
  1798. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SpGetMediaDetails: Unable to read dosnet.inf. "
  1799. "Status = %lx \n", Status ));
  1800. }
  1801. }
  1802. if (DosNetHandle)
  1803. SpFreeTextFile(DosNetHandle);
  1804. //
  1805. // Fall back to old way of finding version, if we failed
  1806. // to get one from dosnet.inf
  1807. //
  1808. if (NT_SUCCESS(Status) && !VersionDetected) {
  1809. if (!DetermineSourceVersionInfo(&Version, &BuildNumber))
  1810. Status = STATUS_FILE_INVALID;
  1811. }
  1812. //
  1813. // fill in the media details
  1814. //
  1815. if (NT_SUCCESS(Status) &&
  1816. ! CCMediaInitialize(MediaObj, Type, Variation, UpgradeMode, Version, BuildNumber)) {
  1817. Status = STATUS_FILE_INVALID;
  1818. }
  1819. }
  1820. return Status;
  1821. }