211 lines
5.1 KiB
C
211 lines
5.1 KiB
C
|
/*++
|
|||
|
|
|||
|
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
|