[PATCH v5] kernel32: Correct ReplaceFileW behaviour

Brock York twunknown at gmail.com
Sat Sep 8 01:09:47 CDT 2018


On Sat, Sep 08, 2018 at 10:45:16AM +0800, Dmitry Timoshkov wrote:
> Brock York <twunknown at gmail.com> wrote:
> 
> >      attr.ObjectName = &nt_replaced_name;
> > -    status = NtOpenFile(&hReplaced, GENERIC_READ|GENERIC_WRITE|DELETE|SYNCHRONIZE,
> > +    status = NtOpenFile(&hReplaced, GENERIC_READ|DELETE|SYNCHRONIZE,
> >                          &attr, &io,
> >                          FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
> >                          FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
> > @@ -1788,6 +1789,19 @@ BOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName, LPCWSTR lpReplacementFileNa
> >          goto fail;
> >      }
> >  
> > +    /* Replacement should fail if replaced is READ_ONLY */
> > +    if (!GetFileInformationByHandle(hReplaced, &file_info))
> > +    {
> > +	    error = GetLastError();
> > +	    goto fail;
> > +    }
> > +
> > +    if (file_info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
> > +    {
> > +        error = ERROR_ACCESS_DENIED;
> > +        goto fail;
> > +    }
> 
> There is an existing test for NtCreateFile that it's supposed to fail if
> the file has read-only attribute. Probably NtOpenFile with WRITE|DELETE
> access supposed to behave in a similar way. Adding such workarounds to
> high level API like ReplaceFile only clutters the code with not appropriate
> hacks.
> 
> -- 
> Dmitry.

Hello Dmitry

I had written a test to check that exact case before I implemented this
patch but it turns out that I had screwed up my test program and was
trying to NtOpenFile the wrong file...
Which made me then think that the ACCESS_DENIED was coming from the
ReplaceFileW call itself. 

The MSDN documentation for ReplaceFileW states that the replaced
file is opened with GENERIC_READ, DELETE and SYNCHRONISE.
But the next sentence after mentions that the user must have write access,
is this implying that the GENERIC_WRITE flag in passed in the like
original author of ReplaceFileW for wine had implemented or is the MSDN
probably wrong? ? If so the fix is easy modifying the check from NtOpenFile
to handle the access_denied case which you were correct that when WRITE | DELETE
is passed as the access flags to open a read only file NtOpenFile correctly returns
ACCESS_DENIED

Thanks for the good pickup and feedback.

Warm regards
Brock



More information about the wine-devel mailing list