From: Alex Andriyanov on
I whant to make copy of all files written to disk in the special folder. So I
have my own file system filter driver, I create new file for shadow copy each
time when dispatch routine for IRP_MJ_CREATE is called (with appropriate
create options), and write to this file from dispatch routine for
IRP_MJ_WRITE. I use IoCreateFileSpecifyDeviceObjectHint to create file and
ZwWriteFile to write. But call to ZwWriteFile fails with
STATUS_FILE_LOCK_CONFLICT status. Moreover, when I call ZwWriteFile, I often
get same status in calls to low-level drivers (IoCallDriver for
IRP_MJ_WRITE), so system make several attempts to write file before success.
This behavior differs in depending on application which writes the file:
explorer.exe always write data successfully to the main destination and to
shadow copy, Mspaint always hangs, and notepad.exe writes big file after 2 -5
attempts.

My code:

NTSTATUS EskdDispatchForWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PESKD_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT fileObject = pIrpStack->FileObject;
PESKD_FILE_OBJECT eskdFileObject =
GetFileObjectEntryByFileObject(fileObject);
PIO_STACK_LOCATION pNewStack;
IO_STATUS_BLOCK IoStatusBlock;
KEVENT event;
PKEVENT pEvent1;
HANDLE hSadowEvent;
NTSTATUS statusWrite;
NTSTATUS statusCall;
LARGE_INTEGER offset;
ULONG length=0;
void* writeBuffer;


pEvent1=IoCreateSynchronizationEvent(NULL, &hSadowEvent);

if (eskdFileObject && eskdFileObject->cacheFileHandle)
{

PRINT_DEBUG_EX("Process: %x; %wZ; Buffer length
%i",PsGetCurrentProcessId(),&eskdFileObject->cacheFileName,
pIrpStack->Parameters.Write.Length);




statusWrite=STATUS_UNSUCCESSFUL;

offset=pIrpStack->Parameters.Write.ByteOffset;
length=pIrpStack->Parameters.Write.Length;

PRINT_DEBUG_EX("Offset %x",offset);

IoCopyCurrentIrpStackLocationToNext(Irp);
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)
EskdCompleteIRP, &event, TRUE, TRUE, TRUE);
statusCall = IoCallDriver(devExt->AttachedToDeviceObject, Irp);
PRINT_DEBUG_EX("IoCallDriver status %x",statusCall);

if(statusCall==STATUS_PENDING)
{
KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL );
}


if(Irp->MdlAddress)
{

writeBuffer=MmGetSystemAddressForMdlSafe(Irp->MdlAddress,NormalPagePriority);
PRINT_DEBUG(writeBuffer ? "Mdl mapped OK" : "Mdl mapped
NULL");
}
else
{
writeBuffer=Irp->UserBuffer;
PRINT_DEBUG(writeBuffer ? "UserBuffer OK" : "UserBuffer
NULL");
}



//!!! This function cause the block
statusWrite=ZwWriteFile(eskdFileObject->cacheFileHandle,
hSadowEvent,
NULL,
NULL,
&IoStatusBlock,
writeBuffer,//Irp->AssociatedIrp.SystemBuffer,
length ,
&offset,
NULL
);

PRINT_DEBUG_EX("ZwWriteFile status %x",statusWrite);

if(statusWrite==STATUS_PENDING)
{
KeWaitForSingleObject(pEvent1,
Executive,
KernelMode,
FALSE,
NULL );
}


ZwClose(hSadowEvent);

IoCompleteRequest(Irp, IO_NO_INCREMENT);


return Irp->IoStatus.Status;

}
else
{
return EskdPassThrough(DeviceObject,Irp);
}

}

File handle is opened in dispatch routine for IRP_MJ_CREATE by the following
calls:

InitializeObjectAttributes(&FileAttributes,&eskdFileObject->cacheFileName,OBJ_KERNEL_HANDLE,NULL,NULL);

IoCreateFileSpecifyDeviceObjectHint(
&eskdFileObject->cacheFileHandle,
GENERIC_WRITE,
&FileAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OVERWRITE_IF,
FILE_NON_DIRECTORY_FILE,
NULL,
0,
CreateFileTypeNone,
NULL,
0,
devExt->AttachedToDeviceObject
);