363 lines
7.7 KiB
C
363 lines
7.7 KiB
C
|
/*++
|
||
|
|
||
|
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
|
||
|
}
|
||
|
|
||
|
|