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

@ -39,12 +39,13 @@ Wine. All those differences are also documented on the
Included bug fixes and improvements
-----------------------------------
**Bug fixes and features included in the next upcoming release [4]:**
**Bug fixes and features included in the next upcoming release [5]:**
* Add implementation for kernel32.GetNumaProcessorNode ([Wine Bug #38660](https://bugs.winehq.org/show_bug.cgi?id=38660))
* Implement mscoree._CorValidateImage for mono runtime ([Wine Bug #38662](https://bugs.winehq.org/show_bug.cgi?id=38662))
* Implement proper handling of CLI .NET images in Wine library loader ([Wine Bug #38661](https://bugs.winehq.org/show_bug.cgi?id=38661))
* Multiple applications needs better NtQueryInformationJobObject stub ([Wine Bug #38658](https://bugs.winehq.org/show_bug.cgi?id=38658))
* Support for NtSetInformationFile class FileRenameInformation ([Wine Bug #30399](https://bugs.winehq.org/show_bug.cgi?id=30399))
**Bug fixes and features in Wine Staging 1.7.44 [236]:**

2
debian/changelog vendored
View File

@ -5,6 +5,8 @@ wine-staging (1.7.45) UNRELEASED; urgency=low
* Updated shell32-Icons patchset to fix a test failure in comctl32/imagelist.
* Updated shlwapi-AssocGetPerceivedType patchset to fix error checking for
RegGetValueW.
* Added patches for FileRenameInformation support (fixes Wine Staging Bug
#296).
* Removed patch to fix NULL pointer dereference in get_frame_by_name
(identical patch accepted upstream).
-- Sebastian Lackner <sebastian@fds-team.de> Sun, 31 May 2015 14:46:37 +0200

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,665 @@
From 4b282588eddd0aaac6889528235fa1b41a3fab76 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Tue, 2 Jun 2015 21:56:35 +0200
Subject: ntdll/tests: Add additional tests for FileRenameInformation.
---
dlls/ntdll/tests/file.c | 586 ++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 573 insertions(+), 13 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 4173166..70ee60a 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1435,20 +1435,36 @@ static void test_file_all_information(void)
CloseHandle( h );
}
+static void delete_object( WCHAR *path )
+{
+ BOOL ret;
+
+ ret = DeleteFileW( path );
+ ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_ACCESS_DENIED,
+ "DeleteFileW failed with %u\n", GetLastError() );
+ if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
+ {
+ ret = RemoveDirectoryW( path );
+ ok( ret, "RemoveDirectoryW failed with %u\n", GetLastError() );
+ }
+}
+
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];
UNICODE_STRING name_str;
- HANDLE handle;
+ HANDLE handle, handle2;
NTSTATUS res;
IO_STATUS_BLOCK io;
- PFILE_RENAME_INFORMATION pfri;
- BOOL fileDeleted;
+ FILE_RENAME_INFORMATION *pfri;
+ FILE_NAME_INFORMATION *pfni;
+ BOOL success, fileDeleted;
GetTempPathW( MAX_PATH, tmp_path );
- /* newpath doesn't exist at first */
+ /* oldpath is a file, newpath doesn't exist */
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 );
@@ -1470,19 +1486,308 @@ static void test_file_rename_information(void)
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 );
+ HeapFree( GetProcessHeap(), 0, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a file, newpath is a file, 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 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, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a file, newpath is a file, Replace = FALSE, target file opened */
+ 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" );
+ 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 );
+ 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, "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 );
+ 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, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a file, newpath is a file, 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 should exist\n" );
+
+ CloseHandle( handle );
+ HeapFree( GetProcessHeap(), 0, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a file, newpath is a file, Replace = TRUE, target file opened */
+ 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" );
+ 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 );
+ 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 == 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" );
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "File should exist\n" );
+
+ CloseHandle( handle );
+ CloseHandle( handle2 );
+ HeapFree( GetProcessHeap(), 0, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a file, newpath is a file, Replace = TRUE, target file opened with FILE_SHARE_DELETE */
+ 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" );
+ 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 );
+ 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 == 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" );
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "File should exist\n" );
+
+ CloseHandle( handle );
+ CloseHandle( handle2 );
+ HeapFree( GetProcessHeap(), 0, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a file, newpath is a file, Replace = TRUE, target file opened with FILE_SHARE_DELETE | FILE_SHARE_WRITE */
+ 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" );
+ handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0 );
+ ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\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 == 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" );
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "File should exist\n" );
+
+ CloseHandle( handle );
+ CloseHandle( handle2 );
+ HeapFree( GetProcessHeap(), 0, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a directory, newpath doesn't exist, Replace = FALSE */
+ res = GetTempFileNameW( tmp_path, foo, 0, oldpath );
+ ok( res != 0, "fail 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, 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" );
+ 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 );
HeapFree( GetProcessHeap(), 0, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a directory (but child object opened), newpath doesn't exist, Replace = FALSE */
+ res = GetTempFileNameW( tmp_path, foo, 0, oldpath );
+ ok( res != 0, "fail 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" );
+
+ lstrcpyW( newpath, oldpath );
+ lstrcatW( newpath, foo_txt );
+ handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
+ ok( handle2 != 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 );
- /* newpath exists in temp directory, Replace = false */
+ 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 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" );
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( fileDeleted, "File should not exist\n" );
+
+ CloseHandle( handle );
+ CloseHandle( handle2 );
+ HeapFree( GetProcessHeap(), 0, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a directory, newpath is a file, 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 );
+ 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, foo, 0, newpath );
@@ -1500,19 +1805,59 @@ static void test_file_rename_information(void)
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" );
+ ok( !fileDeleted, "File should exist\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
- ok( !fileDeleted, "File shouldn't have been deleted!\n" );
+ ok( !fileDeleted, "File should exist\n" );
CloseHandle( handle );
HeapFree( GetProcessHeap(), 0, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a directory, newpath is a file, Replace = FALSE, target file opened */
+ res = GetTempFileNameW( tmp_path, foo, 0, oldpath );
+ ok( res != 0, "fail to create temp file\n" );
DeleteFileW( oldpath );
- DeleteFileW( newpath );
+ 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, foo, 0, newpath );
+ ok( res != 0, "fail 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" );
- /* newpath exists in temp directory, Replace = true */
+ 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 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, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a directory, newpath is a file, 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 );
+ 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, foo, 0, newpath );
@@ -1530,14 +1875,229 @@ static void test_file_rename_information(void)
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" );
+ 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" );
+ ok( !fileDeleted, "File should exist\n" );
CloseHandle( handle );
HeapFree( GetProcessHeap(), 0, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a directory, newpath is a file, Replace = TRUE, target file opened */
+ res = GetTempFileNameW( tmp_path, foo, 0, oldpath );
+ ok( res != 0, "fail 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, foo, 0, newpath );
+ ok( res != 0, "fail 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 );
+ 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 == 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" );
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "File should exist\n" );
+
+ CloseHandle( handle );
+ CloseHandle( handle2 );
+ HeapFree( GetProcessHeap(), 0, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a directory, newpath is a directory, Replace = FALSE */
+ res = GetTempFileNameW( tmp_path, foo, 0, oldpath );
+ ok( res != 0, "fail 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, foo, 0, newpath );
+ ok( res != 0, "fail 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 );
+ 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 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, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a directory, newpath is a directory, Replace = TRUE */
+ res = GetTempFileNameW( tmp_path, foo, 0, oldpath );
+ ok( res != 0, "fail 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, foo, 0, newpath );
+ ok( res != 0, "fail 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 );
+ 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 == 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" );
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "File should exist\n" );
+
+ CloseHandle( handle );
+ HeapFree( GetProcessHeap(), 0, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a directory, newpath is a directory, Replace = TRUE, target file opened */
+ res = GetTempFileNameW( tmp_path, foo, 0, oldpath );
+ ok( res != 0, "fail 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, foo, 0, newpath );
+ ok( res != 0, "fail 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, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
+ ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\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 == 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" );
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "File should exist\n" );
+
+ CloseHandle( handle );
+ CloseHandle( handle2 );
+ HeapFree( GetProcessHeap(), 0, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a file, newpath is a 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" );
+ DeleteFileW( newpath );
+ success = CreateDirectoryW( newpath, NULL );
+ ok( success != 0, "failed to create temp directory\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 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, pfri );
+ delete_object( oldpath );
+ delete_object( newpath );
+
+ /* oldpath is a file, newpath is a 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" );
+ DeleteFileW( newpath );
+ success = CreateDirectoryW( newpath, NULL );
+ ok( success != 0, "failed to create temp directory\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 == 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" );
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
+ ok( !fileDeleted, "File should exist\n" );
+
+ CloseHandle( handle );
+ 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,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

View File

@ -1740,6 +1740,13 @@ if test "$enable_server_Stored_ACLs" -eq 1; then
enable_server_RootDirectory_File=1
fi
if test "$enable_server_RootDirectory_File" -eq 1; then
if test "$enable_ntdll_FileDispositionInformation" -gt 1; then
abort "Patchset ntdll-FileDispositionInformation disabled, but server-RootDirectory_File depends on that."
fi
enable_ntdll_FileDispositionInformation=1
fi
if test "$enable_nvencodeapi_Video_Encoder" -eq 1; then
if test "$enable_nvcuvid_CUDA_Video_Support" -gt 1; then
abort "Patchset nvcuvid-CUDA_Video_Support disabled, but nvencodeapi-Video_Encoder depends on that."
@ -2977,6 +2984,7 @@ fi
# |
# | This patchset fixes the following Wine bugs:
# | * [#30397] Support for NtSetInformationFile class FileDispositionInformation
# | * [#30399] Support for NtSetInformationFile class FileRenameInformation
# |
# | Modified files:
# | * dlls/ntdll/file.c, dlls/ntdll/tests/file.c, server/fd.c, server/file.c, server/file.h, server/protocol.def
@ -2987,12 +2995,30 @@ if test "$enable_ntdll_FileDispositionInformation" -eq 1; then
patch_apply ntdll-FileDispositionInformation/0003-server-Do-not-permit-FileDispositionInformation-to-d.patch
patch_apply ntdll-FileDispositionInformation/0004-ntdll-tests-Added-tests-to-set-disposition-on-file-w.patch
patch_apply ntdll-FileDispositionInformation/0005-server-Do-not-allow-to-set-disposition-on-file-which.patch
patch_apply ntdll-FileDispositionInformation/0006-server-Set-the-closed_fd-unix_name-shortly-before-ad.patch
patch_apply ntdll-FileDispositionInformation/0007-ntdll-tests-Add-tests-for-FileRenameInformation.patch
patch_apply ntdll-FileDispositionInformation/0008-ntdll-tests-Add-additional-tests-for-FileRenameInfor.patch
patch_apply ntdll-FileDispositionInformation/0009-ntdll-tests-Add-tests-for-FileRenameInformation-with.patch
patch_apply ntdll-FileDispositionInformation/0010-ntdll-Implement-a-hacky-version-of-FileRenameInforma.patch
patch_apply ntdll-FileDispositionInformation/0011-server-FileRenameInformation-target-cannot-be-an-exi.patch
patch_apply ntdll-FileDispositionInformation/0012-server-When-combining-root-and-name-make-sure-there-.patch
patch_apply ntdll-FileDispositionInformation/0013-server-Reject-rename-when-target-has-opened-file-han.patch
patch_apply ntdll-FileDispositionInformation/0014-server-Manually-unlink-dest-when-trying-to-replace-a.patch
(
echo '+ { "Dmitry Timoshkov", "server: Keep a pointer to parent'\''s fd unix_name in the closed_fd structure.", 1 },';
echo '+ { "Dmitry Timoshkov", "server: Add support for setting file disposition information.", 1 },';
echo '+ { "Erich E. Hoover", "server: Do not permit FileDispositionInformation to delete a file without write access.", 1 },';
echo '+ { "Qian Hong", "ntdll/tests: Added tests to set disposition on file which is mapped to memory.", 1 },';
echo '+ { "Qian Hong", "server: Do not allow to set disposition on file which has a file mapping.", 1 },';
echo '+ { "Sebastian Lackner", "server: Set the closed_fd->unix_name shortly before adding to the closed fd list.", 1 },';
echo '+ { "Jianqiu Zhang", "ntdll/tests: Add tests for FileRenameInformation.", 1 },';
echo '+ { "Sebastian Lackner", "ntdll/tests: Add additional tests for FileRenameInformation.", 1 },';
echo '+ { "Sebastian Lackner", "ntdll/tests: Add tests for FileRenameInformation with nonzero RootDir.", 1 },';
echo '+ { "Qian Hong", "ntdll: Implement a hacky version of FileRenameInformation support.", 1 },';
echo '+ { "Sebastian Lackner", "server: FileRenameInformation target cannot be an existing directory.", 1 },';
echo '+ { "Sebastian Lackner", "server: When combining root and name, make sure there is only one slash.", 1 },';
echo '+ { "Sebastian Lackner", "server: Reject rename when target has opened file handles.", 1 },';
echo '+ { "Sebastian Lackner", "server: Manually unlink dest when trying to replace a file with directory.", 1 },';
) >> "$patchlist"
fi

View File

@ -1,4 +1,4 @@
From 00cbc5646ce0153babf9f3cebf07461ffaaabaee Mon Sep 17 00:00:00 2001
From 7b50d145c867f5724e20120cd54995752279291a Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Fri, 29 May 2015 22:49:24 +0200
Subject: server: Fix handling of opening a file with RootDirectory pointing to
@ -14,7 +14,7 @@ Changes in v2:
4 files changed, 96 insertions(+), 11 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 2df0edc..f6a6154 100644
index 1f009f6..fbf9daf 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -297,7 +297,8 @@ static void create_file_test(void)
@ -101,10 +101,10 @@ index 2df0edc..f6a6154 100644
CloseHandle( file );
CloseHandle( root );
diff --git a/server/fd.c b/server/fd.c
index f0a52ad..2354b40 100644
index ae97a94..04c0e42 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1712,7 +1712,7 @@ void set_fd_user( struct fd *fd, const struct fd_ops *user_ops, struct object *u
@@ -1718,7 +1718,7 @@ void set_fd_user( struct fd *fd, const struct fd_ops *user_ops, struct object *u
fd->user = user;
}
@ -112,8 +112,8 @@ index f0a52ad..2354b40 100644
+char *dup_fd_name( struct fd *root, const char *name )
{
char *ret;
@@ -2238,14 +2238,36 @@ DECL_HANDLER(flush)
int len;
@@ -2325,14 +2325,36 @@ DECL_HANDLER(flush)
DECL_HANDLER(open_file_object)
{
struct unicode_str name;
@ -154,7 +154,7 @@ index f0a52ad..2354b40 100644
{
if ((result = obj->ops->open_file( obj, req->access, req->sharing, req->options )))
{
@@ -2254,8 +2276,6 @@ DECL_HANDLER(open_file_object)
@@ -2341,8 +2363,6 @@ DECL_HANDLER(open_file_object)
}
release_object( obj );
}
@ -164,7 +164,7 @@ index f0a52ad..2354b40 100644
/* get the Unix name from a file handle */
diff --git a/server/file.c b/server/file.c
index 792bbe0..a189465 100644
index b673bbc..56600d5 100644
--- a/server/file.c
+++ b/server/file.c
@@ -67,6 +67,8 @@ static void file_dump( struct object *obj, int verbose );
@ -212,10 +212,10 @@ index 792bbe0..a189465 100644
{
struct file *file = (struct file *)obj;
diff --git a/server/file.h b/server/file.h
index b5e0ca7..b59de1c 100644
index 460656f..47e6692 100644
--- a/server/file.h
+++ b/server/file.h
@@ -81,6 +81,7 @@ extern void unlock_fd( struct fd *fd, file_pos_t offset, file_pos_t count );
@@ -82,6 +82,7 @@ extern void unlock_fd( struct fd *fd, file_pos_t offset, file_pos_t count );
extern void allow_fd_caching( struct fd *fd );
extern void set_fd_signaled( struct fd *fd, int signaled );
extern int is_fd_signaled( struct fd *fd );

View File

@ -1 +1,2 @@
Fixes: Fix handling of opening a file with RootDirectory pointing to a file handle
Depends: ntdll-FileDispositionInformation