In my routine to handle deferred processing in the post op handler for IR_MJ_DIRECTORY_CONTROL I’m having a problem with the case where the MdlAddress == 0 and FLT_IS_SYSTEM_BUFFER () is false.
I call FltLockUserBuffer() , then MmGetSystemAddressForMdlSafe(). but the return from it is sometimes garbage . Needless to say, when this occurs , I crash.
As you can see in the comments, I’ve copied the documetation provided about accessing user buffers in post op operations and I think I’m doing this correctly.
Questions might be the legitimacy of doing this in the Deferred work item vs. the dispatched routine, but I don’t think that is a problem.
Other questions would be about using try/except blocks around the accesses to the buffers or maybe buffers should be further probedandlocked ? The doc’s don’t indicate that this is necessary.
Any ideas?
TIA
Larry
void SafePostDirectoryControl( IN PFLT_DEFERRED_IO_WORKITEM FltWorkItem,
IN PFLT_CALLBACK_DATA Data,
IN PVOID Context
)
{
NTSTATUS Status;
RDM_STATUS RDM_Status;
FILE_INFORMATION_CLASS POINTER_ALIGNMENT FileInformationClass;
PVOID DirectoryBuffer =0;
ULONG RDMState;
int DataHasBeenModified = 0;
UCHAR MinorFunction;
PUNICODE_STRING FileName;
ULONG Length;
PRDMInstanceContext pIC;
PVOID UserDirectoryBuffer ;
PMDL MdlAddress;
DirControlContext * pDirControl = (DirControlContext*) Context;
HANDLE DirectoryHandle = 0;
UNICODE_STRING DirPath;
pIC = pDirControl->pIC;
FileName = Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileName;
FileInformationClass = Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass;
UserDirectoryBuffer = Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer;
MdlAddress = Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress;
/* see “Accessing User Buffers in a Postoperation Callback Routine” in the IFS Documents
If an MDL exists for the buffer, call MmGetSystemAddressForMdlSafe
to obtain the system address for the buffer.
(This routine can be called at IRQL <= DISPATCH_LEVEL.) Use the system address to access the buffer.
*/
if(MdlAddress != 0)
{
DebugTrace(DEBUG_TRACE_IRPS,“[PostOp DirControl] Mdl != 0 \n " );
Status = FltLockUserBuffer(Data);
if(NT_SUCCESS(Status))
DirectoryBuffer = MmGetSystemAddressForMdlSafe(MdlAddress,NormalPagePriority);
}
else
{/*If there is no MDL for the buffer, check whether the system
buffer flag is set for the operation by using the FLT_IS_SYSTEM_BUFFER macro.
*/
DebugTrace(DEBUG_TRACE_IRPS,”[PostOp DirControl] Mdl == 0 \n " );
if (FLT_IS_SYSTEM_BUFFER(Data))
{/*If the FLT_IS_SYSTEM_BUFFER macro returns TRUE, the
operation uses buffered I/O, and the buffer can safely be accessed at IRQL DISPATCH_LEVEL*/
DebugTrace(DEBUG_TRACE_IRPS,“[PostOp DirControl] DirectoryBuffer is system buffer != 0 \n " );
DirectoryBuffer = UserDirectoryBuffer;
}
else
{/*If the FLT_IS_SYSTEM_BUFFER macro returns FALSE,
the buffer cannot safely be accessed at IRQL DISPATCH_LEVEL.
If the postoperation callback routine can be called at DISPATCH_LEVEL,
it must call FltDoCompletionProcessingWhenSafe to pend the operation until
it can be processed at IRQL <= APC_LEVEL. The SafePostCallback routine
should first call FltLockUserBuffer to lock the buffer and
then call MmGetSystemAddressForMdlSafe to obtain the system address for the buffer.
*/
DebugTrace(DEBUG_TRACE_IRPS,”[PostOp DirControl]Try to allocate Mdl == 0 , !System buffer \n " );
Status = FltLockUserBuffer(Data);
if(NT_SUCCESS(Status))
{MdlAddress = Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress;
DirectoryBuffer = MmGetSystemAddressForMdlSafe(MdlAddress,NormalPagePriority);
DebugTrace(DEBUG_TRACE_IRPS,"[PostOp DirControl]allocated Mdl != 0 \n " );
}
}
}
… now that I’ve got a buffer, go do some work.
…
cleanup
}