-/* $Id: move.c,v 1.3 2000/03/14 23:09:23 ekohl Exp $
+/* $Id$
*
* 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)
+ * Gerhard W. Gruber (sparhawk_at_gmx.at)
* UPDATE HISTORY:
* Created 01/11/98
*/
/* INCLUDES *****************************************************************/
-#include <ddk/ntddk.h>
-#include <windows.h>
+#include <k32.h>
+#include <malloc.h>
#define NDEBUG
-#include <kernel32/kernel32.h>
-
-
-#define FILE_RENAME_SIZE MAX_PATH +sizeof(FILE_RENAME_INFORMATION)
+#include "../include/debug.h"
+/* GLOBALS *****************************************************************/
/* FUNCTIONS ****************************************************************/
+static BOOL
+RemoveReadOnlyAttributeW(IN LPCWSTR lpFileName)
+{
+ DWORD Attributes;
+ Attributes = GetFileAttributesW(lpFileName);
+ if (Attributes != INVALID_FILE_ATTRIBUTES)
+ {
+ return SetFileAttributesW(lpFileName,Attributes -
+ (Attributes & ~FILE_ATTRIBUTE_READONLY));
+ }
+
+ return FALSE;
+}
-WINBOOL
-STDCALL
-MoveFileA (
- LPCSTR lpExistingFileName,
- LPCSTR lpNewFileName
- )
+
+/***********************************************************************
+ * add_boot_rename_entry
+ *
+ * Adds an entry to the registry that is loaded when windows boots and
+ * checks if there are some files to be removed or renamed/moved.
+ * <fn1> has to be valid and <fn2> may be NULL. If both pointers are
+ * non-NULL then the file is moved, otherwise it is deleted. The
+ * entry of the registrykey is always appended with two zero
+ * terminated strings. If <fn2> is NULL then the second entry is
+ * simply a single 0-byte. Otherwise the second filename goes
+ * there. The entries are prepended with \??\ before the path and the
+ * second filename gets also a '!' as the first character if
+ * MOVEFILE_REPLACE_EXISTING is set. After the final string another
+ * 0-byte follows to indicate the end of the strings.
+ * i.e.:
+ * \??\D:\test\file1[0]
+ * !\??\D:\test\file1_renamed[0]
+ * \??\D:\Test|delete[0]
+ * [0] <- file is to be deleted, second string empty
+ * \??\D:\test\file2[0]
+ * !\??\D:\test\file2_renamed[0]
+ * [0] <- indicates end of strings
+ *
+ * or:
+ * \??\D:\test\file1[0]
+ * !\??\D:\test\file1_renamed[0]
+ * \??\D:\Test|delete[0]
+ * [0] <- file is to be deleted, second string empty
+ * [0] <- indicates end of strings
+ *
+ */
+static BOOL add_boot_rename_entry( LPCWSTR source, LPCWSTR dest, DWORD flags )
{
- return MoveFileExA (lpExistingFileName,
- lpNewFileName,
- MOVEFILE_COPY_ALLOWED);
+ static const WCHAR ValueName[] = {'P','e','n','d','i','n','g',
+ 'F','i','l','e','R','e','n','a','m','e',
+ 'O','p','e','r','a','t','i','o','n','s',0};
+
+ UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager");
+
+ static const int info_size = FIELD_OFFSET( KEY_VALUE_PARTIAL_INFORMATION, Data );
+
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING nameW, source_name, dest_name;
+ KEY_VALUE_PARTIAL_INFORMATION *info;
+ BOOL rc = FALSE;
+ HANDLE Reboot = 0;
+ DWORD len1, len2;
+ DWORD DataSize = 0;
+ BYTE *Buffer = NULL;
+ WCHAR *p;
+ NTSTATUS Status;
+
+ DPRINT("Add support to smss for keys created by MOVEFILE_DELAY_UNTIL_REBOOT\n");
+
+ if (!RtlDosPathNameToNtPathName_U( source, &source_name, NULL, NULL ))
+ {
+ SetLastError( ERROR_PATH_NOT_FOUND );
+ return FALSE;
+ }
+ dest_name.Buffer = NULL;
+ if (dest && !RtlDosPathNameToNtPathName_U( dest, &dest_name, NULL, NULL ))
+ {
+ RtlFreeUnicodeString( &source_name );
+ SetLastError( ERROR_PATH_NOT_FOUND );
+ return FALSE;
+ }
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtCreateKey(&Reboot,
+ KEY_QUERY_VALUE | KEY_SET_VALUE,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ NULL);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtCreateKey() failed (Status 0x%lx)\n", Status);
+ RtlFreeUnicodeString( &source_name );
+ RtlFreeUnicodeString( &dest_name );
+ return FALSE;
+ }
+
+ len1 = source_name.Length + sizeof(WCHAR);
+ if (dest)
+ {
+ len2 = dest_name.Length + sizeof(WCHAR);
+ if (flags & MOVEFILE_REPLACE_EXISTING)
+ len2 += sizeof(WCHAR); /* Plus 1 because of the leading '!' */
+ }
+ else len2 = sizeof(WCHAR); /* minimum is the 0 characters for the empty second string */
+
+ RtlInitUnicodeString( &nameW, ValueName );
+
+ /* First we check if the key exists and if so how many bytes it already contains. */
+ if (NtQueryValueKey( Reboot, &nameW, KeyValuePartialInformation,
+ NULL, 0, &DataSize ) == STATUS_BUFFER_OVERFLOW)
+ {
+ if (!(Buffer = HeapAlloc( GetProcessHeap(), 0, DataSize + len1 + len2 + sizeof(WCHAR) )))
+ goto Quit;
+ if (NtQueryValueKey( Reboot, &nameW, KeyValuePartialInformation,
+ Buffer, DataSize, &DataSize )) goto Quit;
+ info = (KEY_VALUE_PARTIAL_INFORMATION *)Buffer;
+ if (info->Type != REG_MULTI_SZ) goto Quit;
+ if (DataSize > sizeof(info)) DataSize -= sizeof(WCHAR); /* remove terminating null (will be added back later) */
+ }
+ else
+ {
+ DataSize = info_size;
+ if (!(Buffer = HeapAlloc( GetProcessHeap(), 0, DataSize + len1 + len2 + sizeof(WCHAR) )))
+ goto Quit;
+ }
+
+ memcpy( Buffer + DataSize, source_name.Buffer, len1 );
+ DataSize += len1;
+ p = (WCHAR *)(Buffer + DataSize);
+ if (dest)
+ {
+ if (flags & MOVEFILE_REPLACE_EXISTING)
+ *p++ = '!';
+ memcpy( p, dest_name.Buffer, len2 );
+ DataSize += len2;
+ }
+ else
+ {
+ *p = 0;
+ DataSize += sizeof(WCHAR);
+ }
+
+ /* add final null */
+ p = (WCHAR *)(Buffer + DataSize);
+ *p = 0;
+ DataSize += sizeof(WCHAR);
+
+ rc = !NtSetValueKey(Reboot, &nameW, 0, REG_MULTI_SZ, Buffer + info_size, DataSize - info_size);
+
+ Quit:
+ RtlFreeUnicodeString( &source_name );
+ RtlFreeUnicodeString( &dest_name );
+ if (Reboot) NtClose(Reboot);
+ HeapFree( GetProcessHeap(), 0, Buffer );
+ return(rc);
}
-WINBOOL
+/*
+ * @implemented
+ */
+BOOL
STDCALL
-MoveFileExA (
- LPCSTR lpExistingFileName,
- LPCSTR lpNewFileName,
- DWORD dwFlags
+MoveFileWithProgressW (
+ LPCWSTR lpExistingFileName,
+ LPCWSTR lpNewFileName,
+ LPPROGRESS_ROUTINE lpProgressRoutine,
+ LPVOID lpData,
+ DWORD dwFlags
)
{
- UNICODE_STRING ExistingFileNameU;
- UNICODE_STRING NewFileNameU;
- ANSI_STRING ExistingFileName;
- ANSI_STRING NewFileName;
- WINBOOL Result;
+ HANDLE hFile = NULL;
+ IO_STATUS_BLOCK IoStatusBlock;
+ PFILE_RENAME_INFORMATION FileRename;
+ NTSTATUS errCode;
+ BOOL Result;
+ UNICODE_STRING DstPathU;
+ BOOL folder = FALSE;
+
+ DPRINT("MoveFileWithProgressW()\n");
- RtlInitAnsiString (&ExistingFileName,
- (LPSTR)lpExistingFileName);
+ if (dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT)
+ return add_boot_rename_entry( lpExistingFileName, lpNewFileName, dwFlags );
- RtlInitAnsiString (&NewFileName,
- (LPSTR)lpNewFileName);
+ hFile = CreateFileW (lpExistingFileName,
+ GENERIC_ALL,
+ FILE_SHARE_WRITE|FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
- /* convert ansi (or oem) string to unicode */
- if (bIsFileApiAnsi)
+ if (hFile == INVALID_HANDLE_VALUE)
{
- RtlAnsiStringToUnicodeString (&ExistingFileNameU,
- &ExistingFileName,
- TRUE);
- RtlAnsiStringToUnicodeString (&NewFileNameU,
- &NewFileName,
- TRUE);
+ return FALSE;
}
+
+
+ /* validate & translate the filename */
+ if (!RtlDosPathNameToNtPathName_U (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 (GetFileAttributesW(lpExistingFileName) & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ folder = TRUE;
+ }
+
+
+ /*
+ * FIXME:
+ * Fail now move the folder
+ * Before we fail at CreateFileW
+ */
+
+
+ if (NT_SUCCESS(errCode))
{
- RtlOemStringToUnicodeString (&ExistingFileNameU,
- &ExistingFileName,
- TRUE);
- RtlOemStringToUnicodeString (&NewFileNameU,
- &NewFileName,
- TRUE);
+ Result = TRUE;
}
+ else
+ {
+ if (folder==FALSE)
+ {
+ Result = CopyFileExW (lpExistingFileName,
+ lpNewFileName,
+ lpProgressRoutine,
+ lpData,
+ NULL,
+ FileRename->ReplaceIfExists ? 0 : COPY_FILE_FAIL_IF_EXISTS);
+ if (Result)
+ {
+ /* Cleanup the source file */
+ Result = DeleteFileW (lpExistingFileName);
+ }
+ }
+ else
+ {
+ /* move folder code start */
+ WIN32_FIND_DATAW findBuffer;
+ LPWSTR lpExistingFileName2 = NULL;
+ LPWSTR lpNewFileName2 = NULL;
+ LPWSTR lpDeleteFile = NULL;
+ INT size;
+ INT size2;
+ BOOL loop = TRUE;
+ BOOL Result = FALSE;
+ INT max_size = MAX_PATH;
+
+
+ /* Build the string */
+ size = wcslen(lpExistingFileName);
+ if (size+6> max_size)
+ max_size = size + 6;
+
+ lpDeleteFile = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR));
+ if (lpDeleteFile == NULL)
+ return FALSE;
+
+ lpNewFileName2 = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR));
+ if (lpNewFileName2 == NULL)
+ {
+ HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);
+ return FALSE;
+ }
+
+ lpExistingFileName2 = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR));
+ if (lpNewFileName2 == NULL)
+ {
+ HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2);
+ HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);
+ return FALSE;
+ }
+
+ wcscpy( (WCHAR *)lpExistingFileName2,lpExistingFileName);
+ wcscpy( (WCHAR *)&lpExistingFileName2[size],L"\\*.*\0");
+
+ /* Get the file name */
+ memset(&findBuffer,0,sizeof(WIN32_FIND_DATAW));
+ hFile = FindFirstFileW(lpExistingFileName2, &findBuffer);
+ if (hFile == NULL)
+ loop=FALSE;
+
+ if (findBuffer.cFileName[0] == L'\0')
+ loop=FALSE;
+
+
+ /* FIXME
+ * remove readonly flag from source folder and do not set the readonly flag to dest folder
+ */
+ RemoveReadOnlyAttributeW(lpExistingFileName);
+ RemoveReadOnlyAttributeW(lpNewFileName);
+ //CreateDirectoryExW(lpExistingFileName,lpNewFileName,NULL);
+ CreateDirectoryW(lpNewFileName, NULL);
+
+ /* search the files/folders and move them */
+ while (loop==TRUE)
+ {
+ Result = TRUE;
+
+ if ((!wcscmp(findBuffer.cFileName,L"..")) || (!wcscmp(findBuffer.cFileName,L".")))
+ {
+ loop = FindNextFileW(hFile, &findBuffer);
+
+ if (!loop)
+ {
+ size = wcslen(lpExistingFileName2)-4;
+ FindClose(hFile);
+ wcscpy( &lpExistingFileName2[size],L"\0");
+
+ if (wcsncmp(lpExistingFileName,lpExistingFileName2,size))
+ {
+ DWORD Attributes;
+
+ FindClose(hFile);
+
+ /* delete folder */
+ DPRINT("MoveFileWithProgressW : Delete folder : %S\n",lpDeleteFile);
+
+ /* remove system folder flag other wise we can not delete the folder */
+ Attributes = GetFileAttributesW(lpExistingFileName2);
+ if (Attributes != INVALID_FILE_ATTRIBUTES)
+ {
+ SetFileAttributesW(lpExistingFileName2,(Attributes & ~FILE_ATTRIBUTE_SYSTEM));
+ }
+
+ RemoveReadOnlyAttributeW(lpExistingFileName2);
+
+ Result = RemoveDirectoryW(lpExistingFileName2);
+ if (Result == FALSE)
+ break;
+
+ loop=TRUE;
+ size = wcslen(lpExistingFileName);
+
+ if (size+6>max_size)
+ {
+ if (lpNewFileName2 != NULL)
+ HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2);
+
+ if (lpExistingFileName2 != NULL)
+ HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2);
+
+ if (lpDeleteFile != NULL)
+ HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);
+
+ return FALSE;
+ }
- Result = MoveFileExW (ExistingFileNameU.Buffer,
- NewFileNameU.Buffer,
- dwFlags);
+ wcscpy( lpExistingFileName2,lpExistingFileName);
+ wcscpy( &lpExistingFileName2[size],L"\\*.*\0");
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- ExistingFileNameU.Buffer);
- RtlFreeHeap (RtlGetProcessHeap (),
- 0,
- NewFileNameU.Buffer);
+ /* Get the file name */
+ memset(&findBuffer,0,sizeof(WIN32_FIND_DATAW));
+ hFile = FindFirstFileW(lpExistingFileName2, &findBuffer);
+ }
+ }
+ continue;
+ }
+
+ if (findBuffer.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ /* Build the new src string */
+ size = wcslen(findBuffer.cFileName);
+ size2= wcslen(lpExistingFileName2);
+
+ if (size2+size+6>max_size)
+ {
+ FindClose(hFile);
+
+ if (lpNewFileName2 != NULL)
+ HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2);
+
+ if (lpExistingFileName2 != NULL)
+ HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2);
+
+ if (lpDeleteFile != NULL)
+ HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);
+
+ return FALSE;
+ }
+
+ wcscpy( &lpExistingFileName2[size2-3],findBuffer.cFileName);
+ wcscpy( &lpExistingFileName2[size2+size-3],L"\0");
+
+
+ /* Continue */
+ wcscpy( lpDeleteFile,lpExistingFileName2);
+ wcscpy( &lpExistingFileName2[size2+size-3],L"\\*.*\0");
+
+
+ /* Build the new dst string */
+ size = wcslen(lpExistingFileName2) + wcslen(lpNewFileName);
+ size2 = wcslen(lpExistingFileName);
+
+ if (size>max_size)
+ {
+ FindClose(hFile);
+
+ if (lpNewFileName2 != NULL)
+ HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2);
+
+ if (lpExistingFileName2 != NULL)
+ HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2);
+
+ if (lpDeleteFile != NULL)
+ HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);
+
+ return FALSE;
+ }
+
+ wcscpy( lpNewFileName2,lpNewFileName);
+ size = wcslen(lpNewFileName);
+ wcscpy( &lpNewFileName2[size], &lpExistingFileName2[size2]);
+ size = wcslen(lpNewFileName2);
+ wcscpy( &lpNewFileName2[size-4],L"\0");
+
+ /* Create Folder */
+
+ /* FIXME
+ * remove readonly flag from source folder and do not set the readonly flag to dest folder
+ */
+ RemoveReadOnlyAttributeW(lpDeleteFile);
+ RemoveReadOnlyAttributeW(lpNewFileName2);
+
+ CreateDirectoryW(lpNewFileName2,NULL);
+ //CreateDirectoryExW(lpDeleteFile, lpNewFileName2,NULL);
+
+
+ /* set new search path from src string */
+ FindClose(hFile);
+ memset(&findBuffer,0,sizeof(WIN32_FIND_DATAW));
+ hFile = FindFirstFileW(lpExistingFileName2, &findBuffer);
+ }
+ else
+ {
+
+ /* Build the new string */
+ size = wcslen(findBuffer.cFileName);
+ size2= wcslen(lpExistingFileName2);
+ wcscpy( lpDeleteFile,lpExistingFileName2);
+ wcscpy( &lpDeleteFile[size2-3],findBuffer.cFileName);
+
+ /* Build dest string */
+ size = wcslen(lpDeleteFile) + wcslen(lpNewFileName);
+ size2 = wcslen(lpExistingFileName);
+
+ if (size>max_size)
+ {
+ FindClose(hFile);
+
+ if (lpNewFileName2 != NULL)
+ HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2);
+
+ if (lpExistingFileName2 != NULL)
+ HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2);
+
+ if (lpDeleteFile != NULL)
+ HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);
+
+ return FALSE;
+ }
+
+ wcscpy( lpNewFileName2,lpNewFileName);
+ size = wcslen(lpNewFileName);
+ wcscpy(&lpNewFileName2[size],&lpDeleteFile[size2]);
+
+
+ /* overrite existsen file, if the file got the flag have readonly
+ * we need reomve that flag
+ */
+
+ /* copy file */
+
+ DPRINT("MoveFileWithProgressW : Copy file : %S to %S\n",lpDeleteFile, lpNewFileName2);
+ RemoveReadOnlyAttributeW(lpDeleteFile);
+ RemoveReadOnlyAttributeW(lpNewFileName2);
+
+ Result = CopyFileExW (lpDeleteFile,
+ lpNewFileName2,
+ lpProgressRoutine,
+ lpData,
+ NULL,
+ 0);
+
+ if (Result == FALSE)
+ break;
+
+ /* delete file */
+ DPRINT("MoveFileWithProgressW : remove readonly flag from file : %S\n",lpNewFileName2);
+ Result = RemoveReadOnlyAttributeW(lpDeleteFile);
+ if (Result == FALSE)
+ break;
+
+ DPRINT("MoveFileWithProgressW : Delete file : %S\n",lpDeleteFile);
+ Result = DeleteFileW(lpDeleteFile);
+ if (Result == FALSE)
+ break;
+
+ }
+ loop = FindNextFileW(hFile, &findBuffer);
+ }
+
+
+ /* Remove last folder */
+ if ((loop == FALSE) && (Result != FALSE))
+ {
+ DWORD Attributes;
+
+ FindClose(hFile);
+ Attributes = GetFileAttributesW(lpDeleteFile);
+ if (Attributes != INVALID_FILE_ATTRIBUTES)
+ {
+ SetFileAttributesW(lpDeleteFile,(Attributes & ~FILE_ATTRIBUTE_SYSTEM));
+ }
+
+ Result = RemoveDirectoryW(lpExistingFileName);
+ }
+
+ /* Cleanup */
+ FindClose(hFile);
+
+ if (lpNewFileName2 != NULL)
+ {
+ HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2);
+ lpNewFileName2 = NULL;
+ }
+
+ if (lpExistingFileName2 != NULL)
+ {
+ HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2);
+ lpExistingFileName2 = NULL;
+ }
+
+ if (lpDeleteFile != NULL)
+ {
+ HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);
+ lpDeleteFile = NULL;
+ }
+
+ return Result;
+
+ // end move folder code
+ }
+ }
+
+
return Result;
}
-WINBOOL
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+MoveFileWithProgressA (
+ LPCSTR lpExistingFileName,
+ LPCSTR lpNewFileName,
+ LPPROGRESS_ROUTINE lpProgressRoutine,
+ LPVOID lpData,
+ DWORD dwFlags
+ )
+{
+ PWCHAR ExistingFileNameW;
+ PWCHAR NewFileNameW;
+ BOOL ret;
+
+ if (!(ExistingFileNameW = FilenameA2W(lpExistingFileName, FALSE)))
+ return FALSE;
+
+ if (!(NewFileNameW= FilenameA2W(lpNewFileName, TRUE)))
+ return FALSE;
+
+ ret = MoveFileWithProgressW (ExistingFileNameW ,
+ NewFileNameW,
+ lpProgressRoutine,
+ lpData,
+ dwFlags);
+
+ RtlFreeHeap (RtlGetProcessHeap (), 0, NewFileNameW);
+
+ return ret;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
STDCALL
MoveFileW (
LPCWSTR lpExistingFileName,
}
-WINBOOL
+/*
+ * @implemented
+ */
+BOOL
STDCALL
MoveFileExW (
LPCWSTR lpExistingFileName,
DWORD dwFlags
)
{
- HANDLE hFile = NULL;
- IO_STATUS_BLOCK IoStatusBlock;
- FILE_RENAME_INFORMATION *FileRename;
- USHORT Buffer[FILE_RENAME_SIZE];
- NTSTATUS errCode;
+ return MoveFileWithProgressW (lpExistingFileName,
+ lpNewFileName,
+ NULL,
+ NULL,
+ dwFlags);
+}
- 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;
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+MoveFileA (
+ LPCSTR lpExistingFileName,
+ LPCSTR lpNewFileName
+ )
+{
+ return MoveFileExA (lpExistingFileName,
+ lpNewFileName,
+ MOVEFILE_COPY_ALLOWED);
+}
- FileRename->FileNameLength = wcslen (lpNewFileName);
- memcpy (FileRename->FileName,
- lpNewFileName,
- min(FileRename->FileNameLength, MAX_PATH));
-
- errCode = NtSetInformationFile (hFile,
- &IoStatusBlock,
- FileRename,
- FILE_RENAME_SIZE,
- FileRenameInformation);
- if (!NT_SUCCESS(errCode))
- {
- if (CopyFileW (lpExistingFileName,
- lpNewFileName,
- FileRename->Replace))
- DeleteFileW (lpExistingFileName);
- }
- CloseHandle(hFile);
- return TRUE;
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+MoveFileExA (
+ LPCSTR lpExistingFileName,
+ LPCSTR lpNewFileName,
+ DWORD dwFlags
+ )
+{
+ return MoveFileWithProgressA (lpExistingFileName,
+ lpNewFileName,
+ NULL,
+ NULL,
+ dwFlags);
}
/* EOF */