ntdll-FileDispositionInformation: Cleanup of patches for File{Rename,Link}Information.

This commit is contained in:
Sebastian Lackner 2015-06-05 00:58:34 +02:00
parent 9fde9be110
commit 32c289493f
18 changed files with 371 additions and 560 deletions

View File

@ -1,4 +1,4 @@
From 48231cd898005f4c3bbb3992776d480e7eee837b Mon Sep 17 00:00:00 2001
From 47f1bcd94dab7f58cda802dd89233ee21274c9fa Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Thu, 7 Aug 2014 18:31:33 -0600
Subject: server: Keep a pointer to parent's fd unix_name in the closed_fd
@ -9,7 +9,7 @@ Subject: server: Keep a pointer to parent's fd unix_name in the closed_fd
1 file changed, 21 insertions(+), 17 deletions(-)
diff --git a/server/fd.c b/server/fd.c
index a432ec7..397e51d 100644
index 14e98ac..7c2d717 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -164,7 +164,8 @@ struct closed_fd
@ -164,5 +164,5 @@ index a432ec7..397e51d 100644
set_error( STATUS_INVALID_PARAMETER );
goto error;
--
2.4.0
2.4.2

View File

@ -1,22 +1,22 @@
From 723aef38c2549d8767bb185906cc3fc8d865b695 Mon Sep 17 00:00:00 2001
From 713c458fc172d02e041ffd04542aada8f8313880 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Thu, 7 Aug 2014 20:32:19 -0600
Subject: server: Add support for setting file disposition information.
---
dlls/ntdll/file.c | 16 ++++++++++++++++
dlls/ntdll/tests/file.c | 12 ++----------
server/fd.c | 30 ++++++++++++++++++++++++++++++
server/file.c | 23 +++++++++++++++++++++++
server/file.h | 1 +
server/protocol.def | 6 ++++++
dlls/ntdll/file.c | 16 ++++++++++++++++
dlls/ntdll/tests/file.c | 12 ++----------
server/fd.c | 30 ++++++++++++++++++++++++++++++
server/file.c | 23 +++++++++++++++++++++++
server/file.h | 1 +
server/protocol.def | 6 ++++++
6 files changed, 78 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index d2efcc1..5d59470 100644
index d081750..86063b6 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -2383,6 +2383,22 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
@@ -2765,6 +2765,22 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
else io->u.Status = STATUS_INVALID_PARAMETER_3;
break;
@ -40,10 +40,10 @@ index d2efcc1..5d59470 100644
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 d70ed6b..1606f83 100644
index 8ec367b..874aa4d 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1371,7 +1371,6 @@ static void test_file_disposition_information(void)
@@ -1471,7 +1471,6 @@ static void test_file_disposition_information(void)
ok( res == STATUS_INVALID_INFO_CLASS || res == STATUS_NOT_IMPLEMENTED, "Unexpected NtQueryInformationFile result (expected STATUS_INVALID_INFO_CLASS, got %x)\n", res );
fdi.DoDeleteFile = TRUE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
@ -51,7 +51,7 @@ index d70ed6b..1606f83 100644
ok( res == STATUS_ACCESS_DENIED, "unexpected FileDispositionInformation result (expected STATUS_ACCESS_DENIED, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1384,11 +1383,9 @@ static void test_file_disposition_information(void)
@@ -1484,11 +1483,9 @@ static void test_file_disposition_information(void)
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
fdi.DoDeleteFile = TRUE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
@ -63,7 +63,7 @@ index d70ed6b..1606f83 100644
ok( fileDeleted, "File should have been deleted\n" );
DeleteFileA( buffer );
@@ -1402,6 +1399,7 @@ static void test_file_disposition_information(void)
@@ -1502,6 +1499,7 @@ static void test_file_disposition_information(void)
ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@ -71,7 +71,7 @@ index d70ed6b..1606f83 100644
ok( !fileDeleted, "File shouldn't have been deleted\n" );
SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
DeleteFileA( buffer );
@@ -1412,11 +1410,9 @@ static void test_file_disposition_information(void)
@@ -1512,11 +1510,9 @@ static void test_file_disposition_information(void)
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
fdi.DoDeleteFile = TRUE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
@ -83,7 +83,7 @@ index d70ed6b..1606f83 100644
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1429,7 +1425,6 @@ static void test_file_disposition_information(void)
@@ -1529,7 +1525,6 @@ static void test_file_disposition_information(void)
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
fdi.DoDeleteFile = FALSE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
@ -91,7 +91,7 @@ index d70ed6b..1606f83 100644
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1444,7 +1439,6 @@ static void test_file_disposition_information(void)
@@ -1544,7 +1539,6 @@ static void test_file_disposition_information(void)
CloseHandle( handle );
fdi.DoDeleteFile = FALSE;
res = pNtSetInformationFile( handle2, &io, &fdi, sizeof fdi, FileDispositionInformation );
@ -99,7 +99,7 @@ index d70ed6b..1606f83 100644
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
CloseHandle( handle2 );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1459,11 +1453,9 @@ static void test_file_disposition_information(void)
@@ -1559,11 +1553,9 @@ static void test_file_disposition_information(void)
ok( handle != INVALID_HANDLE_VALUE, "failed to open a directory\n" );
fdi.DoDeleteFile = TRUE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
@ -111,7 +111,7 @@ index d70ed6b..1606f83 100644
ok( fileDeleted, "Directory should have been deleted\n" );
RemoveDirectoryA( buffer );
@@ -1476,7 +1468,6 @@ static void test_file_disposition_information(void)
@@ -1576,7 +1568,6 @@ static void test_file_disposition_information(void)
RemoveDirectoryA( buffer );
fdi.DoDeleteFile = FALSE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
@ -119,7 +119,7 @@ index d70ed6b..1606f83 100644
ok( res == STATUS_SUCCESS, "unexpected FileDispositionInformation result (expected STATUS_SUCCESS, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1501,6 +1492,7 @@ static void test_file_disposition_information(void)
@@ -1601,6 +1592,7 @@ static void test_file_disposition_information(void)
buffer[dirpos] = '\0';
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@ -128,10 +128,10 @@ index d70ed6b..1606f83 100644
RemoveDirectoryA( buffer );
}
diff --git a/server/fd.c b/server/fd.c
index b022a3c..7be3f4c 100644
index 7c2d717..442e639 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1921,6 +1921,36 @@ unsigned int get_fd_options( struct fd *fd )
@@ -1942,6 +1942,36 @@ unsigned int get_fd_options( struct fd *fd )
return fd->options;
}
@ -169,10 +169,10 @@ index b022a3c..7be3f4c 100644
int get_unix_fd( struct fd *fd )
{
diff --git a/server/file.c b/server/file.c
index cceb8ad..0a7da00 100644
index 792bbe0..b673bbc 100644
--- a/server/file.c
+++ b/server/file.c
@@ -728,3 +728,26 @@ DECL_HANDLER(unlock_file)
@@ -741,3 +741,26 @@ DECL_HANDLER(unlock_file)
release_object( file );
}
}
@ -200,10 +200,10 @@ index cceb8ad..0a7da00 100644
+ }
+}
diff --git a/server/file.h b/server/file.h
index 493d30b..d689d29 100644
index b5e0ca7..460656f 100644
--- a/server/file.h
+++ b/server/file.h
@@ -65,6 +65,7 @@ extern struct fd *get_fd_object_for_mapping( struct fd *fd, unsigned int access,
@@ -70,6 +70,7 @@ extern struct fd *get_fd_object_for_mapping( struct fd *fd, unsigned int access,
extern void *get_fd_user( struct fd *fd );
extern void set_fd_user( struct fd *fd, const struct fd_ops *ops, struct object *user );
extern unsigned int get_fd_options( struct fd *fd );
@ -212,10 +212,10 @@ index 493d30b..d689d29 100644
extern int is_same_file_fd( struct fd *fd1, struct fd *fd2 );
extern int is_fd_removable( struct fd *fd );
diff --git a/server/protocol.def b/server/protocol.def
index a8c1fb9..85505c8 100644
index 9c4dab4..800f73c 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1178,6 +1178,12 @@ enum server_fd_type
@@ -1200,6 +1200,12 @@ enum server_fd_type
@END
@ -229,5 +229,5 @@ index a8c1fb9..85505c8 100644
@REQ(create_socket)
unsigned int access; /* wanted access rights */
--
1.7.9.5
2.4.2

View File

@ -1,19 +1,19 @@
From ea378bcb8a0a6113178c2d42a3e8151b7f99dfb6 Mon Sep 17 00:00:00 2001
From edb8a6ab85a4c07409a8b12ffd3d5955f32e2952 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 7 Aug 2014 21:14:25 -0600
Subject: server: Do not permit FileDispositionInformation to delete a file
without write access.
---
dlls/ntdll/tests/file.c | 28 ++++++++++++++++++++++++++++
server/fd.c | 7 +++++++
dlls/ntdll/tests/file.c | 28 ++++++++++++++++++++++++++++
server/fd.c | 7 +++++++
2 files changed, 35 insertions(+)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 1606f83..05ce517 100644
index 874aa4d..1e7edc3 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1391,6 +1391,20 @@ static void test_file_disposition_information(void)
@@ -1491,6 +1491,20 @@ static void test_file_disposition_information(void)
/* cannot set disposition on readonly file */
GetTempFileNameA( tmp_path, "dis", 0, buffer );
@ -34,7 +34,7 @@ index 1606f83..05ce517 100644
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
ok( handle != INVALID_HANDLE_VALUE, "failed to create temp file\n" );
fdi.DoDeleteFile = TRUE;
@@ -1404,6 +1418,20 @@ static void test_file_disposition_information(void)
@@ -1504,6 +1518,20 @@ static void test_file_disposition_information(void)
SetFileAttributesA( buffer, FILE_ATTRIBUTE_NORMAL );
DeleteFileA( buffer );
@ -56,10 +56,10 @@ index 1606f83..05ce517 100644
GetTempFileNameA( tmp_path, "dis", 0, buffer );
handle = CreateFileA(buffer, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0);
diff --git a/server/fd.c b/server/fd.c
index 7be3f4c..37377d1 100644
index 442e639..d11d98c 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1945,6 +1945,13 @@ void set_fd_disposition( struct fd *fd, int unlink )
@@ -1966,6 +1966,13 @@ void set_fd_disposition( struct fd *fd, int unlink )
return;
}
@ -74,5 +74,5 @@ index 7be3f4c..37377d1 100644
fd->closed->unlink = 1;
else if (!(fd->options & FILE_DELETE_ON_CLOSE))
--
1.7.9.5
2.4.2

View File

@ -1,4 +1,4 @@
From 915da8ef1214b9378683e144ba18e3a185909dbf Mon Sep 17 00:00:00 2001
From 6aeab9117090d0cca99eac5fa02363722022dec0 Mon Sep 17 00:00:00 2001
From: Qian Hong <qhong@codeweavers.com>
Date: Fri, 17 Apr 2015 00:59:02 +0800
Subject: ntdll/tests: Added tests to set disposition on file which is mapped
@ -9,10 +9,10 @@ Subject: ntdll/tests: Added tests to set disposition on file which is mapped
1 file changed, 70 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 05ce517..1726546 100644
index 1e7edc3..89f70de 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1355,11 +1355,12 @@ static void test_file_disposition_information(void)
@@ -1455,11 +1455,12 @@ static void test_file_disposition_information(void)
{
char tmp_path[MAX_PATH], buffer[MAX_PATH + 16];
DWORD dirpos;
@ -26,7 +26,7 @@ index 05ce517..1726546 100644
GetTempPathA( MAX_PATH, tmp_path );
@@ -1523,6 +1524,74 @@ static void test_file_disposition_information(void)
@@ -1623,6 +1624,74 @@ static void test_file_disposition_information(void)
todo_wine
ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
RemoveDirectoryA( buffer );
@ -102,5 +102,5 @@ index 05ce517..1726546 100644
static void test_iocompletion(void)
--
2.3.5
2.4.2

View File

@ -1,4 +1,4 @@
From f32616e681bebc98e6969e142edabbd4b5cf86dd Mon Sep 17 00:00:00 2001
From a9ec2efaf7e9e8eb0440052176e79f71b615bcc8 Mon Sep 17 00:00:00 2001
From: Qian Hong <qhong@codeweavers.com>
Date: Fri, 17 Apr 2015 18:39:59 +0800
Subject: server: Do not allow to set disposition on file which has a file
@ -6,14 +6,14 @@ Subject: server: Do not allow to set disposition on file which has a file
---
dlls/ntdll/tests/file.c | 2 --
server/fd.c | 15 +++++++++++++++
2 files changed, 15 insertions(+), 2 deletions(-)
server/fd.c | 12 ++++++++++++
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 1726546..2784e9b 100644
index 89f70de..b285157 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1533,7 +1533,6 @@ static void test_file_disposition_information(void)
@@ -1633,7 +1633,6 @@ static void test_file_disposition_information(void)
ok( mapping != NULL, "failed to create file mapping\n");
fdi.DoDeleteFile = TRUE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
@ -21,7 +21,7 @@ index 1726546..2784e9b 100644
ok( res == STATUS_CANNOT_DELETE, "unexpected FileDispositionInformation result (expected STATUS_CANNOT_DELETE, got %x)\n", res );
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1567,7 +1566,6 @@ static void test_file_disposition_information(void)
@@ -1667,7 +1666,6 @@ static void test_file_disposition_information(void)
CloseHandle( mapping );
fdi.DoDeleteFile = TRUE;
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
@ -30,10 +30,10 @@ index 1726546..2784e9b 100644
CloseHandle( handle );
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
diff --git a/server/fd.c b/server/fd.c
index 036478a..90487cc 100644
index d11d98c..553d840 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1951,6 +1951,7 @@ unsigned int get_fd_options( struct fd *fd )
@@ -1946,6 +1946,7 @@ unsigned int get_fd_options( struct fd *fd )
void set_fd_disposition( struct fd *fd, int unlink )
{
struct stat st;
@ -41,21 +41,18 @@ index 036478a..90487cc 100644
if (fd->unix_fd == -1)
{
@@ -1978,6 +1979,20 @@ void set_fd_disposition( struct fd *fd, int unlink )
@@ -1973,6 +1974,17 @@ void set_fd_disposition( struct fd *fd, int unlink )
return;
}
+ LIST_FOR_EACH( ptr, &fd->inode->open )
+ {
+ struct fd *fd_ptr = LIST_ENTRY( ptr, struct fd, inode_entry );
+ if (fd_ptr != fd)
+ if (fd_ptr != fd && fd_ptr->access & FILE_MAPPING_ACCESS)
+ {
+ if (fd_ptr->access & FILE_MAPPING_ACCESS)
+ {
+ /* can't unlink files which are mapped to memory */
+ set_error( STATUS_CANNOT_DELETE );
+ return;
+ }
+ /* can't unlink files which are mapped to memory */
+ set_error( STATUS_CANNOT_DELETE );
+ return;
+ }
+ }
+
@ -63,5 +60,5 @@ index 036478a..90487cc 100644
fd->closed->unlink = 1;
else if (!(fd->options & FILE_DELETE_ON_CLOSE))
--
2.3.5
2.4.2

View File

@ -1,4 +1,4 @@
From 946c9589b4e5b38401f8fd4922725b5c64a54da2 Mon Sep 17 00:00:00 2001
From 3e1665a8196e64bc6f28e7ba91f7bf056fc2b2b0 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.
@ -8,7 +8,7 @@ Subject: ntdll/tests: Add tests for FileRenameInformation.
1 file changed, 106 insertions(+)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 8aa6ee2..4173166 100644
index b285157..aced150 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1435,6 +1435,111 @@ static void test_file_all_information(void)
@ -123,7 +123,7 @@ index 8aa6ee2..4173166 100644
static void test_file_both_information(void)
{
IO_STATUS_BLOCK io;
@@ -2923,6 +3028,7 @@ START_TEST(file)
@@ -3001,6 +3106,7 @@ START_TEST(file)
test_file_name_information();
test_file_full_size_information();
test_file_all_name_information();

View File

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

View File

@ -1,4 +1,4 @@
From 4b282588eddd0aaac6889528235fa1b41a3fab76 Mon Sep 17 00:00:00 2001
From 1de9ca4809416c9b3264bdc784cd66b3546d056c 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.
@ -8,7 +8,7 @@ Subject: ntdll/tests: Add additional tests for FileRenameInformation.
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
index aced150..f20319d 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1435,20 +1435,36 @@ static void test_file_all_information(void)

View File

@ -1,4 +1,4 @@
From 4ea4a5d47019daecf77bf03f477b4b23ede6f561 Mon Sep 17 00:00:00 2001
From 9e4a613237ff1c43f335a1cc8525439ce45f8c3e 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
@ -9,7 +9,7 @@ Subject: ntdll/tests: Add tests for FileRenameInformation with nonzero
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
index f20319d..a0aae0a 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1453,7 +1453,7 @@ static void test_file_rename_information(void)

View File

@ -1,15 +1,15 @@
From 8efe01bbe1fbfdc40bbe97f8f779ded0f252cc6c Mon Sep 17 00:00:00 2001
From: Qian Hong <qhong@codeweavers.com>
From 526d905701f6d27f38cce701f36f6280f7c2c6cf Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Tue, 2 Jun 2015 01:56:24 +0800
Subject: ntdll: Implement a hacky version of FileRenameInformation support.
Subject: ntdll: Implement FileRenameInformation support.
Contains various improvements by Sebastian Lackner <sebastian@fds-team.de>.
Based on a patch by Qian Hong.
---
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(-)
dlls/ntdll/file.c | 42 +++++++++++++++++++++
dlls/ntdll/tests/file.c | 80 +++++++++++++++++++++-------------------
server/fd.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++
server/protocol.def | 9 +++++
4 files changed, 192 insertions(+), 37 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 86063b6..6aa46f4 100644
@ -65,7 +65,7 @@ index 86063b6..6aa46f4 100644
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
index a0aae0a..941cc0c 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1483,19 +1483,19 @@ static void test_file_rename_information(void)
@ -126,33 +126,33 @@ index 5fdf4bf..a2d7184 100644
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)
@@ -1619,7 +1619,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 );
- 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" );
+ 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)
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1653,7 +1653,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 );
- 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" );
+ 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)
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1687,7 +1687,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 );
- 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" );
+ 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" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -1721,19 +1721,19 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
@ -220,6 +220,29 @@ index 5fdf4bf..a2d7184 100644
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;
@@ -1872,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" );
@@ -1909,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;
@@ -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 );
@ -229,24 +252,24 @@ index 5fdf4bf..a2d7184 100644
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)
@@ -1982,7 +1988,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 );
- 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" );
+ 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)
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -2021,7 +2027,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 );
- 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" );
+ 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" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -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 );
@ -256,6 +279,15 @@ index 5fdf4bf..a2d7184 100644
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;
@@ -2088,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;
@@ -2121,12 +2127,12 @@ static void test_file_rename_information(void)
U(io).Status = 0xdeadbeef;
@ -274,10 +306,91 @@ index 5fdf4bf..a2d7184 100644
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
index 553d840..d4e5321 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2488,3 +2488,56 @@ DECL_HANDLER(add_fd_completion)
@@ -1991,6 +1991,80 @@ void set_fd_disposition( struct fd *fd, int unlink )
fd->closed->unlink = 0;
}
+/* rename a file */
+static void rename_fd( struct fd *fd, struct fd *root, const char *nameptr, data_size_t len )
+{
+ struct inode *inode;
+ struct stat st;
+ char *name;
+
+ if (!fd->unix_name)
+ {
+ set_error( STATUS_OBJECT_TYPE_MISMATCH );
+ return;
+ }
+ if (!(name = mem_alloc( len + 1 ))) return NULL;
+ memcpy( name, nameptr, len );
+ name[len] = 0;
+
+ if (root)
+ {
+ char *combined_name = dup_fd_name( root, name );
+ if (!combined_name)
+ {
+ set_error( STATUS_NO_MEMORY );
+ goto failed;
+ }
+ free( name );
+ name = combined_name;
+ }
+
+ if (stat( name, &st ))
+ goto do_rename;
+
+ if (!S_ISREG( st.st_mode ))
+ {
+ /* can't replace directories or special files */
+ set_error( STATUS_ACCESS_DENIED );
+ goto failed;
+ }
+
+ if ((inode = get_inode( st.st_dev, st.st_ino, -1 )))
+ {
+ int is_empty = list_empty( &inode->open );
+ release_object( inode );
+ if (!is_empty)
+ {
+ /* can't replace an opened file */
+ set_error( STATUS_ACCESS_DENIED );
+ goto failed;
+ }
+ }
+
+ /* unix rename() doesn't automatically replace files with directories */
+ if (fd->unix_fd != -1 && !fstat( fd->unix_fd, &st ) &&
+ S_ISDIR( st.st_mode ) && unlink( name ))
+ {
+ file_set_error();
+ goto failed;
+ }
+
+do_rename:
+ if (rename( fd->unix_name, name ))
+ {
+ file_set_error();
+ goto failed;
+ }
+
+ free( fd->unix_name );
+ fd->unix_name = name;
+ fd->closed->unix_name = name;
+ return;
+
+failed:
+ free( name );
+}
+
/* retrieve the unix fd for an object */
int get_unix_fd( struct fd *fd )
{
@@ -2484,3 +2558,27 @@ DECL_HANDLER(add_fd_completion)
release_object( fd );
}
}
@ -285,54 +398,25 @@ index ad974bb..ae61f27 100644
+/* rename file */
+DECL_HANDLER(rename_file)
+{
+ struct fd *root_fd = NULL;
+ 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;
+ if (!(root = get_dir_obj( current->process, req->rootdir, 0 ))) return;
+ root_fd = get_obj_fd( (struct object *)root );
+ release_object( root );
+ if (!root_fd) return;
+ }
+
+ /* 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 );
+ rename_fd( fd, root_fd, get_req_data(), get_req_data_size() );
+ release_object( fd );
+ }
+
+ free( path );
+ if (root_fd) release_object( root_fd );
+}
diff --git a/server/protocol.def b/server/protocol.def
index 800f73c..431d2b9 100644

View File

@ -1,4 +1,4 @@
From 9aadb3326ac73489928af85a43ddefd07b6fefb8 Mon Sep 17 00:00:00 2001
From d0201524cc9fcc78997ae699995bb192f37b78d1 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
@ -12,7 +12,7 @@ Changes in v2:
2 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 6710b3a..fbcee9b 100644
index 941cc0c..8072a15 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -2138,8 +2138,8 @@ static void test_file_rename_information(void)
@ -27,10 +27,10 @@ index 6710b3a..fbcee9b 100644
CloseHandle( handle );
diff --git a/server/fd.c b/server/fd.c
index f162346..b46753e 100644
index d4e5321..4b0bf47 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
@@ -1720,6 +1720,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;
@ -38,7 +38,7 @@ index f162346..b46753e 100644
if (!root) return strdup( name );
if (!root->unix_name) return NULL;
@@ -1728,11 +1729,18 @@ static char *dup_fd_name( struct fd *root, const char *name )
@@ -1727,11 +1728,18 @@ static char *dup_fd_name( struct fd *root, const char *name )
/* skip . prefix */
if (name[0] == '.' && (!name[1] || name[1] == '/')) name++;

