reactos/reactos/lib/kernel32/file/move.c

428 lines
12 KiB
C
Raw Normal View History

/* $Id: move.c,v 1.16 2004/12/18 13:26:57 weiden Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/kernel32/file/file.c
* PURPOSE: Directory functions
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
* UPDATE HISTORY:
* Created 01/11/98
*/
/* INCLUDES *****************************************************************/
2003-01-15 Casper S. Hornstrup <chorns@users.sourceforge.net> * lib/kernel32/k32.h: New file. * lib/kernel32/makefile (TARGET_CFLAGS): Add -I./. (TARGET_PCH): Set to k32.h. * lib/kernel32/except/except.c: Use <k32.h>. * lib/kernel32/file/backup.c: Ditto. * lib/kernel32/file/cnotify.c: Ditto. * lib/kernel32/file/copy.c: Ditto. * lib/kernel32/file/create.c: Ditto. * lib/kernel32/file/curdir.c: Ditto. * lib/kernel32/file/delete.c: Ditto. * lib/kernel32/file/deviceio.c: Ditto. * lib/kernel32/file/dir.c: Ditto. * lib/kernel32/file/dosdev.c: Ditto. * lib/kernel32/file/file.c: Ditto. * lib/kernel32/file/find.c: Ditto. * lib/kernel32/file/iocompl.c: Ditto. * lib/kernel32/file/lfile.c: Ditto. * lib/kernel32/file/lock.c: Ditto. * lib/kernel32/file/mailslot.c: Ditto. * lib/kernel32/file/move.c: Ditto. * lib/kernel32/file/npipe.c: Ditto. * lib/kernel32/file/pipe.c: Ditto. * lib/kernel32/file/rw.c: Ditto. * lib/kernel32/file/tape.c: Ditto. * lib/kernel32/file/volume.c: Ditto. * lib/kernel32/mem/global.c: Ditto. * lib/kernel32/mem/heap.c: Ditto. * lib/kernel32/mem/isbad.c: Ditto. * lib/kernel32/mem/local.c: Ditto. * lib/kernel32/mem/procmem.c: Ditto. * lib/kernel32/mem/section.c: Ditto. * lib/kernel32/mem/virtual.c: Ditto. * lib/kernel32/misc/atom.c: Ditto. * lib/kernel32/misc/comm.c: Ditto. * lib/kernel32/misc/console.c: Ditto. * lib/kernel32/misc/debug.c: Ditto. * lib/kernel32/misc/dllmain.c: Ditto. * lib/kernel32/misc/env.c: Ditto. * lib/kernel32/misc/error.c: Ditto. * lib/kernel32/misc/handle.c: Ditto. * lib/kernel32/misc/ldr.c: Ditto. * lib/kernel32/misc/profile.c: Ditto. * lib/kernel32/misc/res.c: Ditto. * lib/kernel32/misc/stubs.c: Ditto. * lib/kernel32/misc/sysinfo.c: Ditto. * lib/kernel32/misc/time.c: Ditto. * lib/kernel32/process/cmdline.c: Ditto. * lib/kernel32/process/create.c: Ditto. * lib/kernel32/process/proc.c: Ditto. * lib/kernel32/process/session.c: Ditto. * lib/kernel32/string/lstring.c: Ditto. * lib/kernel32/synch/critical.c: Ditto. * lib/kernel32/synch/event.c: Ditto. * lib/kernel32/synch/intrlck.c: Ditto. * lib/kernel32/synch/mutex.c: Ditto. * lib/kernel32/synch/sem.c: Ditto. * lib/kernel32/synch/timer.c: Ditto. * lib/kernel32/synch/wait.c: Ditto. * lib/kernel32/thread/fiber.c: Ditto. * lib/kernel32/thread/thread.c: Ditto. * lib/kernel32/thread/tls.c: Ditto. svn path=/trunk/; revision=4009
2003-01-15 21:24:36 +00:00
#include <k32.h>
#define NDEBUG
#include "../include/debug.h"
/* GLOBALS *****************************************************************/
/* FUNCTIONS ****************************************************************/
static BOOL
AdjustFileAttributes (
LPCWSTR ExistingFileName,
LPCWSTR NewFileName
)
{
IO_STATUS_BLOCK IoStatusBlock;
FILE_BASIC_INFORMATION ExistingInfo,
NewInfo;
HANDLE hFile;
DWORD Attributes;
NTSTATUS errCode;
BOOL Result = FALSE;
hFile = CreateFileW (ExistingFileName,
FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE != hFile)
{
errCode = NtQueryInformationFile (hFile,
&IoStatusBlock,
&ExistingInfo,
sizeof(FILE_BASIC_INFORMATION),
FileBasicInformation);
if (NT_SUCCESS (errCode))
{
if (0 != (ExistingInfo.FileAttributes & FILE_ATTRIBUTE_READONLY))
{
Attributes = ExistingInfo.FileAttributes;
ExistingInfo.FileAttributes &= ~ FILE_ATTRIBUTE_READONLY;
if (0 == (ExistingInfo.FileAttributes &
(FILE_ATTRIBUTE_HIDDEN |
FILE_ATTRIBUTE_SYSTEM |
FILE_ATTRIBUTE_ARCHIVE)))
{
ExistingInfo.FileAttributes |= FILE_ATTRIBUTE_NORMAL;
}
errCode = NtSetInformationFile (hFile,
&IoStatusBlock,
&ExistingInfo,
sizeof(FILE_BASIC_INFORMATION),
FileBasicInformation);
if (!NT_SUCCESS(errCode))
{
DPRINT("Removing READONLY attribute from source failed with status 0x%08x\n", errCode);
}
ExistingInfo.FileAttributes = Attributes;
}
CloseHandle(hFile);
if (NT_SUCCESS(errCode))
{
hFile = CreateFileW (NewFileName,
FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE != hFile)
{
errCode = NtQueryInformationFile(hFile,
&IoStatusBlock,
&NewInfo,
sizeof(FILE_BASIC_INFORMATION),
FileBasicInformation);
if (NT_SUCCESS(errCode))
{
NewInfo.FileAttributes = (NewInfo.FileAttributes &
~ (FILE_ATTRIBUTE_HIDDEN |
FILE_ATTRIBUTE_SYSTEM |
FILE_ATTRIBUTE_READONLY |
FILE_ATTRIBUTE_NORMAL)) |
(ExistingInfo.FileAttributes &
(FILE_ATTRIBUTE_HIDDEN |
FILE_ATTRIBUTE_SYSTEM |
FILE_ATTRIBUTE_READONLY |
FILE_ATTRIBUTE_NORMAL)) |
FILE_ATTRIBUTE_ARCHIVE;
NewInfo.CreationTime = ExistingInfo.CreationTime;
NewInfo.LastAccessTime = ExistingInfo.LastAccessTime;
NewInfo.LastWriteTime = ExistingInfo.LastWriteTime;
errCode = NtSetInformationFile (hFile,
&IoStatusBlock,
&NewInfo,
sizeof(FILE_BASIC_INFORMATION),
FileBasicInformation);
if (NT_SUCCESS(errCode))
{
Result = TRUE;
}
else
{
DPRINT("Setting attributes on dest file failed with status 0x%08x\n", errCode);
}
}
else
{
DPRINT("Obtaining attributes from dest file failed with status 0x%08x\n", errCode);
}
CloseHandle(hFile);
}
else
{
DPRINT("Opening dest file to set attributes failed with code %d\n", GetLastError());
}
}
}
else
{
DPRINT("Obtaining attributes from source file failed with status 0x%08x\n", errCode);
CloseHandle(hFile);
}
}
else
{
DPRINT("Opening source file to obtain attributes failed with code %d\n", GetLastError());
}
return Result;
}
2003-07-10 Casper S. Hornstrup <chorns@users.sourceforge.net> * lib/kernel32/debug/break.c: Add @implemented and @unimplemented to APIs. * lib/kernel32/debug/debugger.c: Ditto. * lib/kernel32/debug/output.c: Ditto. * lib/kernel32/except/except.c: Ditto. * lib/kernel32/file/backup.c: Ditto. * lib/kernel32/file/cnotify.c: Ditto. * lib/kernel32/file/copy.c: Ditto. * lib/kernel32/file/create.c: Ditto. * lib/kernel32/file/curdir.c: Ditto. * lib/kernel32/file/delete.c: Ditto. * lib/kernel32/file/deviceio.c: Ditto. * lib/kernel32/file/dir.c: Ditto. * lib/kernel32/file/dosdev.c: Ditto. * lib/kernel32/file/file.c: Ditto. * lib/kernel32/file/find.c: Ditto. * lib/kernel32/file/iocompl.c: Ditto. * lib/kernel32/file/lfile.c: Ditto. * lib/kernel32/file/lock.c: Ditto. * lib/kernel32/file/mailslot.c: Ditto. * lib/kernel32/file/move.c: Ditto. * lib/kernel32/file/npipe.c: Ditto. * lib/kernel32/file/pipe.c: Ditto. * lib/kernel32/file/rw.c: Ditto. * lib/kernel32/file/tape.c: Ditto. * lib/kernel32/file/volume.c: Ditto. * lib/kernel32/mem/global.c: Ditto. * lib/kernel32/mem/heap.c: Ditto. * lib/kernel32/mem/isbad.c: Ditto. * lib/kernel32/mem/local.c: Ditto. * lib/kernel32/mem/procmem.c: Ditto. * lib/kernel32/mem/section.c: Ditto. * lib/kernel32/mem/virtual.c: Ditto. * lib/kernel32/misc/atom.c: Ditto. * lib/kernel32/misc/comm.c: Ditto. * lib/kernel32/misc/computername.c: Ditto. * lib/kernel32/misc/console.c: Ditto. * lib/kernel32/misc/env.c: Ditto. * lib/kernel32/misc/error.c: Ditto. * lib/kernel32/misc/errormsg.c: Ditto. * lib/kernel32/misc/handle.c: Ditto. * lib/kernel32/misc/ldr.c: Ditto. * lib/kernel32/misc/mbchars.c: Ditto. * lib/kernel32/misc/muldiv.c: Ditto. * lib/kernel32/misc/perfcnt.c: Ditto. * lib/kernel32/misc/profile.c: Ditto. * lib/kernel32/misc/res.c: Ditto. * lib/kernel32/misc/stubs.c: Ditto. * lib/kernel32/misc/sysinfo.c: Ditto. * lib/kernel32/misc/time.c: Ditto. * lib/kernel32/misc/toolhelp.c: Ditto. * lib/kernel32/process/cmdline.c: Ditto. * lib/kernel32/process/create.c: Ditto. * lib/kernel32/process/proc.c: Ditto. * lib/kernel32/process/session.c: Ditto. * lib/kernel32/string/lstring.c: Ditto. * lib/kernel32/synch/critical.c: Ditto. * lib/kernel32/synch/event.c: Ditto. * lib/kernel32/synch/intrlck.c: Ditto. * lib/kernel32/synch/mutex.c: Ditto. * lib/kernel32/synch/sem.c: Ditto. * lib/kernel32/synch/timer.c: Ditto. * lib/kernel32/synch/wait.c: Ditto. * lib/kernel32/thread/fiber.c: Ditto. * lib/kernel32/thread/fls.c: Ditto. * lib/kernel32/thread/thread.c: Ditto. * lib/kernel32/thread/tls.c: Ditto. svn path=/trunk/; revision=5045
2003-07-10 18:50:51 +00:00
/*
* @implemented
*/
BOOL
STDCALL
MoveFileWithProgressW (
LPCWSTR lpExistingFileName,
LPCWSTR lpNewFileName,
LPPROGRESS_ROUTINE lpProgressRoutine,
LPVOID lpData,
DWORD dwFlags
)
{
HANDLE hFile = NULL;
IO_STATUS_BLOCK IoStatusBlock;
PFILE_RENAME_INFORMATION FileRename;
NTSTATUS errCode;
BOOL Result;
UNICODE_STRING DstPathU;
DPRINT("MoveFileWithProgressW()\n");
hFile = CreateFileW (lpExistingFileName,
GENERIC_ALL,
FILE_SHARE_WRITE|FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
}
/* validate & translate the filename */
if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpNewFileName,
&DstPathU,
NULL,
NULL))
{
DPRINT("Invalid destination path\n");
CloseHandle(hFile);
SetLastError(ERROR_PATH_NOT_FOUND);
return FALSE;
}
FileRename = alloca(sizeof(FILE_RENAME_INFORMATION) + DstPathU.Length);
if ((dwFlags & MOVEFILE_REPLACE_EXISTING) == MOVEFILE_REPLACE_EXISTING)
FileRename->ReplaceIfExists = TRUE;
else
FileRename->ReplaceIfExists = FALSE;
memcpy(FileRename->FileName, DstPathU.Buffer, DstPathU.Length);
RtlFreeHeap (RtlGetProcessHeap (),
0,
DstPathU.Buffer);
/*
* FIXME:
* Is the length the count of characters or the length of the buffer?
*/
FileRename->FileNameLength = DstPathU.Length / sizeof(WCHAR);
errCode = NtSetInformationFile (hFile,
&IoStatusBlock,
FileRename,
sizeof(FILE_RENAME_INFORMATION) + DstPathU.Length,
FileRenameInformation);
CloseHandle(hFile);
if (NT_SUCCESS(errCode))
{
Result = TRUE;
}
else if (STATUS_NOT_SAME_DEVICE == errCode &&
MOVEFILE_COPY_ALLOWED == (dwFlags & MOVEFILE_COPY_ALLOWED))
{
Result = CopyFileExW (lpExistingFileName,
lpNewFileName,
lpProgressRoutine,
lpData,
NULL,
FileRename->ReplaceIfExists ? 0 : COPY_FILE_FAIL_IF_EXISTS);
if (Result)
{
/* Cleanup the source file */
AdjustFileAttributes(lpExistingFileName, lpNewFileName);
Result = DeleteFileW (lpExistingFileName);
}
}
#if 1
/* FIXME file rename not yet implemented in all FSDs so it will always
* fail, even when the move is to the same device
*/
else if (STATUS_NOT_IMPLEMENTED == errCode)
{
UNICODE_STRING SrcPathU;
SrcPathU.Buffer = alloca(sizeof(WCHAR) * MAX_PATH);
SrcPathU.MaximumLength = MAX_PATH * sizeof(WCHAR);
SrcPathU.Length = GetFullPathNameW(lpExistingFileName, MAX_PATH, SrcPathU.Buffer, NULL);
if (SrcPathU.Length >= MAX_PATH)
{
SetLastError(ERROR_FILENAME_EXCED_RANGE);
return FALSE;
}
SrcPathU.Length *= sizeof(WCHAR);
DstPathU.Buffer = alloca(sizeof(WCHAR) * MAX_PATH);
DstPathU.MaximumLength = MAX_PATH * sizeof(WCHAR);
DstPathU.Length = GetFullPathNameW(lpNewFileName, MAX_PATH, DstPathU.Buffer, NULL);
if (DstPathU.Length >= MAX_PATH)
{
SetLastError(ERROR_FILENAME_EXCED_RANGE);
return FALSE;
}
DstPathU.Length *= sizeof(WCHAR);
if (0 == RtlCompareUnicodeString(&SrcPathU, &DstPathU, TRUE))
{
/* Source and destination file are the same, nothing to do */
return TRUE;
}
Result = CopyFileExW (lpExistingFileName,
lpNewFileName,
lpProgressRoutine,
lpData,
NULL,
FileRename->ReplaceIfExists ? 0 : COPY_FILE_FAIL_IF_EXISTS);
if (Result)
{
/* Cleanup the source file */
AdjustFileAttributes(lpExistingFileName, lpNewFileName);
Result = DeleteFileW (lpExistingFileName);
}
}
#endif
else
{
SetLastErrorByStatus (errCode);
Result = FALSE;
}
return Result;
}
/*
* @implemented
*/
BOOL
STDCALL
MoveFileWithProgressA (
LPCSTR lpExistingFileName,
LPCSTR lpNewFileName,
LPPROGRESS_ROUTINE lpProgressRoutine,
LPVOID lpData,
DWORD dwFlags
)
{
UNICODE_STRING ExistingFileNameU;
UNICODE_STRING NewFileNameU;
ANSI_STRING ExistingFileName;
ANSI_STRING NewFileName;
BOOL Result;
RtlInitAnsiString (&ExistingFileName,
(LPSTR)lpExistingFileName);
RtlInitAnsiString (&NewFileName,
(LPSTR)lpNewFileName);
/* convert ansi (or oem) string to unicode */
if (bIsFileApiAnsi)
{
RtlAnsiStringToUnicodeString (&ExistingFileNameU,
&ExistingFileName,
TRUE);
RtlAnsiStringToUnicodeString (&NewFileNameU,
&NewFileName,
TRUE);
}
else
{
RtlOemStringToUnicodeString (&ExistingFileNameU,
&ExistingFileName,
TRUE);
RtlOemStringToUnicodeString (&NewFileNameU,
&NewFileName,
TRUE);
}
Result = MoveFileWithProgressW (ExistingFileNameU.Buffer,
NewFileNameU.Buffer,
lpProgressRoutine,
lpData,
dwFlags);
RtlFreeHeap (RtlGetProcessHeap (),
0,
ExistingFileNameU.Buffer);
RtlFreeHeap (RtlGetProcessHeap (),
0,
NewFileNameU.Buffer);
return Result;
}
/*
* @implemented
*/
BOOL
STDCALL
MoveFileW (
LPCWSTR lpExistingFileName,
LPCWSTR lpNewFileName
)
{
return MoveFileExW (lpExistingFileName,
lpNewFileName,
MOVEFILE_COPY_ALLOWED);
}
/*
* @implemented
*/
BOOL
STDCALL
MoveFileExW (
LPCWSTR lpExistingFileName,
LPCWSTR lpNewFileName,
DWORD dwFlags
)
{
return MoveFileWithProgressW (lpExistingFileName,
lpNewFileName,
NULL,
NULL,
dwFlags);
}
/*
* @implemented
*/
BOOL
STDCALL
MoveFileA (
LPCSTR lpExistingFileName,
LPCSTR lpNewFileName
)
{
return MoveFileExA (lpExistingFileName,
lpNewFileName,
MOVEFILE_COPY_ALLOWED);
}
/*
* @implemented
*/
BOOL
STDCALL
MoveFileExA (
LPCSTR lpExistingFileName,
LPCSTR lpNewFileName,
DWORD dwFlags
)
{
return MoveFileWithProgressA (lpExistingFileName,
lpNewFileName,
NULL,
NULL,
dwFlags);
}
/* EOF */