|
|
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
copy.c
Abstract:
This module contains the routine to copy a file.
Author:
Dan Hinsley (DanHi) 24-Feb-1991
Revision History:
02-Feb-1994 Danl Fixed memory leak where ioBuffer wasn't getting free'd when doing an error exit from ElfpCopyFile.
--*/
//
// INCLUDES
//
#include <eventp.h>
NTSTATUS ElfpCopyFile ( IN HANDLE SourceHandle, IN PUNICODE_STRING TargetFileName )
/*++
Routine Description:
This routine copies or appends from the source file to the target file. If the target file already exists, the copy fails.
Arguments:
SourceHandle - An open handle to the source file.
TargetFileName - The name of the file to copy to.
Return Value:
NTSTATUS - STATUS_SUCCESS or error.
--*/
{ NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock; FILE_STANDARD_INFORMATION sourceStandardInfo;
OBJECT_ATTRIBUTES ObjectAttributes; HANDLE TargetHandle;
PCHAR ioBuffer; ULONG ioBufferSize; ULONG bytesRead;
//
// Get the size of the file so we can set the attributes of the target
// file.
//
Status = NtQueryInformationFile( SourceHandle, &IoStatusBlock, &sourceStandardInfo, sizeof(sourceStandardInfo), FileStandardInformation );
if (!NT_SUCCESS(Status)) { ELF_LOG1(ERROR, "ElfpCopyFile: Unable to query size of source file %#x\n", Status);
return Status; }
//
// Open the target file, fail if the file already exists.
//
InitializeObjectAttributes( &ObjectAttributes, TargetFileName, OBJ_CASE_INSENSITIVE, NULL, NULL );
Status = NtCreateFile(&TargetHandle, GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, &(sourceStandardInfo.EndOfFile), FILE_ATTRIBUTE_NORMAL, 0, // Share access
FILE_CREATE, FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY, NULL, // EA buffer
0); // EA length
if (!NT_SUCCESS(Status)) { ELF_LOG2(ERROR, "ElfpCopyFile: NtCreateFile of file %ws failed %#x\n", TargetFileName->Buffer, Status);
return Status; }
//
// Allocate a buffer to use for the data copy.
//
ioBufferSize = 4096;
ioBuffer = ElfpAllocateBuffer (ioBufferSize);
if (ioBuffer == NULL) { ELF_LOG1(ERROR, "ElfpCopyFile: Unable to allocate I/O buffer to copy file %ws\n", TargetFileName->Buffer);
NtClose(TargetHandle); return STATUS_NO_MEMORY; }
//
// Copy data--read from source, write to target. Do this until
// all the data is written or an error occurs.
//
while ( TRUE ) { Status = NtReadFile( SourceHandle, NULL, // Event
NULL, // ApcRoutine
NULL, // ApcContext
&IoStatusBlock, ioBuffer, ioBufferSize, NULL, // ByteOffset
NULL); // Key
if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE) { ELF_LOG1(ERROR, "ElfpCopyFile: NtReadFile of source file failed %#x\n", Status);
ElfpFreeBuffer(ioBuffer); NtClose(TargetHandle); return Status; }
if (IoStatusBlock.Information == 0 || Status == STATUS_END_OF_FILE) { break; }
bytesRead = (ULONG)IoStatusBlock.Information;
Status = NtWriteFile( TargetHandle, NULL, // Event
NULL, // ApcRoutine
NULL, // ApcContext
&IoStatusBlock, ioBuffer, bytesRead, NULL, // ByteOffset
NULL); // Key
if (!NT_SUCCESS(Status)) { ELF_LOG2(ERROR, "ElfpCopyFile: NtWriteFile to file %ws failed %#x\n", TargetFileName->Buffer, Status);
ElfpFreeBuffer(ioBuffer); NtClose(TargetHandle); return Status; } }
ElfpFreeBuffer (ioBuffer);
Status = NtClose(TargetHandle);
ASSERT(NT_SUCCESS(Status));
return STATUS_SUCCESS;
} // ElfpCopyFile
|