---
dlls/kernel32/path.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 101 insertions(+), 5 deletions(-)
diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c
index a389743171..98891cde6d 100644
--- a/dlls/kernel32/path.c
+++ b/dlls/kernel32/path.c
@@ -43,6 +43,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(file);
#define MAX_PATHNAME_LEN 1024
+/* struct to hold progress function callback for MoveFileWithProgressW */
+typedef struct {
+ LPPROGRESS_ROUTINE progress;
+ VOID *data;
+ BOOL status; /* flush successful */
+} MFWFData;
+
static int path_safe_mode = -1; /* path mode set by SetSearchPathMode */
/* check if a file name is for an executable file (.exe or .com) */
@@ -1159,10 +1166,14 @@ BOOL WINAPI CopyFileExW(LPCWSTR source, LPCWSTR dest,
static const int buffer_size = 65536;
HANDLE h1, h2;
BY_HANDLE_FILE_INFORMATION info;
+ LARGE_INTEGER file_position,file_size;
DWORD count;
BOOL ret = FALSE;
char *buffer;
+ DWORD progressExit = 0;
+ /* init file size/position */
+ file_position.QuadPart=file_size.QuadPart=0;
if (!source || !dest)
{
SetLastError(ERROR_INVALID_PARAMETER);
@@ -1193,6 +1204,10 @@ BOOL WINAPI CopyFileExW(LPCWSTR source, LPCWSTR dest,
return FALSE;
}
+ /* update total size */
+ file_size.LowPart = info.nFileSizeLow;
+ file_size.HighPart = info.nFileSizeHigh;
+
if (!(flags & COPY_FILE_FAIL_IF_EXISTS))
{
BOOL same_file = FALSE;
@@ -1231,6 +1246,32 @@ BOOL WINAPI CopyFileExW(LPCWSTR source, LPCWSTR dest,
if (!WriteFile( h2, p, count, &res, NULL ) || !res) goto done;
p += res;
count -= res;
+ file_position.QuadPart += res;
+ }
+ /* Call progress function ? */
+ if (progress != NULL) {
+ progressExit = progress(file_size, file_position, file_size,
+ file_position, 1, CALLBACK_CHUNK_FINISHED, h1, h2, param);
+ switch (progressExit) {
+ case PROGRESS_CONTINUE:
+ // keep at it
+ break;
+ case PROGRESS_QUIET:
+ // requested not to be called again
+ progress = NULL;
+ break;
+ case PROGRESS_CANCEL:
+ // cancel and clean up
+ CloseHandle( h2 );
+ h2 = INVALID_HANDLE_VALUE;
+ DeleteFileW( dest );
+ SetLastError( ERROR_REQUEST_ABORTED );
+ goto done;
+ case PROGRESS_STOP:
+ // do nothing, allow for a restart (??)
+ SetLastError( ERROR_REQUEST_ABORTED );
+ goto done;
+ }
}
}
ret = TRUE;
@@ -1239,7 +1280,10 @@ done:
SetFileTime(h2, NULL, NULL, &info.ftLastWriteTime);
HeapFree( GetProcessHeap(), 0, buffer );
CloseHandle( h1 );
- CloseHandle( h2 );
+ if (h2 != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle( h2 );
+ }
return ret;
}
@@ -1269,6 +1313,39 @@ BOOL WINAPI CopyFileExA(LPCSTR sourceFilename, LPCSTR destFilename,
}
+/**************************************************************************
+ * moveFileWFlush
+ */
+DWORD CALLBACK moveFileWFlush(LARGE_INTEGER TotalFileSize,
+ LARGE_INTEGER TotalBytesTransferred,
+ LARGE_INTEGER StreamSize,
+ LARGE_INTEGER StreamBytesTransferred,
+ DWORD dwStreamNumber, DWORD dwCallbackReason,
+ HANDLE hSourceFile,HANDLE hDestinationFile,
+ LPVOID lpData )
+{
+ MFWFData *data = (MFWFData *)lpData;
+ DWORD rval = 0;
+
+ if ( data->progress != NULL)
+ {
+ rval = data->progress( TotalFileSize, TotalBytesTransferred,
+ StreamSize, StreamBytesTransferred,
+ dwStreamNumber, dwCallbackReason,
+ hSourceFile, hDestinationFile, data->data);
+ }
+ /* continue the copy? */
+ if (rval == 0 ) {
+ /* completed the copy? */
+ if (TotalFileSize.QuadPart == TotalBytesTransferred.QuadPart)
+ {
+ /* flush the data */
+ data->status = FlushFileBuffers(hDestinationFile)?1:0;
+ }
+ }
+ return rval;
+}
+
/**************************************************************************
* MoveFileWithProgressW (KERNEL32.@)
*/
@@ -1293,9 +1370,6 @@ BOOL WINAPI MoveFileWithProgressW( LPCWSTR source, LPCWSTR dest,
if (!dest)
return DeleteFileW( source );
- if (flag & MOVEFILE_WRITE_THROUGH)
- FIXME("MOVEFILE_WRITE_THROUGH unimplemented\n");
-
/* check if we are allowed to rename the source */
if (!RtlDosPathNameToNtPathName_U( source, &nt_name, NULL, NULL ))
@@ -1369,8 +1443,30 @@ BOOL WINAPI MoveFileWithProgressW( LPCWSTR source, LPCWSTR dest,
}
/* now perform the rename */
+ if ((flag & MOVEFILE_WRITE_THROUGH) && !(flag & MOVEFILE_DELAY_UNTIL_REBOOT))
+ {
+ /* save the original progress function && param, set status to 0 */
+ MFWFData data;
+ data.progress = fnProgress;
+ data.data = param;
+ data.status = 0;
+ /* try to copy the file, if it fails or the flush failed, set error */
+ if (CopyFileExW( source, dest, moveFileWFlush, &data, NULL, 0) == 0
+ || !data.status) {
+ /* failed, set error */
+ FILE_SetDosError();
+ goto error;
+ }
- if (rename( source_unix.Buffer, dest_unix.Buffer ) == -1)
+ /* delete the source file */
+ if (!DeleteFileW( source ))
+ {
+ /* failed, set error */
+ FILE_SetDosError();
+ goto error;
+ }
+ }
+ else if (rename( source_unix.Buffer, dest_unix.Buffer ) == -1)
{
if (errno == EXDEV && (flag & MOVEFILE_COPY_ALLOWED))
{
--
2.14.1