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.

1593 lines
39 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. pdo.c
  5. Abstract:
  6. This module provides the functions that pertain to MF.SYS PDOs
  7. Author:
  8. Andy Thornton (andrewth) 20-Oct-97
  9. Revision History:
  10. --*/
  11. #include "mfp.h"
  12. /*++
  13. The majority of functions in this file are called based on their presence
  14. in Pnp and Po dispatch tables. In the interests of brevity the arguments
  15. to all those functions will be described below:
  16. NTSTATUS
  17. MfXxxPdo(
  18. IN PIRP Irp,
  19. IN PMF_CHILD_EXTENSION Child,
  20. IN PIO_STACK_LOCATION IrpStack
  21. )
  22. Routine Description:
  23. This function handles the Xxx requests for multifunction PDO's
  24. Arguments:
  25. Irp - Points to the IRP associated with this request.
  26. Child - Points to the child PDO's device extension.
  27. IrpStack - Points to the current stack location for this request.
  28. Return Value:
  29. Status code that indicates whether or not the function was successful.
  30. STATUS_NOT_SUPPORTED indicates that the IRP should be completed without
  31. changing the Irp->IoStatus.Status field otherwise it is updated with this
  32. status.
  33. --*/
  34. NTSTATUS
  35. MfCreatePdo(
  36. IN PMF_PARENT_EXTENSION Parent,
  37. OUT PDEVICE_OBJECT *PhysicalDeviceObject
  38. );
  39. NTSTATUS
  40. MfStartPdo(
  41. IN PIRP Irp,
  42. IN PMF_CHILD_EXTENSION Child,
  43. IN PIO_STACK_LOCATION IrpStack
  44. );
  45. NTSTATUS
  46. MfQueryRemovePdo(
  47. IN PIRP Irp,
  48. IN PMF_CHILD_EXTENSION Child,
  49. IN PIO_STACK_LOCATION IrpStack
  50. );
  51. NTSTATUS
  52. MfRemovePdo(
  53. IN PIRP Irp,
  54. IN PMF_CHILD_EXTENSION Child,
  55. IN PIO_STACK_LOCATION IrpStack
  56. );
  57. NTSTATUS
  58. MfSurpriseRemovePdo(
  59. IN PIRP Irp,
  60. IN PMF_CHILD_EXTENSION Child,
  61. IN PIO_STACK_LOCATION IrpStack
  62. );
  63. NTSTATUS
  64. MfCancelRemovePdo(
  65. IN PIRP Irp,
  66. IN PMF_CHILD_EXTENSION Child,
  67. IN PIO_STACK_LOCATION IrpStack
  68. );
  69. NTSTATUS
  70. MfStopPdo(
  71. IN PIRP Irp,
  72. IN PMF_CHILD_EXTENSION Child,
  73. IN PIO_STACK_LOCATION IrpStack
  74. );
  75. NTSTATUS
  76. MfQueryStopPdo(
  77. IN PIRP Irp,
  78. IN PMF_CHILD_EXTENSION Child,
  79. IN PIO_STACK_LOCATION IrpStack
  80. );
  81. NTSTATUS
  82. MfCancelStopPdo(
  83. IN PIRP Irp,
  84. IN PMF_CHILD_EXTENSION Child,
  85. IN PIO_STACK_LOCATION IrpStack
  86. );
  87. NTSTATUS
  88. MfQueryDeviceRelationsPdo(
  89. IN PIRP Irp,
  90. IN PMF_CHILD_EXTENSION Child,
  91. IN PIO_STACK_LOCATION IrpStack
  92. );
  93. NTSTATUS
  94. MfQueryInterfacePdo(
  95. IN PIRP Irp,
  96. IN PMF_CHILD_EXTENSION Child,
  97. IN PIO_STACK_LOCATION IrpStack
  98. );
  99. NTSTATUS
  100. MfQueryCapabilitiesPdo(
  101. IN PIRP Irp,
  102. IN PMF_CHILD_EXTENSION Child,
  103. IN PIO_STACK_LOCATION IrpStack
  104. );
  105. NTSTATUS
  106. MfQueryResourcesPdo(
  107. IN PIRP Irp,
  108. IN PMF_CHILD_EXTENSION Child,
  109. IN PIO_STACK_LOCATION IrpStack
  110. );
  111. NTSTATUS
  112. MfQueryResourceRequirementsPdo(
  113. IN PIRP Irp,
  114. IN PMF_CHILD_EXTENSION Child,
  115. IN PIO_STACK_LOCATION IrpStack
  116. );
  117. NTSTATUS
  118. MfQueryDeviceTextPdo(
  119. IN PIRP Irp,
  120. IN PMF_CHILD_EXTENSION Child,
  121. IN PIO_STACK_LOCATION IrpStack
  122. );
  123. NTSTATUS
  124. MfQueryIdPdo(
  125. IN PIRP Irp,
  126. IN PMF_CHILD_EXTENSION Child,
  127. IN PIO_STACK_LOCATION IrpStack
  128. );
  129. NTSTATUS
  130. MfQueryPnpDeviceStatePdo(
  131. IN PIRP Irp,
  132. IN PMF_CHILD_EXTENSION Child,
  133. IN PIO_STACK_LOCATION IrpStack
  134. );
  135. NTSTATUS
  136. MfPagingNotificationPdo(
  137. IN PIRP Irp,
  138. IN PMF_CHILD_EXTENSION Child,
  139. IN PIO_STACK_LOCATION IrpStack
  140. );
  141. NTSTATUS
  142. MfSetPowerPdo(
  143. IN PIRP Irp,
  144. IN PMF_CHILD_EXTENSION Child,
  145. IN PIO_STACK_LOCATION IrpStack
  146. );
  147. NTSTATUS
  148. MfQueryPowerPdo(
  149. IN PIRP Irp,
  150. IN PMF_CHILD_EXTENSION Child,
  151. IN PIO_STACK_LOCATION IrpStack
  152. );
  153. VOID
  154. MfTranslatorReference(
  155. IN PVOID Context
  156. );
  157. VOID
  158. MfTranslatorDereference(
  159. IN PVOID Context
  160. );
  161. BOOLEAN
  162. MfIsSubResource(
  163. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Super,
  164. IN ULONGLONG SubStart,
  165. IN ULONG SubLength,
  166. OUT PULONGLONG Offset
  167. );
  168. NTSTATUS
  169. MfPerformTranslation(
  170. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
  171. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated,
  172. IN ULONGLONG Offset,
  173. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
  174. );
  175. NTSTATUS
  176. MfTransFromRawRequirements(
  177. IN PVOID Context,
  178. IN PIO_RESOURCE_DESCRIPTOR Source,
  179. IN PDEVICE_OBJECT PhysicalDeviceObject,
  180. OUT PULONG TargetCount,
  181. OUT PIO_RESOURCE_DESCRIPTOR *Target
  182. );
  183. NTSTATUS
  184. MfTransFromRawResources(
  185. IN PVOID Context,
  186. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
  187. IN RESOURCE_TRANSLATION_DIRECTION Direction,
  188. IN ULONG AlternativesCount, OPTIONAL
  189. IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
  190. IN PDEVICE_OBJECT PhysicalDeviceObject,
  191. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
  192. );
  193. #ifdef ALLOC_PRAGMA
  194. #pragma alloc_text(PAGE, MfCancelRemovePdo)
  195. #pragma alloc_text(PAGE, MfCancelStopPdo)
  196. #pragma alloc_text(PAGE, MfCreatePdo)
  197. #pragma alloc_text(PAGE, MfDispatchPnpPdo)
  198. #pragma alloc_text(PAGE, MfIsSubResource)
  199. #pragma alloc_text(PAGE, MfPerformTranslation)
  200. #pragma alloc_text(PAGE, MfQueryCapabilitiesPdo)
  201. #pragma alloc_text(PAGE, MfQueryDeviceRelationsPdo)
  202. #pragma alloc_text(PAGE, MfQueryDeviceTextPdo)
  203. #pragma alloc_text(PAGE, MfQueryIdPdo)
  204. #pragma alloc_text(PAGE, MfQueryInterfacePdo)
  205. #pragma alloc_text(PAGE, MfQueryRemovePdo)
  206. #pragma alloc_text(PAGE, MfQueryResourceRequirementsPdo)
  207. #pragma alloc_text(PAGE, MfQueryResourcesPdo)
  208. #pragma alloc_text(PAGE, MfQueryStopPdo)
  209. #pragma alloc_text(PAGE, MfRemovePdo)
  210. #pragma alloc_text(PAGE, MfStartPdo)
  211. #pragma alloc_text(PAGE, MfStopPdo)
  212. #pragma alloc_text(PAGE, MfTransFromRawRequirements)
  213. #pragma alloc_text(PAGE, MfTransFromRawResources)
  214. #endif
  215. PMF_DISPATCH MfPnpDispatchTablePdo[] = {
  216. MfStartPdo, // IRP_MN_START_DEVICE
  217. MfQueryRemovePdo, // IRP_MN_QUERY_REMOVE_DEVICE
  218. MfRemovePdo, // IRP_MN_REMOVE_DEVICE
  219. MfCancelRemovePdo, // IRP_MN_CANCEL_REMOVE_DEVICE
  220. MfIrpNotSupported, // IRP_MN_STOP_DEVICE
  221. MfQueryStopPdo, // IRP_MN_QUERY_STOP_DEVICE
  222. MfCancelStopPdo, // IRP_MN_CANCEL_STOP_DEVICE
  223. MfQueryDeviceRelationsPdo, // IRP_MN_QUERY_DEVICE_RELATIONS
  224. MfQueryInterfacePdo, // IRP_MN_QUERY_INTERFACE
  225. MfQueryCapabilitiesPdo, // IRP_MN_QUERY_CAPABILITIES
  226. MfQueryResourcesPdo, // IRP_MN_QUERY_RESOURCES
  227. MfQueryResourceRequirementsPdo, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
  228. MfQueryDeviceTextPdo, // IRP_MN_QUERY_DEVICE_TEXT
  229. MfIrpNotSupported, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
  230. MfIrpNotSupported, // Unused
  231. MfForwardIrpToParent, // IRP_MN_READ_CONFIG
  232. MfForwardIrpToParent, // IRP_MN_WRITE_CONFIG
  233. MfForwardIrpToParent, // IRP_MN_EJECT
  234. MfForwardIrpToParent, // IRP_MN_SET_LOCK
  235. MfQueryIdPdo, // IRP_MN_QUERY_ID
  236. MfQueryPnpDeviceStatePdo, // IRP_MN_QUERY_PNP_DEVICE_STATE
  237. MfForwardIrpToParent, // IRP_MN_QUERY_BUS_INFORMATION
  238. MfDeviceUsageNotificationCommon,// IRP_MN_DEVICE_USAGE_NOTIFICATION
  239. MfSurpriseRemovePdo, // IRP_MN_SURPRISE_REMOVAL
  240. MfIrpNotSupported // IRP_MN_QUERY_LEGACY_BUS_INFORMATION
  241. };
  242. PMF_DISPATCH MfPoDispatchTablePdo[] = {
  243. NULL, // IRP_MN_WAIT_WAKE
  244. NULL, // IRP_MN_POWER_SEQUENCE
  245. MfSetPowerPdo, // IRP_MN_SET_POWER
  246. MfQueryPowerPdo // IRP_MN_QUERY_POWER
  247. };
  248. NTSTATUS
  249. MfCreatePdo(
  250. IN PMF_PARENT_EXTENSION Parent,
  251. OUT PDEVICE_OBJECT *PhysicalDeviceObject
  252. )
  253. /*++
  254. Routine Description:
  255. Creates and initializes a new pdo inserting it into the list of PDOs owned
  256. by Parent
  257. Arguments:
  258. Parent - The parent device that owns this pdo.
  259. PhysicalDeviceObject - On success pointer to the physical device object created
  260. Return Value:
  261. NT status.
  262. --*/
  263. {
  264. NTSTATUS status;
  265. PDEVICE_OBJECT pdo;
  266. PMF_CHILD_EXTENSION extension;
  267. PAGED_CODE();
  268. ASSERT((sizeof(MfPnpDispatchTablePdo) / sizeof(PMF_DISPATCH)) - 1
  269. == IRP_MN_PNP_MAXIMUM_FUNCTION);
  270. ASSERT((sizeof(MfPoDispatchTablePdo) / sizeof(PMF_DISPATCH)) - 1
  271. == IRP_MN_PO_MAXIMUM_FUNCTION);
  272. status = IoCreateDevice(Parent->Self->DriverObject,
  273. sizeof(MF_CHILD_EXTENSION),
  274. NULL, // Name
  275. FILE_DEVICE_UNKNOWN,
  276. FILE_AUTOGENERATED_DEVICE_NAME,
  277. FALSE, // Exclusive
  278. &pdo
  279. );
  280. if (!NT_SUCCESS(status)) {
  281. return status;
  282. }
  283. //
  284. // Fill in our extension
  285. //
  286. extension = pdo->DeviceExtension;
  287. MfInitCommonExtension(&extension->Common, MfPhysicalDeviceObject);
  288. extension->Self = pdo;
  289. extension->Parent = Parent;
  290. extension->Common.PowerState = PowerDeviceUnspecified;
  291. //
  292. // Insert the child into the parents child list. Access already
  293. // protected by the children lock taken in the QDR code.
  294. //
  295. InsertHeadList(&Parent->Children, &extension->ListEntry);
  296. //
  297. // Our FDO stack is pagable, so we need to
  298. // assume pagable as well.
  299. //
  300. pdo->Flags |= DO_POWER_PAGABLE;
  301. //
  302. // We have finished initializing
  303. //
  304. pdo->Flags &= ~DO_DEVICE_INITIALIZING;
  305. *PhysicalDeviceObject = pdo;
  306. //
  307. // Dump the info about the PDO just created
  308. //
  309. DEBUG_MSG(1, ("Created PDO @ 0x%08x\n", pdo));
  310. return STATUS_SUCCESS;
  311. }
  312. VOID
  313. MfDeletePdo(
  314. IN PMF_CHILD_EXTENSION Child
  315. )
  316. /*++
  317. Routine Description:
  318. Cleans a PDO extension and any associated allocations. Then
  319. deletes the PDO itself.
  320. Arguments:
  321. Child - PDO extension
  322. Return Value:
  323. None
  324. --*/
  325. {
  326. if (Child->Common.DeviceState & MF_DEVICE_DELETED) {
  327. //
  328. // Trying to delete twice
  329. //
  330. ASSERT(!(Child->Common.DeviceState & MF_DEVICE_DELETED));
  331. return;
  332. }
  333. MfFreeDeviceInfo(&Child->Info);
  334. Child->Common.DeviceState |= MF_DEVICE_DELETED;
  335. DEBUG_MSG(1, ("Deleted PDO @ 0x%08x\n", Child->Self));
  336. IoDeleteDevice(Child->Self);
  337. }
  338. NTSTATUS
  339. MfDispatchPnpPdo(
  340. IN PDEVICE_OBJECT DeviceObject,
  341. IN PMF_CHILD_EXTENSION Child,
  342. IN PIO_STACK_LOCATION IrpStack,
  343. IN OUT PIRP Irp
  344. )
  345. /*++
  346. Routine Description:
  347. This routine handles IRP_MJ_PNP IRPs for PDOs.
  348. Arguments:
  349. DeviceObject - Pointer to the PDO for which this IRP applies.
  350. Child - PDO extension
  351. IrpStack - Current stack location
  352. Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
  353. Return Value:
  354. NT status.
  355. --*/
  356. {
  357. NTSTATUS status;
  358. BOOLEAN isRemove;
  359. PAGED_CODE();
  360. if (Child->Common.DeviceState & MF_DEVICE_DELETED) {
  361. status = Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  362. } else if (IrpStack->MinorFunction > IRP_MN_PNP_MAXIMUM_FUNCTION) {
  363. status = Irp->IoStatus.Status;
  364. } else {
  365. //
  366. // If IRP_MN_REMOVE_DEVICE is received by a pdo that was not
  367. // enumerated in the last BusRelations query, then it needs to
  368. // delete the pdo *AFTER* completing the remove irp. As this
  369. // is in conflict with the standard dispatch functionality
  370. // provided by this function, explicitly delegate completion
  371. // of this irp to the dispatched routine.
  372. isRemove = IrpStack->MinorFunction == IRP_MN_REMOVE_DEVICE;
  373. status =
  374. MfPnpDispatchTablePdo[IrpStack->MinorFunction](Irp,
  375. Child,
  376. IrpStack
  377. );
  378. if (isRemove) {
  379. return status;
  380. }
  381. if (status != STATUS_NOT_SUPPORTED) {
  382. Irp->IoStatus.Status = status;
  383. } else {
  384. status = Irp->IoStatus.Status;
  385. }
  386. }
  387. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  388. return status;
  389. }
  390. POWER_STATE
  391. MfUpdatePowerPdo(
  392. IN PMF_CHILD_EXTENSION Child,
  393. IN DEVICE_POWER_STATE NewDevicePowerState
  394. )
  395. {
  396. POWER_STATE previousState, newState;
  397. DEVICE_POWER_STATE newParentState;
  398. newState.DeviceState = NewDevicePowerState;
  399. previousState = PoSetPowerState(Child->Self,
  400. DevicePowerState,
  401. newState);
  402. ASSERT(previousState.DeviceState == Child->Common.PowerState);
  403. DEBUG_MSG(1,
  404. ("Updating child power state from %s (believed %s) to %s\n",
  405. DEVICE_POWER_STRING(previousState.DeviceState),
  406. DEVICE_POWER_STRING(Child->Common.PowerState),
  407. DEVICE_POWER_STRING(NewDevicePowerState)
  408. ));
  409. Child->Common.PowerState = NewDevicePowerState;
  410. //
  411. // We may be receiving an operation after our parent has been
  412. // surprise removed/removed in which case we should keep our
  413. // hands out of the cookie jar.
  414. //
  415. if (Child->Parent) {
  416. //
  417. // * We've already claimed that we can go to this power
  418. // state via the capabilities
  419. // * Said yes to QUERY_POWER
  420. // * Children's power state is defined to be as resource consuming
  421. // or less than the parent
  422. //
  423. // Update the children power state references stored in the
  424. // parent extension. Compute a new target power state for the
  425. // parent
  426. newParentState =
  427. MfUpdateChildrenPowerReferences(Child->Parent,
  428. previousState.DeviceState,
  429. NewDevicePowerState
  430. );
  431. //
  432. // Modify the parent's power state to reflect that of it's
  433. // children.
  434. //
  435. MfUpdateParentPowerState(Child->Parent, newParentState);
  436. }
  437. return previousState;
  438. }
  439. NTSTATUS
  440. MfStartPdo(
  441. IN PIRP Irp,
  442. IN PMF_CHILD_EXTENSION Child,
  443. IN PIO_STACK_LOCATION IrpStack
  444. )
  445. {
  446. PDEVICE_OBJECT pDO;
  447. POWER_STATE previousState, newState;
  448. PAGED_CODE();
  449. if (Child->Common.DeviceState & MF_DEVICE_SURPRISE_REMOVED) {
  450. return STATUS_NO_SUCH_DEVICE;
  451. }
  452. //
  453. // Trivially succeed the start
  454. //
  455. MfUpdatePowerPdo(Child, PowerDeviceD0);
  456. return STATUS_SUCCESS;
  457. }
  458. NTSTATUS
  459. MfQueryRemovePdo(
  460. IN PIRP Irp,
  461. IN PMF_CHILD_EXTENSION Child,
  462. IN PIO_STACK_LOCATION IrpStack
  463. )
  464. {
  465. PAGED_CODE();
  466. if (Child->Common.PagingCount > 0
  467. || Child->Common.HibernationCount > 0
  468. || Child->Common.DumpCount > 0) {
  469. return STATUS_DEVICE_BUSY;
  470. } else {
  471. return STATUS_SUCCESS;
  472. }
  473. }
  474. NTSTATUS
  475. MfCancelRemovePdo(
  476. IN PIRP Irp,
  477. IN PMF_CHILD_EXTENSION Child,
  478. IN PIO_STACK_LOCATION IrpStack
  479. )
  480. {
  481. PAGED_CODE();
  482. return STATUS_SUCCESS;
  483. }
  484. NTSTATUS
  485. MfRemovePdo(
  486. IN PIRP Irp,
  487. IN PMF_CHILD_EXTENSION Child,
  488. IN PIO_STACK_LOCATION IrpStack
  489. )
  490. {
  491. PAGED_CODE();
  492. if ((Child->Common.DeviceState & MF_DEVICE_SURPRISE_REMOVED) == 0) {
  493. MfUpdatePowerPdo(Child, PowerDeviceD3);
  494. }
  495. //
  496. // If child appeared in the last BusRelations then just mark it
  497. // removed, otherwise completely delete it.
  498. //
  499. Irp->IoStatus.Status = STATUS_SUCCESS;
  500. if (Child->Common.DeviceState & MF_DEVICE_ENUMERATED) {
  501. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  502. } else {
  503. if (Child->Parent) {
  504. MfAcquireChildrenLock(Child->Parent);
  505. RemoveEntryList(&Child->ListEntry);
  506. MfReleaseChildrenLock(Child->Parent);
  507. }
  508. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  509. MfDeletePdo(Child);
  510. }
  511. return STATUS_SUCCESS;
  512. }
  513. NTSTATUS
  514. MfSurpriseRemovePdo(
  515. IN PIRP Irp,
  516. IN PMF_CHILD_EXTENSION Child,
  517. IN PIO_STACK_LOCATION IrpStack
  518. )
  519. {
  520. PAGED_CODE();
  521. //
  522. // Mark device as surprise removed.
  523. //
  524. Child->Common.DeviceState |= MF_DEVICE_SURPRISE_REMOVED;
  525. //
  526. // Update my pdo's power state *AND* my parent's power state *IFF*
  527. // the parent is still connected.
  528. //
  529. MfUpdatePowerPdo(Child, PowerDeviceD3);
  530. //
  531. // The surprise remove could have one of many causes. One
  532. // possibility that can be excluded is MF reporting its children
  533. // missing directly since MF children can't disappear.
  534. //
  535. return STATUS_SUCCESS;
  536. }
  537. //
  538. // Stopping is disabled at the moment because MF is dependent on
  539. // changes in the arbiters to support resource rebalance.
  540. //
  541. NTSTATUS
  542. MfStopPdo(
  543. IN PIRP Irp,
  544. IN PMF_CHILD_EXTENSION Child,
  545. IN PIO_STACK_LOCATION IrpStack
  546. )
  547. {
  548. PAGED_CODE();
  549. return STATUS_SUCCESS;
  550. }
  551. NTSTATUS
  552. MfQueryStopPdo(
  553. IN PIRP Irp,
  554. IN PMF_CHILD_EXTENSION Child,
  555. IN PIO_STACK_LOCATION IrpStack
  556. )
  557. {
  558. PAGED_CODE();
  559. if (Child->Common.PagingCount > 0
  560. || Child->Common.HibernationCount > 0
  561. || Child->Common.DumpCount > 0) {
  562. return STATUS_UNSUCCESSFUL;
  563. } else {
  564. // REBALANCE
  565. // If rebalance was supported by parent, then this would have
  566. // to succeed.
  567. return STATUS_UNSUCCESSFUL;
  568. }
  569. }
  570. NTSTATUS
  571. MfCancelStopPdo(
  572. IN PIRP Irp,
  573. IN PMF_CHILD_EXTENSION Child,
  574. IN PIO_STACK_LOCATION IrpStack
  575. )
  576. {
  577. PAGED_CODE();
  578. return STATUS_SUCCESS;
  579. }
  580. NTSTATUS
  581. MfQueryDeviceRelationsPdo(
  582. IN PIRP Irp,
  583. IN PMF_CHILD_EXTENSION Child,
  584. IN PIO_STACK_LOCATION IrpStack
  585. )
  586. {
  587. PDEVICE_RELATIONS deviceRelations;
  588. PMF_CHILD_EXTENSION nextChild;
  589. NTSTATUS status;
  590. ULONG index;
  591. PAGED_CODE();
  592. if ((Child->Common.DeviceState & MF_DEVICE_SURPRISE_REMOVED) ||
  593. (Child->Parent == NULL)) {
  594. return STATUS_NO_SUCH_DEVICE;
  595. }
  596. status = Irp->IoStatus.Status;
  597. switch (IrpStack->Parameters.QueryDeviceRelations.Type) {
  598. case TargetDeviceRelation:
  599. deviceRelations = ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
  600. if (!deviceRelations) {
  601. return STATUS_INSUFFICIENT_RESOURCES;
  602. }
  603. status = ObReferenceObjectByPointer(Child->Self,
  604. 0,
  605. NULL,
  606. KernelMode);
  607. if (!NT_SUCCESS(status)) {
  608. ExFreePool(deviceRelations);
  609. return status;
  610. }
  611. deviceRelations->Count = 1;
  612. deviceRelations->Objects[0] = Child->Self;
  613. Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
  614. break;
  615. default:
  616. //
  617. // Don't touch the status
  618. //
  619. break;
  620. }
  621. return status;
  622. }
  623. //
  624. // Seeing as the MF translator don't allocate any memory for their context the
  625. // reference and dereference are nops.
  626. //
  627. VOID
  628. MfTranslatorReference(
  629. IN PVOID Context
  630. )
  631. {
  632. }
  633. VOID
  634. MfTranslatorDereference(
  635. IN PVOID Context
  636. )
  637. {
  638. }
  639. BOOLEAN
  640. MfIsSubResource(
  641. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Super,
  642. IN ULONGLONG SubStart,
  643. IN ULONG SubLength,
  644. OUT PULONGLONG Offset
  645. )
  646. {
  647. /*++
  648. Routine Description:
  649. Reports whether one resource descriptor is encapsulated
  650. in another
  651. Arguments:
  652. Super - the resource descriptor that we want to encapsulate
  653. SubStart - The start of the subrange
  654. SubLength - The length of the subrange
  655. Offset - On success the offset from the beginning of Super and
  656. SubStart.
  657. Return Value:
  658. TRUE on succeess FALSE otherwise
  659. --*/
  660. NTSTATUS status;
  661. ULONGLONG superStart;
  662. ULONG superLength;
  663. PMF_RESOURCE_TYPE restype;
  664. PAGED_CODE();
  665. ASSERT(Offset);
  666. restype = MfFindResourceType(Super->Type);
  667. if (restype == NULL) {
  668. ASSERT(restype != NULL);
  669. return FALSE;
  670. }
  671. status = restype->UnpackResource(Super,&superStart,&superLength);
  672. if (!NT_SUCCESS(status)) {
  673. ASSERT(NT_SUCCESS(status));
  674. return FALSE;
  675. }
  676. //
  677. // special case 0 length resources
  678. //
  679. if (superLength == 0) {
  680. if (SubLength == 0 &&
  681. SubStart == superStart) {
  682. *Offset = 0;
  683. return TRUE;
  684. }
  685. else return FALSE;
  686. }
  687. if (SubLength == 0) {
  688. if (SubStart >= superStart &&
  689. SubStart <= superStart + superLength - 1) {
  690. *Offset = SubStart-superStart;
  691. return TRUE;
  692. }
  693. else return FALSE;
  694. }
  695. //
  696. // if SubStart falls in between the ends of Super, we have
  697. // potential encapsulation
  698. //
  699. if ((SubStart >= superStart) && (SubStart <= superStart+superLength-1)) {
  700. //
  701. // It is an error if the two ranges overlap. Either
  702. // Sub should be encapsulated in Super or they should
  703. // not intersect.
  704. //
  705. ASSERT(SubStart+SubLength-1 <= superStart+superLength-1);
  706. if (SubStart+SubLength-1 > superStart+superLength-1) {
  707. return FALSE;
  708. }
  709. *Offset = SubStart-superStart;
  710. return TRUE;
  711. } else {
  712. //
  713. // Checking again to make sure ranges don't overlap
  714. //
  715. ASSERT((SubStart > superStart+superLength-1) ||
  716. (SubStart+SubLength-1 < superStart));
  717. return FALSE;
  718. }
  719. }
  720. NTSTATUS
  721. MfPerformTranslation(
  722. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
  723. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated,
  724. IN ULONGLONG Offset,
  725. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
  726. )
  727. {
  728. /*++
  729. Routine Description:
  730. stores the translated version of the Source resource in Target.
  731. Arguments:
  732. Source - the raw resource
  733. Translated - the translated resource that matches the raw resource
  734. that encapsulates Source.
  735. offset - the offset of the beginning of Source from the raw parent
  736. resource.
  737. Target - the resource descriptor in which the translated version of
  738. source is stored.
  739. Return Value:
  740. status of operation
  741. --*/
  742. NTSTATUS status;
  743. PMF_RESOURCE_TYPE restype;
  744. ULONGLONG translatedStart, dummy;
  745. ULONG sourceLength, dummy2;
  746. PAGED_CODE();
  747. RtlCopyMemory(Target, Translated, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
  748. //
  749. // Get the length from the source
  750. //
  751. restype = MfFindResourceType(Source->Type);
  752. if (restype == NULL) {
  753. return STATUS_INVALID_PARAMETER;
  754. }
  755. status = restype->UnpackResource(Source, &dummy, &sourceLength);
  756. if (!NT_SUCCESS(status)) {
  757. return status;
  758. }
  759. //
  760. // Get the start of the translated
  761. //
  762. restype = MfFindResourceType(Translated->Type);
  763. if (restype == NULL) {
  764. return STATUS_INVALID_PARAMETER;
  765. }
  766. status = restype->UnpackResource(Translated, &translatedStart, &dummy2);
  767. if (!NT_SUCCESS(status)) {
  768. return status;
  769. }
  770. //
  771. // Apply the offset and any length changes and update the descriptor
  772. //
  773. status = restype->UpdateResource(Target, translatedStart + Offset, sourceLength);
  774. return status;
  775. }
  776. NTSTATUS
  777. MfTransFromRawResources(
  778. IN PVOID Context,
  779. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
  780. IN RESOURCE_TRANSLATION_DIRECTION Direction,
  781. IN ULONG AlternativesCount, OPTIONAL
  782. IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
  783. IN PDEVICE_OBJECT PhysicalDeviceObject,
  784. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
  785. )
  786. /*++
  787. Routine Description:
  788. Translates a raw resource into a global translated resource.
  789. Arguments:
  790. Context - the parent extension that stores the raw and translated resources
  791. Source - the raw resource
  792. Direction - ChildToParent or ParentToChild
  793. PhysicalDeviceObject - the PDO associated with this
  794. Target - the translated resource
  795. Return Value:
  796. status of operation
  797. --*/
  798. {
  799. PMF_PARENT_EXTENSION parent = (PMF_PARENT_EXTENSION) Context;
  800. PCM_PARTIAL_RESOURCE_DESCRIPTOR raw, translated;
  801. NTSTATUS status;
  802. ULONGLONG offset;
  803. ULONGLONG sourceStart;
  804. ULONG sourceLength;
  805. PMF_RESOURCE_TYPE restype;
  806. ULONG index;
  807. PAGED_CODE();
  808. if (Direction == TranslateParentToChild) {
  809. //
  810. // Perform an identity translation
  811. //
  812. RtlCopyMemory(Target, Source, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
  813. return STATUS_SUCCESS;
  814. }
  815. //
  816. // Do some real translation
  817. //
  818. ASSERT(Direction == TranslateChildToParent);
  819. restype = MfFindResourceType(Source->Type);
  820. if (restype == NULL) {
  821. return STATUS_INVALID_PARAMETER;
  822. }
  823. status = restype->UnpackResource(Source,&sourceStart,&sourceLength);
  824. if (!NT_SUCCESS(status)) {
  825. return status;
  826. }
  827. //
  828. // runs through raw and translated resource lists, looking for the
  829. // element of the raw list that corresponds to the source we are
  830. // given as a parameter, then does the translation using the parallel
  831. // element of the translated list
  832. //
  833. index = 0;
  834. status = STATUS_INVALID_PARAMETER;
  835. FOR_ALL_CM_DESCRIPTORS(parent->ResourceList, raw) {
  836. if (raw->Type == Source->Type
  837. && MfIsSubResource(raw, sourceStart, sourceLength, &offset)) {
  838. //
  839. // This is a match, look up the translated entry in the parallel array
  840. //
  841. translated = &parent->TranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[index];
  842. status = MfPerformTranslation(Source, translated, offset, Target);
  843. if (NT_SUCCESS(status)) {
  844. //
  845. // We did our translation from the translated resources our parent got
  846. // and these are already
  847. //
  848. status = STATUS_TRANSLATION_COMPLETE;
  849. }
  850. break;
  851. } else {
  852. index++;
  853. }
  854. }
  855. return status;
  856. }
  857. NTSTATUS
  858. MfTransFromRawRequirements(
  859. IN PVOID Context,
  860. IN PIO_RESOURCE_DESCRIPTOR Source,
  861. IN PDEVICE_OBJECT PhysicalDeviceObject,
  862. OUT PULONG TargetCount,
  863. OUT PIO_RESOURCE_DESCRIPTOR *Target
  864. )
  865. {
  866. PAGED_CODE();
  867. *Target = ExAllocatePool(PagedPool, sizeof(IO_RESOURCE_DESCRIPTOR));
  868. if (!*Target) {
  869. return STATUS_INSUFFICIENT_RESOURCES;
  870. }
  871. RtlCopyMemory(*Target, Source, sizeof(IO_RESOURCE_DESCRIPTOR));
  872. *TargetCount = 1;
  873. return STATUS_TRANSLATION_COMPLETE;
  874. }
  875. NTSTATUS
  876. MfQueryInterfacePdo(
  877. IN PIRP Irp,
  878. IN PMF_CHILD_EXTENSION Child,
  879. IN PIO_STACK_LOCATION IrpStack
  880. )
  881. {
  882. PTRANSLATOR_INTERFACE interface = (PTRANSLATOR_INTERFACE) IrpStack->Parameters.QueryInterface.Interface;
  883. PAGED_CODE();
  884. if ((Child->Common.DeviceState & MF_DEVICE_SURPRISE_REMOVED) ||
  885. (Child->Parent == NULL)) {
  886. return STATUS_NO_SUCH_DEVICE;
  887. }
  888. if (MfCompareGuid(&GUID_TRANSLATOR_INTERFACE_STANDARD,
  889. IrpStack->Parameters.QueryInterface.InterfaceType)) {
  890. interface->Size = sizeof(TRANSLATOR_INTERFACE);
  891. interface->Version = MF_TRANSLATOR_INTERFACE_VERSION;
  892. interface->Context = Child->Parent;
  893. interface->InterfaceReference = MfTranslatorReference;
  894. interface->InterfaceDereference = MfTranslatorDereference;
  895. interface->TranslateResources = MfTransFromRawResources;
  896. interface->TranslateResourceRequirements = MfTransFromRawRequirements;
  897. Irp->IoStatus.Information = 0;
  898. // NTRAID#54667
  899. // Aren't we supposed to reference this before returning it?
  900. return STATUS_SUCCESS;
  901. } else if (MfCompareGuid(&GUID_ARBITER_INTERFACE_STANDARD,
  902. IrpStack->Parameters.QueryInterface.InterfaceType)) {
  903. return STATUS_INVALID_PARAMETER_1;
  904. } else if (MfCompareGuid(&GUID_MF_ENUMERATION_INTERFACE,
  905. IrpStack->Parameters.QueryInterface.InterfaceType)) {
  906. //
  907. // Otherwise you wouldn't be able to instantiate MF on top of a
  908. // MF child.
  909. //
  910. return Irp->IoStatus.Status;
  911. } else {
  912. //
  913. // Fire these off to the parent
  914. //
  915. // NOTE: There is the potential that some future interface(s)
  916. // shouldn't be forwarded to the parent.
  917. return MfForwardIrpToParent(Irp, Child, IrpStack);
  918. }
  919. }
  920. NTSTATUS
  921. MfQueryCapabilitiesPdo(
  922. IN PIRP Irp,
  923. IN PMF_CHILD_EXTENSION Child,
  924. IN PIO_STACK_LOCATION IrpStack
  925. )
  926. {
  927. PDEVICE_CAPABILITIES capabilities;
  928. IO_STACK_LOCATION location;
  929. NTSTATUS status;
  930. PAGED_CODE();
  931. if ((Child->Common.DeviceState & MF_DEVICE_SURPRISE_REMOVED) ||
  932. (Child->Parent == NULL)) {
  933. return STATUS_NO_SUCH_DEVICE;
  934. }
  935. ASSERT (Child->Parent);
  936. if (IrpStack->Parameters.DeviceCapabilities.Capabilities->Version != 1) {
  937. return STATUS_INVALID_PARAMETER;
  938. }
  939. capabilities = ExAllocatePool(PagedPool, sizeof(DEVICE_CAPABILITIES));
  940. if (capabilities == NULL) {
  941. return STATUS_INSUFFICIENT_RESOURCES;
  942. }
  943. RtlZeroMemory(capabilities, sizeof(DEVICE_CAPABILITIES));
  944. capabilities->Size = sizeof(DEVICE_CAPABILITIES);
  945. capabilities->Version = 1;
  946. capabilities->Address = capabilities->UINumber = -1;
  947. RtlZeroMemory(&location, sizeof(IO_STACK_LOCATION));
  948. location.MajorFunction = IRP_MJ_PNP;
  949. location.MinorFunction = IRP_MN_QUERY_CAPABILITIES;
  950. location.Parameters.DeviceCapabilities.Capabilities = capabilities;
  951. status = MfSendPnpIrp(Child->Parent->Self,
  952. &location,
  953. NULL);
  954. if (NT_SUCCESS(status)) {
  955. RtlCopyMemory(IrpStack->Parameters.DeviceCapabilities.Capabilities,
  956. location.Parameters.DeviceCapabilities.Capabilities,
  957. sizeof(DEVICE_CAPABILITIES)
  958. );
  959. //
  960. // The child has now inherited the capabilities of the MF
  961. // parent. Some of these capabilities must now be filtered
  962. // out in order to avoid implying functionality that is really
  963. // limited to the parent's bus driver.
  964. //
  965. //
  966. // Child is not removable, lockable, ejectable or
  967. // SurpriseRemovalOK. Ensure this
  968. //
  969. IrpStack->Parameters.DeviceCapabilities.Capabilities->LockSupported =
  970. IrpStack->Parameters.DeviceCapabilities.Capabilities->EjectSupported =
  971. IrpStack->Parameters.DeviceCapabilities.Capabilities->Removable =
  972. IrpStack->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = FALSE;
  973. }
  974. ExFreePool(capabilities);
  975. return status;
  976. }
  977. NTSTATUS
  978. MfQueryResourcesPdo(
  979. IN PIRP Irp,
  980. IN PMF_CHILD_EXTENSION Child,
  981. IN PIO_STACK_LOCATION IrpStack
  982. )
  983. {
  984. PAGED_CODE();
  985. //
  986. // If the parent device had a boot config then it will have
  987. // reported it (and they will have been preallocated). Don't
  988. // bother to report boot configs for the children as they don't
  989. // gain us anything other than extra arbitration.
  990. //
  991. return STATUS_NOT_SUPPORTED;
  992. }
  993. NTSTATUS
  994. MfQueryResourceRequirementsPdo(
  995. IN PIRP Irp,
  996. IN PMF_CHILD_EXTENSION Child,
  997. IN PIO_STACK_LOCATION IrpStack
  998. )
  999. {
  1000. NTSTATUS status;
  1001. PIO_RESOURCE_REQUIREMENTS_LIST requirements;
  1002. PAGED_CODE();
  1003. if ((Child->Common.DeviceState & MF_DEVICE_SURPRISE_REMOVED) ||
  1004. (Child->Parent == NULL)) {
  1005. return STATUS_NO_SUCH_DEVICE;
  1006. }
  1007. status = MfBuildChildRequirements(Child, &requirements);
  1008. if (NT_SUCCESS(status)) {
  1009. #if DBG
  1010. DEBUG_MSG(1, ("Reporting resource requirements for child 0x%08x\n", Child));
  1011. MfDbgPrintIoResReqList(1, requirements);
  1012. #endif
  1013. Irp->IoStatus.Information = (ULONG_PTR) requirements;
  1014. }
  1015. return status;
  1016. }
  1017. NTSTATUS
  1018. MfQueryDeviceTextPdo(
  1019. IN PIRP Irp,
  1020. IN PMF_CHILD_EXTENSION Child,
  1021. IN PIO_STACK_LOCATION IrpStack
  1022. )
  1023. {
  1024. NTSTATUS status;
  1025. PAGED_CODE();
  1026. if (IrpStack->Parameters.QueryDeviceText.DeviceTextType == DeviceTextDescription) {
  1027. #define MF_DEFAULT_DEVICE_TEXT L"Multifunction Device"
  1028. ULONG len = sizeof(MF_DEFAULT_DEVICE_TEXT);
  1029. PWSTR pStr;
  1030. pStr = ExAllocatePool(PagedPool, len);
  1031. if (!pStr) {
  1032. status = STATUS_INSUFFICIENT_RESOURCES;
  1033. } else {
  1034. RtlCopyMemory(pStr, MF_DEFAULT_DEVICE_TEXT, len);
  1035. Irp->IoStatus.Information = (ULONG_PTR) pStr;
  1036. status = STATUS_SUCCESS;
  1037. }
  1038. } else {
  1039. status = Irp->IoStatus.Status;
  1040. }
  1041. return status;
  1042. }
  1043. NTSTATUS
  1044. MfQueryIdPdo(
  1045. IN PIRP Irp,
  1046. IN PMF_CHILD_EXTENSION Child,
  1047. IN PIO_STACK_LOCATION IrpStack
  1048. )
  1049. {
  1050. NTSTATUS status = STATUS_SUCCESS;
  1051. PUNICODE_STRING copy;
  1052. PVOID buffer = NULL;
  1053. PAGED_CODE();
  1054. if ((Child->Common.DeviceState & MF_DEVICE_SURPRISE_REMOVED) ||
  1055. (Child->Parent == NULL)) {
  1056. return STATUS_NO_SUCH_DEVICE;
  1057. }
  1058. switch (IrpStack->Parameters.QueryId.IdType) {
  1059. case BusQueryDeviceID: // <Enumerator>\<Enumerator-specific device id>
  1060. return MfBuildDeviceID(Child->Parent,
  1061. (PWSTR*)&Irp->IoStatus.Information
  1062. );
  1063. break;
  1064. case BusQueryInstanceID: // persistent id for this instance of the device
  1065. return MfBuildInstanceID(Child,
  1066. (PWSTR*)&Irp->IoStatus.Information
  1067. );
  1068. break;
  1069. case BusQueryHardwareIDs: // Hardware ids
  1070. copy = &Child->Info.HardwareID;
  1071. break;
  1072. case BusQueryCompatibleIDs: // compatible device ids
  1073. copy = &Child->Info.CompatibleID;
  1074. break;
  1075. default:
  1076. return Irp->IoStatus.Status;
  1077. }
  1078. ASSERT(copy);
  1079. //
  1080. // If we have an ID to copy
  1081. //
  1082. if (copy->Length > 0) {
  1083. //
  1084. // Allocate the buffer for the ID and copy it
  1085. //
  1086. buffer = ExAllocatePoolWithTag(PagedPool,
  1087. copy->Length,
  1088. MF_HARDWARE_COMPATIBLE_ID_TAG
  1089. );
  1090. if (!buffer) {
  1091. return STATUS_INSUFFICIENT_RESOURCES;
  1092. }
  1093. RtlCopyMemory(buffer, copy->Buffer, copy->Length);
  1094. }
  1095. Irp->IoStatus.Information = (ULONG_PTR) buffer;
  1096. return STATUS_SUCCESS;
  1097. }
  1098. NTSTATUS
  1099. MfQueryPnpDeviceStatePdo(
  1100. IN PIRP Irp,
  1101. IN PMF_CHILD_EXTENSION Child,
  1102. IN PIO_STACK_LOCATION IrpStack
  1103. )
  1104. {
  1105. PAGED_CODE();
  1106. if (Child->Common.PagingCount > 0
  1107. || Child->Common.HibernationCount > 0
  1108. || Child->Common.DumpCount > 0) {
  1109. Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
  1110. }
  1111. return STATUS_SUCCESS;
  1112. }
  1113. //
  1114. // --- Power operations ---
  1115. //
  1116. NTSTATUS
  1117. MfDispatchPowerPdo(
  1118. IN PDEVICE_OBJECT DeviceObject,
  1119. IN PMF_CHILD_EXTENSION Child,
  1120. IN PIO_STACK_LOCATION IrpStack,
  1121. IN PIRP Irp
  1122. )
  1123. /*++
  1124. Routine Description:
  1125. This routine handles all IRP_MJ_POWER IRPs for PDO. It dispatches
  1126. to the routines described in the PoDispatchTable entry in the
  1127. device object extension.
  1128. This routine is NOT pageable as it can be called at DISPATCH_LEVEL
  1129. Arguments:
  1130. DeviceObject - Pointer to the device object for which this IRP applies.
  1131. Child - PDO extension
  1132. Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
  1133. IrpStack
  1134. Return Value:
  1135. NT status.
  1136. --*/
  1137. {
  1138. NTSTATUS status;
  1139. PMF_COMMON_EXTENSION common = (PMF_COMMON_EXTENSION) Child;
  1140. if ((Child->Common.DeviceState & (MF_DEVICE_SURPRISE_REMOVED|MF_DEVICE_DELETED)) ||
  1141. (Child->Parent == NULL)) {
  1142. PoStartNextPowerIrp(Irp);
  1143. status = STATUS_NO_SUCH_DEVICE;
  1144. } else if ((IrpStack->MinorFunction <= IRP_MN_PO_MAXIMUM_FUNCTION) &&
  1145. (MfPoDispatchTablePdo[IrpStack->MinorFunction])) {
  1146. //
  1147. // We are interested in this irp...
  1148. //
  1149. DEBUG_MSG(1,
  1150. ("--> Dispatching %s IRP for PDO 0x%08x\n",
  1151. PO_IRP_STRING(IrpStack->MinorFunction),
  1152. DeviceObject
  1153. ));
  1154. status =
  1155. MfPoDispatchTablePdo[IrpStack->MinorFunction](Irp,
  1156. (PVOID) common,
  1157. IrpStack
  1158. );
  1159. } else {
  1160. //
  1161. // We don't know about this irp
  1162. //
  1163. DEBUG_MSG(0,
  1164. ("Unknown POWER IRP 0x%x for PDO 0x%08x\n",
  1165. IrpStack->MinorFunction,
  1166. DeviceObject
  1167. ));
  1168. PoStartNextPowerIrp(Irp);
  1169. status = STATUS_NOT_SUPPORTED;
  1170. }
  1171. if (status != STATUS_NOT_SUPPORTED) {
  1172. //
  1173. // We understood the irp so we can set status - otherwise leave
  1174. // the status alone as we don't know what we are doing and a filter
  1175. // might have done the job for us!
  1176. //
  1177. Irp->IoStatus.Status = status;
  1178. DEBUG_MSG(1,
  1179. ("<-- Completing irp with status %s (0x%08x)\n",
  1180. STATUS_STRING(status),
  1181. status
  1182. ));
  1183. } else {
  1184. DEBUG_MSG(1,
  1185. ("<-- Completing unhandled irp, status is %s (0x%08x)\n",
  1186. STATUS_STRING(Irp->IoStatus.Status),
  1187. Irp->IoStatus.Status
  1188. ));
  1189. status = Irp->IoStatus.Status;
  1190. }
  1191. ASSERT(status == Irp->IoStatus.Status);
  1192. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1193. return status;
  1194. }
  1195. NTSTATUS
  1196. MfSetPowerPdo(
  1197. IN PIRP Irp,
  1198. IN PMF_CHILD_EXTENSION Child,
  1199. IN PIO_STACK_LOCATION IrpStack
  1200. )
  1201. {
  1202. NTSTATUS status;
  1203. POWER_STATE previousState;
  1204. UNREFERENCED_PARAMETER(Irp);
  1205. //
  1206. // If this is a system power state then someone else in the stack will have
  1207. // set the policy and we just leave well alone as we don't know anything
  1208. // about the hardware.
  1209. //
  1210. if (IrpStack->Parameters.Power.Type == DevicePowerState) {
  1211. MfUpdatePowerPdo(Child,
  1212. IrpStack->Parameters.Power.State.DeviceState);
  1213. }
  1214. PoStartNextPowerIrp(Irp);
  1215. return STATUS_SUCCESS;
  1216. }
  1217. NTSTATUS
  1218. MfQueryPowerPdo(
  1219. IN PIRP Irp,
  1220. IN PMF_CHILD_EXTENSION Child,
  1221. IN PIO_STACK_LOCATION IrpStack
  1222. )
  1223. {
  1224. UNREFERENCED_PARAMETER(Irp);
  1225. UNREFERENCED_PARAMETER(Child);
  1226. UNREFERENCED_PARAMETER(IrpStack);
  1227. //
  1228. // We can go to any power state...
  1229. //
  1230. PoStartNextPowerIrp(Irp);
  1231. return STATUS_SUCCESS;
  1232. }