Why FltReadFile return STATUS_END_OF_FILE(c0000011)

All,
Could someone please help to review my code ?

I am trying to reading the created file in the post operation of IRP_MJ_CREATE, But Unfortunatedly got zero bytes with failure code STATUS_END_OF_FILE(c0000011).

Please review my code .

FLT_POSTOP_CALLBACK_STATUS
CreateBackUpFile_WhenPostCreatedCallback (
Inout PFLT_CALLBACK_DATA Data,
In PCFLT_RELATED_OBJECTS FltObjects,
In PVOID CompletionContext,
In FLT_POST_OPERATION_FLAGS Flags
)
{
//completeFilePath file is not the current created file.
CopyFile(Data, FltObjects, &completeFilePath);

}
NTSTATUS
CopyFile(
PFLT_CALLBACK_DATA Data,
PCFLT_RELATED_OBJECTS FltObjects,
PUNICODE_STRING pCompleteFileName
)
{
NTSTATUS status;
//UNICODE_STRING tempDeletedFilePath;
OBJECT_ATTRIBUTES tempDeletedObject;
IO_STATUS_BLOCK ioStatusTempDeleted;
LARGE_INTEGER allocate;
FILE_STANDARD_INFORMATION fileStandardInformation;
HANDLE tempDeletedHandle;
ULONG returnedLength;
PFLT_FILE_NAME_INFORMATION readNameInfo;
char readFileName[260] ={“x:”};

allocate.QuadPart = 0x10000;

InitializeObjectAttributes(
&tempDeletedObject,
pCompleteFileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);

status = FltQueryInformationFile(
FltObjects->Instance,
Data->Iopb->TargetFileObject,
&fileStandardInformation,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation,
&returnedLength
);
if(NT_SUCCESS(status))
{
allocate.QuadPart = fileStandardInformation.AllocationSize.QuadPart;
} else {
DbgPrint(“CaptureFileMonitor: ERROR - Could not get files allocation size\n”);
return status;
}

status = FltCreateFile(
FltObjects->Filter,
NULL,
&tempDeletedHandle,
GENERIC_WRITE,
&tempDeletedObject,
&ioStatusTempDeleted,
&allocate,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_CREATE,
FILE_NON_DIRECTORY_FILE,
NULL,
0,
0
);

if(NT_SUCCESS(status))
{
PVOID handleFileObject;
PVOID pFileBuffer;
LARGE_INTEGER offset;

ULONG bytesRead = 0;
ULONG bytesWritten = 0;
offset.QuadPart = 0;
status = ObReferenceObjectByHandle(
tempDeletedHandle,
0,
NULL,
KernelMode,
&handleFileObject,
NULL);
if(!NT_SUCCESS(status))
{
DbgPrint(“CaptureFileMonitor: ERROR - ObReferenceObjectByHandle - FAILED - %08x\n”, status);
return status;
}

pFileBuffer = ExAllocatePoolWithTag(NonPagedPool, 65536, FILE_POOL_TAG);

status=FltGetFileNameInformation(Data,FLT_FILE_NAME_NORMALIZED|FLT_FILE_NAME_QUERY_DEFAULT,&readNameInfo);
status=FltParseFileNameInformation(readNameInfo);
if (NPUnicodeStringToChar(&readNameInfo->Name,readFileName))
{
DbgPrint(“The reading file name is : %s\n”, readFileName);
}

FltReleaseFileNameInformation(readNameInfo);

if(pFileBuffer != NULL)
{
ObReferenceObject(Data->Iopb->TargetFileObject);
do {
IO_STATUS_BLOCK IoStatusBlock;
bytesWritten = 0;

status = FltReadFile(
FltObjects->Instance,
Data->Iopb->TargetFileObject,
&offset,
65536,
pFileBuffer,
0,//FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,
&bytesRead ,
NULL,
NULL
);

if(NT_SUCCESS(status) && bytesRead > 0)
{
//write to file

} else {
DbgPrint(“CopyFile: FltReadFile - %08x\n”, status);
break;
}
offset.QuadPart += bytesRead;
} while(bytesRead == 65536);
ObDereferenceObject(Data->Iopb->TargetFileObject);
ExFreePoolWithTag(pFileBuffer, FILE_POOL_TAG);
}
ObDereferenceObject(handleFileObject);

FltClose(tempDeletedHandle);
} else {
if(status != STATUS_OBJECT_NAME_COLLISION)
{
DbgPrint(“CaptureFileMonitor: ERROR - FltCreateFile FAILED - %08x\n”,status);
return status;
}
}
return STATUS_SUCCESS;
}

Since last post is too big , I need add more.
I had read through the document of the API http://msdn.microsoft.com/en-us/library/windows/hardware/ff544286(v=vs.85).aspx
didn’t found any clue to solve it . Is it because the current position of byte is the end of file ? How can I set it to begin ?

Thanks.
Joe Wang

Don’t use AllocationSize to determine the amount of data to read, use
the EndOfFile. AllocationSize is the allocated size on disk, if you try
to read beyond the EOF you will get an EOF error back.

ValidDataLength <= EndOfFile <= AllocationSize

I didn’t read through all the code but are you checking that the size is
non-zero? There may be no data in the file to read if it was just
created. As you read you will eventually get an EOF error since you are
not checking going beyond the EOF.

As well, you seem to be re-opening the file, referencing the returned
fileobject and the targetfileobject then using the targetfileobject for
the read. Just use the TargetFileObject, no additional referencing
needed, setting the flag you commented out to not update the file position.

Pete

On 9/11/2013 8:02 PM, Joe Wang wrote:

All,

Could someone please help to review my code ?

I am trying to reading the created file in the post operation of
IRP_MJ_CREATE, But Unfortunatedly got zero bytes with failure code
STATUS_END_OF_FILE(c0000011).

Please review my code .

FLT_POSTOP_CALLBACK_STATUS

CreateBackUpFile_WhenPostCreatedCallback (

Inout PFLT_CALLBACK_DATA Data,

In PCFLT_RELATED_OBJECTS FltObjects,

In PVOID CompletionContext,

In FLT_POST_OPERATION_FLAGS Flags

)

{

//completeFilePath file is not the current created file.

CopyFile(Data, FltObjects, &completeFilePath);

}

NTSTATUS

CopyFile(

PFLT_CALLBACK_DATA Data,

PCFLT_RELATED_OBJECTS FltObjects,

PUNICODE_STRING pCompleteFileName

)

