This series improves Wine's support for delete-on-close flag and delete disposition information on files: - adapts tests for Windows 10 - extend and fix some tests - implement some missing features in ntdll & server
-- v4: ntdll: Extend file tests about delete-on-close and disposition. ntdll: Fix share mode for some delete-on-close/delete disposition tests. ntdll: Adapt file tests on delete-on-close / delete disposition to Windows 10.
From: Eric Pouech eric.pouech@gmail.com
Fix a couple of failures on Windows 10: - it seems that attributes are no longer accessible by name after shared deletion - really looks like that shared deletion is now marked at object's name hierarchy level (see error codes have changed too)
So, - replace tests based on GetFileAttribute with testing presence of pending deletion flag (FileStandardInformation) - add Win10 error codes (and mark the Win7/8 ones as broken)
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/ntdll/tests/file.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 98d9e6b3b0a..7b6cf704971 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -2957,6 +2957,7 @@ static void test_file_disposition_information(void) NTSTATUS res; IO_STATUS_BLOCK io; FILE_DISPOSITION_INFORMATION fdi; + FILE_STANDARD_INFORMATION fsi; BOOL fileDeleted; DWORD fdi2, size; void *view; @@ -3141,18 +3142,23 @@ static void test_file_disposition_information(void) GetTempFileNameA( tmp_path, "dis", 0, buffer ); handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, 0, 0); ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" ); + res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation); + ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); + ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n"); fileDeleted = DeleteFileA( buffer ); ok( fileDeleted, "File should have been deleted\n" ); - fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND; - ok( !fileDeleted, "File shouldn't have been deleted\n" ); + res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation); + ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); + todo_wine + ok(fsi.DeletePending, "Handle should be marked for deletion\n"); res = nt_get_file_attrs( buffer, &fdi2 ); todo_wine - ok( res == STATUS_DELETE_PENDING, "got %#lx\n", res ); + ok( res == STATUS_OBJECT_NAME_NOT_FOUND || broken(res == STATUS_DELETE_PENDING), "got %#lx\n", res ); /* can't open the deleted file */ handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 0); ok( handle2 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" ); todo_wine - ok(GetLastError() == ERROR_ACCESS_DENIED, "got %lu\n", GetLastError()); + ok( GetLastError() == ERROR_FILE_NOT_FOUND || broken(GetLastError() == ERROR_ACCESS_DENIED), "got %lu\n", GetLastError()); CloseHandle( handle ); fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND; ok( fileDeleted, "File should have been deleted\n" ); @@ -3190,19 +3196,24 @@ static void test_file_disposition_information(void) ok( CreateDirectoryA( buffer, NULL ), "CreateDirectory failed\n" ); handle = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" ); + res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation); + ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); + ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n"); fileDeleted = RemoveDirectoryA( buffer ); ok( fileDeleted, "Directory should have been deleted\n" ); - fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND; - ok( !fileDeleted, "Directory shouldn't have been deleted\n" ); + res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation); + ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); + todo_wine + ok(fsi.DeletePending, "Handle should be marked for deletion\n"); res = nt_get_file_attrs( buffer, &fdi2 ); todo_wine - ok( res == STATUS_DELETE_PENDING, "got %#lx\n", res ); + ok( res == STATUS_OBJECT_NAME_NOT_FOUND || broken(res == STATUS_DELETE_PENDING), "got %#lx\n", res ); /* can't open the deleted directory */ handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); todo_wine ok( handle2 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" ); todo_wine - ok(GetLastError() == ERROR_ACCESS_DENIED, "got %lu\n", GetLastError()); + ok(GetLastError() == ERROR_FILE_NOT_FOUND || broken(GetLastError() == ERROR_ACCESS_DENIED), "got %lu\n", GetLastError()); if (handle2 != INVALID_HANDLE_VALUE) CloseHandle( handle2 ); CloseHandle( handle ); fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
From: Eric Pouech eric.pouech@gmail.com
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/ntdll/tests/file.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 7b6cf704971..2ec61f72aa9 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -3155,10 +3155,13 @@ static void test_file_disposition_information(void) todo_wine ok( res == STATUS_OBJECT_NAME_NOT_FOUND || broken(res == STATUS_DELETE_PENDING), "got %#lx\n", res ); /* can't open the deleted file */ - handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 0); + handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); + todo_wine ok( handle2 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" ); todo_wine ok( GetLastError() == ERROR_FILE_NOT_FOUND || broken(GetLastError() == ERROR_ACCESS_DENIED), "got %lu\n", GetLastError()); + if (handle2 != INVALID_HANDLE_VALUE) + CloseHandle( handle2); CloseHandle( handle ); fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND; ok( fileDeleted, "File should have been deleted\n" );
From: Eric Pouech eric.pouech@gmail.com
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/ntdll/tests/file.c | 66 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 2ec61f72aa9..6186afdfb63 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -3000,6 +3000,10 @@ static void test_file_disposition_information(void) fdi.DoDeleteFile = TRUE; res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation ); ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %lx)\n", res ); + res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation); + ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); + todo_wine + ok(fsi.DeletePending, "Handle should be marked for deletion\n"); CloseHandle( handle ); fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND; ok( fileDeleted, "File should have been deleted\n" ); @@ -3408,6 +3412,68 @@ static void test_file_disposition_information(void) res = DeleteFileA( buffer ); ok( !res, "expected failure\n" ); ok( GetLastError() == ERROR_FILE_NOT_FOUND, "got error %lu\n", GetLastError() ); + + /* pending delete flag is shared across handles */ + GetTempFileNameA( tmp_path, "dis", 0, buffer ); + handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, 0, 0); + ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" ); + res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation); + ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); + ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n"); + handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); + ok( handle2 != INVALID_HANDLE_VALUE, "failed to create temp file\n" ); + res = NtQueryInformationFile(handle2, &io, &fsi, sizeof(fsi), FileStandardInformation); + ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); + ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n"); + fdi.DoDeleteFile = TRUE; + res = NtSetInformationFile(handle, &io, &fdi, sizeof(fdi), FileDispositionInformation); + ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); + res = NtQueryInformationFile(handle2, &io, &fsi, sizeof(fsi), FileStandardInformation); + ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); + todo_wine + ok(fsi.DeletePending, "Handle should be marked for deletion\n"); + fdi.DoDeleteFile = FALSE; + res = NtSetInformationFile(handle2, &io, &fdi, sizeof(fdi), FileDispositionInformation); + ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); + res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation); + ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); + ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n"); + CloseHandle(handle); + CloseHandle(handle2); + res = GetFileAttributesA( buffer ); + todo_wine + ok( res != INVALID_FILE_ATTRIBUTES, "expected file to exist\n" ); + + /* pending delete flag is shared across handles (even after closing) */ + GetTempFileNameA( tmp_path, "dis", 0, buffer ); + handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, 0, 0); + ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" ); + res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation); + ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); + ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n"); + handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); + ok( handle2 != INVALID_HANDLE_VALUE, "failed to create temp file\n" ); + res = NtQueryInformationFile(handle2, &io, &fsi, sizeof(fsi), FileStandardInformation); + ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); + ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n"); + fdi.DoDeleteFile = TRUE; + res = NtSetInformationFile(handle, &io, &fdi, sizeof(fdi), FileDispositionInformation); + ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); + res = NtQueryInformationFile(handle2, &io, &fsi, sizeof(fsi), FileStandardInformation); + ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); + todo_wine + ok(fsi.DeletePending, "Handle should be marked for deletion\n"); + fdi.DoDeleteFile = FALSE; + res = NtSetInformationFile(handle2, &io, &fdi, sizeof(fdi), FileDispositionInformation); + ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); + CloseHandle(handle2); + res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation); + ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); + ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n"); + CloseHandle(handle); + res = GetFileAttributesA( buffer ); + todo_wine + ok( res != INVALID_FILE_ATTRIBUTES, "expected file to exist\n" ); }
static void test_file_name_information(void)
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=126305
Your paranoid android.
=== w10pro64_ja (testbot log) ===
WineRunTask.pl:error: The previous 1 run(s) terminated abnormally
v4: only keep the tests patches - removed the ntdll&server bits (as no feedback so far)