[PATCH v2] kernelbase: Add support for progress callback in CopyFileEx.
Alexandre Julliard
julliard at winehq.org
Fri Mar 4 03:57:56 CST 2022
Alistair Leslie-Hughes <leslie_alistair at hotmail.com> writes:
> +
> + if (flags & COPY_FILE_OPEN_SOURCE_FOR_WRITE)
> + source_access |= GENERIC_WRITE;
> +
> + if ((h1 = CreateFileW( source, source_access, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
> NULL, OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE)
This looks like an unrelated change.
> @@ -552,7 +565,11 @@ BOOL WINAPI CopyFileExW( const WCHAR *source, const WCHAR *dest, LPPROGRESS_ROUT
> }
> }
>
> - if ((h2 = CreateFileW( dest, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
> + if ((h2 = CreateFileW( dest, GENERIC_WRITE | DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
> + (flags & COPY_FILE_FAIL_IF_EXISTS) ? CREATE_NEW : CREATE_ALWAYS,
> + info.FileAttributes, h1 )) == INVALID_HANDLE_VALUE &&
> + /* retry without DELETE if we got a sharing violation */
> + (h2 = CreateFileW( dest, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
> (flags & COPY_FILE_FAIL_IF_EXISTS) ? CREATE_NEW : CREATE_ALWAYS,
> info.FileAttributes, h1 )) == INVALID_HANDLE_VALUE)
Same here.
> @@ -562,6 +579,29 @@ BOOL WINAPI CopyFileExW( const WCHAR *source, const WCHAR *dest, LPPROGRESS_ROUT
> return FALSE;
> }
>
> + size = info.EndOfFile;
> + transferred.QuadPart = 0;
> +
> + if (progress)
> + {
> + cbret = progress( size, transferred, size, transferred, 1,
> + CALLBACK_STREAM_SWITCH, h1, h2, param );
> + if (cbret == PROGRESS_QUIET)
> + progress = NULL;
> + else if (cbret == PROGRESS_STOP)
> + {
> + SetLastError( ERROR_REQUEST_ABORTED );
> + goto done;
> + }
> + else if (cbret == PROGRESS_CANCEL)
> + {
> + BOOLEAN disp = TRUE;
> + SetFileInformationByHandle( h2, FileDispositionInfo, &disp, sizeof(disp) );
> + SetLastError( ERROR_REQUEST_ABORTED );
> + goto done;
> + }
> + }
> +
> while (ReadFile( h1, buffer, buffer_size, &count, NULL ) && count)
> {
> char *p = buffer;
> @@ -571,13 +611,38 @@ BOOL WINAPI CopyFileExW( const WCHAR *source, const WCHAR *dest, LPPROGRESS_ROUT
> if (!WriteFile( h2, p, count, &res, NULL ) || !res) goto done;
> p += res;
> count -= res;
> +
> + if (progress)
> + {
> + transferred.QuadPart += res;
> + cbret = progress( size, transferred, size, transferred, 1,
> + CALLBACK_CHUNK_FINISHED, h1, h2, param );
> + if (cbret == PROGRESS_QUIET)
> + progress = NULL;
> + else if (cbret == PROGRESS_STOP)
> + {
> + SetLastError( ERROR_REQUEST_ABORTED );
> + goto done;
> + }
> + else if (cbret == PROGRESS_CANCEL)
> + {
> + BOOLEAN disp = TRUE;
> + SetFileInformationByHandle( h2, FileDispositionInfo, &disp, sizeof(disp) );
> + SetLastError( ERROR_REQUEST_ABORTED );
> + goto done;
> + }
> + }
Surely there's a way to avoid duplicating this code.
--
Alexandre Julliard
julliard at winehq.org
More information about the wine-devel
mailing list