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.

8680 lines
264 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. spsetup.c
  5. Abstract:
  6. Main module for character-base setup (ie, text setup).
  7. Author:
  8. Ted Miller (tedm) 29-July-1993
  9. --*/
  10. #include "spprecmp.h"
  11. #pragma hdrstop
  12. #include "spcmdcon.h"
  13. #include <initguid.h>
  14. #include <pnpmgr.h>
  15. #include <devguid.h>
  16. #include <remboot.h>
  17. #include <hdlsblk.h>
  18. #include <hdlsterm.h>
  19. #ifdef _X86_
  20. #include "spwin9xuninstall.h"
  21. #endif
  22. #if !defined(SETUPBLK_FLAGS_ROLLBACK)
  23. #define SETUPBLK_FLAGS_ROLLBACK 0
  24. #endif
  25. #if defined(REMOTE_BOOT)
  26. VOID
  27. IoStartCscForTextmodeSetup(
  28. IN BOOLEAN Upgrade
  29. );
  30. #endif // defined(REMOTE_BOOT)
  31. BOOL
  32. SpDetermineBootPartitionEnumNec98(
  33. IN PPARTITIONED_DISK Disk,
  34. IN PDISK_REGION Region,
  35. IN ULONG_PTR Context
  36. );
  37. VOID
  38. SpCantFindBuildToUpgrade(
  39. VOID
  40. );
  41. //
  42. // TRUE if setup should run in the step-up upgrade mode.
  43. // In this mode, setup is not allowed to do clean install,
  44. // and is not allowed to upgrade workstation to server.
  45. // Also, evaluation time in minutes, read from the setup hive.
  46. // This value is passed through to GUI mode.
  47. //
  48. BOOLEAN StepUpMode;
  49. DWORD EvaluationTime = 0;
  50. ULONG RestrictCpu;
  51. ULONG SuiteType;
  52. //
  53. // TRUE if user chose Custom Setup.
  54. //
  55. BOOLEAN CustomSetup = TRUE;
  56. //
  57. // Non-0 if gui setup is supposed to be restartable.
  58. // This causes us to do special stuff with hives in spconfig.c.
  59. //
  60. BOOLEAN RestartableGuiSetup = TRUE;
  61. //
  62. // TRUE if user chose repair winnt
  63. //
  64. BOOLEAN RepairWinnt = FALSE;
  65. //
  66. // TRUE if this is a command console only boot
  67. //
  68. BOOLEAN ForceConsole = FALSE;
  69. BOOLEAN ConsoleRunning = FALSE;
  70. BOOLEAN ConsoleFromWinnt32 = FALSE;
  71. //
  72. // TRUE if repair from ER diskette
  73. //
  74. BOOLEAN RepairFromErDisk = TRUE;
  75. //
  76. // TRUE if this is advanced server we're setting up.
  77. //
  78. BOOLEAN AdvancedServer;
  79. //
  80. // Windows NT Version.
  81. //
  82. ULONG WinntMajorVer;
  83. ULONG WinntMinorVer;
  84. //
  85. // Win9x uninstall
  86. //
  87. BOOLEAN Win9xRollback = FALSE;
  88. BOOLEAN g_Win9xBackup = FALSE;
  89. #ifdef PRERELEASE
  90. //
  91. // Test hooks
  92. //
  93. INT g_TestHook;
  94. #endif
  95. //
  96. // True if NOLS = 1 in winnts.sif
  97. //
  98. BOOLEAN NoLs = FALSE;
  99. //
  100. // NTUpgrade - Whether we are upgrading an existing NT and if we are
  101. // what type of an upgrade it is. Valid values are:
  102. //
  103. // - DontUpgrade: If we are not upgrading
  104. // - UpgradeFull: Full upgrade
  105. // - UpgradeInstallFresh: There was a failed upgrade, so we want to install
  106. // fresh into this, saving the hives
  107. //
  108. //
  109. ENUMUPGRADETYPE NTUpgrade = DontUpgrade;
  110. //
  111. // Indicates whether actually NT was being upgraded
  112. // to partitioning engine, so that on IA64 it can
  113. // treat active MBR partitions as system partitions
  114. //
  115. ENUMUPGRADETYPE IsNTUpgrade = DontUpgrade;
  116. //
  117. // TRUE if upgrading Workstation to Standard Server, or upgrading
  118. // existing Standard Server
  119. //
  120. BOOLEAN StandardServerUpgrade = FALSE;
  121. //
  122. // Contains the type of windows upgrade, if any (win31 or win95)
  123. //
  124. ENUMNONNTUPRADETYPE WinUpgradeType = NoWinUpgrade;
  125. //
  126. // TRUE if this setup was started with winnt.exe or winnt32.exe.
  127. // Also a flag indicating whether the local source was not created and we
  128. // should get files from the CD instead.
  129. //
  130. BOOLEAN WinntSetup = FALSE;
  131. BOOLEAN WinntFromCd = FALSE;
  132. //
  133. // TRUE if floppyless boot
  134. //
  135. BOOLEAN IsFloppylessBoot = FALSE;
  136. //
  137. // TRUE if textmode is to pick a partition
  138. //
  139. BOOLEAN AutoPartitionPicker;
  140. //
  141. // Preferred installation dir
  142. //
  143. PWSTR PreferredInstallDir;
  144. //
  145. // If this is an unattended setup, this value will be a non-NULL
  146. // handle to the SIF file with setup parameters.
  147. // *Note*: Before referencing UnattendedSifHandle, you must first check
  148. // UnattendedOperation is not FALSE.
  149. //
  150. BOOLEAN UnattendedOperation = FALSE;
  151. BOOLEAN UnattendedGuiOperation = FALSE;
  152. PVOID UnattendedSifHandle = NULL;
  153. PVOID WinntSifHandle = NULL;
  154. PVOID ASRPnPSifHandle = NULL;
  155. PVOID WinntMigrateInfHandle = NULL;
  156. PVOID WinntUnsupDrvInfHandle = NULL;
  157. BOOLEAN AccessibleSetup = FALSE;
  158. //
  159. // this value is a non-null pointer to the drvindex.inf file. It is
  160. // initialized on startup. The list of files that are present in our
  161. // driver cab file are indexed in this inf, so we can quickly look if a
  162. // file is present in the cab
  163. //
  164. PVOID DriverInfHandle;
  165. //
  166. // this is a non-null pointer to the driver cab file. It is also initialzied
  167. // on startup. The list of files in this cab is indexed in drvindex.inf. this is
  168. // the only cab file that textmode setup knows to look into.
  169. //
  170. CABDATA *CabData;
  171. //
  172. // pointer to delta.inf, an INF for private testing
  173. //
  174. PVOID PrivateInfHandle;
  175. //
  176. // This is a handle to txtsetup.oem, used on pre-install mode.
  177. //
  178. PVOID PreinstallOemSifHandle = NULL;
  179. //
  180. // If this flag is true, we ignore files that are not present on the source
  181. // when copying. This is used internally for people who don't build the
  182. // entire system and don't care that a whole bunch of help files,
  183. // device drivers, etc, aren't there.
  184. //
  185. BOOLEAN SkipMissingFiles;
  186. BOOLEAN HideWinDir;
  187. //
  188. // On unattended mode, indicates whether OEM files
  189. // that have same name as Microsoft files released
  190. // with the product should be overwritten.
  191. //
  192. BOOLEAN UnattendedOverwriteOem = TRUE;
  193. //
  194. // On unattended mode, indicates that this is is
  195. // an OEM pre-installation
  196. //
  197. BOOLEAN PreInstall = FALSE;
  198. //
  199. // In unattended mode, indicates whether to wait
  200. // for reboot
  201. //
  202. BOOLEAN UnattendWaitForReboot = FALSE;
  203. //
  204. // On pre-install mode, indicates whether or not an OEM component needs
  205. // to be pre-installed (txtsetup.oem needs to be loaded).
  206. //
  207. // BOOLEAN PreinstallOemComponents = FALSE;
  208. //
  209. // On pre-install mode, the variables below point to the various lists of
  210. // drivers to pre-install
  211. //
  212. // PPREINSTALL_DRIVER_INFO PreinstallDisplayDriverList = NULL;
  213. // PPREINSTALL_DRIVER_INFO PreinstallKeyboardDriverList = NULL;
  214. // PPREINSTALL_DRIVER_INFO PreinstallPointingDeviceDriverList = NULL;
  215. // PPREINSTALL_DRIVER_INFO PreinstallKeyboardLayout = NULL;
  216. //
  217. // On pre-install mode, points to the directory that contains the files
  218. // that need to be copied during textmode setup
  219. //
  220. PWSTR PreinstallOemSourcePath = NULL;
  221. //
  222. // Virtual OEM source devices (accessible through RAM disk driver)
  223. //
  224. PVIRTUAL_OEM_SOURCE_DEVICE VirtualOemSourceDevices = NULL;
  225. //
  226. // Flags that indicate the type of mice detected in the machine.
  227. // Note that more than one type of mice may be present.
  228. //
  229. BOOLEAN UsbMouseDetected = FALSE;
  230. BOOLEAN PS2MouseDetected = FALSE;
  231. BOOLEAN SerMouseDetected = FALSE;
  232. //
  233. // Flags that indicate the type of keyboard detected in the machine.
  234. // Note that more than one type of keyborad may be present.
  235. //
  236. BOOLEAN UsbKeyboardDetected = FALSE;
  237. BOOLEAN StdKeyboardDetected = FALSE;
  238. //
  239. // Gets set to TRUE if the user elects to convert or format to ntfs.
  240. // And a flag indicating whether we are doing a dirty sleazy hack
  241. // for oem preinstall.
  242. //
  243. BOOLEAN ConvertNtVolumeToNtfs = FALSE;
  244. BOOLEAN ExtendingOemPartition = FALSE;
  245. //
  246. // Variable used during the repair process, that indicates that the
  247. // system has no CD-ROM drive.
  248. // This is a hack that we did for World Bank so that they can repair
  249. // the hives even if they don't have a CD-ROM drive.
  250. //
  251. BOOLEAN RepairNoCDROMDrive = FALSE;
  252. //
  253. // Indicates whether or not winnt32 detected at least one
  254. // FT partition in the system.
  255. // Note that on boot floppies install on x86 machines,
  256. // or setupldr/CD install on ARC machines, this flag will always be
  257. // set to FALSE
  258. //
  259. BOOLEAN FtPartitionDetected = FALSE;
  260. //
  261. // Filename of local source directory.
  262. //
  263. PWSTR LocalSourceDirectory = L"\\$win_nt$.~ls";
  264. LIST_ENTRY MigratedDriversList;
  265. //
  266. // Platform-specific extension, used when creating names of sections
  267. // in sif/inf files.
  268. //
  269. #if defined(_AMD64_)
  270. PWSTR PlatformExtension = L".amd64";
  271. #elif defined(_X86_)
  272. PWSTR PlatformExtension = L".x86";
  273. #elif defined(_IA64_)
  274. PWSTR PlatformExtension = L".ia64";
  275. #else
  276. #error "No Target Architecture"
  277. #endif
  278. WCHAR TemporaryBuffer[16384];
  279. const UNICODE_STRING TemporaryBufferUnicodeString = { 0, sizeof(TemporaryBuffer), TemporaryBuffer };
  280. //
  281. // This global structure contains non-pointer values passed to us by setupldr
  282. // in the setup loader parameter block.
  283. //
  284. // This structure is initialized during SpInitialize0().
  285. //
  286. SETUP_LOADER_BLOCK_SCALARS SetupParameters;
  287. //
  288. // These values are set during SpInitialize0() and are the ARC pathname
  289. // of the device from which we were started and the directory within the device.
  290. // DirectoryOnBootDevice will always be all uppercase.
  291. //
  292. PWSTR ArcBootDevicePath,DirectoryOnBootDevice;
  293. //
  294. // Representation of the boot device path in the nt namespace.
  295. //
  296. PWSTR NtBootDevicePath;
  297. //
  298. // Dynamic update boot driver path in NT namespace
  299. //
  300. PWSTR DynUpdtBootDriverPath = NULL;
  301. //
  302. // Global parameter block for command console
  303. //
  304. CMDCON_BLOCK Block = {0};
  305. //
  306. // Setupldr loads a text setup information file and passes us the buffer
  307. // so that we don't have to reload it from disk. During SpInitialize0()
  308. // we allocate some pool and store the image away for later use.
  309. //
  310. PVOID SetupldrInfoFile;
  311. ULONG SetupldrInfoFileSize;
  312. //
  313. // During remote boot setup, setupldr also loads winnt.sif.
  314. //
  315. PVOID SetupldrWinntSifFile;
  316. ULONG SetupldrWinntSifFileSize;
  317. //
  318. // Setupldr loads asrpnp.sif.
  319. //
  320. PVOID SetupldrASRPnPSifFile;
  321. ULONG SetupldrASRPnPSifFileSize;
  322. //
  323. // Setupldr may load an inf that contains registry information that needs to be
  324. // migrated to the setup hive. This file will be processed during SpInitialize0().
  325. //
  326. PVOID SetupldrMigrateInfFile;
  327. ULONG SetupldrMigrateInfFileSize;
  328. //
  329. // Setupldr may load an inf that contains information about unsupported SCSI
  330. // drivers that need to work during textmode setup.
  331. // This file will be processed during SpInitialize0().
  332. //
  333. PVOID SetupldrUnsupDrvInfFile;
  334. ULONG SetupldrUnsupDrvInfFileSize;
  335. #if defined(REMOTE_BOOT)
  336. //
  337. // Setupldr passes in the hal name on remote boot. Store them here
  338. // before the loader block goes away.
  339. //
  340. UCHAR NetBootHalName[MAX_HAL_NAME_LENGTH + 1];
  341. #endif // defined(REMOTE_BOOT)
  342. //
  343. // The name of the SIF file used by remote boot. This is saved since
  344. // it needs to be deleted later.
  345. //
  346. PWSTR NetBootSifPath = NULL;
  347. PDISK_SIGNATURE_INFORMATION DiskSignatureInformation;
  348. //
  349. // Setupldr passes in the path to IMirror.dat, store it here before the loader
  350. // block goes away.
  351. //
  352. PUCHAR RemoteIMirrorFilePath;
  353. //
  354. // For remote install, save the NT boot path from the loader block, because
  355. // DirectoryOnBootDevice becomes something else.
  356. //
  357. PWSTR RemoteIMirrorBootDirectoryPrefix;
  358. //
  359. // The file version and memory version of the IMirror.dat information
  360. // (the memory version is modified to match this actual machine).
  361. //
  362. PMIRROR_CFG_INFO_FILE RemoteIMirrorFileData = NULL;
  363. PMIRROR_CFG_INFO_MEMORY RemoteIMirrorMemoryData = NULL;
  364. //
  365. // Setupldr passes in the IP address of the server we are talking to.
  366. //
  367. ULONG RemoteServerIpAddress;
  368. //
  369. // setupldr may pass us the administrator password in a remote install
  370. // if the user is prompted for the password.
  371. //
  372. PWSTR NetBootAdministratorPassword = NULL;
  373. BOOLEAN GeneralInitialized = FALSE;
  374. BOOLEAN PcmciaLoaded = FALSE;
  375. BOOLEAN AtapiLoaded = FALSE;
  376. //
  377. // Array with the PIDs of all NT greater than 4.x found in the machine (PID 2.0)
  378. // The values in this array will be saved under Setup\PidList key in the registry,
  379. // and will be used during GUI setup
  380. //
  381. PWSTR* Pid20Array = NULL;
  382. //
  383. // Product Id read from setupp.ini
  384. //
  385. PWSTR PidString = NULL;
  386. //
  387. // Plug & Play notification handle
  388. //
  389. PVOID NotificationEntry = NULL;
  390. //
  391. // Plug & Play hardware ID database (unicode)
  392. //
  393. PSETUP_PNP_HARDWARE_ID SetupHardwareIdDatabase = NULL;
  394. //
  395. // Guid strings to identify mouse and keyboard
  396. //
  397. PWSTR MouseGuidString = NULL;
  398. PWSTR KeyboardGuidString = NULL;
  399. //
  400. // This flag identifies "dockable" machines (portables)
  401. // so that we can disble dynamic volumes on them
  402. //
  403. BOOLEAN DockableMachine = FALSE;
  404. //
  405. // Pointer to block of interesting values and other stuff
  406. // passed to spcmdcon.sys
  407. //
  408. PCMDCON_BLOCK gpCmdConsBlock = NULL;
  409. //begin NEC98
  410. PDISK_REGION TargetRegion_Nec98 = NULL;
  411. #define WINNT_D_DRIVEASSIGN_NEC98_W L"DriveAssign_Nec98"
  412. #define WINNT_D_DRIVEASSIGN_NEC98_A "DriveAssign_Nec98"
  413. #ifdef UNICODE
  414. #define WINNT_D_DRIVEASSIGN_NEC98 WINNT_D_DRIVEASSIGN_NEC98_W
  415. #else
  416. #define WINNT_D_DRIVEASSIGN_NEC98 WINNT_D_DRIVEASSIGN_NEC98_A
  417. #endif
  418. //
  419. // Legacy drive assign for NEC98, HD start from A:
  420. // but it is only case of upgrade from NT4.0 or Win9x.
  421. //
  422. BOOLEAN DriveAssignFromA = FALSE; //PC-AT assign.
  423. //
  424. // Indicates whether we have a system partition or not
  425. // on Arc Machines
  426. //
  427. BOOLEAN ValidArcSystemPartition = FALSE;
  428. #ifdef _X86_
  429. //
  430. // NEC98
  431. //
  432. BOOLEAN
  433. SpReInitializeBootVars_Nec98(
  434. VOID
  435. );
  436. #endif
  437. VOID
  438. SpSetAutoBootFlag(
  439. IN PDISK_REGION TargetRegion,
  440. IN BOOLEAN SetBootPosision
  441. );
  442. //end NEC98
  443. VOID
  444. SpTerminate(
  445. VOID
  446. );
  447. VOID
  448. SpInitialize0a(
  449. IN PDRIVER_OBJECT DriverObject,
  450. IN PVOID Context,
  451. IN ULONG ReferenceCount
  452. );
  453. VOID
  454. SpDetermineProductType(
  455. IN PVOID SifHandle
  456. );
  457. BOOL
  458. SpDetermineInstallationSource(
  459. IN PVOID SifHandle,
  460. OUT PWSTR *DevicePath,
  461. OUT PWSTR *DirectoryOnDevice,
  462. IN BOOLEAN bEscape
  463. );
  464. VOID
  465. SpCompleteBootListConfig(
  466. WCHAR DriveLetter
  467. );
  468. VOID
  469. SpInitializePidString(
  470. IN HANDLE MasterSifHandle,
  471. IN PWSTR SetupSourceDevicePath,
  472. IN PWSTR DirectoryOnSourceDevice
  473. );
  474. BOOLEAN
  475. SpGetStepUpMode(
  476. IN PWSTR PidExtraData,
  477. BOOLEAN *StepUpMode
  478. );
  479. NTSTATUS
  480. SpCreateDriverRegistryEntries(
  481. IN PHARDWARE_COMPONENT DriverList
  482. );
  483. #if defined(REMOTE_BOOT)
  484. NTSTATUS
  485. SpFixupRemoteBootLoader(
  486. PWSTR RemoteBootTarget
  487. );
  488. NTSTATUS
  489. SpCreateRemoteBootCfg(
  490. IN PWSTR RemoteBootTarget,
  491. IN PDISK_REGION SystemPartitionRegion
  492. );
  493. NTSTATUS
  494. SpEraseCscCache(
  495. IN PDISK_REGION SystemPartitionRegion
  496. );
  497. #endif // defined(REMOTE_BOOT)
  498. #if defined HEADLESS_ATTENDEDTEXTMODE_UNATTENDEDGUIMODE
  499. VOID SpGetServerType(
  500. )
  501. {
  502. int ServerTypes, i;
  503. PWSTR Server[] = {
  504. L"Web Server",
  505. L"File Server",
  506. L"DHCP Server"
  507. };
  508. ULONG MenuTopY;
  509. ULONG MenuHeight;
  510. ULONG MenuWidth;
  511. PVOID Menu;
  512. ULONG CurrentServer;
  513. ULONG ValidKeys[] = {ASCI_CR};
  514. ULONG KeyPress;
  515. ServerTypes = 3;
  516. SpStartScreen(
  517. SP_SCRN_GET_SERVER_TYPE,
  518. 3,
  519. CLIENT_TOP+1,
  520. FALSE,
  521. FALSE,
  522. DEFAULT_ATTRIBUTE
  523. );
  524. MenuTopY =NextMessageTopLine + 2;
  525. Menu = SpMnCreate(3,
  526. MenuTopY,
  527. VideoVars.ScreenWidth -6,
  528. ServerTypes);
  529. if (Menu==NULL) {
  530. return;
  531. }
  532. for (i=0;i<ServerTypes;i++) {
  533. CurrentServer = (ULONG) i;
  534. SpMnAddItem(Menu,
  535. Server[i],
  536. 3,
  537. VideoVars.ScreenWidth -6,
  538. TRUE,
  539. CurrentServer
  540. );
  541. }
  542. SpMnDisplay(Menu,
  543. 0,
  544. TRUE,
  545. ValidKeys,
  546. NULL,
  547. NULL,
  548. NULL,
  549. &KeyPress,
  550. &CurrentServer
  551. );
  552. switch(KeyPress){
  553. case ASCI_CR:
  554. SpMnDestroy(Menu);
  555. break;
  556. default:
  557. SpMnDestroy(Menu);
  558. }
  559. // Add information to the inf file to setup the correct server
  560. return;
  561. }
  562. VOID
  563. SpGetServerDetails(
  564. )
  565. {
  566. // Get the type of server that needs to be installed on the machine.
  567. WCHAR *Constants[1];
  568. // Assume licenses are purchased per seat
  569. Constants[0]=L"PERSEAT";
  570. SpAddLineToSection(WinntSifHandle,L"LicenseFilePrintData",L"AutoMode",Constants,1);
  571. //Turn on Terminal Services
  572. Constants[0] = L"ON";
  573. SpAddLineToSection(WinntSifHandle,L"Components",L"TSEnable",Constants,1);
  574. // In order that the terminal server comes up properly, we need to make sure
  575. // that the network cards are properly configured. In the case of a multihomed
  576. // NIC or cases we cannot use dhcp, we need to statically configure addresses.
  577. // will try to do this in the GUI setup. now try to determine the type of server
  578. // to install.
  579. SpGetServerType();
  580. return;
  581. }
  582. VOID
  583. SpGetTimeZone(
  584. )
  585. {
  586. ULONG MenuTopY;
  587. ULONG MenuHeight;
  588. ULONG MenuWidth;
  589. PVOID Menu;
  590. ULONG ValidKeys[] = {ASCI_CR};
  591. ULONG KeyPress;
  592. int i,TimeZones;
  593. ULONG CurrentTimeZone=4;
  594. WCHAR *Constants[1];
  595. WCHAR Temp[20];
  596. PWSTR TimeZone[] = {
  597. L" -12:00 Dateline : Eniwetok, Kwajalein",
  598. L" -11:00 Samoa : Midway Island, Samoa",
  599. L" -10:00 Hawaiian : Hawaii",
  600. L" -09:00 Alaskan : Alaska",
  601. L" -08:00 Pacific : Pacific Time (US & Canada); Tijuana",
  602. L" -07:00 Mountain : Mountain Time (US & Canada)",
  603. L" -07:00 US Mountain : Arizona",
  604. L" -06:00 Central : Central Time (US & Canada)",
  605. L" -06:00 Canada Central : Saskatchewan",
  606. L" -06:00 Mexico : Mexico City, Tegucigalpa",
  607. L" -05:00 Eastern : Eastern Time (US & Canada)",
  608. L" -05:00 US Eastern : Indiana (East)",
  609. L" -05:00 SA Pacific : Bogota, Lima, Quito",
  610. L" -04:00 Atlantic : Atlantic Time (Canada)",
  611. L" -04:00 SA Western : Caracas, La Paz",
  612. L" -03:30 Newfoundland : Newfoundland",
  613. L" -03:00 E. South America : Brasilia",
  614. L" -03:00 SA Eastern : Buenos Aires, Georgetown",
  615. L" -02:00 Mid-Atlantic : Mid-Atlantic",
  616. L" -01:00 Azores: Azores, Cape Verde Is.",
  617. L" 00:00 GMT : Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London",
  618. L" 00:00 Greenwich : Casablanca, Monrovia",
  619. L" +01:00 Central Europe : Belgrade, Bratislava, Budapest, Ljubljana, Prague",
  620. L" +01:00 Central European : Sarajevo, Skopje, Sofija, Warsaw, Zagreb",
  621. L" +01:00 Romance : Brussels, Copenhagen, Madrid, Paris, Vilnius",
  622. L" +01:00 W. Europe : Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna",
  623. L" +02:00 E. Europe : Bucharest",
  624. L" +02:00 Egypt : Cairo",
  625. L" +02:00 FLE : Helsinki, Riga, Tallinn",
  626. L" +02:00 GTB : Athens, Istanbul, Minsk",
  627. L" +02:00 Israel : IsraeL",
  628. L" +02:00 South Africa : Harare, Pretoria",
  629. L" +03:00 Russian : Moscow, St. Petersburg, Volgograd",
  630. L" +03:00 Arab : Baghdad, Kuwait, Riyadh",
  631. L" +03:00 E. Africa : Nairobi",
  632. L" +03:30 Iran : Tehran",
  633. L" +04:00 Arabian : Abu Dhabi, Muscat",
  634. L" +04:00 Caucasus : Baku, Tbilisi",
  635. L" +04:30 Afghanistan : KabuL",
  636. L" +05:00 Ekaterinburg : Ekaterinburg",
  637. L" +05:00 West Asia : Islamabad, Karachi, Tashkent",
  638. L" +05:30 India : Bombay, Calcutta, Madras, New Delhi",
  639. L" +06:00 Central Asia : Almaty, Dhaka",
  640. L" +06:00 Sri Lanka : Colombo",
  641. L" +07:00 SE Asia : Bangkok, Hanoi, Jakarta",
  642. L" +08:00 China : Beijing, Chongqing, Hong Kong, Urumqi",
  643. L" +08:00 Singapore : Singapore",
  644. L" +08:00 Taipei : Taipei",
  645. L" +08:00 W. Australia : Perth",
  646. L" +09:00 Korea : SeouL",
  647. L" +09:00 Tokyo : Osaka, Sapporo, Tokyo",
  648. L" +09:00 Yakutsk : Yakutsk",
  649. L" +09:30 AUS Central : Darwin",
  650. L" +09:30 Cen. Australia : Adelaide",
  651. L" +10:00 AUS Eastern : Canberra, Melbourne, Sydney",
  652. L" +10:00 E. Australia : Brisbane",
  653. L" +10:00 Tasmania : Hobart",
  654. L" +10:00 Vladivostok : Vladivostok",
  655. L" +10:00 West Pacific : Guam, Port Moresby",
  656. L" +11:00 Central Pacific : Magadan, Solomon Is., New Caledonia",
  657. L" +12:00 Fiji: Fiji, Kamchatka, Marshall Is.",
  658. L" +12:00 New Zealand : Auckland, Wellington"
  659. };
  660. ULONG TimeZoneIndex[] = {
  661. 0,
  662. 1,
  663. 2,
  664. 3,
  665. 4,
  666. 10,
  667. 15,
  668. 20,
  669. 25,
  670. 30,
  671. 35,
  672. 40,
  673. 45,
  674. 50,
  675. 55,
  676. 60,
  677. 65,
  678. 70,
  679. 75,
  680. 80,
  681. 85,
  682. 90,
  683. 95,
  684. 100,
  685. 105,
  686. 110,
  687. 115,
  688. 120,
  689. 125,
  690. 130,
  691. 135,
  692. 140,
  693. 145,
  694. 150,
  695. 155,
  696. 160,
  697. 165,
  698. 170,
  699. 175,
  700. 180,
  701. 185,
  702. 190,
  703. 195,
  704. 200,
  705. 205,
  706. 210,
  707. 215,
  708. 220,
  709. 225,
  710. 230,
  711. 235,
  712. 240,
  713. 245,
  714. 250,
  715. 255,
  716. 260,
  717. 265,
  718. 270,
  719. 275,
  720. 280,
  721. 285,
  722. 290
  723. };
  724. TimeZones = sizeof(TimeZoneIndex)/sizeof(ULONG);
  725. SpStartScreen(
  726. SP_SCRN_GET_TIME_ZONE,
  727. 3,
  728. CLIENT_TOP+1,
  729. FALSE,
  730. FALSE,
  731. DEFAULT_ATTRIBUTE
  732. );
  733. MenuTopY =NextMessageTopLine + 2;
  734. Menu = SpMnCreate(
  735. 3,
  736. MenuTopY,
  737. VideoVars.ScreenWidth -6,
  738. 10);
  739. if (Menu==NULL) {
  740. Constants[0] = L"4";
  741. SpAddLineToSection(WinntSifHandle,WINNT_GUIUNATTENDED_W,
  742. L"TimeZone",Constants,1);
  743. return;
  744. }
  745. for (i=0;i<TimeZones;i++) {
  746. SpMnAddItem(Menu,
  747. TimeZone[i],
  748. 3,
  749. VideoVars.ScreenWidth -6,
  750. TRUE,
  751. TimeZoneIndex[i]
  752. );
  753. }
  754. SpMnDisplay(Menu,
  755. 0,
  756. TRUE,
  757. ValidKeys,
  758. NULL,
  759. NULL,
  760. NULL,
  761. &KeyPress,
  762. &CurrentTimeZone
  763. );
  764. switch(KeyPress){
  765. case ASCI_CR:
  766. SpMnDestroy(Menu);
  767. break;
  768. default:
  769. SpMnDestroy(Menu);
  770. }
  771. swprintf(Temp,L"%ld",CurrentTimeZone);
  772. Constants[0] = Temp;
  773. SpAddLineToSection(WinntSifHandle,WINNT_GUIUNATTENDED_W,
  774. L"TimeZone",Constants,1);
  775. return;
  776. }
  777. ValidationValue
  778. SpGetAsciiCB(
  779. IN ULONG Key
  780. )
  781. {
  782. if (Key & KEY_NON_CHARACTER) {
  783. return(ValidateReject);
  784. }
  785. return(ValidateAccept);
  786. }
  787. VOID
  788. SpGetNecessaryParameters(
  789. )
  790. /*+++
  791. Reads in the necessary input values to allow GUI mode setup to proceed
  792. unattended.
  793. 1. Name of person
  794. 2. Computer Name
  795. 3. Organization
  796. 4. Timezone
  797. ---*/
  798. {
  799. /*+++
  800. Get Full Name of the User and the Organization
  801. ---*/
  802. WCHAR *Buffer[3];
  803. WCHAR *InputBuffer[3];
  804. WCHAR CompBuffer[200], NameBuffer[200], OrgBuffer[200];
  805. WCHAR Comp[40], Name[40], Org[40];
  806. ULONG Top[3];
  807. int index=0;
  808. int i;
  809. BOOLEAN notdone = TRUE;
  810. BOOLEAN status;
  811. WCHAR *Constants[1];
  812. Buffer[0] = NameBuffer;
  813. Buffer[1] = OrgBuffer;
  814. Buffer[2] = CompBuffer;
  815. InputBuffer[0] = Name;
  816. InputBuffer[1] = Org;
  817. InputBuffer[2] = Comp;
  818. for(i=0;i<3;i++){
  819. swprintf(Buffer[i],L"");
  820. swprintf(InputBuffer[i],L"");
  821. }
  822. do{
  823. notdone= FALSE;
  824. SpStartScreen(
  825. SP_SCRN_GET_GUI_STUFF,
  826. 3,
  827. CLIENT_TOP+1,
  828. FALSE,
  829. FALSE,
  830. DEFAULT_ATTRIBUTE
  831. );
  832. SpFormatMessage(NameBuffer,sizeof(NameBuffer),SP_TEXT_NAME_PROMPT);
  833. //SpvidDisplayString(Buffer[0],DEFAULT_ATTRIBUTE,3,NextMessageTopLine);
  834. SpContinueScreen(SP_TEXT_NAME_PROMPT,3,3,FALSE, DEFAULT_ATTRIBUTE);
  835. Top[0] = NextMessageTopLine - 1;
  836. SpFormatMessage(OrgBuffer,sizeof(OrgBuffer),SP_TEXT_ORG_PROMPT);
  837. //SpvidDisplayString(Buffer[1],DEFAULT_ATTRIBUTE,3,NextMessageTopLine);
  838. SpContinueScreen(SP_TEXT_ORG_PROMPT,3,3,FALSE, DEFAULT_ATTRIBUTE);
  839. Top[1] = NextMessageTopLine - 1;
  840. SpFormatMessage(CompBuffer,sizeof(CompBuffer),SP_TEXT_COMPUTER_PROMPT);
  841. //SpvidDisplayString(Buffer[2],DEFAULT_ATTRIBUTE,3,NextMessageTopLine);
  842. SpContinueScreen(SP_TEXT_COMPUTER_PROMPT,3,3,FALSE, DEFAULT_ATTRIBUTE);
  843. Top[2] = NextMessageTopLine - 1;
  844. index = 0;
  845. do{
  846. status = SpGetInput(SpGetAsciiCB,
  847. SplangGetColumnCount(Buffer[index])+5,
  848. Top[index],
  849. 20,
  850. InputBuffer[index],
  851. FALSE,
  852. 0
  853. );
  854. index = (index+1) %3;
  855. }while (index != 0);
  856. for(i=0;i<3;i++){
  857. if (wcscmp(InputBuffer[i],L"")==0) {
  858. notdone=TRUE;
  859. }
  860. }
  861. }while(notdone);
  862. SpAddLineToSection(WinntSifHandle,WINNT_USERDATA_W,
  863. WINNT_US_FULLNAME_W,InputBuffer,1);
  864. SpAddLineToSection(WinntSifHandle,WINNT_USERDATA_W,
  865. WINNT_US_ORGNAME_W,&(InputBuffer[1]),1);
  866. SpAddLineToSection(WinntSifHandle,WINNT_USERDATA_W,
  867. WINNT_US_COMPNAME_W,&(InputBuffer[2]),1);
  868. Constants[0] = L"1";
  869. SpAddLineToSection(WinntSifHandle,WINNT_GUIUNATTENDED_W,
  870. L"OemSkipWelcome",Constants,1);
  871. SpAddLineToSection(WinntSifHandle,WINNT_GUIUNATTENDED_W,
  872. L"OemSkipRegional",Constants,1);
  873. // Get the Timezone Information
  874. SpGetTimeZone();
  875. Constants[0] =L"*";
  876. SpAddLineToSection(WinntSifHandle,WINNT_GUIUNATTENDED_W, L"AdminPassword",Constants,1);
  877. Constants[0]=L"Yes";
  878. SpAddLineToSection(WinntSifHandle,WINNT_GUIUNATTENDED_W,L"AutoLogon",Constants,1);
  879. SpAddLineToSection(WinntSifHandle,L"Networking",L"ProcessPageSections",Constants,1);
  880. Constants[0]=L"Dummy";
  881. SpAddLineToSection(WinntSifHandle,L"Identification",L"JoinWorkgroup",Constants,1);
  882. Constants[0] = L"%systemroot%\\rccser\\rccser.exe";
  883. SpAddLineToSection(WinntSifHandle,L"GuiRunOnce",NULL,Constants,1);
  884. return;
  885. }
  886. #endif
  887. NTSTATUS
  888. SpRenameSetupAPILog(
  889. PDISK_REGION TargetRegion,
  890. PCWSTR TargetPath
  891. );
  892. NTSTATUS
  893. SpProcessMigrateInfFile(
  894. IN PVOID InfHandle
  895. );
  896. NTSTATUS
  897. SpProcessUnsupDrvInfFile(
  898. IN PVOID InfHandle
  899. );
  900. NTSTATUS
  901. SpCheckForDockableMachine(
  902. );
  903. VOID
  904. SpCheckForBadBios(
  905. );
  906. void
  907. SpUpgradeToNT50FileSystems(
  908. PVOID SifHandle,
  909. PDISK_REGION SystemPartitionRegion,
  910. PDISK_REGION NTPartitionRegion,
  911. PWSTR SetupSourceDevicePath,
  912. PWSTR DirectoryOnSetupSource
  913. );
  914. //
  915. // From spcopy.c.
  916. //
  917. BOOLEAN
  918. SpDelEnumFile(
  919. IN PCWSTR DirName,
  920. IN PFILE_BOTH_DIR_INFORMATION FileInfo,
  921. OUT PULONG ret,
  922. IN PVOID Pointer
  923. );
  924. //begin NEC98
  925. VOID
  926. SpCheckHiveDriveLetters(
  927. VOID
  928. );
  929. VOID
  930. SpSetHiveDriveLetterNec98(
  931. BOOLEAN DriveAssign_AT
  932. );
  933. VOID
  934. SpDeleteDriveLetterFromNTFTNec98(
  935. VOID
  936. );
  937. VOID
  938. SpDeleteDriveLetterFromNTFTWorkerNec98(
  939. VOID
  940. );
  941. NTSTATUS
  942. SpDiskRegistryQueryRoutineNec98(
  943. IN PWSTR ValueName,
  944. IN ULONG ValueType,
  945. IN PVOID ValueData,
  946. IN ULONG ValueLength,
  947. IN PVOID Context,
  948. IN PVOID EntryContext
  949. );
  950. extern VOID
  951. SpPtRemapDriveLetters(
  952. IN BOOLEAN DriveAssign_AT
  953. );
  954. extern VOID
  955. SpPtAssignDriveLetters(
  956. VOID
  957. );
  958. //end NEC98
  959. ValidationValue
  960. SpValidateAdminPassword(
  961. IN ULONG Key
  962. )
  963. {
  964. //
  965. // if the user hits F3,
  966. // then bail the SpGetInput so that
  967. // we can restart the process of getting
  968. // the admin's password again
  969. //
  970. if( Key == KEY_F3 ) {
  971. //
  972. // see if the user wants to exit setup
  973. //
  974. SpConfirmExit();
  975. //
  976. // we didnt exit, so bail from SpGetInput
  977. //
  978. return ValidateTerminate;
  979. }
  980. if( (Key > 0x20) && (Key < 0x7F) ) {
  981. // The key fits our criteria.
  982. return(ValidateAccept);
  983. }
  984. return(ValidateReject);
  985. }
  986. BOOLEAN
  987. SpGetAdministratorPassword(
  988. PWCHAR AdministratorPassword,
  989. ULONG MaxPasswordLength
  990. )
  991. /*++
  992. Routine Description:
  993. This routine asks the user for an administrator password.
  994. The contents of the response are checked to ensure the password
  995. is reasonable. If the response is not deemed reasonable, then
  996. the user is informed and requeried.
  997. Arguments:
  998. AdministratorPassword - Pointer to a string which holds the password.
  999. MaxPasswordLength - size of the AdministratorPassword buffer.
  1000. Return Value:
  1001. Returns TRUE if the password is successfully retrieved.
  1002. FALSE otherwise.
  1003. --*/
  1004. {
  1005. #define MY_MAX_PASSWORD_LENGTH (20)
  1006. BOOLEAN Done = FALSE;
  1007. WCHAR ConfirmAdministratorPassword[MY_MAX_PASSWORD_LENGTH+1];
  1008. ULONG AdminValidKeys[] = { KEY_F3, ASCI_CR };
  1009. BOOLEAN GotAPassword;
  1010. if( (AdministratorPassword == NULL) || (MaxPasswordLength == 0) ) {
  1011. return FALSE;
  1012. }
  1013. //
  1014. // Keep asking the user until we get what we want.
  1015. //
  1016. Done = FALSE;
  1017. do {
  1018. SpDisplayStatusOptions( DEFAULT_STATUS_ATTRIBUTE,
  1019. SP_STAT_F3_EQUALS_EXIT,
  1020. 0 );
  1021. SpDisplayScreen( SP_SCRN_GET_ADMIN_PASSWORD, 3, 4 );
  1022. SpInputDrain();
  1023. AdministratorPassword[0] = TEXT('\0');
  1024. GotAPassword = SpGetInput(
  1025. SpValidateAdminPassword,
  1026. 27, // left edge of edit field.
  1027. NextMessageTopLine - 1,
  1028. (MaxPasswordLength < MY_MAX_PASSWORD_LENGTH) ? MaxPasswordLength : MY_MAX_PASSWORD_LENGTH,
  1029. AdministratorPassword,
  1030. FALSE,
  1031. L'*' );
  1032. if( GotAPassword && wcscmp( AdministratorPassword, TEXT("") ) ) {
  1033. //
  1034. // Ask them to re-enter the password so we can make
  1035. // sure we got it right.
  1036. //
  1037. SpDisplayScreen( SP_SCRN_GET_ADMIN_PASSWORD_CONFIRM, 3, 4 );
  1038. SpInputDrain();
  1039. ConfirmAdministratorPassword[0] = TEXT('\0');
  1040. GotAPassword = SpGetInput(
  1041. SpValidateAdminPassword,
  1042. 27, // left edge of edit field.
  1043. NextMessageTopLine - 1,
  1044. MY_MAX_PASSWORD_LENGTH,
  1045. ConfirmAdministratorPassword,
  1046. FALSE,
  1047. L'*' );
  1048. //
  1049. // if the user exited normaly - pressed return,
  1050. // then process the password
  1051. // else recycle back to the first admin password screen
  1052. //
  1053. if (GotAPassword) {
  1054. if( !wcscmp(AdministratorPassword, ConfirmAdministratorPassword) ) {
  1055. //
  1056. // They match and they're not empty.
  1057. //
  1058. Done = TRUE;
  1059. } else {
  1060. //
  1061. // They didn't enter the same password.
  1062. //
  1063. SpDisplayScreen( SP_SCRN_GET_ADMIN_PASSWORD_FAILURE, 3, 4 );
  1064. SpDisplayStatusOptions(
  1065. DEFAULT_STATUS_ATTRIBUTE,
  1066. SP_STAT_ENTER_EQUALS_CONTINUE,
  1067. SP_STAT_F3_EQUALS_EXIT,
  1068. 0
  1069. );
  1070. SpInputDrain();
  1071. switch(SpWaitValidKey(AdminValidKeys,NULL,NULL)) {
  1072. //
  1073. // User wants to continue.
  1074. //
  1075. case ASCI_CR:
  1076. break;
  1077. //
  1078. // User wants to exit.
  1079. //
  1080. case KEY_F3:
  1081. SpConfirmExit();
  1082. break;
  1083. }
  1084. }
  1085. }
  1086. }
  1087. } while ( !Done );
  1088. return TRUE;
  1089. }
  1090. VOID
  1091. SpMigrateDeviceInstanceData(
  1092. VOID
  1093. )
  1094. {
  1095. NTSTATUS status;
  1096. PVOID tmpWinntSifHandle = NULL;
  1097. ULONG lineCount, errorLine, lineIndex;
  1098. PWSTR keyName, keyValue;
  1099. ULONG ulDisposition, drvInst;
  1100. DWORD valueData;
  1101. UNICODE_STRING unicodeString, valueName, drvInstString;
  1102. OBJECT_ATTRIBUTES obja;
  1103. HANDLE hControlClassKey, hClassGuidKey, hClassGuidSubkey;
  1104. HANDLE hEnumKey, hEnumeratorKey, hDeviceKey, hInstanceKey, hLogConfKey;
  1105. PWSTR classGuid, classGuidSubkey;
  1106. PWSTR enumerator, device, instance;
  1107. //
  1108. // Use the asrpnp.sif file, if present, otherwise use winnt.sif.
  1109. //
  1110. if (SetupldrASRPnPSifFileSize != 0) {
  1111. status = SpLoadSetupTextFile(NULL,
  1112. SetupldrASRPnPSifFile,
  1113. SetupldrASRPnPSifFileSize,
  1114. &tmpWinntSifHandle,
  1115. &errorLine,
  1116. FALSE,
  1117. TRUE
  1118. );
  1119. } else {
  1120. status = SpLoadSetupTextFile(NULL,
  1121. SetupldrWinntSifFile,
  1122. SetupldrWinntSifFileSize,
  1123. &tmpWinntSifHandle,
  1124. &errorLine,
  1125. FALSE,
  1126. TRUE
  1127. );
  1128. }
  1129. if (!NT_SUCCESS(status)) {
  1130. return;
  1131. }
  1132. //
  1133. // Process the section for hash values to migrate
  1134. //
  1135. lineCount = SpCountLinesInSection(tmpWinntSifHandle,
  1136. WINNT_DEVICEHASHVALUES_W);
  1137. if (lineCount != 0) {
  1138. //
  1139. // There are hash values in the sif file that need to be migrated.
  1140. // Open the Enum branch of the registry.
  1141. //
  1142. INIT_OBJA(&obja,
  1143. &unicodeString,
  1144. L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum");
  1145. status = ZwCreateKey(&hEnumKey,
  1146. KEY_ALL_ACCESS,
  1147. &obja,
  1148. 0,
  1149. NULL,
  1150. REG_OPTION_NON_VOLATILE,
  1151. &ulDisposition);
  1152. if (NT_SUCCESS(status)) {
  1153. //
  1154. // Make sure that the Enum key has already been created by
  1155. // kernel-mode PnP. This is important because kernel-mode PnP
  1156. // creates the key with special ACLs.
  1157. //
  1158. ASSERT(ulDisposition == REG_OPENED_EXISTING_KEY);
  1159. for (lineIndex = 0; lineIndex < lineCount; lineIndex++) {
  1160. //
  1161. // key name is the hash value name
  1162. //
  1163. keyName = SpGetKeyName(tmpWinntSifHandle,
  1164. WINNT_DEVICEHASHVALUES_W,
  1165. lineIndex);
  1166. if ((keyName == NULL) || (wcslen(keyName) == 0)) {
  1167. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1168. "SETUP: Unable to get the hash value, Section = %ls \n",
  1169. WINNT_DEVICEHASHVALUES_W));
  1170. continue;
  1171. }
  1172. //
  1173. // key value index == 0 is the hash value data
  1174. //
  1175. keyValue = SpGetSectionKeyIndex(tmpWinntSifHandle,
  1176. WINNT_DEVICEHASHVALUES_W,
  1177. keyName, 0);
  1178. if ((keyValue == NULL) || (wcslen(keyValue) == 0)) {
  1179. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1180. "SETUP: Unable to get the hash value data, Section = %ls, hash = %ls\n",
  1181. WINNT_DEVICEHASHVALUES_W, keyName));
  1182. continue;
  1183. }
  1184. RtlInitUnicodeString(&unicodeString, keyValue);
  1185. status = RtlUnicodeStringToInteger(&unicodeString,
  1186. 0, // base 10 (or as specified)
  1187. &valueData);
  1188. if (NT_SUCCESS(status)) {
  1189. RtlInitUnicodeString(&valueName, SpDupStringW(keyName));
  1190. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL,
  1191. "SETUP: Migrating hash value: %ls = %ls\n",
  1192. keyName, keyValue));
  1193. //
  1194. // Create the hash value under the Enum branch
  1195. //
  1196. status = ZwSetValueKey(hEnumKey,
  1197. &valueName,
  1198. 0, // XXX TITLE_INDEX_VALUE
  1199. REG_DWORD,
  1200. &valueData,
  1201. sizeof(DWORD));
  1202. }
  1203. if (!NT_SUCCESS(status)) {
  1204. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1205. "SETUP: Unable to set hash value entry %ws\n",
  1206. valueName.Buffer));
  1207. }
  1208. SpMemFree(valueName.Buffer);
  1209. }
  1210. //
  1211. // Close the Enum key
  1212. //
  1213. ZwClose(hEnumKey);
  1214. } else {
  1215. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1216. "SETUP: Unable to open Enum key, status == %08lx\n",
  1217. status));
  1218. }
  1219. }
  1220. //
  1221. // Process the section for class keys to migrate
  1222. //
  1223. lineCount = SpCountLinesInSection(tmpWinntSifHandle,
  1224. WINNT_CLASSKEYS_W);
  1225. if (lineCount != 0) {
  1226. //
  1227. // Open the Class key of the registry
  1228. //
  1229. INIT_OBJA(&obja,
  1230. &unicodeString,
  1231. L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class");
  1232. status = ZwCreateKey(&hControlClassKey,
  1233. KEY_ALL_ACCESS,
  1234. &obja,
  1235. 0,
  1236. NULL,
  1237. REG_OPTION_NON_VOLATILE,
  1238. &ulDisposition);
  1239. if (NT_SUCCESS(status)) {
  1240. //
  1241. // Verify that the key was already present
  1242. //
  1243. ASSERT(ulDisposition == REG_OPENED_EXISTING_KEY);
  1244. //
  1245. // Migrate the Class keys in the sif file
  1246. //
  1247. for (lineIndex = 0; lineIndex < lineCount; lineIndex++) {
  1248. //
  1249. // Index == 0 of each line in the classkeys section is the name
  1250. // of a Class subkey to be created
  1251. //
  1252. keyName = SpGetSectionLineIndex(tmpWinntSifHandle,
  1253. WINNT_CLASSKEYS_W,
  1254. lineIndex, 0);
  1255. if (keyName == NULL) {
  1256. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1257. "SETUP: Unable to get the Class subkey, Section = %ls \n",
  1258. WINNT_CLASSKEYS_W));
  1259. continue;
  1260. }
  1261. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Migrating class key = %ls. \n", keyName));
  1262. //
  1263. // Make a copy of the class subkey path
  1264. //
  1265. classGuid = SpDupStringW(keyName);
  1266. if (!classGuid) {
  1267. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1268. "SETUP: Cannot create the migrated Class subkey %ws\n",
  1269. keyName));
  1270. continue;
  1271. }
  1272. //
  1273. // Separate the class GUID key and subkey strings
  1274. //
  1275. classGuidSubkey = wcschr(classGuid, L'\\');
  1276. ASSERT(classGuidSubkey);
  1277. if (classGuidSubkey == NULL) {
  1278. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1279. "SETUP: Cannot create the migrated Class subkey %ws\n",
  1280. keyName));
  1281. SpMemFree(classGuid);
  1282. continue;
  1283. }
  1284. *classGuidSubkey = L'\0';
  1285. classGuidSubkey++;
  1286. //
  1287. // Create/open the class GUID key under the Control\Class key
  1288. //
  1289. INIT_OBJA(&obja,
  1290. &unicodeString,
  1291. classGuid);
  1292. obja.RootDirectory = hControlClassKey;
  1293. status = ZwCreateKey(&hClassGuidKey,
  1294. KEY_ALL_ACCESS,
  1295. &obja,
  1296. 0,
  1297. NULL,
  1298. REG_OPTION_NON_VOLATILE,
  1299. NULL);
  1300. if (NT_SUCCESS(status)) {
  1301. //
  1302. // Create/open the class GUID subkey under the class GUID key
  1303. //
  1304. INIT_OBJA(&obja,
  1305. &unicodeString,
  1306. classGuidSubkey);
  1307. obja.RootDirectory = hClassGuidKey;
  1308. status = ZwCreateKey(&hClassGuidSubkey,
  1309. KEY_ALL_ACCESS,
  1310. &obja,
  1311. 0,
  1312. NULL,
  1313. REG_OPTION_NON_VOLATILE,
  1314. NULL);
  1315. if (NT_SUCCESS(status)) {
  1316. //
  1317. // Close the Class GUID subkey
  1318. //
  1319. ZwClose(hClassGuidSubkey);
  1320. } else {
  1321. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1322. "SETUP: Unable to create subkey %ws for class %ws, status == %08lx\n",
  1323. classGuid, classGuidSubkey, status));
  1324. }
  1325. //
  1326. // Close the Class GUID key
  1327. //
  1328. ZwClose(hClassGuidKey);
  1329. } else {
  1330. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1331. "SETUP: Unable to create class key %ws, status == %08lx\n",
  1332. classGuid, status));
  1333. }
  1334. //
  1335. // Free the allocated string
  1336. //
  1337. SpMemFree(classGuid);
  1338. }
  1339. //
  1340. // Close the Control\Class key
  1341. //
  1342. ZwClose(hControlClassKey);
  1343. } else {
  1344. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1345. "SETUP: Unable to open Control\\Class key, status == %08lx\n",
  1346. status));
  1347. }
  1348. }
  1349. //
  1350. // Process the section for device instances to migrate
  1351. //
  1352. lineCount = SpCountLinesInSection(tmpWinntSifHandle,
  1353. WINNT_DEVICEINSTANCES_W);
  1354. if (lineCount != 0) {
  1355. //
  1356. // Open the Enum key of the registry
  1357. //
  1358. INIT_OBJA(&obja,
  1359. &unicodeString,
  1360. L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum");
  1361. status = ZwCreateKey(&hEnumKey,
  1362. KEY_ALL_ACCESS,
  1363. &obja,
  1364. 0,
  1365. NULL,
  1366. REG_OPTION_NON_VOLATILE,
  1367. &ulDisposition);
  1368. //
  1369. // Verify that the Enum key was already present
  1370. //
  1371. ASSERT(ulDisposition == REG_OPENED_EXISTING_KEY);
  1372. for (lineIndex = 0; lineIndex < lineCount; lineIndex++) {
  1373. //
  1374. // Index == 0 of each line in the deviceinstances section is a
  1375. // device instance key to be created
  1376. //
  1377. keyName = SpGetSectionLineIndex(tmpWinntSifHandle,
  1378. WINNT_DEVICEINSTANCES_W,
  1379. lineIndex, 0);
  1380. if (keyName == NULL) {
  1381. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1382. "SETUP: Unable to get the device instance path, Section = %ls \n",
  1383. WINNT_DEVICEINSTANCES_W));
  1384. continue;
  1385. }
  1386. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Migrating device instance = %ls. \n", keyName));
  1387. //
  1388. // Make a copy of the device instance path
  1389. //
  1390. enumerator = SpDupStringW(keyName);
  1391. if (!enumerator) {
  1392. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1393. "SETUP: Cannot copy device instance path %ws\n",
  1394. keyName));
  1395. continue;
  1396. }
  1397. //
  1398. // Separate the enumerator and device strings
  1399. //
  1400. device = wcschr(enumerator, L'\\');
  1401. ASSERT(device);
  1402. if (device == NULL) {
  1403. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1404. "SETUP: Cannot separate device string from device instance path %ws\n",
  1405. enumerator));
  1406. SpMemFree(enumerator);
  1407. continue;
  1408. }
  1409. *device = L'\0';
  1410. device++;
  1411. //
  1412. // Separate the device and instance strings
  1413. //
  1414. instance = wcschr(device, L'\\');
  1415. ASSERT(instance);
  1416. if (instance == NULL) {
  1417. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1418. "SETUP: Cannot separate instance string from device instance path %ws\n",
  1419. enumerator));
  1420. SpMemFree(enumerator);
  1421. continue;
  1422. }
  1423. *instance = L'\0';
  1424. instance++;
  1425. //
  1426. // Create/open the enumerator key under the Enum key
  1427. //
  1428. INIT_OBJA(&obja,
  1429. &unicodeString,
  1430. enumerator);
  1431. obja.RootDirectory = hEnumKey;
  1432. status = ZwCreateKey(&hEnumeratorKey,
  1433. KEY_ALL_ACCESS,
  1434. &obja,
  1435. 0,
  1436. NULL,
  1437. REG_OPTION_NON_VOLATILE,
  1438. NULL);
  1439. if (NT_SUCCESS(status)) {
  1440. //
  1441. // Create/open the device subkey under the enumerator key
  1442. //
  1443. INIT_OBJA(&obja,
  1444. &unicodeString,
  1445. device);
  1446. obja.RootDirectory = hEnumeratorKey;
  1447. status = ZwCreateKey(&hDeviceKey,
  1448. KEY_ALL_ACCESS,
  1449. &obja,
  1450. 0,
  1451. NULL,
  1452. REG_OPTION_NON_VOLATILE,
  1453. NULL);
  1454. //
  1455. // Close the enumerator key
  1456. //
  1457. ZwClose(hEnumeratorKey);
  1458. if (NT_SUCCESS(status)) {
  1459. //
  1460. // Create/open the instance subkey under the device key
  1461. //
  1462. INIT_OBJA(&obja,
  1463. &unicodeString,
  1464. instance);
  1465. obja.RootDirectory = hDeviceKey;
  1466. status = ZwCreateKey(&hInstanceKey,
  1467. KEY_ALL_ACCESS,
  1468. &obja,
  1469. 0,
  1470. NULL,
  1471. REG_OPTION_NON_VOLATILE,
  1472. &ulDisposition);
  1473. //
  1474. // Close the device key
  1475. //
  1476. ZwClose(hDeviceKey);
  1477. if (NT_SUCCESS(status)) {
  1478. //
  1479. // If this instance key was newly created, set a value
  1480. // indicating that it is a special migrated key.
  1481. //
  1482. if (ulDisposition == REG_CREATED_NEW_KEY) {
  1483. valueData = 1;
  1484. RtlInitUnicodeString(&valueName, L"Migrated");
  1485. status = ZwSetValueKey(hInstanceKey,
  1486. &valueName,
  1487. 0, // XXX TITLE_INDEX_VALUE
  1488. REG_DWORD,
  1489. &valueData,
  1490. sizeof(DWORD));
  1491. if (!NT_SUCCESS(status)) {
  1492. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1493. "SETUP: Unable to set Migrated == 1 for %ws, status == %08lx\n",
  1494. keyName, status));
  1495. }
  1496. }
  1497. //
  1498. // Index == 1 is the UniqueParentID
  1499. //
  1500. keyValue = SpGetSectionLineIndex(tmpWinntSifHandle,
  1501. WINNT_DEVICEINSTANCES_W,
  1502. lineIndex, 1);
  1503. if (keyValue && (wcslen(keyValue) != 0)) {
  1504. // temporarily use unicodeString for conversion
  1505. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL,
  1506. "SETUP:\tUniqueParentID = %ls. \n",
  1507. keyValue));
  1508. RtlInitUnicodeString(&unicodeString, keyValue);
  1509. status = RtlUnicodeStringToInteger(&unicodeString,
  1510. 16, // base 16
  1511. &valueData);
  1512. if (NT_SUCCESS(status)) {
  1513. RtlInitUnicodeString(&valueName, L"UniqueParentID");
  1514. status = ZwSetValueKey(hInstanceKey,
  1515. &valueName,
  1516. 0, // XXX TITLE_INDEX_VALUE
  1517. REG_DWORD,
  1518. &valueData,
  1519. sizeof(DWORD));
  1520. }
  1521. if (!NT_SUCCESS(status)) {
  1522. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1523. "SETUP: Unable to set UniqueParentID value for %ws, status == %08lx\n",
  1524. keyName, status));
  1525. }
  1526. }
  1527. //
  1528. // Index == 2 is the parent id prefix
  1529. //
  1530. keyValue = SpGetSectionLineIndex(tmpWinntSifHandle,
  1531. WINNT_DEVICEINSTANCES_W,
  1532. lineIndex, 2);
  1533. if (keyValue && (wcslen(keyValue) != 0)) {
  1534. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL,
  1535. "SETUP:\tParentIdPrefix = %ls. \n",
  1536. keyValue));
  1537. RtlInitUnicodeString(&unicodeString, keyValue);
  1538. RtlInitUnicodeString(&valueName, L"ParentIdPrefix");
  1539. status = ZwSetValueKey(hInstanceKey,
  1540. &valueName,
  1541. 0, // XXX TITLE_INDEX_VALUE
  1542. REG_SZ,
  1543. unicodeString.Buffer,
  1544. unicodeString.Length + sizeof(UNICODE_NULL));
  1545. if (!NT_SUCCESS(status)) {
  1546. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1547. "SETUP: Unable to set ParentIdPrefix value for %ws, status == %08lx\n",
  1548. keyName, status));
  1549. }
  1550. }
  1551. //
  1552. // Index == 3 is the class key name
  1553. //
  1554. keyValue = SpGetSectionLineIndex(tmpWinntSifHandle,
  1555. WINNT_DEVICEINSTANCES_W,
  1556. lineIndex, 3);
  1557. if (keyValue && (wcslen(keyValue) > GUID_STRING_LEN)) {
  1558. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP:\tClass key = %ls. \n", keyValue));
  1559. RtlInitUnicodeString(&valueName, REGSTR_VAL_DRIVER);
  1560. status = ZwSetValueKey(
  1561. hInstanceKey,
  1562. &valueName,
  1563. 0,
  1564. REG_SZ,
  1565. keyValue,
  1566. (wcslen(keyValue) + 1) * sizeof(WCHAR));
  1567. if (!NT_SUCCESS(status)) {
  1568. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1569. "SETUP: Unable to set Driver value for %ws, status == %08lx\n",
  1570. keyName, status));
  1571. }
  1572. //
  1573. // Migrate the ClassGUID value also (implied from
  1574. // the class key name), otherwise the class key name
  1575. // value may be considered invalid.
  1576. //
  1577. instance = wcschr(keyValue, L'\\');
  1578. ASSERT(instance);
  1579. ASSERT((instance - keyValue + 1) == GUID_STRING_LEN);
  1580. if ((instance != NULL) && ((instance - keyValue + 1) == GUID_STRING_LEN)) {
  1581. //
  1582. // Separate the instance subkey from the class GUID.
  1583. //
  1584. *instance = L'\0';
  1585. RtlInitUnicodeString(&valueName, REGSTR_VAL_CLASSGUID);
  1586. status = ZwSetValueKey(
  1587. hInstanceKey,
  1588. &valueName,
  1589. 0,
  1590. REG_SZ,
  1591. keyValue,
  1592. GUID_STRING_LEN * sizeof(WCHAR));
  1593. if (!NT_SUCCESS(status)) {
  1594. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1595. "SETUP: Unable to set ClassGUID value for %ws, status == %08lx\n",
  1596. keyName, status));
  1597. }
  1598. } else {
  1599. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1600. "SETUP: Cannot separate instance string class GUID for %ws\n",
  1601. keyName));
  1602. }
  1603. }
  1604. //
  1605. // Index == 4 is the Service name, migrated for ROOT
  1606. // enumerated device instances only.
  1607. //
  1608. keyValue = SpGetSectionLineIndex(tmpWinntSifHandle,
  1609. WINNT_DEVICEINSTANCES_W,
  1610. lineIndex, 4);
  1611. if (keyValue && (wcslen(keyValue) != 0)) {
  1612. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP:\tService = %ls. \n", keyValue));
  1613. RtlInitUnicodeString(&unicodeString, keyValue);
  1614. RtlInitUnicodeString(&valueName, REGSTR_VAL_SERVICE);
  1615. status = ZwSetValueKey(hInstanceKey,
  1616. &valueName,
  1617. 0, // XXX TITLE_INDEX_VALUE
  1618. REG_SZ,
  1619. unicodeString.Buffer,
  1620. unicodeString.Length + sizeof(UNICODE_NULL));
  1621. if (!NT_SUCCESS(status)) {
  1622. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1623. "SETUP: Unable to set Service value for %ws, status == %08lx\n",
  1624. keyName, status));
  1625. }
  1626. }
  1627. //
  1628. // Index == 5 is the BootConfig data, migrated for ROOT
  1629. // enumerated device instances only.
  1630. //
  1631. keyValue = SpGetSectionLineIndex(tmpWinntSifHandle,
  1632. WINNT_DEVICEINSTANCES_W,
  1633. lineIndex, 5);
  1634. if (keyValue && (wcslen(keyValue) != 0)) {
  1635. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL,
  1636. "SETUP:\tBootConfig = %ls. \n",
  1637. keyValue));
  1638. //
  1639. // Create/open the non-volatile LogConf subkey,
  1640. // under the instance key.
  1641. //
  1642. INIT_OBJA(&obja,
  1643. &unicodeString,
  1644. L"LogConf");
  1645. obja.RootDirectory = hInstanceKey;
  1646. status = ZwCreateKey(&hLogConfKey,
  1647. KEY_ALL_ACCESS,
  1648. &obja,
  1649. 0,
  1650. NULL,
  1651. REG_OPTION_NON_VOLATILE,
  1652. &ulDisposition);
  1653. if (NT_SUCCESS(status) && (ulDisposition == REG_CREATED_NEW_KEY)) {
  1654. DWORD i, length;
  1655. WCHAR szByte[3];
  1656. ULONG ulByte;
  1657. PBYTE pBootConfig = NULL;
  1658. //
  1659. // Since each character is just a nibble, make
  1660. // sure we have an even number of characters,
  1661. // else we won't have a whole number of bytes.
  1662. //
  1663. length = wcslen(keyValue);
  1664. ASSERT((length % 2) == 0);
  1665. pBootConfig = SpMemAlloc(length/2);
  1666. if (pBootConfig) {
  1667. //
  1668. // Convert the BootConfig string buffer data
  1669. // to bytes.
  1670. //
  1671. for (i = 0; i < length; i+=2) {
  1672. szByte[0] = keyValue[i];
  1673. szByte[1] = keyValue[i+1];
  1674. szByte[2] = UNICODE_NULL;
  1675. RtlInitUnicodeString(&unicodeString, szByte);
  1676. status = RtlUnicodeStringToInteger(&unicodeString,
  1677. 16,
  1678. &ulByte);
  1679. ASSERT(NT_SUCCESS(status));
  1680. ASSERT(ulByte <= 0xFF);
  1681. pBootConfig[i/2] = (BYTE)ulByte;
  1682. }
  1683. RtlInitUnicodeString(&valueName, REGSTR_VAL_BOOTCONFIG);
  1684. status = ZwSetValueKey(hLogConfKey,
  1685. &valueName,
  1686. 0, // XXX TITLE_INDEX_VALUE
  1687. REG_RESOURCE_LIST,
  1688. pBootConfig,
  1689. length/2);
  1690. if (!NT_SUCCESS(status)) {
  1691. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1692. "SETUP: Unable to set BootConfig value for %ws, status == %08lx\n",
  1693. keyName, status));
  1694. }
  1695. //
  1696. // Free the allocated BootConfig buffer.
  1697. //
  1698. SpMemFree(pBootConfig);
  1699. } else {
  1700. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1701. "SETUP: Unable to allocate BootConfig buffer for %ws\n",
  1702. keyName));
  1703. }
  1704. //
  1705. // Close the LogConf key
  1706. //
  1707. ZwClose(hLogConfKey);
  1708. }
  1709. }
  1710. //
  1711. // Index == 6 is the FirmwareIdentified value, migrated for ROOT
  1712. // enumerated device instances only.
  1713. //
  1714. keyValue = SpGetSectionLineIndex(tmpWinntSifHandle,
  1715. WINNT_DEVICEINSTANCES_W,
  1716. lineIndex, 6);
  1717. if (keyValue && (wcslen(keyValue) != 0)) {
  1718. // temporarily use unicodeString for conversion
  1719. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL,
  1720. "SETUP:\tFirmwareIdentified = %ls. \n",
  1721. keyValue));
  1722. RtlInitUnicodeString(&unicodeString, keyValue);
  1723. valueData = 0;
  1724. status = RtlUnicodeStringToInteger(&unicodeString,
  1725. 16, // base 16
  1726. &valueData);
  1727. if (NT_SUCCESS(status) && valueData != 0) {
  1728. RtlInitUnicodeString(&valueName, L"FirmwareIdentified");
  1729. status = ZwSetValueKey(hInstanceKey,
  1730. &valueName,
  1731. 0, // XXX TITLE_INDEX_VALUE
  1732. REG_DWORD,
  1733. &valueData,
  1734. sizeof(DWORD));
  1735. }
  1736. if (!NT_SUCCESS(status)) {
  1737. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1738. "SETUP: Unable to set FirmwareIdentified value for %ws, status == %08lx\n",
  1739. keyName, status));
  1740. }
  1741. }
  1742. //
  1743. // Close the instance key
  1744. //
  1745. ZwClose(hInstanceKey);
  1746. } else {
  1747. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1748. "SETUP: Unable to create instance subkey %ws for device %ws, status == %08lx\n",
  1749. instance, device, status));
  1750. }
  1751. } else {
  1752. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1753. "SETUP: Unable to create device subkey %ws for enumerator %ws, status == %08lx\n",
  1754. device, enumerator, status));
  1755. }
  1756. } else {
  1757. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1758. "SETUP: Unable to create enumerator subkey %ws, status == %08lx\n",
  1759. enumerator, status));
  1760. }
  1761. //
  1762. // Free the allocated device instance path string
  1763. //
  1764. SpMemFree(enumerator);
  1765. }
  1766. //
  1767. // Close the Enum key
  1768. //
  1769. ZwClose(hEnumKey);
  1770. }
  1771. //
  1772. // Free the loaded sif file
  1773. //
  1774. SpFreeTextFile(tmpWinntSifHandle);
  1775. }
  1776. BOOL
  1777. SpGetPnPDeviceInfo(
  1778. IN PWSTR DeviceId,
  1779. IN PSETUP_PNP_HARDWARE_ID HardwareIdDatabase,
  1780. OUT PWSTR* ServiceName,
  1781. OUT PWSTR* ClassGuid
  1782. )
  1783. /*++
  1784. Routine Description:
  1785. This routine searches the hardware id database, for an entry that matches
  1786. the hardware id passed as parameter.
  1787. If an entry is found, then the function returns the name of the service
  1788. associated to the hardware id, and its ClassGUID (if any).
  1789. Since this function is called by SpPnpNotificationCallback, it should not
  1790. use TemporaryBuffer.
  1791. If a temporary buffer is needed, then this function should allocate its own.
  1792. Arguments:
  1793. HardwareId - Pointer to a hardware id string.
  1794. ServiceName - On return, it will contain the pointer to the service name
  1795. for the device.
  1796. ClassGuid - On return, it will contain the pointer the class GUID for
  1797. the device.
  1798. Return Value:
  1799. Returns TRUE if the HardwareId was found on the database,
  1800. or FALSE otherwise.
  1801. --*/
  1802. {
  1803. PWCHAR s,lastsep;
  1804. BOOLEAN DeviceFound;
  1805. PSETUP_PNP_HARDWARE_ID p;
  1806. lastsep = DeviceId;
  1807. for(s=DeviceId; *s; s++) {
  1808. if((*s == L'*') || (*s == L'\\')) {
  1809. lastsep = s+1;
  1810. }
  1811. }
  1812. DeviceFound = FALSE;
  1813. for(p=HardwareIdDatabase; p; p=p->Next) {
  1814. //
  1815. // Check for a direct match
  1816. //
  1817. if(!_wcsicmp(p->Id,DeviceId)) {
  1818. *ServiceName = p->DriverName;
  1819. *ClassGuid = p->ClassGuid;
  1820. DeviceFound = TRUE;
  1821. break;
  1822. }
  1823. //
  1824. // If there was a '*' check for a component match
  1825. //
  1826. if((p->Id[0] == L'*') && !_wcsicmp(p->Id+1,lastsep)) {
  1827. *ServiceName = p->DriverName;
  1828. *ClassGuid = p->ClassGuid;
  1829. DeviceFound = TRUE;
  1830. break;
  1831. }
  1832. }
  1833. return(DeviceFound);
  1834. }
  1835. NTSTATUS
  1836. SpPnPNotificationCallBack(
  1837. IN PVOID NotificationStructure,
  1838. IN PVOID Context
  1839. )
  1840. /*++
  1841. Routine Description:
  1842. This is the callback function called by P&P, to inform textmode
  1843. setup of a new hardware detected.
  1844. Arguments:
  1845. NotificationStructure - Pointer to a structure of type
  1846. SETUP_DEVICE_ARRIVAL_NOTIFICATION.
  1847. Context - Context information that textmode setup provided during
  1848. notification registration.
  1849. Return Value:
  1850. Status is returned.
  1851. --*/
  1852. {
  1853. NTSTATUS Status;
  1854. UNICODE_STRING UnicodeString;
  1855. HANDLE hKey;
  1856. ULONG Length;
  1857. PWSTR Data = NULL;
  1858. ULONG DataSize;
  1859. PWSTR ServiceName = NULL;
  1860. PWSTR ClassGuid = NULL;
  1861. PWSTR p;
  1862. PWSTR HardwareID = NULL;
  1863. ULONG i;
  1864. BOOLEAN SerialPortDetected = FALSE;
  1865. PVOID Buffer = NULL;
  1866. ULONG BufferSize;
  1867. PWSTR ValueNames[] = {
  1868. REGSTR_VAL_HARDWAREID,
  1869. REGSTR_VAL_COMPATIBLEIDS
  1870. };
  1871. HARDWAREIDLIST *MyHardwareIDList = HardwareIDList;
  1872. if (!((PSETUP_DEVICE_ARRIVAL_NOTIFICATION)NotificationStructure)->InstallDriver) {
  1873. return STATUS_SUCCESS;
  1874. }
  1875. //
  1876. // Retrieve the service name for the device detected.
  1877. // To do this, we need to get each each hardware id, and determine
  1878. // if there is a service name associated with the id. If there is
  1879. // no service associated with any of the hardware ids, then we try
  1880. // find a service name associated the compatible id.
  1881. // If we can't find a service name for this device at all, then we don't
  1882. // need this device during textmode setup (ie, we don't install this
  1883. // device during textmode setup).
  1884. //
  1885. //
  1886. // Allocate a big buffer to read the registry value (service name).
  1887. // Note that this function should not use TemporaryBuffer, since
  1888. // this function can be called asyncronously at any point during setup,
  1889. // and TemporaryBuffer may be in use.
  1890. //
  1891. BufferSize = 4*1024;
  1892. Buffer = SpMemAlloc( BufferSize );
  1893. if( Buffer == NULL ) {
  1894. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpPnPNotificationCallBack() failed to allocate memory.\n"));
  1895. Status = STATUS_NO_MEMORY;
  1896. goto CleanUp;
  1897. }
  1898. for( i = 0; i < sizeof(ValueNames)/sizeof(PWSTR); i++ ) {
  1899. RtlInitUnicodeString(&UnicodeString, ValueNames[i]);
  1900. Status = ZwQueryValueKey(((PSETUP_DEVICE_ARRIVAL_NOTIFICATION)NotificationStructure)->EnumEntryKey,
  1901. &UnicodeString,
  1902. KeyValuePartialInformation,
  1903. Buffer,
  1904. BufferSize,
  1905. &Length
  1906. );
  1907. if( !NT_SUCCESS(Status) && ( Status == STATUS_BUFFER_OVERFLOW ) ) {
  1908. BufferSize = Length;
  1909. Buffer = SpMemRealloc( Buffer, BufferSize );
  1910. Status = ZwQueryValueKey(((PSETUP_DEVICE_ARRIVAL_NOTIFICATION)NotificationStructure)->EnumEntryKey,
  1911. &UnicodeString,
  1912. KeyValuePartialInformation,
  1913. Buffer,
  1914. Length,
  1915. &Length
  1916. );
  1917. }
  1918. if( !NT_SUCCESS(Status) ) {
  1919. if( i == 0 ) {
  1920. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpPnPNotificationCallBack() failed to retrieve HardwareID. Status = %lx \n", Status));
  1921. continue;
  1922. } else {
  1923. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpPnPNotificationCallBack() failed to retrieve HardwareID and CompatibleID. Status = %lx \n", Status));
  1924. SpMemFree( Buffer );
  1925. goto CleanUp;
  1926. }
  1927. }
  1928. Data = (PWCHAR)(((PKEY_VALUE_PARTIAL_INFORMATION)Buffer)->Data);
  1929. DataSize = ((PKEY_VALUE_PARTIAL_INFORMATION)Buffer)->DataLength;
  1930. for( p = Data;
  1931. (p < (PWSTR)((PUCHAR)Data + DataSize) && (*p != (WCHAR)'\0'));
  1932. p += wcslen( p ) + 1 ) {
  1933. //
  1934. // Retrieve the service name for this device
  1935. //
  1936. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: HardwareID = %ls. \n", p));
  1937. ServiceName = NULL;
  1938. ClassGuid = NULL;
  1939. //
  1940. // Now remember our list of devices for later use.
  1941. //
  1942. MyHardwareIDList = SpMemAlloc( sizeof(HARDWAREIDLIST) );
  1943. MyHardwareIDList->HardwareID = SpDupStringW( p );
  1944. MyHardwareIDList->Next = HardwareIDList;
  1945. HardwareIDList = MyHardwareIDList;
  1946. if( SpGetPnPDeviceInfo(p,
  1947. (PSETUP_PNP_HARDWARE_ID)Context,
  1948. &ServiceName,
  1949. &ClassGuid) ) {
  1950. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: HardwareID = %ls, ServiceName = %ls. \n", p, ServiceName));
  1951. if (RemoteSysPrepSetup) {
  1952. HardwareID = SpMemAlloc((wcslen(p) + 1) * sizeof(WCHAR));
  1953. if (HardwareID != NULL) {
  1954. wcscpy(HardwareID, p);
  1955. }
  1956. }
  1957. break;
  1958. }
  1959. }
  1960. if( ServiceName != NULL ) {
  1961. break;
  1962. }
  1963. }
  1964. if( ServiceName == NULL ) {
  1965. //
  1966. // We just don't care about this device during text setup phase
  1967. //
  1968. SpMemFree( Buffer );
  1969. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  1970. goto CleanUp;
  1971. }
  1972. //
  1973. // Find out if this device is a mouse or a USB keyboard
  1974. //
  1975. if( !_wcsicmp( ServiceName, L"i8042prt" ) ) {
  1976. if( !_wcsicmp( ClassGuid, KeyboardGuidString ) ) {
  1977. //
  1978. // This is a keyboard
  1979. //
  1980. StdKeyboardDetected = TRUE;
  1981. } else if( !_wcsicmp( ClassGuid, MouseGuidString ) ) {
  1982. //
  1983. // This is a Mouse Port compatible mouse
  1984. //
  1985. PS2MouseDetected = TRUE;
  1986. }
  1987. } else if( !_wcsicmp( ServiceName, L"sermouse" ) ) {
  1988. SerMouseDetected = TRUE;
  1989. } else if( !_wcsicmp( ServiceName, L"mouhid" ) ) {
  1990. UsbMouseDetected = TRUE;
  1991. } else if( !_wcsicmp( ServiceName, L"kbdhid" ) ) {
  1992. UsbKeyboardDetected = TRUE;
  1993. } else if( !_wcsicmp( ServiceName, L"serial" ) ) {
  1994. SerialPortDetected = TRUE;
  1995. }
  1996. //
  1997. // At this point Buffer is no longer needed, so we free it.
  1998. //
  1999. SpMemFree( Buffer );
  2000. BufferSize = 0;
  2001. Buffer = NULL;
  2002. //
  2003. // If the driver for this device was already loaded, then the device may
  2004. // be needed during textmode setup.
  2005. // Create a value entry called "Service" of type REG_SZ, with the name
  2006. // of the service associated with this device only if the service string is not
  2007. // empty as we allow inserting only a GUID.
  2008. //
  2009. if((NULL != ServiceName) && (UNICODE_NULL != ServiceName[0])){
  2010. RtlInitUnicodeString(&UnicodeString, REGSTR_VAL_SERVICE);
  2011. Status = ZwSetValueKey( ((PSETUP_DEVICE_ARRIVAL_NOTIFICATION)NotificationStructure)->EnumEntryKey,
  2012. &UnicodeString,
  2013. 0,
  2014. REG_SZ,
  2015. ServiceName,
  2016. (wcslen( ServiceName ) + 1)*sizeof(WCHAR) );
  2017. }
  2018. if(NT_SUCCESS( Status ) && ( NULL != ClassGuid ) ) {
  2019. RtlInitUnicodeString(&UnicodeString, REGSTR_VAL_CLASSGUID);
  2020. Status = ZwSetValueKey( ((PSETUP_DEVICE_ARRIVAL_NOTIFICATION)NotificationStructure)->EnumEntryKey,
  2021. &UnicodeString,
  2022. 0,
  2023. REG_SZ,
  2024. ClassGuid,
  2025. (wcslen(ClassGuid) + 1) * sizeof(WCHAR));
  2026. }
  2027. if( NT_SUCCESS( Status ) ) {
  2028. //
  2029. // If we successfully set the controlling service value, then we should also set
  2030. // the CONFIGFLAG_FINISH_INSTALL config flag, so that we'll finish the installation
  2031. // of this device later (i.e., when we're in user-mode and have access to the device
  2032. // installer APIs, class installers, etc.)
  2033. //
  2034. ULONG ConfigFlags = 0x00000400; // CONFIGFLAG_FINISH_INSTALL from sdk\inc\regstr.h
  2035. RtlInitUnicodeString(&UnicodeString, REGSTR_VAL_CONFIGFLAGS);
  2036. Status = ZwSetValueKey( ((PSETUP_DEVICE_ARRIVAL_NOTIFICATION)NotificationStructure)->EnumEntryKey,
  2037. &UnicodeString,
  2038. 0,
  2039. REG_DWORD,
  2040. &ConfigFlags,
  2041. sizeof(ConfigFlags) );
  2042. if( !NT_SUCCESS( Status ) ) {
  2043. goto CleanUp;
  2044. }
  2045. //
  2046. // If we are doing an installation of a SysPrep image, then we want to
  2047. // remember this device so that we can transfer it as a 'CriticalDevice'
  2048. // to the SysPrep hives in SpPatchSysPrepImage()
  2049. //
  2050. if (RemoteSysPrepSetup && (HardwareID != NULL)) {
  2051. OBJECT_ATTRIBUTES Obj;
  2052. HANDLE TmpHandle;
  2053. HANDLE NodeHandle;
  2054. PWCHAR pwch;
  2055. BufferSize = 4*1024;
  2056. Buffer = SpMemAlloc( BufferSize );
  2057. if( Buffer == NULL ) {
  2058. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpPnPNotificationCallBack() failed to allocate memory.\n"));
  2059. goto CleanSysPrepSetup;
  2060. }
  2061. INIT_OBJA(&Obj,
  2062. &UnicodeString,
  2063. L"\\Registry\\Machine\\System\\CurrentControlSet\\Control"
  2064. );
  2065. Status = ZwOpenKey(&TmpHandle, KEY_ALL_ACCESS, &Obj);
  2066. if( !NT_SUCCESS(Status) ) {
  2067. goto CleanSysPrepSetup;
  2068. }
  2069. INIT_OBJA(&Obj, &UnicodeString, L"CriticalDeviceDatabase");
  2070. Obj.RootDirectory = TmpHandle;
  2071. Status = ZwCreateKey(&NodeHandle,
  2072. KEY_ALL_ACCESS,
  2073. &Obj,
  2074. 0,
  2075. NULL,
  2076. 0,
  2077. NULL
  2078. );
  2079. ZwClose(TmpHandle);
  2080. if( !NT_SUCCESS(Status) ) {
  2081. goto CleanSysPrepSetup;
  2082. }
  2083. //
  2084. // Now create subkey with the device name
  2085. //
  2086. for (pwch = HardwareID; *pwch != UNICODE_NULL; pwch++) {
  2087. if (*pwch == L'\\') {
  2088. *pwch = L'#';
  2089. }
  2090. }
  2091. INIT_OBJA(&Obj, &UnicodeString, HardwareID);
  2092. Obj.RootDirectory = NodeHandle;
  2093. Status = ZwCreateKey(&TmpHandle,
  2094. KEY_ALL_ACCESS,
  2095. &Obj,
  2096. 0,
  2097. NULL,
  2098. 0,
  2099. NULL
  2100. );
  2101. ZwClose(NodeHandle);
  2102. if( !NT_SUCCESS(Status) ) {
  2103. goto CleanSysPrepSetup;
  2104. }
  2105. //
  2106. // Fill in service value now
  2107. //
  2108. RtlInitUnicodeString(&UnicodeString, REGSTR_VAL_SERVICE);
  2109. ZwSetValueKey(TmpHandle,
  2110. &UnicodeString,
  2111. 0,
  2112. REG_SZ,
  2113. ServiceName,
  2114. (wcslen( ServiceName ) + 1)*sizeof(WCHAR)
  2115. );
  2116. if (ClassGuid != NULL) {
  2117. RtlInitUnicodeString(&UnicodeString, REGSTR_VAL_CLASSGUID);
  2118. ZwSetValueKey(TmpHandle,
  2119. &UnicodeString,
  2120. 0,
  2121. REG_SZ,
  2122. ClassGuid,
  2123. (wcslen( ClassGuid ) + 1)*sizeof(WCHAR)
  2124. );
  2125. }
  2126. ZwClose(TmpHandle);
  2127. CleanSysPrepSetup:
  2128. if (Buffer != NULL) {
  2129. SpMemFree( Buffer );
  2130. BufferSize = 0;
  2131. Buffer = NULL;
  2132. }
  2133. }
  2134. //
  2135. // Hack for serial
  2136. //
  2137. if( SerialPortDetected ) {
  2138. // DWORD PollingPeriod = 0x32;
  2139. WCHAR SerialUpperFilters[] = L"serenum\0";
  2140. #if 0 // remove polling, will be enabled after NT5.0
  2141. Status = IoOpenDeviceRegistryKey( ((PSETUP_DEVICE_ARRIVAL_NOTIFICATION)NotificationStructure)->PhysicalDeviceObject,
  2142. PLUGPLAY_REGKEY_DEVICE,
  2143. MAXIMUM_ALLOWED,
  2144. &hKey );
  2145. if( !NT_SUCCESS( Status ) ) {
  2146. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: IoOpenDeviceRegistryKey() failed. Status = %lx. \n", Status));
  2147. goto CleanUp;
  2148. }
  2149. RtlInitUnicodeString(&UnicodeString, L"PollingPeriod");
  2150. Status = ZwSetValueKey( hKey,
  2151. &UnicodeString,
  2152. 0,
  2153. REG_DWORD,
  2154. &PollingPeriod,
  2155. sizeof(PollingPeriod) );
  2156. ZwClose( hKey );
  2157. if( !NT_SUCCESS( Status ) ) {
  2158. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: ZwSetValueKey() failed to create PollingPeriod. Status = %lx. \n", Status));
  2159. goto CleanUp;
  2160. }
  2161. #endif
  2162. RtlInitUnicodeString(&UnicodeString, REGSTR_VAL_UPPERFILTERS);
  2163. Status = ZwSetValueKey( ((PSETUP_DEVICE_ARRIVAL_NOTIFICATION)NotificationStructure)->EnumEntryKey,
  2164. &UnicodeString,
  2165. 0,
  2166. REG_MULTI_SZ,
  2167. SerialUpperFilters,
  2168. sizeof(SerialUpperFilters) );
  2169. if( !NT_SUCCESS( Status ) ) {
  2170. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: ZwSetValueKey() failed to create SerialUpperFilters. Status = %lx. \n", Status));
  2171. goto CleanUp;
  2172. }
  2173. }
  2174. }
  2175. CleanUp:
  2176. if (HardwareID != NULL) {
  2177. SpMemFree(HardwareID);
  2178. }
  2179. return Status;
  2180. }
  2181. PCOMMAND_INTERPRETER_ROUTINE _CmdRoutine;
  2182. #ifdef _IA64_
  2183. VOID
  2184. SpAssignDriveLetterToESP(
  2185. VOID
  2186. )
  2187. /*++
  2188. Routine Description:
  2189. This routine assigns a drive letter to ESP to make it accessible
  2190. from the Recovery Console
  2191. Arguments:
  2192. None
  2193. Return Value:
  2194. None
  2195. --*/
  2196. {
  2197. PDISK_REGION SystemPartitionArea = NULL;
  2198. ULONG Index;
  2199. //
  2200. // Select a system partition from among those defined in NV-RAM.
  2201. //
  2202. for(Index = 0; (Index < HardDiskCount) && (!SystemPartitionArea); Index++) {
  2203. SystemPartitionArea = SPPT_GET_PRIMARY_DISK_REGION(Index);
  2204. while (SystemPartitionArea) {
  2205. if (SPPT_IS_REGION_SYSTEMPARTITION(SystemPartitionArea)) {
  2206. break; // found the required region
  2207. }
  2208. SystemPartitionArea = SystemPartitionArea->Next;
  2209. }
  2210. }
  2211. //
  2212. // If a system partition exists
  2213. //
  2214. if (SystemPartitionArea) {
  2215. PWCHAR MyTempBuffer = NULL;
  2216. //
  2217. // Retrieve NT pathname for this region.
  2218. //
  2219. MyTempBuffer = (PWCHAR)SpMemAlloc(MAX_PATH);
  2220. if (MyTempBuffer) {
  2221. MyTempBuffer[0] = UNICODE_NULL;
  2222. SpNtNameFromRegion(SystemPartitionArea,
  2223. MyTempBuffer,
  2224. MAX_PATH,
  2225. PrimaryArcPath);
  2226. //
  2227. // Assign the drive letter to the ESP
  2228. //
  2229. SystemPartitionArea->DriveLetter = SpGetDriveLetter(MyTempBuffer, NULL);
  2230. SpMemFree(MyTempBuffer);
  2231. } else {
  2232. //
  2233. // No memory...
  2234. //
  2235. KdPrintEx(( DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  2236. "SETUP: SpPtInitializeDiskAreas: SpMemAlloc failed!\n" ));
  2237. }
  2238. }
  2239. }
  2240. #endif
  2241. VOID
  2242. CommandConsoleInterface(
  2243. PCOMMAND_INTERPRETER_ROUTINE CmdRoutine
  2244. )
  2245. {
  2246. _CmdRoutine = CmdRoutine;
  2247. }
  2248. ULONG
  2249. SpStartCommandConsole(
  2250. PVOID SifHandle,
  2251. PWSTR SetupSourceDevicePath,
  2252. PWSTR DirectoryOnSetupSource
  2253. )
  2254. {
  2255. #define CMDCONS_NAME L"SPCMDCON.SYS"
  2256. NTSTATUS Status;
  2257. static BOOLEAN Loaded = FALSE;
  2258. PWCHAR FullName;
  2259. PWCHAR ServiceKey;
  2260. UNICODE_STRING ServiceKeyU;
  2261. PWSTR pwstr;
  2262. ULONG rc;
  2263. BOOLEAN b;
  2264. OBJECT_ATTRIBUTES objectAttributes;
  2265. UNICODE_STRING unicodeString;
  2266. IO_STATUS_BLOCK ioStatusBlock;
  2267. HANDLE hFile;
  2268. PWSTR Tagfile;
  2269. PWSTR Description;
  2270. PWSTR MediaShortName;
  2271. ULONG MediaType=INDEX_WHICHBOOTMEDIA;
  2272. ULONG LoadCount;
  2273. extern PVOID KeyboardTable;
  2274. //
  2275. // Let JPN/KOR user select keyboard type before running Command Console.
  2276. //
  2277. // SplangSelectKeyboard & SplangReinitializeKeyboard are from spddlang.sys.
  2278. //
  2279. // These two functions only affect JPN/KOR builds.
  2280. //
  2281. // They are stub functions on US build and do nothing.
  2282. //
  2283. // 0xFF in SplangSelectKeyboard is a tag, such that it knows this is
  2284. // called from Command Console.
  2285. //
  2286. if (ConsoleFromWinnt32) {
  2287. SplangSelectKeyboard(
  2288. FALSE,
  2289. NULL,
  2290. 0xFF,
  2291. SifHandle,
  2292. HardwareComponents
  2293. );
  2294. SplangReinitializeKeyboard(
  2295. FALSE,
  2296. SifHandle,
  2297. DirectoryOnBootDevice,
  2298. &KeyboardTable,
  2299. HardwareComponents
  2300. );
  2301. }
  2302. pwstr = TemporaryBuffer;
  2303. //
  2304. // Form the full name of the device driver file.
  2305. //
  2306. wcscpy(pwstr,NtBootDevicePath);
  2307. SpConcatenatePaths(pwstr,DirectoryOnBootDevice);
  2308. SpConcatenatePaths(pwstr,CMDCONS_NAME);
  2309. FullName = SpDupStringW(pwstr);
  2310. //
  2311. // check to see if the file exists on the source media
  2312. // if not then prompt for the correct media
  2313. //
  2314. SpStringToLower(pwstr);
  2315. if(wcsstr(pwstr,L"cdrom"))
  2316. MediaType = INDEX_WHICHMEDIA;
  2317. else if(wcsstr(pwstr,L"floppy"))
  2318. MediaType = INDEX_WHICHBOOTMEDIA;
  2319. INIT_OBJA(&objectAttributes,&unicodeString,FullName);
  2320. MediaShortName = SpLookUpValueForFile(SifHandle,CMDCONS_NAME,MediaType,TRUE);
  2321. SpGetSourceMediaInfo(SifHandle,MediaShortName,&Description,&Tagfile,NULL);
  2322. LoadCount = 0;
  2323. do {
  2324. Status = ZwOpenFile(
  2325. &hFile,
  2326. FILE_GENERIC_READ,
  2327. &objectAttributes,
  2328. &ioStatusBlock,
  2329. 0,
  2330. 0
  2331. );
  2332. if (NT_SUCCESS(Status)) {
  2333. ZwClose(hFile);
  2334. } else {
  2335. if (!SpPromptForDisk(
  2336. Description,
  2337. NtBootDevicePath,
  2338. CMDCONS_NAME,
  2339. TRUE, // Always prompt for at least once
  2340. TRUE, // Allow user to cancel
  2341. FALSE, // No multiple prompts
  2342. NULL // don't care about redraw flag
  2343. ))
  2344. {
  2345. break;
  2346. }
  2347. //
  2348. // try once more after prompting for disk
  2349. //
  2350. LoadCount++;
  2351. }
  2352. } while (!NT_SUCCESS(Status) && (LoadCount < 2));
  2353. if (!NT_SUCCESS(Status)) {
  2354. SpStartScreen(
  2355. SP_CMDCONS_NOT_FOUND,
  2356. 0,
  2357. 0,
  2358. TRUE,
  2359. TRUE,
  2360. ATT_FG_INTENSE | ATT_FG_WHITE | ATT_BG_BLACK
  2361. );
  2362. SpInputDrain();
  2363. while(SpInputGetKeypress() != KEY_F3);
  2364. SpMemFree(FullName);
  2365. return 0;
  2366. }
  2367. //
  2368. // Create a service entry for the driver.
  2369. //
  2370. ServiceKey = NULL;
  2371. Status = SpCreateServiceEntry(FullName,&ServiceKey);
  2372. SpMemFree(FullName);
  2373. if(!NT_SUCCESS(Status)) {
  2374. return 0;
  2375. }
  2376. RtlInitUnicodeString(&ServiceKeyU,ServiceKey);
  2377. again:
  2378. if(!Loaded) {
  2379. Status = ZwLoadDriver(&ServiceKeyU);
  2380. if(NT_SUCCESS(Status)) {
  2381. Loaded = TRUE;
  2382. } else {
  2383. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to load %s (%lx)\n",CMDCONS_NAME,Status));
  2384. }
  2385. }
  2386. if(Loaded) {
  2387. Block.VideoVars = &VideoVars;
  2388. Block.TemporaryBuffer = TemporaryBuffer;
  2389. Block.TemporaryBufferSize = sizeof(TemporaryBuffer);
  2390. Block.UsetupProcess = UsetupProcess;
  2391. Block.BootDevicePath = NtBootDevicePath;
  2392. Block.DirectoryOnBootDevice = DirectoryOnBootDevice;
  2393. Block.SifHandle = SifHandle;
  2394. Block.SetupSourceDevicePath = SetupSourceDevicePath;
  2395. Block.DirectoryOnSetupSource = DirectoryOnSetupSource;
  2396. if (HeadlessTerminalConnected) {
  2397. Block.VideoVars->ScreenHeight = HEADLESS_SCREEN_HEIGHT+1;
  2398. }
  2399. // make the global variable point to the block
  2400. gpCmdConsBlock = &Block;
  2401. ConsoleRunning = TRUE;
  2402. #ifdef _IA64_
  2403. //
  2404. // Make the ESP visible so that it can be accessed from
  2405. // Recovery Console.
  2406. //
  2407. SpAssignDriveLetterToESP();
  2408. #endif
  2409. rc = _CmdRoutine(&Block);
  2410. ConsoleRunning = FALSE;
  2411. if (rc == 1) {
  2412. Status = ZwUnloadDriver(&ServiceKeyU);
  2413. if(NT_SUCCESS(Status)) {
  2414. Loaded = FALSE;
  2415. goto again;
  2416. } else {
  2417. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to un-load %s (%lx)\n",CMDCONS_NAME,Status));
  2418. }
  2419. }
  2420. #if 0
  2421. // why is this here? -matth 02/12/2001
  2422. //
  2423. // In the non-local case, this gets sent to a remote console,
  2424. // then stays there until the machine reboots and pasts post.
  2425. // This can take a really long time and confuses end users.
  2426. //
  2427. SpDisplayHeaderText(
  2428. SpGetHeaderTextId(),
  2429. DEFAULT_ATTRIBUTE
  2430. );
  2431. #endif
  2432. }
  2433. SpMemFree(ServiceKey);
  2434. return 0;
  2435. }
  2436. NTSTATUS
  2437. SpInitialize0(
  2438. IN PDRIVER_OBJECT DriverObject
  2439. )
  2440. /*++
  2441. Routine Description:
  2442. Initialize the setup device driver. This includes initializing
  2443. the memory allocator, saving away pieces of the os loader block,
  2444. and populating the registry with information about device drivers
  2445. that setupldr loaded for us.
  2446. Arguments:
  2447. DriverObject - supplies pointer to driver object for setupdd.sys.
  2448. Return Value:
  2449. Status is returned.
  2450. --*/
  2451. {
  2452. PLOADER_PARAMETER_BLOCK loaderBlock;
  2453. PSETUP_LOADER_BLOCK setupLoaderBlock;
  2454. PLIST_ENTRY nextEntry;
  2455. PBOOT_DRIVER_LIST_ENTRY bootDriver;
  2456. PWSTR ServiceName;
  2457. NTSTATUS Status = STATUS_SUCCESS;
  2458. PWSTR imagePath;
  2459. PWSTR registryPath;
  2460. UNICODE_STRING GuidString;
  2461. //
  2462. // Fetch a pointer to the os loader block and setup loader block.
  2463. //
  2464. loaderBlock = *(PLOADER_PARAMETER_BLOCK *)KeLoaderBlock;
  2465. setupLoaderBlock = loaderBlock->SetupLoaderBlock;
  2466. if ( (setupLoaderBlock->Flags & SETUPBLK_FLAGS_CONSOLE) != 0 ) {
  2467. ForceConsole = TRUE;
  2468. }
  2469. if (setupLoaderBlock->Flags & SETUPBLK_FLAGS_ROLLBACK) {
  2470. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Rollback enabled through osloadoptions"));
  2471. Win9xRollback = TRUE;
  2472. }
  2473. //
  2474. // Phase 0 display initialization.
  2475. //
  2476. SpvidInitialize0(loaderBlock);
  2477. //
  2478. // Make a copy of the ARC pathname from which we booted.
  2479. // This is guaranteed to be the ARC equivalent of \systemroot.
  2480. //
  2481. ArcBootDevicePath = SpToUnicode(loaderBlock->ArcBootDeviceName);
  2482. if ( (setupLoaderBlock->Flags & SETUPBLK_FLAGS_IS_REMOTE_BOOT) != 0 ) {
  2483. PUCHAR p;
  2484. PUCHAR q;
  2485. //
  2486. // This is a remote boot setup. NtBootPathName is of the form
  2487. // \<server>\<share>\setup\<install-directory>\<platform>.
  2488. // System initialization (in ntos\fstub\drivesup.c, routine
  2489. // xHalIoAssignDriveLetters) has assigned the C: drive to point to
  2490. // \Device\LanmanRedirector\<server>\<share>\setup\<install-directory>.
  2491. // DirectoryOnBootDevice should contain the path that needs to be
  2492. // added to C: in order to access files from user mode. So to
  2493. // calculate it, we want to start at the backslash before <platform>.
  2494. //
  2495. // N.B. We know that the strrchr calls below will not return NULL,
  2496. // because xHalIoAssignDriveLetters would have bugchecked if
  2497. // the string in NtBootPathName was malformed.
  2498. //
  2499. ASSERT( _stricmp( loaderBlock->ArcBootDeviceName, "net(0)" ) == 0 );
  2500. RemoteBootSetup = TRUE;
  2501. if (setupLoaderBlock->Flags & SETUPBLK_FLAGS_SYSPREP_INSTALL) {
  2502. RemoteSysPrepSetup = TRUE;
  2503. RemoteIMirrorFilePath = SpDupString(setupLoaderBlock->NetBootIMirrorFilePath);
  2504. RemoteServerIpAddress = setupLoaderBlock->ServerIpAddress;
  2505. RtlCopyMemory(&RemoteSysPrepNetCardInfo, setupLoaderBlock->NetbootCardInfo, sizeof(NET_CARD_INFO));
  2506. }
  2507. p = strrchr( loaderBlock->NtBootPathName, '\\' );
  2508. ASSERT( p != NULL );
  2509. if (!p)
  2510. return STATUS_OBJECT_PATH_INVALID;
  2511. if ( *(p+1) == 0 ) {
  2512. //
  2513. // NtBootPathName ends with a backslash, so we need to back up
  2514. // to the previous backslash.
  2515. //
  2516. q = p;
  2517. *q = 0;
  2518. p = strrchr( loaderBlock->NtBootPathName, '\\' ); // find last separator
  2519. ASSERT( p != NULL );
  2520. *q = '\\';
  2521. }
  2522. if (!p)
  2523. return STATUS_OBJECT_PATH_INVALID; // shut up PREfix.
  2524. DirectoryOnBootDevice = SpToUnicode(p);
  2525. SpStringToUpper(DirectoryOnBootDevice);
  2526. //
  2527. // Save this -- it is the part of loaderBlock->NtBootPathName that
  2528. // is before the part we just copied to DirectoryOnBootDevice,
  2529. // of the form \<server>\<share>\setup\<install-directory>.
  2530. // NtBootDeviceName will be initially set up as \Device\LanmanRedirector
  2531. // and DirectoryOnBootDevice was just set to be be only \<platform>
  2532. // (so user-mode access works, see discussion above). We save the
  2533. // intervening path and append it to NtBootDeviceName, so that
  2534. // kernel-mode access that uses NtBootDeviceName + DirectoryOnBootDevice
  2535. // will go to the correct path.
  2536. //
  2537. *p = 0;
  2538. RemoteIMirrorBootDirectoryPrefix = SpToUnicode(loaderBlock->NtBootPathName);
  2539. *p = '\\';
  2540. if (setupLoaderBlock->NetBootAdministratorPassword[0] != '\0') {
  2541. //
  2542. // The Admin password that came through the setupldr block may not be terminated.
  2543. // Copy it into a temporary buffer, terminate it, and then SpToUnicode it.
  2544. //
  2545. UCHAR TmpNetBootAdministratorPassword[NETBOOT_ADMIN_PASSWORD_LEN+1] = {0};
  2546. RtlMoveMemory( TmpNetBootAdministratorPassword,
  2547. setupLoaderBlock->NetBootAdministratorPassword,
  2548. NETBOOT_ADMIN_PASSWORD_LEN );
  2549. TmpNetBootAdministratorPassword[NETBOOT_ADMIN_PASSWORD_LEN] = '\0';
  2550. NetBootAdministratorPassword =
  2551. SpToUnicode( TmpNetBootAdministratorPassword );
  2552. } else if (setupLoaderBlock->NetBootAdministratorPassword[NETBOOT_ADMIN_PASSWORD_LEN-1] == 0xFF) {
  2553. //
  2554. // this indicates that the administrator password was blank.
  2555. //
  2556. NetBootAdministratorPassword = SpToUnicode( "" );
  2557. }
  2558. } else {
  2559. DirectoryOnBootDevice = SpToUnicode(loaderBlock->NtBootPathName);
  2560. SpStringToUpper(DirectoryOnBootDevice);
  2561. }
  2562. //
  2563. // Make a copy of the image of the setup information file.
  2564. //
  2565. SetupldrInfoFileSize = setupLoaderBlock->IniFileLength;
  2566. SetupldrInfoFile = SpMemAlloc(SetupldrInfoFileSize);
  2567. RtlMoveMemory(SetupldrInfoFile,setupLoaderBlock->IniFile,SetupldrInfoFileSize);
  2568. SP_SET_UPGRADE_GRAPHICS_MODE(FALSE);
  2569. //
  2570. // Make a copy of the image of the winnt.sif file.
  2571. //
  2572. SetupldrWinntSifFileSize = setupLoaderBlock->WinntSifFileLength;
  2573. if ( SetupldrWinntSifFileSize != 0 ) {
  2574. NTSTATUS Status;
  2575. ULONG ErrorLine;
  2576. SetupldrWinntSifFile = SpMemAlloc(SetupldrWinntSifFileSize);
  2577. RtlMoveMemory(SetupldrWinntSifFile,setupLoaderBlock->WinntSifFile,SetupldrWinntSifFileSize);
  2578. Status = SpLoadSetupTextFile(NULL,
  2579. SetupldrWinntSifFile,
  2580. SetupldrWinntSifFileSize,
  2581. &WinntSifHandle,
  2582. &ErrorLine,
  2583. FALSE,
  2584. TRUE);
  2585. if (NT_SUCCESS(Status)) {
  2586. PWSTR NtUpgradeValue = SpGetSectionKeyIndex(WinntSifHandle,
  2587. SIF_DATA, WINNT_D_NTUPGRADE_W, 0);
  2588. if(NtUpgradeValue && !_wcsicmp(NtUpgradeValue, WINNT_A_YES_W)) {
  2589. SP_SET_UPGRADE_GRAPHICS_MODE(TRUE);
  2590. IsNTUpgrade = UpgradeFull;
  2591. } else {
  2592. PWSTR Win9xUpgradeValue = SpGetSectionKeyIndex(WinntSifHandle,
  2593. SIF_DATA, WINNT_D_WIN95UPGRADE_W, 0);
  2594. if (Win9xUpgradeValue && !_wcsicmp(Win9xUpgradeValue, WINNT_A_YES_W)) {
  2595. SP_SET_UPGRADE_GRAPHICS_MODE(TRUE);
  2596. }
  2597. }
  2598. } else {
  2599. WinntSifHandle = NULL;
  2600. }
  2601. } else {
  2602. SetupldrWinntSifFile = NULL;
  2603. }
  2604. #ifdef _GRAPHICS_TESTING_
  2605. SP_SET_UPGRADE_GRAPHICS_MODE(TRUE);
  2606. #endif
  2607. //
  2608. // Make a copy of the image of the asrpnp.sif file.
  2609. //
  2610. SetupldrASRPnPSifFileSize = setupLoaderBlock->ASRPnPSifFileLength;
  2611. if (SetupldrASRPnPSifFileSize != 0) {
  2612. SetupldrASRPnPSifFile = SpMemAlloc(SetupldrASRPnPSifFileSize);
  2613. RtlMoveMemory(SetupldrASRPnPSifFile,setupLoaderBlock->ASRPnPSifFile,SetupldrASRPnPSifFileSize);
  2614. //
  2615. // If user provided asrpnp.sif, he wants ASR.
  2616. //
  2617. SpAsrSetAsrMode(ASRMODE_NORMAL);
  2618. RepairWinnt = FALSE;
  2619. } else {
  2620. SetupldrASRPnPSifFile = NULL;
  2621. //
  2622. // user didn't provide asrpnp.sif, he doesn't want ASR.
  2623. //
  2624. SpAsrSetAsrMode(ASRMODE_NONE);
  2625. }
  2626. //
  2627. // Make a copy of the image of the migrate.inf file.
  2628. //
  2629. SetupldrMigrateInfFileSize = setupLoaderBlock->MigrateInfFileLength;
  2630. if ( SetupldrMigrateInfFileSize != 0 ) {
  2631. SetupldrMigrateInfFile = SpMemAlloc(SetupldrMigrateInfFileSize);
  2632. RtlMoveMemory(SetupldrMigrateInfFile,setupLoaderBlock->MigrateInfFile,SetupldrMigrateInfFileSize);
  2633. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: migrate.inf was loaded. Address = %lx, size = %d \n", SetupldrMigrateInfFile, SetupldrMigrateInfFileSize));
  2634. } else {
  2635. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Couldn't load migrate.inf \n"));
  2636. SetupldrMigrateInfFile = NULL;
  2637. }
  2638. //
  2639. // NEC98 need to decide drive assign method right away(before IoAssignDriveLetters())..
  2640. //
  2641. // NEC98 has 2 kind of drive mapping method.
  2642. // One is NEC98 legacy style assign that mapping hard drive begining from A:,
  2643. // other is same as PC/AT.
  2644. //
  2645. if (IsNEC_98) { //NEC98
  2646. //
  2647. // If no winnt.sif present, we don't need to check hive.
  2648. //
  2649. if ( SetupldrWinntSifFileSize != 0 ) {
  2650. SpCheckHiveDriveLetters();
  2651. }
  2652. } //NEC98
  2653. if ((SetupldrWinntSifFileSize != 0) || (SetupldrASRPnPSifFileSize != 0)) {
  2654. SpMigrateDeviceInstanceData();
  2655. }
  2656. //
  2657. // Make a copy of the image of the unsupdrv.inf file.
  2658. //
  2659. SetupldrUnsupDrvInfFileSize = setupLoaderBlock->UnsupDriversInfFileLength;
  2660. if ( SetupldrUnsupDrvInfFileSize != 0 ) {
  2661. SetupldrUnsupDrvInfFile = SpMemAlloc(SetupldrUnsupDrvInfFileSize);
  2662. RtlMoveMemory(SetupldrUnsupDrvInfFile,setupLoaderBlock->UnsupDriversInfFile,SetupldrUnsupDrvInfFileSize);
  2663. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: driver.inf was loaded. Address = %lx, size = %d \n", SetupldrUnsupDrvInfFile, SetupldrUnsupDrvInfFileSize));
  2664. } else {
  2665. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Couldn't load unsupdrv.inf \n"));
  2666. SetupldrUnsupDrvInfFile = NULL;
  2667. }
  2668. //
  2669. // Make a copy of the scalar portions of the setup loader block.
  2670. //
  2671. SetupParameters = setupLoaderBlock->ScalarValues;
  2672. //
  2673. // Save away remote boot information.
  2674. //
  2675. if (RemoteBootSetup) {
  2676. #if defined(REMOTE_BOOT)
  2677. memcpy(NetBootHalName, setupLoaderBlock->NetBootHalName, sizeof(NetBootHalName));
  2678. #endif // defined(REMOTE_BOOT)
  2679. if (setupLoaderBlock->NetBootSifPath) {
  2680. NetBootSifPath = SpToUnicode(setupLoaderBlock->NetBootSifPath);
  2681. }
  2682. }
  2683. //
  2684. // Find out if the machine is dockable
  2685. // Note that at this point we could remove dmio.sys, dmboot.sys and dmload.sys from our lists
  2686. // if we determine that the this is a dockable machine. In this way, dynamic volumes would be
  2687. // disable during textmode setup. This should be done in the future.
  2688. //
  2689. SpCheckForDockableMachine();
  2690. //
  2691. // Remember migrated boot drivers
  2692. //
  2693. InitializeListHead (&MigratedDriversList);
  2694. SpRememberMigratedDrivers(&MigratedDriversList, setupLoaderBlock->ScsiDevices);
  2695. //
  2696. // Save away the hardware information passed to us by setupldr.
  2697. //
  2698. HardwareComponents[HwComponentDisplay] = SpSetupldrHwToHwDevice(&setupLoaderBlock->VideoDevice);
  2699. HardwareComponents[HwComponentKeyboard] = SpSetupldrHwToHwDevice(setupLoaderBlock->KeyboardDevices);
  2700. HardwareComponents[HwComponentComputer] = SpSetupldrHwToHwDevice(&setupLoaderBlock->ComputerDevice);
  2701. ScsiHardware = SpSetupldrHwToHwDevice(setupLoaderBlock->ScsiDevices);
  2702. BootBusExtenders = SpSetupldrHwToHwDevice(setupLoaderBlock->BootBusExtenders);
  2703. BusExtenders = SpSetupldrHwToHwDevice(setupLoaderBlock->BusExtenders);
  2704. InputDevicesSupport = SpSetupldrHwToHwDevice(setupLoaderBlock->InputDevicesSupport);
  2705. //
  2706. // For each driver loaded by setupldr, we need to go create a service list entry
  2707. // for that driver in the registry.
  2708. //
  2709. for( nextEntry = loaderBlock->BootDriverListHead.Flink;
  2710. nextEntry != &loaderBlock->BootDriverListHead;
  2711. nextEntry = nextEntry->Flink)
  2712. {
  2713. bootDriver = CONTAINING_RECORD(nextEntry,BOOT_DRIVER_LIST_ENTRY,Link);
  2714. //
  2715. // Get the image path.
  2716. //
  2717. imagePath = SpMemAlloc(bootDriver->FilePath.Length + sizeof(WCHAR));
  2718. wcsncpy(
  2719. imagePath,
  2720. bootDriver->FilePath.Buffer,
  2721. bootDriver->FilePath.Length / sizeof(WCHAR)
  2722. );
  2723. imagePath[bootDriver->FilePath.Length / sizeof(WCHAR)] = 0;
  2724. //
  2725. // If provided, get the registry path, otherwise it will
  2726. // be created by SpCreateServiceEntry.
  2727. //
  2728. if (bootDriver->RegistryPath.Length > 0) {
  2729. registryPath = SpMemAlloc(bootDriver->RegistryPath.Length + sizeof(WCHAR));
  2730. wcsncpy(
  2731. registryPath,
  2732. bootDriver->RegistryPath.Buffer,
  2733. bootDriver->RegistryPath.Length / sizeof(WCHAR)
  2734. );
  2735. registryPath[bootDriver->RegistryPath.Length / sizeof(WCHAR)] = 0;
  2736. ServiceName = registryPath;
  2737. } else {
  2738. registryPath = NULL;
  2739. ServiceName = NULL;
  2740. }
  2741. Status = SpCreateServiceEntry(imagePath,&ServiceName);
  2742. //
  2743. // If this operation fails, nothing to do about it here. If we did
  2744. // not provide the registry path, then save the returned one.
  2745. //
  2746. if(NT_SUCCESS(Status)) {
  2747. if (bootDriver->RegistryPath.Length == 0) {
  2748. bootDriver->RegistryPath.MaximumLength =
  2749. bootDriver->RegistryPath.Length = wcslen(ServiceName)*sizeof(WCHAR);
  2750. bootDriver->RegistryPath.Buffer = ServiceName;
  2751. }
  2752. } else {
  2753. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: warning: unable to create service entry for %ws (%lx)\n",imagePath,Status));
  2754. }
  2755. SpMemFree(imagePath);
  2756. if (registryPath) {
  2757. SpMemFree(registryPath);
  2758. }
  2759. }
  2760. if (NT_SUCCESS(Status)) {
  2761. //
  2762. // Create the virtual floppy (RAM driver) parameter entries
  2763. //
  2764. // NOTE: We ignore the error here since we can't do much here
  2765. // other than bug check the machine. The error
  2766. // will be handled properly while copying the files
  2767. // from the non existent OEM source devices
  2768. //
  2769. SpInitVirtualOemDevices(setupLoaderBlock, &VirtualOemSourceDevices);
  2770. }
  2771. //
  2772. // Create the thirdy party OEM SCSI driver entries
  2773. //
  2774. SpCreateDriverRegistryEntries(ScsiHardware);
  2775. #ifdef FULL_DOUBLE_SPACE_SUPPORT
  2776. if(NT_SUCCESS(Status)) {
  2777. OBJECT_ATTRIBUTES Obja;
  2778. UNICODE_STRING UnicodeString;
  2779. HANDLE hKey;
  2780. ULONG val = 1;
  2781. //
  2782. // Make sure we are automounting DoubleSpace
  2783. //
  2784. INIT_OBJA(
  2785. &Obja,
  2786. &UnicodeString,
  2787. L"\\registry\\machine\\system\\currentcontrolset\\control\\doublespace"
  2788. );
  2789. Status = ZwCreateKey(
  2790. &hKey,
  2791. KEY_ALL_ACCESS,
  2792. &Obja,
  2793. 0,
  2794. NULL,
  2795. REG_OPTION_NON_VOLATILE,
  2796. NULL
  2797. );
  2798. if(NT_SUCCESS(Status)) {
  2799. RtlInitUnicodeString(&UnicodeString,L"AutomountRemovable");
  2800. Status = ZwSetValueKey(hKey,&UnicodeString,0,REG_DWORD,&val,sizeof(ULONG));
  2801. if(!NT_SUCCESS(Status)) {
  2802. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: init0: unable to create DoubleSpace automount value (%lx)\n",Status));
  2803. }
  2804. ZwClose(hKey);
  2805. } else {
  2806. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: init0: unable to create DoubleSpace key (%lx)\n",Status));
  2807. }
  2808. }
  2809. #endif
  2810. //
  2811. // Save arc disk info
  2812. //
  2813. if(NT_SUCCESS(Status)) {
  2814. PARC_DISK_INFORMATION ArcInformation;
  2815. PARC_DISK_SIGNATURE DiskInfo;
  2816. PLIST_ENTRY ListEntry;
  2817. PDISK_SIGNATURE_INFORMATION myInfo,prev;
  2818. ArcInformation = loaderBlock->ArcDiskInformation;
  2819. ListEntry = ArcInformation->DiskSignatures.Flink;
  2820. prev = NULL;
  2821. while(ListEntry != &ArcInformation->DiskSignatures) {
  2822. DiskInfo = CONTAINING_RECORD(ListEntry,ARC_DISK_SIGNATURE,ListEntry);
  2823. myInfo = SpMemAlloc(sizeof(DISK_SIGNATURE_INFORMATION));
  2824. myInfo->Signature = DiskInfo->Signature;
  2825. myInfo->ArcPath = SpToUnicode(DiskInfo->ArcName);
  2826. myInfo->CheckSum = DiskInfo->CheckSum;
  2827. myInfo->ValidPartitionTable = DiskInfo->ValidPartitionTable;
  2828. myInfo->xInt13 = DiskInfo->xInt13;
  2829. myInfo->IsGPTDisk = DiskInfo->IsGpt;
  2830. myInfo->Next = NULL;
  2831. if(prev) {
  2832. prev->Next = myInfo;
  2833. } else {
  2834. DiskSignatureInformation = myInfo;
  2835. }
  2836. prev = myInfo;
  2837. ListEntry = ListEntry->Flink;
  2838. }
  2839. }
  2840. //
  2841. // Create the registry keys listed in migrate.inf.
  2842. //
  2843. if(NT_SUCCESS(Status)) {
  2844. if ( SetupldrMigrateInfFile != NULL ) {
  2845. ULONG ErrorLine;
  2846. Status = SpLoadSetupTextFile(
  2847. NULL,
  2848. SetupldrMigrateInfFile,
  2849. SetupldrMigrateInfFileSize,
  2850. &WinntMigrateInfHandle,
  2851. &ErrorLine,
  2852. FALSE,
  2853. TRUE
  2854. );
  2855. if( NT_SUCCESS(Status) ) {
  2856. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: SpLoadSetupTextFile( migrate.inf ) succeeded.\n"));
  2857. Status = SpProcessMigrateInfFile( WinntMigrateInfHandle );
  2858. if( !NT_SUCCESS(Status) ) {
  2859. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Failed to process migrate.inf. Status = %lx\n",Status));
  2860. }
  2861. #ifdef _X86_
  2862. //
  2863. // Delete drive letter information from registry that
  2864. // translated from migrate.inf.
  2865. //
  2866. if( IsNEC_98 ) {
  2867. if( NT_SUCCESS(Status) ) {
  2868. SpDeleteDriveLetterFromNTFTNec98();
  2869. }
  2870. }
  2871. #endif //NEC98
  2872. } else {
  2873. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpLoadSetupTextFile( migrate.inf ) failed. Status = %lx\n",Status));
  2874. }
  2875. }
  2876. if ( (NT_SUCCESS(Status)) && (SetupldrUnsupDrvInfFile != NULL) ) {
  2877. ULONG ErrorLine;
  2878. Status = SpLoadSetupTextFile(
  2879. NULL,
  2880. SetupldrUnsupDrvInfFile,
  2881. SetupldrUnsupDrvInfFileSize,
  2882. &WinntUnsupDrvInfHandle,
  2883. &ErrorLine,
  2884. FALSE,
  2885. TRUE
  2886. );
  2887. if( NT_SUCCESS(Status) ) {
  2888. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: SpLoadSetupTextFile( driver.inf ) succeeded.\n"));
  2889. Status = SpProcessUnsupDrvInfFile( WinntUnsupDrvInfHandle );
  2890. if( !NT_SUCCESS(Status) ) {
  2891. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Failed to process driver.inf. Status = %lx\n",Status));
  2892. }
  2893. } else {
  2894. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpLoadSetupTextFile( driver.inf ) failed. Status = %lx\n",Status));
  2895. }
  2896. }
  2897. }
  2898. SetupHardwareIdDatabase = SpSetupldrPnpDatabaseToSetupPnpDatabase( setupLoaderBlock->HardwareIdDatabase );
  2899. if(NT_SUCCESS(Status)) {
  2900. //
  2901. // Initialize keyboard Guid string
  2902. //
  2903. Status = RtlStringFromGUID( &GUID_DEVCLASS_KEYBOARD, &GuidString );
  2904. if( NT_SUCCESS( Status ) ) {
  2905. KeyboardGuidString = SpDupStringW( GuidString.Buffer );
  2906. if( KeyboardGuidString == NULL ) {
  2907. Status = STATUS_NO_MEMORY;
  2908. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: cannot create a GUID string for keyboard device. Status = %lx \n", Status ));
  2909. }
  2910. RtlFreeUnicodeString( &GuidString );
  2911. } else {
  2912. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: cannot create a GUID string for keyboard device. Status = %lx \n", Status ));
  2913. }
  2914. }
  2915. if(NT_SUCCESS(Status)) {
  2916. //
  2917. // Initialize mouse Guid strings
  2918. //
  2919. Status = RtlStringFromGUID( &GUID_DEVCLASS_MOUSE, &GuidString );
  2920. if( NT_SUCCESS( Status ) ) {
  2921. MouseGuidString = SpDupStringW( GuidString.Buffer );
  2922. if( MouseGuidString == NULL ) {
  2923. Status = STATUS_NO_MEMORY;
  2924. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: cannot create a GUID string for mouse device. Status = %lx \n", Status ));
  2925. }
  2926. RtlFreeUnicodeString( &GuidString );
  2927. } else {
  2928. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: cannot create a GUID string for mouse device. Status = %lx \n", Status ));
  2929. }
  2930. }
  2931. if(NT_SUCCESS(Status)) {
  2932. //
  2933. // Register for Plug & Play notification
  2934. //
  2935. Status = IoRegisterPlugPlayNotification ( EventCategoryReserved,
  2936. 0,
  2937. NULL,
  2938. DriverObject,
  2939. SpPnPNotificationCallBack,
  2940. SetupHardwareIdDatabase,
  2941. &NotificationEntry );
  2942. if(!NT_SUCCESS(Status)) {
  2943. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: init0: unable to register for PnP notification (%lx)\n",Status));
  2944. }
  2945. //
  2946. // Register for reinitialization.
  2947. //
  2948. if(NT_SUCCESS(Status)) {
  2949. IoRegisterDriverReinitialization(DriverObject,SpInitialize0a,loaderBlock);
  2950. }
  2951. }
  2952. return(Status);
  2953. }
  2954. VOID
  2955. SpInitialize0a(
  2956. IN PDRIVER_OBJECT DriverObject,
  2957. IN PVOID Context,
  2958. IN ULONG ReferenceCount
  2959. )
  2960. {
  2961. PLOADER_PARAMETER_BLOCK LoaderBlock;
  2962. PLIST_ENTRY nextEntry;
  2963. PBOOT_DRIVER_LIST_ENTRY bootDriver;
  2964. PKLDR_DATA_TABLE_ENTRY driverEntry;
  2965. PHARDWARE_COMPONENT pHw,pHwPrev,pHwTemp;
  2966. BOOLEAN ReallyLoaded;
  2967. PUNICODE_STRING name;
  2968. ULONG i;
  2969. PHARDWARE_COMPONENT* HwArray[] = {
  2970. &ScsiHardware,
  2971. &BootBusExtenders,
  2972. &BusExtenders,
  2973. &InputDevicesSupport,
  2974. };
  2975. UNREFERENCED_PARAMETER(DriverObject);
  2976. UNREFERENCED_PARAMETER(ReferenceCount);
  2977. //
  2978. // Context points to the os loader block.
  2979. //
  2980. LoaderBlock = Context;
  2981. //
  2982. // Find out if the machine is dockable.
  2983. // We do this once more because some machines may not have provided this info in the first
  2984. // time we attempted to retrieve this information.
  2985. //
  2986. SpCheckForDockableMachine();
  2987. //
  2988. // Iterate all scsi hardware and bus enumerators we think we detected
  2989. // and make sure the driver really initialized.
  2990. //
  2991. for( i = 0; i < sizeof(HwArray)/sizeof(PHARDWARE_COMPONENT*); i++ ) {
  2992. pHwPrev = NULL;
  2993. for(pHw=*(HwArray[i]); pHw; ) {
  2994. //
  2995. // Assume not really loaded.
  2996. //
  2997. ReallyLoaded = FALSE;
  2998. //
  2999. // Scan the boot driver list for this driver's entry.
  3000. //
  3001. nextEntry = LoaderBlock->BootDriverListHead.Flink;
  3002. while(nextEntry != &LoaderBlock->BootDriverListHead) {
  3003. bootDriver = CONTAINING_RECORD( nextEntry,
  3004. BOOT_DRIVER_LIST_ENTRY,
  3005. Link );
  3006. driverEntry = bootDriver->LdrEntry;
  3007. name = &driverEntry->BaseDllName;
  3008. if(!_wcsnicmp(name->Buffer,pHw->BaseDllName,name->Length/sizeof(WCHAR))) {
  3009. //
  3010. // This is the driver entry we need.
  3011. //
  3012. if(!(driverEntry->Flags & LDRP_FAILED_BUILTIN_LOAD)
  3013. ) {
  3014. ReallyLoaded = TRUE;
  3015. }
  3016. break;
  3017. }
  3018. nextEntry = nextEntry->Flink;
  3019. }
  3020. //
  3021. // If the driver didn't initialize properly,
  3022. // then it's not really loaded.
  3023. //
  3024. if(ReallyLoaded) {
  3025. if( !pHw->MigratedDriver ) {
  3026. //
  3027. // not a migrated driver, continue on
  3028. // processing with the next node
  3029. //
  3030. pHwPrev = pHw;
  3031. pHw = pHw->Next;
  3032. } else {
  3033. //
  3034. // Migrated driver, remove & free the
  3035. // node from the linked list
  3036. //
  3037. pHwTemp = pHw->Next;
  3038. if(pHwPrev) {
  3039. pHwPrev->Next = pHwTemp;
  3040. } else {
  3041. *(HwArray[i]) = pHwTemp;
  3042. }
  3043. SpFreeHwComponent(&pHw,FALSE);
  3044. pHw = pHwTemp;
  3045. }
  3046. } else {
  3047. //
  3048. // Remove and free the node or link it to unsupported driver
  3049. // list if its a migrated driver
  3050. //
  3051. pHwTemp = pHw->Next;
  3052. if(pHwPrev) {
  3053. pHwPrev->Next = pHwTemp;
  3054. } else {
  3055. *(HwArray[i]) = pHwTemp;
  3056. }
  3057. if( ( HwArray[i] == &ScsiHardware ) && ( pHw->MigratedDriver ) ) {
  3058. //
  3059. // If this is an unsupported migrated driver that failed to initialize, then
  3060. // remember it so that we can disable it later on. This can happen if the
  3061. // system contains a driver that controls the unsupported device, but winnt32
  3062. // winnt32 couldn't figure it out.
  3063. //
  3064. pHw->Next = UnsupportedScsiHardwareToDisable;
  3065. UnsupportedScsiHardwareToDisable = pHw;
  3066. } else {
  3067. SpFreeHwComponent(&pHw,FALSE);
  3068. }
  3069. pHw = pHwTemp;
  3070. }
  3071. }
  3072. }
  3073. //
  3074. // Find the pcmcia and atapi drivers and make sure these drivers really
  3075. // initialized
  3076. //
  3077. //
  3078. // Assume not really loaded.
  3079. //
  3080. PcmciaLoaded = FALSE;
  3081. AtapiLoaded = FALSE;
  3082. //
  3083. // Scan the boot driver list for this driver's entry.
  3084. //
  3085. nextEntry = LoaderBlock->BootDriverListHead.Flink;
  3086. while(nextEntry != &LoaderBlock->BootDriverListHead) {
  3087. bootDriver = CONTAINING_RECORD( nextEntry,
  3088. BOOT_DRIVER_LIST_ENTRY,
  3089. Link );
  3090. driverEntry = bootDriver->LdrEntry;
  3091. name = &driverEntry->BaseDllName;
  3092. if(!_wcsnicmp(name->Buffer,L"pcmcia.sys",name->Length/sizeof(WCHAR))) {
  3093. //
  3094. // This is the driver entry we need.
  3095. //
  3096. if(!(driverEntry->Flags & LDRP_FAILED_BUILTIN_LOAD)) {
  3097. PcmciaLoaded = TRUE;
  3098. }
  3099. } else if(!_wcsnicmp(name->Buffer,L"atapi.sys",name->Length/sizeof(WCHAR))) {
  3100. //
  3101. // This is the driver entry we need.
  3102. //
  3103. if(!(driverEntry->Flags & LDRP_FAILED_BUILTIN_LOAD)) {
  3104. AtapiLoaded = TRUE;
  3105. }
  3106. }
  3107. nextEntry = nextEntry->Flink;
  3108. }
  3109. }
  3110. VOID
  3111. SpInitialize1(
  3112. VOID
  3113. )
  3114. {
  3115. ASSERT(!GeneralInitialized);
  3116. if(GeneralInitialized) {
  3117. return;
  3118. }
  3119. SpFormatMessage(TemporaryBuffer,sizeof(TemporaryBuffer),SP_MNEMONICS);
  3120. MnemonicValues = SpMemAlloc((wcslen(TemporaryBuffer)+1)*sizeof(WCHAR));
  3121. wcscpy(MnemonicValues,TemporaryBuffer);
  3122. GeneralInitialized = TRUE;
  3123. }
  3124. VOID
  3125. SpTerminate(
  3126. VOID
  3127. )
  3128. {
  3129. ASSERT(GeneralInitialized);
  3130. if(GeneralInitialized) {
  3131. if(MnemonicValues) {
  3132. SpMemFree(MnemonicValues);
  3133. MnemonicValues = NULL;
  3134. }
  3135. GeneralInitialized = FALSE;
  3136. }
  3137. }
  3138. VOID
  3139. SpInvalidSystemPartition(
  3140. VOID
  3141. )
  3142. /*++
  3143. Routine Description:
  3144. Display a screen telling the user that we think his system
  3145. partition is invalid.
  3146. Arguments:
  3147. None.
  3148. Return Value:
  3149. None.
  3150. --*/
  3151. {
  3152. ULONG EvaluationInstallKeys[] = { KEY_F3, ASCI_CR };
  3153. SpDisplayScreen(SP_SCRN_SYSTEMPARTITION_INVALID, 3, 4 );
  3154. SpDisplayStatusOptions(
  3155. DEFAULT_STATUS_ATTRIBUTE,
  3156. SP_STAT_ENTER_EQUALS_CONTINUE,
  3157. SP_STAT_F3_EQUALS_EXIT,
  3158. 0
  3159. );
  3160. //
  3161. // Wait for keypress. Valid keys:
  3162. //
  3163. // ENTER = continue
  3164. //
  3165. SpInputDrain();
  3166. switch(SpWaitValidKey(EvaluationInstallKeys,NULL,NULL)) {
  3167. //
  3168. // User wants to continue.
  3169. //
  3170. case ASCI_CR:
  3171. break;
  3172. //
  3173. // User wants to exit.
  3174. //
  3175. case KEY_F3:
  3176. SpConfirmExit();
  3177. break;
  3178. }
  3179. }
  3180. VOID
  3181. SpNotifyEvaluationInstall(
  3182. VOID
  3183. )
  3184. /*++
  3185. Routine Description:
  3186. Display a screen telling the user we're about to install a demo
  3187. version.
  3188. Arguments:
  3189. None.
  3190. Return Value:
  3191. None.
  3192. --*/
  3193. {
  3194. ULONG EvaluationInstallKeys[] = { KEY_F3, ASCI_CR };
  3195. SpDisplayScreen(SP_SCRN_EVALUATION_NOTIFY, 3, 4 );
  3196. SpDisplayStatusOptions(
  3197. DEFAULT_STATUS_ATTRIBUTE,
  3198. SP_STAT_ENTER_EQUALS_CONTINUE,
  3199. SP_STAT_F3_EQUALS_EXIT,
  3200. 0
  3201. );
  3202. //
  3203. // Wait for keypress. Valid keys:
  3204. //
  3205. // ENTER = continue
  3206. //
  3207. SpInputDrain();
  3208. switch(SpWaitValidKey(EvaluationInstallKeys,NULL,NULL)) {
  3209. //
  3210. // User wants to continue.
  3211. //
  3212. case ASCI_CR:
  3213. break;
  3214. //
  3215. // User wants to exit.
  3216. //
  3217. case KEY_F3:
  3218. SpConfirmExit();
  3219. break;
  3220. }
  3221. }
  3222. VOID
  3223. SpWelcomeScreen(
  3224. VOID
  3225. )
  3226. /*++
  3227. Routine Description:
  3228. Display a screen welcoming the user and allow him to choose among
  3229. some options (help, exit, aux. menu, continue, repair).
  3230. Arguments:
  3231. None.
  3232. Return Value:
  3233. None.
  3234. --*/
  3235. {
  3236. ULONG WelcomeKeys[] = { KEY_F3, ASCI_CR, ASCI_ESC, KEY_F10, 0 };
  3237. ULONG MnemonicKeys[] = { MnemonicRepair, 0 };
  3238. BOOLEAN Welcoming;
  3239. //
  3240. // Welcome the user.
  3241. //
  3242. for(Welcoming = TRUE; Welcoming; ) {
  3243. if (SpIsERDisabled()) {
  3244. SpDisplayScreen(SP_SCRN_WELCOME_1, 3, 4);
  3245. SpDisplayStatusOptions(
  3246. DEFAULT_STATUS_ATTRIBUTE,
  3247. SP_STAT_ENTER_EQUALS_CONTINUE,
  3248. SP_STAT_R_EQUALS_REPAIR,
  3249. SP_STAT_F3_EQUALS_EXIT,
  3250. 0
  3251. );
  3252. } else {
  3253. SpDisplayScreen(SP_SCRN_WELCOME,3,4);
  3254. SpDisplayStatusOptions(
  3255. DEFAULT_STATUS_ATTRIBUTE,
  3256. SP_STAT_ENTER_EQUALS_CONTINUE,
  3257. SP_STAT_R_EQUALS_REPAIR,
  3258. SP_STAT_F3_EQUALS_EXIT,
  3259. 0
  3260. );
  3261. }
  3262. //
  3263. // Wait for keypress. Valid keys:
  3264. //
  3265. // F1 = help
  3266. // F3 = exit
  3267. // ENTER = continue
  3268. // R = Repair Winnt
  3269. // ESC = auxillary menu.
  3270. //
  3271. SpInputDrain();
  3272. switch(SpWaitValidKey(WelcomeKeys,NULL,MnemonicKeys)) {
  3273. case ASCI_ESC:
  3274. //
  3275. // User wants auxillary menu.
  3276. //
  3277. break;
  3278. case ASCI_CR:
  3279. //
  3280. // User wants to continue.
  3281. //
  3282. RepairWinnt = FALSE;
  3283. Welcoming = FALSE;
  3284. break;
  3285. case KEY_F3:
  3286. //
  3287. // User wants to exit.
  3288. //
  3289. SpConfirmExit();
  3290. break;
  3291. case KEY_F10:
  3292. Welcoming = FALSE;
  3293. ForceConsole = TRUE;
  3294. break;
  3295. default:
  3296. //
  3297. // Must be repair mnemonic
  3298. //
  3299. SpAsrSetAsrMode(ASRMODE_NORMAL);
  3300. RepairWinnt = TRUE;
  3301. Welcoming = FALSE;
  3302. break;
  3303. }
  3304. }
  3305. }
  3306. VOID
  3307. SpDisplayEula (
  3308. IN HANDLE MasterSifHandle,
  3309. IN PWSTR SetupSourceDevicePath,
  3310. IN PWSTR DirectoryOnSourceDevice
  3311. )
  3312. /*++
  3313. Routine Description:
  3314. Display the End User Licensing Agreement.
  3315. Arguments:
  3316. MasterSifHandle - Handle to txtsetup.sif.
  3317. SetupSourceDevicePath - Path to the device that contains the source media.
  3318. DirectoryOnSourceDevice - Directory on the media where EULA is located.
  3319. Return Value:
  3320. None. Does not return if user does not accept licensing agreement or if
  3321. the licensing agreement cannot be opened.
  3322. --*/
  3323. {
  3324. PWSTR MediaShortName;
  3325. PWSTR MediaDirectory;
  3326. PWSTR EulaPath;
  3327. NTSTATUS Status;
  3328. PVOID BaseAddress;
  3329. ULONG FileSize;
  3330. HANDLE hFile, hSection;
  3331. ULONG ValidKeys[2] = { KEY_F3,0 };
  3332. PWSTR Eula;
  3333. ULONG EulaSize;
  3334. PWSTR p;
  3335. if (PreInstall) {
  3336. return;
  3337. }
  3338. //
  3339. // Winnt32 displays the EULA now so we might be able to skip it
  3340. //
  3341. p = SpGetSectionKeyIndex(WinntSifHandle,SIF_DATA,WINNT_D_EULADONE_W,0);
  3342. if(p && SpStringToLong(p,NULL,10)) {
  3343. return;
  3344. }
  3345. //
  3346. // Figure out the path to eula.txt
  3347. //
  3348. MediaShortName = SpLookUpValueForFile(
  3349. MasterSifHandle,
  3350. L"eula.txt",
  3351. INDEX_WHICHMEDIA,
  3352. TRUE
  3353. );
  3354. SpPromptForSetupMedia(
  3355. MasterSifHandle,
  3356. MediaShortName,
  3357. SetupSourceDevicePath
  3358. );
  3359. if (UnattendedOperation && CustomSetup) {
  3360. return;
  3361. }
  3362. SpGetSourceMediaInfo(
  3363. MasterSifHandle,MediaShortName,NULL,NULL,&MediaDirectory);
  3364. wcscpy( TemporaryBuffer, SetupSourceDevicePath );
  3365. SpConcatenatePaths( TemporaryBuffer, DirectoryOnSourceDevice );
  3366. SpConcatenatePaths( TemporaryBuffer, MediaDirectory );
  3367. SpConcatenatePaths( TemporaryBuffer, L"eula.txt" );
  3368. EulaPath = SpDupStringW( TemporaryBuffer );
  3369. //
  3370. // Open and map the file for read access.
  3371. //
  3372. hFile = 0; // use EulaPath instead
  3373. Status = SpOpenAndMapFile(
  3374. EulaPath,
  3375. &hFile,
  3376. &hSection,
  3377. &BaseAddress,
  3378. &FileSize,
  3379. FALSE
  3380. );
  3381. if(!NT_SUCCESS(Status)) {
  3382. //
  3383. // Display a message indicating that there was a fatal error while trying
  3384. // to open the EULA file.
  3385. //
  3386. SpStartScreen(
  3387. SP_SCRN_FATAL_ERROR_EULA_NOT_FOUND,
  3388. 3,
  3389. HEADER_HEIGHT+3,
  3390. FALSE,
  3391. FALSE,
  3392. DEFAULT_ATTRIBUTE
  3393. );
  3394. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,SP_STAT_F3_EQUALS_EXIT,
  3395. 0);
  3396. SpWaitValidKey(ValidKeys,NULL,NULL);
  3397. SpDone(0,FALSE,TRUE);
  3398. }
  3399. //
  3400. // Convert the text to Unicode.
  3401. //
  3402. Eula = SpMemAlloc ((FileSize+1) * sizeof(WCHAR));
  3403. ASSERT (Eula);
  3404. Status = RtlMultiByteToUnicodeN (
  3405. Eula,
  3406. FileSize * sizeof(WCHAR),
  3407. &EulaSize,
  3408. BaseAddress,
  3409. FileSize
  3410. );
  3411. ASSERT (NT_SUCCESS(Status));
  3412. Eula[EulaSize / sizeof(WCHAR)] = (WCHAR)'\0';
  3413. //
  3414. // Show text to user.
  3415. //
  3416. SpHelp(
  3417. 0,
  3418. Eula,
  3419. SPHELP_LICENSETEXT
  3420. );
  3421. //
  3422. // Clean up
  3423. //
  3424. if (UnattendedOperation && !CustomSetup) {
  3425. PWSTR szOne = L"1";
  3426. //
  3427. // Remember that we displayed it here.
  3428. //
  3429. SpAddLineToSection(WinntSifHandle, SIF_DATA, WINNT_D_EULADONE_W, &szOne, 1);
  3430. }
  3431. SpMemFree (EulaPath);
  3432. SpMemFree (Eula);
  3433. SpUnmapFile(hSection,BaseAddress);
  3434. ZwClose(hFile);
  3435. }
  3436. VOID
  3437. SpCustomExpressScreen(
  3438. VOID
  3439. )
  3440. /*++
  3441. Routine Description:
  3442. Allow the user to choose between custom and express setup.
  3443. The global variable CustomSetup is set according to the user's choice.
  3444. NOTE : This feature is only available for headless installs
  3445. Arguments:
  3446. None.
  3447. Return Value:
  3448. None.
  3449. --*/
  3450. {
  3451. ULONG ValidKeys[] = { ASCI_CR, KEY_F3, 0 };
  3452. ULONG MnemonicKeys[] = { MnemonicCustom, 0 };
  3453. BOOLEAN Choosing;
  3454. ULONG c;
  3455. //
  3456. // See whether this parameter is specified for unattended operation.
  3457. //
  3458. if(UnattendedOperation) {
  3459. PWSTR p = SpGetSectionKeyIndex(UnattendedSifHandle,
  3460. SIF_UNATTENDED,WINNT_U_METHOD_W,0);
  3461. PWSTR q = SpGetSectionKeyIndex(UnattendedSifHandle,
  3462. SIF_UNATTENDED,WINNT_U_OVERWRITEOEM_W,0);
  3463. if( q && !_wcsicmp( q, L"no" ) ) {
  3464. UnattendedOverwriteOem = FALSE;
  3465. } else {
  3466. UnattendedOverwriteOem = TRUE;
  3467. }
  3468. //
  3469. // Default is custom. If user specified something
  3470. // else then use express.
  3471. //
  3472. if(p && _wcsicmp(p,L"custom")) {
  3473. CustomSetup = FALSE;
  3474. }
  3475. return;
  3476. }
  3477. //
  3478. // Don't do this if they ran from winnt/winnt32
  3479. // or headless terminal was not connected
  3480. //
  3481. if( WinntSetup || !HeadlessTerminalConnected) {
  3482. return;
  3483. }
  3484. for(Choosing = TRUE; Choosing; ) {
  3485. SpDisplayScreen(SP_SCRN_CUSTOM_EXPRESS,3,4);
  3486. SpDisplayStatusOptions(
  3487. DEFAULT_STATUS_ATTRIBUTE,
  3488. SP_STAT_ENTER_EQUALS_EXPRESS,
  3489. SP_STAT_C_EQUALS_CUSTOM,
  3490. SP_STAT_F3_EQUALS_EXIT,
  3491. 0
  3492. );
  3493. //
  3494. // Wait for keypress. Valid keys:
  3495. //
  3496. // ENTER = express setup
  3497. // <MnemonicCustom> = custom setup
  3498. //
  3499. SpInputDrain();
  3500. switch(c=SpWaitValidKey(ValidKeys,NULL,MnemonicKeys)) {
  3501. case ASCI_CR:
  3502. //
  3503. // User wants express setup.
  3504. //
  3505. CustomSetup = FALSE;
  3506. Choosing = FALSE;
  3507. break;
  3508. case (MnemonicCustom | KEY_MNEMONIC):
  3509. CustomSetup = TRUE;
  3510. Choosing = FALSE;
  3511. break;
  3512. case KEY_F3:
  3513. SpDone(0, FALSE, TRUE);
  3514. break;
  3515. default:
  3516. break;
  3517. }
  3518. }
  3519. }
  3520. PVOID
  3521. SpLoadSetupInformationFile(
  3522. VOID
  3523. )
  3524. {
  3525. NTSTATUS Status;
  3526. ULONG ErrLine;
  3527. PVOID SifHandle;
  3528. CLEAR_CLIENT_SCREEN();
  3529. //
  3530. // The image of txtsetup.sif has been passed to us
  3531. // by setupldr.
  3532. //
  3533. Status = SpLoadSetupTextFile(
  3534. NULL,
  3535. SetupldrInfoFile,
  3536. SetupldrInfoFileSize,
  3537. &SifHandle,
  3538. &ErrLine,
  3539. TRUE,
  3540. FALSE
  3541. );
  3542. //
  3543. // We're done with the image.
  3544. //
  3545. SpMemFree(SetupldrInfoFile);
  3546. SetupldrInfoFile = NULL;
  3547. SetupldrInfoFileSize = 0;
  3548. if(NT_SUCCESS(Status)) {
  3549. return(SifHandle);
  3550. }
  3551. //
  3552. // The file was already parsed once by setupldr.
  3553. // If we can't do it here, there's a serious problem.
  3554. // Assume it was a syntax error, because we didn't
  3555. // have to load it from disk.
  3556. //
  3557. SpStartScreen(
  3558. SP_SCRN_SIF_PROCESS_ERROR,
  3559. 3,
  3560. HEADER_HEIGHT+1,
  3561. FALSE,
  3562. FALSE,
  3563. DEFAULT_ATTRIBUTE,
  3564. ErrLine
  3565. );
  3566. //
  3567. // Since we haven't yet loaded the keyboard layout, we can't prompt the
  3568. // user to press F3 to exit
  3569. //
  3570. SpDisplayStatusText(SP_STAT_KBD_HARD_REBOOT, DEFAULT_STATUS_ATTRIBUTE);
  3571. SpInputGetKeypress();
  3572. while(TRUE); // Loop forever
  3573. }
  3574. VOID
  3575. SpIsWinntOrUnattended(
  3576. IN PVOID SifHandle
  3577. )
  3578. {
  3579. PWSTR szZero = L"0";
  3580. PWSTR szOne = L"1";
  3581. NTSTATUS Status;
  3582. ULONG ErrorLine;
  3583. PWSTR p;
  3584. WCHAR DiskDevicePath[MAX_PATH];
  3585. ULONG i;
  3586. PWSTR Architecture;
  3587. //
  3588. // Attempt to load winnt.sif. If the user is in the middle of
  3589. // a winnt setup, this file will be present.
  3590. //
  3591. if ( SetupldrWinntSifFile != NULL ) {
  3592. Status = SpLoadSetupTextFile(
  3593. NULL,
  3594. SetupldrWinntSifFile,
  3595. SetupldrWinntSifFileSize,
  3596. &WinntSifHandle,
  3597. &ErrorLine,
  3598. TRUE,
  3599. FALSE
  3600. );
  3601. } else {
  3602. //
  3603. // There's no winnt.sif handle, so this is probably an el-torito
  3604. // boot. If that's true, *and* the user chose to do an express
  3605. // setup, then use the on-CD unattend file.
  3606. //
  3607. if( !CustomSetup ) {
  3608. //
  3609. // The only way we should ever get here is if we went to
  3610. // the custom/express screen and the user chose express, which
  3611. // means this is the second time through this function (we had
  3612. // to call this fuction again to re-initialize our variables
  3613. // using the on-CD unattend file.
  3614. //
  3615. //
  3616. // Use this for testing purposes. Check for floppy0\unattend.txt
  3617. // before getting the file off the CDROM.
  3618. //
  3619. wcscpy( DiskDevicePath, L"\\device\\floppy0\\unattend.txt" );
  3620. Status = SpLoadSetupTextFile( DiskDevicePath,
  3621. NULL,
  3622. 0,
  3623. &WinntSifHandle,
  3624. &ErrorLine,
  3625. TRUE,
  3626. FALSE );
  3627. if( !NT_SUCCESS(Status) ) {
  3628. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  3629. i = 0;
  3630. Architecture = SpGetSectionKeyIndex( SifHandle,
  3631. SIF_SETUPDATA,
  3632. L"Architecture",
  3633. 0 );
  3634. if( Architecture == NULL ) {
  3635. #if defined(_AMD64_)
  3636. Architecture = L"amd64";
  3637. #elif defined(_X86_)
  3638. Architecture = L"x86";
  3639. #elif defined(_IA64_)
  3640. Architecture = L"ia64";
  3641. #else
  3642. #error "No Target Architcture"
  3643. #endif
  3644. }
  3645. while( (i < IoGetConfigurationInformation()->CdRomCount) && (!NT_SUCCESS(Status)) ) {
  3646. swprintf( DiskDevicePath, L"\\device\\cdrom%u", i);
  3647. SpConcatenatePaths( DiskDevicePath, Architecture );
  3648. SpConcatenatePaths( DiskDevicePath, L"\\unattend.txt" );
  3649. Status = SpLoadSetupTextFile( DiskDevicePath,
  3650. NULL,
  3651. 0,
  3652. &WinntSifHandle,
  3653. &ErrorLine,
  3654. TRUE,
  3655. FALSE );
  3656. i++;
  3657. }
  3658. }
  3659. if( NT_SUCCESS(Status) ) {
  3660. //
  3661. // Add a bunch of defaults which *should* of been there, but
  3662. // were not
  3663. SpAddLineToSection(WinntSifHandle,SIF_DATA,
  3664. WINNT_D_MSDOS_W,&szZero,1);
  3665. SpAddLineToSection(WinntSifHandle,SIF_DATA,
  3666. WINNT_D_FLOPPY_W,&szZero,1);
  3667. SpAddLineToSection(WinntSifHandle,SIF_SETUPPARAMS,
  3668. WINNT_S_SKIPMISSING_W,&szOne,1);
  3669. SpAddLineToSection(WinntSifHandle,SIF_DATA,
  3670. WINNT_D_AUTO_PART_W,&szOne,1);
  3671. //
  3672. // Tell the autopartition picker to do his job.
  3673. //
  3674. AutoPartitionPicker = TRUE;
  3675. }
  3676. } else {
  3677. //
  3678. // fail.
  3679. //
  3680. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  3681. }
  3682. }
  3683. if(NT_SUCCESS(Status)) {
  3684. //
  3685. // Check for winnt setup and the case where the user left the
  3686. // files on the CD-ROM.
  3687. //
  3688. p = SpGetSectionKeyIndex(WinntSifHandle,SIF_DATA,WINNT_D_MSDOS_W,0);
  3689. if(p && SpStringToLong(p,NULL,10)) {
  3690. WinntSetup = TRUE;
  3691. p = SpGetSectionKeyIndex(WinntSifHandle,SIF_DATA,WINNT_D_LOCALSRC_CD_W,0);
  3692. if(p && SpStringToLong(p,NULL,10)) {
  3693. WinntFromCd = TRUE;
  3694. }
  3695. }
  3696. //
  3697. // Check for the case where the user ran "winnt32 -cmdcons"
  3698. //
  3699. p = SpGetSectionKeyIndex(WinntSifHandle,SIF_DATA,
  3700. WINNT_D_CMDCONS_W,0);
  3701. if(p && SpStringToLong(p,NULL,10)) {
  3702. ConsoleFromWinnt32 = TRUE;
  3703. }
  3704. #if defined(_AMD64_) || defined(_X86_)
  3705. //
  3706. // Check for floppyless boot.
  3707. //
  3708. p = SpGetSectionKeyIndex(WinntSifHandle,SIF_DATA,
  3709. WINNT_D_FLOPPY_W,0);
  3710. if(p && SpStringToLong(p,NULL,10)) {
  3711. IsFloppylessBoot = TRUE;
  3712. }
  3713. //
  3714. // Check for fake CD.
  3715. //
  3716. p = SpGetSectionKeyIndex (WinntSifHandle, SIF_DATA, WINNT_D_NOLS_W, 0);
  3717. if (p && SpStringToLong (p, NULL, 10)) {
  3718. //
  3719. // get the original source path first
  3720. //
  3721. p = SpGetSectionKeyIndex (WinntSifHandle, SIF_DATA, WINNT_D_ORI_SRCPATH_W, 0);
  3722. if (p) {
  3723. if (p[0] && p[1] == L':') {
  3724. p += 2;
  3725. }
  3726. wcscpy (TemporaryBuffer, p);
  3727. SpConcatenatePaths (TemporaryBuffer, (!IsNEC_98) ? L"i386" : L"nec98");
  3728. LocalSourceDirectory = SpDupStringW (TemporaryBuffer);
  3729. NoLs = TRUE;
  3730. }
  3731. }
  3732. #endif // defined(_AMD64_) || defined(_X86_)
  3733. //
  3734. // Check for ASR test mode. This is intended as a way to automate
  3735. // ASR testing.
  3736. //
  3737. p = SpGetSectionKeyIndex(WinntSifHandle,SIF_DATA,L"AsrMode",0);
  3738. if(p && SpStringToLong(p,NULL,10)) {
  3739. switch (SpStringToLong(p,NULL,10)) {
  3740. case 1:
  3741. SpAsrSetAsrMode(ASRMODE_NORMAL);
  3742. break;
  3743. case 2:
  3744. SpAsrSetAsrMode(ASRMODE_QUICKTEST_TEXT);
  3745. break;
  3746. case 3:
  3747. SpAsrSetAsrMode(ASRMODE_QUICKTEST_FULL);
  3748. break;
  3749. default:
  3750. SpAsrSetAsrMode(ASRMODE_NORMAL);
  3751. break;
  3752. }
  3753. RepairWinnt = FALSE; // ASR not ER
  3754. }
  3755. //
  3756. // Check for auto Partition picker
  3757. //
  3758. p = SpGetSectionKeyIndex(WinntSifHandle,SIF_DATA,WINNT_D_AUTO_PART_W,0);
  3759. if(p && SpStringToLong(p,NULL,10)) {
  3760. AutoPartitionPicker = TRUE;
  3761. }
  3762. //
  3763. // Check for a preferred install directory
  3764. //
  3765. p = SpGetSectionKeyIndex(WinntSifHandle,SIF_DATA,WINNT_D_INSTALLDIR_W,0);
  3766. if (p) {
  3767. PreferredInstallDir = SpDupStringW( p );
  3768. }
  3769. //
  3770. // Check for ignore missing files.
  3771. //
  3772. p = SpGetSectionKeyIndex(WinntSifHandle,SIF_SETUPPARAMS,WINNT_S_SKIPMISSING_W,0);
  3773. if(p && SpStringToLong(p,NULL,10)) {
  3774. SkipMissingFiles = TRUE;
  3775. }
  3776. //
  3777. // Check for hide windir
  3778. //
  3779. p = SpGetSectionKeyIndex(WinntSifHandle,SIF_DATA,L"HideWinDir",0);
  3780. if(p && SpStringToLong(p,NULL,10)) {
  3781. HideWinDir = TRUE;
  3782. }
  3783. //
  3784. // Check for accessibility options
  3785. //
  3786. AccessibleSetup = SpNonZeroValuesInSection(WinntSifHandle, SIF_ACCESSIBILITY, 0);
  3787. //
  3788. // Now check for an unattended setup.
  3789. //
  3790. if(SpSearchTextFileSection(WinntSifHandle,SIF_UNATTENDED)) {
  3791. //
  3792. // Run in unattended mode. Leave the sif open
  3793. // and save away its handle for later use.
  3794. //
  3795. UnattendedSifHandle = WinntSifHandle;
  3796. UnattendedOperation = TRUE;
  3797. } else if(SpSearchTextFileSection(WinntSifHandle,SIF_GUI_UNATTENDED)) {
  3798. //
  3799. // Leave UnattendedOperation to FALSE (because it mainly uses to
  3800. // control text mode setup.) Store the handle of winnt.sif for later
  3801. // reference.
  3802. //
  3803. UnattendedGuiOperation = TRUE;
  3804. }
  3805. if(UnattendedOperation) {
  3806. PWSTR TempStr = NULL;
  3807. //
  3808. // If this is an unattended operation, find out if this is
  3809. // also an OEM pre-install
  3810. //
  3811. p = SpGetSectionKeyIndex(UnattendedSifHandle,
  3812. SIF_UNATTENDED,
  3813. WINNT_U_OEMPREINSTALL_W,
  3814. 0);
  3815. if( p && !_wcsicmp( p, L"yes" ) ) {
  3816. PreInstall = TRUE;
  3817. }
  3818. //
  3819. // Find out if no wait has been specified or not.
  3820. // Default is always false, in unattended case
  3821. //
  3822. UnattendWaitForReboot = FALSE;
  3823. TempStr = SpGetSectionKeyIndex(UnattendedSifHandle,
  3824. SIF_UNATTENDED,
  3825. WINNT_U_WAITFORREBOOT_W,
  3826. 0);
  3827. if (TempStr && !_wcsicmp(TempStr, L"yes")) {
  3828. UnattendWaitForReboot = TRUE;
  3829. }
  3830. //
  3831. // See if we're upgrading.
  3832. //
  3833. p = SpGetSectionKeyIndex(UnattendedSifHandle,
  3834. SIF_DATA,
  3835. WINNT_D_NTUPGRADE_W,
  3836. 0);
  3837. if( p && !_wcsicmp( p, L"yes" ) ) {
  3838. NTUpgrade = UpgradeFull;
  3839. }
  3840. }
  3841. } else {
  3842. // Case where there isn't an WINNT.SIF file to be found
  3843. //
  3844. // Create a handle to the new file
  3845. //
  3846. WinntSifHandle = SpNewSetupTextFile();
  3847. //
  3848. // Add a bunch of defaults which *should* of been there, but
  3849. // was not
  3850. SpAddLineToSection(WinntSifHandle,SIF_DATA,
  3851. WINNT_D_MSDOS_W,&szZero,1);
  3852. SpAddLineToSection(WinntSifHandle,SIF_DATA,
  3853. WINNT_D_FLOPPY_W,&szZero,1);
  3854. SpAddLineToSection(WinntSifHandle,SIF_SETUPPARAMS,
  3855. WINNT_S_SKIPMISSING_W,&szZero,1);
  3856. }
  3857. }
  3858. VOID
  3859. SpCheckSufficientMemory(
  3860. IN PVOID SifHandle
  3861. )
  3862. /*++
  3863. Routine Description:
  3864. Determine whether sufficient memory exists in the system
  3865. for installation to proceed. The required amount is specified
  3866. in the sif file.
  3867. Arguments:
  3868. SifHandle - supplies handle to open setup information file.
  3869. Return Value:
  3870. None.
  3871. --*/
  3872. {
  3873. ULONGLONG RequiredBytes,AvailableBytes, RequiredMBytes, AvailableMBytes;
  3874. PWSTR p;
  3875. p = SpGetSectionKeyIndex(SifHandle,SIF_SETUPDATA,SIF_REQUIREDMEMORY,0);
  3876. if(!p) {
  3877. SpFatalSifError(SifHandle,SIF_SETUPDATA,SIF_REQUIREDMEMORY,0,0);
  3878. }
  3879. RequiredBytes = (ULONGLONG)(ULONG)SpStringToLong(p,NULL,10);
  3880. AvailableBytes = UInt32x32To64(SystemBasicInfo.NumberOfPhysicalPages,SystemBasicInfo.PageSize);
  3881. //
  3882. // Now round to Mbytes for cleanliness... Include a 4MB slack-factor.
  3883. //
  3884. RequiredMBytes = ((RequiredBytes + ((4*1024*1024)-1)) >> 22) << 2;
  3885. AvailableMBytes = ((AvailableBytes + ((4*1024*1024)-1)) >> 22) << 2;
  3886. //
  3887. // Allow UMA machines which may reserve 8MB for video memory.
  3888. //
  3889. if(AvailableMBytes < (RequiredMBytes-8)) {
  3890. SpStartScreen(
  3891. SP_SCRN_INSUFFICIENT_MEMORY,
  3892. 3,
  3893. HEADER_HEIGHT+1,
  3894. FALSE,
  3895. FALSE,
  3896. DEFAULT_ATTRIBUTE,
  3897. RequiredMBytes,
  3898. 0
  3899. );
  3900. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,SP_STAT_F3_EQUALS_EXIT,0);
  3901. SpInputDrain();
  3902. while(SpInputGetKeypress() != KEY_F3) ;
  3903. SpDone(0,FALSE,TRUE);
  3904. }
  3905. }
  3906. PWSTR SetupSourceDevicePath = NULL;
  3907. PWSTR DirectoryOnSetupSource = NULL;
  3908. PVOID SifHandle;
  3909. ULONG
  3910. SpStartSetup(
  3911. VOID
  3912. )
  3913. {
  3914. PDISK_REGION TargetRegion,SystemPartitionRegion=NULL;
  3915. PDISK_REGION BootRegion; //NEC98
  3916. PWSTR TargetPath=NULL,SystemPartitionDirectory=NULL,OriginalSystemPartitionDirectory=NULL;
  3917. PWSTR DefaultTarget;
  3918. PWSTR OldOsLoadOptions;
  3919. PWSTR FullTargetPath;
  3920. #if defined(REMOTE_BOOT)
  3921. PWSTR RemoteBootTarget;
  3922. #endif // defined(REMOTE_BOOT)
  3923. BOOLEAN CdInstall = FALSE;
  3924. BOOLEAN b, DeleteTarget=FALSE;
  3925. NTSTATUS Status;
  3926. PVOID NtfsConvert;
  3927. PWSTR ThirdPartySourceDevicePath;
  3928. HANDLE ThreadHandle = NULL;
  3929. #if defined(_AMD64_) || defined(_X86_)
  3930. PCWSTR disableCompression;
  3931. PCWSTR enableBackup;
  3932. TCOMP compressionType;
  3933. #endif // defined(_AMD64_) || defined(_X86_)
  3934. //
  3935. // First things first, initialize the upgrade graphics global
  3936. // variables and hook up the upgrade progress indicator
  3937. // for graphics mode, if needed.
  3938. //
  3939. if (SP_IS_UPGRADE_GRAPHICS_MODE()) {
  3940. UpgradeGraphicsInit();
  3941. RegisterSetupProgressCallback(GraphicsModeProgressUpdate, NULL);
  3942. }
  3943. SendSetupProgressEvent(InitializationEvent, InitializationStartEvent, NULL);
  3944. SpInitialize1();
  3945. SpvidInitialize(); // initialize video first, so we can give err msg if keyboard error
  3946. SpInputInitialize();
  3947. if(!SpPatchBootMessages()) {
  3948. SpBugCheck(SETUP_BUGCHECK_BOOTMSGS,0,0,0);
  3949. }
  3950. //
  3951. // Initialize ARC<==>NT name translations.
  3952. //
  3953. SpInitializeArcNames(VirtualOemSourceDevices);
  3954. //
  3955. // Set up the boot device path, which we have stashed away
  3956. // from the os loader block.
  3957. //
  3958. NtBootDevicePath = SpArcToNt(ArcBootDevicePath);
  3959. if(!NtBootDevicePath) {
  3960. SpBugCheck(SETUP_BUGCHECK_BOOTPATH,0,0,0);
  3961. }
  3962. //
  3963. // Initialize dynamic update boot driver root directory path
  3964. //
  3965. DynUpdtBootDriverPath = SpGetDynamicUpdateBootDriverPath(NtBootDevicePath,
  3966. DirectoryOnBootDevice,
  3967. WinntSifHandle);
  3968. //
  3969. // For remote install, append RemoteIMirrorBootDirectoryPrefix to
  3970. // NtBootDevicePath so that it matches what C: is linked to.
  3971. // That way DirectoryOnBootDevice will be valid both from kernel
  3972. // and user mode.
  3973. //
  3974. if (RemoteBootSetup) {
  3975. ULONG NewBootDevicePathLen =
  3976. (wcslen(NtBootDevicePath) + wcslen(RemoteIMirrorBootDirectoryPrefix) + 1) * sizeof(WCHAR);
  3977. PWSTR NewBootDevicePath = SpMemAlloc(NewBootDevicePathLen);
  3978. wcscpy(NewBootDevicePath, NtBootDevicePath);
  3979. wcscat(NewBootDevicePath, RemoteIMirrorBootDirectoryPrefix);
  3980. SpMemFree(NtBootDevicePath);
  3981. NtBootDevicePath = NewBootDevicePath;
  3982. }
  3983. // Read SKU data, such as whether we are a product suite or
  3984. // this is an evaluation unit. Fills in SuiteType and
  3985. // EvaluationTime globals.
  3986. //
  3987. SpReadSKUStuff();
  3988. //
  3989. // Reinitialize video -- noop in western builds but switches into DBCS mode,
  3990. // etc, in Far Eastern builds.
  3991. //
  3992. if (NT_SUCCESS(SplangInitializeFontSupport(NtBootDevicePath,
  3993. DirectoryOnBootDevice,
  3994. BootFontImage,
  3995. BootFontImageLength))) {
  3996. SpvidInitialize(); // reinitialize video in alternate mode for Far East
  3997. }
  3998. //
  3999. // Process the txtsetup.sif file, which the boot loader
  4000. // will have loaded for us.
  4001. //
  4002. SifHandle = SpLoadSetupInformationFile();
  4003. //
  4004. // Determine whether this is advanced server.
  4005. //
  4006. SpDetermineProductType(SifHandle);
  4007. //
  4008. // Start the upgrade graphics
  4009. //
  4010. if (SP_IS_UPGRADE_GRAPHICS_MODE()) {
  4011. if (!NT_SUCCESS(UpgradeGraphicsStart())) {
  4012. SP_SET_UPGRADE_GRAPHICS_MODE(FALSE);
  4013. CLEAR_ENTIRE_SCREEN();
  4014. }
  4015. }
  4016. SpInputLoadLayoutDll(SifHandle,DirectoryOnBootDevice);
  4017. #ifdef PRERELEASE
  4018. //
  4019. // Initialize test hooks to allow testers to inject bug checks at random
  4020. // points in text mode (internal use only)
  4021. //
  4022. {
  4023. PCWSTR data;
  4024. if (WinntSifHandle) {
  4025. data = SpGetSectionKeyIndex (
  4026. WinntSifHandle,
  4027. L"TestHooks",
  4028. L"BugCheckPoint",
  4029. 0
  4030. );
  4031. if (data) {
  4032. while (*data >= L'0' && *data <= L'9') {
  4033. g_TestHook = g_TestHook * 10 + (*data - L'0');
  4034. data++;
  4035. }
  4036. }
  4037. }
  4038. }
  4039. #endif
  4040. //
  4041. // Check for bad BIOS. Does not return if a bad BIOS is found.
  4042. //
  4043. SpCheckForBadBios();
  4044. //
  4045. // Check for sufficient memory. Does not return if not enough.
  4046. //
  4047. SpCheckSufficientMemory(SifHandle);
  4048. //
  4049. // Determine whether this is a winnt/winnt32 setup and/or unattended setup.
  4050. // If unattended, the global variable UnattendedSifHandle will be filled in.
  4051. // If winnt/winnt32, the global variable WinntSetup will be set to TRUE.
  4052. //
  4053. SpIsWinntOrUnattended(SifHandle);
  4054. #if defined(_X86_)
  4055. //
  4056. // Check if SIF has Rollback flag
  4057. //
  4058. if (SpGetSectionKeyIndex (
  4059. WinntSifHandle,
  4060. SIF_DATA,
  4061. WINNT_D_WIN9X_ROLLBACK_W,
  4062. 0
  4063. )) {
  4064. Win9xRollback = TRUE;
  4065. }
  4066. #ifdef PRERELEASE
  4067. if (Win9xRollback) {
  4068. g_TestHook -= 1000; // uninstall test hooks start at 1001
  4069. }
  4070. #endif
  4071. #endif // defined(_X86_)
  4072. TESTHOOK(1);
  4073. //
  4074. // If this is a remote boot setup, get the path to the target.
  4075. //
  4076. // If TargetNtPartition is not specified in winnt.sif, then this is a
  4077. // remote boot for a remote install, not a remote boot setup.
  4078. //
  4079. if (RemoteBootSetup) {
  4080. #if defined(REMOTE_BOOT)
  4081. RemoteBootTarget = SpGetSectionKeyIndex(WinntSifHandle,SIF_SETUPDATA,L"TargetNtPartition",0);
  4082. if (RemoteBootTarget == NULL) {
  4083. RemoteInstallSetup = (BOOLEAN)(!RemoteSysPrepSetup);
  4084. } else {
  4085. RemoteBootTargetRegion = SpPtAllocateDiskRegionStructure(0xffffffff,0,0,TRUE,NULL,0);
  4086. ASSERT(RemoteBootTargetRegion);
  4087. wcscpy(RemoteBootTargetRegion->TypeName,RemoteBootTarget);
  4088. }
  4089. #else
  4090. RemoteInstallSetup = (BOOLEAN)(!RemoteSysPrepSetup);
  4091. #endif // defined(REMOTE_BOOT)
  4092. }
  4093. //
  4094. // Display the correct header text based on the product.
  4095. //
  4096. if (!ForceConsole && !Win9xRollback) {
  4097. SpDisplayHeaderText(
  4098. SpGetHeaderTextId(),
  4099. DEFAULT_ATTRIBUTE
  4100. );
  4101. }
  4102. //
  4103. // Check to see if we need to notify the user that we're installing a
  4104. // demo version. We assume that if the user is doing an unattended
  4105. // install, they know what they're doing.
  4106. //
  4107. if ((!ForceConsole) && (!Win9xRollback) && (!UnattendedOperation) &&
  4108. (EvaluationTime != 0) && (!SpDrEnabled())
  4109. ) {
  4110. SpNotifyEvaluationInstall();
  4111. }
  4112. if ((!ForceConsole) && (!Win9xRollback) && (!SpDrEnabled())) {
  4113. //
  4114. // Welcome the user and determine if this is for repairing.
  4115. //
  4116. if(!UnattendedOperation) {
  4117. SpWelcomeScreen();
  4118. }
  4119. }
  4120. //
  4121. // The user may have chosen to do a repair during
  4122. // the welcome screen, so we need to skip the check for
  4123. // custom/express in this case.
  4124. //
  4125. if ((!ForceConsole) && (!Win9xRollback) && (!SpDrEnabled()) && (!RepairWinnt)) {
  4126. SpCustomExpressScreen();
  4127. if( !CustomSetup ) {
  4128. //
  4129. // The user wants to do an express setup.
  4130. // reread the unattend file off the CD and use that.
  4131. //
  4132. // NULL-out the SetupldrWinntSifFile so we force the
  4133. // re-read of the unattend file off the CDROM or floppy.
  4134. //
  4135. SetupldrWinntSifFile = NULL;
  4136. SpIsWinntOrUnattended(SifHandle);
  4137. }
  4138. }
  4139. if( (HeadlessTerminalConnected) &&
  4140. (UnattendedOperation) &&
  4141. (NTUpgrade != UpgradeFull) &&
  4142. (!ForceConsole) ) {
  4143. //
  4144. // We're unattended and we're headless. We really want to try and
  4145. // not let gui-mode setup do *ANY* user-interaction. So let's set
  4146. // the unattend mode to fullunattended.
  4147. //
  4148. PWSTR Value[1];
  4149. WCHAR Answer[128];
  4150. Value[0] = Answer;
  4151. wcscpy( Answer, WINNT_A_FULLUNATTENDED_W );
  4152. SpAddLineToSection( WinntSifHandle,
  4153. WINNT_UNATTENDED_W,
  4154. WINNT_U_UNATTENDMODE_W,
  4155. Value,
  4156. 1 );
  4157. //
  4158. // Is there already an Administrator Password in the unattend file?
  4159. //
  4160. Value[0] = SpGetSectionKeyIndex( WinntSifHandle,
  4161. WINNT_GUIUNATTENDED_W,
  4162. WINNT_US_ADMINPASS_W,
  4163. 0 );
  4164. if( (NetBootAdministratorPassword == NULL) &&
  4165. ((Value[0] == NULL) || !(_wcsicmp(Value[0], L"*"))) ) {
  4166. //
  4167. // We will also need to have the user provide an administrator password
  4168. // because blank admin passwords are no longer acceptable on servers. This
  4169. // can be especially deadly on headless machines because it means the admin
  4170. // can never login to change the admin password from being blank. For that
  4171. // reason, let's go get a password right now.
  4172. //
  4173. // Before we do that though, we need to accomodate OEMs that actually
  4174. // *want* to ship their servers with a blank admin password. They do
  4175. // this because they want to allow the end-user to set the password
  4176. // themselves. To detect that, we need to look for a secondary
  4177. // unattend key that says it's okay to allow a blank password.
  4178. //
  4179. Value[0] = SpGetSectionKeyIndex( WinntSifHandle,
  4180. WINNT_GUIUNATTENDED_W,
  4181. L"EMSBlankPassWord",
  4182. 0 );
  4183. if( (Value[0] == NULL) ||
  4184. !(_wcsicmp(Value[0], L"0")) ||
  4185. !(_wcsicmp(Value[0], L"no")) ) {
  4186. //
  4187. // It's either not there, it's '0', or it's 'no'. Any
  4188. // of these mean that we do need an admin password on this
  4189. // headless server. Go get it now.
  4190. //
  4191. if( SpGetAdministratorPassword( Answer, ARRAYSIZE(Answer)) ) {
  4192. // Write the password into the unattend file.
  4193. Value[0] = Answer;
  4194. SpAddLineToSection( WinntSifHandle,
  4195. WINNT_GUIUNATTENDED_W,
  4196. WINNT_US_ADMINPASS_W,
  4197. Value,
  4198. 1 );
  4199. }
  4200. }
  4201. }
  4202. }
  4203. if (ForceConsole) {
  4204. CLEAR_ENTIRE_SCREEN();
  4205. }
  4206. //
  4207. // Detect/load scsi miniports.
  4208. // WARNING WARNING WARNING
  4209. //
  4210. // Do NOT change the order of the actions carried out below without
  4211. // understanding EXACTLY what you are doing.
  4212. // There are many interdependencies...
  4213. //
  4214. SpConfirmScsiMiniports(SifHandle, NtBootDevicePath, DirectoryOnBootDevice);
  4215. //
  4216. // Load disk class drivers if necessary.
  4217. // Do this before loading scsi class drivers, because atdisks
  4218. // and the like 'come before' scsi disks in the load order.
  4219. //
  4220. SpLoadDiskDrivers(SifHandle,NtBootDevicePath,DirectoryOnBootDevice);
  4221. //
  4222. // Load scsi class drivers if necessary.
  4223. //
  4224. SpLoadScsiClassDrivers(SifHandle,NtBootDevicePath,DirectoryOnBootDevice);
  4225. //
  4226. // Reinitialize ARC<==>NT name translations.
  4227. // Do this after loading disk and scsi class drivers because doing so
  4228. // may bring additional devices on-line.
  4229. //
  4230. SpFreeArcNames();
  4231. SpInitializeArcNames(VirtualOemSourceDevices);
  4232. SendSetupProgressEvent(InitializationEvent, InitializationEndEvent, NULL);
  4233. SendSetupProgressEvent(PartitioningEvent, PartitioningStartEvent, NULL);
  4234. //
  4235. // Initialize hard disk information.
  4236. // Do this after loading disk drivers so we can talk to all attached disks.
  4237. //
  4238. SpDetermineHardDisks(SifHandle);
  4239. SendSetupProgressEvent(PartitioningEvent, ScanDisksEvent, &HardDiskCount);
  4240. //
  4241. // Figure out where we are installing from (cd-rom or floppy).
  4242. // (tedm, 12/8/93) there is a minor problem here.
  4243. // This only works because we currently only support scsi cd-rom drives,
  4244. // and we have loaded the scsi class drivers above.
  4245. // SpDetermineInstallationSource won't allow cd-rom installation
  4246. // it there are no cd-rom drives on-line -- but we haven't loaded
  4247. // non-scsi cd-rom drivers yet. What we really should do is
  4248. // allow cd-rom as a choice on all machines, and if the user selects
  4249. // it, not verify the presence of a drive until after we have called
  4250. // SpLoadCdRomDrivers().
  4251. //
  4252. // If winnt setup, defer this for now, because we will let the partitioning
  4253. // engine search for the local source directory when it initializes.
  4254. //
  4255. TESTHOOK(2);
  4256. if (Win9xRollback) {
  4257. CdInstall = FALSE;
  4258. } else {
  4259. CdInstall = ((WinntSetup && !WinntFromCd && !RemoteBootSetup && !RemoteSysPrepSetup) ||
  4260. ConsoleFromWinnt32)
  4261. ? FALSE
  4262. : SpDetermineInstallationSource(
  4263. SifHandle,
  4264. &SetupSourceDevicePath,
  4265. &DirectoryOnSetupSource,
  4266. FALSE // restart if CD-ROM is not present
  4267. );
  4268. }
  4269. //
  4270. // Load cd-rom drivers if necessary.
  4271. // Note that if we booted from CD (like on an ARC machine) then drivers
  4272. // will already have been loaded by setupldr. This call here catches the
  4273. // case where we booted from floppy or hard disk and the user chose
  4274. // 'install from cd' during SpDetermineInstallationSource.
  4275. //
  4276. // If we're in step-up mode then we load cd drivers, because the user
  4277. // might need to insert a CD to prove that he qualifies for the step-up.
  4278. //
  4279. if (StepUpMode || CdInstall) {
  4280. SpLoadCdRomDrivers(SifHandle,NtBootDevicePath,DirectoryOnBootDevice);
  4281. //
  4282. // Reinitialize ARC<==>NT name translations.
  4283. //
  4284. SpFreeArcNames();
  4285. SpInitializeArcNames(VirtualOemSourceDevices);
  4286. }
  4287. //
  4288. // At this point, any and all drivers that are to be loaded
  4289. // are loaded -- we are done with the boot media and can switch over
  4290. // to the setup media
  4291. //
  4292. // Initialize the partitioning engine.
  4293. //
  4294. SpPtInitialize();
  4295. TESTHOOK(3);
  4296. //
  4297. // Initialize the boot variables (for ARC)
  4298. //
  4299. if (SpIsArc()) {
  4300. SpInitBootVars();
  4301. }
  4302. //
  4303. // If this is a winnt setup, the partition engine initialization
  4304. // will have attempted to locate the local source partition for us.
  4305. //
  4306. // WARNING: Do not use the SetupSourceDevicePath or DirectoryOnSetupSource
  4307. // variables in the winnt case until AFTER this bit of code has executed
  4308. // as they are not set until we get here!
  4309. //
  4310. if(!ForceConsole && !Win9xRollback && WinntSetup && !WinntFromCd && !RemoteBootSetup && !RemoteSysPrepSetup) {
  4311. SpGetWinntParams(&SetupSourceDevicePath,&DirectoryOnSetupSource);
  4312. }
  4313. if (!SpIsArc()) {
  4314. //
  4315. // Initialize the boot variables (amd64/x86)
  4316. //
  4317. SpInitBootVars();
  4318. }
  4319. //
  4320. // invoke the command console
  4321. //
  4322. if (ForceConsole) {
  4323. SpStartCommandConsole(SifHandle,SetupSourceDevicePath,DirectoryOnSetupSource);
  4324. SpShutdownSystem();
  4325. }
  4326. //
  4327. // invoke rollback
  4328. //
  4329. #if defined(_X86_)
  4330. if (Win9xRollback) {
  4331. PCWSTR testPath;
  4332. BOOLEAN defaultToBootDir = TRUE;
  4333. TESTHOOK(1001); // this is bugcheck point 2001 in the answer file
  4334. //
  4335. // Prepare the globals that tell the rest of the code which drives to use
  4336. //
  4337. WinUpgradeType = SpLocateWin95 (&TargetRegion, &TargetPath, &SystemPartitionRegion);
  4338. if(!SpIsArc()) {
  4339. //
  4340. // system partition directory is the root of C:.
  4341. //
  4342. SystemPartitionDirectory = L"";
  4343. } else {
  4344. SystemPartitionDirectory = SpDetermineSystemPartitionDirectory(
  4345. SystemPartitionRegion,
  4346. OriginalSystemPartitionDirectory
  4347. );
  4348. }
  4349. SpStringToUpper(TargetPath);
  4350. //
  4351. // Force the ~LS directory to be the ~BT directory if needed. We need
  4352. // this for autochk (which is normally in ~ls during setup).
  4353. //
  4354. if (LocalSourceRegion) {
  4355. SpGetWinntParams (&SetupSourceDevicePath, &DirectoryOnSetupSource);
  4356. if (SetupSourceDevicePath && DirectoryOnSetupSource) {
  4357. wcscpy (TemporaryBuffer, SetupSourceDevicePath);
  4358. SpConcatenatePaths (TemporaryBuffer, DirectoryOnSetupSource);
  4359. testPath = SpDupStringW (TemporaryBuffer);
  4360. if (SpFileExists (testPath, TRUE)) {
  4361. defaultToBootDir = FALSE;
  4362. }
  4363. SpMemFree ((PVOID) testPath);
  4364. }
  4365. }
  4366. if (defaultToBootDir) {
  4367. SetupSourceDevicePath = SpDupStringW (NtBootDevicePath);
  4368. DirectoryOnSetupSource = SpDupStringW (L"\\$win_nt$.~bt");
  4369. }
  4370. //
  4371. // Execute autochk
  4372. //
  4373. AutochkRunning = TRUE;
  4374. SpRunAutochkOnNtAndSystemPartitions (
  4375. SifHandle,
  4376. TargetRegion,
  4377. SystemPartitionRegion,
  4378. SetupSourceDevicePath,
  4379. DirectoryOnSetupSource,
  4380. TargetPath
  4381. );
  4382. AutochkRunning = FALSE;
  4383. TESTHOOK(1002); // this is bugcheck point 2002 in the answer file
  4384. //
  4385. // We finished; now it is safe to restore the machine
  4386. //
  4387. SpExecuteWin9xRollback (WinntSifHandle, NtBootDevicePath);
  4388. goto CleanAndFinish;
  4389. }
  4390. #endif // defined(_X86_)
  4391. if(!SpDrEnabled()) {
  4392. //
  4393. // Display End User Licensing Agreement. Also, in unattended case,
  4394. // make sure the media is available.
  4395. //
  4396. SpDisplayEula (
  4397. SifHandle,
  4398. SetupSourceDevicePath,
  4399. DirectoryOnSetupSource);
  4400. }
  4401. //
  4402. // Read the product id and setup info from setupp.ini. If we are doing ASR (specifically
  4403. // ER), we will wait, and only require the CD if we need it.
  4404. //
  4405. if (!SpDrEnabled()) {
  4406. SpInitializePidString( SifHandle,
  4407. SetupSourceDevicePath,
  4408. DirectoryOnSetupSource );
  4409. }
  4410. //
  4411. // Find out if there is any NT to upgrade and if the user wants us to
  4412. // upgrade it.
  4413. //
  4414. #if defined(REMOTE_BOOT)
  4415. // If this is a remote boot setup, the target partition is
  4416. // specified in winnt.sif.
  4417. //
  4418. #endif // defined(REMOTE_BOOT)
  4419. TargetRegion = NULL;
  4420. if(SpDrEnabled()) {
  4421. NTUpgrade = DontUpgrade;
  4422. } else if (RemoteSysPrepSetup) {
  4423. NTUpgrade = DontUpgrade;
  4424. } else {
  4425. NTUpgrade = SpFindNtToUpgrade(SifHandle,
  4426. &TargetRegion,
  4427. &TargetPath,
  4428. &SystemPartitionRegion,
  4429. &OriginalSystemPartitionDirectory);
  4430. }
  4431. if( PreInstall ) {
  4432. //
  4433. // In pre-install mode, get the information about the components
  4434. // to pre-install
  4435. //
  4436. wcscpy( TemporaryBuffer, DirectoryOnSetupSource );
  4437. SpConcatenatePaths( TemporaryBuffer, WINNT_OEM_TEXTMODE_DIR_W );
  4438. PreinstallOemSourcePath = SpDupStringW( ( PWSTR )TemporaryBuffer );
  4439. SpInitializePreinstallList(SifHandle,
  4440. SetupSourceDevicePath ,
  4441. PreinstallOemSourcePath);
  4442. }
  4443. //
  4444. // Detect/confirm hardware.
  4445. //
  4446. SpConfirmHardware(SifHandle);
  4447. //
  4448. // Reinitialize the keyboard layout dll. This is a no-op for western builds
  4449. // but in Far East builds this can cause a new keyboard layout dll to be loaded.
  4450. //
  4451. if(NTUpgrade != UpgradeFull) {
  4452. extern PVOID KeyboardTable;
  4453. SplangReinitializeKeyboard(
  4454. UnattendedOperation,
  4455. SifHandle,
  4456. DirectoryOnBootDevice,
  4457. &KeyboardTable,
  4458. HardwareComponents
  4459. );
  4460. }
  4461. TESTHOOK(4);
  4462. //
  4463. // Try to locate previous versions of windows, IFF we are not repairing
  4464. //
  4465. #if defined(_X86_)
  4466. if (!RepairWinnt && !SpDrEnabled()) {
  4467. if(!RemoteBootSetup && !RemoteSysPrepSetup && (NTUpgrade == DontUpgrade)) {
  4468. //
  4469. // Take a gander on the hard drives, looking for win95 or win3.1.
  4470. //
  4471. WinUpgradeType = SpLocateWin95(&TargetRegion,&TargetPath,&SystemPartitionRegion);
  4472. if(WinUpgradeType == NoWinUpgrade) {
  4473. if(SpLocateWin31(SifHandle,&TargetRegion,&TargetPath,&SystemPartitionRegion)) {
  4474. WinUpgradeType = UpgradeWin31;
  4475. //
  4476. // Note that on x86, it can happen that the machine already has NT installed
  4477. // on top of Win31, and the user is not upgrading NT but he is upgrading win31.
  4478. //
  4479. // This is kind of a strange case but we take the extra step here to
  4480. // ensure that the config directory is cleaned out so the fresh install
  4481. // will really be fresh.
  4482. //
  4483. if(SpIsNtInDirectory(TargetRegion,TargetPath)) {
  4484. NTUpgrade = UpgradeInstallFresh;
  4485. }
  4486. }
  4487. } else {
  4488. //
  4489. // We come here only if we are in the Win9x/Win31 case
  4490. // WE want to make sure that we have a TargetRegion at this point
  4491. //
  4492. if( !TargetRegion ){
  4493. //Tell the user that we could not find Win9x to upgrade
  4494. //This is potentially possible when Win9x was installed on 1394 or USB or some such drive that is
  4495. //not supported currently for the install drive.
  4496. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: We could not find the installation to upgrade (Win9x) - could be on USB or Firewire drive\n" ));
  4497. SpCantFindBuildToUpgrade();
  4498. }
  4499. }
  4500. } else {
  4501. //
  4502. // Just check to see if the target region also contains WIN31, Note
  4503. // that the MIN KB to check for is 0, since we already have done
  4504. // the space check.
  4505. // Note also that if the directory contains Win95, then the Win95
  4506. // migration was already done when NT was installed, and we don't
  4507. // care about it now.
  4508. //
  4509. if(!RemoteBootSetup && !RemoteSysPrepSetup && SpIsWin31Dir(TargetRegion,TargetPath,0)) {
  4510. if(SpConfirmRemoveWin31()) {
  4511. WinUpgradeType = UpgradeWin31;
  4512. }
  4513. } else {
  4514. WinUpgradeType = NoWinUpgrade;
  4515. }
  4516. }
  4517. }
  4518. if (IsNEC_98) { //NEC98
  4519. if (WinUpgradeType==UpgradeWin31) {
  4520. //
  4521. // Remap drive letter, as hard drive start from A:
  4522. //
  4523. DriveAssignFromA = TRUE;
  4524. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Re-map drive letters as NEC assign.\n" ));
  4525. SpPtRemapDriveLetters(FALSE); // Re-map as "NEC" assign.
  4526. //
  4527. // ReInitialize structure;
  4528. //
  4529. SpPtAssignDriveLetters();
  4530. }
  4531. } //NEC98
  4532. #endif // defined(_X86_)
  4533. //
  4534. // Special case upgrades where we want to convert to NTFS
  4535. //
  4536. if( ANY_TYPE_OF_UPGRADE && (( UnattendedSifHandle && (NtfsConvert = SpGetSectionKeyIndex(UnattendedSifHandle,SIF_UNATTENDED,L"Filesystem",0)) ) ||
  4537. ( WinntSifHandle && (NtfsConvert = SpGetSectionKeyIndex(WinntSifHandle,SIF_DATA,L"Filesystem",0))) ) ) {
  4538. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Should we convert to NTFS ?\n" ));
  4539. if(!_wcsicmp(NtfsConvert,L"ConvertNtfs")){
  4540. ConvertNtVolumeToNtfs = TRUE;
  4541. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Yes we should convert to NTFS\n" ));
  4542. }
  4543. }
  4544. //
  4545. // Do partitioning and ask the user for the target path.
  4546. //
  4547. if(!ANY_TYPE_OF_UPGRADE) {
  4548. if(SpDrEnabled()) {
  4549. BOOLEAN RepairedNt = FALSE;
  4550. TargetRegion = NULL;
  4551. SystemPartitionRegion = NULL;
  4552. SpDrPtPrepareDisks(
  4553. SifHandle,
  4554. &TargetRegion,
  4555. &SystemPartitionRegion,
  4556. SetupSourceDevicePath,
  4557. DirectoryOnSetupSource,
  4558. &RepairedNt
  4559. );
  4560. //
  4561. // invoke the command console
  4562. //
  4563. if (ForceConsole) {
  4564. CLEAR_ENTIRE_SCREEN();
  4565. SpStartCommandConsole(SifHandle,SetupSourceDevicePath,DirectoryOnSetupSource);
  4566. SpShutdownSystem();
  4567. }
  4568. if (RepairedNt) {
  4569. //
  4570. // retrieve information about the install we repaired
  4571. //
  4572. ASSERT(Gbl_HandleToSetupLog != NULL);
  4573. SppGetRepairPathInformation(
  4574. Gbl_HandleToSetupLog,
  4575. &Gbl_SystemPartitionName,
  4576. &Gbl_SystemPartitionDirectory,
  4577. &Gbl_BootPartitionName,
  4578. &Gbl_BootPartitionDirectory );
  4579. TargetPath = Gbl_BootPartitionDirectory;
  4580. SystemPartitionDirectory = Gbl_SystemPartitionDirectory;
  4581. ASSERT((TargetPath != NULL) && (SystemPartitionDirectory != NULL));
  4582. RepairWinnt = TRUE;
  4583. goto UpdateBootList;
  4584. }
  4585. }
  4586. else if (RemoteSysPrepSetup) {
  4587. PWSTR UseWholeDisk = NULL;
  4588. BOOLEAN UseWholeDiskFlag = TRUE;
  4589. //
  4590. // Find IMirror.Dat file on server. doesn't return on failure.
  4591. //
  4592. SpReadIMirrorFile(&RemoteIMirrorFileData, RemoteIMirrorFilePath);
  4593. //
  4594. // Determine what the local disk layout should be based
  4595. // on IMirror.Dat and possible user input. doesn't return on
  4596. // failure. Read the .sif to see if it specifies that disks
  4597. // should be partitioned as they originally were, or use the
  4598. // entire size of the new disk.
  4599. //
  4600. #if defined(REMOTE_BOOT)
  4601. UseWholeDisk = SpGetSectionKeyIndex(WinntSifHandle,SIF_REMOTEBOOT,SIF_USEWHOLEDISK,0);
  4602. #else
  4603. UseWholeDisk = SpGetSectionKeyIndex(WinntSifHandle,SIF_REMOTEINSTALL,SIF_USEWHOLEDISK,0);
  4604. #endif
  4605. if ((UseWholeDisk != NULL) &&
  4606. ((UseWholeDisk[0] == 'N') || (UseWholeDisk[0] == 'n')))
  4607. {
  4608. UseWholeDiskFlag = FALSE;
  4609. }
  4610. SpDetermineDiskLayout(RemoteIMirrorFileData, &RemoteIMirrorMemoryData);
  4611. //
  4612. // Make the local disks look ok. doesn't return on failure.
  4613. //
  4614. SpFixupLocalDisks(SifHandle,
  4615. &TargetRegion,
  4616. &SystemPartitionRegion,
  4617. SetupSourceDevicePath,
  4618. DirectoryOnSetupSource,
  4619. RemoteIMirrorMemoryData,
  4620. UseWholeDiskFlag);
  4621. } else {
  4622. PWSTR RemoteBootRepartition = NULL;
  4623. BOOLEAN PrepareForRemoteBoot = RemoteBootSetup;
  4624. //
  4625. // We tell SpPtPrepareDisks to repartition in a remote boot
  4626. // case, unless there is an entry in the [RemoteBoot] section
  4627. // saying "Repartition = No".
  4628. //
  4629. if (RemoteBootSetup) {
  4630. #if defined(REMOTE_BOOT)
  4631. RemoteBootRepartition = SpGetSectionKeyIndex(WinntSifHandle,SIF_REMOTEBOOT,SIF_REPARTITION,0);
  4632. #else
  4633. RemoteBootRepartition = SpGetSectionKeyIndex(WinntSifHandle,SIF_REMOTEINSTALL,SIF_REPARTITION,0);
  4634. #endif // defined(REMOTE_BOOT)
  4635. if ((RemoteBootRepartition != NULL) &&
  4636. ((RemoteBootRepartition[0] != 'Y') && (RemoteBootRepartition[0] != 'y')))
  4637. {
  4638. PrepareForRemoteBoot = FALSE;
  4639. }
  4640. } else {
  4641. BOOLEAN IsCdBoot = (!WinntSetup && !WinntFromCd);
  4642. //
  4643. // Honor Repartition flag only in the case of CD boot
  4644. //
  4645. if (UnattendedSifHandle && IsCdBoot) {
  4646. RemoteBootRepartition = SpGetSectionKeyIndex(UnattendedSifHandle,
  4647. SIF_UNATTENDED,
  4648. SIF_REPARTITION,
  4649. 0);
  4650. if ((RemoteBootRepartition != NULL) &&
  4651. ((RemoteBootRepartition[0] == 'Y') || (RemoteBootRepartition[0] == 'y')))
  4652. {
  4653. PrepareForRemoteBoot = TRUE;
  4654. }
  4655. }
  4656. }
  4657. //
  4658. // HACK
  4659. // Some OEMs are shipping machines with a hidden, active partition
  4660. // that gets marked unactive after the machine is booted once. The
  4661. // problem is that sometimes these machines are turned on with a win2k
  4662. // bootable CD in them and we do all sorts of nasty stuff to their
  4663. // hidden partition because its marked active and we think it's a
  4664. // boot partition (which it is).
  4665. //
  4666. // If we detect this case, then we need to throw an error message
  4667. // and go to the partitioning screen.
  4668. //
  4669. while( 1 ) {
  4670. SpPtPrepareDisks(
  4671. SifHandle,
  4672. &TargetRegion,
  4673. &SystemPartitionRegion,
  4674. SetupSourceDevicePath,
  4675. DirectoryOnSetupSource,
  4676. PrepareForRemoteBoot
  4677. );
  4678. #if defined(_AMD64_) || defined(_X86_)
  4679. if( SpIsArc() )
  4680. break;
  4681. //
  4682. // Only check this on a BIOS X86 machine
  4683. //
  4684. if( SpPtIsSystemPartitionRecognizable() ) {
  4685. #else
  4686. if( 1 ) {
  4687. #endif // defined(_AMD64_) || defined(_X86_)
  4688. break;
  4689. } else {
  4690. //
  4691. // Either exit or go back to the partitioning menu.
  4692. //
  4693. SpInvalidSystemPartition();
  4694. }
  4695. }
  4696. #if defined(REMOTE_BOOT)
  4697. //
  4698. // If this is a remote boot, erase any existing CSC cache, if we
  4699. // did not repartition.
  4700. //
  4701. if (RemoteBootSetup && !RemoteInstallSetup && !PrepareForRemoteBoot &&
  4702. !RemoteSysPrepSetup && (HardDiskCount != 0)) {
  4703. SpEraseCscCache(SystemPartitionRegion);
  4704. }
  4705. #endif // defined(REMOTE_BOOT)
  4706. }
  4707. //
  4708. // Partitioning may have changed the partition ordinal of the local source
  4709. //
  4710. if(WinntSetup && !WinntFromCd) {
  4711. SpMemFree(SetupSourceDevicePath);
  4712. SpGetWinntParams(&SetupSourceDevicePath,&DirectoryOnSetupSource);
  4713. }
  4714. DefaultTarget = SpGetSectionKeyIndex(
  4715. SifHandle,
  4716. SIF_SETUPDATA,
  4717. SIF_DEFAULTPATH,
  4718. 0
  4719. );
  4720. if(!DefaultTarget) {
  4721. SpFatalSifError(
  4722. SifHandle,
  4723. SIF_SETUPDATA,
  4724. SIF_DEFAULTPATH,
  4725. 0,
  4726. 0
  4727. );
  4728. }
  4729. //
  4730. // Select the target path.
  4731. //
  4732. if (TargetRegion != NULL)
  4733. DeleteTarget = SpGetTargetPath(SifHandle,TargetRegion,DefaultTarget,&TargetPath);
  4734. }
  4735. TESTHOOK(5);
  4736. //
  4737. // Form the SystemPartitionDirectory
  4738. //
  4739. if(!SpIsArc())
  4740. {
  4741. //
  4742. // system partition directory is the root of C:.
  4743. //
  4744. SystemPartitionDirectory = L"";
  4745. }
  4746. else
  4747. {
  4748. SystemPartitionDirectory = SpDetermineSystemPartitionDirectory(
  4749. SystemPartitionRegion,
  4750. OriginalSystemPartitionDirectory
  4751. );
  4752. }
  4753. SpStringToUpper(TargetPath);
  4754. //
  4755. // do any file system conversion
  4756. //
  4757. if(!RemoteSysPrepSetup && !SpDrEnabled()) {
  4758. SpUpgradeToNT50FileSystems(
  4759. SifHandle,
  4760. SystemPartitionRegion,
  4761. TargetRegion,
  4762. SetupSourceDevicePath,
  4763. DirectoryOnSetupSource
  4764. );
  4765. }
  4766. //
  4767. // Run autochk on Nt and system partitions
  4768. //
  4769. //
  4770. // if it boot from hard disk, need to check the current partition.
  4771. //
  4772. if(IsNEC_98) {
  4773. BootRegion = SystemPartitionRegion;
  4774. if(!_wcsnicmp(NtBootDevicePath,DISK_DEVICE_NAME_BASE,wcslen(DISK_DEVICE_NAME_BASE))) {
  4775. SpEnumerateDiskRegions( (PSPENUMERATEDISKREGIONS)SpDetermineBootPartitionEnumNec98,
  4776. (ULONG_PTR)&BootRegion );
  4777. }
  4778. }
  4779. if (!SpAsrIsQuickTest()) {
  4780. AutochkRunning = TRUE;
  4781. SpRunAutochkOnNtAndSystemPartitions( SifHandle,
  4782. TargetRegion,
  4783. (!IsNEC_98 ? SystemPartitionRegion : BootRegion),
  4784. SetupSourceDevicePath,
  4785. DirectoryOnSetupSource,
  4786. TargetPath
  4787. );
  4788. AutochkRunning = FALSE;
  4789. }
  4790. if( DeleteTarget )
  4791. SpDeleteExistingTargetDir( TargetRegion, TargetPath, TRUE, SP_SCRN_CLEARING_OLD_WINNT );
  4792. #ifdef _X86_
  4793. if (WinUpgradeType == UpgradeWin95) {
  4794. enableBackup = SpGetSectionKeyIndex (
  4795. WinntSifHandle,
  4796. WINNT_D_WIN9XUPG_USEROPTIONS_W,
  4797. WINNT_D_ENABLE_BACKUP_W,
  4798. 0
  4799. );
  4800. if (enableBackup && _wcsicmp(enableBackup, WINNT_A_YES_W) == 0) {
  4801. disableCompression = SpGetSectionKeyIndex (
  4802. WinntSifHandle,
  4803. WINNT_D_WIN9XUPG_USEROPTIONS_W,
  4804. WINNT_D_DISABLE_BACKUP_COMPRESSION_W,
  4805. 0
  4806. );
  4807. if (disableCompression && _wcsicmp(disableCompression, WINNT_A_YES_W) == 0) {
  4808. compressionType = tcompTYPE_NONE;
  4809. } else {
  4810. compressionType = tcompTYPE_MSZIP;
  4811. }
  4812. g_Win9xBackup = SpBackUpWin9xFiles (WinntSifHandle, compressionType);
  4813. }
  4814. }
  4815. #endif // X86
  4816. //
  4817. // If we are installing into an existing tree we need to delete some
  4818. // files and backup some files
  4819. //
  4820. if(NTUpgrade != DontUpgrade) {
  4821. SpDeleteAndBackupFiles(
  4822. SifHandle,
  4823. TargetRegion,
  4824. TargetPath
  4825. );
  4826. }
  4827. TESTHOOK(6);
  4828. #ifdef _X86_
  4829. //
  4830. // If we are migrating Win95, delete some files, and move other files
  4831. //
  4832. switch(WinUpgradeType) {
  4833. case UpgradeWin95:
  4834. SpDeleteWin9xFiles(WinntSifHandle);
  4835. SpMoveWin9xFiles(WinntSifHandle);
  4836. break;
  4837. case UpgradeWin31:
  4838. SpRemoveWin31(TargetRegion,TargetPath);
  4839. break;
  4840. }
  4841. #endif
  4842. #if defined(REMOTE_BOOT)
  4843. //
  4844. // If this is a remote boot, tell the redirector that the local disk is
  4845. // ready to be used for "local" items like the cache and pagefile.
  4846. //
  4847. if (RemoteBootSetup && !RemoteInstallSetup && !RemoteSysPrepSetup && (HardDiskCount != 0)) {
  4848. IoStartCscForTextmodeSetup( (BOOLEAN)(NTUpgrade != DontUpgrade) );
  4849. }
  4850. #endif // defined(REMOTE_BOOT)
  4851. TESTHOOK(7);
  4852. //
  4853. // Create the paging file.
  4854. //
  4855. // The copy files and registry operations use memory mapped IO.
  4856. // This can result in huge numbers of dirty pages and can cause
  4857. // the filesystems to throttle if the percentage of memory that
  4858. // is dirty becomes high. The only way out of this is for the
  4859. // dirty page writer thread to run and it cannot do so unless
  4860. // there is a paging file.
  4861. //
  4862. SpNtNameFromRegion(
  4863. TargetRegion,
  4864. TemporaryBuffer,
  4865. sizeof(TemporaryBuffer),
  4866. PartitionOrdinalCurrent
  4867. );
  4868. SpConcatenatePaths(TemporaryBuffer,L"PAGEFILE.SYS");
  4869. FullTargetPath = SpDupStringW(TemporaryBuffer);
  4870. // Status = SpCreatePageFile(FullTargetPath,1*(1024*1024*1024),(1792*1024*1024));
  4871. Status = SpCreatePageFile(FullTargetPath,40*(1024*1024),50*(1024*1024));
  4872. if(!NT_SUCCESS(Status)) {
  4873. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Warning: unable to create pagefile %ws (%lx)",FullTargetPath,Status));
  4874. }
  4875. SpMemFree(FullTargetPath);
  4876. //
  4877. // On a remote boot machine, copy over the sources to the disk,
  4878. // then change the setup path to point to them.
  4879. //
  4880. if (RemoteInstallSetup) {
  4881. PWSTR TargetPartitionName;
  4882. PWSTR CopySource;
  4883. PWSTR LocalSourcePath;
  4884. //
  4885. // Initialize the diamond decompression engine.
  4886. //
  4887. SpdInitialize();
  4888. wcscpy( TemporaryBuffer, SetupSourceDevicePath );
  4889. SpConcatenatePaths( TemporaryBuffer, DirectoryOnSetupSource );
  4890. CopySource = SpDupStringW( TemporaryBuffer );
  4891. //
  4892. // Copy all the source files to the disk.
  4893. //
  4894. SpNtNameFromRegion(
  4895. TargetRegion,
  4896. TemporaryBuffer,
  4897. sizeof(TemporaryBuffer),
  4898. PartitionOrdinalCurrent
  4899. );
  4900. TargetPartitionName = SpDupStringW(TemporaryBuffer);
  4901. //
  4902. // Delete the directory if it is there.
  4903. //
  4904. SpConcatenatePaths(TemporaryBuffer,
  4905. LocalSourceDirectory);
  4906. LocalSourcePath = SpDupStringW(TemporaryBuffer);
  4907. if (SpFileExists(LocalSourcePath, TRUE)) {
  4908. ENUMFILESRESULT Result;
  4909. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Deleting existing %ws directory\n", LocalSourcePath));
  4910. SpStartScreen(SP_SCRN_WAIT_REMOVING_TEMP_FILES,0,6,TRUE,FALSE,DEFAULT_ATTRIBUTE);
  4911. Result = SpEnumFilesRecursive(
  4912. LocalSourcePath,
  4913. SpDelEnumFile,
  4914. &Status,
  4915. NULL);
  4916. }
  4917. SpMemFree(LocalSourcePath);
  4918. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Copying directories from %ws to %ws%ws\n",
  4919. CopySource, TargetPartitionName, LocalSourceDirectory));
  4920. SpCopyDirRecursive(
  4921. CopySource,
  4922. TargetPartitionName,
  4923. LocalSourceDirectory,
  4924. COPY_NODECOMP
  4925. );
  4926. //
  4927. // Now that the copy is done, the setup source path becomes the
  4928. // previous target. We are no longer even pretending to be doing
  4929. // a remote boot setup.
  4930. //
  4931. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Switching to local setup source\n"));
  4932. SetupSourceDevicePath = TargetPartitionName;
  4933. DirectoryOnSetupSource = LocalSourceDirectory;
  4934. if ( PreInstall ) {
  4935. wcscpy( TemporaryBuffer, DirectoryOnSetupSource );
  4936. SpConcatenatePaths( TemporaryBuffer, WINNT_OEM_TEXTMODE_DIR_W );
  4937. SpMemFree( PreinstallOemSourcePath );
  4938. PreinstallOemSourcePath = SpDupStringW( TemporaryBuffer );
  4939. }
  4940. RemoteBootSetup = FALSE;
  4941. SpMemFree(CopySource);
  4942. }
  4943. //
  4944. // If this isn't an automated ASR test, copy the files that make up the product.
  4945. // Note that we cannot pass \device\floppy0 to SpCopyFiles() as a constant string,
  4946. // because this function at some point will attempt to convert the string to lower case,
  4947. // which will cause a bugcheck, since SpToLowerCase will overwrite the constant string.
  4948. // So we make a duplicate of the constant string.
  4949. //
  4950. ThirdPartySourceDevicePath = SpDupStringW( L"\\device\\floppy0" );
  4951. if (RemoteSysPrepSetup) {
  4952. //
  4953. // Initialize the diamond decompression engine.
  4954. //
  4955. SpdInitialize();
  4956. SpInstallSysPrepImage(SifHandle,WinntSifHandle, RemoteIMirrorFileData, RemoteIMirrorMemoryData);
  4957. SpFixupThirdPartyComponents( SifHandle,
  4958. ( PreInstall ) ? SetupSourceDevicePath : ThirdPartySourceDevicePath,
  4959. TargetRegion,
  4960. TargetPath,
  4961. SystemPartitionRegion,
  4962. SystemPartitionDirectory );
  4963. goto CleanAndFinish;
  4964. }
  4965. //
  4966. // HACK: rename setupapi.log to setupapi.old here because this logfile can
  4967. // get very large on upgrades
  4968. //
  4969. if (NTUpgrade != DontUpgrade) {
  4970. SpRenameSetupAPILog(TargetRegion,TargetPath);
  4971. }
  4972. if (!SpAsrIsQuickTest()) {
  4973. SpCopyFiles(
  4974. SifHandle,
  4975. SystemPartitionRegion,
  4976. TargetRegion,
  4977. TargetPath,
  4978. SystemPartitionDirectory,
  4979. SetupSourceDevicePath,
  4980. DirectoryOnSetupSource,
  4981. ( PreInstall )? SetupSourceDevicePath : ThirdPartySourceDevicePath
  4982. );
  4983. }
  4984. TESTHOOK(8);
  4985. if (SpDrEnabled()) {
  4986. SpDrCleanup();
  4987. }
  4988. #if defined HEADLESS_ATTENDEDTEXTMODE_UNATTENDEDGUIMODE
  4989. // Get data into inf file if we have a terminal connected and it
  4990. // is a fresh install only
  4991. if (HeadlessTerminalConnected && (!UnattendedOperation) &&(!ANY_TYPE_OF_UPGRADE)) {
  4992. UnattendedGuiOperation = TRUE;
  4993. SpGetNecessaryParameters();
  4994. if (AdvancedServer) {
  4995. SpGetServerDetails();
  4996. }
  4997. }
  4998. #endif
  4999. SendSetupProgressEvent(SavingSettingsEvent, SavingSettingsStartEvent, NULL);
  5000. //
  5001. // Process Crash Recovery settings on upgrade. We call this here for another reason here. We flush the
  5002. // $winnt$.inf file in SpInitializeRegistry. Since we write to that file doing it here makes sure that
  5003. // the file gets the entries we wrote
  5004. //
  5005. if( NTUpgrade == UpgradeFull ){
  5006. SpDisableCrashRecoveryForGuiMode(TargetRegion, TargetPath);
  5007. }
  5008. if (ASRMODE_QUICKTEST_TEXT != SpAsrGetAsrMode()) {
  5009. //
  5010. // Configure the registry.
  5011. //
  5012. SpInitializeRegistry(
  5013. SifHandle,
  5014. TargetRegion,
  5015. TargetPath,
  5016. SetupSourceDevicePath,
  5017. DirectoryOnSetupSource,
  5018. wcsstr(DirectoryOnBootDevice,L"\\$WIN_NT$.~BT") ? NtBootDevicePath : NULL,
  5019. SystemPartitionRegion
  5020. );
  5021. TESTHOOK(9);
  5022. }
  5023. SendSetupProgressEvent(SavingSettingsEvent, HiveProcessingEndEvent, NULL);
  5024. UpdateBootList:
  5025. if (SpDrEnabled() && !RepairWinnt) { // ASR (not ER)
  5026. SpDrCopyFiles();
  5027. }
  5028. #ifdef _X86_
  5029. //
  5030. // NEC98
  5031. //
  5032. if (IsNEC_98) { //NEC98
  5033. //
  5034. // Once clear BOOTVARS[], then rebuild it when upgrade from NT.
  5035. //
  5036. TargetRegion_Nec98 = TargetRegion;
  5037. SpReInitializeBootVars_Nec98();
  5038. } //NEC98
  5039. #endif
  5040. //
  5041. // If this is an upgrade we need to remove the entry which exists for
  5042. // this system right now, because we are using new entries. We can use
  5043. // this opportunity to also clean out the boot ini and remove all entries
  5044. // which point to the current nt partition and path
  5045. //
  5046. // Also do this in the case where we wiped out an existing directory during
  5047. // a clean install.
  5048. //
  5049. OldOsLoadOptions = NULL;
  5050. if(NTUpgrade == UpgradeFull || RepairItems[RepairNvram] || DeleteTarget
  5051. #if defined(REMOTE_BOOT)
  5052. || RemoteBootSetup
  5053. #endif // defined(REMOTE_BOOT)
  5054. ) {
  5055. SpRemoveInstallationFromBootList(
  5056. NULL,
  5057. TargetRegion,
  5058. TargetPath,
  5059. NULL,
  5060. NULL,
  5061. PrimaryArcPath,
  5062. #if defined(REMOTE_BOOT)
  5063. RemoteBootSetup,
  5064. #endif // defined(REMOTE_BOOT)
  5065. &OldOsLoadOptions
  5066. );
  5067. #if defined(_AMD64_) || defined(_X86_)
  5068. // call again to delete the secondary Arc name
  5069. SpRemoveInstallationFromBootList(
  5070. NULL,
  5071. TargetRegion,
  5072. TargetPath,
  5073. NULL,
  5074. NULL,
  5075. SecondaryArcPath,
  5076. #if defined(REMOTE_BOOT)
  5077. RemoteBootSetup,
  5078. #endif // defined(REMOTE_BOOT)
  5079. &OldOsLoadOptions
  5080. );
  5081. #endif // defined(_AMD64_) || defined(_X86_)
  5082. }
  5083. #if defined(_AMD64_) || defined(_X86_)
  5084. //
  5085. // Lay NT boot code on C:. Do this before flushing boot vars
  5086. // because it may change the 'previous os' selection.
  5087. //
  5088. if ((SystemPartitionRegion != NULL) && (!RepairWinnt || RepairItems[RepairBootSect])) {
  5089. SpLayBootCode(SystemPartitionRegion);
  5090. }
  5091. #endif // defined(_AMD64_) || defined(_X86_)
  5092. /*
  5093. At the end of text-mode setup, issue an IOCTL_STORAGE_EJECT_MEDIA to the CD-ROM
  5094. you are installing from. On some machines this won't help at all, but on others we
  5095. can avoid the (txtsetup, reboot, boot from CD back into txtsetup) cycle that i always
  5096. get into. This would also provide an interrupt for developers like me who don't pay
  5097. any attention to setup - we could tell when textmode setup was finished.
  5098. In GUI-mode setup if the CD can't be found in the cdrom drive issue an
  5099. IOCTL_STORAGE_LOAD_MEDIA to the cd to pull the tray back in.
  5100. If you still can't find the CD, wait for a media change notification from the
  5101. system. When you get one (or the user hits the okay button), you continue.
  5102. Figureing out when the media has been inserted automagically would be snazzier
  5103. than just waiting there for the user to hit the OK button.
  5104. */
  5105. #if defined(REMOTE_BOOT)
  5106. //
  5107. // If this is a remote boot setup, rename the loaders and initialize configuration.
  5108. //
  5109. if (RemoteBootSetup) {
  5110. (VOID)SpFixupRemoteBootLoader(RemoteBootTarget);
  5111. (VOID)SpCreateRemoteBootCfg(RemoteBootTarget, SystemPartitionRegion);
  5112. }
  5113. #endif // defined(REMOTE_BOOT)
  5114. if (!RepairWinnt || RepairItems[RepairNvram]) {
  5115. //
  5116. // Add a boot set for this installation.
  5117. //
  5118. SpAddInstallationToBootList(
  5119. SifHandle,
  5120. SystemPartitionRegion,
  5121. SystemPartitionDirectory,
  5122. TargetRegion,
  5123. TargetPath,
  5124. FALSE,
  5125. OldOsLoadOptions
  5126. );
  5127. if(OldOsLoadOptions) {
  5128. SpMemFree(OldOsLoadOptions);
  5129. }
  5130. SpCleanSysPartOrphan();
  5131. #if defined(REMOTE_BOOT)
  5132. //
  5133. // Make sure that the boot.ini in the machine directory is written.
  5134. //
  5135. if (RemoteBootSetup) {
  5136. if (!SpFlushRemoteBootVars(TargetRegion)) {
  5137. WCHAR DriveLetterString[2];
  5138. DriveLetterString[0] = TargetRegion->DriveLetter;
  5139. DriveLetterString[1] = L'\0';
  5140. SpStringToUpper(DriveLetterString);
  5141. SpStartScreen(SP_SCRN_CANT_INIT_FLEXBOOT,
  5142. 3,
  5143. HEADER_HEIGHT+1,
  5144. FALSE,
  5145. FALSE,
  5146. DEFAULT_ATTRIBUTE,
  5147. DriveLetterString,
  5148. DriveLetterString
  5149. );
  5150. // SpDisplayScreen(SP_SCRN_CANT_INIT_FLEXBOOT,3,HEADER_HEIGHT+1);
  5151. SpDisplayStatusText(SP_STAT_F3_EQUALS_EXIT,DEFAULT_STATUS_ATTRIBUTE);
  5152. SpInputDrain();
  5153. while(SpInputGetKeypress() != KEY_F3) ;
  5154. SpDone(0,FALSE,TRUE);
  5155. }
  5156. }
  5157. #endif // defined(REMOTE_BOOT)
  5158. SpCompleteBootListConfig( TargetRegion->DriveLetter );
  5159. if (IsNEC_98) { //NEC98
  5160. //
  5161. // Set auto boot flag into PTE.
  5162. //
  5163. SpSetAutoBootFlag(TargetRegion,TRUE);
  5164. } //NEC98
  5165. }
  5166. //
  5167. // If system was repaired, and either the System Partition
  5168. // or the NT Partition is an FT partition, then set the
  5169. // appropriate flag in the registry, so that next time the
  5170. // system boots, it checks and updates the partition's image.
  5171. //
  5172. // (guhans) removed SpDrEnabled, ASR doesn't support FT partitions
  5173. //
  5174. if( RepairWinnt ) {
  5175. UCHAR TmpSysId;
  5176. UCHAR TmpNtPartitionSysId;
  5177. BOOLEAN SystemPartitionIsFT;
  5178. BOOLEAN TargetPartitionIsFT;
  5179. TmpSysId = SpPtGetPartitionType(SystemPartitionRegion);
  5180. ASSERT(TmpSysId != PARTITION_ENTRY_UNUSED);
  5181. SystemPartitionIsFT = ((TmpSysId & VALID_NTFT) == VALID_NTFT) ||
  5182. ((TmpSysId & PARTITION_NTFT) == PARTITION_NTFT);
  5183. TmpSysId = SpPtGetPartitionType(TargetRegion);
  5184. ASSERT(TmpSysId != PARTITION_ENTRY_UNUSED);
  5185. TargetPartitionIsFT = ((TmpSysId & VALID_NTFT) == VALID_NTFT) ||
  5186. ((TmpSysId & PARTITION_NTFT) == PARTITION_NTFT);
  5187. #if defined(_AMD64_) || defined(_X86_)
  5188. if( ( SystemPartitionIsFT &&
  5189. ( RepairItems[ RepairNvram ] || RepairItems[ RepairBootSect ] )
  5190. ) ||
  5191. ( TargetPartitionIsFT &&
  5192. ( RepairItems[ RepairFiles ] )
  5193. )
  5194. ) {
  5195. SpSetDirtyShutdownFlag( TargetRegion, TargetPath );
  5196. }
  5197. #else
  5198. if( ( SystemPartitionIsFT || TargetPartitionIsFT ) && RepairItems[ RepairFiles ] ) {
  5199. SpSetDirtyShutdownFlag( TargetRegion, TargetPath );
  5200. }
  5201. #endif // defined(_AMD64_) || defined(_X86_)
  5202. }
  5203. CleanAndFinish:
  5204. if ((RemoteInstallSetup || RemoteSysPrepSetup) && (NetBootSifPath != NULL)) {
  5205. //
  5206. // Clean out the temporary .sif file. SpDeleteFile concatenates its
  5207. // arguments to form the final path.
  5208. //
  5209. Status = SpDeleteFile(L"\\Device\\LanmanRedirector", NetBootSifPath, NULL);
  5210. if (!NT_SUCCESS(Status)) {
  5211. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Could not delete temporary file %ws\n", NetBootSifPath));
  5212. }
  5213. }
  5214. SendSetupProgressEvent(SavingSettingsEvent, SavingSettingsEndEvent, NULL);
  5215. #if defined(EFI_NVRAM_ENABLED)
  5216. //
  5217. // Deal with the driver entry for fpswa.efi
  5218. //
  5219. {
  5220. PWSTR SystemPartitionDevicePath;
  5221. SpNtNameFromRegion(SystemPartitionRegion, TemporaryBuffer, sizeof(TemporaryBuffer), PartitionOrdinalCurrent);
  5222. SystemPartitionDevicePath = SpDupStringW(TemporaryBuffer);
  5223. Status = SpUpdateDriverEntry(
  5224. FPSWA_DRIVER_IMAGE_NAME,
  5225. FPSWA_DRIVER_FRIENDLY_NAME,
  5226. SystemPartitionDevicePath,
  5227. SystemPartitionDirectory,
  5228. NULL,
  5229. FPSWA_DRIVER_DEST_DIR
  5230. );
  5231. SpMemFree(SystemPartitionDevicePath);
  5232. if(!NT_SUCCESS(Status)) {
  5233. KdPrintEx((
  5234. DPFLTR_SETUP_ID,
  5235. DPFLTR_ERROR_LEVEL,
  5236. "SETUP: Could not update driver entry for fpswa.efi, status == %08lx\n",
  5237. Status
  5238. ));
  5239. }
  5240. }
  5241. #endif
  5242. //
  5243. // Done with boot variables and arc names.
  5244. //
  5245. SpFreeBootVars();
  5246. SpFreeArcNames();
  5247. SpDone(0,TRUE, UnattendedOperation ? UnattendWaitForReboot : TRUE);
  5248. //
  5249. // We never get here because SpDone doesn't return.
  5250. //
  5251. SpvidTerminate();
  5252. SpInputTerminate();
  5253. SpTerminate();
  5254. return((ULONG)STATUS_SUCCESS);
  5255. }
  5256. VOID
  5257. SpDetermineProductType(
  5258. IN PVOID SifHandle
  5259. )
  5260. /*++
  5261. Routine Description:
  5262. Determine whether this is advanced server we are setting up,
  5263. as dictated by the ProductType value in [SetupData] section of
  5264. txtsetup.sif. A non-0 value indicates that we are running
  5265. advanced server.
  5266. Also determine product version.
  5267. The global variables:
  5268. - AdvancedServer
  5269. - MajorVersion
  5270. - MinorVersion
  5271. are modified
  5272. Arguments:
  5273. SifHandle - supplies handle to loaded txtsetup.sif.
  5274. Return Value:
  5275. None.
  5276. --*/
  5277. {
  5278. PWSTR p;
  5279. ULONG l;
  5280. //
  5281. // Assume Workstation product.
  5282. //
  5283. AdvancedServer = FALSE;
  5284. //
  5285. // Get the product type from the sif file.
  5286. //
  5287. p = SpGetSectionKeyIndex(SifHandle,SIF_SETUPDATA,SIF_PRODUCTTYPE,0);
  5288. if(p) {
  5289. //
  5290. // Convert to numeric value.
  5291. //
  5292. l = SpStringToLong(p,NULL,10);
  5293. switch (l) {
  5294. case 1: //SRV
  5295. case 2: //ADS
  5296. case 3: //DTC
  5297. case 5: //BLA
  5298. case 6: //SBS
  5299. AdvancedServer = TRUE;
  5300. break;
  5301. case 4: //PER
  5302. case 0: //PRO
  5303. default:
  5304. ;
  5305. }
  5306. } else {
  5307. SpFatalSifError(SifHandle,SIF_SETUPDATA,SIF_PRODUCTTYPE,0,0);
  5308. }
  5309. //
  5310. // Get the product major version
  5311. //
  5312. p = SpGetSectionKeyIndex(
  5313. SifHandle,
  5314. SIF_SETUPDATA,
  5315. SIF_MAJORVERSION,
  5316. 0
  5317. );
  5318. if(!p) {
  5319. SpFatalSifError(SifHandle,SIF_SETUPDATA,SIF_MAJORVERSION,0,0);
  5320. }
  5321. WinntMajorVer = (ULONG)SpStringToLong(p,NULL,10);
  5322. //
  5323. // Get the product minor version
  5324. //
  5325. p = SpGetSectionKeyIndex(
  5326. SifHandle,
  5327. SIF_SETUPDATA,
  5328. SIF_MINORVERSION,
  5329. 0
  5330. );
  5331. if(!p) {
  5332. SpFatalSifError(SifHandle,SIF_SETUPDATA,SIF_MINORVERSION,0,0);
  5333. }
  5334. WinntMinorVer = (ULONG)SpStringToLong(p,NULL,10);
  5335. //
  5336. // Build the string that contains the signature that
  5337. // identifies setup.log
  5338. // Allocate a buffer of reasonable size
  5339. //
  5340. SIF_NEW_REPAIR_NT_VERSION = SpMemAlloc( 30*sizeof(WCHAR) );
  5341. if( SIF_NEW_REPAIR_NT_VERSION == NULL ) {
  5342. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to allocate memory for SIF_NEW_REPAIR_NT_VERSION \n" ));
  5343. return;
  5344. }
  5345. swprintf( SIF_NEW_REPAIR_NT_VERSION,
  5346. SIF_NEW_REPAIR_NT_VERSION_TEMPLATE,
  5347. WinntMajorVer,WinntMinorVer );
  5348. }
  5349. BOOL
  5350. SpDetermineInstallationSource(
  5351. IN PVOID SifHandle,
  5352. OUT PWSTR *DevicePath,
  5353. OUT PWSTR *DirectoryOnDevice,
  5354. IN BOOLEAN bEscape
  5355. )
  5356. {
  5357. PWSTR p,q;
  5358. BOOLEAN CdInstall;
  5359. //
  5360. // Assume CD-ROM installation.
  5361. //
  5362. CdInstall = TRUE;
  5363. //
  5364. // See whether an override source device has been specified. This can be
  5365. // specified in either winnt.sif or in txtsetup.sif. (Remote boot setup
  5366. // uses winnt.sif.)
  5367. //
  5368. p = SpGetSectionKeyIndex(WinntSifHandle,SIF_SETUPDATA,SIF_SETUPSOURCEDEVICE,0);
  5369. if (p == NULL) {
  5370. p = SpGetSectionKeyIndex(SifHandle,SIF_SETUPDATA,SIF_SETUPSOURCEDEVICE,0);
  5371. }
  5372. if(p != NULL) {
  5373. //
  5374. // Determine if the specified device is a cd-rom so we can set the
  5375. // cd-rom flag accordingly.
  5376. //
  5377. q = SpDupStringW(p);
  5378. if (q) {
  5379. SpStringToLower(q);
  5380. if(!wcsstr(q,L"\\device\\cdrom")) {
  5381. CdInstall = FALSE;
  5382. }
  5383. SpMemFree(q);
  5384. }
  5385. //
  5386. // Inform the caller of the device path.
  5387. //
  5388. *DevicePath = p;
  5389. } else {
  5390. WCHAR szDevicePath[MAX_PATH];
  5391. PWSTR szDefDevicePath = L"\\device\\cdrom0";
  5392. ULONG ulNumCDRoms = IoGetConfigurationInformation()->CdRomCount;
  5393. // assume cdrom0 has the required installation CD
  5394. wcscpy(szDevicePath, szDefDevicePath);
  5395. //
  5396. // If there is no CD-ROM drive, put a message informing the user
  5397. // that setup cannot continue.
  5398. // In the repair case, we pretend that there is a CD-ROM drive,
  5399. // so that the user can at least repair the hives, boot sector,
  5400. // and the boot variables (boot.ini on amd64/x86 case)
  5401. //
  5402. if (!ulNumCDRoms) {
  5403. if (!RepairWinnt && !SpAsrIsQuickTest()) {
  5404. if(!bEscape) {
  5405. SpDisplayScreen(SP_SCRN_NO_VALID_SOURCE,3,HEADER_HEIGHT+1);
  5406. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,
  5407. SP_STAT_F3_EQUALS_EXIT,0);
  5408. SpInputDrain();
  5409. while(SpInputGetKeypress() != KEY_F3) ;
  5410. SpDone(0,FALSE,TRUE);
  5411. }
  5412. } else {
  5413. RepairNoCDROMDrive = TRUE;
  5414. }
  5415. } else {
  5416. if(!RepairWinnt && !SpAsrIsQuickTest()) {
  5417. PWSTR szTagfile = 0, szDescription = 0, szMediaShortName;
  5418. BOOLEAN bRedrawNeeded = FALSE;
  5419. BOOLEAN bDiskInserted = FALSE;
  5420. szMediaShortName = SpLookUpValueForFile(
  5421. SifHandle,
  5422. L"eula.txt",
  5423. INDEX_WHICHMEDIA,
  5424. TRUE
  5425. );
  5426. SpGetSourceMediaInfo(SifHandle, szMediaShortName,
  5427. &szDescription, &szTagfile, NULL);
  5428. //
  5429. // Prompt for the disk, based on the setup media type.
  5430. // (this routine will scan all the CD-ROMs and return
  5431. // proper CD-ROM device path)
  5432. //
  5433. bDiskInserted = SpPromptForDisk(
  5434. szDescription,
  5435. szDevicePath,
  5436. szTagfile,
  5437. FALSE, // don't ignore disk in drive
  5438. bEscape, // allow/disallow escape
  5439. TRUE, // warn about multiple prompts for same disk
  5440. &bRedrawNeeded
  5441. );
  5442. if(!bDiskInserted)
  5443. wcscpy(szDevicePath, szDefDevicePath);
  5444. }
  5445. }
  5446. *DevicePath = SpDupStringW(szDevicePath);
  5447. }
  5448. //
  5449. // Fetch the directory on the source device.
  5450. //
  5451. if((p = SpGetSectionKeyIndex(SifHandle,SIF_SETUPDATA,SIF_SETUPSOURCEPATH,0)) == NULL) {
  5452. SpFatalSifError(SifHandle,SIF_SETUPDATA,SIF_SETUPSOURCEPATH,0,0);
  5453. }
  5454. *DirectoryOnDevice = p;
  5455. return(CdInstall);
  5456. }
  5457. VOID
  5458. SpGetWinntParams(
  5459. OUT PWSTR *DevicePath,
  5460. OUT PWSTR *DirectoryOnDevice
  5461. )
  5462. /*++
  5463. Routine Description:
  5464. Determine the local source partition and directory on the partition.
  5465. The local source partition should have already been located for us
  5466. by the partitioning engine when it initialized. The directory name
  5467. within the partition is constant.
  5468. Note: this routine should only be called in the winnt.exe setup case!
  5469. Arguments:
  5470. DevicePath - receives the path to the local source partition
  5471. in the nt namespace. The caller should not attempt to free
  5472. this buffer.
  5473. DirectoryOnDevice - receives the directory name of the local source.
  5474. This is actually a fixed constant but is included here for future use.
  5475. Return Value:
  5476. None. If the local source was not located, setup cannot continue.
  5477. --*/
  5478. {
  5479. ASSERT(WinntSetup && !WinntFromCd);
  5480. if(LocalSourceRegion) {
  5481. SpNtNameFromRegion(
  5482. LocalSourceRegion,
  5483. TemporaryBuffer,
  5484. sizeof(TemporaryBuffer),
  5485. PartitionOrdinalCurrent
  5486. );
  5487. *DevicePath = SpDupStringW(TemporaryBuffer);
  5488. *DirectoryOnDevice = LocalSourceDirectory;
  5489. } else {
  5490. //
  5491. // Error -- can't locate local source directory
  5492. // prepared by winnt.exe.
  5493. //
  5494. SpDisplayScreen(SP_SCRN_CANT_FIND_LOCAL_SOURCE,3,HEADER_HEIGHT+1);
  5495. SpDisplayStatusOptions(
  5496. DEFAULT_STATUS_ATTRIBUTE,
  5497. SP_STAT_F3_EQUALS_EXIT,
  5498. 0
  5499. );
  5500. SpInputDrain();
  5501. while(SpInputGetKeypress() != KEY_F3) ;
  5502. SpDone(0,FALSE,TRUE);
  5503. }
  5504. }
  5505. VOID
  5506. SpInitializeDriverInf(
  5507. IN HANDLE MasterSifHandle,
  5508. IN PWSTR SetupSourceDevicePath,
  5509. IN PWSTR DirectoryOnSourceDevice
  5510. )
  5511. /*++
  5512. Routine Description:
  5513. Open a handle to drvindex.inf
  5514. Then open a handle to driver.cab
  5515. Arguments:
  5516. MasterSifHandle - Handle to txtsetup.sif.
  5517. SetupSourceDevicePath - Path to the device that contains the source media.
  5518. DirectoryOnSourceDevice - Directory on the media where setupp.ini is located.
  5519. Return Value:
  5520. NONE.
  5521. --*/
  5522. {
  5523. PWSTR MediaShortName;
  5524. PWSTR MediaDirectory;
  5525. PWSTR DriverInfPath;
  5526. ULONG ErrorSubId;
  5527. ULONG ErrorLine;
  5528. PWSTR TmpPid;
  5529. NTSTATUS Status;
  5530. PWSTR PidExtraData;
  5531. CHAR ExtraDataArray[25];
  5532. PWSTR PrivateInfPath;
  5533. OBJECT_ATTRIBUTES Obja;
  5534. UNICODE_STRING UnicodeString;
  5535. IO_STATUS_BLOCK IoStatusBlock;
  5536. PWSTR Tagfile,Description;
  5537. BOOLEAN bRedraw = FALSE;
  5538. ULONG ValidKeys[3] = { KEY_F3,ASCI_CR,0 };
  5539. //
  5540. // Prepair to load drvindex.inf
  5541. //
  5542. MediaShortName = SpLookUpValueForFile(
  5543. MasterSifHandle,
  5544. L"drvindex.inf",
  5545. INDEX_WHICHMEDIA,
  5546. TRUE
  5547. );
  5548. if (ForceConsole || ConsoleFromWinnt32){
  5549. //
  5550. // The user needs to reach to console so he can
  5551. // ESCAPE is the removable media is not present
  5552. // in the drive
  5553. //
  5554. SpGetSourceMediaInfo(MasterSifHandle,MediaShortName,&Description,&Tagfile,NULL);
  5555. //
  5556. // if setup source or directory on source is not present
  5557. // try to fetch it
  5558. //
  5559. if (!SetupSourceDevicePath)
  5560. SetupSourceDevicePath = gpCmdConsBlock->SetupSourceDevicePath;
  5561. if (!DirectoryOnSourceDevice)
  5562. DirectoryOnSourceDevice = gpCmdConsBlock->DirectoryOnSetupSource;
  5563. if (!SetupSourceDevicePath || !DirectoryOnSourceDevice){
  5564. SpDetermineInstallationSource(
  5565. MasterSifHandle,
  5566. &SetupSourceDevicePath,
  5567. &DirectoryOnSourceDevice,
  5568. TRUE // allow to ESCAPE if CD-ROM is not found
  5569. );
  5570. if (SetupSourceDevicePath) {
  5571. if (gpCmdConsBlock->SetupSourceDevicePath) {
  5572. SpMemFree(gpCmdConsBlock->SetupSourceDevicePath);
  5573. gpCmdConsBlock->SetupSourceDevicePath = SetupSourceDevicePath;
  5574. }
  5575. }
  5576. if (DirectoryOnSourceDevice){
  5577. if(gpCmdConsBlock->DirectoryOnSetupSource) {
  5578. SpMemFree(gpCmdConsBlock->DirectoryOnSetupSource);
  5579. gpCmdConsBlock->DirectoryOnSetupSource = DirectoryOnSourceDevice;
  5580. }
  5581. }
  5582. if (!SetupSourceDevicePath || !DirectoryOnSourceDevice)
  5583. return; // can't proceed
  5584. }
  5585. if (!SpPromptForDisk(
  5586. Description,
  5587. SetupSourceDevicePath,
  5588. Tagfile,
  5589. FALSE, // don't ignore disk in drive
  5590. TRUE, // allow escape
  5591. TRUE, // warn about multiple prompts for same disk
  5592. &bRedraw
  5593. )) {
  5594. DriverInfHandle = NULL;
  5595. if (bRedraw) {
  5596. // redraw the screen
  5597. SpvidClearScreenRegion( 0, 0, 0, 0, DEFAULT_BACKGROUND );
  5598. }
  5599. return;
  5600. }
  5601. if (bRedraw) {
  5602. // redraw the screen
  5603. SpvidClearScreenRegion( 0, 0, 0, 0, DEFAULT_BACKGROUND );
  5604. }
  5605. } else {
  5606. //
  5607. // Prompt for the disk, based on the setup media type.
  5608. // Note : Will not return until the media is provided
  5609. //
  5610. SpPromptForSetupMedia(
  5611. MasterSifHandle,
  5612. MediaShortName,
  5613. SetupSourceDevicePath
  5614. );
  5615. }
  5616. SpGetSourceMediaInfo(MasterSifHandle,MediaShortName,NULL,NULL,&MediaDirectory);
  5617. wcscpy( TemporaryBuffer, SetupSourceDevicePath );
  5618. SpConcatenatePaths( TemporaryBuffer, DirectoryOnSourceDevice );
  5619. SpConcatenatePaths( TemporaryBuffer, MediaDirectory );
  5620. SpConcatenatePaths( TemporaryBuffer, L"drvindex.inf" );
  5621. DriverInfPath = SpDupStringW( TemporaryBuffer );
  5622. if (!DriverInfPath) {
  5623. Status = STATUS_NO_MEMORY;
  5624. } else {
  5625. TryAgain1:
  5626. //
  5627. // load the inf
  5628. //
  5629. Status = SpLoadSetupTextFile(
  5630. DriverInfPath,
  5631. NULL, // No image already in memory
  5632. 0, // Image size is empty
  5633. &DriverInfHandle,
  5634. &ErrorLine,
  5635. TRUE,
  5636. FALSE
  5637. );
  5638. }
  5639. if(!NT_SUCCESS(Status)) {
  5640. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to read drvindex.inf. Status = %lx \n", Status ));
  5641. DriverInfHandle = NULL;
  5642. //
  5643. // bail out of setup
  5644. //
  5645. SpStartScreen(
  5646. SP_SCRN_DRIVERCACHE_FATAL,
  5647. 3,
  5648. HEADER_HEIGHT+1,
  5649. FALSE,
  5650. FALSE,
  5651. DEFAULT_ATTRIBUTE
  5652. );
  5653. SpDisplayStatusOptions(
  5654. DEFAULT_STATUS_ATTRIBUTE,
  5655. SP_STAT_ENTER_EQUALS_RETRY,
  5656. SP_STAT_F3_EQUALS_EXIT,
  5657. 0
  5658. );
  5659. SpInputDrain();
  5660. switch(SpWaitValidKey(ValidKeys,NULL,NULL)) {
  5661. case ASCI_CR:
  5662. goto TryAgain1;
  5663. break;
  5664. case KEY_F3:
  5665. SpConfirmExit();
  5666. break;
  5667. }
  5668. SpDone(0,FALSE,FALSE);
  5669. ASSERT(FALSE);
  5670. }
  5671. if (DriverInfPath) {
  5672. SpMemFree( DriverInfPath );
  5673. }
  5674. //
  5675. // load the driver cab
  5676. //
  5677. // won't return if it fails
  5678. //
  5679. SpOpenDriverCab(
  5680. MasterSifHandle,
  5681. SetupSourceDevicePath,
  5682. DirectoryOnSourceDevice,
  5683. &MediaDirectory);
  5684. //
  5685. // now read delta.inf from the directory the driver cab was in
  5686. //
  5687. wcscpy( TemporaryBuffer, SetupSourceDevicePath );
  5688. SpConcatenatePaths( TemporaryBuffer, DirectoryOnSourceDevice );
  5689. SpConcatenatePaths( TemporaryBuffer, MediaDirectory );
  5690. SpConcatenatePaths( TemporaryBuffer, L"delta.inf" );
  5691. PrivateInfPath = SpDupStringW( TemporaryBuffer );
  5692. if (!PrivateInfPath) {
  5693. Status = STATUS_NO_MEMORY;
  5694. } else {
  5695. //
  5696. // load the inf
  5697. //
  5698. Status = SpLoadSetupTextFile(
  5699. PrivateInfPath,
  5700. NULL, // No image already in memory
  5701. 0, // Image size is empty
  5702. &PrivateInfHandle,
  5703. &ErrorLine,
  5704. TRUE,
  5705. FALSE
  5706. );
  5707. }
  5708. if(!NT_SUCCESS(Status)) {
  5709. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Unable to read delta.inf. Status = %lx \n", Status ));
  5710. PrivateInfHandle = NULL;
  5711. }
  5712. if( PrivateInfPath ) {
  5713. SpMemFree( PrivateInfPath );
  5714. }
  5715. return;
  5716. }
  5717. VOID
  5718. SpOpenDriverCab(
  5719. IN HANDLE MasterSifHandle,
  5720. IN PWSTR SetupSourceDevicePath,
  5721. IN PWSTR DirectoryOnSourceDevice,
  5722. OUT PWSTR *Directory OPTIONAL
  5723. )
  5724. /*++
  5725. Routine Description:
  5726. open driver.cab based on the current source path and directory.
  5727. Arguments:
  5728. MasterSifHandle - Handle to txtsetup.sif.
  5729. SetupSourceDevicePath - Path to the device that contains the source media.
  5730. DirectoryOnSourceDevice - Directory on the media where setupp.ini is located.
  5731. Directory - If specified, returns the directory below DirectoryOnSourceDevice
  5732. where the cab was opened from.
  5733. Return Value:
  5734. NONE.
  5735. --*/
  5736. {
  5737. PWSTR CabFileSection, CabFileName;
  5738. WCHAR CabPath[MAX_PATH];
  5739. PWSTR MediaShortName;
  5740. PWSTR MediaDirectory;
  5741. NTSTATUS Status;
  5742. PWSTR DriverCabName, DriverCabPath;
  5743. OBJECT_ATTRIBUTES Obja;
  5744. UNICODE_STRING UnicodeString;
  5745. IO_STATUS_BLOCK IoStatusBlock;
  5746. CABDATA *MyCabData;
  5747. DWORD i;
  5748. HANDLE CabHandle;
  5749. ULONG ValidKeys[3] = { KEY_F3,ASCI_CR,0 };
  5750. //
  5751. // Load up every cab that's listed in drvindex.inf
  5752. // and fill in the CabData structure.
  5753. //
  5754. ASSERT( DriverInfHandle );
  5755. if (ARGUMENT_PRESENT(Directory)) {
  5756. //
  5757. // --lookup the name of the cab in txtsetup.sif
  5758. // then get the path to the file and open it
  5759. //
  5760. DriverCabName = SpGetSectionKeyIndex (MasterSifHandle,
  5761. L"SetupData",
  5762. L"DriverCabName",
  5763. 0);
  5764. if (DriverCabName) {
  5765. MediaShortName = SpLookUpValueForFile(
  5766. MasterSifHandle,
  5767. DriverCabName,
  5768. INDEX_WHICHMEDIA,
  5769. TRUE
  5770. );
  5771. SpGetSourceMediaInfo(MasterSifHandle,MediaShortName,NULL,NULL,&MediaDirectory);
  5772. *Directory = MediaDirectory;
  5773. } else {
  5774. //
  5775. // bail out of setup
  5776. //
  5777. DriverInfHandle = NULL;
  5778. SpFatalSifError(MasterSifHandle,
  5779. L"SetupData",
  5780. L"DriverCabName",
  5781. 0,
  5782. 0);
  5783. return; // for prefix
  5784. }
  5785. }
  5786. //
  5787. // get the cabfiles line from the Version section
  5788. //
  5789. i = 0;
  5790. CabFileSection = NULL;
  5791. CabData = SpMemAlloc( sizeof(CABDATA) );
  5792. RtlZeroMemory( CabData, sizeof(CABDATA) );
  5793. MyCabData = CabData;
  5794. //
  5795. // SpGetSectionKeyIndex will return NULL when there are no more entries on
  5796. // this line.
  5797. //
  5798. while( CabFileSection = SpGetSectionKeyIndex(DriverInfHandle,L"Version",L"CabFiles",i) ) {
  5799. //
  5800. // Got the section name. Go figure out which cab we need
  5801. // to open and load the handle.
  5802. //
  5803. CabFileName = SpGetSectionKeyIndex(DriverInfHandle,L"Cabs",CabFileSection,0);
  5804. if( CabFileName ) {
  5805. MediaShortName = SpLookUpValueForFile( MasterSifHandle,
  5806. CabFileName,
  5807. INDEX_WHICHMEDIA,
  5808. TRUE );
  5809. SpGetSourceMediaInfo(MasterSifHandle,MediaShortName,NULL,NULL,&MediaDirectory);
  5810. wcscpy( CabPath, SetupSourceDevicePath );
  5811. SpConcatenatePaths( CabPath, DirectoryOnSourceDevice );
  5812. SpConcatenatePaths( CabPath, MediaDirectory );
  5813. SpConcatenatePaths( CabPath, CabFileName );
  5814. TryAgain2:
  5815. INIT_OBJA(&Obja,&UnicodeString,CabPath);
  5816. Status = ZwCreateFile( &CabHandle,
  5817. FILE_GENERIC_READ,
  5818. &Obja,
  5819. &IoStatusBlock,
  5820. NULL,
  5821. FILE_ATTRIBUTE_NORMAL,
  5822. FILE_SHARE_READ,
  5823. FILE_OPEN,
  5824. 0,
  5825. NULL,
  5826. 0 );
  5827. if( NT_SUCCESS(Status) ) {
  5828. //
  5829. // load the data structure.
  5830. //
  5831. if( (MyCabData->CabName) && (MyCabData->CabHandle) ) {
  5832. //
  5833. // This entry is being used. Create another.
  5834. //
  5835. MyCabData->Next = SpMemAlloc( sizeof(CABDATA) );
  5836. MyCabData = MyCabData->Next;
  5837. }
  5838. if( MyCabData ) {
  5839. MyCabData->Next = NULL;
  5840. MyCabData->CabName = SpDupStringW(CabFileName);
  5841. MyCabData->CabHandle = CabHandle;
  5842. MyCabData->CabInfHandle = DriverInfHandle;
  5843. MyCabData->CabSectionName = SpDupStringW(CabFileSection);
  5844. } else {
  5845. //
  5846. // What to do...
  5847. //
  5848. }
  5849. } else {
  5850. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open cab file %ws. Status = %lx \n", CabPath, Status ));
  5851. //
  5852. // bail out of setup
  5853. //
  5854. DriverInfHandle = NULL;
  5855. SpStartScreen(
  5856. SP_SCRN_DRIVERCACHE_FATAL,
  5857. 3,
  5858. HEADER_HEIGHT+1,
  5859. FALSE,
  5860. FALSE,
  5861. DEFAULT_ATTRIBUTE
  5862. );
  5863. SpDisplayStatusOptions(
  5864. DEFAULT_STATUS_ATTRIBUTE,
  5865. SP_STAT_ENTER_EQUALS_RETRY,
  5866. SP_STAT_F3_EQUALS_EXIT,
  5867. 0
  5868. );
  5869. SpInputDrain();
  5870. switch(SpWaitValidKey(ValidKeys,NULL,NULL)) {
  5871. case ASCI_CR:
  5872. goto TryAgain2;
  5873. break;
  5874. case KEY_F3:
  5875. SpConfirmExit();
  5876. break;
  5877. }
  5878. SpDone(0,FALSE,FALSE);
  5879. ASSERT(FALSE);
  5880. }
  5881. }
  5882. //
  5883. // Go look in the next section.
  5884. //
  5885. i++;
  5886. }
  5887. return;
  5888. }
  5889. VOID
  5890. SpInitializePidString(
  5891. IN HANDLE MasterSifHandle,
  5892. IN PWSTR SetupSourceDevicePath,
  5893. IN PWSTR DirectoryOnSourceDevice
  5894. )
  5895. /*++
  5896. Routine Description:
  5897. Read th Pid20 from setupp.ini on the media, and save it on the global
  5898. variable PidString. Also read the "extradata" from setupp.ini and translate it
  5899. into the StepUpMode global. Note that the StepUpMode global is already set from
  5900. reading setupreg.hiv initially, but this overrides that value
  5901. Arguments:
  5902. MasterSifHandle - Handle to txtsetup.sif.
  5903. SetupSourceDevicePath - Path to the device that contains the source media.
  5904. DirectoryOnSourceDevice - Directory on the media where setupp.ini is located.
  5905. Return Value:
  5906. NONE.
  5907. --*/
  5908. {
  5909. PWSTR MediaShortName;
  5910. PWSTR MediaDirectory;
  5911. PWSTR SetupIniPath;
  5912. ULONG ErrorSubId;
  5913. ULONG ErrorLine;
  5914. PVOID SetupIniHandle;
  5915. PWSTR TmpPid;
  5916. NTSTATUS Status;
  5917. PWSTR PidExtraData;
  5918. CHAR ExtraDataArray[25];
  5919. //
  5920. // Prepair to run autofmt
  5921. //
  5922. MediaShortName = SpLookUpValueForFile(
  5923. MasterSifHandle,
  5924. L"setupp.ini",
  5925. INDEX_WHICHMEDIA,
  5926. TRUE
  5927. );
  5928. //
  5929. // Prompt the user to insert the setup media.
  5930. //
  5931. SpPromptForSetupMedia(
  5932. MasterSifHandle,
  5933. MediaShortName,
  5934. SetupSourceDevicePath
  5935. );
  5936. SpGetSourceMediaInfo(MasterSifHandle,MediaShortName,NULL,NULL,&MediaDirectory);
  5937. wcscpy( TemporaryBuffer, SetupSourceDevicePath );
  5938. SpConcatenatePaths( TemporaryBuffer, DirectoryOnSourceDevice );
  5939. SpConcatenatePaths( TemporaryBuffer, MediaDirectory );
  5940. SpConcatenatePaths( TemporaryBuffer, L"setupp.ini" );
  5941. SetupIniPath = SpDupStringW( TemporaryBuffer );
  5942. CLEAR_CLIENT_SCREEN();
  5943. Status = SpLoadSetupTextFile(
  5944. SetupIniPath,
  5945. NULL, // No image already in memory
  5946. 0, // Image size is empty
  5947. &SetupIniHandle,
  5948. &ErrorLine,
  5949. TRUE,
  5950. FALSE
  5951. );
  5952. if(!NT_SUCCESS(Status)) {
  5953. //
  5954. // Silently fail if unable to read setupp.ini
  5955. //
  5956. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Unable to read setupp.ini. Status = %lx \n", Status ));
  5957. PidString = NULL;
  5958. StepUpMode = TRUE;
  5959. return;
  5960. }
  5961. TmpPid = SpGetSectionKeyIndex (SetupIniHandle,
  5962. L"Pid",
  5963. L"Pid",
  5964. 0);
  5965. PidString = ( TmpPid == NULL )? NULL : SpDupStringW(TmpPid);
  5966. TmpPid = SpGetSectionKeyIndex (SetupIniHandle,
  5967. L"Pid",
  5968. L"Pid",
  5969. 0);
  5970. PidString = ( TmpPid == NULL )? NULL : SpDupStringW(TmpPid);
  5971. TmpPid = SpGetSectionKeyIndex (SetupIniHandle,
  5972. L"Pid",
  5973. L"ExtraData",
  5974. 0);
  5975. PidExtraData = (TmpPid == NULL) ? NULL : SpDupStringW(TmpPid);
  5976. if ( PidExtraData ) {
  5977. if (! SpGetStepUpMode(PidExtraData,&StepUpMode)) {
  5978. //
  5979. // fatal error processing PidExtraData
  5980. // -- someone tampered with this file so bail out
  5981. //
  5982. SpStartScreen(
  5983. SP_SCRN_PIDINIT_FATAL,
  5984. 3,
  5985. HEADER_HEIGHT+1,
  5986. FALSE,
  5987. FALSE,
  5988. DEFAULT_ATTRIBUTE
  5989. );
  5990. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,SP_STAT_F3_EQUALS_EXIT,0);
  5991. SpInputDrain();
  5992. while(SpInputGetKeypress() != KEY_F3);
  5993. SpDone(0, FALSE,FALSE);
  5994. ASSERT(FALSE);
  5995. }
  5996. SpMemFree( PidExtraData );
  5997. }
  5998. SpFreeTextFile( SetupIniHandle );
  5999. return;
  6000. }
  6001. NTSTATUS
  6002. SpRenameSetupAPILog(
  6003. PDISK_REGION TargetRegion,
  6004. PCWSTR TargetPath
  6005. )
  6006. /*++
  6007. Routine Description:
  6008. This routine deletes the copy of setupapi.old if present, and then
  6009. renames setupapi.log to setupapi.old.
  6010. Arguments:
  6011. TargetRegion - identifies the disk containing the NT installation
  6012. TargetPath - path to NT installation on disk
  6013. Return Value:
  6014. NONE.
  6015. --*/
  6016. {
  6017. PWSTR SetupAPIOldName;
  6018. PWSTR SetupAPILogName;
  6019. PWSTR p;
  6020. NTSTATUS Status;
  6021. SpNtNameFromRegion(
  6022. TargetRegion,
  6023. TemporaryBuffer,
  6024. sizeof(TemporaryBuffer),
  6025. PartitionOrdinalCurrent
  6026. );
  6027. SpConcatenatePaths( TemporaryBuffer, TargetPath );
  6028. //
  6029. // Allocate a string buffer large enough to contain space for the string
  6030. // in TemporaryBuffer, plus "setupapi.old", plus the path seperator that
  6031. // SpConcatenatePaths() may insert between them. Include room for the
  6032. // null terminator as well.
  6033. //
  6034. SetupAPIOldName = SpMemAlloc(wcslen(TemporaryBuffer) * sizeof(WCHAR) +
  6035. sizeof(L'\\') +
  6036. sizeof(L"setupapi.old") +
  6037. sizeof(L'\0'));
  6038. if (SetupAPIOldName == NULL) {
  6039. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Could not allocate memory to rename setupapi.log.\n"));
  6040. return STATUS_NO_MEMORY;
  6041. }
  6042. SetupAPILogName = SpMemAlloc(wcslen(TemporaryBuffer) * sizeof(WCHAR) +
  6043. sizeof(L'\\') +
  6044. sizeof(L"setupapi.log") +
  6045. sizeof(L'\0'));
  6046. if (SetupAPILogName == NULL) {
  6047. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Could not allocate memory to rename setupapi.log.\n"));
  6048. SpMemFree(SetupAPIOldName);
  6049. return STATUS_NO_MEMORY;
  6050. }
  6051. wcscpy(SetupAPIOldName, TemporaryBuffer);
  6052. SpConcatenatePaths(SetupAPIOldName, L"setupapi.old");
  6053. wcscpy(SetupAPILogName, TemporaryBuffer);
  6054. SpConcatenatePaths(SetupAPILogName, L"setupapi.log");
  6055. Status = SpDeleteFile(SetupAPIOldName, NULL, NULL);
  6056. if (!NT_SUCCESS(Status)) {
  6057. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Could not delete %ws: %lx.\n", SetupAPIOldName, Status));
  6058. }
  6059. Status = SpRenameFile(SetupAPILogName, SetupAPIOldName, FALSE);
  6060. if (!NT_SUCCESS(Status)) {
  6061. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Could not rename %ws to %ws: %lx.\n", SetupAPILogName, SetupAPIOldName, Status));
  6062. }
  6063. SpMemFree(SetupAPILogName);
  6064. SpMemFree(SetupAPIOldName);
  6065. return Status;
  6066. }
  6067. #if defined(REMOTE_BOOT)
  6068. NTSTATUS
  6069. SpFixupRemoteBootLoader(
  6070. PWSTR RemoteBootTarget
  6071. )
  6072. /*++
  6073. Routine Description:
  6074. This routine deletes the setup loader that is currently NTLDR, and
  6075. puts the os loader in its place.
  6076. Arguments:
  6077. RemoteBootTarget -- the network path to the machine directory root
  6078. on the server.
  6079. Return Value:
  6080. NONE.
  6081. --*/
  6082. {
  6083. PWSTR NtldrName;
  6084. PWSTR OsLoaderName;
  6085. PWSTR p;
  6086. NTSTATUS Status;
  6087. NtldrName = SpMemAlloc(wcslen(RemoteBootTarget) * sizeof(WCHAR) + sizeof(L"ntldr"));
  6088. if (NtldrName == NULL) {
  6089. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Could not allocate memory to fixup remote boot loader.\n"));
  6090. return STATUS_NO_MEMORY;
  6091. }
  6092. OsLoaderName = SpMemAlloc((wcslen(RemoteBootTarget) + 20) * sizeof(WCHAR));
  6093. if (OsLoaderName == NULL) {
  6094. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Could not allocate memory to fixup remote boot loader.\n"));
  6095. SpMemFree(NtldrName);
  6096. return STATUS_NO_MEMORY;
  6097. }
  6098. wcscpy(NtldrName, RemoteBootTarget);
  6099. p = wcsstr(NtldrName, L"BootDrive");
  6100. ASSERT(p != NULL);
  6101. wcscpy(p, L"ntldr");
  6102. Status = SpDeleteFile(NtldrName, NULL, NULL);
  6103. if (!NT_SUCCESS(Status)) {
  6104. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Could not delete %ws: %lx.\n", NtldrName, Status));
  6105. goto Cleanup;
  6106. }
  6107. wcscpy(OsLoaderName, RemoteBootTarget);
  6108. wcscat(OsLoaderName, L"\\winnt\\osloader.exe");
  6109. Status = SpRenameFile(OsLoaderName, NtldrName, FALSE);
  6110. if (!NT_SUCCESS(Status)) {
  6111. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Could not rename %ws to %ws: %lx.\n", OsLoaderName, NtldrName, Status));
  6112. }
  6113. Cleanup:
  6114. SpMemFree(NtldrName);
  6115. SpMemFree(OsLoaderName);
  6116. return Status;
  6117. }
  6118. NTSTATUS
  6119. SpCreateRemoteBootCfg(
  6120. IN PWSTR RemoteBootTarget,
  6121. IN PDISK_REGION SystemPartitionRegion
  6122. )
  6123. /*++
  6124. Routine Description:
  6125. This routine creates the RemoteBoot.cfg file in the system32\config directory, and
  6126. initializes it.
  6127. Arguments:
  6128. RemoteBootTarget -- the network path to the machine directory root
  6129. on the server.
  6130. SystemPartitionRegion -- The drive that is installed on the local machine.
  6131. Return Value:
  6132. NONE.
  6133. --*/
  6134. {
  6135. OBJECT_ATTRIBUTES ObjectAttributes;
  6136. UNICODE_STRING UnicodeString;
  6137. IO_STATUS_BLOCK IoStatusBlock;
  6138. PWSTR FileName;
  6139. PWSTR p;
  6140. NTSTATUS Status;
  6141. HANDLE Handle;
  6142. ULONG BootSerialNumber = 1;
  6143. ULONG DiskSignature;
  6144. LARGE_INTEGER ByteOffset;
  6145. if ((SystemPartitionRegion != NULL) &&
  6146. (!SystemPartitionRegion->PartitionedSpace ||
  6147. (SystemPartitionRegion->Filesystem != FilesystemNtfs))) {
  6148. KdPrintEx((Ex"SDPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, ETUP: ERROR! Invalid system partition for remoteboot!\n");
  6149. return STATUS_UNSUCCESSFUL;
  6150. }
  6151. if (SystemPartitionRegion != NULL) {
  6152. DiskSignature = U_ULONG(SystemPartitionRegion->MbrInfo->OnDiskMbr.NTFTSignature);
  6153. } else {
  6154. DiskSignature = 0;
  6155. }
  6156. FileName = SpMemAlloc(wcslen(RemoteBootTarget) * sizeof(WCHAR) + sizeof(L"RemoteBoot.cfg"));
  6157. if (FileName == NULL) {
  6158. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Could not allocate memory remoteboot.cfg file name.\n"));
  6159. return STATUS_NO_MEMORY;
  6160. }
  6161. wcscpy(FileName, RemoteBootTarget);
  6162. p = wcsstr(FileName, L"BootDrive");
  6163. ASSERT(p != NULL);
  6164. wcscpy(p, L"RemoteBoot.cfg");
  6165. INIT_OBJA(&ObjectAttributes,&UnicodeString,FileName);
  6166. Status = ZwCreateFile( &Handle,
  6167. (ACCESS_MASK)FILE_GENERIC_WRITE | FILE_GENERIC_READ,
  6168. &ObjectAttributes,
  6169. &IoStatusBlock,
  6170. NULL,
  6171. FILE_ATTRIBUTE_HIDDEN,
  6172. FILE_SHARE_READ | FILE_SHARE_WRITE,
  6173. FILE_OVERWRITE_IF,
  6174. FILE_SYNCHRONOUS_IO_NONALERT | FILE_RANDOM_ACCESS,
  6175. NULL,
  6176. 0
  6177. );
  6178. if(!NT_SUCCESS(Status)) {
  6179. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Could not create %ws file. Status == 0x%x\n", FileName, Status));
  6180. goto Cleanup;
  6181. }
  6182. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_TRACE_LEVEL, "SETUP: Writing remoteboot.cfg file.\n"));
  6183. //
  6184. // Update the information
  6185. //
  6186. ByteOffset.LowPart = 0;
  6187. ByteOffset.HighPart = 0;
  6188. ZwWriteFile( Handle,
  6189. NULL,
  6190. NULL,
  6191. NULL,
  6192. &IoStatusBlock,
  6193. &BootSerialNumber,
  6194. sizeof(ULONG),
  6195. &ByteOffset,
  6196. NULL
  6197. );
  6198. ByteOffset.LowPart = sizeof(ULONG);
  6199. ZwWriteFile( Handle,
  6200. NULL,
  6201. NULL,
  6202. NULL,
  6203. &IoStatusBlock,
  6204. &DiskSignature,
  6205. sizeof(ULONG),
  6206. &ByteOffset,
  6207. NULL
  6208. );
  6209. ByteOffset.LowPart = sizeof(ULONG) + sizeof(ULONG);
  6210. ZwWriteFile( Handle,
  6211. NULL,
  6212. NULL,
  6213. NULL,
  6214. &IoStatusBlock,
  6215. NetBootHalName,
  6216. sizeof(NetBootHalName),
  6217. &ByteOffset,
  6218. NULL
  6219. );
  6220. ZwClose(Handle);
  6221. Cleanup:
  6222. SpMemFree(FileName);
  6223. return Status;
  6224. }
  6225. NTSTATUS
  6226. SpEraseCscCache(
  6227. IN PDISK_REGION SystemPartitionRegion
  6228. )
  6229. /*++
  6230. Routine Description:
  6231. This routine erases the local CSC cache.
  6232. Arguments:
  6233. SystemPartitionRegion - The system partition region (the local drive).
  6234. Return Value:
  6235. NONE.
  6236. --*/
  6237. {
  6238. NTSTATUS Status;
  6239. ENUMFILESRESULT Result;
  6240. PWSTR FullCscPath;
  6241. //
  6242. // Show a screen, the status line will show each file as it is
  6243. // deleted.
  6244. //
  6245. SpDisplayScreen(SP_SCRN_CLEARING_CSC, 3, 4 );
  6246. SpNtNameFromRegion(
  6247. SystemPartitionRegion,
  6248. TemporaryBuffer,
  6249. sizeof(TemporaryBuffer),
  6250. PartitionOrdinalCurrent
  6251. );
  6252. SpConcatenatePaths(TemporaryBuffer,
  6253. REMOTE_BOOT_IMIRROR_PATH_W REMOTE_BOOT_CSC_SUBDIR_W);
  6254. FullCscPath = SpDupStringW(TemporaryBuffer);
  6255. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_TRACE_LEVEL, "SETUP: SpEraseCscCache clearing CSC cache %ws\n", FullCscPath));
  6256. Result = SpEnumFilesRecursive(
  6257. FullCscPath,
  6258. SpDelEnumFile,
  6259. &Status,
  6260. NULL);
  6261. SpMemFree(FullCscPath);
  6262. return Status;
  6263. }
  6264. #endif // defined(REMOTE_BOOT)
  6265. NTSTATUS
  6266. SpProcessMigrateInfFile(
  6267. IN PVOID InfHandle
  6268. )
  6269. /*++
  6270. Routine Description:
  6271. Process the [AddReg] section of migrate.inf.
  6272. The keys are created on the setup hive.
  6273. Arguments:
  6274. InfHandle - Handle to migrate.inf file.
  6275. Return Value:
  6276. Status code indicating outcome.
  6277. --*/
  6278. {
  6279. NTSTATUS Status;
  6280. OBJECT_ATTRIBUTES Obja;
  6281. UNICODE_STRING UnicodeString;
  6282. HANDLE SystemHiveRoot;
  6283. PWSTR KeyPath = L"\\registry\\machine\\system";
  6284. //
  6285. // Open a handle to HKEY_LOCAL_MACHINE\System on the setup hive
  6286. //
  6287. INIT_OBJA(&Obja,&UnicodeString,KeyPath);
  6288. Obja.RootDirectory = NULL;
  6289. Status = ZwOpenKey(&SystemHiveRoot,KEY_ALL_ACCESS,&Obja);
  6290. if( !NT_SUCCESS( Status ) ) {
  6291. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open %ls on the setup hive. Status = %lx \n", KeyPath, Status));
  6292. return( Status );
  6293. }
  6294. Status = SpProcessAddRegSection( InfHandle,
  6295. L"AddReg",
  6296. SystemHiveRoot,
  6297. NULL,
  6298. NULL,
  6299. NULL );
  6300. ZwClose( SystemHiveRoot );
  6301. return( Status );
  6302. }
  6303. //begin NEC98
  6304. VOID
  6305. SpSetAutoBootFlag(
  6306. PDISK_REGION TargetRegion,
  6307. BOOLEAN SetBootPosision
  6308. )
  6309. {
  6310. #if defined(NEC_98) //NEC98
  6311. PHARD_DISK pHardDisk;
  6312. WCHAR DevicePath[(sizeof(DISK_DEVICE_NAME_BASE)+sizeof(L"000"))/sizeof(WCHAR)];
  6313. ULONG i,bps;//,DiskLayoutSize;
  6314. HANDLE Handle;
  6315. NTSTATUS Sts;
  6316. PREAL_DISK_PTE_NEC98 Pte;
  6317. PUCHAR Buffer,UBuffer;
  6318. UCHAR Position = 0;
  6319. UBuffer = SpMemAlloc(2 * 2 * 512);
  6320. Buffer = ALIGN(UBuffer,512);
  6321. for(i=0; i<HardDiskCount; i++){
  6322. swprintf(DevicePath,L"\\Device\\Harddisk%u",i);
  6323. if(HardDisks[i].Status == DiskOffLine) {
  6324. continue;
  6325. }
  6326. //
  6327. // ignore removable disk.
  6328. //
  6329. if(HardDisks[i].Characteristics & FILE_REMOVABLE_MEDIA ){
  6330. continue;
  6331. }
  6332. bps = HardDisks[i].Geometry.BytesPerSector;
  6333. Sts = SpOpenPartition0(DevicePath,&Handle,TRUE);
  6334. if(!NT_SUCCESS(Sts)) {
  6335. continue;
  6336. }
  6337. RtlZeroMemory(Buffer,bps * 2);
  6338. Sts = SpReadWriteDiskSectors(Handle,0,1,bps,Buffer,FALSE);
  6339. if(!NT_SUCCESS(Sts)) {
  6340. ZwClose(Handle);
  6341. continue;
  6342. }
  6343. //
  6344. // Clear BootRecord
  6345. //
  6346. Buffer[bps - 5] = 0x00;
  6347. Buffer[bps - 6] = 0x00;
  6348. Sts = SpReadWriteDiskSectors(Handle,0,1,bps,Buffer,TRUE);
  6349. if(!NT_SUCCESS(Sts)) {
  6350. ZwClose(Handle);
  6351. continue;
  6352. }
  6353. ZwClose(Handle);
  6354. }
  6355. if(SetBootPosision){
  6356. //
  6357. // Set RealDiskPosition.(in upgrade or repair)
  6358. //
  6359. if( (NTUpgrade == UpgradeFull) || (WinUpgradeType != NoWinUpgrade) || RepairWinnt ||
  6360. (AutoPartitionPicker
  6361. #if defined(REMOTE_BOOT)
  6362. && !RemoteBootSetup
  6363. #endif // defined(REMOTE_BOOT)
  6364. ) ) {
  6365. ASSERT(TargetRegion);
  6366. TargetRegion->MbrInfo->OnDiskMbr.PartitionTable[TargetRegion->TablePosition].RealDiskPosition
  6367. = (UCHAR)TargetRegion->TablePosition;
  6368. }
  6369. ASSERT(TargetRegion);
  6370. RtlZeroMemory(Buffer,bps * 2);
  6371. pHardDisk = &HardDisks[TargetRegion->DiskNumber];
  6372. bps = HardDisks[TargetRegion->DiskNumber].Geometry.BytesPerSector;
  6373. Sts = SpOpenPartition0(pHardDisk->DevicePath,&Handle,TRUE);
  6374. if(!NT_SUCCESS(Sts)) {
  6375. return;
  6376. }
  6377. Sts = SpReadWriteDiskSectors(Handle,0,2,bps,Buffer,FALSE);
  6378. if(!NT_SUCCESS(Sts)) {
  6379. ZwClose(Handle);
  6380. SpMemFree(UBuffer);
  6381. return;
  6382. }
  6383. (PUCHAR)Pte = &Buffer[bps];
  6384. Position = TargetRegion->MbrInfo->OnDiskMbr.PartitionTable[TargetRegion->TablePosition].RealDiskPosition;
  6385. //
  6386. // Update BootRecord and Volume Information
  6387. //
  6388. Buffer[bps - 5] = Position;
  6389. Buffer[bps - 6] = 0x80;
  6390. Pte[Position].ActiveFlag |= 0x80;
  6391. Pte[Position].SystemId |= 0x80;
  6392. //
  6393. // If target partition was created windisk.exe on NT3.5, there is not IPL adress
  6394. // in its volume info. So,textmode setup must write it to the volume info.
  6395. //
  6396. if ((Pte[Position].IPLSector != Pte[Position].StartSector) ||
  6397. (Pte[Position].IPLHead != Pte[Position].StartHead) ||
  6398. (Pte[Position].IPLCylinderLow != Pte[Position].StartCylinderLow) ||
  6399. (Pte[Position].IPLCylinderHigh != Pte[Position].StartCylinderHigh))
  6400. {
  6401. //
  6402. // Not much! Set IPL adress value same as partition start address.
  6403. //
  6404. Pte[Position].IPLSector = Pte[Position].StartSector;
  6405. Pte[Position].IPLHead = Pte[Position].StartHead;
  6406. Pte[Position].IPLCylinderLow = Pte[Position].StartCylinderLow;
  6407. Pte[Position].IPLCylinderHigh = Pte[Position].StartCylinderHigh;
  6408. }
  6409. Sts = SpReadWriteDiskSectors(Handle,0,2,bps,Buffer,TRUE);
  6410. if(!NT_SUCCESS(Sts)) {
  6411. ZwClose(Handle);
  6412. SpMemFree(UBuffer);
  6413. return;
  6414. }
  6415. ZwClose(Handle);
  6416. }
  6417. SpMemFree(UBuffer);
  6418. #endif //NEC98
  6419. }
  6420. VOID
  6421. SpCheckHiveDriveLetters(
  6422. VOID
  6423. )
  6424. {
  6425. #if defined(NEC_98) //NEC98
  6426. NTSTATUS Status;
  6427. PWSTR p;
  6428. ULONG ErrorLine;
  6429. PVOID TmpWinntSifHandle = NULL;
  6430. BOOLEAN ForceRemapDriveLetter = FALSE;
  6431. BOOLEAN DriveAssign_AT = TRUE;
  6432. if ( SetupldrWinntSifFileSize ) {
  6433. Status = SpLoadSetupTextFile( NULL,
  6434. SetupldrWinntSifFile,
  6435. SetupldrWinntSifFileSize,
  6436. &TmpWinntSifHandle,
  6437. &ErrorLine,
  6438. FALSE,
  6439. TRUE
  6440. );
  6441. if (!NT_SUCCESS(Status))
  6442. return;
  6443. p = SpGetSectionKeyIndex(TmpWinntSifHandle,SIF_DATA,WINNT_D_DRIVEASSIGN_NEC98_W,0);
  6444. if(p && !_wcsicmp(p,WINNT_A_YES_W)) {
  6445. if (SetupldrMigrateInfFile) {
  6446. p = SpGetSectionKeyIndex(TmpWinntSifHandle,SIF_DATA,WINNT_D_NTUPGRADE_W,0);
  6447. if(p && !_wcsicmp(p,WINNT_A_YES_W)) {
  6448. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Upgrade NEC assigned WinNT.(AT=FALSE)\n"));
  6449. DriveAssign_AT = FALSE;
  6450. } else {
  6451. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Fresh setup from NEC assigned WinNT.(AT=TRUE)\n"));
  6452. DriveAssign_AT = TRUE;
  6453. }
  6454. } else {
  6455. p = SpGetSectionKeyIndex(TmpWinntSifHandle,SIF_DATA,WINNT_D_WIN95UPGRADE_W,0);
  6456. if(p && !_wcsicmp(p,WINNT_A_YES_W)) {
  6457. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Upgrade NEC assigned Win95.(AT=FALSE)\n"));
  6458. DriveAssign_AT = FALSE;
  6459. } else {
  6460. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Fresh setup from NEC assigned Win95.(AT=TRUE)\n"));
  6461. DriveAssign_AT = TRUE;
  6462. }
  6463. }
  6464. }
  6465. } else {
  6466. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Fresh setup.(AT=TRUE)\n"));
  6467. DriveAssign_AT = TRUE;
  6468. }
  6469. SpSetHiveDriveLetterNec98( DriveAssign_AT );
  6470. #endif //NEC98
  6471. }
  6472. VOID
  6473. SpSetHiveDriveLetterNec98(
  6474. BOOLEAN DriveAssign_AT
  6475. )
  6476. {
  6477. #if defined(NEC_98) //NEC98
  6478. NTSTATUS Status;
  6479. UNICODE_STRING StartDriveLetterFrom;
  6480. UNICODE_STRING Dummy;
  6481. RTL_QUERY_REGISTRY_TABLE SetupTypeTable[]=
  6482. {
  6483. {NULL,
  6484. RTL_QUERY_REGISTRY_DIRECT,
  6485. L"DriveLetter",
  6486. &StartDriveLetterFrom,
  6487. REG_SZ,
  6488. &Dummy,
  6489. 0
  6490. },
  6491. {NULL,0,NULL,NULL,REG_NONE,NULL,0}
  6492. };
  6493. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_TRACE_LEVEL, "SETUP: SpSetHiveDriveLetter(%ld).\n", DriveAssign_AT));
  6494. RtlInitUnicodeString(&StartDriveLetterFrom, NULL);
  6495. RtlInitUnicodeString(&Dummy, NULL);
  6496. Status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
  6497. L"\\Registry\\MACHINE\\SYSTEM\\Setup",
  6498. SetupTypeTable,
  6499. NULL,
  6500. NULL);
  6501. if (DriveAssign_AT) {
  6502. //
  6503. // Write hive "DriveLetter",
  6504. //
  6505. if ((StartDriveLetterFrom.Buffer[0] != L'C') &&
  6506. (StartDriveLetterFrom.Buffer[0] != L'c')) {
  6507. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Write DriveLetter=C into setup hiv.\n"));
  6508. Status = RtlWriteRegistryValue( RTL_REGISTRY_ABSOLUTE,
  6509. L"\\Registry\\Machine\\System\\Setup",
  6510. L"DriveLetter",
  6511. REG_SZ,
  6512. L"C",
  6513. sizeof(L"C")+sizeof(WCHAR));
  6514. }
  6515. DriveAssignFromA = FALSE;
  6516. } else {
  6517. //
  6518. // Delete hive "DriveLetter",
  6519. //
  6520. if (NT_SUCCESS(Status)) {
  6521. if ((StartDriveLetterFrom.Buffer[0] == L'C') ||
  6522. (StartDriveLetterFrom.Buffer[0] == L'c')) {
  6523. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Delete DriveLetter=C from setup hiv.\n"));
  6524. Status = RtlDeleteRegistryValue(RTL_REGISTRY_ABSOLUTE,
  6525. L"\\Registry\\MACHINE\\SYSTEM\\Setup",
  6526. L"DriveLetter");
  6527. }
  6528. }
  6529. DriveAssignFromA = TRUE;
  6530. }
  6531. #endif //NEC98
  6532. }
  6533. VOID
  6534. SpDeleteDriveLetterFromNTFTNec98(
  6535. VOID
  6536. )
  6537. {
  6538. #if defined(NEC_98) //NEC98
  6539. NTSTATUS Status;
  6540. PWSTR p;
  6541. ULONG ErrorLine;
  6542. UNICODE_STRING StartDriveLetterFrom;
  6543. UNICODE_STRING Dummy;
  6544. PVOID TmpWinntSifHandle = NULL;
  6545. BOOLEAN ForceRemapDriveLetter = FALSE;
  6546. // 1st step:
  6547. // Check whether we need to reassign drive letters.
  6548. Status = SpLoadSetupTextFile(
  6549. NULL,
  6550. SetupldrWinntSifFile,
  6551. SetupldrWinntSifFileSize,
  6552. &TmpWinntSifHandle,
  6553. &ErrorLine,
  6554. FALSE,
  6555. TRUE
  6556. );
  6557. if (!NT_SUCCESS(Status))
  6558. return;
  6559. if (SetupldrMigrateInfFile) {
  6560. p = SpGetSectionKeyIndex(TmpWinntSifHandle,SIF_DATA,WINNT_D_NTUPGRADE_W,0);
  6561. if(!p || !_wcsicmp(p,WINNT_A_NO_W)) {
  6562. SpDeleteDriveLetterFromNTFTWorkerNec98();
  6563. }
  6564. }
  6565. #endif //NEC98
  6566. }
  6567. VOID
  6568. SpDeleteDriveLetterFromNTFTWorkerNec98(
  6569. VOID
  6570. )
  6571. {
  6572. #if defined(NEC_98) //NEC98
  6573. #define MOUNT_REGISTRY_KEY_W L"\\registry\\machine\\SYSTEM\\MountedDevices"
  6574. #define DISK_REGISTRY_KEY_W L"\\registry\\machine\\SYSTEM\\DISK"
  6575. NTSTATUS Status;
  6576. OBJECT_ATTRIBUTES Obja;
  6577. UNICODE_STRING UnicodeString;
  6578. HANDLE KeyHandle;
  6579. ULONG Disposition;
  6580. RTL_QUERY_REGISTRY_TABLE queryTable[2];
  6581. ULONG registrySize;
  6582. //NTSTATUS status;
  6583. PDISK_CONFIG_HEADER registry;
  6584. PDISK_REGISTRY diskRegistry;
  6585. PDISK_DESCRIPTION diskDescription;
  6586. ULONG signature;
  6587. LONGLONG offset;
  6588. PDISK_PARTITION diskPartition;
  6589. UCHAR driveLetter;
  6590. USHORT i, j;
  6591. //
  6592. // Delete \SYSTEM\\MountedDevices.
  6593. //
  6594. INIT_OBJA(&Obja,&UnicodeString,MOUNT_REGISTRY_KEY_W);
  6595. Obja.RootDirectory = NULL;
  6596. Status = ZwOpenKey(&KeyHandle,KEY_ALL_ACCESS,&Obja);
  6597. if( NT_SUCCESS( Status ) ) {
  6598. Status = ZwDeleteKey(KeyHandle);
  6599. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Delete %ls on the setup hive. Status = %lx \n", MOUNT_REGISTRY_KEY_W, Status));
  6600. ZwClose(KeyHandle);
  6601. } else {
  6602. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: No %ls on the setup hive.\n", MOUNT_REGISTRY_KEY_W));
  6603. }
  6604. //
  6605. // Delete drive letter information from \SYSTEM\\DISK.
  6606. //
  6607. INIT_OBJA(&Obja,&UnicodeString,DISK_REGISTRY_KEY_W);
  6608. Obja.RootDirectory = NULL;
  6609. Status = ZwOpenKey(&KeyHandle,KEY_ALL_ACCESS,&Obja);
  6610. if( NT_SUCCESS( Status ) ) {
  6611. RtlZeroMemory(queryTable, 2*sizeof(RTL_QUERY_REGISTRY_TABLE));
  6612. queryTable[0].QueryRoutine = SpDiskRegistryQueryRoutineNec98;
  6613. queryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
  6614. queryTable[0].Name = L"Information";
  6615. queryTable[0].EntryContext = &registrySize;
  6616. Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, DISK_REGISTRY_KEY_W,
  6617. queryTable, &registry, NULL);
  6618. if( NT_SUCCESS(Status) ) {
  6619. diskRegistry = (PDISK_REGISTRY) ((PUCHAR)registry +
  6620. registry->DiskInformationOffset);
  6621. diskDescription = &diskRegistry->Disks[0];
  6622. for (i = 0; i < diskRegistry->NumberOfDisks; i++) {
  6623. for (j = 0; j < diskDescription->NumberOfPartitions; j++) {
  6624. diskPartition = &diskDescription->Partitions[j];
  6625. diskPartition->AssignDriveLetter = TRUE;
  6626. diskPartition->DriveLetter = (UCHAR)NULL;
  6627. }
  6628. diskDescription = (PDISK_DESCRIPTION) &diskDescription->
  6629. Partitions[diskDescription->NumberOfPartitions];
  6630. }
  6631. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Delete %ls on the setup hive. Status = %lx \n", DISK_REGISTRY_KEY_W, Status));
  6632. ZwDeleteKey(KeyHandle);
  6633. ZwClose(KeyHandle);
  6634. INIT_OBJA(&Obja,&UnicodeString,DISK_REGISTRY_KEY_W);
  6635. Obja.RootDirectory = NULL;
  6636. Status = ZwCreateKey(&KeyHandle,
  6637. READ_CONTROL | KEY_SET_VALUE,
  6638. //KEY_ALL_ACCESS,
  6639. &Obja,
  6640. 0,
  6641. NULL,
  6642. REG_OPTION_NON_VOLATILE,
  6643. &Disposition
  6644. );
  6645. if( NT_SUCCESS( Status ) ) {
  6646. ZwClose(KeyHandle);
  6647. }
  6648. Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
  6649. DISK_REGISTRY_KEY_W,
  6650. L"Information",
  6651. REG_BINARY,
  6652. registry,
  6653. registrySize);
  6654. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Wrote Information in %ls. Status = %lx \n", DISK_REGISTRY_KEY_W, Status));
  6655. } else {
  6656. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: No Information found in DISK registry.\n"));
  6657. ZwDeleteKey(KeyHandle);
  6658. ZwClose(KeyHandle);
  6659. }
  6660. }
  6661. #endif //NEC98
  6662. }
  6663. NTSTATUS
  6664. SpDiskRegistryQueryRoutineNec98(
  6665. IN PWSTR ValueName,
  6666. IN ULONG ValueType,
  6667. IN PVOID ValueData,
  6668. IN ULONG ValueLength,
  6669. IN PVOID Context,
  6670. IN PVOID EntryContext
  6671. )
  6672. /*++
  6673. Routine Description:
  6674. This routine is a query routine for the disk registry entry. It allocates
  6675. space for the disk registry and copies it to the given context.
  6676. Arguments:
  6677. ValueName - Supplies the name of the registry value.
  6678. ValueType - Supplies the type of the registry value.
  6679. ValueData - Supplies the data of the registry value.
  6680. ValueLength - Supplies the length of the registry value.
  6681. Context - Returns the disk registry entry.
  6682. EntryContext - Returns the disk registry size.
  6683. Return Value:
  6684. NTSTATUS
  6685. --*/
  6686. {
  6687. #if defined(NEC_98) //NEC98
  6688. PVOID p;
  6689. PDISK_CONFIG_HEADER* reg;
  6690. PULONG size;
  6691. p = ExAllocatePool(PagedPool, ValueLength);
  6692. if (!p) {
  6693. return STATUS_INSUFFICIENT_RESOURCES;
  6694. }
  6695. RtlCopyMemory(p, ValueData, ValueLength);
  6696. reg = (PDISK_CONFIG_HEADER*) Context;
  6697. *reg = (PDISK_CONFIG_HEADER) p;
  6698. size = (PULONG) EntryContext;
  6699. if (size) {
  6700. *size = ValueLength;
  6701. }
  6702. #endif //NEC98
  6703. return STATUS_SUCCESS;
  6704. }
  6705. BOOL
  6706. SpDetermineBootPartitionEnumNec98(
  6707. IN PPARTITIONED_DISK Disk,
  6708. IN PDISK_REGION Region,
  6709. IN ULONG_PTR Context
  6710. )
  6711. /*++
  6712. Routine Description:
  6713. Callback routine passed to SpEnumDiskRegions.
  6714. Arguments:
  6715. Region - a pointer to a disk region returned by SpEnumDiskRegions
  6716. Ignore - ignored parameter
  6717. Return Value:
  6718. TRUE - to continue enumeration
  6719. FALSE - to end enumeration
  6720. --*/
  6721. {
  6722. WCHAR DeviceName[256];
  6723. SpNtNameFromRegion(
  6724. Region,
  6725. DeviceName,
  6726. MAX_PATH * sizeof(WCHAR),
  6727. PartitionOrdinalOnDisk
  6728. );
  6729. if( !_wcsicmp(DeviceName,NtBootDevicePath)) {
  6730. *(PDISK_REGION *)Context = Region;
  6731. return FALSE;
  6732. }
  6733. return TRUE;
  6734. }
  6735. //end NEC98
  6736. NTSTATUS
  6737. SpProcessUnsupDrvInfFile(
  6738. IN PVOID InfHandle
  6739. )
  6740. /*++
  6741. Routine Description:
  6742. Process the [AddReg] section of migrate.inf.
  6743. The keys are created on the setup hive.
  6744. Arguments:
  6745. InfHandle - Handle to migrate.inf file.
  6746. Return Value:
  6747. Status code indicating outcome.
  6748. --*/
  6749. {
  6750. NTSTATUS Status;
  6751. NTSTATUS SavedStatus = STATUS_SUCCESS;
  6752. OBJECT_ATTRIBUTES Obja;
  6753. UNICODE_STRING UnicodeString;
  6754. HANDLE SystemHiveRoot;
  6755. PWSTR KeyPath = L"\\registry\\machine\\system";
  6756. ULONG i;
  6757. PWSTR p, q;
  6758. //
  6759. // Verify arguments
  6760. //
  6761. if (!InfHandle) {
  6762. KdPrintEx((DPFLTR_SETUP_ID,
  6763. DPFLTR_ERROR_LEVEL,
  6764. "SETUP: Invalid argument to SpProcessUnsupDrvInfFile(%p) \n",
  6765. InfHandle));
  6766. return STATUS_INVALID_PARAMETER;
  6767. }
  6768. //
  6769. // Open a handle to HKEY_LOCAL_MACHINE\System on the setup hive
  6770. //
  6771. INIT_OBJA(&Obja,&UnicodeString,KeyPath);
  6772. Obja.RootDirectory = NULL;
  6773. Status = ZwOpenKey(&SystemHiveRoot,KEY_ALL_ACCESS,&Obja);
  6774. if( !NT_SUCCESS( Status ) ) {
  6775. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open %ls on the setup hive. Status = %lx \n", KeyPath, Status));
  6776. return( Status );
  6777. }
  6778. for( i = 0;
  6779. ((p = SpGetSectionLineIndex( InfHandle,
  6780. L"Devices",
  6781. i,
  6782. 0 )) != NULL);
  6783. i++ ) {
  6784. wcscpy( TemporaryBuffer, L"AddReg." );
  6785. wcscat( TemporaryBuffer, p );
  6786. q = SpDupStringW( ( PWSTR )TemporaryBuffer );
  6787. Status = SpProcessAddRegSection( InfHandle,
  6788. q,
  6789. SystemHiveRoot,
  6790. NULL,
  6791. NULL,
  6792. NULL );
  6793. if( !NT_SUCCESS(Status) ) {
  6794. if( SavedStatus == STATUS_SUCCESS ) {
  6795. SavedStatus = Status;
  6796. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Unable to process section %ls in driver.inf. Status = %lx \n", q, Status));
  6797. }
  6798. }
  6799. SpMemFree( q );
  6800. }
  6801. ZwClose( SystemHiveRoot );
  6802. return( Status );
  6803. }
  6804. NTSTATUS
  6805. SpCheckForDockableMachine(
  6806. )
  6807. /*++
  6808. Routine Description:
  6809. This routine attempts to determine if the machine is "dockable" (laptops),
  6810. and set the flag DockableMachine appropriately.
  6811. Arguments:
  6812. None.
  6813. Return Value:
  6814. None.
  6815. --*/
  6816. {
  6817. NTSTATUS Status;
  6818. OBJECT_ATTRIBUTES Obja;
  6819. UNICODE_STRING UnicodeString;
  6820. HANDLE hKey;
  6821. PWSTR KeyPath = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\IDConfigDB\\CurrentDockInfo";
  6822. PWSTR ValueName = L"DockingState";
  6823. ULONG ResultLength;
  6824. DWORD DockingState;
  6825. Status = STATUS_SUCCESS;
  6826. //
  6827. // If we have already determined if the machine is dockable, then just return
  6828. // This is because some machine will have the info in the registry already set prior to pnp
  6829. // notification, and some machines won't. So this function is always called twice.
  6830. //
  6831. if( !DockableMachine ) {
  6832. //
  6833. // Open a the key in the setup hive that contains the docking information
  6834. //
  6835. INIT_OBJA(&Obja,&UnicodeString,KeyPath);
  6836. Obja.RootDirectory = NULL;
  6837. Status = ZwOpenKey(&hKey,KEY_READ,&Obja);
  6838. if( !NT_SUCCESS( Status ) ) {
  6839. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open %ls on the setup hive. Status = %lx \n", KeyPath, Status));
  6840. return( Status );
  6841. }
  6842. RtlInitUnicodeString(&UnicodeString,ValueName);
  6843. Status = ZwQueryValueKey( hKey,
  6844. &UnicodeString,
  6845. KeyValuePartialInformation,
  6846. TemporaryBuffer,
  6847. sizeof(TemporaryBuffer),
  6848. &ResultLength );
  6849. ZwClose(hKey);
  6850. if( !NT_SUCCESS(Status) ) {
  6851. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: ZwQueryValueKey() failed. Value name = %ls, Status = %lx \n", ValueName, Status));
  6852. return( Status );
  6853. }
  6854. DockingState = *((PDWORD)(((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data));
  6855. DockingState &= HW_PROFILE_DOCKSTATE_UNKNOWN;
  6856. if( ( DockingState == HW_PROFILE_DOCKSTATE_UNDOCKED ) ||
  6857. ( DockingState == HW_PROFILE_DOCKSTATE_DOCKED ) ) {
  6858. DockableMachine = TRUE;
  6859. } else {
  6860. DockableMachine = FALSE;
  6861. }
  6862. }
  6863. return( Status );
  6864. }
  6865. VOID
  6866. SpCheckForBadBios(
  6867. )
  6868. /*++
  6869. Routine Description:
  6870. Determine whether the bios of the machine supports NT, by checking the
  6871. registry value "BadBios" on \Registry\Machine\System\CurrentControlSet\Services\Setup.
  6872. If this value exists and it is set to 1, then we stop the installation. Otherwise, we
  6873. assume that the bios on this machine is fine.
  6874. Arguments:
  6875. None.
  6876. Return Value:
  6877. None.
  6878. --*/
  6879. {
  6880. NTSTATUS Status;
  6881. OBJECT_ATTRIBUTES Obja;
  6882. UNICODE_STRING UnicodeString;
  6883. HANDLE hKey;
  6884. PWSTR KeyPath = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\setupdd";
  6885. PWSTR ValueName = L"BadBios";
  6886. ULONG ResultLength;
  6887. DWORD BadBios;
  6888. Status = STATUS_SUCCESS;
  6889. //
  6890. // Open a the setup key in the setup hive
  6891. //
  6892. INIT_OBJA(&Obja,&UnicodeString,KeyPath);
  6893. Obja.RootDirectory = NULL;
  6894. Status = ZwOpenKey(&hKey,KEY_READ,&Obja);
  6895. if( !NT_SUCCESS( Status ) ) {
  6896. //
  6897. // If we can't open the key, then assume the BIOS is fine.
  6898. //
  6899. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open %ls on the setup hive. Status = %lx \n", KeyPath, Status));
  6900. return;
  6901. }
  6902. RtlInitUnicodeString(&UnicodeString,ValueName);
  6903. Status = ZwQueryValueKey( hKey,
  6904. &UnicodeString,
  6905. KeyValuePartialInformation,
  6906. TemporaryBuffer,
  6907. sizeof(TemporaryBuffer),
  6908. &ResultLength );
  6909. ZwClose(hKey);
  6910. if( !NT_SUCCESS(Status) ) {
  6911. //
  6912. // If we can't query the value, assume that the BIOS is fine
  6913. //
  6914. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: ZwQueryValueKey() failed. Value name = %ls, Status = %lx \n", ValueName, Status));
  6915. return;
  6916. }
  6917. BadBios = *((PDWORD)(((PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer)->Data));
  6918. if( BadBios ) {
  6919. //
  6920. // If BadBios is anything other then 0, then stop the installation
  6921. //
  6922. SpStartScreen( SP_SCRN_BAD_BIOS,
  6923. 3,
  6924. HEADER_HEIGHT+1,
  6925. FALSE,
  6926. FALSE,
  6927. DEFAULT_ATTRIBUTE );
  6928. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,SP_STAT_F3_EQUALS_EXIT,0);
  6929. SpInputDrain();
  6930. while(SpInputGetKeypress() != KEY_F3) ;
  6931. SpDone(0,FALSE,TRUE);
  6932. }
  6933. return;
  6934. }
  6935. NTSTATUS
  6936. SpCreateDriverRegistryEntries(
  6937. IN PHARDWARE_COMPONENT DriverList
  6938. )
  6939. /*++
  6940. Routine Description:
  6941. Creates the specified registry keys & values for the
  6942. thirdy party (OEM) drivers
  6943. Arguments:
  6944. DriverList : List of OEM drivers loaded for which the
  6945. keys need to be created
  6946. Return Value:
  6947. STATUS_SUCCESS if successful, otherwise appropriate
  6948. error code.
  6949. --*/
  6950. {
  6951. NTSTATUS LastError = STATUS_SUCCESS;
  6952. PHARDWARE_COMPONENT CurrNode;
  6953. NTSTATUS Status = DriverList ?
  6954. STATUS_SUCCESS : STATUS_INVALID_PARAMETER;
  6955. for (CurrNode = DriverList; CurrNode; CurrNode = CurrNode->Next) {
  6956. if (CurrNode->ThirdPartyOptionSelected) {
  6957. PHARDWARE_COMPONENT_FILE CurrFile;
  6958. for (CurrFile = CurrNode->Files;
  6959. CurrFile;
  6960. CurrFile = CurrFile->Next) {
  6961. if ((CurrFile->FileType == HwFileDriver) &&
  6962. CurrFile->ConfigName && CurrFile->RegistryValueList) {
  6963. WCHAR DriverKeyName[128];
  6964. WCHAR DriverName[32];
  6965. PWSTR DriverExt;
  6966. HANDLE hDriverKey = NULL;
  6967. UNICODE_STRING UniDriverKeyName;
  6968. OBJECT_ATTRIBUTES ObjAttrs;
  6969. PHARDWARE_COMPONENT_REGISTRY CurrEntry;
  6970. wcscpy(DriverName, CurrFile->Filename);
  6971. DriverExt = wcsrchr(DriverName, L'.');
  6972. if (DriverExt) {
  6973. *DriverExt = UNICODE_NULL;
  6974. }
  6975. //
  6976. // Note : We use driver name, instead of ConfigName for
  6977. // subkey name to take care of the case where ConfigName
  6978. // is different from DriverName
  6979. //
  6980. wcscpy(DriverKeyName,
  6981. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
  6982. wcscat(DriverKeyName, DriverName);
  6983. RtlInitUnicodeString(&UniDriverKeyName,
  6984. DriverKeyName);
  6985. InitializeObjectAttributes(&ObjAttrs,
  6986. &UniDriverKeyName,
  6987. OBJ_CASE_INSENSITIVE,
  6988. NULL,
  6989. NULL);
  6990. Status = ZwCreateKey(&hDriverKey,
  6991. KEY_ALL_ACCESS,
  6992. &ObjAttrs,
  6993. 0,
  6994. NULL,
  6995. REG_OPTION_NON_VOLATILE,
  6996. NULL);
  6997. if (NT_SUCCESS(Status) && hDriverKey) {
  6998. for (CurrEntry = CurrFile->RegistryValueList;
  6999. CurrEntry;
  7000. CurrEntry = CurrEntry->Next) {
  7001. PWSTR SubKey = CurrEntry->KeyName;
  7002. if (SubKey && !*SubKey) {
  7003. SubKey = NULL;
  7004. }
  7005. Status = SpOpenSetValueAndClose(
  7006. hDriverKey,
  7007. SubKey,
  7008. CurrEntry->ValueName,
  7009. CurrEntry->ValueType,
  7010. CurrEntry->Buffer,
  7011. CurrEntry->BufferSize);
  7012. if (!NT_SUCCESS(Status)) {
  7013. LastError = Status;
  7014. KdPrintEx((DPFLTR_SETUP_ID,
  7015. DPFLTR_ERROR_LEVEL,
  7016. "SETUP:SpCreateDriverRegistryEntries() :"
  7017. " unable to set %ws (%lx)\n",
  7018. CurrEntry->ValueName,
  7019. Status));
  7020. }
  7021. }
  7022. ZwClose(hDriverKey);
  7023. } else {
  7024. LastError = Status;
  7025. }
  7026. }
  7027. }
  7028. }
  7029. }
  7030. if (!NT_SUCCESS(LastError)) {
  7031. Status = LastError;
  7032. }
  7033. return Status;
  7034. }
  7035. BOOL
  7036. SpRememberMigratedDrivers (
  7037. OUT PLIST_ENTRY List,
  7038. IN PDETECTED_DEVICE SetupldrList
  7039. )
  7040. {
  7041. PSP_MIG_DRIVER_ENTRY MigEntry;
  7042. BOOL b = TRUE;
  7043. while (SetupldrList) {
  7044. if (SetupldrList->MigratedDriver) {
  7045. MigEntry = SpMemAlloc(sizeof (*MigEntry));
  7046. if (MigEntry) {
  7047. MigEntry->BaseDllName = SpToUnicode(SetupldrList->BaseDllName);
  7048. if (MigEntry->BaseDllName) {
  7049. InsertTailList (List, &MigEntry->ListEntry);
  7050. } else {
  7051. SpMemFree (MigEntry);
  7052. b = FALSE;
  7053. }
  7054. } else {
  7055. b = FALSE;
  7056. }
  7057. }
  7058. SetupldrList = SetupldrList->Next;
  7059. }
  7060. return b;
  7061. }