{

NTSTATUS status;

//UNICODE_STRING tempDeletedFilePath;

OBJECT_ATTRIBUTES tempDeletedObject;

IO_STATUS_BLOCK ioStatusTempDeleted;

LARGE_INTEGER allocate;

FILE_STANDARD_INFORMATION fileStandardInformation;

HANDLE tempDeletedHandle;

ULONG returnedLength;

PFLT_FILE_NAME_INFORMATION readNameInfo;

char readFileName[260] ={“x:”};

allocate.QuadPart = 0x10000;

InitializeObjectAttributes(

&tempDeletedObject,

pCompleteFileName,

OBJ_CASE_INSENSITIVE,

NULL,

NULL

);

status = FltQueryInformationFile(

FltObjects->Instance,

Data->Iopb->TargetFileObject,

&fileStandardInformation,

sizeof(FILE_STANDARD_INFORMATION),

FileStandardInformation,

&returnedLength

);

if(NT_SUCCESS(status))

{

allocate.QuadPart =
fileStandardInformation.AllocationSize.QuadPart;

} else {

DbgPrint(“CaptureFileMonitor: ERROR -
Could not get files allocation size\n”);

return status;

}

status = FltCreateFile(

FltObjects->Filter,

NULL,

&tempDeletedHandle,

GENERIC_WRITE,

&tempDeletedObject,

&ioStatusTempDeleted,

&allocate,

FILE_ATTRIBUTE_NORMAL,

0,

FILE_CREATE,

FILE_NON_DIRECTORY_FILE,

NULL,

0,

0

);

if(NT_SUCCESS(status))

{

PVOID handleFileObject;

PVOID pFileBuffer;

LARGE_INTEGER offset;

ULONG bytesRead = 0;

ULONG bytesWritten = 0;

offset.QuadPart = 0;

status = ObReferenceObjectByHandle(

tempDeletedHandle,

0,

NULL,

KernelMode,

&handleFileObject,

NULL);

if(!NT_SUCCESS(status))

{

DbgPrint("CaptureFileMonitor: ERROR - ObReferenceObjectByHandle - FAILED

  • %08x\n", status);

return status;

}

pFileBuffer =
ExAllocatePoolWithTag(NonPagedPool, 65536, FILE_POOL_TAG);

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

status=FltParseFileNameInformation(readNameInfo);

if
(NPUnicodeStringToChar(&readNameInfo->Name,readFileName))

{

DbgPrint(“The reading
file name is : %s\n”, readFileName);

}

FltReleaseFileNameInformation(readNameInfo);

if(pFileBuffer != NULL)

{

ObReferenceObject(Data->Iopb->TargetFileObject);

do {

IO_STATUS_BLOCK IoStatusBlock;

bytesWritten = 0;

status
= FltReadFile(

FltObjects->Instance,

Data->Iopb->TargetFileObject,

&offset,

65536,

pFileBuffer,

0,//FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,

&bytesRead ,

NULL,

NULL

);

if(NT_SUCCESS(status) && bytesRead > 0)

{

//write to file

} else {

DbgPrint(“CopyFile: FltReadFile - %08x\n”, status);

break;

}

offset.QuadPart += bytesRead;

} while(bytesRead ==
65536);

ObDereferenceObject(Data->Iopb->TargetFileObject);

ExFreePoolWithTag(pFileBuffer, FILE_POOL_TAG);

}

ObDereferenceObject(handleFileObject);

FltClose(tempDeletedHandle);

} else {

if(status != STATUS_OBJECT_NAME_COLLISION)

{

DbgPrint(“CaptureFileMonitor: ERROR - FltCreateFile FAILED -
%08x\n”,status);

return status;

}

}

return STATUS_SUCCESS;

}


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295

Hi Peter,

Following your suggestion, I remove the code of reference TargetFileObject (ObReferenceObject(Data->Iopb->TargetFileObject);), and Check the size of the file been reading (it is about 3.6KB). But still got the same error code as before. Any other ideas?

Thanks.
Joe Wang

Hi Peter,
I try to change the size of the buffer from 65536 to 1000, To make the minifilter read more time from the source file. It seems even the first time to read file failed.
Does it mean this error doesn’t matter with the buffer size and the length of trying to read?

Thanks.
Joe Wang

If you perform a read of 1KB starting at offset 0 from a file which has
data, the first read will not return an EOF error, it will return
success. There is something not correct in your code. Can you post what
you have now?

Pete

On 9/12/2013 12:59 AM, xxxxx@achievo.com wrote:

Hi Peter,
I try to change the size of the buffer from 65536 to 1000, To make the minifilter read more time from the source file. It seems even the first time to read file failed.
Does it mean this error doesn’t matter with the buffer size and the length of trying to read?

Thanks.
Joe Wang


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer


Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295

Sure, If you can help to review my code . It will be appreciated. Please review the following reply.

Thanks.
Joe Wang

#define _CRT_SECURE_NO_WARNINGS
#include “mspyKern.h”
#include <stdio.h>
#include <ntstrsafe.h>

#define FILE_POOL_TAG ‘cfm’
//
// Global variables
//

MINISPY_DATA MiniSpyData;
NTSTATUS StatusToBreakOn = 0;

//---------------------------------------------------------------------------
// Function prototypes
//---------------------------------------------------------------------------
DRIVER_INITIALIZE DriverEntry;
NTSTATUS
DriverEntry (
In PDRIVER_OBJECT DriverObject,
In PUNICODE_STRING RegistryPath
);

NTSTATUS
SpyMessage (
In PVOID ConnectionCookie,
In_reads_bytes_opt(InputBufferSize) PVOID InputBuffer,
In ULONG InputBufferSize,
Out_writes_bytes_to_opt(OutputBufferSize,*ReturnOutputBufferLength) PVOID OutputBuffer,
In ULONG OutputBufferSize,
Out PULONG ReturnOutputBufferLength
);

NTSTATUS
SpyConnect(
In PFLT_PORT ClientPort,
In PVOID ServerPortCookie,
In_reads_bytes(SizeOfContext) PVOID ConnectionContext,
In ULONG SizeOfContext,
Flt_ConnectionCookie_Outptr PVOID *ConnectionCookie
);

VOID
SpyDisconnect(
In_opt PVOID ConnectionCookie
);

NTSTATUS
SpyEnlistInTransaction (
In PCFLT_RELATED_OBJECTS FltObjects
);

BOOLEAN NPUnicodeStringToChar(PUNICODE_STRING UniName, char Name);

VOID
GetDosDeviceName(PDEVICE_OBJECT pDeviceObject,
PUNICODE_STRING pShareName,
PUNICODE_STRING pDosName);

NTSTATUS
CopyFile(
PFLT_CALLBACK_DATA Data,
PCFLT_RELATED_OBJECTS FltObjects,
PUNICODE_STRING pCompleteFileName
);

//---------------------------------------------------------------------------
// Assign text sections for each routine.
//---------------------------------------------------------------------------

#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, SpyFilterUnload)
#pragma alloc_text(PAGE, SpyQueryTeardown)
#pragma alloc_text(PAGE, SpyConnect)
#pragma alloc_text(PAGE, SpyDisconnect)
#pragma alloc_text(PAGE, SpyMessage)
#endif

#define SetFlagInterlocked(_ptrFlags,_flagToSet) <br> ((VOID)InterlockedOr(((volatile LONG *)(_ptrFlags)),_flagToSet))</ntstrsafe.h></stdio.h>

NTSTATUS
DriverEntry (
In PDRIVER_OBJECT DriverObject,
In PUNICODE_STRING RegistryPath
)
/*++

Routine Description:

This routine is called when a driver first loads. Its purpose is to
initialize global state and then register with FltMgr to start filtering.

Arguments:

DriverObject - Pointer to driver object created by the system to
represent this driver.
RegistryPath - Unicode string identifying where the parameters for this
driver are located in the registry.

Return Value:

Status of the operation.

–*/
{
PSECURITY_DESCRIPTOR sd;
OBJECT_ATTRIBUTES oa;
UNICODE_STRING uniString;
NTSTATUS status = STATUS_SUCCESS;

try {

//
// Initialize global data structures.
//

MiniSpyData.LogSequenceNumber = 0;
MiniSpyData.MaxRecordsToAllocate = DEFAULT_MAX_RECORDS_TO_ALLOCATE;
MiniSpyData.RecordsAllocated = 0;
MiniSpyData.NameQueryMethod = DEFAULT_NAME_QUERY_METHOD;

MiniSpyData.DriverObject = DriverObject;

InitializeListHead( &MiniSpyData.OutputBufferList );
KeInitializeSpinLock( &MiniSpyData.OutputBufferLock );

ExInitializeNPagedLookasideList( &MiniSpyData.FreeBufferList,
NULL,
NULL,
0,
RECORD_SIZE,
SPY_TAG,
0 );

#if MINISPY_VISTA

//
// Dynamically import FilterMgr APIs for transaction support
//

#pragma warning(push)
#pragma warning(disable:4055) // type cast from data pointer to function pointer
MiniSpyData.PFltSetTransactionContext = (PFLT_SET_TRANSACTION_CONTEXT) FltGetRoutineAddress( “FltSetTransactionContext” );
MiniSpyData.PFltGetTransactionContext = (PFLT_GET_TRANSACTION_CONTEXT) FltGetRoutineAddress( “FltGetTransactionContext” );
MiniSpyData.PFltEnlistInTransaction = (PFLT_ENLIST_IN_TRANSACTION) FltGetRoutineAddress( “FltEnlistInTransaction” );
#pragma warning(pop)

#endif

//
// Read the custom parameters for MiniSpy from the registry
//

SpyReadDriverParameters(RegistryPath);

//
// Now that our global configuration is complete, register with FltMgr.
//

status = FltRegisterFilter( DriverObject,
&FilterRegistration,
&MiniSpyData.Filter );

if (!NT_SUCCESS( status )) {

leave;
}

status = FltBuildDefaultSecurityDescriptor( &sd,
FLT_PORT_ALL_ACCESS );

if (!NT_SUCCESS( status )) {
leave;
}

RtlInitUnicodeString( &uniString, MINISPY_PORT_NAME );

InitializeObjectAttributes( &oa,
&uniString,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
NULL,
sd );

status = FltCreateCommunicationPort( MiniSpyData.Filter,
&MiniSpyData.ServerPort,
&oa,
NULL,
SpyConnect,
SpyDisconnect,
SpyMessage,
1 );

FltFreeSecurityDescriptor( sd );

if (!NT_SUCCESS( status )) {
leave;
}

//
// We are now ready to start filtering
//

status = FltStartFiltering( MiniSpyData.Filter );

} finally {

if (!NT_SUCCESS( status ) ) {

if (NULL != MiniSpyData.ServerPort) {
FltCloseCommunicationPort( MiniSpyData.ServerPort );
}

if (NULL != MiniSpyData.Filter) {
FltUnregisterFilter( MiniSpyData.Filter );
}

ExDeleteNPagedLookasideList( &MiniSpyData.FreeBufferList );
}
}

return status;
}

NTSTATUS
SpyConnect(
In PFLT_PORT ClientPort,
In PVOID ServerPortCookie,
In_reads_bytes(SizeOfContext) PVOID ConnectionContext,
In ULONG SizeOfContext,
Flt_ConnectionCookie_Outptr PVOID *ConnectionCookie
)
/*++

Routine Description

This is called when user-mode connects to the server
port - to establish a connection

Arguments

ClientPort - This is the pointer to the client port that
will be used to send messages from the filter.
ServerPortCookie - unused
ConnectionContext - unused
SizeofContext - unused
ConnectionCookie - unused

Return Value

STATUS_SUCCESS - to accept the connection
–*/
{

PAGED_CODE();

UNREFERENCED_PARAMETER( ServerPortCookie );
UNREFERENCED_PARAMETER( ConnectionContext );
UNREFERENCED_PARAMETER( SizeOfContext);
UNREFERENCED_PARAMETER( ConnectionCookie );

FLT_ASSERT( MiniSpyData.ClientPort == NULL );
MiniSpyData.ClientPort = ClientPort;
return STATUS_SUCCESS;
}

VOID
SpyDisconnect(
In_opt PVOID ConnectionCookie
)
/*++

Routine Description

This is called when the connection is torn-down. We use it to close our handle to the connection

Arguments

ConnectionCookie - unused

Return value

None
–*/
{

PAGED_CODE();

UNREFERENCED_PARAMETER( ConnectionCookie );

//
// Close our handle
//

FltCloseClientPort( MiniSpyData.Filter, &MiniSpyData.ClientPort );
}

NTSTATUS
SpyFilterUnload (
In FLT_FILTER_UNLOAD_FLAGS Flags
)
/*++

Routine Description:

This is called when a request has been made to unload the filter. Unload
requests from the Operation System (ex: “sc stop minispy” can not be
failed. Other unload requests may be failed.

You can disallow OS unload request by setting the
FLTREGFL_DO_NOT_SUPPORT_SERVICE_STOP flag in the FLT_REGISTARTION
structure.

Arguments:

Flags - Flags pertinent to this operation

Return Value:

Always success

–*/
{
UNREFERENCED_PARAMETER( Flags );

PAGED_CODE();

//
// Close the server port. This will stop new connections.
//

FltCloseCommunicationPort( MiniSpyData.ServerPort );

FltUnregisterFilter( MiniSpyData.Filter );

SpyEmptyOutputBufferList();
ExDeleteNPagedLookasideList( &MiniSpyData.FreeBufferList );

return STATUS_SUCCESS;
}

NTSTATUS
SpyQueryTeardown (
In PCFLT_RELATED_OBJECTS FltObjects,
In FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
)
/*++

Routine Description:

This allows our filter to be manually detached from a volume.

Arguments:

FltObjects - Contains pointer to relevant objects for this operation.
Note that the FileObject field will always be NULL.

Flags - Flags pertinent to this operation

Return Value:

–*/
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
return STATUS_SUCCESS;
}

