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.

1793 lines
53 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. All rights reserved
  4. Module Name:
  5. pnpdd.c
  6. Abstract:
  7. This module implements new Plug-And-Play driver entries and IRPs.
  8. Author:
  9. Shie-Lin Tzong (shielint) June-16-1995
  10. Environment:
  11. Kernel mode only.
  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,'ddpP')
  19. #endif
  20. //
  21. // Internal definitions and references
  22. //
  23. typedef struct _ROOT_ENUMERATOR_CONTEXT {
  24. NTSTATUS Status;
  25. PUNICODE_STRING KeyName;
  26. ULONG MaxDeviceCount;
  27. ULONG DeviceCount;
  28. PDEVICE_OBJECT *DeviceList;
  29. } ROOT_ENUMERATOR_CONTEXT, *PROOT_ENUMERATOR_CONTEXT;
  30. NTSTATUS
  31. IopGetServiceType(
  32. IN PUNICODE_STRING KeyName,
  33. IN PULONG ServiceType
  34. );
  35. BOOLEAN
  36. IopInitializeDeviceInstanceKey(
  37. IN HANDLE KeyHandle,
  38. IN PUNICODE_STRING KeyName,
  39. IN OUT PVOID Context
  40. );
  41. BOOLEAN
  42. IopInitializeDeviceKey(
  43. IN HANDLE KeyHandle,
  44. IN PUNICODE_STRING KeyName,
  45. IN OUT PVOID Context
  46. );
  47. BOOLEAN
  48. IopIsFirmwareDisabled (
  49. IN PDEVICE_NODE DeviceNode
  50. );
  51. VOID
  52. IopPnPCompleteRequest(
  53. IN OUT PIRP Irp,
  54. IN NTSTATUS Status,
  55. IN ULONG_PTR Information
  56. );
  57. NTSTATUS
  58. IopTranslatorHandlerCm (
  59. IN PVOID Context,
  60. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
  61. IN RESOURCE_TRANSLATION_DIRECTION Direction,
  62. IN ULONG AlternativesCount, OPTIONAL
  63. IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
  64. IN PDEVICE_OBJECT DeviceObject,
  65. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
  66. );
  67. NTSTATUS
  68. IopTranslatorHandlerIo (
  69. IN PVOID Context,
  70. IN PIO_RESOURCE_DESCRIPTOR Source,
  71. IN PDEVICE_OBJECT DeviceObject,
  72. OUT PULONG TargetCount,
  73. OUT PIO_RESOURCE_DESCRIPTOR *Target
  74. );
  75. #ifdef ALLOC_PRAGMA
  76. #pragma alloc_text(PAGE, IopGetRootDevices)
  77. #pragma alloc_text(PAGE, IopGetServiceType)
  78. #pragma alloc_text(PAGE, IopInitializeDeviceKey)
  79. #pragma alloc_text(PAGE, IopInitializeDeviceInstanceKey)
  80. #pragma alloc_text(PAGE, IopIsFirmwareDisabled)
  81. #pragma alloc_text(PAGE, PipIsFirmwareMapperDevicePresent)
  82. #pragma alloc_text(PAGE, IopPnPAddDevice)
  83. #pragma alloc_text(PAGE, IopPnPDispatch)
  84. #pragma alloc_text(PAGE, IopTranslatorHandlerCm)
  85. #pragma alloc_text(PAGE, IopTranslatorHandlerIo)
  86. #pragma alloc_text(PAGE, IopSystemControlDispatch)
  87. #endif // ALLOC_PRAGMA
  88. NTSTATUS
  89. IopPnPAddDevice(
  90. IN PDRIVER_OBJECT DriverObject,
  91. IN PDEVICE_OBJECT DeviceObject
  92. )
  93. /*++
  94. Routine Description:
  95. This routine handles AddDevice for an madeup PDO device.
  96. Arguments:
  97. DriverObject - Pointer to our pseudo driver object.
  98. DeviceObject - Pointer to the device object for which this requestapplies.
  99. Return Value:
  100. NT status.
  101. --*/
  102. {
  103. UNREFERENCED_PARAMETER( DriverObject );
  104. UNREFERENCED_PARAMETER( DeviceObject );
  105. PAGED_CODE();
  106. #if DBG
  107. //
  108. // We should never get an AddDevice request.
  109. //
  110. DbgBreakPoint();
  111. #endif
  112. return STATUS_SUCCESS;
  113. }
  114. // PNPRES test
  115. NTSTATUS
  116. IopArbiterHandlerxx (
  117. IN PVOID Context,
  118. IN ARBITER_ACTION Action,
  119. IN OUT PARBITER_PARAMETERS Parameters
  120. )
  121. {
  122. PLIST_ENTRY listHead, listEntry;
  123. PIO_RESOURCE_DESCRIPTOR ioDesc;
  124. PCM_PARTIAL_RESOURCE_DESCRIPTOR cmDesc;
  125. PARBITER_LIST_ENTRY arbiterListEntry;
  126. UNREFERENCED_PARAMETER( Context );
  127. if (Action == ArbiterActionQueryArbitrate) {
  128. return STATUS_SUCCESS;
  129. }
  130. if (Parameters == NULL) {
  131. return STATUS_SUCCESS;
  132. }
  133. listHead = Parameters->Parameters.TestAllocation.ArbitrationList;
  134. if (IsListEmpty(listHead)) {
  135. return STATUS_SUCCESS;
  136. }
  137. listEntry = listHead->Flink;
  138. while (listEntry != listHead) {
  139. arbiterListEntry = (PARBITER_LIST_ENTRY)listEntry;
  140. cmDesc = arbiterListEntry->Assignment;
  141. ioDesc = arbiterListEntry->Alternatives;
  142. if (cmDesc == NULL || ioDesc == NULL) {
  143. return STATUS_SUCCESS;
  144. }
  145. cmDesc->Type = ioDesc->Type;
  146. cmDesc->ShareDisposition = ioDesc->ShareDisposition;
  147. cmDesc->Flags = ioDesc->Flags;
  148. if (ioDesc->Type == CmResourceTypePort) {
  149. cmDesc->u.Port.Start = ioDesc->u.Port.MinimumAddress;
  150. cmDesc->u.Port.Length = ioDesc->u.Port.Length;
  151. } else if (ioDesc->Type == CmResourceTypeInterrupt) {
  152. cmDesc->u.Interrupt.Level = ioDesc->u.Interrupt.MinimumVector;
  153. cmDesc->u.Interrupt.Vector = ioDesc->u.Interrupt.MinimumVector;
  154. cmDesc->u.Interrupt.Affinity = (ULONG) -1;
  155. } else if (ioDesc->Type == CmResourceTypeMemory) {
  156. cmDesc->u.Memory.Start = ioDesc->u.Memory.MinimumAddress;
  157. cmDesc->u.Memory.Length = ioDesc->u.Memory.Length;
  158. } else if (ioDesc->Type == CmResourceTypeDma) {
  159. cmDesc->u.Dma.Channel = ioDesc->u.Dma.MinimumChannel;
  160. cmDesc->u.Dma.Port = 0;
  161. cmDesc->u.Dma.Reserved1 = 0;
  162. }
  163. listEntry = listEntry->Flink;
  164. }
  165. return STATUS_SUCCESS;
  166. }
  167. NTSTATUS
  168. IopTranslatorHandlerCm (
  169. IN PVOID Context,
  170. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
  171. IN RESOURCE_TRANSLATION_DIRECTION Direction,
  172. IN ULONG AlternativesCount, OPTIONAL
  173. IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
  174. IN PDEVICE_OBJECT DeviceObject,
  175. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
  176. )
  177. {
  178. UNREFERENCED_PARAMETER( Context );
  179. UNREFERENCED_PARAMETER( Direction );
  180. UNREFERENCED_PARAMETER( AlternativesCount );
  181. UNREFERENCED_PARAMETER( Alternatives );
  182. UNREFERENCED_PARAMETER( DeviceObject );
  183. PAGED_CODE();
  184. *Target = *Source;
  185. #if 0
  186. if (Direction == TranslateChildToParent) {
  187. if (Target->Type == CmResourceTypePort) {
  188. Target->u.Port.Start.LowPart += 0x10000;
  189. } else if (Target->Type == CmResourceTypeMemory) {
  190. Target->u.Memory.Start.LowPart += 0x100000;
  191. }
  192. } else {
  193. if (Target->Type == CmResourceTypePort) {
  194. Target->u.Port.Start.LowPart -= 0x10000;
  195. } else if (Target->Type == CmResourceTypeMemory) {
  196. Target->u.Memory.Start.LowPart -= 0x100000;
  197. }
  198. }
  199. #endif
  200. return STATUS_SUCCESS;
  201. }
  202. NTSTATUS
  203. IopTranslatorHandlerIo (
  204. IN PVOID Context,
  205. IN PIO_RESOURCE_DESCRIPTOR Source,
  206. IN PDEVICE_OBJECT DeviceObject,
  207. OUT PULONG TargetCount,
  208. OUT PIO_RESOURCE_DESCRIPTOR *Target
  209. )
  210. {
  211. PIO_RESOURCE_DESCRIPTOR newDesc;
  212. UNREFERENCED_PARAMETER( Context );
  213. UNREFERENCED_PARAMETER( DeviceObject );
  214. PAGED_CODE();
  215. newDesc = (PIO_RESOURCE_DESCRIPTOR) ExAllocatePool(PagedPool, sizeof(IO_RESOURCE_DESCRIPTOR));
  216. if (newDesc == NULL) {
  217. return STATUS_INSUFFICIENT_RESOURCES;
  218. }
  219. *TargetCount = 1;
  220. *newDesc = *Source;
  221. #if 0
  222. if (newDesc->Type == CmResourceTypePort) {
  223. newDesc->u.Port.MinimumAddress.LowPart += 0x10000;
  224. newDesc->u.Port.MaximumAddress.LowPart += 0x10000;
  225. } else if (newDesc->Type == CmResourceTypeMemory) {
  226. newDesc->u.Memory.MinimumAddress.LowPart += 0x100000;
  227. newDesc->u.Memory.MaximumAddress.LowPart += 0x100000;
  228. }
  229. #endif
  230. *Target = newDesc;
  231. return STATUS_SUCCESS;
  232. }
  233. NTSTATUS
  234. IopPowerDispatch(
  235. IN PDEVICE_OBJECT DeviceObject,
  236. IN OUT PIRP Irp
  237. )
  238. {
  239. PIO_STACK_LOCATION IrpSp;
  240. PPOWER_SEQUENCE PowerSequence;
  241. NTSTATUS Status;
  242. UNREFERENCED_PARAMETER( DeviceObject );
  243. IrpSp = IoGetCurrentIrpStackLocation (Irp);
  244. Status = Irp->IoStatus.Status;
  245. switch (IrpSp->MinorFunction) {
  246. case IRP_MN_WAIT_WAKE:
  247. Status = STATUS_NOT_SUPPORTED;
  248. break;
  249. case IRP_MN_POWER_SEQUENCE:
  250. PowerSequence = IrpSp->Parameters.PowerSequence.PowerSequence;
  251. PowerSequence->SequenceD1 = PoPowerSequence;
  252. PowerSequence->SequenceD2 = PoPowerSequence;
  253. PowerSequence->SequenceD3 = PoPowerSequence;
  254. Status = STATUS_SUCCESS;
  255. break;
  256. case IRP_MN_QUERY_POWER:
  257. Status = STATUS_SUCCESS;
  258. break;
  259. case IRP_MN_SET_POWER:
  260. switch (IrpSp->Parameters.Power.Type) {
  261. case SystemPowerState:
  262. Status = STATUS_SUCCESS;
  263. break;
  264. case DevicePowerState:
  265. //
  266. // To be here the FDO must have passed the IRP on.
  267. // We do not know how to turn the device off, but the
  268. // FDO is prepaired for it work
  269. //
  270. Status = STATUS_SUCCESS;
  271. break;
  272. default:
  273. // Unkown power type
  274. Status = STATUS_NOT_SUPPORTED;
  275. break;
  276. }
  277. break;
  278. default:
  279. // Unkown power minor code
  280. Status = STATUS_NOT_SUPPORTED;
  281. break;
  282. }
  283. //
  284. // For lagecy devices that do not have drivers loaded, complete
  285. // power irps with success.
  286. //
  287. PoStartNextPowerIrp(Irp);
  288. if (Status != STATUS_NOT_SUPPORTED) {
  289. Irp->IoStatus.Status = Status;
  290. } else {
  291. Status = Irp->IoStatus.Status;
  292. }
  293. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  294. return Status;
  295. }
  296. NTSTATUS
  297. IopPnPDispatch(
  298. IN PDEVICE_OBJECT DeviceObject,
  299. IN OUT PIRP Irp
  300. )
  301. /*++
  302. Routine Description:
  303. This routine handles all IRP_MJ_PNP IRPs for madeup PDO device.
  304. Arguments:
  305. DeviceObject - Pointer to the device object for which this IRP applies.
  306. Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
  307. Return Value:
  308. NT status.
  309. --*/
  310. {
  311. PIOPNP_DEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  312. PIO_STACK_LOCATION irpSp;
  313. NTSTATUS status;
  314. PVOID information = NULL;
  315. ULONG length, uiNumber;
  316. PWCHAR id, wp;
  317. PDEVICE_NODE deviceNode;
  318. PARBITER_INTERFACE arbiterInterface; // PNPRES test
  319. PTRANSLATOR_INTERFACE translatorInterface; // PNPRES test
  320. PAGED_CODE();
  321. //
  322. // Get a pointer to our stack location and take appropriate action based
  323. // on the minor function.
  324. //
  325. irpSp = IoGetCurrentIrpStackLocation(Irp);
  326. switch (irpSp->MinorFunction){
  327. case IRP_MN_DEVICE_USAGE_NOTIFICATION:
  328. case IRP_MN_START_DEVICE:
  329. //
  330. // If we get a start device request for a PDO, we simply
  331. // return success.
  332. //
  333. status = STATUS_SUCCESS;
  334. break;
  335. case IRP_MN_CANCEL_STOP_DEVICE:
  336. //
  337. // As we fail all STOP's, this cancel is always successful, and we have
  338. // no work to do.
  339. //
  340. status = STATUS_SUCCESS;
  341. break;
  342. case IRP_MN_QUERY_STOP_DEVICE:
  343. case IRP_MN_STOP_DEVICE:
  344. //
  345. // We can not success the query stop. We don't handle it. because
  346. // we don't know how to stop a root enumerated device.
  347. //
  348. status = STATUS_UNSUCCESSFUL ;
  349. break;
  350. case IRP_MN_QUERY_RESOURCES:
  351. status = IopGetDeviceResourcesFromRegistry(
  352. DeviceObject,
  353. QUERY_RESOURCE_LIST,
  354. REGISTRY_BOOT_CONFIG,
  355. &information,
  356. &length);
  357. if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
  358. status = STATUS_SUCCESS;
  359. information = NULL;
  360. }
  361. break;
  362. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  363. status = IopGetDeviceResourcesFromRegistry(
  364. DeviceObject,
  365. QUERY_RESOURCE_REQUIREMENTS,
  366. REGISTRY_BASIC_CONFIGVECTOR,
  367. &information,
  368. &length);
  369. if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
  370. status = STATUS_SUCCESS;
  371. information = NULL;
  372. }
  373. break;
  374. case IRP_MN_QUERY_REMOVE_DEVICE:
  375. case IRP_MN_REMOVE_DEVICE:
  376. case IRP_MN_CANCEL_REMOVE_DEVICE:
  377. //
  378. // For root enumerated devices we let the device objects stay.
  379. //
  380. status = STATUS_SUCCESS;
  381. break;
  382. case IRP_MN_QUERY_DEVICE_RELATIONS:
  383. if (DeviceObject == IopRootDeviceNode->PhysicalDeviceObject &&
  384. irpSp->Parameters.QueryDeviceRelations.Type == BusRelations) {
  385. status = IopGetRootDevices((PDEVICE_RELATIONS *)&information);
  386. } else {
  387. if (irpSp->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation) {
  388. PDEVICE_RELATIONS deviceRelations;
  389. deviceRelations = ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
  390. if (deviceRelations == NULL) {
  391. status = STATUS_INSUFFICIENT_RESOURCES;
  392. } else {
  393. deviceRelations->Count = 1;
  394. deviceRelations->Objects[0] = DeviceObject;
  395. ObReferenceObject(DeviceObject);
  396. information = (PVOID)deviceRelations;
  397. status = STATUS_SUCCESS;
  398. }
  399. } else {
  400. information = (PVOID)Irp->IoStatus.Information;
  401. status = Irp->IoStatus.Status;
  402. }
  403. }
  404. break;
  405. case IRP_MN_QUERY_INTERFACE:
  406. status = Irp->IoStatus.Status;
  407. deviceNode = (PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
  408. if (deviceNode == IopRootDeviceNode) {
  409. if ( IopCompareGuid((PVOID)irpSp->Parameters.QueryInterface.InterfaceType, (PVOID)&GUID_ARBITER_INTERFACE_STANDARD)) {
  410. status = STATUS_SUCCESS;
  411. arbiterInterface = (PARBITER_INTERFACE) irpSp->Parameters.QueryInterface.Interface;
  412. arbiterInterface->ArbiterHandler = ArbArbiterHandler;
  413. switch ((UCHAR)((ULONG_PTR)irpSp->Parameters.QueryInterface.InterfaceSpecificData)) {
  414. case CmResourceTypePort:
  415. arbiterInterface->Context = (PVOID) &IopRootPortArbiter;
  416. break;
  417. case CmResourceTypeMemory:
  418. arbiterInterface->Context = (PVOID) &IopRootMemArbiter;
  419. break;
  420. case CmResourceTypeInterrupt:
  421. arbiterInterface->Context = (PVOID) &IopRootIrqArbiter;
  422. break;
  423. case CmResourceTypeDma:
  424. arbiterInterface->Context = (PVOID) &IopRootDmaArbiter;
  425. break;
  426. case CmResourceTypeBusNumber:
  427. arbiterInterface->Context = (PVOID) &IopRootBusNumberArbiter;
  428. break;
  429. default:
  430. status = STATUS_INVALID_PARAMETER;
  431. break;
  432. }
  433. } else if ( IopCompareGuid((PVOID)irpSp->Parameters.QueryInterface.InterfaceType, (PVOID)&GUID_TRANSLATOR_INTERFACE_STANDARD)) {
  434. translatorInterface = (PTRANSLATOR_INTERFACE) irpSp->Parameters.QueryInterface.Interface;
  435. translatorInterface->TranslateResources = IopTranslatorHandlerCm;
  436. translatorInterface->TranslateResourceRequirements = IopTranslatorHandlerIo;
  437. status = STATUS_SUCCESS;
  438. }
  439. }
  440. break;
  441. case IRP_MN_QUERY_CAPABILITIES:
  442. {
  443. ULONG i;
  444. PDEVICE_POWER_STATE state;
  445. PDEVICE_CAPABILITIES deviceCapabilities;
  446. deviceNode = (PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
  447. deviceCapabilities = irpSp->Parameters.DeviceCapabilities.Capabilities;
  448. deviceCapabilities->Size = sizeof(DEVICE_CAPABILITIES);
  449. deviceCapabilities->Version = 1;
  450. deviceCapabilities->DeviceState[PowerSystemUnspecified]=PowerDeviceUnspecified;
  451. deviceCapabilities->DeviceState[PowerSystemWorking]=PowerDeviceD0;
  452. state = &deviceCapabilities->DeviceState[PowerSystemSleeping1];
  453. for (i = PowerSystemSleeping1; i < PowerSystemMaximum; i++) {
  454. //
  455. // Only supported state, currently, is off.
  456. //
  457. *state++ = PowerDeviceD3;
  458. }
  459. if(IopIsFirmwareDisabled(deviceNode)) {
  460. //
  461. // this device has been disabled by BIOS
  462. //
  463. deviceCapabilities->HardwareDisabled = TRUE;
  464. }
  465. if (deviceCapabilities->UINumber == (ULONG)-1) {
  466. //
  467. // Get the UI number from the registry.
  468. //
  469. length = sizeof(uiNumber);
  470. status = PiGetDeviceRegistryProperty(
  471. DeviceObject,
  472. REG_DWORD,
  473. REGSTR_VALUE_UI_NUMBER,
  474. NULL,
  475. &uiNumber,
  476. &length);
  477. if (NT_SUCCESS(status)) {
  478. deviceCapabilities->UINumber = uiNumber;
  479. }
  480. }
  481. status = STATUS_SUCCESS;
  482. }
  483. break;
  484. case IRP_MN_QUERY_ID:
  485. if (DeviceObject != IopRootDeviceNode->PhysicalDeviceObject &&
  486. (!NT_SUCCESS(Irp->IoStatus.Status) || !Irp->IoStatus.Information)) {
  487. deviceNode = (PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
  488. switch (irpSp->Parameters.QueryId.IdType) {
  489. case BusQueryInstanceID:
  490. case BusQueryDeviceID:
  491. id = (PWCHAR)ExAllocatePool(PagedPool, deviceNode->InstancePath.Length);
  492. if (id) {
  493. ULONG separatorCount = 0;
  494. RtlZeroMemory(id, deviceNode->InstancePath.Length);
  495. information = id;
  496. status = STATUS_SUCCESS;
  497. wp = deviceNode->InstancePath.Buffer;
  498. if (irpSp->Parameters.QueryId.IdType == BusQueryDeviceID) {
  499. while(*wp) {
  500. if (*wp == OBJ_NAME_PATH_SEPARATOR) {
  501. separatorCount++;
  502. if (separatorCount == 2) {
  503. break;
  504. }
  505. }
  506. *id = *wp;
  507. id++;
  508. wp++;
  509. }
  510. } else {
  511. while(*wp) {
  512. if (*wp == OBJ_NAME_PATH_SEPARATOR) {
  513. separatorCount++;
  514. if (separatorCount == 2) {
  515. wp++;
  516. break;
  517. }
  518. }
  519. wp++;
  520. }
  521. while (*wp) {
  522. *id = *wp;
  523. id++;
  524. wp++;
  525. }
  526. }
  527. } else {
  528. status = STATUS_INSUFFICIENT_RESOURCES;
  529. }
  530. break;
  531. case BusQueryCompatibleIDs:
  532. if((Irp->IoStatus.Status != STATUS_NOT_SUPPORTED) ||
  533. (deviceExtension == NULL)) {
  534. //
  535. // Upper driver has given some sort of reply or this device
  536. // object wasn't allocated to handle these requests.
  537. //
  538. status = Irp->IoStatus.Status;
  539. break;
  540. }
  541. if(deviceExtension->CompatibleIdListSize != 0) {
  542. id = ExAllocatePool(PagedPool,
  543. deviceExtension->CompatibleIdListSize);
  544. if(id == NULL) {
  545. status = STATUS_INSUFFICIENT_RESOURCES;
  546. break;
  547. }
  548. RtlCopyMemory(id,
  549. deviceExtension->CompatibleIdList,
  550. deviceExtension->CompatibleIdListSize);
  551. information = id;
  552. status = STATUS_SUCCESS;
  553. break;
  554. }
  555. default:
  556. information = (PVOID)Irp->IoStatus.Information;
  557. status = Irp->IoStatus.Status;
  558. }
  559. } else {
  560. information = (PVOID)Irp->IoStatus.Information;
  561. status = Irp->IoStatus.Status;
  562. }
  563. break;
  564. case IRP_MN_QUERY_DEVICE_TEXT:
  565. if ( irpSp->Parameters.QueryDeviceText.DeviceTextType == DeviceTextLocationInformation &&
  566. !Irp->IoStatus.Information) {
  567. //
  568. // Read and return the location in the registry.
  569. //
  570. length = 0;
  571. PiGetDeviceRegistryProperty(
  572. DeviceObject,
  573. REG_SZ,
  574. REGSTR_VALUE_LOCATION_INFORMATION,
  575. NULL,
  576. NULL,
  577. &length);
  578. if (length) {
  579. information = ExAllocatePool(PagedPool, length);
  580. if (information) {
  581. status = PiGetDeviceRegistryProperty(
  582. DeviceObject,
  583. REG_SZ,
  584. REGSTR_VALUE_LOCATION_INFORMATION,
  585. NULL,
  586. information,
  587. &length);
  588. if (!NT_SUCCESS(status)) {
  589. ExFreePool(information);
  590. information = NULL;
  591. }
  592. } else {
  593. status = STATUS_INSUFFICIENT_RESOURCES;
  594. }
  595. } else {
  596. status = STATUS_UNSUCCESSFUL;
  597. }
  598. } else {
  599. information = (PVOID)Irp->IoStatus.Information;
  600. status = Irp->IoStatus.Status;
  601. }
  602. break;
  603. default:
  604. information = (PVOID)Irp->IoStatus.Information;
  605. status = Irp->IoStatus.Status;
  606. break;
  607. }
  608. //
  609. // Complete the Irp and return.
  610. //
  611. IopPnPCompleteRequest(Irp, status, (ULONG_PTR)information);
  612. return status;
  613. }
  614. VOID
  615. IopPnPCompleteRequest(
  616. IN OUT PIRP Irp,
  617. IN NTSTATUS Status,
  618. IN ULONG_PTR Information
  619. )
  620. /*++
  621. Routine Description:
  622. This routine completes PnP irps for our pseudo driver.
  623. Arguments:
  624. Irp - Supplies a pointer to the irp to be completed.
  625. Status - completion status.
  626. Information - completion information to be passed back.
  627. Return Value:
  628. None.
  629. --*/
  630. {
  631. //
  632. // Complete the IRP. First update the status...
  633. //
  634. Irp->IoStatus.Status = Status;
  635. Irp->IoStatus.Information = Information;
  636. //
  637. // ... and complete it.
  638. //
  639. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  640. }
  641. BOOLEAN
  642. IopIsFirmwareDisabled (
  643. IN PDEVICE_NODE DeviceNode
  644. )
  645. /*++
  646. Routine Description:
  647. This routine determines if the devicenode has been disabled by firmware.
  648. Arguments:
  649. DeviceNode - Supplies a pointer to the device node structure of the device.
  650. Return Value:
  651. TRUE if disabled, otherwise FALSE
  652. --*/
  653. {
  654. NTSTATUS status;
  655. PDEVICE_OBJECT deviceObject = DeviceNode->PhysicalDeviceObject;
  656. HANDLE handle, handlex;
  657. UNICODE_STRING unicodeName;
  658. UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION)+sizeof(ULONG)];
  659. PKEY_VALUE_PARTIAL_INFORMATION value = (PKEY_VALUE_PARTIAL_INFORMATION)buffer;
  660. ULONG buflen;
  661. BOOLEAN FirmwareDisabled = FALSE;
  662. PiLockPnpRegistry(FALSE);
  663. status = IopDeviceObjectToDeviceInstance(
  664. deviceObject,
  665. &handlex,
  666. KEY_ALL_ACCESS);
  667. if (NT_SUCCESS(status)) {
  668. //
  669. // Open the LogConfig key of the device instance.
  670. //
  671. PiWstrToUnicodeString(&unicodeName, REGSTR_KEY_CONTROL);
  672. status = IopCreateRegistryKeyEx( &handle,
  673. handlex,
  674. &unicodeName,
  675. KEY_ALL_ACCESS,
  676. REG_OPTION_VOLATILE,
  677. NULL
  678. );
  679. ZwClose(handlex);
  680. if (NT_SUCCESS(status)) {
  681. PiWstrToUnicodeString(&unicodeName, REGSTR_VAL_FIRMWAREDISABLED);
  682. value = (PKEY_VALUE_PARTIAL_INFORMATION)buffer;
  683. buflen = sizeof(buffer);
  684. status = ZwQueryValueKey(handle,
  685. &unicodeName,
  686. KeyValuePartialInformation,
  687. value,
  688. sizeof(buffer),
  689. &buflen
  690. );
  691. ZwClose(handle);
  692. //
  693. // We don't need to check the buffer was big enough because it starts
  694. // off that way and doesn't get any smaller!
  695. //
  696. if (NT_SUCCESS(status)
  697. && value->Type == REG_DWORD
  698. && value->DataLength == sizeof(ULONG)
  699. && (*(PULONG)(value->Data))!=0) {
  700. //
  701. // firmware disabled
  702. //
  703. FirmwareDisabled = TRUE;
  704. }
  705. }
  706. }
  707. PiUnlockPnpRegistry();
  708. return FirmwareDisabled;
  709. }
  710. NTSTATUS
  711. IopGetRootDevices (
  712. PDEVICE_RELATIONS *DeviceRelations
  713. )
  714. /*++
  715. Routine Description:
  716. This routine scans through System\Enum\Root subtree to build a device node for
  717. each root device.
  718. Arguments:
  719. DeviceRelations - supplies a variable to receive the returned DEVICE_RELATIONS structure.
  720. Return Value:
  721. A NTSTATUS code.
  722. --*/
  723. {
  724. NTSTATUS status;
  725. HANDLE baseHandle;
  726. UNICODE_STRING workName, tmpName;
  727. PVOID buffer;
  728. ROOT_ENUMERATOR_CONTEXT context;
  729. ULONG i;
  730. PDEVICE_RELATIONS deviceRelations;
  731. PAGED_CODE();
  732. *DeviceRelations = NULL;
  733. buffer = ExAllocatePool(PagedPool, PNP_LARGE_SCRATCH_BUFFER_SIZE);
  734. if (!buffer) {
  735. return STATUS_INSUFFICIENT_RESOURCES;
  736. }
  737. //
  738. // Allocate a buffer to store the PDOs enumerated.
  739. // Note, the the buffer turns out to be not big enough, it will be reallocated dynamically.
  740. //
  741. context.DeviceList = (PDEVICE_OBJECT *) ExAllocatePool(PagedPool, PNP_SCRATCH_BUFFER_SIZE * 2);
  742. if (context.DeviceList) {
  743. context.MaxDeviceCount = (PNP_SCRATCH_BUFFER_SIZE * 2) / sizeof(PDEVICE_OBJECT);
  744. context.DeviceCount = 0;
  745. } else {
  746. ExFreePool(buffer);
  747. return STATUS_INSUFFICIENT_RESOURCES;
  748. }
  749. PiLockPnpRegistry(TRUE);
  750. //
  751. // Open System\CurrentControlSet\Enum\Root key and call worker routine to recursively
  752. // scan through the subkeys.
  753. //
  754. status = IopCreateRegistryKeyEx( &baseHandle,
  755. NULL,
  756. &CmRegistryMachineSystemCurrentControlSetEnumRootName,
  757. KEY_READ,
  758. REG_OPTION_NON_VOLATILE,
  759. NULL
  760. );
  761. if (NT_SUCCESS(status)) {
  762. workName.Buffer = (PWSTR)buffer;
  763. RtlFillMemory(buffer, PNP_LARGE_SCRATCH_BUFFER_SIZE, 0);
  764. workName.MaximumLength = PNP_LARGE_SCRATCH_BUFFER_SIZE;
  765. workName.Length = 0;
  766. //
  767. // only look at ROOT key
  768. //
  769. PiWstrToUnicodeString(&tmpName, REGSTR_KEY_ROOTENUM);
  770. RtlAppendStringToString((PSTRING)&workName, (PSTRING)&tmpName);
  771. //
  772. // Enumerate all subkeys under the System\CCS\Enum\Root.
  773. //
  774. context.Status = STATUS_SUCCESS;
  775. context.KeyName = &workName;
  776. status = PipApplyFunctionToSubKeys(baseHandle,
  777. NULL,
  778. KEY_ALL_ACCESS,
  779. FUNCTIONSUBKEY_FLAG_IGNORE_NON_CRITICAL_ERRORS,
  780. IopInitializeDeviceKey,
  781. &context
  782. );
  783. ZwClose(baseHandle);
  784. //
  785. // Build returned information from ROOT_ENUMERATOR_CONTEXT.
  786. //
  787. status = context.Status;
  788. if (NT_SUCCESS(status) && context.DeviceCount != 0) {
  789. deviceRelations = (PDEVICE_RELATIONS) ExAllocatePool(
  790. PagedPool,
  791. sizeof (DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * context.DeviceCount
  792. );
  793. if (deviceRelations == NULL) {
  794. status = STATUS_INSUFFICIENT_RESOURCES;
  795. } else {
  796. deviceRelations->Count = context.DeviceCount;
  797. RtlCopyMemory(deviceRelations->Objects,
  798. context.DeviceList,
  799. sizeof (PDEVICE_OBJECT) * context.DeviceCount);
  800. *DeviceRelations = deviceRelations;
  801. }
  802. }
  803. if (!NT_SUCCESS(status)) {
  804. //
  805. // If somehow the enumeration failed, we need to derefernece all the
  806. // device objects.
  807. //
  808. for (i = 0; i < context.DeviceCount; i++) {
  809. ObDereferenceObject(context.DeviceList[i]);
  810. }
  811. }
  812. }
  813. PiUnlockPnpRegistry();
  814. ExFreePool(buffer);
  815. ExFreePool(context.DeviceList);
  816. return status;
  817. }
  818. BOOLEAN
  819. IopInitializeDeviceKey(
  820. IN HANDLE KeyHandle,
  821. IN PUNICODE_STRING KeyName,
  822. IN OUT PVOID Context
  823. )
  824. /*++
  825. Routine Description:
  826. This routine is a callback function for PipApplyFunctionToSubKeys.
  827. It is called for each subkey under HKLM\System\CCS\Enum\BusKey.
  828. Arguments:
  829. KeyHandle - Supplies a handle to this key.
  830. KeyName - Supplies the name of this key.
  831. Context - points to the ROOT_ENUMERATOR_CONTEXT structure.
  832. Returns:
  833. TRUE to continue the enumeration.
  834. FALSE to abort it.
  835. --*/
  836. {
  837. USHORT length;
  838. PWSTR p;
  839. PUNICODE_STRING unicodeName = ((PROOT_ENUMERATOR_CONTEXT)Context)->KeyName;
  840. length = unicodeName->Length;
  841. p = unicodeName->Buffer;
  842. if ( unicodeName->Length / sizeof(WCHAR) != 0) {
  843. p += unicodeName->Length / sizeof(WCHAR);
  844. *p = OBJ_NAME_PATH_SEPARATOR;
  845. unicodeName->Length += sizeof (WCHAR);
  846. }
  847. RtlAppendStringToString((PSTRING)unicodeName, (PSTRING)KeyName);
  848. //
  849. // Enumerate all subkeys under the current device key.
  850. //
  851. PipApplyFunctionToSubKeys(KeyHandle,
  852. NULL,
  853. KEY_ALL_ACCESS,
  854. FUNCTIONSUBKEY_FLAG_IGNORE_NON_CRITICAL_ERRORS,
  855. IopInitializeDeviceInstanceKey,
  856. Context
  857. );
  858. unicodeName->Length = length;
  859. return (BOOLEAN)NT_SUCCESS(((PROOT_ENUMERATOR_CONTEXT)Context)->Status);
  860. }
  861. BOOLEAN
  862. IopInitializeDeviceInstanceKey(
  863. IN HANDLE KeyHandle,
  864. IN PUNICODE_STRING KeyName,
  865. IN OUT PVOID Context
  866. )
  867. /*++
  868. Routine Description:
  869. This routine is a callback function for PipApplyFunctionToSubKeys.
  870. It is called for each subkey under HKLM\System\Enum\Root\DeviceKey.
  871. Arguments:
  872. KeyHandle - Supplies a handle to this key.
  873. KeyName - Supplies the name of this key.
  874. Context - points to the ROOT_ENUMERATOR_CONTEXT structure.
  875. Returns:
  876. TRUE to continue the enumeration.
  877. FALSE to abort it.
  878. --*/
  879. {
  880. UNICODE_STRING unicodeName, serviceName;
  881. PKEY_VALUE_FULL_INFORMATION serviceKeyValueInfo;
  882. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  883. NTSTATUS status;
  884. BOOLEAN isDuplicate = FALSE;
  885. BOOLEAN configuredBySetup;
  886. ULONG deviceFlags, tmpValue1;
  887. ULONG legacy;
  888. USHORT savedLength;
  889. PUNICODE_STRING pUnicode;
  890. HANDLE handle;
  891. PDEVICE_OBJECT deviceObject;
  892. PDEVICE_NODE deviceNode = NULL;
  893. PROOT_ENUMERATOR_CONTEXT enumContext = (PROOT_ENUMERATOR_CONTEXT)Context;
  894. //
  895. // First off, check to see if this is a phantom device instance (i.e.,
  896. // registry key only). If so, we want to totally ignore this key and
  897. // move on to the next one.
  898. //
  899. status = IopGetRegistryValue(KeyHandle,
  900. REGSTR_VAL_PHANTOM,
  901. &keyValueInformation);
  902. if (NT_SUCCESS(status)) {
  903. if ((keyValueInformation->Type == REG_DWORD) &&
  904. (keyValueInformation->DataLength >= sizeof(ULONG))) {
  905. tmpValue1 = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
  906. } else {
  907. tmpValue1 = 0;
  908. }
  909. ExFreePool(keyValueInformation);
  910. if (tmpValue1) {
  911. return TRUE;
  912. }
  913. }
  914. //
  915. // Since it is highly likely we are going to report another PDO make sure
  916. // there will be room in the buffer.
  917. //
  918. if (enumContext->DeviceCount == enumContext->MaxDeviceCount) {
  919. PDEVICE_OBJECT *tmpDeviceObjectList;
  920. ULONG tmpDeviceObjectListSize;
  921. //
  922. // We need to grow our PDO list buffer.
  923. //
  924. tmpDeviceObjectListSize = (enumContext->MaxDeviceCount * sizeof(PDEVICE_OBJECT))
  925. + (PNP_SCRATCH_BUFFER_SIZE * 2);
  926. tmpDeviceObjectList = ExAllocatePool(PagedPool, tmpDeviceObjectListSize);
  927. if (tmpDeviceObjectList) {
  928. RtlCopyMemory( tmpDeviceObjectList,
  929. enumContext->DeviceList,
  930. enumContext->DeviceCount * sizeof(PDEVICE_OBJECT)
  931. );
  932. ExFreePool(enumContext->DeviceList);
  933. enumContext->DeviceList = tmpDeviceObjectList;
  934. enumContext->MaxDeviceCount = tmpDeviceObjectListSize / sizeof(PDEVICE_OBJECT);
  935. } else {
  936. //
  937. // We are out of memory. There is no point going any further
  938. // since we don't have any place to report the PDOs anyways.
  939. //
  940. enumContext->Status = STATUS_INSUFFICIENT_RESOURCES;
  941. return FALSE;
  942. }
  943. }
  944. //
  945. // Combine Context->KeyName, i.e. the device name and KeyName (device instance name)
  946. // to form device instance path.
  947. //
  948. pUnicode = ((PROOT_ENUMERATOR_CONTEXT)Context)->KeyName;
  949. savedLength = pUnicode->Length; // Save WorkName
  950. if (pUnicode->Buffer[pUnicode->Length / sizeof(WCHAR) - 1] != OBJ_NAME_PATH_SEPARATOR) {
  951. pUnicode->Buffer[pUnicode->Length / sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
  952. pUnicode->Length += 2;
  953. }
  954. RtlAppendStringToString((PSTRING)pUnicode, (PSTRING)KeyName);
  955. //
  956. // Check if the PDO for the device instance key exists already. If no,
  957. // see if we need to create it.
  958. //
  959. deviceObject = IopDeviceObjectFromDeviceInstance(pUnicode);
  960. if (deviceObject != NULL) {
  961. enumContext->DeviceList[enumContext->DeviceCount] = deviceObject;
  962. enumContext->DeviceCount++;
  963. pUnicode->Length = savedLength; // Restore WorkName
  964. return TRUE;
  965. }
  966. //
  967. // We don't have device object for it.
  968. // First check if this key was created by firmware mapper. If yes, make sure
  969. // the device is still present.
  970. //
  971. if (!PipIsFirmwareMapperDevicePresent(KeyHandle)) {
  972. pUnicode->Length = savedLength; // Restore WorkName
  973. return TRUE;
  974. }
  975. //
  976. // Get the "DuplicateOf" value entry to determine if the device instance
  977. // should be registered. If the device instance is duplicate, We don't
  978. // add it to its service key's enum branch.
  979. //
  980. status = IopGetRegistryValue( KeyHandle,
  981. REGSTR_VALUE_DUPLICATEOF,
  982. &keyValueInformation
  983. );
  984. if (NT_SUCCESS(status)) {
  985. if (keyValueInformation->Type == REG_SZ &&
  986. keyValueInformation->DataLength > 0) {
  987. isDuplicate = TRUE;
  988. }
  989. ExFreePool(keyValueInformation);
  990. }
  991. //
  992. // Get the "Service=" value entry from KeyHandle
  993. //
  994. serviceKeyValueInfo = NULL;
  995. PiWstrToUnicodeString(&serviceName, NULL);
  996. status = IopGetRegistryValue ( KeyHandle,
  997. REGSTR_VALUE_SERVICE,
  998. &serviceKeyValueInfo
  999. );
  1000. if (NT_SUCCESS(status)) {
  1001. //
  1002. // Append the new instance to its corresponding
  1003. // Service\Name\Enum.
  1004. //
  1005. if (serviceKeyValueInfo->Type == REG_SZ &&
  1006. serviceKeyValueInfo->DataLength != 0) {
  1007. //
  1008. // Set up ServiceKeyName unicode string
  1009. //
  1010. IopRegistryDataToUnicodeString(
  1011. &serviceName,
  1012. (PWSTR)KEY_VALUE_DATA(serviceKeyValueInfo),
  1013. serviceKeyValueInfo->DataLength
  1014. );
  1015. }
  1016. //
  1017. // Do not Free serviceKeyValueInfo. It contains Service Name.
  1018. //
  1019. }
  1020. //
  1021. // Register this device instance by constructing new value entry for
  1022. // ServiceKeyName\Enum key.i.e., <Number> = <PathToSystemEnumBranch>
  1023. // For the stuff under Root, we need to expose devnodes for everything
  1024. // except those devices whose CsConfigFlags are set to CSCONFIGFLAG_DO_NOT_CREATE.
  1025. //
  1026. status = IopGetDeviceInstanceCsConfigFlags( pUnicode, &deviceFlags );
  1027. if (NT_SUCCESS(status) && (deviceFlags & CSCONFIGFLAG_DO_NOT_CREATE)) {
  1028. ExFreePool(serviceKeyValueInfo);
  1029. pUnicode->Length = savedLength; // Restore WorkName
  1030. return TRUE;
  1031. }
  1032. //
  1033. // Make sure this device instance is really a "device" by checking
  1034. // the "Legacy" value name.
  1035. //
  1036. legacy = 0;
  1037. status = IopGetRegistryValue( KeyHandle,
  1038. REGSTR_VALUE_LEGACY,
  1039. &keyValueInformation
  1040. );
  1041. if (NT_SUCCESS(status)) {
  1042. //
  1043. // If "Legacy=" exists ...
  1044. //
  1045. if (keyValueInformation->Type == REG_DWORD) {
  1046. if (keyValueInformation->DataLength >= sizeof(ULONG)) {
  1047. legacy = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
  1048. }
  1049. }
  1050. ExFreePool(keyValueInformation);
  1051. }
  1052. if (legacy) {
  1053. BOOLEAN doCreate = FALSE;
  1054. //
  1055. // Check if the the service for the device instance is a kernel mode
  1056. // driver (even though it is a legacy device instance.) If yes, we will
  1057. // create a PDO for it.
  1058. //
  1059. if (serviceName.Length) {
  1060. status = IopGetServiceType(&serviceName, &tmpValue1);
  1061. if (NT_SUCCESS(status) && tmpValue1 == SERVICE_KERNEL_DRIVER) {
  1062. doCreate = TRUE;
  1063. }
  1064. }
  1065. if (!doCreate) {
  1066. //
  1067. // We are not creating PDO for the device instance. In this case we
  1068. // need to register the device ourself for legacy compatibility.
  1069. //
  1070. // Note we will register this device to its driver even it is a
  1071. // duplicate. It will be deregistered when the real enumerated
  1072. // device shows up. We need to do this because the driver which
  1073. // controls the device may be a boot driver.
  1074. //
  1075. PpDeviceRegistration( pUnicode, TRUE, NULL );
  1076. //
  1077. // We did not create a PDO. Release the service and ordinal names.
  1078. //
  1079. if (serviceKeyValueInfo) {
  1080. ExFreePool(serviceKeyValueInfo);
  1081. }
  1082. pUnicode->Length = savedLength; // Restore WorkName
  1083. return TRUE;
  1084. }
  1085. }
  1086. if (serviceKeyValueInfo) {
  1087. ExFreePool(serviceKeyValueInfo);
  1088. }
  1089. //
  1090. // Create madeup PDO and device node to represent the root device.
  1091. //
  1092. //
  1093. // Madeup a name for the device object.
  1094. //
  1095. //
  1096. // Create madeup PDO and device node to represent the root device.
  1097. //
  1098. status = IoCreateDevice( IoPnpDriverObject,
  1099. sizeof(IOPNP_DEVICE_EXTENSION),
  1100. NULL,
  1101. FILE_DEVICE_CONTROLLER,
  1102. FILE_AUTOGENERATED_DEVICE_NAME,
  1103. FALSE,
  1104. &deviceObject );
  1105. if (NT_SUCCESS(status)) {
  1106. deviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;
  1107. deviceObject->DeviceObjectExtension->ExtensionFlags |= DOE_START_PENDING;
  1108. status = PipAllocateDeviceNode(deviceObject, &deviceNode);
  1109. if (status != STATUS_SYSTEM_HIVE_TOO_LARGE && deviceNode) {
  1110. //
  1111. // Make a copy of the device instance path and save it in
  1112. // device node.
  1113. //
  1114. if (PipConcatenateUnicodeStrings( &deviceNode->InstancePath,
  1115. pUnicode,
  1116. NULL
  1117. )) {
  1118. PCM_RESOURCE_LIST cmResource;
  1119. deviceNode->Flags = DNF_MADEUP | DNF_ENUMERATED;
  1120. PipSetDevNodeState(deviceNode, DeviceNodeInitialized, NULL);
  1121. PpDevNodeInsertIntoTree(IopRootDeviceNode, deviceNode);
  1122. if (legacy) {
  1123. deviceNode->Flags |= DNF_LEGACY_DRIVER | DNF_NO_RESOURCE_REQUIRED;
  1124. PipSetDevNodeState( deviceNode, DeviceNodeStarted, NULL );
  1125. } else {
  1126. //
  1127. // The device instance key exists. We need to propagate the ConfigFlag
  1128. // to problem and StatusFlags
  1129. //
  1130. deviceFlags = 0;
  1131. status = IopGetRegistryValue(KeyHandle,
  1132. REGSTR_VALUE_CONFIG_FLAGS,
  1133. &keyValueInformation);
  1134. if (NT_SUCCESS(status)) {
  1135. if ((keyValueInformation->Type == REG_DWORD) &&
  1136. (keyValueInformation->DataLength >= sizeof(ULONG))) {
  1137. deviceFlags = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
  1138. }
  1139. ExFreePool(keyValueInformation);
  1140. if (deviceFlags & CONFIGFLAG_REINSTALL) {
  1141. PipSetDevNodeProblem(deviceNode, CM_PROB_REINSTALL);
  1142. } else if (deviceFlags & CONFIGFLAG_PARTIAL_LOG_CONF) {
  1143. PipSetDevNodeProblem(deviceNode, CM_PROB_PARTIAL_LOG_CONF);
  1144. } else if (deviceFlags & CONFIGFLAG_FAILEDINSTALL) {
  1145. PipSetDevNodeProblem(deviceNode, CM_PROB_FAILED_INSTALL);
  1146. }
  1147. } else if (status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_OBJECT_PATH_NOT_FOUND) {
  1148. PipSetDevNodeProblem(deviceNode, CM_PROB_NOT_CONFIGURED);
  1149. }
  1150. }
  1151. if (isDuplicate) {
  1152. deviceNode->Flags |= DNF_DUPLICATE;
  1153. }
  1154. //
  1155. // If the key say don't assign any resource, honor it...
  1156. //
  1157. PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_NO_RESOURCE_AT_INIT);
  1158. status = IopGetRegistryValue( KeyHandle,
  1159. unicodeName.Buffer,
  1160. &keyValueInformation
  1161. );
  1162. if (NT_SUCCESS(status)) {
  1163. if (keyValueInformation->Type == REG_DWORD) {
  1164. if (keyValueInformation->DataLength >= sizeof(ULONG)) {
  1165. tmpValue1 = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
  1166. if (tmpValue1 != 0) {
  1167. deviceNode->Flags |= DNF_NO_RESOURCE_REQUIRED;
  1168. }
  1169. }
  1170. }
  1171. ExFreePool(keyValueInformation);
  1172. }
  1173. //
  1174. // we need to set initial capabilities, like any other device
  1175. // this will also handle hardware-disabled case
  1176. //
  1177. IopQueryAndSaveDeviceNodeCapabilities(deviceNode);
  1178. if (IopDeviceNodeFlagsToCapabilities(deviceNode)->HardwareDisabled &&
  1179. !PipIsDevNodeProblem(deviceNode,CM_PROB_NOT_CONFIGURED)) {
  1180. //
  1181. // mark the node as hardware disabled, if no other problems
  1182. //
  1183. PipClearDevNodeProblem(deviceNode);
  1184. PipSetDevNodeProblem(deviceNode, CM_PROB_HARDWARE_DISABLED);
  1185. //
  1186. // Issue a PNP REMOVE_DEVICE Irp so when we query resources
  1187. // we have those required after boot
  1188. //
  1189. //status = IopRemoveDevice (deviceNode->PhysicalDeviceObject, IRP_MN_REMOVE_DEVICE);
  1190. //ASSERT(NT_SUCCESS(status));
  1191. }
  1192. //
  1193. // Install service for critical devices.
  1194. // however don't do it if we found HardwareDisabled to be set
  1195. //
  1196. if (PipDoesDevNodeHaveProblem(deviceNode) &&
  1197. !IopDeviceNodeFlagsToCapabilities(deviceNode)->HardwareDisabled) {
  1198. PipProcessCriticalDevice(deviceNode);
  1199. }
  1200. //
  1201. // Set DNF_DISABLED flag if the device instance is disabled.
  1202. //
  1203. ASSERT(!PipDoesDevNodeHaveProblem(deviceNode) ||
  1204. PipIsDevNodeProblem(deviceNode, CM_PROB_NOT_CONFIGURED) ||
  1205. PipIsDevNodeProblem(deviceNode, CM_PROB_REINSTALL) ||
  1206. PipIsDevNodeProblem(deviceNode, CM_PROB_FAILED_INSTALL) ||
  1207. PipIsDevNodeProblem(deviceNode, CM_PROB_HARDWARE_DISABLED) ||
  1208. PipIsDevNodeProblem(deviceNode, CM_PROB_PARTIAL_LOG_CONF));
  1209. if (!PipIsDevNodeProblem(deviceNode, CM_PROB_DISABLED) &&
  1210. !PipIsDevNodeProblem(deviceNode, CM_PROB_HARDWARE_DISABLED) &&
  1211. !IopIsDeviceInstanceEnabled(KeyHandle, &deviceNode->InstancePath, TRUE)) {
  1212. //
  1213. // Normally IopIsDeviceInstanceEnabled would set
  1214. // CM_PROB_DISABLED as a side effect (if necessary). But it
  1215. // relies on the DeviceReference already being in the registry.
  1216. // We don't write it out till later so just set the problem
  1217. // now.
  1218. PipClearDevNodeProblem( deviceNode );
  1219. PipSetDevNodeProblem( deviceNode, CM_PROB_DISABLED );
  1220. }
  1221. status = IopNotifySetupDeviceArrival( deviceNode->PhysicalDeviceObject,
  1222. KeyHandle,
  1223. TRUE);
  1224. configuredBySetup = (BOOLEAN)NT_SUCCESS(status);
  1225. status = PpDeviceRegistration( &deviceNode->InstancePath,
  1226. TRUE,
  1227. &deviceNode->ServiceName
  1228. );
  1229. if (NT_SUCCESS(status) && configuredBySetup &&
  1230. PipIsDevNodeProblem(deviceNode, CM_PROB_NOT_CONFIGURED)) {
  1231. PipClearDevNodeProblem(deviceNode);
  1232. }
  1233. //
  1234. // Add an entry into the table to set up a mapping between the DO
  1235. // and the instance path.
  1236. //
  1237. status = IopMapDeviceObjectToDeviceInstance(deviceNode->PhysicalDeviceObject, &deviceNode->InstancePath);
  1238. ASSERT(NT_SUCCESS(status));
  1239. //
  1240. // Add a reference for config magr
  1241. //
  1242. ObReferenceObject(deviceObject);
  1243. //
  1244. // Check if this device has BOOT config. If yes, reserve them
  1245. //
  1246. cmResource = NULL;
  1247. status = IopGetDeviceResourcesFromRegistry (
  1248. deviceObject,
  1249. QUERY_RESOURCE_LIST,
  1250. REGISTRY_BOOT_CONFIG,
  1251. &cmResource,
  1252. &tmpValue1
  1253. );
  1254. if (NT_SUCCESS(status) && cmResource) {
  1255. //
  1256. // Still reserve boot config, even though the device is
  1257. // disabled.
  1258. //
  1259. status = (*IopAllocateBootResourcesRoutine)(
  1260. ArbiterRequestPnpEnumerated,
  1261. deviceNode->PhysicalDeviceObject,
  1262. cmResource);
  1263. if (NT_SUCCESS(status)) {
  1264. deviceNode->Flags |= DNF_HAS_BOOT_CONFIG;
  1265. }
  1266. ExFreePool(cmResource);
  1267. }
  1268. status = STATUS_SUCCESS;
  1269. //
  1270. // Add a reference for query device relations
  1271. //
  1272. ObReferenceObject(deviceObject);
  1273. } else {
  1274. IoDeleteDevice(deviceObject);
  1275. deviceObject = NULL;
  1276. status = STATUS_INSUFFICIENT_RESOURCES;
  1277. }
  1278. } else {
  1279. IoDeleteDevice(deviceObject);
  1280. deviceObject = NULL;
  1281. status = STATUS_INSUFFICIENT_RESOURCES;
  1282. }
  1283. }
  1284. pUnicode->Length = savedLength; // Restore WorkName
  1285. //
  1286. // If we enumerated a root device, add it to the device list
  1287. //
  1288. if (NT_SUCCESS(status)) {
  1289. ASSERT(deviceObject != NULL);
  1290. enumContext->DeviceList[enumContext->DeviceCount] = deviceObject;
  1291. enumContext->DeviceCount++;
  1292. return TRUE;
  1293. } else {
  1294. enumContext->Status = status;
  1295. return FALSE;
  1296. }
  1297. }
  1298. NTSTATUS
  1299. IopGetServiceType(
  1300. IN PUNICODE_STRING KeyName,
  1301. IN PULONG ServiceType
  1302. )
  1303. /*++
  1304. Routine Description:
  1305. This routine returns the controlling service's service type of the specified
  1306. Device instance.
  1307. Arguments:
  1308. KeyName - supplies a unicode string to specify the device instance.
  1309. ServiceType - supplies a pointer to a variable to receive the service type.
  1310. Return Value:
  1311. NTSTATUS code.
  1312. --*/
  1313. {
  1314. NTSTATUS status;
  1315. HANDLE handle;
  1316. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  1317. PAGED_CODE();
  1318. *ServiceType = ~0ul;
  1319. status = PipOpenServiceEnumKeys (
  1320. KeyName,
  1321. KEY_READ,
  1322. &handle,
  1323. NULL,
  1324. FALSE
  1325. );
  1326. if (NT_SUCCESS(status)) {
  1327. status = IopGetRegistryValue(handle, L"Type", &keyValueInformation);
  1328. if (NT_SUCCESS(status)) {
  1329. if (keyValueInformation->Type == REG_DWORD) {
  1330. if (keyValueInformation->DataLength >= sizeof(ULONG)) {
  1331. *ServiceType = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
  1332. }
  1333. }
  1334. ExFreePool(keyValueInformation);
  1335. }
  1336. ZwClose(handle);
  1337. }
  1338. return status;
  1339. }
  1340. BOOLEAN
  1341. PipIsFirmwareMapperDevicePresent (
  1342. IN HANDLE KeyHandle
  1343. )
  1344. /*++
  1345. Routine Description:
  1346. This routine checks if the registry key is created by FirmwareMapper.
  1347. If Yes, it further checks if the device for the key is present in this
  1348. boot.
  1349. Parameters:
  1350. KeyHandle - Specifies a handle to the registry key to be checked.
  1351. Return Value:
  1352. A BOOLEAN vaStatus code that indicates whether or not the function was successful.
  1353. --*/
  1354. {
  1355. NTSTATUS status;
  1356. HANDLE handle;
  1357. UNICODE_STRING unicodeName;
  1358. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  1359. ULONG tmp = 0;
  1360. PAGED_CODE();
  1361. //
  1362. // First check to see if this device instance key is a firmware-created one
  1363. //
  1364. status = IopGetRegistryValue (KeyHandle,
  1365. REGSTR_VAL_FIRMWAREIDENTIFIED,
  1366. &keyValueInformation);
  1367. if (NT_SUCCESS(status)) {
  1368. if ((keyValueInformation->Type == REG_DWORD) &&
  1369. (keyValueInformation->DataLength == sizeof(ULONG))) {
  1370. tmp = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
  1371. }
  1372. ExFreePool(keyValueInformation);
  1373. }
  1374. if (tmp == 0) {
  1375. return TRUE;
  1376. }
  1377. //
  1378. // Make sure the device is present.
  1379. //
  1380. PiWstrToUnicodeString(&unicodeName, REGSTR_KEY_CONTROL);
  1381. status = IopOpenRegistryKeyEx( &handle,
  1382. KeyHandle,
  1383. &unicodeName,
  1384. KEY_READ
  1385. );
  1386. if (!NT_SUCCESS(status)) {
  1387. return FALSE;
  1388. }
  1389. status = IopGetRegistryValue (handle,
  1390. REGSTR_VAL_FIRMWAREMEMBER,
  1391. &keyValueInformation);
  1392. ZwClose(handle);
  1393. tmp = 0;
  1394. if (NT_SUCCESS(status)) {
  1395. if ((keyValueInformation->Type == REG_DWORD) &&
  1396. (keyValueInformation->DataLength == sizeof(ULONG))) {
  1397. tmp = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
  1398. }
  1399. ExFreePool(keyValueInformation);
  1400. }
  1401. if (!tmp) {
  1402. return FALSE;
  1403. } else {
  1404. return TRUE;
  1405. }
  1406. }
  1407. NTSTATUS
  1408. IopSystemControlDispatch(
  1409. IN PDEVICE_OBJECT DeviceObject,
  1410. IN OUT PIRP Irp
  1411. )
  1412. {
  1413. NTSTATUS status;
  1414. PAGED_CODE();
  1415. status = Irp->IoStatus.Status;
  1416. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1417. return status;
  1418. }