/*++ Copyright (c) 2000 Microsoft Corporation Module Name: vfpacket.c Abstract: This module contains functions used to manage the verifier packet data that tracks IRPs. Author: Adrian J. Oney (adriao) 20-Apr-1998 Environment: Kernel mode Revision History: AdriaO 05/02/2000 - Seperated out from ntos\io\hashirp.c --*/ #include "vfdef.h" #include "vfipacket.h" #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGEVRFY, VfPacketCreateAndLock) #pragma alloc_text(PAGEVRFY, VfPacketFindAndLock) #pragma alloc_text(PAGEVRFY, VfPacketAcquireLock) #pragma alloc_text(PAGEVRFY, VfPacketReleaseLock) #pragma alloc_text(PAGEVRFY, VfPacketReference) #pragma alloc_text(PAGEVRFY, VfPacketDereference) #pragma alloc_text(PAGEVRFY, VfpPacketFree) #pragma alloc_text(PAGEVRFY, VfpPacketNotificationCallback) #pragma alloc_text(PAGEVRFY, VfPacketGetCurrentSessionData) #pragma alloc_text(PAGEVRFY, VfPacketLogEntry) #endif #define POOL_TAG_TRACKING_DATA 'tprI' PIOV_REQUEST_PACKET FASTCALL VfPacketCreateAndLock( IN PIRP Irp ) /*++ Description: This routine creates a tracking packet for a new IRP. The IRP does not get an initial reference count however. VfPacketReleaseLock must be called to drop the lock. Arguments: Irp - Irp to begin tracking. Return Value: iovPacket block, NULL if no memory. --*/ { PIOV_REQUEST_PACKET iovPacket; ULONG allocSize; BOOLEAN successfullyInserted; allocSize = sizeof(IOV_REQUEST_PACKET) + VfSettingsGetSnapshotSize(); iovPacket = ExAllocatePoolWithTag( NonPagedPool, allocSize, POOL_TAG_TRACKING_DATA ); if (!iovPacket) { return NULL; } // // From top to bottom, initialize the fields. Note that there is not a // "surrogateHead". If any code needs to find out the first entry in the // circularly linked list of IRPs (the first is the only non-surrogate IRP), // then HeadPacket should be used. Note that the link to the session is // stored by the headPacket, more on this later. // iovPacket->Flags = 0; InitializeListHead(&iovPacket->SessionHead); iovPacket->StackCount = Irp->StackCount; iovPacket->RealIrpCompletionRoutine = NULL; iovPacket->RealIrpControl = 0; iovPacket->RealIrpContext = NULL; iovPacket->TopStackLocation = 0; iovPacket->PriorityBoost = 0; iovPacket->LastLocation = 0; iovPacket->RefTrackingCount = 0; iovPacket->VerifierSettings = (PVERIFIER_SETTINGS_SNAPSHOT) (iovPacket+1); iovPacket->pIovSessionData = NULL; iovPacket->QuotaCharge = 0; iovPacket->QuotaProcess = NULL; iovPacket->SystemDestVA = NULL; #if DBG iovPacket->LogEntryHead = 0; iovPacket->LogEntryTail = 0; RtlZeroMemory(iovPacket->LogEntries, sizeof(IOV_LOG_ENTRY)*IRP_LOG_ENTRIES); #endif VfSettingsCreateSnapshot(iovPacket->VerifierSettings); successfullyInserted = VfIrpDatabaseEntryInsertAndLock( Irp, VfpPacketNotificationCallback, (PIOV_DATABASE_HEADER) iovPacket ); return successfullyInserted ? iovPacket : NULL; } PIOV_REQUEST_PACKET FASTCALL VfPacketFindAndLock( IN PIRP Irp ) /*++ Description: This routine will return the tracking data for an IRP that is being tracked without a surrogate or the tracking data for with a surrogate if the surrogate IRP is what was passed in. Arguments: Irp - Irp to find. Return Value: IovPacket block, iff above conditions are satified. --*/ { return (PIOV_REQUEST_PACKET) VfIrpDatabaseEntryFindAndLock(Irp); } VOID FASTCALL VfPacketAcquireLock( IN PIOV_REQUEST_PACKET IovPacket OPTIONAL ) /*++ Description: This routine is called by to acquire the IRPs tracking data lock. Incoming IRQL must be the same as the callers (IoCallDriver, IoCompleteRequest) We may be at DPC level when we return. Callers *must* follow up with VfPacketReleaseLock. Arguments: IovPacket - Pointer to the IRP tracking data (or NULL, in which case this routine does nothing). Return Value: None. --*/ { VfIrpDatabaseEntryAcquireLock((PIOV_DATABASE_HEADER) IovPacket); } VOID FASTCALL VfPacketReleaseLock( IN PIOV_REQUEST_PACKET IovPacket ) /*++ Description: This routine releases the IRPs tracking data lock and adjusts the ref count as appropriate. If the reference count drops to zero, the tracking data is freed. Arguments: IovPacket - Pointer to the IRP tracking data. Return Value: None. --*/ { VfIrpDatabaseEntryReleaseLock((PIOV_DATABASE_HEADER) IovPacket); } VOID FASTCALL VfPacketReference( IN PIOV_REQUEST_PACKET IovPacket, IN IOV_REFERENCE_TYPE IovRefType ) { VfIrpDatabaseEntryReference((PIOV_DATABASE_HEADER) IovPacket, IovRefType); } VOID FASTCALL VfPacketDereference( IN PIOV_REQUEST_PACKET IovPacket, IN IOV_REFERENCE_TYPE IovRefType ) { VfIrpDatabaseEntryDereference((PIOV_DATABASE_HEADER) IovPacket, IovRefType); } VOID FASTCALL VfpPacketFree( IN PIOV_REQUEST_PACKET IovPacket ) /*++ Description: This routine free's the tracking data. The tracking data should already have been removed from the table by a call to VfPacketReleaseLock with the ReferenceCount at 0. Arguments: IovPacket - Tracking data to free. Return Value: Nope. --*/ { ExFreePool(IovPacket); } VOID VfpPacketNotificationCallback( IN PIOV_DATABASE_HEADER IovHeader, IN PIRP TrackedIrp OPTIONAL, IN IRP_DATABASE_EVENT Event ) { switch(Event) { case IRPDBEVENT_POINTER_COUNT_ZERO: TrackedIrp->Flags &= ~IRPFLAG_EXAMINE_MASK; break; case IRPDBEVENT_REFERENCE_COUNT_ZERO: ASSERT((((PIOV_REQUEST_PACKET) IovHeader)->pIovSessionData == NULL) || (IovHeader != IovHeader->ChainHead)); VfpPacketFree((PIOV_REQUEST_PACKET) IovHeader); break; default: break; } } PIOV_SESSION_DATA FASTCALL VfPacketGetCurrentSessionData( IN PIOV_REQUEST_PACKET IovPacket ) { PIOV_REQUEST_PACKET headPacket; headPacket = (PIOV_REQUEST_PACKET) IovPacket->ChainHead; ASSERT_SPINLOCK_HELD(&IovPacket->IrpLock); ASSERT_SPINLOCK_HELD(&IovPacket->HeadPacket->IrpLock); ASSERT((headPacket->pIovSessionData == NULL)|| (IovPacket->Flags&TRACKFLAG_ACTIVE)) ; return headPacket->pIovSessionData; } VOID FASTCALL VfPacketLogEntry( IN PIOV_REQUEST_PACKET IovPacket, IN IOV_LOG_EVENT IovLogEvent, IN PVOID Address, IN ULONG_PTR Data ) /*++ Description: This routine logs an event in the IRP request packet data. Arguments: IovPacket - Tracking data to write log entry into. IovLogEvent - Log Event Address - Address to associate log with Data - A chunk of data to go with the address Return Value: Nope. --*/ { #if DBG PIOV_LOG_ENTRY logEntry; ASSERT_SPINLOCK_HELD(&IovPacket->IrpLock); logEntry = IovPacket->LogEntries + IovPacket->LogEntryHead; KeQueryTickCount(&logEntry->TimeStamp); logEntry->Thread = PsGetCurrentThread(); logEntry->Event = IovLogEvent; logEntry->Address = Address; logEntry->Data = Data; IovPacket->LogEntryHead = ((IovPacket->LogEntryHead + 1) % IRP_LOG_ENTRIES); if (IovPacket->LogEntryHead == IovPacket->LogEntryTail) { IovPacket->LogEntryTail = ((IovPacket->LogEntryTail + 1) % IRP_LOG_ENTRIES); } #else UNREFERENCED_PARAMETER(IovPacket); UNREFERENCED_PARAMETER(IovLogEvent); UNREFERENCED_PARAMETER(Address); UNREFERENCED_PARAMETER(Data); #endif }