mirror of
https://github.com/reactos/reactos.git
synced 2025-04-30 11:08:51 +00:00

* 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
383 lines
10 KiB
C
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 */
|