NTSTATUS
SpyMessage (
In PVOID ConnectionCookie,
In_reads_bytes_opt(InputBufferSize) PVOID InputBuffer,
In ULONG InputBufferSize,
Out_writes_bytes_to_opt(OutputBufferSize,*ReturnOutputBufferLength) PVOID OutputBuffer,
In ULONG OutputBufferSize,
Out PULONG ReturnOutputBufferLength
)
/*++

Routine Description:

This is called whenever a user mode application wishes to communicate
with this minifilter.

Arguments:

ConnectionCookie - unused

OperationCode - An identifier describing what type of message this
is. These codes are defined by the MiniFilter.
InputBuffer - A buffer containing input data, can be NULL if there
is no input data.
InputBufferSize - The size in bytes of the InputBuffer.
OutputBuffer - A buffer provided by the application that originated
the communication in which to store data to be returned to this
application.
OutputBufferSize - The size in bytes of the OutputBuffer.
ReturnOutputBufferSize - The size in bytes of meaningful data
returned in the OutputBuffer.

Return Value:

Returns the status of processing the message.

–*/
{
MINISPY_COMMAND command;
NTSTATUS status;

PAGED_CODE();

UNREFERENCED_PARAMETER( ConnectionCookie );

//
// **** PLEASE READ ****
//
// The INPUT and OUTPUT buffers are raw user mode addresses. The filter
// manager has already done a ProbedForRead (on InputBuffer) and
// ProbedForWrite (on OutputBuffer) which guarentees they are valid
// addresses based on the access (user mode vs. kernel mode). The
// minifilter does not need to do their own probe.
//
// The filter manager is NOT doing any alignment checking on the pointers.
// The minifilter must do this themselves if they care (see below).
//
// The minifilter MUST continue to use a try/except around any access to
// these buffers.
//

if ((InputBuffer != NULL) &&
(InputBufferSize >= (FIELD_OFFSET(COMMAND_MESSAGE,Command) +
sizeof(MINISPY_COMMAND)))) {

try {

//
// Probe and capture input message: the message is raw user mode
// buffer, so need to protect with exception handler
//

command = ((PCOMMAND_MESSAGE) InputBuffer)->Command;

} except (SpyExceptionFilter( GetExceptionInformation(), TRUE )) {

return GetExceptionCode();
}

switch (command) {

case GetMiniSpyLog:

//
// Return as many log records as can fit into the OutputBuffer
//

if ((OutputBuffer == NULL) || (OutputBufferSize == 0)) {

status = STATUS_INVALID_PARAMETER;
break;
}

//
// We want to validate that the given buffer is POINTER
// aligned. But if this is a 64bit system and we want to
// support 32bit applications we need to be careful with how
// we do the check. Note that the way SpyGetLog is written
// it actually does not care about alignment but we are
// demonstrating how to do this type of check.
//

#if defined(_WIN64)

if (IoIs32bitProcess( NULL )) {

//
// Validate alignment for the 32bit process on a 64bit
// system
//

if (!IS_ALIGNED(OutputBuffer,sizeof(ULONG))) {

status = STATUS_DATATYPE_MISALIGNMENT;
break;
}

} else {

#endif

if (!IS_ALIGNED(OutputBuffer,sizeof(PVOID))) {

status = STATUS_DATATYPE_MISALIGNMENT;
break;
}

#if defined(_WIN64)

}

#endif

//
// Get the log record.
//

status = SpyGetLog( OutputBuffer,
OutputBufferSize,
ReturnOutputBufferLength );
break;

case GetMiniSpyVersion:

//
// Return version of the MiniSpy filter driver. Verify
// we have a valid user buffer including valid
// alignment
//

if ((OutputBufferSize < sizeof( MINISPYVER )) ||
(OutputBuffer == NULL)) {

status = STATUS_INVALID_PARAMETER;
break;
}

//
// Validate Buffer alignment. If a minifilter cares about
// the alignment value of the buffer pointer they must do
// this check themselves. Note that a try/except will not
// capture alignment faults.
//

if (!IS_ALIGNED(OutputBuffer,sizeof(ULONG))) {

status = STATUS_DATATYPE_MISALIGNMENT;
break;
}

//
// Protect access to raw user-mode output buffer with an
// exception handler
//

try {

((PMINISPYVER)OutputBuffer)->Major = MINISPY_MAJ_VERSION;
((PMINISPYVER)OutputBuffer)->Minor = MINISPY_MIN_VERSION;

} except (SpyExceptionFilter( GetExceptionInformation(), TRUE )) {

return GetExceptionCode();
}

*ReturnOutputBufferLength = sizeof( MINISPYVER );
status = STATUS_SUCCESS;
break;

default:
status = STATUS_INVALID_PARAMETER;
break;
}

} else {

status = STATUS_INVALID_PARAMETER;
}

return status;
}

