|
|
/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
sessnirp.c
Abstract:
I/O Verifier irp support routines.
Author:
Adrian Oney (adriao)
Environment:
Kernel mode
Revision History:
--*/
#include "iop.h"
#include "srb.h"
//
// This entire file is only present if NO_SPECIAL_IRP isn't defined
//
#ifndef NO_SPECIAL_IRP
//
// When enabled, everything is locked down on demand...
//
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGEVRFY, IovpSessionDataCreate)
#pragma alloc_text(PAGEVRFY, IovpSessionDataAdvance)
#pragma alloc_text(PAGEVRFY, IovpSessionDataReference)
#pragma alloc_text(PAGEVRFY, IovpSessionDataDereference)
#pragma alloc_text(PAGEVRFY, IovpSessionDataClose)
#pragma alloc_text(PAGEVRFY, IovpSessionDataDeterminePolicy)
#pragma alloc_text(PAGEVRFY, IovpSessionDataAttachSurrogate)
#pragma alloc_text(PAGEVRFY, IovpSessionDataFinalizeSurrogate)
#pragma alloc_text(PAGEVRFY, IovpSessionDataBufferIO)
#pragma alloc_text(PAGEVRFY, IovpSessionDataUnbufferIO)
#endif
#define POOL_TAG_SESSION_DATA 'sprI'
#define POOL_TAG_DIRECT_BUFFER 'BprI'
PIOV_SESSION_DATA FASTCALL IovpSessionDataCreate( IN PDEVICE_OBJECT DeviceObject, IN OUT PIOV_REQUEST_PACKET *IovPacketPointer, OUT PBOOLEAN SurrogateSpawned ) /*++
Description:
This routine creates tracking data for a new IRP. It must be called on the thread the IRP was originally sent down...
Arguments:
Irp - Irp to track.
Return Value:
iovPacket block, NULL if no memory.
--*/ { PIRP irp, surrogateIrp; PIOV_SESSION_DATA iovSessionData; PIOV_REQUEST_PACKET headPacket; ULONG sessionDataSize; BOOLEAN trackable, useSurrogateIrp;
*SurrogateSpawned = FALSE;
headPacket = (PIOV_REQUEST_PACKET) (*IovPacketPointer)->ChainHead; ASSERT(headPacket == (*IovPacketPointer)); irp = headPacket->TrackedIrp;
//
// Check the IRP appropriately
//
IovpSessionDataDeterminePolicy( headPacket, DeviceObject, &trackable, &useSurrogateIrp );
if (!trackable) {
return NULL; }
//
// One extra stack location is allocated as the "zero'th" is used to
// simplify some logic...
//
sessionDataSize = sizeof(IOV_SESSION_DATA)+ irp->StackCount*sizeof(IOV_STACK_LOCATION) + VfSettingsGetSnapshotSize();
iovSessionData = ExAllocatePoolWithTag( NonPagedPool, sessionDataSize, POOL_TAG_SESSION_DATA );
if (iovSessionData == NULL) {
return NULL; }
RtlZeroMemory(iovSessionData, sessionDataSize);
iovSessionData->VerifierSettings = (PVERIFIER_SETTINGS_SNAPSHOT) (((PUCHAR) iovSessionData) + (sessionDataSize-VfSettingsGetSnapshotSize()));
RtlCopyMemory( iovSessionData->VerifierSettings, headPacket->VerifierSettings, VfSettingsGetSnapshotSize() );
iovSessionData->IovRequestPacket = headPacket; InsertHeadList(&headPacket->SessionHead, &iovSessionData->SessionLink);
if (VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_DEFER_COMPLETION)|| VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_COMPLETE_AT_PASSIVE)) {
VfSettingsSetOption(iovSessionData->VerifierSettings, VERIFIER_OPTION_FORCE_PENDING, TRUE); }
//
// If DeferIoCompletion is set we definitely want to monitor pending I/O, as
// screwing it up is gaurenteed to be fatal!
//
if ((irp->Flags & IRP_DEFER_IO_COMPLETION) && VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS)) {
VfSettingsSetOption(iovSessionData->VerifierSettings, VERIFIER_OPTION_MONITOR_PENDING_IO, TRUE); }
headPacket->pIovSessionData = iovSessionData; headPacket->TopStackLocation = irp->CurrentLocation; headPacket->Flags |= TRACKFLAG_ACTIVE; headPacket->Flags &= ~ ( TRACKFLAG_QUEUED_INTERNALLY| TRACKFLAG_RELEASED| TRACKFLAG_SRB_MUNGED| TRACKFLAG_SWAPPED_BACK );
iovSessionData->BestVisibleIrp = irp; if (useSurrogateIrp) {
//
// We will track the IRP using a surrogate.
//
*SurrogateSpawned = IovpSessionDataAttachSurrogate( IovPacketPointer, iovSessionData ); }
TRACKIRP_DBGPRINT(( " SSN CREATE(%x)->%x\n", headPacket, iovSessionData ), 3);
return iovSessionData; }
VOID FASTCALL IovpSessionDataAdvance( IN PDEVICE_OBJECT DeviceObject, IN PIOV_SESSION_DATA IovSessionData, IN OUT PIOV_REQUEST_PACKET *IovPacketPointer, OUT PBOOLEAN SurrogateSpawned ) { *SurrogateSpawned = FALSE; }
VOID FASTCALL IovpSessionDataDereference( IN PIOV_SESSION_DATA IovSessionData ) { PIOV_REQUEST_PACKET iovPacket;
iovPacket = IovSessionData->IovRequestPacket; ASSERT((PIOV_REQUEST_PACKET) iovPacket->ChainHead == iovPacket);
ASSERT_SPINLOCK_HELD(&iovPacket->HeaderLock); ASSERT(IovSessionData->SessionRefCount > 0); ASSERT(iovPacket->ReferenceCount >= 0);
TRACKIRP_DBGPRINT(( " SSN DEREF(%x) %x--\n", IovSessionData, IovSessionData->SessionRefCount ), 3);
IovSessionData->SessionRefCount--; if (!IovSessionData->SessionRefCount) {
ASSERT(iovPacket->pIovSessionData != IovSessionData); ASSERT(iovPacket->ReferenceCount > iovPacket->PointerCount); //ASSERT(IsListEmpty(&IovSessionData->SessionLink));
RemoveEntryList(&IovSessionData->SessionLink); InitializeListHead(&IovSessionData->SessionLink);
VfPacketDereference(iovPacket, IOVREFTYPE_PACKET);
ExFreePool(IovSessionData); } }
VOID FASTCALL IovpSessionDataReference( IN PIOV_SESSION_DATA IovSessionData ) { PIOV_REQUEST_PACKET iovPacket;
iovPacket = IovSessionData->IovRequestPacket; ASSERT((PIOV_REQUEST_PACKET) iovPacket->ChainHead == iovPacket);
ASSERT_SPINLOCK_HELD(&iovPacket->HeaderLock); ASSERT(IovSessionData->SessionRefCount >= 0); ASSERT(iovPacket->ReferenceCount >= 0);
TRACKIRP_DBGPRINT(( " SSN REF(%x) %x++\n", IovSessionData, IovSessionData->SessionRefCount ), 3);
if (!IovSessionData->SessionRefCount) {
VfPacketReference(iovPacket, IOVREFTYPE_PACKET); } IovSessionData->SessionRefCount++; }
VOID FASTCALL IovpSessionDataClose( IN PIOV_SESSION_DATA IovSessionData ) { PIOV_REQUEST_PACKET iovPacket = IovSessionData->IovRequestPacket;
ASSERT_SPINLOCK_HELD(&iovPacket->HeaderLock);
ASSERT(iovPacket == (PIOV_REQUEST_PACKET) iovPacket->ChainHead); ASSERT(iovPacket->pIovSessionData == IovSessionData);
TRACKIRP_DBGPRINT(( " SSN CLOSE(%x)\n", IovSessionData ), 3);
iovPacket->Flags &= ~TRACKFLAG_ACTIVE; iovPacket->pIovSessionData = NULL; }
VOID IovpSessionDataDeterminePolicy( IN PIOV_REQUEST_PACKET IovRequestPacket, IN PDEVICE_OBJECT DeviceObject, OUT PBOOLEAN Trackable, OUT PBOOLEAN UseSurrogateIrp ) /*++
Description:
This routine is called by IovpCallDriver1 to determine which IRPs should be tracked and how that tracking should be done.
Arguments:
IovRequestPacket - Verifier data representing the incoming IRP
DeviceObject - Device object the IRP is being forwarded to
Trackable - Set if the IRP should be marked trackable
UseSurrogateIrp - Set a surrogate should be created for this IRP
Return Value:
None.
--*/ { PIO_STACK_LOCATION irpSp; PIRP irp;
irp = IovRequestPacket->TrackedIrp;
//
// Determine whether we are to monitor this IRP. If we are going to test
// any one driver in a stack, then we must unfortunately monitor the IRP's
// progress through the *entire* stack. Thus our granularity here is stack
// based, not device based! We will compensate for this somewhat in the
// driver check code, which will attempt to ignore asserts from those
// "non-targetted" drivers who happen to have messed up in our stack...
//
*Trackable = IovUtilIsVerifiedDeviceStack(DeviceObject);
irpSp = IoGetNextIrpStackLocation(irp);
if (VfSettingsIsOptionEnabled(IovRequestPacket->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS)) {
*UseSurrogateIrp = VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_SURROGATE_IRPS); *UseSurrogateIrp &= (VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_SMASH_SRBS) || (irpSp->MajorFunction != IRP_MJ_SCSI)); } else {
*UseSurrogateIrp = FALSE; } }
BOOLEAN FASTCALL IovpSessionDataAttachSurrogate( IN OUT PIOV_REQUEST_PACKET *IovPacketPointer, IN PIOV_SESSION_DATA IovSessionData ) /*++
Description:
This routine creates tracking data for a new IRP. It must be called on the thread the IRP was originally sent down...
Arguments:
IovPacketPointer - Pointer to IRP packet to attach surrogate to. If a surrogate can be attached the packet will be updated to track the surrogate.
SurrogateIrp - Prepared surrogate IRP to attach.
Return Value:
iovPacket block, NULL if no memory.
--*/ {
PIOV_REQUEST_PACKET iovSurrogatePacket, iovPacket, headPacket; PIRP surrogateIrp, irp; PIO_STACK_LOCATION irpSp; PSCSI_REQUEST_BLOCK srb; CCHAR activeSize;
iovPacket = *IovPacketPointer; ASSERT_SPINLOCK_HELD(&iovPacket->HeaderLock);
ASSERT(VfIrpDatabaseEntryGetChainNext((PIOV_DATABASE_HEADER) iovPacket) == NULL);
ASSERT(iovPacket->Flags & TRACKFLAG_ACTIVE);
irp = iovPacket->TrackedIrp; activeSize = (irp->CurrentLocation-1); ASSERT(activeSize);
//
// We now try to make a copy of this new IRP which we will track. We
// do this so that we may free *every* tracked IRP immediately upon
// completion.
// Technically speaking, we only need to allocate what's left of the
// stack, not the entire thing. But using the entire stack makes our
// work much much easier. Specifically the session stack array may depend
// on this.
//
// ADRIAO N.B. 03/04/1999 - Make this work only copying a portion of the
// IRP.
//
surrogateIrp = VfIrpAllocate(irp->StackCount); // activeSize
if (surrogateIrp == NULL) {
return FALSE; }
//
// Now set up the new IRP - we do this here so VfPacketCreateAndLock
// can peek at it's fields. Start with the IRP header.
//
RtlCopyMemory(surrogateIrp, irp, sizeof(IRP));
//
// Adjust StackCount and CurrentLocation
//
surrogateIrp->StackCount = irp->StackCount; // activeSize
surrogateIrp->Tail.Overlay.CurrentStackLocation = ((PIO_STACK_LOCATION) (surrogateIrp+1))+activeSize;
//
// Our new IRP "floats", and is not attached to any thread.
// Note that all cancels due to thread death will come through the
// original IRP.
//
InitializeListHead(&surrogateIrp->ThreadListEntry);
//
// Our new IRP also is not connected to user mode.
//
surrogateIrp->UserEvent = NULL; surrogateIrp->UserIosb = NULL;
//
// Now copy over only the active portions of IRP. Be very careful to not
// assume that the last stack location is right after the end of the IRP,
// as we may change this someday!
//
irpSp = (IoGetCurrentIrpStackLocation(irp)-activeSize); RtlCopyMemory(surrogateIrp+1, irpSp, sizeof(IO_STACK_LOCATION)*activeSize);
//
// Zero the portion of the new IRP we won't be using (this should
// eventually go away).
//
RtlZeroMemory( ((PIO_STACK_LOCATION) (surrogateIrp+1))+activeSize, sizeof(IO_STACK_LOCATION)*(surrogateIrp->StackCount - activeSize) );
//
// Now create a surrogate packet to track the new IRP.
//
iovSurrogatePacket = VfPacketCreateAndLock(surrogateIrp); if (iovSurrogatePacket == NULL) {
VfIrpFree(surrogateIrp); return FALSE; }
headPacket = (PIOV_REQUEST_PACKET) iovPacket->ChainHead;
ASSERT(iovSurrogatePacket->LockIrql == DISPATCH_LEVEL); irpSp = IoGetNextIrpStackLocation(irp);
//
// We will flag this bug later.
//
irp->CancelRoutine = NULL;
//
// Let's take advantage of the original IRP not being the thing partied on
// now; store a pointer to our tracking data in the information field. We
// don't use this, but it's nice when debugging...
//
irp->IoStatus.Information = (ULONG_PTR) iovPacket;
//
// ADRIAO N.B. #28 06/10/98 - This is absolutely *gross*, and not
// deterministic enough for my tastes.
//
// For IRP_MJ_SCSI (ie, IRP_MJ_INTERNAL_DEVICE_CONTROL), look and see
// if we have an SRB coming through. If so, fake out the OriginalRequest
// IRP pointer as appropriate.
//
if (irpSp->MajorFunction == IRP_MJ_SCSI) { srb = irpSp->Parameters.Others.Argument1; if (VfUtilIsMemoryRangeReadable(srb, SCSI_REQUEST_BLOCK_SIZE, VFMP_INSTANT_NONPAGED)) { if ((srb->Length == SCSI_REQUEST_BLOCK_SIZE)&&(srb->OriginalRequest == irp)) { srb->OriginalRequest = surrogateIrp; headPacket->Flags |= TRACKFLAG_SRB_MUNGED; } } }
//
// Since the replacement will never make it back to user mode (the real
// IRP shall of course), we will steal a field or two for debugging info.
//
surrogateIrp->UserIosb = (PIO_STATUS_BLOCK) iovPacket;
//
// Now that everything is built correctly, attach the surrogate. The
// surrogate holds down the packet we are attaching to. When the surrogate
// dies we will remove this reference.
//
VfPacketReference(iovPacket, IOVREFTYPE_POINTER);
//
// Stamp IRPs appropriately.
//
surrogateIrp->Flags |= IRP_DIAG_IS_SURROGATE; irp->Flags |= IRP_DIAG_HAS_SURROGATE;
//
// Mark packet as surrogate and inherit appropriate fields from iovPacket.
//
iovSurrogatePacket->Flags |= TRACKFLAG_SURROGATE | TRACKFLAG_ACTIVE; iovSurrogatePacket->pIovSessionData = iovPacket->pIovSessionData;
RtlCopyMemory( iovSurrogatePacket->VerifierSettings, iovPacket->VerifierSettings, VfSettingsGetSnapshotSize() );
iovSurrogatePacket->LastLocation = iovPacket->LastLocation; iovSurrogatePacket->TopStackLocation = irp->CurrentLocation;
iovSurrogatePacket->ArrivalIrql = iovPacket->ArrivalIrql; iovSurrogatePacket->DepartureIrql = iovPacket->DepartureIrql;
iovPacket->Flags |= TRACKFLAG_HAS_SURROGATE;
//
// Link in the new surrogate
//
VfIrpDatabaseEntryAppendToChain( (PIOV_DATABASE_HEADER) iovPacket, (PIOV_DATABASE_HEADER) iovSurrogatePacket );
*IovPacketPointer = iovSurrogatePacket;
IovpSessionDataBufferIO( iovSurrogatePacket, surrogateIrp );
return TRUE; }
VOID FASTCALL IovpSessionDataFinalizeSurrogate( IN PIOV_SESSION_DATA IovSessionData, IN OUT PIOV_REQUEST_PACKET IovPacket, IN PIRP SurrogateIrp ) /*++
Description:
This routine removes the flags from both the real and surrogate IRP and records the final IRP settings. Finally, the surrogate IRP is made "untouchable" (decommitted).
Arguments:
iovPacket - Pointer to the IRP tracking data.
Return Value:
None. --*/ { PIOV_REQUEST_PACKET iovPrevPacket; NTSTATUS status, lockedStatus; ULONG nonInterestingFlags; PIO_STACK_LOCATION irpSp; PIRP irp;
ASSERT(IovPacket->Flags&TRACKFLAG_SURROGATE);
ASSERT(VfPacketGetCurrentSessionData(IovPacket) == IovSessionData);
IovPacket->pIovSessionData = NULL;
//
// It's a surrogate, do as appropriate.
//
ASSERT(IovPacket->TopStackLocation == SurrogateIrp->CurrentLocation+1);
IovpSessionDataUnbufferIO(IovPacket, SurrogateIrp);
iovPrevPacket = (PIOV_REQUEST_PACKET) VfIrpDatabaseEntryGetChainPrevious( (PIOV_DATABASE_HEADER) IovPacket );
irp = iovPrevPacket->TrackedIrp;
//
// Carry the pending bit over.
//
if (SurrogateIrp->PendingReturned) { IoMarkIrpPending(irp); }
nonInterestingFlags = ( IRPFLAG_EXAMINE_MASK | IRP_DIAG_IS_SURROGATE| IRP_DIAG_HAS_SURROGATE );
//
// Wipe the flags nice and clean
//
SurrogateIrp->Flags &= ~IRP_DIAG_IS_SURROGATE; irp->Flags &= ~IRP_DIAG_HAS_SURROGATE;
//
// ASSERT portions of the IRP header have not changed.
//
ASSERT(irp->StackCount == SurrogateIrp->StackCount); // Later to be removed
ASSERT(irp->Type == SurrogateIrp->Type); ASSERT(irp->RequestorMode == SurrogateIrp->RequestorMode); ASSERT(irp->ApcEnvironment == SurrogateIrp->ApcEnvironment); ASSERT(irp->AllocationFlags == SurrogateIrp->AllocationFlags); ASSERT(irp->Tail.Overlay.Thread == SurrogateIrp->Tail.Overlay.Thread);
ASSERT( irp->Overlay.AsynchronousParameters.UserApcRoutine == SurrogateIrp->Overlay.AsynchronousParameters.UserApcRoutine );
ASSERT( irp->Overlay.AsynchronousParameters.UserApcContext == SurrogateIrp->Overlay.AsynchronousParameters.UserApcContext );
ASSERT( irp->Tail.Overlay.OriginalFileObject == SurrogateIrp->Tail.Overlay.OriginalFileObject );
ASSERT( irp->Tail.Overlay.AuxiliaryBuffer == SurrogateIrp->Tail.Overlay.AuxiliaryBuffer );
/*
ASSERT( irp->AssociatedIrp.SystemBuffer == SurrogateIrp->AssociatedIrp.SystemBuffer );
ASSERT( (irp->Flags & ~nonInterestingFlags) == (SurrogateIrp->Flags & ~nonInterestingFlags) );
ASSERT(irp->MdlAddress == SurrogateIrp->MdlAddress); */ //
// ADRIAO N.B. 02/28/1999 -
// How do these change as an IRP progresses?
//
irp->Flags |= SurrogateIrp->Flags; irp->MdlAddress = SurrogateIrp->MdlAddress; irp->AssociatedIrp.SystemBuffer = SurrogateIrp->AssociatedIrp.SystemBuffer;
//
// ADRIAO N.B. 10/18/1999 - UserBuffer is edited by netbios on Type3 device
// ioctls. Yuck!
//
irp->UserBuffer = SurrogateIrp->UserBuffer;
if ((irp->Flags&IRP_DEALLOCATE_BUFFER)&& (irp->AssociatedIrp.SystemBuffer == NULL)) {
irp->Flags &= ~IRP_DEALLOCATE_BUFFER; }
//
// Copy the salient fields back. We only need to touch certain areas of the
// header.
//
irp->IoStatus = SurrogateIrp->IoStatus; irp->PendingReturned = SurrogateIrp->PendingReturned; irp->Cancel = SurrogateIrp->Cancel;
iovPrevPacket->Flags &= ~TRACKFLAG_HAS_SURROGATE;
//
// Record data from it and make the system fault if the IRP is touched
// after this completion routine.
//
IovSessionData->BestVisibleIrp = irp;
IovSessionData->IovRequestPacket = iovPrevPacket;
VfIrpDatabaseEntryRemoveFromChain((PIOV_DATABASE_HEADER) IovPacket);
VfPacketDereference(iovPrevPacket, IOVREFTYPE_POINTER);
ASSERT(IovPacket->PointerCount == 0);
VfIrpFree(SurrogateIrp); }
VOID FASTCALL IovpSessionDataBufferIO( IN OUT PIOV_REQUEST_PACKET IovSurrogatePacket, IN PIRP SurrogateIrp ) { PMDL mdl; ULONG bufferLength; PUCHAR bufferVA, systemDestVA; PVOID systemBuffer; PIO_STACK_LOCATION irpSp;
if (!VfSettingsIsOptionEnabled(IovSurrogatePacket->VerifierSettings, VERIFIER_OPTION_BUFFER_DIRECT_IO)) {
return; }
if (SurrogateIrp->Flags & IRP_PAGING_IO) {
return; }
if (SurrogateIrp->MdlAddress == NULL) {
return; }
if (SurrogateIrp->MdlAddress->Next) {
return; }
if (SurrogateIrp->Flags & IRP_BUFFERED_IO) {
return; }
irpSp = IoGetNextIrpStackLocation(SurrogateIrp);
if (irpSp->MajorFunction != IRP_MJ_READ) {
return; }
//
// Extract length and VA from the MDL.
//
bufferLength = SurrogateIrp->MdlAddress->ByteCount; bufferVA = (PUCHAR) SurrogateIrp->MdlAddress->StartVa + SurrogateIrp->MdlAddress->ByteOffset;
//
// Allocate memory and make it the target of the MDL
//
systemBuffer = ExAllocatePoolWithTagPriority( NonPagedPool, bufferLength, POOL_TAG_DIRECT_BUFFER, HighPoolPrioritySpecialPoolOverrun );
if (systemBuffer == NULL) {
return; }
//
// Save off a pointer to the Mdl's buffer. This should never fail, but
// one never knows...
//
systemDestVA = MmGetSystemAddressForMdlSafe(SurrogateIrp->MdlAddress, HighPagePriority);
if (systemDestVA == NULL) {
ASSERT(0); ExFreePool(systemBuffer); return; }
//
// Allocate a MDL, update the IRP.
//
mdl = IoAllocateMdl( systemBuffer, bufferLength, FALSE, TRUE, SurrogateIrp );
if (mdl == NULL) {
ExFreePool(systemBuffer); return; }
MmProbeAndLockPages( mdl, KernelMode, IoWriteAccess ); IovSurrogatePacket->SystemDestVA = systemDestVA; IovSurrogatePacket->Flags |= TRACKFLAG_DIRECT_BUFFERED; }
VOID FASTCALL IovpSessionDataUnbufferIO( IN OUT PIOV_REQUEST_PACKET IovSurrogatePacket, IN PIRP SurrogateIrp ) { PMDL mdl; ULONG surrogateLength, originalLength; ULONG_PTR bufferLength; PUCHAR surrogateVA, originalVA, systemDestVA; PVOID systemBuffer; PIOV_REQUEST_PACKET iovPrevPacket; PIRP irp;
if (!(IovSurrogatePacket->Flags & TRACKFLAG_DIRECT_BUFFERED)) {
return; }
iovPrevPacket = (PIOV_REQUEST_PACKET) VfIrpDatabaseEntryGetChainPrevious( (PIOV_DATABASE_HEADER) IovSurrogatePacket );
irp = iovPrevPacket->TrackedIrp;
ASSERT(SurrogateIrp->MdlAddress); ASSERT(SurrogateIrp->MdlAddress->Next == NULL); ASSERT(irp->MdlAddress); ASSERT(irp->MdlAddress->Next == NULL); ASSERT(!(SurrogateIrp->Flags & IRP_BUFFERED_IO)); ASSERT(!(irp->Flags & IRP_BUFFERED_IO));
//
// Extract length and VA from the MDLs.
//
surrogateLength = SurrogateIrp->MdlAddress->ByteCount; surrogateVA = (PUCHAR) SurrogateIrp->MdlAddress->StartVa + SurrogateIrp->MdlAddress->ByteOffset;
//
// We use these only for the purpose of assertions.
//
originalLength = irp->MdlAddress->ByteCount; originalVA = (PUCHAR) irp->MdlAddress->StartVa + irp->MdlAddress->ByteOffset;
ASSERT(surrogateLength == originalLength); ASSERT(SurrogateIrp->IoStatus.Information <= originalLength);
//
// Get the target buffer address and the length to write.
//
bufferLength = SurrogateIrp->IoStatus.Information; systemDestVA = IovSurrogatePacket->SystemDestVA;
//
// Copy things over.
//
RtlCopyMemory(systemDestVA, surrogateVA, bufferLength);
//
// Unlock the MDL. We have to do this ourselves as this IRP is not going to
// progress through all of IoCompleteRequest.
//
MmUnlockPages(SurrogateIrp->MdlAddress);
//
// Cleanup.
//
IoFreeMdl(SurrogateIrp->MdlAddress);
//
// Free our allocated VA
//
ExFreePool(surrogateVA);
//
// Hack the MDL back as IovpSessionDataFinalizeSurrogate requires it.
//
SurrogateIrp->MdlAddress = irp->MdlAddress;
IovSurrogatePacket->Flags &= ~TRACKFLAG_DIRECT_BUFFERED; }
#endif // NO_SPECIAL_IRP
|