kernel32: Open replaced file without GENERIC_WRITE in ReplaceFileW().
As MSDN says, the replaced file is opened with the GENERIC_READ, DELETE, and SYNCHRONIZE access rights. If GENERIC_WRITE is added, then it will fail with previous file opens without FILE_SHARE_WRITE. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=33845 Signed-off-by: Zhiyi Zhang <zzhang@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
57e8e2d59c
commit
04ccd995b1
|
@ -1746,6 +1746,7 @@ BOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName, LPCWSTR lpReplacementFileNa
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
|
FILE_BASIC_INFORMATION info;
|
||||||
|
|
||||||
TRACE("%s %s %s 0x%08x %p %p\n", debugstr_w(lpReplacedFileName),
|
TRACE("%s %s %s 0x%08x %p %p\n", debugstr_w(lpReplacedFileName),
|
||||||
debugstr_w(lpReplacementFileName), debugstr_w(lpBackupFileName),
|
debugstr_w(lpReplacementFileName), debugstr_w(lpBackupFileName),
|
||||||
|
@ -1772,7 +1773,7 @@ BOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName, LPCWSTR lpReplacementFileNa
|
||||||
attr.SecurityDescriptor = NULL;
|
attr.SecurityDescriptor = NULL;
|
||||||
attr.SecurityQualityOfService = NULL;
|
attr.SecurityQualityOfService = NULL;
|
||||||
|
|
||||||
/* Open the "replaced" file for reading and writing */
|
/* Open the "replaced" file for reading */
|
||||||
if (!(RtlDosPathNameToNtPathName_U(lpReplacedFileName, &nt_replaced_name, NULL, NULL)))
|
if (!(RtlDosPathNameToNtPathName_U(lpReplacedFileName, &nt_replaced_name, NULL, NULL)))
|
||||||
{
|
{
|
||||||
error = ERROR_PATH_NOT_FOUND;
|
error = ERROR_PATH_NOT_FOUND;
|
||||||
|
@ -1780,7 +1781,7 @@ BOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName, LPCWSTR lpReplacementFileNa
|
||||||
}
|
}
|
||||||
replaced_flags = lpBackupFileName ? FILE_OPEN : FILE_OPEN_IF;
|
replaced_flags = lpBackupFileName ? FILE_OPEN : FILE_OPEN_IF;
|
||||||
attr.ObjectName = &nt_replaced_name;
|
attr.ObjectName = &nt_replaced_name;
|
||||||
status = NtOpenFile(&hReplaced, GENERIC_READ|GENERIC_WRITE|DELETE|SYNCHRONIZE,
|
status = NtOpenFile(&hReplaced, GENERIC_READ|DELETE|SYNCHRONIZE,
|
||||||
&attr, &io,
|
&attr, &io,
|
||||||
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
|
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
|
||||||
FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
|
FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
|
||||||
|
@ -1796,6 +1797,20 @@ BOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName, LPCWSTR lpReplacementFileNa
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Replacement should fail if replaced is READ_ONLY */
|
||||||
|
status = NtQueryInformationFile(hReplaced, &io, &info, sizeof(info), FileBasicInformation);
|
||||||
|
if (status != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
error = RtlNtStatusToDosError(status);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.FileAttributes & FILE_ATTRIBUTE_READONLY)
|
||||||
|
{
|
||||||
|
error = ERROR_ACCESS_DENIED;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open the replacement file for reading, writing, and deleting
|
* Open the replacement file for reading, writing, and deleting
|
||||||
* (writing and deleting are needed when finished)
|
* (writing and deleting are needed when finished)
|
||||||
|
|
|
@ -3691,7 +3691,7 @@ static void test_ReplaceFileA(void)
|
||||||
*/
|
*/
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0);
|
ret = pReplaceFileA(replaced, replacement, backup, 0, 0, 0);
|
||||||
todo_wine ok(ret == 0 && GetLastError() == ERROR_ACCESS_DENIED, "ReplaceFileA: unexpected error %d\n", GetLastError());
|
ok(ret == 0 && GetLastError() == ERROR_ACCESS_DENIED, "ReplaceFileA: unexpected error %d\n", GetLastError());
|
||||||
/* make sure that the replacement file still exists */
|
/* make sure that the replacement file still exists */
|
||||||
hReplacementFile = CreateFileA(replacement, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
|
hReplacementFile = CreateFileA(replacement, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
|
||||||
ok(hReplacementFile != INVALID_HANDLE_VALUE ||
|
ok(hReplacementFile != INVALID_HANDLE_VALUE ||
|
||||||
|
@ -3727,7 +3727,7 @@ static void test_ReplaceFileA(void)
|
||||||
"unexpected error, replaced file should be able to be opened %d\n", GetLastError());
|
"unexpected error, replaced file should be able to be opened %d\n", GetLastError());
|
||||||
/*Calling ReplaceFileA on an exe should succeed*/
|
/*Calling ReplaceFileA on an exe should succeed*/
|
||||||
ret = pReplaceFileA(replaced, replacement, NULL, 0, 0, 0);
|
ret = pReplaceFileA(replaced, replacement, NULL, 0, 0, 0);
|
||||||
todo_wine ok(ret, "ReplaceFileA: unexpected error %d\n", GetLastError());
|
ok(ret, "ReplaceFileA: unexpected error %d\n", GetLastError());
|
||||||
CloseHandle(hReplacedFile);
|
CloseHandle(hReplacedFile);
|
||||||
|
|
||||||
/* replace file while replacement is opened */
|
/* replace file while replacement is opened */
|
||||||
|
|
Loading…
Reference in New Issue