Added patches for FileRenameInformation support (fixes Wine Staging Bug #296).

This commit is contained in:
Sebastian Lackner
2015-06-03 03:04:46 +02:00
parent fdc5f5c1dd
commit 2923808892
15 changed files with 1602 additions and 11 deletions

View File

@@ -0,0 +1,43 @@
From 2679e91c82514d2f2d90374a06588601498c1baa Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 3 Jun 2015 02:46:57 +0200
Subject: server: Set the closed_fd->unix_name shortly before adding to the
closed fd list.
---
server/fd.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/server/fd.c b/server/fd.c
index cc6425c..ad974bb 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1473,6 +1473,7 @@ static void fd_destroy( struct object *obj )
if (fd->poll_index != -1) remove_poll_user( fd, fd->poll_index );
if (fd->inode)
{
+ fd->closed->unix_name = fd->unix_name;
inode_add_closed_fd( fd->inode, fd->closed );
release_object( fd->inode );
}
@@ -1667,7 +1668,7 @@ struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sha
}
closed->unix_fd = fd->unix_fd;
closed->unlink = 0;
- closed->unix_name = fd->unix_name;
+ closed->unix_name = NULL;
fd->closed = closed;
fd->inode = (struct inode *)grab_object( orig->inode );
list_add_head( &fd->inode->open, &fd->inode_entry );
@@ -1838,7 +1839,7 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
closed_fd->unix_fd = fd->unix_fd;
closed_fd->unlink = 0;
- closed_fd->unix_name = fd->unix_name;
+ closed_fd->unix_name = NULL;
if (do_chmod) fchmod( fd->unix_fd, *mode );
fstat( fd->unix_fd, &st );
--
2.4.2

View File

