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.

2132 lines
65 KiB

  1. /*++
  2. Copyright (c) 1994-2000 Microsoft Corporation
  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_ERROR_LEVEL,
  369. "Mapper: No pointer match found\n"));
  370. }
  371. } else {
  372. IopDbgPrint((IOP_MAPPER_ERROR_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_ERROR_LEVEL,
  386. "Mapper: No keyboard match found\n"));
  387. }
  388. } else {
  389. IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
  390. "Mapper: No identifier specified\n"));
  391. }
  392. break;
  393. default:
  394. IopDbgPrint((IOP_MAPPER_ERROR_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( BusInformation );
  447. UNREFERENCED_PARAMETER( ControllerType );
  448. UNREFERENCED_PARAMETER( ControllerNumber );
  449. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  450. "Mapper: peripheral registry location is\n %ws\n",
  451. PathName->Buffer));
  452. if (!ControllerInformation) {
  453. IopDbgPrint((IOP_MAPPER_VERBOSE_LEVEL,
  454. "Mapper: No component information\n"));
  455. }
  456. if (!PeripheralInformation) {
  457. IopDbgPrint((IOP_MAPPER_VERBOSE_LEVEL,
  458. "Mapper: No peripheral information\n"));
  459. return STATUS_SUCCESS;
  460. }
  461. //
  462. // Map the PnP Id for this device.
  463. //
  464. if (PeripheralInformation[IoQueryDeviceIdentifier]) {
  465. information = PeripheralInformation[IoQueryDeviceIdentifier];
  466. firmwareEntry->PnPId = MapperTranslatePnPId(PeripheralType, information);
  467. if (firmwareEntry->PnPId) {
  468. //
  469. // Remember the peripheral's identifier (if it has one, and it's a REG_SZ value)
  470. // for use as the default PnP device description.
  471. //
  472. if (((dataLength = information->DataLength) > sizeof(WCHAR)) &&
  473. (information->Type == REG_SZ)) {
  474. ptr = (PWCHAR) ((PUCHAR)information + information->DataOffset);
  475. if (*ptr) {
  476. temp = ExAllocatePool(NonPagedPool, dataLength);
  477. if (temp) {
  478. //
  479. // If there's already an identifier here (from the peripheral's
  480. // controller) then wipe it out.
  481. //
  482. if(firmwareEntry->Identifier) {
  483. ExFreePool(firmwareEntry->Identifier);
  484. }
  485. //
  486. // Move the data
  487. //
  488. firmwareEntry->Identifier = temp;
  489. firmwareEntry->IdentifierType = information->Type;
  490. firmwareEntry->IdentifierLength = dataLength;
  491. RtlCopyMemory(temp, ptr, dataLength);
  492. }
  493. }
  494. }
  495. }
  496. }
  497. //
  498. // Save the ordinals for the peripheral type and number
  499. //
  500. firmwareEntry->PeripheralType = PeripheralType;
  501. firmwareEntry->PeripheralNumber = PeripheralNumber;
  502. return STATUS_SUCCESS;
  503. }
  504. NTSTATUS
  505. MapperCallback(
  506. IN PVOID Context,
  507. IN PUNICODE_STRING PathName,
  508. IN INTERFACE_TYPE BusType,
  509. IN ULONG BusNumber,
  510. IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
  511. IN CONFIGURATION_TYPE ControllerType,
  512. IN ULONG ControllerNumber,
  513. IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
  514. IN CONFIGURATION_TYPE PeripheralType,
  515. IN ULONG PeripheralNumber,
  516. IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
  517. )
  518. /*++
  519. Routine Description:
  520. This routine is used to acquire firmware tree information about
  521. pointer devices in the system.
  522. Arguments:
  523. Context - Pointer to the device extension.
  524. PathName - unicode registry path.
  525. BusType - Internal, Isa, ...
  526. BusNumber - Which bus if we are on a multibus system.
  527. BusInformation - Configuration information about the bus. Not Used.
  528. ControllerType - serial or ata disk.
  529. ControllerNumber - Which controller if there is more than one
  530. controller in the system.
  531. ControllerInformation - Array of pointers to the three pieces of
  532. registry information.
  533. PeripheralType - Undefined for this call.
  534. PeripheralNumber - Undefined for this call.
  535. PeripheralInformation - Undefined for this call.
  536. Return Value:
  537. STATUS_SUCCESS if everything went ok, or STATUS_INSUFFICIENT_RESOURCES
  538. if it couldn't map the base csr or acquire the device object, or
  539. all of the resource information couldn't be acquired.
  540. --*/
  541. {
  542. PDEVICE_EXTENSION deviceExtension = Context;
  543. PCM_FULL_RESOURCE_DESCRIPTOR controllerData;
  544. PKEY_VALUE_FULL_INFORMATION information;
  545. PFIRMWARE_CONFIGURATION firmwareEntry;
  546. CONFIGURATION_TYPE peripheralType;
  547. PUCHAR buffer;
  548. ULONG dataLength;
  549. UNREFERENCED_PARAMETER( BusInformation );
  550. UNREFERENCED_PARAMETER( PeripheralType );
  551. UNREFERENCED_PARAMETER( PeripheralNumber );
  552. UNREFERENCED_PARAMETER( PeripheralInformation );
  553. //
  554. // If entry is found, but there is no information just return
  555. //
  556. information = ControllerInformation[IoQueryDeviceConfigurationData];
  557. if (information == NULL) {
  558. return STATUS_SUCCESS;
  559. }
  560. dataLength = information->DataLength;
  561. if (dataLength == 0) {
  562. return STATUS_SUCCESS;
  563. }
  564. //
  565. // Setup to capture the information from the firmware tree
  566. //
  567. firmwareEntry = ExAllocatePool(NonPagedPool, sizeof(FIRMWARE_CONFIGURATION));
  568. if (!firmwareEntry) {
  569. return STATUS_INSUFFICIENT_RESOURCES;
  570. }
  571. RtlZeroMemory(firmwareEntry, sizeof(FIRMWARE_CONFIGURATION));
  572. //
  573. // Save information concerning the controller
  574. //
  575. firmwareEntry->ControllerType = ControllerType;
  576. firmwareEntry->ControllerNumber = ControllerNumber;
  577. firmwareEntry->BusNumber = BusNumber;
  578. firmwareEntry->BusType = BusType;
  579. //
  580. // Save the resource descriptor
  581. //
  582. buffer = firmwareEntry->ResourceDescriptor = ExAllocatePool(NonPagedPool,
  583. dataLength);
  584. if (!buffer) {
  585. ExFreePool(firmwareEntry);
  586. return STATUS_INSUFFICIENT_RESOURCES;
  587. }
  588. //
  589. // Save the configuration information on this controller.
  590. //
  591. controllerData = (PCM_FULL_RESOURCE_DESCRIPTOR)
  592. ((PUCHAR)information + information->DataOffset);
  593. RtlCopyMemory(buffer, controllerData, dataLength);
  594. firmwareEntry->ResourceDescriptorSize = dataLength;
  595. //
  596. // If there is a device identifier save it.
  597. //
  598. information = ControllerInformation[IoQueryDeviceIdentifier];
  599. if (information != NULL) {
  600. PWCHAR ptr;
  601. dataLength = information->DataLength;
  602. if (dataLength != 0) {
  603. ptr = (PWCHAR) ((PUCHAR)information + information->DataOffset);
  604. if (ControllerType == ParallelController) {
  605. PWCHAR tmpChar;
  606. //
  607. // Some extra mapping is performed here to
  608. // translate the firmware names to LPT names.
  609. //
  610. *ptr++ = (WCHAR) 'L';
  611. *ptr++ = (WCHAR) 'P';
  612. *ptr++ = (WCHAR) 'T';
  613. //
  614. // Find the number.
  615. //
  616. tmpChar = ptr;
  617. while (*tmpChar) {
  618. if ((*tmpChar >= (WCHAR) '0') &&
  619. (*tmpChar <= (WCHAR) '9')) {
  620. break;
  621. }
  622. tmpChar++;
  623. }
  624. if (*tmpChar) {
  625. while (*tmpChar) {
  626. *ptr++ = *tmpChar++;
  627. }
  628. *ptr = (WCHAR) 0;
  629. //
  630. // Update the datalength to be 4 wchars and eos and
  631. // restore the pointer.
  632. //
  633. ptr = (PWCHAR) ((PUCHAR)information + information->DataOffset);
  634. dataLength = 10;
  635. } else {
  636. dataLength = 0;
  637. IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
  638. "Mapper: no parallel port number!\n"));
  639. }
  640. }
  641. if (dataLength) {
  642. firmwareEntry->Identifier = ExAllocatePool(NonPagedPool,
  643. dataLength);
  644. if (firmwareEntry->Identifier) {
  645. //
  646. // Move the data
  647. //
  648. firmwareEntry->IdentifierType = information->Type;
  649. firmwareEntry->IdentifierLength = dataLength;
  650. RtlCopyMemory(firmwareEntry->Identifier, ptr, dataLength);
  651. }
  652. }
  653. }
  654. }
  655. //
  656. // For some controllers, search the peripheral information
  657. //
  658. switch (ControllerType) {
  659. case SerialController:
  660. case ParallelController:
  661. //
  662. // Don't look for a peripheral.
  663. //
  664. peripheralType = (CONFIGURATION_TYPE) 0;
  665. break;
  666. case DiskController:
  667. peripheralType = FloppyDiskPeripheral;
  668. break;
  669. case KeyboardController:
  670. peripheralType = KeyboardPeripheral;
  671. break;
  672. case PointerController:
  673. peripheralType = PointerPeripheral;
  674. break;
  675. default:
  676. peripheralType = (CONFIGURATION_TYPE) 0;
  677. break;
  678. }
  679. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  680. "Mapper: registry location is\n %ws\n",
  681. PathName->Buffer));
  682. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  683. "Mapper: ControllerInformation[] -\n\tIdent: %x -\n\tData: %x -\n\tInformation: %x\n",
  684. ControllerInformation[0],
  685. ControllerInformation[1],
  686. ControllerInformation[2]));
  687. if (peripheralType) {
  688. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  689. "Mapper: searching for peripheral type %d\n",
  690. peripheralType));
  691. IoQueryDeviceDescription(&BusType,
  692. &BusNumber,
  693. &ControllerType,
  694. &ControllerNumber,
  695. &peripheralType,
  696. NULL,
  697. MapperPeripheralCallback,
  698. firmwareEntry);
  699. }
  700. //
  701. // firmwareEntry->PnPId will be NULL if there are no peripherals of this
  702. // type in the tree or if the peripheral's description doesn't match one of
  703. // those in our table.
  704. //
  705. // firmwareEntry->PeripheralType will be equal to peripheralType if we found
  706. // one of the proper type regardless of whether or not it is in the table.
  707. //
  708. // So this test just ensures that we fallback to the controller IDs in the
  709. // case were there is no peripheral entry. If there is a peripheral entry
  710. // that we don't understand we will suppress the entire node.
  711. //
  712. // This prevents creating devices with hw ids of bogus as we were seeing on
  713. // the SGI x86 ARC machines.
  714. //
  715. if (!firmwareEntry->PnPId && firmwareEntry->PeripheralType == 0) {
  716. //
  717. // Attempt to get PnPId from the controller type.
  718. //
  719. firmwareEntry->PnPId = MapperTranslatePnPId(ControllerType, NULL);
  720. if (!firmwareEntry->PnPId) {
  721. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  722. "Mapper: NO PnP Id for\n ==> %ws\n",
  723. PathName->Buffer));
  724. }
  725. }
  726. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  727. "Mapper: constructed name %d_%d_%d_%d_%d_%d\n",
  728. firmwareEntry->BusType,
  729. firmwareEntry->BusNumber,
  730. firmwareEntry->ControllerType,
  731. firmwareEntry->ControllerNumber,
  732. firmwareEntry->PeripheralType,
  733. firmwareEntry->PeripheralNumber));
  734. if (firmwareEntry->PnPId) {
  735. //
  736. // Link into chain of entries.
  737. //
  738. firmwareEntry->Next = deviceExtension->FirmwareList;
  739. deviceExtension->FirmwareList = firmwareEntry;
  740. } else {
  741. //
  742. // No map found - don't remember this entry.
  743. //
  744. ExFreePool(buffer);
  745. if(firmwareEntry->Identifier) {
  746. ExFreePool(firmwareEntry->Identifier);
  747. }
  748. ExFreePool(firmwareEntry);
  749. }
  750. return STATUS_SUCCESS;
  751. }
  752. VOID
  753. MapperProcessFirmwareTree(
  754. IN BOOLEAN OnlyProcessSerialPorts
  755. )
  756. /*++
  757. Routine Description:
  758. Query the information in the firmware tree to know what
  759. system board devices were located. This will cause a FirmwareList
  760. to be created on the device extention passed.
  761. Arguments:
  762. OnlyProcessSerialPorts - if non-zero, then we'll only look at serial ports.
  763. This is done on ACPI machines where, in general, we don't want to pay
  764. attention to ntdetect/firmware information (but we have to for serial
  765. ports so that legacy add-in ISA serial ports and modems are detected
  766. automatically as in previous versions of NT as well as Win9x).
  767. Return Value:
  768. None
  769. --*/
  770. {
  771. INTERFACE_TYPE interfaceType;
  772. ULONG index;
  773. CONFIGURATION_TYPE sc;
  774. CONFIGURATION_TYPE controllerTypes[] = { PointerController,
  775. KeyboardController,
  776. ParallelController,
  777. DiskController,
  778. FloppyDiskPeripheral,
  779. SerialController // must be last
  780. };
  781. #define CONTROLLER_TYPES_COUNT (sizeof(controllerTypes) / sizeof(controllerTypes[0]))
  782. PAGED_CODE();
  783. //
  784. // Locate all firmware controller information and save its resource usage.
  785. //
  786. // It's pretty inefficient to be going through all interface types, when we
  787. // really only care about a very small subset of non-PnP buses (e.g., ISA,
  788. // EISA, maybe Internal).
  789. //
  790. for (interfaceType = 0; interfaceType < MaximumInterfaceType; interfaceType++) {
  791. IopDbgPrint((IOP_MAPPER_VERBOSE_LEVEL,
  792. "Mapper: searching on interface ===> %d\n",
  793. interfaceType));
  794. if(OnlyProcessSerialPorts) {
  795. //
  796. // Start out at the last element of the array, so we only process
  797. // SerialControllers.
  798. //
  799. index = CONTROLLER_TYPES_COUNT - 1;
  800. } else {
  801. index = 0;
  802. }
  803. for ( ; index < CONTROLLER_TYPES_COUNT; index++) {
  804. sc = controllerTypes[index];
  805. IoQueryDeviceDescription(&interfaceType,
  806. NULL,
  807. &sc,
  808. NULL,
  809. NULL,
  810. NULL,
  811. MapperCallback,
  812. &MapperDeviceExtension);
  813. }
  814. }
  815. }
  816. VOID
  817. MapperMarkKey(
  818. IN HANDLE Handle,
  819. IN PUNICODE_STRING PathName,
  820. IN PFIRMWARE_CONFIGURATION FirmwareEntry
  821. )
  822. /*++
  823. Routine Description:
  824. Record in the root enum key that the firmware mapper found this entry.
  825. Migrate configuration information entries.
  826. Arguments:
  827. Handle - handle to the key
  828. PathName - base path name to this key
  829. FirmwareEntry - information from the firmware tree.
  830. Return Value:
  831. None
  832. --*/
  833. {
  834. OBJECT_ATTRIBUTES objectAttributes;
  835. PCM_RESOURCE_LIST resourceList;
  836. UNICODE_STRING unicodeName;
  837. NTSTATUS status;
  838. HANDLE subKeyHandle;
  839. PWCHAR wcptr;
  840. ULONG disposition;
  841. ULONG buffer;
  842. USHORT originalLength;
  843. //
  844. // Mark that this entry was in the firmware tree.
  845. //
  846. buffer = 1;
  847. PiWstrToUnicodeString(&unicodeName, REGSTR_VAL_FIRMWAREIDENTIFIED);
  848. ZwSetValueKey(Handle,
  849. &unicodeName,
  850. 0,
  851. REG_DWORD,
  852. &buffer,
  853. sizeof(ULONG));
  854. //
  855. // Create the control subkey
  856. //
  857. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  858. "Mapper: marking existing key\n"));
  859. originalLength = PathName->Length;
  860. wcptr = (PWCHAR) ((PUCHAR)PathName->Buffer + PathName->Length);
  861. wcptr++; // locate eos
  862. //
  863. // Build the volatile control key
  864. //
  865. InitializeObjectAttributes(&objectAttributes,
  866. PathName,
  867. OBJ_CASE_INSENSITIVE,
  868. NULL,
  869. NULL);
  870. RtlAppendUnicodeToString(PathName, L"\\Control");
  871. status = ZwCreateKey(&subKeyHandle,
  872. KEY_READ | KEY_WRITE,
  873. &objectAttributes,
  874. 0,
  875. NULL,
  876. REG_OPTION_VOLATILE,
  877. &disposition);
  878. if (NT_SUCCESS(status)) {
  879. //
  880. // Create the found by firmware volatile.
  881. //
  882. buffer = 1;
  883. PiWstrToUnicodeString(&unicodeName, REGSTR_VAL_FIRMWAREMEMBER);
  884. ZwSetValueKey(subKeyHandle,
  885. &unicodeName,
  886. 0,
  887. REG_DWORD,
  888. &buffer,
  889. sizeof(ULONG));
  890. ZwClose(subKeyHandle);
  891. } else {
  892. //
  893. // ignore failures
  894. //
  895. IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
  896. "Mapper: failed to mark control key %x\n",
  897. status));
  898. }
  899. //
  900. // if there is a resource descriptor, restore path and open LogConf key.
  901. //
  902. if (FirmwareEntry->ResourceDescriptor) {
  903. PathName->Length = originalLength;
  904. *wcptr = (WCHAR) 0;
  905. InitializeObjectAttributes(&objectAttributes,
  906. PathName,
  907. OBJ_CASE_INSENSITIVE,
  908. NULL,
  909. NULL);
  910. RtlAppendUnicodeToString(PathName, L"\\LogConf");
  911. status = ZwCreateKey(&subKeyHandle,
  912. KEY_READ | KEY_WRITE,
  913. &objectAttributes,
  914. 0,
  915. NULL,
  916. REG_OPTION_VOLATILE,
  917. &disposition);
  918. if (NT_SUCCESS(status)) {
  919. ULONG size;
  920. //
  921. // two entries need to be made:
  922. // BootConfig:REG_RESOURCE_LIST
  923. // BasicConfigVector:REG_RESOURCE_REQUIREMENTS_LIST
  924. //
  925. size = sizeof(CM_RESOURCE_LIST) -
  926. sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
  927. FirmwareEntry->ResourceDescriptorSize;
  928. resourceList = ExAllocatePool(NonPagedPool, size);
  929. if (resourceList) {
  930. resourceList->Count = 1;
  931. RtlCopyMemory(&resourceList->List[0],
  932. FirmwareEntry->ResourceDescriptor,
  933. FirmwareEntry->ResourceDescriptorSize);
  934. resourceList = MapperAdjustResourceList (
  935. resourceList,
  936. FirmwareEntry->PnPId,
  937. &size
  938. );
  939. PiWstrToUnicodeString(&unicodeName,
  940. L"BootConfig");
  941. ZwSetValueKey(subKeyHandle,
  942. &unicodeName,
  943. 0,
  944. REG_RESOURCE_LIST,
  945. resourceList,
  946. size);
  947. #if 0
  948. //
  949. // Now do the resource requirements list.
  950. //
  951. reqList = IopCmResourcesToIoResources(0, resourceList);
  952. if (reqList) {
  953. PiWstrToUnicodeString(&unicodeName,
  954. L"BasicConfigVector");
  955. ZwSetValueKey(subKeyHandle,
  956. &unicodeName,
  957. 0,
  958. REG_RESOURCE_REQUIREMENTS_LIST,
  959. reqList,
  960. reqList->ListSize);
  961. ExFreePool(reqList);
  962. }
  963. #endif
  964. ExFreePool(resourceList);
  965. }
  966. ZwClose(subKeyHandle);
  967. } else {
  968. //
  969. // ignore errors
  970. //
  971. IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
  972. "Mapper: failed to update logconf key %x\n",
  973. status));
  974. }
  975. }
  976. //
  977. // Restore path passed in.
  978. //
  979. PathName->Length = originalLength;
  980. *wcptr = (WCHAR) 0;
  981. }
  982. VOID
  983. MapperSeedKey(
  984. IN HANDLE Handle,
  985. IN PUNICODE_STRING PathName,
  986. IN PFIRMWARE_CONFIGURATION FirmwareEntry,
  987. IN BOOLEAN DeviceIsPhantom
  988. )
  989. /*++
  990. Routine Description:
  991. This routine seeds a registry key with enough information
  992. to get PnP to run the class installer on the devnode.
  993. Arguments:
  994. Handle - handle to the key
  995. PathName - base path name to this key
  996. FirmwareEntry - information from the firmware tree
  997. DeviceIsPhantom - if non-zero, add "Phantom" value entry so the root
  998. enumerator will skip this device instance (i.e., not turn it into a
  999. devnode)
  1000. Return Value:
  1001. None
  1002. --*/
  1003. {
  1004. #define SEED_BUFFER_SIZE (512 * sizeof(WCHAR))
  1005. UNICODE_STRING unicodeName;
  1006. OBJECT_ATTRIBUTES objectAttributes;
  1007. MAPPER_SEED const* valueSeed;
  1008. KEY_SEED const* keySeed;
  1009. NTSTATUS status;
  1010. HANDLE subKeyHandle;
  1011. WCHAR const* pnpid;
  1012. PWCHAR buffer;
  1013. PWCHAR wcptr;
  1014. ULONG disposition;
  1015. ULONG size;
  1016. USHORT originalLength;
  1017. buffer = ExAllocatePool(NonPagedPool, SEED_BUFFER_SIZE);
  1018. if (!buffer) {
  1019. return;
  1020. }
  1021. RtlZeroMemory(buffer, SEED_BUFFER_SIZE);
  1022. //
  1023. // Create subkeys.
  1024. //
  1025. originalLength = PathName->Length;
  1026. wcptr = (PWCHAR) ((PUCHAR)PathName->Buffer + PathName->Length);
  1027. for (keySeed = MapperKeySeed; keySeed->KeyName; keySeed++) {
  1028. //
  1029. // Reset the base path for the next key to seed.
  1030. //
  1031. *wcptr = (WCHAR) 0;
  1032. PathName->Length = originalLength;
  1033. RtlAppendUnicodeToString(PathName, keySeed->KeyName);
  1034. //
  1035. // Only build a device parameters key if there is something
  1036. // to put in the key (i.e., this is a serial or parallel port).
  1037. //
  1038. if (keySeed->Options & KEY_SEED_DEVICE_PARAMETERS) {
  1039. if (((FirmwareEntry->ControllerType != SerialController) && (FirmwareEntry->ControllerType != ParallelController)) ||
  1040. !FirmwareEntry->Identifier) {
  1041. continue;
  1042. }
  1043. status = IopOpenDeviceParametersSubkey( &subKeyHandle,
  1044. NULL,
  1045. PathName,
  1046. KEY_READ | KEY_WRITE
  1047. );
  1048. if (NT_SUCCESS(status)) {
  1049. status = STATUS_SUCCESS;
  1050. } else {
  1051. status = STATUS_UNSUCCESSFUL;
  1052. }
  1053. } else {
  1054. //
  1055. // need to construct this key.
  1056. //
  1057. InitializeObjectAttributes(&objectAttributes,
  1058. PathName,
  1059. OBJ_CASE_INSENSITIVE,
  1060. NULL,
  1061. NULL);
  1062. status = ZwCreateKey(&subKeyHandle,
  1063. KEY_READ | KEY_WRITE,
  1064. &objectAttributes,
  1065. 0,
  1066. NULL,
  1067. keySeed->Attribute,
  1068. &disposition);
  1069. }
  1070. if (NT_SUCCESS(status)) {
  1071. //
  1072. // Check to see if this is the parameters key and
  1073. // migrate the parameter information.
  1074. //
  1075. if (keySeed->Options & KEY_SEED_DEVICE_PARAMETERS) {
  1076. if (FirmwareEntry->ControllerType == SerialController) {
  1077. ComPortDBAdd(subKeyHandle, (PWSTR)FirmwareEntry->Identifier);
  1078. } else {
  1079. //
  1080. // to get here there must be identifier information
  1081. // in the FirmwareEntry, so that check is not performed.
  1082. //
  1083. // NOTE: this will only happen once - when the key is
  1084. // created -- perhaps this needs to happen on every
  1085. // boot.
  1086. //
  1087. PiWstrToUnicodeString(&unicodeName,
  1088. L"DosDeviceName");
  1089. ZwSetValueKey(subKeyHandle,
  1090. &unicodeName,
  1091. 0,
  1092. FirmwareEntry->IdentifierType,
  1093. FirmwareEntry->Identifier,
  1094. FirmwareEntry->IdentifierLength);
  1095. }
  1096. }
  1097. ZwClose(subKeyHandle);
  1098. } else {
  1099. //
  1100. // ignore failures
  1101. //
  1102. IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
  1103. "Mapper: failed to build control key %x\n",
  1104. status));
  1105. }
  1106. }
  1107. //
  1108. // Undo the mangling of the path name performed in the loop above.
  1109. //
  1110. *wcptr = (WCHAR) 0;
  1111. PathName->Length = originalLength;
  1112. //
  1113. // Create values.
  1114. //
  1115. pnpid = FirmwareEntry->PnPId;
  1116. for (valueSeed = MapperValueSeed; valueSeed->ValueName; valueSeed++) {
  1117. if (valueSeed->ValueType == REG_DWORD) {
  1118. if ((valueSeed->Options == OPTIONS_INSERT_PHANTOM_MARKER) &&
  1119. !DeviceIsPhantom) {
  1120. //
  1121. // Device isn't a phantom--we don't want to mark it as such.
  1122. //
  1123. continue;
  1124. }
  1125. size = sizeof(ULONG);
  1126. RtlCopyMemory(buffer, &valueSeed->DwordValueContent, size);
  1127. } else if (valueSeed->Options == OPTIONS_INSERT_PNP_ID) {
  1128. size = (ULONG)((wcslen(pnpid) + 2) * sizeof(WCHAR)); // eos multi_sz
  1129. if (FirmwareEntry->BusType == Eisa) {
  1130. //
  1131. // need a mult_sz of EISA\PNPblah *PNPblah
  1132. //
  1133. RtlZeroMemory(buffer, SEED_BUFFER_SIZE);
  1134. wcptr = (PWCHAR)pnpid;
  1135. wcptr++;
  1136. swprintf(buffer, L"EISA\\%s", wcptr);
  1137. wcptr = buffer;
  1138. while (*wcptr) {
  1139. wcptr++;
  1140. }
  1141. wcptr++; // step past eos for 1st string
  1142. RtlCopyMemory(wcptr, pnpid, size);
  1143. size += (ULONG)((PUCHAR)wcptr - (PUCHAR)buffer);
  1144. } else {
  1145. RtlCopyMemory(buffer, pnpid, size - sizeof(WCHAR));
  1146. buffer[size / sizeof(WCHAR) - 1] = L'\0';
  1147. }
  1148. } else if (valueSeed->Options == OPTIONS_INSERT_COMPATIBLE_IDS) {
  1149. if (FirmwareEntry->PeripheralType == KeyboardPeripheral) {
  1150. size = sizeof(PS2_KEYBOARD_COMPATIBLE_ID);
  1151. RtlCopyMemory(buffer, PS2_KEYBOARD_COMPATIBLE_ID, size);
  1152. } else if (FirmwareEntry->PeripheralType == PointerPeripheral &&
  1153. (wcscmp(pnpid, L"*PNP0F0E") == 0 ||
  1154. wcscmp(pnpid, L"*PNP0F03") == 0 ||
  1155. wcscmp(pnpid, L"*PNP0F12") == 0)) {
  1156. size = sizeof(PS2_MOUSE_COMPATIBLE_ID);
  1157. RtlCopyMemory(buffer, PS2_MOUSE_COMPATIBLE_ID, size);
  1158. } else {
  1159. continue;
  1160. }
  1161. buffer[size / 2] = L'\0'; // 2nd NUL for MULTI_SZ
  1162. size += sizeof(L'\0');
  1163. } else if (valueSeed->Options == OPTIONS_INSERT_DEVICEDESC) {
  1164. size = FirmwareEntry->IdentifierLength;
  1165. RtlCopyMemory(buffer, FirmwareEntry->Identifier, size);
  1166. } else {
  1167. IopDbgPrint((IOP_MAPPER_ERROR_LEVEL, "Mapper: NO VALUE TYPE!\n"));
  1168. ASSERT(FALSE);
  1169. continue;
  1170. }
  1171. RtlInitUnicodeString(&unicodeName,
  1172. valueSeed->ValueName);
  1173. ZwSetValueKey(Handle,
  1174. &unicodeName,
  1175. 0,
  1176. valueSeed->ValueType,
  1177. buffer,
  1178. size);
  1179. }
  1180. ExFreePool(buffer);
  1181. }
  1182. VOID
  1183. MapperFreeList(
  1184. VOID
  1185. )
  1186. /*++
  1187. Routine Description:
  1188. This routine walks through the list of firmware entries
  1189. and frees all allocated memory.
  1190. Arguments:
  1191. None
  1192. Return Value:
  1193. None
  1194. --*/
  1195. {
  1196. PDEVICE_EXTENSION deviceExtension = &MapperDeviceExtension;
  1197. PFIRMWARE_CONFIGURATION tempEntry;
  1198. PFIRMWARE_CONFIGURATION firmwareEntry;
  1199. firmwareEntry = deviceExtension->FirmwareList;
  1200. while (firmwareEntry) {
  1201. //
  1202. // free allocated structures associated with the firmware entry
  1203. //
  1204. if (firmwareEntry->ResourceDescriptor) {
  1205. ExFreePool(firmwareEntry->ResourceDescriptor);
  1206. }
  1207. if (firmwareEntry->Identifier) {
  1208. ExFreePool(firmwareEntry->Identifier);
  1209. }
  1210. //
  1211. // free this entry and move to the next
  1212. //
  1213. tempEntry = firmwareEntry->Next;
  1214. ExFreePool(firmwareEntry);
  1215. firmwareEntry = tempEntry;
  1216. }
  1217. }
  1218. VOID
  1219. MapperConstructRootEnumTree(
  1220. IN BOOLEAN CreatePhantomDevices
  1221. )
  1222. /*++
  1223. Routine Description:
  1224. This routine walks through the list of firmware entries
  1225. in the device extension and migrates the information into
  1226. the root enumerator's tree in the registry.
  1227. Arguments:
  1228. CreatePhantomDevices - If non-zero, then the device instances are created
  1229. as "phantoms" (i.e., they are marked with the "Phantom" value entry so
  1230. that the root enumerator will ignore them). The only time these device
  1231. instance registry keys will ever turn into real live devnodes is if the
  1232. class installer (in response to DIF_FIRSTTIMESETUP or DIF_DETECT)
  1233. decides that these devices aren't duplicates of any PnP-enumerated
  1234. devnodes, and subsequently registers and installs them.
  1235. Return Value:
  1236. None
  1237. --*/
  1238. {
  1239. #define ENUM_KEY_BUFFER_SIZE (1024 * sizeof(WCHAR))
  1240. #define INSTANCE_BUFFER_SIZE (256 * sizeof(WCHAR))
  1241. UNICODE_STRING enumKey;
  1242. PFIRMWARE_CONFIGURATION firmwareEntry;
  1243. OBJECT_ATTRIBUTES objectAttributes;
  1244. NTSTATUS status;
  1245. BOOLEAN keyPresent;
  1246. PWCHAR registryBase;
  1247. PWCHAR instanceBuffer;
  1248. HANDLE handle;
  1249. ULONG disposition;
  1250. PVOID buffer;
  1251. PDEVICE_EXTENSION DeviceExtension = &MapperDeviceExtension;
  1252. PAGED_CODE();
  1253. //
  1254. // allocate space needed for the registry path into the root
  1255. // enumerator tree. Note, limited size on path length.
  1256. //
  1257. buffer = ExAllocatePool(NonPagedPool, ENUM_KEY_BUFFER_SIZE);
  1258. if (!buffer) {
  1259. MapperFreeList();
  1260. IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
  1261. "Mapper: could not allocate memory for registry update\n"));
  1262. return;
  1263. }
  1264. instanceBuffer = ExAllocatePool(NonPagedPool, INSTANCE_BUFFER_SIZE);
  1265. if (!instanceBuffer) {
  1266. MapperFreeList();
  1267. ExFreePool(buffer);
  1268. IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
  1269. "Mapper: could not allocate memory for instance buffer\n"));
  1270. return;
  1271. }
  1272. InitializeObjectAttributes(&objectAttributes,
  1273. &enumKey,
  1274. OBJ_CASE_INSENSITIVE,
  1275. NULL,
  1276. NULL);
  1277. #if UMODETEST
  1278. registryBase = L"\\Registry\\Machine\\System\\TestControlSet\\Enum\\Root\\";
  1279. #else
  1280. registryBase = L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\Root\\";
  1281. #endif
  1282. firmwareEntry = DeviceExtension->FirmwareList;
  1283. while (firmwareEntry) {
  1284. //
  1285. // Construct the base for the path for this entry.
  1286. //
  1287. PiWstrToUnicodeString(&enumKey, NULL);
  1288. enumKey.MaximumLength = ENUM_KEY_BUFFER_SIZE;
  1289. enumKey.Buffer = buffer;
  1290. RtlZeroMemory(buffer, ENUM_KEY_BUFFER_SIZE);
  1291. RtlAppendUnicodeToString(&enumKey, registryBase);
  1292. RtlAppendUnicodeToString(&enumKey, firmwareEntry->PnPId);
  1293. //
  1294. // Build the pnp Key.
  1295. //
  1296. status = ZwCreateKey(&handle,
  1297. KEY_READ | KEY_WRITE,
  1298. &objectAttributes,
  1299. 0,
  1300. NULL,
  1301. REG_OPTION_NON_VOLATILE,
  1302. &disposition);
  1303. if (NT_SUCCESS(status)) {
  1304. //
  1305. // Do not need the handle, so close it
  1306. // Remember if the key was present prior to call
  1307. //
  1308. ZwClose(handle);
  1309. keyPresent = (disposition == REG_OPENED_EXISTING_KEY) ? TRUE : FALSE;
  1310. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  1311. "Mapper: Key was %s\n",
  1312. keyPresent ? "Present" : "Created"));
  1313. //
  1314. // Construct the instance name.
  1315. //
  1316. RtlZeroMemory(instanceBuffer, INSTANCE_BUFFER_SIZE);
  1317. swprintf(instanceBuffer,
  1318. L"\\%d_%d_%d_%d_%d_%d",
  1319. firmwareEntry->BusType,
  1320. firmwareEntry->BusNumber,
  1321. firmwareEntry->ControllerType,
  1322. firmwareEntry->ControllerNumber,
  1323. firmwareEntry->PeripheralType,
  1324. firmwareEntry->PeripheralNumber);
  1325. RtlAppendUnicodeToString(&enumKey, instanceBuffer);
  1326. status = ZwCreateKey(&handle,
  1327. KEY_READ | KEY_WRITE,
  1328. &objectAttributes,
  1329. 0,
  1330. NULL,
  1331. REG_OPTION_NON_VOLATILE,
  1332. &disposition);
  1333. if (NT_SUCCESS(status)) {
  1334. if (firmwareEntry->ResourceDescriptor) {
  1335. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  1336. "Mapper: firmware entry has resources %x\n",
  1337. firmwareEntry->ResourceDescriptor));
  1338. }
  1339. if (firmwareEntry->Identifier) {
  1340. IopDbgPrint((IOP_MAPPER_INFO_LEVEL,
  1341. "Mapper: firmware entry has identifier %x\n",
  1342. firmwareEntry->Identifier));
  1343. }
  1344. //
  1345. // If the key already exists because it was explicitly migrated
  1346. // during textmode setup, we should still consider it a "new key".
  1347. //
  1348. if (disposition != REG_CREATED_NEW_KEY) {
  1349. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  1350. UNICODE_STRING unicodeString;
  1351. status = IopGetRegistryValue(handle,
  1352. REGSTR_VALUE_MIGRATED,
  1353. &keyValueInformation);
  1354. if (NT_SUCCESS(status)) {
  1355. if ((keyValueInformation->Type == REG_DWORD) &&
  1356. (keyValueInformation->DataLength == sizeof(ULONG)) &&
  1357. ((*(PULONG)KEY_VALUE_DATA(keyValueInformation)) != 0)) {
  1358. disposition = REG_CREATED_NEW_KEY;
  1359. }
  1360. ExFreePool(keyValueInformation);
  1361. PiWstrToUnicodeString(&unicodeString, REGSTR_VALUE_MIGRATED);
  1362. ZwDeleteValueKey(handle, &unicodeString);
  1363. }
  1364. }
  1365. //
  1366. // Only if this is a new entry do we see the key.
  1367. //
  1368. if (disposition == REG_CREATED_NEW_KEY) {
  1369. //
  1370. // Remember the fact that the key was newly-created for the
  1371. // PnP BIOS case where we need to come along and "phantomize"
  1372. // all newly-created ntdetect COM ports.
  1373. //
  1374. firmwareEntry->NewlyCreated = TRUE;
  1375. //
  1376. // Create enough information to get pnp to
  1377. // install drivers
  1378. //
  1379. MapperSeedKey(handle,
  1380. &enumKey,
  1381. firmwareEntry,
  1382. CreatePhantomDevices
  1383. );
  1384. }
  1385. MapperMarkKey(handle,
  1386. &enumKey,
  1387. firmwareEntry);
  1388. ZwClose(handle);
  1389. } else {
  1390. IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
  1391. "Mapper: create of instance key failed %x\n",
  1392. status));
  1393. }
  1394. } else {
  1395. IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
  1396. "Mapper: create pnp key failed %x\n",
  1397. status));
  1398. }
  1399. firmwareEntry = firmwareEntry->Next;
  1400. }
  1401. ExFreePool(instanceBuffer);
  1402. }
  1403. PCM_RESOURCE_LIST
  1404. MapperAdjustResourceList (
  1405. IN PCM_RESOURCE_LIST ResourceList,
  1406. IN WCHAR const* PnPId,
  1407. IN OUT PULONG Size
  1408. )
  1409. {
  1410. PCM_PARTIAL_RESOURCE_LIST partialResourceList;
  1411. PCM_PARTIAL_RESOURCE_DESCRIPTOR problemPartialDescriptors;
  1412. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors;
  1413. PCM_RESOURCE_LIST newResourceList;
  1414. ULONG i;
  1415. newResourceList = ResourceList;
  1416. #if _X86_
  1417. if (KeI386MachineType == MACHINE_TYPE_EISA) {
  1418. PCM_FULL_RESOURCE_DESCRIPTOR fullDescriptor;
  1419. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptor;
  1420. PUCHAR nextDescriptor;
  1421. ULONG j;
  1422. ULONG lastResourceIndex;
  1423. fullDescriptor = &ResourceList->List[0];
  1424. for (i = 0; i < ResourceList->Count; i++) {
  1425. partialResourceList = &fullDescriptor->PartialResourceList;
  1426. for (j = 0; j < partialResourceList->Count; j++) {
  1427. partialDescriptor = &partialResourceList->PartialDescriptors[j];
  1428. if (partialDescriptor->Type == CmResourceTypePort) {
  1429. if (partialDescriptor->u.Port.Start.HighPart == 0 &&
  1430. (partialDescriptor->u.Port.Start.LowPart & 0x00000300) == 0) {
  1431. partialDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
  1432. }
  1433. }
  1434. }
  1435. nextDescriptor = (PUCHAR)fullDescriptor + sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
  1436. //
  1437. // account for any resource descriptors in addition to the single
  1438. // imbedded one I've already accounted for (if there aren't any,
  1439. // then I'll end up subtracting off the extra imbedded descriptor
  1440. // from the previous step)
  1441. //
  1442. //
  1443. // finally, account for any extra device specific data at the end of
  1444. // the last partial resource descriptor (if any)
  1445. //
  1446. if (partialResourceList->Count > 0) {
  1447. nextDescriptor += (partialResourceList->Count - 1) *
  1448. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  1449. lastResourceIndex = partialResourceList->Count - 1;
  1450. if (partialResourceList->PartialDescriptors[lastResourceIndex].Type ==
  1451. CmResourceTypeDeviceSpecific) {
  1452. nextDescriptor += partialResourceList->PartialDescriptors[lastResourceIndex].
  1453. u.DeviceSpecificData.DataSize;
  1454. }
  1455. }
  1456. fullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)nextDescriptor;
  1457. }
  1458. }
  1459. #endif
  1460. if (wcscmp(PnPId, FloppyId) == 0) {
  1461. if (ResourceList->Count == 1) {
  1462. partialResourceList = &ResourceList->List->PartialResourceList;
  1463. partialDescriptors = partialResourceList->PartialDescriptors;
  1464. //
  1465. // Look for the one and only one 8 byte port resource
  1466. //
  1467. problemPartialDescriptors = NULL;
  1468. for (i=0; i<partialResourceList->Count; i++) {
  1469. if ((partialDescriptors[i].Type == CmResourceTypePort) &&
  1470. (partialDescriptors[i].u.Port.Length == 8)) {
  1471. if (problemPartialDescriptors == NULL) {
  1472. problemPartialDescriptors = partialDescriptors + i;
  1473. } else {
  1474. problemPartialDescriptors = NULL;
  1475. break;
  1476. }
  1477. }
  1478. }
  1479. if (problemPartialDescriptors) {
  1480. problemPartialDescriptors->u.Port.Length = 6;
  1481. newResourceList = ExAllocatePool (
  1482. NonPagedPool,
  1483. *Size + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
  1484. );
  1485. if (newResourceList) {
  1486. RtlCopyMemory (
  1487. newResourceList,
  1488. ResourceList,
  1489. *Size
  1490. );
  1491. //
  1492. // pick out the new partial resource descriptor
  1493. //
  1494. partialDescriptors = newResourceList->List->
  1495. PartialResourceList.PartialDescriptors;
  1496. partialDescriptors += newResourceList->List->PartialResourceList.Count;
  1497. RtlCopyMemory (
  1498. partialDescriptors,
  1499. problemPartialDescriptors,
  1500. sizeof(*partialDescriptors)
  1501. );
  1502. partialDescriptors->u.Port.Start.QuadPart += 7;
  1503. partialDescriptors->u.Port.Length = 1;
  1504. //
  1505. // we got one more now
  1506. //
  1507. newResourceList->List->PartialResourceList.Count++;
  1508. *Size += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  1509. ExFreePool (ResourceList);
  1510. } else {
  1511. newResourceList = ResourceList;
  1512. }
  1513. }
  1514. }
  1515. }
  1516. return newResourceList;
  1517. }
  1518. NTSTATUS
  1519. ComPortDBAdd(
  1520. IN HANDLE DeviceParamKey,
  1521. IN PWSTR PortName
  1522. )
  1523. {
  1524. UNICODE_STRING portNameString;
  1525. UNICODE_STRING portPrefixString;
  1526. UNICODE_STRING comDBName;
  1527. UNICODE_STRING valueName;
  1528. PKEY_VALUE_PARTIAL_INFORMATION valueInfo;
  1529. ULONG valueInfoLength;
  1530. ULONG returnedLength;
  1531. HANDLE comDBKey;
  1532. ULONG portNo;
  1533. NTSTATUS status;
  1534. RtlInitUnicodeString(&portNameString, PortName);
  1535. if (portNameString.Length > 3 * sizeof(WCHAR)) {
  1536. portNameString.Length = 3 * sizeof(WCHAR);
  1537. }
  1538. PiWstrToUnicodeString(&portPrefixString, L"COM");
  1539. if (RtlCompareUnicodeString(&portNameString, &portPrefixString, TRUE) == 0) {
  1540. portNo = _wtol(&PortName[3]);
  1541. if (portNo > 0 && portNo <= 256) {
  1542. #if UMODETEST
  1543. PiWstrToUnicodeString(&comDBName, L"\\Registry\\Machine\\System\\TestControlSet\\Control\\COM Name Arbiter");
  1544. #else
  1545. PiWstrToUnicodeString(&comDBName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\COM Name Arbiter");
  1546. #endif
  1547. status = IopCreateRegistryKeyEx( &comDBKey,
  1548. NULL,
  1549. &comDBName,
  1550. KEY_ALL_ACCESS,
  1551. REG_OPTION_NON_VOLATILE,
  1552. NULL
  1553. );
  1554. if (NT_SUCCESS(status)) {
  1555. PiWstrToUnicodeString(&valueName, L"ComDB Merge");
  1556. #define COMPORT_DB_MERGE_SIZE 32 // 256 / 8
  1557. valueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + COMPORT_DB_MERGE_SIZE;
  1558. valueInfo = ExAllocatePool(PagedPool, valueInfoLength);
  1559. if (valueInfo != NULL) {
  1560. status = ZwQueryValueKey( comDBKey,
  1561. &valueName,
  1562. KeyValuePartialInformation,
  1563. valueInfo,
  1564. valueInfoLength,
  1565. &returnedLength);
  1566. if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
  1567. valueInfo->Type = REG_BINARY;
  1568. valueInfo->DataLength = COMPORT_DB_MERGE_SIZE;
  1569. RtlZeroMemory(valueInfo->Data, valueInfo->DataLength);
  1570. status = STATUS_SUCCESS;
  1571. }
  1572. if (NT_SUCCESS(status)) {
  1573. portNo--;
  1574. valueInfo->Data[ portNo / 8 ] |= 1 << (portNo % 8);
  1575. status = ZwSetValueKey( comDBKey,
  1576. &valueName,
  1577. 0,
  1578. valueInfo->Type,
  1579. valueInfo->Data,
  1580. valueInfo->DataLength );
  1581. ASSERT(NT_SUCCESS(status));
  1582. }
  1583. ExFreePool(valueInfo);
  1584. }
  1585. ZwClose(comDBKey);
  1586. }
  1587. }
  1588. }
  1589. PiWstrToUnicodeString( &valueName, L"DosDeviceName" );
  1590. status = ZwSetValueKey( DeviceParamKey,
  1591. &valueName,
  1592. 0,
  1593. REG_SZ,
  1594. PortName,
  1595. (ULONG)((wcslen(PortName) + 1) * sizeof(WCHAR)) );
  1596. return status;
  1597. }
  1598. VOID
  1599. MapperPhantomizeDetectedComPorts (
  1600. VOID
  1601. )
  1602. /*++
  1603. Routine Description:
  1604. This routine turns all newly-created firmware/ntdetect COM ports into
  1605. phantoms.
  1606. Arguments:
  1607. None
  1608. Return Value:
  1609. None
  1610. --*/
  1611. {
  1612. PFIRMWARE_CONFIGURATION firmwareEntry;
  1613. NTSTATUS status;
  1614. PWCHAR registryBase;
  1615. PWCHAR instanceBuffer;
  1616. HANDLE handle;
  1617. PWCHAR buffer;
  1618. PDEVICE_EXTENSION DeviceExtension = &MapperDeviceExtension;
  1619. UNICODE_STRING enumKey;
  1620. OBJECT_ATTRIBUTES objectAttributes;
  1621. UNICODE_STRING unicodeName;
  1622. ULONG regValue;
  1623. //
  1624. // allocate space needed for the registry path into the root
  1625. // enumerator tree. Note, limited size on path length.
  1626. //
  1627. buffer = ExAllocatePool(NonPagedPool, ENUM_KEY_BUFFER_SIZE);
  1628. if (!buffer) {
  1629. IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
  1630. "Mapper: could not allocate memory for registry update\n"));
  1631. return;
  1632. }
  1633. instanceBuffer = ExAllocatePool(NonPagedPool, INSTANCE_BUFFER_SIZE);
  1634. if (!instanceBuffer) {
  1635. ExFreePool(buffer);
  1636. IopDbgPrint((IOP_MAPPER_ERROR_LEVEL,
  1637. "Mapper: could not allocate memory for instance buffer\n"));
  1638. return;
  1639. }
  1640. InitializeObjectAttributes(&objectAttributes,
  1641. &enumKey,
  1642. OBJ_CASE_INSENSITIVE,
  1643. NULL,
  1644. NULL);
  1645. #if UMODETEST
  1646. registryBase = L"\\Registry\\Machine\\System\\TestControlSet\\Enum\\Root\\";
  1647. #else
  1648. registryBase = L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\Root\\";
  1649. #endif
  1650. firmwareEntry = DeviceExtension->FirmwareList;
  1651. while (firmwareEntry) {
  1652. //
  1653. // Construct the base for the path for this entry.
  1654. //
  1655. if ((firmwareEntry->ControllerType == SerialController) &&
  1656. firmwareEntry->NewlyCreated) {
  1657. PiWstrToUnicodeString(&enumKey, NULL);
  1658. enumKey.MaximumLength = ENUM_KEY_BUFFER_SIZE;
  1659. enumKey.Buffer = buffer;
  1660. RtlZeroMemory(buffer, ENUM_KEY_BUFFER_SIZE);
  1661. RtlAppendUnicodeToString(&enumKey, registryBase);
  1662. RtlAppendUnicodeToString(&enumKey, firmwareEntry->PnPId);
  1663. //
  1664. // Construct the instance name.
  1665. //
  1666. RtlZeroMemory(instanceBuffer, INSTANCE_BUFFER_SIZE);
  1667. swprintf(instanceBuffer,
  1668. L"\\%d_%d_%d_%d_%d_%d",
  1669. firmwareEntry->BusType,
  1670. firmwareEntry->BusNumber,
  1671. firmwareEntry->ControllerType,
  1672. firmwareEntry->ControllerNumber,
  1673. firmwareEntry->PeripheralType,
  1674. firmwareEntry->PeripheralNumber);
  1675. RtlAppendUnicodeToString(&enumKey, instanceBuffer);
  1676. status = ZwOpenKey(&handle,
  1677. KEY_READ | KEY_WRITE,
  1678. &objectAttributes
  1679. );
  1680. if (NT_SUCCESS(status)) {
  1681. PiWstrToUnicodeString(&unicodeName, REGSTR_VAL_PHANTOM);
  1682. regValue = 1;
  1683. ZwSetValueKey(handle,
  1684. &unicodeName,
  1685. 0,
  1686. REG_DWORD,
  1687. &regValue,
  1688. sizeof(regValue)
  1689. );
  1690. ZwClose(handle);
  1691. }
  1692. }
  1693. firmwareEntry = firmwareEntry->Next;
  1694. }
  1695. ExFreePool (buffer);
  1696. ExFreePool (instanceBuffer);
  1697. }