Hi,
As shown by minifilter code snippet below, I am incrementing the IRP_MJ_WRITE buffers directly in PreOpWrite and decrementing them in PostOpWrite.
- My first query is whether I can manipulate buffers directly (no file size/attributes changed though) or should I use “swap buffers” as in swapbuffer WDK sample.
I am testing it in Wordpad (small 4-5kb file). On debug printing the Write buffer I found out that:
* I am receiving 2 WRITE IRPrequests for same file save. First one is without MdlAddress and Second one is with MdlAdress.
* PreOpWrite for 2nd IRP has buffer bytes already incremented, even though I am decrementing it in PostOpWrite for 1st IRP. As a result final buffer in 2nd IRP PreOpWrite is incremented twice.
However, after closing and opening the file again, the contents were correct i.e. the characters in file were only the one increment of original buffers.
- Is this a bug I need to correct, how? Is there a way to check if I have already manipulated the buffer before and not do it again.
Note the if I comment out the PostOpWrite the file (after saving, closing and then opening) shows that the buffers bytes were incremented twice).
//CODE
FLT_PREOP_CALLBACK_STATUS
PreOpWrite (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__deref_out PVOID *CompletionContext
)
{
FLT_PREOP_CALLBACK_STATUS returnStatus = FLT_PREOP_SUCCESS_NO_CALLBACK; //assume we are NOT going to call our completion routine
UNICODE_STRING uStrPath;
NTSTATUS nStatus;
if (PASSIVE_LEVEL == KeGetCurrentIrql() &&
RP_MJ_WRITE == Data->Iopb->MajorFunction &&
SUCCESS == getFileNameWithCompletePath(&uStrPath, Data, FltObjects->FileObject) &&
TRUE == isFileToBeChanged(uStrPath))
{
char *ioBuffer = NULL;
PMDL MdlAddress = Data->Iopb->Parameters.Write.MdlAddress;
ULONG Length = (ULONG)Data->Iopb->Parameters.Write.Length;
if (NULL != MdlAddress)
{
// Don’t expect chained MDLs this high up the stack
ASSERT(MdlAddress->Next == NULL);
ioBuffer = (char*)MmGetSystemAddressForMdlSafe(MdlAddress, NormalPagePriority);
}
else
{
ioBuffer = (char*)Data->Iopb->Parameters.Write.WriteBuffer;
}
if (NULL != ioBuffer)
{
ULONG ii;
FltSetCallbackDataDirty(Data);
for(ii = 0; ii < Length; ii++) ioBuffer[ii]++;
}
else
{
Data->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Data->IoStatus.Information = 0;
}
ExFreePoolWithTag(uStrPath.Buffer,‘2fNP’);
uStrPath.Buffer = NULL;
returnStatus = FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
return returnStatus;
}
FLT_POSTOP_CALLBACK_STATUS
PostOpWrite (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__in PVOID CompletionContext,
__in FLT_POST_OPERATION_FLAGS Flags
)
{
UNICODE_STRING uStrPath;
NTSTATUS nStatus;
if (PASSIVE_LEVEL == KeGetCurrentIrql() &&
RP_MJ_WRITE == Data->Iopb->MajorFunction &&
SUCCESS == getFileNameWithCompletePath(&uStrPath, Data, FltObjects->FileObject) &&
TRUE == isFileToBeChanged(uStrPath))
{
char *ioBuffer = NULL;
PMDL MdlAddress = Data->Iopb->Parameters.Write.MdlAddress;
ULONG Length = (ULONG)Data->Iopb->Parameters.Write.Length;
if (NULL != MdlAddress)
{
// Don’t expect chained MDLs this high up the stack
ASSERT(MdlAddress->Next == NULL);
ioBuffer = (char*)MmGetSystemAddressForMdlSafe(MdlAddress, NormalPagePriority);
}
else
{
ioBuffer = (char*)Data->Iopb->Parameters.Write.WriteBuffer;
}
if (NULL != ioBuffer)
{
ULONG ii;
if (NT_SUCCESS(Data->IoStatus.Status)) Length = (ULONG)Data->IoStatus.Information;
for(ii = 0; ii < Length; ii++) ioBuffer[ii]–;
}
else
{
Data->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Data->IoStatus.Information = 0;
}
ExFreePoolWithTag(uStrPath.Buffer,‘2fNP’);
uStrPath.Buffer = NULL;
}
return FLT_POSTOP_FINISHED_PROCESSING;
}