Please do not post the ENTIRE driver code, just the relevant code for
the post-create processing.

Pete

On 9/12/2013 5:48 AM, xxxxx@achievo.com wrote:

NTSTATUS
SpyConnect(
In PFLT_PORT ClientPort,
In PVOID ServerPortCookie,
In_reads_bytes(SizeOfContext) PVOID ConnectionContext,
In ULONG SizeOfContext,
Flt_ConnectionCookie_Outptr PVOID *ConnectionCookie
)
/*++

Routine Description

This is called when user-mode connects to the server
port - to establish a connection

Arguments

ClientPort - This is the pointer to the client port that
will be used to send messages from the filter.
ServerPortCookie - unused
ConnectionContext - unused
SizeofContext - unused
ConnectionCookie - unused

Return Value

STATUS_SUCCESS - to accept the connection
–*/
{

PAGED_CODE();

UNREFERENCED_PARAMETER( ServerPortCookie );
UNREFERENCED_PARAMETER( ConnectionContext );
UNREFERENCED_PARAMETER( SizeOfContext);
UNREFERENCED_PARAMETER( ConnectionCookie );

FLT_ASSERT( MiniSpyData.ClientPort == NULL );
MiniSpyData.ClientPort = ClientPort;
return STATUS_SUCCESS;
}

VOID
SpyDisconnect(
In_opt PVOID ConnectionCookie
)
/*++

Routine Description

This is called when the connection is torn-down. We use it to close our handle to the connection

Arguments

ConnectionCookie - unused

Return value

None
–*/
{

PAGED_CODE();

UNREFERENCED_PARAMETER( ConnectionCookie );

//
// Close our handle
//

FltCloseClientPort( MiniSpyData.Filter, &MiniSpyData.ClientPort );
}

NTSTATUS
SpyFilterUnload (
In FLT_FILTER_UNLOAD_FLAGS Flags
)
/*++

Routine Description:

This is called when a request has been made to unload the filter. Unload
requests from the Operation System (ex: “sc stop minispy” can not be
failed. Other unload requests may be failed.

You can disallow OS unload request by setting the
FLTREGFL_DO_NOT_SUPPORT_SERVICE_STOP flag in the FLT_REGISTARTION
structure.

Arguments:

Flags - Flags pertinent to this operation

Return Value:

Always success

–*/
{
UNREFERENCED_PARAMETER( Flags );

PAGED_CODE();

//
// Close the server port. This will stop new connections.
//

FltCloseCommunicationPort( MiniSpyData.ServerPort );

FltUnregisterFilter( MiniSpyData.Filter );

SpyEmptyOutputBufferList();
ExDeleteNPagedLookasideList( &MiniSpyData.FreeBufferList );

return STATUS_SUCCESS;
}

NTSTATUS
SpyQueryTeardown (
In PCFLT_RELATED_OBJECTS FltObjects,
In FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
)
/*++

Routine Description:

This allows our filter to be manually detached from a volume.

Arguments:

FltObjects - Contains pointer to relevant objects for this operation.
Note that the FileObject field will always be NULL.

Flags - Flags pertinent to this operation

Return Value:

–*/
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
return STATUS_SUCCESS;
}


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer


Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295

Ok. Please review the below code. it is the PostOpCreate call back . thanks.

