Context management using the Scanner sample code provided with IF

Hi,

I am performing encryption for only the interested files in the callback
for IRP_MJ_WRITE in the non cached path i.e. with IRP_NOCACHE flag set. To
determine the name of the file to be encrypted I have used the context
management code used in the Scanner sample code provided with IFS. The
problem I am facing is that the context is deleted too soon. When the final
non cached write occurs on the file (This write is in context of the system
process i.e. the process with process id 4) my code fails with context not
found error and hence encryption does not happen. (Just for information, my
code works when data is up to 729 characters (Maybe this is not relevant).
After that if I add even one character the context has been already freed).
What could I be doing wrong here or is this the expected behavior (I don’t
think so)? Or is my approach wrong altogether?

Following is the code snippet:

  1. Post create:

status = FltAllocateContext(gFilterHandle,

FLT_STREAMHANDLE_CONTEXT,

sizeof(SCANNER_STREAM_HANDLE_CONTEXT),

NonPagedPool,

&scannerContext);

if (NT_SUCCESS(status))

{

USHORT size = 0;

size = FltObjects->FileObject->FileName.Length + sizeof(WCHAR);

scannerContext->ustrFileName.Length = 0;

scannerContext->ustrFileName.MaximumLength = size;

scannerContext->ustrFileName.Buffer =
ExAllocatePoolWithTag(NonPagedPool,

size,

‘hsiv’);

RtlCopyUnicodeString(&scannerContext->ustrFileName,

&FltObjects->FileObject->FileName);

DbgPrint(“PostCreateOperation – Context data is
%wZ”,&scannerContext->ustrFileName);

status = FltSetStreamHandleContext( FltObjects->Instance,

FltObjects->FileObject,

FLT_SET_CONTEXT_KEEP_IF_EXISTS /*Tried both the options.*/,

scannerContext,

NULL );

FltReleaseContext( scannerContext );

  1. PreWrite:

if(NULL != FltObjects->FileObject)

{

UNICODE_STRING
wstrExtension;

if(Data->Iopb->IrpFlags & IRP_NOCACHE)

{

DbgPrint(“PreWriteOperation – Data in non cached io
is %s”,newBuf);

status =
FltGetStreamHandleContext(FltObjects->Instance,

FltObjects->FileObject,

&context);

if(!NT_SUCCESS(status))

{

DbgPrint(“PreWriteOperation – Failed to get the
context. status = %d”,status);

if(STATUS_NOT_FOUND == status)

{

DbgPrint(“PreWriteOperation – NOT
FOUND”);

}

return FLT_PREOP_SUCCESS_NO_CALLBACK;

}

DbgPrint(“PreWriteOperation – FileName from context
is %wZ”,&context->ustrFileName);

status =
FltParseFileName(&context->ustrFileName,&wstrExtension,NULL,NULL);

if(STATUS_SUCCESS != status)

{

DbgPrint(“PostCreateOperation –
FltParseFileName failed. Status = %d”,status);

return FLT_POSTOP_FINISHED_PROCESSING;

}

if(ScannerpCheckExtension(&wstrExtension))

{

ULONG
ulCipherTextLength = 0;

unsigned char* pSrc = (unsigned
char*)origBuf;

unsigned char* pDst = (unsigned
char*)newBuf;

DbgPrint(“PreWriteOperation – Noncached
Data is %s”,newBuf);

Encrypt(ulPlainTextLength,pSrc,&ulCipherTextLength,pDst);

}

if(context)

{

FltReleaseContext( context );

}

}

else

{

DbgPrint(“PreWriteOperation – cached IO Data is
%s”,newBuf);

}

Thanks,

Vishal

Oops what I needed was STREAM context. Stream context is the same for all
opens on that particular stream while stream handle context is unique for
every new open. That solved the problem.

Vishal


From: Vishal Pai [mailto:xxxxx@persistent.co.in]
Sent: Sunday, April 30, 2006 6:50 PM
To: ‘xxxxx@lists.osr.com’
Subject: Context management using the Scanner sample code provided with IF

Hi,

I am performing encryption for only the interested files in the callback
for IRP_MJ_WRITE in the non cached path i.e. with IRP_NOCACHE flag set. To
determine the name of the file to be encrypted I have used the context
management code used in the Scanner sample code provided with IFS. The
problem I am facing is that the context is deleted too soon. When the final
non cached write occurs on the file (This write is in context of the system
process i.e. the process with process id 4) my code fails with context not
found error and hence encryption does not happen. (Just for information, my
code works when data is up to 729 characters (Maybe this is not relevant).
After that if I add even one character the context has been already freed).
What could I be doing wrong here or is this the expected behavior (I don’t
think so)? Or is my approach wrong altogether?

Following is the code snippet:

  1. Post create:

status = FltAllocateContext(gFilterHandle,

FLT_STREAMHANDLE_CONTEXT,

sizeof(SCANNER_STREAM_HANDLE_CONTEXT),

NonPagedPool,

&scannerContext);

if (NT_SUCCESS(status))

{

USHORT size = 0;

size = FltObjects->FileObject->FileName.Length + sizeof(WCHAR);

scannerContext->ustrFileName.Length = 0;

scannerContext->ustrFileName.MaximumLength = size;

scannerContext->ustrFileName.Buffer =
ExAllocatePoolWithTag(NonPagedPool,

size,

‘hsiv’);

RtlCopyUnicodeString(&scannerContext->ustrFileName,

&FltObjects->FileObject->FileName);

DbgPrint(“PostCreateOperation – Context data is
%wZ”,&scannerContext->ustrFileName);

status = FltSetStreamHandleContext( FltObjects->Instance,

FltObjects->FileObject,

FLT_SET_CONTEXT_KEEP_IF_EXISTS /*Tried both the options.*/,

scannerContext,

NULL );

FltReleaseContext( scannerContext );

  1. PreWrite:

if(NULL != FltObjects->FileObject)

{

UNICODE_STRING
wstrExtension;

if(Data->Iopb->IrpFlags & IRP_NOCACHE)

{

DbgPrint(“PreWriteOperation – Data in non cached io
is %s”,newBuf);

status =
FltGetStreamHandleContext(FltObjects->Instance,

FltObjects->FileObject,

&context);

if(!NT_SUCCESS(status))

{

DbgPrint(“PreWriteOperation – Failed to get the
context. status = %d”,status);

if(STATUS_NOT_FOUND == status)

{

DbgPrint(“PreWriteOperation – NOT
FOUND”);

}

return FLT_PREOP_SUCCESS_NO_CALLBACK;

}

DbgPrint(“PreWriteOperation – FileName from context
is %wZ”,&context->ustrFileName);

status =
FltParseFileName(&context->ustrFileName,&wstrExtension,NULL,NULL);

if(STATUS_SUCCESS != status)

{

DbgPrint(“PostCreateOperation –
FltParseFileName failed. Status = %d”,status);

return FLT_POSTOP_FINISHED_PROCESSING;

}

if(ScannerpCheckExtension(&wstrExtension))

{

ULONG
ulCipherTextLength = 0;

unsigned char* pSrc = (unsigned
char*)origBuf;

unsigned char* pDst = (unsigned
char*)newBuf;

DbgPrint(“PreWriteOperation – Noncached
Data is %s”,newBuf);

Encrypt(ulPlainTextLength,pSrc,&ulCipherTextLength,pDst);

}

if(context)

{

FltReleaseContext( context );

}

}

else

{

DbgPrint(“PreWriteOperation – cached IO Data is
%s”,newBuf);

}

Thanks,

Vishal