From: Joel Holdsworth <joel(a)airwebreathe.org.uk>
Signed-off-by: Joel Holdsworth <joel(a)airwebreathe.org.uk>
---
dlls/ntdll/tests/file.c | 204 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 203 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 9dd49c925b7..02050918cac 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -2185,7 +2185,7 @@ static void test_file_rename_information_ex(void)
static const WCHAR fooW[] = {'f','o','o',0};
WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16];
FILE_RENAME_INFORMATION *fri;
- BOOL fileDeleted;
+ BOOL success, fileDeleted;
UNICODE_STRING name_str;
HANDLE handle, handle2;
IO_STATUS_BLOCK io;
@@ -2276,6 +2276,208 @@ static void test_file_rename_information_ex(void)
HeapFree( GetProcessHeap(), 0, fri );
delete_object( oldpath );
delete_object( newpath );
+
+ /* oldpath is a file, newpath is a file, with FILE_RENAME_REPLACE_IF_EXISTS, with
+ * FILE_RENAME_POSIX_SEMANTICS, target file opened without sharing mode */
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+ ok( res != 0, "failed to create temp file\n" );
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0
);
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+ ok( res != 0, "failed to create temp file\n" );
+ handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0
);
+ ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+ fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) +
name_str.Length );
+ fri->Flags = FILE_RENAME_REPLACE_IF_EXISTS | FILE_RENAME_POSIX_SEMANTICS;
+ fri->RootDirectory = NULL;
+ fri->FileNameLength = name_str.Length;
+ memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+ pRtlFreeUnicodeString( &name_str );
+
+ io.Status = 0xdeadbeef;
+ res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) +
fri->FileNameLength, FileRenameInformationEx );
+ todo_wine ok( io.Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got
%lx\n", io.Status );
+ ok( res == STATUS_SHARING_VIOLATION || res == STATUS_ACCESS_DENIED,
+ "res expected STATUS_SHARING_VIOLATION or STATUS_ACCESS_DENIED, got
%lx\n", res );
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "file should exist\n" );
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "file should exist\n" );
+
+ CloseHandle( handle );
+ CloseHandle( handle2 );
+ HeapFree( GetProcessHeap(), 0, fri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a file, newpath is a file, with FILE_RENAME_REPLACE_IF_EXISTS, with
+ * FILE_RENAME_POSIX_SEMANTICS, target file opened with sharing mode */
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+ ok( res != 0, "failed to create temp file\n" );
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0
);
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+ ok( res != 0, "failed to create temp file\n" );
+ handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE,
+ NULL, CREATE_ALWAYS, 0, 0 );
+ ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+ fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) +
name_str.Length );
+ fri->Flags = FILE_RENAME_REPLACE_IF_EXISTS | FILE_RENAME_POSIX_SEMANTICS;
+ fri->RootDirectory = NULL;
+ fri->FileNameLength = name_str.Length;
+ memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+ pRtlFreeUnicodeString( &name_str );
+
+ io.Status = 0xdeadbeef;
+ res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) +
fri->FileNameLength, FileRenameInformationEx );
+ todo_wine ok( io.Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS,
got %lx\n", io.Status );
+ todo_wine ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got
%lx\n", res );
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
+ todo_wine ok( fileDeleted, "file should not exist\n" );
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "file should exist\n" );
+
+ CloseHandle( handle );
+ CloseHandle( handle2 );
+ HeapFree( GetProcessHeap(), 0, fri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a directory, newpath is a file, with FILE_RENAME_REPLACE_IF_EXISTS,
with
+ * FILE_RENAME_POSIX_SEMANTICS, target file opened */
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+ ok( res != 0, "failed to create temp file\n" );
+ DeleteFileW( oldpath );
+ success = CreateDirectoryW( oldpath, NULL );
+ ok( success != 0, "failed to create temp directory\n" );
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, 0 );
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+ ok( res != 0, "failed to create temp file\n" );
+ handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE,
+ NULL, CREATE_ALWAYS, 0, 0 );
+ ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+ fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) +
name_str.Length );
+ fri->Flags = FILE_RENAME_REPLACE_IF_EXISTS | FILE_RENAME_POSIX_SEMANTICS;
+ fri->RootDirectory = NULL;
+ fri->FileNameLength = name_str.Length;
+ memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+ pRtlFreeUnicodeString( &name_str );
+
+ io.Status = 0xdeadbeef;
+ res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) +
fri->FileNameLength, FileRenameInformationEx );
+ todo_wine ok( io.Status == STATUS_SUCCESS || io.Status == 0xdeadbeef,
+ "io.Status expected STATUS_SUCCESS or 0xdeadbeef, got %lx\n",
io.Status );
+ todo_wine ok( res == STATUS_SUCCESS || res == STATUS_NOT_A_DIRECTORY,
+ "res expected STATUS_SUCCESS or STATUS_NOT_A_DIRECTORY, got
%lx\n", res );
+
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
+ if (res == STATUS_SUCCESS)
+ ok( fileDeleted, "file should not exist\n" );
+ else if (res == STATUS_NOT_A_DIRECTORY)
+ ok( !fileDeleted, "file should exist\n" );
+
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "file should exist\n" );
+
+ CloseHandle( handle );
+ CloseHandle( handle2 );
+ HeapFree( GetProcessHeap(), 0, fri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a directory, newpath is a directory, with
FILE_RENAME_REPLACE_IF_EXISTS, with
+ * FILE_RENAME_POSIX_SEMANTICS, target file opened */
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+ ok( res != 0, "failed to create temp file\n" );
+ DeleteFileW( oldpath );
+ success = CreateDirectoryW( oldpath, NULL );
+ ok( success != 0, "failed to create temp directory\n" );
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0,
+ NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+ ok( res != 0, "failed to create temp file\n" );
+ DeleteFileW( newpath );
+ success = CreateDirectoryW( newpath, NULL );
+ ok( success != 0, "failed to create temp directory\n" );
+ handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE,
+ NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+ ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+ fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) +
name_str.Length );
+ fri->Flags = FILE_RENAME_REPLACE_IF_EXISTS | FILE_RENAME_POSIX_SEMANTICS;
+ fri->RootDirectory = NULL;
+ fri->FileNameLength = name_str.Length;
+ memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+ pRtlFreeUnicodeString( &name_str );
+
+ io.Status = 0xdeadbeef;
+ res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) +
fri->FileNameLength, FileRenameInformationEx );
+ todo_wine ok( io.Status == STATUS_SUCCESS || io.Status == 0xdeadbeef,
+ "io.Status expected STATUS_SUCCESS or 0xdeadbeef, got %lx\n",
io.Status );
+ ok( res == STATUS_SUCCESS || res == STATUS_ACCESS_DENIED,
+ "res expected STATUS_SUCCESS or STATUS_ACCESS_DENIED, got %lx\n", res
);
+
+ if (res == STATUS_SUCCESS) {
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( fileDeleted, "file should not exist\n" );
+ }
+
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "file should exist\n" );
+
+ CloseHandle( handle );
+ CloseHandle( handle2 );
+ HeapFree( GetProcessHeap(), 0, fri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a file, newpath is a directory, with FILE_RENAME_REPLACE_IF_EXISTS,
with
+ * FILE_RENAME_POSIX_SEMANTICS */
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
+ ok( res != 0, "failed to create temp file\n" );
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0
);
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
+ ok( res != 0, "failed to create temp file\n" );
+ DeleteFileW( newpath );
+ success = CreateDirectoryW( newpath, NULL );
+ ok( success != 0, "failed to create temp directory\n" );
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+ fri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) +
name_str.Length );
+ fri->Flags = FILE_RENAME_REPLACE_IF_EXISTS | FILE_RENAME_POSIX_SEMANTICS;
+ fri->RootDirectory = NULL;
+ fri->FileNameLength = name_str.Length;
+ memcpy( fri->FileName, name_str.Buffer, name_str.Length );
+ pRtlFreeUnicodeString( &name_str );
+
+ io.Status = 0xdeadbeef;
+ res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) +
fri->FileNameLength, FileRenameInformationEx );
+ todo_wine ok( io.Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got
%lx\n", io.Status );
+ ok( res == STATUS_FILE_IS_A_DIRECTORY || res == STATUS_ACCESS_DENIED,
+ "res expected STATUS_FILE_IS_A_DIRECTORY or STATUS_ACCESS_DENIED, got
%lx\n", res );
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "file should exist\n" );
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "file should exist\n" );
+
+ CloseHandle( handle );
+ HeapFree( GetProcessHeap(), 0, fri );
+ delete_object( oldpath );
+ delete_object( newpath );
}
static void test_file_link_information(FILE_INFORMATION_CLASS class)
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/4457