FLT_POSTOP_CALLBACK_STATUS
CreateBackUpFile_WhenPostCreatedCallback (
Inout PFLT_CALLBACK_DATA Data,
In PCFLT_RELATED_OBJECTS FltObjects,
In PVOID CompletionContext,
In FLT_POST_OPERATION_FLAGS Flags
)
/*++

Routine Description:

This routine receives ALL post-operation callbacks. This will take
the log record passed in the context parameter and update it with
the completion information. It will then insert it on a list to be
sent to the usermode component.

NOTE: This routine must be NON-PAGED because it can be called at DPC level

Arguments:

Data - Contains information about the given operation.

FltObjects - Contains pointers to the various objects that are pertinent
to this operation.

CompletionContext - Pointer to the RECORD_LIST structure in which we
store the information we are logging. This was passed from the
pre-operation callback

Flags - Contains information as to why this routine was called.

Return Value:

Identifies how processing should continue for this operation

–*/
{

NTSTATUS status;
BOOLEAN isDirectory;
//OBJECT_ATTRIBUTES objAttributes;
//HANDLE directoryHandle = NULL;
//IO_STATUS_BLOCK ioStatusBlock;
//PCUNICODE_STRING ParentDirectory;
char FileName[260] ={“x:”};
//char DosDriveName[260] ={“x:”};
PFLT_FILE_NAME_INFORMATION nameInfo;
UNICODE_STRING completeFilePath;
UNICODE_STRING logDirectory;

/*
BOOLEAN ignoreCase = !BooleanFlagOn( Flags,
FLTFL_NORMALIZE_NAME_CASE_SENSITIVE );

InitializeObjectAttributes( &objAttributes,
(PUNICODE_STRING)ParentDirectory,
OBJ_KERNEL_HANDLE
| (ignoreCase ? OBJ_CASE_INSENSITIVE : 0),
NULL,
NULL );
*/

UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
UNREFERENCED_PARAMETER(Flags);

PAGED_CODE();

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

if (Data->IoStatus.Information==FILE_DOES_NOT_EXIST)
{
DbgPrint(“IoStatus.Information is FILE_DOES_NOT_EXIST.\n”);
}

if (Data->IoStatus.Information==FILE_EXISTS)
{
DbgPrint(“IoStatus.Information is FILE_EXISTS.\n”);
}

if (Data->IoStatus.Information==FILE_OPENED)
{
DbgPrint(“IoStatus.Information is FILE_OPENED.\n”);
}

if (Data->IoStatus.Information==FILE_OVERWRITTEN)
{
DbgPrint(“IoStatus.Information is FILE_OVERWRITTEN.\n”);
}

if (Data->IoStatus.Information==FILE_SUPERSEDED)
{
DbgPrint(“IoStatus.Information is FILE_SUPERSEDED.\n”);
}

FltIsDirectory(Data->Iopb->TargetFileObject,FltObjects->Instance,&isDirectory);

if(isDirectory)
{
DbgPrint(“Current object is a Directory.\n”);
return FLT_POSTOP_FINISHED_PROCESSING;
}
else
{
DbgPrint(“Current object is a File.\n”);
}

if (Data->IoStatus.Information==FILE_CREATED)
{
DbgPrint(“IoStatus.Information is FILE_CREATED.\n”);
if (NT_SUCCESS(status))
{
status=FltParseFileNameInformation(nameInfo);
//KdBreakPoint();
if (NT_SUCCESS( status )) {
if (NPUnicodeStringToChar(&nameInfo->Name,FileName))
{
DbgPrint(“The created file name is : %s\n”, FileName);
}

/*
if (KeAreAllApcsDisabled())
{
DbgPrint(“Can not call the IoVolumeDeviceToDosName.\n”);
}
else
{

RtlInitEmptyUnicodeString(&fileDosDrive,NULL,0);
if (NT_SUCCESS(FltGetDiskDeviceObject(FltObjects->Volume, &pDeviceObject)))
{
if (NT_SUCCESS(IoVolumeDeviceToDosName(pDeviceObject,&fileDosDrive)))
{
DbgPrint(“Invoke IoVolumeDeviceToDosName successfully.\n”);
DbgPrint(“DosDrive: %wZ\n”, &fileDosDrive);
}
else
{
DbgPrint(“Invoking IoVolumeDeviceToDosName fails.\n”);
}
}
}
*/

RtlUnicodeStringInit(&logDirectory, L"\??\c:\logs\created_files\");

completeFilePath.Length = 0;
completeFilePath.MaximumLength = 256;
completeFilePath.Buffer = ExAllocatePoolWithTag(NonPagedPool, completeFilePath.MaximumLength, FILE_POOL_TAG);

RtlUnicodeStringCat(&completeFilePath, &logDirectory);
RtlUnicodeStringCat(&completeFilePath, &nameInfo->FinalComponent);

DbgPrint(“CompleteFilePath is : %wZ\n”, &completeFilePath);

CopyFile(Data, FltObjects, &completeFilePath);

if(completeFilePath.Buffer != NULL)
ExFreePoolWithTag(completeFilePath.Buffer, FILE_POOL_TAG);
}
FltReleaseFileNameInformation(nameInfo);
}
}
}
__except(EXCEPTION_EXECUTE_HANDLER){
DbgPrint(“Error in the CreateBackUpFile_WhenPostCreatedCallback.\n”);
}

/*
status = FltCreateFile( MiniSpyData.Filter,
FltObjects->Instance,
&directoryHandle,
FILE_LIST_DIRECTORY | SYNCHRONIZE, // DesiredAccess
&objAttributes,
&ioStatusBlock,
NULL, // AllocationSize
FILE_ATTRIBUTE_DIRECTORY
| FILE_ATTRIBUTE_NORMAL, // FileAttributes
FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE, // ShareAccess
FILE_OPEN, // CreateDisposition
FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT, // CreateOptions
NULL, // EaBuffer
0, // EaLength
IO_IGNORE_SHARE_ACCESS_CHECK ); // Flags

*/
return FLT_POSTOP_FINISHED_PROCESSING;
}

And the code of the CopyFile is in the first post . Please review it .thanks.

