windows-nt/Source/XPSP1/NT/base/ntos/verifier/vfpacket.c

363 lines
7.7 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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
}