mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
Added patches for FileRenameInformation support (fixes Wine Staging Bug #296).
This commit is contained in:
parent
fdc5f5c1dd
commit
2923808892
@ -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
2
debian/changelog
vendored
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,2 +1,3 @@
|
||||
Fixes: [30397] Support for NtSetInformationFile class FileDispositionInformation
|
||||
Fixes: [30399] Support for NtSetInformationFile class FileRenameInformation
|
||||
Depends: server-File_Permissions
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 );
|
||||
|
@ -1 +1,2 @@
|
||||
Fixes: Fix handling of opening a file with RootDirectory pointing to a file handle
|
||||
Depends: ntdll-FileDispositionInformation
|
||||
|
Loading…
x
Reference in New Issue
Block a user