On Sat, Sep 08, 2018 at 10:45:16AM +0800, Dmitry Timoshkov wrote:
Brock York <twunknown(a)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