[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