Wrote a File Copy Function for all who are intrested.

Hey, as I have seen many posts concerning copying files i have took some time to write a file copy function for legacy drivers that can be used with very few changes (the DeviceObject part has to be adjusted)…

The good thing, its not gonna reenter your create file dispatch routines.

Anyway, I hope I could help you a little bit:

VOID CagaraCopyFile(PUNICODE_STRING source, PUNICODE_STRING destination, PDEVICE_OBJECT devExt)
{

/* STATUS BLOCKS NEEDED FOR FILECOPY */
IO_STATUS_BLOCK iosbWrite;
IO_STATUS_BLOCK iosbRead;
IO_STATUS_BLOCK iosbOpenWrite;
IO_STATUS_BLOCK iosbOpenRead;

/* OBJATTR’s NEEDED FOR FILECOPY */
OBJECT_ATTRIBUTES objAttrOpen;
OBJECT_ATTRIBUTES objAttrWrite;

/* STATUS CODES FOR FILECOPY */
NTSTATUS statusWrite;
NTSTATUS statusRead;

/* HANDLE FOR FILE COPY */
HANDLE handleRead=NULL;
HANDLE handleWrite=NULL;

/* LARGE INTEGER TO SAVE CURRENT POINTER POSITION */
LARGE_INTEGER byteOffset;

/* READ BUFFER */
PCHAR pBuffer = (PCHAR)ExAllocatePool(NonPagedPool,128); // 64 chars buffer, 128 bytes shouldnt fill the Stack and still work fast

/* Device Object */
PSFILTER_DEVICE_EXTENSION devExtMy = (PSFILTER_DEVICE_EXTENSION)(devExt->DeviceExtension);

/* INIT THE FILECOPY OBJATTR’s */
InitializeObjectAttributes(&objAttrOpen, source,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL, NULL);

InitializeObjectAttributes(&objAttrWrite, destination,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL, NULL);

// Open Handles to both, original file and new file
statusWrite = IoCreateFileSpecifyDeviceObjectHint(&handleWrite,
GENERIC_WRITE,
&objAttrWrite, &iosbOpenWrite, NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OVERWRITE_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0, /* FROM NOW ON ADDITIONAL PARAMETERS*/ CreateFileTypeNone, NULL, 0, devExtMy->NLExtHeader.AttachedToDeviceObject);

statusRead = IoCreateFileSpecifyDeviceObjectHint(&handleRead,
GENERIC_READ,
&objAttrOpen, &iosbOpenRead,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0, /* FROM NOW ON ADDITIONAL PARAMETERS*/ CreateFileTypeNone, NULL, 0, devExtMy->NLExtHeader.AttachedToDeviceObject);

/* HERE COMES THE ACTUAL COPY LOOK */
if(NT_SUCCESS(statusRead) && NT_SUCCESS(statusWrite))
{
byteOffset.LowPart = byteOffset.HighPart = 0;

do
{
RtlZeroMemory(pBuffer,128);

statusRead = ZwReadFile(handleRead, NULL, NULL, NULL, &iosbRead,
pBuffer, 128, &byteOffset, NULL);

byteOffset.LowPart+=128;

statusWrite = ZwWriteFile(handleWrite, NULL, NULL, NULL, &iosbWrite,
pBuffer, safeWrite, NULL, NULL);

}
while(NT_SUCCESS(statusRead));

}

/* DONT FORGET TO CLOSE BOTH HANDLES */
ZwClose(handleWrite);
ZwClose(handleRead);

// FREE THE BUFFER
ExFreePool(pBuffer); // Important so we dont fill up the Stack

/* FILE COPY DONE */

}

A couple notes for people looking at the code that was posted:

  1. A 128-byte copy buffer size is tiny and will make for very inefficient copies.

  2. Also, I was wondering about the comment “64 chars buffer, 128 bytes shouldnt fill the Stack and still work fast”. I’m not sure why is says “64” chars nor why it says “Stack”…

  3. Note that standard file information (file attributes, timestamps, etc) is not copied.

  4. It is faster to pre-allocate the file size then copy the data so that the FS does not have to keep extending the file. (That’s what tools like robocopy do.)

  5. There is no error-handling nor provisions to detect an aborted copy – say the system crashes or loses power… (A tool such as robocopy handles aborted copies by pre-setting the timestamp to some bogus standard value and then doing the final stamp after the file is copied – and, if the code is being careful, flushed.)

  6. Also, no EAs are copied either.

  • Danilo

