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

hashirp.c

Go to the documentation of this file.
00001 #include "iop.h" 00002 00003 // 00004 // This entire file is only present if NO_SPECIAL_IRP isn't defined 00005 // 00006 #ifndef NO_SPECIAL_IRP 00007 00008 // 00009 // When enabled, everything is locked down on demand... 00010 // 00011 #ifdef ALLOC_PRAGMA 00012 #pragma alloc_text(PAGE, IovpTrackingDataInit) 00013 #pragma alloc_text(PAGEVRFY, IovpTrackingDataFindPointer) 00014 #pragma alloc_text(PAGEVRFY, IovpTrackingDataFindAndLock) 00015 #pragma alloc_text(PAGEVRFY, IovpTrackingDataCreateAndLock) 00016 #pragma alloc_text(PAGEVRFY, IovpTrackingDataGetCurrentSessionData) 00017 #pragma alloc_text(PAGEVRFY, IovpTrackingDataFree) 00018 #pragma alloc_text(PAGEVRFY, IovpTrackingDataAcquireLock) 00019 #pragma alloc_text(PAGEVRFY, IovpTrackingDataReleaseLock) 00020 #pragma alloc_text(PAGEVRFY, IovpTrackingDataReference) 00021 #pragma alloc_text(PAGEVRFY, IovpTrackingDataDereference) 00022 #pragma alloc_text(PAGEVRFY, IovpWatermarkIrp) 00023 #endif 00024 00025 #define POOL_TAG_TRACKING_DATA 'tprI' 00026 #define POOL_TAG_PROTECTED_IRP '+prI' 00027 00028 // 00029 // Debug spew level 00030 // 00031 ULONG IovpIrpTrackingSpewLevel = 0 ; 00032 00033 // 00034 // This is our IRP tracking table, a hash table that points to a block of 00035 // data associated with each IRP. 00036 // 00037 LIST_ENTRY IovpIrpTrackingTable[IRP_TRACKING_HASH_SIZE]; 00038 KSPIN_LOCK IovpIrpHashLock; 00039 00040 /* 00041 * The 10 routines listed below - 00042 * IovpTrackingDataInit 00043 * IovpTrackingDataCreateAndLock 00044 * IovpTrackingDataFindAndLock 00045 * IovpTrackingDataGetCurrentSessionData 00046 * IovpTrackingDataReference 00047 * IovpTrackingDataDereference 00048 * IovpTrackingDataAcquireLock 00049 * IovpTrackingDataReleaseLock 00050 * IovpTrackingDataFree - (internal) 00051 * IovpTrackingDataFindPointer - (internal) 00052 * 00053 * - handle the IRP tracking structures. This is an allocation of memory 00054 * that lives alongside the IRP. We need this as the IRP structure and 00055 * size are things that drivers must pass around, so we cannot add this 00056 * information into the IRP itself by expanding it's size. We use a hash 00057 * table setup to quickly find the IRPs in our table, so not too much time 00058 * is lost. 00059 * 00060 * Locking semantics: No IRP may be removed from or inserted into the table 00061 * without the HashLock being taken. Furthermore at some point in the lifetime 00062 * of the tracking data the pointer to the IRP may be zero'd, making it 00063 * "unreachable". This zeroing of the IRP pointer must also happen under the 00064 * hash lock. 00065 * 00066 * Three functions may be called to retrieve tracking data, the create and find 00067 * instructions. The acquire lock function can be used if you already have a 00068 * referenced pointer to the tracking data and merely need to lock it. None of 00069 * these functions add a reference to the object. Reference counts aren't 00070 * examined until the lock on the tracking data is dropped (ReleaseLock). 00071 * First the PointerCount member is first checked to see if the tracking 00072 * data should be marked "unreachable" (TrackedIrp = NULL). Then ReferenceCount 00073 * is examined to see if the tracking data can be freed. 00074 * 00075 * Note that find searches the table holding the hashlock. If an entry is found 00076 * a handoff to the IRP specific lock must be executed. This is done by 00077 * incrementing the ReferenceCount and then releasing the hash lock to ensure 00078 * the packet stays in the table. The hash lock is then dropped and the IRPlock 00079 * picked up. Note that ReferenceCount is only dropped under the held IRPlock 00080 * though, allowing us to avoid taking it to examining the count under the 00081 * hash lock as often as possible. 00082 * 00083 * Perf - The hashlock should be replaced with an array of 00084 * IRP_TRACKING_HASH_SIZE hashlocks with little cost. 00085 */ 00086 00087 VOID 00088 FASTCALL 00089 IovpTrackingDataInit( 00090 VOID 00091 ) 00092 /*++ 00093 00094 Description: 00095 00096 This routine initializes all the important structures we use to track 00097 IRPs through the hash tables. 00098 00099 Arguments: 00100 00101 None 00102 00103 Return Value: 00104 00105 None 00106 00107 --*/ 00108 { 00109 ULONG i; 00110 00111 PAGED_CODE(); 00112 00113 KeInitializeSpinLock( &IovpIrpHashLock ); 00114 for(i=0; i<IRP_TRACKING_HASH_SIZE; i++) { 00115 00116 InitializeListHead(IovpIrpTrackingTable+i); 00117 } 00118 } 00119 00120 PIOV_REQUEST_PACKET 00121 FASTCALL 00122 IovpTrackingDataCreateAndLock( 00123 IN PIRP Irp 00124 ) 00125 /*++ 00126 00127 Description: 00128 00129 This routine creates a tracking packet for a new IRP. The IRP does not get 00130 an initial reference count however. IovpTrackingDataReleaseLock must be 00131 called to drop the lock. 00132 00133 Arguments: 00134 00135 Irp - Irp to begin tracking. 00136 00137 Return Value: 00138 00139 iovPacket block, NULL if no memory. 00140 00141 --*/ 00142 { 00143 KIRQL oldIrql; 00144 PIOV_REQUEST_PACKET iovPacket; 00145 PLIST_ENTRY hashHead; 00146 ULONG trackingDataSize; 00147 LONG newCount; 00148 00149 ExAcquireSpinLock( &IovpIrpHashLock, &oldIrql ); 00150 00151 iovPacket = IovpTrackingDataFindPointer(Irp, &hashHead) ; 00152 00153 ASSERT(!iovPacket) ; 00154 00155 // 00156 // One extra stack location is allocated as the "zero'th" is used to 00157 // simplify some logic... 00158 // 00159 trackingDataSize = sizeof(IOV_REQUEST_PACKET)+Irp->StackCount*sizeof(IOV_STACK_LOCATION) ; 00160 00161 iovPacket = ExAllocatePoolWithTag( 00162 NonPagedPool, 00163 trackingDataSize, 00164 POOL_TAG_TRACKING_DATA 00165 ); 00166 00167 if (!iovPacket) { 00168 00169 ExReleaseSpinLock( &IovpIrpHashLock, oldIrql ); 00170 return iovPacket; 00171 } 00172 00173 //RtlZeroMemory(iovPacket, trackingDataSize) ; 00174 00175 // 00176 // From top to bottom, initialize the fields. Note that there is not a 00177 // "surrogateHead". If any code needs to find out the first entry in the 00178 // circularly linked list of IRPs (the first is the only non-surrogate IRP), 00179 // then HeadPacket should be used. Note that the link to the session is 00180 // stored by the headPacket, more on this later. 00181 // 00182 iovPacket->TrackedIrp = Irp; 00183 KeInitializeSpinLock( &iovPacket->IrpLock ); 00184 iovPacket->ReferenceCount = 1; 00185 iovPacket->PointerCount = 0; 00186 iovPacket->Flags = 0; 00187 InitializeListHead(&iovPacket->HashLink); 00188 InitializeListHead(&iovPacket->SurrogateLink); 00189 InitializeListHead(&iovPacket->SessionHead); 00190 iovPacket->HeadPacket = iovPacket; 00191 iovPacket->StackCount = Irp->StackCount; 00192 iovPacket->AssertFlags = IovpTrackingFlags; 00193 iovPacket->RealIrpCompletionRoutine = NULL; 00194 iovPacket->RealIrpControl = 0; 00195 iovPacket->RealIrpContext = NULL; 00196 iovPacket->TopStackLocation = 0; 00197 iovPacket->PriorityBoost = 0; 00198 iovPacket->LastLocation = 0; 00199 iovPacket->RefTrackingCount =0; 00200 iovPacket->RestoreHandle = NULL; 00201 iovPacket->pIovSessionData = NULL; 00202 00203 // 00204 // Place into hash table under lock (with the initial reference count) 00205 // 00206 InsertHeadList(hashHead, &iovPacket->HashLink); 00207 00208 ExReleaseSpinLock( &IovpIrpHashLock, oldIrql ); 00209 00210 ExAcquireSpinLock( &iovPacket->IrpLock, &iovPacket->CallerIrql ); 00211 00212 newCount = InterlockedDecrement(&iovPacket->ReferenceCount); 00213 00214 // 00215 // If this assert gets hit it means somebody got hold of tracking data 00216 // at a very odd (and probably buggy) time. Actually, this might happen 00217 // if an IRP was cancelled right as it entered IoCallDriver... 00218 // 00219 //ASSERT(newCount == 0); 00220 00221 TRACKIRP_DBGPRINT(( 00222 " VRP CREATE(%x)->%x\n", 00223 Irp, 00224 iovPacket 00225 ), 3) ; 00226 00227 return iovPacket ; 00228 } 00229 00230 VOID 00231 FASTCALL 00232 IovpTrackingDataFree( 00233 IN PIOV_REQUEST_PACKET IovPacket 00234 ) 00235 /*++ 00236 00237 Description: 00238 00239 This routine free's the tracking data. The tracking data should already 00240 have been removed from the table by a call to IovpTrackingDataReleaseLock 00241 with the ReferenceCount at 0. 00242 00243 Arguments: 00244 00245 IovPacket - Tracking data to free. 00246 00247 Return Value: 00248 00249 Nope. 00250 00251 --*/ 00252 { 00253 // 00254 // The list entry is inited to point back to itself when removed. The 00255 // pointer count should of course still be zero. 00256 // 00257 IovPacket->Flags|=TRACKFLAG_REMOVED_FROM_TABLE ; 00258 ASSERT(IsListEmpty(&IovPacket->HashLink)) ; 00259 00260 // 00261 // with no reference counts... 00262 // 00263 ASSERT(!IovPacket->ReferenceCount) ; 00264 ASSERT(!IovPacket->PointerCount) ; 00265 00266 TRACKIRP_DBGPRINT(( 00267 " VRP FREE(%x)x\n", 00268 IovPacket 00269 ), 3) ; 00270 00271 ExFreePool(IovPacket) ; 00272 } 00273 00274 PIOV_REQUEST_PACKET 00275 FASTCALL 00276 IovpTrackingDataFindAndLock( 00277 IN PIRP Irp 00278 ) 00279 /*++ 00280 00281 Description: 00282 00283 This routine will return the tracking data for an IRP that is 00284 being tracked without a surrogate or the tracking data for with 00285 a surrogate if the surrogate IRP is what was passed in. 00286 00287 Arguments: 00288 00289 Irp - Irp to find. 00290 00291 Return Value: 00292 00293 IovPacket block, iff above conditions are satified. 00294 00295 --*/ 00296 { 00297 KIRQL oldIrql ; 00298 PIOV_REQUEST_PACKET iovPacket ; 00299 PLIST_ENTRY listHead; 00300 00301 ASSERT(Irp) ; 00302 ExAcquireSpinLock( &IovpIrpHashLock, &oldIrql ); 00303 00304 iovPacket = IovpTrackingDataFindPointer(Irp, &listHead) ; 00305 00306 if (!iovPacket) { 00307 00308 ExReleaseSpinLock( &IovpIrpHashLock, oldIrql ); 00309 return NULL; 00310 } 00311 00312 InterlockedIncrement(&iovPacket->ReferenceCount); 00313 00314 ExReleaseSpinLock( &IovpIrpHashLock, oldIrql ); 00315 00316 IovpTrackingDataAcquireLock(iovPacket) ; 00317 iovPacket->CallerIrql = oldIrql; 00318 00319 InterlockedDecrement(&iovPacket->ReferenceCount); 00320 00321 if (iovPacket->TrackedIrp == NULL) { 00322 00323 ASSERT(0); 00324 // 00325 // Someone IRP is being mishandled, we got in a race condition where 00326 // we got the packet but the pointer count decayed to zero. Therefore 00327 // we do not want this packet so we will return NULL after dropping 00328 // it's lock. This sort of thing really shouldn't happen ya know. 00329 // 00330 IovpTrackingDataReleaseLock(iovPacket); 00331 return NULL; 00332 } 00333 00334 TRACKIRP_DBGPRINT(( 00335 " VRP FIND(%x)->%x\n", 00336 Irp, 00337 iovPacket 00338 ), 3) ; 00339 00340 return iovPacket; 00341 } 00342 00343 PIOV_REQUEST_PACKET 00344 FASTCALL 00345 IovpTrackingDataFindPointer( 00346 IN PIRP Irp, 00347 OUT PLIST_ENTRY *HashHead 00348 ) 00349 /*++ 00350 00351 Description: 00352 00353 This routine returns a pointer to a pointer to the Irp tracking data. 00354 This function is meant to be called by other routines in this file. 00355 00356 N.B. The tracking lock is assumed to be held by the caller. 00357 00358 Arguments: 00359 00360 Irp - Irp to locate in the tracking table. 00361 00362 HashHead - If return is non-null, points to the 00363 list head that should be used to insert 00364 the IRP. 00365 00366 Return Value: 00367 00368 IrpTrackingData iff found, NULL otherwise. 00369 00370 --*/ 00371 { 00372 KIRQL oldIrql ; 00373 PIOV_REQUEST_PACKET iovPacket ; 00374 PLIST_ENTRY listEntry, listHead; 00375 UINT_PTR hash ; 00376 00377 ASSERT_SPINLOCK_HELD(&IovpIrpHashLock) ; 00378 00379 hash = (((UINT_PTR) Irp)/PAGE_SIZE)*IRP_TRACKING_HASH_PRIME ; 00380 hash %= IRP_TRACKING_HASH_SIZE ; 00381 00382 *HashHead = listHead = IovpIrpTrackingTable + hash ; 00383 00384 for(listEntry = listHead; 00385 listEntry->Flink != listHead; 00386 listEntry = listEntry->Flink) { 00387 00388 iovPacket = CONTAINING_RECORD(listEntry->Flink, IOV_REQUEST_PACKET, HashLink); 00389 00390 if (iovPacket->TrackedIrp == Irp) { 00391 00392 return iovPacket; 00393 } 00394 } 00395 00396 return NULL ; 00397 } 00398 00399 VOID 00400 FASTCALL 00401 IovpTrackingDataAcquireLock( 00402 IN PIOV_REQUEST_PACKET IovPacket OPTIONAL 00403 ) 00404 /*++ 00405 00406 Description: 00407 00408 This routine is called by to acquire the IRPs tracking data lock. 00409 00410 Incoming IRQL must be the same as the callers (IoCallDriver, IoCompleteRequest) 00411 We may be at DPC level when we return. Callers *must* follow up with 00412 IovpTrackingDataReleaseLock. 00413 00414 Arguments: 00415 00416 IovPacket - Pointer to the IRP tracking data (or NULL, in which 00417 case this routine does nothing). 00418 00419 Return Value: 00420 00421 None. 00422 --*/ 00423 { 00424 KIRQL oldIrql ; 00425 PIOV_REQUEST_PACKET iovCurPacket; 00426 00427 if (!IovPacket) { 00428 00429 return ; 00430 } 00431 00432 iovCurPacket = IovPacket; 00433 ASSERT(iovCurPacket->ReferenceCount != 0); 00434 while(1) { 00435 00436 ExAcquireSpinLock( &iovCurPacket->IrpLock, &oldIrql ); 00437 iovCurPacket->CallerIrql = oldIrql ; 00438 00439 if (iovCurPacket == IovPacket->HeadPacket) { 00440 00441 break; 00442 } 00443 00444 iovCurPacket = CONTAINING_RECORD( 00445 iovCurPacket->SurrogateLink.Blink, 00446 IOV_REQUEST_PACKET, 00447 SurrogateLink 00448 ); 00449 } 00450 } 00451 00452 VOID 00453 FASTCALL 00454 IovpTrackingDataReleaseLock( 00455 IN PIOV_REQUEST_PACKET IovPacket 00456 ) 00457 /*++ 00458 00459 Description: 00460 00461 This routine releases the IRPs tracking data lock and adjusts the ref count 00462 as appropriate. If the reference count drops to zero, the tracking data is 00463 freed. 00464 00465 Arguments: 00466 00467 IovPacket - Pointer to the IRP tracking data. 00468 00469 Return Value: 00470 00471 None. 00472 00473 --*/ 00474 { 00475 BOOLEAN freeTrackingData; 00476 PIOV_REQUEST_PACKET iovCurPacket, iovHeadPacket, iovNextPacket; 00477 KIRQL oldIrql; 00478 00479 // 00480 // Pass one, delink anyone from the tree who's leaving, and assert that 00481 // no surrogates are left after a freed one. 00482 // 00483 iovCurPacket = iovHeadPacket = IovPacket->HeadPacket; 00484 while(1) { 00485 00486 ASSERT_SPINLOCK_HELD(&iovCurPacket->IrpLock); 00487 00488 iovNextPacket = CONTAINING_RECORD( 00489 iovCurPacket->SurrogateLink.Flink, 00490 IOV_REQUEST_PACKET, 00491 SurrogateLink 00492 ); 00493 00494 // 00495 // PointerCount is always referenced under the IRP lock. 00496 // 00497 if (iovCurPacket->PointerCount == 0) { 00498 00499 ExAcquireSpinLock( &IovpIrpHashLock, &oldIrql ); 00500 00501 // 00502 // This field may be examined only under the hash lock. 00503 // 00504 if (iovCurPacket->TrackedIrp) { 00505 00506 iovCurPacket->TrackedIrp->Flags &=~ IRPFLAG_EXAMINE_MASK; 00507 iovCurPacket->TrackedIrp = NULL; 00508 } 00509 00510 ExReleaseSpinLock( &IovpIrpHashLock, oldIrql ); 00511 } 00512 00513 // 00514 // We now remove any entries that will be leaving from the hash table. 00515 // Note that the ReferenceCount may be incremented outside the IRP lock 00516 // (but under the hash lock) but ReferenceCount can never be dropped 00517 // outside of the IRP lock. Therefore for performance we check once 00518 // and then take the lock to prevent anyone finding it and incrementing 00519 // it. 00520 // 00521 00522 if (iovCurPacket->ReferenceCount == 0) { 00523 00524 ExAcquireSpinLock( &IovpIrpHashLock, &oldIrql ); 00525 00526 if (iovCurPacket->ReferenceCount ==0) { 00527 00528 ASSERT(iovCurPacket->PointerCount == 0); 00529 ASSERT((iovCurPacket->pIovSessionData == NULL) || 00530 (iovCurPacket != iovHeadPacket)); 00531 ASSERT((iovNextPacket->ReferenceCount == 0) || 00532 (iovNextPacket == iovHeadPacket)); 00533 00534 RemoveEntryList(&iovCurPacket->HashLink); 00535 00536 InitializeListHead(&iovCurPacket->HashLink); 00537 } 00538 ExReleaseSpinLock( &IovpIrpHashLock, oldIrql ); 00539 } 00540 00541 if (iovCurPacket == IovPacket) { 00542 00543 break; 00544 } 00545 00546 iovCurPacket = iovNextPacket; 00547 } 00548 00549 // 00550 // Pass two, drop locks and free neccessary data. 00551 // 00552 iovCurPacket = iovHeadPacket; 00553 while(1) { 00554 00555 freeTrackingData = IsListEmpty(&iovCurPacket->HashLink); 00556 00557 iovNextPacket = CONTAINING_RECORD( 00558 iovCurPacket->SurrogateLink.Flink, 00559 IOV_REQUEST_PACKET, 00560 SurrogateLink 00561 ); 00562 00563 ExReleaseSpinLock(&iovCurPacket->IrpLock, iovCurPacket->CallerIrql) ; 00564 00565 if (freeTrackingData) { 00566 00567 RemoveEntryList(&iovCurPacket->SurrogateLink); 00568 InitializeListHead(&iovCurPacket->SurrogateLink); 00569 00570 IovpTrackingDataFree(iovCurPacket) ; 00571 } 00572 00573 if (iovCurPacket == IovPacket) { 00574 00575 break; 00576 } 00577 00578 iovCurPacket = iovNextPacket; 00579 } 00580 } 00581 00582 VOID 00583 FASTCALL 00584 IovpTrackingDataReference( 00585 IN PIOV_REQUEST_PACKET IovPacket, 00586 IN IOV_REFERENCE_TYPE IovRefType 00587 ) 00588 { 00589 ASSERT_SPINLOCK_HELD(&IovPacket->IrpLock); 00590 00591 TRACKIRP_DBGPRINT(( 00592 " VRP REF(%x) %x++\n", 00593 IovPacket, 00594 IovPacket->ReferenceCount 00595 ), 3) ; 00596 00597 InterlockedIncrement(&IovPacket->ReferenceCount); 00598 if (IovRefType == IOVREFTYPE_POINTER) { 00599 00600 TRACKIRP_DBGPRINT(( 00601 " VRP REF2(%x) %x++\n", 00602 IovPacket, 00603 IovPacket->PointerCount 00604 ), 3) ; 00605 00606 IovPacket->PointerCount++; 00607 } 00608 } 00609 00610 VOID 00611 FASTCALL 00612 IovpTrackingDataDereference( 00613 IN PIOV_REQUEST_PACKET IovPacket, 00614 IN IOV_REFERENCE_TYPE IovRefType 00615 ) 00616 { 00617 KIRQL oldIrql; 00618 00619 ASSERT_SPINLOCK_HELD(&IovPacket->IrpLock); 00620 ASSERT(IovPacket->ReferenceCount > 0); 00621 00622 TRACKIRP_DBGPRINT(( 00623 " VRP DEREF(%x) %x--\n", 00624 IovPacket, 00625 IovPacket->ReferenceCount 00626 ), 3) ; 00627 00628 if (IovRefType == IOVREFTYPE_POINTER) { 00629 00630 ASSERT(IovPacket->PointerCount > 0); 00631 00632 TRACKIRP_DBGPRINT(( 00633 " VRP DEREF2(%x) %x--\n", 00634 IovPacket, 00635 IovPacket->PointerCount 00636 ), 3) ; 00637 00638 IovPacket->PointerCount--; 00639 00640 if (IovPacket->PointerCount == 0) { 00641 00642 ExAcquireSpinLock( &IovpIrpHashLock, &oldIrql ); 00643 00644 IovPacket->TrackedIrp->Flags &=~ IRPFLAG_EXAMINE_MASK; 00645 IovPacket->TrackedIrp = NULL; 00646 00647 ExReleaseSpinLock( &IovpIrpHashLock, oldIrql ); 00648 } 00649 } 00650 InterlockedDecrement(&IovPacket->ReferenceCount); 00651 00652 ASSERT(IovPacket->ReferenceCount >= IovPacket->PointerCount); 00653 } 00654 00655 PIOV_SESSION_DATA 00656 FASTCALL 00657 IovpTrackingDataGetCurrentSessionData( 00658 IN PIOV_REQUEST_PACKET IovPacket 00659 ) 00660 { 00661 ASSERT_SPINLOCK_HELD(&IovPacket->IrpLock); 00662 ASSERT_SPINLOCK_HELD(&IovPacket->HeadPacket->IrpLock); 00663 ASSERT((IovPacket->HeadPacket->pIovSessionData == NULL)|| 00664 (IovPacket->Flags&TRACKFLAG_ACTIVE)) ; 00665 00666 return IovPacket->HeadPacket->pIovSessionData; 00667 } 00668 00669 /* 00670 * The 4 routines listed below - 00671 * IovpProtectedIrpAllocate 00672 * IovpProtectedIrpMakeTouchable 00673 * IovpProtectedIrpMakeUntouchable 00674 * IovpProtectedIrpFree 00675 * 00676 * - handle management of the replacement IRP. Specifically, we want to be 00677 * able to allocate a set of non-paged bytes we can remove the backing 00678 * physical memory from, and release the virtual addresses for later (we 00679 * are essentially breaking free into it's two components). We do this with 00680 * help from the special pool. 00681 * 00682 */ 00683 00684 PIRP 00685 FASTCALL 00686 IovpProtectedIrpAllocate( 00687 IN CCHAR StackSize, 00688 IN BOOLEAN ChargeQuota, 00689 IN PETHREAD QuotaThread OPTIONAL 00690 ) 00691 /*++ 00692 00693 Description: 00694 00695 This routine allocates an IRP from the special pool using the 00696 "replacement IRP" tag. 00697 00698 Arguments: 00699 00700 StackSize - Number of stack locations to give the new IRP 00701 00702 ChargeQuota - TRUE iff quota should be charged against QuotaThread 00703 00704 QuotaThread - See above 00705 00706 Return Value: 00707 00708 Pointer to the memory allocated. 00709 00710 --*/ 00711 { 00712 PIRP pSurrogateIrp; 00713 ULONG_PTR irpPtr; 00714 SIZE_T sizeOfAllocation; 00715 00716 // 00717 // We are allocating an IRP from the special pool. Since IRPs may come from 00718 // lookaside lists they may be ULONG aligned. The memory manager on the 00719 // other hand gaurentees quad-aligned allocations. So to catch all special 00720 // pool overrun bugs we "skew" the IRP right up to the edge. 00721 // 00722 sizeOfAllocation = IoSizeOfIrp(StackSize); 00723 00724 ASSERT((sizeOfAllocation % (sizeof(ULONG))) == 0); 00725 00726 // 00727 // ADRIAO BUGBUG 08/16/98 - Use a quota'd alloc function if one is available 00728 // later... 00729 // 00730 irpPtr = (ULONG_PTR) ExAllocatePoolWithTagPriority( 00731 NonPagedPool, 00732 sizeOfAllocation, 00733 POOL_TAG_PROTECTED_IRP, 00734 HighPoolPrioritySpecialPoolOverrun 00735 ); 00736 00737 pSurrogateIrp = (PIRP) (irpPtr); 00738 00739 return pSurrogateIrp; 00740 } 00741 00742 PVOID 00743 FASTCALL 00744 IovpProtectedIrpMakeUntouchable( 00745 IN PIRP Irp OPTIONAL, 00746 IN BOOLEAN Permanent 00747 ) 00748 /*++ 00749 00750 Description: 00751 00752 This routine makes the surrogate IRP untouchable. Currently, this is 00753 done by freeing the IRP back to the special pool. 00754 00755 Arguments: 00756 00757 Irp - Pointer to the Irp to make untouchable 00758 Permanent - TRUE iff Irp should not be made touchable again 00759 00760 00761 Return Value: 00762 00763 RestoreHandle to be passed to make the Irp touchable again, or to free it. 00764 00765 --*/ 00766 { 00767 ULONG howModified; 00768 00769 if (!Irp) { 00770 return NULL ; 00771 } 00772 00773 if (Permanent) { 00774 ExFreePool(Irp) ; 00775 return NULL; 00776 } 00777 00778 howModified = (ULONG) MmProtectSpecialPool(Irp, PAGE_NOACCESS); 00779 00780 switch(howModified) { 00781 00782 case (ULONG) -1: 00783 00784 // 00785 // Didn't come from special pool. 00786 // 00787 return NULL; 00788 00789 case 0: 00790 00791 // 00792 // Can't comply with request, ref counts, etc hold down page. 00793 // 00794 return NULL; 00795 00796 default: 00797 00798 // 00799 // Allocation has been successfully marked as untouchable. 00800 // 00801 return (PVOID) Irp; 00802 } 00803 } 00804 00805 VOID 00806 FASTCALL 00807 IovpProtectedIrpMakeTouchable( 00808 IN PIRP Irp, 00809 IN PVOID *RestoreHandle 00810 ) 00811 /*++ 00812 00813 Description: 00814 00815 This routine makes the an IRP touchable if previously untouchable. 00816 00817 Arguments: 00818 00819 Irp - Pointer to the Irp to make untouchable 00820 RestoreHandle - Pointer to handle returned by IovpProtectedIrpMakeUntouchable 00821 00822 00823 Return Value: 00824 00825 None. 00826 --*/ 00827 { 00828 if (*RestoreHandle) { 00829 00830 ASSERT(*RestoreHandle == Irp); 00831 MmProtectSpecialPool(Irp, PAGE_READWRITE) ; 00832 *RestoreHandle = NULL ; 00833 } 00834 } 00835 00836 VOID 00837 FASTCALL 00838 IovpProtectedIrpFree( 00839 IN PIRP Irp OPTIONAL, 00840 IN PVOID *RestoreHandle 00841 ) 00842 /*++ 00843 00844 Description: 00845 00846 This routine is called when the call stack has entirely unwound 00847 and the IRP has completed. At this point it is no longer really 00848 useful to hold the surrogate IRP around. As we are using the 00849 special pool currently, this routine needs to do nothing. 00850 00851 Arguments: 00852 00853 IrpTrackingData - Pointer to the IRP tracking data. 00854 00855 Return Value: 00856 00857 None. 00858 --*/ 00859 { 00860 ASSERT((*RestoreHandle) == NULL); 00861 } 00862 00863 VOID 00864 FASTCALL 00865 IovpWatermarkIrp( 00866 IN PIRP Irp, 00867 IN ULONG Flags 00868 ) 00869 { 00870 PIOV_REQUEST_PACKET iovPacket; 00871 00872 iovPacket = IovpTrackingDataFindAndLock(Irp); 00873 00874 if (iovPacket == NULL) { 00875 00876 return; 00877 } 00878 00879 if (Flags & IRP_SYSTEM_RESTRICTED) { 00880 00881 // 00882 // Note that calling this function is not in itself enough to get the 00883 // system to prevent drivers from sending restricted IRPs. Those IRPs to 00884 // be protected must also be added to IovpIsSystemRestrictedIrp in 00885 // flunkirp.c 00886 // 00887 iovPacket->Flags |= TRACKFLAG_WATERMARKED; 00888 } 00889 00890 if (Flags & IRP_BOGUS) { 00891 00892 iovPacket->Flags |= TRACKFLAG_BOGUS; 00893 } 00894 00895 IovpTrackingDataReleaseLock(iovPacket); 00896 } 00897 00898 #endif // NO_SPECIAL_IRP 00899 00900 00901

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