Rebase against 5ccc463a4e3ba181b96a161c3c8cd4bc0cb0e607.

This commit is contained in:
Sebastian Lackner
2015-08-21 16:54:56 +02:00
parent 1dc5f2f601
commit f3b30373fb
9 changed files with 13 additions and 1353 deletions

View File

@ -1,4 +1,4 @@
From 4c33b67050e2dc88ab8f1e08f4b2559132a50262 Mon Sep 17 00:00:00 2001
From b4eabfd0a1eaca783c6a0fe35de8b1166412f078 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,10 +12,10 @@ 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 99aaa37..d1055e8 100644
index 440cfaa..40c932b 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -2068,8 +2068,8 @@ static void test_file_rename_information(void)
@@ -2111,8 +2111,8 @@ static void test_file_rename_information(void)
res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
@ -27,18 +27,18 @@ index 99aaa37..d1055e8 100644
CloseHandle( handle );
diff --git a/server/fd.c b/server/fd.c
index 04891e7..c0b5548 100644
index b30ae11..07e0fc5 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -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 *dup_fd_name( struct fd *root, const char *name )
{
char *ret;
+ int len;
if (!root) return strdup( name );
if (!root->unix_name) return NULL;
@@ -1727,11 +1728,18 @@ static char *dup_fd_name( struct fd *root, const char *name )
@@ -1727,11 +1728,18 @@ char *dup_fd_name( struct fd *root, const char *name )
/* skip . prefix */
if (name[0] == '.' && (!name[1] || name[1] == '/')) name++;

View File

@ -1,344 +0,0 @@
From 33b20afef41c75ec5fb2407ec226daef12039c97 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 | 44 ++++++++++++++++++++++++++++++++++++++++
dlls/ntdll/tests/file.c | 54 ++++++++++++++++++++++++-------------------------
server/fd.c | 25 +++++++++++++++++++----
server/protocol.def | 1 +
4 files changed, 93 insertions(+), 31 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 3cef11b..be6b591 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -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))
+ {
+ FILE_LINK_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->RootDirectory;
+ 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->ReplaceIfExists && io->u.Status == STATUS_SUCCESS)
+ {
+ RtlFreeAnsiString( &unix_name );
+ io->u.Status = STATUS_OBJECT_NAME_COLLISION;
+ break;
+ }
+
+ SERVER_START_REQ( set_fd_name_info )
+ {
+ req->handle = wine_server_obj_handle( handle );
+ req->rootdir = wine_server_obj_handle( attr.RootDirectory );
+ 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 177c2c5..5b3db09 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -2113,12 +2113,12 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
- 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;
ok( !fileDeleted, "file should 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" );
fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
@@ -2152,7 +2152,7 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
+ ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, 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;
@@ -2185,7 +2185,7 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
+ ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, 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;
@@ -2215,8 +2215,8 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
- 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;
ok( !fileDeleted, "file should exist\n" );
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
@@ -2249,7 +2249,7 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
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 );
+ 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;
@@ -2283,7 +2283,7 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
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 );
+ 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;
@@ -2317,7 +2317,7 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
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 );
+ 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;
@@ -2352,7 +2352,7 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
todo_wine ok( U(io).Status == 0xdeadbeef , "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
- todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+ ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, 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;
@@ -2399,7 +2399,7 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
- todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+ ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, 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;
@@ -2433,8 +2433,8 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
- "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+ ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
+ "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, 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;
@@ -2470,8 +2470,8 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
- "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+ ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
+ "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, 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;
@@ -2505,7 +2505,7 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
- todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+ ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, 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;
@@ -2541,7 +2541,7 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
- todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+ ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, 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;
@@ -2578,8 +2578,8 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
- "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+ ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
+ "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, 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;
@@ -2615,7 +2615,7 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
- todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+ ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, 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;
@@ -2654,7 +2654,7 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
- todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
+ ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, 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;
@@ -2688,7 +2688,7 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
+ ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, 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;
@@ -2721,7 +2721,7 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
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 );
+ 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;
@@ -2754,12 +2754,12 @@ static void test_file_link_information(void)
U(io).Status = 0xdeadbeef;
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
- 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;
ok( !fileDeleted, "file should 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" );
fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
diff --git a/server/fd.c b/server/fd.c
index c0b5548..94489e7 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2275,7 +2275,7 @@ static void set_fd_disposition( struct fd *fd, int unlink )
}
/* set new name for the fd */
-static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, data_size_t len )
+static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, data_size_t len, int do_link )
{
struct inode *inode;
struct stat st;
@@ -2307,6 +2307,14 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da
name = combined_name;
}
+ /* when creating a hard link, source must be a file */
+ if (do_link && fd->unix_fd != -1 &&
+ !fstat( fd->unix_fd, &st ) && S_ISDIR( st.st_mode ))
+ {
+ set_error( STATUS_FILE_IS_A_DIRECTORY );
+ goto failed;
+ }
+
if (!stat( name, &st ))
{
/* can't replace directories or special files */
@@ -2328,15 +2336,24 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da
}
}
+ /* link() expects that the target doesn't exist */
/* rename() cannot 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;
}
}
+ if (do_link)
+ {
+ if (link( fd->unix_name, name ))
+ file_set_error();
+ free( name );
+ return;
+ }
+
if (rename( fd->unix_name, name ))
{
file_set_error();
@@ -2576,7 +2593,7 @@ DECL_HANDLER(set_fd_name_info)
if ((fd = get_handle_fd_obj( current->process, req->handle, 0 )))
{
- set_fd_name( fd, root_fd, get_req_data(), get_req_data_size() );
+ set_fd_name( fd, root_fd, get_req_data(), get_req_data_size(), req->link );
release_object( fd );
}
if (root_fd) release_object( root_fd );
diff --git a/server/protocol.def b/server/protocol.def
index d3ff4b7..c313006 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3536,6 +3536,7 @@ enum coords_relative
@REQ(set_fd_name_info)
obj_handle_t handle; /* handle to a file or directory */
obj_handle_t rootdir; /* root directory */
+ int link; /* link instead of renaming */
VARARG(filename,string); /* new file name */
@END
--
2.5.0

View File

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