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.

535 lines
14 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. NULL
  90. );
  91. }
  92. VOID
  93. FASTCALL
  94. VfPowerVerifyNewRequest(
  95. IN PIOV_REQUEST_PACKET IovPacket,
  96. IN PDEVICE_OBJECT DeviceObject,
  97. IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
  98. IN PIO_STACK_LOCATION IrpSp,
  99. IN PIOV_STACK_LOCATION StackLocationData,
  100. IN PVOID CallerAddress OPTIONAL
  101. )
  102. {
  103. PIRP irp;
  104. NTSTATUS currentStatus;
  105. UNREFERENCED_PARAMETER (DeviceObject);
  106. UNREFERENCED_PARAMETER (IrpSp);
  107. UNREFERENCED_PARAMETER (IrpLastSp);
  108. irp = IovPacket->TrackedIrp;
  109. currentStatus = irp->IoStatus.Status;
  110. //
  111. // Verify new IRPs start out life accordingly
  112. //
  113. if (currentStatus!=STATUS_NOT_SUPPORTED) {
  114. WDM_FAIL_ROUTINE((
  115. DCERROR_POWER_IRP_BAD_INITIAL_STATUS,
  116. DCPARAM_IRP + DCPARAM_ROUTINE,
  117. CallerAddress,
  118. irp
  119. ));
  120. //
  121. // Don't blame anyone else for this driver's mistake.
  122. //
  123. if (!NT_SUCCESS(currentStatus)) {
  124. StackLocationData->Flags |= STACKFLAG_FAILURE_FORWARDED;
  125. }
  126. }
  127. }
  128. VOID
  129. FASTCALL
  130. VfPowerVerifyIrpStackDownward(
  131. IN PIOV_REQUEST_PACKET IovPacket,
  132. IN PDEVICE_OBJECT DeviceObject,
  133. IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
  134. IN PIO_STACK_LOCATION IrpSp,
  135. IN PIOV_STACK_LOCATION RequestHeadLocationData,
  136. IN PIOV_STACK_LOCATION StackLocationData,
  137. IN PVOID CallerAddress OPTIONAL
  138. )
  139. {
  140. PIRP irp = IovPacket->TrackedIrp;
  141. NTSTATUS currentStatus, lastStatus;
  142. BOOLEAN statusChanged;
  143. PDRIVER_OBJECT driverObject;
  144. PIOV_SESSION_DATA iovSessionData;
  145. UNREFERENCED_PARAMETER (IrpSp);
  146. currentStatus = irp->IoStatus.Status;
  147. lastStatus = RequestHeadLocationData->LastStatusBlock.Status;
  148. statusChanged = (BOOLEAN)(currentStatus != lastStatus);
  149. iovSessionData = VfPacketGetCurrentSessionData(IovPacket);
  150. //
  151. // Verify the IRP was forwarded properly
  152. //
  153. if (iovSessionData->ForwardMethod == SKIPPED_A_DO) {
  154. WDM_FAIL_ROUTINE((
  155. DCERROR_SKIPPED_DEVICE_OBJECT,
  156. DCPARAM_IRP + DCPARAM_ROUTINE,
  157. CallerAddress,
  158. irp
  159. ));
  160. }
  161. //
  162. // For some IRP major's going down a stack, there *must* be a handler
  163. //
  164. driverObject = DeviceObject->DriverObject;
  165. if (!IovUtilHasDispatchHandler(driverObject, IRP_MJ_POWER)) {
  166. RequestHeadLocationData->Flags |= STACKFLAG_BOGUS_IRP_TOUCHED;
  167. WDM_FAIL_ROUTINE((
  168. DCERROR_MISSING_DISPATCH_FUNCTION,
  169. DCPARAM_IRP + DCPARAM_ROUTINE,
  170. driverObject->DriverInit,
  171. irp
  172. ));
  173. StackLocationData->Flags |= STACKFLAG_NO_HANDLER;
  174. }
  175. //
  176. // The following is only executed if we are not a new IRP...
  177. //
  178. if (IrpLastSp == NULL) {
  179. return;
  180. }
  181. //
  182. // The only legit failure code to pass down is STATUS_NOT_SUPPORTED
  183. //
  184. if ((!NT_SUCCESS(currentStatus)) && (currentStatus != STATUS_NOT_SUPPORTED) &&
  185. (!(RequestHeadLocationData->Flags & STACKFLAG_FAILURE_FORWARDED))) {
  186. WDM_FAIL_ROUTINE((
  187. DCERROR_POWER_FAILURE_FORWARDED,
  188. DCPARAM_IRP + DCPARAM_ROUTINE,
  189. CallerAddress,
  190. irp
  191. ));
  192. //
  193. // Don't blame anyone else for this drivers's mistakes.
  194. //
  195. RequestHeadLocationData->Flags |= STACKFLAG_FAILURE_FORWARDED;
  196. }
  197. //
  198. // Status of a Power IRP may not be converted to STATUS_NOT_SUPPORTED on
  199. // the way down.
  200. //
  201. if ((currentStatus == STATUS_NOT_SUPPORTED)&&statusChanged) {
  202. WDM_FAIL_ROUTINE((
  203. DCERROR_POWER_IRP_STATUS_RESET,
  204. DCPARAM_IRP + DCPARAM_ROUTINE,
  205. CallerAddress,
  206. irp
  207. ));
  208. }
  209. }
  210. VOID
  211. FASTCALL
  212. VfPowerVerifyIrpStackUpward(
  213. IN PIOV_REQUEST_PACKET IovPacket,
  214. IN PIO_STACK_LOCATION IrpSp,
  215. IN PIOV_STACK_LOCATION RequestHeadLocationData,
  216. IN PIOV_STACK_LOCATION StackLocationData,
  217. IN BOOLEAN IsNewlyCompleted,
  218. IN BOOLEAN RequestFinalized
  219. )
  220. {
  221. PIRP irp;
  222. NTSTATUS currentStatus;
  223. BOOLEAN mustPassDown, isBogusIrp, isPdo;
  224. PVOID routine;
  225. UNREFERENCED_PARAMETER (IrpSp);
  226. UNREFERENCED_PARAMETER (RequestFinalized);
  227. irp = IovPacket->TrackedIrp;
  228. currentStatus = irp->IoStatus.Status;
  229. //
  230. // Who'd we call for this one?
  231. //
  232. routine = StackLocationData->LastDispatch;
  233. ASSERT(routine) ;
  234. //
  235. // If this "Request" has been "Completed", perform some checks
  236. //
  237. if (IsNewlyCompleted) {
  238. //
  239. // Remember bogosity...
  240. //
  241. isBogusIrp = (BOOLEAN)((IovPacket->Flags&TRACKFLAG_BOGUS)!=0);
  242. //
  243. // Is this a PDO?
  244. //
  245. isPdo = (BOOLEAN)((StackLocationData->Flags&STACKFLAG_REACHED_PDO)!=0);
  246. //
  247. // Was anything completed too early?
  248. // A driver may outright fail almost anything but a bogus IRP
  249. //
  250. mustPassDown = (BOOLEAN)(!(StackLocationData->Flags&STACKFLAG_NO_HANDLER));
  251. mustPassDown &= (!isPdo);
  252. mustPassDown &= (isBogusIrp || NT_SUCCESS(currentStatus) || (currentStatus == STATUS_NOT_SUPPORTED));
  253. if (mustPassDown) {
  254. //
  255. // Print appropriate error message
  256. //
  257. if (IovPacket->Flags&TRACKFLAG_BOGUS) {
  258. WDM_FAIL_ROUTINE((
  259. DCERROR_BOGUS_POWER_IRP_COMPLETED,
  260. DCPARAM_IRP + DCPARAM_ROUTINE,
  261. routine,
  262. irp
  263. ));
  264. } else if (NT_SUCCESS(currentStatus)) {
  265. WDM_FAIL_ROUTINE((
  266. DCERROR_SUCCESSFUL_POWER_IRP_NOT_FORWARDED,
  267. DCPARAM_IRP + DCPARAM_ROUTINE,
  268. routine,
  269. irp
  270. ));
  271. } else if (currentStatus == STATUS_NOT_SUPPORTED) {
  272. WDM_FAIL_ROUTINE((
  273. DCERROR_UNTOUCHED_POWER_IRP_NOT_FORWARDED,
  274. DCPARAM_IRP + DCPARAM_ROUTINE,
  275. routine,
  276. irp
  277. ));
  278. }
  279. }
  280. }
  281. //
  282. // Did anyone stomp the status erroneously?
  283. //
  284. if ((currentStatus == STATUS_NOT_SUPPORTED) &&
  285. (currentStatus != RequestHeadLocationData->LastStatusBlock.Status)) {
  286. //
  287. // Status of a PnP or Power IRP may not be converted from success to
  288. // STATUS_NOT_SUPPORTED on the way down.
  289. //
  290. WDM_FAIL_ROUTINE((
  291. DCERROR_POWER_IRP_STATUS_RESET,
  292. DCPARAM_IRP + DCPARAM_ROUTINE,
  293. routine,
  294. irp
  295. ));
  296. }
  297. }
  298. VOID
  299. FASTCALL
  300. VfPowerDumpIrpStack(
  301. IN PIO_STACK_LOCATION IrpSp
  302. )
  303. {
  304. DbgPrint("IRP_MJ_POWER.");
  305. if (IrpSp->MinorFunction <= MAX_NAMED_POWER_IRP) {
  306. DbgPrint(PowerIrpNames[IrpSp->MinorFunction]);
  307. if ((IrpSp->MinorFunction == IRP_MN_QUERY_POWER) ||
  308. (IrpSp->MinorFunction == IRP_MN_SET_POWER)) {
  309. DbgPrint("(");
  310. if (IrpSp->Parameters.Power.Type == SystemPowerState) {
  311. if (IrpSp->Parameters.Power.State.SystemState <= MAX_NAMED_SYSTEM_STATES) {
  312. DbgPrint(SystemStateNames[IrpSp->Parameters.Power.State.SystemState]);
  313. }
  314. } else {
  315. if (IrpSp->Parameters.Power.State.DeviceState <= MAX_NAMED_DEVICE_STATES) {
  316. DbgPrint(DeviceStateNames[IrpSp->Parameters.Power.State.DeviceState]);
  317. }
  318. }
  319. if (IrpSp->Parameters.Power.ShutdownType <= MAX_ACTION_NAMES) {
  320. DbgPrint(".%s", ActionNames[IrpSp->Parameters.Power.ShutdownType]);
  321. }
  322. DbgPrint(")");
  323. }
  324. } else if (IrpSp->MinorFunction == 0xFF) {
  325. DbgPrint("IRP_MN_BOGUS");
  326. } else {
  327. DbgPrint("(Bogus)");
  328. }
  329. }
  330. BOOLEAN
  331. FASTCALL
  332. VfPowerIsSystemRestrictedIrp(
  333. IN PIO_STACK_LOCATION IrpSp
  334. )
  335. {
  336. switch(IrpSp->MinorFunction) {
  337. case IRP_MN_POWER_SEQUENCE:
  338. return FALSE;
  339. case IRP_MN_QUERY_POWER:
  340. case IRP_MN_SET_POWER:
  341. case IRP_MN_WAIT_WAKE:
  342. return TRUE;
  343. default:
  344. break;
  345. }
  346. return TRUE;
  347. }
  348. BOOLEAN
  349. FASTCALL
  350. VfPowerAdvanceIrpStatus(
  351. IN PIO_STACK_LOCATION IrpSp,
  352. IN NTSTATUS OriginalStatus,
  353. IN OUT NTSTATUS *StatusToAdvance
  354. )
  355. /*++
  356. Description:
  357. Given an IRP stack pointer, is it legal to change the status for
  358. debug-ability? If so, this function determines what the new status
  359. should be. Note that for each stack location, this function is iterated
  360. over n times where n is equal to the number of drivers who IoSkip'd this
  361. location.
  362. Arguments:
  363. IrpSp - Current stack right after complete for the given stack
  364. location, but before the completion routine for the
  365. stack location above has been called.
  366. OriginalStatus - The status of the IRP at the time listed above. Does
  367. not change over iteration per skipping driver.
  368. StatusToAdvance - Pointer to the current status that should be updated.
  369. Return Value:
  370. TRUE if the status has been adjusted, FALSE otherwise (in this case
  371. StatusToAdvance is untouched).
  372. --*/
  373. {
  374. UNREFERENCED_PARAMETER (IrpSp);
  375. if (((ULONG) OriginalStatus) >= 256) {
  376. return FALSE;
  377. }
  378. (*StatusToAdvance)++;
  379. if ((*StatusToAdvance) == STATUS_PENDING) {
  380. (*StatusToAdvance)++;
  381. }
  382. return TRUE;
  383. }
  384. VOID
  385. FASTCALL
  386. VfPowerTestStartedPdoStack(
  387. IN PDEVICE_OBJECT PhysicalDeviceObject
  388. )
  389. /*++
  390. Description:
  391. As per the title, we are going to throw some IRPs at the stack to
  392. see if they are handled correctly.
  393. Returns:
  394. Nothing
  395. --*/
  396. {
  397. IO_STACK_LOCATION irpSp;
  398. PAGED_CODE();
  399. //
  400. // Initialize the stack location to pass to IopSynchronousCall()
  401. //
  402. RtlZeroMemory(&irpSp, sizeof(IO_STACK_LOCATION));
  403. if (VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_SEND_BOGUS_POWER_IRPS)) {
  404. //
  405. // And a bogus Power IRP
  406. //
  407. irpSp.MajorFunction = IRP_MJ_POWER;
  408. irpSp.MinorFunction = 0xff;
  409. VfIrpSendSynchronousIrp(
  410. PhysicalDeviceObject,
  411. &irpSp,
  412. TRUE,
  413. STATUS_NOT_SUPPORTED,
  414. 0,
  415. NULL,
  416. NULL
  417. );
  418. }
  419. }