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.

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