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.

1475 lines
49 KiB

  1. /*++
  2. Copyright (c) 1995-2000 Microsoft Corporation
  3. Module Name:
  4. bus.c
  5. Abstract:
  6. Author:
  7. Shie-Lin Tzong (shielint) July-26-1995
  8. Environment:
  9. Kernel mode only.
  10. Revision History:
  11. --*/
  12. #include "busp.h"
  13. #include "pnpisa.h"
  14. #if ISOLATE_CARDS
  15. BOOLEAN
  16. PipIsDeviceInstanceInstalled(
  17. IN HANDLE Handle,
  18. IN PUNICODE_STRING DeviceInstanceName
  19. );
  20. VOID
  21. PipInitializeDeviceInfo (
  22. IN OUT PDEVICE_INFORMATION deviceInfo,
  23. IN PCARD_INFORMATION cardinfo,
  24. IN USHORT index
  25. );
  26. NTSTATUS
  27. PipGetInstalledLogConf(
  28. IN HANDLE EnumHandle,
  29. IN PDEVICE_INFORMATION DeviceInfo,
  30. OUT PHANDLE LogConfHandle
  31. );
  32. #ifdef ALLOC_PRAGMA
  33. #pragma alloc_text(PAGE,PipCreateReadDataPort)
  34. #pragma alloc_text(PAGE,PipStartReadDataPort)
  35. #pragma alloc_text(PAGE,PipStartAndSelectRdp)
  36. #pragma alloc_text(PAGE,PipCheckBus)
  37. #pragma alloc_text(PAGE,PipIsDeviceInstanceInstalled)
  38. #pragma alloc_text(PAGE,PipGetInstalledLogConf)
  39. #pragma alloc_text(PAGE,PipInitializeDeviceInfo)
  40. #endif
  41. VOID
  42. PipVerifyCards(
  43. IN OUT ULONG *CardsExpected
  44. )
  45. /*++
  46. Routine Description:
  47. This routine checks to see how many cards can be found using the
  48. current RDP resources.
  49. Arguments:
  50. CardsExpected - Pointer to ULONG in which to store the number of
  51. cards found and minimally verified.
  52. Return Value:
  53. None
  54. --*/
  55. {
  56. ULONG j, cardsDetected = 0;
  57. NTSTATUS status;
  58. ASSERT(PipState == PiSSleep);
  59. if (*CardsExpected == 0) {
  60. return;
  61. }
  62. for (j = 1; j <= *CardsExpected; j++) {
  63. ULONG noDevices, dataLength;
  64. PUCHAR cardData;
  65. PipConfig((UCHAR)j);
  66. status = PipReadCardResourceData (
  67. &noDevices,
  68. &cardData,
  69. &dataLength);
  70. if (!NT_SUCCESS(status)) {
  71. continue;
  72. } else {
  73. ExFreePool(cardData);
  74. cardsDetected++;
  75. }
  76. }
  77. *CardsExpected = cardsDetected;
  78. }
  79. NTSTATUS
  80. PipStartAndSelectRdp(
  81. PDEVICE_INFORMATION DeviceInfo,
  82. PPI_BUS_EXTENSION BusExtension,
  83. PDEVICE_OBJECT DeviceObject,
  84. PCM_RESOURCE_LIST StartResources
  85. )
  86. /*++
  87. Routine Description:
  88. This routine selects an RDP and trims down the resources to just the RDP.
  89. Arguments:
  90. DeviceInfo - device extension for RDP
  91. BusExtension - device extension for BUS object
  92. DeviceObject - device object for RDP
  93. StartResources - the start resources we received in the RDP start irp
  94. Return Value:
  95. STATUS_SUCCESS = Current resources are fine but need trimming
  96. anything else - current resources failed in some way
  97. --*/
  98. {
  99. ULONG i, j, CardsFound, LastMapped = -1;
  100. NTSTATUS status;
  101. // Already tested for null start resources, and start resource list too small
  102. status = PipMapAddressAndCmdPort(BusExtension);
  103. if (!NT_SUCCESS(status)) {
  104. DebugPrint((DEBUG_ERROR, "failed to map the address and command ports\n"));
  105. return status;
  106. }
  107. for (i = 2, j = 0; i < StartResources->List->PartialResourceList.Count; i++, j++) {
  108. PipReadDataPortRanges[j].CardsFound = 0;
  109. // RDP possibilities that we didn't get.
  110. if (StartResources->List->PartialResourceList.PartialDescriptors[i].u.Port.Length == 0) {
  111. continue;
  112. }
  113. status = PipMapReadDataPort(
  114. BusExtension,
  115. StartResources->List->PartialResourceList.PartialDescriptors[i].u.Port.Start,
  116. StartResources->List->PartialResourceList.PartialDescriptors[i].u.Port.Length
  117. );
  118. if (!NT_SUCCESS(status))
  119. {
  120. DebugPrint((DEBUG_ERROR, "failed to map RDP range\n"));
  121. continue;
  122. }
  123. LastMapped = i;
  124. PipIsolateCards(&CardsFound);
  125. DebugPrint((DEBUG_STATE, "Found %d cards at RDP %x\n", CardsFound, BusExtension->ReadDataPort));
  126. #if 0
  127. PipVerifyCards(&CardsFound);
  128. DebugPrint((DEBUG_STATE, "Found %d cards at RDP %x, verified OK\n", CardsFound, BusExtension->ReadDataPort));
  129. #endif
  130. PipReadDataPortRanges[j].CardsFound = CardsFound;
  131. PipWaitForKey();
  132. }
  133. if (LastMapped == -1) { // never mapped a RDP successfully
  134. PipCleanupAcquiredResources(BusExtension);
  135. return STATUS_CONFLICTING_ADDRESSES;
  136. }
  137. //
  138. // Establish that we want trimmed resource requirements and that
  139. // we're still processing the RDP.
  140. //
  141. ASSERT((DeviceInfo->Flags & DF_PROCESSING_RDP) == 0);
  142. DeviceInfo->Flags |= DF_PROCESSING_RDP|DF_REQ_TRIMMED;
  143. //
  144. // Release unwanted resources.
  145. //
  146. PipCleanupAcquiredResources(BusExtension);
  147. IoInvalidateDeviceState(DeviceObject);
  148. return STATUS_SUCCESS;
  149. }
  150. NTSTATUS
  151. PipStartReadDataPort(
  152. PDEVICE_INFORMATION DeviceInfo,
  153. PPI_BUS_EXTENSION BusExtension,
  154. PDEVICE_OBJECT DeviceObject,
  155. PCM_RESOURCE_LIST StartResources
  156. )
  157. {
  158. NTSTATUS status;
  159. ULONG i, CardsFound;
  160. if (StartResources == NULL) {
  161. DebugPrint((DEBUG_ERROR, "Start RDP with no resources?\n"));
  162. ASSERT(0);
  163. return STATUS_UNSUCCESSFUL;
  164. }
  165. if (StartResources->List->PartialResourceList.Count < 2) {
  166. DebugPrint((DEBUG_ERROR, "Start RDP with insufficient resources?\n"));
  167. ASSERT(0);
  168. return STATUS_UNSUCCESSFUL;
  169. }
  170. if (StartResources->List->PartialResourceList.Count > 3) {
  171. return PipStartAndSelectRdp(
  172. DeviceInfo,
  173. BusExtension,
  174. DeviceObject,
  175. StartResources
  176. );
  177. }
  178. DebugPrint((DEBUG_STATE|DEBUG_PNP,
  179. "Starting RDP as port %x\n",
  180. StartResources->List->PartialResourceList.PartialDescriptors[2].u.Port.Start.LowPart + 3));
  181. status = PipMapAddressAndCmdPort(BusExtension);
  182. if (!NT_SUCCESS(status)) {
  183. DebugPrint((DEBUG_ERROR, "failed to map the address and command ports\n"));
  184. return status;
  185. }
  186. status = PipMapReadDataPort(
  187. BusExtension,
  188. StartResources->List->PartialResourceList.PartialDescriptors[2].u.Port.Start,
  189. StartResources->List->PartialResourceList.PartialDescriptors[2].u.Port.Length
  190. );
  191. if (!NT_SUCCESS(status)) {
  192. // BUGBUG probably have to free something
  193. DebugPrint((DEBUG_ERROR, "failed to map RDP range\n"));
  194. return status;
  195. }
  196. PipIsolateCards(&CardsFound);
  197. DebugPrint((DEBUG_STATE, "Found %d cards at RDP %x, WaitForKey\n", CardsFound, BusExtension->ReadDataPort));
  198. #if 0
  199. PipVerifyCards(&CardsFound);
  200. DebugPrint((DEBUG_STATE, "Found %d cards are OK at RDP %x, WaitForKey\n", CardsFound, BusExtension->ReadDataPort));
  201. #endif
  202. DeviceInfo->Flags &= ~DF_PROCESSING_RDP;
  203. DeviceInfo->Flags |= DF_ACTIVATED;
  204. PipWaitForKey();
  205. return status;
  206. }
  207. NTSTATUS
  208. PipCreateReadDataPortBootResources(
  209. IN PDEVICE_INFORMATION DeviceInfo
  210. )
  211. /*++
  212. Routine Description:
  213. This routine creates the CM_RESOURCE_LIST reported as a partial
  214. boot config for the RDP. This ensures that the RDP start isn't
  215. deferred excessively.
  216. Arguments:
  217. DeviceInfo - device extension for PDO
  218. Return Value:
  219. STATUS_SUCCESS
  220. STATUS_INSUFFICIENT_RESOURCES
  221. --*/
  222. {
  223. PCM_RESOURCE_LIST bootResources;
  224. PCM_PARTIAL_RESOURCE_LIST partialResList;
  225. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDesc;
  226. ULONG bootResourcesSize, i;
  227. bootResourcesSize = sizeof(CM_RESOURCE_LIST) +
  228. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  229. bootResources = ExAllocatePool(PagedPool,
  230. bootResourcesSize);
  231. if (bootResources == NULL) {
  232. return STATUS_INSUFFICIENT_RESOURCES;
  233. }
  234. RtlZeroMemory(bootResources, bootResourcesSize);
  235. bootResources->Count = 1;
  236. partialResList = (PCM_PARTIAL_RESOURCE_LIST)&bootResources->List[0].PartialResourceList;
  237. partialResList->Version = 0;
  238. partialResList->Revision = 0x3000;
  239. partialResList->Count = 2;
  240. partialDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)&partialResList->PartialDescriptors[0];
  241. for (i = 0; i < 2; i++) {
  242. partialDesc->Type = CmResourceTypePort;
  243. partialDesc->ShareDisposition = CmResourceShareDeviceExclusive;
  244. partialDesc->Flags = CM_RESOURCE_PORT_IO;
  245. if (i == 0) {
  246. partialDesc->u.Port.Start.LowPart = COMMAND_PORT;
  247. }
  248. else {
  249. partialDesc->u.Port.Start.LowPart = ADDRESS_PORT;
  250. }
  251. partialDesc->Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
  252. partialDesc->u.Port.Length = 1;
  253. partialDesc++;
  254. }
  255. DeviceInfo->BootResources = bootResources;
  256. DeviceInfo->BootResourcesLength = bootResourcesSize;
  257. return STATUS_SUCCESS;
  258. }
  259. NTSTATUS
  260. PipCreateReadDataPort(
  261. PPI_BUS_EXTENSION BusExtension
  262. )
  263. /*++
  264. Routine Description:
  265. This routine isolates all the PNP ISA cards.
  266. Arguments:
  267. None.
  268. Return Value:
  269. Always return STATUS_UNSUCCESSFUL.
  270. --*/
  271. {
  272. NTSTATUS status;
  273. PUCHAR readDataPort = NULL;
  274. PDEVICE_INFORMATION deviceInfo;
  275. PDEVICE_OBJECT pdo;
  276. status = IoCreateDevice(PipDriverObject,
  277. sizeof(PDEVICE_INFORMATION),
  278. NULL,
  279. FILE_DEVICE_BUS_EXTENDER,
  280. FILE_AUTOGENERATED_DEVICE_NAME,
  281. FALSE,
  282. &pdo);
  283. if (!NT_SUCCESS(status)) {
  284. return status;
  285. }
  286. // Create a physical device object to represent this logical function
  287. //
  288. deviceInfo = ExAllocatePoolWithTag(NonPagedPool,
  289. sizeof(DEVICE_INFORMATION),
  290. 'iPnP');
  291. if (!deviceInfo) {
  292. DebugPrint((DEBUG_ERROR, "PnpIsa:failed to allocate DEVICEINFO structure\n"));
  293. IoDeleteDevice(pdo);
  294. return STATUS_INSUFFICIENT_RESOURCES;
  295. }
  296. PipInitializeDeviceInfo (deviceInfo,NULL,0);
  297. status = PipCreateReadDataPortBootResources(deviceInfo);
  298. if (NT_SUCCESS(status)) {
  299. deviceInfo->PhysicalDeviceObject = pdo;
  300. //
  301. // Mark this node as the special read data port node
  302. //
  303. deviceInfo->Flags |= DF_ENUMERATED|DF_READ_DATA_PORT;
  304. deviceInfo->Flags &= ~DF_NOT_FUNCTIONING;
  305. deviceInfo->PhysicalDeviceObject->DeviceExtension = (PVOID)deviceInfo;
  306. deviceInfo->ParentDeviceExtension = BusExtension;
  307. PipRDPNode = deviceInfo;
  308. PipLockDeviceDatabase();
  309. PushEntryList (&BusExtension->DeviceList,
  310. &deviceInfo->DeviceList
  311. );
  312. PipUnlockDeviceDatabase();
  313. deviceInfo->PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  314. } else {
  315. IoDeleteDevice(pdo);
  316. ExFreePool(deviceInfo);
  317. }
  318. return status;
  319. }
  320. //
  321. // PipCheckBus and PipMinimalCheckBus enumerate the ISAPNP cards present.
  322. //
  323. // PipMinimalCheckBus is used on return from hibernation to avoid
  324. // having to make everything referenced by PipCheckBus non-pageable.
  325. //
  326. // Conventions:
  327. // * Cards are marked dead by setting their CSN to 0.
  328. // * Cards are marked potentially missing by setting their CSN to -1.
  329. // Cards that are found later in the routines have their CSNs
  330. // properly set, any remaining cards get their CSN set to 0.
  331. // * Logical devices of dead cards have the DF_NOT_FUNCTIONING flag set.
  332. //
  333. BOOLEAN
  334. PipMinimalCheckBus (
  335. IN PPI_BUS_EXTENSION BusExtension
  336. )
  337. /*++
  338. Routine Description:
  339. This routine enumerates the ISAPNP cards on return from hibernate.
  340. It is a subset of PipCheckBus and assumes that PipCheckBus will be
  341. run shortly thereafter. It deals with cards that disappear after
  342. hibernate or new cards that have appeared. It's primary task is
  343. to put cards where they used to be before the hibernate.
  344. Arguments:
  345. BusExtension - FDO extension
  346. Return Value:
  347. None
  348. --*/
  349. {
  350. PDEVICE_INFORMATION deviceInfo;
  351. PCARD_INFORMATION cardInfo;
  352. PSINGLE_LIST_ENTRY cardLink, deviceLink;
  353. ULONG dataLength, noDevices, logicalDevice, FoundCSNs, i;
  354. NTSTATUS status;
  355. USHORT csn;
  356. PUCHAR cardData;
  357. BOOLEAN needsFullRescan = FALSE;
  358. DebugPrint((DEBUG_POWER | DEBUG_ISOLATE,
  359. "Minimal check bus for restore: %d CSNs expected\n",
  360. BusExtension->NumberCSNs
  361. ));
  362. DebugPrint((DEBUG_POWER, "reset csns in extensions\n"));
  363. // forget any previously issued CSNs
  364. cardLink = BusExtension->CardList.Next;
  365. while (cardLink) {
  366. cardInfo = CONTAINING_RECORD (cardLink, CARD_INFORMATION, CardList);
  367. if (cardInfo->CardSelectNumber != 0) {
  368. cardInfo->CardSelectNumber = (USHORT) -1;
  369. }
  370. cardLink = cardInfo->CardList.Next;
  371. }
  372. //
  373. // Perform Pnp isolation process. This will assign card select number for each
  374. // Pnp Isa card isolated by the system. All the isolated cards will be left in
  375. // isolation state.
  376. //
  377. if (PipReadDataPort && PipCommandPort && PipAddressPort) {
  378. PipIsolateCards(&FoundCSNs);
  379. DebugPrint((DEBUG_POWER | DEBUG_ISOLATE,
  380. "Minimal check bus for restore: %d cards found\n",
  381. FoundCSNs));
  382. } else {
  383. //
  384. // If we can't enumerate (no resources) stop now
  385. //
  386. DebugPrint((DEBUG_POWER | DEBUG_ISOLATE,
  387. "Minimal check bus failed, no resources\n"));
  388. PipWaitForKey();
  389. return FALSE;
  390. }
  391. //
  392. // For each card selected build CardInformation and DeviceInformation structures.
  393. //
  394. // PipLFSRInitiation(); BUG?
  395. for (csn = 1; csn <= FoundCSNs; csn++) {
  396. PipConfig((UCHAR)csn);
  397. status = PipReadCardResourceData (
  398. &noDevices,
  399. &cardData,
  400. &dataLength);
  401. if (!NT_SUCCESS(status)) {
  402. DebugPrint((DEBUG_ERROR | DEBUG_POWER, "CSN %d gives bad resource data\n", csn));
  403. continue;
  404. }
  405. cardInfo = PipIsCardEnumeratedAlready(BusExtension, cardData, dataLength);
  406. if (!cardInfo) {
  407. DebugPrint((DEBUG_ERROR | DEBUG_POWER,
  408. "No match for card CSN %d, turning off\n", csn));
  409. for (i = 0; i < noDevices; i++) {
  410. PipSelectDevice((UCHAR) i);
  411. PipDeactivateDevice();
  412. }
  413. needsFullRescan = TRUE;
  414. continue;
  415. }
  416. cardInfo->CardSelectNumber = csn;
  417. for (deviceLink = cardInfo->LogicalDeviceList.Next; deviceLink;
  418. deviceLink = deviceInfo->LogicalDeviceList.Next) {
  419. deviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, LogicalDeviceList);
  420. if (deviceInfo->Flags & DF_NOT_FUNCTIONING) {
  421. continue;
  422. }
  423. PipSelectDevice((UCHAR)deviceInfo->LogicalDeviceNumber);
  424. if ((deviceInfo->DevicePowerState == PowerDeviceD0) &&
  425. (deviceInfo->Flags & DF_ACTIVATED))
  426. {
  427. DebugPrint((DEBUG_POWER, "CSN %d/LDN %d was never powered off\n",
  428. (ULONG) deviceInfo->LogicalDeviceNumber,
  429. (ULONG) csn));
  430. PipDeactivateDevice();
  431. (VOID) PipSetDeviceResources(deviceInfo,
  432. deviceInfo->AllocatedResources);
  433. PipActivateDevice();
  434. } else {
  435. PipDeactivateDevice();
  436. }
  437. }
  438. }
  439. cardLink = BusExtension->CardList.Next;
  440. while (cardLink) {
  441. cardInfo = CONTAINING_RECORD (cardLink, CARD_INFORMATION, CardList);
  442. if (cardInfo->CardSelectNumber == (USHORT)-1) {
  443. DebugPrint((DEBUG_ERROR, "Marked a card as DEAD, logical devices\n"));
  444. cardInfo->CardSelectNumber = (USHORT)0; // Mark it is no longer present
  445. deviceLink = cardInfo->LogicalDeviceList.Next;
  446. while (deviceLink) {
  447. deviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, LogicalDeviceList);
  448. deviceInfo->Flags |= DF_NOT_FUNCTIONING;
  449. deviceLink = deviceInfo->LogicalDeviceList.Next;
  450. }
  451. needsFullRescan = TRUE;
  452. }
  453. cardLink = cardInfo->CardList.Next;
  454. }
  455. PipWaitForKey();
  456. return needsFullRescan;
  457. }
  458. VOID
  459. PipCheckBus (
  460. IN PPI_BUS_EXTENSION BusExtension
  461. )
  462. /*++
  463. Routine Description:
  464. The function enumerates the bus specified by BusExtension
  465. Arguments:
  466. BusExtension - supplies a pointer to the BusExtension structure of the bus
  467. to be enumerated.
  468. Return Value:
  469. None.
  470. --*/
  471. {
  472. NTSTATUS status;
  473. ULONG objectSize, noDevices;
  474. OBJECT_ATTRIBUTES objectAttributes;
  475. PUCHAR cardData;
  476. ULONG dataLength;
  477. USHORT csn, i, detectedCsn = 0, irqReqFlags, irqBootFlags;
  478. PDEVICE_INFORMATION deviceInfo;
  479. PCARD_INFORMATION cardInfo;
  480. UCHAR tmp;
  481. PSINGLE_LIST_ENTRY link;
  482. ULONG dumpData;
  483. UNICODE_STRING unicodeString;
  484. HANDLE logConfHandle, enumHandle = NULL;
  485. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  486. PCM_RESOURCE_LIST cmResource;
  487. BOOLEAN conflictDetected,requireEdge;
  488. ULONG dummy, bootFlags = 0;
  489. PSINGLE_LIST_ENTRY deviceLink;
  490. PSINGLE_LIST_ENTRY cardLink;
  491. // mark all cards as 'maybe missing'
  492. cardLink = BusExtension->CardList.Next;
  493. while (cardLink) {
  494. cardInfo = CONTAINING_RECORD (cardLink, CARD_INFORMATION, CardList);
  495. if (cardInfo->CardSelectNumber != (USHORT)0) {
  496. cardInfo->CardSelectNumber = (USHORT)-1;
  497. }
  498. cardLink = cardInfo->CardList.Next;
  499. }
  500. //
  501. // Clear DF_ENUMERTED flag for all the devices.
  502. //
  503. deviceLink = BusExtension->DeviceList.Next;
  504. while (deviceLink) {
  505. deviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, DeviceList);
  506. if (!(deviceInfo->Flags & DF_READ_DATA_PORT)) {
  507. deviceInfo ->Flags &= ~DF_ENUMERATED;
  508. }
  509. deviceLink = deviceInfo->DeviceList.Next;
  510. }
  511. //
  512. // Perform Pnp isolation process. This will assign card select number for each
  513. // Pnp Isa card isolated by the system. All the isolated cards will be left in
  514. // isolation state.
  515. //
  516. if (PipReadDataPort && PipCommandPort && PipAddressPort) {
  517. DebugPrint((DEBUG_PNP, "QueryDeviceRelations checking the BUS\n"));
  518. PipIsolateCards(&BusExtension->NumberCSNs);
  519. } else {
  520. //
  521. // If we can't enumerate (no resources) stop now
  522. //
  523. DebugPrint((DEBUG_PNP, "QueryDeviceRelations: No RDP\n"));
  524. return;
  525. }
  526. DebugPrint((DEBUG_PNP, "CheckBus found %d cards\n",
  527. BusExtension->NumberCSNs));
  528. #if NT4_DRIVER_COMPAT
  529. //
  530. // If there is no PnpISA card, we are done.
  531. // Oterwise, open HKLM\System\CCS\ENUM\PNPISA.
  532. //
  533. if (BusExtension->NumberCSNs != 0) {
  534. RtlInitUnicodeString(
  535. &unicodeString,
  536. L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
  537. status = PipOpenRegistryKey(&enumHandle,
  538. NULL,
  539. &unicodeString,
  540. KEY_ALL_ACCESS,
  541. FALSE
  542. );
  543. if (!NT_SUCCESS(status)) {
  544. dumpData = status;
  545. PipLogError(PNPISA_OPEN_CURRENTCONTROLSET_ENUM_FAILED,
  546. PNPISA_CHECKDEVICE_1,
  547. status,
  548. &dumpData,
  549. 1,
  550. 0,
  551. NULL
  552. );
  553. DebugPrint((DEBUG_ERROR, "PnPIsa: Unable to open HKLM\\SYSTEM\\CCS\\ENUM"));
  554. return;
  555. }
  556. }
  557. #endif // NT4_DRIVER_COMPAT
  558. //
  559. // For each card selected build CardInformation and DeviceInformation structures.
  560. //
  561. for (csn = 1; csn <= BusExtension->NumberCSNs; csn++) {
  562. PipConfig((UCHAR)csn);
  563. status = PipReadCardResourceData (
  564. &noDevices,
  565. &cardData,
  566. &dataLength);
  567. if (!NT_SUCCESS(status)) {
  568. //
  569. // card will marked 'not functioning' later
  570. //
  571. DebugPrint((DEBUG_ERROR, "PnpIsaCheckBus: Found a card which gives bad resource data\n"));
  572. continue;
  573. }
  574. detectedCsn++;
  575. cardInfo = PipIsCardEnumeratedAlready(BusExtension, cardData, dataLength);
  576. if (!cardInfo) {
  577. //
  578. // Allocate and initialize card information and its associate device
  579. // information structures.
  580. //
  581. cardInfo = (PCARD_INFORMATION)ExAllocatePoolWithTag(
  582. NonPagedPool,
  583. sizeof(CARD_INFORMATION),
  584. 'iPnP');
  585. if (!cardInfo) {
  586. dumpData = sizeof(CARD_INFORMATION);
  587. PipLogError(PNPISA_INSUFFICIENT_POOL,
  588. PNPISA_CHECKBUS_1,
  589. STATUS_INSUFFICIENT_RESOURCES,
  590. &dumpData,
  591. 1,
  592. 0,
  593. NULL
  594. );
  595. ExFreePool(cardData);
  596. DebugPrint((DEBUG_ERROR, "PnpIsaCheckBus: failed to allocate CARD_INFO structure\n"));
  597. continue;
  598. }
  599. //
  600. // Initialize card information structure
  601. //
  602. RtlZeroMemory(cardInfo, sizeof(CARD_INFORMATION));
  603. cardInfo->CardSelectNumber = csn;
  604. cardInfo->NumberLogicalDevices = noDevices;
  605. cardInfo->CardData = cardData;
  606. cardInfo->CardDataLength = dataLength;
  607. cardInfo->CardFlags = PipGetCardFlags(cardInfo);
  608. PushEntryList (&BusExtension->CardList,
  609. &cardInfo->CardList
  610. );
  611. DebugPrint ((DEBUG_ISOLATE, "adding one pnp card %x\n",
  612. cardInfo));
  613. //
  614. // For each logical device supported by the card build its DEVICE_INFORMATION
  615. // structures.
  616. //
  617. cardData += sizeof(SERIAL_IDENTIFIER);
  618. dataLength -= sizeof(SERIAL_IDENTIFIER);
  619. PipFindNextLogicalDeviceTag(&cardData, &dataLength);
  620. //
  621. // Select card
  622. //
  623. for (i = 0; i < noDevices; i++) { // logical device number starts from 0
  624. //
  625. // Create and initialize device tracking structure (Device_Information.)
  626. //
  627. deviceInfo = (PDEVICE_INFORMATION) ExAllocatePoolWithTag(
  628. NonPagedPool,
  629. sizeof(DEVICE_INFORMATION),
  630. 'iPnP');
  631. if (!deviceInfo) {
  632. dumpData = sizeof(DEVICE_INFORMATION);
  633. PipLogError(PNPISA_INSUFFICIENT_POOL,
  634. PNPISA_CHECKBUS_2,
  635. STATUS_INSUFFICIENT_RESOURCES,
  636. &dumpData,
  637. 1,
  638. 0,
  639. NULL
  640. );
  641. DebugPrint((DEBUG_ERROR, "PnpIsa:failed to allocate DEVICEINFO structure\n"));
  642. continue;
  643. }
  644. //
  645. // This sets card data to point to the next device.
  646. //
  647. PipInitializeDeviceInfo (deviceInfo,cardInfo,i);
  648. deviceInfo->ParentDeviceExtension = BusExtension;
  649. //
  650. // cardData is UPDATED by this routine to the next logical device.
  651. //
  652. deviceInfo->DeviceData = cardData;
  653. if (cardData) {
  654. deviceInfo->DeviceDataLength = PipFindNextLogicalDeviceTag(&cardData, &dataLength);
  655. } else {
  656. deviceInfo->DeviceDataLength = 0;
  657. ASSERT(deviceInfo->DeviceDataLength != 0);
  658. continue;
  659. }
  660. ASSERT(deviceInfo->DeviceDataLength != 0);
  661. //
  662. // The PNP ISA spec lets the device specify IRQ
  663. // settings that don't actually work, and some that
  664. // work rarely. And some devices just get it wrong.
  665. //
  666. // IRQ edge/level interpretation strategy:
  667. //
  668. // * Extract the irq requirements from the tags on a
  669. // per device basis.
  670. // * Extract the boot config, note edge/level settings
  671. // * Trust the boot config over requirements. When in
  672. // doubt, assume edge.
  673. // * Fix boot config and requirements to reflect the
  674. // edge/level settings we've decided upon.
  675. // * Ignore the high/low settings in the requirements
  676. // and in the boot config. Only support high- // edge
  677. // and low-level.
  678. //
  679. // Determine whether requirements specify edge or
  680. // level triggered interrupts. Unfortunately, we
  681. // don't build the IO_REQUIREMENTS_LIST until later,
  682. // so just examine the tags.
  683. irqReqFlags = PipIrqLevelRequirementsFromDeviceData(
  684. deviceInfo->DeviceData,
  685. deviceInfo->DeviceDataLength
  686. );
  687. DebugPrint((DEBUG_IRQ, "Irqs for CSN %d/LDN %d are %s\n",
  688. deviceInfo->CardInformation->CardSelectNumber,
  689. deviceInfo->LogicalDeviceNumber,
  690. (irqReqFlags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) ? "level" : "edge"));
  691. //
  692. // Select the logical device, disable its io range check
  693. // and read its boot config before disabling it.
  694. //
  695. PipSelectDevice((UCHAR)i);
  696. if (!(deviceInfo->CardInformation->CardFlags & CF_IGNORE_BOOTCONFIG)) {
  697. status = PipReadDeviceResources (
  698. 0,
  699. deviceInfo->DeviceData,
  700. deviceInfo->CardInformation->CardFlags,
  701. &deviceInfo->BootResources,
  702. &deviceInfo->BootResourcesLength,
  703. &irqBootFlags
  704. );
  705. if (!NT_SUCCESS(status)) {
  706. deviceInfo->BootResources = NULL;
  707. deviceInfo->BootResourcesLength = 0;
  708. // If we had a boot config on this boot,
  709. // extract saved irqBootFlags that we saved earlier.
  710. status = PipGetBootIrqFlags(deviceInfo, &irqBootFlags);
  711. if (!NT_SUCCESS(status)) {
  712. // if we have no boot config, and no saved
  713. // boot config from earlier this boot then
  714. // we are going to take a shot in the dark
  715. // and declare it edge. Experience has
  716. // shown that if you actually believe
  717. // resource requirements of level w/o
  718. // confirmation from the BIOS, then you
  719. // die horribly. Very very few cards
  720. // actually do level and do it right.
  721. irqBootFlags = CM_RESOURCE_INTERRUPT_LATCHED;
  722. (VOID) PipSaveBootIrqFlags(deviceInfo, irqBootFlags);
  723. }
  724. } else {
  725. // save irqBootFlags in case the RDP gets
  726. // removed and our boot config is lost.
  727. (VOID) PipSaveBootIrqFlags(deviceInfo, irqBootFlags);
  728. }
  729. DebugPrint((DEBUG_IRQ, "Irqs (boot config) for CSN %d/LDN %d are %s\n",
  730. deviceInfo->CardInformation->CardSelectNumber,
  731. deviceInfo->LogicalDeviceNumber,
  732. (irqBootFlags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) ? "level" : "edge"));
  733. } else {
  734. // when in doubt....
  735. irqBootFlags = CM_RESOURCE_INTERRUPT_LATCHED;
  736. }
  737. if (irqBootFlags != irqReqFlags) {
  738. DebugPrint((DEBUG_IRQ, "Req and Boot config disagree on irq type, favoring boot config"));
  739. irqReqFlags = irqBootFlags;
  740. }
  741. // override flags in case a card *MUST* be configured
  742. // one way and the above code fails to do this.
  743. if (deviceInfo->CardInformation->CardFlags == CF_FORCE_LEVEL) {
  744. irqReqFlags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
  745. } else if (deviceInfo->CardInformation->CardFlags == CF_FORCE_EDGE) {
  746. irqReqFlags = CM_RESOURCE_INTERRUPT_LATCHED;
  747. }
  748. if (deviceInfo->BootResources) {
  749. // apply irq level/edge decision to boot config
  750. PipFixBootConfigIrqs(deviceInfo->BootResources,
  751. irqReqFlags);
  752. (VOID) PipSaveBootResources(deviceInfo);
  753. cmResource = deviceInfo->BootResources;
  754. } else {
  755. status = PipGetSavedBootResources(deviceInfo, &cmResource);
  756. if (!NT_SUCCESS(status)) {
  757. cmResource = NULL;
  758. }
  759. }
  760. #if 0
  761. PipWriteAddress(IO_RANGE_CHECK_PORT);
  762. tmp = PipReadData();
  763. tmp &= ~2;
  764. PipWriteAddress(IO_RANGE_CHECK_PORT);
  765. PipWriteData(tmp);
  766. #endif
  767. PipDeactivateDevice();
  768. PipQueryDeviceResourceRequirements (
  769. deviceInfo,
  770. 0, // Bus Number
  771. 0, // Slot number??
  772. cmResource,
  773. irqReqFlags,
  774. &deviceInfo->ResourceRequirements,
  775. &dumpData
  776. );
  777. if (cmResource && !deviceInfo->BootResources) {
  778. ExFreePool(cmResource);
  779. cmResource = NULL;
  780. }
  781. //
  782. // Create a physical device object to represent this logical function
  783. //
  784. status = IoCreateDevice( PipDriverObject,
  785. sizeof(PDEVICE_INFORMATION),
  786. NULL,
  787. FILE_DEVICE_BUS_EXTENDER,
  788. FILE_AUTOGENERATED_DEVICE_NAME,
  789. FALSE,
  790. &deviceInfo->PhysicalDeviceObject);
  791. if (NT_SUCCESS(status)) {
  792. deviceInfo->Flags |= DF_ENUMERATED;
  793. deviceInfo->Flags &= ~DF_NOT_FUNCTIONING;
  794. deviceInfo->PhysicalDeviceObject->DeviceExtension = (PVOID)deviceInfo;
  795. //
  796. // Add it to the logical device list of the pnp isa card.
  797. //
  798. PushEntryList (&cardInfo->LogicalDeviceList,
  799. &deviceInfo->LogicalDeviceList
  800. );
  801. //
  802. // Add it to the list of devices for this bus
  803. //
  804. PushEntryList (&BusExtension->DeviceList,
  805. &deviceInfo->DeviceList
  806. );
  807. #if NT4_DRIVER_COMPAT
  808. //
  809. // Check should we enable this device. If the device has
  810. // Service setup and ForcedConfig then enable the device.
  811. //
  812. logConfHandle = NULL;
  813. status = PipGetInstalledLogConf(enumHandle,
  814. deviceInfo,
  815. &logConfHandle);
  816. if (NT_SUCCESS(status)) {
  817. //
  818. // Read the boot config selected by user and activate the device.
  819. // First check if ForcedConfig is set. If not, check BootConfig.
  820. //
  821. status = PipGetRegistryValue(logConfHandle,
  822. L"ForcedConfig",
  823. &keyValueInformation);
  824. if (NT_SUCCESS(status)) {
  825. if ((keyValueInformation->Type == REG_RESOURCE_LIST) &&
  826. (keyValueInformation->DataLength != 0)) {
  827. cmResource = (PCM_RESOURCE_LIST)
  828. KEY_VALUE_DATA(keyValueInformation);
  829. //
  830. // Act as if force config
  831. // reflected the level/edge
  832. // decision we made based on
  833. // the boot config and
  834. // resource requirements.
  835. //
  836. PipFixBootConfigIrqs(cmResource,
  837. irqReqFlags);
  838. conflictDetected = FALSE;
  839. //
  840. // Before activating the device, make sure no one is using
  841. // the resources.
  842. //
  843. status = IoReportResourceForDetection(
  844. PipDriverObject,
  845. NULL,
  846. 0,
  847. deviceInfo->PhysicalDeviceObject,
  848. cmResource,
  849. keyValueInformation->DataLength,
  850. &conflictDetected
  851. );
  852. if (NT_SUCCESS(status) && (conflictDetected == FALSE)) {
  853. //
  854. // Set resources and activate the device.
  855. //
  856. status = PipSetDeviceResources (deviceInfo, cmResource);
  857. if (NT_SUCCESS(status)) {
  858. PipActivateDevice();
  859. deviceInfo->Flags |= DF_ACTIVATED;
  860. deviceInfo->Flags &= ~DF_REMOVED;
  861. //
  862. // Write ForcedConfig to AllocConfig
  863. //
  864. RtlInitUnicodeString(&unicodeString, L"AllocConfig");
  865. ZwSetValueKey(logConfHandle,
  866. &unicodeString,
  867. 0,
  868. REG_RESOURCE_LIST,
  869. cmResource,
  870. keyValueInformation->DataLength
  871. );
  872. //
  873. // Make ForcedConfig our new BootConfig.
  874. //
  875. if (deviceInfo->BootResources) {
  876. ExFreePool(deviceInfo->BootResources);
  877. deviceInfo->BootResourcesLength = 0;
  878. deviceInfo->BootResources = NULL;
  879. }
  880. deviceInfo->BootResources = (PCM_RESOURCE_LIST) ExAllocatePool (
  881. PagedPool, keyValueInformation->DataLength);
  882. if (deviceInfo->BootResources) {
  883. deviceInfo->BootResourcesLength = keyValueInformation->DataLength;
  884. RtlMoveMemory(deviceInfo->BootResources,
  885. cmResource,
  886. deviceInfo->BootResourcesLength
  887. );
  888. }
  889. deviceInfo->DevicePowerState = PowerDeviceD0;
  890. deviceInfo->LogConfHandle = logConfHandle;
  891. }
  892. //
  893. // Release the resources. If someone else gets the resources
  894. // before us, then ....
  895. //
  896. dummy = 0;
  897. IoReportResourceForDetection(
  898. PipDriverObject,
  899. NULL,
  900. 0,
  901. deviceInfo->PhysicalDeviceObject,
  902. (PCM_RESOURCE_LIST) &dummy,
  903. sizeof(dummy),
  904. &conflictDetected
  905. );
  906. }
  907. }
  908. ExFreePool(keyValueInformation);
  909. }
  910. if (deviceInfo->LogConfHandle == NULL) {
  911. ZwClose(logConfHandle);
  912. }
  913. }
  914. #endif
  915. deviceInfo->PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  916. } else {
  917. // NTRAID#20181
  918. // Still leaking the DeviceInfo structure
  919. // and it's contents if IoCreateDevice failed.
  920. }
  921. }
  922. } else {
  923. //
  924. // The card has been enumerated and setup. We only need to change the CSN.
  925. //
  926. cardInfo->CardSelectNumber = csn;
  927. ExFreePool(cardData);
  928. //
  929. // Set DF_ENUMERATED flag on all the logical devices on the isapnp card.
  930. //
  931. deviceLink = cardInfo->LogicalDeviceList.Next;
  932. while (deviceLink) {
  933. deviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, LogicalDeviceList);
  934. if (!(deviceInfo->Flags & DF_NOT_FUNCTIONING)) {
  935. deviceInfo->Flags |= DF_ENUMERATED;
  936. }
  937. // what did this accomplish?
  938. if ((deviceInfo->DevicePowerState == PowerDeviceD0) &&
  939. (deviceInfo->Flags & DF_ACTIVATED)) {
  940. PipSelectDevice((UCHAR)deviceInfo->LogicalDeviceNumber);
  941. PipActivateDevice();
  942. }
  943. deviceLink = deviceInfo->LogicalDeviceList.Next;
  944. }
  945. }
  946. }
  947. //
  948. // Go through the card link list for cards that we didn't find this time.
  949. //
  950. cardLink = BusExtension->CardList.Next;
  951. while (cardLink) {
  952. cardInfo = CONTAINING_RECORD (cardLink, CARD_INFORMATION, CardList);
  953. if (cardInfo->CardSelectNumber == (USHORT)-1) {
  954. DebugPrint((DEBUG_ERROR, "Marked a card as DEAD, logical devices\n"));
  955. cardInfo->CardSelectNumber = (USHORT)0; // Mark it is no longer present
  956. deviceLink = cardInfo->LogicalDeviceList.Next;
  957. while (deviceLink) {
  958. deviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, LogicalDeviceList);
  959. deviceInfo->Flags |= DF_NOT_FUNCTIONING;
  960. deviceInfo->Flags &= ~DF_ENUMERATED;
  961. deviceLink = deviceInfo->LogicalDeviceList.Next;
  962. }
  963. }
  964. cardLink = cardInfo->CardList.Next;
  965. }
  966. #if NT4_DRIVER_COMPAT
  967. if (enumHandle) {
  968. ZwClose(enumHandle);
  969. }
  970. #endif
  971. //
  972. // Finaly put all cards into wait for key state.
  973. //
  974. DebugPrint((DEBUG_STATE, "All cards ready\n"));
  975. PipWaitForKey();
  976. BusExtension->NumberCSNs = detectedCsn;
  977. }
  978. BOOLEAN
  979. PipIsDeviceInstanceInstalled(
  980. IN HANDLE Handle,
  981. IN PUNICODE_STRING DeviceInstanceName
  982. )
  983. /*++
  984. Routine Description:
  985. This routine checks if the device instance is installed.
  986. Arguments:
  987. Handle - Supplies a handle to the device instanace key to be checked.
  988. DeviceInstanceName - supplies a pointer to a UNICODE_STRING which specifies
  989. the path of the device instance to be checked.
  990. Returns:
  991. A BOOLEAN value.
  992. --*/
  993. {
  994. NTSTATUS status;
  995. ULONG deviceFlags;
  996. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  997. BOOLEAN installed;
  998. UNICODE_STRING serviceName, unicodeString;
  999. HANDLE handle, handlex;
  1000. ULONG dumpData;
  1001. //
  1002. // Check if the "Service=" value entry initialized. If no, its driver
  1003. // is not installed yet.
  1004. //
  1005. status = PipGetRegistryValue(Handle,
  1006. L"Service",
  1007. &keyValueInformation);
  1008. if (NT_SUCCESS(status)) {
  1009. if ((keyValueInformation->Type == REG_SZ) &&
  1010. (keyValueInformation->DataLength != 0)) {
  1011. serviceName.Buffer = (PWSTR)((PCHAR)keyValueInformation +
  1012. keyValueInformation->DataOffset);
  1013. serviceName.MaximumLength = serviceName.Length = (USHORT)keyValueInformation->DataLength;
  1014. if (serviceName.Buffer[(keyValueInformation->DataLength / sizeof(WCHAR)) - 1] == UNICODE_NULL) {
  1015. serviceName.Length -= sizeof(WCHAR);
  1016. }
  1017. //
  1018. // try open the service key to make sure it is a valid key
  1019. //
  1020. RtlInitUnicodeString(
  1021. &unicodeString,
  1022. L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\SERVICES");
  1023. status = PipOpenRegistryKey(&handle,
  1024. NULL,
  1025. &unicodeString,
  1026. KEY_READ,
  1027. FALSE
  1028. );
  1029. if (!NT_SUCCESS(status)) {
  1030. dumpData = status;
  1031. PipLogError(PNPISA_OPEN_CURRENTCONTROLSET_SERVICE_FAILED,
  1032. PNPISA_CHECKINSTALLED_1,
  1033. status,
  1034. &dumpData,
  1035. 1,
  1036. 0,
  1037. NULL
  1038. );
  1039. DebugPrint((DEBUG_ERROR, "PnPIsaCheckDeviceInstalled: Can not open CCS\\SERVICES key"));
  1040. ExFreePool(keyValueInformation);
  1041. return FALSE;
  1042. }
  1043. status = PipOpenRegistryKey(&handlex,
  1044. handle,
  1045. &serviceName,
  1046. KEY_READ,
  1047. FALSE
  1048. );
  1049. ZwClose (handle);
  1050. if (!NT_SUCCESS(status)) {
  1051. dumpData = status;
  1052. PipLogError(PNPISA_OPEN_CURRENTCONTROLSET_SERVICE_DRIVER_FAILED,
  1053. PNPISA_CHECKINSTALLED_2,
  1054. status,
  1055. &dumpData,
  1056. 1,
  1057. serviceName.Length,
  1058. serviceName.Buffer
  1059. );
  1060. DebugPrint((DEBUG_ERROR, "PnPIsaCheckDeviceInstalled: Can not open CCS\\SERVICES key"));
  1061. ExFreePool(keyValueInformation);
  1062. return FALSE;
  1063. }
  1064. ZwClose(handlex);
  1065. }
  1066. ExFreePool(keyValueInformation);
  1067. } else {
  1068. return FALSE;
  1069. }
  1070. //
  1071. // Check if the device instance has been disabled.
  1072. // First check global flag: CONFIGFLAG and then CSCONFIGFLAG.
  1073. //
  1074. deviceFlags = 0;
  1075. status = PipGetRegistryValue(Handle,
  1076. L"ConfigFlags",
  1077. &keyValueInformation);
  1078. if (NT_SUCCESS(status)) {
  1079. if ((keyValueInformation->Type == REG_DWORD) &&
  1080. (keyValueInformation->DataLength >= sizeof(ULONG))) {
  1081. deviceFlags = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
  1082. }
  1083. ExFreePool(keyValueInformation);
  1084. }
  1085. if (!(deviceFlags & CONFIGFLAG_DISABLED)) {
  1086. deviceFlags = 0;
  1087. status = PipGetDeviceInstanceCsConfigFlags(
  1088. DeviceInstanceName,
  1089. &deviceFlags
  1090. );
  1091. if (NT_SUCCESS(status)) {
  1092. if ((deviceFlags & CSCONFIGFLAG_DISABLED) ||
  1093. (deviceFlags & CSCONFIGFLAG_DO_NOT_CREATE)) {
  1094. deviceFlags = CONFIGFLAG_DISABLED;
  1095. } else {
  1096. deviceFlags = 0;
  1097. }
  1098. }
  1099. }
  1100. installed = TRUE;
  1101. if (deviceFlags & CONFIGFLAG_DISABLED) {
  1102. installed = FALSE;
  1103. }
  1104. return installed;
  1105. }
  1106. VOID
  1107. PipInitializeDeviceInfo (PDEVICE_INFORMATION deviceInfo,
  1108. PCARD_INFORMATION cardInfo,
  1109. USHORT index
  1110. )
  1111. {
  1112. ULONG dataLength;
  1113. RtlZeroMemory (deviceInfo,sizeof (DEVICE_INFORMATION));
  1114. deviceInfo->Flags = DF_NOT_FUNCTIONING;
  1115. deviceInfo->CardInformation = cardInfo;
  1116. deviceInfo->LogicalDeviceNumber = index;
  1117. deviceInfo->DevicePowerState = PowerDeviceD0;
  1118. }
  1119. #if NT4_DRIVER_COMPAT
  1120. NTSTATUS
  1121. PipGetInstalledLogConf(
  1122. IN HANDLE EnumHandle,
  1123. IN PDEVICE_INFORMATION DeviceInfo,
  1124. OUT PHANDLE LogConfHandle
  1125. )
  1126. {
  1127. HANDLE deviceIdHandle = NULL, uniqueIdHandle = NULL, confHandle = NULL;
  1128. PWCHAR deviceId = NULL, uniqueId = NULL, buffer;
  1129. UNICODE_STRING unicodeString;
  1130. NTSTATUS status;
  1131. USHORT length;
  1132. status = PipQueryDeviceId(DeviceInfo, &deviceId, 0);
  1133. if (!NT_SUCCESS(status)) {
  1134. goto Cleanup;
  1135. }
  1136. RtlInitUnicodeString(&unicodeString, deviceId);
  1137. status = PipOpenRegistryKey(&deviceIdHandle,
  1138. EnumHandle,
  1139. &unicodeString,
  1140. KEY_READ,
  1141. FALSE
  1142. );
  1143. if (!NT_SUCCESS(status)) {
  1144. goto Cleanup;
  1145. }
  1146. status = PipQueryDeviceUniqueId(DeviceInfo, &uniqueId);
  1147. if (!NT_SUCCESS(status)) {
  1148. goto Cleanup;
  1149. }
  1150. //
  1151. // Open this registry path under HKLM\CCS\System\Enum
  1152. //
  1153. RtlInitUnicodeString(&unicodeString, uniqueId);
  1154. status = PipOpenRegistryKey(&uniqueIdHandle,
  1155. deviceIdHandle,
  1156. &unicodeString,
  1157. KEY_READ,
  1158. FALSE
  1159. );
  1160. if (!NT_SUCCESS(status)) {
  1161. goto Cleanup;
  1162. }
  1163. RtlInitUnicodeString(&unicodeString, L"LogConf");
  1164. status = PipOpenRegistryKey(&confHandle,
  1165. uniqueIdHandle,
  1166. &unicodeString,
  1167. KEY_READ,
  1168. FALSE
  1169. );
  1170. if (!NT_SUCCESS(status)) {
  1171. goto Cleanup;
  1172. }
  1173. // allocate enough space for "deviceid\uniqueid<unicode null>"
  1174. length = (wcslen(uniqueId) + wcslen(deviceId)) * sizeof(WCHAR) +
  1175. sizeof(WCHAR) + sizeof(WCHAR);
  1176. buffer = ExAllocatePool(PagedPool, length);
  1177. if (buffer == NULL) {
  1178. status = STATUS_INSUFFICIENT_RESOURCES;
  1179. goto Cleanup;
  1180. }
  1181. swprintf(buffer, L"%s\\%s", deviceId, uniqueId);
  1182. RtlInitUnicodeString(&unicodeString, buffer);
  1183. if (PipIsDeviceInstanceInstalled(uniqueIdHandle, &unicodeString)) {
  1184. status = STATUS_SUCCESS;
  1185. *LogConfHandle = confHandle;
  1186. } else {
  1187. status = STATUS_UNSUCCESSFUL;
  1188. }
  1189. ExFreePool(buffer);
  1190. Cleanup:
  1191. if (uniqueIdHandle) {
  1192. ZwClose(uniqueIdHandle);
  1193. }
  1194. if (uniqueId) {
  1195. ExFreePool(uniqueId);
  1196. }
  1197. if (deviceIdHandle) {
  1198. ZwClose(deviceIdHandle);
  1199. }
  1200. if (deviceId) {
  1201. ExFreePool(deviceId);
  1202. }
  1203. if (!NT_SUCCESS(status)) {
  1204. *LogConfHandle = NULL;
  1205. if (confHandle) {
  1206. ZwClose(confHandle);
  1207. }
  1208. }
  1209. return status;
  1210. }
  1211. #endif
  1212. #endif