Signed-off-by: Tom Watson <coder@tommywatson.com>
---
��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