Filesystem Filter driver doesn't work

Hi!

I have written a simple driver that should monitor a volume activity. It doesn’t work as I expect it to work… Does anyone know what is wrong in the driver?

The driver looks like this:

#include <ntddk.h>

typedef unsigned int UINT;
typedef char * PCHAR;

typedef struct _MY_FILTER_EXTENSION
{
PDEVICE_OBJECT pNextDeviceInChain;

} MY_FILTER_EXTENSION, *PMY_FILTER_EXTENSION;

VOID MyUnload(PDRIVER_OBJECT DriverObject);
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath);
NTSTATUS MyCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS MyClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS MyCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS MyIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS MyWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS MyRead(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS MyUnSupportedFunction(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS MyIoControlInternal(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS MyCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
NTSTATUS MyFixNullString(PCHAR pString, UINT uiSize);
NTSTATUS MyFastIoWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp);

NTSTATUS MyCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_SUCCESS;
PMY_FILTER_EXTENSION pMyFilterDeviceContext = (PMY_FILTER_EXTENSION)DeviceObject->DeviceExtension;
PIO_STACK_LOCATION pIoStackIrp = NULL;

DbgPrint(“MyCreate Called \r\n”);

IoSkipCurrentIrpStackLocation(Irp);

NtStatus = IoCallDriver(pMyFilterDeviceContext->pNextDeviceInChain, Irp);

DbgPrint(“MyCreate Exit 0x%0x \r\n”, NtStatus);

return NtStatus;
}

NTSTATUS MyClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_SUCCESS;
PMY_FILTER_EXTENSION pMyFilterDeviceContext = (PMY_FILTER_EXTENSION)DeviceObject->DeviceExtension;
PIO_STACK_LOCATION pIoStackIrp = NULL;

DbgPrint(“MyClose Called \r\n”);

IoSkipCurrentIrpStackLocation(Irp);

NtStatus = IoCallDriver(pMyFilterDeviceContext->pNextDeviceInChain, Irp);

DbgPrint(“MyClose Exit 0x%0x \r\n”, NtStatus);

return NtStatus;
}

NTSTATUS MyCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_SUCCESS;
PMY_FILTER_EXTENSION pMyFilterDeviceContext = (PMY_FILTER_EXTENSION)DeviceObject->DeviceExtension;
PIO_STACK_LOCATION pIoStackIrp = NULL;

DbgPrint(“MyCleanup Called \r\n”);

IoSkipCurrentIrpStackLocation(Irp);

NtStatus = IoCallDriver(pMyFilterDeviceContext->pNextDeviceInChain, Irp);

DbgPrint(“MyCleanup Exit 0x%0x \r\n”, NtStatus);

return NtStatus;
}

NTSTATUS MyIoControlInternal(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_SUCCESS;
PMY_FILTER_EXTENSION pMyFilterDeviceContext = (PMY_FILTER_EXTENSION)DeviceObject->DeviceExtension;
PIO_STACK_LOCATION pIoStackIrp = NULL;

DbgPrint(“MyIoControlInternal Called \r\n”);

IoSkipCurrentIrpStackLocation(Irp);

NtStatus = IoCallDriver(pMyFilterDeviceContext->pNextDeviceInChain, Irp);

DbgPrint(“MyIoControlInternal Exit 0x%0x \r\n”, NtStatus);

return NtStatus;
}

NTSTATUS MyIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_SUCCESS;
PMY_FILTER_EXTENSION pMyFilterDeviceContext = (PMY_FILTER_EXTENSION)DeviceObject->DeviceExtension;
PIO_STACK_LOCATION pIoStackIrp = NULL;

DbgPrint(“MyIoControl Called \r\n”);

IoSkipCurrentIrpStackLocation(Irp);

NtStatus = IoCallDriver(pMyFilterDeviceContext->pNextDeviceInChain, Irp);

DbgPrint(“MyIoControl Exit 0x%0x \r\n”, NtStatus);

return NtStatus;
}

NTSTATUS MyWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_SUCCESS;
PMY_FILTER_EXTENSION pMyFilterDeviceContext = (PMY_FILTER_EXTENSION)DeviceObject->DeviceExtension;
PIO_STACK_LOCATION pIoStackIrp = NULL;

DbgPrint(“MyWrite Called \r\n”);

IoSkipCurrentIrpStackLocation(Irp);

