* 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 <k32.h>
+#include <malloc.h>
#define NDEBUG
#include "../include/debug.h"
/* GLOBALS *****************************************************************/
/* FUNCTIONS ****************************************************************/
-
static BOOL
-AdjustFileAttributes (
- LPCWSTR ExistingFileName,
- LPCWSTR NewFileName
- )
+RemoveReadOnlyAttributeW(IN LPCWSTR lpFileName)
{
- IO_STATUS_BLOCK IoStatusBlock;
- FILE_BASIC_INFORMATION ExistingInfo,
- NewInfo;
- HANDLE hFile;
- DWORD Attributes;
- NTSTATUS errCode;
- BOOL Result = FALSE;
+ DWORD Attributes;
+ Attributes = GetFileAttributesW(lpFileName);
+ if (Attributes != INVALID_FILE_ATTRIBUTES)
+ {
+ return SetFileAttributesW(lpFileName,Attributes -
+ (Attributes & ~FILE_ATTRIBUTE_READONLY));
+ }
+
+ return 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;
+/***********************************************************************
+ * 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 )
+{
+ 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);
}
NTSTATUS errCode;
BOOL Result;
UNICODE_STRING DstPathU;
+ BOOL folder = FALSE;
DPRINT("MoveFileWithProgressW()\n");
+ if (dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT)
+ return add_boot_rename_entry( lpExistingFileName, lpNewFileName, dwFlags );
+
hFile = CreateFileW (lpExistingFileName,
GENERIC_ALL,
FILE_SHARE_WRITE|FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
+ FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
- return FALSE;
+ return FALSE;
}
+
/* validate & translate the filename */
- if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpNewFileName,
+ if (!RtlDosPathNameToNtPathName_U (lpNewFileName,
&DstPathU,
NULL,
NULL))
RtlFreeHeap (RtlGetProcessHeap (),
0,
DstPathU.Buffer);
- /*
+ /*
* FIXME:
* Is the length the count of characters or the length of the buffer?
*/
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))
{
Result = TRUE;
}
- else if (STATUS_NOT_SAME_DEVICE == errCode &&
- MOVEFILE_COPY_ALLOWED == (dwFlags & MOVEFILE_COPY_ALLOWED))
+ else
{
- Result = CopyFileExW (lpExistingFileName,
+ if (folder==FALSE)
+ {
+ Result = CopyFileExW (lpExistingFileName,
lpNewFileName,
lpProgressRoutine,
lpData,
NULL,
FileRename->ReplaceIfExists ? 0 : COPY_FILE_FAIL_IF_EXISTS);
- if (Result)
- {
- /* Cleanup the source file */
- AdjustFileAttributes(lpExistingFileName, lpNewFileName);
+ if (Result)
+ {
+ /* Cleanup the source file */
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,
+ }
+ }
+ 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;
+ }
+
+ wcscpy( lpExistingFileName2,lpExistingFileName);
+ wcscpy( &lpExistingFileName2[size],L"\\*.*\0");
+
+ /* 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,
- 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;
+ 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;
}
PWCHAR ExistingFileNameW;
PWCHAR NewFileNameW;
BOOL ret;
-
+
if (!(ExistingFileNameW = FilenameA2W(lpExistingFileName, FALSE)))
return FALSE;