/*++ 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 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