NtStatus = IoCallDriver(pMyFilterDeviceContext->pNextDeviceInChain, Irp);

DbgPrint(“MyWrite Exit 0x%0x \r\n”, NtStatus);

return NtStatus;
}

NTSTATUS MyRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_BUFFER_TOO_SMALL;
PMY_FILTER_EXTENSION pMyFilterDeviceContext = (PMY_FILTER_EXTENSION)DeviceObject->DeviceExtension;
PIO_STACK_LOCATION pIoStackIrp = NULL;
PCHAR pReadDataBuffer;

DbgPrint(“MyRead Called \r\n”);

pIoStackIrp = IoGetCurrentIrpStackLocation(Irp);

IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) MyCompletionRoutine, NULL, TRUE, TRUE, TRUE);

NtStatus = IoCallDriver(pMyFilterDeviceContext->pNextDeviceInChain, Irp);

if(NT_SUCCESS(NtStatus))
{
if(Irp->IoStatus.Information)
{
if(DeviceObject->Flags & DO_BUFFERED_IO)
{

DbgPrint(“MyRead - Use Buffered I/O \r\n”);

pReadDataBuffer = (PCHAR)Irp->AssociatedIrp.SystemBuffer;

if(pReadDataBuffer && pIoStackIrp->Parameters.Read.Length > 0)
{
MyFixNullString(pReadDataBuffer, (UINT)Irp->IoStatus.Information);
}
}
else
{
if(DeviceObject->Flags & DO_DIRECT_IO)
{
DbgPrint(“MyRead - Use Direct I/O \r\n”);

if(pIoStackIrp && Irp->MdlAddress)
{
pReadDataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

if(pReadDataBuffer && pIoStackIrp->Parameters.Read.Length)
{
MyFixNullString(pReadDataBuffer, (UINT)Irp->IoStatus.Information);
}
}
}
else
{

DbgPrint(“MyRead - Use Neither I/O \r\n”);

__try {

if(pIoStackIrp->Parameters.Read.Length > 0 && Irp->UserBuffer)
{

ProbeForWrite(Irp->UserBuffer, pIoStackIrp->Parameters.Read.Length, TYPE_ALIGNMENT(char));
pReadDataBuffer = Irp->UserBuffer;

MyFixNullString(pReadDataBuffer, (UINT)Irp->IoStatus.Information);
}

}__except( EXCEPTION_EXECUTE_HANDLER ) {

NtStatus = GetExceptionCode();
}
}
}

}
}

Irp->IoStatus.Status = NtStatus;
IoCompleteRequest(Irp, IO_NO_INCREMENT);

DbgPrint(“MyRead Exit 0x%0x \r\n”, NtStatus);

return NtStatus;
}

NTSTATUS MyUnSupportedFunction(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_SUCCESS;
PMY_FILTER_EXTENSION pMyFilterDeviceContext = (PMY_FILTER_EXTENSION)DeviceObject->DeviceExtension;
PIO_STACK_LOCATION pIoStackIrp = NULL;

DbgPrint(“MyUnSupportedFunction Called \r\n”);

IoSkipCurrentIrpStackLocation(Irp);

NtStatus = IoCallDriver(pMyFilterDeviceContext->pNextDeviceInChain, Irp);

DbgPrint(“MyUnSupportedFunction Exit 0x%0x \r\n”, NtStatus);

return NtStatus;
}

NTSTATUS MyCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
DbgPrint(“MyCompletionRoutine Called \r\n”);

