Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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