Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4936 lines
143 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. sphw.c
  5. Abstract:
  6. Hardware detection and confirmation routines for text setup.
  7. Author:
  8. Ted Miller (tedm) 1-October-1993
  9. Revision History:
  10. --*/
  11. #include "spprecmp.h"
  12. #pragma hdrstop
  13. extern BOOLEAN HandleLineContinueChars;
  14. VOID
  15. SpHardwareConfirmInteract(
  16. IN PVOID SifHandle
  17. );
  18. VOID
  19. SpConfirmScsiInteract(
  20. IN PVOID SifHandle,
  21. IN PWSTR SourceDevicePath,
  22. IN PWSTR DirectoryOnSourceDevice
  23. );
  24. BOOLEAN
  25. SpSelectHwItem(
  26. IN PVOID SifHandle,
  27. IN PWSTR NonlocalizedComponentName,
  28. IN PWSTR OemSectionName, OPTIONAL
  29. IN ULONG SelectHwScreenId,
  30. IN ULONG SelectOemHwScreenId,
  31. IN ULONG AllowedFileTypes,
  32. IN ULONG RequiredFileTypes,
  33. IN OUT PHARDWARE_COMPONENT HwComp
  34. );
  35. VOID
  36. SpScanHardwareDescription(
  37. IN PWSTR DesiredKeyName
  38. );
  39. VOID
  40. SpDetectComputer(
  41. IN PVOID SifHandle
  42. );
  43. VOID
  44. SpDetectVideo(
  45. IN PVOID SifHandle
  46. );
  47. VOID
  48. SpDetectKeyboard(
  49. IN PVOID SifHandle
  50. );
  51. VOID
  52. SpDetectMouse(
  53. IN PVOID SifHandle
  54. );
  55. VOID
  56. SpDetectLayout(
  57. IN PVOID SifHandle
  58. );
  59. VOID
  60. SpDetectScsi(
  61. IN PVOID SifHandle,
  62. IN PWSTR SourceDevicePath,
  63. IN PWSTR DirectoryOnSourceDevice
  64. );
  65. VOID
  66. SpDetermineComponent(
  67. IN PVOID SifHandle,
  68. OUT PHARDWARE_COMPONENT HwComp,
  69. IN PWSTR HardwareDescriptionKeyName,
  70. IN PWSTR FallbackIdentifier,
  71. IN PWSTR ComponentName
  72. );
  73. BOOLEAN
  74. SpOemDiskette(
  75. IN PVOID SifHandle,
  76. IN PWSTR SectionName,
  77. IN ULONG SelectOemHwScreenId,
  78. IN ULONG AllowedFileTypes,
  79. IN ULONG RequiredFileTypes,
  80. IN OUT PHARDWARE_COMPONENT HwComp,
  81. IN ULONG ErrorId
  82. );
  83. BOOLEAN
  84. SpOemInfSelection(
  85. IN PVOID TxtsetupOem,
  86. IN PWSTR NonlocalizedComponentName,
  87. IN PWSTR SelectedId,
  88. IN PWSTR ItemDescription,
  89. IN ULONG AllowedFileTypes,
  90. IN ULONG RequiredFileTypes,
  91. OUT PHARDWARE_COMPONENT HwComp,
  92. IN ULONG ErrorId
  93. );
  94. VOID
  95. SpFreeLocatedIdStrings(
  96. VOID
  97. );
  98. VOID
  99. SpScanHardwareDescriptionWorker(
  100. IN HANDLE KeyHandle,
  101. IN PWSTR KeyName,
  102. IN PWSTR DesiredKeyName
  103. );
  104. BOOLEAN
  105. SpScanMapSection(
  106. IN PVOID SifHandle,
  107. OUT PHARDWARE_COMPONENT HwComp,
  108. IN PWSTR ComponentName,
  109. IN PWSTR IdString
  110. );
  111. VOID
  112. SpInitHwComponent(
  113. OUT PHARDWARE_COMPONENT HwComp,
  114. IN PWSTR IdString,
  115. IN PWSTR Description,
  116. IN BOOLEAN ThirdPartyOption,
  117. IN ULONG FileTypeBits,
  118. IN PWSTR BaseDllName,
  119. IN BOOLEAN MigratedDriver
  120. );
  121. VOID
  122. SpInitHwComponentFile(
  123. OUT PHARDWARE_COMPONENT_FILE HwCompFile,
  124. IN PWSTR Filename,
  125. IN HwFileType FileType,
  126. IN PWSTR ConfigName,
  127. IN PWSTR DiskDescription,
  128. IN PWSTR DiskTagFile,
  129. IN PWSTR Directory,
  130. IN PWSTR ArcDeviceName
  131. );
  132. VOID
  133. SpInitHwComponentRegVal(
  134. OUT PHARDWARE_COMPONENT_REGISTRY HwCompReg,
  135. IN PWSTR KeyName,
  136. IN PWSTR ValueName,
  137. IN ULONG ValueType,
  138. IN PVOID Buffer,
  139. IN ULONG BufferSize
  140. );
  141. VOID
  142. SpFreeHwComponentFile(
  143. IN OUT PHARDWARE_COMPONENT_FILE *HwCompFile
  144. );
  145. VOID
  146. SpFreeHwComponentReg(
  147. IN OUT PHARDWARE_COMPONENT_REGISTRY *HwCompReg
  148. );
  149. PHARDWARE_COMPONENT_REGISTRY
  150. SpInterpretOemRegistryData(
  151. IN PVOID SifHandle,
  152. IN PWSTR SectionName,
  153. IN ULONG Line,
  154. IN ULONG ValueType,
  155. IN PWSTR KeyName,
  156. IN PWSTR ValueName
  157. );
  158. VOID
  159. SpGetDriverValuesForLoad(
  160. IN PVOID SifHandle,
  161. IN PWSTR ComponentSectionName,
  162. IN PWSTR ComponentLoadSectionName,
  163. IN PWSTR Shortname,
  164. OUT PWSTR *Filename,
  165. OUT PWSTR *MediaDesignator,
  166. OUT PWSTR *Description OPTIONAL
  167. );
  168. //
  169. // These two globals track a table that gets built as the
  170. // hardware description in the registry is scanned for a
  171. // particular hardware component. See SpScanHardwareDescription().
  172. //
  173. PWSTR *IdStringArray;
  174. ULONG IdStringCount;
  175. //
  176. // Array of ulongs that are the message ids for screens that
  177. // prompt the user to select a type of a component from the
  178. // list below.
  179. //
  180. ULONG SelectHwScreens[HwComponentMax] = { SP_SCRN_SELECT_COMPUTER,
  181. SP_SCRN_SELECT_DISPLAY,
  182. SP_SCRN_SELECT_KEYBOARD,
  183. SP_SCRN_SELECT_LAYOUT,
  184. SP_SCRN_SELECT_MOUSE
  185. };
  186. //
  187. // Array of ulongs that are the message ids for screens that
  188. // prompt the user to select an option from an oem disk for
  189. // a component from the list below.
  190. //
  191. ULONG SelectOemHwScreens[HwComponentMax] = { SP_SCRN_SELECT_OEM_COMPUTER,
  192. SP_SCRN_SELECT_OEM_DISPLAY,
  193. SP_SCRN_SELECT_OEM_KEYBOARD,
  194. SP_SCRN_SELECT_OEM_LAYOUT,
  195. SP_SCRN_SELECT_OEM_MOUSE
  196. };
  197. ULONG UnknownHwScreens[HwComponentMax] = { SP_SCRN_UNKNOWN_COMPUTER,
  198. SP_SCRN_UNKNOWN_DISPLAY,
  199. SP_SCRN_UNKNOWN_KEYBOARD,
  200. SP_SCRN_UNKNOWN_LAYOUT,
  201. SP_SCRN_UNKNOWN_MOUSE
  202. };
  203. //
  204. // These are the names of the components. This is array is not localized
  205. // because it is used only to index hardware-related sections in the
  206. // setup information file.
  207. //
  208. PWSTR NonlocalizedComponentNames[HwComponentMax] = { L"Computer",
  209. L"Display",
  210. L"Keyboard",
  211. L"Keyboard Layout",
  212. L"Mouse"
  213. };
  214. //
  215. // The following is the name of the SCSI section in txtsetup.sif.
  216. // On amd64/x86 machines, this is one of SCSI.ISA, SCSI.EISA, or SCSI.MCA.
  217. // On other machines, this is just SCSI.
  218. //
  219. PWSTR ScsiSectionName;
  220. PWSTR ScsiLoadSectionName;
  221. PWSTR FileTypeNames[HwFileMax+1] = { L"Driver",
  222. L"Port",
  223. L"Class",
  224. L"Inf",
  225. L"Dll",
  226. L"Detect",
  227. L"Hal",
  228. L"Catalog",
  229. NULL
  230. };
  231. PWSTR RegistryTypeNames[HwRegistryMax+1] = { L"REG_DWORD",
  232. L"REG_BINARY",
  233. L"REG_SZ",
  234. L"REG_EXPAND_SZ",
  235. L"REG_MULTI_SZ",
  236. NULL
  237. };
  238. ULONG RegistryValueTypeMap[HwRegistryMax] = { REG_DWORD,
  239. REG_BINARY,
  240. REG_SZ,
  241. REG_EXPAND_SZ,
  242. REG_MULTI_SZ
  243. };
  244. PHARDWARE_COMPONENT HardwareComponents[HwComponentMax] = { NULL,NULL,NULL,NULL,NULL };
  245. PHARDWARE_COMPONENT ScsiHardware;
  246. PHARDWARE_COMPONENT BootBusExtenders;
  247. PHARDWARE_COMPONENT BusExtenders;
  248. PHARDWARE_COMPONENT InputDevicesSupport;
  249. PHARDWARE_COMPONENT PreinstallHardwareComponents[HwComponentMax] = { NULL,NULL,NULL,NULL,NULL };
  250. PHARDWARE_COMPONENT PreinstallScsiHardware = NULL;
  251. PHARDWARE_COMPONENT UnsupportedScsiHardwareToDisable = NULL;
  252. PWSTR PreinstallSectionNames[HwComponentMax] = { WINNT_U_COMPUTERTYPE_W,
  253. WINNT_OEMDISPLAYDRIVERS_W,
  254. WINNT_OEMKEYBOARDDRIVERS_W,
  255. WINNT_U_KEYBOARDLAYOUT_W,
  256. WINNT_OEMPOINTERDRIVERS_W
  257. };
  258. #define MAX_SCSI_MINIPORT_COUNT 5
  259. ULONG LoadedScsiMiniportCount;
  260. //
  261. // This array lists the type of files allowed for each component type.
  262. // For example, detect files are allowed for computer and driver files are
  263. // allowed for all component types. Keep in sync with HwComponentType enum!
  264. //
  265. ULONG AllowedFileTypes[HwComponentMax] = {
  266. // Computer
  267. FILETYPE(HwFileDriver) | FILETYPE(HwFilePort) | FILETYPE(HwFileClass)
  268. | FILETYPE(HwFileInf) | FILETYPE(HwFileDll) | FILETYPE(HwFileDetect)
  269. | FILETYPE(HwFileHal) | FILETYPE(HwFileCatalog),
  270. // Display
  271. FILETYPE(HwFileDriver) | FILETYPE(HwFilePort) | FILETYPE(HwFileInf)
  272. | FILETYPE(HwFileDll) | FILETYPE(HwFileCatalog),
  273. // Keyboard
  274. FILETYPE(HwFileDriver) | FILETYPE(HwFilePort) | FILETYPE(HwFileClass)
  275. | FILETYPE(HwFileInf) | FILETYPE(HwFileDll) | FILETYPE(HwFileCatalog),
  276. // Layout
  277. FILETYPE(HwFileDll) | FILETYPE(HwFileInf),
  278. // Mouse
  279. FILETYPE(HwFileDriver) | FILETYPE(HwFilePort) | FILETYPE(HwFileClass)
  280. | FILETYPE(HwFileInf) | FILETYPE(HwFileDll) | FILETYPE(HwFileCatalog)
  281. };
  282. #define SCSI_ALLOWED_FILETYPES (FILETYPE(HwFileDriver) | FILETYPE(HwFilePort) | FILETYPE(HwFileInf) | FILETYPE(HwFileCatalog))
  283. //
  284. // This array lists the type of files required for each component type.
  285. // For example, a hal is required for computer. Keep in sync with
  286. // HwComponentType enum!
  287. //
  288. ULONG RequiredFileTypes[HwComponentMax] = {
  289. // Computer
  290. FILETYPE(HwFileHal),
  291. // Display
  292. FILETYPE(HwFileDriver) | FILETYPE(HwFileDll),
  293. // Keyboard
  294. FILETYPE(HwFileDriver),
  295. // Layout
  296. FILETYPE(HwFileDll),
  297. // Mouse
  298. FILETYPE(HwFileDriver)
  299. };
  300. #define SCSI_REQUIRED_FILETYPES FILETYPE(HwFileDriver)
  301. #define MAP_SECTION_NAME_PREFIX L"Map."
  302. #define HARDWARE_MENU_SIZE HwComponentMax
  303. #define MICROSOFT_BUS_MOUSE_NAME L"MICROSOFT BUS MOUSE"
  304. FloppyDriveType
  305. SpGetFloppyDriveType(
  306. IN ULONG FloppyOrdinal
  307. )
  308. /*++
  309. Routine Description:
  310. Inspect a floppy disk drive attempting to classify it as a
  311. 5.25 or 3.5" drive, hi or low density. For 5.25" disks,
  312. 1.2MB drives are high density; smaller drives are low-density.
  313. For 3.5" drives, 1.44, 2.88, or 20.8MB is high density, smaller
  314. drives are low density.
  315. Any other drive types are unrecognized and result in
  316. FloppyTypeNone being returned.
  317. Arguments:
  318. FloppyOrdinal - supplies ordinal number of floppy (0=A:, etc).
  319. Return Value:
  320. Value from the FloppyDriveType enum indicating which type the drive is.
  321. FloppyTypeNone if we couldn't determine this information.
  322. --*/
  323. {
  324. NTSTATUS Status;
  325. IO_STATUS_BLOCK IoStatusBlock;
  326. OBJECT_ATTRIBUTES ObjectAttributes;
  327. UNICODE_STRING UnicodeString;
  328. HANDLE Handle;
  329. WCHAR OpenPath[64];
  330. DISK_GEOMETRY DiskGeom[25];
  331. ULONG_PTR MediaTypeCount;
  332. static FloppyDriveType CachedTypes[2] = { -1,-1 };
  333. FloppyDriveType FloppyType;
  334. //
  335. // If we have already determined this for this drive,
  336. // return the cached info.
  337. //
  338. if((FloppyOrdinal < ELEMENT_COUNT(CachedTypes))
  339. && (CachedTypes[FloppyOrdinal] != -1))
  340. {
  341. return(CachedTypes[FloppyOrdinal]);
  342. }
  343. //
  344. // Assume the floppy doesn't exist or we can't tell what type it is.
  345. //
  346. FloppyType = FloppyTypeNone;
  347. swprintf(OpenPath,L"\\device\\floppy%u",FloppyOrdinal);
  348. INIT_OBJA(&ObjectAttributes,&UnicodeString,OpenPath);
  349. Status = ZwCreateFile(
  350. &Handle,
  351. SYNCHRONIZE | FILE_READ_ATTRIBUTES,
  352. &ObjectAttributes,
  353. &IoStatusBlock,
  354. NULL, // allocation size
  355. FILE_ATTRIBUTE_NORMAL,
  356. FILE_SHARE_VALID_FLAGS, // full sharing
  357. FILE_OPEN,
  358. FILE_SYNCHRONOUS_IO_NONALERT,
  359. NULL, // no EAs
  360. 0
  361. );
  362. if(NT_SUCCESS(Status)) {
  363. //
  364. // Get supported media types.
  365. //
  366. Status = ZwDeviceIoControlFile(
  367. Handle,
  368. NULL,
  369. NULL,
  370. NULL,
  371. &IoStatusBlock,
  372. IOCTL_DISK_GET_MEDIA_TYPES,
  373. NULL,
  374. 0,
  375. DiskGeom,
  376. sizeof(DiskGeom)
  377. );
  378. if(NT_SUCCESS(Status)) {
  379. ASSERT((IoStatusBlock.Information % sizeof(DISK_GEOMETRY)) == 0);
  380. if(MediaTypeCount = IoStatusBlock.Information / sizeof(DISK_GEOMETRY)) {
  381. //
  382. // Highest capacity media type is last entry.
  383. //
  384. switch(DiskGeom[MediaTypeCount-1].MediaType) {
  385. case F5_1Pt23_1024: //NEC98
  386. if (!IsNEC_98) {
  387. break;
  388. }
  389. // trough down to set FloppyType525High on NEC98
  390. case F5_1Pt2_512:
  391. FloppyType = FloppyType525High;
  392. break;
  393. case F3_1Pt23_1024: //NEC98
  394. if (!IsNEC_98) {
  395. break;
  396. }
  397. // trough down to set FloppyType35High on NEC98
  398. case F3_1Pt44_512:
  399. case F3_2Pt88_512:
  400. case F3_20Pt8_512:
  401. FloppyType = FloppyType35High;
  402. break;
  403. case F3_720_512:
  404. FloppyType = FloppyType35Low;
  405. break;
  406. case F5_360_512:
  407. case F5_320_512:
  408. case F5_320_1024:
  409. case F5_180_512:
  410. case F5_160_512:
  411. FloppyType = FloppyType525Low;
  412. break;
  413. case F3_120M_512:
  414. FloppyType = FloppyType35High120MB;
  415. break;
  416. }
  417. } else {
  418. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: no media types for %ws!\n",OpenPath));
  419. }
  420. } else {
  421. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to get media types for %ws (%lx)\n",OpenPath,Status));
  422. }
  423. ZwClose(Handle);
  424. } else {
  425. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: %ws does not exist (%lx)\n",OpenPath,Status));
  426. }
  427. //
  428. // Save the value.
  429. //
  430. if(FloppyOrdinal < ELEMENT_COUNT(CachedTypes)) {
  431. CachedTypes[FloppyOrdinal] = FloppyType;
  432. }
  433. return(FloppyType);
  434. }
  435. VOID
  436. SpConfirmScsiMiniports(
  437. IN PVOID SifHandle,
  438. IN PWSTR SourceDevicePath,
  439. IN PWSTR DirectoryOnSourceDevice
  440. )
  441. {
  442. CLEAR_CLIENT_SCREEN();
  443. SpDisplayStatusText(SP_STAT_PLEASE_WAIT,DEFAULT_STATUS_ATTRIBUTE);
  444. //
  445. // Start with scsi.
  446. //
  447. SpDetectScsi(SifHandle,SourceDevicePath,DirectoryOnSourceDevice);
  448. SpConfirmScsiInteract(SifHandle,SourceDevicePath,DirectoryOnSourceDevice);
  449. }
  450. VOID
  451. SpConfirmHardware(
  452. IN PVOID SifHandle
  453. )
  454. {
  455. ULONG i;
  456. BOOLEAN AllConfirmed,FirstPass,NeedConfirm;
  457. PWSTR p;
  458. CLEAR_CLIENT_SCREEN();
  459. SpDisplayStatusText(SP_STAT_PLEASE_WAIT,DEFAULT_STATUS_ATTRIBUTE);
  460. //
  461. // Determine the computer type.
  462. //
  463. SpDetectComputer(SifHandle);
  464. //
  465. // Determine the video type.
  466. //
  467. SpDetectVideo(SifHandle);
  468. //
  469. // Determine the keyboard type.
  470. //
  471. SpDetectKeyboard(SifHandle);
  472. //
  473. // Determine the mouse.
  474. //
  475. SpDetectMouse(SifHandle);
  476. //
  477. // Determine the keyboard layout.
  478. //
  479. SpDetectLayout(SifHandle);
  480. //
  481. // If we have upgrade, we don't need to know what display, keyboard,
  482. // layout, mouse we have. We just need the computer type and that
  483. // is 100% accurate. So we can skip the hardware confirmation dialog
  484. //
  485. if(NTUpgrade == UpgradeFull) {
  486. return;
  487. }
  488. //
  489. // Handle locale-specific keyboard stuff for Far East.
  490. //
  491. SplangSelectKeyboard(
  492. UnattendedOperation,
  493. UnattendedSifHandle,
  494. NTUpgrade,
  495. SifHandle,
  496. HardwareComponents
  497. );
  498. //
  499. // See whether this is an unattended setup.
  500. //
  501. NeedConfirm = FALSE;
  502. if(UnattendedOperation) {
  503. NeedConfirm = FALSE;
  504. if( !PreInstall ) {
  505. //
  506. // If this is not an OEM pre-install, then check if we need
  507. // to confirm the hardware
  508. //
  509. p = SpGetSectionKeyIndex(
  510. UnattendedSifHandle,
  511. SIF_UNATTENDED,
  512. SIF_CONFIRMHW,
  513. 0
  514. );
  515. if(p && !_wcsicmp(p,L"yes")) {
  516. NeedConfirm = TRUE;
  517. }
  518. } else {
  519. return;
  520. }
  521. }
  522. FirstPass = TRUE;
  523. do {
  524. //
  525. // See if we know what everything is.
  526. //
  527. AllConfirmed = TRUE;
  528. for(i=0; i<HwComponentMax; i++) {
  529. if(HardwareComponents[i]->Description == NULL) {
  530. AllConfirmed = FALSE;
  531. break;
  532. }
  533. }
  534. //
  535. // If we don't know what everything is, put up a warning.
  536. //
  537. if(FirstPass) {
  538. if(CustomSetup && NeedConfirm) {
  539. AllConfirmed = FALSE;
  540. }
  541. FirstPass = FALSE;
  542. } else if(!AllConfirmed) {
  543. SpDisplayScreen(UnknownHwScreens[i],4,HEADER_HEIGHT+2);
  544. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,SP_STAT_ENTER_EQUALS_CONTINUE,0);
  545. SpInputDrain();
  546. while(SpInputGetKeypress() != ASCI_CR) ;
  547. }
  548. //
  549. // If this is a custom setup or we don't know what
  550. // a piece of hardware is, present the confirmation screen
  551. // to the user.
  552. //
  553. if(!AllConfirmed) {
  554. SpHardwareConfirmInteract(SifHandle);
  555. }
  556. } while(!AllConfirmed);
  557. }
  558. VOID
  559. SpHardwareConfirmInteract(
  560. IN PVOID SifHandle
  561. )
  562. {
  563. PWSTR szUnknown,szListMatches;
  564. PWSTR p;
  565. ULONG MenuLeftX,MenuTopY;
  566. ULONG LongestLength,len;
  567. PWSTR MenuItems[HARDWARE_MENU_SIZE];
  568. PVOID Menu;
  569. ULONG KeyPressed;
  570. ULONG_PTR Selection;
  571. ULONG ValidKeys[3] = { KEY_F3,ASCI_CR,0 };
  572. BOOLEAN Done;
  573. ULONG i;
  574. WCHAR c;
  575. //
  576. // Fetch 'unknown' and 'the above list matches my computer' from the resources.
  577. //
  578. SpFormatMessage(TemporaryBuffer,sizeof(TemporaryBuffer),SP_TEXT_UNKNOWN);
  579. szUnknown = SpDupStringW(TemporaryBuffer);
  580. SpFormatMessage(TemporaryBuffer,sizeof(TemporaryBuffer),SP_TEXT_LIST_MATCHES);
  581. szListMatches = SpDupStringW(TemporaryBuffer);
  582. for(Done=FALSE; !Done; ) {
  583. //
  584. // Part 1 of the screen.
  585. //
  586. SpDisplayScreen(SP_SCRN_HW_CONFIRM_1,3,HEADER_HEIGHT+1);
  587. //
  588. // Remember top line of the menu.
  589. //
  590. MenuTopY = NextMessageTopLine + 2;
  591. //
  592. // Part 2 of the screen.
  593. //
  594. SpContinueScreen(SP_SCRN_HW_CONFIRM_2,3,2,FALSE,DEFAULT_ATTRIBUTE);
  595. //
  596. // To determine where the left margin of the menu is, we'll load
  597. // the second part of the screen and look for the first semicolon.
  598. //
  599. SpFormatMessage(TemporaryBuffer,sizeof(TemporaryBuffer),SP_SCRN_HW_CONFIRM_2);
  600. p = wcschr(TemporaryBuffer,L':');
  601. ASSERT(p);
  602. if(p) {
  603. c = *p;
  604. *p = 0;
  605. MenuLeftX = SplangGetColumnCount(TemporaryBuffer) + 5;
  606. *p = c;
  607. } else {
  608. MenuLeftX = 23;
  609. }
  610. //
  611. // Build up menu items.
  612. //
  613. LongestLength = SplangGetColumnCount(szListMatches);
  614. for(i=0; i<HARDWARE_MENU_SIZE; i++) {
  615. MenuItems[i] = HardwareComponents[i]->Description
  616. ? HardwareComponents[i]->Description
  617. : szUnknown;
  618. if((len=SplangGetColumnCount(MenuItems[i])) > LongestLength) {
  619. LongestLength = len;
  620. }
  621. }
  622. Menu = SpMnCreate(MenuLeftX,MenuTopY,LongestLength,HARDWARE_MENU_SIZE+2);
  623. ASSERT(Menu);
  624. //
  625. // Silently fail, if we cannot create the menu
  626. //
  627. if (!Menu) {
  628. Done = TRUE;
  629. continue;
  630. }
  631. //
  632. // Add all the items to the menu, plus one unselectable spacer and
  633. // the 'the list matches' item.
  634. //
  635. for(i=0; i<HARDWARE_MENU_SIZE; i++) {
  636. BOOLEAN ItemSelectable;
  637. #if defined(_IA64_)
  638. ItemSelectable = TRUE; // in softsdv the mouse + keyboard are
  639. // unknown; we need to select them.
  640. #else
  641. ItemSelectable = ( (i != HwComponentKeyboard) &&
  642. (i != HwComponentMouse) );
  643. #endif
  644. SpMnAddItem(Menu,
  645. MenuItems[i],
  646. MenuLeftX,
  647. LongestLength,
  648. ItemSelectable,
  649. ItemSelectable ? i : 0);
  650. }
  651. SpMnAddItem(Menu,L"",MenuLeftX,LongestLength,FALSE,0);
  652. SpMnAddItem(Menu,szListMatches,MenuLeftX,LongestLength,TRUE,(ULONG_PTR)(-1));
  653. //
  654. // Display the status text.
  655. //
  656. SpDisplayStatusOptions(
  657. DEFAULT_STATUS_ATTRIBUTE,
  658. SP_STAT_ENTER_EQUALS_SELECT,
  659. SP_STAT_F3_EQUALS_EXIT,
  660. 0
  661. );
  662. //
  663. // Display the menu and await a selection.
  664. //
  665. SpMnDisplay(Menu,
  666. (ULONG_PTR)(-1),
  667. FALSE,
  668. ValidKeys,
  669. NULL,
  670. NULL,
  671. NULL,
  672. &KeyPressed,
  673. &Selection);
  674. SpMnDestroy(Menu);
  675. switch(KeyPressed) {
  676. case KEY_F3:
  677. SpConfirmExit();
  678. break;
  679. case ASCI_CR:
  680. //
  681. // Selection was made.
  682. //
  683. if(Selection == (ULONG_PTR)(-1)) {
  684. Done = TRUE;
  685. } else {
  686. ASSERT(Selection < HwComponentMax);
  687. //
  688. // Allow user to make alternate selection for this component.
  689. //
  690. SpSelectHwItem(
  691. SifHandle,
  692. NonlocalizedComponentNames[Selection],
  693. NULL, // use component name as section name
  694. SelectHwScreens[Selection],
  695. SelectOemHwScreens[Selection],
  696. AllowedFileTypes[Selection],
  697. RequiredFileTypes[Selection],
  698. HardwareComponents[Selection]
  699. );
  700. }
  701. break;
  702. default:
  703. // should never get here!
  704. ASSERT(0);
  705. break;
  706. }
  707. }
  708. SpMemFree(szUnknown);
  709. SpMemFree(szListMatches);
  710. }
  711. BOOLEAN
  712. SpSelectHwItem(
  713. IN PVOID SifHandle,
  714. IN PWSTR NonlocalizedComponentName,
  715. IN PWSTR OemSectionName, OPTIONAL
  716. IN ULONG SelectHwScreenId,
  717. IN ULONG SelectOemHwScreenId,
  718. IN ULONG AllowedFileTypes,
  719. IN ULONG RequiredFileTypes,
  720. IN OUT PHARDWARE_COMPONENT HwComp
  721. )
  722. /*++
  723. Routine Description:
  724. Allow the user to make selection from a list of choices for a component.
  725. The list comes from a section in the setup information file named
  726. for the component. For example, [Display].
  727. The descriptions in that section will be placed into a menu to make
  728. up the selections. Also added to the menu will be a choice for 'other'
  729. which the user can choose if he has a third-party driver diskette.
  730. If a third-party option is the currently selected option, then that
  731. option will also be on the menu and will be the default.
  732. If the user selects 'other' then prompt for a driver diskette.
  733. Arguments:
  734. SifHandle - supplies handle to open setup information file.
  735. NonlocalizedComponentName - supplies name of component to be used
  736. as the name of a section in the sif file for the component.
  737. OemSectionName - supplies name of a section that will contain the
  738. options for the component in txtsetup.oem. This may be different
  739. than NonloclizedComponentName -- for example, the componentname
  740. string might be "SCSI.MCA" but the OemSectionName would be "SCSI."
  741. SelectHwScreenId - supplies message id of the screen prompting the user
  742. to select an option for this component.
  743. SelectOemHwScreenId - supplies message id of the screen prompting the
  744. user to select an option on an oem screen for this component
  745. (ie, the screen the user gets when he selects 'other' hw type
  746. and inserts an oem floppy).
  747. AllowedFileTypes - supplies a mask indicating which types of files are
  748. allowed for this component. Used to validate the oem selection
  749. if the user chooses the 'other' hardware type and inserts an oem floppy.
  750. RequiredFileTypes - supplies a mask indicating which types of files are
  751. required for this component. Used to validate the oem selection
  752. if the user chooses the 'other' hardware type and inserts an oem floppy.
  753. HwComp - hardware component structure to be filled in with information
  754. about the user's selection.
  755. Return Value:
  756. TRUE if the selected hardware item has been changed by the user's action.
  757. FALSE otherwise.
  758. --*/
  759. {
  760. ULONG LineCount,Line;
  761. PVOID Menu;
  762. ULONG MenuTopY,MenuHeight,MenuWidth;
  763. PWSTR Description;
  764. ULONG_PTR Selection;
  765. PWSTR szOtherHardware;
  766. ULONG OtherOption;
  767. ULONG_PTR OriginalSelection = (ULONG_PTR)(-1);
  768. ULONG ValidKeys[4] = { KEY_F3,ASCI_CR,ASCI_ESC,0 };
  769. ULONG Keypress;
  770. BOOLEAN Done;
  771. BOOLEAN rc = FALSE;
  772. PWSTR Id,Descr;
  773. //
  774. // Fetch the 'other hardware' string from resources.
  775. //
  776. SpFormatMessage(TemporaryBuffer,sizeof(TemporaryBuffer),SP_TEXT_OTHER_HARDWARE);
  777. szOtherHardware = SpDupStringW(TemporaryBuffer);
  778. for(Done=FALSE; !Done; ) {
  779. //
  780. // Display the selection prompt screen.
  781. //
  782. SpDisplayScreen(SelectHwScreenId,5,HEADER_HEIGHT+1);
  783. MenuTopY = NextMessageTopLine + 2;
  784. MenuHeight = VideoVars.ScreenHeight - MenuTopY - 3;
  785. MenuWidth = VideoVars.ScreenWidth - 6;
  786. //
  787. // Create a menu.
  788. //
  789. Menu = SpMnCreate(3,MenuTopY,MenuWidth,MenuHeight);
  790. ASSERT(Menu);
  791. //
  792. // Assume unknown option.
  793. //
  794. Selection = (ULONG_PTR)(-1);
  795. //
  796. // Build a list of options containing the options in our box
  797. // and the currently selected oem option (if any).
  798. //
  799. LineCount = SpCountLinesInSection(SifHandle,NonlocalizedComponentName);
  800. for(Line=0; Line<LineCount; Line++) {
  801. //
  802. // Get the description from the current line and add it to the menu.
  803. //
  804. Description = SpGetSectionLineIndex(
  805. SifHandle,
  806. NonlocalizedComponentName,
  807. Line,
  808. INDEX_DESCRIPTION
  809. );
  810. if(!Description) {
  811. SpFatalSifError(SifHandle,NonlocalizedComponentName,NULL,Line,INDEX_DESCRIPTION);
  812. }
  813. SpMnAddItem(Menu,Description,3,VideoVars.ScreenWidth-6,TRUE,Line);
  814. //
  815. // See if this is the currently selected item.
  816. //
  817. if(HwComp->Description && !wcscmp(HwComp->Description,Description)) {
  818. Selection = Line;
  819. }
  820. }
  821. //
  822. // If there is an oem option, add its description and make it the default.
  823. //
  824. if(HwComp->ThirdPartyOptionSelected) {
  825. SpMnAddItem(Menu,HwComp->Description,3,VideoVars.ScreenWidth-6,TRUE,Line);
  826. Selection = Line++;
  827. }
  828. //
  829. // Add 'other to the list and make it the defualt if the current type is
  830. // 'other' and there is no third-party option.
  831. // Note that we don't allow oem keyboard layouts any more.
  832. //
  833. if(HwComp == HardwareComponents[HwComponentLayout]) {
  834. if(Selection == (ULONG_PTR)(-1)) {
  835. Selection = 0;
  836. }
  837. OtherOption = (ULONG)(-1);
  838. } else {
  839. SpMnAddItem(Menu,szOtherHardware,3,VideoVars.ScreenWidth-6,TRUE,Line);
  840. if((Selection == (ULONG_PTR)(-1))
  841. || (!HwComp->ThirdPartyOptionSelected && !HwComp->IdString))
  842. {
  843. Selection = Line;
  844. }
  845. OtherOption = Line;
  846. }
  847. if(OriginalSelection == (ULONG_PTR)(-1)) {
  848. OriginalSelection = Selection;
  849. }
  850. //
  851. // Display the status text options.
  852. //
  853. SpDisplayStatusOptions(
  854. DEFAULT_STATUS_ATTRIBUTE,
  855. SP_STAT_ENTER_EQUALS_SELECT,
  856. SP_STAT_F3_EQUALS_EXIT,
  857. SP_STAT_ESC_EQUALS_CANCEL,
  858. 0
  859. );
  860. //
  861. // Display the menu.
  862. //
  863. SpMnDisplay(
  864. Menu,
  865. Selection,
  866. TRUE,
  867. ValidKeys,
  868. NULL,
  869. NULL,
  870. NULL,
  871. &Keypress,
  872. &Selection
  873. );
  874. //
  875. // Fetch the description text before we free the menu structure.
  876. //
  877. Descr = SpMnGetTextDup(Menu,Selection);
  878. SpMnDestroy(Menu);
  879. switch(Keypress) {
  880. case ASCI_CR:
  881. if(Selection == OtherOption) {
  882. //
  883. // User selected 'other' -- prompt for a diskette, etc.
  884. //
  885. rc = SpOemDiskette(
  886. SifHandle,
  887. OemSectionName ? OemSectionName : NonlocalizedComponentName,
  888. SelectOemHwScreenId,
  889. AllowedFileTypes,
  890. RequiredFileTypes,
  891. HwComp,
  892. SP_SCRN_OEM_INF_ERROR
  893. );
  894. } else if(Selection == OriginalSelection) {
  895. //
  896. // User chose same thinbg that was selected before.
  897. //
  898. rc = FALSE;
  899. } else {
  900. //
  901. // User chose a non-oem option. Update structures accordingly
  902. // and forget any previously selected oem option.
  903. //
  904. Id = SpGetKeyName(SifHandle,NonlocalizedComponentName,(ULONG)Selection);
  905. if(!Id) {
  906. SpFatalSifError(SifHandle,NonlocalizedComponentName,NULL,(ULONG)Selection,(ULONG)(-1));
  907. }
  908. ASSERT(Descr);
  909. SpFreeHwComponentFile(&HwComp->Files);
  910. SpInitHwComponent(HwComp,Id,Descr,FALSE,0,NULL,FALSE);
  911. rc = TRUE;
  912. }
  913. Done = TRUE;
  914. break;
  915. case ASCI_ESC:
  916. Done = TRUE;
  917. break;
  918. case KEY_F3:
  919. SpConfirmExit();
  920. break;
  921. default:
  922. // shouldn't ever get here!
  923. ASSERT(0);
  924. break;
  925. }
  926. SpMemFree(Descr);
  927. }
  928. SpMemFree(szOtherHardware);
  929. return(rc);
  930. }
  931. VOID
  932. SpOemInfError(
  933. IN ULONG ErrorScreenId,
  934. IN ULONG SubErrorId,
  935. IN PWSTR SectionName,
  936. IN ULONG LineNumber,
  937. IN PWSTR Description
  938. )
  939. {
  940. WCHAR SubError[512];
  941. //
  942. // Line numbers are 0-based. Want to display to user as 1-based.
  943. //
  944. LineNumber++;
  945. //
  946. // Fetch/format the suberror.
  947. //
  948. SpFormatMessage(SubError,sizeof(SubError),SubErrorId,SectionName,LineNumber,Description);
  949. //
  950. // Display the error screen.
  951. //
  952. SpStartScreen(
  953. ErrorScreenId,
  954. 3,
  955. HEADER_HEIGHT+1,
  956. FALSE,
  957. FALSE,
  958. DEFAULT_ATTRIBUTE,
  959. SubError
  960. );
  961. if( !PreInstall ) {
  962. //
  963. // Display status options: enter to continue.
  964. //
  965. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,SP_STAT_ENTER_EQUALS_CONTINUE,0);
  966. //
  967. // Wait for the user to press enter.
  968. //
  969. SpInputDrain();
  970. while(SpInputGetKeypress() != ASCI_CR) ;
  971. } else {
  972. //
  973. // If this is an OEM pre-install then treat the error as a fatal one.
  974. // Display status options: F3 to exit.
  975. //
  976. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,SP_STAT_F3_EQUALS_EXIT,0);
  977. //
  978. // Wait for the user to press enter.
  979. //
  980. SpInputDrain();
  981. while(SpInputGetKeypress() != KEY_F3) ;
  982. SpDone(0,FALSE,TRUE);
  983. }
  984. }
  985. BOOLEAN
  986. SpOemDiskette(
  987. IN PVOID SifHandle,
  988. IN PWSTR SectionName,
  989. IN ULONG SelectOemHwScreenId,
  990. IN ULONG AllowedFileTypes,
  991. IN ULONG RequiredFileTypes,
  992. IN OUT PHARDWARE_COMPONENT HwComp,
  993. IN ULONG ErrorId
  994. )
  995. {
  996. PWSTR szDiskName;
  997. BOOLEAN b;
  998. ULONG ErrorLine;
  999. NTSTATUS Status;
  1000. PVOID TxtsetupOem;
  1001. ULONG Count;
  1002. ULONG Line;
  1003. ULONG_PTR DefaultSelection,Selection;
  1004. PWSTR DefSelId;
  1005. PVOID Menu;
  1006. ULONG MenuTopY,MenuHeight,MenuWidth;
  1007. BOOLEAN rc;
  1008. ULONG ValidKeys[3] = { ASCI_CR, ASCI_ESC, 0 };
  1009. ULONG Key;
  1010. PWSTR szDefaults = TXTSETUP_OEM_DEFAULTS_U;
  1011. PWSTR szDevicePath = 0;
  1012. //
  1013. // Assume failure.
  1014. //
  1015. rc = FALSE;
  1016. //
  1017. // Always want to prompt for the disk in A:.
  1018. // First, make sure there is an A:!
  1019. //
  1020. if(SpGetFloppyDriveType(0) == FloppyTypeNone) {
  1021. SpDisplayScreen(SP_SCRN_NO_FLOPPY_FOR_OEM_DISK,3,HEADER_HEIGHT+1);
  1022. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,SP_STAT_ENTER_EQUALS_CONTINUE,0);
  1023. SpInputDrain();
  1024. while(SpInputGetKeypress() != ASCI_CR) ;
  1025. goto sod0;
  1026. }
  1027. //
  1028. // Fetch the generic oem disk name.
  1029. //
  1030. SpFormatMessage(TemporaryBuffer,sizeof(TemporaryBuffer),SP_TEXT_OEM_DISK_NAME);
  1031. szDiskName = SpDupStringW(TemporaryBuffer);
  1032. //
  1033. // Prompt for the disk -- ignore what may be in the drive already,
  1034. // and allow escape.
  1035. //
  1036. szDevicePath = SpDupStringW(L"\\device\\floppy0");
  1037. if (szDevicePath) {
  1038. b = SpPromptForDisk(
  1039. szDiskName,
  1040. szDevicePath,
  1041. TXTSETUP_OEM_FILENAME_U,
  1042. TRUE,
  1043. TRUE,
  1044. FALSE,
  1045. NULL
  1046. );
  1047. SpMemFree(szDevicePath);
  1048. } else {
  1049. b = FALSE;
  1050. }
  1051. SpMemFree(szDiskName);
  1052. //
  1053. // If the user pressed escape at the disk prompt, bail out now.
  1054. //
  1055. if(!b) {
  1056. goto sod0;
  1057. }
  1058. //
  1059. // Load txtsetup.oem.
  1060. //
  1061. HandleLineContinueChars = FALSE;
  1062. Status = SpLoadSetupTextFile(
  1063. L"\\device\\floppy0\\" TXTSETUP_OEM_FILENAME_U,
  1064. NULL,
  1065. 0,
  1066. &TxtsetupOem,
  1067. &ErrorLine,
  1068. TRUE,
  1069. FALSE
  1070. );
  1071. HandleLineContinueChars = TRUE;
  1072. if(!NT_SUCCESS(Status)) {
  1073. if(Status == STATUS_UNSUCCESSFUL) {
  1074. SpOemInfError(ErrorId,SP_TEXT_OEM_INF_ERROR_A,NULL,ErrorLine,NULL);
  1075. } else {
  1076. SpOemInfError(ErrorId,SP_TEXT_OEM_INF_ERROR_0,NULL,0,NULL);
  1077. }
  1078. goto sod0;
  1079. }
  1080. //
  1081. // Determine if this inf file is relevent to the device class the user
  1082. // is selecting. If there is a section called 'display' 'keyboard' etc
  1083. // as appropriate for DeviceClass, then we're in business.
  1084. //
  1085. Count = SpCountLinesInSection(TxtsetupOem,SectionName);
  1086. if(!Count) {
  1087. SpOemInfError(ErrorId,SP_TEXT_OEM_INF_ERROR_1,SectionName,0,NULL);
  1088. goto sod1;
  1089. }
  1090. //
  1091. // Get the id of the default choice.
  1092. //
  1093. DefaultSelection = 0;
  1094. DefSelId = SpGetSectionKeyIndex(TxtsetupOem,szDefaults,SectionName,OINDEX_DEFAULT);
  1095. if(DefSelId == NULL) {
  1096. DefSelId = L"";
  1097. }
  1098. //
  1099. // Display the prompt screen, calculate where the menu goes,
  1100. // and create a menu.
  1101. //
  1102. SpDisplayScreen(SelectOemHwScreenId,5,HEADER_HEIGHT+1);
  1103. MenuTopY = NextMessageTopLine + 2;
  1104. MenuHeight = VideoVars.ScreenHeight - MenuTopY - 3;
  1105. MenuWidth = VideoVars.ScreenWidth - 6;
  1106. Menu = SpMnCreate(3,MenuTopY,MenuWidth,MenuHeight);
  1107. //
  1108. // Build a menu from the choices in the oem inf file section.
  1109. //
  1110. for(Line=0; Line<Count; Line++) {
  1111. PWSTR p,Descr;
  1112. Descr = SpGetSectionLineIndex(TxtsetupOem,SectionName,Line,OINDEX_DESCRIPTION);
  1113. if(Descr == NULL) {
  1114. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpOemDiskette: no description on line %u in [%ws]",Line,SectionName));
  1115. SpOemInfError(ErrorId,SP_TEXT_OEM_INF_ERROR_2,SectionName,Line,NULL);
  1116. goto sod2;
  1117. }
  1118. SpMnAddItem(Menu,Descr,3,MenuWidth,TRUE,Line);
  1119. // determine if this is the default selection.
  1120. if(p = SpGetKeyName(TxtsetupOem,SectionName,Line)) {
  1121. if(!_wcsicmp(p,DefSelId)) {
  1122. DefaultSelection = Line;
  1123. }
  1124. } else {
  1125. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpOemDiskette: no key on line %u of section %ws",Line,SectionName));
  1126. SpOemInfError(ErrorId,SP_TEXT_OEM_INF_ERROR_2,SectionName,Line,NULL);
  1127. goto sod2;
  1128. }
  1129. }
  1130. //
  1131. // Display options in status bar: enter = select, escape = cancel.
  1132. //
  1133. SpDisplayStatusOptions(
  1134. DEFAULT_STATUS_ATTRIBUTE,
  1135. SP_STAT_ENTER_EQUALS_SELECT,
  1136. SP_STAT_ESC_EQUALS_CANCEL,
  1137. 0
  1138. );
  1139. //
  1140. // Display the menu and await a selection.
  1141. //
  1142. SpMnDisplay(Menu,
  1143. DefaultSelection,
  1144. TRUE,
  1145. ValidKeys,
  1146. NULL,
  1147. NULL,
  1148. NULL,
  1149. &Key,
  1150. &Selection);
  1151. if(Key == ASCI_CR) {
  1152. PWSTR Id = SpGetKeyName(TxtsetupOem,SectionName,(ULONG)Selection);
  1153. PWSTR p;
  1154. //
  1155. // We already checked this once for non-null (above).
  1156. //
  1157. ASSERT(Id);
  1158. rc = SpOemInfSelection(
  1159. TxtsetupOem,
  1160. SectionName,
  1161. Id,
  1162. p = SpMnGetTextDup(Menu,Selection),
  1163. AllowedFileTypes,
  1164. RequiredFileTypes,
  1165. HwComp,
  1166. ErrorId
  1167. );
  1168. SpMemFree(p);
  1169. } else {
  1170. ASSERT(Key == ASCI_ESC);
  1171. // just fall through and return false.
  1172. }
  1173. sod2:
  1174. SpMnDestroy(Menu);
  1175. sod1:
  1176. SpFreeTextFile(TxtsetupOem);
  1177. sod0:
  1178. return(rc);
  1179. }
  1180. BOOLEAN
  1181. SpOemInfSelection(
  1182. IN PVOID TxtsetupOem,
  1183. IN PWSTR NonlocalizedComponentName,
  1184. IN PWSTR SelectedId,
  1185. IN PWSTR ItemDescription,
  1186. IN ULONG AllowedFileTypes,
  1187. IN ULONG RequiredFileTypes,
  1188. OUT PHARDWARE_COMPONENT HwComp,
  1189. IN ULONG ErrorId
  1190. )
  1191. {
  1192. PWSTR FilesSectionName,ConfigSectionName;
  1193. ULONG Line,Count,Line2,Count2;
  1194. BOOLEAN rc = FALSE;
  1195. PHARDWARE_COMPONENT_FILE FileList = NULL;
  1196. PHARDWARE_COMPONENT_REGISTRY RegList = NULL;
  1197. ULONG FileTypeBits = 0;
  1198. PWSTR szDisks = TXTSETUP_OEM_DISKS_U;
  1199. //
  1200. // Iterate through the files section, remembering info about the
  1201. // files to be copied in support of the selection.
  1202. //
  1203. FilesSectionName = SpMemAlloc(
  1204. ((wcslen(NonlocalizedComponentName)+wcslen(SelectedId)+1)*sizeof(WCHAR))
  1205. + sizeof(L"Files.")
  1206. );
  1207. wcscpy(FilesSectionName,L"Files.");
  1208. wcscat(FilesSectionName,NonlocalizedComponentName);
  1209. wcscat(FilesSectionName,L".");
  1210. wcscat(FilesSectionName,SelectedId);
  1211. Count = SpCountLinesInSection(TxtsetupOem,FilesSectionName);
  1212. if(Count == 0) {
  1213. SpOemInfError(ErrorId,SP_TEXT_OEM_INF_ERROR_3,FilesSectionName,0,NULL);
  1214. goto sod0;
  1215. }
  1216. for(Line=0; Line<Count; Line++) {
  1217. PWSTR Disk,Filename,Filetype,Tagfile,Description,Directory,ConfigName;
  1218. HwFileType filetype;
  1219. PHARDWARE_COMPONENT_FILE FileStruct;
  1220. //
  1221. // Get the disk specification, filename, and filetype from the line.
  1222. //
  1223. Disk = SpGetSectionLineIndex(TxtsetupOem,FilesSectionName,Line,OINDEX_DISKSPEC);
  1224. Filename = SpGetSectionLineIndex(TxtsetupOem,FilesSectionName,Line,OINDEX_FILENAME);
  1225. Filetype = SpGetKeyName(TxtsetupOem,FilesSectionName,Line);
  1226. if(!Disk || !Filename || !Filetype) {
  1227. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1228. "SETUP: SpOemInfSelection: Disk=%ws, Filename=%ws, Filetype=%ws",
  1229. Disk ? Disk : L"(null)",
  1230. Filename ? Filename : L"(null)",
  1231. Filetype ? Filetype : L"(null)"
  1232. ));
  1233. SpOemInfError(ErrorId,SP_TEXT_OEM_INF_ERROR_2,FilesSectionName,Line,NULL);
  1234. SpFreeHwComponentFile(&FileList);
  1235. goto sod0;
  1236. }
  1237. //
  1238. // Parse the filetype.
  1239. //
  1240. filetype = SpFindStringInTable(FileTypeNames,Filetype);
  1241. if(filetype == HwFileMax) {
  1242. SpOemInfError(ErrorId,SP_TEXT_OEM_INF_ERROR_4,FilesSectionName,Line,NULL);
  1243. SpFreeHwComponentFile(&FileList);
  1244. goto sod0;
  1245. }
  1246. //
  1247. // Fetch the name of the section containing configuration information.
  1248. // Required if file is of type port, class, or driver.
  1249. //
  1250. if((filetype == HwFilePort) || (filetype == HwFileClass) || (filetype == HwFileDriver)) {
  1251. ConfigName = SpGetSectionLineIndex(TxtsetupOem,FilesSectionName,Line,OINDEX_CONFIGNAME);
  1252. if(ConfigName == NULL) {
  1253. SpOemInfError(ErrorId,SP_TEXT_OEM_INF_ERROR_8,FilesSectionName,Line,NULL);
  1254. SpFreeHwComponentFile(&FileList);
  1255. goto sod0;
  1256. }
  1257. } else {
  1258. ConfigName = NULL;
  1259. }
  1260. //
  1261. // Using the disk specification, look up the tagfile, description,
  1262. // and directory for the disk.
  1263. //
  1264. Tagfile = SpGetSectionKeyIndex(TxtsetupOem,szDisks,Disk,OINDEX_TAGFILE);
  1265. Description = SpGetSectionKeyIndex(TxtsetupOem,szDisks,Disk,OINDEX_DISKDESCR);
  1266. Directory = SpGetSectionKeyIndex(TxtsetupOem,szDisks,Disk,OINDEX_DIRECTORY);
  1267. if((Directory == NULL) || !wcscmp(Directory,L"\\")) {
  1268. Directory = L"";
  1269. }
  1270. if(!Tagfile || !Description) {
  1271. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1272. "SETUP: SpOemInfSelection: Tagfile=%ws, Description=%ws",
  1273. Tagfile ? Tagfile : L"(null)",
  1274. Description ? Description : L"(null)"
  1275. ));
  1276. SpOemInfError(ErrorId,SP_TEXT_OEM_INF_ERROR_5,FilesSectionName,Line,NULL);
  1277. SpFreeHwComponentFile(&FileList);
  1278. goto sod0;
  1279. }
  1280. FileStruct = SpMemAlloc(sizeof(HARDWARE_COMPONENT_FILE));
  1281. RtlZeroMemory(FileStruct,sizeof(HARDWARE_COMPONENT_FILE));
  1282. SpInitHwComponentFile(
  1283. FileStruct,
  1284. Filename,
  1285. filetype,
  1286. ConfigName,
  1287. Description,
  1288. Tagfile,
  1289. Directory,
  1290. NULL
  1291. );
  1292. FileStruct->Next = FileList;
  1293. FileList = FileStruct;
  1294. if((filetype == HwFilePort) || (filetype == HwFileDriver)) {
  1295. SET_FILETYPE_PRESENT(FileTypeBits,HwFilePort);
  1296. SET_FILETYPE_PRESENT(FileTypeBits,HwFileDriver);
  1297. } else {
  1298. SET_FILETYPE_PRESENT(FileTypeBits,filetype);
  1299. }
  1300. //
  1301. // Now go look in the [Config.<ConfigName>] section for registry
  1302. // information that is to be set for this driver file.
  1303. //
  1304. if(ConfigName) {
  1305. ConfigSectionName = SpMemAlloc((wcslen(ConfigName)*sizeof(WCHAR)) + sizeof(L"Config."));
  1306. wcscpy(ConfigSectionName,L"Config.");
  1307. wcscat(ConfigSectionName,ConfigName);
  1308. Count2 = SpCountLinesInSection(TxtsetupOem,ConfigSectionName);
  1309. for(Line2=0; Line2<Count2; Line2++) {
  1310. PWSTR KeyName,ValueName,ValueType;
  1311. PHARDWARE_COMPONENT_REGISTRY Reg;
  1312. HwRegistryType valuetype;
  1313. //
  1314. // Fetch KeyName, ValueName, and ValueType from the line.
  1315. //
  1316. KeyName = SpGetSectionLineIndex(TxtsetupOem,ConfigSectionName,Line2,OINDEX_KEYNAME);
  1317. ValueName = SpGetSectionLineIndex(TxtsetupOem,ConfigSectionName,Line2,OINDEX_VALUENAME);
  1318. ValueType = SpGetSectionLineIndex(TxtsetupOem,ConfigSectionName,Line2,OINDEX_VALUETYPE);
  1319. if(!KeyName || !ValueName || !ValueType) {
  1320. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1321. "SETUP: SpOemInfSelection: KeyName=%ws, ValueName=%ws, ValueType=%ws",
  1322. KeyName ? KeyName : L"(null)",
  1323. ValueName ? ValueName : L"(null)",
  1324. ValueType ? ValueType : L"(null)"
  1325. ));
  1326. SpOemInfError(ErrorId,SP_TEXT_OEM_INF_ERROR_2,ConfigSectionName,Line2,NULL);
  1327. SpFreeHwComponentReg(&RegList);
  1328. SpFreeHwComponentFile(&FileList);
  1329. goto sod0;
  1330. }
  1331. //
  1332. // Parse the value type and associated values.
  1333. //
  1334. valuetype = SpFindStringInTable(RegistryTypeNames,ValueType);
  1335. if(valuetype == HwRegistryMax) {
  1336. SpOemInfError(ErrorId,SP_TEXT_OEM_INF_ERROR_6,ConfigSectionName,Line2,NULL);
  1337. SpFreeHwComponentFile(&FileList);
  1338. SpFreeHwComponentReg(&RegList);
  1339. goto sod0;
  1340. }
  1341. valuetype = RegistryValueTypeMap[valuetype];
  1342. Reg = SpInterpretOemRegistryData(
  1343. TxtsetupOem,
  1344. ConfigSectionName,
  1345. Line2,
  1346. valuetype,
  1347. KeyName,
  1348. ValueName
  1349. );
  1350. if(Reg) {
  1351. Reg->Next = RegList;
  1352. RegList = Reg;
  1353. } else {
  1354. SpOemInfError(ErrorId,SP_TEXT_OEM_INF_ERROR_7,ConfigSectionName,Line2,NULL);
  1355. SpFreeHwComponentReg(&RegList);
  1356. SpFreeHwComponentFile(&FileList);
  1357. goto sod0;
  1358. }
  1359. }
  1360. FileStruct->RegistryValueList = RegList;
  1361. RegList = NULL;
  1362. SpMemFree(ConfigSectionName);
  1363. }
  1364. }
  1365. //
  1366. // Check to see whether only files of the allowed types for this component
  1367. // have been specified.
  1368. //
  1369. if((AllowedFileTypes | FileTypeBits) != AllowedFileTypes) {
  1370. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SppOemInfSelection: allowed files: %lx, what we've got: %lx",AllowedFileTypes,FileTypeBits));
  1371. SpOemInfError(ErrorId,SP_TEXT_OEM_INF_ERROR_9,FilesSectionName,0,NULL);
  1372. SpFreeHwComponentFile(&FileList);
  1373. goto sod0;
  1374. }
  1375. //
  1376. // Check to see whether files were specified for each required type.
  1377. //
  1378. if((RequiredFileTypes & FileTypeBits) != RequiredFileTypes) {
  1379. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SppOemInfSelection: required files: %lx, what we've got: %lx",RequiredFileTypes,FileTypeBits));
  1380. SpOemInfError(ErrorId,SP_TEXT_OEM_INF_ERROR_9,FilesSectionName,0,NULL);
  1381. SpFreeHwComponentFile(&FileList);
  1382. goto sod0;
  1383. }
  1384. //
  1385. // Everything is OK so we can place the information we have gathered
  1386. // into the main structure for the device class.
  1387. //
  1388. SpFreeHwComponentFile(&HwComp->Files);
  1389. SpInitHwComponent(HwComp,SelectedId,ItemDescription,TRUE,FileTypeBits,NULL,FALSE);
  1390. HwComp->Files = FileList;
  1391. rc = TRUE;
  1392. //
  1393. // Clean up and exit.
  1394. //
  1395. sod0:
  1396. SpMemFree(FilesSectionName);
  1397. return(rc);
  1398. }
  1399. VOID
  1400. SpDetectComputer(
  1401. IN PVOID SifHandle
  1402. )
  1403. {
  1404. PHARDWARE_COMPONENT pHw = HardwareComponents[HwComponentComputer];
  1405. PWSTR Description;
  1406. //
  1407. // Setupldr *must* have given us this information.
  1408. //
  1409. ASSERT(pHw);
  1410. ASSERT(pHw->Next == NULL);
  1411. //
  1412. // If the computer is a third-aprty type, the desscription
  1413. // should already be there.
  1414. //
  1415. if(pHw->ThirdPartyOptionSelected) {
  1416. ASSERT(pHw->Description);
  1417. } else {
  1418. //
  1419. // Description might already be there if the user chose
  1420. // a type we support, during setupldr phase.
  1421. //
  1422. if(pHw->Description) {
  1423. SpMemFree(pHw->Description);
  1424. }
  1425. //
  1426. // Look up the description.
  1427. //
  1428. Description = SpGetSectionKeyIndex(
  1429. SifHandle,
  1430. NonlocalizedComponentNames[HwComponentComputer],
  1431. pHw->IdString,
  1432. INDEX_DESCRIPTION
  1433. );
  1434. if(!Description) {
  1435. SpFatalSifError(
  1436. SifHandle,
  1437. NonlocalizedComponentNames[HwComponentComputer],
  1438. pHw->IdString,
  1439. 0,
  1440. INDEX_DESCRIPTION
  1441. );
  1442. }
  1443. pHw->Description = SpDupStringW(Description);
  1444. }
  1445. }
  1446. VOID
  1447. SpDetectVideo(
  1448. IN PVOID SifHandle
  1449. )
  1450. {
  1451. PHARDWARE_COMPONENT VideoDevice;
  1452. VideoDevice = HardwareComponents[HwComponentDisplay];
  1453. //
  1454. // Just use what setupldr detected but we'll have to go
  1455. // fetch the description for non-oem video types.
  1456. //
  1457. if(!VideoDevice->ThirdPartyOptionSelected && !VideoDevice->Description) {
  1458. VideoDevice->Description = SpGetSectionKeyIndex(
  1459. SifHandle,
  1460. NonlocalizedComponentNames[HwComponentDisplay],
  1461. VideoDevice->IdString,
  1462. INDEX_DESCRIPTION
  1463. );
  1464. if(VideoDevice->Description) {
  1465. VideoDevice->Description = SpDupStringW(VideoDevice->Description);
  1466. } else {
  1467. SpFatalSifError(
  1468. SifHandle,
  1469. NonlocalizedComponentNames[HwComponentDisplay],
  1470. VideoDevice->IdString,
  1471. 0,
  1472. INDEX_DESCRIPTION
  1473. );
  1474. }
  1475. }
  1476. //
  1477. // There should be only one video device.
  1478. //
  1479. ASSERT(VideoDevice->Next == NULL);
  1480. }
  1481. VOID
  1482. SpDetectKeyboard(
  1483. IN PVOID SifHandle
  1484. )
  1485. {
  1486. #if 0
  1487. PHARDWARE_COMPONENT KeyboardDevice;
  1488. KeyboardDevice = HardwareComponents[HwComponentKeyboard];
  1489. //
  1490. // If setupldr did any keyboard detection, ignore it
  1491. // unless it's a third-party option.
  1492. //
  1493. if(KeyboardDevice && KeyboardDevice->ThirdPartyOptionSelected) {
  1494. //
  1495. // There should be only one keyboard device.
  1496. //
  1497. ASSERT(KeyboardDevice->Next == NULL);
  1498. } else {
  1499. //
  1500. // Free the keyboard device if there is one.
  1501. //
  1502. if(KeyboardDevice) {
  1503. SpFreeHwComponent(&KeyboardDevice,TRUE);
  1504. }
  1505. KeyboardDevice = SpMemAlloc(sizeof(HARDWARE_COMPONENT));
  1506. RtlZeroMemory(KeyboardDevice,sizeof(HARDWARE_COMPONENT));
  1507. SpDetermineComponent(
  1508. SifHandle,
  1509. KeyboardDevice,
  1510. L"KeyboardPeripheral",
  1511. NULL,
  1512. L"Keyboard"
  1513. );
  1514. HardwareComponents[HwComponentKeyboard] = KeyboardDevice;
  1515. }
  1516. #endif
  1517. PHARDWARE_COMPONENT KeyboardDevice, p;
  1518. PWSTR ComponentName;
  1519. PWSTR Key;
  1520. PWSTR Description;
  1521. #if 0
  1522. for( KeyboardDevice = HardwareComponents[HwComponentKeyboard];
  1523. KeyboardDevice != NULL;
  1524. KeyboardDevice = KeyboardDevice->Next ) {
  1525. //
  1526. // Free the keyboard device if there is one.
  1527. //
  1528. if(KeyboardDevice) {
  1529. SpFreeHwComponent(&KeyboardDevice,TRUE);
  1530. }
  1531. }
  1532. #endif
  1533. KeyboardDevice = HardwareComponents[HwComponentKeyboard];
  1534. //
  1535. // Free the keyboard device if there is one.
  1536. //
  1537. if(KeyboardDevice) {
  1538. SpFreeHwComponent(&KeyboardDevice,TRUE);
  1539. }
  1540. ComponentName = NonlocalizedComponentNames[HwComponentKeyboard];
  1541. KeyboardDevice = NULL;
  1542. p = NULL;
  1543. if( UsbKeyboardDetected ) {
  1544. Key = SpDupStringW( L"kbdhid" );
  1545. if (Key) {
  1546. Description = SpGetSectionKeyIndex(SifHandle,ComponentName,Key,INDEX_DESCRIPTION);
  1547. } else {
  1548. Description = NULL;
  1549. Key = L"kbdhid";
  1550. }
  1551. if(!Description) {
  1552. SpFatalSifError(SifHandle,ComponentName,Key,0,INDEX_DESCRIPTION);
  1553. }
  1554. p = SpMemAlloc(sizeof(HARDWARE_COMPONENT));
  1555. RtlZeroMemory(p,sizeof(HARDWARE_COMPONENT));
  1556. SpInitHwComponent(p,Key,Description,FALSE,0,NULL,FALSE);
  1557. KeyboardDevice = p;
  1558. }
  1559. else if (StdKeyboardDetected) {
  1560. Key = SpDupStringW( L"STANDARD" );
  1561. if (Key) {
  1562. Description = SpGetSectionKeyIndex(SifHandle,ComponentName,Key,INDEX_DESCRIPTION);
  1563. } else {
  1564. Description = NULL;
  1565. Key = L"STANDARD";
  1566. }
  1567. if(!Description) {
  1568. SpFatalSifError(SifHandle,ComponentName,Key,0,INDEX_DESCRIPTION);
  1569. }
  1570. p = SpMemAlloc(sizeof(HARDWARE_COMPONENT));
  1571. RtlZeroMemory(p,sizeof(HARDWARE_COMPONENT));
  1572. SpInitHwComponent(p,Key,Description,FALSE,0,NULL,FALSE);
  1573. KeyboardDevice = p;
  1574. } else {
  1575. p = SpMemAlloc(sizeof(HARDWARE_COMPONENT));
  1576. if (p) {
  1577. RtlZeroMemory(p,sizeof(HARDWARE_COMPONENT));
  1578. SpDetermineComponent(
  1579. SifHandle,
  1580. p,
  1581. L"KeyboardPeripheral",
  1582. L"NO KEYBOARD",
  1583. L"Keyboard"
  1584. );
  1585. KeyboardDevice = p;
  1586. }
  1587. }
  1588. ASSERT(KeyboardDevice);
  1589. HardwareComponents[HwComponentKeyboard] = KeyboardDevice;
  1590. }
  1591. VOID
  1592. SpDetectLayout(
  1593. IN PVOID SifHandle
  1594. )
  1595. {
  1596. PHARDWARE_COMPONENT KeyboardLayout;
  1597. PWSTR IdString,Description;
  1598. KeyboardLayout = HardwareComponents[HwComponentLayout];
  1599. //
  1600. // Setupldr never chooses a layout.
  1601. //
  1602. ASSERT(KeyboardLayout == NULL);
  1603. KeyboardLayout = SpMemAlloc(sizeof(HARDWARE_COMPONENT));
  1604. RtlZeroMemory(KeyboardLayout,sizeof(HARDWARE_COMPONENT));
  1605. HardwareComponents[HwComponentLayout] = KeyboardLayout;
  1606. //
  1607. // Look up the default layout in the setup information file.
  1608. //
  1609. IdString = SpGetSectionKeyIndex(SifHandle,SIF_NLS,SIF_DEFAULTLAYOUT,0);
  1610. if(!IdString) {
  1611. SpFatalSifError(SifHandle,SIF_NLS,SIF_DEFAULTLAYOUT,0,0);
  1612. }
  1613. Description = SpGetSectionKeyIndex(
  1614. SifHandle,
  1615. NonlocalizedComponentNames[HwComponentLayout],
  1616. IdString,
  1617. INDEX_DESCRIPTION
  1618. );
  1619. if(!Description) {
  1620. SpFatalSifError(
  1621. SifHandle,
  1622. NonlocalizedComponentNames[HwComponentLayout],
  1623. IdString,
  1624. 0,
  1625. INDEX_DESCRIPTION
  1626. );
  1627. }
  1628. //
  1629. // Initialize the hardware component strucutre for the layout.
  1630. //
  1631. SpInitHwComponent(KeyboardLayout,IdString,Description,FALSE,0,NULL,FALSE);
  1632. }
  1633. VOID
  1634. SpDetectMouse(
  1635. IN PVOID SifHandle
  1636. )
  1637. {
  1638. #if 0
  1639. PHARDWARE_COMPONENT MouseDevice;
  1640. //
  1641. // Setupldr does not do any mouse detection.
  1642. //
  1643. ASSERT(HardwareComponents[HwComponentMouse] == NULL);
  1644. MouseDevice = SpMemAlloc(sizeof(HARDWARE_COMPONENT));
  1645. RtlZeroMemory(MouseDevice,sizeof(HARDWARE_COMPONENT));
  1646. SpDetermineComponent(
  1647. SifHandle,
  1648. MouseDevice,
  1649. L"PointerPeripheral",
  1650. L"NO MOUSE",
  1651. L"Mouse"
  1652. );
  1653. HardwareComponents[HwComponentMouse] = MouseDevice;
  1654. #endif
  1655. PHARDWARE_COMPONENT MouseDevice, p;
  1656. PWSTR ComponentName;
  1657. PWSTR Key;
  1658. PWSTR Description;
  1659. ComponentName = NonlocalizedComponentNames[HwComponentMouse];
  1660. MouseDevice = NULL;
  1661. p = NULL;
  1662. //
  1663. // If a mouse was detected (through pnp), then add the mouse to the list
  1664. //
  1665. // none = "No Mouse or Other Pointing Device",files.none,""
  1666. // mouhid = "USB Mouse",files.mouhid,mouhid
  1667. // msser = "Microsoft Serial Mouse",files.sermouse,sermouse
  1668. // ps2 = "Mouse Port Mouse",files.i8042,i8042prt
  1669. // sermouse = "Serial Mouse",files.sermouse,sermouse
  1670. //
  1671. if( UsbMouseDetected ) {
  1672. Key = SpDupStringW( L"mouhid" );
  1673. if (Key) {
  1674. Description = SpGetSectionKeyIndex(SifHandle,ComponentName,Key,INDEX_DESCRIPTION);
  1675. } else {
  1676. Description = NULL;
  1677. Key = L"mouhid";
  1678. }
  1679. if(!Description) {
  1680. SpFatalSifError(SifHandle,ComponentName,Key,0,INDEX_DESCRIPTION);
  1681. }
  1682. p = SpMemAlloc(sizeof(HARDWARE_COMPONENT));
  1683. RtlZeroMemory(p,sizeof(HARDWARE_COMPONENT));
  1684. SpInitHwComponent(p,Key,Description,FALSE,0,NULL,FALSE);
  1685. MouseDevice = p;
  1686. } else if( SerMouseDetected ) {
  1687. Key = SpDupStringW( L"msser" );
  1688. if (Key) {
  1689. Description = SpGetSectionKeyIndex(SifHandle,ComponentName,Key,INDEX_DESCRIPTION);
  1690. } else {
  1691. Description = NULL;
  1692. Key = L"msser";
  1693. }
  1694. if(!Description) {
  1695. SpFatalSifError(SifHandle,ComponentName,Key,0,INDEX_DESCRIPTION);
  1696. }
  1697. p = SpMemAlloc(sizeof(HARDWARE_COMPONENT));
  1698. RtlZeroMemory(p,sizeof(HARDWARE_COMPONENT));
  1699. SpInitHwComponent(p,Key,Description,FALSE,0,NULL,FALSE);
  1700. p->Next = MouseDevice;
  1701. MouseDevice = p;
  1702. }
  1703. #if defined(_AMD64_) || defined(_IA64_)
  1704. else if( PS2MouseDetected ) {
  1705. Key = SpDupStringW( L"ps2" );
  1706. if (Key) {
  1707. Description = SpGetSectionKeyIndex(SifHandle,ComponentName,Key,INDEX_DESCRIPTION);
  1708. } else {
  1709. Description = NULL;
  1710. Key = L"ps2";
  1711. }
  1712. if(!Description) {
  1713. SpFatalSifError(SifHandle,ComponentName,Key,0,INDEX_DESCRIPTION);
  1714. }
  1715. p = SpMemAlloc(sizeof(HARDWARE_COMPONENT));
  1716. RtlZeroMemory(p,sizeof(HARDWARE_COMPONENT));
  1717. SpInitHwComponent(p,Key,Description,FALSE,0,NULL,FALSE);
  1718. p->Next = MouseDevice;
  1719. MouseDevice = p;
  1720. }
  1721. else
  1722. #endif // defined(_AMD64_) || defined (_IA64_)
  1723. {
  1724. //
  1725. // Now look for a mouse detected by NTDETECT.
  1726. //
  1727. p = SpMemAlloc(sizeof(HARDWARE_COMPONENT));
  1728. RtlZeroMemory(p,sizeof(HARDWARE_COMPONENT));
  1729. SpDetermineComponent(
  1730. SifHandle,
  1731. p,
  1732. L"PointerPeripheral",
  1733. L"NO MOUSE",
  1734. L"Mouse"
  1735. );
  1736. if( MouseDevice == NULL ) {
  1737. //
  1738. // If we did not any mice through pnp, then add whatever we found through NTDETECT
  1739. // (even "No Mouse"), to the mice list.
  1740. //
  1741. MouseDevice = p;
  1742. } else {
  1743. //
  1744. // Add the mouse detected through NTDETECT, if any
  1745. //
  1746. if( _wcsicmp( p->IdString, L"none" ) != 0 ) {
  1747. p->Next = MouseDevice;
  1748. MouseDevice = p;
  1749. }
  1750. }
  1751. }
  1752. ASSERT(MouseDevice);
  1753. HardwareComponents[HwComponentMouse] = MouseDevice;
  1754. }
  1755. VOID
  1756. SpDetermineComponent(
  1757. IN PVOID SifHandle,
  1758. OUT PHARDWARE_COMPONENT HwComp,
  1759. IN PWSTR HardwareDescriptionKeyName,
  1760. IN PWSTR FallbackIdentifier,
  1761. IN PWSTR ComponentName
  1762. )
  1763. /*++
  1764. Routine Description:
  1765. Make an initial determination about the type of a hardware component
  1766. (ie, perform a hardware 'detection').
  1767. The detection is performed by scanning the hardware configuration tree
  1768. for a key representing a particular hardware component, and attempting
  1769. to match its identifier string with a set of known identifier strings
  1770. (stored in the setup information file).
  1771. Arguments:
  1772. SifHandle - supplies handle for main setup information file.
  1773. HwComp - a hardware component structure that is filled in with information
  1774. about the component we find.
  1775. HardwareDescriptionKeyName - supplies the name of the key in the hardware
  1776. description (ie, the firmware configuration tree).
  1777. FallbackIdentifier - supplies the id string to use if we cannot detect
  1778. the hardware type for the component. For example, if we can't find
  1779. a PointerPeripheral (mouse), this might be "NO MOUSE."
  1780. ComponentName - supplies name of the component. This name is not translated.
  1781. Return Value:
  1782. TRUE if a match was found, FALSE otherwise.
  1783. --*/
  1784. {
  1785. PWSTR IdString;
  1786. //
  1787. // Scan the firmware configuration tree.
  1788. //
  1789. SpScanHardwareDescription(HardwareDescriptionKeyName);
  1790. if (IdStringCount && (0 == _wcsicmp(HardwareDescriptionKeyName, L"PointerPeripheral"))) {
  1791. //
  1792. // Skip the Microsoft Bus Mouse device
  1793. //
  1794. ULONG Index;
  1795. for (Index = 0; Index < IdStringCount; Index++) {
  1796. if (IdStringArray[Index] && _wcsicmp(IdStringArray[Index], MICROSOFT_BUS_MOUSE_NAME)) {
  1797. if (Index) {
  1798. PWSTR FirstId = IdStringArray[0];
  1799. IdStringArray[0] = IdStringArray[Index];
  1800. IdStringArray[Index] = FirstId;
  1801. }
  1802. break;
  1803. }
  1804. }
  1805. if (Index >= IdStringCount) {
  1806. IdStringCount = 0;
  1807. }
  1808. }
  1809. //
  1810. // Pick off the first identifier found. If no such node
  1811. // was found, then use the fallback identifier.
  1812. //
  1813. IdString = IdStringCount ? IdStringArray[0] : FallbackIdentifier;
  1814. //
  1815. // Now go scan the map section in the sif file to see whether we
  1816. // recognize the hardware described by this particular id string.
  1817. //
  1818. SpScanMapSection(SifHandle,HwComp,ComponentName,IdString);
  1819. SpFreeLocatedIdStrings();
  1820. }
  1821. BOOLEAN
  1822. SpScanMapSection(
  1823. IN PVOID SifHandle,
  1824. OUT PHARDWARE_COMPONENT HwComp,
  1825. IN PWSTR ComponentName,
  1826. IN PWSTR IdString
  1827. )
  1828. /*++
  1829. Routine Description:
  1830. Scan a 'map' section in the main sif file. A 'map' section is used to
  1831. map values seen as id strings in the firmware configuration tree t0
  1832. 'shortnames' -- ie, key values that represent a particular component type.
  1833. A map section has the form, for example,
  1834. [Map.Display]
  1835. g300 = *G300
  1836. g364 = *G364
  1837. vxl = *VXL
  1838. where the values on the RHS represent possible values for the DisplayController
  1839. node in the hardware description. The values on the LHS are the keys to be used
  1840. throughout the rest of setup to represent the type of video present in the machine.
  1841. If an entry starts with a * then it need only appear as a substring of the
  1842. id string found in the firmware configuration tree; otherwise the entry and
  1843. the id string must match exactly.
  1844. There is then a section like
  1845. [Display]
  1846. g300 = "Integrated Video Controller (G300)",...
  1847. g364 = "Integrated Video Controller (G364)",...
  1848. vxl = "Integrated Jaguar Video",...
  1849. that gives additional information about the video type, like a description, etc.
  1850. This routine scans the map section for a match of a given id string found in
  1851. the firmware tree, looks up additional information about the component if a match
  1852. is found, and fills in a hardware component structure.
  1853. Arguments:
  1854. SifHandle - supplies handle for main setup information file.
  1855. HwComp - a hardware component structure that is filled in with information
  1856. about the component we find, if a match is found.
  1857. ComponentName - supplies name of the component. This name is not translated.
  1858. IdString - supplies the id string located in a key in the
  1859. firmware configuration tree.
  1860. Return Value:
  1861. TRUE if a match was found, FALSE otherwise.
  1862. --*/
  1863. {
  1864. PWSTR MapSectionName;
  1865. ULONG LineCount;
  1866. ULONG Line;
  1867. BOOLEAN b;
  1868. PWSTR Value;
  1869. PWSTR Key,Description;
  1870. if(IdString == NULL) {
  1871. IdString = L"";
  1872. }
  1873. //
  1874. // Form the name of the map section.
  1875. //
  1876. MapSectionName = SpMemAlloc((wcslen(ComponentName)*sizeof(WCHAR)) + sizeof(MAP_SECTION_NAME_PREFIX));
  1877. wcscpy(MapSectionName,MAP_SECTION_NAME_PREFIX);
  1878. wcscat(MapSectionName,ComponentName);
  1879. LineCount = SpCountLinesInSection(SifHandle,MapSectionName);
  1880. if(!LineCount) {
  1881. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Warning: no lines in [%ws]\n",MapSectionName));
  1882. SpMemFree(MapSectionName);
  1883. return(FALSE);
  1884. }
  1885. //
  1886. // We have a section like
  1887. //
  1888. // [Map.Display]
  1889. // vga = "VGA"
  1890. // xga = *XGA
  1891. //
  1892. // We look at each line in the section, seeing if the IdString found in the
  1893. // firmware configuration tree matches the value on the right hand side.
  1894. // If so, then we expect to find a line like, for example
  1895. //
  1896. // [Display]
  1897. // xga = "IBM XGA or XGA2"
  1898. //
  1899. for(Line=0; Line<LineCount; Line++) {
  1900. Value = SpGetSectionLineIndex(SifHandle,MapSectionName,Line,INDEX_MAP_FWID);
  1901. if(!Value) {
  1902. SpFatalSifError(SifHandle,MapSectionName,NULL,Line,INDEX_MAP_FWID);
  1903. return FALSE;
  1904. }
  1905. if(*Value == L'*') {
  1906. b = (BOOLEAN)(wcsstr(IdString,Value+1) != NULL);
  1907. } else {
  1908. b = (BOOLEAN)(wcscmp(IdString,Value) == 0);
  1909. }
  1910. if(b) {
  1911. //
  1912. // We've got a match.
  1913. //
  1914. if((Key = SpGetKeyName(SifHandle,MapSectionName,Line)) == NULL) {
  1915. SpFatalSifError(SifHandle,MapSectionName,NULL,Line,(ULONG)(-1));
  1916. }
  1917. Description = SpGetSectionKeyIndex(SifHandle,ComponentName,Key,INDEX_DESCRIPTION);
  1918. if(!Description) {
  1919. SpFatalSifError(SifHandle,ComponentName,Key,0,INDEX_DESCRIPTION);
  1920. }
  1921. SpInitHwComponent(HwComp,Key,Description,FALSE,0,NULL,FALSE);
  1922. SpMemFree(MapSectionName);
  1923. return(TRUE);
  1924. }
  1925. }
  1926. SpMemFree(MapSectionName);
  1927. return(FALSE);
  1928. }
  1929. VOID
  1930. SpScanHardwareDescription(
  1931. IN PWSTR DesiredKeyName
  1932. )
  1933. /*++
  1934. Routine Description:
  1935. Scan the hardware tree looking for subkeys of a key whose name
  1936. matches a given value.
  1937. Keys in the hardware tree do not match nodes in the arc configuration
  1938. tree exactly. In the arc configuration tree, each node has 3 attributes:
  1939. a class, a type, and a key (not the same as a registry key; an arc key
  1940. is more like an instance number or ordinal). In the TN tree, the instances
  1941. are themselves made subkeys. So something like scsi(0)disk(0)rdisk(0)
  1942. in the arc space ends up looking like
  1943. HKEY_LOCAL_MACHINE
  1944. HARDWARE
  1945. DESCRIPTION
  1946. System
  1947. ScsiAdapter
  1948. 0
  1949. DiskController
  1950. 0
  1951. DiskPeripheral
  1952. 0
  1953. in the nt hardware description tree.
  1954. This is why we need to look for subkeys on a desired node in the arc tree --
  1955. we assume that the subkeys of, say, a PointerPeripheral key in the registry
  1956. are named "0" "1" etc and contain the ARC configuration data and id string.
  1957. Id strings in keys we locate are added to a global table, in the variables
  1958. IdStringCount and IdStringArray. The caller must free these resources by
  1959. calling SpFreeLocatedIdStrings.
  1960. Arguments:
  1961. Return Value:
  1962. --*/
  1963. {
  1964. NTSTATUS Status;
  1965. OBJECT_ATTRIBUTES Obja;
  1966. UNICODE_STRING UnicodeString;
  1967. HANDLE hKey;
  1968. //
  1969. // Initialize some globals that allow us to track identifier strings
  1970. // of devices we have located.
  1971. //
  1972. IdStringCount = 0;
  1973. IdStringArray = SpMemAlloc(0);
  1974. //
  1975. // Open the root of the hardware description tree.
  1976. //
  1977. INIT_OBJA(&Obja,&UnicodeString,L"\\Registry\\Machine\\Hardware\\Description\\System");
  1978. Status = ZwOpenKey(&hKey,KEY_READ,&Obja);
  1979. if(!NT_SUCCESS(Status)) {
  1980. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open hardware description (%lx)\n",Status));
  1981. return;
  1982. }
  1983. //
  1984. // Scan the tree.
  1985. //
  1986. SpScanHardwareDescriptionWorker(hKey,L"System",DesiredKeyName);
  1987. ZwClose(hKey);
  1988. }
  1989. VOID
  1990. SpScanHardwareDescriptionWorker(
  1991. IN HANDLE KeyHandle,
  1992. IN PWSTR KeyName,
  1993. IN PWSTR DesiredKeyName
  1994. )
  1995. /*++
  1996. Routine Description:
  1997. Recursive worker routine used to do a depth-first traveral of a registry
  1998. tree rooted at a given key.
  1999. Arguments:
  2000. KeyHandle - handle for a registry tree.
  2001. KeyName - name of the key for which KeyHandle is an open handle.
  2002. This is one component long -- ie, no path separator characters appear.
  2003. DesiredKeyName - supplies the name of the key we are looking for.
  2004. Return Value:
  2005. --*/
  2006. {
  2007. ULONG SubKeyIndex;
  2008. ULONG ResultLength;
  2009. PKEY_BASIC_INFORMATION KeyInfo;
  2010. PKEY_VALUE_PARTIAL_INFORMATION ValInfo;
  2011. HANDLE hSubkey;
  2012. NTSTATUS Status;
  2013. UNICODE_STRING UnicodeString;
  2014. OBJECT_ATTRIBUTES Obja;
  2015. PWSTR SubkeyName;
  2016. KeyInfo = (PKEY_BASIC_INFORMATION)TemporaryBuffer;
  2017. ValInfo = (PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer;
  2018. //
  2019. // Enumerate all subkeys of the current key.
  2020. //
  2021. for( SubKeyIndex=0;
  2022. NT_SUCCESS(
  2023. ZwEnumerateKey(
  2024. KeyHandle,
  2025. SubKeyIndex,
  2026. KeyBasicInformation,
  2027. TemporaryBuffer,
  2028. sizeof(TemporaryBuffer),
  2029. &ResultLength
  2030. )
  2031. );
  2032. SubKeyIndex++ )
  2033. {
  2034. //
  2035. // Zero-terminate the subkey name just in case.
  2036. //
  2037. KeyInfo->Name[KeyInfo->NameLength/sizeof(WCHAR)] = 0;
  2038. //
  2039. // Make a duplicate of the subkey name because the name is
  2040. // in TemporaryBuffer, which might get clobbered by recursive
  2041. // calls to this routine.
  2042. //
  2043. SubkeyName = SpDupStringW(KeyInfo->Name);
  2044. if (SubkeyName) {
  2045. //
  2046. // Open this subkey.
  2047. //
  2048. INIT_OBJA(&Obja,&UnicodeString,SubkeyName);
  2049. Obja.RootDirectory = KeyHandle;
  2050. Status = ZwOpenKey(&hSubkey,KEY_READ,&Obja);
  2051. if(NT_SUCCESS(Status)) {
  2052. //
  2053. // See if the current key's name matches the type we're looking for.
  2054. //
  2055. if(!_wcsicmp(KeyName,DesiredKeyName)) {
  2056. RtlInitUnicodeString(&UnicodeString,L"Identifier");
  2057. //
  2058. // Get the identifier string,
  2059. //
  2060. Status = ZwQueryValueKey(
  2061. hSubkey,
  2062. &UnicodeString,
  2063. KeyValuePartialInformation,
  2064. TemporaryBuffer,
  2065. sizeof(TemporaryBuffer),
  2066. &ResultLength
  2067. );
  2068. if(NT_SUCCESS(Status)) {
  2069. //
  2070. // Zero-terminate the id string value just in case.
  2071. // The data is a wstring, so there shouldn't be
  2072. // any alignment problems.
  2073. //
  2074. *(PWCHAR)(ValInfo->Data + ValInfo->DataLength) = 0;
  2075. //
  2076. // Now we have the identifier string -- save it.
  2077. //
  2078. IdStringArray = SpMemRealloc(
  2079. IdStringArray,
  2080. (IdStringCount+1) * sizeof(PWSTR)
  2081. );
  2082. IdStringArray[IdStringCount++] = SpDupStringW((PWSTR)ValInfo->Data);
  2083. } else {
  2084. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  2085. "SETUP: Unable to get identifier string in %ws\\%ws (%lx)\n",
  2086. KeyName,
  2087. SubkeyName,
  2088. Status
  2089. ));
  2090. }
  2091. } else {
  2092. //
  2093. // Enumerate this subkey's subkeys.
  2094. //
  2095. SpScanHardwareDescriptionWorker(hSubkey,SubkeyName,DesiredKeyName);
  2096. }
  2097. ZwClose(hSubkey);
  2098. } else {
  2099. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  2100. "SETUP: Warning: unable to open key %ws\\%ws (%lx)\n",
  2101. KeyName,SubkeyName,Status));
  2102. }
  2103. SpMemFree(SubkeyName);
  2104. }
  2105. }
  2106. }
  2107. VOID
  2108. SpFreeLocatedIdStrings(
  2109. VOID
  2110. )
  2111. {
  2112. ULONG i;
  2113. ASSERT(IdStringArray);
  2114. for(i=0; i<IdStringCount; i++) {
  2115. SpMemFree(IdStringArray[i]);
  2116. }
  2117. SpMemFree(IdStringArray);
  2118. IdStringArray = NULL;
  2119. IdStringCount = 0;
  2120. }
  2121. PHARDWARE_COMPONENT
  2122. SpSetupldrHwToHwDevice(
  2123. IN PDETECTED_DEVICE SetupldrHw
  2124. )
  2125. {
  2126. PHARDWARE_COMPONENT HwComp,HwCompPrev,HwCompFirst=NULL;
  2127. PHARDWARE_COMPONENT_FILE HwCompFile,HwCompFilePrev;
  2128. PHARDWARE_COMPONENT_REGISTRY HwCompReg,HwCompRegPrev;
  2129. PDETECTED_DEVICE_FILE SetupldrFile;
  2130. PDETECTED_DEVICE_REGISTRY SetupldrReg;
  2131. PWSTR s1,s2,s3,s4,s5;
  2132. PVOID Buffer;
  2133. ULONG BufferSize;
  2134. if (SetupldrHw==NULL) {
  2135. return(NULL);
  2136. }
  2137. HwCompPrev = NULL;
  2138. for( ; SetupldrHw; SetupldrHw=SetupldrHw->Next) {
  2139. //
  2140. // Fetch and convert the two strings from the detected device structure.
  2141. //
  2142. s1 = SpToUnicode(SetupldrHw->IdString);
  2143. #ifdef UNICODE_SETUPLDR
  2144. // cast this to avoid having to drag in tchar.h, etc.
  2145. s2 = (PWSTR)SetupldrHw->Description;
  2146. #else
  2147. s2 = SetupldrHw->Description ? SpToUnicode(SetupldrHw->Description) : NULL;
  2148. #endif
  2149. s3 = SpToUnicode(SetupldrHw->BaseDllName);
  2150. //
  2151. // Create a new hardware component structure.
  2152. //
  2153. HwComp = SpMemAlloc(sizeof(HARDWARE_COMPONENT));
  2154. RtlZeroMemory(HwComp,sizeof(HARDWARE_COMPONENT));
  2155. //
  2156. // Initialize the component structure.
  2157. //
  2158. SpInitHwComponent(
  2159. HwComp,
  2160. s1,
  2161. s2,
  2162. SetupldrHw->ThirdPartyOptionSelected,
  2163. SetupldrHw->FileTypeBits,
  2164. s3,
  2165. SetupldrHw->MigratedDriver
  2166. );
  2167. //
  2168. // Link the component structure into the list.
  2169. //
  2170. if(HwCompPrev) {
  2171. HwCompPrev->Next = HwComp;
  2172. } else {
  2173. HwCompFirst = HwComp;
  2174. }
  2175. HwCompPrev = HwComp;
  2176. //
  2177. // Free the unicode strings.
  2178. //
  2179. SpMemFree(s1);
  2180. #ifndef UNICODE_SETUPLDR
  2181. if(s2) {
  2182. SpMemFree(s2);
  2183. }
  2184. #endif
  2185. SpMemFree(s3);
  2186. //
  2187. // Create new entries for each of the hardware component's files.
  2188. //
  2189. HwCompFilePrev = NULL;
  2190. for(SetupldrFile=SetupldrHw->Files; SetupldrFile; SetupldrFile=SetupldrFile->Next) {
  2191. //
  2192. // We can't convert the ARC device name to NT device name since may may not have
  2193. // the ARC <-> NT name map fully initialized yet
  2194. //
  2195. PWSTR ArcDeviceName = SetupldrFile->ArcDeviceName ?
  2196. SpToUnicode(SetupldrFile->ArcDeviceName) : NULL;
  2197. //
  2198. // Fetch and convert the 5 strings from the detected device file structure.
  2199. //
  2200. s1 = SpToUnicode(SetupldrFile->Filename);
  2201. #ifdef UNICODE_SETUPLDR
  2202. // cast this to avoid having to drag in tchar.h, etc.
  2203. s2 = (PWSTR)SetupldrFile->DiskDescription;
  2204. #else
  2205. s2 = SpToUnicode(SetupldrFile->DiskDescription);
  2206. #endif
  2207. s3 = SpToUnicode(SetupldrFile->DiskTagfile);
  2208. s4 = SpToUnicode(SetupldrFile->Directory);
  2209. if (SetupldrFile->ConfigName != NULL) {
  2210. s5 = SpToUnicode(SetupldrFile->ConfigName);
  2211. } else {
  2212. s5 = NULL;
  2213. }
  2214. //
  2215. // Create a new hardware component file structure.
  2216. //
  2217. HwCompFile = SpMemAlloc(sizeof(HARDWARE_COMPONENT_FILE));
  2218. //
  2219. // Initialize the component file structure.
  2220. //
  2221. SpInitHwComponentFile(HwCompFile,
  2222. s1,
  2223. SetupldrFile->FileType,
  2224. s5,
  2225. s2,
  2226. s3,
  2227. s4,
  2228. ArcDeviceName
  2229. );
  2230. //
  2231. // Link the component file structure into the list.
  2232. //
  2233. if(HwCompFilePrev) {
  2234. HwCompFilePrev->Next = HwCompFile;
  2235. } else {
  2236. HwComp->Files = HwCompFile;
  2237. }
  2238. HwCompFilePrev = HwCompFile;
  2239. //
  2240. // Free the unicode strings.
  2241. //
  2242. SpMemFree(s1);
  2243. #ifndef UNICODE_SETUPLDR
  2244. SpMemFree(s2);
  2245. #endif
  2246. SpMemFree(s3);
  2247. SpMemFree(s4);
  2248. if (s5 != NULL) {
  2249. SpMemFree(s5);
  2250. }
  2251. if (ArcDeviceName) {
  2252. SpMemFree(ArcDeviceName);
  2253. }
  2254. //
  2255. // Create new entries for each registry value structure for this file.
  2256. //
  2257. HwCompRegPrev = NULL;
  2258. for( SetupldrReg=SetupldrFile->RegistryValueList;
  2259. SetupldrReg;
  2260. SetupldrReg=SetupldrReg->Next)
  2261. {
  2262. //
  2263. // Make a duplicate of the buffer.
  2264. // Special case REG_SZ, REG_EXPAND_SZ and REG_MULTI_SZ values because
  2265. // we need to convert then to unicode.
  2266. //
  2267. if(SetupldrReg->ValueType == REG_SZ || SetupldrReg->ValueType == REG_EXPAND_SZ) {
  2268. Buffer = SpToUnicode(SetupldrReg->Buffer);
  2269. BufferSize = (wcslen(Buffer) + 1) * sizeof(WCHAR);
  2270. } else {
  2271. if(SetupldrReg->ValueType == REG_MULTI_SZ) {
  2272. PUCHAR p;
  2273. ULONG len;
  2274. //
  2275. // Determine the size of the buffer needed to hold the unicode
  2276. // equivalent of the multi_sz. Assume all characters are
  2277. // single-byte and thus the size exactly doubles.
  2278. //
  2279. for(BufferSize=sizeof(WCHAR),p=SetupldrReg->Buffer; *p; ) {
  2280. len = strlen(p) + 1;
  2281. BufferSize += len * sizeof(WCHAR);
  2282. p += len;
  2283. }
  2284. Buffer = SpMemAlloc(BufferSize);
  2285. //
  2286. // Convert each string in the multi_sz to unicode
  2287. // and place in the resulting unicode multi_sz.
  2288. //
  2289. for(s1=Buffer,p=SetupldrReg->Buffer; *p; ) {
  2290. s2 = SpToUnicode(p);
  2291. wcscpy(s1,s2);
  2292. SpMemFree(s2);
  2293. p += strlen(p) + 1;
  2294. s1 += wcslen(s1) + 1;
  2295. }
  2296. //
  2297. // Final terminating nul in the multi_sz.
  2298. //
  2299. *s1++ = 0;
  2300. //
  2301. // Reallocate the buffer. If some of the characters
  2302. // were double-byte, the buffer will be smaller than
  2303. // the maximum size we allocated above.
  2304. //
  2305. BufferSize = (ULONG)((PUCHAR)s1 - (PUCHAR)Buffer);
  2306. Buffer = SpMemRealloc(Buffer,BufferSize);
  2307. } else {
  2308. BufferSize = SetupldrReg->BufferSize;
  2309. Buffer = SpMemAlloc(BufferSize);
  2310. ASSERT(Buffer);
  2311. RtlMoveMemory(Buffer,SetupldrReg->Buffer,BufferSize);
  2312. }
  2313. }
  2314. //
  2315. // Fetch and convert the 2 strings from the detected device
  2316. // registry value structure.
  2317. //
  2318. s1 = SpToUnicode(SetupldrReg->KeyName);
  2319. s2 = SpToUnicode(SetupldrReg->ValueName);
  2320. //
  2321. // Create a new registry value structure.
  2322. //
  2323. HwCompReg = SpMemAlloc(sizeof(HARDWARE_COMPONENT_REGISTRY));
  2324. //
  2325. // Initialize the component registry value structure.
  2326. //
  2327. SpInitHwComponentRegVal(
  2328. HwCompReg,
  2329. s1,
  2330. s2,
  2331. SetupldrReg->ValueType,
  2332. Buffer,
  2333. BufferSize
  2334. );
  2335. //
  2336. // Link the component registry value structure into the list.
  2337. //
  2338. if(HwCompRegPrev) {
  2339. HwCompRegPrev->Next = HwCompReg;
  2340. } else {
  2341. HwCompFile->RegistryValueList = HwCompReg;
  2342. }
  2343. HwCompRegPrev = HwCompReg;
  2344. //
  2345. // Free the unicode strings.
  2346. //
  2347. SpMemFree(s1);
  2348. SpMemFree(s2);
  2349. }
  2350. }
  2351. }
  2352. return(HwCompFirst);
  2353. }
  2354. VOID
  2355. SpInitHwComponent(
  2356. OUT PHARDWARE_COMPONENT HwComp,
  2357. IN PWSTR IdString,
  2358. IN PWSTR Description,
  2359. IN BOOLEAN ThirdPartyOption,
  2360. IN ULONG FileTypeBits,
  2361. IN PWSTR BaseDllName,
  2362. IN BOOLEAN MigratedDriver
  2363. )
  2364. /*++
  2365. Routine Description:
  2366. Initialize the fields of a HARDWARE_COMPONENT structure.
  2367. Before initializing the fields, ther IdString and Description
  2368. strings are freed if they are present in the given hardware
  2369. component structure.
  2370. All string values are duplicated by this routine so the caller
  2371. may free them without worrying about ruining the hardware component
  2372. structure.
  2373. Arguments:
  2374. IdString - supplies a nul-terminated unicode string for the
  2375. IdString field of the structure. May be NULL.
  2376. Description - supplies a nul-terminated unicode string for the
  2377. Description field pf the structure. May be NULL.
  2378. ThirdPartyOption - supplies value of the ThirdPartyOptionSelected
  2379. field of the strcture.
  2380. FileTypeBits - supplies value for the FileTypeBits field
  2381. of the structure.
  2382. Return Value:
  2383. None.
  2384. --*/
  2385. {
  2386. if(HwComp->IdString) {
  2387. SpMemFree(HwComp->IdString);
  2388. }
  2389. if(HwComp->Description) {
  2390. SpMemFree(HwComp->Description);
  2391. }
  2392. if(HwComp->BaseDllName) {
  2393. SpMemFree(HwComp->BaseDllName);
  2394. }
  2395. RtlZeroMemory(HwComp,sizeof(HARDWARE_COMPONENT));
  2396. if(IdString) {
  2397. HwComp->IdString = SpDupStringW(IdString);
  2398. }
  2399. if(Description) {
  2400. HwComp->Description = SpDupStringW(Description);
  2401. }
  2402. if(BaseDllName) {
  2403. HwComp->BaseDllName = SpDupStringW(BaseDllName);
  2404. }
  2405. HwComp->ThirdPartyOptionSelected = ThirdPartyOption;
  2406. HwComp->FileTypeBits = FileTypeBits;
  2407. HwComp->MigratedDriver = MigratedDriver;
  2408. }
  2409. VOID
  2410. SpFreeHwComponent(
  2411. IN OUT PHARDWARE_COMPONENT *HwComp,
  2412. IN BOOLEAN FreeAllInList
  2413. )
  2414. {
  2415. PHARDWARE_COMPONENT hwComp,Next;
  2416. for(hwComp = *HwComp; hwComp; hwComp=(FreeAllInList ? Next : NULL)) {
  2417. SpFreeHwComponentFile(&hwComp->Files);
  2418. if(hwComp->IdString) {
  2419. SpMemFree(hwComp->IdString);
  2420. }
  2421. if(hwComp->Description) {
  2422. SpMemFree(hwComp->Description);
  2423. }
  2424. if(hwComp->BaseDllName) {
  2425. SpMemFree(hwComp->BaseDllName);
  2426. }
  2427. Next = hwComp->Next;
  2428. SpMemFree(hwComp);
  2429. }
  2430. *HwComp = NULL;
  2431. }
  2432. VOID
  2433. SpFreeHwComponentFile(
  2434. IN OUT PHARDWARE_COMPONENT_FILE *HwCompFile
  2435. )
  2436. /*++
  2437. Routine Description:
  2438. Free a hardware component file list and all resources used by it,
  2439. including any registry value structures associated with the file
  2440. and resources used by such structgures.
  2441. Arguments:
  2442. HwCompFile - supplies pointer to pointer to the first hardware
  2443. component file structure in a linked list.
  2444. Return Value:
  2445. None. HwCompFile is filled in with NULL to prevent the caller
  2446. from retaining a 'dangling' pointer to memory that has been freed.
  2447. --*/
  2448. {
  2449. PHARDWARE_COMPONENT_FILE hwCompFile,NextFile;
  2450. for(hwCompFile = *HwCompFile ; hwCompFile; hwCompFile=NextFile) {
  2451. if(hwCompFile->Filename) {
  2452. SpMemFree(hwCompFile->Filename);
  2453. }
  2454. if(hwCompFile->ConfigName) {
  2455. SpMemFree(hwCompFile->ConfigName);
  2456. }
  2457. if(hwCompFile->DiskDescription) {
  2458. SpMemFree(hwCompFile->DiskDescription);
  2459. }
  2460. if(hwCompFile->DiskTagFile) {
  2461. SpMemFree(hwCompFile->DiskTagFile);
  2462. }
  2463. if(hwCompFile->Directory) {
  2464. SpMemFree(hwCompFile->Directory);
  2465. }
  2466. //
  2467. // Free registry values as well.
  2468. //
  2469. SpFreeHwComponentReg(&hwCompFile->RegistryValueList);
  2470. NextFile = hwCompFile->Next;
  2471. SpMemFree(hwCompFile);
  2472. }
  2473. *HwCompFile = NULL;
  2474. }
  2475. VOID
  2476. SpInitHwComponentFile(
  2477. OUT PHARDWARE_COMPONENT_FILE HwCompFile,
  2478. IN PWSTR Filename,
  2479. IN HwFileType FileType,
  2480. IN PWSTR ConfigName,
  2481. IN PWSTR DiskDescription,
  2482. IN PWSTR DiskTagFile,
  2483. IN PWSTR Directory,
  2484. IN PWSTR ArcDeviceName
  2485. )
  2486. /*++
  2487. Routine Description:
  2488. Initialize the fields of a HARDWARE_COMPONENT_FILE structure.
  2489. All string values are duplicated by this routine so the caller
  2490. may free them without worrying about ruining the
  2491. hardware component file structure.
  2492. Arguments:
  2493. Filename - supplies a nul-terminated unicode string for the
  2494. Filename field of the structure. May be NULL.
  2495. FileType - supplies value for the FileType field of the structure.
  2496. ConfigName - supplies a nul-terminated unicode string for the
  2497. ConfigName field of the structure. May be NULL.
  2498. DiskDescription - supplies a nul-terminated unicode string for the
  2499. DiskDescription field of the structure. May be NULL.
  2500. DiskTagFile - supplies a nul-terminated unicode string for the
  2501. DiskTagFile field of the structure. May be NULL.
  2502. Directory - supplies a nul-terminated unicode string for the
  2503. Directory field of the structure. May be NULL.
  2504. ArcDeviceName - supplies the arc device name where the file
  2505. resides.
  2506. Return Value:
  2507. None.
  2508. --*/
  2509. {
  2510. RtlZeroMemory(HwCompFile,sizeof(HARDWARE_COMPONENT_FILE));
  2511. if(Filename) {
  2512. HwCompFile->Filename = SpDupStringW(Filename);
  2513. }
  2514. HwCompFile->FileType = FileType;
  2515. if(ConfigName) {
  2516. HwCompFile->ConfigName = SpDupStringW(ConfigName);
  2517. }
  2518. if(DiskDescription) {
  2519. HwCompFile->DiskDescription = SpDupStringW(DiskDescription);
  2520. }
  2521. if(DiskTagFile) {
  2522. HwCompFile->DiskTagFile = SpDupStringW(DiskTagFile);
  2523. }
  2524. if(Directory) {
  2525. HwCompFile->Directory = SpDupStringW(Directory);
  2526. }
  2527. if (ArcDeviceName) {
  2528. HwCompFile->ArcDeviceName = SpDupStringW(ArcDeviceName);
  2529. }
  2530. }
  2531. VOID
  2532. SpFreeHwComponentReg(
  2533. IN OUT PHARDWARE_COMPONENT_REGISTRY *HwCompReg
  2534. )
  2535. /*++
  2536. Routine Description:
  2537. Free a hardware component registry value list and all resources
  2538. used by it.
  2539. Arguments:
  2540. HwCompReg - supplies pointer to pointer to the first hardware
  2541. component registry value structure in a linked list.
  2542. Return Value:
  2543. None. HwCompReg is filled in with NULL to prevent the caller
  2544. from retaining a 'dangling' pointer to memory that has been freed.
  2545. --*/
  2546. {
  2547. PHARDWARE_COMPONENT_REGISTRY hwCompReg,NextReg;
  2548. for(hwCompReg = *HwCompReg ; hwCompReg; hwCompReg=NextReg) {
  2549. if(hwCompReg->KeyName) {
  2550. SpMemFree(hwCompReg->KeyName);
  2551. }
  2552. if(hwCompReg->ValueName) {
  2553. SpMemFree(hwCompReg->ValueName);
  2554. }
  2555. if(hwCompReg->Buffer) {
  2556. SpMemFree(hwCompReg->Buffer);
  2557. }
  2558. NextReg = hwCompReg->Next;
  2559. SpMemFree(hwCompReg);
  2560. }
  2561. *HwCompReg = NULL;
  2562. }
  2563. VOID
  2564. SpInitHwComponentRegVal(
  2565. OUT PHARDWARE_COMPONENT_REGISTRY HwCompReg,
  2566. IN PWSTR KeyName,
  2567. IN PWSTR ValueName,
  2568. IN ULONG ValueType,
  2569. IN PVOID Buffer,
  2570. IN ULONG BufferSize
  2571. )
  2572. /*++
  2573. Routine Description:
  2574. Initialize the fields of a HARDWARE_COMPONENT_REGISTRY structure.
  2575. All string values are duplicated by this routine so the caller
  2576. may free them without worrying about ruining the
  2577. hardware component file structure.
  2578. Arguments:
  2579. KeyName - supplies a nul-terminated unicode string for the
  2580. KeyName field of the structure. May be NULL.
  2581. ValueName - supplies a nul-terminated unicode string for the
  2582. ValueName field of the structure. May be NULL.
  2583. ValueType - supplies value for the ValueType field of the structure.
  2584. Buffer - supplies value for the Buffer field of the structure.
  2585. BufferSize - supplies value for the BufferSize field of the structure.
  2586. Return Value:
  2587. None.
  2588. --*/
  2589. {
  2590. RtlZeroMemory(HwCompReg,sizeof(HARDWARE_COMPONENT_REGISTRY));
  2591. if(KeyName) {
  2592. HwCompReg->KeyName = SpDupStringW(KeyName);
  2593. }
  2594. if(ValueName) {
  2595. HwCompReg->ValueName = SpDupStringW(ValueName);
  2596. }
  2597. HwCompReg->ValueType = ValueType;
  2598. HwCompReg->Buffer = Buffer;
  2599. HwCompReg->BufferSize = BufferSize;
  2600. }
  2601. PHARDWARE_COMPONENT_REGISTRY
  2602. SpInterpretOemRegistryData(
  2603. IN PVOID SifHandle,
  2604. IN PWSTR SectionName,
  2605. IN ULONG Line,
  2606. IN ULONG ValueType,
  2607. IN PWSTR KeyName,
  2608. IN PWSTR ValueName
  2609. )
  2610. {
  2611. PHARDWARE_COMPONENT_REGISTRY Reg;
  2612. PWSTR Value;
  2613. unsigned i,len;
  2614. ULONG Dword;
  2615. ULONG BufferSize;
  2616. PVOID Buffer = NULL;
  2617. PWSTR BufferWstr;
  2618. WCHAR str[3];
  2619. //
  2620. // Perform appropriate action based on the type
  2621. //
  2622. switch(ValueType) {
  2623. case REG_DWORD:
  2624. Value = SpGetSectionLineIndex(SifHandle,SectionName,Line,OINDEX_FIRSTVALUE);
  2625. if(Value == NULL) {
  2626. goto x1;
  2627. }
  2628. //
  2629. // Make sure it's really a hex number
  2630. //
  2631. len = wcslen(Value);
  2632. if(len > 8) {
  2633. goto x1;
  2634. }
  2635. for(i=0; i<len; i++) {
  2636. if(!SpIsXDigit(Value[i])) {
  2637. goto x1;
  2638. }
  2639. }
  2640. //
  2641. // convert it from unicode to a hex number
  2642. //
  2643. Dword = (ULONG)SpStringToLong(Value,NULL,16);
  2644. //
  2645. // Allocate a 4-byte buffer and store the dword in it
  2646. //
  2647. Buffer = SpMemAlloc(BufferSize = sizeof(ULONG));
  2648. *(PULONG)Buffer = Dword;
  2649. break;
  2650. case REG_SZ:
  2651. case REG_EXPAND_SZ:
  2652. Value = SpGetSectionLineIndex(SifHandle,SectionName,Line,OINDEX_FIRSTVALUE);
  2653. if(Value == NULL) {
  2654. goto x1;
  2655. }
  2656. //
  2657. // Allocate a buffer of appropriate size for the string
  2658. //
  2659. Buffer = SpDupStringW(Value);
  2660. BufferSize = (wcslen(Value)+1) * sizeof(WCHAR);
  2661. break;
  2662. case REG_BINARY:
  2663. Value = SpGetSectionLineIndex(SifHandle,SectionName,Line,OINDEX_FIRSTVALUE);
  2664. if(Value == NULL) {
  2665. goto x1;
  2666. }
  2667. //
  2668. // Figure out how many byte values are specified
  2669. //
  2670. len = wcslen(Value);
  2671. if(len & 1) {
  2672. goto x1; // odd # of characters
  2673. }
  2674. //
  2675. // Allocate a buffer to hold the byte values
  2676. //
  2677. Buffer = SpMemAlloc(BufferSize = len / 2);
  2678. //
  2679. // For each digit pair, convert to a hex number and store in the
  2680. // buffer
  2681. //
  2682. str[2] = 0;
  2683. for(i=0; i<len; i+=2) {
  2684. //
  2685. // SpIsXDigit evaluates args more than once so break out assignments.
  2686. //
  2687. str[0] = SpToUpper(Value[i]);
  2688. str[1] = SpToUpper(Value[i+1]);
  2689. if(!SpIsXDigit(str[0]) || !SpIsXDigit(str[1])) {
  2690. goto x1;
  2691. }
  2692. ((PUCHAR)Buffer)[i/2] = (UCHAR)SpStringToLong(str,NULL,16);
  2693. }
  2694. break;
  2695. case REG_MULTI_SZ:
  2696. //
  2697. // Calculate size of the buffer needed to hold all specified strings
  2698. //
  2699. for(BufferSize=sizeof(WCHAR),i=0;
  2700. Value = SpGetSectionLineIndex(SifHandle,SectionName,Line,OINDEX_FIRSTVALUE+i);
  2701. i++)
  2702. {
  2703. BufferSize += (wcslen(Value)+1) * sizeof(WCHAR);
  2704. }
  2705. //
  2706. // Allocate a buffer of appropriate size
  2707. //
  2708. Buffer = SpMemAlloc(BufferSize);
  2709. BufferWstr = Buffer;
  2710. //
  2711. // Store each string in the buffer, converting to wide char format
  2712. // in the process
  2713. //
  2714. for(i=0;
  2715. Value = SpGetSectionLineIndex(SifHandle,SectionName,Line,OINDEX_FIRSTVALUE+i);
  2716. i++)
  2717. {
  2718. wcscpy(BufferWstr,Value);
  2719. BufferWstr += wcslen(Value) + 1;
  2720. }
  2721. //
  2722. // Place final terminating widechar nul in the buffer
  2723. //
  2724. *BufferWstr = 0;
  2725. break;
  2726. default:
  2727. x1:
  2728. //
  2729. // Error - bad type specified or maybe we detected bad data values
  2730. // and jumped here
  2731. //
  2732. if(Buffer) {
  2733. SpMemFree(Buffer);
  2734. }
  2735. return(NULL);
  2736. }
  2737. Reg = SpMemAlloc(sizeof(HARDWARE_COMPONENT_REGISTRY));
  2738. SpInitHwComponentRegVal(Reg,KeyName,ValueName,ValueType,Buffer,BufferSize);
  2739. return(Reg);
  2740. }
  2741. VOID
  2742. SpDetectScsi(
  2743. IN PVOID SifHandle,
  2744. IN PWSTR SourceDevicePath,
  2745. IN PWSTR DirectoryOnSourceDevice
  2746. )
  2747. {
  2748. BOOLEAN DetectScsi;
  2749. BOOLEAN b;
  2750. ULONG DriverLoadCount;
  2751. ULONG d;
  2752. NTSTATUS Status;
  2753. PWSTR DriverDescription,DriverFilename;
  2754. PWSTR DriverShortname,DiskDesignator;
  2755. PHARDWARE_COMPONENT scsi,Prev;
  2756. PWSTR PreviousDiskDesignator;
  2757. //
  2758. // Determine the name of the scsi section.
  2759. // This is a remnant from the time when we had separate
  2760. // lists for isa, eisa, and mca machines.
  2761. //
  2762. ScsiSectionName = SpDupStringW(L"SCSI");
  2763. ScsiLoadSectionName = SpDupStringW(L"SCSI.Load");
  2764. LoadedScsiMiniportCount = 0;
  2765. //
  2766. // If scsi drivers have already been loaded, assume setupldr
  2767. // did the detection and skip the scsi confirmation screen.
  2768. //
  2769. if(SetupParameters.LoadedScsi) {
  2770. DetectScsi = FALSE;
  2771. //
  2772. // Fill in descriptions, ignoring what setupldr may have put in
  2773. // the device descriptor.
  2774. //
  2775. for(scsi=ScsiHardware; scsi; scsi=scsi->Next) {
  2776. if(scsi->ThirdPartyOptionSelected) {
  2777. ASSERT(scsi->Description);
  2778. if(!scsi->Description) {
  2779. }
  2780. } else if(scsi->MigratedDriver) {
  2781. if(scsi->Description) {
  2782. SpMemFree(scsi->Description);
  2783. }
  2784. SpFormatMessage( TemporaryBuffer,
  2785. sizeof(TemporaryBuffer),
  2786. SP_TEXT_MIGRATED_DRIVER,
  2787. scsi->BaseDllName );
  2788. scsi->Description = SpDupStringW( TemporaryBuffer );
  2789. } else {
  2790. if(scsi->Description) {
  2791. SpMemFree(scsi->Description);
  2792. }
  2793. scsi->Description = SpGetSectionKeyIndex(
  2794. SifHandle,
  2795. ScsiSectionName,
  2796. scsi->IdString,
  2797. INDEX_DESCRIPTION
  2798. );
  2799. if(!scsi->Description) {
  2800. SpFatalSifError(SifHandle,ScsiSectionName,scsi->IdString,0,INDEX_DESCRIPTION);
  2801. }
  2802. }
  2803. }
  2804. } else {
  2805. //
  2806. // Scsi drivers have not been loaded.
  2807. // Assume we need to perform detection and confirmation here.
  2808. //
  2809. //
  2810. // If this is a custom setup, ask the user if he wants to skip detection.
  2811. // We do this because loading some miniports can whack the hardware such
  2812. // that the machine hangs.
  2813. //
  2814. if(CustomSetup) {
  2815. ULONG ValidKeys[3] = { KEY_F3,ASCI_CR,0 };
  2816. ULONG Mnemonics[2] = { MnemonicSkipDetection,0 };
  2817. do {
  2818. SpDisplayScreen(SP_SCRN_CONFIRM_SCSI_DETECT,3,HEADER_HEIGHT+1);
  2819. SpDisplayStatusOptions(
  2820. DEFAULT_STATUS_ATTRIBUTE,
  2821. SP_STAT_F3_EQUALS_EXIT,
  2822. SP_STAT_ENTER_EQUALS_CONTINUE,
  2823. SP_STAT_S_EQUALS_SKIP_DETECTION,
  2824. 0
  2825. );
  2826. switch(SpWaitValidKey(ValidKeys,NULL,Mnemonics)) {
  2827. case KEY_F3:
  2828. SpConfirmExit();
  2829. b = TRUE;
  2830. break;
  2831. case ASCI_CR:
  2832. DetectScsi = TRUE;
  2833. b = FALSE;
  2834. break;
  2835. default:
  2836. //
  2837. // Must be MnemonicSkipDetection.
  2838. //
  2839. DetectScsi = FALSE;
  2840. b = FALSE;
  2841. break;
  2842. }
  2843. } while(b);
  2844. } else {
  2845. //
  2846. // Express Setup; always detect scsi.
  2847. //
  2848. DetectScsi = TRUE;
  2849. }
  2850. }
  2851. //
  2852. // If we are supposed to detect scsi, do that here.
  2853. // We will 'detect' scsi by loading scsi miniport drivers.
  2854. //
  2855. if(DetectScsi) {
  2856. ASSERT(ScsiHardware == NULL);
  2857. CLEAR_CLIENT_SCREEN();
  2858. //
  2859. // Determine the number of drivers to be loaded.
  2860. //
  2861. PreviousDiskDesignator = L"";
  2862. Prev = NULL;
  2863. DriverLoadCount = SpCountLinesInSection(SifHandle,ScsiLoadSectionName);
  2864. for(d=0; (d<DriverLoadCount) && (LoadedScsiMiniportCount < MAX_SCSI_MINIPORT_COUNT); d++) {
  2865. PWSTR p;
  2866. //
  2867. // Determine whether we are really supposed to load this driver.
  2868. //
  2869. if((p = SpGetSectionLineIndex(SifHandle,ScsiLoadSectionName,d,2)) && !_wcsicmp(p,L"noload")) {
  2870. continue;
  2871. }
  2872. //
  2873. // Get the driver shortname.
  2874. //
  2875. DriverShortname = SpGetKeyName(SifHandle,ScsiLoadSectionName,d);
  2876. if(!DriverShortname) {
  2877. SpFatalSifError(SifHandle,ScsiLoadSectionName,NULL,d,(ULONG)(-1));
  2878. }
  2879. //
  2880. // Get parameters used to load the driver.
  2881. //
  2882. SpGetDriverValuesForLoad(
  2883. SifHandle,
  2884. ScsiSectionName,
  2885. ScsiLoadSectionName,
  2886. DriverShortname,
  2887. &DriverFilename,
  2888. &DiskDesignator,
  2889. &DriverDescription
  2890. );
  2891. //
  2892. // Prompt for the disk containing the driver.
  2893. //
  2894. retryload:
  2895. if(_wcsicmp(DiskDesignator,PreviousDiskDesignator)) {
  2896. ULONG i;
  2897. SpPromptForSetupMedia(
  2898. SifHandle,
  2899. DiskDesignator,
  2900. SourceDevicePath
  2901. );
  2902. //
  2903. // Redraw the found list.
  2904. //
  2905. CLEAR_CLIENT_SCREEN();
  2906. for(i=0,scsi=ScsiHardware; scsi; scsi=scsi->Next,i++) {
  2907. SpDisplayFormattedMessage(
  2908. SP_TEXT_FOUND_ADAPTER,
  2909. FALSE,
  2910. FALSE,
  2911. DEFAULT_ATTRIBUTE,
  2912. 4,
  2913. HEADER_HEIGHT+4+i,
  2914. scsi->Description
  2915. );
  2916. }
  2917. PreviousDiskDesignator = DiskDesignator;
  2918. }
  2919. //
  2920. // Attempt to load the driver.
  2921. //
  2922. Status = SpLoadDeviceDriver(
  2923. DriverDescription,
  2924. SourceDevicePath,
  2925. DirectoryOnSourceDevice,
  2926. DriverFilename
  2927. );
  2928. //
  2929. // If the driver loaded, remember it.
  2930. //
  2931. if(NT_SUCCESS(Status)) {
  2932. SpDisplayFormattedMessage(
  2933. SP_TEXT_FOUND_ADAPTER,
  2934. FALSE,
  2935. FALSE,
  2936. DEFAULT_ATTRIBUTE,
  2937. 4,
  2938. HEADER_HEIGHT+4+LoadedScsiMiniportCount,
  2939. DriverDescription
  2940. );
  2941. LoadedScsiMiniportCount++;
  2942. scsi = SpMemAlloc(sizeof(HARDWARE_COMPONENT));
  2943. RtlZeroMemory(scsi,sizeof(HARDWARE_COMPONENT));
  2944. SpInitHwComponent(scsi,DriverShortname,DriverDescription,FALSE,0,NULL,FALSE);
  2945. //
  2946. // Link the hardware description into the list.
  2947. //
  2948. if(Prev) {
  2949. Prev->Next = scsi;
  2950. } else {
  2951. ScsiHardware = scsi;
  2952. }
  2953. Prev = scsi;
  2954. } else {
  2955. if(Status == STATUS_NO_MEDIA_IN_DEVICE) {
  2956. PreviousDiskDesignator = L"";
  2957. goto retryload;
  2958. }
  2959. }
  2960. }
  2961. } else {
  2962. //
  2963. // Count the number of loaded miniport drivers.
  2964. //
  2965. for(scsi=ScsiHardware; scsi; scsi=scsi->Next) {
  2966. LoadedScsiMiniportCount++;
  2967. }
  2968. }
  2969. }
  2970. VOID
  2971. SpConfirmScsiInteract(
  2972. IN PVOID SifHandle,
  2973. IN PWSTR SourceDevicePath,
  2974. IN PWSTR DirectoryOnSourceDevice
  2975. )
  2976. {
  2977. ULONG ValidKeys[3] = { ASCI_CR, KEY_F3, 0 };
  2978. ULONG Mnemonics[2] = { MnemonicScsiAdapters,0 };
  2979. ULONG ListTopY;
  2980. PHARDWARE_COMPONENT scsi;
  2981. ULONG i;
  2982. BOOLEAN ScsiConfirmed;
  2983. BOOLEAN b;
  2984. BOOLEAN AddDriver;
  2985. NTSTATUS Status;
  2986. #define SCSI_LIST_LEFT_X 7
  2987. //
  2988. // In unattended mode, we might skip this
  2989. // depending on the unattended script.
  2990. //
  2991. if(UnattendedOperation) {
  2992. if( !PreInstall ) {
  2993. PWSTR p;
  2994. p = SpGetSectionKeyIndex(
  2995. UnattendedSifHandle,
  2996. SIF_UNATTENDED,
  2997. SIF_CONFIRMHW,
  2998. 0
  2999. );
  3000. //
  3001. // If not specified or specified and not "yes"
  3002. // then return.
  3003. //
  3004. if(!p || _wcsicmp(p,L"yes")) {
  3005. return;
  3006. }
  3007. } else {
  3008. return;
  3009. }
  3010. } else if (LoadedScsiMiniportCount) {
  3011. return;
  3012. }
  3013. ScsiConfirmed = FALSE;
  3014. do {
  3015. //
  3016. // First part of the screen.
  3017. //
  3018. SpDisplayScreen(SP_SCRN_SCSI_LIST_1,3,HEADER_HEIGHT+1);
  3019. //
  3020. // Remember where the first part of the screen ends.
  3021. //
  3022. ListTopY = NextMessageTopLine + 2;
  3023. //
  3024. // Second part of the screen.
  3025. //
  3026. SpContinueScreen(
  3027. SP_SCRN_SCSI_LIST_2,
  3028. 3,
  3029. MAX_SCSI_MINIPORT_COUNT+6,
  3030. FALSE,
  3031. DEFAULT_ATTRIBUTE
  3032. );
  3033. //
  3034. // Display each loaded miniport driver description.
  3035. //
  3036. if(ScsiHardware) {
  3037. for(i=0,scsi=ScsiHardware; scsi; scsi=scsi->Next,i++) {
  3038. if(i == MAX_SCSI_MINIPORT_COUNT) {
  3039. SpvidDisplayString(
  3040. L"...",
  3041. DEFAULT_ATTRIBUTE,
  3042. SCSI_LIST_LEFT_X,
  3043. ListTopY+i
  3044. );
  3045. break;
  3046. }
  3047. SpvidDisplayString(
  3048. scsi->Description,
  3049. DEFAULT_ATTRIBUTE,
  3050. SCSI_LIST_LEFT_X,
  3051. ListTopY+i
  3052. );
  3053. }
  3054. } else {
  3055. SpDisplayFormattedMessage(
  3056. SP_TEXT_ANGLED_NONE,
  3057. FALSE,
  3058. FALSE,
  3059. DEFAULT_ATTRIBUTE,
  3060. SCSI_LIST_LEFT_X,
  3061. ListTopY
  3062. );
  3063. }
  3064. //
  3065. // display status text options.
  3066. //
  3067. SpDisplayStatusOptions(
  3068. DEFAULT_STATUS_ATTRIBUTE,
  3069. SP_STAT_S_EQUALS_SCSI_ADAPTER,
  3070. SP_STAT_ENTER_EQUALS_CONTINUE,
  3071. SP_STAT_F3_EQUALS_EXIT,
  3072. 0
  3073. );
  3074. //
  3075. // Wait for the user to press a valid key.
  3076. //
  3077. switch(SpWaitValidKey(ValidKeys,NULL,Mnemonics)) {
  3078. case ASCI_CR:
  3079. ScsiConfirmed = TRUE;
  3080. break;
  3081. case KEY_F3:
  3082. SpConfirmExit();
  3083. break;
  3084. default:
  3085. //
  3086. // Must be s=specify additional adapter.
  3087. //
  3088. AddDriver = FALSE;
  3089. scsi = SpMemAlloc(sizeof(HARDWARE_COMPONENT));
  3090. RtlZeroMemory(scsi,sizeof(HARDWARE_COMPONENT));
  3091. b = SpSelectHwItem(
  3092. SifHandle,
  3093. ScsiSectionName,
  3094. L"Scsi",
  3095. SP_SCRN_SELECT_SCSI,
  3096. SP_SCRN_SELECT_OEM_SCSI,
  3097. SCSI_ALLOWED_FILETYPES,
  3098. SCSI_REQUIRED_FILETYPES,
  3099. scsi
  3100. );
  3101. if(b) {
  3102. //
  3103. // User made a selection. Determine whether that scsi adapter
  3104. // is already on the list for instllation.
  3105. //
  3106. PHARDWARE_COMPONENT p;
  3107. b = FALSE;
  3108. for(p=ScsiHardware; p; p=p->Next) {
  3109. if((p->ThirdPartyOptionSelected == scsi->ThirdPartyOptionSelected)
  3110. && !_wcsicmp(p->IdString,scsi->IdString))
  3111. {
  3112. b = TRUE;
  3113. break;
  3114. }
  3115. }
  3116. if(b) {
  3117. //
  3118. // The driver is already loaded -- silently ignore the user's selection.
  3119. //
  3120. #if 0
  3121. //
  3122. // This driver is already loaded -- tell the user.
  3123. //
  3124. SpDisplayScreen(SP_SCRN_SCSI_ALREADY_LOADED,3,HEADER_HEIGHT+1);
  3125. SpDisplayStatusOptions(
  3126. DEFAULT_STATUS_ATTRIBUTE,
  3127. SP_STAT_ENTER_EQUALS_CONTINUE,
  3128. 0
  3129. );
  3130. SpInputDrain();
  3131. while(SpInputGetKeypress() != ASCI_CR) ;
  3132. #endif
  3133. } else {
  3134. PWSTR DiskDevicePath;
  3135. PWSTR DirectoryOnDisk;
  3136. PWSTR DriverFilename;
  3137. PWSTR Media;
  3138. //
  3139. // The driver is not loaded. Atempt to load it.
  3140. //
  3141. if(scsi->ThirdPartyOptionSelected) {
  3142. PHARDWARE_COMPONENT_FILE fil;
  3143. //
  3144. // Locate the first file of type driver or port.
  3145. //
  3146. for(fil=scsi->Files; fil; fil=fil->Next) {
  3147. if((fil->FileType == HwFileDriver) || (fil->FileType == HwFilePort)) {
  3148. DirectoryOnDisk = fil->Directory;
  3149. DriverFilename = fil->Filename;
  3150. break;
  3151. }
  3152. }
  3153. DiskDevicePath = L"\\device\\floppy0";
  3154. } else {
  3155. DiskDevicePath = SourceDevicePath;
  3156. DirectoryOnDisk = DirectoryOnSourceDevice;
  3157. SpGetDriverValuesForLoad(
  3158. SifHandle,
  3159. ScsiSectionName,
  3160. ScsiLoadSectionName,
  3161. scsi->IdString,
  3162. &DriverFilename,
  3163. &Media,
  3164. NULL
  3165. );
  3166. SpPromptForSetupMedia(
  3167. SifHandle,
  3168. Media,
  3169. DiskDevicePath
  3170. );
  3171. }
  3172. CLEAR_CLIENT_SCREEN();
  3173. Status = SpLoadDeviceDriver(
  3174. scsi->Description,
  3175. DiskDevicePath,
  3176. DirectoryOnDisk,
  3177. DriverFilename
  3178. );
  3179. //
  3180. // If the driver did not load, tell the user.
  3181. //
  3182. if(NT_SUCCESS(Status)) {
  3183. AddDriver = TRUE;
  3184. } else {
  3185. SpDisplayScreen(SP_SCRN_SCSI_DIDNT_LOAD,3,HEADER_HEIGHT+1);
  3186. SpDisplayStatusOptions(
  3187. DEFAULT_STATUS_ATTRIBUTE,
  3188. SP_STAT_ENTER_EQUALS_CONTINUE,
  3189. 0
  3190. );
  3191. SpInputDrain();
  3192. while(SpInputGetKeypress() != ASCI_CR) ;
  3193. }
  3194. }
  3195. }
  3196. if(AddDriver) {
  3197. if(ScsiHardware) {
  3198. PHARDWARE_COMPONENT p = ScsiHardware;
  3199. while(p->Next) {
  3200. p = p->Next;
  3201. }
  3202. p->Next = scsi;
  3203. } else {
  3204. ScsiHardware = scsi;
  3205. }
  3206. LoadedScsiMiniportCount++;
  3207. } else {
  3208. SpFreeHwComponent(&scsi,TRUE);
  3209. }
  3210. break;
  3211. }
  3212. } while(!ScsiConfirmed);
  3213. }
  3214. VOID
  3215. SpGetDriverValuesForLoad(
  3216. IN PVOID SifHandle,
  3217. IN PWSTR ComponentSectionName,
  3218. IN PWSTR ComponentLoadSectionName,
  3219. IN PWSTR Shortname,
  3220. OUT PWSTR *Filename,
  3221. OUT PWSTR *MediaDesignator,
  3222. OUT PWSTR *Description OPTIONAL
  3223. )
  3224. {
  3225. PWSTR description,mediaDesignator,filename;
  3226. //
  3227. // Get the filename associated with this load option.
  3228. //
  3229. filename = SpGetSectionKeyIndex(SifHandle,ComponentLoadSectionName,Shortname,0);
  3230. if(!filename) {
  3231. SpFatalSifError(SifHandle,ComponentLoadSectionName,Shortname,0,0);
  3232. }
  3233. //
  3234. // Look up the description in the component section.
  3235. //
  3236. description = SpGetSectionKeyIndex(
  3237. SifHandle,
  3238. ComponentSectionName,
  3239. Shortname,
  3240. INDEX_DESCRIPTION
  3241. );
  3242. if(!description) {
  3243. SpFatalSifError(SifHandle,ComponentSectionName,Shortname,0,INDEX_DESCRIPTION);
  3244. }
  3245. //
  3246. // Look up the media designator. If we are loading the driver for use
  3247. // during setup, we want to get it from the setup boot media.
  3248. //
  3249. mediaDesignator = SpLookUpValueForFile(SifHandle,filename,INDEX_WHICHBOOTMEDIA,TRUE);
  3250. //
  3251. // Pass information back to caller.
  3252. //
  3253. *Filename = filename;
  3254. *MediaDesignator = mediaDesignator;
  3255. if(Description) {
  3256. *Description = description;
  3257. }
  3258. }
  3259. BOOLEAN
  3260. SpInstallingMp(
  3261. VOID
  3262. )
  3263. {
  3264. PWSTR ComputerId;
  3265. ULONG ComputerIdLen;
  3266. ComputerId = HardwareComponents[HwComponentComputer]->IdString;
  3267. ComputerIdLen = wcslen(ComputerId);
  3268. //
  3269. // If _up is specified use the up kernel. Otherwise use the mp kernel.
  3270. //
  3271. if((ComputerIdLen >= 3) && !_wcsicmp(ComputerId+ComputerIdLen-3,L"_mp")) {
  3272. return(TRUE);
  3273. }
  3274. return(FALSE);
  3275. }
  3276. PHARDWARE_COMPONENT
  3277. SpGetPreinstallComponentInfo(
  3278. IN HANDLE MasterSifHandle,
  3279. IN BOOLEAN OemComponent,
  3280. IN PWSTR ComponentName,
  3281. IN PWSTR Description,
  3282. IN ULONG AllowedFileTypes,
  3283. IN ULONG RequiredFileTypes
  3284. )
  3285. /*++
  3286. Routine Description:
  3287. Initialize a structure that contains the information about a
  3288. component to be pre-installed.
  3289. Arguments:
  3290. MasterSifHandle - Handle to txtsetup.sif.
  3291. OemComponent - Flag that indicates if the component to be pre-installed
  3292. is an OEM or retail component.
  3293. ComponentName - Name of the component whose information will be retrieved
  3294. (Computer, Display, Keyboard, Keyboard Layout and Mouse ).
  3295. AllowedFileTypes -
  3296. RequiredFileTypes -
  3297. Return Value:
  3298. Returns a pointer to an initialized HARDWARE_COMPONENT structure.
  3299. --*/
  3300. {
  3301. PHARDWARE_COMPONENT TempHwComponent;
  3302. PWSTR IdString;
  3303. ULONG ValidKeys[2] = { KEY_F3,0 };
  3304. TempHwComponent = SpMemAlloc(sizeof(HARDWARE_COMPONENT));
  3305. RtlZeroMemory(TempHwComponent,sizeof(HARDWARE_COMPONENT));
  3306. if( !OemComponent ) {
  3307. //
  3308. // Pre-install a retail component
  3309. //
  3310. IdString = SpGetKeyNameByValue( MasterSifHandle,
  3311. ComponentName,
  3312. Description );
  3313. if( IdString == NULL ) {
  3314. //
  3315. // This is a fatal error
  3316. //
  3317. SpStartScreen( SP_SCRN_OEM_PREINSTALL_VALUE_NOT_FOUND,
  3318. 3,
  3319. HEADER_HEIGHT+3,
  3320. FALSE,
  3321. FALSE,
  3322. DEFAULT_ATTRIBUTE,
  3323. Description,
  3324. ComponentName);
  3325. SpDisplayStatusOptions(DEFAULT_STATUS_ATTRIBUTE,SP_STAT_F3_EQUALS_EXIT,0);
  3326. SpWaitValidKey(ValidKeys,NULL,NULL);
  3327. SpDone(0,FALSE,TRUE);
  3328. return NULL; // for prefix
  3329. }
  3330. SpInitHwComponent(TempHwComponent,IdString,Description,FALSE,0,NULL,FALSE);
  3331. } else {
  3332. //
  3333. // Pre-install an OEM component
  3334. //
  3335. IdString = SpGetKeyNameByValue( PreinstallOemSifHandle,
  3336. ComponentName,
  3337. Description );
  3338. if( IdString == NULL ) {
  3339. //
  3340. // Put a fatal error message indicating that txtsetup.oem
  3341. // is needed but that it couldn't be loaded. Note that the
  3342. // that SpOemInfError() will not return.
  3343. //
  3344. SpOemInfError(SP_SCRN_OEM_PREINSTALL_INF_ERROR,
  3345. SP_TEXT_OEM_INF_ERROR_B,
  3346. ComponentName,
  3347. 0,
  3348. Description);
  3349. // SpDone(0,FALSE,TRUE);
  3350. }
  3351. if( !SpOemInfSelection( PreinstallOemSifHandle,
  3352. ComponentName,
  3353. IdString,
  3354. Description,
  3355. AllowedFileTypes,
  3356. RequiredFileTypes,
  3357. TempHwComponent,
  3358. SP_SCRN_OEM_PREINSTALL_INF_ERROR ) ) {
  3359. //
  3360. // This case shoud never occur, becase in case of error,
  3361. // SpOemInfSelection will not return.
  3362. //
  3363. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpOemInfSelection() in pre-install mode failed \n" ));
  3364. ASSERT(FALSE);
  3365. // SpDone(0,FALSE,TRUE);
  3366. }
  3367. }
  3368. return( TempHwComponent );
  3369. }
  3370. VOID
  3371. SpInitializePreinstallList(
  3372. IN HANDLE MasterSifHandle,
  3373. IN PWSTR SetupSourceDevicePath,
  3374. IN PWSTR OemPreinstallSourcePath
  3375. )
  3376. /*++
  3377. Routine Description:
  3378. Initialize the structures that contains the information about the
  3379. components to be pre-installed.
  3380. Arguments:
  3381. MasterSifHandle - Handle to txtsetup.sif.
  3382. SetupSourceDevicePath - Path to the device that contains the source media.
  3383. OemDirectoryOnSourceDevice - Directory on the media where the OEM
  3384. components are loacted.
  3385. Return Value:
  3386. NONE.
  3387. --*/
  3388. {
  3389. PWSTR TxtsetupOemPath;
  3390. PWSTR p;
  3391. PWSTR OemTag = L"OEM";
  3392. BOOLEAN OemComponent;
  3393. NTSTATUS Status;
  3394. PHARDWARE_COMPONENT TempHwComponent;
  3395. PWSTR IdString;
  3396. PWSTR Description;
  3397. ULONG ErrorLine;
  3398. ULONG i,j;
  3399. #if defined(_AMD64_) || defined(_X86_)
  3400. PWSTR r, s;
  3401. #endif // defined(_AMD64_) || defined(_X86_)
  3402. #if defined(_AMD64_) || defined(_X86_)
  3403. //
  3404. // First, we need to check if the directory '\$' exists on the root.
  3405. // if it does, we need to move it to (\$win_nt$.~ls\$OEM$).
  3406. // This will happen only when winnt.exe (DOS) was used in the installation
  3407. // process.
  3408. // Winnt.exe copies the $OEM$ to the '\$', in order to avoid hitting the
  3409. // DOS limitiation for the length of a path (maximum of 64 characters).
  3410. //
  3411. wcscpy(TemporaryBuffer, SetupSourceDevicePath);
  3412. SpConcatenatePaths( TemporaryBuffer, WINNT_OEM_DEST_DIR_W );
  3413. r = SpDupStringW(TemporaryBuffer);
  3414. if (r) {
  3415. if( SpFileExists( r, TRUE ) ) {
  3416. wcscpy(TemporaryBuffer, SetupSourceDevicePath);
  3417. SpConcatenatePaths( TemporaryBuffer, PreinstallOemSourcePath );
  3418. s = wcsrchr( TemporaryBuffer, (WCHAR)'\\' );
  3419. if( s != NULL ) {
  3420. *s = (WCHAR)'\0';
  3421. }
  3422. s = SpDupStringW(TemporaryBuffer);
  3423. if (s) {
  3424. Status = SpMoveFileOrDirectory( r, s );
  3425. SpMemFree( s );
  3426. } else {
  3427. Status = STATUS_NO_MEMORY;
  3428. }
  3429. if( !NT_SUCCESS( Status ) ) {
  3430. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  3431. "SETUP: Unable to move directory %ws to %ws. Status = %lx \n",
  3432. r, s, Status ));
  3433. }
  3434. }
  3435. SpMemFree( r );
  3436. }
  3437. #endif // defined(_AMD64_) || defined(_X86_)
  3438. //
  3439. // Attempt to load txtsetup.oem
  3440. //
  3441. wcscpy( TemporaryBuffer, SetupSourceDevicePath );
  3442. SpConcatenatePaths( TemporaryBuffer, OemPreinstallSourcePath );
  3443. SpConcatenatePaths( TemporaryBuffer, L"txtsetup.oem" );
  3444. TxtsetupOemPath = SpDupStringW( TemporaryBuffer );
  3445. CLEAR_CLIENT_SCREEN();
  3446. HandleLineContinueChars = FALSE;
  3447. Status = SpLoadSetupTextFile(
  3448. TxtsetupOemPath,
  3449. NULL, // No image already in memory
  3450. 0, // Image size is empty
  3451. &PreinstallOemSifHandle,
  3452. &ErrorLine,
  3453. TRUE,
  3454. FALSE
  3455. );
  3456. HandleLineContinueChars = TRUE;
  3457. if(!NT_SUCCESS(Status)) {
  3458. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to read txtsetup.oem. Status = %lx \n", Status ));
  3459. PreinstallOemSifHandle = NULL;
  3460. if(Status == STATUS_UNSUCCESSFUL) {
  3461. //
  3462. // Put an fatal error. On pre-install mode, the function will
  3463. // never come back.
  3464. //
  3465. SpOemInfError(SP_SCRN_OEM_PREINSTALL_INF_ERROR,SP_TEXT_OEM_INF_ERROR_A,NULL,ErrorLine,NULL);
  3466. return;
  3467. } else {
  3468. //
  3469. // Unable to load txtsetup.oem. Don't put an error message yet.
  3470. // Wait until we know that the file is needed.
  3471. //
  3472. }
  3473. }
  3474. for( j = 0; j < HwComponentMax; j++ ) {
  3475. PreinstallHardwareComponents[j] = NULL;
  3476. if( ( j == HwComponentComputer ) || ( j == HwComponentLayout ) ) {
  3477. Description = SpGetSectionKeyIndex(UnattendedSifHandle,
  3478. SIF_UNATTENDED,
  3479. PreinstallSectionNames[j],
  3480. 0);
  3481. if( Description != NULL ) {
  3482. if( j != HwComponentLayout ) {
  3483. p = SpGetSectionKeyIndex(UnattendedSifHandle,
  3484. SIF_UNATTENDED,
  3485. PreinstallSectionNames[j],
  3486. 1);
  3487. OemComponent = (p != NULL) && (_wcsicmp(p, OemTag) == 0);
  3488. if( OemComponent && ( PreinstallOemSifHandle == NULL ) ) {
  3489. //
  3490. // Put a fatal error message indicating that txtsetup.oem
  3491. // is needed but that it couldn't be loaded. Note that the
  3492. // SpOemInfError() will not return.
  3493. //
  3494. SpOemInfError(SP_SCRN_OEM_PREINSTALL_INF_ERROR,SP_TEXT_OEM_INF_ERROR_A,NULL,0,NULL);
  3495. // return;
  3496. }
  3497. } else {
  3498. OemComponent = FALSE;
  3499. }
  3500. PreinstallHardwareComponents[j] =
  3501. SpGetPreinstallComponentInfo( MasterSifHandle,
  3502. OemComponent,
  3503. NonlocalizedComponentNames[j],
  3504. Description,
  3505. AllowedFileTypes[j],
  3506. RequiredFileTypes[j] );
  3507. }
  3508. } else {
  3509. for( i = 0;
  3510. Description = SpGetKeyName( UnattendedSifHandle,
  3511. PreinstallSectionNames[j],
  3512. i );
  3513. i++ ) {
  3514. p = SpGetSectionKeyIndex(UnattendedSifHandle,
  3515. PreinstallSectionNames[j],
  3516. Description,
  3517. 0);
  3518. OemComponent = (p != NULL) && (_wcsicmp(p, OemTag) == 0);
  3519. if( OemComponent && ( PreinstallOemSifHandle == NULL ) ) {
  3520. //
  3521. // Put a fatal error message indicating that txtsetup.oem
  3522. // is needed but that it couldn't be loaded. Note that the
  3523. // SpOemInfError() will not return.
  3524. //
  3525. SpOemInfError(SP_SCRN_OEM_PREINSTALL_INF_ERROR,SP_TEXT_OEM_INF_ERROR_A,NULL,0,NULL);
  3526. // return;
  3527. }
  3528. TempHwComponent =
  3529. SpGetPreinstallComponentInfo( MasterSifHandle,
  3530. OemComponent,
  3531. NonlocalizedComponentNames[j],
  3532. Description,
  3533. AllowedFileTypes[j],
  3534. RequiredFileTypes[j] );
  3535. TempHwComponent->Next = PreinstallHardwareComponents[j];
  3536. PreinstallHardwareComponents[j] = TempHwComponent;
  3537. }
  3538. }
  3539. }
  3540. //
  3541. // Note that there is no need to get the information about the scsi
  3542. // drivers to pre-install, ScsiHardware already contains the correct
  3543. // information.
  3544. //
  3545. // #if 0
  3546. for( i = 0;
  3547. Description = SpGetKeyName( UnattendedSifHandle,
  3548. WINNT_OEMSCSIDRIVERS_W,
  3549. i );
  3550. i++ ) {
  3551. p = SpGetSectionKeyIndex(UnattendedSifHandle,
  3552. WINNT_OEMSCSIDRIVERS_W,
  3553. Description,
  3554. 0);
  3555. OemComponent = (p != NULL) && (_wcsicmp(p, OemTag) == 0);
  3556. if( OemComponent && ( PreinstallOemSifHandle == NULL ) ) {
  3557. //
  3558. // Put a fatal error message indicating that txtsetup.oem
  3559. // is needed but that it couldn't be loaded. Note that the
  3560. // SpOemInfError() will not return.
  3561. //
  3562. SpOemInfError(SP_SCRN_OEM_PREINSTALL_INF_ERROR,SP_TEXT_OEM_INF_ERROR_A,NULL,0,NULL);
  3563. // return;
  3564. }
  3565. TempHwComponent =
  3566. SpGetPreinstallComponentInfo( MasterSifHandle,
  3567. OemComponent,
  3568. L"SCSI",
  3569. Description,
  3570. SCSI_ALLOWED_FILETYPES,
  3571. SCSI_REQUIRED_FILETYPES );
  3572. TempHwComponent->Next = PreinstallScsiHardware;
  3573. PreinstallScsiHardware = TempHwComponent;
  3574. }
  3575. // #endif
  3576. }
  3577. PSETUP_PNP_HARDWARE_ID
  3578. SpSetupldrPnpDatabaseToSetupPnpDatabase(
  3579. IN PPNP_HARDWARE_ID AnsiHardwareIdDatabase
  3580. )
  3581. {
  3582. PPNP_HARDWARE_ID TempAnsiId;
  3583. PSETUP_PNP_HARDWARE_ID TempUnicodeId;
  3584. PSETUP_PNP_HARDWARE_ID UnicodeHardwareIdDatabase;
  3585. #if 0
  3586. ULONG Index;
  3587. #endif
  3588. UnicodeHardwareIdDatabase = NULL;
  3589. for( TempAnsiId = AnsiHardwareIdDatabase; TempAnsiId != NULL; TempAnsiId = TempAnsiId->Next ) {
  3590. TempUnicodeId = SpMemAlloc( sizeof( SETUP_PNP_HARDWARE_ID ) );
  3591. ASSERT(TempUnicodeId);
  3592. RtlZeroMemory( TempUnicodeId, sizeof(SETUP_PNP_HARDWARE_ID ) );
  3593. TempUnicodeId->Id = SpToUnicode( TempAnsiId->Id );
  3594. ASSERT(TempUnicodeId->Id);
  3595. TempUnicodeId->DriverName = SpToUnicode( TempAnsiId->DriverName );
  3596. ASSERT(TempUnicodeId->DriverName);
  3597. if( TempAnsiId->ClassGuid != NULL ) {
  3598. TempUnicodeId->ClassGuid = SpToUnicode( TempAnsiId->ClassGuid );
  3599. } else {
  3600. TempUnicodeId->ClassGuid = NULL;
  3601. }
  3602. TempUnicodeId->Next = UnicodeHardwareIdDatabase;
  3603. UnicodeHardwareIdDatabase = TempUnicodeId;
  3604. }
  3605. #if 0
  3606. for( TempUnicodeId = UnicodeHardwareIdDatabase, Index = 0;
  3607. TempUnicodeId != NULL;
  3608. TempUnicodeId = TempUnicodeId->Next, Index++ ) {
  3609. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Index = %d, Id = %ls, DriverName = %ls, ClassGUID = %ls \n", Index, TempUnicodeId->Id, TempUnicodeId->DriverName, ((TempUnicodeId->ClassGuid)? TempUnicodeId->ClassGuid : none)));
  3610. }
  3611. #endif
  3612. return( UnicodeHardwareIdDatabase );
  3613. }
  3614. BOOLEAN
  3615. SpSelectSectionItem(
  3616. IN PVOID SifHandle,
  3617. IN PWSTR SectionName,
  3618. IN ULONG SelectScreenId,
  3619. IN ULONG DefaultSelection OPTIONAL,
  3620. OUT PULONG SelectedOption
  3621. )
  3622. /*++
  3623. Routine Description:
  3624. Allow the user to make selection from a list of choices for a component.
  3625. The list comes from a section in the setup information file named
  3626. for the component. For example, [Display].
  3627. The descriptions in that section will be placed into a menu to make
  3628. up the selections.
  3629. Arguments:
  3630. SifHandle - supplies handle to open setup information file.
  3631. SectionName - supplies name of section to be used.
  3632. SelectHwScreenId - supplies message id of the screen prompting the user
  3633. to select an option for this section.
  3634. DefaultSelection - Item index, which should be highlighted as the default
  3635. choice when the menu is shown
  3636. SelectedOption - Returns the selected option
  3637. Return Value:
  3638. TRUE if a valid option is selected, otherwise FALSE
  3639. --*/
  3640. {
  3641. BOOLEAN Result;
  3642. ULONG LineCount,Line;
  3643. PVOID Menu;
  3644. ULONG MenuTopY,MenuHeight,MenuWidth;
  3645. PWSTR Description;
  3646. ULONG_PTR Selection;
  3647. ULONG ValidKeys[4] = {ASCI_CR, ASCI_ESC, 0};
  3648. ULONG Keypress;
  3649. //
  3650. // Display the selection prompt screen.
  3651. //
  3652. SpDisplayScreen(SelectScreenId, 5, HEADER_HEIGHT+1);
  3653. MenuTopY = NextMessageTopLine + 2;
  3654. MenuHeight = VideoVars.ScreenHeight - MenuTopY - 3;
  3655. MenuWidth = VideoVars.ScreenWidth - 6;
  3656. //
  3657. // Create a menu.
  3658. //
  3659. Menu = SpMnCreate(3, MenuTopY, MenuWidth, MenuHeight);
  3660. Result = (Menu != NULL);
  3661. //
  3662. // Assume unknown option.
  3663. //
  3664. Selection = (ULONG_PTR)(-1);
  3665. //
  3666. // Build a list of options containing the options in our box
  3667. //
  3668. LineCount = SpCountLinesInSection(SifHandle, SectionName);
  3669. for(Line=0; (Line < LineCount) && Result; Line++) {
  3670. //
  3671. // Get the description from the current line and add it to the menu.
  3672. //
  3673. Description = SpGetSectionLineIndex(
  3674. SifHandle,
  3675. SectionName,
  3676. Line,
  3677. INDEX_DESCRIPTION
  3678. );
  3679. if(!Description) {
  3680. Result = FALSE;
  3681. break;
  3682. }
  3683. SpMnAddItem(Menu, Description, 3, VideoVars.ScreenWidth-6, TRUE, Line);
  3684. //
  3685. // See if this is the currently selected item.
  3686. //
  3687. if((DefaultSelection != -1) && (DefaultSelection == Line)) {
  3688. Selection = Line;
  3689. }
  3690. }
  3691. if (Result) {
  3692. if(Selection == (ULONG_PTR)(-1)) {
  3693. Selection = 0;
  3694. }
  3695. //
  3696. // Display the status text options.
  3697. //
  3698. SpDisplayStatusOptions(
  3699. (UCHAR)(ATT_FG_BLACK | ATT_BG_WHITE),
  3700. SP_STAT_ENTER_EQUALS_SELECT,
  3701. SP_STAT_ESC_EQUALS_CANCEL,
  3702. 0
  3703. );
  3704. //
  3705. // Display the menu.
  3706. //
  3707. SpMnDisplay(Menu,
  3708. Selection,
  3709. TRUE,
  3710. ValidKeys,
  3711. NULL,
  3712. NULL,
  3713. NULL,
  3714. &Keypress,
  3715. &Selection);
  3716. //
  3717. // Destroy the menu
  3718. //
  3719. SpMnDestroy(Menu);
  3720. switch(Keypress) {
  3721. case ASCI_CR:
  3722. Result = TRUE;
  3723. *SelectedOption = (ULONG)Selection;
  3724. break;
  3725. case ASCI_ESC:
  3726. Result = FALSE;
  3727. if (DefaultSelection != -1)
  3728. *SelectedOption = (ULONG)Selection;
  3729. break;
  3730. default:
  3731. Result = FALSE;
  3732. break;
  3733. }
  3734. }
  3735. return Result;
  3736. }
  3737. NTSTATUS
  3738. SpInitVirtualOemDevices(
  3739. IN PSETUP_LOADER_BLOCK SetupLoaderBlock,
  3740. OUT PVIRTUAL_OEM_SOURCE_DEVICE *SourceDevices
  3741. )
  3742. /*++
  3743. Routine Description:
  3744. Iterates through the virtual OEM source devices which loader
  3745. created and converts them into VIRTUAL_OEM_SOURCE_DEVICE list.
  3746. Also creates the required registry entries for each device
  3747. under RAM disk's parameters key.
  3748. Arguments:
  3749. SetupLoaderBlock - Setup loader block constructed by setupldr.
  3750. SourceDevice - Place holder for receiving the pointer to
  3751. head of the linked list of VIRTUAL_OEM_SOURCE_DEVICEs.
  3752. Return Value:
  3753. Appropriate NTSTATUS code
  3754. --*/
  3755. {
  3756. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  3757. if (SetupLoaderBlock && SourceDevices) {
  3758. Status = STATUS_SUCCESS;
  3759. //
  3760. // Setupldr would have constructed its own version
  3761. // of the virtual OEM source devices
  3762. //
  3763. if (SetupLoaderBlock->OemSourceDevices) {
  3764. PVIRTUAL_OEM_SOURCE_DEVICE DeviceList = NULL;
  3765. PDETECTED_OEM_SOURCE_DEVICE CurrDevice = SetupLoaderBlock->OemSourceDevices;
  3766. ULONG DeviceCount = 0;
  3767. //
  3768. // Replicate the device list
  3769. //
  3770. while (CurrDevice) {
  3771. PVIRTUAL_OEM_SOURCE_DEVICE NewDevice;
  3772. NewDevice = SpMemAlloc(sizeof(VIRTUAL_OEM_SOURCE_DEVICE));
  3773. if (!NewDevice) {
  3774. Status = STATUS_NO_MEMORY;
  3775. break;
  3776. }
  3777. RtlZeroMemory(NewDevice, sizeof(VIRTUAL_OEM_SOURCE_DEVICE));
  3778. NewDevice->ArcDeviceName = SpToUnicode(CurrDevice->ArcDeviceName);
  3779. #if defined(_AMD64_) || defined(_X86_)
  3780. //
  3781. // NOTE : Loader allocated "LoaderFirmwarePermanent" memory
  3782. // so that memory manager while initializing doesn't
  3783. // reclaim this memory. This also helps us to avoid
  3784. // double copy -- i.e. this is the only location
  3785. // where we read the device contents into memory and
  3786. // this memory is valid through out the textmode setup so
  3787. // just reuse the memory.
  3788. //
  3789. NewDevice->ImageBase = CurrDevice->ImageBase;
  3790. #else
  3791. //
  3792. // NOTE : 05/13/2001 : LoaderFirmwarePermanent doesn't seem to work on non
  3793. // x86 platforsm (particularly IA64). Till this issue is resolved
  3794. // we have to allocate paged pool memory and replicate the disk
  3795. // image in loader heap tracked by "CurrDevice->ImageBase".
  3796. //
  3797. NewDevice->ImageBase = SpMemAlloc((SIZE_T)(CurrDevice->ImageSize));
  3798. if (NewDevice->ImageBase) {
  3799. memcpy(NewDevice->ImageBase,
  3800. CurrDevice->ImageBase,
  3801. (SIZE_T)(CurrDevice->ImageSize));
  3802. } else {
  3803. Status = STATUS_NO_MEMORY; // ran out of memory
  3804. break;
  3805. }
  3806. #endif // defined(_AMD64_) || defined(_X86_)
  3807. NewDevice->ImageSize = CurrDevice->ImageSize;
  3808. NewDevice->DeviceId = DeviceCount++;
  3809. //
  3810. // Insert the node at the head of the list
  3811. //
  3812. if (!DeviceList) {
  3813. DeviceList = NewDevice;
  3814. } else {
  3815. NewDevice->Next = DeviceList;
  3816. DeviceList = NewDevice;
  3817. }
  3818. CurrDevice = CurrDevice->Next;
  3819. }
  3820. //
  3821. // Sanity check
  3822. //
  3823. if (NT_SUCCESS(Status) && !DeviceList) {
  3824. Status = STATUS_UNSUCCESSFUL;
  3825. }
  3826. //
  3827. // Setup the parameters for the RAM disk driver
  3828. // to create appropriate device objects as
  3829. // needed by us
  3830. //
  3831. if (NT_SUCCESS(Status) && DeviceList) {
  3832. WCHAR KeyName[MAX_PATH];
  3833. UNICODE_STRING RamDiskDriverName;
  3834. OBJECT_ATTRIBUTES ObjectAttrs;
  3835. HANDLE RamDiskDriverHandle = NULL;
  3836. //
  3837. // Create the service key
  3838. //
  3839. swprintf(KeyName,
  3840. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\%ws",
  3841. RAMDISK_DRIVER_NAME
  3842. );
  3843. INIT_OBJA(&ObjectAttrs, &RamDiskDriverName, KeyName);
  3844. Status = ZwCreateKey(&RamDiskDriverHandle,
  3845. KEY_ALL_ACCESS,
  3846. &ObjectAttrs,
  3847. 0,
  3848. NULL,
  3849. REG_OPTION_NON_VOLATILE,
  3850. NULL);
  3851. if (NT_SUCCESS(Status)) {
  3852. UNICODE_STRING ParamName;
  3853. OBJECT_ATTRIBUTES ParamAttrs;
  3854. HANDLE ParamHandle = NULL;
  3855. //
  3856. // Create the parameters key
  3857. //
  3858. INIT_OBJA(&ParamAttrs, &ParamName, L"Parameters");
  3859. ParamAttrs.RootDirectory = RamDiskDriverHandle;
  3860. Status = ZwCreateKey(&ParamHandle,
  3861. KEY_ALL_ACCESS,
  3862. &ParamAttrs,
  3863. 0,
  3864. NULL,
  3865. REG_OPTION_NON_VOLATILE,
  3866. NULL);
  3867. if (NT_SUCCESS(Status)) {
  3868. WCHAR ValueStr[MAX_PATH];
  3869. PVIRTUAL_OEM_SOURCE_DEVICE CurrDevice = DeviceList;
  3870. //
  3871. // Create the regsitry values indicating the virtual
  3872. // devices for the Ram drive
  3873. //
  3874. while (CurrDevice) {
  3875. UNICODE_STRING ValueName;
  3876. BYTE Value[MAX_PATH * 2];
  3877. PBYTE ValuePtr = (PBYTE)Value;
  3878. ULONG ValueSize;
  3879. ULONGLONG ImageBase = (ULONGLONG)(ULONG_PTR)(CurrDevice->ImageBase);
  3880. ULONG ImageSize = (ULONG)(CurrDevice->ImageSize);
  3881. swprintf(ValueStr,
  3882. L"%ws%d",
  3883. MS_RAMDISK_DRIVER_PARAM,
  3884. CurrDevice->DeviceId);
  3885. memcpy(ValuePtr, &ImageBase, sizeof(ULONGLONG));
  3886. ValuePtr += sizeof(ULONGLONG);
  3887. memcpy(ValuePtr, &ImageSize, sizeof(ULONG));
  3888. ValuePtr += sizeof(ULONG);
  3889. ValueSize = (ULONG)(ULONG_PTR)(ValuePtr - Value);
  3890. RtlInitUnicodeString(&ValueName, ValueStr);
  3891. Status = ZwSetValueKey(ParamHandle,
  3892. &ValueName,
  3893. 0,
  3894. REG_BINARY,
  3895. Value,
  3896. ValueSize);
  3897. if (!NT_SUCCESS(Status)) {
  3898. break;
  3899. }
  3900. //
  3901. // process next device
  3902. //
  3903. CurrDevice = CurrDevice->Next;
  3904. }
  3905. ZwClose(ParamHandle);
  3906. }
  3907. ZwClose(RamDiskDriverHandle);
  3908. }
  3909. }
  3910. //
  3911. // Initialize the return value only if we are successful
  3912. //
  3913. if (NT_SUCCESS(Status)) {
  3914. *SourceDevices = DeviceList;
  3915. }
  3916. } else {
  3917. *SourceDevices = NULL;
  3918. }
  3919. }
  3920. return Status;
  3921. }