Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

trackirp.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1998 Microsoft Corporation 00004 00005 Module Name: 00006 00007 trackirp.c 00008 00009 Abstract: 00010 00011 This module tracks irps and verified drivers when people do stupid things with 00012 them. 00013 00014 Note to people hitting bugs in these code paths due to core changes: 00015 00016 - "This file is NOT vital to operation of the OS, and could easily be 00017 disabled while a redesign to compensate for the core change is 00018 implemented." - the author 00019 00020 Author: 00021 00022 Adrian J. Oney (adriao) 09-May-1998 00023 00024 Environment: 00025 00026 Kernel mode 00027 00028 Revision History: 00029 00030 Known BUGBUGs: 00031 00032 ADRIAO BUGBUG #07 05/11/98 - Add a pass-through filter at every attach. 00033 ADRIAO BUGBUG #05 05/12/98 - Find a way to check pends when not forced. 00034 ADRIAO BUGBUG #17 05/30/98 - WMI IRPs may assert second time erroneously. 00035 ADRIAO BUGBUG #28 06/10/98 - Need to find a better way to id SCSI SRBs 00036 ADRIAO BUGBUG 08/16/98 - Pass on quota charging iff appropriate... 00037 ADRIAO BUGBUG 08/19/98 - Don't use hardcoded number. 00038 00039 Known HACKHACKs: 00040 00041 ADRIAO HACKHACK #05 05/30/98 - Create IRPs aren't surrogated as MUP chokes. 00042 (HACKHACK_FOR_MUP) 00043 ADRIAO HACKHACK #10 06/12/98 - Scsiport never skips, so I rip too much to boot. 00044 (HACKHACK_FOR_SCSIPORT) 00045 00046 --*/ 00047 00048 #include "iop.h" 00049 00050 #if (( defined(_X86_) ) && ( FPO )) 00051 #pragma optimize( "y", off ) // disable FPO for consistent stack traces 00052 #endif 00053 00054 #define POOL_TAG_DEFERRED_CONTEXT 'dprI' 00055 00056 #define HACKHACK_FOR_MUP 00057 #define HACKHACK_FOR_SCSIPORT 00058 #define HACKHACK_FOR_ACPI 00059 #define HACKHACK_FOR_BOGUSIRPS 00060 00061 // 00062 // This entire file is only present if NO_SPECIAL_IRP isn't defined 00063 // 00064 #ifndef NO_SPECIAL_IRP 00065 00066 // 00067 // When enabled, everything is locked down on demand... 00068 // 00069 #ifdef ALLOC_PRAGMA 00070 //#pragma alloc_text(NONPAGE, IovpDoAssertIrps) 00071 #pragma alloc_text(PAGE, IovpInitIrpTracking) 00072 #pragma alloc_text(PAGE, IovpReexamineAllStacks) 00073 #pragma alloc_text(PAGEVRFY, IovpCallDriver1) 00074 #pragma alloc_text(PAGEVRFY, IovpCallDriver2) 00075 #pragma alloc_text(PAGEVRFY, IovpCompleteRequest1) 00076 #pragma alloc_text(PAGEVRFY, IovpCompleteRequest2) 00077 #pragma alloc_text(PAGEVRFY, IovpCompleteRequest3) 00078 #pragma alloc_text(PAGEVRFY, IovpCompleteRequest4) 00079 #pragma alloc_text(PAGEVRFY, IovpCompleteRequest5) 00080 #pragma alloc_text(PAGEVRFY, IovpCompleteRequest) 00081 #pragma alloc_text(PAGEVRFY, IovpCancelIrp) 00082 #pragma alloc_text(PAGEVRFY, IovpFreeIrp) 00083 #pragma alloc_text(PAGEVRFY, IovpAllocateIrp1) 00084 #pragma alloc_text(PAGEVRFY, IovpAllocateIrp2) 00085 #pragma alloc_text(PAGEVRFY, IovpInitializeIrp) 00086 #pragma alloc_text(PAGEVRFY, IovpAttachDeviceToDeviceStack) 00087 #pragma alloc_text(PAGEVRFY, IovpDetachDevice) 00088 #pragma alloc_text(PAGEVRFY, IovpDeleteDevice) 00089 #pragma alloc_text(PAGEVRFY, IovpInternalCompletionTrap) 00090 #pragma alloc_text(PAGEVRFY, IovpSwapSurrogateIrp) 00091 #pragma alloc_text(PAGEVRFY, IovpProtectedIrpAllocate) 00092 #pragma alloc_text(PAGEVRFY, IovpProtectedIrpMakeTouchable) 00093 #pragma alloc_text(PAGEVRFY, IovpProtectedIrpMakeUntouchable) 00094 #pragma alloc_text(PAGEVRFY, IovpProtectedIrpFree) 00095 #pragma alloc_text(PAGEVRFY, IovpExamineDevObjForwarding) 00096 #pragma alloc_text(PAGEVRFY, IovpExamineIrpStackForwarding) 00097 #pragma alloc_text(PAGEVRFY, IovpGetDeviceAttachedTo) 00098 #pragma alloc_text(PAGEVRFY, IovpGetLowestDevice) 00099 #pragma alloc_text(PAGEVRFY, IovpAssertNonLegacyDevice) 00100 #pragma alloc_text(PAGEVRFY, IovpIsInFdoStack) 00101 #pragma alloc_text(PAGEVRFY, IovpSeedStack) 00102 #pragma alloc_text(PAGEVRFY, IovpSeedOnePage) 00103 #pragma alloc_text(PAGEVRFY, IovpSeedTwoPages) 00104 #pragma alloc_text(PAGEVRFY, IovpSeedThreePages) 00105 #pragma alloc_text(PAGEVRFY, IovpInternalDeferredCompletion) 00106 #pragma alloc_text(PAGEVRFY, IovpInternalCompleteAfterWait) 00107 #pragma alloc_text(PAGEVRFY, IovpInternalCompleteAtDPC) 00108 #pragma alloc_text(PAGEVRFY, IovpAdvanceStackDownwards) 00109 #pragma alloc_text(PAGEVRFY, IovpEnumDevObjCallback) 00110 #pragma alloc_text(PAGEVRFY, IovpIsInterestingStack) 00111 #pragma alloc_text(PAGEVRFY, IovpIsInterestingDriver) 00112 #endif 00113 00114 // 00115 // These flags control the tracking features and which hacks are enabled. 00116 // Both values will be set to the appropriate values if they are found 00117 // to be -1 at boot time. If they are changed at ^K time they will not 00118 // be subsequently overridden. 7FFFFFFF and 0 will do the maximum level 00119 // of testing... 00120 // 00121 ULONG IovpTrackingFlags = 0; //(ULONG) -1; 00122 ULONG IovpHackFlags = (ULONG) -1; 00123 00124 // 00125 // This global flag is set if assertions have been enabled. It will never 00126 // transition from TRUE to FALSE, so it is safe to do a quick check for 00127 // TRUE outside a spinlock. Furthermore, a false "FALSE" is guarenteed to 00128 // be safe. 00129 // 00130 BOOLEAN IovpIrpTrackingEnabled = FALSE; 00131 00132 // 00133 // Flags that indicate how we were initialized. 00134 // 00135 ULONG IovpInitFlags = 0; 00136 00137 // 00138 // This counter is used in picking random IRPs to cancel 00139 // 00140 ULONG IovpCancelCount = 0; 00141 00142 // 00143 // This is the time in 100ns units to defer an IRP if so told. 00144 // 00145 // ADRIAO BUGBUG 08/19/98 - Don't use hardcoded number. 00146 // 00147 LONG IovpIrpDeferralTime = 10 * 300; // 300us 00148 00149 /* 00150 * - The IRP verification code works as follows - 00151 * 00152 * To enforce the correct handling of an IRP, we must maintain some data about 00153 * it. But the IRP is a public structure and as drivers are allowed to create 00154 * IRPs without using IoAllocateIrp we cannot add any fields to it. Therefore 00155 * we maintain out own side structures that are looked up via a hash table. 00156 * 00157 * IOV_REQUEST_PACKETs cover the lifetime of the IRP from allocation to 00158 * deallocation, and from there (sans pointer) until all "references" have 00159 * been dropped, which may happen long after the IRP itself was freed and 00160 * recycled. 00161 * 00162 * When an IRP is progress down a stack, a "session" is allocated. An 00163 * IovRequestPacket has a current session until such time as the IRP is 00164 * completed. The session still exists until all references are dropped, but 00165 * before that happens a new session may become the current session (ie the IRP 00166 * was sent back down before the previous call stacks unwound). The tracking 00167 * data is held around until all sessions have decayed. 00168 * 00169 * Each session has an array of stack locations corresponding to those in use 00170 * by the IRP. These IOV_STACK_LOCATIONs are used to track "requests" within 00171 * the IRP, ie the passage of a major/minor/parameter set down the stack. 00172 * Of course multiple requests may exist in the same session/stack at once. 00173 * 00174 * Finally, surrogates. The IoVerifier may "switch" the IRP in use as it goes 00175 * down the stack. In this case the new IRP is usually allocated from the 00176 * special pool and freed as early as possible to catch bugs (people who touch 00177 * after completes). Each surrogate gets it's own IovRequestPacket, which is 00178 * linked to the previous surrogate or real irp in use prior to it. 00179 * 00180 * +--------------------+ +--------------------+ 00181 * | IOV_REQUEST_PACKET | | IOV_REQUEST_PACKET | 00182 * | (original irp) |<--------------------| (surrogate) | 00183 * | | | | 00184 * +--------------------+ +--------------------+ 00185 * || 00186 * v 00187 * +-------------------+ +-------------------------+ 00188 * | IOV_SESSION_DATA | | IOV_STACK_LOCATION[...] | 00189 * | (current session) |------>| (per IrpSp data) | 00190 * | | | | 00191 * +-------------------+ +-------------------------+ 00192 * 00193 * 00194 * The following flags change the behavior of IRPs memory allocation, 00195 * and code preemption in the OS. They should not neccessarily be on by 00196 * default, as they will seriously Heisenburg the system... 00197 * 00198 * ASSERTFLAG_TRACKIRPS - If this is not on, all of the below (excepting 00199 * ASSERTFLAG_MONITOR_ALLOCS) do not occur, and 00200 * IRPs are handled as in the free build (with 00201 * very few assertions). If on, all IRPs are 00202 * tracked, but not asserted on. 00203 * 00204 * ASSERTFLAG_MONITOR_ALLOCS - Calls to IoAllocateIrp go through the Special 00205 * pool. For every IRP so allocated a snapshot 00206 * of the thread stack at allocation time is 00207 * taken. 00208 * 00209 * ASSERTFLAG_POLICEIRPS - Monitors IRPs for basic/common mistakes. 00210 * Required for below flags to be used. 00211 * 00212 * ASSERTFLAG_MONITORMAJORS - Catches issues specific to various Major and 00213 * minor specific issues. 00214 * 00215 * ASSERTFLAG_SURROGATE - Tracked IRPs are automatically freed upon 00216 * completion. This is done with a surrogate 00217 * IRP allocated from the special pool that 00218 * replaces the original while travelling down 00219 * the stack. 00220 * 00221 * ASSERTFLAG_SMASH_SRBS - Some SCSI IRPs can't be surrogated unless 00222 * the SRB->OriginalRequest pointer is updated. 00223 * This is due to a busted SRB architecture. 00224 * Note that the technique used to identify an 00225 * SRB IRP is "fuzzy", and could in theory touch 00226 * an IRP it shouldn't have! 00227 * 00228 * ASSERTFLAG_FORCEPENDING - Tracked IRPs are automatically pended, but 00229 * are not held for any period of time. 00230 * 00231 * ASSERTFLAG_DEFERCOMPLETION - Tracked IRPs are completed later via timer. 00232 * ASSERTFLAG_FORCEPENDING set by inference. 00233 * 00234 * ASSERTFLAG_COMPLETEATDPC - completes every IRP at DPC, regardless of 00235 * major function. 00236 * 00237 * ASSERTFLAG_COMPLETEATPASSIVE - completes every IRP as Passive, regardless 00238 * of major function. ASSERTFLAG_FORCEPENDING 00239 * is set by inference. 00240 * 00241 * ASSERTFLAG_CONSUME_ALWAYS - Stack locations are forced to be copied (ie 00242 * any skips are undone). Note that we do not 00243 * consume if the IRP was just forwarded to 00244 * another stack. 00245 * 00246 * ASSERTFLAG_ROTATE_STATUS - Alternate successful status's are chosen where 00247 * appropriate as the IRP returns up the stack. 00248 * This catches many IRP forwarding bugs. 00249 * 00250 * ASSERTFLAG_SEEDSTACK - Seeds the stack so that uninitialized 00251 * variables are caught more easily... 00252 * 00253 */ 00254 00255 BOOLEAN 00256 FASTCALL 00257 IovpInitIrpTracking( 00258 IN ULONG Level, 00259 IN ULONG Flags 00260 ) 00261 /*++ 00262 00263 Description: 00264 00265 Initialize that which needs to be initialized. 00266 00267 Arguments: 00268 00269 Level - Level of testing to apply 00270 0 - No checks 00271 1 - Tracking with surrogate irp allocation 00272 2 - Monitors basic IRP mistakes 00273 3 - Monitors mistakes based on the irp major 00274 Surrogate IRPs used, status values rotated, 00275 and various other checks. 00276 4 - IRPs always completed at DPC. 00277 5 - All IRPs pended with completion defered via timer. 00278 6 - Any hacks turned off. 00279 00280 Return Value: 00281 00282 Returns TRUE iff settings were successfully applied. 00283 00284 --*/ 00285 { 00286 PVOID sectionHeaderHandle; 00287 ULONG newTrackingFlags; 00288 00289 PAGED_CODE(); 00290 00291 if (IovpIrpTrackingEnabled) { 00292 00293 IovpInitFlags = (Flags | (IovpInitFlags&IOVERIFIERINIT_EVERYTHING_TRACKED)); 00294 00295 } else { 00296 00297 IovpTrackingDataInit(); 00298 00299 IovpInitFlags = Flags; 00300 IovpIrpTrackingEnabled = TRUE; 00301 } 00302 00303 newTrackingFlags = 0; 00304 switch(Level) { 00305 00306 default: 00307 case 7: 00308 IovpHackFlags = 0; 00309 00310 case 6: 00311 newTrackingFlags |= ASSERTFLAG_FORCEPENDING | 00312 ASSERTFLAG_DEFERCOMPLETION; 00313 // 00314 // Fall through 00315 // 00316 00317 case 5: 00318 newTrackingFlags |= ASSERTFLAG_COMPLETEATDPC; 00319 // 00320 // Fall through 00321 // 00322 00323 case 4: 00324 newTrackingFlags |= ASSERTFLAG_SURROGATE | 00325 ASSERTFLAG_SMASH_SRBS | 00326 ASSERTFLAG_CONSUME_ALWAYS | 00327 ASSERTFLAG_ROTATE_STATUS | 00328 ASSERTFLAG_SEEDSTACK; 00329 // 00330 // Fall through 00331 // 00332 00333 case 3: 00334 newTrackingFlags |= ASSERTFLAG_MONITORMAJORS; 00335 // 00336 // Fall through 00337 // 00338 00339 case 2: 00340 newTrackingFlags |= ASSERTFLAG_POLICEIRPS; 00341 // 00342 // Fall through 00343 // 00344 00345 case 1: 00346 newTrackingFlags |= ASSERTFLAG_TRACKIRPS | 00347 ASSERTFLAG_MONITOR_ALLOCS; 00348 // 00349 // Fall through 00350 // 00351 00352 case 0: 00353 break; 00354 } 00355 00356 if ((Level == 0) && (Flags&IOVERIFIERINIT_NO_REINIT)) { 00357 00358 // 00359 // Preinit flags 00360 // 00361 newTrackingFlags = IovpTrackingFlags; 00362 } 00363 00364 if (IovpHackFlags == (ULONG) -1) { 00365 00366 IovpHackFlags = 00367 #ifdef HACKHACKS_ENABLED 00368 #ifdef HACKHACK_FOR_MUP 00369 HACKFLAG_FOR_MUP | 00370 #endif 00371 #ifdef HACKHACK_FOR_SCSIPORT 00372 HACKFLAG_FOR_SCSIPORT | 00373 #endif 00374 #ifdef HACKHACK_FOR_ACPI 00375 HACKFLAG_FOR_ACPI | 00376 #endif 00377 #ifdef HACKHACK_FOR_BOGUSIRPS 00378 HACKFLAG_FOR_BOGUSIRPS | 00379 #endif 00380 #endif // HACKHACKS_ENABLED 00381 0; 00382 } 00383 00384 if (!(IovpInitFlags & IOVERIFIERINIT_EVERYTHING_TRACKED)) { 00385 00386 // 00387 // These options aren't available unless we were marking IRPs since 00388 // boot. 00389 // 00390 newTrackingFlags &=~ ( 00391 ASSERTFLAG_MONITORMAJORS | 00392 ASSERTFLAG_SURROGATE | 00393 ASSERTFLAG_SMASH_SRBS | 00394 ASSERTFLAG_CONSUME_ALWAYS 00395 ); 00396 } 00397 00398 IovpTrackingFlags = newTrackingFlags; 00399 return TRUE; 00400 } 00401 00402 BOOLEAN 00403 FASTCALL 00404 IovpDoAssertIrps( 00405 VOID 00406 ) 00407 /*++ 00408 00409 Description: 00410 00411 This routine is called to ensure we can do IRP assertions. When called we 00412 lock the neccessary data structures and code if we haven't been initialized. 00413 00414 Arguments: None 00415 00416 Return Value: 00417 00418 TRUE if assertions can be done, FALSE otherwise (e.g., 00419 called at DPC time and we weren't already enabled) 00420 00421 --*/ 00422 { 00423 ASSERT(IovpTrackingFlags); 00424 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL) ; 00425 00426 // 00427 // If we aren't enabled, call the enabling function. This is harmless to 00428 // call repeatedly. We are not gaurenteed to be enabled when this function 00429 // returns (it can't block anyway, as paging might need to occur, and we'd 00430 // be sitting on file system IRPs). The IOVERIFIERINIT_EVERYTHING_TRACKED is 00431 // used to let us know we caught all IRPs, ie none are outstanding that 00432 // haven't been tracked/marked in some manner. We can set this here as 00433 // SPECIALIRP_MARK_NON_TRACKABLE() is called in the normal IofCallDriver 00434 // code paths if SPECIAL_IRP's are enabled. 00435 // 00436 if (!IovpIrpTrackingEnabled) { 00437 00438 #if 0 00439 IoVerifierInit( 00440 DRIVER_VERIFIER_IO_CHECKING, 00441 IOVERIFIERINIT_EVERYTHING_TRACKED | 00442 IOVERIFIERINIT_ASYNCHRONOUSINIT | 00443 IOVERIFIERINIT_NO_REINIT 00444 ); 00445 #endif 00446 } 00447 00448 // 00449 // If enabled, return so. 00450 // 00451 return IovpIrpTrackingEnabled; 00452 } 00453 00454 /* 00455 * The 13 routines listed below - 00456 * IovpCallDriver1 00457 * IovpCallDriver2 00458 * IovpCompleteRequest1 00459 * IovpCompleteRequest2 00460 * IovpCompleteRequest3 00461 * IovpCompleteRequest4 00462 * IovpCompleteRequest5 00463 * IovpCompleteRequest 00464 * IovpCancelIrp 00465 * IovpFreeIrp 00466 * IovpAllocateIrp1 00467 * IovpAllocateIrp2 00468 * IovpInitializeIrp 00469 * and their helper routine 00470 * IovpSwapSurrogateIrp 00471 * 00472 * - all hook into various parts IofCallDriver and IofCompleteRequest to 00473 * track the IRP through it's life and determine whether it has been handled 00474 * correctly. Some of them may even change internal variables in the hooked 00475 * function. Most dramatically, IovpCallDriver1 may build a 00476 * replacement Irp which will take the place of the one passed into 00477 * IoCallDriver. 00478 * 00479 * All of the below functions use a tracking structure called (reasonably 00480 * enough) IRP_TRACKING_DATA. This lasts the longer of the call stack 00481 * unwinding or the IRP completing. 00482 * 00483 */ 00484 00485 #define FAIL_CALLER_OF_IOFCALLDRIVER(msg, irpSp) \ 00486 WDM_FAIL_CALLER(msg, 3+2*((irpSp)->MajorFunction == IRP_MJ_POWER)) 00487 00488 #define FAIL_CALLER_OF_IOFCALLDRIVER2(msg, irpSp) \ 00489 WDM_FAIL_CALLER(msg, 4+2*((irpSp)->MajorFunction == IRP_MJ_POWER)) 00490 00491 VOID 00492 FASTCALL 00493 IovpCallDriver1( 00494 IN OUT PIRP *IrpPointer, 00495 IN PDEVICE_OBJECT DeviceObject, 00496 IN OUT PIOFCALLDRIVER_STACKDATA IofCallDriverStackData 00497 ) 00498 /*++ 00499 00500 Description: 00501 00502 This routine is called by IofCallDriver just before adjusting 00503 the IRP stack and calling the driver's dispatch routine. 00504 00505 Arguments: 00506 00507 IrpPointer - a pointer* to the IRP passed in to 00508 IofCallDriver. This routine may 00509 change the pointer if a surrogate 00510 IRP is allocated. 00511 00512 DeviceObject - Device object passed into IofCallDriver. 00513 00514 IofCallDriverStackData - Pointer to a local variable on 00515 IofCallDriver's stack to store data. 00516 The stored information will be picked 00517 up by IovpCallDriver2, and 00518 may be adjusted at other times. 00519 00520 00521 Return Value: 00522 00523 None. 00524 00525 --*/ 00526 { 00527 PIOV_REQUEST_PACKET iovPacket; 00528 PIOV_SESSION_DATA iovSessionData; 00529 PIOV_STACK_LOCATION iovCurrentStackLocation; 00530 PIRP irp, replacementIrp; 00531 PIO_STACK_LOCATION irpSp, irpLastSp; 00532 BOOLEAN isNewSession, isNewRequest, previouslyInUse, surrogateSpawned; 00533 ULONG isSameStack; 00534 ULONG locationsAdvanced, completeStyle; 00535 PDEVICE_OBJECT pdo, lowerDeviceObject; 00536 PDRIVER_OBJECT driverObject; 00537 PVOID dispatchRoutine; 00538 00539 irp = *IrpPointer; 00540 irpSp = IoGetNextIrpStackLocation( irp ); 00541 00542 // 00543 // Preinitialize the CallStackData. 00544 // 00545 RtlZeroMemory(IofCallDriverStackData, sizeof(IOFCALLDRIVER_STACKDATA)); 00546 00547 // 00548 // If we are going to die shortly, kindly say so. 00549 // 00550 if (DeviceObject == NULL) { 00551 00552 FAIL_CALLER_OF_IOFCALLDRIVER( 00553 (DCERROR_NULL_DEVOBJ_FORWARDED, DCPARAM_IRP, irp), 00554 irpSp 00555 ); 00556 } 00557 00558 // 00559 // The examined flag is set on any IRP that has come through 00560 // IofCallDriver. We use the flag to detect whether we have seen the IRP 00561 // before. 00562 // 00563 switch(irp->Flags&IRPFLAG_EXAMINE_MASK) { 00564 00565 case IRPFLAG_EXAMINE_NOT_TRACKED: 00566 00567 // 00568 // This packet is marked do not touch. So we ignore it. 00569 // 00570 iovPacket = NULL; 00571 break; 00572 00573 case IRPFLAG_EXAMINE_TRACKED: 00574 00575 // 00576 // This packet has been marked. We should find it. 00577 // 00578 iovPacket = IovpTrackingDataFindAndLock(irp); 00579 ASSERT(iovPacket != NULL); 00580 break; 00581 00582 case IRPFLAG_EXAMINE_UNMARKED: 00583 00584 iovPacket = IovpTrackingDataFindAndLock(irp); 00585 if (iovPacket) { 00586 00587 // 00588 // Was tracked but cache flag got wiped. Replace. 00589 // 00590 irp->Flags |= IRPFLAG_EXAMINE_TRACKED; 00591 00592 } else if (IovpTrackingFlags&ASSERTFLAG_TRACKIRPS) { 00593 00594 // 00595 // Create the packet 00596 // 00597 iovPacket = IovpTrackingDataCreateAndLock(irp); 00598 if (iovPacket) { 00599 00600 // 00601 // Mark it 00602 // 00603 irp->Flags |= IRPFLAG_EXAMINE_TRACKED; 00604 } else { 00605 00606 // 00607 // No memory, try to keep it out of the IRP assert though. 00608 // 00609 irp->Flags |= IRPFLAG_EXAMINE_NOT_TRACKED; 00610 } 00611 } else { 00612 00613 // 00614 // Do as told, don't track through IofCallDriver. 00615 // 00616 irp->Flags |= IRPFLAG_EXAMINE_NOT_TRACKED; 00617 } 00618 break; 00619 00620 default: 00621 ASSERT(0); 00622 break; 00623 } 00624 00625 if (iovPacket == NULL) { 00626 00627 // 00628 // Nothing to track, get out. 00629 // 00630 return; 00631 } 00632 00633 // 00634 // Find the current session. The session terminates when the final top-level 00635 // completion routine gets called. 00636 // 00637 iovSessionData = IovpTrackingDataGetCurrentSessionData(iovPacket); 00638 00639 if (iovSessionData) { 00640 00641 ASSERT(iovPacket->Flags&TRACKFLAG_ACTIVE); 00642 isNewSession = FALSE; 00643 00644 IovpSessionDataAdvance( 00645 DeviceObject, 00646 iovSessionData, // This param is optional. 00647 &iovPacket, 00648 &surrogateSpawned 00649 ); 00650 00651 } else if (!(iovPacket->Flags&TRACKFLAG_ACTIVE)){ 00652 00653 iovPacket->Flags |= TRACKFLAG_ACTIVE; 00654 isNewSession = TRUE; 00655 00656 iovSessionData = IovpSessionDataCreate( 00657 DeviceObject, 00658 &iovPacket, 00659 &surrogateSpawned 00660 ); 00661 00662 } else { 00663 00664 // 00665 // Might hit this path under low memory, or we are tracking allocations 00666 // but not the IRP sessions themselves. 00667 // 00668 } 00669 00670 // 00671 // Let IovpCallDriver2 know what it's tracking... 00672 // 00673 IofCallDriverStackData->IovSessionData = iovSessionData; 00674 00675 if (iovSessionData == NULL) { 00676 00677 IovpTrackingDataReleaseLock(iovPacket) ; 00678 return; 00679 } 00680 00681 if (surrogateSpawned) { 00682 00683 // 00684 // iovPacket was changed to cover the surrogate IRP. Update our own 00685 // local variable and IofCallDriver's local variable appropriately. 00686 // 00687 irp = iovPacket->TrackedIrp; 00688 irpSp = IoGetNextIrpStackLocation(irp); 00689 *IrpPointer = irp; 00690 } 00691 00692 if (isNewSession) { 00693 00694 IovpTrackingDataReference(iovPacket, IOVREFTYPE_POINTER); 00695 IovpSessionDataReference(iovSessionData); 00696 } 00697 00698 if (iovPacket->AssertFlags&ASSERTFLAG_POLICEIRPS) { 00699 00700 // 00701 // If someone has given us an IRP with a cancel routine, beat them. Drivers 00702 // set cancel routines when they are going to be pending IRPs *themselves* 00703 // and should remove them before passing the IRP below. This is also true 00704 // as the driver will *not* call your cancel routine if he writes in his 00705 // own (which it may). Nor is the lower driver expected to put yours back 00706 // either... 00707 // 00708 if (irp->CancelRoutine) { 00709 00710 FAIL_CALLER_OF_IOFCALLDRIVER( 00711 (DCERROR_CANCELROUTINE_FORWARDED, DCPARAM_IRP, irp), 00712 irpSp 00713 ); 00714 00715 irp->CancelRoutine = NULL; 00716 } 00717 } 00718 00719 // 00720 // Now do any checking that requires tracking data. 00721 // 00722 if (iovPacket->Flags&TRACKFLAG_QUEUED_INTERNALLY) { 00723 00724 // 00725 // We internally queue irps to catch bugs. When we are doing this, we 00726 // force the stack returned status to STATUS_PENDING, and we queue the 00727 // irp and release it on a timer. We also may make the IRP non-touchable. 00728 // This particular caller is trying to forward an IRP he doesn't own, 00729 // and we didn't actually end up with an untouchable irp. 00730 // 00731 FAIL_CALLER_OF_IOFCALLDRIVER( 00732 (DCERROR_QUEUED_IRP_FORWARDED, DCPARAM_IRP, irp), 00733 irpSp 00734 ); 00735 } 00736 00737 // 00738 // Figure out how many stack locations we've moved up since we've last seen 00739 // this IRP, and determine if the stack locations were copied appropriately. 00740 // We also need to see exactly how the IRP was forwarded (down the stack, 00741 // to another stack, straight to the PDO, etc). 00742 // 00743 // ADRIAO BUGBUG #07 05/11/98 - The only way to truely detect this is to 00744 // attach a filter at every layer in stack. 00745 // This is left as an exercise for later. 00746 // 00747 IovpExamineDevObjForwarding( 00748 DeviceObject, 00749 iovSessionData->DeviceLastCalled, 00750 &iovSessionData->ForwardMethod 00751 ) ; 00752 00753 IovpExamineIrpStackForwarding( 00754 iovPacket, 00755 isNewSession, 00756 iovSessionData->ForwardMethod, 00757 DeviceObject, 00758 irp, 00759 &irpSp, 00760 &irpLastSp, 00761 &locationsAdvanced 00762 ); 00763 00764 TRACKIRP_DBGPRINT(( 00765 " CD1: Current, Last = (%x, %x)\n", 00766 irp->CurrentLocation, 00767 iovPacket->LastLocation 00768 ), 3) ; 00769 00770 // 00771 // Figure out whether this is a new request or not, and record a 00772 // pointer in this slot to the requests originating slot as appropriate. 00773 // 00774 isNewRequest = IovpAssertIsNewRequest(irpLastSp, irpSp); 00775 00776 // 00777 // Record information in our private stack locations and 00778 // write that back into the "stack" data itself... 00779 // 00780 previouslyInUse = IovpAdvanceStackDownwards( 00781 iovSessionData->StackData, 00782 irp->CurrentLocation, 00783 irpSp, 00784 irpLastSp, 00785 locationsAdvanced, 00786 isNewRequest, 00787 TRUE, 00788 &iovCurrentStackLocation 00789 ); 00790 00791 ASSERT(iovCurrentStackLocation); 00792 00793 if (previouslyInUse) { 00794 00795 ASSERT(!isNewRequest); 00796 ASSERT(!isNewSession); 00797 KeQuerySystemTime(&iovCurrentStackLocation->PerfDispatchStart) ; 00798 00799 } else { 00800 00801 IofCallDriverStackData->Flags = CALLFLAG_TOPMOST_IN_SLOT ; 00802 InitializeListHead(&IofCallDriverStackData->SharedLocationList) ; 00803 00804 KeQuerySystemTime(&iovCurrentStackLocation->PerfDispatchStart) ; 00805 KeQuerySystemTime(&iovCurrentStackLocation->PerfStackLocationStart) ; 00806 00807 // 00808 // Record the first thread this IRP slot was dispatched to. 00809 // 00810 iovCurrentStackLocation->ThreadDispatchedTo = PsGetCurrentThread(); 00811 if (isNewRequest) { 00812 00813 iovCurrentStackLocation->InitialStatusBlock = irp->IoStatus; 00814 iovCurrentStackLocation->LastStatusBlock = irp->IoStatus; 00815 if (isNewSession) { 00816 00817 iovCurrentStackLocation->Flags |= STACKFLAG_FIRST_REQUEST; 00818 } 00819 } 00820 } 00821 00822 // 00823 // Record whether this is the last device object for this IRP... 00824 // PDO's have devnodes filled out, so look for that field. 00825 // Actually, we can't quite do that trick as during Bus 00826 // enumeration a bus filter might be sending down Irps before 00827 // the OS has ever seen the node. So we assume a devobj is a 00828 // PDO if he has never attached to anyone. 00829 // 00830 lowerDeviceObject = IovpGetDeviceAttachedTo(DeviceObject) ; 00831 if (lowerDeviceObject) { 00832 ObDereferenceObject(lowerDeviceObject) ; 00833 } else { 00834 iovCurrentStackLocation->Flags |= STACKFLAG_REACHED_PDO ; 00835 } 00836 00837 // 00838 // Record who is getting this IRP (we will blame any mistakes on him 00839 // if this request gets completed.) Note that we've already asserted 00840 // DeviceObject is non-NULL... 00841 // 00842 driverObject = DeviceObject->DriverObject ; 00843 dispatchRoutine = driverObject->MajorFunction[irpSp->MajorFunction] ; 00844 iovCurrentStackLocation->LastDispatch = dispatchRoutine ; 00845 00846 // 00847 // Uncomplete the request if we are heading back down with it... 00848 // 00849 iovCurrentStackLocation->Flags &=~ STACKFLAG_REQUEST_COMPLETED ; 00850 00851 // 00852 // This IofCallDriver2 dude will need to be told what his status should 00853 // be later. Add him to the linked list of addresses to scribble away 00854 // stati when the appropriate level is completed. 00855 // 00856 InsertHeadList( 00857 &iovCurrentStackLocation->CallStackData, 00858 &IofCallDriverStackData->SharedLocationList 00859 ) ; 00860 00861 // 00862 // More IofCallDriver2 stuff, tell him the stack location. 00863 // 00864 IofCallDriverStackData->IovStackLocation = iovCurrentStackLocation ; 00865 00866 // If it's a remove IRP, mark everyone appropriately 00867 if ((irpSp->MajorFunction == IRP_MJ_PNP)&& 00868 (irpSp->MinorFunction == IRP_MN_REMOVE_DEVICE)) { 00869 00870 IofCallDriverStackData->Flags |= CALLFLAG_IS_REMOVE_IRP ; 00871 00872 pdo = IovpGetLowestDevice(DeviceObject) ; 00873 ASSERT(pdo) ; 00874 IofCallDriverStackData->RemovePdo = pdo ; 00875 ObDereferenceObject(pdo) ; 00876 if (IovpIsInFdoStack(DeviceObject) && 00877 (!(DeviceObject->DeviceObjectExtension->ExtensionFlags&DOE_RAW_FDO))) { 00878 IofCallDriverStackData->Flags |= CALLFLAG_REMOVING_FDO_STACK_DO ; 00879 } 00880 } 00881 00882 if ((iovPacket->AssertFlags&ASSERTFLAG_POLICEIRPS) && 00883 (iovPacket->AssertFlags&ASSERTFLAG_MONITORMAJORS)) { 00884 00885 // 00886 // Do IRP-major specific assertions as appropriate 00887 // 00888 if (isNewSession) { 00889 00890 IovpAssertNewIrps(iovPacket, irpSp, iovCurrentStackLocation) ; 00891 } 00892 00893 if (isNewRequest) { 00894 00895 IovpAssertNewRequest(iovPacket, DeviceObject, irpLastSp, irpSp, iovCurrentStackLocation) ; 00896 } 00897 00898 IovpAssertIrpStackDownward(iovPacket, DeviceObject, irpLastSp, irpSp, iovCurrentStackLocation) ; 00899 } 00900 00901 // 00902 // Update our fields 00903 // 00904 iovSessionData->DeviceLastCalled = DeviceObject ; 00905 iovPacket->LastLocation = irp->CurrentLocation ; 00906 iovCurrentStackLocation->RequestsFirstStackLocation->LastStatusBlock = irp->IoStatus; 00907 00908 // 00909 // Dope the next stack location so we can detect usage of 00910 // IoCopyCurrentIrpStackLocationToNext or IoSetCompletionRoutine. 00911 // 00912 if (irp->CurrentLocation>1) { 00913 IoSetNextIrpStackLocation( irp ) ; 00914 irpSp = IoGetNextIrpStackLocation( irp ); 00915 irpSp->Control |= SL_NOTCOPIED ; 00916 IoSkipCurrentIrpStackLocation( irp ) ; 00917 } 00918 00919 // 00920 // Randomly set the cancel flag on a percentage of forwarded IRPs. Many 00921 // drivers queue first and after dequeue assume the cancel routine they 00922 // set must have been cleared if Cancel = TRUE. They don't handle the case 00923 // were the Irp was cancelled in flight. 00924 // 00925 // ADRIAO BUGBUG 07/16/1999 - 00926 // Do better spontaneous cancel logic later. 00927 // 00928 if ((IovpInitFlags & IOVERIFIERINIT_RANDOMLY_CANCEL_IRPS) && 00929 (!(irp->Flags & IRP_PAGING_IO))) { 00930 00931 if (((++IovpCancelCount) % 4000) == 0) { 00932 00933 irp->Cancel = TRUE; 00934 } 00935 } 00936 00937 // 00938 // Assert LastLocation is consistent with an IRP that may be completed. 00939 // 00940 ASSERT(iovSessionData->StackData[iovPacket->LastLocation-1].InUse) ; 00941 00942 IovpSessionDataReference(iovSessionData); 00943 IovpTrackingDataReleaseLock(iovPacket) ; 00944 } 00945 00946 VOID 00947 FASTCALL 00948 IovpCallDriver2( 00949 IN PIRP Irp, 00950 IN PDEVICE_OBJECT DeviceObject, 00951 IN PVOID DispatchRoutine, 00952 IN OUT NTSTATUS *FinalStatus, 00953 IN PIOFCALLDRIVER_STACKDATA IofCallDriverStackData 00954 ) 00955 /*++ 00956 00957 Description: 00958 00959 This routine is called by IofCallDriver just after the driver's dispatch 00960 routine has been called. The IRP may not be touchable at this time. 00961 00962 Arguments: 00963 00964 Irp - A pointer to the IRP passed into IofCallDriver. 00965 The IRP may not be touchable right now. 00966 00967 DispatchRoutine - Dispatch routine that was called by IofCallDriver. 00968 00969 FinalStatus - A pointer to the status returned by the dispatch 00970 routine. This may be changed if all IRPs are being 00971 forced "pending". 00972 00973 IofCallDriverStackData - Pointer to a local variable on IofCallDriver's 00974 stack to retreive data stored by 00975 IovpCallDriver1. 00976 00977 Return Value: 00978 00979 None. 00980 00981 --*/ 00982 { 00983 NTSTATUS status, lastStatus; 00984 PIOV_REQUEST_PACKET iovPacket; 00985 PIOV_SESSION_DATA iovSessionData; 00986 ULONG refCount; 00987 PIOV_STACK_LOCATION iovCurrentStackLocation; 00988 BOOLEAN mustDetachAndDelete; 00989 PDEVICE_NODE devNode; 00990 PDEVICE_OBJECT lowerDevObj; 00991 00992 iovSessionData = IofCallDriverStackData->IovSessionData; 00993 if (iovSessionData == NULL) { 00994 00995 return; 00996 } 00997 00998 iovPacket = iovSessionData->IovRequestPacket; 00999 ASSERT(iovPacket); 01000 IovpTrackingDataAcquireLock(iovPacket); 01001 01002 // 01003 // ADRIAO BUGBUG 08/10/1999 - 01004 // This needs to be reenabled once the DNF_ flags are used in a 01005 // consistant manner. 01006 // 01007 #if 0 01008 if (iovSessionData->AssertFlags&ASSERTFLAG_POLICEIRPS) { 01009 01010 if (IofCallDriverStackData->Flags&CALLFLAG_IS_REMOVE_IRP) { 01011 01012 if ((*FinalStatus != STATUS_PENDING) && 01013 (iovCurrentStackLocation->ThreadDispatchedTo == PsGetCurrentThread())) { 01014 01015 lowerDevObj = IovpGetDeviceAttachedTo(DeviceObject) ; 01016 01017 // 01018 // We can look at this because the caller has committed to this being 01019 // completed now, and we are on the original thread. 01020 // 01021 // N.B. This works because all the objects in the stack have been 01022 // referenced during a remove. If we decide to only reference the 01023 // top object, this logic would break... 01024 // 01025 if (IofCallDriverStackData->Flags&CALLFLAG_REMOVING_FDO_STACK_DO) { 01026 01027 // 01028 // FDO, Upper, & Lower filters *must* go. Note that lowerDevObj 01029 // should be null as we should have detached. 01030 // 01031 mustDetachAndDelete = TRUE ; 01032 01033 } else { 01034 01035 devNode = IofCallDriverStackData->RemovePdo->DeviceObjectExtension->DeviceNode ; 01036 ASSERT(devNode) ; 01037 01038 if (devNode->Flags & DNF_DEVICE_GONE) { 01039 01040 // 01041 // It's been reported as missing. It *must* go! 01042 // 01043 mustDetachAndDelete = TRUE ; 01044 01045 } else { 01046 01047 // 01048 // It must stay! 01049 // 01050 mustDetachAndDelete = FALSE ; 01051 } 01052 } 01053 01054 if (mustDetachAndDelete) { 01055 01056 // 01057 // IoDetachDevice and IoDeleteDevice should have been called. 01058 // First verify IoDetachDevice... 01059 // 01060 if (lowerDevObj) { 01061 01062 WDM_FAIL_ROUTINE(( 01063 DCERROR_SHOULDVE_DETACHED, 01064 DCPARAM_IRP + DCPARAM_ROUTINE + DCPARAM_DEVOBJ, 01065 iovSessionData->BestVisibleIrp, 01066 DispatchRoutine, 01067 DeviceObject 01068 )); 01069 } 01070 01071 // 01072 // Now verify IoDeleteDevice 01073 // 01074 if (!(DeviceObject->DeviceObjectExtension->ExtensionFlags&DOE_DELETE_PENDING)) { 01075 01076 WDM_FAIL_ROUTINE(( 01077 DCERROR_SHOULDVE_DELETED, 01078 DCPARAM_IRP + DCPARAM_ROUTINE + DCPARAM_DEVOBJ, 01079 iovSessionData->BestVisibleIrp, 01080 DispatchRoutine, 01081 DeviceObject 01082 )); 01083 } 01084 01085 } else { 01086 01087 // 01088 // Did we mistakenly leave? Verify we aren't a bus filter that 01089 // has been fooled. In that case, no checking can be done... 01090 // 01091 ASSERT(!(IofCallDriverStackData->Flags&CALLFLAG_REMOVING_FDO_STACK_DO)) ; 01092 01093 if (DeviceObject == IofCallDriverStackData->RemovePdo) { 01094 01095 // 01096 // Check PDO's - did we mistakenly delete ourselves? 01097 // 01098 if (DeviceObject->DeviceObjectExtension->ExtensionFlags&DOE_DELETE_PENDING) { 01099 01100 WDM_FAIL_ROUTINE(( 01101 DCERROR_DELETED_PRESENT_PDO, 01102 DCPARAM_IRP + DCPARAM_ROUTINE + DCPARAM_DEVOBJ, 01103 iovSessionData->BestVisibleIrp, 01104 DispatchRoutine, 01105 DeviceObject 01106 )); 01107 } 01108 01109 } else if (!(IofCallDriverStackData->RemovePdo->DeviceObjectExtension->ExtensionFlags&DOE_DELETE_PENDING)) { 01110 01111 // 01112 // Check bus filters. Bus filters better not have detached 01113 // or deleted themselves, as the PDO is still present! 01114 // 01115 if (lowerDevObj == NULL) { 01116 01117 // 01118 // Oops, it detached. Baad bus filter... 01119 // 01120 WDM_FAIL_ROUTINE(( 01121 DCERROR_BUS_FILTER_ERRONEOUSLY_DETACHED, 01122 DCPARAM_IRP + DCPARAM_ROUTINE + DCPARAM_DEVOBJ, 01123 iovSessionData->BestVisibleIrp, 01124 DispatchRoutine, 01125 DeviceObject 01126 )); 01127 } 01128 01129 if (DeviceObject->DeviceObjectExtension->ExtensionFlags&DOE_DELETE_PENDING) { 01130 01131 // 01132 // It deleted itself. Also very bad... 01133 // 01134 WDM_FAIL_ROUTINE(( 01135 DCERROR_BUS_FILTER_ERRONEOUSLY_DELETED, 01136 DCPARAM_IRP + DCPARAM_ROUTINE + DCPARAM_DEVOBJ, 01137 iovSessionData->BestVisibleIrp, 01138 DispatchRoutine, 01139 DeviceObject 01140 )); 01141 } 01142 } 01143 } 01144 01145 if (lowerDevObj) { 01146 01147 ObDereferenceObject(lowerDevObj) ; 01148 } 01149 } 01150 } 01151 } 01152 #endif 01153 if (IofCallDriverStackData->Flags&CALLFLAG_COMPLETED) { 01154 01155 TRACKIRP_DBGPRINT(( 01156 " Verifying status in CD2\n" 01157 ),2) ; 01158 01159 if ((*FinalStatus != IofCallDriverStackData->ExpectedStatus)&& 01160 (*FinalStatus != STATUS_PENDING)) { 01161 01162 if ((iovSessionData->AssertFlags&ASSERTFLAG_POLICEIRPS) && 01163 (!(iovSessionData->SessionFlags&SESSIONFLAG_UNWOUND_INCONSISTANT))) { 01164 01165 01166 // 01167 // The completion routine and the return value don't match. Hey! 01168 // 01169 WDM_FAIL_ROUTINE(( 01170 DCERROR_INCONSISTANT_STATUS, 01171 DCPARAM_IRP + DCPARAM_ROUTINE + DCPARAM_STATUS*2, 01172 iovSessionData->BestVisibleIrp, 01173 DispatchRoutine, 01174 IofCallDriverStackData->ExpectedStatus, 01175 *FinalStatus 01176 )); 01177 } 01178 01179 iovSessionData->SessionFlags |= SESSIONFLAG_UNWOUND_INCONSISTANT; 01180 01181 } else if (*FinalStatus == 0xFFFFFFFF) { 01182 01183 if (iovSessionData->AssertFlags&ASSERTFLAG_POLICEIRPS) { 01184 01185 01186 // 01187 // This status value is illegal. If we see it, we probably have 01188 // an uninitialized variable... 01189 // 01190 WDM_FAIL_ROUTINE(( 01191 DCERROR_UNINITIALIZED_STATUS, 01192 DCPARAM_IRP + DCPARAM_ROUTINE, 01193 iovSessionData->BestVisibleIrp, 01194 DispatchRoutine 01195 )); 01196 } 01197 } 01198 01199 // 01200 // We do not need to remove ourselves from the list because 01201 // we will not be completed twice (InUse is NULL makes sure). 01202 // 01203 01204 } else { 01205 01206 // 01207 // OK, we haven't completed yet. Status better 01208 // be pending... 01209 // 01210 TRACKIRP_DBGPRINT(( 01211 " Verifying status is STATUS_PENDING in CR2\n" 01212 ), 2) ; 01213 01214 if (*FinalStatus != STATUS_PENDING) { 01215 01216 if ((iovSessionData->AssertFlags&ASSERTFLAG_POLICEIRPS) && 01217 (!(iovPacket->Flags&TRACKFLAG_UNWOUND_BADLY))) { 01218 01219 // 01220 // We got control before this slot was completed. This is 01221 // legal as long as STATUS_PENDING was returned (it was not), 01222 // so it's bug time. Note that the IRP may not be safe to touch. 01223 // 01224 WDM_FAIL_ROUTINE(( 01225 DCERROR_IRP_RETURNED_WITHOUT_COMPLETION, 01226 DCPARAM_IRP + DCPARAM_ROUTINE, 01227 iovSessionData->BestVisibleIrp, 01228 DispatchRoutine 01229 )); 01230 } 01231 01232 iovPacket->Flags |= TRACKFLAG_UNWOUND_BADLY; 01233 } 01234 01235 iovCurrentStackLocation = (PIOV_STACK_LOCATION)(IofCallDriverStackData->IovStackLocation) ; 01236 ASSERT(iovCurrentStackLocation->InUse) ; 01237 ASSERT(!IsListEmpty(&iovCurrentStackLocation->CallStackData)) ; 01238 01239 // 01240 // We now extricate ourselves from the list. 01241 // 01242 RemoveEntryList(&IofCallDriverStackData->SharedLocationList) ; 01243 } 01244 01245 if ((IofCallDriverStackData->Flags&CALLFLAG_OVERRIDE_STATUS)&& 01246 (*FinalStatus != STATUS_PENDING)) { 01247 01248 *FinalStatus = IofCallDriverStackData->NewStatus ; 01249 } 01250 01251 if ((iovSessionData->AssertFlags&ASSERTFLAG_FORCEPENDING) && 01252 (!(IofCallDriverStackData->Flags&CALLFLAG_IS_REMOVE_IRP))) { 01253 01254 // 01255 // We also have the option of causing trouble by making every Irp 01256 // look as if were pending. 01257 // 01258 *FinalStatus = STATUS_PENDING ; 01259 } 01260 01261 IovpSessionDataDereference(iovSessionData); 01262 IovpTrackingDataReleaseLock(iovPacket); 01263 } 01264 01265 VOID 01266 FASTCALL 01267 IovpCompleteRequest1( 01268 IN PIRP Irp, 01269 IN CCHAR PriorityBoost, 01270 IN OUT PIOFCOMPLETEREQUEST_STACKDATA CompletionPacket 01271 ) 01272 /*++ 01273 01274 Description 01275 01276 This routine is called the moment IofCompleteRequest is invoked, and 01277 before any completion routines get called and before the IRP stack 01278 is adjusted in any way. 01279 01280 Arguments: 01281 01282 Irp - A pointer to the IRP passed into 01283 IofCompleteRequest. 01284 01285 PriorityBoost - The priority boost passed into 01286 IofCompleteRequest. 01287 01288 CompletionPacket - A pointer to a local variable on the stack of 01289 IofCompleteRequest. The information stored in 01290 this local variable will be picked up by 01291 IovpCompleteRequest2-5. 01292 Return Value: 01293 01294 None. 01295 --*/ 01296 { 01297 PIOV_REQUEST_PACKET iovPacket; 01298 PIOV_SESSION_DATA iovSessionData; 01299 BOOLEAN slotIsInUse; 01300 PIOV_STACK_LOCATION iovCurrentStackLocation; 01301 ULONG locationsAdvanced; 01302 PIO_STACK_LOCATION irpSp; 01303 PDEVICE_OBJECT lowerDevobj; 01304 01305 iovPacket = IovpTrackingDataFindAndLock(Irp); 01306 01307 CompletionPacket->RaisedCount = 0; 01308 01309 if (iovPacket == NULL) { 01310 01311 CompletionPacket->IovSessionData = NULL; 01312 return; 01313 } 01314 01315 iovSessionData = IovpTrackingDataGetCurrentSessionData(iovPacket); 01316 01317 CompletionPacket->IovSessionData = iovSessionData; 01318 CompletionPacket->IovRequestPacket = iovPacket; 01319 01320 if (iovSessionData == NULL) { 01321 01322 // 01323 // We just got a look at the allocation, not the session itself. 01324 // This can happen if a driver calls IofCompleteRequest on an internally 01325 // generated IRP before calling IofCallDriver. NPFS does this. 01326 // 01327 IovpTrackingDataReleaseLock(iovPacket); 01328 return; 01329 } 01330 01331 TRACKIRP_DBGPRINT(( 01332 " CR1: Current, Last = (%x, %x)\n", 01333 Irp->CurrentLocation, iovPacket->LastLocation 01334 ), 3); 01335 01336 irpSp = IoGetCurrentIrpStackLocation(Irp); 01337 01338 if (iovPacket->Flags&TRACKFLAG_QUEUED_INTERNALLY) { 01339 01340 // 01341 // We are probably going to die now. Anyway, it was a good life... 01342 // 01343 WDM_FAIL_CALLER3((DCERROR_QUEUED_IRP_COMPLETED, DCPARAM_IRP, Irp)); 01344 } 01345 01346 // 01347 // This would be *very* bad - someone is completing an IRP that is 01348 // currently in progress... 01349 // 01350 ASSERT(!(Irp->Flags&IRP_DIAG_HAS_SURROGATE)); 01351 01352 // 01353 // Hmmm, someone is completing an IRP that IoCallDriver never called. These 01354 // is possible but rather gross, so we warn. 01355 // 01356 if (Irp->CurrentLocation == ((CCHAR) Irp->StackCount + 1)) { 01357 01358 WDM_CHASTISE_CALLER3((DCERROR_UNFORWARDED_IRP_COMPLETED, DCPARAM_IRP, Irp)); 01359 } 01360 01361 // 01362 // Record priority for our own later recompletion... 01363 // 01364 iovPacket->PriorityBoost = PriorityBoost; 01365 01366 // 01367 // We have the option of causing trouble by making every Irp look 01368 // as if were pending. It is best to do it here, as this also takes 01369 // care of anybody who has synchronized the IRP and thus does not need 01370 // to mark it pending in his completion routine. 01371 // 01372 if (iovSessionData->AssertFlags&ASSERTFLAG_FORCEPENDING) { 01373 01374 IoMarkIrpPending(Irp); 01375 } 01376 01377 // 01378 // Do this so that if the IRP comes down again, it looks like a new one 01379 // to the "forward them correctly" code. 01380 // 01381 iovSessionData->DeviceLastCalled = NULL; 01382 01383 locationsAdvanced = iovPacket->LastLocation - Irp->CurrentLocation; 01384 01385 // 01386 // Remember this so that we can detect the case where someone is completing 01387 // to themselves. 01388 // 01389 CompletionPacket->LocationsAdvanced = locationsAdvanced; 01390 01391 // 01392 // If this failed, somebody skipped then completed. 01393 // 01394 ASSERT(locationsAdvanced); 01395 01396 // 01397 // If somebody called IoSetNextIrpStackLocation, and then completed, 01398 // update our internal stack locations (slots) as appropriate. 01399 // 01400 slotIsInUse = IovpAdvanceStackDownwards( 01401 iovSessionData->StackData, 01402 Irp->CurrentLocation, 01403 irpSp, 01404 irpSp + locationsAdvanced, 01405 locationsAdvanced, 01406 FALSE, 01407 FALSE, 01408 &iovCurrentStackLocation 01409 ); 01410 01411 IovpTrackingDataReleaseLock(iovPacket); 01412 } 01413 01414 VOID 01415 FASTCALL 01416 IovpCompleteRequest2( 01417 IN PIRP Irp, 01418 IN OUT PIOFCOMPLETEREQUEST_STACKDATA CompletionPacket 01419 ) 01420 /*++ 01421 01422 Description: 01423 01424 This routine is called for each stack location that might have a completion 01425 routine. 01426 01427 Arguments: 01428 01429 Irp - A pointer to the IRP passed into 01430 IofCompleteRequest. 01431 01432 CompletionPacket - A pointer to a local variable on the stack of 01433 IofCompleteRequest. The information stored in 01434 this local variable will be picked up by 01435 IovpCompleteRequest4&5. 01436 01437 Return Value: 01438 01439 None. 01440 --*/ 01441 { 01442 PIOV_REQUEST_PACKET iovPacket; 01443 PIOV_SESSION_DATA iovSessionData; 01444 BOOLEAN raiseToDPC, newlyCompleted, requestFinalized ; 01445 KIRQL oldIrql ; 01446 PIOV_STACK_LOCATION iovCurrentStackLocation, requestsFirstStackLocation ; 01447 NTSTATUS status, entranceStatus ; 01448 PIOFCALLDRIVER_STACKDATA IofCallDriverStackData ; 01449 PIO_STACK_LOCATION irpSp ; 01450 ULONG refAction ; 01451 PLIST_ENTRY listEntry ; 01452 01453 iovSessionData = CompletionPacket->IovSessionData; 01454 if (iovSessionData == NULL) { 01455 01456 return; 01457 } 01458 01459 iovPacket = CompletionPacket->IovRequestPacket; 01460 ASSERT(iovPacket); 01461 IovpTrackingDataAcquireLock(iovPacket); 01462 01463 ASSERT(iovSessionData == IovpTrackingDataGetCurrentSessionData(iovPacket)); 01464 01465 ASSERT(!Irp->CancelRoutine) ; 01466 01467 status = Irp->IoStatus.Status ; 01468 01469 TRACKIRP_DBGPRINT(( 01470 " CR2: Current, Last = (%x, %x)\n", 01471 Irp->CurrentLocation, iovPacket->LastLocation 01472 ), 3) ; 01473 01474 iovCurrentStackLocation = iovSessionData->StackData + Irp->CurrentLocation -1 ; 01475 TRACKIRP_DBGPRINT(( 01476 " Smacking %lx in CR2\n", 01477 iovCurrentStackLocation-iovSessionData->StackData 01478 ), 2) ; 01479 01480 if (Irp->CurrentLocation <= iovPacket->TopStackLocation) { 01481 01482 // 01483 // Might this be false if the completion routine is to an 01484 // internal stack loc as set up by IoSetNextIrpStackLocation? 01485 // 01486 ASSERT(iovCurrentStackLocation->InUse) ; 01487 01488 // 01489 // Determine if a request was newly completed. Note that 01490 // several requests may exist within an IRP if it is being 01491 // "reused". For instance, in response to a IRP_MJ_READ, a 01492 // driver might convert it into a IRP_MJ_PNP request for the 01493 // rest of the stack. The two are treated as seperate requests. 01494 // 01495 requestsFirstStackLocation = iovCurrentStackLocation->RequestsFirstStackLocation ; 01496 TRACKIRP_DBGPRINT(( 01497 " CR2: original request for %lx is %lx\n", 01498 iovCurrentStackLocation-iovSessionData->StackData, 01499 requestsFirstStackLocation-iovSessionData->StackData 01500 ), 3) ; 01501 01502 ASSERT(requestsFirstStackLocation) ; 01503 if (requestsFirstStackLocation->Flags&STACKFLAG_REQUEST_COMPLETED) { 01504 newlyCompleted = FALSE ; 01505 } else { 01506 requestsFirstStackLocation->Flags|=STACKFLAG_REQUEST_COMPLETED ; 01507 newlyCompleted = TRUE ; 01508 TRACKIRP_DBGPRINT(( 01509 " CR2: Request %lx newly completed by %lx\n", 01510 requestsFirstStackLocation-iovSessionData->StackData, 01511 iovCurrentStackLocation-iovSessionData->StackData 01512 ), 3) ; 01513 } 01514 requestFinalized = (iovCurrentStackLocation == requestsFirstStackLocation) ; 01515 if (requestFinalized) { 01516 01517 TRACKIRP_DBGPRINT(( 01518 " CR2: Request %lx finalized\n", 01519 iovCurrentStackLocation-iovSessionData->StackData 01520 ), 3) ; 01521 } 01522 01523 // 01524 // OK - 01525 // If we haven't unwound yet, then IofCallDriverStackData will 01526 // start out non-NULL, in which case we will scribble away the final 01527 // completion routine status to everybody asking (could be multiple 01528 // if they IoSkip'd). 01529 // On the other hand, everybody might have unwound, in which 01530 // case IofCallDriver(...) will start out NULL, and we will already have 01531 // asserted if STATUS_PENDING wasn't returned much much earlier... 01532 // Finally, this slot may not have been "prepared" if an 01533 // internal stack location called IoSetNextIrpStackLocation, thus 01534 // consuming a stack location. In this case, IofCallDriverStackData 01535 // will come from a zero'd slot, and we will do nothing, which is 01536 // also fine. 01537 // 01538 irpSp = IoGetNextIrpStackLocation(Irp) ; 01539 01540 if ((iovPacket->AssertFlags&ASSERTFLAG_POLICEIRPS) && 01541 (iovPacket->AssertFlags&ASSERTFLAG_MONITORMAJORS)) { 01542 01543 IovpAssertIrpStackUpward( 01544 iovPacket, 01545 irpSp, 01546 iovCurrentStackLocation, 01547 newlyCompleted, 01548 requestFinalized 01549 ); 01550 } 01551 01552 entranceStatus = status ; 01553 01554 while(!IsListEmpty(&iovCurrentStackLocation->CallStackData)) { 01555 01556 // 01557 // Pop off the list head. 01558 // 01559 listEntry = RemoveHeadList(&iovCurrentStackLocation->CallStackData) ; 01560 IofCallDriverStackData = CONTAINING_RECORD( 01561 listEntry, 01562 IOFCALLDRIVER_STACKDATA, 01563 SharedLocationList) ; 01564 01565 ASSERT(!(IofCallDriverStackData->Flags&CALLFLAG_COMPLETED)) ; 01566 01567 IofCallDriverStackData->Flags |= CALLFLAG_COMPLETED ; 01568 IofCallDriverStackData->ExpectedStatus = status ; 01569 01570 if ((iovSessionData->AssertFlags&ASSERTFLAG_ROTATE_STATUS)&& 01571 IovpAssertDoAdvanceStatus(irpSp, entranceStatus, &status)) { 01572 01573 // 01574 // Purposely munge the returned status for everyone at this 01575 // layer to flush more bugs. We are specifically trolling for 01576 // this buggy sequence: 01577 // Irp->IoStatus.Status = STATUS_SUCCESS ; 01578 // IoSkipCurrentIrpStackLocation(Irp); 01579 // IoCallDriver(DeviceBelow, Irp) ; 01580 // return STATUS_SUCCESS ; 01581 // 01582 IofCallDriverStackData->Flags |= CALLFLAG_OVERRIDE_STATUS ; 01583 IofCallDriverStackData->NewStatus = status ; 01584 } 01585 } 01586 Irp->IoStatus.Status = status ; 01587 01588 // 01589 // Set InUse = FALSE and CallStackData = NULL 01590 // 01591 RtlZeroMemory(iovCurrentStackLocation, sizeof(IOV_STACK_LOCATION)) ; 01592 InitializeListHead(&iovCurrentStackLocation->CallStackData) ; 01593 } else { 01594 01595 ASSERT(0) ; 01596 } 01597 01598 // 01599 // Once we return, we may be completed again before IofCompleteRequest3 01600 // get's called, so we make sure we are at DPC level throughout. 01601 // 01602 raiseToDPC = FALSE ; 01603 01604 if (iovSessionData->AssertFlags&ASSERTFLAG_COMPLETEATDPC) { 01605 01606 if (!CompletionPacket->RaisedCount) { 01607 01608 // 01609 // Copy away the callers IRQL 01610 // 01611 CompletionPacket->PreviousIrql = iovPacket->CallerIrql; 01612 raiseToDPC = TRUE ; 01613 } 01614 CompletionPacket->RaisedCount++ ; 01615 } 01616 01617 iovPacket->LastLocation = Irp->CurrentLocation+1 ; 01618 01619 if (iovPacket->TopStackLocation == Irp->CurrentLocation) { 01620 01621 CompletionPacket->IovSessionData = NULL; 01622 01623 if (iovPacket->Flags&TRACKFLAG_SURROGATE) { 01624 01625 // 01626 // Scribble away the real completion routine and corrosponding control 01627 // 01628 irpSp = IoGetNextIrpStackLocation(Irp) ; 01629 iovPacket->RealIrpCompletionRoutine = irpSp->CompletionRoutine ; 01630 iovPacket->RealIrpControl = irpSp->Control ; 01631 iovPacket->RealIrpContext = irpSp->Context ; 01632 01633 // 01634 // We want to peek at the Irp prior to completion. This is why we 01635 // have expanded the initial number of stack locations with the 01636 // driver verifier enabled. 01637 // 01638 IoSetCompletionRoutine( 01639 Irp, 01640 IovpSwapSurrogateIrp, 01641 Irp, 01642 TRUE, 01643 TRUE, 01644 TRUE 01645 ) ; 01646 01647 } else { 01648 01649 // 01650 // Close this session as the IRP has entirely completed. We drop 01651 // the pointer count we added to the tracking data here for the 01652 // same reason. 01653 // 01654 irpSp = IoGetNextIrpStackLocation(Irp) ; 01655 if (iovPacket->AssertFlags&ASSERTFLAG_POLICEIRPS) { 01656 01657 IovpAssertFinalIrpStack(iovPacket, irpSp) ; 01658 } 01659 01660 ASSERT(iovPacket->TopStackLocation == Irp->CurrentLocation); 01661 IovpSessionDataClose(iovSessionData); 01662 IovpSessionDataDereference(iovSessionData); 01663 IovpTrackingDataDereference(iovPacket, IOVREFTYPE_POINTER); 01664 } 01665 01666 } else { 01667 01668 // 01669 // We will be seeing this IRP again. Hold a session count against it. 01670 // 01671 IovpSessionDataReference(iovSessionData); 01672 } 01673 01674 // 01675 // Assert LastLocation is consistent with an IRP that may be completed. 01676 // 01677 if (iovPacket->LastLocation < iovPacket->TopStackLocation) { 01678 01679 ASSERT(iovSessionData->StackData[iovPacket->LastLocation-1].InUse) ; 01680 } 01681 01682 IovpTrackingDataReleaseLock(iovPacket); 01683 01684 if (raiseToDPC) { 01685 KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); 01686 } 01687 01688 CompletionPacket->LocationsAdvanced --; 01689 } 01690 01691 VOID 01692 FASTCALL 01693 IovpCompleteRequest3( 01694 IN PIRP Irp, 01695 IN PVOID Routine, 01696 IN OUT PIOFCOMPLETEREQUEST_STACKDATA CompletionPacket 01697 ) 01698 /*++ 01699 01700 Description: 01701 01702 This routine is called just before each completion routine is invoked. 01703 01704 Arguments: 01705 01706 Irp - A pointer to the IRP passed into 01707 IofCompleteRequest. 01708 01709 Routine - The completion routine about to be called. 01710 01711 CompletionPacket - A pointer to data on the callers stack. This will 01712 be picked up IovpCompleteRequest4 and 01713 IovpCompleteRequest5. 01714 01715 Return Value: 01716 01717 None. 01718 --*/ 01719 { 01720 PIOV_REQUEST_PACKET iovPacket; 01721 PIOV_SESSION_DATA iovSessionData; 01722 PIO_STACK_LOCATION irpSpCur, irpSpNext ; 01723 PDEFERRAL_CONTEXT deferralContext ; 01724 01725 iovSessionData = CompletionPacket->IovSessionData; 01726 if (iovSessionData == NULL) { 01727 01728 return; 01729 } 01730 01731 iovPacket = iovSessionData->IovRequestPacket; 01732 ASSERT(iovPacket); 01733 IovpTrackingDataAcquireLock(iovPacket); 01734 01735 // 01736 // Verify all completion routines are in nonpaged code, exempting one 01737 // special case - when a driver completes the IRP to itself by calling 01738 // IoSetNextStackLocation before calling IoCompleteRequest. 01739 // 01740 if (iovSessionData->AssertFlags&ASSERTFLAG_POLICEIRPS) { 01741 01742 if ((CompletionPacket->LocationsAdvanced <= 0) && 01743 (MmIsSystemAddressLocked(Routine) == FALSE)) { 01744 01745 DbgPrint( 01746 "Verifier Notes: LocationsAdvanced %d\n", 01747 CompletionPacket->LocationsAdvanced 01748 ); 01749 01750 WDM_FAIL_ROUTINE(( 01751 DCERROR_COMPLETION_ROUTINE_PAGABLE, 01752 DCPARAM_IRP + DCPARAM_ROUTINE, 01753 Irp, 01754 Routine 01755 )); 01756 } 01757 } 01758 01759 // 01760 // Setup fields for those assertion functions that will be called *after* 01761 // the completion routine has been called. 01762 // 01763 irpSpCur = IoGetCurrentIrpStackLocation(Irp) ; 01764 CompletionPacket->IsRemoveIrp = 01765 ((Irp->CurrentLocation <= (CCHAR) Irp->StackCount) && 01766 (irpSpCur->MajorFunction == IRP_MJ_PNP) && 01767 (irpSpCur->MinorFunction == IRP_MN_REMOVE_DEVICE)) ; 01768 01769 CompletionPacket->CompletionRoutine = Routine ; 01770 01771 // 01772 // Is this a completion routine that should be called later? Note that this 01773 // is only legal if we are pending the IRPs (because to the upper driver, 01774 // IofCallDriver is returning before it's completion routine has been called) 01775 // 01776 if ((!CompletionPacket->IsRemoveIrp)&& 01777 ((iovSessionData->AssertFlags&ASSERTFLAG_DEFERCOMPLETION)|| 01778 (iovSessionData->AssertFlags&ASSERTFLAG_COMPLETEATPASSIVE))) { 01779 01780 ASSERT(iovSessionData->AssertFlags&ASSERTFLAG_FORCEPENDING) ; 01781 01782 irpSpNext = IoGetNextIrpStackLocation(Irp) ; 01783 01784 deferralContext = ExAllocatePoolWithTag( 01785 NonPagedPool, 01786 sizeof(DEFERRAL_CONTEXT), 01787 POOL_TAG_DEFERRED_CONTEXT 01788 ) ; 01789 01790 if (deferralContext) { 01791 01792 // 01793 // Swap the original completion and context for our own. 01794 // 01795 deferralContext->IovRequestPacket = iovPacket; 01796 deferralContext->IrpSpNext = irpSpNext; 01797 deferralContext->OriginalCompletionRoutine = irpSpNext->CompletionRoutine; 01798 deferralContext->OriginalContext = irpSpNext->Context; 01799 deferralContext->OriginalIrp = Irp; 01800 deferralContext->OriginalPriorityBoost = iovPacket->PriorityBoost; 01801 01802 irpSpNext->CompletionRoutine = IovpInternalDeferredCompletion; 01803 irpSpNext->Context = deferralContext; 01804 IovpTrackingDataReference(iovPacket, IOVREFTYPE_POINTER); 01805 } 01806 } 01807 01808 IovpTrackingDataReleaseLock(iovPacket) ; 01809 } 01810 01811 VOID 01812 FASTCALL 01813 IovpCompleteRequest4( 01814 IN PIRP Irp, 01815 IN NTSTATUS ReturnedStatus, 01816 IN OUT PIOFCOMPLETEREQUEST_STACKDATA CompletionPacket 01817 ) 01818 /*++ 01819 01820 Description: 01821 01822 This assert routine is called just after each completion routine is 01823 invoked (but not if STATUS_MORE_PROCESSING is returned) 01824 01825 Arguments: 01826 01827 Irp - A pointer to the IRP passed into 01828 IofCompleteRequest. 01829 01830 Routine - The completion routine called. 01831 01832 ReturnedStatus - The status value returned. 01833 01834 CompletionPacket - A pointer to data on the callers stack. This was 01835 filled in by IovpCompleteRequest3. 01836 01837 Return Value: 01838 01839 None. 01840 --*/ 01841 { 01842 PIOV_REQUEST_PACKET iovPacket; 01843 PIOV_SESSION_DATA iovSessionData; 01844 PIO_STACK_LOCATION irpSp; 01845 PVOID routine; 01846 01847 routine = CompletionPacket->CompletionRoutine; 01848 iovSessionData = CompletionPacket->IovSessionData; 01849 01850 if (iovSessionData == NULL) { 01851 01852 return; 01853 } 01854 01855 iovPacket = iovSessionData->IovRequestPacket; 01856 ASSERT(iovPacket); 01857 IovpTrackingDataAcquireLock(iovPacket); 01858 01859 // 01860 // ADRIAO BUGBUG 01/06/1999 - 01861 // Check for leaked Cancel routines here. 01862 // 01863 if (iovSessionData->AssertFlags&ASSERTFLAG_FORCEPENDING) { 01864 01865 // 01866 // ADRIAO BUGBUG #05 05/12/98 - Find a way to do this in the non-pend 01867 // everything path... 01868 // 01869 if ((ReturnedStatus != STATUS_MORE_PROCESSING_REQUIRED)&& 01870 (iovPacket->pIovSessionData == iovSessionData)) { 01871 01872 // 01873 // At this point, we know the completion routine is required to have 01874 // set the IRP pending bit, because we've hardwired everyone below 01875 // him to return pending, and we've marked the pending returned bit. 01876 // Verify he did his part 01877 // 01878 irpSp = IoGetCurrentIrpStackLocation(Irp) ; 01879 if (!(irpSp->Control & SL_PENDING_RETURNED )) { 01880 01881 WDM_FAIL_ROUTINE(( 01882 DCERROR_PENDING_BIT_NOT_MIGRATED, 01883 DCPARAM_IRP + DCPARAM_ROUTINE, 01884 Irp, 01885 routine 01886 )); 01887 01888 // 01889 // This will keep the IRP above from erroneously asserting (and 01890 // correctly hanging). 01891 // 01892 IoMarkIrpPending(Irp); 01893 } 01894 } 01895 } 01896 IovpTrackingDataReleaseLock(iovPacket); 01897 } 01898 01899 VOID 01900 FASTCALL 01901 IovpCompleteRequest5( 01902 IN PIRP Irp, 01903 IN OUT PIOFCOMPLETEREQUEST_STACKDATA CompletionPacket 01904 ) 01905 /*++ 01906 01907 Description: 01908 01909 This routine is called for each stack location that could have had a 01910 completion routine, after any possible completion routine has been 01911 called. 01912 01913 Arguments: 01914 01915 Irp - A pointer to the IRP passed into 01916 IofCompleteRequest. 01917 01918 CompletionPacket - A pointer to a local variable on the stack of 01919 IofCompleteRequest. This information was stored 01920 by IovpCompleteRequest2 and 3. 01921 01922 Return Value: 01923 01924 None. 01925 --*/ 01926 { 01927 PIOV_REQUEST_PACKET iovPacket; 01928 PIOV_SESSION_DATA iovSessionData; 01929 PIOV_STACK_LOCATION iovCurrentStackLocation ; 01930 NTSTATUS status ; 01931 01932 iovSessionData = CompletionPacket->IovSessionData; 01933 01934 if (iovSessionData) { 01935 01936 iovPacket = iovSessionData->IovRequestPacket; 01937 ASSERT(iovPacket); 01938 IovpTrackingDataAcquireLock(iovPacket); 01939 01940 ASSERT((!CompletionPacket->RaisedCount) || 01941 (iovSessionData->AssertFlags&ASSERTFLAG_COMPLETEATDPC)) ; 01942 01943 IovpSessionDataDereference(iovSessionData); 01944 IovpTrackingDataReleaseLock(iovPacket); 01945 } 01946 01947 // 01948 // When this count is at zero, we have unnested out of every 01949 // completion routine, so it is OK to return back to our original IRQL 01950 // 01951 if (CompletionPacket->RaisedCount) { 01952 01953 if (!(--CompletionPacket->RaisedCount)) { 01954 // 01955 // Undo IRQL madness (wouldn't want to return to 01956 // the caller at DPC, would we now?) 01957 // 01958 KeLowerIrql(CompletionPacket->PreviousIrql); 01959 } 01960 } 01961 } 01962 01963 VOID 01964 FASTCALL 01965 IovpCompleteRequestApc( 01966 IN PIRP Irp, 01967 IN PVOID BestStackOffset 01968 ) 01969 /*++ 01970 01971 Description: 01972 01973 This routine is after the APC for completing IRPs and fired. 01974 01975 Arguments: 01976 01977 Irp - A pointer to the IRP passed into retrieved from 01978 the APC in IopCompleteRequest. 01979 01980 BestStackOffset - A pointer to a last parameter passed on the stack. 01981 We use this to detect the case where a driver has 01982 ignored STATUS_PENDING and left the UserIosb on 01983 it's stack. 01984 01985 Return Value: 01986 01987 None. 01988 --*/ 01989 { 01990 #if DBG 01991 #if defined(_X86_) 01992 PUCHAR addr; 01993 PIOV_REQUEST_PACKET iovPacket; 01994 01995 addr = (PUCHAR)Irp->UserIosb; 01996 if ((addr > (PUCHAR)KeGetCurrentThread()->StackLimit) && 01997 (addr <= (PUCHAR)BestStackOffset)) { 01998 01999 iovPacket = IovpTrackingDataFindAndLock(Irp) ; 02000 02001 RtlAssert("UserIosb below stack pointer", __FILE__, (ULONG) iovPacket, 02002 "Call AdriaO"); 02003 02004 IovpTrackingDataReleaseLock(iovPacket) ; 02005 } 02006 02007 addr = (PUCHAR)Irp->UserEvent; 02008 if ((addr > (PUCHAR)KeGetCurrentThread()->StackLimit) && 02009 (addr <= (PUCHAR)BestStackOffset)) { 02010 02011 iovPacket = IovpTrackingDataFindAndLock(Irp) ; 02012 02013 RtlAssert("UserEvent below stack pointer", __FILE__, (ULONG) iovPacket, 02014 "Call AdriaO"); 02015 02016 IovpTrackingDataReleaseLock(iovPacket) ; 02017 } 02018 #endif 02019 #endif 02020 } 02021 02022 BOOLEAN 02023 IovpAdvanceStackDownwards( 02024 IN PIOV_STACK_LOCATION StackDataArray, 02025 IN CCHAR CurrentLocation, 02026 IN PIO_STACK_LOCATION IrpSp, 02027 IN PIO_STACK_LOCATION IrpLastSp OPTIONAL, 02028 IN ULONG LocationsAdvanced, 02029 IN BOOLEAN IsNewRequest, 02030 IN BOOLEAN MarkAsTaken, 02031 OUT PIOV_STACK_LOCATION *StackLocationInfo 02032 ) 02033 { 02034 PIOV_STACK_LOCATION iovCurrentStackLocation, advancedLocationData, requestOriginalSLD; 02035 PIO_STACK_LOCATION irpSpTemp; 02036 PLARGE_INTEGER dispatchTime, stackTime; 02037 BOOLEAN isNewSession, wasInUse; 02038 PVOID dispatchRoutine; 02039 02040 isNewSession = (IrpLastSp == NULL); 02041 ASSERT((!isNewSession) || (LocationsAdvanced == 1)); 02042 ASSERT(isNewSession || ((ULONG) (IrpLastSp - IrpSp) == LocationsAdvanced)); 02043 02044 // 02045 // The CurrentLocation will be decremented when we leave. If it hit's zero 02046 // we will bugcheck, therefore it should be at least two, and we'd need to 02047 // subtract two off it to make it an index into an array of slot locations 02048 // (our analog for stack locations). However we reserve an extra empty slot 02049 // at the head of the array to make our logic easier. Therefore we subtract 02050 // only one. 02051 // 02052 iovCurrentStackLocation = StackDataArray + CurrentLocation -1; 02053 02054 TRACKIRP_DBGPRINT(( 02055 " Smacking %lx (%lx) to valid in SD\n", 02056 CurrentLocation -1, iovCurrentStackLocation 02057 ), 2); 02058 02059 // 02060 // Note that we do set the InUse field. That's for the caller to do. 02061 // 02062 if (iovCurrentStackLocation->InUse) { 02063 02064 // 02065 // The only way the stack slot could be in use is if we skipped before 02066 // 02067 ASSERT(!LocationsAdvanced); // && (!isNewSession) 02068 ASSERT(IrpSp == iovCurrentStackLocation->IrpSp); 02069 02070 } else if (MarkAsTaken) { 02071 02072 // 02073 // ADRIAO BUGBUG 01/02/1999 - 02074 // Is the below assertion is not true in the case of an internally 02075 // forwarded, completed, and then externally forwarded IRP? 02076 // 02077 ASSERT(LocationsAdvanced); // || isNewSession 02078 RtlZeroMemory(iovCurrentStackLocation, sizeof(IOV_STACK_LOCATION)); 02079 InitializeListHead(&iovCurrentStackLocation->CallStackData); 02080 iovCurrentStackLocation->IrpSp = IrpSp; 02081 } 02082 02083 // 02084 // Determine the last original request. A "Request" is block of data in a 02085 // stack location that is progressively copied downwards as the IRP is 02086 // forwarded (ie, a forwarded START IRP, a forwarded IOCTL, etc). A clever 02087 // driver writer could use his own stack location to send down a quick 02088 // query before forwarding along the original request. We correctly 02089 // differentiate between those two unique requests within the IRP below. 02090 // 02091 if (isNewSession) { 02092 02093 // 02094 // *We* are the original request. None of these fields below should 02095 // be used. 02096 // 02097 dispatchRoutine = NULL; 02098 requestOriginalSLD = NULL; 02099 stackTime = NULL; 02100 dispatchTime = NULL; 02101 02102 } else if (LocationsAdvanced) { 02103 02104 // 02105 // To get the original request (the pointer to the Irp slot that 02106 // represents where we *first* saw this request), we go backwards to get 02107 // the most recent previous irp slot data (set up when the device above 02108 // forwarded this Irp to us), and we read what it's original request was. 02109 // We also get the dispatch routine for that slot, which we will use to 02110 // backfill skipped slots if we advanced more than one Irp stack 02111 // location this time (ie, someone called IoSetNextIrpStackLocation). 02112 // 02113 dispatchTime = &iovCurrentStackLocation[LocationsAdvanced].PerfDispatchStart; 02114 stackTime = &iovCurrentStackLocation[LocationsAdvanced].PerfStackLocationStart; 02115 dispatchRoutine = iovCurrentStackLocation[LocationsAdvanced].LastDispatch; 02116 requestOriginalSLD = iovCurrentStackLocation[LocationsAdvanced].RequestsFirstStackLocation; 02117 02118 ASSERT(dispatchRoutine); 02119 ASSERT(iovCurrentStackLocation[LocationsAdvanced].InUse); 02120 ASSERT(requestOriginalSLD->RequestsFirstStackLocation == requestOriginalSLD); 02121 iovCurrentStackLocation->RequestsFirstStackLocation = requestOriginalSLD; 02122 02123 } else { 02124 02125 // 02126 // We skipped. The slot should already be filled. 02127 // 02128 dispatchRoutine = NULL; 02129 dispatchTime = NULL; 02130 stackTime = NULL; 02131 requestOriginalSLD = iovCurrentStackLocation->RequestsFirstStackLocation; 02132 ASSERT(requestOriginalSLD); 02133 ASSERT(requestOriginalSLD->RequestsFirstStackLocation == requestOriginalSLD); 02134 } 02135 02136 // 02137 // The previous request seen is in requestOriginalSLD (NULL if none). If 02138 // we advanced more than one stack location (ie, someone called 02139 // IoSetNextIrpStackLocation), we need to update the slots we never saw get 02140 // consumed. Note that the dispatch routine we set in the slot is for the 02141 // driver that owned the last slot - we do not use the device object at 02142 // that IrpSp because it might be stale (or perhaps even NULL). 02143 // 02144 advancedLocationData = iovCurrentStackLocation; 02145 irpSpTemp = IrpSp; 02146 while(LocationsAdvanced>1) { 02147 advancedLocationData++ ; 02148 LocationsAdvanced-- ; 02149 irpSpTemp++ ; 02150 TRACKIRP_DBGPRINT(( 02151 " Late smacking %lx to valid in CD1\n", 02152 advancedLocationData - StackDataArray 02153 ), 3) ; 02154 02155 ASSERT(!advancedLocationData->InUse) ; 02156 RtlZeroMemory(advancedLocationData, sizeof(IOV_STACK_LOCATION)) ; 02157 InitializeListHead(&advancedLocationData->CallStackData) ; 02158 advancedLocationData->InUse = TRUE ; 02159 advancedLocationData->IrpSp = irpSpTemp ; 02160 02161 advancedLocationData->RequestsFirstStackLocation = requestOriginalSLD ; 02162 advancedLocationData->PerfDispatchStart = *dispatchTime; 02163 advancedLocationData->PerfStackLocationStart = *stackTime; 02164 advancedLocationData->LastDispatch = dispatchRoutine ; 02165 } 02166 02167 // 02168 // For the assertion below... 02169 // 02170 if (LocationsAdvanced) { 02171 irpSpTemp++ ; 02172 } 02173 ASSERT((irpSpTemp == IrpLastSp)||(IrpLastSp == NULL)) ; 02174 02175 // 02176 // Write out the slot we're using. 02177 // 02178 *StackLocationInfo = iovCurrentStackLocation; 02179 02180 if (!MarkAsTaken) { 02181 return iovCurrentStackLocation->InUse; 02182 } 02183 02184 // 02185 // Record a pointer in this slot to the requests originating slot as 02186 // appropriate. 02187 // 02188 if (IsNewRequest) { 02189 02190 TRACKIRP_DBGPRINT(( 02191 " CD1: %lx is a new request\n", 02192 advancedLocationData-StackDataArray 02193 ), 3) ; 02194 02195 ASSERT(LocationsAdvanced == 1) ; 02196 // 02197 // ADRIAO BUGBUG 01/02/1999 - 02198 // 02199 // Why the **ll did I have this there? If this were correct then the 02200 // backfill logic above would need fixing. I think what I have now is 02201 // correct, not this: 02202 // 02203 // advancedLocationData->RequestsFirstStackLocation = advancedLocationData ; 02204 // 02205 iovCurrentStackLocation->RequestsFirstStackLocation = iovCurrentStackLocation; 02206 02207 } else if (LocationsAdvanced) { 02208 02209 ASSERT(!isNewSession) ; 02210 // 02211 // ADRIAO BUGBUG 01/02/1999 - 02212 // As per above, this should already have been handled. 02213 // 02214 //advancedLocationData->RequestsFirstStackLocation = requestOriginalSLD ; 02215 TRACKIRP_DBGPRINT(( 02216 " CD1: %lx is a request for %lx\n", 02217 advancedLocationData-StackDataArray, 02218 requestOriginalSLD-StackDataArray 02219 ), 3) ; 02220 02221 } else { 02222 02223 // 02224 // As we skipped, the request should not have changed. If it did, 02225 // either guy we called trashed the stack given to him (giving none 02226 // to the dude under him), or we incorrectly saw a new request when 02227 // we shouldn't have (see previous comment). 02228 // 02229 ASSERT(!isNewSession) ; 02230 ASSERT(advancedLocationData->RequestsFirstStackLocation == requestOriginalSLD) ; 02231 } 02232 02233 wasInUse = iovCurrentStackLocation->InUse; 02234 iovCurrentStackLocation->InUse = TRUE; 02235 return wasInUse; 02236 } 02237 02238 VOID 02239 IovpExamineIrpStackForwarding( 02240 IN OUT PIOV_REQUEST_PACKET IovPacket, 02241 IN BOOLEAN IsNewSession, 02242 IN ULONG ForwardMethod, 02243 IN PDEVICE_OBJECT DeviceObject, 02244 IN PIRP Irp, 02245 IN OUT PIO_STACK_LOCATION *IoCurrentStackLocation, 02246 OUT PIO_STACK_LOCATION *IoLastStackLocation, 02247 OUT ULONG *StackLocationsAdvanced 02248 ) 02249 { 02250 PIRP irp; 02251 PIO_STACK_LOCATION irpSp, irpLastSp; 02252 BOOLEAN isSameStack; 02253 ULONG locationsAdvanced; 02254 02255 irpSp = *IoCurrentStackLocation; 02256 02257 if (!IsNewSession) { 02258 02259 // 02260 // We are sitting on current next being one back (-1) from 02261 // CurrentStackLocation. 02262 // 02263 locationsAdvanced = IovPacket->LastLocation-Irp->CurrentLocation ; 02264 irpLastSp = Irp->Tail.Overlay.CurrentStackLocation+(locationsAdvanced-1) ; 02265 02266 } else { 02267 02268 // 02269 // New IRP, so no last SP and we always advance "1" 02270 // 02271 locationsAdvanced = 1 ; 02272 irpLastSp = NULL ; 02273 } 02274 02275 if ((!IsNewSession) && (IovPacket->AssertFlags&ASSERTFLAG_POLICEIRPS)) { 02276 02277 // 02278 // As the control field is zeroed by IoCopyCurrentStackLocation, we 02279 // dope each stack location with the value SL_NOTCOPIED. If it is 02280 // zeroed or the IRP stack location has stayed the same, the one of 02281 // the two API's was called. Otherwise the next stack location wasn't 02282 // set up properly (I have yet to find a case otherwise)... 02283 // 02284 if ((irpSp->Control&SL_NOTCOPIED)&& 02285 IovPacket->LastLocation != Irp->CurrentLocation) { 02286 02287 #if 0 02288 FAIL_CALLER_OF_IOFCALLDRIVER2( 02289 (DCERROR_NEXTIRPSP_DIRTY, DCPARAM_IRP, Irp), 02290 irpSp 02291 ); 02292 #endif 02293 } 02294 02295 // 02296 // Now check for people who copy the stack locations and forget to 02297 // wipe out previous completion routines. 02298 // 02299 if (locationsAdvanced) { 02300 02301 // 02302 // IoCopyCurrentStackLocation copies everything but Completion, 02303 // Context, and Control 02304 // 02305 isSameStack = RtlEqualMemory(irpSp, irpLastSp, 02306 FIELD_OFFSET(IO_STACK_LOCATION, Control)) ; 02307 02308 isSameStack &= RtlEqualMemory(&irpSp->Parameters, &irpLastSp->Parameters, 02309 FIELD_OFFSET(IO_STACK_LOCATION, DeviceObject)- 02310 FIELD_OFFSET(IO_STACK_LOCATION, Parameters)) ; 02311 02312 isSameStack &= (irpSp->FileObject == irpLastSp->FileObject) ; 02313 02314 // 02315 // We should *never* see this on the stack! If we do, something 02316 // quite bizarre has happened... 02317 // 02318 ASSERT(irpSp->CompletionRoutine != IovpSwapSurrogateIrp) ; 02319 02320 if (isSameStack) { 02321 02322 // 02323 // We caught them doing something either very bad or quite 02324 // inefficient. We can tell which based on whether there is 02325 // a completion routine. 02326 // 02327 if ((irpSp->CompletionRoutine == irpLastSp->CompletionRoutine)&& 02328 (irpSp->Context == irpLastSp->Context) && 02329 (irpSp->Control == irpLastSp->Control) && 02330 (irpSp->CompletionRoutine != NULL) && 02331 (DeviceObject->DriverObject != irpLastSp->DeviceObject->DriverObject) 02332 ) { 02333 02334 // 02335 // Duplication of both the completion and the context 02336 // while not properly zeroing the control field is enough 02337 // to make me believe the caller has made a vexing mistake. 02338 // 02339 FAIL_CALLER_OF_IOFCALLDRIVER2( 02340 (DCERROR_IRPSP_COPIED, DCPARAM_IRP, Irp), 02341 irpSp 02342 ) ; 02343 02344 // 02345 // Repair the stack 02346 // 02347 irpSp->CompletionRoutine = NULL ; 02348 irpSp->Control = 0 ; 02349 02350 } else if (!irpSp->CompletionRoutine) { 02351 02352 if (!(irpSp->Control&SL_NOTCOPIED) 02353 #ifdef HACKHACKS_ENABLED 02354 && (!(IovpHackFlags&HACKFLAG_FOR_SCSIPORT)) 02355 #endif 02356 ) { 02357 02358 // 02359 // ADRIAO HACKHACK 06/12/98 #10 - PeterWie does this for 02360 // two reasons: 02361 // 1) It's easier to debug 02362 // 2) The space is not really recovered anyway. 02363 // 02364 // This will be an ongoing argument it seems, but #2 can 02365 // be cleverly solved if one decrements their stack 02366 // count, and #1 I've solved in Debug... 02367 // 02368 if (irpSp->MajorFunction == IRP_MJ_POWER) { 02369 02370 // 02371 // Unwind back past PoCallDriver... 02372 // 02373 WDM_CHASTISE_CALLER5( 02374 (DCERROR_UNNECCESSARY_COPY, DCPARAM_IRP, Irp) 02375 ); 02376 02377 } else { 02378 02379 WDM_CHASTISE_CALLER3( 02380 (DCERROR_UNNECCESSARY_COPY, DCPARAM_IRP, Irp) 02381 ); 02382 } 02383 } 02384 02385 IoSetCompletionRoutine( 02386 Irp, 02387 IovpInternalCompletionTrap, 02388 IoGetCurrentIrpStackLocation( Irp ), 02389 TRUE, 02390 TRUE, 02391 TRUE 02392 ) ; 02393 } 02394 } 02395 02396 } else if (IovPacket->AssertFlags&ASSERTFLAG_CONSUME_ALWAYS) { 02397 02398 if (ForwardMethod == FORWARDED_TO_NEXT_DO) { 02399 02400 if (Irp->CurrentLocation<2) { 02401 02402 FAIL_CALLER_OF_IOFCALLDRIVER2( 02403 (DCERROR_INSUFFICIENT_STACK_LOCATIONS, DCPARAM_IRP, Irp), 02404 irpSp 02405 ) ; 02406 02407 } else { 02408 02409 // 02410 // Back up the skip, then copy. Add a completion routine with 02411 // unique and assertable context to catch people who clumsily 02412 // Rtl-copy stack locations (we can't catch them if the caller 02413 // above used an empty stack with no completion routine)... 02414 // 02415 IoSetNextIrpStackLocation( Irp ) ; 02416 02417 // 02418 // Set the trap... 02419 // 02420 IoCopyCurrentIrpStackLocationToNext( Irp ) ; 02421 IoSetCompletionRoutine( 02422 Irp, 02423 IovpInternalCompletionTrap, 02424 IoGetCurrentIrpStackLocation( Irp ), 02425 TRUE, 02426 TRUE, 02427 TRUE 02428 ) ; 02429 02430 // 02431 // This is our new reality... 02432 // 02433 locationsAdvanced = 1 ; 02434 irpSp = IoGetNextIrpStackLocation( Irp ); 02435 } 02436 } 02437 } 02438 } 02439 02440 *IoCurrentStackLocation = irpSp; 02441 *IoLastStackLocation = irpLastSp; 02442 *StackLocationsAdvanced = locationsAdvanced; 02443 } 02444 02445 NTSTATUS 02446 IovpInternalCompletionTrap( 02447 IN PDEVICE_OBJECT DeviceObject, 02448 IN PIRP Irp, 02449 IN PVOID Context 02450 ) 02451 /*++ 02452 02453 Description: 02454 02455 This routine does nothing but act as a trap for people 02456 incorrectly copying stack locations... 02457 02458 Arguments: 02459 02460 DeviceObject - Device object set at this level of the completion 02461 routine - ignored. 02462 02463 Irp - A pointer to the IRP. 02464 02465 Context - Context should equal the Irp's stack location - 02466 this is asserted. 02467 02468 Return Value: 02469 02470 STATUS_SUCCESS 02471 02472 --*/ 02473 { 02474 PIO_STACK_LOCATION irpSp ; 02475 02476 if (Irp->PendingReturned) { 02477 02478 IoMarkIrpPending( Irp ) ; 02479 } 02480 irpSp = IoGetCurrentIrpStackLocation( Irp ) ; 02481 02482 ASSERT((PVOID) irpSp == Context) ; 02483 02484 return STATUS_SUCCESS ; 02485 } 02486 02487 VOID 02488 IovpInternalCompleteAtDPC( 02489 IN PKDPC Dpc, 02490 IN PVOID DeferredContext, 02491 IN PVOID SystemArgument1, 02492 IN PVOID SystemArgument2 02493 ) 02494 { 02495 IovpInternalCompleteAfterWait(DeferredContext) ; 02496 } 02497 02498 VOID 02499 IovpInternalCompleteAfterWait( 02500 IN PVOID Context 02501 ) 02502 { 02503 PDEFERRAL_CONTEXT deferralContext = (PDEFERRAL_CONTEXT) Context ; 02504 PIO_STACK_LOCATION irpSpNext ; 02505 NTSTATUS status ; 02506 02507 if (deferralContext->DeferAction == DEFERACTION_QUEUE_PASSIVE_TIMER) { 02508 02509 // 02510 // Wait the appropriate amount of time if so ordered... 02511 // 02512 ASSERT(KeGetCurrentIrql()==PASSIVE_LEVEL) ; 02513 KeWaitForSingleObject( 02514 &deferralContext->DeferralTimer, 02515 Executive, 02516 KernelMode, 02517 FALSE, 02518 NULL 02519 ) ; 02520 } 02521 02522 IovpTrackingDataAcquireLock(deferralContext->IovRequestPacket) ; 02523 02524 IovpProtectedIrpMakeTouchable( 02525 deferralContext->OriginalIrp, 02526 &deferralContext->IovRequestPacket->RestoreHandle 02527 ); 02528 02529 irpSpNext = IoGetNextIrpStackLocation( deferralContext->OriginalIrp ) ; 02530 02531 ASSERT(irpSpNext == deferralContext->IrpSpNext) ; 02532 ASSERT(irpSpNext->CompletionRoutine == deferralContext->OriginalCompletionRoutine) ; 02533 ASSERT(irpSpNext->Context == deferralContext->OriginalContext) ; 02534 02535 ASSERT(deferralContext->IovRequestPacket->Flags & TRACKFLAG_QUEUED_INTERNALLY) ; 02536 deferralContext->IovRequestPacket->Flags &=~ TRACKFLAG_QUEUED_INTERNALLY ; 02537 02538 IovpTrackingDataDereference(deferralContext->IovRequestPacket, IOVREFTYPE_POINTER) ; 02539 IovpTrackingDataReleaseLock(deferralContext->IovRequestPacket) ; 02540 02541 status = irpSpNext->CompletionRoutine( 02542 deferralContext->DeviceObject, 02543 deferralContext->OriginalIrp, 02544 irpSpNext->Context 02545 ) ; 02546 02547 if (status!=STATUS_MORE_PROCESSING_REQUIRED) { 02548 02549 IoCompleteRequest(deferralContext->OriginalIrp, deferralContext->OriginalPriorityBoost) ; 02550 } 02551 ExFreePool(deferralContext) ; 02552 } 02553 02554 NTSTATUS 02555 IovpInternalDeferredCompletion( 02556 IN PDEVICE_OBJECT DeviceObject, 02557 IN PIRP Irp, 02558 IN PVOID Context 02559 ) 02560 /*++ 02561 02562 Description: 02563 02564 This function is slipped in as a completion routine when we are 02565 "deferring" completion via work item, etc. 02566 02567 Arguments: 02568 02569 DeviceObject - Device object set at this level of the completion 02570 routine - passed on. 02571 02572 Irp - A pointer to the IRP. 02573 02574 Context - Context block that includes original completion 02575 routine. 02576 02577 Return Value: 02578 02579 NTSTATUS 02580 02581 --*/ 02582 { 02583 PDEFERRAL_CONTEXT deferralContext = (PDEFERRAL_CONTEXT) Context; 02584 PIO_STACK_LOCATION irpSpNext; 02585 BOOLEAN passiveCompletionOK; 02586 DEFER_ACTION deferAction; 02587 ULONG refAction; 02588 ULONG trackingFlags; 02589 LARGE_INTEGER deltaTime; 02590 02591 // 02592 // Do delta time conversion. 02593 // 02594 deltaTime.QuadPart = - IovpIrpDeferralTime ; 02595 02596 // 02597 // The *next* stack location holds our completion and context. The current 02598 // stack location has already been wiped. 02599 // 02600 irpSpNext = IoGetNextIrpStackLocation( Irp ) ; 02601 02602 ASSERT((PVOID) irpSpNext->CompletionRoutine == IovpInternalDeferredCompletion) ; 02603 02604 // 02605 // Put everything back in case someone is looking... 02606 // 02607 irpSpNext->CompletionRoutine = deferralContext->OriginalCompletionRoutine ; 02608 irpSpNext->Context = deferralContext->OriginalContext ; 02609 02610 // 02611 // Some IRP dispatch routines cannot be called at passive. Two examples are 02612 // paging IRPs (cause we could switch) and Power IRPs. As we don't check yet, 02613 // if we "were" completed passive, continue to do so, but elsewhere... 02614 // 02615 passiveCompletionOK = (KeGetCurrentIrql()==PASSIVE_LEVEL) ; 02616 02617 IovpTrackingDataAcquireLock(deferralContext->IovRequestPacket) ; 02618 02619 // 02620 // Verify all completion routines are in nonpaged code. 02621 // 02622 if (deferralContext->IovRequestPacket->AssertFlags&ASSERTFLAG_POLICEIRPS) { 02623 02624 if (MmIsSystemAddressLocked(irpSpNext->CompletionRoutine) == FALSE) { 02625 02626 WDM_FAIL_ROUTINE(( 02627 DCERROR_COMPLETION_ROUTINE_PAGABLE, 02628 DCPARAM_IRP + DCPARAM_ROUTINE, 02629 Irp, 02630 irpSpNext->CompletionRoutine 02631 )) ; 02632 } 02633 } 02634 02635 trackingFlags = deferralContext->IovRequestPacket->AssertFlags; 02636 02637 ASSERT(trackingFlags&ASSERTFLAG_FORCEPENDING) ; 02638 02639 switch(trackingFlags&(ASSERTFLAG_DEFERCOMPLETION| 02640 ASSERTFLAG_COMPLETEATPASSIVE| 02641 ASSERTFLAG_COMPLETEATDPC)) { 02642 02643 case ASSERTFLAG_COMPLETEATPASSIVE: 02644 deferAction = passiveCompletionOK ? DEFERACTION_QUEUE_WORKITEM : 02645 DEFERACTION_NORMAL ; 02646 break; 02647 02648 case ASSERTFLAG_DEFERCOMPLETION | ASSERTFLAG_COMPLETEATPASSIVE: 02649 deferAction = passiveCompletionOK ? DEFERACTION_QUEUE_PASSIVE_TIMER : 02650 DEFERACTION_NORMAL ; 02651 break; 02652 02653 case ASSERTFLAG_DEFERCOMPLETION | ASSERTFLAG_COMPLETEATDPC: 02654 deferAction = DEFERACTION_QUEUE_DISPATCH_TIMER ; 02655 break; 02656 02657 case ASSERTFLAG_DEFERCOMPLETION: 02658 deferAction = (KeGetCurrentIrql()==DISPATCH_LEVEL) ? 02659 DEFERACTION_QUEUE_DISPATCH_TIMER : 02660 DEFERACTION_QUEUE_PASSIVE_TIMER ; 02661 break; 02662 02663 default: 02664 deferAction = DEFERACTION_NORMAL ; 02665 KDASSERT(0) ; 02666 } 02667 02668 if (deferAction != DEFERACTION_NORMAL) { 02669 02670 // 02671 // Set this flag. If anybody uses this IRP while this flag is on, complain 02672 // immediately! 02673 // 02674 ASSERT(!(trackingFlags&TRACKFLAG_QUEUED_INTERNALLY)) ; 02675 deferralContext->IovRequestPacket->Flags |= TRACKFLAG_QUEUED_INTERNALLY ; 02676 deferralContext->DeviceObject = DeviceObject ; 02677 02678 deferralContext->IovRequestPacket->RestoreHandle = 02679 IovpProtectedIrpMakeUntouchable( 02680 Irp, 02681 FALSE 02682 ) ; 02683 } else { 02684 02685 IovpTrackingDataDereference(deferralContext->IovRequestPacket, IOVREFTYPE_POINTER); 02686 } 02687 02688 IovpTrackingDataReleaseLock(deferralContext->IovRequestPacket) ; 02689 02690 deferralContext->DeferAction = deferAction ; 02691 02692 switch(deferAction) { 02693 02694 case DEFERACTION_QUEUE_PASSIVE_TIMER: 02695 KeInitializeTimerEx(&deferralContext->DeferralTimer, SynchronizationTimer) ; 02696 KeSetTimerEx( 02697 &deferralContext->DeferralTimer, 02698 deltaTime, 02699 0, 02700 NULL 02701 ) ; 02702 02703 // 02704 // Fall through... 02705 // 02706 02707 case DEFERACTION_QUEUE_WORKITEM: 02708 02709 // 02710 // Queue this up so we can complete this passively. 02711 // 02712 ExInitializeWorkItem( 02713 (PWORK_QUEUE_ITEM)&deferralContext->WorkQueueItem, 02714 IovpInternalCompleteAfterWait, 02715 deferralContext 02716 ); 02717 02718 ExQueueWorkItem( 02719 (PWORK_QUEUE_ITEM)&deferralContext->WorkQueueItem, 02720 DelayedWorkQueue 02721 ); 02722 02723 return STATUS_MORE_PROCESSING_REQUIRED ; 02724 02725 case DEFERACTION_QUEUE_DISPATCH_TIMER: 02726 02727 KeInitializeDpc( 02728 &deferralContext->DpcItem, 02729 IovpInternalCompleteAtDPC, 02730 deferralContext 02731 ); 02732 02733 KeInitializeTimerEx(&deferralContext->DeferralTimer, SynchronizationTimer) ; 02734 KeSetTimerEx( 02735 &deferralContext->DeferralTimer, 02736 deltaTime, 02737 0, 02738 &deferralContext->DpcItem 02739 ) ; 02740 return STATUS_MORE_PROCESSING_REQUIRED ; 02741 02742 case DEFERACTION_NORMAL: 02743 default: 02744 02745 ExFreePool(deferralContext) ; 02746 return irpSpNext->CompletionRoutine(DeviceObject, Irp, irpSpNext->Context) ; 02747 } 02748 } 02749 02750 NTSTATUS 02751 IovpSwapSurrogateIrp( 02752 IN PDEVICE_OBJECT DeviceObject, 02753 IN PIRP Irp, 02754 IN PVOID Context 02755 ) 02756 /*++ 02757 02758 Description: 02759 02760 This completion routine will copy back the surrogate IRP 02761 to the original and complete the original IRP. 02762 02763 Arguments: 02764 02765 DeviceObject - Device object set at this level 02766 of the completion routine - ignored. 02767 02768 Irp - A pointer to the IRP. 02769 02770 Context - Context should equal the IRP - this is 02771 asserted. 02772 02773 Return Value: 02774 02775 STATUS_MORE_PROCESSING_REQUIRED... 02776 02777 --*/ 02778 { 02779 PIOV_REQUEST_PACKET iovPacket, iovPrevPacket; 02780 PIOV_SESSION_DATA iovSessionData; 02781 ULONG irpSize ; 02782 PIRP realIrp ; 02783 BOOLEAN freeTrackingData ; 02784 NTSTATUS status, lockedStatus ; 02785 CCHAR priorityBoost ; 02786 PVOID completionRoutine ; 02787 PIO_STACK_LOCATION irpSp ; 02788 BOOLEAN locked ; 02789 02790 // 02791 // If this one fails, somebody has probably copied the stack 02792 // inclusive with our completion routine. We should already 02793 // have caught this... 02794 // 02795 ASSERT(Irp == Context) ; 02796 02797 iovPacket = IovpTrackingDataFindAndLock(Irp) ; 02798 ASSERT(iovPacket) ; 02799 02800 if (iovPacket == NULL) { 02801 02802 return STATUS_SUCCESS ; 02803 } 02804 02805 ASSERT(iovPacket->TopStackLocation == Irp->CurrentLocation) ; 02806 02807 iovSessionData = IovpTrackingDataGetCurrentSessionData(iovPacket); 02808 ASSERT(iovSessionData); 02809 02810 // 02811 // Put everything back 02812 // 02813 ASSERT(iovPacket->HeadPacket != iovPacket); 02814 02815 iovPrevPacket = CONTAINING_RECORD( 02816 iovPacket->SurrogateLink.Blink, 02817 IOV_REQUEST_PACKET, 02818 SurrogateLink 02819 ); 02820 02821 realIrp = iovPrevPacket->TrackedIrp ; 02822 irpSize = IoSizeOfIrp( Irp->StackCount ) ; 02823 02824 // 02825 // Back the IRP stack up so that the original completion routine 02826 // is called if appropriate 02827 // 02828 IoSetNextIrpStackLocation(Irp); 02829 IoSetNextIrpStackLocation(realIrp); 02830 02831 irpSp = IoGetCurrentIrpStackLocation(Irp) ; 02832 irpSp->CompletionRoutine = iovPacket->RealIrpCompletionRoutine ; 02833 irpSp->Control = iovPacket->RealIrpControl ; 02834 irpSp->Context = iovPacket->RealIrpContext ; 02835 02836 // 02837 // Record final data and make any accesses to the surrogate IRP 02838 // crash. 02839 // 02840 irpSp = IoGetNextIrpStackLocation(Irp) ; 02841 if (iovPacket->AssertFlags&ASSERTFLAG_POLICEIRPS) { 02842 02843 IovpAssertFinalIrpStack(iovPacket, irpSp) ; 02844 } 02845 02846 priorityBoost = iovPacket->PriorityBoost ; 02847 IovpTrackingDataDereference(iovPacket, IOVREFTYPE_POINTER); 02848 IovpSessionDataFinalizeSurrogate(iovSessionData, iovPacket, Irp); 02849 IovpSessionDataClose(iovSessionData); 02850 IovpSessionDataDereference(iovSessionData); 02851 02852 TRACKIRP_DBGPRINT(( 02853 " Swapping surrogate IRP %lx back to %lx (Tracking data %lx)\n", 02854 Irp, 02855 realIrp, 02856 iovPacket 02857 ), 1) ; 02858 02859 iovPacket->Flags |= TRACKFLAG_SWAPPED_BACK ; 02860 IovpTrackingDataReleaseLock(iovPacket) ; 02861 02862 // 02863 // Send the IRP onwards and upwards. 02864 // 02865 IoCompleteRequest(realIrp, priorityBoost) ; 02866 02867 return STATUS_MORE_PROCESSING_REQUIRED ; 02868 } 02869 02870 VOID 02871 FASTCALL 02872 IovpCancelIrp( 02873 IN PIRP Irp, 02874 OUT PBOOLEAN CancelHandled, 02875 OUT PBOOLEAN ReturnValue 02876 ) 02877 /*++ 02878 02879 Description: 02880 02881 This routine is called by IoCancelIrp and returns TRUE iff 02882 the cancelation was handled internally here (in which case 02883 IoCancelIrp should do nothing). 02884 02885 We need to handle the call internally when we are currently 02886 dealing with a surrogate. In this case, we make sure the 02887 surrogate is cancelled instead. 02888 02889 Arguments: 02890 02891 Irp - A pointer to the IRP passed into 02892 IoCancelIrp. 02893 02894 CancelHandled - Indicates whether the IRP cancellation 02895 was handled entirely by this routine. 02896 02897 ReturnValue - Set to the value IoCancelIrp 02898 should return if the IRP cancelation 02899 was handled entirely by this routine. 02900 02901 Return Value: 02902 02903 None. 02904 02905 --*/ 02906 { 02907 PIOV_REQUEST_PACKET iovPacket, iovNextPacket; 02908 PIRP irpToCancel; 02909 KIRQL irql ; 02910 02911 *CancelHandled = FALSE ; 02912 02913 iovPacket = IovpTrackingDataFindAndLock(Irp) ; 02914 if (!iovPacket) { 02915 02916 return ; 02917 } 02918 02919 // 02920 // If the IRP is queued internally, touching it is not very safe as we may 02921 // have temporarily removed the page's backing. Restore the backing while 02922 // under the IRPs track lock. 02923 // 02924 02925 if (iovPacket->Flags&TRACKFLAG_QUEUED_INTERNALLY) { 02926 02927 IovpProtectedIrpMakeTouchable( 02928 Irp, 02929 &iovPacket->RestoreHandle 02930 ); 02931 02932 iovPacket->RestoreHandle = NULL ; 02933 } 02934 02935 if (!(iovPacket->Flags&TRACKFLAG_ACTIVE)) { 02936 02937 // 02938 // We've already completed the IRP, and the only reason it's 02939 // still being tracked is because of it's allocation. 02940 // So it is not ours to cancel. 02941 // 02942 IovpTrackingDataReleaseLock(iovPacket); 02943 return; 02944 } 02945 02946 if (!(iovPacket->Flags&TRACKFLAG_HAS_SURROGATE)) { 02947 02948 // 02949 // Cancel of an IRP that doesn't have an active surrogate. Let it 02950 // proceed normally. 02951 // 02952 IovpTrackingDataReleaseLock(iovPacket); 02953 return; 02954 } 02955 02956 if (iovPacket->AssertFlags&ASSERTFLAG_POLICEIRPS) { 02957 02958 if (Irp->CancelRoutine) { 02959 02960 WDM_FAIL_ROUTINE(( 02961 DCERROR_CANCELROUTINE_ON_FORWARDED_IRP, 02962 DCPARAM_IRP + DCPARAM_ROUTINE, 02963 Irp, 02964 Irp->CancelRoutine 02965 )); 02966 02967 // 02968 // We will ignore this routine. As we should... 02969 // 02970 } 02971 } 02972 02973 iovNextPacket = CONTAINING_RECORD( 02974 iovPacket->SurrogateLink.Flink, 02975 IOV_REQUEST_PACKET, 02976 SurrogateLink 02977 ); 02978 02979 Irp->Cancel = TRUE; 02980 *CancelHandled = TRUE ; 02981 irpToCancel = iovNextPacket->TrackedIrp ; 02982 IovpTrackingDataReleaseLock(iovPacket) ; 02983 *ReturnValue = IoCancelIrp(irpToCancel) ; 02984 02985 return ; 02986 } 02987 02988 VOID 02989 FASTCALL 02990 IovpFreeIrp( 02991 IN PIRP Irp, 02992 IN OUT PBOOLEAN FreeHandled 02993 ) 02994 /*++ 02995 02996 Description: 02997 02998 This routine is called by IoFreeIrp and returns TRUE iff 02999 the free was handled internally here (in which case IoFreeIrp 03000 should do nothing). 03001 03002 We need to handle the call internally because we may turn off lookaside 03003 list cacheing to catch people reusing IRPs after they are freed. 03004 03005 Arguments: 03006 03007 Irp - A pointer to the IRP passed into 03008 IoCancelIrp. 03009 03010 FreeHandled - Indicates whether the free operation was 03011 handled entirely by this routine. 03012 03013 Return Value: 03014 03015 None. 03016 03017 --*/ 03018 { 03019 PIOV_REQUEST_PACKET iovPacket; 03020 PVOID restoreHandle ; 03021 03022 iovPacket = IovpTrackingDataFindAndLock(Irp); 03023 03024 if (iovPacket == NULL) { 03025 03026 // 03027 // ADRIAO BUGBUG 01/06/1999 - 03028 // Below assertion might fire if an IRP allocated then freed twice. 03029 // 03030 ASSERT(!(Irp->AllocationFlags&IRP_ALLOCATION_MONITORED)); 03031 *FreeHandled = FALSE ; 03032 return; 03033 } 03034 03035 if (!IsListEmpty(&Irp->ThreadListEntry)) { 03036 03037 if (iovPacket->AssertFlags&ASSERTFLAG_POLICEIRPS) { 03038 03039 WDM_FAIL_CALLER2( 03040 (DCERROR_FREE_OF_THREADED_IRP, DCPARAM_IRP, Irp) 03041 ); 03042 } 03043 03044 // 03045 // <Grumble> keep us alive by not actually freeing the IRP if someone did 03046 // this to us. We leak for life... 03047 // 03048 *FreeHandled = TRUE ; 03049 return ; 03050 } 03051 03052 if (IovpTrackingDataGetCurrentSessionData(iovPacket)) { 03053 03054 // 03055 // If there's a current session, that means someone is freeing an IRP 03056 // that they don't own. Of course, if the stack unwound badly because 03057 // someone forgot to return PENDING or complete the IRP, then we don't 03058 // assert here (we'd probably end up blaiming kernel). 03059 // 03060 if ((iovPacket->AssertFlags&ASSERTFLAG_POLICEIRPS) && 03061 (!(iovPacket->Flags&TRACKFLAG_UNWOUND_BADLY))) { 03062 03063 WDM_FAIL_CALLER2( 03064 (DCERROR_FREE_OF_INUSE_IRP, DCPARAM_IRP, Irp) 03065 ); 03066 } 03067 03068 // 03069 // <Grumble> keep us alive by not actually freeing the IRP if someone did 03070 // this to us. We leak for life... 03071 // 03072 IovpTrackingDataReleaseLock(iovPacket) ; 03073 *FreeHandled = TRUE ; 03074 return ; 03075 } 03076 03077 if (!(iovPacket->Flags&TRACKFLAG_IO_ALLOCATED)) { 03078 03079 // 03080 // We weren't tracking this at allocation time. We shouldn't got our 03081 // packet unless the IRP had a pointer count still, meaning it's has 03082 // a session. And that should've been caught above. 03083 // 03084 ASSERT(0); 03085 IovpTrackingDataReleaseLock(iovPacket) ; 03086 *FreeHandled = FALSE ; 03087 return; 03088 } 03089 03090 // 03091 // The IRP may have been reinitialized, possibly losing it's allocation 03092 // flags. We catch this bug in the IoInitializeIrp hook. 03093 // 03094 //ASSERT(Irp->AllocationFlags&IRP_ALLOCATION_MONITORED) ; 03095 // 03096 03097 if (!(iovPacket->Flags&TRACKFLAG_PROTECTEDIRP)) { 03098 03099 // 03100 // We're just tagging along this IRP. Drop our pointer count but bail. 03101 // 03102 IovpTrackingDataDereference(iovPacket, IOVREFTYPE_POINTER); 03103 IovpTrackingDataReleaseLock(iovPacket); 03104 *FreeHandled = FALSE; 03105 return; 03106 } 03107 03108 // 03109 // Set up a nice bugcheck for those who free their IRPs twice. This is done 03110 // because the special pool may have been exhausted, in which case the IRP 03111 // can be touched after it has been freed. 03112 // 03113 Irp->Type = 0; 03114 03115 ASSERT(iovPacket) ; 03116 ASSERT(iovPacket->AssertFlags&ASSERTFLAG_POLICEIRPS); 03117 IovpTrackingDataDereference(iovPacket, IOVREFTYPE_POINTER); 03118 ASSERT(iovPacket->PointerCount == 0); 03119 IovpTrackingDataReleaseLock(iovPacket) ; 03120 restoreHandle = IovpProtectedIrpMakeUntouchable(Irp, TRUE) ; 03121 IovpProtectedIrpFree(Irp, &restoreHandle) ; 03122 03123 // 03124 // We handled allocation and initialization. There is nothing much more to 03125 // do. 03126 // 03127 *FreeHandled = TRUE ; 03128 } 03129 03130 VOID 03131 FASTCALL 03132 IovpAllocateIrp1( 03133 IN CCHAR StackSize, 03134 IN BOOLEAN ChargeQuota, 03135 IN OUT PIRP *IrpPointer 03136 ) 03137 /*++ 03138 03139 Description: 03140 03141 This routine is called by IoAllocateIrp and returns an IRP iff 03142 we are handled the allocations ourselves. 03143 03144 We may need to do this internally so we can turn off IRP lookaside lists 03145 and use the special pool to catch people reusing free'd IRPs. 03146 03147 Arguments: 03148 03149 StackSize - Count of stack locations to allocate for this IRP. 03150 03151 ChargeQuote - TRUE if quote should be charged against the current 03152 thread. 03153 03154 IrpPointer - Pointer to IRP if one was allocated. This will 03155 point to NULL after the call iff IoAllocateIrp 03156 should use it's normal lookaside list code. 03157 03158 Return Value: 03159 03160 None. 03161 03162 --*/ 03163 { 03164 PIOV_REQUEST_PACKET iovPacket; 03165 PVOID returnAddress[1]; 03166 ULONG stackHash; 03167 PIRP irp; 03168 03169 *IrpPointer = NULL ; 03170 if (!(IovpTrackingFlags&ASSERTFLAG_MONITOR_ALLOCS)) { 03171 03172 return ; 03173 } 03174 03175 if (!(IovpTrackingFlags&ASSERTFLAG_POLICEIRPS)) { 03176 03177 return ; 03178 } 03179 03180 irp = IovpProtectedIrpAllocate( 03181 StackSize, 03182 ChargeQuota, 03183 PsGetCurrentThread() 03184 ) ; 03185 03186 if (irp == NULL) { 03187 03188 return; 03189 } 03190 03191 IopInitializeIrp(irp, IoSizeOfIrp(StackSize), StackSize); 03192 *IrpPointer = irp; 03193 03194 iovPacket = IovpTrackingDataCreateAndLock(irp); 03195 03196 if (iovPacket == NULL) { 03197 03198 return; 03199 } 03200 03201 IovpTrackingDataReference(iovPacket, IOVREFTYPE_POINTER); 03202 iovPacket->Flags |= TRACKFLAG_PROTECTEDIRP | TRACKFLAG_IO_ALLOCATED; 03203 irp->AllocationFlags |= IRP_ALLOCATION_MONITORED ; 03204 irp->Flags |= IRPFLAG_EXAMINE_TRACKED; 03205 03206 // 03207 // Record he who allocated this IRP (if we can get it) 03208 // 03209 RtlCaptureStackBackTrace(3, IRP_ALLOC_COUNT, iovPacket->AllocatorStack, &stackHash) ; 03210 03211 IovpTrackingDataReleaseLock(iovPacket) ; 03212 } 03213 03214 VOID 03215 FASTCALL 03216 IovpAllocateIrp2( 03217 IN PIRP Irp 03218 ) 03219 /*++ 03220 03221 Description: 03222 03223 This routine is called by IoAllocateIrp and captures information if 03224 the IRP was allocated by the OS. 03225 03226 Arguments: 03227 03228 Irp - Pointer to IRP 03229 03230 Return Value: 03231 03232 None. 03233 03234 --*/ 03235 { 03236 PIOV_REQUEST_PACKET iovPacket; 03237 PVOID returnAddress[1]; 03238 ULONG stackHash; 03239 03240 if (!(IovpTrackingFlags&ASSERTFLAG_MONITOR_ALLOCS)) { 03241 03242 return; 03243 } 03244 03245 // ASSERT(!(IovpTrackingFlags&ASSERTFLAG_POLICEIRPS)); 03246 03247 iovPacket = IovpTrackingDataCreateAndLock(Irp); 03248 if (iovPacket == NULL) { 03249 03250 return; 03251 } 03252 03253 IovpTrackingDataReference(iovPacket, IOVREFTYPE_POINTER); 03254 iovPacket->Flags |= TRACKFLAG_IO_ALLOCATED; 03255 Irp->AllocationFlags |= IRP_ALLOCATION_MONITORED; 03256 Irp->Flags |= IRPFLAG_EXAMINE_TRACKED; 03257 03258 // 03259 // Record he who allocated this IRP (if we can get it) 03260 // 03261 RtlCaptureStackBackTrace(2, IRP_ALLOC_COUNT, iovPacket->AllocatorStack, &stackHash) ; 03262 03263 IovpTrackingDataReleaseLock(iovPacket) ; 03264 } 03265 03266 VOID 03267 FASTCALL 03268 IovpInitializeIrp( 03269 IN OUT PIRP Irp, 03270 IN USHORT PacketSize, 03271 IN CCHAR StackSize, 03272 IN OUT PBOOLEAN InitializeHandled 03273 ) 03274 /*++ 03275 03276 Description: 03277 03278 This routine is called by IoInitializeIrp and sets InitializeHandled to 03279 TRUE if the entire initialization was handled internally. 03280 03281 While here we verify the caller is not Initializing an IRP allocated 03282 through IoAllocateIrp, as doing so means we may leak quota/etc. 03283 03284 Arguments: 03285 03286 Irp - Irp to initialize 03287 03288 PacketSize - Size of the IRP in bytes. 03289 03290 StackSize - Count of stack locations for this IRP. 03291 03292 InitializeHandled - Pointer to a BOOLEAN that will be set to true iff 03293 the initialization of the IRP was handled entirely 03294 within this routine. If FALSE, IoInitializeIrp 03295 should initialize the IRP as normal. 03296 03297 Return Value: 03298 03299 None. 03300 03301 --*/ 03302 { 03303 PIOV_REQUEST_PACKET iovPacket ; 03304 03305 iovPacket = IovpTrackingDataFindAndLock(Irp); 03306 if (iovPacket == NULL) { 03307 03308 *InitializeHandled = FALSE ; 03309 return; 03310 } 03311 03312 if ((iovPacket->AssertFlags&ASSERTFLAG_POLICEIRPS) && 03313 (iovPacket->Flags&TRACKFLAG_IO_ALLOCATED)) { 03314 03315 if (Irp->AllocationFlags&IRP_QUOTA_CHARGED) { 03316 03317 // 03318 // Don't let us leak quota now! 03319 // 03320 WDM_FAIL_CALLER2( 03321 (DCERROR_REINIT_OF_ALLOCATED_IRP_WITH_QUOTA, DCPARAM_IRP, Irp) 03322 ); 03323 03324 } else { 03325 03326 // 03327 // In this case we are draining our lookaside lists erroneously. 03328 // 03329 // WDM_CHASTISE_CALLER2( 03330 // (DCERROR_REINIT_OF_ALLOCATED_IRP_WITHOUT_QUOTA, DCPARAM_IRP, Irp) 03331 // ); 03332 } 03333 } 03334 03335 *InitializeHandled = FALSE ; 03336 IovpTrackingDataReleaseLock(iovPacket) ; 03337 } 03338 03339 /* 03340 * Device Object functions 03341 * IovpExamineDevObjForwarded 03342 * 03343 */ 03344 03345 VOID 03346 IovpAttachDeviceToDeviceStack( 03347 IN PDEVICE_OBJECT NewDevice, 03348 IN PDEVICE_OBJECT ExistingDevice 03349 ) 03350 { 03351 } 03352 03353 VOID 03354 IovpDetachDevice( 03355 IN PDEVICE_OBJECT LowerDevice 03356 ) 03357 { 03358 PDEVOBJ_EXTENSION deviceExtension; 03359 03360 if (LowerDevice->AttachedDevice == NULL) { 03361 03362 WDM_FAIL_CALLER2((DCERROR_DETACH_NOT_ATTACHED, DCPARAM_DEVOBJ, LowerDevice)); 03363 } else { 03364 03365 // 03366 // ADRIAO BUGBUG 01/07/1999 - 03367 // As the stack can be torn apart simulatenously from above and 03368 // below during a remove IRP, we cannot assert the below, and moreover 03369 // changes to the ExtensionFlags will have to involve walking the tree. 03370 // 03371 // ASSERT(LowerDevice->AttachedDevice->AttachedDevice == NULL); 03372 // 03373 deviceExtension = LowerDevice->AttachedDevice->DeviceObjectExtension; 03374 deviceExtension->ExtensionFlags &=~ (DOE_EXAMINED | DOE_TRACKED); 03375 } 03376 } 03377 03378 VOID 03379 IovpDeleteDevice( 03380 IN PDEVICE_OBJECT DeviceObject 03381 ) 03382 { 03383 PDEVICE_OBJECT deviceBelow; 03384 03385 // 03386 // ADRIAO BUGBUG 03/03/1999 - 03387 // Complain if the dude already deleted himself. 03388 // 03389 03390 deviceBelow = IovpGetDeviceAttachedTo(DeviceObject); 03391 if (deviceBelow) { 03392 03393 WDM_FAIL_CALLER1((DCERROR_DELETE_WHILE_ATTACHED, 0)); 03394 ObDereferenceObject(deviceBelow); 03395 } 03396 } 03397 03398 VOID 03399 IovpReexamineAllStacks( 03400 VOID 03401 ) 03402 { 03403 PAGED_CODE(); 03404 03405 ObEnumerateObjectsByType( 03406 IoDeviceObjectType, 03407 IovpEnumDevObjCallback, 03408 NULL 03409 ); 03410 } 03411 03412 BOOLEAN 03413 IovpEnumDevObjCallback( 03414 IN PVOID Object, 03415 IN PUNICODE_STRING ObjectName, 03416 IN ULONG HandleCount, 03417 IN ULONG PointerCount, 03418 IN PVOID Context 03419 ) 03420 { 03421 PDEVICE_OBJECT deviceObject; 03422 PDEVOBJ_EXTENSION deviceExtension; 03423 03424 deviceObject = (PDEVICE_OBJECT) Object; 03425 deviceExtension = deviceObject->DeviceObjectExtension; 03426 03427 if (PointerCount || HandleCount) { 03428 03429 deviceExtension->ExtensionFlags &=~ (DOE_EXAMINED | DOE_TRACKED); 03430 } 03431 03432 return TRUE; 03433 } 03434 03435 BOOLEAN 03436 IovpIsInterestingStack( 03437 IN PDEVICE_OBJECT DeviceObject 03438 ) 03439 { 03440 PDEVOBJ_EXTENSION deviceExtension; 03441 PDEVICE_OBJECT currentDevObj, deviceAttachedTo; 03442 BOOLEAN stackIsInteresting; 03443 KIRQL irql; 03444 03445 // 03446 // Walk downward until we find the PDO or an examined device object. 03447 // 03448 ExAcquireFastLock( &IopDatabaseLock, &irql ); 03449 03450 // 03451 // Quickly check the top of the stack... 03452 // 03453 if (DeviceObject->DeviceObjectExtension->ExtensionFlags & DOE_EXAMINED) { 03454 03455 stackIsInteresting = 03456 ((DeviceObject->DeviceObjectExtension->ExtensionFlags & DOE_TRACKED) != 0); 03457 03458 ExReleaseFastLock( &IopDatabaseLock, irql ); 03459 return stackIsInteresting; 03460 } 03461 03462 // 03463 // OK, if the top hasn't been examined, odds are devices below it haven't 03464 // either. Walk downwards until we can determine whether the stack as a 03465 // whole should be tracked. 03466 // 03467 stackIsInteresting = FALSE; 03468 deviceAttachedTo = DeviceObject; 03469 do { 03470 currentDevObj = deviceAttachedTo; 03471 deviceExtension = currentDevObj->DeviceObjectExtension; 03472 deviceAttachedTo = deviceExtension->AttachedTo; 03473 03474 // 03475 // Remember this... 03476 // 03477 if (IovpIsInterestingDriver(currentDevObj->DriverObject)) { 03478 03479 stackIsInteresting = TRUE; 03480 } 03481 03482 } while (deviceAttachedTo && 03483 (deviceAttachedTo->DeviceObjectExtension->ExtensionFlags & DOE_EXAMINED) 03484 ); 03485 03486 if (deviceAttachedTo && 03487 (deviceAttachedTo->DeviceObjectExtension->ExtensionFlags & DOE_TRACKED)) { 03488 03489 // 03490 // Propogate upwards the "interesting-ness" of the last examined device 03491 // in the stack... 03492 // 03493 stackIsInteresting = TRUE; 03494 } 03495 03496 // 03497 // Walk upwards, marking everything examined and appropriately tracked. 03498 // 03499 do { 03500 deviceExtension = currentDevObj->DeviceObjectExtension; 03501 03502 if (stackIsInteresting) { 03503 03504 deviceExtension->ExtensionFlags |= DOE_TRACKED; 03505 } else { 03506 03507 deviceExtension->ExtensionFlags &=~ DOE_TRACKED; 03508 } 03509 03510 deviceExtension->ExtensionFlags |= DOE_EXAMINED; 03511 03512 currentDevObj = currentDevObj->AttachedDevice; 03513 03514 } while (currentDevObj); 03515 03516 ExReleaseFastLock( &IopDatabaseLock, irql ); 03517 return stackIsInteresting; 03518 } 03519 03520 BOOLEAN 03521 IovpIsInterestingDriver( 03522 IN PDRIVER_OBJECT DriverObject 03523 ) 03524 { 03525 if (IovpInitFlags&IOVERIFIERINIT_VERIFIER_DRIVER_LIST) { 03526 03527 return (BOOLEAN) MmIsDriverVerifying(DriverObject); 03528 03529 } else { 03530 03531 return TRUE; 03532 } 03533 } 03534 03535 VOID 03536 FASTCALL 03537 IovpExamineDevObjForwarding( 03538 IN PDEVICE_OBJECT DeviceBeingCalled, 03539 IN PDEVICE_OBJECT DeviceLastCalled, 03540 OUT PULONG ForwardTechnique 03541 ) 03542 /*++ 03543 03544 Returns: 03545 03546 STARTED_TOP_OF_STACK 03547 FORWARDED_TO_NEXT_DO 03548 SKIPPED_A_DO 03549 STARTED_INSIDE_STACK 03550 CHANGED_STACKS_AT_BOTTOM 03551 CHANGED_STACKS_MID_STACK 03552 03553 --*/ 03554 03555 { 03556 PDEVICE_OBJECT upperDevobj, lowerObject ; 03557 ULONG result ; 03558 KIRQL irql; 03559 03560 lowerObject = IovpGetDeviceAttachedTo(DeviceLastCalled) ; 03561 03562 ExAcquireFastLock( &IopDatabaseLock, &irql ); 03563 03564 // 03565 // Nice and simple. Walk the device being called 03566 // upwards and find either NULL or the last device 03567 // we called. 03568 // 03569 upperDevobj = DeviceBeingCalled->AttachedDevice ; 03570 while(upperDevobj && (upperDevobj != DeviceLastCalled)) { 03571 03572 upperDevobj = upperDevobj->AttachedDevice ; 03573 } 03574 03575 if (DeviceLastCalled == NULL) { 03576 03577 // 03578 // This is a newly started IRP, was it targetted 03579 // at the top of a stack or at the middle/bottom? 03580 // 03581 result = (DeviceBeingCalled->AttachedDevice) ? STARTED_INSIDE_STACK : 03582 STARTED_TOP_OF_STACK ; 03583 03584 } else if (upperDevobj == NULL) { 03585 03586 // 03587 // We were forwarded the Irp beyond our own stack 03588 // 03589 result = (lowerObject) ? CHANGED_STACKS_MID_STACK : 03590 CHANGED_STACKS_AT_BOTTOM ; 03591 03592 } else if (DeviceBeingCalled->AttachedDevice == upperDevobj) { 03593 03594 result = FORWARDED_TO_NEXT_DO ; 03595 03596 // 03597 // Quick assertion, if LastDevice was non-NULL, the 03598 // device under him should be the one we are calling... 03599 // 03600 ASSERT(lowerObject == DeviceBeingCalled) ; 03601 03602 } else { 03603 03604 // 03605 // DeviceLastCalled was found higher in the stack, but wasn't 03606 // directly above DeviceBeingCalled 03607 // 03608 result = SKIPPED_A_DO ; 03609 } 03610 03611 ExReleaseFastLock( &IopDatabaseLock, irql ); 03612 if (lowerObject) { 03613 ObDereferenceObject(lowerObject) ; 03614 } 03615 *ForwardTechnique = result ; 03616 } 03617 03618 PDEVICE_OBJECT 03619 FASTCALL 03620 IovpGetDeviceAttachedTo( 03621 IN PDEVICE_OBJECT DeviceObject 03622 ) 03623 { 03624 PDEVOBJ_EXTENSION deviceExtension; 03625 PDEVICE_OBJECT deviceAttachedTo ; 03626 KIRQL irql ; 03627 03628 if (DeviceObject == NULL) { 03629 03630 return NULL ; 03631 } 03632 03633 ExAcquireFastLock( &IopDatabaseLock, &irql ); 03634 03635 deviceExtension = DeviceObject->DeviceObjectExtension; 03636 deviceAttachedTo = deviceExtension->AttachedTo ; 03637 03638 if (deviceAttachedTo) { 03639 ObReferenceObject(deviceAttachedTo) ; 03640 } 03641 03642 ExReleaseFastLock( &IopDatabaseLock, irql ); 03643 return deviceAttachedTo ; 03644 } 03645 03646 PDEVICE_OBJECT 03647 FASTCALL 03648 IovpGetLowestDevice( 03649 IN PDEVICE_OBJECT DeviceObject 03650 ) 03651 /*++ 03652 03653 Opposite of IoGetAttachedDeviceReference 03654 03655 --*/ 03656 { 03657 PDEVOBJ_EXTENSION deviceExtension; 03658 PDEVICE_OBJECT lowerDevobj, deviceAttachedTo ; 03659 KIRQL irql ; 03660 03661 deviceAttachedTo = DeviceObject ; 03662 03663 ExAcquireFastLock( &IopDatabaseLock, &irql ); 03664 03665 do { 03666 lowerDevobj = deviceAttachedTo ; 03667 deviceExtension = lowerDevobj->DeviceObjectExtension; 03668 deviceAttachedTo = deviceExtension->AttachedTo ; 03669 03670 } while ( deviceAttachedTo ); 03671 03672 ObReferenceObject(lowerDevobj) ; 03673 03674 ExReleaseFastLock( &IopDatabaseLock, irql ); 03675 return lowerDevobj ; 03676 } 03677 03678 VOID 03679 FASTCALL 03680 IovpAssertNonLegacyDevice( 03681 IN PDEVICE_OBJECT DeviceObject, 03682 IN ULONG StackFramesToSkip, 03683 IN PUCHAR FailureTxt 03684 ) 03685 /*++ 03686 03687 --*/ 03688 { 03689 PDEVICE_OBJECT pdoDeviceObject ; 03690 PDEVICE_NODE pDevNode ; 03691 03692 pdoDeviceObject = IovpGetLowestDevice(DeviceObject) ; 03693 03694 if (pdoDeviceObject) { 03695 03696 pDevNode = pdoDeviceObject->DeviceObjectExtension->DeviceNode ; 03697 if (pDevNode&&(!(pDevNode->Flags&DNF_LEGACY_DRIVER))) { 03698 03699 // 03700 // ADRIAO BUGBUG 12/30/98 - More stuff to fix... 03701 // 03702 ASSERT(0); 03703 /* 03704 WDM_FAIL_CALLER( 03705 (FailureTxt), 03706 StackFramesToSkip+1, 03707 NULL 03708 ); 03709 */ 03710 } 03711 ObDereferenceObject(pdoDeviceObject) ; 03712 } 03713 } 03714 03715 BOOLEAN 03716 FASTCALL 03717 IovpIsInFdoStack( 03718 IN PDEVICE_OBJECT DeviceObject 03719 ) 03720 { 03721 PDEVOBJ_EXTENSION deviceExtension; 03722 PDEVICE_OBJECT deviceAttachedTo, lowerDevobj ; 03723 KIRQL irql ; 03724 03725 deviceAttachedTo = DeviceObject ; 03726 03727 ExAcquireFastLock( &IopDatabaseLock, &irql ); 03728 03729 do { 03730 if (deviceAttachedTo->DeviceObjectExtension->ExtensionFlags&DOE_BOTTOM_OF_FDO_STACK) { 03731 break; 03732 } 03733 deviceAttachedTo = deviceAttachedTo->DeviceObjectExtension->AttachedTo ; 03734 03735 } while ( deviceAttachedTo ); 03736 03737 ExReleaseFastLock( &IopDatabaseLock, irql ); 03738 return (deviceAttachedTo != NULL) ; 03739 } 03740 03741 VOID 03742 FASTCALL 03743 IovpSeedOnePage( 03744 VOID 03745 ) 03746 { 03747 ULONG StackSeed[(PAGE_SIZE/sizeof(ULONG))] ; 03748 ULONG register i ; 03749 03750 // 03751 // We use the return value 0xFFFFFFFF, as it is an illegal return value. We 03752 // are trying to catch people who don't initialize NTSTATUS, and it's also 03753 // a good pointer trap too. 03754 // 03755 for(i=0; i<(PAGE_SIZE/sizeof(ULONG)); i++) StackSeed[i]=0xFFFFFFFF ; 03756 } 03757 03758 VOID 03759 FASTCALL 03760 IovpSeedTwoPages( 03761 VOID 03762 ) 03763 { 03764 ULONG StackSeed[(PAGE_SIZE*2/sizeof(ULONG))] ; 03765 ULONG register i ; 03766 03767 for(i=0; i<(PAGE_SIZE*2/sizeof(ULONG)); i++) StackSeed[i]=0xFFFFFFFF ; 03768 } 03769 03770 VOID 03771 FASTCALL 03772 IovpSeedThreePages( 03773 VOID 03774 ) 03775 { 03776 ULONG register i ; 03777 ULONG StackSeed[(PAGE_SIZE*3/sizeof(ULONG))] ; 03778 03779 for(i=0; i<(PAGE_SIZE*3/sizeof(ULONG)); i++) StackSeed[i]=0xFFFFFFFF ; 03780 } 03781 03782 VOID 03783 FASTCALL 03784 IovpSeedStack( 03785 VOID 03786 ) 03787 /*++ 03788 03789 Description: 03790 03791 This routine "seeds" the stack so that uninitialized variables are 03792 more easily ferreted out. 03793 03794 ADRIAO BUGBUG 08/17/98 - This is a really neat idea that runs into a 03795 memory manager optimization. While I do find 03796 the appropriate guard page, the memory manager 03797 throws out the above touched pages on a thread 03798 switch and bring in new (and probably zero'd) 03799 ones. 03800 03801 Arguments: None 03802 03803 Return Value: None 03804 03805 --*/ 03806 { 03807 int i, interruptReservedOverhead ; 03808 03809 if (!(IovpTrackingFlags&ASSERTFLAG_SEEDSTACK)) { 03810 return ; 03811 } 03812 03813 // 03814 // Is there room to try this before we run out of stack? We will reserve 03815 // half a page for interrupt overhead... 03816 // 03817 interruptReservedOverhead = PAGE_SIZE/2 ; 03818 03819 // 03820 // There must be a guard page somewhere. Find it... 03821 // 03822 for(i=0; i<4; i++) { 03823 if (!MmIsAddressValid(((PUCHAR)&i)-i*PAGE_SIZE-interruptReservedOverhead)) { 03824 break; 03825 } 03826 } 03827 03828 switch(i) { 03829 case 4: IovpSeedThreePages() ; break ; 03830 case 3: IovpSeedTwoPages() ; break ; 03831 case 2: IovpSeedOnePage() ; break ; 03832 case 1: break ; // Minimum is overhead 03833 case 0: break ; // Umm, we don't even have overhead! 03834 default: break ; 03835 } 03836 } 03837 03838 #endif // NO_SPECIAL_IRP 03839 03840 03841

Generated on Sat May 15 19:42:02 2004 for test by doxygen 1.3.7