Hello everyone!
I am writing a file system filter driver and dispatch functions for IRP_MJ_READ and IRP_MJ_WRITE.
Here is the code for IRP_MJ_READ:
NTSTATUS
MyRead ( PDEVICE_OBJECT DeviceObject, PIRP Irp )
{
PIO_STACK_LOCATION pIoStackLocation;
PVOID pBuffer;
ULONG Length;
pIoStackLocation = IoGetCurrentIrpStackLocation( Irp );
Length = pIoStackLocation->Parameters.Read.Length;
pBuffer = ExAllocatePoolWithTag( NonPagedPool, Length, ‘cuL’ );
if ( NULL == pBuffer )
{
DbgPrint( “\npBuffer = ExAllocatePoolWithTag Error” );
DbgBreakPoint();
}
RtlFillMemory( pBuffer, Length, 65 );
try
{
if ( Irp->RequestorMode == UserMode )
{
ProbeForWrite( Irp->UserBuffer, Length, TYPE_ALIGNMENT( WCHAR ) );
RtlCopyMemory( Irp->UserBuffer, pBuffer, Length );
}
}
except ( EXCEPTION_EXECUTE_HANDLER )
{
DbgPrint( “\nMyRead: EXCEPTION_EXECUTE_HANDLER” );
ExFreePoolWithTag( pBuffer, ‘cuL’ );
Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_ACCESS_DENIED;
}
ExFreePoolWithTag( pBuffer, ‘cuL’ );
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = Length;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
This is not the original and all code. I want to complete this IRP with a buffer filled with “A”.
I know that Irp->UserBuffer is valid only in the context of the calling thread. The problem is that I want to mark the IRP pending, queue it and process it in a separate thread. Obviously I won’t be able to use this pointer Irp->UserBuffer to copy data to it from my created thread.
I know that if Irp->RequestorMode is UserMode, the Irp->MdlAddress is NULL. Is it possible to use IoAllocateMdl() and passing the Irp->UserBuffer as the input VirtualAddress of this function? Theb call MmProbeAndLockPages(). Then set Irp->MdlAddress to point to my allocated MDL. Then later from my thread may I use this MDL to write data to that buffer?
PMDL
IoAllocateMdl(
IN PVOID VirtualAddress,
IN ULONG Length,
IN BOOLEAN SecondaryBuffer,
IN BOOLEAN ChargeQuota,
IN OUT PIRP Irp OPTIONAL
);
Can VirtualAddress be a pointer from user-mode?
I don’t understand the meaning of ChargeQuota.
Thank you!