- Split up the handling if the fsd returns STATUS_NOT_IMPLEMENTED in MoveFileWithProgressW.

- Converted the destination name before calling NtSetInformationFile in MoveFileWithProgressW.

svn path=/trunk/; revision=11912
This commit is contained in:
Hartmut Birr 2004-12-04 15:38:22 +00:00
parent 98ac389c31
commit 88ab19cd71

View file

@ -1,4 +1,4 @@
/* $Id: move.c,v 1.14 2004/06/13 20:04:55 navaraf Exp $ /* $Id: move.c,v 1.15 2004/12/04 15:38:22 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
@ -16,9 +16,15 @@
#define NDEBUG #define NDEBUG
#include "../include/debug.h" #include "../include/debug.h"
/* GLOBALS *****************************************************************/
#define FILE_RENAME_SIZE MAX_PATH +sizeof(FILE_RENAME_INFORMATION) #if defined(__GNUC__)
void * alloca(size_t size);
#elif defined(_MSC_VER)
void* _alloca(size_t size);
#else
#error Unknown compiler for alloca intrinsic stack allocation "function"
#endif
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
@ -164,11 +170,12 @@ MoveFileWithProgressW (
{ {
HANDLE hFile = NULL; HANDLE hFile = NULL;
IO_STATUS_BLOCK IoStatusBlock; IO_STATUS_BLOCK IoStatusBlock;
FILE_RENAME_INFORMATION *FileRename; PFILE_RENAME_INFORMATION FileRename;
USHORT Buffer[FILE_RENAME_SIZE];
NTSTATUS errCode; NTSTATUS errCode;
DWORD err;
BOOL Result; BOOL Result;
UNICODE_STRING DstPathU;
DPRINT("MoveFileWithProgressW()\n");
hFile = CreateFileW (lpExistingFileName, hFile = CreateFileW (lpExistingFileName,
GENERIC_ALL, GENERIC_ALL,
@ -178,71 +185,118 @@ MoveFileWithProgressW (
FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL,
NULL); NULL);
FileRename = (FILE_RENAME_INFORMATION *)Buffer; 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) if ((dwFlags & MOVEFILE_REPLACE_EXISTING) == MOVEFILE_REPLACE_EXISTING)
FileRename->ReplaceIfExists = TRUE; FileRename->ReplaceIfExists = TRUE;
else else
FileRename->ReplaceIfExists = FALSE; FileRename->ReplaceIfExists = FALSE;
FileRename->FileNameLength = wcslen (lpNewFileName);
memcpy (FileRename->FileName,
lpNewFileName,
min(FileRename->FileNameLength, MAX_PATH));
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, errCode = NtSetInformationFile (hFile,
&IoStatusBlock, &IoStatusBlock,
FileRename, FileRename,
FILE_RENAME_SIZE, sizeof(FILE_RENAME_INFORMATION) + DstPathU.Length,
FileRenameInformation); FileRenameInformation);
CloseHandle(hFile); CloseHandle(hFile);
if (NT_SUCCESS(errCode)) if (NT_SUCCESS(errCode))
{ {
Result = TRUE; 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 && else if (STATUS_NOT_SAME_DEVICE == errCode &&
MOVEFILE_COPY_ALLOWED == (dwFlags & MOVEFILE_COPY_ALLOWED)) MOVEFILE_COPY_ALLOWED == (dwFlags & MOVEFILE_COPY_ALLOWED))
#else
else
#endif
{ {
Result = CopyFileExW (lpExistingFileName, Result = CopyFileExW (lpExistingFileName,
lpNewFileName, lpNewFileName,
lpProgressRoutine, lpProgressRoutine,
lpData, lpData,
NULL, NULL,
FileRename->ReplaceIfExists ? 0 : COPY_FILE_FAIL_IF_EXISTS) && FileRename->ReplaceIfExists ? 0 : COPY_FILE_FAIL_IF_EXISTS);
AdjustFileAttributes(lpExistingFileName, lpNewFileName) && if (Result)
DeleteFileW (lpExistingFileName);
if (! Result)
{ {
/* Delete of the existing file failed so the /* Cleanup the source file */
* existing file is still there. Clean up the AdjustFileAttributes(lpExistingFileName, lpNewFileName);
* new file (if possible) 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
*/ */
err = GetLastError(); else if (STATUS_NOT_IMPLEMENTED == errCode)
if (! SetFileAttributesW (lpNewFileName, FILE_ATTRIBUTE_NORMAL))
{ {
DPRINT("Removing possible READONLY attrib from new file failed with code %d\n", GetLastError());
} UNICODE_STRING SrcPathU;
if (! DeleteFileW (lpNewFileName))
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)
{ {
DPRINT("Deleting new file during cleanup failed with code %d\n", GetLastError()); SetLastError(ERROR_FILENAME_EXCED_RANGE);
return FALSE;
} }
SetLastError (err); 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);
} }
} }
/* See FIXME above */ #endif
#if 0
else else
{ {
SetLastErrorByStatus (errCode); SetLastErrorByStatus (errCode);
Result = FALSE; Result = FALSE;
} }
#endif
return Result; return Result;
} }