@@ -0,0 +1,136 @@
From 946c9589b4e5b38401f8fd4922725b5c64a54da2 Mon Sep 17 00:00:00 2001
From: Jianqiu Zhang <zhangjianqiu_133@yeah.net>
Date: Thu, 14 May 2015 20:18:52 +0800
Subject: ntdll/tests: Add tests for FileRenameInformation.
---
dlls/ntdll/tests/file.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 106 insertions(+)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 8aa6ee2..4173166 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1435,6 +1435,111 @@ static void test_file_all_information(void)
CloseHandle( h );
}
+static void test_file_rename_information(void)
+{
+ static const WCHAR foo[] = {'f','o','o',0};
+ WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16];
+ UNICODE_STRING name_str;
+ HANDLE handle;
+ NTSTATUS res;
+ IO_STATUS_BLOCK io;
+ PFILE_RENAME_INFORMATION pfri;
+ BOOL fileDeleted;
+
+ GetTempPathW( MAX_PATH, tmp_path );
+
+ /* newpath doesn't exist at first */
+ res = GetTempFileNameW( tmp_path, foo, 0, oldpath );
+ ok( res != 0, "fail 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, foo, 0, newpath );
+ ok( res != 0, "fail to create temp file\n" );
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+ DeleteFileW( newpath );
+ pfri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+ pfri->Replace = FALSE;
+ pfri->RootDir = NULL;
+ pfri->FileNameLength = name_str.Length;
+ memcpy( pfri->FileName, name_str.Buffer, name_str.Length );
+ pRtlFreeUnicodeString( &name_str );
+
+ U(io).Status = 0xdeadbeef;
+ res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
+ todo_wine ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
+ todo_wine ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+ todo_wine ok( fileDeleted, "File should have been deleted\n" );
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+ todo_wine ok( !fileDeleted, "File should exist\n" );
+
+ CloseHandle( handle );
+ HeapFree( GetProcessHeap(), 0, pfri );
+ DeleteFileW( oldpath );
+ DeleteFileW( newpath );
+
+ /* newpath exists in temp directory, Replace = false */
+ res = GetTempFileNameW( tmp_path, foo, 0, oldpath );
+ ok( res != 0, "fail 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, foo, 0, newpath );
+ ok( res != 0, "fail to create temp file\n" );
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+ pfri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+ pfri->Replace = FALSE;
+ pfri->RootDir = NULL;
+ pfri->FileNameLength = name_str.Length;
+ memcpy( pfri->FileName, name_str.Buffer, name_str.Length );
+ pRtlFreeUnicodeString( &name_str );
+
+ U(io).Status = 0xdeadbeef;
+ res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
+ todo_wine ok( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileRenameInformation, io.Status is %x\n", U(io).Status );
+ todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION, "expect STATUS_OBJECT_NAME_COLLISION, res is %x\n", res );
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "File shouldn't have been deleted!\n" );
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "File shouldn't have been deleted!\n" );
+
+ CloseHandle( handle );
+ HeapFree( GetProcessHeap(), 0, pfri );
+ DeleteFileW( oldpath );
+ DeleteFileW( newpath );
+
+ /* newpath exists in temp directory, Replace = true */
+ res = GetTempFileNameW( tmp_path, foo, 0, oldpath );
+ ok( res != 0, "fail 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, foo, 0, newpath );
+ ok( res != 0, "fail to create temp file\n" );
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
+ pfri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + name_str.Length );
+ pfri->Replace = TRUE;
+ pfri->RootDir = NULL;
+ pfri->FileNameLength = name_str.Length;
+ memcpy( pfri->FileName, name_str.Buffer, name_str.Length );
+ pRtlFreeUnicodeString( &name_str );
+
+ U(io).Status = 0xdeadbeef;
+ res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
+ todo_wine ok( U(io).Status == STATUS_SUCCESS, "io.Status expect STATUS_SUCCESS, io.Status is %x\n", U(io).Status );
+ todo_wine ok( res == STATUS_SUCCESS, "res expect STATUS_SUCCESS, res is %x\n", res );
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+ todo_wine ok( fileDeleted, "File should have been deleted!\n" );
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "File shouldn't have been deleted!\n" );
+
+ CloseHandle( handle );
+ HeapFree( GetProcessHeap(), 0, pfri );
+ DeleteFileW( oldpath );
+ DeleteFileW( newpath );
+}
+
static void test_file_both_information(void)
{
IO_STATUS_BLOCK io;
@@ -2923,6 +3028,7 @@ START_TEST(file)
test_file_name_information();
test_file_full_size_information();
test_file_all_name_information();
+ test_file_rename_information();
test_file_disposition_information();
test_query_volume_information_file();
test_query_attribute_information_file();
--
2.4.2

View File

@@ -0,0 +1,76 @@
From 4ea4a5d47019daecf77bf03f477b4b23ede6f561 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 3 Jun 2015 00:50:18 +0200
Subject: ntdll/tests: Add tests for FileRenameInformation with nonzero
RootDir.
---
dlls/ntdll/tests/file.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 44 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 70ee60a..5fdf4bf 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1453,7 +1453,7 @@ static void test_file_rename_information(void)
{
static const WCHAR foo_txt[] = {'\\','f','o','o','.','t','x','t',0};
static const WCHAR foo[] = {'f','o','o',0};
- WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16];
+ WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
UNICODE_STRING name_str;
HANDLE handle, handle2;
NTSTATUS res;
@@ -2098,6 +2098,49 @@ static void test_file_rename_information(void)
HeapFree( GetProcessHeap(), 0, pfri );
delete_object( oldpath );
delete_object( newpath );
+
+ /* oldpath is a file, newpath doesn't exist, test with RootDir != NULL */
+ res = GetTempFileNameW( tmp_path, foo, 0, oldpath );
+ ok( res != 0, "fail 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, foo, 0, newpath );
+ ok( res != 0, "fail to create temp file\n" );
+ DeleteFileW( newpath );
+ for (filename = newpath, p = newpath; *p; p++)
+ if (*p == '\\') filename = p + 1;
+ handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+ ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
+
+ pfri = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_RENAME_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
+ pfri->Replace = FALSE;
+ pfri->RootDir = handle2;
+ pfri->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
+ memcpy( pfri->FileName, filename, pfri->FileNameLength );
+
+ U(io).Status = 0xdeadbeef;
+ res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
+ todo_wine ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
+ todo_wine ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\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;
+ todo_wine ok( !fileDeleted, "File should exist\n" );
+
+ pfni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
+ res = pNtQueryInformationFile( handle, &io, pfni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
+ ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+ pfni->FileName[ pfni->FileNameLength / sizeof(WCHAR) ] = 0;
+ todo_wine ok( !lstrcmpW(pfni->FileName, newpath + 2), "FileName expected %s, got %s\n",
+ wine_dbgstr_w(newpath + 2), wine_dbgstr_w(pfni->FileName) );
+ HeapFree( GetProcessHeap(), 0, pfni );
+
+ CloseHandle( handle );
+ CloseHandle( handle2 );
+ HeapFree( GetProcessHeap(), 0, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
}
static void test_file_both_information(void)
--
2.4.2

View File

@@ -0,0 +1,359 @@
From 8efe01bbe1fbfdc40bbe97f8f779ded0f252cc6c Mon Sep 17 00:00:00 2001
From: Qian Hong <qhong@codeweavers.com>
Date: Tue, 2 Jun 2015 01:56:24 +0800
Subject: ntdll: Implement a hacky version of FileRenameInformation support.
Contains various improvements by Sebastian Lackner <sebastian@fds-team.de>.
---
dlls/ntdll/file.c | 42 +++++++++++++++++++++++++++++
dlls/ntdll/tests/file.c | 70 +++++++++++++++++++++++++++----------------------
server/fd.c | 53 +++++++++++++++++++++++++++++++++++++
server/protocol.def | 9 +++++++
4 files changed, 142 insertions(+), 32 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 86063b6..6aa46f4 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -2781,6 +2781,48 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
io->u.Status = STATUS_INVALID_PARAMETER_3;
break;
+ case FileRenameInformation:
+ if (len >= sizeof(FILE_RENAME_INFORMATION))
+ {
+ FILE_RENAME_INFORMATION *info = ptr;
+ UNICODE_STRING name_str;
+ OBJECT_ATTRIBUTES attr;
+ ANSI_STRING unix_name;
+
+ name_str.Buffer = info->FileName;
+ name_str.Length = info->FileNameLength;
+ name_str.MaximumLength = info->FileNameLength + sizeof(WCHAR);
+
+ attr.Length = sizeof(attr);
+ attr.ObjectName = &name_str;
+ attr.RootDirectory = info->RootDir;
+ attr.Attributes = OBJ_CASE_INSENSITIVE;
+
+ io->u.Status = nt_to_unix_file_name_attr( &attr, &unix_name, FILE_OPEN_IF );
+ if (io->u.Status != STATUS_SUCCESS && io->u.Status != STATUS_NO_SUCH_FILE)
+ break;
+
+ if (!info->Replace && io->u.Status == STATUS_SUCCESS)
+ {
+ RtlFreeAnsiString( &unix_name );
+ io->u.Status = STATUS_OBJECT_NAME_COLLISION;
+ break;
+ }
+
+ SERVER_START_REQ( rename_file )
+ {
+ req->handle = wine_server_obj_handle( handle );
+ req->rootdir = wine_server_obj_handle( attr.RootDirectory );
+ wine_server_add_data( req, unix_name.Buffer, unix_name.Length );
+ io->u.Status = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+
+ RtlFreeAnsiString( &unix_name );
+ }
+ else io->u.Status = STATUS_INVALID_PARAMETER_3;
+ break;
+
default:
FIXME("Unsupported class (%d)\n", class);
io->u.Status = STATUS_NOT_IMPLEMENTED;
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 5fdf4bf..a2d7184 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1483,19 +1483,19 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
- todo_wine ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
- todo_wine ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+ ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
+ ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- todo_wine ok( fileDeleted, "File should not exist\n" );
+ ok( fileDeleted, "File should not exist\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- todo_wine ok( !fileDeleted, "File should exist\n" );
+ ok( !fileDeleted, "File should exist\n" );
pfni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
res = pNtQueryInformationFile( handle, &io, pfni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
pfni->FileName[ pfni->FileNameLength / sizeof(WCHAR) ] = 0;
- todo_wine ok( !lstrcmpW(pfni->FileName, newpath + 2), "FileName expected %s, got %s\n",
- wine_dbgstr_w(newpath + 2), wine_dbgstr_w(pfni->FileName) );
+ ok( !lstrcmpW(pfni->FileName, newpath + 2), "FileName expected %s, got %s\n",
+ wine_dbgstr_w(newpath + 2), wine_dbgstr_w(pfni->FileName) );
HeapFree( GetProcessHeap(), 0, pfni );
CloseHandle( handle );
@@ -1522,7 +1522,7 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileRenameInformation, io.Status is %x\n", U(io).Status );
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION, "expect STATUS_OBJECT_NAME_COLLISION, res is %x\n", res );
+ ok( res == STATUS_OBJECT_NAME_COLLISION, "expect STATUS_OBJECT_NAME_COLLISION, res is %x\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;
@@ -1555,7 +1555,7 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expect 0xdeadbeef, io.Status is %x\n", U(io).Status );
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION, "res expect STATUS_OBJECT_NAME_COLLISION, res is %x\n", res );
+ ok( res == STATUS_OBJECT_NAME_COLLISION, "res expect STATUS_OBJECT_NAME_COLLISION, res is %x\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;
@@ -1585,10 +1585,10 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
- todo_wine ok( U(io).Status == STATUS_SUCCESS, "io.Status expect STATUS_SUCCESS, io.Status is %x\n", U(io).Status );
- todo_wine ok( res == STATUS_SUCCESS, "res expect STATUS_SUCCESS, res is %x\n", res );
+ ok( U(io).Status == STATUS_SUCCESS, "io.Status expect STATUS_SUCCESS, io.Status is %x\n", U(io).Status );
+ ok( res == STATUS_SUCCESS, "res expect STATUS_SUCCESS, res is %x\n", res );
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- todo_wine ok( fileDeleted, "File should have been deleted\n" );
+ ok( fileDeleted, "File should have been deleted\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "File should exist\n" );
@@ -1621,7 +1621,7 @@ static void test_file_rename_information(void)
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expect 0xdeadbeef, io.Status is %x\n", U(io).Status );
todo_wine ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\n", res );
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- ok( !fileDeleted, "File should exist\n" );
+ todo_wine ok( !fileDeleted, "File should exist\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "File should exist\n" );
@@ -1655,7 +1655,7 @@ static void test_file_rename_information(void)
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expect 0xdeadbeef, io.Status is %x\n", U(io).Status );
todo_wine ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\n", res );
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- ok( !fileDeleted, "File should exist\n" );
+ todo_wine ok( !fileDeleted, "File should exist\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "File should exist\n" );
@@ -1689,7 +1689,7 @@ static void test_file_rename_information(void)
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expect 0xdeadbeef, io.Status is %x\n", U(io).Status );
todo_wine ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\n", res );
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- ok( !fileDeleted, "File should exist\n" );
+ todo_wine ok( !fileDeleted, "File should exist\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "File should exist\n" );
@@ -1721,19 +1721,19 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
- todo_wine ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
- todo_wine ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+ ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
+ ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- todo_wine ok( fileDeleted, "File should have been deleted\n" );
+ ok( fileDeleted, "File should have been deleted\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- todo_wine ok( !fileDeleted, "File should exist\n" );
+ ok( !fileDeleted, "File should exist\n" );
pfni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
res = pNtQueryInformationFile( handle, &io, pfni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
pfni->FileName[ pfni->FileNameLength / sizeof(WCHAR) ] = 0;
- todo_wine ok( !lstrcmpW(pfni->FileName, newpath + 2), "FileName expected %s, got %s\n",
- wine_dbgstr_w(newpath + 2), wine_dbgstr_w(pfni->FileName) );
+ ok( !lstrcmpW(pfni->FileName, newpath + 2), "FileName expected %s, got %s\n",
+ wine_dbgstr_w(newpath + 2), wine_dbgstr_w(pfni->FileName) );
HeapFree( GetProcessHeap(), 0, pfni );
CloseHandle( handle );
@@ -1771,14 +1771,20 @@ static void test_file_rename_information(void)
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- ok( !fileDeleted, "File should exist\n" );
+ todo_wine ok( !fileDeleted, "File should exist\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- ok( fileDeleted, "File should not exist\n" );
+ todo_wine ok( fileDeleted, "File should not exist\n" );
CloseHandle( handle );
CloseHandle( handle2 );
HeapFree( GetProcessHeap(), 0, pfri );
delete_object( oldpath );
+ if (res == STATUS_SUCCESS) /* remove when wine is fixed */
+ {
+ lstrcpyW( oldpath, newpath );
+ lstrcatW( oldpath, foo_txt );
+ delete_object( oldpath );
+ }
delete_object( newpath );
/* oldpath is a directory, newpath is a file, Replace = FALSE */
@@ -1803,7 +1809,7 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileRenameInformation, io.Status is %x\n", U(io).Status );
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION, "expect STATUS_OBJECT_NAME_COLLISION, res is %x\n", res );
+ ok( res == STATUS_OBJECT_NAME_COLLISION, "expect STATUS_OBJECT_NAME_COLLISION, res is %x\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;
@@ -1839,7 +1845,7 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileRenameInformation, io.Status is %x\n", U(io).Status );
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION, "expect STATUS_OBJECT_NAME_COLLISION, res is %x\n", res );
+ ok( res == STATUS_OBJECT_NAME_COLLISION, "expect STATUS_OBJECT_NAME_COLLISION, res is %x\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;
@@ -1946,7 +1952,7 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileRenameInformation, io.Status is %x\n", U(io).Status );
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION, "expect STATUS_OBJECT_NAME_COLLISION, res is %x\n", res );
+ ok( res == STATUS_OBJECT_NAME_COLLISION, "expect STATUS_OBJECT_NAME_COLLISION, res is %x\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;
@@ -1984,7 +1990,7 @@ static void test_file_rename_information(void)
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expect 0xdeadbeef, io.Status is %x\n", U(io).Status );
todo_wine ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\n", res );
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- ok( !fileDeleted, "File should exist\n" );
+ todo_wine ok( !fileDeleted, "File should exist\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "File should exist\n" );
@@ -2023,7 +2029,7 @@ static void test_file_rename_information(void)
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expect 0xdeadbeef, io.Status is %x\n", U(io).Status );
todo_wine ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\n", res );
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- ok( !fileDeleted, "File should exist\n" );
+ todo_wine ok( !fileDeleted, "File should exist\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "File should exist\n" );
@@ -2055,7 +2061,7 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "shouldn't be able to set FileRenameInformation, io.Status is %x\n", U(io).Status );
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION, "expect STATUS_OBJECT_NAME_COLLISION, res is %x\n", res );
+ ok( res == STATUS_OBJECT_NAME_COLLISION, "expect STATUS_OBJECT_NAME_COLLISION, res is %x\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;
@@ -2121,12 +2127,12 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
- todo_wine ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
- todo_wine ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
+ ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
+ ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- todo_wine ok( fileDeleted, "File should not exist\n" );
+ ok( fileDeleted, "File should not exist\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- todo_wine ok( !fileDeleted, "File should exist\n" );
+ ok( !fileDeleted, "File should exist\n" );
pfni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
res = pNtQueryInformationFile( handle, &io, pfni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
diff --git a/server/fd.c b/server/fd.c
index ad974bb..ae61f27 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2488,3 +2488,56 @@ DECL_HANDLER(add_fd_completion)
release_object( fd );
}
}
+
+/* rename file */
+DECL_HANDLER(rename_file)
+{
+ struct fd *fd;
+ char *path;
+
+ if (!(path = mem_alloc( get_req_data_size() + 1 )))
+ return;
+ memcpy( path, get_req_data(), get_req_data_size() );
+ path[ get_req_data_size() ] = 0;
+
+ /* handle rootdir */
+ if (req->rootdir)
+ {
+ char *combined_path = NULL;
+ struct dir *root;
+ if ((root = get_dir_obj( current->process, req->rootdir, 0 )))
+ {
+ struct fd *root_fd;
+ if ((root_fd = get_obj_fd( (struct object *)root )))
+ {
+ combined_path = dup_fd_name( root_fd, path );
+ release_object( root_fd );
+ }
+ release_object( root );
+ }
+
+ if (!combined_path) return;
+ free( path );
+ path = combined_path;
+ }
+
+ /* do the rename */
+ if ((fd = get_handle_fd_obj( current->process, req->handle, 0 )))
+ {
+ if (fd->unix_name)
+ {
+ if (rename( fd->unix_name, path ))
+ file_set_error();
+ else
+ {
+ free( fd->unix_name );
+ fd->unix_name = path;
+ path = NULL;
+ }
+ }
+ else set_error( STATUS_OBJECT_TYPE_MISMATCH );
+ release_object( fd );
+ }
+
+ free( path );
+}
diff --git a/server/protocol.def b/server/protocol.def
index 800f73c..431d2b9 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1206,6 +1206,15 @@ enum server_fd_type
int unlink; /* whether to unlink file on close */
@END
+
+/* Rename a file */
+@REQ(rename_file)
+ obj_handle_t handle; /* handle to the file */
+ obj_handle_t rootdir; /* root directory */
+ VARARG(unix_name,string); /* file name */
+@END
+
+
/* Create a socket */
@REQ(create_socket)
unsigned int access; /* wanted access rights */
--
2.4.2

View File

@@ -0,0 +1,66 @@
From c11a0a4e007badd714f500da3899a88ab363e51a Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 3 Jun 2015 01:26:54 +0200
Subject: server: FileRenameInformation target cannot be an existing directory.
---
dlls/ntdll/tests/file.c | 10 +++++-----
server/fd.c | 5 ++++-
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index a2d7184..6710b3a 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1988,9 +1988,9 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expect 0xdeadbeef, io.Status is %x\n", U(io).Status );
- todo_wine ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\n", res );
+ ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\n", res );
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- todo_wine ok( !fileDeleted, "File should exist\n" );
+ ok( !fileDeleted, "File should exist\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "File should exist\n" );
@@ -2027,9 +2027,9 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expect 0xdeadbeef, io.Status is %x\n", U(io).Status );
- todo_wine ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\n", res );
+ ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\n", res );
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- todo_wine ok( !fileDeleted, "File should exist\n" );
+ ok( !fileDeleted, "File should exist\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "File should exist\n" );
@@ -2094,7 +2094,7 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expect 0xdeadbeef, io.Status is %x\n", U(io).Status );
- todo_wine ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\n", res );
+ ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\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;
diff --git a/server/fd.c b/server/fd.c
index ae61f27..f162346 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2526,7 +2526,10 @@ DECL_HANDLER(rename_file)
{
if (fd->unix_name)
{
- if (rename( fd->unix_name, path ))
+ struct stat st;
+ if (!stat( path, &st ) && !S_ISREG( st.st_mode ))
+ set_error( STATUS_ACCESS_DENIED );
+ else if (rename( fd->unix_name, path ))
file_set_error();
else
{
--
2.4.2

View File

@@ -0,0 +1,60 @@
From 9c41d7fd597e32552fa8ea4b9c1f754abfb719f8 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 3 Jun 2015 01:37:34 +0200
Subject: server: When combining root and name, make sure there is only one
slash.
---
dlls/ntdll/tests/file.c | 4 ++--
server/fd.c | 12 ++++++++----
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 6710b3a..fbcee9b 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -2138,8 +2138,8 @@ static void test_file_rename_information(void)
res = pNtQueryInformationFile( handle, &io, pfni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
pfni->FileName[ pfni->FileNameLength / sizeof(WCHAR) ] = 0;
- todo_wine ok( !lstrcmpW(pfni->FileName, newpath + 2), "FileName expected %s, got %s\n",
- wine_dbgstr_w(newpath + 2), wine_dbgstr_w(pfni->FileName) );
+ ok( !lstrcmpW(pfni->FileName, newpath + 2), "FileName expected %s, got %s\n",
+ wine_dbgstr_w(newpath + 2), wine_dbgstr_w(pfni->FileName) );
HeapFree( GetProcessHeap(), 0, pfni );
CloseHandle( handle );
diff --git a/server/fd.c b/server/fd.c
index f162346..c261397 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1721,6 +1721,7 @@ void set_fd_user( struct fd *fd, const struct fd_ops *user_ops, struct object *u
static char *dup_fd_name( struct fd *root, const char *name )
{
char *ret;
+ int len;
if (!root) return strdup( name );
if (!root->unix_name) return NULL;
@@ -1728,11 +1729,14 @@ static char *dup_fd_name( struct fd *root, const char *name )
/* skip . prefix */
if (name[0] == '.' && (!name[1] || name[1] == '/')) name++;
- if ((ret = malloc( strlen(root->unix_name) + strlen(name) + 2 )))
+ len = strlen( root->unix_name );
+ if ((ret = malloc( len + strlen(name) + 2 )))
{
- strcpy( ret, root->unix_name );
- if (name[0] && name[0] != '/') strcat( ret, "/" );
- strcat( ret, name );
+ memcpy( ret, root->unix_name, len );
+ while (len && ret[len - 1] == '/') len--;
+ while (name[0] == '/') name++;
+ strcpy( ret + len + 1, name );
+ ret[ len ] = '/';
}
return ret;
}
--
2.4.2

View File

@@ -0,0 +1,105 @@
From c39f1e2c924271c262aef89202bec0a4593134af Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 3 Jun 2015 02:03:07 +0200
Subject: server: Reject rename when target has opened file handles.
---
dlls/ntdll/tests/file.c | 14 +++++++-------
server/fd.c | 25 ++++++++++++++++++++++---
2 files changed, 29 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index fbcee9b..f60b287 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1619,9 +1619,9 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expect 0xdeadbeef, io.Status is %x\n", U(io).Status );
- todo_wine ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\n", res );
+ ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\n", res );
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- todo_wine ok( !fileDeleted, "File should exist\n" );
+ ok( !fileDeleted, "File should exist\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "File should exist\n" );
@@ -1653,9 +1653,9 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expect 0xdeadbeef, io.Status is %x\n", U(io).Status );
- todo_wine ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\n", res );
+ ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\n", res );
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- todo_wine ok( !fileDeleted, "File should exist\n" );
+ ok( !fileDeleted, "File should exist\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "File should exist\n" );
@@ -1687,9 +1687,9 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expect 0xdeadbeef, io.Status is %x\n", U(io).Status );
- todo_wine ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\n", res );
+ ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\n", res );
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- todo_wine ok( !fileDeleted, "File should exist\n" );
+ ok( !fileDeleted, "File should exist\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "File should exist\n" );
@@ -1915,7 +1915,7 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expect 0xdeadbeef, io.Status is %x\n", U(io).Status );
- todo_wine ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\n", res );
+ ok( res == STATUS_ACCESS_DENIED, "res expect STATUS_ACCESS_DENIED, res is %x\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;
diff --git a/server/fd.c b/server/fd.c
index c261397..719b95f 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2531,9 +2531,27 @@ DECL_HANDLER(rename_file)
if (fd->unix_name)
{
struct stat st;
- if (!stat( path, &st ) && !S_ISREG( st.st_mode ))
- set_error( STATUS_ACCESS_DENIED );
- else if (rename( fd->unix_name, path ))
+ if (!stat( path, &st ))
+ {
+ struct inode *inode;
+ if (!S_ISREG( st.st_mode ))
+ {
+ set_error( STATUS_ACCESS_DENIED );
+ goto out;
+ }
+ if ((inode = get_inode( st.st_dev, st.st_ino, -1 )))
+ {
+ int is_empty = list_empty( &inode->open );
+ release_object( inode );
+ if (!is_empty)
+ {
+ set_error( STATUS_ACCESS_DENIED );
+ goto out;
+ }
+ }
+ }
+
+ if (rename( fd->unix_name, path ))
file_set_error();
else
{
@@ -2543,6 +2561,7 @@ DECL_HANDLER(rename_file)
}
}
else set_error( STATUS_OBJECT_TYPE_MISMATCH );
+out:
release_object( fd );
}
--
2.4.2

View File

@@ -0,0 +1,50 @@
From 0df467329be9b32d8dadc93230e89629d465511f Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 3 Jun 2015 02:57:21 +0200
Subject: server: Manually unlink dest when trying to replace a file with
directory.
---
dlls/ntdll/tests/file.c | 6 +++---
server/fd.c | 7 +++++++
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index f60b287..1f009f6 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1878,10 +1878,10 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, pfri, sizeof(FILE_RENAME_INFORMATION) + pfri->FileNameLength, FileRenameInformation );
- todo_wine ok( U(io).Status == STATUS_SUCCESS, "io.Status expect STATUS_SUCCESS, io.Status is %x\n", U(io).Status );
- todo_wine ok( res == STATUS_SUCCESS, "res expect STATUS_SUCCESS, res is %x\n", res );
+ ok( U(io).Status == STATUS_SUCCESS, "io.Status expect STATUS_SUCCESS, io.Status is %x\n", U(io).Status );
+ ok( res == STATUS_SUCCESS, "res expect STATUS_SUCCESS, res is %x\n", res );
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- todo_wine ok( fileDeleted, "File should have been deleted\n" );
+ ok( fileDeleted, "File should have been deleted\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
ok( !fileDeleted, "File should exist\n" );
diff --git a/server/fd.c b/server/fd.c
index 719b95f..ae97a94 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2549,6 +2549,13 @@ DECL_HANDLER(rename_file)
goto out;
}
}
+
+ if (fd->unix_fd != -1 && !fstat( fd->unix_fd, &st ) &&
+ S_ISDIR( st.st_mode ) && unlink( path ))
+ {
+ file_set_error();
+ goto out;
+ }
}
if (rename( fd->unix_name, path ))
--
2.4.2

View File

@@ -1,2 +1,3 @@
Fixes: [30397] Support for NtSetInformationFile class FileDispositionInformation
Fixes: [30399] Support for NtSetInformationFile class FileRenameInformation
Depends: server-File_Permissions