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

2119 lines
66 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. mapper.c
  5. Abstract:
  6. This module contains the code that manipulates the ARC firmware
  7. tree and other elements in the registry.
  8. Author:
  9. Bob Rinne (BobRi) 15-Oct-1994
  10. Environment:
  11. Kernel mode
  12. Revision History :
  13. --*/
  14. #include "pnpmgrp.h"
  15. #pragma hdrstop
  16. #ifdef POOL_TAGGING
  17. #undef ExAllocatePool
  18. #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'rpaM')
  19. #endif
  20. //
  21. // This contains information obtained by checking the firmware
  22. // tree of the registry
  23. //
  24. typedef struct _FIRMWARE_CONFIGURATION {
  25. struct _FIRMWARE_CONFIGURATION *Next;
  26. INTERFACE_TYPE BusType;
  27. ULONG BusNumber;
  28. CONFIGURATION_TYPE ControllerType;
  29. ULONG ControllerNumber;
  30. CONFIGURATION_TYPE PeripheralType;
  31. ULONG PeripheralNumber;
  32. ULONG NumberBases;
  33. ULONG ResourceDescriptorSize;
  34. PVOID ResourceDescriptor;
  35. ULONG IdentifierLength;
  36. ULONG IdentifierType;
  37. PVOID Identifier;
  38. WCHAR const* PnPId;
  39. BOOLEAN NewlyCreated;
  40. } FIRMWARE_CONFIGURATION, *PFIRMWARE_CONFIGURATION;
  41. //
  42. // Device extension information
  43. //
  44. typedef struct _DEVICE_EXTENSION {
  45. PDEVICE_OBJECT DeviceObject;
  46. PDRIVER_OBJECT DriverObject;
  47. INTERFACE_TYPE InterfaceType;
  48. ULONG BusNumber;
  49. PFIRMWARE_CONFIGURATION FirmwareList;
  50. } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
  51. //
  52. // mapping table from firmware to enum
  53. //
  54. typedef struct _FIRMWARE_IDENT_TO_PNP_ID {
  55. PWCHAR FirmwareName;
  56. PWCHAR PnPId;
  57. } FIRMWARE_IDENT_TO_PNP_ID, *PFIRMWARE_IDENT_TO_PNP_ID;
  58. //
  59. // table to hold seed information for a firmware tree entry.
  60. //
  61. #define OPTIONS_NONE 0x00000000
  62. #define OPTIONS_INSERT_PNP_ID 0x00000001
  63. #define OPTIONS_INSERT_DEVICEDESC 0x00000002
  64. #define OPTIONS_INSERT_COMPATIBLE_IDS 0x00000004
  65. #define OPTIONS_INSERT_PHANTOM_MARKER 0x00000008
  66. typedef struct _MAPPER_SEED {
  67. PWCHAR ValueName;
  68. ULONG ValueType;
  69. ULONG DwordValueContent;
  70. ULONG Options;
  71. } MAPPER_SEED, *PMAPPER_SEED;
  72. //
  73. // table to hold key names and attributes for construction
  74. // in the root enumerator tree
  75. //
  76. #define KEY_SEED_REQUIRED 0x00000000
  77. #define KEY_SEED_DEVICE_PARAMETERS 0x00000001
  78. typedef struct _KEY_SEED {
  79. PWCHAR KeyName;
  80. ULONG Attribute;
  81. ULONG Options;
  82. } KEY_SEED, *PKEY_SEED;
  83. //
  84. // All the data here is INIT only
  85. //
  86. #ifdef ALLOC_DATA_PRAGMA
  87. #pragma const_seg("INITCONST")
  88. #pragma data_seg("INITDATA")
  89. #endif
  90. DEVICE_EXTENSION MapperDeviceExtension;
  91. //
  92. // This table is used to translate the firmware tree information
  93. // to the root enumerator PNP id for keyboard devices.
  94. //
  95. const FIRMWARE_IDENT_TO_PNP_ID KeyboardMap[] = {
  96. L"XT_83KEY", L"*PNP0300",
  97. L"PCAT_86KEY", L"*PNP0301",
  98. L"PCXT_84KEY", L"*PNP0302",
  99. L"XT_84KEY", L"*PNP0302",
  100. L"101-KEY", L"*PNP0303",
  101. L"OLI_83KEY", L"*PNP0304",
  102. L"ATT_301", L"*PNP0304",
  103. L"OLI_102KEY", L"*PNP0305",
  104. L"OLI_86KEY", L"*PNP0306",
  105. L"OLI_A101_102KEY", L"*PNP0309",
  106. L"ATT_302", L"*PNP030a",
  107. L"PCAT_ENHANCED", L"*PNP030b",
  108. L"PC98_106KEY", L"*nEC1300",
  109. L"PC98_LaptopKEY", L"*nEC1300",
  110. L"PC98_N106KEY", L"*PNP0303",
  111. NULL, NULL
  112. };
  113. #define PS2_KEYBOARD_COMPATIBLE_ID L"PS2_KEYBOARD"
  114. #define PS2_MOUSE_COMPATIBLE_ID L"PS2_MOUSE"
  115. //
  116. // This table is used to translate the firmware tree information
  117. // to the root enumerator PNP id for pointer devices.
  118. //
  119. const FIRMWARE_IDENT_TO_PNP_ID PointerMap[] = {
  120. L"PS2 MOUSE", L"*PNP0F0E",
  121. L"SERIAL MOUSE", L"*PNP0F0C",
  122. L"MICROSOFT PS2 MOUSE", L"*PNP0F03",
  123. L"LOGITECH PS2 MOUSE", L"*PNP0F12",
  124. L"MICROSOFT INPORT MOUSE", L"*PNP0F02",
  125. L"MICROSOFT SERIAL MOUSE", L"*PNP0F01",
  126. L"MICROSOFT BALLPOINT SERIAL MOUSE", L"*PNP0F09",
  127. L"LOGITECH SERIAL MOUSE", L"*PNP0F08",
  128. L"MICROSOFT BUS MOUSE", L"*PNP0F00",
  129. L"NEC PC-9800 BUS MOUSE", L"*nEC1F00",
  130. NULL, NULL
  131. };
  132. //
  133. // the MapperValueSeed table is a NULL terminated table (i.e. the name
  134. // pointer is NULL) that contains the list of values and their type
  135. // for insertion in a newly created root enumerator key.
  136. //
  137. const MAPPER_SEED MapperValueSeed[] = {
  138. REGSTR_VALUE_HARDWAREID, REG_MULTI_SZ, 0, OPTIONS_INSERT_PNP_ID,
  139. REGSTR_VALUE_COMPATIBLEIDS, REG_MULTI_SZ, 0, OPTIONS_INSERT_COMPATIBLE_IDS,
  140. REGSTR_VAL_FIRMWAREIDENTIFIED, REG_DWORD, 1, OPTIONS_NONE,
  141. REGSTR_VAL_DEVDESC, REG_SZ, 0, OPTIONS_INSERT_DEVICEDESC,
  142. REGSTR_VAL_PHANTOM, REG_DWORD, 1, OPTIONS_INSERT_PHANTOM_MARKER,
  143. NULL, 0, 0, 0
  144. };
  145. //
  146. // the MapperKeySeed table is a NULL terminated table (i.e. the name
  147. // pointer is NULL) that contains the list of keys to and their
  148. // attributes (volatile or non-volatile) for keys to be created under
  149. // a newly created root enumerator key.
  150. //
  151. // The preceeding backslash is required on all entries in this table.
  152. //
  153. const KEY_SEED MapperKeySeed[] = {
  154. L"\\Control", REG_OPTION_VOLATILE, KEY_SEED_REQUIRED,
  155. L"\\LogConf", REG_OPTION_NON_VOLATILE, KEY_SEED_REQUIRED,
  156. L"", REG_OPTION_NON_VOLATILE, KEY_SEED_DEVICE_PARAMETERS,
  157. NULL, 0, 0
  158. };
  159. //
  160. // SerialId is used as the PNP id for all serial controllers.
  161. // NOTE: there is no code to detect presense of a 16550.
  162. //
  163. const WCHAR SerialId[] = L"*PNP0501"; // RDR should be two entries. *PNP0501 is 16550
  164. //
  165. // ParallelId is used as the PNP id for all parallel controllers.
  166. // NOTE: there is no code to detect presense of ECP support.
  167. //
  168. const WCHAR ParallelId[] = L"*PNP0400"; // RDR should be two entries. *PNP0401 is ECP
  169. //
  170. // FloppyId is used as the PNP id for all floppy peripherals.
  171. //
  172. const WCHAR FloppyId[] = L"*PNP0700";
  173. //
  174. // ATAId is here, but not used - there is nothing in the firmware
  175. // tree for the IDE controller.
  176. //
  177. const WCHAR ATAId[] = L"*PNP0600";
  178. //
  179. // Proto type declarations
  180. //
  181. FIRMWARE_IDENT_TO_PNP_ID const*
  182. MapperFindIdentMatch(
  183. FIRMWARE_IDENT_TO_PNP_ID const* IdentTable,
  184. PWCHAR String
  185. );
  186. WCHAR const*
  187. MapperTranslatePnPId(
  188. CONFIGURATION_TYPE PeripheralType,
  189. PKEY_VALUE_FULL_INFORMATION Identifier
  190. );
  191. NTSTATUS
  192. MapperPeripheralCallback(
  193. IN PVOID Context,
  194. IN PUNICODE_STRING PathName,
  195. IN INTERFACE_TYPE BusType,
  196. IN ULONG BusNumber,
  197. IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
  198. IN CONFIGURATION_TYPE ControllerType,
  199. IN ULONG ControllerNumber,
  200. IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
  201. IN CONFIGURATION_TYPE PeripheralType,
  202. IN ULONG PeripheralNumber,
  203. IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
  204. );
  205. NTSTATUS
  206. MapperCallback(
  207. IN PVOID Context,
  208. IN PUNICODE_STRING PathName,
  209. IN INTERFACE_TYPE BusType,
  210. IN ULONG BusNumber,
  211. IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
  212. IN CONFIGURATION_TYPE ControllerType,
  213. IN ULONG ControllerNumber,
  214. IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
  215. IN CONFIGURATION_TYPE PeripheralType,
  216. IN ULONG PeripheralNumber,
  217. IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
  218. );
  219. VOID
  220. MapperMarkKey(
  221. IN HANDLE Handle,
  222. IN PUNICODE_STRING PathName,
  223. IN PFIRMWARE_CONFIGURATION FirmwareEntry
  224. );
  225. VOID
  226. MapperSeedKey(
  227. IN HANDLE Handle,
  228. IN PUNICODE_STRING PathName,
  229. IN PFIRMWARE_CONFIGURATION FirmwareEntry,
  230. IN BOOLEAN DeviceIsPhantom
  231. );
  232. PCM_RESOURCE_LIST
  233. MapperAdjustResourceList (
  234. IN PCM_RESOURCE_LIST ResourceList,
  235. IN WCHAR const* PnPId,
  236. IN OUT PULONG Size
  237. );
  238. NTSTATUS
  239. ComPortDBAdd(
  240. IN HANDLE DeviceParamKey,
  241. IN PWSTR PortName
  242. );
  243. #ifdef ALLOC_PRAGMA
  244. #pragma alloc_text(INIT, MapperFindIdentMatch)
  245. #pragma alloc_text(INIT, MapperTranslatePnPId)
  246. #pragma alloc_text(INIT, MapperPeripheralCallback)
  247. #pragma alloc_text(INIT, MapperCallback)
  248. #pragma alloc_text(INIT, MapperProcessFirmwareTree)
  249. #pragma alloc_text(INIT, MapperMarkKey)
  250. #pragma alloc_text(INIT, MapperSeedKey)
  251. #pragma alloc_text(INIT, MapperFreeList)
  252. #pragma alloc_text(INIT, MapperConstructRootEnumTree)
  253. #pragma alloc_text(INIT, MapperAdjustResourceList)
  254. #pragma alloc_text(INIT, ComPortDBAdd)
  255. #pragma alloc_text(INIT, MapperPhantomizeDetectedComPorts)
  256. #endif
  257. FIRMWARE_IDENT_TO_PNP_ID const*
  258. MapperFindIdentMatch(
  259. FIRMWARE_IDENT_TO_PNP_ID const* IdentTable,
  260. PWCHAR String
  261. )
  262. /*++
  263. Routine Description:
  264. Given a table of strings to match, find the match for
  265. the identifier given.
  266. Arguments:
  267. Return Value:
  268. A pointer to the ident table entry for the match if found
  269. NULL if not found.
  270. --*/
  271. {
  272. FIRMWARE_IDENT_TO_PNP_ID const* entry;
  273. entry = IdentTable;
  274. while (entry->FirmwareName) {
  275. if (!wcscmp(String, entry->FirmwareName)) {
  276. return entry;
  277. }
  278. entry++;
  279. }
  280. return NULL;
  281. }
  282. WCHAR const*
  283. MapperTranslatePnPId(
  284. CONFIGURATION_TYPE PeripheralType,
  285. PKEY_VALUE_FULL_INFORMATION Identifier
  286. )
  287. /*++
  288. Routine Description:
  289. Given the peripheral type and a location in the firmware tree
  290. this routine will determine the PnP Id to be used when constructing
  291. the root enumeration portion of the registry.
  292. Arguments:
  293. PeripheralType - the type of item being translated (keyboard, mouse, etc)
  294. PathName - the registry path name into the firmware tree for
  295. this device.
  296. Return Value:
  297. A pointer to the PnP Id string if a map is found.
  298. --*/
  299. {
  300. FIRMWARE_IDENT_TO_PNP_ID const* identMap;
  301. PWSTR identifierString = NULL;
  302. WCHAR const* idStr;
  303. if (Identifier) {
  304. identifierString = (PWSTR)((PUCHAR)Identifier + Identifier->DataOffset);
  305. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  306. "Mapper: identifier = %ws\n\tType = ",
  307. identifierString));
  308. }
  309. idStr = NULL;
  310. switch (PeripheralType) {
  311. case DiskController:
  312. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  313. "%s (%d)\n",
  314. "DiskController",
  315. PeripheralType));
  316. idStr = FloppyId;
  317. break;
  318. case SerialController:
  319. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  320. "%s (%d)\n",
  321. "SerialController",
  322. PeripheralType));
  323. idStr = SerialId;
  324. break;
  325. case ParallelController:
  326. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  327. "%s (%d)\n",
  328. "ParallelController",
  329. PeripheralType));
  330. idStr = ParallelId;
  331. break;
  332. case PointerController:
  333. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  334. "%s (%d)\n",
  335. "PointerController",
  336. PeripheralType));
  337. idStr = PointerMap[0].PnPId;
  338. break;
  339. case KeyboardController:
  340. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  341. "%s (%d)\n",
  342. "KeyboardController",
  343. PeripheralType));
  344. idStr = KeyboardMap[0].PnPId;
  345. break;
  346. case DiskPeripheral:
  347. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  348. "%s (%d)\n",
  349. "DiskPeripheral",
  350. PeripheralType));
  351. break;
  352. case FloppyDiskPeripheral:
  353. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  354. "%s (%d)\n",
  355. "FloppyDiskPeripheral",
  356. PeripheralType));
  357. idStr = FloppyId;
  358. break;
  359. case PointerPeripheral:
  360. if (identifierString) {
  361. identMap = MapperFindIdentMatch(PointerMap, identifierString);
  362. if (identMap) {
  363. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  364. "%ws\n",
  365. identMap->PnPId));
  366. idStr = identMap->PnPId;
  367. } else {
  368. IopDbgPrint((IOP_MAPPER_WARNING_LEVEL,
  369. "Mapper: No pointer match found for %ws\n", identifierString));
  370. }
  371. } else {
  372. IopDbgPrint((IOP_MAPPER_WARNING_LEVEL,
  373. "Mapper: No identifier specified\n"));
  374. }
  375. break;
  376. case KeyboardPeripheral:
  377. if (identifierString) {
  378. identMap = MapperFindIdentMatch(KeyboardMap, identifierString);
  379. if (identMap) {
  380. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  381. "%ws\n",
  382. identMap->PnPId));
  383. idStr = identMap->PnPId;
  384. } else {
  385. IopDbgPrint((IOP_MAPPER_WARNING_LEVEL,
  386. "Mapper: No keyboard match found for %ws\n", identifierString));
  387. }
  388. } else {
  389. IopDbgPrint((IOP_MAPPER_WARNING_LEVEL,
  390. "Mapper: No identifier specified\n"));
  391. }
  392. break;
  393. default:
  394. IopDbgPrint((IOP_MAPPER_WARNING_LEVEL,
  395. "Mapper: Unknown device (%d)\n",
  396. PeripheralType));
  397. break;
  398. }
  399. return idStr;
  400. }
  401. NTSTATUS
  402. MapperPeripheralCallback(
  403. IN PVOID Context,
  404. IN PUNICODE_STRING PathName,
  405. IN INTERFACE_TYPE BusType,
  406. IN ULONG BusNumber,
  407. IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
  408. IN CONFIGURATION_TYPE ControllerType,
  409. IN ULONG ControllerNumber,
  410. IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
  411. IN CONFIGURATION_TYPE PeripheralType,
  412. IN ULONG PeripheralNumber,
  413. IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
  414. )
  415. /*++
  416. Routine Description:
  417. This routine is used to acquire firmware tree information about
  418. pointer devices in the system.
  419. Arguments:
  420. Context - Pointer to the device extension.
  421. PathName - unicode registry path.
  422. BusType - Internal, Isa, ...
  423. BusNumber - Which bus if we are on a multibus system.
  424. BusInformation - Configuration information about the bus. Not Used.
  425. ControllerType - serial or ata disk.
  426. ControllerNumber - Which controller if there is more than one
  427. controller in the system.
  428. ControllerInformation - Array of pointers to the three pieces of
  429. registry information.
  430. PeripheralType - Undefined for this call.
  431. PeripheralNumber - Undefined for this call.
  432. PeripheralInformation - Undefined for this call.
  433. Return Value:
  434. STATUS_SUCCESS if everything went ok, or STATUS_INSUFFICIENT_RESOURCES
  435. if it couldn't map the base csr or acquire the device object, or
  436. all of the resource information couldn't be acquired.
  437. --*/
  438. {
  439. PFIRMWARE_CONFIGURATION firmwareEntry = Context;
  440. PKEY_VALUE_FULL_INFORMATION information;
  441. ULONG dataLength;
  442. PWCHAR ptr;
  443. PVOID temp;
  444. UNREFERENCED_PARAMETER( BusType );
  445. UNREFERENCED_PARAMETER( BusNumber );
  446. UNREFERENCED_PARAMETER( PathName );
  447. UNREFERENCED_PARAMETER( BusInformation );
  448. UNREFERENCED_PARAMETER( ControllerType );
  449. UNREFERENCED_PARAMETER( ControllerNumber );
  450. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  451. "Mapper: peripheral registry location is\n %ws\n",
  452. PathName->Buffer));
  453. if (!ControllerInformation) {
  454. IopDbgPrint((IOP_MAPPER_VERBOSE_LEVEL,
  455. "Mapper: No component information\n"));
  456. }
  457. if (!PeripheralInformation) {
  458. IopDbgPrint((IOP_MAPPER_VERBOSE_LEVEL,
  459. "Mapper: No peripheral information\n"));
  460. return STATUS_SUCCESS;
  461. }
  462. //
  463. // Map the PnP Id for this device.
  464. //
  465. if (PeripheralInformation[IoQueryDeviceIdentifier]) {
  466. information = PeripheralInformation[IoQueryDeviceIdentifier];
  467. firmwareEntry->PnPId = MapperTranslatePnPId(PeripheralType, information);
  468. if (firmwareEntry->PnPId) {
  469. //
  470. // Remember the peripheral's identifier (if it has one, and it's a REG_SZ value)
  471. // for use as the default PnP device description.
  472. //
  473. if (((dataLength = information->DataLength) > sizeof(WCHAR)) &&
  474. (information->Type == REG_SZ)) {
  475. ptr = (PWCHAR) ((PUCHAR)information + information->DataOffset);
  476. if (*ptr) {
  477. temp = ExAllocatePool(NonPagedPool, dataLength);
  478. if (temp) {
  479. //
  480. // If there's already an identifier here (from the peripheral's
  481. // controller) then wipe it out.
  482. //
  483. if(firmwareEntry->Identifier) {
  484. ExFreePool(firmwareEntry->Identifier);
  485. }
  486. //
  487. // Move the data
  488. //
  489. firmwareEntry->Identifier = temp;
  490. firmwareEntry->IdentifierType = information->Type;
  491. firmwareEntry->IdentifierLength = dataLength;
  492. RtlCopyMemory(temp, ptr, dataLength);
  493. }
  494. }
  495. }
  496. }
  497. }
  498. //
  499. // Save the ordinals for the peripheral type and number
  500. //
  501. firmwareEntry->PeripheralType = PeripheralType;
  502. firmwareEntry->PeripheralNumber = PeripheralNumber;
  503. return STATUS_SUCCESS;
  504. }
  505. NTSTATUS
  506. MapperCallback(
  507. IN PVOID Context,
  508. IN PUNICODE_STRING PathName,
  509. IN INTERFACE_TYPE BusType,
  510. IN ULONG BusNumber,
  511. IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
  512. IN CONFIGURATION_TYPE ControllerType,
  513. IN ULONG ControllerNumber,
  514. IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
  515. IN CONFIGURATION_TYPE PeripheralType,
  516. IN ULONG PeripheralNumber,
  517. IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
  518. )
  519. /*++
  520. Routine Description:
  521. This routine is used to acquire firmware tree information about
  522. pointer devices in the system.
  523. Arguments:
  524. Context - Pointer to the device extension.
  525. PathName - unicode registry path.
  526. BusType - Internal, Isa, ...
  527. BusNumber - Which bus if we are on a multibus system.
  528. BusInformation - Configuration information about the bus. Not Used.
  529. ControllerType - serial or ata disk.
  530. ControllerNumber - Which controller if there is more than one
  531. controller in the system.
  532. ControllerInformation - Array of pointers to the three pieces of
  533. registry information.
  534. PeripheralType - Undefined for this call.
  535. PeripheralNumber - Undefined for this call.
  536. PeripheralInformation - Undefined for this call.
  537. Return Value:
  538. STATUS_SUCCESS if everything went ok, or STATUS_INSUFFICIENT_RESOURCES
  539. if it couldn't map the base csr or acquire the device object, or
  540. all of the resource information couldn't be acquired.
  541. --*/
  542. {
  543. PDEVICE_EXTENSION deviceExtension = Context;
  544. PCM_FULL_RESOURCE_DESCRIPTOR controllerData;
  545. PKEY_VALUE_FULL_INFORMATION information;
  546. PFIRMWARE_CONFIGURATION firmwareEntry;
  547. CONFIGURATION_TYPE peripheralType;
  548. PUCHAR buffer;
  549. ULONG dataLength;
  550. UNREFERENCED_PARAMETER( PathName );
  551. UNREFERENCED_PARAMETER( BusInformation );
  552. UNREFERENCED_PARAMETER( PeripheralType );
  553. UNREFERENCED_PARAMETER( PeripheralNumber );
  554. UNREFERENCED_PARAMETER( PeripheralInformation );
  555. //
  556. // If entry is found, but there is no information just return
  557. //
  558. information = ControllerInformation[IoQueryDeviceConfigurationData];
  559. if (information == NULL) {
  560. return STATUS_SUCCESS;
  561. }
  562. dataLength = information->DataLength;
  563. if (dataLength == 0) {
  564. return STATUS_SUCCESS;
  565. }
  566. //
  567. // Setup to capture the information from the firmware tree
  568. //
  569. firmwareEntry = ExAllocatePool(NonPagedPool, sizeof(FIRMWARE_CONFIGURATION));
  570. if (!firmwareEntry) {
  571. return STATUS_INSUFFICIENT_RESOURCES;
  572. }
  573. RtlZeroMemory(firmwareEntry, sizeof(FIRMWARE_CONFIGURATION));
  574. //
  575. // Save information concerning the controller
  576. //
  577. firmwareEntry->ControllerType = ControllerType;
  578. firmwareEntry->ControllerNumber = ControllerNumber;
  579. firmwareEntry->BusNumber = BusNumber;
  580. firmwareEntry->BusType = BusType;
  581. //
  582. // Save the resource descriptor
  583. //
  584. buffer = firmwareEntry->ResourceDescriptor = ExAllocatePool(NonPagedPool,
  585. dataLength);
  586. if (!buffer) {
  587. ExFreePool(firmwareEntry);
  588. return STATUS_INSUFFICIENT_RESOURCES;
  589. }
  590. //
  591. // Save the configuration information on this controller.
  592. //
  593. controllerData = (PCM_FULL_RESOURCE_DESCRIPTOR)
  594. ((PUCHAR)information + information->DataOffset);
  595. RtlCopyMemory(buffer, controllerData, dataLength);
  596. firmwareEntry->ResourceDescriptorSize = dataLength;
  597. //
  598. // If there is a device identifier save it.
  599. //
  600. information = ControllerInformation[IoQueryDeviceIdentifier];
  601. if (information != NULL) {
  602. PWCHAR ptr;
  603. dataLength = information->DataLength;
  604. if (dataLength != 0) {
  605. ptr = (PWCHAR) ((PUCHAR)information + information->DataOffset);
  606. if (ControllerType == ParallelController) {
  607. PWCHAR tmpChar;
  608. //
  609. // Some extra mapping is performed here to
  610. // translate the firmware names to LPT names.
  611. //
  612. *ptr++ = (WCHAR) 'L';
  613. *ptr++ = (WCHAR) 'P';
  614. *ptr++ = (WCHAR) 'T';
  615. //
  616. // Find the number.
  617. //
  618. tmpChar = ptr;
  619. while (*tmpChar) {
  620. if ((*tmpChar >= (WCHAR) '0') &&
  621. (*tmpChar <= (WCHAR) '9')) {
  622. break;
  623. }
  624. tmpChar++;
  625. }
  626. if (*tmpChar) {
  627. while (*tmpChar) {
  628. *ptr++ = *tmpChar++;
  629. }
  630. *ptr = (WCHAR) 0;
  631. //
  632. // Update the datalength to be 4 wchars and eos and
  633. // restore the pointer.
  634. //
  635. ptr = (PWCHAR) ((PUCHAR)information + information->DataOffset);
  636. dataLength = 10;
  637. } else {
  638. dataLength = 0;
  639. IopDbgPrint((IOP_MAPPER_WARNING_LEVEL,
  640. "Mapper: no parallel port number!\n"));
  641. }
  642. }
  643. if (dataLength) {
  644. firmwareEntry->Identifier = ExAllocatePool(NonPagedPool,
  645. dataLength);
  646. if (firmwareEntry->Identifier) {
  647. //
  648. // Move the data
  649. //
  650. firmwareEntry->IdentifierType = information->Type;
  651. firmwareEntry->IdentifierLength = dataLength;
  652. RtlCopyMemory(firmwareEntry->Identifier, ptr, dataLength);
  653. }
  654. }
  655. }
  656. }
  657. //
  658. // For some controllers, search the peripheral information
  659. //
  660. switch (ControllerType) {
  661. case SerialController:
  662. case ParallelController:
  663. //
  664. // Don't look for a peripheral.
  665. //
  666. peripheralType = (CONFIGURATION_TYPE) 0;
  667. break;
  668. case DiskController:
  669. peripheralType = FloppyDiskPeripheral;
  670. break;
  671. case KeyboardController:
  672. peripheralType = KeyboardPeripheral;
  673. break;
  674. case PointerController:
  675. peripheralType = PointerPeripheral;
  676. break;
  677. default:
  678. peripheralType = (CONFIGURATION_TYPE) 0;
  679. break;
  680. }
  681. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  682. "Mapper: registry location is\n %ws\n",
  683. PathName->Buffer));
  684. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  685. "Mapper: ControllerInformation[] -\n\tIdent: %x -\n\tData: %x -\n\tInformation: %x\n",
  686. ControllerInformation[0],
  687. ControllerInformation[1],
  688. ControllerInformation[2]));
  689. if (peripheralType) {
  690. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  691. "Mapper: searching for peripheral type %d\n",
  692. peripheralType));
  693. IoQueryDeviceDescription(&BusType,
  694. &BusNumber,
  695. &ControllerType,
  696. &ControllerNumber,
  697. &peripheralType,
  698. NULL,
  699. MapperPeripheralCallback,
  700. firmwareEntry);
  701. }
  702. //
  703. // firmwareEntry->PnPId will be NULL if there are no peripherals of this
  704. // type in the tree or if the peripheral's description doesn't match one of
  705. // those in our table.
  706. //
  707. // firmwareEntry->PeripheralType will be equal to peripheralType if we found
  708. // one of the proper type regardless of whether or not it is in the table.
  709. //
  710. // So this test just ensures that we fallback to the controller IDs in the
  711. // case were there is no peripheral entry. If there is a peripheral entry
  712. // that we don't understand we will suppress the entire node.
  713. //
  714. // This prevents creating devices with hw ids of bogus as we were seeing on
  715. // the SGI x86 ARC machines.
  716. //
  717. if (!firmwareEntry->PnPId && firmwareEntry->PeripheralType == 0) {
  718. //
  719. // Attempt to get PnPId from the controller type.
  720. //
  721. firmwareEntry->PnPId = MapperTranslatePnPId(ControllerType, NULL);
  722. if (!firmwareEntry->PnPId) {
  723. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  724. "Mapper: NO PnP Id for\n ==> %ws\n",
  725. PathName->Buffer));
  726. }
  727. }
  728. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  729. "Mapper: constructed name %d_%d_%d_%d_%d_%d\n",
  730. firmwareEntry->BusType,
  731. firmwareEntry->BusNumber,
  732. firmwareEntry->ControllerType,
  733. firmwareEntry->ControllerNumber,
  734. firmwareEntry->PeripheralType,
  735. firmwareEntry->PeripheralNumber));
  736. if (firmwareEntry->PnPId) {
  737. //
  738. // Link into chain of entries.
  739. //
  740. firmwareEntry->Next = deviceExtension->FirmwareList;
  741. deviceExtension->FirmwareList = firmwareEntry;
  742. } else {
  743. //
  744. // No map found - don't remember this entry.
  745. //
  746. ExFreePool(buffer);
  747. if(firmwareEntry->Identifier) {
  748. ExFreePool(firmwareEntry->Identifier);
  749. }
  750. ExFreePool(firmwareEntry);
  751. }
  752. return STATUS_SUCCESS;
  753. }
  754. VOID
  755. MapperProcessFirmwareTree(
  756. IN BOOLEAN OnlyProcessSerialPorts
  757. )
  758. /*++
  759. Routine Description:
  760. Query the information in the firmware tree to know what
  761. system board devices were located. This will cause a FirmwareList
  762. to be created on the device extention passed.
  763. Arguments:
  764. OnlyProcessSerialPorts - if non-zero, then we'll only look at serial ports.
  765. This is done on ACPI machines where, in general, we don't want to pay
  766. attention to ntdetect/firmware information (but we have to for serial
  767. ports so that legacy add-in ISA serial ports and modems are detected
  768. automatically as in previous versions of NT as well as Win9x).
  769. Return Value:
  770. None
  771. --*/
  772. {
  773. INTERFACE_TYPE interfaceType;
  774. ULONG index;
  775. CONFIGURATION_TYPE sc;
  776. CONFIGURATION_TYPE controllerTypes[] = { PointerController,
  777. KeyboardController,
  778. ParallelController,
  779. DiskController,
  780. FloppyDiskPeripheral,
  781. SerialController // must be last
  782. };
  783. #define CONTROLLER_TYPES_COUNT (sizeof(controllerTypes) / sizeof(controllerTypes[0]))
  784. PAGED_CODE();
  785. //
  786. // Locate all firmware controller information and save its resource usage.
  787. //
  788. // It's pretty inefficient to be going through all interface types, when we
  789. // really only care about a very small subset of non-PnP buses (e.g., ISA,
  790. // EISA, maybe Internal).
  791. //
  792. for (interfaceType = 0; interfaceType < MaximumInterfaceType; interfaceType++) {
  793. IopDbgPrint((IOP_MAPPER_VERBOSE_LEVEL,
  794. "Mapper: searching on interface ===> %d\n",
  795. interfaceType));
  796. if(OnlyProcessSerialPorts) {
  797. //
  798. // Start out at the last element of the array, so we only process
  799. // SerialControllers.
  800. //
  801. index = CONTROLLER_TYPES_COUNT - 1;
  802. } else {
  803. index = 0;
  804. }
  805. for ( ; index < CONTROLLER_TYPES_COUNT; index++) {
  806. sc = controllerTypes[index];
  807. IoQueryDeviceDescription(&interfaceType,
  808. NULL,
  809. &sc,
  810. NULL,
  811. NULL,
  812. NULL,
  813. MapperCallback,
  814. &MapperDeviceExtension);
  815. }
  816. }
  817. }
  818. VOID
  819. MapperMarkKey(
  820. IN HANDLE Handle,
  821. IN PUNICODE_STRING PathName,
  822. IN PFIRMWARE_CONFIGURATION FirmwareEntry
  823. )
  824. /*++
  825. Routine Description:
  826. Record in the root enum key that the firmware mapper found this entry.
  827. Migrate configuration information entries.
  828. Arguments:
  829. Handle - handle to the key
  830. PathName - base path name to this key
  831. FirmwareEntry - information from the firmware tree.
  832. Return Value:
  833. None
  834. --*/
  835. {
  836. OBJECT_ATTRIBUTES objectAttributes;
  837. PCM_RESOURCE_LIST resourceList;
  838. UNICODE_STRING unicodeName;
  839. NTSTATUS status;
  840. HANDLE subKeyHandle;
  841. PWCHAR wcptr;
  842. ULONG disposition;
  843. ULONG buffer;
  844. USHORT originalLength;
  845. //
  846. // Mark that this entry was in the firmware tree.
  847. //
  848. buffer = 1;
  849. PiWstrToUnicodeString(&unicodeName, REGSTR_VAL_FIRMWAREIDENTIFIED);
  850. ZwSetValueKey(Handle,
  851. &unicodeName,
  852. 0,
  853. REG_DWORD,
  854. &buffer,
  855. sizeof(ULONG));
  856. //
  857. // Create the control subkey
  858. //
  859. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  860. "Mapper: marking existing key\n"));
  861. originalLength = PathName->Length;
  862. wcptr = (PWCHAR) ((PUCHAR)PathName->Buffer + PathName->Length);
  863. wcptr++; // locate eos
  864. //
  865. // Build the volatile control key
  866. //
  867. InitializeObjectAttributes(&objectAttributes,
  868. PathName,
  869. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  870. NULL,
  871. NULL);
  872. RtlAppendUnicodeToString(PathName, L"\\Control");
  873. status = ZwCreateKey(&subKeyHandle,
  874. KEY_READ | KEY_WRITE,
  875. &objectAttributes,
  876. 0,
  877. NULL,
  878. REG_OPTION_VOLATILE,
  879. &disposition);
  880. if (NT_SUCCESS(status)) {
  881. //
  882. // Create the found by firmware volatile.
  883. //
  884. buffer = 1;
  885. PiWstrToUnicodeString(&unicodeName, REGSTR_VAL_FIRMWAREMEMBER);
  886. ZwSetValueKey(subKeyHandle,
  887. &unicodeName,
  888. 0,
  889. REG_DWORD,
  890. &buffer,
  891. sizeof(ULONG));
  892. ZwClose(subKeyHandle);
  893. } else {
  894. //
  895. // ignore failures
  896. //
  897. IopDbgPrint((IOP_MAPPER_WARNING_LEVEL,
  898. "Mapper: failed to mark control key %x\n",
  899. status));
  900. }
  901. //
  902. // if there is a resource descriptor, restore path and open LogConf key.
  903. //
  904. if (FirmwareEntry->ResourceDescriptor) {
  905. PathName->Length = originalLength;
  906. *wcptr = (WCHAR) 0;
  907. InitializeObjectAttributes(&objectAttributes,
  908. PathName,
  909. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  910. NULL,
  911. NULL);
  912. RtlAppendUnicodeToString(PathName, L"\\LogConf");
  913. status = ZwCreateKey(&subKeyHandle,
  914. KEY_READ | KEY_WRITE,
  915. &objectAttributes,
  916. 0,
  917. NULL,
  918. REG_OPTION_VOLATILE,
  919. &disposition);
  920. if (NT_SUCCESS(status)) {
  921. ULONG size;
  922. //
  923. // two entries need to be made:
  924. // BootConfig:REG_RESOURCE_LIST
  925. // BasicConfigVector:REG_RESOURCE_REQUIREMENTS_LIST
  926. //
  927. size = sizeof(CM_RESOURCE_LIST) -
  928. sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
  929. FirmwareEntry->ResourceDescriptorSize;
  930. resourceList = ExAllocatePool(NonPagedPool, size);
  931. if (resourceList) {
  932. resourceList->Count = 1;
  933. RtlCopyMemory(&resourceList->List[0],
  934. FirmwareEntry->ResourceDescriptor,
  935. FirmwareEntry->ResourceDescriptorSize);
  936. resourceList = MapperAdjustResourceList (
  937. resourceList,
  938. FirmwareEntry->PnPId,
  939. &size
  940. );
  941. PiWstrToUnicodeString(&unicodeName,
  942. L"BootConfig");
  943. ZwSetValueKey(subKeyHandle,
  944. &unicodeName,
  945. 0,
  946. REG_RESOURCE_LIST,
  947. resourceList,
  948. size);
  949. ExFreePool(resourceList);
  950. }
  951. ZwClose(subKeyHandle);
  952. } else {
  953. //
  954. // ignore errors
  955. //
  956. IopDbgPrint((IOP_MAPPER_WARNING_LEVEL,
  957. "Mapper: failed to update logconf key %x\n",
  958. status));
  959. }
  960. }
  961. //
  962. // Restore path passed in.
  963. //
  964. PathName->Length = originalLength;
  965. *wcptr = (WCHAR) 0;
  966. }
  967. VOID
  968. MapperSeedKey(
  969. IN HANDLE Handle,
  970. IN PUNICODE_STRING PathName,
  971. IN PFIRMWARE_CONFIGURATION FirmwareEntry,
  972. IN BOOLEAN DeviceIsPhantom
  973. )
  974. /*++
  975. Routine Description:
  976. This routine seeds a registry key with enough information
  977. to get PnP to run the class installer on the devnode.
  978. Arguments:
  979. Handle - handle to the key
  980. PathName - base path name to this key
  981. FirmwareEntry - information from the firmware tree
  982. DeviceIsPhantom - if non-zero, add "Phantom" value entry so the root
  983. enumerator will skip this device instance (i.e., not turn it into a
  984. devnode)
  985. Return Value:
  986. None
  987. --*/
  988. {
  989. #define SEED_BUFFER_SIZE (512 * sizeof(WCHAR))
  990. UNICODE_STRING unicodeName;
  991. OBJECT_ATTRIBUTES objectAttributes;
  992. MAPPER_SEED const* valueSeed;
  993. KEY_SEED const* keySeed;
  994. NTSTATUS status;
  995. HANDLE subKeyHandle;
  996. WCHAR const* pnpid;
  997. PWCHAR buffer;
  998. PWCHAR wcptr;
  999. ULONG disposition;
  1000. ULONG size;
  1001. USHORT originalLength;
  1002. buffer = ExAllocatePool(NonPagedPool, SEED_BUFFER_SIZE);
  1003. if (!buffer) {
  1004. return;
  1005. }
  1006. RtlZeroMemory(buffer, SEED_BUFFER_SIZE);
  1007. //
  1008. // Create subkeys.
  1009. //
  1010. originalLength = PathName->Length;
  1011. wcptr = (PWCHAR) ((PUCHAR)PathName->Buffer + PathName->Length);
  1012. for (keySeed = MapperKeySeed; keySeed->KeyName; keySeed++) {
  1013. //
  1014. // Reset the base path for the next key to seed.
  1015. //
  1016. *wcptr = (WCHAR) 0;
  1017. PathName->Length = originalLength;
  1018. RtlAppendUnicodeToString(PathName, keySeed->KeyName);
  1019. //
  1020. // Only build a device parameters key if there is something
  1021. // to put in the key (i.e., this is a serial or parallel port).
  1022. //
  1023. if (keySeed->Options & KEY_SEED_DEVICE_PARAMETERS) {
  1024. if (((FirmwareEntry->ControllerType != SerialController) && (FirmwareEntry->ControllerType != ParallelController)) ||
  1025. !FirmwareEntry->Identifier) {
  1026. continue;
  1027. }
  1028. status = IopOpenDeviceParametersSubkey( &subKeyHandle,
  1029. NULL,
  1030. PathName,
  1031. KEY_READ | KEY_WRITE
  1032. );
  1033. if (NT_SUCCESS(status)) {
  1034. status = STATUS_SUCCESS;
  1035. } else {
  1036. status = STATUS_UNSUCCESSFUL;
  1037. }
  1038. } else {
  1039. //
  1040. // need to construct this key.
  1041. //
  1042. InitializeObjectAttributes(&objectAttributes,
  1043. PathName,
  1044. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  1045. NULL,
  1046. NULL);
  1047. status = ZwCreateKey(&subKeyHandle,
  1048. KEY_READ | KEY_WRITE,
  1049. &objectAttributes,
  1050. 0,
  1051. NULL,
  1052. keySeed->Attribute,
  1053. &disposition);
  1054. }
  1055. if (NT_SUCCESS(status)) {
  1056. //
  1057. // Check to see if this is the parameters key and
  1058. // migrate the parameter information.
  1059. //
  1060. if (keySeed->Options & KEY_SEED_DEVICE_PARAMETERS) {
  1061. if (FirmwareEntry->ControllerType == SerialController) {
  1062. ComPortDBAdd(subKeyHandle, (PWSTR)FirmwareEntry->Identifier);
  1063. } else {
  1064. //
  1065. // to get here there must be identifier information
  1066. // in the FirmwareEntry, so that check is not performed.
  1067. //
  1068. // NOTE: this will only happen once - when the key is
  1069. // created -- perhaps this needs to happen on every
  1070. // boot.
  1071. //
  1072. PiWstrToUnicodeString(&unicodeName,
  1073. L"DosDeviceName");
  1074. ZwSetValueKey(subKeyHandle,
  1075. &unicodeName,
  1076. 0,
  1077. FirmwareEntry->IdentifierType,
  1078. FirmwareEntry->Identifier,
  1079. FirmwareEntry->IdentifierLength);
  1080. }
  1081. }
  1082. ZwClose(subKeyHandle);
  1083. } else {
  1084. //
  1085. // ignore failures
  1086. //
  1087. IopDbgPrint((IOP_MAPPER_WARNING_LEVEL,
  1088. "Mapper: failed to build control key %x\n",
  1089. status));
  1090. }
  1091. }
  1092. //
  1093. // Undo the mangling of the path name performed in the loop above.
  1094. //
  1095. *wcptr = (WCHAR) 0;
  1096. PathName->Length = originalLength;
  1097. //
  1098. // Create values.
  1099. //
  1100. pnpid = FirmwareEntry->PnPId;
  1101. for (valueSeed = MapperValueSeed; valueSeed->ValueName; valueSeed++) {
  1102. if (valueSeed->ValueType == REG_DWORD) {
  1103. if ((valueSeed->Options == OPTIONS_INSERT_PHANTOM_MARKER) &&
  1104. !DeviceIsPhantom) {
  1105. //
  1106. // Device isn't a phantom--we don't want to mark it as such.
  1107. //
  1108. continue;
  1109. }
  1110. size = sizeof(ULONG);
  1111. RtlCopyMemory(buffer, &valueSeed->DwordValueContent, size);
  1112. } else if (valueSeed->Options == OPTIONS_INSERT_PNP_ID) {
  1113. size = (ULONG)((wcslen(pnpid) + 2) * sizeof(WCHAR)); // eos multi_sz
  1114. if (FirmwareEntry->BusType == Eisa) {
  1115. //
  1116. // need a mult_sz of EISA\PNPblah *PNPblah
  1117. //
  1118. RtlZeroMemory(buffer, SEED_BUFFER_SIZE);
  1119. wcptr = (PWCHAR)pnpid;
  1120. wcptr++;
  1121. StringCbPrintfW(buffer, SEED_BUFFER_SIZE, L"EISA\\%s", wcptr);
  1122. wcptr = buffer;
  1123. while (*wcptr) {
  1124. wcptr++;
  1125. }
  1126. wcptr++; // step past eos for 1st string
  1127. RtlCopyMemory(wcptr, pnpid, size);
  1128. size += (ULONG)((PUCHAR)wcptr - (PUCHAR)buffer);
  1129. } else {
  1130. RtlCopyMemory(buffer, pnpid, size - sizeof(WCHAR));
  1131. buffer[size / sizeof(WCHAR) - 1] = L'\0';
  1132. }
  1133. } else if (valueSeed->Options == OPTIONS_INSERT_COMPATIBLE_IDS) {
  1134. if (FirmwareEntry->PeripheralType == KeyboardPeripheral) {
  1135. size = sizeof(PS2_KEYBOARD_COMPATIBLE_ID);
  1136. RtlCopyMemory(buffer, PS2_KEYBOARD_COMPATIBLE_ID, size);
  1137. } else if (FirmwareEntry->PeripheralType == PointerPeripheral &&
  1138. (wcscmp(pnpid, L"*PNP0F0E") == 0 ||
  1139. wcscmp(pnpid, L"*PNP0F03") == 0 ||
  1140. wcscmp(pnpid, L"*PNP0F12") == 0)) {
  1141. size = sizeof(PS2_MOUSE_COMPATIBLE_ID);
  1142. RtlCopyMemory(buffer, PS2_MOUSE_COMPATIBLE_ID, size);
  1143. } else {
  1144. continue;
  1145. }
  1146. buffer[size / 2] = L'\0'; // 2nd NUL for MULTI_SZ
  1147. size += sizeof(L'\0');
  1148. } else if (valueSeed->Options == OPTIONS_INSERT_DEVICEDESC) {
  1149. size = FirmwareEntry->IdentifierLength;
  1150. RtlCopyMemory(buffer, FirmwareEntry->Identifier, size);
  1151. } else {
  1152. IopDbgPrint((IOP_MAPPER_WARNING_LEVEL, "Mapper: NO VALUE TYPE!\n"));
  1153. ASSERT(FALSE);
  1154. continue;
  1155. }
  1156. RtlInitUnicodeString(&unicodeName,
  1157. valueSeed->ValueName);
  1158. ZwSetValueKey(Handle,
  1159. &unicodeName,
  1160. 0,
  1161. valueSeed->ValueType,
  1162. buffer,
  1163. size);
  1164. }
  1165. ExFreePool(buffer);
  1166. }
  1167. VOID
  1168. MapperFreeList(
  1169. VOID
  1170. )
  1171. /*++
  1172. Routine Description:
  1173. This routine walks through the list of firmware entries
  1174. and frees all allocated memory.
  1175. Arguments:
  1176. None
  1177. Return Value:
  1178. None
  1179. --*/
  1180. {
  1181. PDEVICE_EXTENSION deviceExtension = &MapperDeviceExtension;
  1182. PFIRMWARE_CONFIGURATION tempEntry;
  1183. PFIRMWARE_CONFIGURATION firmwareEntry;
  1184. firmwareEntry = deviceExtension->FirmwareList;
  1185. while (firmwareEntry) {
  1186. //
  1187. // free allocated structures associated with the firmware entry
  1188. //
  1189. if (firmwareEntry->ResourceDescriptor) {
  1190. ExFreePool(firmwareEntry->ResourceDescriptor);
  1191. }
  1192. if (firmwareEntry->Identifier) {
  1193. ExFreePool(firmwareEntry->Identifier);
  1194. }
  1195. //
  1196. // free this entry and move to the next
  1197. //
  1198. tempEntry = firmwareEntry->Next;
  1199. ExFreePool(firmwareEntry);
  1200. firmwareEntry = tempEntry;
  1201. }
  1202. }
  1203. VOID
  1204. MapperConstructRootEnumTree(
  1205. IN BOOLEAN CreatePhantomDevices
  1206. )
  1207. /*++
  1208. Routine Description:
  1209. This routine walks through the list of firmware entries
  1210. in the device extension and migrates the information into
  1211. the root enumerator's tree in the registry.
  1212. Arguments:
  1213. CreatePhantomDevices - If non-zero, then the device instances are created
  1214. as "phantoms" (i.e., they are marked with the "Phantom" value entry so
  1215. that the root enumerator will ignore them). The only time these device
  1216. instance registry keys will ever turn into real live devnodes is if the
  1217. class installer (in response to DIF_FIRSTTIMESETUP or DIF_DETECT)
  1218. decides that these devices aren't duplicates of any PnP-enumerated
  1219. devnodes, and subsequently registers and installs them.
  1220. Return Value:
  1221. None
  1222. --*/
  1223. {
  1224. #define ENUM_KEY_BUFFER_SIZE (1024 * sizeof(WCHAR))
  1225. #define INSTANCE_BUFFER_SIZE (256 * sizeof(WCHAR))
  1226. UNICODE_STRING enumKey;
  1227. PFIRMWARE_CONFIGURATION firmwareEntry;
  1228. OBJECT_ATTRIBUTES objectAttributes;
  1229. NTSTATUS status;
  1230. BOOLEAN keyPresent;
  1231. PWCHAR registryBase;
  1232. PWCHAR instanceBuffer;
  1233. HANDLE handle;
  1234. ULONG disposition;
  1235. PVOID buffer;
  1236. PDEVICE_EXTENSION DeviceExtension = &MapperDeviceExtension;
  1237. PAGED_CODE();
  1238. //
  1239. // allocate space needed for the registry path into the root
  1240. // enumerator tree. Note, limited size on path length.
  1241. //
  1242. buffer = ExAllocatePool(NonPagedPool, ENUM_KEY_BUFFER_SIZE);
  1243. if (!buffer) {
  1244. MapperFreeList();
  1245. IopDbgPrint((IOP_MAPPER_WARNING_LEVEL,
  1246. "Mapper: could not allocate memory for registry update\n"));
  1247. return;
  1248. }
  1249. instanceBuffer = ExAllocatePool(NonPagedPool, INSTANCE_BUFFER_SIZE);
  1250. if (!instanceBuffer) {
  1251. MapperFreeList();
  1252. ExFreePool(buffer);
  1253. IopDbgPrint((IOP_MAPPER_WARNING_LEVEL,
  1254. "Mapper: could not allocate memory for instance buffer\n"));
  1255. return;
  1256. }
  1257. InitializeObjectAttributes(&objectAttributes,
  1258. &enumKey,
  1259. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  1260. NULL,
  1261. NULL);
  1262. #if UMODETEST
  1263. registryBase = L"\\Registry\\Machine\\System\\TestControlSet\\Enum\\Root\\";
  1264. #else
  1265. registryBase = L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\Root\\";
  1266. #endif
  1267. firmwareEntry = DeviceExtension->FirmwareList;
  1268. while (firmwareEntry) {
  1269. //
  1270. // Construct the base for the path for this entry.
  1271. //
  1272. PiWstrToUnicodeString(&enumKey, NULL);
  1273. enumKey.MaximumLength = ENUM_KEY_BUFFER_SIZE;
  1274. enumKey.Buffer = buffer;
  1275. RtlZeroMemory(buffer, ENUM_KEY_BUFFER_SIZE);
  1276. RtlAppendUnicodeToString(&enumKey, registryBase);
  1277. RtlAppendUnicodeToString(&enumKey, firmwareEntry->PnPId);
  1278. //
  1279. // Build the pnp Key.
  1280. //
  1281. status = ZwCreateKey(&handle,
  1282. KEY_READ | KEY_WRITE,
  1283. &objectAttributes,
  1284. 0,
  1285. NULL,
  1286. REG_OPTION_NON_VOLATILE,
  1287. &disposition);
  1288. if (NT_SUCCESS(status)) {
  1289. //
  1290. // Do not need the handle, so close it
  1291. // Remember if the key was present prior to call
  1292. //
  1293. ZwClose(handle);
  1294. keyPresent = (disposition == REG_OPENED_EXISTING_KEY) ? TRUE : FALSE;
  1295. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  1296. "Mapper: Key was %s\n",
  1297. keyPresent ? "Present" : "Created"));
  1298. //
  1299. // Construct the instance name.
  1300. //
  1301. RtlZeroMemory(instanceBuffer, INSTANCE_BUFFER_SIZE);
  1302. StringCbPrintfW(
  1303. instanceBuffer,
  1304. INSTANCE_BUFFER_SIZE,
  1305. L"\\%d_%d_%d_%d_%d_%d",
  1306. firmwareEntry->BusType,
  1307. firmwareEntry->BusNumber,
  1308. firmwareEntry->ControllerType,
  1309. firmwareEntry->ControllerNumber,
  1310. firmwareEntry->PeripheralType,
  1311. firmwareEntry->PeripheralNumber);
  1312. RtlAppendUnicodeToString(&enumKey, instanceBuffer);
  1313. status = ZwCreateKey(&handle,
  1314. KEY_READ | KEY_WRITE,
  1315. &objectAttributes,
  1316. 0,
  1317. NULL,
  1318. REG_OPTION_NON_VOLATILE,
  1319. &disposition);
  1320. if (NT_SUCCESS(status)) {
  1321. if (firmwareEntry->ResourceDescriptor) {
  1322. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  1323. "Mapper: firmware entry has resources %x\n",
  1324. firmwareEntry->ResourceDescriptor));
  1325. }
  1326. if (firmwareEntry->Identifier) {
  1327. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  1328. "Mapper: firmware entry has identifier %x\n",
  1329. firmwareEntry->Identifier));
  1330. }
  1331. //
  1332. // If the key already exists because it was explicitly migrated
  1333. // during textmode setup, we should still consider it a "new key".
  1334. //
  1335. if (disposition != REG_CREATED_NEW_KEY) {
  1336. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  1337. UNICODE_STRING unicodeString;
  1338. status = IopGetRegistryValue(handle,
  1339. REGSTR_VALUE_MIGRATED,
  1340. &keyValueInformation);
  1341. if (NT_SUCCESS(status)) {
  1342. if ((keyValueInformation->Type == REG_DWORD) &&
  1343. (keyValueInformation->DataLength == sizeof(ULONG)) &&
  1344. ((*(PULONG)KEY_VALUE_DATA(keyValueInformation)) != 0)) {
  1345. disposition = REG_CREATED_NEW_KEY;
  1346. }
  1347. ExFreePool(keyValueInformation);
  1348. PiWstrToUnicodeString(&unicodeString, REGSTR_VALUE_MIGRATED);
  1349. ZwDeleteValueKey(handle, &unicodeString);
  1350. }
  1351. }
  1352. //
  1353. // Only if this is a new entry do we see the key.
  1354. //
  1355. if (disposition == REG_CREATED_NEW_KEY) {
  1356. //
  1357. // Remember the fact that the key was newly-created for the
  1358. // PnP BIOS case where we need to come along and "phantomize"
  1359. // all newly-created ntdetect COM ports.
  1360. //
  1361. firmwareEntry->NewlyCreated = TRUE;
  1362. //
  1363. // Create enough information to get pnp to
  1364. // install drivers
  1365. //
  1366. MapperSeedKey(handle,
  1367. &enumKey,
  1368. firmwareEntry,
  1369. CreatePhantomDevices
  1370. );
  1371. }
  1372. MapperMarkKey(handle,
  1373. &enumKey,
  1374. firmwareEntry);
  1375. ZwClose(handle);
  1376. } else {
  1377. IopDbgPrint((IOP_MAPPER_WARNING_LEVEL,
  1378. "Mapper: create of instance key failed %x\n",
  1379. status));
  1380. }
  1381. } else {
  1382. IopDbgPrint((IOP_MAPPER_WARNING_LEVEL,
  1383. "Mapper: create pnp key failed %x\n",
  1384. status));
  1385. }
  1386. firmwareEntry = firmwareEntry->Next;
  1387. }
  1388. ExFreePool(instanceBuffer);
  1389. }
  1390. PCM_RESOURCE_LIST
  1391. MapperAdjustResourceList (
  1392. IN PCM_RESOURCE_LIST ResourceList,
  1393. IN WCHAR const* PnPId,
  1394. IN OUT PULONG Size
  1395. )
  1396. {
  1397. PCM_PARTIAL_RESOURCE_LIST partialResourceList;
  1398. PCM_PARTIAL_RESOURCE_DESCRIPTOR problemPartialDescriptors;
  1399. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors;
  1400. PCM_RESOURCE_LIST newResourceList;
  1401. ULONG i;
  1402. newResourceList = ResourceList;
  1403. #if _X86_
  1404. if (KeI386MachineType == MACHINE_TYPE_EISA) {
  1405. PCM_FULL_RESOURCE_DESCRIPTOR fullDescriptor;
  1406. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptor;
  1407. PUCHAR nextDescriptor;
  1408. ULONG j;
  1409. ULONG lastResourceIndex;
  1410. fullDescriptor = &ResourceList->List[0];
  1411. for (i = 0; i < ResourceList->Count; i++) {
  1412. partialResourceList = &fullDescriptor->PartialResourceList;
  1413. for (j = 0; j < partialResourceList->Count; j++) {
  1414. partialDescriptor = &partialResourceList->PartialDescriptors[j];
  1415. if (partialDescriptor->Type == CmResourceTypePort) {
  1416. if (partialDescriptor->u.Port.Start.HighPart == 0 &&
  1417. (partialDescriptor->u.Port.Start.LowPart & 0x00000300) == 0) {
  1418. partialDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
  1419. }
  1420. }
  1421. }
  1422. nextDescriptor = (PUCHAR)fullDescriptor + sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
  1423. //
  1424. // account for any resource descriptors in addition to the single
  1425. // imbedded one I've already accounted for (if there aren't any,
  1426. // then I'll end up subtracting off the extra imbedded descriptor
  1427. // from the previous step)
  1428. //
  1429. //
  1430. // finally, account for any extra device specific data at the end of
  1431. // the last partial resource descriptor (if any)
  1432. //
  1433. if (partialResourceList->Count > 0) {
  1434. nextDescriptor += (partialResourceList->Count - 1) *
  1435. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  1436. lastResourceIndex = partialResourceList->Count - 1;
  1437. if (partialResourceList->PartialDescriptors[lastResourceIndex].Type ==
  1438. CmResourceTypeDeviceSpecific) {
  1439. nextDescriptor += partialResourceList->PartialDescriptors[lastResourceIndex].
  1440. u.DeviceSpecificData.DataSize;
  1441. }
  1442. }
  1443. fullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)nextDescriptor;
  1444. }
  1445. }
  1446. #endif
  1447. if (wcscmp(PnPId, FloppyId) == 0) {
  1448. if (ResourceList->Count == 1) {
  1449. partialResourceList = &ResourceList->List->PartialResourceList;
  1450. partialDescriptors = partialResourceList->PartialDescriptors;
  1451. //
  1452. // Look for the one and only one 8 byte port resource
  1453. //
  1454. problemPartialDescriptors = NULL;
  1455. for (i=0; i<partialResourceList->Count; i++) {
  1456. if ((partialDescriptors[i].Type == CmResourceTypePort) &&
  1457. (partialDescriptors[i].u.Port.Length == 8)) {
  1458. if (problemPartialDescriptors == NULL) {
  1459. problemPartialDescriptors = partialDescriptors + i;
  1460. } else {
  1461. problemPartialDescriptors = NULL;
  1462. break;
  1463. }
  1464. }
  1465. }
  1466. if (problemPartialDescriptors) {
  1467. problemPartialDescriptors->u.Port.Length = 6;
  1468. newResourceList = ExAllocatePool (
  1469. NonPagedPool,
  1470. *Size + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
  1471. );
  1472. if (newResourceList) {
  1473. RtlCopyMemory (
  1474. newResourceList,
  1475. ResourceList,
  1476. *Size
  1477. );
  1478. //
  1479. // pick out the new partial resource descriptor
  1480. //
  1481. partialDescriptors = newResourceList->List->
  1482. PartialResourceList.PartialDescriptors;
  1483. partialDescriptors += newResourceList->List->PartialResourceList.Count;
  1484. RtlCopyMemory (
  1485. partialDescriptors,
  1486. problemPartialDescriptors,
  1487. sizeof(*partialDescriptors)
  1488. );
  1489. partialDescriptors->u.Port.Start.QuadPart += 7;
  1490. partialDescriptors->u.Port.Length = 1;
  1491. //
  1492. // we got one more now
  1493. //
  1494. newResourceList->List->PartialResourceList.Count++;
  1495. *Size += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  1496. ExFreePool (ResourceList);
  1497. } else {
  1498. newResourceList = ResourceList;
  1499. }
  1500. }
  1501. }
  1502. }
  1503. return newResourceList;
  1504. }
  1505. NTSTATUS
  1506. ComPortDBAdd(
  1507. IN HANDLE DeviceParamKey,
  1508. IN PWSTR PortName
  1509. )
  1510. {
  1511. UNICODE_STRING portNameString;
  1512. UNICODE_STRING portPrefixString;
  1513. UNICODE_STRING comDBName;
  1514. UNICODE_STRING valueName;
  1515. PKEY_VALUE_PARTIAL_INFORMATION valueInfo;
  1516. ULONG valueInfoLength;
  1517. ULONG returnedLength;
  1518. HANDLE comDBKey;
  1519. ULONG portNo;
  1520. NTSTATUS status;
  1521. RtlInitUnicodeString(&portNameString, PortName);
  1522. if (portNameString.Length > 3 * sizeof(WCHAR)) {
  1523. portNameString.Length = 3 * sizeof(WCHAR);
  1524. }
  1525. PiWstrToUnicodeString(&portPrefixString, L"COM");
  1526. if (RtlCompareUnicodeString(&portNameString, &portPrefixString, TRUE) == 0) {
  1527. portNo = _wtol(&PortName[3]);
  1528. if (portNo > 0 && portNo <= 256) {
  1529. #if UMODETEST
  1530. PiWstrToUnicodeString(&comDBName, L"\\Registry\\Machine\\System\\TestControlSet\\Control\\COM Name Arbiter");
  1531. #else
  1532. PiWstrToUnicodeString(&comDBName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\COM Name Arbiter");
  1533. #endif
  1534. status = IopCreateRegistryKeyEx( &comDBKey,
  1535. NULL,
  1536. &comDBName,
  1537. KEY_ALL_ACCESS,
  1538. REG_OPTION_NON_VOLATILE,
  1539. NULL
  1540. );
  1541. if (NT_SUCCESS(status)) {
  1542. PiWstrToUnicodeString(&valueName, L"ComDB Merge");
  1543. #define COMPORT_DB_MERGE_SIZE 32 // 256 / 8
  1544. valueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + COMPORT_DB_MERGE_SIZE;
  1545. valueInfo = ExAllocatePool(PagedPool, valueInfoLength);
  1546. if (valueInfo != NULL) {
  1547. status = ZwQueryValueKey( comDBKey,
  1548. &valueName,
  1549. KeyValuePartialInformation,
  1550. valueInfo,
  1551. valueInfoLength,
  1552. &returnedLength);
  1553. if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
  1554. valueInfo->Type = REG_BINARY;
  1555. valueInfo->DataLength = COMPORT_DB_MERGE_SIZE;
  1556. RtlZeroMemory(valueInfo->Data, valueInfo->DataLength);
  1557. status = STATUS_SUCCESS;
  1558. }
  1559. if (NT_SUCCESS(status)) {
  1560. portNo--;
  1561. valueInfo->Data[ portNo / 8 ] |= 1 << (portNo % 8);
  1562. status = ZwSetValueKey( comDBKey,
  1563. &valueName,
  1564. 0,
  1565. valueInfo->Type,
  1566. valueInfo->Data,
  1567. valueInfo->DataLength );
  1568. ASSERT(NT_SUCCESS(status));
  1569. }
  1570. ExFreePool(valueInfo);
  1571. }
  1572. ZwClose(comDBKey);
  1573. }
  1574. }
  1575. }
  1576. PiWstrToUnicodeString( &valueName, L"DosDeviceName" );
  1577. status = ZwSetValueKey( DeviceParamKey,
  1578. &valueName,
  1579. 0,
  1580. REG_SZ,
  1581. PortName,
  1582. (ULONG)((wcslen(PortName) + 1) * sizeof(WCHAR)) );
  1583. return status;
  1584. }
  1585. VOID
  1586. MapperPhantomizeDetectedComPorts (
  1587. VOID
  1588. )
  1589. /*++
  1590. Routine Description:
  1591. This routine turns all newly-created firmware/ntdetect COM ports into
  1592. phantoms.
  1593. Arguments:
  1594. None
  1595. Return Value:
  1596. None
  1597. --*/
  1598. {
  1599. PFIRMWARE_CONFIGURATION firmwareEntry;
  1600. NTSTATUS status;
  1601. PWCHAR registryBase;
  1602. PWCHAR instanceBuffer;
  1603. HANDLE handle;
  1604. PWCHAR buffer;
  1605. PDEVICE_EXTENSION DeviceExtension = &MapperDeviceExtension;
  1606. UNICODE_STRING enumKey;
  1607. OBJECT_ATTRIBUTES objectAttributes;
  1608. UNICODE_STRING unicodeName;
  1609. ULONG regValue;
  1610. //
  1611. // allocate space needed for the registry path into the root
  1612. // enumerator tree. Note, limited size on path length.
  1613. //
  1614. buffer = ExAllocatePool(NonPagedPool, ENUM_KEY_BUFFER_SIZE);
  1615. if (!buffer) {
  1616. IopDbgPrint((IOP_MAPPER_WARNING_LEVEL,
  1617. "Mapper: could not allocate memory for registry update\n"));
  1618. return;
  1619. }
  1620. instanceBuffer = ExAllocatePool(NonPagedPool, INSTANCE_BUFFER_SIZE);
  1621. if (!instanceBuffer) {
  1622. ExFreePool(buffer);
  1623. IopDbgPrint((IOP_MAPPER_WARNING_LEVEL,
  1624. "Mapper: could not allocate memory for instance buffer\n"));
  1625. return;
  1626. }
  1627. InitializeObjectAttributes(&objectAttributes,
  1628. &enumKey,
  1629. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  1630. NULL,
  1631. NULL);
  1632. #if UMODETEST
  1633. registryBase = L"\\Registry\\Machine\\System\\TestControlSet\\Enum\\Root\\";
  1634. #else
  1635. registryBase = L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\Root\\";
  1636. #endif
  1637. firmwareEntry = DeviceExtension->FirmwareList;
  1638. while (firmwareEntry) {
  1639. //
  1640. // Construct the base for the path for this entry.
  1641. //
  1642. if ((firmwareEntry->ControllerType == SerialController) &&
  1643. firmwareEntry->NewlyCreated) {
  1644. PiWstrToUnicodeString(&enumKey, NULL);
  1645. enumKey.MaximumLength = ENUM_KEY_BUFFER_SIZE;
  1646. enumKey.Buffer = buffer;
  1647. RtlZeroMemory(buffer, ENUM_KEY_BUFFER_SIZE);
  1648. RtlAppendUnicodeToString(&enumKey, registryBase);
  1649. RtlAppendUnicodeToString(&enumKey, firmwareEntry->PnPId);
  1650. //
  1651. // Construct the instance name.
  1652. //
  1653. RtlZeroMemory(instanceBuffer, INSTANCE_BUFFER_SIZE);
  1654. StringCbPrintfW(
  1655. instanceBuffer,
  1656. INSTANCE_BUFFER_SIZE,
  1657. L"\\%d_%d_%d_%d_%d_%d",
  1658. firmwareEntry->BusType,
  1659. firmwareEntry->BusNumber,
  1660. firmwareEntry->ControllerType,
  1661. firmwareEntry->ControllerNumber,
  1662. firmwareEntry->PeripheralType,
  1663. firmwareEntry->PeripheralNumber);
  1664. RtlAppendUnicodeToString(&enumKey, instanceBuffer);
  1665. status = ZwOpenKey(&handle,
  1666. KEY_READ | KEY_WRITE,
  1667. &objectAttributes
  1668. );
  1669. if (NT_SUCCESS(status)) {
  1670. PiWstrToUnicodeString(&unicodeName, REGSTR_VAL_PHANTOM);
  1671. regValue = 1;
  1672. ZwSetValueKey(handle,
  1673. &unicodeName,
  1674. 0,
  1675. REG_DWORD,
  1676. &regValue,
  1677. sizeof(regValue)
  1678. );
  1679. ZwClose(handle);
  1680. }
  1681. }
  1682. firmwareEntry = firmwareEntry->Next;
  1683. }
  1684. ExFreePool (buffer);
  1685. ExFreePool (instanceBuffer);
  1686. }
  1687. #ifdef ALLOC_DATA_PRAGMA
  1688. #pragma const_seg()
  1689. #pragma data_seg()
  1690. #endif