This reverts commit af35741d3681f21222a85900b54d95ee422fe074.
As reported on IRC by user supermario1313, and bisected by Rounin, this commit made Wine no longer follow symlinks in Z:, which the former needs for a Wine-aware sandboxing solution.
I'm not a huge fan of the test, but I like leaving things untested even less. The Correct™ solution would be CreateSymbolicLink() or FSCTL_SET_REPARSE_POINT, but they're not implemented in Wine.
From: Alfred Agrell floating@muncher.se
This reverts commit af35741d3681f21222a85900b54d95ee422fe074. --- dlls/ntdll/unix/file.c | 28 ++++++++++++++++++++++++++++ server/change.c | 2 +- server/fd.c | 16 ---------------- server/file.c | 2 +- server/file.h | 1 - 5 files changed, 30 insertions(+), 19 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 958ae9a6937..6f1fc71c4db 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -7322,6 +7322,34 @@ NTSTATUS WINAPI NtQueryObject( HANDLE handle, OBJECT_INFORMATION_CLASS info_clas case ObjectNameInformation: { OBJECT_NAME_INFORMATION *p = ptr; + char *unix_name; + WCHAR *nt_name; + + /* first try as a file object */ + + if (!(status = server_get_unix_name( handle, &unix_name ))) + { + if (!(status = unix_to_nt_file_name( unix_name, &nt_name, FILE_OPEN ))) + { + ULONG size = (wcslen(nt_name) + 1) * sizeof(WCHAR); + if (len < sizeof(*p)) status = STATUS_INFO_LENGTH_MISMATCH; + else if (len < sizeof(*p) + size) status = STATUS_BUFFER_OVERFLOW; + else + { + p->Name.Buffer = (WCHAR *)(p + 1); + p->Name.Length = size - sizeof(WCHAR); + p->Name.MaximumLength = size; + wcscpy( p->Name.Buffer, nt_name ); + } + if (used_len) *used_len = sizeof(*p) + size; + free( nt_name ); + } + free( unix_name ); + break; + } + else if (status != STATUS_OBJECT_TYPE_MISMATCH) break; + + /* not a file, treat as a generic object */
SERVER_START_REQ( get_object_name ) { diff --git a/server/change.c b/server/change.c index 5bcd0676e0d..a42ee42ffaa 100644 --- a/server/change.c +++ b/server/change.c @@ -119,7 +119,7 @@ static const struct object_ops dir_ops = default_map_access, /* map_access */ dir_get_sd, /* get_sd */ dir_set_sd, /* set_sd */ - default_fd_get_full_name, /* get_full_name */ + no_get_full_name, /* get_full_name */ no_lookup_name, /* lookup_name */ no_link_name, /* link_name */ NULL, /* unlink_name */ diff --git a/server/fd.c b/server/fd.c index c4be028845f..76f004250f1 100644 --- a/server/fd.c +++ b/server/fd.c @@ -2202,22 +2202,6 @@ struct object *default_fd_get_sync( struct object *obj ) return sync; }
-/* default get_full_name() routine for objects with an fd */ -WCHAR *default_fd_get_full_name( struct object *obj, data_size_t max, data_size_t *ret_len ) -{ - struct fd *fd = get_obj_fd( obj ); - WCHAR *ret = NULL; - - if (fd->nt_name) - { - *ret_len = fd->nt_namelen; - ret = memdup( fd->nt_name, fd->nt_namelen ); - } - release_object( fd ); - if (*ret_len > max) set_error( STATUS_BUFFER_OVERFLOW ); - return ret; -} - int default_fd_get_poll_events( struct fd *fd ) { int events = 0; diff --git a/server/file.c b/server/file.c index cc5acc2aadc..8fe0ba2230a 100644 --- a/server/file.c +++ b/server/file.c @@ -101,7 +101,7 @@ static const struct object_ops file_ops = default_map_access, /* map_access */ file_get_sd, /* get_sd */ file_set_sd, /* set_sd */ - default_fd_get_full_name, /* get_full_name */ + no_get_full_name, /* get_full_name */ file_lookup_name, /* lookup_name */ no_link_name, /* link_name */ NULL, /* unlink_name */ diff --git a/server/file.h b/server/file.h index 567194bf00a..03582434776 100644 --- a/server/file.h +++ b/server/file.h @@ -109,7 +109,6 @@ extern char *dup_fd_name( struct fd *root, const char *name ) __WINE_DEALLOC(fre extern void get_nt_name( struct fd *fd, struct unicode_str *name );
extern struct object *default_fd_get_sync( struct object *obj ); -extern WCHAR *default_fd_get_full_name( struct object *obj, data_size_t max, data_size_t *ret_len ); extern int default_fd_get_poll_events( struct fd *fd ); extern void default_poll_event( struct fd *fd, int event ); extern void fd_cancel_async( struct fd *fd, struct async *async );
From: Alfred Agrell floating@muncher.se
--- dlls/kernel32/tests/file.c | 44 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 47b8307aeda..25ef6355e13 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -5717,6 +5717,49 @@ static void test_GetFinalPathNameByHandleW(void) CloseHandle(file); }
+static void test_GetFinalPathNameByHandleW_with_symlink(void) +{ + WCHAR junction_path[MAX_PATH]; + WCHAR *userprofile_end; + DWORD attrs; + BOOL is_link; + HANDLE file; + WCHAR result_path[MAX_PATH]; + UNICODE_STRING nt_path; + + if (!pGetFinalPathNameByHandleW) + { + win_skip("GetFinalPathNameByHandleW is missing\n"); + return; + } + + GetEnvironmentVariableW(L"USERPROFILE", junction_path, sizeof(junction_path)); + userprofile_end = junction_path + wcslen(junction_path); + + wcscpy(userprofile_end, L"\My Documents"); + attrs = GetFileAttributesW(junction_path); + is_link = (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_REPARSE_POINT)); + todo_wine ok(is_link, "%s should be a junction\n", wine_dbgstr_w(junction_path)); + if (!is_link) + { + /* use another directory on Wine */ + wcscpy(userprofile_end, L"\Desktop"); + attrs = GetFileAttributesW(junction_path); + is_link = (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_REPARSE_POINT)); + ok(is_link, "%s should be a symlink on Wine\n", wine_dbgstr_w(junction_path)); + } + + file = CreateFileW(junction_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, 0); + pGetFinalPathNameByHandleW(file, result_path, sizeof(result_path), FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); + CloseHandle(file); + + pRtlDosPathNameToNtPathName_U(junction_path, &nt_path, NULL, NULL); + /* extra +4 to skip \?\ prefix, since it's ??\ instead in nt_path */ + ok(wcscmp(result_path+4, nt_path.Buffer+4) != 0, + "expected %s and %s to be different\n", wine_dbgstr_w(result_path), wine_dbgstr_w(nt_path.Buffer)); + RtlFreeUnicodeString(&nt_path); +} + static void test_SetFileInformationByHandle(void) { FILE_ATTRIBUTE_TAG_INFO fileattrinfo = { 0 }; @@ -6937,6 +6980,7 @@ START_TEST(file) test_file_access(); test_GetFinalPathNameByHandleA(); test_GetFinalPathNameByHandleW(); + test_GetFinalPathNameByHandleW_with_symlink(); test_SetFileInformationByHandle(); test_SetFileRenameInfo(); test_GetFileAttributesExW();