View File

@ -1,4 +1,4 @@
From b4838252600fd8b4325b1a7d5753a84df40ef131 Mon Sep 17 00:00:00 2001
From 5a4985d6c6748fef78e69367848569e69d46c13f Mon Sep 17 00:00:00 2001
From: Zhaonan Liang <bt2517@126.com>
Date: Tue, 28 Apr 2015 19:06:31 +0800
Subject: include: Add declaration for FILE_LINK_INFORMATION.

View File

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

View File

@ -1,4 +1,4 @@
From 3049a4cb5eaa0e35e2ce1621a4c090c1fdc13a57 Mon Sep 17 00:00:00 2001
From e8f81b0c785cf349fcfee69b9dcdfe42ee9020d5 Mon Sep 17 00:00:00 2001
From: Qian Hong <qhong@codeweavers.com>
Date: Wed, 3 Jun 2015 17:41:59 +0800
Subject: ntdll/tests: Add tests for FileLinkInformation class.

View File

@ -1,24 +1,35 @@
From eb0a9708ab107897cb41a20299f530a8d7bddb4c Mon Sep 17 00:00:00 2001
From 0777c89085c995e4160750c12bdd0afd68eecafb Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 3 Jun 2015 17:04:23 +0200
Subject: server: Implement support for FileLinkInformation class in
NtSetInformationFile.
---
dlls/ntdll/file.c | 42 ++++++++++++++++++++++++++
dlls/ntdll/tests/file.c | 54 ++++++++++++++++-----------------
server/fd.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++-
server/protocol.def | 8 +++++
4 files changed, 155 insertions(+), 28 deletions(-)
dlls/ntdll/file.c | 44 ++++++++++++++++++++++++++++++++++++++++
dlls/ntdll/tests/file.c | 54 ++++++++++++++++++++++++-------------------------
server/fd.c | 47 ++++++++++++++++++++++++++++--------------
server/protocol.def | 3 ++-
4 files changed, 105 insertions(+), 43 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 6aa46f4..1e27afb 100644
index 6aa46f4..f5f2458 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -2823,6 +2823,48 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
else io->u.Status = STATUS_INVALID_PARAMETER_3;
break;
@@ -2813,6 +2813,50 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
{
req->handle = wine_server_obj_handle( handle );
req->rootdir = wine_server_obj_handle( attr.RootDirectory );
+ req->link = FALSE;
+ 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;
+
+ case FileLinkInformation:
+ if (len >= sizeof(FILE_LINK_INFORMATION))
+ {
@ -47,23 +58,14 @@ index 6aa46f4..1e27afb 100644
+ break;
+ }
+
+ SERVER_START_REQ( link_file )
+ 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;
+ req->link = TRUE;
wine_server_add_data( req, unix_name.Buffer, unix_name.Length );
io->u.Status = wine_server_call( req );
}
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index c985a03..92613d5 100644
--- a/dlls/ntdll/tests/file.c
@ -262,118 +264,118 @@ index c985a03..92613d5 100644
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 0234fc0..4729170 100644
index 4b0bf47..db299dd 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2561,7 +2561,6 @@ DECL_HANDLER(rename_file)
goto out;
}
}
-
if (rename( fd->unix_name, path ))
file_set_error();
else
@@ -2578,3 +2577,81 @@ out:
free( path );
@@ -1999,8 +1999,8 @@ void set_fd_disposition( struct fd *fd, int unlink )
fd->closed->unlink = 0;
}
-/* rename a file */
-static void rename_fd( struct fd *fd, struct fd *root, const char *nameptr, data_size_t len )
+/* rename or link a file */
+static void rename_fd( struct fd *fd, struct fd *root, const char *nameptr, data_size_t len, int do_link )
{
struct inode *inode;
struct stat st;
@@ -2027,8 +2027,16 @@ static void rename_fd( struct fd *fd, struct fd *root, const char *nameptr, data
name = combined_name;
}
+ if (do_link && fd->unix_fd != -1 &&
+ !fstat( fd->unix_fd, &st ) && S_ISDIR( st.st_mode ))
+ {
+ /* when creating a hard link, source must be a file */
+ set_error( STATUS_FILE_IS_A_DIRECTORY );
+ goto failed;
+ }
+
+/* create hardlink - FIXME: merge with rename_file */
+DECL_HANDLER(link_file)
+{
+ struct fd *fd;
+ char *path;
+
+ if (!(path = mem_alloc( get_req_data_size() + 1 )))
if (stat( name, &st ))
- goto do_rename;
+ goto skip_checks;
if (!S_ISREG( st.st_mode ))
{
@@ -2049,25 +2057,34 @@ static void rename_fd( struct fd *fd, struct fd *root, const char *nameptr, data
}
}
+ /* unix link() doesn't succeed when the target already exists */
/* unix rename() doesn't automatically replace files with directories */
- if (fd->unix_fd != -1 && !fstat( fd->unix_fd, &st ) &&
- S_ISDIR( st.st_mode ) && unlink( name ))
+ if ((do_link || (fd->unix_fd != -1 && !fstat( fd->unix_fd, &st ) &&
+ S_ISDIR( st.st_mode ))) && unlink( name ))
{
file_set_error();
goto failed;
}
-do_rename:
- if (rename( fd->unix_name, name ))
+skip_checks:
+ if (do_link)
{
- file_set_error();
- goto failed;
+ if (link( fd->unix_name, name ))
+ file_set_error();
}
+ else
+ {
+ if (rename( fd->unix_name, name ))
+ {
+ file_set_error();
+ goto failed;
+ }
- free( fd->unix_name );
- fd->unix_name = name;
- fd->closed->unix_name = name;
- return;
+ free( fd->unix_name );
+ fd->unix_name = name;
+ fd->closed->unix_name = name;
+ 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;
+ }
+
+ /* create a hardlink */
+ if ((fd = get_handle_fd_obj( current->process, req->handle, 0 )))
+ {
+ if (fd->unix_name)
+ {
+ struct stat st;
+ if (fd->unix_fd != -1 && !fstat( fd->unix_fd, &st ) && S_ISDIR( st.st_mode ))
+ {
+ set_error( STATUS_FILE_IS_A_DIRECTORY );
+ goto out;
+ }
+ 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 (unlink( path ))
+ {
+ file_set_error();
+ goto out;
+ }
+ }
+ if (link( fd->unix_name, path ))
+ file_set_error();
+ }
+ else set_error( STATUS_OBJECT_TYPE_MISMATCH );
+out:
+ release_object( fd );
+ }
+
+ free( path );
+}
failed:
free( name );
@@ -2567,7 +2584,7 @@ DECL_HANDLER(add_fd_completion)
}
}
-/* rename file */
+/* rename or link a file */
DECL_HANDLER(rename_file)
{
struct fd *root_fd = NULL;
@@ -2584,7 +2601,7 @@ DECL_HANDLER(rename_file)
if ((fd = get_handle_fd_obj( current->process, req->handle, 0 )))
{
- rename_fd( fd, root_fd, get_req_data(), get_req_data_size() );
+ rename_fd( fd, root_fd, get_req_data(), get_req_data_size(), req->link );
release_object( fd );
}
diff --git a/server/protocol.def b/server/protocol.def
index 431d2b9..1b7814b 100644
index 431d2b9..c2c4221 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1215,6 +1215,14 @@ enum server_fd_type
@@ -1207,10 +1207,11 @@ enum server_fd_type
@END
+/* Create a hardlink */
+@REQ(link_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 */
-/* Rename a file */
+/* Rename or link a file */
@REQ(rename_file)
obj_handle_t handle; /* handle to the file */
obj_handle_t rootdir; /* root directory */
+ int link; /* link instead of renaming */
VARARG(unix_name,string); /* file name */
@END
--
2.4.2

View File

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

View File

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

View File

@ -3030,33 +3030,25 @@ 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
patch_apply ntdll-FileDispositionInformation/0015-include-Add-declaration-for-FILE_LINK_INFORMATION.patch
patch_apply ntdll-FileDispositionInformation/0016-ntdll-tests-Add-tests-for-FileLinkInformation-class.patch
patch_apply ntdll-FileDispositionInformation/0017-server-Implement-support-for-FileLinkInformation-cla.patch
patch_apply ntdll-FileDispositionInformation/0006-ntdll-tests-Add-tests-for-FileRenameInformation.patch
patch_apply ntdll-FileDispositionInformation/0007-ntdll-tests-Add-additional-tests-for-FileRenameInfor.patch
patch_apply ntdll-FileDispositionInformation/0008-ntdll-tests-Add-tests-for-FileRenameInformation-with.patch
patch_apply ntdll-FileDispositionInformation/0009-ntdll-Implement-FileRenameInformation-support.patch
patch_apply ntdll-FileDispositionInformation/0010-server-When-combining-root-and-name-make-sure-there-.patch
patch_apply ntdll-FileDispositionInformation/0011-include-Add-declaration-for-FILE_LINK_INFORMATION.patch
patch_apply ntdll-FileDispositionInformation/0012-ntdll-tests-Add-tests-for-FileLinkInformation-class.patch
patch_apply ntdll-FileDispositionInformation/0013-server-Implement-support-for-FileLinkInformation-cla.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", "ntdll: Implement FileRenameInformation support.", 1 },';
echo '+ { "Sebastian Lackner", "server: When combining root and name, make sure there is only one slash.", 2 },';
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 },';
echo '+ { "Zhaonan Liang", "include: Add declaration for FILE_LINK_INFORMATION.", 1 },';
echo '+ { "Qian Hong", "ntdll/tests: Add tests for FileLinkInformation class.", 1 },';
echo '+ { "Sebastian Lackner", "server: Implement support for FileLinkInformation class in NtSetInformationFile.", 1 },';