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.

534 lines
13 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. vfpower.c
  5. Abstract:
  6. This module handles Power Irp verification.
  7. Author:
  8. Adrian J. Oney (adriao) 20-Apr-1998
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. AdriaO 06/15/2000 - Seperated out from ntos\io\flunkirp.c
  13. --*/
  14. #include "vfdef.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(INIT, VfPowerInit)
  17. #pragma alloc_text(PAGEVRFY, VfPowerDumpIrpStack)
  18. #pragma alloc_text(PAGEVRFY, VfPowerVerifyNewRequest)
  19. #pragma alloc_text(PAGEVRFY, VfPowerVerifyIrpStackDownward)
  20. #pragma alloc_text(PAGEVRFY, VfPowerVerifyIrpStackUpward)
  21. #pragma alloc_text(PAGEVRFY, VfPowerIsSystemRestrictedIrp)
  22. #pragma alloc_text(PAGEVRFY, VfPowerAdvanceIrpStatus)
  23. #pragma alloc_text(PAGEVRFY, VfPowerTestStartedPdoStack)
  24. #endif
  25. #ifdef ALLOC_DATA_PRAGMA
  26. #pragma const_seg("PAGEVRFC")
  27. #endif
  28. const PCHAR PowerIrpNames[] = {
  29. "IRP_MN_WAIT_WAKE", // 0x00
  30. "IRP_MN_POWER_SEQUENCE", // 0x01
  31. "IRP_MN_SET_POWER", // 0x02
  32. "IRP_MN_QUERY_POWER", // 0x03
  33. NULL
  34. };
  35. #define MAX_NAMED_POWER_IRP 0x3
  36. const PCHAR SystemStateNames[] = {
  37. "PowerSystemUnspecified", // 0x00
  38. "PowerSystemWorking.S0", // 0x01
  39. "PowerSystemSleeping1.S1", // 0x02
  40. "PowerSystemSleeping2.S2", // 0x03
  41. "PowerSystemSleeping3.S3", // 0x04
  42. "PowerSystemHibernate.S4", // 0x05
  43. "PowerSystemShutdown.S5", // 0x06
  44. NULL
  45. };
  46. #define MAX_NAMED_SYSTEM_STATES 0x6
  47. const PCHAR DeviceStateNames[] = {
  48. "PowerDeviceUnspecified", // 0x00
  49. "PowerDeviceD0", // 0x01
  50. "PowerDeviceD1", // 0x02
  51. "PowerDeviceD2", // 0x03
  52. "PowerDeviceD3", // 0x04
  53. NULL
  54. };
  55. #define MAX_NAMED_DEVICE_STATES 0x4
  56. const PCHAR ActionNames[] = {
  57. "PowerActionNone", // 0x00
  58. "PowerActionReserved", // 0x01
  59. "PowerActionSleep", // 0x02
  60. "PowerActionHibernate", // 0x03
  61. "PowerActionShutdown", // 0x04
  62. "PowerActionShutdownReset", // 0x05
  63. "PowerActionShutdownOff", // 0x06
  64. "PowerActionWarmEject", // 0x07
  65. NULL
  66. };
  67. #define MAX_ACTION_NAMES 0x7
  68. #ifdef ALLOC_DATA_PRAGMA
  69. #pragma const_seg()
  70. #endif // ALLOC_DATA_PRAGMA
  71. VOID
  72. VfPowerInit(
  73. VOID
  74. )
  75. {
  76. VfMajorRegisterHandlers(
  77. IRP_MJ_POWER,
  78. VfPowerDumpIrpStack,
  79. VfPowerVerifyNewRequest,
  80. VfPowerVerifyIrpStackDownward,
  81. VfPowerVerifyIrpStackUpward,
  82. VfPowerIsSystemRestrictedIrp,
  83. NULL,
  84. NULL,
  85. NULL,
  86. NULL,
  87. NULL,
  88. VfPowerTestStartedPdoStack
  89. );
  90. }
  91. VOID
  92. FASTCALL
  93. VfPowerVerifyNewRequest(
  94. IN PIOV_REQUEST_PACKET IovPacket,
  95. IN PDEVICE_OBJECT DeviceObject,
  96. IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
  97. IN PIO_STACK_LOCATION IrpSp,
  98. IN PIOV_STACK_LOCATION StackLocationData,
  99. IN PVOID CallerAddress OPTIONAL
  100. )
  101. {
  102. PIRP irp;
  103. NTSTATUS currentStatus;
  104. UNREFERENCED_PARAMETER (DeviceObject);
  105. UNREFERENCED_PARAMETER (IrpSp);
  106. UNREFERENCED_PARAMETER (IrpLastSp);
  107. irp = IovPacket->TrackedIrp;
  108. currentStatus = irp->IoStatus.Status;
  109. //
  110. // Verify new IRPs start out life accordingly
  111. //
  112. if (currentStatus!=STATUS_NOT_SUPPORTED) {
  113. WDM_FAIL_ROUTINE((
  114. DCERROR_POWER_IRP_BAD_INITIAL_STATUS,
  115. DCPARAM_IRP + DCPARAM_ROUTINE,
  116. CallerAddress,
  117. irp
  118. ));
  119. //
  120. // Don't blame anyone else for this driver's mistake.
  121. //
  122. if (!NT_SUCCESS(currentStatus)) {
  123. StackLocationData->Flags |= STACKFLAG_FAILURE_FORWARDED;
  124. }
  125. }
  126. }
  127. VOID
  128. FASTCALL
  129. VfPowerVerifyIrpStackDownward(
  130. IN PIOV_REQUEST_PACKET IovPacket,
  131. IN PDEVICE_OBJECT DeviceObject,
  132. IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
  133. IN PIO_STACK_LOCATION IrpSp,
  134. IN PIOV_STACK_LOCATION RequestHeadLocationData,
  135. IN PIOV_STACK_LOCATION StackLocationData,
  136. IN PVOID CallerAddress OPTIONAL
  137. )
  138. {
  139. PIRP irp = IovPacket->TrackedIrp;
  140. NTSTATUS currentStatus, lastStatus;
  141. BOOLEAN statusChanged;
  142. PDRIVER_OBJECT driverObject;
  143. PIOV_SESSION_DATA iovSessionData;
  144. UNREFERENCED_PARAMETER (IrpSp);
  145. currentStatus = irp->IoStatus.Status;
  146. lastStatus = RequestHeadLocationData->LastStatusBlock.Status;
  147. statusChanged = (BOOLEAN)(currentStatus != lastStatus);
  148. iovSessionData = VfPacketGetCurrentSessionData(IovPacket);
  149. //
  150. // Verify the IRP was forwarded properly
  151. //
  152. if (iovSessionData->ForwardMethod == SKIPPED_A_DO) {
  153. WDM_FAIL_ROUTINE((
  154. DCERROR_SKIPPED_DEVICE_OBJECT,
  155. DCPARAM_IRP + DCPARAM_ROUTINE,
  156. CallerAddress,
  157. irp
  158. ));
  159. }
  160. //
  161. // For some IRP major's going down a stack, there *must* be a handler
  162. //
  163. driverObject = DeviceObject->DriverObject;
  164. if (!IovUtilHasDispatchHandler(driverObject, IRP_MJ_POWER)) {
  165. RequestHeadLocationData->Flags |= STACKFLAG_BOGUS_IRP_TOUCHED;
  166. WDM_FAIL_ROUTINE((
  167. DCERROR_MISSING_DISPATCH_FUNCTION,
  168. DCPARAM_IRP + DCPARAM_ROUTINE,
  169. driverObject->DriverInit,
  170. irp
  171. ));
  172. StackLocationData->Flags |= STACKFLAG_NO_HANDLER;
  173. }
  174. //
  175. // The following is only executed if we are not a new IRP...
  176. //
  177. if (IrpLastSp == NULL) {
  178. return;
  179. }
  180. //
  181. // The only legit failure code to pass down is STATUS_NOT_SUPPORTED
  182. //
  183. if ((!NT_SUCCESS(currentStatus)) && (currentStatus != STATUS_NOT_SUPPORTED) &&
  184. (!(RequestHeadLocationData->Flags & STACKFLAG_FAILURE_FORWARDED))) {
  185. WDM_FAIL_ROUTINE((
  186. DCERROR_POWER_FAILURE_FORWARDED,
  187. DCPARAM_IRP + DCPARAM_ROUTINE,
  188. CallerAddress,
  189. irp
  190. ));
  191. //
  192. // Don't blame anyone else for this drivers's mistakes.
  193. //
  194. RequestHeadLocationData->Flags |= STACKFLAG_FAILURE_FORWARDED;
  195. }
  196. //
  197. // Status of a Power IRP may not be converted to STATUS_NOT_SUPPORTED on
  198. // the way down.
  199. //
  200. if ((currentStatus == STATUS_NOT_SUPPORTED)&&statusChanged) {
  201. WDM_FAIL_ROUTINE((
  202. DCERROR_POWER_IRP_STATUS_RESET,
  203. DCPARAM_IRP + DCPARAM_ROUTINE,
  204. CallerAddress,
  205. irp
  206. ));
  207. }
  208. }
  209. VOID
  210. FASTCALL
  211. VfPowerVerifyIrpStackUpward(
  212. IN PIOV_REQUEST_PACKET IovPacket,
  213. IN PIO_STACK_LOCATION IrpSp,
  214. IN PIOV_STACK_LOCATION RequestHeadLocationData,
  215. IN PIOV_STACK_LOCATION StackLocationData,
  216. IN BOOLEAN IsNewlyCompleted,
  217. IN BOOLEAN RequestFinalized
  218. )
  219. {
  220. PIRP irp;
  221. NTSTATUS currentStatus;
  222. BOOLEAN mustPassDown, isBogusIrp, isPdo;
  223. PVOID routine;
  224. UNREFERENCED_PARAMETER (IrpSp);
  225. UNREFERENCED_PARAMETER (RequestFinalized);
  226. irp = IovPacket->TrackedIrp;
  227. currentStatus = irp->IoStatus.Status;
  228. //
  229. // Who'd we call for this one?
  230. //
  231. routine = StackLocationData->LastDispatch;
  232. ASSERT(routine) ;
  233. //
  234. // If this "Request" has been "Completed", perform some checks
  235. //
  236. if (IsNewlyCompleted) {
  237. //
  238. // Remember bogosity...
  239. //
  240. isBogusIrp = (BOOLEAN)((IovPacket->Flags&TRACKFLAG_BOGUS)!=0);
  241. //
  242. // Is this a PDO?
  243. //
  244. isPdo = (BOOLEAN)((StackLocationData->Flags&STACKFLAG_REACHED_PDO)!=0);
  245. //
  246. // Was anything completed too early?
  247. // A driver may outright fail almost anything but a bogus IRP
  248. //
  249. mustPassDown = (BOOLEAN)(!(StackLocationData->Flags&STACKFLAG_NO_HANDLER));
  250. mustPassDown &= (!isPdo);
  251. mustPassDown &= (isBogusIrp || NT_SUCCESS(currentStatus) || (currentStatus == STATUS_NOT_SUPPORTED));
  252. if (mustPassDown) {
  253. //
  254. // Print appropriate error message
  255. //
  256. if (IovPacket->Flags&TRACKFLAG_BOGUS) {
  257. WDM_FAIL_ROUTINE((
  258. DCERROR_BOGUS_POWER_IRP_COMPLETED,
  259. DCPARAM_IRP + DCPARAM_ROUTINE,
  260. routine,
  261. irp
  262. ));
  263. } else if (NT_SUCCESS(currentStatus)) {
  264. WDM_FAIL_ROUTINE((
  265. DCERROR_SUCCESSFUL_POWER_IRP_NOT_FORWARDED,
  266. DCPARAM_IRP + DCPARAM_ROUTINE,
  267. routine,
  268. irp
  269. ));
  270. } else if (currentStatus == STATUS_NOT_SUPPORTED) {
  271. WDM_FAIL_ROUTINE((
  272. DCERROR_UNTOUCHED_POWER_IRP_NOT_FORWARDED,
  273. DCPARAM_IRP + DCPARAM_ROUTINE,
  274. routine,
  275. irp
  276. ));
  277. }
  278. }
  279. }
  280. //
  281. // Did anyone stomp the status erroneously?
  282. //
  283. if ((currentStatus == STATUS_NOT_SUPPORTED) &&
  284. (currentStatus != RequestHeadLocationData->LastStatusBlock.Status)) {
  285. //
  286. // Status of a PnP or Power IRP may not be converted from success to
  287. // STATUS_NOT_SUPPORTED on the way down.
  288. //
  289. WDM_FAIL_ROUTINE((
  290. DCERROR_POWER_IRP_STATUS_RESET,
  291. DCPARAM_IRP + DCPARAM_ROUTINE,
  292. routine,
  293. irp
  294. ));
  295. }
  296. }
  297. VOID
  298. FASTCALL
  299. VfPowerDumpIrpStack(
  300. IN PIO_STACK_LOCATION IrpSp
  301. )
  302. {
  303. DbgPrint("IRP_MJ_POWER.");
  304. if (IrpSp->MinorFunction <= MAX_NAMED_POWER_IRP) {
  305. DbgPrint(PowerIrpNames[IrpSp->MinorFunction]);
  306. if ((IrpSp->MinorFunction == IRP_MN_QUERY_POWER) ||
  307. (IrpSp->MinorFunction == IRP_MN_SET_POWER)) {
  308. DbgPrint("(");
  309. if (IrpSp->Parameters.Power.Type == SystemPowerState) {
  310. if (IrpSp->Parameters.Power.State.SystemState <= MAX_NAMED_SYSTEM_STATES) {
  311. DbgPrint(SystemStateNames[IrpSp->Parameters.Power.State.SystemState]);
  312. }
  313. } else {
  314. if (IrpSp->Parameters.Power.State.DeviceState <= MAX_NAMED_DEVICE_STATES) {
  315. DbgPrint(DeviceStateNames[IrpSp->Parameters.Power.State.DeviceState]);
  316. }
  317. }
  318. if (IrpSp->Parameters.Power.ShutdownType <= MAX_ACTION_NAMES) {
  319. DbgPrint(".%s", ActionNames[IrpSp->Parameters.Power.ShutdownType]);
  320. }
  321. DbgPrint(")");
  322. }
  323. } else if (IrpSp->MinorFunction == 0xFF) {
  324. DbgPrint("IRP_MN_BOGUS");
  325. } else {
  326. DbgPrint("(Bogus)");
  327. }
  328. }
  329. BOOLEAN
  330. FASTCALL
  331. VfPowerIsSystemRestrictedIrp(
  332. IN PIO_STACK_LOCATION IrpSp
  333. )
  334. {
  335. switch(IrpSp->MinorFunction) {
  336. case IRP_MN_POWER_SEQUENCE:
  337. return FALSE;
  338. case IRP_MN_QUERY_POWER:
  339. case IRP_MN_SET_POWER:
  340. case IRP_MN_WAIT_WAKE:
  341. return TRUE;
  342. default:
  343. break;
  344. }
  345. return TRUE;
  346. }
  347. BOOLEAN
  348. FASTCALL
  349. VfPowerAdvanceIrpStatus(
  350. IN PIO_STACK_LOCATION IrpSp,
  351. IN NTSTATUS OriginalStatus,
  352. IN OUT NTSTATUS *StatusToAdvance
  353. )
  354. /*++
  355. Description:
  356. Given an IRP stack pointer, is it legal to change the status for
  357. debug-ability? If so, this function determines what the new status
  358. should be. Note that for each stack location, this function is iterated
  359. over n times where n is equal to the number of drivers who IoSkip'd this
  360. location.
  361. Arguments:
  362. IrpSp - Current stack right after complete for the given stack
  363. location, but before the completion routine for the
  364. stack location above has been called.
  365. OriginalStatus - The status of the IRP at the time listed above. Does
  366. not change over iteration per skipping driver.
  367. StatusToAdvance - Pointer to the current status that should be updated.
  368. Return Value:
  369. TRUE if the status has been adjusted, FALSE otherwise (in this case
  370. StatusToAdvance is untouched).
  371. --*/
  372. {
  373. UNREFERENCED_PARAMETER (IrpSp);
  374. if (((ULONG) OriginalStatus) >= 256) {
  375. return FALSE;
  376. }
  377. (*StatusToAdvance)++;
  378. if ((*StatusToAdvance) == STATUS_PENDING) {
  379. (*StatusToAdvance)++;
  380. }
  381. return TRUE;
  382. }
  383. VOID
  384. FASTCALL
  385. VfPowerTestStartedPdoStack(
  386. IN PDEVICE_OBJECT PhysicalDeviceObject
  387. )
  388. /*++
  389. Description:
  390. As per the title, we are going to throw some IRPs at the stack to
  391. see if they are handled correctly.
  392. Returns:
  393. Nothing
  394. --*/
  395. {
  396. IO_STACK_LOCATION irpSp;
  397. PAGED_CODE();
  398. //
  399. // Initialize the stack location to pass to IopSynchronousCall()
  400. //
  401. RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
  402. if (VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_SEND_BOGUS_POWER_IRPS)) {
  403. //
  404. // And a bogus Power IRP
  405. //
  406. irpSp.MajorFunction = IRP_MJ_POWER;
  407. irpSp.MinorFunction = 0xff;
  408. VfIrpSendSynchronousIrp(
  409. PhysicalDeviceObject,
  410. &irpSp,
  411. TRUE,
  412. STATUS_NOT_SUPPORTED,
  413. 0,
  414. NULL,
  415. NULL
  416. );
  417. }
  418. }