Hi Peter, Better to Post the current code of the CopyFile . Please review it . thanks.
NTSTATUS
CopyFile(
PFLT_CALLBACK_DATA Data,
PCFLT_RELATED_OBJECTS FltObjects,
PUNICODE_STRING pCompleteFileName
)
{
NTSTATUS status;
OBJECT_ATTRIBUTES tempDeletedObject;
IO_STATUS_BLOCK ioStatusTempDeleted;
LARGE_INTEGER allocate;
FILE_STANDARD_INFORMATION fileStandardInformation;
HANDLE tempDeletedHandle;
ULONG returnedLength;
PFLT_FILE_NAME_INFORMATION readNameInfo;
allocate.QuadPart = 0x10000;

InitializeObjectAttributes(
&tempDeletedObject,
pCompleteFileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
status = FltQueryInformationFile(
FltObjects->Instance,
Data->Iopb->TargetFileObject,
&fileStandardInformation,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation,
&returnedLength
);
if(NT_SUCCESS(status))
{
allocate.QuadPart = fileStandardInformation.AllocationSize.QuadPart;
} else {
return status;
}
status = FltCreateFile(
FltObjects->Filter,
NULL,
&tempDeletedHandle,
GENERIC_WRITE,
&tempDeletedObject,
&ioStatusTempDeleted,
&allocate,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_CREATE,
FILE_NON_DIRECTORY_FILE,
NULL,
0,
0
);

if(NT_SUCCESS(status))
{
PVOID handleFileObject;
PVOID pFileBuffer;
LARGE_INTEGER offset;
ULONG bytesRead = 0;
ULONG bytesWritten = 0;
offset.QuadPart = 0;
status = ObReferenceObjectByHandle(
tempDeletedHandle,
0,
NULL,
KernelMode,
&handleFileObject,
NULL);
if(!NT_SUCCESS(status))
{
return status;
}
pFileBuffer = ExAllocatePoolWithTag(NonPagedPool, 1000, FILE_POOL_TAG);
if(pFileBuffer != NULL)
{
do {
IO_STATUS_BLOCK IoStatusBlock;
bytesWritten = 0;

status = FltReadFile(
FltObjects->Instance,

FltObjects->FileObject,
&offset,
1000,
pFileBuffer,
FLTFL_IO_OPERATION_NON_CACHED |
FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,
&bytesRead ,
NULL,
NULL
);
if(NT_SUCCESS(status) && bytesRead > 0)
{
//begin to write file.
} else {
break;
}
offset.QuadPart += bytesRead;
} while(bytesRead == 1000);
FltFreePoolAlignedWithTag( FltObjects->Instance, pFileBuffer, FILE_POOL_TAG );
}
else
{}
ObDereferenceObject(handleFileObject);
FltClose(tempDeletedHandle);
} else {
if(status != STATUS_OBJECT_NAME_COLLISION)
{
return status;
}
}
return STATUS_SUCCESS;
}

In the previous listing for the post-create processing, before you call
CopyFile(), you are checking if the current file had been CREATED

if( Data->IoStatus.Information==FILE_CREATED)

If the file was just created then there is NO data in the file since it
has not been written to yet. Do you want to check for when the file is
OPENED?

Pete

On 9/12/2013 6:16 AM, Joe Wang wrote:

Hi Peter, Better to Post the current code of the CopyFile . Please review it . thanks.
NTSTATUS
CopyFile(
PFLT_CALLBACK_DATA Data,
PCFLT_RELATED_OBJECTS FltObjects,
PUNICODE_STRING pCompleteFileName
)
{
NTSTATUS status;
OBJECT_ATTRIBUTES tempDeletedObject;
IO_STATUS_BLOCK ioStatusTempDeleted;
LARGE_INTEGER allocate;
FILE_STANDARD_INFORMATION fileStandardInformation;
HANDLE tempDeletedHandle;
ULONG returnedLength;
PFLT_FILE_NAME_INFORMATION readNameInfo;
allocate.QuadPart = 0x10000;

InitializeObjectAttributes(
&tempDeletedObject,
pCompleteFileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
status = FltQueryInformationFile(
FltObjects->Instance,
Data->Iopb->TargetFileObject,
&fileStandardInformation,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation,
&returnedLength
);
if(NT_SUCCESS(status))
{
allocate.QuadPart = fileStandardInformation.AllocationSize.QuadPart;
} else {
return status;
}
status = FltCreateFile(
FltObjects->Filter,
NULL,
&tempDeletedHandle,
GENERIC_WRITE,
&tempDeletedObject,
&ioStatusTempDeleted,
&allocate,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_CREATE,
FILE_NON_DIRECTORY_FILE,
NULL,
0,
0
);

if(NT_SUCCESS(status))
{
PVOID handleFileObject;
PVOID pFileBuffer;
LARGE_INTEGER offset;
ULONG bytesRead = 0;
ULONG bytesWritten = 0;
offset.QuadPart = 0;
status = ObReferenceObjectByHandle(
tempDeletedHandle,
0,
NULL,
KernelMode,
&handleFileObject,
NULL);
if(!NT_SUCCESS(status))
{
return status;
}
pFileBuffer = ExAllocatePoolWithTag(NonPagedPool, 1000, FILE_POOL_TAG);
if(pFileBuffer != NULL)
{
do {
IO_STATUS_BLOCK IoStatusBlock;
bytesWritten = 0;

status = FltReadFile(
FltObjects->Instance,

FltObjects->FileObject,
&offset,
1000,
pFileBuffer,
FLTFL_IO_OPERATION_NON_CACHED |
FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,
&bytesRead ,
NULL,
NULL
);
if(NT_SUCCESS(status) && bytesRead > 0)
{
//begin to write file.
} else {
break;
}
offset.QuadPart += bytesRead;
} while(bytesRead == 1000);
FltFreePoolAlignedWithTag( FltObjects->Instance, pFileBuffer, FILE_POOL_TAG );
}
else
{}
ObDereferenceObject(handleFileObject);
FltClose(tempDeletedHandle);
} else {
if(status != STATUS_OBJECT_NAME_COLLISION)
{
return status;
}
}
return STATUS_SUCCESS;
}


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer


Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295

Hi Peter,
If it is not the right time to copy the whole file , When should I do it? Calling the CopyFile function In the PostOpWrite call back ? right?
Please give me some instructions to follow. Thanks.

Kind Regards.
Joe Wang

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Peter Scott
Sent: Thursday, September 12, 2013 8:24 PM
To: Windows File Systems Devs Interest List
Subject: Re: [ntfsd] Why FltReadFile return STATUS_END_OF_FILE(c0000011)

In the previous listing for the post-create processing, before you call CopyFile(), you are checking if the current file had been CREATED

if( Data->IoStatus.Information==FILE_CREATED)

If the file was just created then there is NO data in the file since it has not been written to yet. Do you want to check for when the file is OPENED?

Pete

On 9/12/2013 6:16 AM, Joe Wang wrote:

Hi Peter, Better to Post the current code of the CopyFile . Please review it . thanks.
NTSTATUS
CopyFile(
PFLT_CALLBACK_DATA Data,
PCFLT_RELATED_OBJECTS FltObjects,
PUNICODE_STRING pCompleteFileName
)
{
NTSTATUS status;
OBJECT_ATTRIBUTES tempDeletedObject;
IO_STATUS_BLOCK ioStatusTempDeleted;
LARGE_INTEGER allocate;
FILE_STANDARD_INFORMATION fileStandardInformation;
HANDLE tempDeletedHandle;
ULONG returnedLength;
PFLT_FILE_NAME_INFORMATION readNameInfo;
allocate.QuadPart = 0x10000;

InitializeObjectAttributes(
&tempDeletedObject,
pCompleteFileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
status = FltQueryInformationFile(
FltObjects->Instance,
Data->Iopb->TargetFileObject,
&fileStandardInformation,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation,
&returnedLength
);
if(NT_SUCCESS(status))
{
allocate.QuadPart = fileStandardInformation.AllocationSize.QuadPart;
} else {
return status;
}
status = FltCreateFile(
FltObjects->Filter,
NULL,
&tempDeletedHandle,
GENERIC_WRITE,
&tempDeletedObject,
&ioStatusTempDeleted,
&allocate,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_CREATE,
FILE_NON_DIRECTORY_FILE,
NULL,
0,
0
);

if(NT_SUCCESS(status))
{
PVOID handleFileObject;
PVOID pFileBuffer;
LARGE_INTEGER offset;
ULONG bytesRead = 0;
ULONG bytesWritten = 0;
offset.QuadPart = 0;
status = ObReferenceObjectByHandle(
tempDeletedHandle,
0,
NULL,
KernelMode,
&handleFileObject,
NULL);
if(!NT_SUCCESS(status))
{
return status;
}
pFileBuffer = ExAllocatePoolWithTag(NonPagedPool, 1000, FILE_POOL_TAG);
if(pFileBuffer != NULL)
{
do {
IO_STATUS_BLOCK IoStatusBlock;
bytesWritten = 0;

status = FltReadFile(
FltObjects->Instance,

FltObjects->FileObject,
&offset,
1000,
pFileBuffer,
FLTFL_IO_OPERATION_NON_CACHED |
FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,
&bytesRead ,
NULL,
NULL
);
if(NT_SUCCESS(status) && bytesRead > 0)
{
//begin to write file.
} else {
break;
}
offset.QuadPart += bytesRead;
} while(bytesRead == 1000);
FltFreePoolAlignedWithTag( FltObjects->Instance, pFileBuffer, FILE_POOL_TAG );
}
else
{}
ObDereferenceObject(handleFileObject);
FltClose(tempDeletedHandle);
} else {
if(status != STATUS_OBJECT_NAME_COLLISION)
{
return status;
}
}
return STATUS_SUCCESS;
}


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


Kernel Drivers
Windows File System and Device Driver Consulting www.KernelDrivers.com
866.263.9295


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Why don’t you check for the file being opened?

if( Data->IoStatus.Information==FILE_OPENED)

Otherwise, if you want to copy it after it has been created and written
to then you could do it in close processing but there are other issues
there. You would need to re-open the original file in most cases to
perform the copy, tracking of course if the file had been written to,
etc. It would be best to post that work to a worker thread to perform
the copy.

Pete

On 9/12/2013 6:37 AM, Joe Wang wrote:

Hi Peter,
If it is not the right time to copy the whole file , When should I do it? Calling the CopyFile function In the PostOpWrite call back ? right?
Please give me some instructions to follow. Thanks.

Kind Regards.
Joe Wang

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Peter Scott
Sent: Thursday, September 12, 2013 8:24 PM
To: Windows File Systems Devs Interest List
Subject: Re: [ntfsd] Why FltReadFile return STATUS_END_OF_FILE(c0000011)

In the previous listing for the post-create processing, before you call CopyFile(), you are checking if the current file had been CREATED

if( Data->IoStatus.Information==FILE_CREATED)

If the file was just created then there is NO data in the file since it has not been written to yet. Do you want to check for when the file is OPENED?

Pete

On 9/12/2013 6:16 AM, Joe Wang wrote:
> Hi Peter, Better to Post the current code of the CopyFile . Please review it . thanks.
> NTSTATUS
> CopyFile(
> PFLT_CALLBACK_DATA Data,
> PCFLT_RELATED_OBJECTS FltObjects,
> PUNICODE_STRING pCompleteFileName
> )
> {
> NTSTATUS status;
> OBJECT_ATTRIBUTES tempDeletedObject;
> IO_STATUS_BLOCK ioStatusTempDeleted;
> LARGE_INTEGER allocate;
> FILE_STANDARD_INFORMATION fileStandardInformation;
> HANDLE tempDeletedHandle;
> ULONG returnedLength;
> PFLT_FILE_NAME_INFORMATION readNameInfo;
> allocate.QuadPart = 0x10000;
>
> InitializeObjectAttributes(
> &tempDeletedObject,
> pCompleteFileName,
> OBJ_CASE_INSENSITIVE,
> NULL,
> NULL
> );
> status = FltQueryInformationFile(
> FltObjects->Instance,
> Data->Iopb->TargetFileObject,
> &fileStandardInformation,
> sizeof(FILE_STANDARD_INFORMATION),
> FileStandardInformation,
> &returnedLength
> );
> if(NT_SUCCESS(status))
> {
> allocate.QuadPart = fileStandardInformation.AllocationSize.QuadPart;
> } else {
> return status;
> }
> status = FltCreateFile(
> FltObjects->Filter,
> NULL,
> &tempDeletedHandle,
> GENERIC_WRITE,
> &tempDeletedObject,
> &ioStatusTempDeleted,
> &allocate,
> FILE_ATTRIBUTE_NORMAL,
> 0,
> FILE_CREATE,
> FILE_NON_DIRECTORY_FILE,
> NULL,
> 0,
> 0
> );
>
> if(NT_SUCCESS(status))
> {
> PVOID handleFileObject;
> PVOID pFileBuffer;
> LARGE_INTEGER offset;
> ULONG bytesRead = 0;
> ULONG bytesWritten = 0;
> offset.QuadPart = 0;
> status = ObReferenceObjectByHandle(
> tempDeletedHandle,
> 0,
> NULL,
> KernelMode,
> &handleFileObject,
> NULL);
> if(!NT_SUCCESS(status))
> {
> return status;
> }
> pFileBuffer = ExAllocatePoolWithTag(NonPagedPool, 1000, FILE_POOL_TAG);
> if(pFileBuffer != NULL)
> {
> do {
> IO_STATUS_BLOCK IoStatusBlock;
> bytesWritten = 0;
>
> status = FltReadFile(
> FltObjects->Instance,
>
> FltObjects->FileObject,
> &offset,
> 1000,
> pFileBuffer,
> FLTFL_IO_OPERATION_NON_CACHED |
> FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,
> &bytesRead ,
> NULL,
> NULL
> );
> if(NT_SUCCESS(status) && bytesRead > 0)
> {
> //begin to write file.
> } else {
> break;
> }
> offset.QuadPart += bytesRead;
> } while(bytesRead == 1000);
> FltFreePoolAlignedWithTag( FltObjects->Instance, pFileBuffer, FILE_POOL_TAG );
> }
> else
> {}
> ObDereferenceObject(handleFileObject);
> FltClose(tempDeletedHandle);
> } else {
> if(status != STATUS_OBJECT_NAME_COLLISION)
> {
> return status;
> }
> }
> return STATUS_SUCCESS;
> }
>
> —
> NTFSD is sponsored by OSR
>
> OSR is hiring!! Info at http://www.osr.com/careers
>
> For our schedule of debugging and file system seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>


Kernel Drivers
Windows File System and Device Driver Consulting www.KernelDrivers.com
866.263.9295


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer


Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295

Hi Peter,
You mean in the PostOpClose call back check if the file had been updated. If updated. then copy the original file . right ?
If I was wrong , Please help to correct me . It is better to show my some sample code(just main code please).

Thanks.
Joe Wang

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Peter Scott
Sent: Thursday, September 12, 2013 8:43 PM
To: Windows File Systems Devs Interest List
Subject: Re: [ntfsd] Why FltReadFile return STATUS_END_OF_FILE(c0000011)

Why don’t you check for the file being opened?

if( Data->IoStatus.Information==FILE_OPENED)

Otherwise, if you want to copy it after it has been created and written to then you could do it in close processing but there are other issues there. You would need to re-open the original file in most cases to perform the copy, tracking of course if the file had been written to, etc. It would be best to post that work to a worker thread to perform the copy.

Pete

On 9/12/2013 6:37 AM, Joe Wang wrote:

Hi Peter,
If it is not the right time to copy the whole file , When should I do it? Calling the CopyFile function In the PostOpWrite call back ? right?
Please give me some instructions to follow. Thanks.

Kind Regards.
Joe Wang

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Peter Scott
Sent: Thursday, September 12, 2013 8:24 PM
To: Windows File Systems Devs Interest List
Subject: Re: [ntfsd] Why FltReadFile return STATUS_END_OF_FILE(c0000011)

In the previous listing for the post-create processing, before you call CopyFile(), you are checking if the current file had been CREATED

if( Data->IoStatus.Information==FILE_CREATED)

If the file was just created then there is NO data in the file since it has not been written to yet. Do you want to check for when the file is OPENED?

Pete

On 9/12/2013 6:16 AM, Joe Wang wrote:
> Hi Peter, Better to Post the current code of the CopyFile . Please review it . thanks.
> NTSTATUS
> CopyFile(
> PFLT_CALLBACK_DATA Data,
> PCFLT_RELATED_OBJECTS FltObjects,
> PUNICODE_STRING pCompleteFileName
> )
> {
> NTSTATUS status;
> OBJECT_ATTRIBUTES tempDeletedObject;
> IO_STATUS_BLOCK ioStatusTempDeleted;
> LARGE_INTEGER allocate;
> FILE_STANDARD_INFORMATION fileStandardInformation;
> HANDLE tempDeletedHandle;
> ULONG returnedLength;
> PFLT_FILE_NAME_INFORMATION readNameInfo;
> allocate.QuadPart = 0x10000;
>
> InitializeObjectAttributes(
> &tempDeletedObject,
> pCompleteFileName,
> OBJ_CASE_INSENSITIVE,
> NULL,
> NULL
> );
> status = FltQueryInformationFile(
> FltObjects->Instance,
> Data->Iopb->TargetFileObject,
> &fileStandardInformation,
> sizeof(FILE_STANDARD_INFORMATION),
> FileStandardInformation,
> &returnedLength
> );
> if(NT_SUCCESS(status))
> {
> allocate.QuadPart = fileStandardInformation.AllocationSize.QuadPart;
> } else {
> return status;
> }
> status = FltCreateFile(
> FltObjects->Filter,
> NULL,
> &tempDeletedHandle,
> GENERIC_WRITE,
> &tempDeletedObject,
> &ioStatusTempDeleted,
> &allocate,
> FILE_ATTRIBUTE_NORMAL,
> 0,
> FILE_CREATE,
> FILE_NON_DIRECTORY_FILE,
> NULL,
> 0,
> 0
> );
>
> if(NT_SUCCESS(status))
> {
> PVOID handleFileObject;
> PVOID pFileBuffer;
> LARGE_INTEGER offset;
> ULONG bytesRead = 0;
> ULONG bytesWritten = 0;
> offset.QuadPart = 0;
> status = ObReferenceObjectByHandle(
> tempDeletedHandle,
> 0,
> NULL,
> KernelMode,
> &handleFileObject,
> NULL);
> if(!NT_SUCCESS(status))
> {
> return status;
> }
> pFileBuffer = ExAllocatePoolWithTag(NonPagedPool, 1000, FILE_POOL_TAG);
> if(pFileBuffer != NULL)
> {
> do {
> IO_STATUS_BLOCK IoStatusBlock;
> bytesWritten = 0;
>
> status = FltReadFile(
> FltObjects->Instance,
>
> FltObjects->FileObject,
> &offset,
> 1000,
> pFileBuffer,
> FLTFL_IO_OPERATION_NON_CACHED |
> FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,
> &bytesRead ,
> NULL,
> NULL
> );
> if(NT_SUCCESS(status) && bytesRead > 0)
> {
> //begin to write file.
> } else {
> break;
> }
> offset.QuadPart += bytesRead;
> } while(bytesRead == 1000);
> FltFreePoolAlignedWithTag( FltObjects->Instance, pFileBuffer, FILE_POOL_TAG );
> }
> else
> {}
> ObDereferenceObject(handleFileObject);
> FltClose(tempDeletedHandle);
> } else {
> if(status != STATUS_OBJECT_NAME_COLLISION)
> {
> return status;
> }
> }
> return STATUS_SUCCESS;
> }
>
> —
> NTFSD is sponsored by OSR
>
> OSR is hiring!! Info at http://www.osr.com/careers
>
> For our schedule of debugging and file system seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>


Kernel Drivers
Windows File System and Device Driver Consulting www.KernelDrivers.com
866.263.9295


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer


Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Correct but you will need to re-open the file. Also, you may want to do
this in a worker thread for asynchronous processing but then you need to
ensure that the file is not re-opened and your open conflicts with the
callers.

I would suggest to have the processing in post-create but check for the
file being opened, not created. You can then get your copy processing
working.

A note on copy processing, there is more to copying the default data
stream of a file if you want to ensure a full copy. You need to handle
all alternate data streams, EA’s, attributes, etc.

Pete

On 9/12/2013 7:10 AM, Joe Wang wrote:

Hi Peter,
You mean in the PostOpClose call back check if the file had been updated. If updated. then copy the original file . right ?
If I was wrong , Please help to correct me . It is better to show my some sample code(just main code please).

Thanks.
Joe Wang

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Peter Scott
Sent: Thursday, September 12, 2013 8:43 PM
To: Windows File Systems Devs Interest List
Subject: Re: [ntfsd] Why FltReadFile return STATUS_END_OF_FILE(c0000011)

Why don’t you check for the file being opened?

if( Data->IoStatus.Information==FILE_OPENED)

Otherwise, if you want to copy it after it has been created and written to then you could do it in close processing but there are other issues there. You would need to re-open the original file in most cases to perform the copy, tracking of course if the file had been written to, etc. It would be best to post that work to a worker thread to perform the copy.

Pete

On 9/12/2013 6:37 AM, Joe Wang wrote:
> Hi Peter,
> If it is not the right time to copy the whole file , When should I do it? Calling the CopyFile function In the PostOpWrite call back ? right?
> Please give me some instructions to follow. Thanks.
>
>
>
> Kind Regards.
> Joe Wang
>
>
> -----Original Message-----
> From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Peter Scott
> Sent: Thursday, September 12, 2013 8:24 PM
> To: Windows File Systems Devs Interest List
> Subject: Re: [ntfsd] Why FltReadFile return STATUS_END_OF_FILE(c0000011)
>
>
> In the previous listing for the post-create processing, before you call CopyFile(), you are checking if the current file had been CREATED
>
> if( Data->IoStatus.Information==FILE_CREATED)
> …
>
> If the file was just created then there is NO data in the file since it has not been written to yet. Do you want to check for when the file is OPENED?
>
> Pete
>
> On 9/12/2013 6:16 AM, Joe Wang wrote:
>> Hi Peter, Better to Post the current code of the CopyFile . Please review it . thanks.
>> NTSTATUS
>> CopyFile(
>> PFLT_CALLBACK_DATA Data,
>> PCFLT_RELATED_OBJECTS FltObjects,
>> PUNICODE_STRING pCompleteFileName
>> )
>> {
>> NTSTATUS status;
>> OBJECT_ATTRIBUTES tempDeletedObject;
>> IO_STATUS_BLOCK ioStatusTempDeleted;
>> LARGE_INTEGER allocate;
>> FILE_STANDARD_INFORMATION fileStandardInformation;
>> HANDLE tempDeletedHandle;
>> ULONG returnedLength;
>> PFLT_FILE_NAME_INFORMATION readNameInfo;
>> allocate.QuadPart = 0x10000;
>>
>> InitializeObjectAttributes(
>> &tempDeletedObject,
>> pCompleteFileName,
>> OBJ_CASE_INSENSITIVE,
>> NULL,
>> NULL
>> );
>> status = FltQueryInformationFile(
>> FltObjects->Instance,
>> Data->Iopb->TargetFileObject,
>> &fileStandardInformation,
>> sizeof(FILE_STANDARD_INFORMATION),
>> FileStandardInformation,
>> &returnedLength
>> );
>> if(NT_SUCCESS(status))
>> {
>> allocate.QuadPart = fileStandardInformation.AllocationSize.QuadPart;
>> } else {
>> return status;
>> }
>> status = FltCreateFile(
>> FltObjects->Filter,
>> NULL,
>> &tempDeletedHandle,
>> GENERIC_WRITE,
>> &tempDeletedObject,
>> &ioStatusTempDeleted,
>> &allocate,
>> FILE_ATTRIBUTE_NORMAL,
>> 0,
>> FILE_CREATE,
>> FILE_NON_DIRECTORY_FILE,
>> NULL,
>> 0,
>> 0
>> );
>>
>> if(NT_SUCCESS(status))
>> {
>> PVOID handleFileObject;
>> PVOID pFileBuffer;
>> LARGE_INTEGER offset;
>> ULONG bytesRead = 0;
>> ULONG bytesWritten = 0;
>> offset.QuadPart = 0;
>> status = ObReferenceObjectByHandle(
>> tempDeletedHandle,
>> 0,
>> NULL,
>> KernelMode,
>> &handleFileObject,
>> NULL);
>> if(!NT_SUCCESS(status))
>> {
>> return status;
>> }
>> pFileBuffer = ExAllocatePoolWithTag(NonPagedPool, 1000, FILE_POOL_TAG);
>> if(pFileBuffer != NULL)
>> {
>> do {
>> IO_STATUS_BLOCK IoStatusBlock;
>> bytesWritten = 0;
>>
>> status = FltReadFile(
>> FltObjects->Instance,
>>
>> FltObjects->FileObject,
>> &offset,
>> 1000,
>> pFileBuffer,
>> FLTFL_IO_OPERATION_NON_CACHED |
>> FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,
>> &bytesRead ,
>> NULL,
>> NULL
>> );
>> if(NT_SUCCESS(status) && bytesRead > 0)
>> {
>> //begin to write file.
>> } else {
>> break;
>> }
>> offset.QuadPart += bytesRead;
>> } while(bytesRead == 1000);
>> FltFreePoolAlignedWithTag( FltObjects->Instance, pFileBuffer, FILE_POOL_TAG );
>> }
>> else
>> {}
>> ObDereferenceObject(handleFileObject);
>> FltClose(tempDeletedHandle);
>> } else {
>> if(status != STATUS_OBJECT_NAME_COLLISION)
>> {
>> return status;
>> }
>> }
>> return STATUS_SUCCESS;
>> }
>>
>> —
>> NTFSD is sponsored by OSR
>>
>> OSR is hiring!! Info at http://www.osr.com/careers
>>
>> For our schedule of debugging and file system seminars visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
>
> –
> Kernel Drivers
> Windows File System and Device Driver Consulting www.KernelDrivers.com
> 866.263.9295
>
> —
> NTFSD is sponsored by OSR
>
> OSR is hiring!! Info at http://www.osr.com/careers
>
> For our schedule of debugging and file system seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
>
> —
> NTFSD is sponsored by OSR
>
> OSR is hiring!! Info at http://www.osr.com/careers
>
> For our schedule of debugging and file system seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
>


Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295