reactos/reactos/lib/kernel32/file/move.c
Casper Hornstrup 5a7413d3b7 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

383 lines
10 KiB
C

/* $Id: move.c,v 1.10 2003/07/10 18:50:51 chorns 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 *****************************************************************/
#include <k32.h>
#define NDEBUG
#include <kernel32/kernel32.h>
#include <kernel32/error.h>
#define FILE_RENAME_SIZE MAX_PATH +sizeof(FILE_RENAME_INFORMATION)
/* FUNCTIONS ****************************************************************/
/*
* @implemented
*/
WINBOOL
STDCALL
MoveFileA (
LPCSTR lpExistingFileName,
LPCSTR lpNewFileName
)
{
return MoveFileExA (lpExistingFileName,
lpNewFileName,
MOVEFILE_COPY_ALLOWED);
}
/*
* @implemented
*/
WINBOOL
STDCALL
MoveFileExA (
LPCSTR lpExistingFileName,
LPCSTR lpNewFileName,
DWORD dwFlags
)
{
return MoveFileWithProgressA (lpExistingFileName,
lpNewFileName,
NULL,
NULL,
dwFlags);
}
/*
* @implemented
*/
WINBOOL
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;
WINBOOL 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
*/
WINBOOL
STDCALL
MoveFileW (
LPCWSTR lpExistingFileName,
LPCWSTR lpNewFileName
)
{
return MoveFileExW (lpExistingFileName,
lpNewFileName,
MOVEFILE_COPY_ALLOWED);
}
/*
* @implemented
*/
WINBOOL
STDCALL
MoveFileExW (
LPCWSTR lpExistingFileName,
LPCWSTR lpNewFileName,
DWORD dwFlags
)
{
return MoveFileWithProgressW (lpExistingFileName,
lpNewFileName,
NULL,
NULL,
dwFlags);
}
static WINBOOL
AdjustFileAttributes (
LPCWSTR ExistingFileName,
LPCWSTR NewFileName
)
{
IO_STATUS_BLOCK IoStatusBlock;
FILE_BASIC_INFORMATION ExistingInfo,
NewInfo;
HANDLE hFile;
DWORD Attributes;
NTSTATUS errCode;
WINBOOL 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;
}
/*
* @implemented
*/
WINBOOL
STDCALL
MoveFileWithProgressW (
LPCWSTR lpExistingFileName,
LPCWSTR lpNewFileName,
LPPROGRESS_ROUTINE lpProgressRoutine,
LPVOID lpData,
DWORD dwFlags
)
{
HANDLE hFile = NULL;
IO_STATUS_BLOCK IoStatusBlock;
FILE_RENAME_INFORMATION *FileRename;
USHORT Buffer[FILE_RENAME_SIZE];
NTSTATUS errCode;
DWORD err;
WINBOOL Result;
hFile = CreateFileW (lpExistingFileName,
GENERIC_ALL,
FILE_SHARE_WRITE|FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
FileRename = (FILE_RENAME_INFORMATION *)Buffer;
if ((dwFlags & MOVEFILE_REPLACE_EXISTING) == MOVEFILE_REPLACE_EXISTING)
FileRename->Replace = TRUE;
else
FileRename->Replace = FALSE;
FileRename->FileNameLength = wcslen (lpNewFileName);
memcpy (FileRename->FileName,
lpNewFileName,
min(FileRename->FileNameLength, MAX_PATH));
errCode = NtSetInformationFile (hFile,
&IoStatusBlock,
FileRename,
FILE_RENAME_SIZE,
FileRenameInformation);
CloseHandle(hFile);
if (NT_SUCCESS(errCode))
{
Result = TRUE;
}
/* FIXME file rename not yet implemented in all FSDs so it will always
* fail, even when the move is to the same device
*/
#if 0
else if (STATUS_NOT_SAME_DEVICE == errCode &&
MOVEFILE_COPY_ALLOWED == (dwFlags & MOVEFILE_COPY_ALLOWED))
#else
else
#endif
{
Result = CopyFileExW (lpExistingFileName,
lpNewFileName,
lpProgressRoutine,
lpData,
NULL,
FileRename->Replace ? 0 : COPY_FILE_FAIL_IF_EXISTS) &&
AdjustFileAttributes(lpExistingFileName, lpNewFileName) &&
DeleteFileW (lpExistingFileName);
if (! Result)
{
/* Delete of the existing file failed so the
* existing file is still there. Clean up the
* new file (if possible)
*/
err = GetLastError();
if (! SetFileAttributesW (lpNewFileName, FILE_ATTRIBUTE_NORMAL))
{
DPRINT("Removing possible READONLY attrib from new file failed with code %d\n", GetLastError());
}
if (! DeleteFileW (lpNewFileName))
{
DPRINT("Deleting new file during cleanup failed with code %d\n", GetLastError());
}
SetLastError (err);
}
}
/* See FIXME above */
#if 0
else
{
SetLastErrorByStatus (errCode);
Result = FALSE;
}
#endif
return Result;
}
/* EOF */