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.

1618 lines
42 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 | FILE_DEVICE_SECURE_OPEN,
  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. Child->Common.DeviceState &= ~MF_DEVICE_SURPRISE_REMOVED;
  496. //
  497. // If child appeared in the last BusRelations then just mark it
  498. // removed, otherwise completely delete it.
  499. //
  500. Irp->IoStatus.Status = STATUS_SUCCESS;
  501. if (Child->Common.DeviceState & MF_DEVICE_ENUMERATED) {
  502. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  503. } else {
  504. if (Child->Parent) {
  505. MfAcquireChildrenLock(Child->Parent);
  506. RemoveEntryList(&Child->ListEntry);
  507. MfReleaseChildrenLock(Child->Parent);
  508. }
  509. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  510. MfDeletePdo(Child);
  511. }
  512. return STATUS_SUCCESS;
  513. }
  514. NTSTATUS
  515. MfSurpriseRemovePdo(
  516. IN PIRP Irp,
  517. IN PMF_CHILD_EXTENSION Child,
  518. IN PIO_STACK_LOCATION IrpStack
  519. )
  520. {
  521. PAGED_CODE();
  522. //
  523. // Mark device as surprise removed.
  524. //
  525. Child->Common.DeviceState |= MF_DEVICE_SURPRISE_REMOVED;
  526. //
  527. // Update my pdo's power state *AND* my parent's power state *IFF*
  528. // the parent is still connected.
  529. //
  530. MfUpdatePowerPdo(Child, PowerDeviceD3);
  531. //
  532. // The surprise remove could have one of many causes. One
  533. // possibility that can be excluded is MF reporting its children
  534. // missing directly since MF children can't disappear.
  535. //
  536. return STATUS_SUCCESS;
  537. }
  538. //
  539. // Stopping is disabled at the moment because MF is dependent on
  540. // changes in the arbiters to support resource rebalance.
  541. //
  542. NTSTATUS
  543. MfStopPdo(
  544. IN PIRP Irp,
  545. IN PMF_CHILD_EXTENSION Child,
  546. IN PIO_STACK_LOCATION IrpStack
  547. )
  548. {
  549. PAGED_CODE();
  550. return STATUS_SUCCESS;
  551. }
  552. NTSTATUS
  553. MfQueryStopPdo(
  554. IN PIRP Irp,
  555. IN PMF_CHILD_EXTENSION Child,
  556. IN PIO_STACK_LOCATION IrpStack
  557. )
  558. {
  559. PAGED_CODE();
  560. if (Child->Common.PagingCount > 0
  561. || Child->Common.HibernationCount > 0
  562. || Child->Common.DumpCount > 0) {
  563. return STATUS_UNSUCCESSFUL;
  564. } else {
  565. // REBALANCE
  566. // If rebalance was supported by parent, then this would have
  567. // to succeed.
  568. return STATUS_UNSUCCESSFUL;
  569. }
  570. }
  571. NTSTATUS
  572. MfCancelStopPdo(
  573. IN PIRP Irp,
  574. IN PMF_CHILD_EXTENSION Child,
  575. IN PIO_STACK_LOCATION IrpStack
  576. )
  577. {
  578. PAGED_CODE();
  579. return STATUS_SUCCESS;
  580. }
  581. NTSTATUS
  582. MfQueryDeviceRelationsPdo(
  583. IN PIRP Irp,
  584. IN PMF_CHILD_EXTENSION Child,
  585. IN PIO_STACK_LOCATION IrpStack
  586. )
  587. {
  588. PDEVICE_RELATIONS deviceRelations;
  589. PMF_CHILD_EXTENSION nextChild;
  590. NTSTATUS status;
  591. ULONG index;
  592. PAGED_CODE();
  593. if ((Child->Common.DeviceState & MF_DEVICE_SURPRISE_REMOVED) ||
  594. (Child->Parent == NULL)) {
  595. return STATUS_NO_SUCH_DEVICE;
  596. }
  597. status = Irp->IoStatus.Status;
  598. switch (IrpStack->Parameters.QueryDeviceRelations.Type) {
  599. case TargetDeviceRelation:
  600. deviceRelations = ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
  601. if (!deviceRelations) {
  602. return STATUS_INSUFFICIENT_RESOURCES;
  603. }
  604. status = ObReferenceObjectByPointer(Child->Self,
  605. 0,
  606. NULL,
  607. KernelMode);
  608. if (!NT_SUCCESS(status)) {
  609. ExFreePool(deviceRelations);
  610. return status;
  611. }
  612. deviceRelations->Count = 1;
  613. deviceRelations->Objects[0] = Child->Self;
  614. Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
  615. break;
  616. default:
  617. //
  618. // Don't touch the status
  619. //
  620. break;
  621. }
  622. return status;
  623. }
  624. //
  625. // Seeing as the MF translator don't allocate any memory for their context the
  626. // reference and dereference are nops.
  627. //
  628. VOID
  629. MfTranslatorReference(
  630. IN PVOID Context
  631. )
  632. {
  633. }
  634. VOID
  635. MfTranslatorDereference(
  636. IN PVOID Context
  637. )
  638. {
  639. }
  640. BOOLEAN
  641. MfIsSubResource(
  642. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Super,
  643. IN ULONGLONG SubStart,
  644. IN ULONG SubLength,
  645. OUT PULONGLONG Offset
  646. )
  647. {
  648. /*++
  649. Routine Description:
  650. Reports whether one resource descriptor is encapsulated
  651. in another
  652. Arguments:
  653. Super - the resource descriptor that we want to encapsulate
  654. SubStart - The start of the subrange
  655. SubLength - The length of the subrange
  656. Offset - On success the offset from the beginning of Super and
  657. SubStart.
  658. Return Value:
  659. TRUE on succeess FALSE otherwise
  660. --*/
  661. NTSTATUS status;
  662. ULONGLONG superStart;
  663. ULONG superLength;
  664. PMF_RESOURCE_TYPE restype;
  665. PAGED_CODE();
  666. ASSERT(Offset);
  667. restype = MfFindResourceType(Super->Type);
  668. if (restype == NULL) {
  669. ASSERT(restype != NULL);
  670. return FALSE;
  671. }
  672. status = restype->UnpackResource(Super,&superStart,&superLength);
  673. if (!NT_SUCCESS(status)) {
  674. ASSERT(NT_SUCCESS(status));
  675. return FALSE;
  676. }
  677. //
  678. // special case 0 length resources
  679. //
  680. if (superLength == 0) {
  681. if (SubLength == 0 &&
  682. SubStart == superStart) {
  683. *Offset = 0;
  684. return TRUE;
  685. }
  686. else return FALSE;
  687. }
  688. if (SubLength == 0) {
  689. if (SubStart >= superStart &&
  690. SubStart <= superStart + superLength - 1) {
  691. *Offset = SubStart-superStart;
  692. return TRUE;
  693. }
  694. else return FALSE;
  695. }
  696. //
  697. // if SubStart falls in between the ends of Super, we have
  698. // potential encapsulation
  699. //
  700. if ((SubStart >= superStart) && (SubStart <= superStart+superLength-1)) {
  701. //
  702. // It is an error if the two ranges overlap. Either
  703. // Sub should be encapsulated in Super or they should
  704. // not intersect.
  705. //
  706. ASSERT(SubStart+SubLength-1 <= superStart+superLength-1);
  707. if (SubStart+SubLength-1 > superStart+superLength-1) {
  708. return FALSE;
  709. }
  710. *Offset = SubStart-superStart;
  711. return TRUE;
  712. } else {
  713. //
  714. // Checking again to make sure ranges don't overlap
  715. //
  716. ASSERT((SubStart > superStart+superLength-1) ||
  717. (SubStart+SubLength-1 < superStart));
  718. return FALSE;
  719. }
  720. }
  721. NTSTATUS
  722. MfPerformTranslation(
  723. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
  724. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated,
  725. IN ULONGLONG Offset,
  726. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
  727. )
  728. {
  729. /*++
  730. Routine Description:
  731. stores the translated version of the Source resource in Target.
  732. Arguments:
  733. Source - the raw resource
  734. Translated - the translated resource that matches the raw resource
  735. that encapsulates Source.
  736. offset - the offset of the beginning of Source from the raw parent
  737. resource.
  738. Target - the resource descriptor in which the translated version of
  739. source is stored.
  740. Return Value:
  741. status of operation
  742. --*/
  743. NTSTATUS status;
  744. PMF_RESOURCE_TYPE restype;
  745. ULONGLONG translatedStart, dummy;
  746. ULONG sourceLength, dummy2;
  747. PAGED_CODE();
  748. RtlCopyMemory(Target, Translated, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
  749. //
  750. // Get the length from the source
  751. //
  752. restype = MfFindResourceType(Source->Type);
  753. if (restype == NULL) {
  754. return STATUS_INVALID_PARAMETER;
  755. }
  756. status = restype->UnpackResource(Source, &dummy, &sourceLength);
  757. if (!NT_SUCCESS(status)) {
  758. return status;
  759. }
  760. //
  761. // Get the start of the translated
  762. //
  763. restype = MfFindResourceType(Translated->Type);
  764. if (restype == NULL) {
  765. return STATUS_INVALID_PARAMETER;
  766. }
  767. status = restype->UnpackResource(Translated, &translatedStart, &dummy2);
  768. if (!NT_SUCCESS(status)) {
  769. return status;
  770. }
  771. //
  772. // Apply the offset and any length changes and update the descriptor
  773. //
  774. status = restype->UpdateResource(Target, translatedStart + Offset, sourceLength);
  775. return status;
  776. }
  777. NTSTATUS
  778. MfTransFromRawResources(
  779. IN PVOID Context,
  780. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
  781. IN RESOURCE_TRANSLATION_DIRECTION Direction,
  782. IN ULONG AlternativesCount, OPTIONAL
  783. IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
  784. IN PDEVICE_OBJECT PhysicalDeviceObject,
  785. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
  786. )
  787. /*++
  788. Routine Description:
  789. Translates a raw resource into a global translated resource.
  790. MF has translators to deal with child devices who request interrupts. The system
  791. interrupt translator can translate for PDOs that have routing information in the BIOS.
  792. This includes the MF parent device. MF child devices, however, are just logical
  793. subdivisions of the MF parent device, so they don't have the appropriate BIOS goop,
  794. and the system interrupt translator will fail translation on MF child PDOs.
  795. To handle this, MF exposes a translator. It only translates resources, not requirements,
  796. since raw requirements are the same as translated requirements. The translator recognizes
  797. that child resources are simply sub-resources of parent resources. Therefore, for a given
  798. raw child resource, the translator finds the raw parent resource that is a superset of the
  799. child resource, and copies the corresponding translated parent resource into the translated
  800. child resource, applying appropriate offsets. It then returns STATUS_TRANSLATION_COMPLETE
  801. to indicate that this is the final translation, and no other translators should be sought
  802. out for this device.
  803. Thus, the system interrupt translator will do the appropriate translation for the parent,
  804. and then MF applies this translation to the child inside its own translator. Returning
  805. STATUS_TRANSLATION_COMPLETE prevents the system interrupt translator from being called
  806. for the child device, and so prevents it from failing the translation.
  807. Arguments:
  808. Context - the parent extension that stores the raw and translated resources
  809. Source - the raw child resource
  810. Direction - ChildToParent or ParentToChild
  811. PhysicalDeviceObject - the PDO associated with this
  812. Target - the translated child resource
  813. Return Value:
  814. NT Status code. If the translation actually occurs, this will be STATUS_TRANSLATION_COMPLETE
  815. to indicate that pnp does not need to traverse the tree any more to find other translators.
  816. --*/
  817. {
  818. PMF_PARENT_EXTENSION parent = (PMF_PARENT_EXTENSION) Context;
  819. PCM_PARTIAL_RESOURCE_DESCRIPTOR raw, translated;
  820. NTSTATUS status;
  821. ULONGLONG offset;
  822. ULONGLONG sourceStart;
  823. ULONG sourceLength;
  824. PMF_RESOURCE_TYPE restype;
  825. ULONG index;
  826. PAGED_CODE();
  827. if (Direction == TranslateParentToChild) {
  828. //
  829. // Perform an identity translation
  830. //
  831. RtlCopyMemory(Target, Source, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
  832. return STATUS_SUCCESS;
  833. }
  834. //
  835. // Do some real translation
  836. //
  837. ASSERT(Direction == TranslateChildToParent);
  838. restype = MfFindResourceType(Source->Type);
  839. if (restype == NULL) {
  840. return STATUS_INVALID_PARAMETER;
  841. }
  842. status = restype->UnpackResource(Source,&sourceStart,&sourceLength);
  843. if (!NT_SUCCESS(status)) {
  844. return status;
  845. }
  846. //
  847. // runs through raw and translated resource lists, looking for the
  848. // element of the raw list that corresponds to the source we are
  849. // given as a parameter, then does the translation using the parallel
  850. // element of the translated list
  851. //
  852. index = 0;
  853. status = STATUS_INVALID_PARAMETER;
  854. FOR_ALL_CM_DESCRIPTORS(parent->ResourceList, raw) {
  855. if (raw->Type == Source->Type
  856. && MfIsSubResource(raw, sourceStart, sourceLength, &offset)) {
  857. //
  858. // This is a match, look up the translated entry in the parallel array
  859. //
  860. translated = &parent->TranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[index];
  861. status = MfPerformTranslation(Source, translated, offset, Target);
  862. if (NT_SUCCESS(status)) {
  863. //
  864. // We did our translation from the translated resources our parent got
  865. // and these are already
  866. //
  867. status = STATUS_TRANSLATION_COMPLETE;
  868. }
  869. break;
  870. } else {
  871. index++;
  872. }
  873. }
  874. return status;
  875. }
  876. NTSTATUS
  877. MfTransFromRawRequirements(
  878. IN PVOID Context,
  879. IN PIO_RESOURCE_DESCRIPTOR Source,
  880. IN PDEVICE_OBJECT PhysicalDeviceObject,
  881. OUT PULONG TargetCount,
  882. OUT PIO_RESOURCE_DESCRIPTOR *Target
  883. )
  884. {
  885. PAGED_CODE();
  886. *Target = ExAllocatePool(PagedPool, sizeof(IO_RESOURCE_DESCRIPTOR));
  887. if (!*Target) {
  888. return STATUS_INSUFFICIENT_RESOURCES;
  889. }
  890. RtlCopyMemory(*Target, Source, sizeof(IO_RESOURCE_DESCRIPTOR));
  891. *TargetCount = 1;
  892. return STATUS_TRANSLATION_COMPLETE;
  893. }
  894. NTSTATUS
  895. MfQueryInterfacePdo(
  896. IN PIRP Irp,
  897. IN PMF_CHILD_EXTENSION Child,
  898. IN PIO_STACK_LOCATION IrpStack
  899. )
  900. {
  901. PTRANSLATOR_INTERFACE transInterface;
  902. PAGED_CODE();
  903. if ((Child->Common.DeviceState & MF_DEVICE_SURPRISE_REMOVED) ||
  904. (Child->Parent == NULL)) {
  905. return STATUS_NO_SUCH_DEVICE;
  906. }
  907. if (MfCompareGuid(&GUID_TRANSLATOR_INTERFACE_STANDARD,
  908. IrpStack->Parameters.QueryInterface.InterfaceType)) {
  909. transInterface = (PTRANSLATOR_INTERFACE)IrpStack->Parameters.QueryInterface.Interface;
  910. transInterface->Size = sizeof(TRANSLATOR_INTERFACE);
  911. transInterface->Version = MF_TRANSLATOR_INTERFACE_VERSION;
  912. transInterface->Context = Child->Parent;
  913. transInterface->InterfaceReference = MfTranslatorReference;
  914. transInterface->InterfaceDereference = MfTranslatorDereference;
  915. transInterface->TranslateResources = MfTransFromRawResources;
  916. transInterface->TranslateResourceRequirements = MfTransFromRawRequirements;
  917. Irp->IoStatus.Information = 0;
  918. // NTRAID#54667
  919. // Aren't we supposed to reference this before returning it?
  920. return STATUS_SUCCESS;
  921. } else if (MfCompareGuid(&GUID_ARBITER_INTERFACE_STANDARD,
  922. IrpStack->Parameters.QueryInterface.InterfaceType)) {
  923. return STATUS_INVALID_PARAMETER_1;
  924. } else if (MfCompareGuid(&GUID_MF_ENUMERATION_INTERFACE,
  925. IrpStack->Parameters.QueryInterface.InterfaceType)) {
  926. //
  927. // Otherwise you wouldn't be able to instantiate MF on top of a
  928. // MF child.
  929. //
  930. return Irp->IoStatus.Status;
  931. } else {
  932. //
  933. // Fire these off to the parent
  934. //
  935. // NOTE: There is the potential that some future interface(s)
  936. // shouldn't be forwarded to the parent.
  937. return MfForwardIrpToParent(Irp, Child, IrpStack);
  938. }
  939. }
  940. NTSTATUS
  941. MfQueryCapabilitiesPdo(
  942. IN PIRP Irp,
  943. IN PMF_CHILD_EXTENSION Child,
  944. IN PIO_STACK_LOCATION IrpStack
  945. )
  946. {
  947. PDEVICE_CAPABILITIES capabilities;
  948. IO_STACK_LOCATION location;
  949. NTSTATUS status;
  950. PAGED_CODE();
  951. if ((Child->Common.DeviceState & MF_DEVICE_SURPRISE_REMOVED) ||
  952. (Child->Parent == NULL)) {
  953. return STATUS_NO_SUCH_DEVICE;
  954. }
  955. ASSERT (Child->Parent);
  956. if (IrpStack->Parameters.DeviceCapabilities.Capabilities->Version != 1) {
  957. return STATUS_INVALID_PARAMETER;
  958. }
  959. capabilities = ExAllocatePool(PagedPool, sizeof(DEVICE_CAPABILITIES));
  960. if (capabilities == NULL) {
  961. return STATUS_INSUFFICIENT_RESOURCES;
  962. }
  963. RtlZeroMemory(capabilities, sizeof(DEVICE_CAPABILITIES));
  964. capabilities->Size = sizeof(DEVICE_CAPABILITIES);
  965. capabilities->Version = 1;
  966. capabilities->Address = capabilities->UINumber = -1;
  967. RtlZeroMemory(&location, sizeof(IO_STACK_LOCATION));
  968. location.MajorFunction = IRP_MJ_PNP;
  969. location.MinorFunction = IRP_MN_QUERY_CAPABILITIES;
  970. location.Parameters.DeviceCapabilities.Capabilities = capabilities;
  971. status = MfSendPnpIrp(Child->Parent->Self,
  972. &location,
  973. NULL);
  974. if (NT_SUCCESS(status)) {
  975. RtlCopyMemory(IrpStack->Parameters.DeviceCapabilities.Capabilities,
  976. location.Parameters.DeviceCapabilities.Capabilities,
  977. sizeof(DEVICE_CAPABILITIES)
  978. );
  979. //
  980. // The child has now inherited the capabilities of the MF
  981. // parent. Some of these capabilities must now be filtered
  982. // out in order to avoid implying functionality that is really
  983. // limited to the parent's bus driver.
  984. //
  985. //
  986. // Child is not removable, lockable, ejectable or
  987. // SurpriseRemovalOK. Ensure this
  988. //
  989. IrpStack->Parameters.DeviceCapabilities.Capabilities->LockSupported =
  990. IrpStack->Parameters.DeviceCapabilities.Capabilities->EjectSupported =
  991. IrpStack->Parameters.DeviceCapabilities.Capabilities->Removable =
  992. IrpStack->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = FALSE;
  993. }
  994. ExFreePool(capabilities);
  995. return status;
  996. }
  997. NTSTATUS
  998. MfQueryResourcesPdo(
  999. IN PIRP Irp,
  1000. IN PMF_CHILD_EXTENSION Child,
  1001. IN PIO_STACK_LOCATION IrpStack
  1002. )
  1003. {
  1004. PAGED_CODE();
  1005. //
  1006. // If the parent device had a boot config then it will have
  1007. // reported it (and they will have been preallocated). Don't
  1008. // bother to report boot configs for the children as they don't
  1009. // gain us anything other than extra arbitration.
  1010. //
  1011. return STATUS_NOT_SUPPORTED;
  1012. }
  1013. NTSTATUS
  1014. MfQueryResourceRequirementsPdo(
  1015. IN PIRP Irp,
  1016. IN PMF_CHILD_EXTENSION Child,
  1017. IN PIO_STACK_LOCATION IrpStack
  1018. )
  1019. {
  1020. NTSTATUS status;
  1021. PIO_RESOURCE_REQUIREMENTS_LIST requirements;
  1022. PAGED_CODE();
  1023. if ((Child->Common.DeviceState & MF_DEVICE_SURPRISE_REMOVED) ||
  1024. (Child->Parent == NULL)) {
  1025. return STATUS_NO_SUCH_DEVICE;
  1026. }
  1027. status = MfBuildChildRequirements(Child, &requirements);
  1028. if (NT_SUCCESS(status)) {
  1029. #if DBG
  1030. DEBUG_MSG(1, ("Reporting resource requirements for child 0x%08x\n", Child));
  1031. MfDbgPrintIoResReqList(1, requirements);
  1032. #endif
  1033. Irp->IoStatus.Information = (ULONG_PTR) requirements;
  1034. }
  1035. return status;
  1036. }
  1037. NTSTATUS
  1038. MfQueryDeviceTextPdo(
  1039. IN PIRP Irp,
  1040. IN PMF_CHILD_EXTENSION Child,
  1041. IN PIO_STACK_LOCATION IrpStack
  1042. )
  1043. {
  1044. NTSTATUS status;
  1045. PAGED_CODE();
  1046. if (IrpStack->Parameters.QueryDeviceText.DeviceTextType == DeviceTextDescription) {
  1047. #define MF_DEFAULT_DEVICE_TEXT L"Multifunction Device"
  1048. ULONG len = sizeof(MF_DEFAULT_DEVICE_TEXT);
  1049. PWSTR pStr;
  1050. pStr = ExAllocatePool(PagedPool, len);
  1051. if (!pStr) {
  1052. status = STATUS_INSUFFICIENT_RESOURCES;
  1053. } else {
  1054. RtlCopyMemory(pStr, MF_DEFAULT_DEVICE_TEXT, len);
  1055. Irp->IoStatus.Information = (ULONG_PTR) pStr;
  1056. status = STATUS_SUCCESS;
  1057. }
  1058. } else {
  1059. status = Irp->IoStatus.Status;
  1060. }
  1061. return status;
  1062. }
  1063. NTSTATUS
  1064. MfQueryIdPdo(
  1065. IN PIRP Irp,
  1066. IN PMF_CHILD_EXTENSION Child,
  1067. IN PIO_STACK_LOCATION IrpStack
  1068. )
  1069. {
  1070. NTSTATUS status = STATUS_SUCCESS;
  1071. PUNICODE_STRING copy;
  1072. PVOID buffer = NULL;
  1073. PAGED_CODE();
  1074. Irp->IoStatus.Information = 0;
  1075. if ((Child->Common.DeviceState & MF_DEVICE_SURPRISE_REMOVED) ||
  1076. (Child->Parent == NULL)) {
  1077. return STATUS_NO_SUCH_DEVICE;
  1078. }
  1079. switch (IrpStack->Parameters.QueryId.IdType) {
  1080. case BusQueryDeviceID: // <Enumerator>\<Enumerator-specific device id>
  1081. return MfBuildDeviceID(Child->Parent,
  1082. (PWSTR*)&Irp->IoStatus.Information
  1083. );
  1084. break;
  1085. case BusQueryInstanceID: // persistent id for this instance of the device
  1086. return MfBuildInstanceID(Child,
  1087. (PWSTR*)&Irp->IoStatus.Information
  1088. );
  1089. break;
  1090. case BusQueryHardwareIDs: // Hardware ids
  1091. copy = &Child->Info.HardwareID;
  1092. break;
  1093. case BusQueryCompatibleIDs: // compatible device ids
  1094. copy = &Child->Info.CompatibleID;
  1095. break;
  1096. default:
  1097. return Irp->IoStatus.Status;
  1098. }
  1099. ASSERT(copy);
  1100. if (copy->Length == 0) {
  1101. return STATUS_INVALID_PARAMETER;
  1102. }
  1103. //
  1104. // Allocate the buffer for the ID and copy it
  1105. //
  1106. buffer = ExAllocatePoolWithTag(PagedPool,
  1107. copy->Length,
  1108. MF_HARDWARE_COMPATIBLE_ID_TAG
  1109. );
  1110. if (!buffer) {
  1111. return STATUS_INSUFFICIENT_RESOURCES;
  1112. }
  1113. RtlCopyMemory(buffer, copy->Buffer, copy->Length);
  1114. Irp->IoStatus.Information = (ULONG_PTR) buffer;
  1115. return STATUS_SUCCESS;
  1116. }
  1117. NTSTATUS
  1118. MfQueryPnpDeviceStatePdo(
  1119. IN PIRP Irp,
  1120. IN PMF_CHILD_EXTENSION Child,
  1121. IN PIO_STACK_LOCATION IrpStack
  1122. )
  1123. {
  1124. PAGED_CODE();
  1125. if (Child->Common.PagingCount > 0
  1126. || Child->Common.HibernationCount > 0
  1127. || Child->Common.DumpCount > 0) {
  1128. Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
  1129. }
  1130. return STATUS_SUCCESS;
  1131. }
  1132. //
  1133. // --- Power operations ---
  1134. //
  1135. NTSTATUS
  1136. MfDispatchPowerPdo(
  1137. IN PDEVICE_OBJECT DeviceObject,
  1138. IN PMF_CHILD_EXTENSION Child,
  1139. IN PIO_STACK_LOCATION IrpStack,
  1140. IN PIRP Irp
  1141. )
  1142. /*++
  1143. Routine Description:
  1144. This routine handles all IRP_MJ_POWER IRPs for PDO. It dispatches
  1145. to the routines described in the PoDispatchTable entry in the
  1146. device object extension.
  1147. This routine is NOT pageable as it can be called at DISPATCH_LEVEL
  1148. Arguments:
  1149. DeviceObject - Pointer to the device object for which this IRP applies.
  1150. Child - PDO extension
  1151. Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
  1152. IrpStack
  1153. Return Value:
  1154. NT status.
  1155. --*/
  1156. {
  1157. NTSTATUS status;
  1158. PMF_COMMON_EXTENSION common = (PMF_COMMON_EXTENSION) Child;
  1159. if ((Child->Common.DeviceState & (MF_DEVICE_SURPRISE_REMOVED|MF_DEVICE_DELETED)) ||
  1160. (Child->Parent == NULL)) {
  1161. PoStartNextPowerIrp(Irp);
  1162. status = STATUS_NO_SUCH_DEVICE;
  1163. } else if ((IrpStack->MinorFunction <= IRP_MN_PO_MAXIMUM_FUNCTION) &&
  1164. (MfPoDispatchTablePdo[IrpStack->MinorFunction])) {
  1165. //
  1166. // We are interested in this irp...
  1167. //
  1168. DEBUG_MSG(1,
  1169. ("--> Dispatching %s IRP for PDO 0x%08x\n",
  1170. PO_IRP_STRING(IrpStack->MinorFunction),
  1171. DeviceObject
  1172. ));
  1173. status =
  1174. MfPoDispatchTablePdo[IrpStack->MinorFunction](Irp,
  1175. (PVOID) common,
  1176. IrpStack
  1177. );
  1178. } else {
  1179. //
  1180. // We don't know about this irp
  1181. //
  1182. DEBUG_MSG(0,
  1183. ("Unknown POWER IRP 0x%x for PDO 0x%08x\n",
  1184. IrpStack->MinorFunction,
  1185. DeviceObject
  1186. ));
  1187. PoStartNextPowerIrp(Irp);
  1188. status = STATUS_NOT_SUPPORTED;
  1189. }
  1190. if (status != STATUS_NOT_SUPPORTED) {
  1191. //
  1192. // We understood the irp so we can set status - otherwise leave
  1193. // the status alone as we don't know what we are doing and a filter
  1194. // might have done the job for us!
  1195. //
  1196. Irp->IoStatus.Status = status;
  1197. DEBUG_MSG(1,
  1198. ("<-- Completing irp with status %s (0x%08x)\n",
  1199. STATUS_STRING(status),
  1200. status
  1201. ));
  1202. } else {
  1203. DEBUG_MSG(1,
  1204. ("<-- Completing unhandled irp, status is %s (0x%08x)\n",
  1205. STATUS_STRING(Irp->IoStatus.Status),
  1206. Irp->IoStatus.Status
  1207. ));
  1208. status = Irp->IoStatus.Status;
  1209. }
  1210. ASSERT(status == Irp->IoStatus.Status);
  1211. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1212. return status;
  1213. }
  1214. NTSTATUS
  1215. MfSetPowerPdo(
  1216. IN PIRP Irp,
  1217. IN PMF_CHILD_EXTENSION Child,
  1218. IN PIO_STACK_LOCATION IrpStack
  1219. )
  1220. {
  1221. NTSTATUS status;
  1222. POWER_STATE previousState;
  1223. UNREFERENCED_PARAMETER(Irp);
  1224. //
  1225. // If this is a system power state then someone else in the stack will have
  1226. // set the policy and we just leave well alone as we don't know anything
  1227. // about the hardware.
  1228. //
  1229. if (IrpStack->Parameters.Power.Type == DevicePowerState) {
  1230. MfUpdatePowerPdo(Child,
  1231. IrpStack->Parameters.Power.State.DeviceState);
  1232. }
  1233. PoStartNextPowerIrp(Irp);
  1234. return STATUS_SUCCESS;
  1235. }
  1236. NTSTATUS
  1237. MfQueryPowerPdo(
  1238. IN PIRP Irp,
  1239. IN PMF_CHILD_EXTENSION Child,
  1240. IN PIO_STACK_LOCATION IrpStack
  1241. )
  1242. {
  1243. UNREFERENCED_PARAMETER(Irp);
  1244. UNREFERENCED_PARAMETER(Child);
  1245. UNREFERENCED_PARAMETER(IrpStack);
  1246. //
  1247. // We can go to any power state...
  1248. //
  1249. PoStartNextPowerIrp(Irp);
  1250. return STATUS_SUCCESS;
  1251. }