Please, don’t anyone out there use this routine.

I looked at it for less than a minute and found 2 BSODs and 4 different ways
the output file can be corrupt.

And it doesn’t even attempt to do what is implied by “file copy”.

  • Dan.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@web.de
Sent: Saturday, September 29, 2007 11:26 AM
To: Windows File Systems Devs Interest List
Subject: [ntfsd] Wrote a File Copy Function for all who are intrested.

Hey, as I have seen many posts concerning copying files i have took some
time to write a file copy function for legacy drivers that can be used with
very few changes (the DeviceObject part has to be adjusted)…

The good thing, its not gonna reenter your create file dispatch routines.

Anyway, I hope I could help you a little bit:

VOID CagaraCopyFile(PUNICODE_STRING source, PUNICODE_STRING destination,
PDEVICE_OBJECT devExt) {

/* STATUS BLOCKS NEEDED FOR FILECOPY */
IO_STATUS_BLOCK iosbWrite;
IO_STATUS_BLOCK iosbRead;
IO_STATUS_BLOCK iosbOpenWrite;
IO_STATUS_BLOCK iosbOpenRead;

/* OBJATTR’s NEEDED FOR FILECOPY */
OBJECT_ATTRIBUTES objAttrOpen;
OBJECT_ATTRIBUTES objAttrWrite;

/* STATUS CODES FOR FILECOPY */
NTSTATUS statusWrite;
NTSTATUS statusRead;

/* HANDLE FOR FILE COPY */
HANDLE handleRead=NULL;
HANDLE handleWrite=NULL;

/* LARGE INTEGER TO SAVE CURRENT POINTER POSITION */
LARGE_INTEGER byteOffset;

/* READ BUFFER */
PCHAR pBuffer = (PCHAR)ExAllocatePool(NonPagedPool,128); // 64 chars
buffer, 128 bytes shouldnt fill the Stack and still work fast

/* Device Object */
PSFILTER_DEVICE_EXTENSION devExtMy =
(PSFILTER_DEVICE_EXTENSION)(devExt->DeviceExtension);

/* INIT THE FILECOPY OBJATTR’s */
InitializeObjectAttributes(&objAttrOpen, source,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL, NULL);

InitializeObjectAttributes(&objAttrWrite, destination,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL, NULL);

// Open Handles to both, original file and new file
statusWrite = IoCreateFileSpecifyDeviceObjectHint(&handleWrite,
GENERIC_WRITE,
&objAttrWrite, &iosbOpenWrite, NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OVERWRITE_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0, /* FROM NOW ON ADDITIONAL PARAMETERS*/
CreateFileTypeNone, NULL, 0, devExtMy->NLExtHeader.AttachedToDeviceObject);

statusRead = IoCreateFileSpecifyDeviceObjectHint(&handleRead,
GENERIC_READ,
&objAttrOpen, &iosbOpenRead,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0, /* FROM NOW ON ADDITIONAL PARAMETERS*/
CreateFileTypeNone, NULL, 0, devExtMy->NLExtHeader.AttachedToDeviceObject);

/* HERE COMES THE ACTUAL COPY LOOK */
if(NT_SUCCESS(statusRead) && NT_SUCCESS(statusWrite))
{
byteOffset.LowPart = byteOffset.HighPart = 0;

do
{
RtlZeroMemory(pBuffer,128);

statusRead = ZwReadFile(handleRead, NULL, NULL, NULL, &iosbRead,
pBuffer, 128, &byteOffset, NULL);

byteOffset.LowPart+=128;

statusWrite = ZwWriteFile(handleWrite, NULL, NULL, NULL,
&iosbWrite,
pBuffer, safeWrite, NULL, NULL);

}
while(NT_SUCCESS(statusRead));

}

/* DONT FORGET TO CLOSE BOTH HANDLES */
ZwClose(handleWrite);
ZwClose(handleRead);

// FREE THE BUFFER
ExFreePool(pBuffer); // Important so we dont fill up the Stack

/* FILE COPY DONE */

}


NTFSD is sponsored by OSR

For our schedule debugging and file system seminars (including our new fs
mini-filter seminar) visit:
http://www.osr.com/seminars

You are currently subscribed to ntfsd as: xxxxx@privtek.com To unsubscribe
send a blank email to xxxxx@lists.osr.com