Modfying the WDM scanner sample

Hello Forumers,

I am trying to learn WDM to possibly implement EFS at some point in the future.

I found the scanner sample as part of the WDM the place to start.

I removed certain pieces of code that communicate with the user mode and certain pre and post operations, added a postRead operation.

What I am trying to do is change all ‘a’ to ‘b’ and ‘b’ to ‘c’ on write and on read revert the change.

While running the code, I found the write pre operation is being called twice. (all ‘a’ converted to ‘c’). The read post operation is not doing anything(when i open the file again the changes are not reverted).

The following are the callbacks I have registered, the other callbacks have been removed from the scanner sample

ScannerPostCreate, ScannerPostRead, ScannerPreWrite

I am pasting the code here the other parts are same as the scanner sample.

Can some one please tell me what I am doing wrong? I don’t have two systems that I can use to debug!

FLT_POSTOP_CALLBACK_STATUS
ScannerPostCreate (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__in_opt PVOID CompletionContext,
__in FLT_POST_OPERATION_FLAGS Flags
)
/*++

{
PSCANNER_STREAM_HANDLE_CONTEXT scannerContext;
FLT_POSTOP_CALLBACK_STATUS returnStatus = FLT_POSTOP_FINISHED_PROCESSING;
PFLT_FILE_NAME_INFORMATION nameInfo;
NTSTATUS status;
BOOLEAN safeToOpen, scanFile;

UNREFERENCED_PARAMETER( CompletionContext );
UNREFERENCED_PARAMETER( Flags );

if (!NT_SUCCESS( Data->IoStatus.Status ) ||
(STATUS_REPARSE == Data->IoStatus.Status)) {

return FLT_POSTOP_FINISHED_PROCESSING;
}

status = FltGetFileNameInformation( Data,
FLT_FILE_NAME_NORMALIZED |
FLT_FILE_NAME_QUERY_DEFAULT,
&nameInfo );

if (!NT_SUCCESS( status )) {

return FLT_POSTOP_FINISHED_PROCESSING;
}

FltParseFileNameInformation( nameInfo );

scanFile = ScannerpCheckExtension( &nameInfo->Extension );

if (!scanFile) {

return FLT_POSTOP_FINISHED_PROCESSING;
}

//do only for read or write
if ((FltObjects->FileObject->WriteAccess)||(FltObjects->FileObject->ReadAccess)) {

status = FltAllocateContext( ScannerData.Filter,
FLT_STREAMHANDLE_CONTEXT,
sizeof(SCANNER_STREAM_HANDLE_CONTEXT),
PagedPool,
&scannerContext );

if (NT_SUCCESS(status)) {

(VOID) FltSetStreamHandleContext( FltObjects->Instance,
FltObjects->FileObject,
FLT_SET_CONTEXT_REPLACE_IF_EXISTS,
scannerContext,
NULL );

FltReleaseContext( scannerContext );
}
}

return returnStatus;
}

FLT_PREOP_CALLBACK_STATUS
ScannerPreWrite (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__deref_out_opt PVOID *CompletionContext
)
{
FLT_PREOP_CALLBACK_STATUS returnStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
NTSTATUS status;
PSCANNER_NOTIFICATION notification = NULL;
PSCANNER_STREAM_HANDLE_CONTEXT context = NULL;
ULONG replyLength;
BOOLEAN safe = TRUE;
PUCHAR buffer;
ULONG i;
UNREFERENCED_PARAMETER( CompletionContext );

status = FltGetStreamHandleContext( FltObjects->Instance,
FltObjects->FileObject,
&context );

if (!NT_SUCCESS( status )) {

return FLT_PREOP_SUCCESS_NO_CALLBACK;

}

try { //get buffer

if (Data->Iopb->Parameters.Write.Length != 0) {

if (Data->Iopb->Parameters.Write.MdlAddress != NULL) {
buffer = MmGetSystemAddressForMdlSafe( Data->Iopb->Parameters.Write.MdlAddress,
NormalPagePriority );

if (buffer == NULL) {

Data->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Data->IoStatus.Information = 0;
returnStatus = FLT_PREOP_COMPLETE;
leave;
}

} else {

buffer = Data->Iopb->Parameters.Write.WriteBuffer;
}
//change a to b , b to c
for (i=0;i<(Data->Iopb->Parameters.Write.Length);i++)
{
if (*(buffer+i)==‘a’)
*(buffer+i)=‘b’;
else if (*(buffer+i)==‘b’)
*(buffer+i)=‘c’;
}
}
} finally {

if (context) {

FltReleaseContext( context );
}
}

return returnStatus;
}

FLT_POSTOP_CALLBACK_STATUS
ScannerPostRead (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__in_opt PVOID CompletionContext,
__in FLT_POST_OPERATION_FLAGS Flags
)
{

NTSTATUS status;
PSCANNER_STREAM_HANDLE_CONTEXT context = NULL;
PUCHAR buffer;
FLT_POSTOP_CALLBACK_STATUS returnStatus =FLT_POSTOP_FINISHED_PROCESSING;
ULONG i;

status = FltGetStreamHandleContext( FltObjects->Instance,
FltObjects->FileObject,
&context );

if (!NT_SUCCESS( status )) {

return FLT_POSTOP_FINISHED_PROCESSING;
}

try{

if (Data->IoStatus.Information!=0)
{
if (Data->Iopb->Parameters.Read.MdlAddress != NULL) {

buffer = MmGetSystemAddressForMdlSafe( Data->Iopb->Parameters.Read.MdlAddress,
NormalPagePriority );

if (buffer == NULL) {

Data->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Data->IoStatus.Information = 0;
returnStatus = FLT_POSTOP_FINISHED_PROCESSING;
leave;
}

} else {

buffer = Data->Iopb->Parameters.Read.ReadBuffer;
}
//revert changes
for (i=0;i<(Data->IoStatus.Information);i++)
{
if (*(buffer+i)==‘b’)
*(buffer+i)=‘a’;
else if (*(buffer+i)==‘c’)
*(buffer+i)=‘b’;

}
}
}//try
finally
{
if (context) {

FltReleaseContext( context );
}
}
return FLT_POSTOP_FINISHED_PROCESSING;
}

What you’re doing wrong is you don’t have debugging set up. So, go set it up now.

Note that ONE of your machines CAN BE A VIRTUAL MACHINE. Download Virtual Box or something.

There is no reasonable way you’ll be able to write a driver – or support that driver once it’s written – without having a debugger. Yes, yes… you could do extensive DbgPrint debugging… but that’s time consuming and difficult. Much easier to just single-step through your code to watch what’s happening, don’t you think?

Peter
OSR