FLT_PREOP_CALLBACK_STATUS
SwapPreReadBuffers(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_
PVOID
*CompletionContext
)
{
PFLT_IO_PARAMETER_BLOCK iopb = Data->Iopb;
FLT_PREOP_CALLBACK_STATUS retValue = FLT_PREOP_SUCCESS_NO_CALLBACK;
PVOID
newBuf = NULL;
PMDL newMdl = NULL;
PVOLUME_CONTEXT volCtx = NULL;
PPRE_2_POST_CONTEXT p2pCtx;
NTSTATUS status;
ULONG
readLen = iopb->Parameters.Read.Length;
try
{
if
(readLen == 0) { leave; }
status = FltGetVolumeContext(FltObjects->Filter,
FltObjects->Volume,
&volCtx);
if
(!NT_SUCCESS(status)) { leave; }
if
(FlagOn(IRP_NOCACHE, iopb->IrpFlags)) {
readLen = (
ULONG
)ROUND_TO_SIZE(readLen, volCtx->SectorSize);
}
newBuf = FltAllocatePoolAlignedWithTag(FltObjects->Instance,
NonPagedPool,
(
SIZE_T
)readLen,
BUFFER_SWAP_TAG);
if
(newBuf == NULL) { leave; }
if
(FlagOn(Data->Flags, FLTFL_CALLBACK_DATA_IRP_OPERATION)) {
newMdl = IoAllocateMdl(newBuf,
readLen,
FALSE,
FALSE,
NULL);
if
(newMdl == NULL) { leave; }
MmBuildMdlForNonPagedPool(newMdl);
}
p2pCtx = ExAllocateFromNPagedLookasideList(&Pre2PostContextList);
if
(p2pCtx == NULL) { leave; }
iopb->Parameters.Read.ReadBuffer = newBuf;
iopb->Parameters.Read.MdlAddress = newMdl;
FltSetCallbackDataDirty(Data);
p2pCtx->SwappedBuffer = newBuf;
p2pCtx->VolCtx = volCtx;
*CompletionContext = p2pCtx;
retValue = FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
finally{
if
(retValue != FLT_PREOP_SUCCESS_WITH_CALLBACK) {
if
(newBuf != NULL) {
FltFreePoolAlignedWithTag(FltObjects->Instance,
newBuf,
BUFFER_SWAP_TAG);
}
if
(newMdl != NULL) {
IoFreeMdl(newMdl);
}
if
(volCtx != NULL) {
FltReleaseContext(volCtx);
}
}
}
return
retValue;
}
FLT_POSTOP_CALLBACK_STATUS
SwapPostReadBuffers(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_
PVOID
CompletionContext,
_In_ FLT_POST_OPERATION_FLAGS Flags
)
{
PVOID
origBuf;
PFLT_IO_PARAMETER_BLOCK iopb = Data->Iopb;
FLT_POSTOP_CALLBACK_STATUS retValue = FLT_POSTOP_FINISHED_PROCESSING;
PPRE_2_POST_CONTEXT p2pCtx = CompletionContext;
BOOLEAN
cleanupAllocatedBuffer = TRUE;
FLT_ASSERT(!FlagOn(Flags, FLTFL_POST_OPERATION_DRAINING));
try
{
if
(!NT_SUCCESS(Data->IoStatus.Status) ||
(Data->IoStatus.Information == 0)) {
leave;
}
if
(iopb->Parameters.Read.MdlAddress != NULL) {
FLT_ASSERT(((PMDL)iopb->Parameters.Read.MdlAddress)->Next == NULL);
origBuf = MmGetSystemAddressForMdlSafe(iopb->Parameters.Read.MdlAddress,
NormalPagePriority | MdlMappingNoExecute);
if
(origBuf == NULL) {
Data->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Data->IoStatus.Information = 0;
leave;
}
}
else
if
(FlagOn(Data->Flags, FLTFL_CALLBACK_DATA_SYSTEM_BUFFER) ||
FlagOn(Data->Flags, FLTFL_CALLBACK_DATA_FAST_IO_OPERATION)) {
origBuf = iopb->Parameters.Read.ReadBuffer;
}
else
{
if
(FltDoCompletionProcessingWhenSafe(Data,
FltObjects,
CompletionContext,
Flags,
SwapPostReadBuffersWhenSafe,
&retValue)) {
cleanupAllocatedBuffer = FALSE;
}
else
{
Data->IoStatus.Status = STATUS_UNSUCCESSFUL;
Data->IoStatus.Information = 0;
}
leave;
}
try
{
RtlCopyMemory(origBuf,
p2pCtx->SwappedBuffer,
Data->IoStatus.Information);
} except(EXCEPTION_EXECUTE_HANDLER) {
Data->IoStatus.Status = GetExceptionCode();
Data->IoStatus.Information = 0;
}
}
finally{
if
(cleanupAllocatedBuffer) {
FltFreePoolAlignedWithTag(FltObjects->Instance,
p2pCtx->SwappedBuffer,
BUFFER_SWAP_TAG);
FltReleaseContext(p2pCtx->VolCtx);
ExFreeToNPagedLookasideList(&Pre2PostContextList,
p2pCtx);
}
}
return
retValue;
}
FLT_POSTOP_CALLBACK_STATUS
SwapPostReadBuffersWhenSafe(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_
PVOID
CompletionContext,
_In_ FLT_POST_OPERATION_FLAGS Flags
)
{
PFLT_IO_PARAMETER_BLOCK iopb = Data->Iopb;
PPRE_2_POST_CONTEXT p2pCtx = CompletionContext;
PVOID
origBuf;
NTSTATUS status;
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
FLT_ASSERT(Data->IoStatus.Information != 0);
status = FltLockUserBuffer(Data);
if
(!NT_SUCCESS(status)) {
Data->IoStatus.Status = status;
Data->IoStatus.Information = 0;
}
else
{
origBuf = MmGetSystemAddressForMdlSafe(iopb->Parameters.Read.MdlAddress,
NormalPagePriority | MdlMappingNoExecute);
if
(origBuf == NULL) {
Data->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Data->IoStatus.Information = 0;
}
else
{
RtlCopyMemory(origBuf,
p2pCtx->SwappedBuffer,
Data->IoStatus.Information);
}
}
FltFreePoolAlignedWithTag(FltObjects->Instance,
p2pCtx->SwappedBuffer,
BUFFER_SWAP_TAG);
FltReleaseContext(p2pCtx->VolCtx);
ExFreeToNPagedLookasideList(&Pre2PostContextList,
p2pCtx);
return
FLT_POSTOP_FINISHED_PROCESSING;
}