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

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