From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/kernel32/tests/file.c | 50 ++++++++++++++++++++++++++++++++++++++ dlls/kernelbase/file.c | 4 +-- 2 files changed, 52 insertions(+), 2 deletions(-)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 17cfe24d50a..02625140702 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -850,6 +850,56 @@ static void test_CopyFileA(void) CloseHandle(hmapfile); CloseHandle(hfile);
+ /* check read-only attribute */ + ret = GetFileAttributesA(source); + ok(ret != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA: error %ld\n", GetLastError()); + ok(!(ret & FILE_ATTRIBUTE_READONLY), "source is read-only\n"); + ret = GetFileAttributesA(dest); + ok(ret != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA: error %ld\n", GetLastError()); + ok(!(ret & FILE_ATTRIBUTE_READONLY), "dest is read-only\n"); + + /* make source read-only */ + ret = SetFileAttributesA(source, FILE_ATTRIBUTE_READONLY); + ok(ret, "SetFileAttributesA: error %ld\n", GetLastError()); + ret = GetFileAttributesA(source); + ok(ret != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA: error %ld\n", GetLastError()); + ok(ret & FILE_ATTRIBUTE_READONLY, "source is not read-only\n"); + ret = GetFileAttributesA(dest); + ok(ret != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA: error %ld\n", GetLastError()); + ok(!(ret & FILE_ATTRIBUTE_READONLY), "dest is read-only\n"); + + /* dest becomes read-only after copied from read-only source */ + ret = SetFileAttributesA(source, FILE_ATTRIBUTE_READONLY); + ok(ret, "SetFileAttributesA: error %ld\n", GetLastError()); + ret = GetFileAttributesA(source); + ok(ret != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA: error %ld\n", GetLastError()); + ok(ret & FILE_ATTRIBUTE_READONLY, "source is not read-only\n"); + ret = GetFileAttributesA(dest); + ok(ret != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA: error %ld\n", GetLastError()); + ok(!(ret & FILE_ATTRIBUTE_READONLY), "dest is read-only\n"); + + ret = CopyFileA(source, dest, FALSE); + ok(ret, "CopyFileA: error %ld\n", GetLastError()); + ret = GetFileAttributesA(dest); + ok(ret != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA: error %ld\n", GetLastError()); + ok(ret & FILE_ATTRIBUTE_READONLY, "dest is not read-only\n"); + + /* same when dest does not exist */ + ret = SetFileAttributesA(dest, FILE_ATTRIBUTE_NORMAL); + ok(ret, "SetFileAttributesA: error %ld\n", GetLastError()); + ret = DeleteFileA(dest); + ok(ret, "DeleteFileA: error %ld\n", GetLastError()); + ret = CopyFileA(source, dest, TRUE); + ok(ret, "CopyFileA: error %ld\n", GetLastError()); + ret = GetFileAttributesA(dest); + ok(ret != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA: error %ld\n", GetLastError()); + ok(ret & FILE_ATTRIBUTE_READONLY, "dest is not read-only\n"); + + ret = SetFileAttributesA(source, FILE_ATTRIBUTE_NORMAL); + ok(ret, "SetFileAttributesA: error %ld\n", GetLastError()); + ret = SetFileAttributesA(dest, FILE_ATTRIBUTE_NORMAL); + ok(ret, "SetFileAttributesA: error %ld\n", GetLastError()); + ret = DeleteFileA(source); ok(ret, "DeleteFileA: error %ld\n", GetLastError()); ret = DeleteFileA(dest); diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index e1ba92a6448..cef861492e0 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -579,8 +579,8 @@ BOOL WINAPI CopyFileExW( const WCHAR *source, const WCHAR *dest, LPPROGRESS_ROUT } ret = TRUE; done: - /* Maintain the timestamp of source file to destination file */ - info.FileAttributes = 0; + /* Maintain the timestamp of source file to destination file and read-only attribute */ + info.FileAttributes &= FILE_ATTRIBUTE_READONLY; NtSetInformationFile( h2, &io, &info, sizeof(info), FileBasicInformation ); HeapFree( GetProcessHeap(), 0, buffer ); CloseHandle( h1 );