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.

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