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.

621 lines
14 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. vfmajor.c
  5. Abstract:
  6. This module routes calls for per-major and generic 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. #include "vimajor.h"
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text(INIT, VfMajorInit)
  18. #pragma alloc_text(PAGEVRFY, VfMajorRegisterHandlers)
  19. #pragma alloc_text(PAGEVRFY, VfMajorDumpIrpStack)
  20. #pragma alloc_text(PAGEVRFY, VfMajorVerifyNewRequest)
  21. #pragma alloc_text(PAGEVRFY, VfMajorVerifyIrpStackDownward)
  22. #pragma alloc_text(PAGEVRFY, VfMajorVerifyIrpStackUpward)
  23. #pragma alloc_text(PAGEVRFY, VfMajorIsSystemRestrictedIrp)
  24. #pragma alloc_text(PAGEVRFY, VfMajorAdvanceIrpStatus)
  25. #pragma alloc_text(PAGEVRFY, VfMajorIsValidIrpStatus)
  26. #pragma alloc_text(PAGEVRFY, VfMajorIsNewRequest)
  27. #pragma alloc_text(PAGEVRFY, VfMajorVerifyNewIrp)
  28. #pragma alloc_text(PAGEVRFY, VfMajorVerifyFinalIrpStack)
  29. #pragma alloc_text(PAGEVRFY, VfMajorTestStartedPdoStack)
  30. #endif
  31. //
  32. // We have two extra slots, one for "all majors" and one permanently full of
  33. // zeroes.
  34. //
  35. IRP_MAJOR_VERIFIER_ROUTINES ViMajorVerifierRoutines[IRP_MJ_MAXIMUM_FUNCTION + 3];
  36. #define GET_MAJOR_ROUTINES(Major) \
  37. (ViMajorVerifierRoutines + \
  38. ((Major <= IRP_MJ_MAXIMUM_FUNCTION) ? Major : \
  39. ((Major == IRP_MJ_ALL_MAJORS) ? (IRP_MJ_MAXIMUM_FUNCTION + 1) : \
  40. (IRP_MJ_MAXIMUM_FUNCTION + 2))))
  41. VOID
  42. VfMajorInit(
  43. VOID
  44. )
  45. {
  46. //
  47. // Set every pointer to NULL.
  48. //
  49. RtlZeroMemory(ViMajorVerifierRoutines, sizeof(ViMajorVerifierRoutines));
  50. }
  51. VOID
  52. FASTCALL
  53. VfMajorRegisterHandlers(
  54. IN UCHAR IrpMajorCode,
  55. IN PFN_DUMP_IRP_STACK DumpIrpStack OPTIONAL,
  56. IN PFN_VERIFY_NEW_REQUEST VerifyNewRequest OPTIONAL,
  57. IN PFN_VERIFY_IRP_STACK_DOWNWARD VerifyStackDownward OPTIONAL,
  58. IN PFN_VERIFY_IRP_STACK_UPWARD VerifyStackUpward OPTIONAL,
  59. IN PFN_IS_SYSTEM_RESTRICTED_IRP IsSystemRestrictedIrp OPTIONAL,
  60. IN PFN_ADVANCE_IRP_STATUS AdvanceIrpStatus OPTIONAL,
  61. IN PFN_IS_VALID_IRP_STATUS IsValidIrpStatus OPTIONAL,
  62. IN PFN_IS_NEW_REQUEST IsNewRequest OPTIONAL,
  63. IN PFN_VERIFY_NEW_IRP VerifyNewIrp OPTIONAL,
  64. IN PFN_VERIFY_FINAL_IRP_STACK VerifyFinalIrpStack OPTIONAL,
  65. IN PFN_TEST_STARTED_PDO_STACK TestStartedPdoStack OPTIONAL
  66. )
  67. {
  68. PIRP_MAJOR_VERIFIER_ROUTINES verifierRoutines;
  69. //
  70. // Ensure only legal major codes are passed in.
  71. //
  72. if ((IrpMajorCode != IRP_MJ_ALL_MAJORS) &&
  73. (IrpMajorCode > IRP_MJ_MAXIMUM_FUNCTION)) {
  74. return;
  75. }
  76. verifierRoutines = GET_MAJOR_ROUTINES(IrpMajorCode);
  77. verifierRoutines->VerifyNewRequest = VerifyNewRequest;
  78. verifierRoutines->VerifyStackDownward = VerifyStackDownward;
  79. verifierRoutines->VerifyStackUpward = VerifyStackUpward;
  80. verifierRoutines->DumpIrpStack = DumpIrpStack;
  81. verifierRoutines->IsSystemRestrictedIrp = IsSystemRestrictedIrp;
  82. verifierRoutines->AdvanceIrpStatus = AdvanceIrpStatus;
  83. verifierRoutines->IsValidIrpStatus = IsValidIrpStatus;
  84. verifierRoutines->IsNewRequest = IsNewRequest;
  85. verifierRoutines->VerifyNewIrp = VerifyNewIrp;
  86. verifierRoutines->VerifyFinalIrpStack = VerifyFinalIrpStack;
  87. verifierRoutines->TestStartedPdoStack = TestStartedPdoStack;
  88. }
  89. VOID
  90. FASTCALL
  91. VfMajorDumpIrpStack(
  92. IN PIO_STACK_LOCATION IrpSp
  93. )
  94. {
  95. PIRP_MAJOR_VERIFIER_ROUTINES verifierRoutines;
  96. verifierRoutines = GET_MAJOR_ROUTINES(IrpSp->MajorFunction);
  97. //
  98. // First try to get a specific routine, else try a generic one. We never
  99. // call both for the purposes of printing.
  100. //
  101. if (verifierRoutines->DumpIrpStack == NULL) {
  102. verifierRoutines = GET_MAJOR_ROUTINES(IRP_MJ_ALL_MAJORS);
  103. if (verifierRoutines->DumpIrpStack == NULL) {
  104. return;
  105. }
  106. }
  107. verifierRoutines->DumpIrpStack(IrpSp);
  108. }
  109. VOID
  110. FASTCALL
  111. VfMajorVerifyNewRequest(
  112. IN PIOV_REQUEST_PACKET IovPacket,
  113. IN PDEVICE_OBJECT DeviceObject,
  114. IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
  115. IN PIO_STACK_LOCATION IrpSp,
  116. IN PIOV_STACK_LOCATION StackLocationData,
  117. IN PVOID CallerAddress OPTIONAL
  118. )
  119. {
  120. PIRP_MAJOR_VERIFIER_ROUTINES verifierRoutines;
  121. //
  122. // Perform major specific checks
  123. //
  124. verifierRoutines = GET_MAJOR_ROUTINES(IrpSp->MajorFunction);
  125. if (verifierRoutines->VerifyNewRequest) {
  126. verifierRoutines->VerifyNewRequest(
  127. IovPacket,
  128. DeviceObject,
  129. IrpLastSp,
  130. IrpSp,
  131. StackLocationData,
  132. CallerAddress
  133. );
  134. }
  135. //
  136. // Perform generic checks
  137. //
  138. verifierRoutines = GET_MAJOR_ROUTINES(IRP_MJ_ALL_MAJORS);
  139. if (verifierRoutines->VerifyNewRequest) {
  140. verifierRoutines->VerifyNewRequest(
  141. IovPacket,
  142. DeviceObject,
  143. IrpLastSp,
  144. IrpSp,
  145. StackLocationData,
  146. CallerAddress
  147. );
  148. }
  149. }
  150. VOID
  151. FASTCALL
  152. VfMajorVerifyIrpStackDownward(
  153. IN PIOV_REQUEST_PACKET IovPacket,
  154. IN PDEVICE_OBJECT DeviceObject,
  155. IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
  156. IN PIO_STACK_LOCATION IrpSp,
  157. IN PIOV_STACK_LOCATION StackLocationData,
  158. IN PVOID CallerAddress OPTIONAL
  159. )
  160. {
  161. PIRP_MAJOR_VERIFIER_ROUTINES verifierRoutines;
  162. //
  163. // Perform major specific checks
  164. //
  165. verifierRoutines = GET_MAJOR_ROUTINES(IrpSp->MajorFunction);
  166. if (verifierRoutines->VerifyStackDownward) {
  167. verifierRoutines->VerifyStackDownward(
  168. IovPacket,
  169. DeviceObject,
  170. IrpLastSp,
  171. IrpSp,
  172. StackLocationData->RequestsFirstStackLocation,
  173. StackLocationData,
  174. CallerAddress
  175. );
  176. }
  177. //
  178. // Perform generic checks
  179. //
  180. verifierRoutines = GET_MAJOR_ROUTINES(IRP_MJ_ALL_MAJORS);
  181. if (verifierRoutines->VerifyStackDownward) {
  182. verifierRoutines->VerifyStackDownward(
  183. IovPacket,
  184. DeviceObject,
  185. IrpLastSp,
  186. IrpSp,
  187. StackLocationData->RequestsFirstStackLocation,
  188. StackLocationData,
  189. CallerAddress
  190. );
  191. }
  192. }
  193. VOID
  194. FASTCALL
  195. VfMajorVerifyIrpStackUpward(
  196. IN PIOV_REQUEST_PACKET IovPacket,
  197. IN PIO_STACK_LOCATION IrpSp,
  198. IN PIOV_STACK_LOCATION StackLocationData,
  199. IN BOOLEAN IsNewlyCompleted,
  200. IN BOOLEAN RequestFinalized
  201. )
  202. {
  203. PIRP_MAJOR_VERIFIER_ROUTINES verifierRoutines;
  204. //
  205. // Perform major specific checks
  206. //
  207. verifierRoutines = GET_MAJOR_ROUTINES(IrpSp->MajorFunction);
  208. if (verifierRoutines->VerifyStackUpward) {
  209. verifierRoutines->VerifyStackUpward(
  210. IovPacket,
  211. IrpSp,
  212. StackLocationData->RequestsFirstStackLocation,
  213. StackLocationData,
  214. IsNewlyCompleted,
  215. RequestFinalized
  216. );
  217. }
  218. //
  219. // Perform generic checks
  220. //
  221. verifierRoutines = GET_MAJOR_ROUTINES(IRP_MJ_ALL_MAJORS);
  222. if (verifierRoutines->VerifyStackUpward) {
  223. verifierRoutines->VerifyStackUpward(
  224. IovPacket,
  225. IrpSp,
  226. StackLocationData->RequestsFirstStackLocation,
  227. StackLocationData,
  228. IsNewlyCompleted,
  229. RequestFinalized
  230. );
  231. }
  232. }
  233. BOOLEAN
  234. FASTCALL
  235. VfMajorIsSystemRestrictedIrp(
  236. IN PIO_STACK_LOCATION IrpSp
  237. )
  238. {
  239. PIRP_MAJOR_VERIFIER_ROUTINES verifierRoutines;
  240. //
  241. // Perform major specific checks
  242. //
  243. verifierRoutines = GET_MAJOR_ROUTINES(IrpSp->MajorFunction);
  244. if (verifierRoutines->IsSystemRestrictedIrp) {
  245. if (verifierRoutines->IsSystemRestrictedIrp(IrpSp)) {
  246. return TRUE;
  247. }
  248. }
  249. //
  250. // Perform generic checks
  251. //
  252. verifierRoutines = GET_MAJOR_ROUTINES(IRP_MJ_ALL_MAJORS);
  253. if (verifierRoutines->IsSystemRestrictedIrp) {
  254. return verifierRoutines->IsSystemRestrictedIrp(IrpSp);
  255. }
  256. return FALSE;
  257. }
  258. BOOLEAN
  259. FASTCALL
  260. VfMajorAdvanceIrpStatus(
  261. IN PIO_STACK_LOCATION IrpSp,
  262. IN NTSTATUS OriginalStatus,
  263. IN OUT NTSTATUS *StatusToAdvance
  264. )
  265. /*++
  266. Description:
  267. Given an IRP stack pointer, is it legal to change the status for
  268. debug-ability? If so, this function determines what the new status
  269. should be. Note that for each stack location, this function is iterated
  270. over n times where n is equal to the number of drivers who IoSkip'd this
  271. location.
  272. Arguments:
  273. IrpSp - Current stack right after complete for the given stack
  274. location, but before the completion routine for the
  275. stack location above has been called.
  276. OriginalStatus - The status of the IRP at the time listed above. Does
  277. not change over iteration per skipping driver.
  278. StatusToAdvance - Pointer to the current status that should be updated.
  279. Return Value:
  280. TRUE if the status has been adjusted, FALSE otherwise (in this case
  281. StatusToAdvance is untouched).
  282. --*/
  283. {
  284. PIRP_MAJOR_VERIFIER_ROUTINES verifierRoutines;
  285. //
  286. // Perform major specific checks
  287. //
  288. verifierRoutines = GET_MAJOR_ROUTINES(IrpSp->MajorFunction);
  289. if (verifierRoutines->AdvanceIrpStatus) {
  290. if (verifierRoutines->AdvanceIrpStatus(
  291. IrpSp,
  292. OriginalStatus,
  293. StatusToAdvance
  294. )) {
  295. return TRUE;
  296. }
  297. }
  298. //
  299. // Perform generic checks
  300. //
  301. verifierRoutines = GET_MAJOR_ROUTINES(IRP_MJ_ALL_MAJORS);
  302. if (verifierRoutines->AdvanceIrpStatus) {
  303. return verifierRoutines->AdvanceIrpStatus(
  304. IrpSp,
  305. OriginalStatus,
  306. StatusToAdvance
  307. );
  308. }
  309. return FALSE;
  310. }
  311. BOOLEAN
  312. FASTCALL
  313. VfMajorIsValidIrpStatus(
  314. IN PIO_STACK_LOCATION IrpSp,
  315. IN NTSTATUS Status
  316. )
  317. /*++
  318. Description:
  319. As per the title, this function determines whether an IRP status is
  320. valid or probably random trash. See NTStatus.h for info on how status
  321. codes break down...
  322. Arguments:
  323. IrpSp - Current stack location.
  324. Status - Status code.
  325. Returns:
  326. TRUE iff IRP status looks to be valid. FALSE otherwise.
  327. --*/
  328. {
  329. PIRP_MAJOR_VERIFIER_ROUTINES verifierRoutines;
  330. //
  331. // Perform major specific checks
  332. //
  333. verifierRoutines = GET_MAJOR_ROUTINES(IrpSp->MajorFunction);
  334. if (verifierRoutines->IsValidIrpStatus) {
  335. if (!verifierRoutines->IsValidIrpStatus(IrpSp, Status)) {
  336. return FALSE;
  337. }
  338. }
  339. //
  340. // Perform generic checks
  341. //
  342. verifierRoutines = GET_MAJOR_ROUTINES(IRP_MJ_ALL_MAJORS);
  343. if (verifierRoutines->IsValidIrpStatus) {
  344. return verifierRoutines->IsValidIrpStatus(IrpSp, Status);
  345. }
  346. return FALSE;
  347. }
  348. BOOLEAN
  349. FASTCALL
  350. VfMajorIsNewRequest(
  351. IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
  352. IN PIO_STACK_LOCATION IrpSp
  353. )
  354. /*++
  355. Description:
  356. Determines whether the two Irp stacks refer to the same "request",
  357. ie starting the same device, etc. This is used to detect whether an IRP
  358. has been simply forwarded or rather the IRP has been reused to initiate
  359. a new request.
  360. Arguments:
  361. The two IRP stacks to compare.
  362. N.B. - the device object is not currently part of those IRP stacks.
  363. Return Value:
  364. TRUE if the stacks represent the same request, FALSE otherwise.
  365. --*/
  366. {
  367. PIRP_MAJOR_VERIFIER_ROUTINES verifierRoutines;
  368. //
  369. // Perform major specific checks
  370. //
  371. verifierRoutines = GET_MAJOR_ROUTINES(IrpSp->MajorFunction);
  372. if (verifierRoutines->IsNewRequest) {
  373. if (verifierRoutines->IsNewRequest(IrpLastSp, IrpSp)) {
  374. return TRUE;
  375. }
  376. }
  377. //
  378. // Perform generic checks
  379. //
  380. verifierRoutines = GET_MAJOR_ROUTINES(IRP_MJ_ALL_MAJORS);
  381. if (verifierRoutines->IsNewRequest) {
  382. return verifierRoutines->IsNewRequest(IrpLastSp, IrpSp);
  383. }
  384. return FALSE;
  385. }
  386. VOID
  387. FASTCALL
  388. VfMajorVerifyNewIrp(
  389. IN PIOV_REQUEST_PACKET IovPacket,
  390. IN PIRP Irp,
  391. IN PIO_STACK_LOCATION IrpSp,
  392. IN PIOV_STACK_LOCATION StackLocationData,
  393. IN PVOID CallerAddress OPTIONAL
  394. )
  395. {
  396. PIRP_MAJOR_VERIFIER_ROUTINES verifierRoutines;
  397. //
  398. // Perform major specific checks
  399. //
  400. verifierRoutines = GET_MAJOR_ROUTINES(IrpSp->MajorFunction);
  401. if (verifierRoutines->VerifyNewIrp) {
  402. verifierRoutines->VerifyNewIrp(
  403. IovPacket,
  404. Irp,
  405. IrpSp,
  406. StackLocationData,
  407. CallerAddress
  408. );
  409. }
  410. //
  411. // Perform generic checks
  412. //
  413. verifierRoutines = GET_MAJOR_ROUTINES(IRP_MJ_ALL_MAJORS);
  414. if (verifierRoutines->VerifyNewIrp) {
  415. verifierRoutines->VerifyNewIrp(
  416. IovPacket,
  417. Irp,
  418. IrpSp,
  419. StackLocationData,
  420. CallerAddress
  421. );
  422. }
  423. }
  424. VOID
  425. FASTCALL
  426. VfMajorVerifyFinalIrpStack(
  427. IN PIOV_REQUEST_PACKET IovPacket,
  428. IN PIO_STACK_LOCATION IrpSp
  429. )
  430. {
  431. PIRP_MAJOR_VERIFIER_ROUTINES verifierRoutines;
  432. //
  433. // Perform major specific checks
  434. //
  435. verifierRoutines = GET_MAJOR_ROUTINES(IrpSp->MajorFunction);
  436. if (verifierRoutines->VerifyFinalIrpStack) {
  437. verifierRoutines->VerifyFinalIrpStack(IovPacket, IrpSp);
  438. }
  439. //
  440. // Perform generic checks
  441. //
  442. verifierRoutines = GET_MAJOR_ROUTINES(IRP_MJ_ALL_MAJORS);
  443. if (verifierRoutines->VerifyFinalIrpStack) {
  444. verifierRoutines->VerifyFinalIrpStack(IovPacket, IrpSp);
  445. }
  446. }
  447. VOID
  448. FASTCALL
  449. VfMajorTestStartedPdoStack(
  450. IN PDEVICE_OBJECT PhysicalDeviceObject
  451. )
  452. /*++
  453. Description:
  454. As per the title, we are going to throw some IRPs at the stack to
  455. see if they are handled correctly.
  456. Returns:
  457. Nothing
  458. --*/
  459. {
  460. PIRP_MAJOR_VERIFIER_ROUTINES verifierRoutines;
  461. ULONG index;
  462. for(index=0; index <= IRP_MJ_MAXIMUM_FUNCTION; index++) {
  463. verifierRoutines = GET_MAJOR_ROUTINES(index);
  464. if (verifierRoutines->TestStartedPdoStack) {
  465. verifierRoutines->TestStartedPdoStack(PhysicalDeviceObject);
  466. }
  467. }
  468. verifierRoutines = GET_MAJOR_ROUTINES(IRP_MJ_ALL_MAJORS);
  469. if (verifierRoutines->TestStartedPdoStack) {
  470. verifierRoutines->TestStartedPdoStack(PhysicalDeviceObject);
  471. }
  472. }