return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS MyFixNullString(PCHAR pString, UINT uiSize)
{
NTSTATUS NtStatus = STATUS_SUCCESS;
UINT uiIndex = 0;

while(uiIndex < (uiSize - 1))
{
if(pString[uiIndex] == 0)
{
pString[uiIndex] = ’ ';
}

uiIndex++;
}

pString[uiIndex] = 0;

return NtStatus;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
{
NTSTATUS NtStatus = STATUS_SUCCESS;
UINT uiIndex = 0;
PDEVICE_OBJECT pDeviceObject = NULL, pFilteredDevice = NULL;
UNICODE_STRING usDeviceToFilter;
PMY_FILTER_EXTENSION pMyFilterDeviceContext;

DbgPrint(“DriverEntry Called \r\n”);

// Create the Device:
NtStatus = IoCreateDevice(pDriverObject, sizeof(MY_FILTER_EXTENSION), NULL, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObject);

if(NtStatus == STATUS_SUCCESS)
{
DbgPrint(“Device Created \r\n”);

// Register IRP’s:
for(uiIndex = 0; uiIndex < IRP_MJ_MAXIMUM_FUNCTION; uiIndex++)
pDriverObject->MajorFunction[uiIndex] = MyUnSupportedFunction;

pDriverObject->MajorFunction[IRP_MJ_CLOSE] = MyClose;
pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = MyCleanup;
pDriverObject->MajorFunction[IRP_MJ_CREATE] = MyCreate;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyIoControl;
pDriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = MyIoControlInternal;
pDriverObject->MajorFunction[IRP_MJ_READ] = MyRead;
pDriverObject->MajorFunction[IRP_MJ_WRITE] = MyWrite;

DbgPrint(“MajorFunctions Added 0x%0x \r\n”, NtStatus);

// Set the Unload function:
pDriverObject->DriverUnload = MyUnload;

pMyFilterDeviceContext = (PMY_FILTER_EXTENSION)pDeviceObject->DeviceExtension;

RtlInitUnicodeString(&usDeviceToFilter, L"\??\C:");

// Attach to the volume:
NtStatus = IoAttachDevice(pDeviceObject, &usDeviceToFilter, &pMyFilterDeviceContext->pNextDeviceInChain);

if(NtStatus == STATUS_SUCCESS)
{
DbgPrint(“Attached To Device \r\n”);
}

if(!NT_SUCCESS(NtStatus))
{
IoDeleteDevice(pDeviceObject);
}
else
{
pFilteredDevice = pMyFilterDeviceContext->pNextDeviceInChain;

pDeviceObject->Flags |= pFilteredDevice->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO);
pDeviceObject->DeviceType = pFilteredDevice->DeviceType;
pDeviceObject->Characteristics = pFilteredDevice->Characteristics;
pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
}
}

DbgPrint(“DriverEntry Finished 0x%0x \r\n”, NtStatus);

return NtStatus;
}

VOID MyUnload(PDRIVER_OBJECT DriverObject)
{
PMY_FILTER_EXTENSION pMyFilterDeviceContext = (PMY_FILTER_EXTENSION)DriverObject->DeviceObject->DeviceExtension;
DbgPrint(“MyUnload Called \r\n”);
IoDetachDevice(pMyFilterDeviceContext->pNextDeviceInChain);
IoDeleteDevice(DriverObject->DeviceObject);
}

I would be very thankful it anyone could help…</ntddk.h>

Hi

Welcome to “I have filter driver and it doesn’t work” club.
Could you please be more specific about “It doesn’t work as
I expect it to work” ? Does is crash ? Does it freeze system ?

L.

hi, sorry for not being clear.
the driver doesn’t seem to intercept IO request after the first one. i.e after i start the driver and open a file i will see it in the debugger. but after that it wont respond to any other IO operations. at least not as i intended it it do. meaning if i say try to load something via another program it does some times show it but it doesn’t work all the time, i cant figure out the reason why it does it. i have a theory that maybe after my driver refers the IRP to the drivers below it, it “leaves” the stack and it cant view the results of the IO request. i’ve just started developing drivers so I’m not so sure if I’m even correct.

thanks in advance for any assistance you may offer.

Hello,

MyRead() is not processing the IRP correctly. For example you are not
checking the return status for pending before accessing the output
buffers and completing the irp.

Andrei

xxxxx@gmail.com wrote:

hi, sorry for not being clear.
the driver doesn’t seem to intercept IO request after the first one. i.e after i start the driver and open a file i will see it in the debugger. but after that it wont respond to any other IO operations. at least not as i intended it it do. meaning if i say try to load something via another program it does some times show it but it doesn’t work all the time, i cant figure out the reason why it does it. i have a theory that maybe after my driver refers the IRP to the drivers below it, it “leaves” the stack and it cant view the results of the IO request. i’ve just started developing drivers so I’m not so sure if I’m even correct.

thanks in advance for any assistance you may offer.


NTFSD is sponsored by OSR

For our schedule debugging and file system seminars
(including our new fs mini-filter seminar) visit:
http://www.osr.com/seminars

You are currently subscribed to ntfsd as: xxxxx@bitdefender.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

I have already found the answer… Thanks anyway!