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

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