online encrypt can't process all data!

Merry Christmas all,

i’m writting a online encrypt/decrypt minifilter driver with win2003 ifs
ddk(SP1). I encrypt data in the IRP_MJ_WRITE routine,i use the microsoft
sample in the ddk,the problem is ,i only can encrypt 4kbytes,if a file large
than 4kb,sometimes can process it,and sometimes not,how can i fix this
problem? the ms’s sample is "swapbuffers ",if you have the win2003 ifs
ddk(sp1) on your pc,you can find the sample in this place:ddk install dir
\src\filesys\minifilter\swapbuffers.

The sample’s IRP_MJ_WRITE pre_operation routine as below:

FLT_PREOP_CALLBACK_STATUS
SwapPreWriteBuffers(
IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
OUT PVOID *CompletionContext
)
/*++

Routine Description:

This routine demonstrates how to swap buffers for the WRITE operation.

Note that it handles all errors by simply not doing the buffer swap.

Arguments:

Data - Pointer to the filter callbackData that is passed to us.

FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure
containing
opaque handles to this filter, instance, its associated volume and
file object.

CompletionContext - Receives the context that will be passed to the
post-operation callback.

Return Value:

FLT_PREOP_SUCCESS_WITH_CALLBACK - we want a postOpeation callback
FLT_PREOP_SUCCESS_NO_CALLBACK - we don’t want a postOperation callback
FLT_PREOP_COMPLETE -
–*/
{
PFLT_IO_PARAMETER_BLOCK iopb = Data->Iopb;
FLT_PREOP_CALLBACK_STATUS retValue = FLT_PREOP_SUCCESS_NO_CALLBACK;
PVOID newBuf = NULL;
PMDL newMdl = NULL;
PVOLUME_CONTEXT volCtx = NULL;
PPRE_2_POST_CONTEXT p2pCtx;
PVOID origBuf;
NTSTATUS status;
ULONG writeLen = iopb->Parameters.Write.Length;

try {

//
// If they are trying to write ZERO bytes, then don’t do anything
and
// we don’t need a post-operation callback.
//

if (writeLen == 0) {

leave;
}

//
// Get our volume context so we can display our volume name in the
// debug output.
//

status = FltGetVolumeContext( FltObjects->Filter,
FltObjects->Volume,
&volCtx );

if (!NT_SUCCESS(status)) {

LOG_PRINT( LOGFL_ERRORS,
(“SwapBuffers!SwapPreWriteBuffers: Error
getting volume context, status=%x\n”,
status) );

leave;
}

//
// If this is a non-cached I/O we need to round the length up to
the
// sector size for this device. We must do this because the file
// systems do this and we need to make sure our buffer is as big
// as they are expecting.
//

if (FlagOn(IRP_NOCACHE,iopb->IrpFlags)) {
//**********************************************************************************************************************
// i think the writeLen’s value is the key,because the
volctx->SectorSize is 4kb on my pc,but i don’t know how
//to fix this problem.
writeLen = (ULONG)ROUND_TO_SIZE(writeLen,volCtx->SectorSize);
}

//
// Allocate nonPaged memory for the buffer we are swapping to.
// If we fail to get the memory, just don’t swap buffers on this
// operation.
//

newBuf = ExAllocatePoolWithTag( NonPagedPool,
writeLen,
BUFFER_SWAP_TAG );

if (newBuf == NULL) {

LOG_PRINT( LOGFL_ERRORS,
(“SwapBuffers!SwapPreWriteBuffers: %wZ
Failed to allocate %d bytes of memory.\n”,
&volCtx->Name,
writeLen) );

leave;
}

//
// We only need to build a MDL for IRP operations. We don’t need
to
// do this for a FASTIO operation because it is a waste of time
since
// the FASTIO interface has no parameter for passing the MDL to the
// file system.
//

if (FlagOn(Data->Flags,FLTFL_CALLBACK_DATA_IRP_OPERATION)) {

//
// Allocate a MDL for the new allocated memory. If we fail
// the MDL allocation then we won’t swap buffer for this
operation
//

newMdl = IoAllocateMdl( newBuf,
writeLen,
FALSE,
FALSE,
NULL );

if (newMdl == NULL) {

LOG_PRINT( LOGFL_ERRORS,
(“SwapBuffers!SwapPreWriteBuffers: %wZ
Failed to allocate MDL.\n”,
&volCtx->Name) );

leave;
}

//
// setup the MDL for the non-paged pool we just allocated
//

MmBuildMdlForNonPagedPool( newMdl );
}

//
// If the users original buffer had a MDL, get a system address.
//

if (iopb->Parameters.Write.MdlAddress != NULL) {

origBuf = MmGetSystemAddressForMdlSafe(
iopb->Parameters.Write.MdlAddress,
NormalPagePriority );

if (origBuf == NULL) {

LOG_PRINT( LOGFL_ERRORS,
(“SwapBuffers!SwapPreWriteBuffers: %wZ
Failed to get system address for MDL: %p\n”,
&volCtx->Name,
iopb->Parameters.Write.MdlAddress) );

//
// If we could not get a system address for the users
buffer,
// then we are going to fail this operation.
//

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

} else {

//
// There was no MDL defined, use the given buffer address.
//

origBuf = iopb->Parameters.Write.WriteBuffer;
}

//
// Copy the memory, we must do this inside the try/except because
we
// may be using a users buffer address
//

try {

RtlCopyMemory( newBuf,
origBuf,
writeLen );

} except (EXCEPTION_EXECUTE_HANDLER) {

//
// The copy failed, return an error, failing the operation.
//

Data->IoStatus.Status = GetExceptionCode();
Data->IoStatus.Information = 0;
retValue = FLT_PREOP_COMPLETE;

LOG_PRINT( LOGFL_ERRORS,
(“SwapBuffers!SwapPreWriteBuffers: %wZ
Invalid user buffer, oldB=%p, status=%x\n”,
&volCtx->Name,
origBuf,
Data->IoStatus.Status) );

leave;
}

//
// We are ready to swap buffers, get a pre2Post context structure.
// We need it to pass the volume context and the allocate memory
// buffer to the post operation callback.
//

p2pCtx = ExAllocateFromNPagedLookasideList( &Pre2PostContextList );

if (p2pCtx == NULL) {

LOG_PRINT( LOGFL_ERRORS,
(“SwapBuffers!SwapPreWriteBuffers: %wZ
Failed to allocate pre2Post context structure\n”,
&volCtx->Name) );

leave;
}

//
// Set new buffers
//

//*****************************************************************************************************************
// I encrypt the new buffer here,pass to the encrypt routine two
parameter,buffer pointer and the buffer
// length,
EncryptBuf(newBuf,writelen);
//only this routine is mine,other part are the original routine.
//******************************************************************************************************************
LOG_PRINT( LOGFL_WRITE,
(“SwapBuffers!SwapPreWriteBuffers: %wZ newB=%p
newMdl=%p oldB=%p oldMdl=%p len=%d\n”,
&volCtx->Name,
newBuf,
newMdl,
iopb->Parameters.Write.WriteBuffer,
iopb->Parameters.Write.MdlAddress,
writeLen) );

iopb->Parameters.Write.WriteBuffer = newBuf;
iopb->Parameters.Write.MdlAddress = newMdl;
FltSetCallbackDataDirty( Data );

//
// Pass state to our post-operation callback.
//

p2pCtx->SwappedBuffer = newBuf;
p2pCtx->VolCtx = volCtx;

*CompletionContext = p2pCtx;

//
// Return we want a post-operation callback
//

retValue = FLT_PREOP_SUCCESS_WITH_CALLBACK;

} finally {

//
// If we don’t want a post-operation callback, then free the buffer
// or MDL if it was allocated.
//

if (retValue != FLT_PREOP_SUCCESS_WITH_CALLBACK) {

if (newBuf != NULL) {

ExFreePool( newBuf );
}

if (newMdl != NULL) {

IoFreeMdl( newMdl );
}

if (volCtx != NULL) {

FltReleaseContext( volCtx );
}
}
}

return retValue;
}

This has been discussed here many times. Please, check the old archives
for the answers.

Anyway, writing an encryption filter using the “I will take FileSpy
or SwapBuffers example, add a few lines and it will work” method
is a wrong approach, if you don’t understand the underlaying
basics.

L.