From 8e5c8cc63b57dbe9b2cf2ff075c12648845b22fa Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Sat, 8 May 2021 15:13:53 -0500 Subject: [PATCH] ntdll-Junction_Points: Updates from Erich E. Hoover. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50770 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50804 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50878 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51059 --- ...-support-for-junction-point-creation.patch | 30 +-- ...-support-for-reading-junction-points.patch | 50 +++-- ...support-for-deleting-junction-points.patch | 33 ++-- ...est-for-junction-point-advertisement.patch | 8 +- ...rt-for-deleting-junction-points-with.patch | 16 +- ...l32-Advertise-junction-point-support.patch | 18 +- ...upport-for-absolute-symlink-creation.patch | 60 +++--- ...upport-for-reading-absolute-symlinks.patch | 44 +++-- ...ll-Add-support-for-deleting-symlinks.patch | 20 +- ...upport-for-relative-symlink-creation.patch | 42 ++--- ...upport-for-reading-relative-symlinks.patch | 24 +-- ...-ntdll-Add-support-for-file-symlinks.patch | 22 +-- ...tion-of-dangling-reparse-points-to-n.patch | 23 +-- ...-report-file-symbolic-links-as-files.patch | 41 ++-- ...rt-FILE_FLAG_OPEN_REPARSE_POINT-for-.patch | 8 +- ...ement-FILE_OPEN_REPARSE_POINT-option.patch | 102 ++++++++-- ...file_times_precise-to-work-on-repars.patch | 34 ++-- ...roperly-handle-file-symlink-deletion.patch | 18 +- ...ly-handle-deleting-dangling-symlinks.patch | 14 +- ...ILE_OPEN_REPARSE_POINT-in-RemoveDire.patch | 8 +- ...ort-symbolic-links-as-containing-zer.patch | 34 ++-- ...ntdll-Find-dangling-symlinks-quickly.patch | 4 +- ...taining-information-about-a-symlink.patch} | 36 ++-- ...h-no-data-for-NtReadFile-on-reparse.patch} | 18 +- ...parse-point-properties-in-fd_get_fil.patch | 101 ++++++++++ ...ort-for-FileAttributeTagInformation.patch} | 34 ++-- ...t-CreateSymbolicLink-A-W-with-ntdll.patch} | 8 +- ...Add-reparse-support-to-FindNextFile.patch} | 41 ++-- ...rse-point-type-in-directory-listing.patch} | 4 +- ...parse-point-properties-in-fd_get_fil.patch | 169 ----------------- ...e-point-target-in-directory-listing.patch} | 4 +- ...dd-junction-point-support-to-mklink.patch} | 10 +- ...ly-handle-renames-involving-symlinks.patch | 12 +- ...ILE_OPEN_REPARSE_POINT-in-MoveFileWi.patch | 8 +- ...ILE_OPEN_REPARSE_POINT-in-DeleteFile.patch | 8 +- ...decoded-unix-symlinks-as-NT-symlinks.patch | 114 ----------- ...coded-unix-symlinks-as-WSL-Linux-Uni.patch | 178 ++++++++++++++++++ ...ort-for-creating-Unix-Linux-symlinks.patch | 156 +++++++++++++++ ...ine-prefix-from-reparse-point-paths.patch} | 8 +- ...r-to-reparse-point-paths-to-indicat.patch} | 10 +- ...solute-reparse-point-targets-if-the.patch} | 90 ++++----- patches/patchinstall.sh | 31 +-- 42 files changed, 960 insertions(+), 733 deletions(-) rename patches/ntdll-Junction_Points/{0028-server-Fix-obtaining-information-about-a-symlink.patch => 0023-server-Fix-obtaining-information-about-a-symlink.patch} (81%) rename patches/ntdll-Junction_Points/{0029-ntdll-Succeed-with-no-data-for-NtReadFile-on-reparse.patch => 0024-ntdll-Succeed-with-no-data-for-NtReadFile-on-reparse.patch} (84%) create mode 100644 patches/ntdll-Junction_Points/0025-ntdll-Support-reparse-point-properties-in-fd_get_fil.patch rename patches/ntdll-Junction_Points/{0031-ntdll-Add-support-for-FileAttributeTagInformation.patch => 0026-ntdll-Add-support-for-FileAttributeTagInformation.patch} (66%) rename patches/ntdll-Junction_Points/{0023-kernel32-Implement-CreateSymbolicLink-A-W-with-ntdll.patch => 0027-kernel32-Implement-CreateSymbolicLink-A-W-with-ntdll.patch} (99%) rename patches/ntdll-Junction_Points/{0024-kernel32-Add-reparse-support-to-FindNextFile.patch => 0028-kernel32-Add-reparse-support-to-FindNextFile.patch} (57%) rename patches/ntdll-Junction_Points/{0025-wcmd-Display-reparse-point-type-in-directory-listing.patch => 0029-wcmd-Display-reparse-point-type-in-directory-listing.patch} (96%) delete mode 100644 patches/ntdll-Junction_Points/0030-ntdll-Support-reparse-point-properties-in-fd_get_fil.patch rename patches/ntdll-Junction_Points/{0026-wcmd-Show-reparse-point-target-in-directory-listing.patch => 0030-wcmd-Show-reparse-point-target-in-directory-listing.patch} (97%) rename patches/ntdll-Junction_Points/{0027-wcmd-Add-junction-point-support-to-mklink.patch => 0031-wcmd-Add-junction-point-support-to-mklink.patch} (93%) delete mode 100644 patches/ntdll-Junction_Points/0035-ntdll-Treat-undecoded-unix-symlinks-as-NT-symlinks.patch create mode 100644 patches/ntdll-Junction_Points/0035-ntdll-Treat-undecoded-unix-symlinks-as-WSL-Linux-Uni.patch create mode 100644 patches/ntdll-Junction_Points/0036-ntdll-Add-support-for-creating-Unix-Linux-symlinks.patch rename patches/ntdll-Junction_Points/{0036-ntdll-Strip-the-wine-prefix-from-reparse-point-paths.patch => 0037-ntdll-Strip-the-wine-prefix-from-reparse-point-paths.patch} (86%) rename patches/ntdll-Junction_Points/{0037-ntdll-Add-a-marker-to-reparse-point-paths-to-indicat.patch => 0038-ntdll-Add-a-marker-to-reparse-point-paths-to-indicat.patch} (85%) rename patches/ntdll-Junction_Points/{0038-server-Rewrite-absolute-reparse-point-targets-if-the.patch => 0039-server-Rewrite-absolute-reparse-point-targets-if-the.patch} (61%) diff --git a/patches/ntdll-Junction_Points/0001-ntdll-Add-support-for-junction-point-creation.patch b/patches/ntdll-Junction_Points/0001-ntdll-Add-support-for-junction-point-creation.patch index 9453749f..f12f4699 100644 --- a/patches/ntdll-Junction_Points/0001-ntdll-Add-support-for-junction-point-creation.patch +++ b/patches/ntdll-Junction_Points/0001-ntdll-Add-support-for-junction-point-creation.patch @@ -1,4 +1,4 @@ -From 719f4d5ab7ba2b2e9f3797dfce0370fa5cba5a66 Mon Sep 17 00:00:00 2001 +From a83181801d5248f7e228810bfe0a829a81be345f Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Thu, 16 Jan 2014 20:56:49 -0700 Subject: [PATCH] ntdll: Add support for junction point creation. @@ -14,10 +14,10 @@ Signed-off-by: Erich E. Hoover create mode 100644 include/ntifs.h diff --git a/configure.ac b/configure.ac -index ce6bad68f68..11f57d13274 100644 +index 71991bd3938..7553b22e76d 100644 --- a/configure.ac +++ b/configure.ac -@@ -2218,6 +2218,8 @@ AC_CHECK_FUNCS(\ +@@ -2219,6 +2219,8 @@ AC_CHECK_FUNCS(\ proc_pidinfo \ pwrite \ readlink \ @@ -27,7 +27,7 @@ index ce6bad68f68..11f57d13274 100644 setproctitle \ setprogname \ diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index 498da270a34..792c07b0d8e 100644 +index 2c1835e3ff0..54e06a3f126 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -38,6 +38,7 @@ @@ -38,7 +38,7 @@ index 498da270a34..792c07b0d8e 100644 #ifndef IO_COMPLETION_ALL_ACCESS #define IO_COMPLETION_ALL_ACCESS 0x001F0003 -@@ -5152,6 +5153,105 @@ static void test_mailslot_name(void) +@@ -5233,6 +5234,105 @@ static void test_mailslot_name(void) CloseHandle( device ); } @@ -144,7 +144,7 @@ index 498da270a34..792c07b0d8e 100644 START_TEST(file) { HMODULE hkernel32 = GetModuleHandleA("kernel32.dll"); -@@ -5224,5 +5324,6 @@ START_TEST(file) +@@ -5305,5 +5405,6 @@ START_TEST(file) test_ioctl(); test_query_ea(); test_flush_buffers_file(); @@ -152,7 +152,7 @@ index 498da270a34..792c07b0d8e 100644 test_mailslot_name(); } diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index a4728003cf8..ea9c0d811f5 100644 +index 700ee717294..492838d9031 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -36,6 +36,7 @@ @@ -182,7 +182,7 @@ index a4728003cf8..ea9c0d811f5 100644 #ifdef linux /* We want the real kernel dirent structure, not the libc one */ -@@ -479,6 +485,32 @@ static int xattr_set( const char *path, const char *name, void *value, size_t si +@@ -477,6 +483,32 @@ static int xattr_set( const char *path, const char *name, void *value, size_t si #endif } @@ -215,7 +215,7 @@ index a4728003cf8..ea9c0d811f5 100644 /* get space from the current directory data buffer, allocating a new one if necessary */ static void *get_dir_data_space( struct dir_data *data, unsigned int size ) { -@@ -5806,6 +5838,116 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer, +@@ -5950,6 +5982,116 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer, } @@ -223,7 +223,7 @@ index a4728003cf8..ea9c0d811f5 100644 + * Retrieve the unix name corresponding to a file handle, remove that directory, and then symlink + * the requested directory to the location of the old directory. + */ -+NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer) ++NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) +{ + BOOL src_allocated = FALSE, dest_allocated = FALSE, tempdir_created = FALSE; + int dest_len = buffer->MountPointReparseBuffer.SubstituteNameLength; @@ -332,7 +332,7 @@ index a4728003cf8..ea9c0d811f5 100644 /****************************************************************************** * NtFsControlFile (NTDLL.@) */ -@@ -5888,6 +6030,23 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap +@@ -6032,6 +6174,23 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap break; } @@ -343,7 +343,7 @@ index a4728003cf8..ea9c0d811f5 100644 + switch(buffer->ReparseTag) + { + case IO_REPARSE_TAG_MOUNT_POINT: -+ status = FILE_CreateSymlink( handle, buffer ); ++ status = create_reparse_point( handle, buffer ); + break; + default: + FIXME("stub: FSCTL_SET_REPARSE_POINT(%x)\n", buffer->ReparseTag); @@ -357,10 +357,10 @@ index a4728003cf8..ea9c0d811f5 100644 TRACE("FSCTL_SET_SPARSE: Ignoring request\n"); io->Information = 0; diff --git a/include/Makefile.in b/include/Makefile.in -index 6c16e01a271..bf938cae250 100644 +index 9822bce6bdd..00a1be0b74e 100644 --- a/include/Makefile.in +++ b/include/Makefile.in -@@ -533,6 +533,7 @@ SOURCES = \ +@@ -538,6 +538,7 @@ SOURCES = \ ntddvdeo.h \ ntdef.h \ ntdsapi.h \ @@ -417,5 +417,5 @@ index 00000000000..21d42e17325 + +#endif /* __WINE_NTIFS_H */ -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0002-ntdll-Add-support-for-reading-junction-points.patch b/patches/ntdll-Junction_Points/0002-ntdll-Add-support-for-reading-junction-points.patch index d68a0a8c..4b90afcb 100644 --- a/patches/ntdll-Junction_Points/0002-ntdll-Add-support-for-reading-junction-points.patch +++ b/patches/ntdll-Junction_Points/0002-ntdll-Add-support-for-reading-junction-points.patch @@ -1,23 +1,28 @@ -From ba7660d29357412b0a12475dacd1d96da9d5679c Mon Sep 17 00:00:00 2001 +From 49ed938003d970383e684d7db56bf570d0d94b2a Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Thu, 16 Jan 2014 20:57:57 -0700 Subject: [PATCH] ntdll: Add support for reading junction points. Signed-off-by: Erich E. Hoover --- - dlls/ntdll/tests/file.c | 14 ++++- - dlls/ntdll/unix/file.c | 120 ++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 133 insertions(+), 1 deletion(-) + dlls/ntdll/tests/file.c | 20 ++++++- + dlls/ntdll/unix/file.c | 125 ++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 144 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index 792c07b0d8e..88e114ab7a2 100644 +index 54e06a3f126..a3f3485ce46 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c -@@ -5189,9 +5189,10 @@ static void test_reparse_points(void) +@@ -5265,14 +5265,15 @@ static void test_reparse_points(void) + static const WCHAR reparseW[] = {'\\','r','e','p','a','r','s','e',0}; + WCHAR path[MAX_PATH], reparse_path[MAX_PATH], target_path[MAX_PATH]; + static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0}; ++ INT buffer_len, string_len, path_len, total_len; + static const WCHAR fooW[] = {'f','o','o',0}; + static WCHAR volW[] = {'c',':','\\',0}; static const WCHAR dotW[] = {'.',0}; REPARSE_DATA_BUFFER *buffer = NULL; DWORD dwret, dwLen, dwFlags; -+ INT buffer_len, string_len; UNICODE_STRING nameW; - INT buffer_len; HANDLE handle; @@ -25,7 +30,7 @@ index 792c07b0d8e..88e114ab7a2 100644 BOOL bret; /* Create a temporary folder for the junction point tests */ -@@ -5239,6 +5240,17 @@ static void test_reparse_points(void) +@@ -5320,6 +5321,23 @@ static void test_reparse_points(void) buffer_len = build_reparse_buffer(nameW.Buffer, &buffer); bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0); ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError()); @@ -40,14 +45,20 @@ index 792c07b0d8e..88e114ab7a2 100644 + dest = &buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)]; + ok((memcmp(dest, nameW.Buffer, string_len) == 0), "Junction point destination does not match ('%s' != '%s')!\n", + wine_dbgstr_w(dest), wine_dbgstr_w(nameW.Buffer)); ++ path_len = buffer->MountPointReparseBuffer.PrintNameOffset/sizeof(WCHAR); ++ path_len += buffer->MountPointReparseBuffer.PrintNameLength/sizeof(WCHAR); ++ total_len = FIELD_OFFSET(typeof(*buffer), MountPointReparseBuffer.PathBuffer[path_len+1]) ++ - FIELD_OFFSET(typeof(*buffer), GenericReparseBuffer); ++ ok(buffer->ReparseDataLength == total_len, "ReparseDataLength has unexpected value (%d != %d)\n", ++ buffer->ReparseDataLength, total_len); CloseHandle(handle); cleanup: diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index ea9c0d811f5..6389e7c8f20 100644 +index 492838d9031..5289c0eec71 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -5948,6 +5948,120 @@ cleanup: +@@ -6092,6 +6092,125 @@ cleanup: } @@ -55,9 +66,10 @@ index ea9c0d811f5..6389e7c8f20 100644 + * Retrieve the unix name corresponding to a file handle and use that to find the destination of the + * symlink corresponding to that file handle. + */ -+NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_size) ++NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_size) +{ + char *unix_src, unix_dest[PATH_MAX]; ++ INT prefix_len, path_len, total_len; + VOID *subst_name, *print_name; + SIZE_T nt_dest_len = PATH_MAX; + BOOL dest_allocated = FALSE; @@ -66,7 +78,6 @@ index ea9c0d811f5..6389e7c8f20 100644 + DWORD max_length; + NTSTATUS status; + WCHAR *nt_dest; -+ INT prefix_len; + ssize_t ret; + char *p; + int i; @@ -135,12 +146,16 @@ index ea9c0d811f5..6389e7c8f20 100644 + { + case IO_REPARSE_TAG_MOUNT_POINT: + max_length = out_size-FIELD_OFFSET(typeof(*buffer), MountPointReparseBuffer.PathBuffer[1]); -+ buffer->MountPointReparseBuffer.SubstituteNameOffset = 0; ++ path_len = 0; ++ buffer->MountPointReparseBuffer.SubstituteNameOffset = path_len; + buffer->MountPointReparseBuffer.SubstituteNameLength = nt_dest_len; ++ path_len += nt_dest_len + sizeof(WCHAR); + subst_name = &buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)]; -+ buffer->MountPointReparseBuffer.PrintNameOffset = nt_dest_len + sizeof(WCHAR); ++ buffer->MountPointReparseBuffer.PrintNameOffset = path_len; + buffer->MountPointReparseBuffer.PrintNameLength = nt_dest_len - prefix_len*sizeof(WCHAR); + print_name = &buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.PrintNameOffset/sizeof(WCHAR)]; ++ path_len += (nt_dest_len - prefix_len*sizeof(WCHAR)) + sizeof(WCHAR); ++ total_len = FIELD_OFFSET(typeof(*buffer), MountPointReparseBuffer.PathBuffer[path_len/sizeof(WCHAR)]); + break; + default: + /* unrecognized (regular) files should probably be treated as symlinks */ @@ -156,6 +171,7 @@ index ea9c0d811f5..6389e7c8f20 100644 + + memcpy( subst_name, nt_dest, nt_dest_len ); + memcpy( print_name, &nt_dest[prefix_len], nt_dest_len - prefix_len*sizeof(WCHAR) ); ++ buffer->ReparseDataLength = total_len - FIELD_OFFSET(typeof(*buffer), GenericReparseBuffer); + status = STATUS_SUCCESS; + +cleanup: @@ -168,19 +184,19 @@ index ea9c0d811f5..6389e7c8f20 100644 /****************************************************************************** * NtFsControlFile (NTDLL.@) */ -@@ -6030,6 +6144,12 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap +@@ -6174,6 +6293,12 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap break; } + case FSCTL_GET_REPARSE_POINT: + { + REPARSE_DATA_BUFFER *buffer = (REPARSE_DATA_BUFFER *)out_buffer; -+ status = FILE_GetSymlink( handle, buffer, out_size ); ++ status = get_reparse_point( handle, buffer, out_size ); + break; + } case FSCTL_SET_REPARSE_POINT: { REPARSE_DATA_BUFFER *buffer = (REPARSE_DATA_BUFFER *)in_buffer; -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0003-ntdll-Add-support-for-deleting-junction-points.patch b/patches/ntdll-Junction_Points/0003-ntdll-Add-support-for-deleting-junction-points.patch index b578c2b6..4aee6554 100644 --- a/patches/ntdll-Junction_Points/0003-ntdll-Add-support-for-deleting-junction-points.patch +++ b/patches/ntdll-Junction_Points/0003-ntdll-Add-support-for-deleting-junction-points.patch @@ -1,4 +1,4 @@ -From 7554efacce44c930a981312bcf341b74e896fc17 Mon Sep 17 00:00:00 2001 +From cc1a2a1ade9c176a7c77a5673c26cee6ab85963c Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Thu, 16 Jan 2014 21:00:21 -0700 Subject: [PATCH] ntdll: Add support for deleting junction points. @@ -11,13 +11,13 @@ Signed-off-by: Erich E. Hoover 3 files changed, 131 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index 88e114ab7a2..0dcefdef97b 100644 +index a3f3485ce46..b844fe9e1d3 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c -@@ -5184,12 +5184,15 @@ static void test_reparse_points(void) - static const WCHAR reparseW[] = {'\\','r','e','p','a','r','s','e',0}; +@@ -5266,11 +5266,14 @@ static void test_reparse_points(void) WCHAR path[MAX_PATH], reparse_path[MAX_PATH], target_path[MAX_PATH]; static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0}; + INT buffer_len, string_len, path_len, total_len; + FILE_BASIC_INFORMATION old_attrib, new_attrib; static const WCHAR fooW[] = {'f','o','o',0}; static WCHAR volW[] = {'c',':','\\',0}; @@ -25,12 +25,11 @@ index 88e114ab7a2..0dcefdef97b 100644 static const WCHAR dotW[] = {'.',0}; REPARSE_DATA_BUFFER *buffer = NULL; DWORD dwret, dwLen, dwFlags; - INT buffer_len, string_len; + IO_STATUS_BLOCK iosb; UNICODE_STRING nameW; HANDLE handle; WCHAR *dest; -@@ -5237,6 +5240,8 @@ static void test_reparse_points(void) +@@ -5318,6 +5321,8 @@ static void test_reparse_points(void) win_skip("Failed to open junction point directory handle (0x%x).\n", GetLastError()); goto cleanup; } @@ -39,10 +38,10 @@ index 88e114ab7a2..0dcefdef97b 100644 buffer_len = build_reparse_buffer(nameW.Buffer, &buffer); bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0); ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError()); -@@ -5251,6 +5256,22 @@ static void test_reparse_points(void) - dest = &buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)]; - ok((memcmp(dest, nameW.Buffer, string_len) == 0), "Junction point destination does not match ('%s' != '%s')!\n", - wine_dbgstr_w(dest), wine_dbgstr_w(nameW.Buffer)); +@@ -5338,6 +5343,22 @@ static void test_reparse_points(void) + - FIELD_OFFSET(typeof(*buffer), GenericReparseBuffer); + ok(buffer->ReparseDataLength == total_len, "ReparseDataLength has unexpected value (%d != %d)\n", + buffer->ReparseDataLength, total_len); + + /* Delete the junction point */ + memset(&old_attrib, 0x00, sizeof(old_attrib)); @@ -62,7 +61,7 @@ index 88e114ab7a2..0dcefdef97b 100644 CloseHandle(handle); cleanup: -@@ -5258,7 +5279,7 @@ cleanup: +@@ -5345,7 +5366,7 @@ cleanup: pRtlFreeUnicodeString(&nameW); HeapFree(GetProcessHeap(), 0, buffer); bret = RemoveDirectoryW(reparse_path); @@ -72,10 +71,10 @@ index 88e114ab7a2..0dcefdef97b 100644 ok(bret, "Failed to remove temporary target directory!\n"); RemoveDirectoryW(path); diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 6389e7c8f20..982df84d029 100644 +index 5289c0eec71..118f81db3c1 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -6062,6 +6062,87 @@ cleanup: +@@ -6211,6 +6211,87 @@ cleanup: } @@ -83,7 +82,7 @@ index 6389e7c8f20..982df84d029 100644 + * Retrieve the unix name corresponding to a file handle, remove that symlink, and then recreate + * a directory at the location of the old filename. + */ -+NTSTATUS FILE_RemoveSymlink(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer) ++NTSTATUS remove_reparse_point(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer) +{ + char tmpdir[PATH_MAX], tmpfile[PATH_MAX], *d; + BOOL tempdir_created = FALSE; @@ -163,7 +162,7 @@ index 6389e7c8f20..982df84d029 100644 /****************************************************************************** * NtFsControlFile (NTDLL.@) */ -@@ -6144,6 +6225,22 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap +@@ -6293,6 +6374,22 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap break; } @@ -174,7 +173,7 @@ index 6389e7c8f20..982df84d029 100644 + switch(buffer->ReparseTag) + { + case IO_REPARSE_TAG_MOUNT_POINT: -+ status = FILE_RemoveSymlink( handle, buffer ); ++ status = remove_reparse_point( handle, buffer ); + break; + default: + FIXME("stub: FSCTL_DELETE_REPARSE_POINT(%x)\n", buffer->ReparseTag); @@ -208,5 +207,5 @@ index 21d42e17325..4539b89d583 100644 + #endif /* __WINE_NTIFS_H */ -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0004-ntdll-Add-a-test-for-junction-point-advertisement.patch b/patches/ntdll-Junction_Points/0004-ntdll-Add-a-test-for-junction-point-advertisement.patch index fbfa538a..c5b2810c 100644 --- a/patches/ntdll-Junction_Points/0004-ntdll-Add-a-test-for-junction-point-advertisement.patch +++ b/patches/ntdll-Junction_Points/0004-ntdll-Add-a-test-for-junction-point-advertisement.patch @@ -1,4 +1,4 @@ -From c0fe3802d5baca7d4048abfca0dcc261fb63ad2c Mon Sep 17 00:00:00 2001 +From 2b0a539941dcd1a292cda3f506abb6359f409527 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Thu, 16 Jan 2014 21:01:25 -0700 Subject: [PATCH] ntdll: Add a test for junction point advertisement. @@ -9,10 +9,10 @@ Signed-off-by: Erich E. Hoover 1 file changed, 5 insertions(+) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index 0dcefdef97b..7ad25ffd239 100644 +index b844fe9e1d3..504d67adde6 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c -@@ -5246,6 +5246,11 @@ static void test_reparse_points(void) +@@ -5327,6 +5327,11 @@ static void test_reparse_points(void) bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0); ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError()); @@ -25,5 +25,5 @@ index 0dcefdef97b..7ad25ffd239 100644 HeapFree(GetProcessHeap(), 0, buffer); buffer_len = sizeof(*buffer) + MAX_PATH*sizeof(WCHAR); -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0005-server-Add-support-for-deleting-junction-points-with.patch b/patches/ntdll-Junction_Points/0005-server-Add-support-for-deleting-junction-points-with.patch index d4424ae1..276edca3 100644 --- a/patches/ntdll-Junction_Points/0005-server-Add-support-for-deleting-junction-points-with.patch +++ b/patches/ntdll-Junction_Points/0005-server-Add-support-for-deleting-junction-points-with.patch @@ -1,4 +1,4 @@ -From 55571cb23f81d2d5836c69793d5621f09f535009 Mon Sep 17 00:00:00 2001 +From d5a062699b1a599fc87ba757e65b3aeb2ead9834 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Thu, 16 Jan 2014 21:02:11 -0700 Subject: [PATCH] server: Add support for deleting junction points with @@ -11,19 +11,19 @@ Signed-off-by: Erich E. Hoover 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index 7ad25ffd239..5a2ac2114b0 100644 +index 504d67adde6..2ddabc865bf 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c -@@ -5190,7 +5190,7 @@ static void test_reparse_points(void) +@@ -5272,7 +5272,7 @@ static void test_reparse_points(void) REPARSE_GUID_DATA_BUFFER guid_buffer; static const WCHAR dotW[] = {'.',0}; REPARSE_DATA_BUFFER *buffer = NULL; - DWORD dwret, dwLen, dwFlags; + DWORD dwret, dwLen, dwFlags, err; - INT buffer_len, string_len; IO_STATUS_BLOCK iosb; UNICODE_STRING nameW; -@@ -5279,6 +5279,38 @@ static void test_reparse_points(void) + HANDLE handle; +@@ -5366,6 +5366,38 @@ static void test_reparse_points(void) "Junction point folder's access time does not match.\n"); CloseHandle(handle); @@ -63,7 +63,7 @@ index 7ad25ffd239..5a2ac2114b0 100644 /* Cleanup */ pRtlFreeUnicodeString(&nameW); diff --git a/server/fd.c b/server/fd.c -index 65a6f876e5c..4f43f41fb31 100644 +index 481e9a88f0f..2605adf96ff 100644 --- a/server/fd.c +++ b/server/fd.c @@ -169,7 +169,8 @@ struct closed_fd @@ -187,7 +187,7 @@ index 65a6f876e5c..4f43f41fb31 100644 /* check directory options */ if ((options & FILE_DIRECTORY_FILE) && !S_ISDIR(st.st_mode)) { -@@ -2611,10 +2629,10 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da +@@ -2605,10 +2623,10 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da free( fd->nt_name ); fd->nt_name = dup_nt_name( root, nt_name, &fd->nt_namelen ); @@ -201,5 +201,5 @@ index 65a6f876e5c..4f43f41fb31 100644 return; -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0006-kernel32-Advertise-junction-point-support.patch b/patches/ntdll-Junction_Points/0006-kernel32-Advertise-junction-point-support.patch index 82e342ca..3e9bf8cc 100644 --- a/patches/ntdll-Junction_Points/0006-kernel32-Advertise-junction-point-support.patch +++ b/patches/ntdll-Junction_Points/0006-kernel32-Advertise-junction-point-support.patch @@ -1,4 +1,4 @@ -From 2086a18555c0c4111c48676af90c642828ce87f5 Mon Sep 17 00:00:00 2001 +From 58c9e69484d7c8da358e61de61827ec1d8399bbd Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Sat, 12 Dec 2020 17:28:31 -0700 Subject: [PATCH] kernel32: Advertise junction point support. @@ -9,7 +9,7 @@ Subject: [PATCH] kernel32: Advertise junction point support. 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/dlls/mountmgr.sys/device.c b/dlls/mountmgr.sys/device.c -index dd2c7d70759..171dc6ea592 100644 +index 04e8fe3c0f5..c8e7d6bf088 100644 --- a/dlls/mountmgr.sys/device.c +++ b/dlls/mountmgr.sys/device.c @@ -31,6 +31,21 @@ @@ -34,7 +34,7 @@ index dd2c7d70759..171dc6ea592 100644 #define NONAMELESSUNION -@@ -1828,6 +1843,68 @@ static NTSTATUS query_property( struct disk_device *device, IRP *irp ) +@@ -1902,6 +1917,68 @@ static NTSTATUS query_property( struct disk_device *device, IRP *irp ) return status; } @@ -103,7 +103,7 @@ index dd2c7d70759..171dc6ea592 100644 static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp ) { IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); -@@ -1916,7 +1993,8 @@ static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp ) +@@ -1990,7 +2067,8 @@ static NTSTATUS WINAPI harddisk_query_volume( DEVICE_OBJECT *device, IRP *irp ) memcpy(info->FileSystemName, fat32W, info->FileSystemNameLength); break; default: @@ -114,10 +114,10 @@ index dd2c7d70759..171dc6ea592 100644 info->FileSystemNameLength = min( sizeof(ntfsW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) ); memcpy(info->FileSystemName, ntfsW, info->FileSystemNameLength); diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index 5a2ac2114b0..5882793c883 100644 +index 2ddabc865bf..699d5e67d88 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c -@@ -5181,8 +5181,8 @@ static INT build_reparse_buffer(const WCHAR *filename, REPARSE_DATA_BUFFER **pbu +@@ -5262,8 +5262,8 @@ static INT build_reparse_buffer(const WCHAR *filename, REPARSE_DATA_BUFFER **pbu static void test_reparse_points(void) { @@ -125,9 +125,9 @@ index 5a2ac2114b0..5882793c883 100644 static const WCHAR reparseW[] = {'\\','r','e','p','a','r','s','e',0}; - WCHAR path[MAX_PATH], reparse_path[MAX_PATH], target_path[MAX_PATH]; static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0}; + INT buffer_len, string_len, path_len, total_len; FILE_BASIC_INFORMATION old_attrib, new_attrib; - static const WCHAR fooW[] = {'f','o','o',0}; -@@ -5211,7 +5211,12 @@ static void test_reparse_points(void) +@@ -5292,7 +5292,12 @@ static void test_reparse_points(void) pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL); volW[0] = nameW.Buffer[4]; pRtlFreeUnicodeString( &nameW ); @@ -142,5 +142,5 @@ index 5a2ac2114b0..5882793c883 100644 { skip("File system does not support reparse points.\n"); -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0007-ntdll-Add-support-for-absolute-symlink-creation.patch b/patches/ntdll-Junction_Points/0007-ntdll-Add-support-for-absolute-symlink-creation.patch index 5da94266..ad0791d0 100644 --- a/patches/ntdll-Junction_Points/0007-ntdll-Add-support-for-absolute-symlink-creation.patch +++ b/patches/ntdll-Junction_Points/0007-ntdll-Add-support-for-absolute-symlink-creation.patch @@ -1,4 +1,4 @@ -From 7fd3c661bce1c490fe9e2ad04b524777e897b896 Mon Sep 17 00:00:00 2001 +From fb7afe57f143a7777f54c1e936d60af5ace51865 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Thu, 16 Jan 2014 21:06:24 -0700 Subject: [PATCH] ntdll: Add support for absolute symlink creation. @@ -6,15 +6,15 @@ Subject: [PATCH] ntdll: Add support for absolute symlink creation. Signed-off-by: Erich E. Hoover --- dlls/ntdll/tests/file.c | 117 ++++++++++++++++++++++++++++++++++------ - dlls/ntdll/unix/file.c | 37 +++++++++++-- + dlls/ntdll/unix/file.c | 49 ++++++++++++----- include/ntifs.h | 10 ++++ - 3 files changed, 145 insertions(+), 19 deletions(-) + 3 files changed, 146 insertions(+), 30 deletions(-) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index 5882793c883..53a24574eec 100644 +index 699d5e67d88..e0fa36ea64f 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c -@@ -5153,26 +5153,50 @@ static void test_mailslot_name(void) +@@ -5234,26 +5234,50 @@ static void test_mailslot_name(void) CloseHandle( device ); } @@ -73,10 +73,10 @@ index 5882793c883..53a24574eec 100644 lstrcpyW(subst_dest, filename); lstrcpyW(print_dest, &filename[prefix_len]); *pbuffer = buffer; -@@ -5192,10 +5216,12 @@ static void test_reparse_points(void) +@@ -5273,10 +5297,12 @@ static void test_reparse_points(void) + static const WCHAR dotW[] = {'.',0}; REPARSE_DATA_BUFFER *buffer = NULL; DWORD dwret, dwLen, dwFlags, err; - INT buffer_len, string_len; + HANDLE handle, token; IO_STATUS_BLOCK iosb; UNICODE_STRING nameW; @@ -87,7 +87,7 @@ index 5882793c883..53a24574eec 100644 BOOL bret; /* Create a temporary folder for the junction point tests */ -@@ -5247,7 +5273,7 @@ static void test_reparse_points(void) +@@ -5328,7 +5354,7 @@ static void test_reparse_points(void) } dwret = NtQueryInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation); ok(dwret == STATUS_SUCCESS, "Failed to get junction point folder's attributes (0x%x).\n", dwret); @@ -96,7 +96,7 @@ index 5882793c883..53a24574eec 100644 bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0); ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError()); -@@ -5288,7 +5314,7 @@ static void test_reparse_points(void) +@@ -5375,7 +5401,7 @@ static void test_reparse_points(void) HeapFree(GetProcessHeap(), 0, buffer); handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); @@ -105,7 +105,7 @@ index 5882793c883..53a24574eec 100644 bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0); ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError()); CloseHandle(handle); -@@ -5303,7 +5329,7 @@ static void test_reparse_points(void) +@@ -5390,7 +5416,7 @@ static void test_reparse_points(void) ok(bret, "Failed to create junction point target directory.\n"); handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); @@ -114,7 +114,7 @@ index 5882793c883..53a24574eec 100644 bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0); ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError()); CloseHandle(handle); -@@ -5316,14 +5342,73 @@ static void test_reparse_points(void) +@@ -5403,14 +5429,73 @@ static void test_reparse_points(void) ok(dwret != (DWORD)~0, "Junction point doesn't exist (attributes: 0x%x)!\n", dwret); ok(dwret & FILE_ATTRIBUTE_REPARSE_POINT, "File is not a junction point! (attributes: 0x%x)\n", dwret); @@ -193,11 +193,11 @@ index 5882793c883..53a24574eec 100644 } diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 773223acd7c..9e4d00deb0e 100644 +index 118f81db3c1..da5136db68c 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -5845,18 +5845,34 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer, - NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer) +@@ -5989,18 +5989,35 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer, + NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) { BOOL src_allocated = FALSE, dest_allocated = FALSE, tempdir_created = FALSE; - int dest_len = buffer->MountPointReparseBuffer.SubstituteNameLength; @@ -228,13 +228,14 @@ index 773223acd7c..9e4d00deb0e 100644 + dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[offset]; + break; + default: ++ FIXME("stub: FSCTL_SET_REPARSE_POINT(%x)\n", buffer->ReparseTag); + return STATUS_NOT_IMPLEMENTED; + } + if ((status = server_get_unix_fd( handle, FILE_SPECIAL_ACCESS, &dest_fd, &needs_close, NULL, NULL ))) return status; -@@ -5891,6 +5907,20 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer) +@@ -6035,6 +6052,20 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) strcat( magic_dest, "." ); strcat( magic_dest, "/" ); } @@ -255,14 +256,25 @@ index 773223acd7c..9e4d00deb0e 100644 strcat( magic_dest, unix_dest ); /* Produce the link in a temporary location in the same folder */ -@@ -6254,6 +6284,7 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap - switch(buffer->ReparseTag) - { - case IO_REPARSE_TAG_MOUNT_POINT: -+ case IO_REPARSE_TAG_SYMLINK: - status = FILE_CreateSymlink( handle, buffer ); - break; - default: +@@ -6399,17 +6430,7 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap + case FSCTL_SET_REPARSE_POINT: + { + REPARSE_DATA_BUFFER *buffer = (REPARSE_DATA_BUFFER *)in_buffer; +- +- switch(buffer->ReparseTag) +- { +- case IO_REPARSE_TAG_MOUNT_POINT: +- status = create_reparse_point( handle, buffer ); +- break; +- default: +- FIXME("stub: FSCTL_SET_REPARSE_POINT(%x)\n", buffer->ReparseTag); +- status = STATUS_NOT_IMPLEMENTED; +- break; +- } ++ status = create_reparse_point( handle, buffer ); + break; + } + diff --git a/include/ntifs.h b/include/ntifs.h index 4539b89d583..ab3273d3f81 100644 --- a/include/ntifs.h @@ -297,5 +309,5 @@ index 4539b89d583..ab3273d3f81 100644 typedef struct _REPARSE_GUID_DATA_BUFFER { DWORD ReparseTag; -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0008-ntdll-Add-support-for-reading-absolute-symlinks.patch b/patches/ntdll-Junction_Points/0008-ntdll-Add-support-for-reading-absolute-symlinks.patch index 12fe108f..0ce4accd 100644 --- a/patches/ntdll-Junction_Points/0008-ntdll-Add-support-for-reading-absolute-symlinks.patch +++ b/patches/ntdll-Junction_Points/0008-ntdll-Add-support-for-reading-absolute-symlinks.patch @@ -1,19 +1,19 @@ -From 59ba8b3a0f29945da7e1f082b197ce398bf442f2 Mon Sep 17 00:00:00 2001 +From 5859da2b48592d1a13f471a6932a2529aa1e0395 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Wed, 13 Mar 2019 12:55:20 -0600 Subject: [PATCH] ntdll: Add support for reading absolute symlinks. Signed-off-by: Erich E. Hoover --- - dlls/ntdll/tests/file.c | 13 ++++++++++++- - dlls/ntdll/unix/file.c | 22 ++++++++++++++++++++++ - 2 files changed, 34 insertions(+), 1 deletion(-) + dlls/ntdll/tests/file.c | 19 ++++++++++++++++++- + dlls/ntdll/unix/file.c | 26 ++++++++++++++++++++++++++ + 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index 53a24574eec..9a6f72cb783 100644 +index e0fa36ea64f..cfc0d176b53 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c -@@ -5393,7 +5393,6 @@ static void test_reparse_points(void) +@@ -5480,7 +5480,6 @@ static void test_reparse_points(void) ok(dwret == STATUS_SUCCESS, "Failed to get symlink folder's attributes (0x%x).\n", dwret); buffer_len = build_reparse_buffer(nameW.Buffer, IO_REPARSE_TAG_SYMLINK, &buffer); bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0); @@ -21,7 +21,7 @@ index 53a24574eec..9a6f72cb783 100644 ok(bret, "Failed to create symlink! (0x%x)\n", GetLastError()); /* Check the file attributes of the symlink */ -@@ -5401,6 +5400,18 @@ static void test_reparse_points(void) +@@ -5488,6 +5487,24 @@ static void test_reparse_points(void) ok(dwret != (DWORD)~0, "Symlink doesn't exist (attributes: 0x%x)!\n", dwret); ok(dwret & FILE_ATTRIBUTE_REPARSE_POINT, "File is not a symlink! (attributes: %d)\n", dwret); @@ -35,24 +35,30 @@ index 53a24574eec..9a6f72cb783 100644 + ok(bret, "Failed to read symlink!\n"); + ok((memcmp(dest, nameW.Buffer, string_len) == 0), "Symlink destination does not match ('%s' != '%s')!\n", + wine_dbgstr_w(dest), wine_dbgstr_w(nameW.Buffer)); ++ path_len = buffer->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR); ++ path_len += buffer->SymbolicLinkReparseBuffer.PrintNameLength/sizeof(WCHAR); ++ total_len = FIELD_OFFSET(typeof(*buffer), MountPointReparseBuffer.PathBuffer[path_len+1]) ++ - FIELD_OFFSET(typeof(*buffer), GenericReparseBuffer); ++ ok(buffer->ReparseDataLength == total_len, "ReparseDataLength has unexpected value (%d != %d)\n", ++ buffer->ReparseDataLength, total_len); + CloseHandle(handle); + cleanup: /* Cleanup */ pRtlFreeUnicodeString(&nameW); diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 11a7269c09e..19a2d0ae471 100644 +index da5136db68c..668f4fe2c80 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -5988,6 +5988,7 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s +@@ -6138,6 +6138,7 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out int unix_dest_len; DWORD max_length; NTSTATUS status; + ULONG flags = 0; WCHAR *nt_dest; - INT prefix_len; ssize_t ret; -@@ -6032,6 +6033,17 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s + char *p; +@@ -6181,6 +6182,17 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out } buffer->ReparseTag |= (val << i); } @@ -70,23 +76,27 @@ index 11a7269c09e..19a2d0ae471 100644 unix_dest_len -= (p - unix_dest); memmove(unix_dest, p, unix_dest_len); unix_dest[unix_dest_len] = 0; -@@ -6065,6 +6077,16 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s - buffer->MountPointReparseBuffer.PrintNameLength = nt_dest_len - prefix_len*sizeof(WCHAR); - print_name = &buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.PrintNameOffset/sizeof(WCHAR)]; +@@ -6218,6 +6230,20 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out + path_len += (nt_dest_len - prefix_len*sizeof(WCHAR)) + sizeof(WCHAR); + total_len = FIELD_OFFSET(typeof(*buffer), MountPointReparseBuffer.PathBuffer[path_len/sizeof(WCHAR)]); break; + case IO_REPARSE_TAG_SYMLINK: + max_length = out_size-FIELD_OFFSET(typeof(*buffer), SymbolicLinkReparseBuffer.PathBuffer[1]); -+ buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0; ++ path_len = 0; ++ buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = path_len; + buffer->SymbolicLinkReparseBuffer.SubstituteNameLength = nt_dest_len; ++ path_len += nt_dest_len + sizeof(WCHAR); + subst_name = &buffer->SymbolicLinkReparseBuffer.PathBuffer[buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)]; -+ buffer->SymbolicLinkReparseBuffer.PrintNameOffset = nt_dest_len + sizeof(WCHAR); ++ buffer->SymbolicLinkReparseBuffer.PrintNameOffset = path_len; + buffer->SymbolicLinkReparseBuffer.PrintNameLength = nt_dest_len - prefix_len*sizeof(WCHAR); + print_name = &buffer->SymbolicLinkReparseBuffer.PathBuffer[buffer->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR)]; ++ path_len += (nt_dest_len - prefix_len*sizeof(WCHAR)) + sizeof(WCHAR); ++ total_len = FIELD_OFFSET(typeof(*buffer), MountPointReparseBuffer.PathBuffer[path_len/sizeof(WCHAR)]); + buffer->SymbolicLinkReparseBuffer.Flags = flags; + break; default: /* unrecognized (regular) files should probably be treated as symlinks */ WARN("unrecognized symbolic link\n"); -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0009-ntdll-Add-support-for-deleting-symlinks.patch b/patches/ntdll-Junction_Points/0009-ntdll-Add-support-for-deleting-symlinks.patch index 8ada4832..f0454480 100644 --- a/patches/ntdll-Junction_Points/0009-ntdll-Add-support-for-deleting-symlinks.patch +++ b/patches/ntdll-Junction_Points/0009-ntdll-Add-support-for-deleting-symlinks.patch @@ -1,4 +1,4 @@ -From a563404dcdc796241cb83da788c5ac62dfe1fc17 Mon Sep 17 00:00:00 2001 +From 1cd53753c747d30cb1acee7f93264747a58c338b Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Wed, 13 Mar 2019 13:02:22 -0600 Subject: [PATCH] ntdll: Add support for deleting symlinks. @@ -10,13 +10,13 @@ Signed-off-by: Erich E. Hoover 2 files changed, 17 insertions(+) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index 9a6f72cb783..dd21083ebbb 100644 +index cfc0d176b53..1fe5fea47d5 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c -@@ -5410,6 +5410,22 @@ static void test_reparse_points(void) - ok(bret, "Failed to read symlink!\n"); - ok((memcmp(dest, nameW.Buffer, string_len) == 0), "Symlink destination does not match ('%s' != '%s')!\n", - wine_dbgstr_w(dest), wine_dbgstr_w(nameW.Buffer)); +@@ -5503,6 +5503,22 @@ static void test_reparse_points(void) + - FIELD_OFFSET(typeof(*buffer), GenericReparseBuffer); + ok(buffer->ReparseDataLength == total_len, "ReparseDataLength has unexpected value (%d != %d)\n", + buffer->ReparseDataLength, total_len); + + /* Delete the symlink */ + memset(&old_attrib, 0x00, sizeof(old_attrib)); @@ -37,17 +37,17 @@ index 9a6f72cb783..dd21083ebbb 100644 cleanup: diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 19a2d0ae471..4e16db830d2 100644 +index 668f4fe2c80..bddf55faad8 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -6280,6 +6280,7 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap +@@ -6438,6 +6438,7 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap switch(buffer->ReparseTag) { case IO_REPARSE_TAG_MOUNT_POINT: + case IO_REPARSE_TAG_SYMLINK: - status = FILE_RemoveSymlink( handle, buffer ); + status = remove_reparse_point( handle, buffer ); break; default: -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0010-ntdll-Add-support-for-relative-symlink-creation.patch b/patches/ntdll-Junction_Points/0010-ntdll-Add-support-for-relative-symlink-creation.patch index c14db982..3155004d 100644 --- a/patches/ntdll-Junction_Points/0010-ntdll-Add-support-for-relative-symlink-creation.patch +++ b/patches/ntdll-Junction_Points/0010-ntdll-Add-support-for-relative-symlink-creation.patch @@ -1,4 +1,4 @@ -From b5698ce1750769a0b57372be14bf4efb5f1c872c Mon Sep 17 00:00:00 2001 +From a56456fcccb14d889925b8f82c2f4c8506143b0a Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Thu, 11 Apr 2019 12:16:49 -0600 Subject: [PATCH] ntdll: Add support for relative symlink creation. @@ -11,10 +11,10 @@ Signed-off-by: Erich E. Hoover 3 files changed, 111 insertions(+), 13 deletions(-) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index dd21083ebbb..8ed749cfe33 100644 +index 1fe5fea47d5..367eef539ce 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c -@@ -5153,7 +5153,8 @@ static void test_mailslot_name(void) +@@ -5234,7 +5234,8 @@ static void test_mailslot_name(void) CloseHandle( device ); } @@ -24,7 +24,7 @@ index dd21083ebbb..8ed749cfe33 100644 { static INT header_size = offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer); INT buffer_size, struct_size, data_size, string_len, prefix_len; -@@ -5171,7 +5172,7 @@ static INT build_reparse_buffer(const WCHAR *filename, ULONG tag, REPARSE_DATA_B +@@ -5252,7 +5253,7 @@ static INT build_reparse_buffer(const WCHAR *filename, ULONG tag, REPARSE_DATA_B default: return 0; } @@ -33,7 +33,7 @@ index dd21083ebbb..8ed749cfe33 100644 string_len = lstrlenW(&filename[prefix_len]); data_size = (prefix_len + 2 * string_len + 2) * sizeof(WCHAR); buffer_size = struct_size + data_size; -@@ -5191,6 +5192,7 @@ static INT build_reparse_buffer(const WCHAR *filename, ULONG tag, REPARSE_DATA_B +@@ -5272,6 +5273,7 @@ static INT build_reparse_buffer(const WCHAR *filename, ULONG tag, REPARSE_DATA_B buffer->SymbolicLinkReparseBuffer.SubstituteNameLength = (prefix_len + string_len) * sizeof(WCHAR); buffer->SymbolicLinkReparseBuffer.PrintNameOffset = (prefix_len + string_len + 1) * sizeof(WCHAR); buffer->SymbolicLinkReparseBuffer.PrintNameLength = string_len * sizeof(WCHAR); @@ -41,7 +41,7 @@ index dd21083ebbb..8ed749cfe33 100644 subst_dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[0]; print_dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[prefix_len + string_len + 1]; break; -@@ -5273,7 +5275,7 @@ static void test_reparse_points(void) +@@ -5354,7 +5356,7 @@ static void test_reparse_points(void) } dwret = NtQueryInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation); ok(dwret == STATUS_SUCCESS, "Failed to get junction point folder's attributes (0x%x).\n", dwret); @@ -50,7 +50,7 @@ index dd21083ebbb..8ed749cfe33 100644 bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0); ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError()); -@@ -5314,7 +5316,7 @@ static void test_reparse_points(void) +@@ -5401,7 +5403,7 @@ static void test_reparse_points(void) HeapFree(GetProcessHeap(), 0, buffer); handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); @@ -59,7 +59,7 @@ index dd21083ebbb..8ed749cfe33 100644 bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0); ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError()); CloseHandle(handle); -@@ -5329,7 +5331,7 @@ static void test_reparse_points(void) +@@ -5416,7 +5418,7 @@ static void test_reparse_points(void) ok(bret, "Failed to create junction point target directory.\n"); handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); @@ -68,7 +68,7 @@ index dd21083ebbb..8ed749cfe33 100644 bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0); ok(bret, "Failed to create junction point! (0x%x)\n", GetLastError()); CloseHandle(handle); -@@ -5391,7 +5393,7 @@ static void test_reparse_points(void) +@@ -5478,7 +5480,7 @@ static void test_reparse_points(void) } dwret = NtQueryInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation); ok(dwret == STATUS_SUCCESS, "Failed to get symlink folder's attributes (0x%x).\n", dwret); @@ -77,7 +77,7 @@ index dd21083ebbb..8ed749cfe33 100644 bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0); ok(bret, "Failed to create symlink! (0x%x)\n", GetLastError()); -@@ -5428,6 +5430,22 @@ static void test_reparse_points(void) +@@ -5521,6 +5523,22 @@ static void test_reparse_points(void) "Symlink folder's access time does not match.\n"); CloseHandle(handle); @@ -92,7 +92,7 @@ index dd21083ebbb..8ed749cfe33 100644 + } + dwret = NtQueryInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation); + ok(dwret == STATUS_SUCCESS, "Failed to get symlink folder's attributes (0x%x).\n", dwret); -+ buffer_len = build_reparse_buffer(targetW, IO_REPARSE_TAG_SYMLINK, SYMLINK_FLAG_RELATIVE, &buffer); ++ buffer_len = build_reparse_buffer(&targetW[1], IO_REPARSE_TAG_SYMLINK, SYMLINK_FLAG_RELATIVE, &buffer); + bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0); + CloseHandle(handle); + ok(bret, "Failed to create symlink! (0x%x)\n", GetLastError()); @@ -101,12 +101,12 @@ index dd21083ebbb..8ed749cfe33 100644 /* Cleanup */ pRtlFreeUnicodeString(&nameW); diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 4e16db830d2..45aab990fb5 100644 +index bddf55faad8..d907d455fc9 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -5844,17 +5844,20 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer, +@@ -5988,17 +5988,20 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer, */ - NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer) + NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) { - BOOL src_allocated = FALSE, dest_allocated = FALSE, tempdir_created = FALSE; + BOOL src_allocated = FALSE, path_allocated = FALSE, dest_allocated = FALSE; @@ -127,7 +127,7 @@ index 4e16db830d2..45aab990fb5 100644 int i; switch(buffer->ReparseTag) -@@ -5863,11 +5866,13 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer) +@@ -6007,11 +6010,13 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) dest_len = buffer->MountPointReparseBuffer.SubstituteNameLength; offset = buffer->MountPointReparseBuffer.SubstituteNameOffset; dest = &buffer->MountPointReparseBuffer.PathBuffer[offset]; @@ -140,8 +140,8 @@ index 4e16db830d2..45aab990fb5 100644 + flags = buffer->SymbolicLinkReparseBuffer.Flags; break; default: - return STATUS_NOT_IMPLEMENTED; -@@ -5879,8 +5884,66 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer) + FIXME("stub: FSCTL_SET_REPARSE_POINT(%x)\n", buffer->ReparseTag); +@@ -6024,8 +6029,66 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) if ((status = server_get_unix_name( handle, &unix_src ))) goto cleanup; src_allocated = TRUE; @@ -210,7 +210,7 @@ index 4e16db830d2..45aab990fb5 100644 for (;;) { unix_dest = malloc( unix_dest_len ); -@@ -5896,11 +5959,24 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer) +@@ -6041,11 +6104,24 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) if (status != STATUS_SUCCESS && status != STATUS_NO_SUCH_FILE) goto cleanup; dest_allocated = TRUE; @@ -237,7 +237,7 @@ index 4e16db830d2..45aab990fb5 100644 for (i = 0; i < sizeof(ULONG)*8; i++) { if ((buffer->ReparseTag >> i) & 1) -@@ -5917,7 +5993,7 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer) +@@ -6066,7 +6142,7 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) strcat( magic_dest, "." ); strcat( magic_dest, "/" ); } @@ -246,7 +246,7 @@ index 4e16db830d2..45aab990fb5 100644 /* Produce the link in a temporary location in the same folder */ strcpy( tmpdir, unix_src ); -@@ -5967,7 +6043,9 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer) +@@ -6116,7 +6192,9 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) cleanup: if (tempdir_created) rmdir( tmpdir ); @@ -268,5 +268,5 @@ index ab3273d3f81..0d02225bc4f 100644 + #endif /* __WINE_NTIFS_H */ -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0011-ntdll-Add-support-for-reading-relative-symlinks.patch b/patches/ntdll-Junction_Points/0011-ntdll-Add-support-for-reading-relative-symlinks.patch index 839d081d..a71e6671 100644 --- a/patches/ntdll-Junction_Points/0011-ntdll-Add-support-for-reading-relative-symlinks.patch +++ b/patches/ntdll-Junction_Points/0011-ntdll-Add-support-for-reading-relative-symlinks.patch @@ -1,4 +1,4 @@ -From 26b27a370a0fac1344dc6f480648d6698a10876e Mon Sep 17 00:00:00 2001 +From de6ef008eced847e63429f1a09fe1e7573110093 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Thu, 11 Apr 2019 12:31:16 -0600 Subject: [PATCH] ntdll: Add support for reading relative symlinks. @@ -10,12 +10,12 @@ Signed-off-by: Erich E. Hoover 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index 8ed749cfe33..bdc1a151b45 100644 +index 367eef539ce..46aadeb7e7d 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c -@@ -5443,9 +5443,22 @@ static void test_reparse_points(void) +@@ -5536,9 +5536,22 @@ static void test_reparse_points(void) ok(dwret == STATUS_SUCCESS, "Failed to get symlink folder's attributes (0x%x).\n", dwret); - buffer_len = build_reparse_buffer(targetW, IO_REPARSE_TAG_SYMLINK, SYMLINK_FLAG_RELATIVE, &buffer); + buffer_len = build_reparse_buffer(&targetW[1], IO_REPARSE_TAG_SYMLINK, SYMLINK_FLAG_RELATIVE, &buffer); bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0); - CloseHandle(handle); ok(bret, "Failed to create symlink! (0x%x)\n", GetLastError()); @@ -27,21 +27,21 @@ index 8ed749cfe33..bdc1a151b45 100644 + bret = DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, (LPVOID)buffer, buffer_len, &dwret, 0); + ok(bret, "Failed to read relative symlink!\n"); + string_len = buffer->SymbolicLinkReparseBuffer.SubstituteNameLength; -+ ok(string_len != lstrlenW(targetW), "Symlink destination length does not match ('%d' != '%d')!\n", -+ string_len, lstrlenW(targetW)); ++ ok(string_len != lstrlenW(&targetW[1]), "Symlink destination length does not match ('%d' != '%d')!\n", ++ string_len, lstrlenW(&targetW[1])); + dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)]; -+ ok((memcmp(dest, targetW, string_len) == 0), "Symlink destination does not match ('%s' != '%s')!\n", -+ wine_dbgstr_w(dest), wine_dbgstr_w(targetW)); ++ ok((memcmp(dest, &targetW[1], string_len) == 0), "Symlink destination does not match ('%s' != '%s')!\n", ++ wine_dbgstr_w(dest), wine_dbgstr_w(&targetW[1])); + CloseHandle(handle); + cleanup: /* Cleanup */ pRtlFreeUnicodeString(&nameW); diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 45aab990fb5..522cc38f2fc 100644 +index d907d455fc9..3a25b803d6f 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -6089,6 +6089,11 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s +@@ -6238,6 +6238,11 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out /* Decode the reparse tag from the symlink */ p = unix_dest; @@ -53,7 +53,7 @@ index 45aab990fb5..522cc38f2fc 100644 if (*p++ != '/') { status = STATUS_NOT_IMPLEMENTED; -@@ -6126,24 +6131,47 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s +@@ -6275,24 +6280,47 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out memmove(unix_dest, p, unix_dest_len); unix_dest[unix_dest_len] = 0; @@ -107,5 +107,5 @@ index 45aab990fb5..522cc38f2fc 100644 { case IO_REPARSE_TAG_MOUNT_POINT: -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0012-ntdll-Add-support-for-file-symlinks.patch b/patches/ntdll-Junction_Points/0012-ntdll-Add-support-for-file-symlinks.patch index 87bf9953..9c46ce6a 100644 --- a/patches/ntdll-Junction_Points/0012-ntdll-Add-support-for-file-symlinks.patch +++ b/patches/ntdll-Junction_Points/0012-ntdll-Add-support-for-file-symlinks.patch @@ -1,4 +1,4 @@ -From 4a1aecb1e9b29fbe0f8d2f4e7d7410af0bbc060e Mon Sep 17 00:00:00 2001 +From 9129b44e1ef8458064d773a5605d1ff182d67c54 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Thu, 11 Apr 2019 17:57:53 -0600 Subject: [PATCH] ntdll: Add support for file symlinks. @@ -10,10 +10,10 @@ Signed-off-by: Erich E. Hoover 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index bdc1a151b45..8938c5bf50c 100644 +index 46aadeb7e7d..e5cfbb68793 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c -@@ -5376,6 +5376,35 @@ static void test_reparse_points(void) +@@ -5463,6 +5463,35 @@ static void test_reparse_points(void) /* Delete the junction point directory and create a blank slate for symlink tests */ bret = RemoveDirectoryW(reparse_path); ok(bret, "Failed to delete junction point!\n"); @@ -50,10 +50,10 @@ index bdc1a151b45..8938c5bf50c 100644 ok(bret, "Failed to create junction point directory.\n"); dwret = GetFileAttributesW(reparse_path); diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 0d064d98743..9b8458b413c 100644 +index 3a25b803d6f..ead0c48d62e 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -5854,6 +5854,7 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer) +@@ -5998,6 +5998,7 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) int relative_offset = 0; UNICODE_STRING nt_dest; int dest_len, offset; @@ -61,7 +61,7 @@ index 0d064d98743..9b8458b413c 100644 NTSTATUS status; struct stat st; WCHAR *dest; -@@ -5986,7 +5987,6 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer) +@@ -6131,7 +6132,6 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) /* Encode the type (file or directory) if NT symlink */ if (buffer->ReparseTag == IO_REPARSE_TAG_SYMLINK) { @@ -69,7 +69,7 @@ index 0d064d98743..9b8458b413c 100644 if (fstat( dest_fd, &st ) == -1) { status = errno_to_status( errno ); -@@ -6020,8 +6020,11 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer) +@@ -6165,8 +6165,11 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) /* Atomically move the link into position */ if (!renameat2( -1, tmplink, -1, unix_src, RENAME_EXCHANGE )) { @@ -83,7 +83,7 @@ index 0d064d98743..9b8458b413c 100644 } else if (errno == ENOSYS) { -@@ -6229,6 +6232,7 @@ NTSTATUS FILE_RemoveSymlink(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer) +@@ -6383,6 +6386,7 @@ NTSTATUS remove_reparse_point(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer) char tmpdir[PATH_MAX], tmpfile[PATH_MAX], *d; BOOL tempdir_created = FALSE; int dest_fd, needs_close; @@ -91,7 +91,7 @@ index 0d064d98743..9b8458b413c 100644 NTSTATUS status; char *unix_name; struct stat st; -@@ -6241,12 +6245,13 @@ NTSTATUS FILE_RemoveSymlink(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer) +@@ -6395,12 +6399,13 @@ NTSTATUS remove_reparse_point(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer) TRACE( "Deleting symlink %s\n", unix_name ); @@ -106,7 +106,7 @@ index 0d064d98743..9b8458b413c 100644 strcpy( tmpdir, unix_name ); d = dirname( tmpdir); if (d != tmpdir) strcpy( tmpdir, d ); -@@ -6259,11 +6264,21 @@ NTSTATUS FILE_RemoveSymlink(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer) +@@ -6413,11 +6418,21 @@ NTSTATUS remove_reparse_point(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer) tempdir_created = TRUE; strcpy( tmpfile, tmpdir ); strcat( tmpfile, "/tmpfile" ); @@ -130,5 +130,5 @@ index 0d064d98743..9b8458b413c 100644 lchown( tmpfile, st.st_uid, st.st_gid ); /* Atomically move the directory into position */ -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0013-ntdll-Allow-creation-of-dangling-reparse-points-to-n.patch b/patches/ntdll-Junction_Points/0013-ntdll-Allow-creation-of-dangling-reparse-points-to-n.patch index dc67500f..6fa216b3 100644 --- a/patches/ntdll-Junction_Points/0013-ntdll-Allow-creation-of-dangling-reparse-points-to-n.patch +++ b/patches/ntdll-Junction_Points/0013-ntdll-Allow-creation-of-dangling-reparse-points-to-n.patch @@ -1,4 +1,4 @@ -From ba365806d06a93493f1f91d6ca8ab3676a513136 Mon Sep 17 00:00:00 2001 +From 5c409a2387a0df100f0fe163d48ab86b66fefa20 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Tue, 30 Apr 2019 16:24:54 -0600 Subject: [PATCH] ntdll: Allow creation of dangling reparse points to @@ -6,15 +6,15 @@ Subject: [PATCH] ntdll: Allow creation of dangling reparse points to Signed-off-by: Erich E. Hoover --- - dlls/ntdll/unix/file.c | 18 ++++++++++++++++-- + dlls/ntdll/unix/file.c | 19 +++++++++++++++++-- include/winternl.h | 1 + - 2 files changed, 17 insertions(+), 2 deletions(-) + 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 0655371dc66..a9fcf6cc444 100644 +index ead0c48d62e..be57865f6b3 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -3378,7 +3378,8 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer +@@ -3388,7 +3388,8 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer /* if this is the last element, not finding it is not necessarily fatal */ if (!name_len) { @@ -24,11 +24,12 @@ index 0655371dc66..a9fcf6cc444 100644 { status = STATUS_OBJECT_NAME_NOT_FOUND; if (disposition != FILE_OPEN && disposition != FILE_OVERWRITE) -@@ -3398,6 +3399,19 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer +@@ -3408,6 +3409,20 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer status = STATUS_OBJECT_NAME_COLLISION; } } -+ else if (disposition == FILE_WINE_PATH && status == STATUS_OBJECT_PATH_NOT_FOUND) ++ else if (disposition == FILE_WINE_PATH && (status == STATUS_OBJECT_PATH_NOT_FOUND ++ || status == STATUS_OBJECT_NAME_NOT_FOUND)) + { + ret = ntdll_wcstoumbs( name, end - name, unix_name + pos + 1, MAX_DIR_ENTRY_LEN + 1, TRUE ); + if (ret > 0 && ret <= MAX_DIR_ENTRY_LEN) @@ -44,7 +45,7 @@ index 0655371dc66..a9fcf6cc444 100644 if (status != STATUS_SUCCESS) break; -@@ -5953,7 +5967,7 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer) +@@ -6098,7 +6113,7 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) status = STATUS_NO_MEMORY; goto cleanup; } @@ -54,10 +55,10 @@ index 0655371dc66..a9fcf6cc444 100644 free( unix_dest ); } diff --git a/include/winternl.h b/include/winternl.h -index d35d509eb41..561a83bd648 100644 +index 8bfc7de67d0..2daee57e50f 100644 --- a/include/winternl.h +++ b/include/winternl.h -@@ -2513,6 +2513,7 @@ typedef struct _RTL_ATOM_TABLE +@@ -2678,6 +2678,7 @@ typedef struct _RTL_ATOM_TABLE #define FILE_OVERWRITE 4 #define FILE_OVERWRITE_IF 5 #define FILE_MAXIMUM_DISPOSITION 5 @@ -66,5 +67,5 @@ index d35d509eb41..561a83bd648 100644 /* Characteristics of a File System */ #define FILE_REMOVABLE_MEDIA 0x00000001 -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0014-ntdll-Correctly-report-file-symbolic-links-as-files.patch b/patches/ntdll-Junction_Points/0014-ntdll-Correctly-report-file-symbolic-links-as-files.patch index 84a3fef4..75498602 100644 --- a/patches/ntdll-Junction_Points/0014-ntdll-Correctly-report-file-symbolic-links-as-files.patch +++ b/patches/ntdll-Junction_Points/0014-ntdll-Correctly-report-file-symbolic-links-as-files.patch @@ -1,28 +1,28 @@ -From 30353100c8647bd85bdf53fe95ccc039ca3ee867 Mon Sep 17 00:00:00 2001 +From 99f1cef882a3f8098c76cf0918b99882533d1bbd Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Sat, 30 Mar 2019 12:00:51 -0600 Subject: [PATCH] ntdll: Correctly report file symbolic links as files. Signed-off-by: Erich E. Hoover --- - dlls/ntdll/unix/file.c | 115 +++++++++++++++++++++++++++-------------- - 1 file changed, 77 insertions(+), 38 deletions(-) + dlls/ntdll/unix/file.c | 116 +++++++++++++++++++++++++++-------------- + 1 file changed, 78 insertions(+), 38 deletions(-) diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index a9fcf6cc444..5d41919267e 100644 +index be57865f6b3..94be474a0ff 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -1612,6 +1612,9 @@ static inline int get_file_xattr( char *hexattr, int attrlen ) +@@ -1606,6 +1606,9 @@ static inline int get_file_xattr( char *hexattr, int attrlen ) return 0; } -+NTSTATUS FILE_DecodeSymlink(const char *unix_src, char *unix_dest, int *unix_dest_len, -+ DWORD *tag, ULONG *flags, BOOL *is_dir); ++NTSTATUS get_symlink_properties(const char *unix_src, char *unix_dest, int *unix_dest_len, ++ DWORD *tag, ULONG *flags, BOOL *is_dir); + /* fetch the attributes of a file */ static inline ULONG get_file_attributes( const struct stat *st ) { -@@ -1696,10 +1699,15 @@ static int get_file_info( const char *path, struct stat *st, ULONG *attr ) +@@ -1690,10 +1693,15 @@ static int get_file_info( const char *path, struct stat *st, ULONG *attr ) if (ret == -1) return ret; if (S_ISLNK( st->st_mode )) { @@ -37,12 +37,12 @@ index a9fcf6cc444..5d41919267e 100644 + /* symbolic links (either junction points or NT symlinks) are "reparse points" */ + *attr |= FILE_ATTRIBUTE_REPARSE_POINT; + /* whether a reparse point is a file or a directory is stored inside the link target */ -+ if (FILE_DecodeSymlink( path, NULL, NULL, NULL, NULL, &is_dir ) == STATUS_SUCCESS) ++ if (get_symlink_properties( path, NULL, NULL, NULL, NULL, &is_dir ) == STATUS_SUCCESS) + st->st_mode = (st->st_mode & ~S_IFMT) | (is_dir ? S_IFDIR : S_IFREG); } else if (S_ISDIR( st->st_mode ) && (parent_path = malloc( strlen(path) + 4 ))) { -@@ -6070,46 +6078,35 @@ cleanup: +@@ -6219,46 +6227,35 @@ cleanup: } @@ -50,11 +50,12 @@ index a9fcf6cc444..5d41919267e 100644 - * Retrieve the unix name corresponding to a file handle and use that to find the destination of the - * symlink corresponding to that file handle. - */ --NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_size) -+NTSTATUS FILE_DecodeSymlink(const char *unix_src, char *unix_dest, int *unix_dest_len, -+ DWORD *tag, ULONG *flags, BOOL *is_dir) +-NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_size) ++NTSTATUS get_symlink_properties(const char *unix_src, char *unix_dest, int *unix_dest_len, ++ DWORD *tag, ULONG *flags, BOOL *is_dir) { - char *unix_src, unix_dest[PATH_MAX]; +- INT prefix_len, path_len, total_len; - VOID *subst_name, *print_name; - SIZE_T nt_dest_len = PATH_MAX; - BOOL dest_allocated = FALSE; @@ -66,7 +67,6 @@ index a9fcf6cc444..5d41919267e 100644 NTSTATUS status; - ULONG flags = 0; - WCHAR *nt_dest; -- INT prefix_len; + BOOL dir_flag; + char *p, *tmp; ssize_t ret; @@ -105,7 +105,7 @@ index a9fcf6cc444..5d41919267e 100644 p++; } if (*p++ != '/') -@@ -6117,7 +6114,7 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s +@@ -6266,7 +6263,7 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out status = STATUS_NOT_IMPLEMENTED; goto cleanup; } @@ -114,7 +114,7 @@ index a9fcf6cc444..5d41919267e 100644 for (i = 0; i < sizeof(ULONG)*8; i++) { char c = *p++; -@@ -6132,22 +6129,64 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s +@@ -6281,22 +6278,65 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out status = STATUS_NOT_IMPLEMENTED; goto cleanup; } @@ -160,8 +160,9 @@ index a9fcf6cc444..5d41919267e 100644 + * Retrieve the unix name corresponding to a file handle and use that to find the destination of the + * symlink corresponding to that file handle. + */ -+NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_size) ++NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_size) +{ ++ INT prefix_len, path_len, total_len; + char *unix_src, unix_dest[PATH_MAX]; + VOID *subst_name, *print_name; + SIZE_T nt_dest_len = PATH_MAX; @@ -172,7 +173,6 @@ index a9fcf6cc444..5d41919267e 100644 + NTSTATUS status; + ULONG flags = 0; + WCHAR *nt_dest; -+ INT prefix_len; + + if ((status = server_get_unix_fd( handle, FILE_ANY_ACCESS, &dest_fd, &needs_close, NULL, NULL ))) + return status; @@ -180,11 +180,12 @@ index a9fcf6cc444..5d41919267e 100644 + if ((status = server_get_unix_name( handle, &unix_src ))) + goto cleanup; + -+ if ((status = FILE_DecodeSymlink( unix_src, unix_dest, &unix_dest_len, &buffer->ReparseTag, &flags, NULL ))) ++ if ((status = get_symlink_properties( unix_src, unix_dest, &unix_dest_len, &buffer->ReparseTag, ++ &flags, NULL ))) + goto cleanup; /* convert the relative path into an absolute path */ if (flags == SYMLINK_FLAG_RELATIVE) -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0015-kernelbase-Convert-FILE_FLAG_OPEN_REPARSE_POINT-for-.patch b/patches/ntdll-Junction_Points/0015-kernelbase-Convert-FILE_FLAG_OPEN_REPARSE_POINT-for-.patch index 45de43fd..2fa3fef8 100644 --- a/patches/ntdll-Junction_Points/0015-kernelbase-Convert-FILE_FLAG_OPEN_REPARSE_POINT-for-.patch +++ b/patches/ntdll-Junction_Points/0015-kernelbase-Convert-FILE_FLAG_OPEN_REPARSE_POINT-for-.patch @@ -1,4 +1,4 @@ -From 17a86aec0579d7632eaa718800d51cdda191a4b4 Mon Sep 17 00:00:00 2001 +From 29337136ad7b6bdacd2910622ef3685ebacfe8fa Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Sun, 22 Nov 2020 22:35:50 -0700 Subject: [PATCH] kernelbase: Convert FILE_FLAG_OPEN_REPARSE_POINT for passing @@ -9,10 +9,10 @@ Subject: [PATCH] kernelbase: Convert FILE_FLAG_OPEN_REPARSE_POINT for passing 1 file changed, 2 insertions(+) diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c -index abfdade04ed..ad3c002d8c6 100644 +index e0a75c2ad08..7eabf5aa211 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c -@@ -723,6 +723,8 @@ static UINT get_nt_file_options( DWORD attributes ) +@@ -725,6 +725,8 @@ static UINT get_nt_file_options( DWORD attributes ) options |= FILE_RANDOM_ACCESS; if (attributes & FILE_FLAG_WRITE_THROUGH) options |= FILE_WRITE_THROUGH; @@ -22,5 +22,5 @@ index abfdade04ed..ad3c002d8c6 100644 } -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0016-server-Implement-FILE_OPEN_REPARSE_POINT-option.patch b/patches/ntdll-Junction_Points/0016-server-Implement-FILE_OPEN_REPARSE_POINT-option.patch index 882922e7..988e6f46 100644 --- a/patches/ntdll-Junction_Points/0016-server-Implement-FILE_OPEN_REPARSE_POINT-option.patch +++ b/patches/ntdll-Junction_Points/0016-server-Implement-FILE_OPEN_REPARSE_POINT-option.patch @@ -1,18 +1,26 @@ -From 663544d9d76dcd9d9338528a41a4e58343a8fc75 Mon Sep 17 00:00:00 2001 +From 05c1471fc29add8269c805692def9107de436bfa Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Sat, 12 Dec 2020 16:54:28 -0700 Subject: [PATCH] server: Implement FILE_OPEN_REPARSE_POINT option. --- - dlls/ntdll/tests/file.c | 8 ++++---- - server/fd.c | 18 +++++++++++++++++- - 2 files changed, 21 insertions(+), 5 deletions(-) + dlls/ntdll/tests/file.c | 27 +++++++++++++++++++++++---- + server/fd.c | 39 ++++++++++++++++++++++++++++++++------- + 2 files changed, 55 insertions(+), 11 deletions(-) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index 8938c5bf50c..59f10ea8cce 100644 +index e5cfbb68793..f3eecbbc708 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c -@@ -5299,7 +5299,7 @@ static void test_reparse_points(void) +@@ -5299,6 +5299,7 @@ static void test_reparse_points(void) + static const WCHAR dotW[] = {'.',0}; + REPARSE_DATA_BUFFER *buffer = NULL; + DWORD dwret, dwLen, dwFlags, err; ++ WCHAR buf[] = {0,0,0,0}; + HANDLE handle, token; + IO_STATUS_BLOCK iosb; + UNICODE_STRING nameW; +@@ -5386,7 +5387,7 @@ static void test_reparse_points(void) memset(&old_attrib, 0x00, sizeof(old_attrib)); old_attrib.LastAccessTime.QuadPart = 0x200deadcafebeef; dwret = NtSetInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation); @@ -21,7 +29,7 @@ index 8938c5bf50c..59f10ea8cce 100644 memset(&guid_buffer, 0x00, sizeof(guid_buffer)); guid_buffer.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; bret = DeviceIoControl(handle, FSCTL_DELETE_REPARSE_POINT, (LPVOID)&guid_buffer, -@@ -5308,7 +5308,7 @@ static void test_reparse_points(void) +@@ -5395,7 +5396,7 @@ static void test_reparse_points(void) memset(&new_attrib, 0x00, sizeof(new_attrib)); dwret = NtQueryInformationFile(handle, &iosb, &new_attrib, sizeof(new_attrib), FileBasicInformation); ok(dwret == STATUS_SUCCESS, "Failed to get junction point folder's attributes (0x%x).\n", dwret); @@ -30,7 +38,32 @@ index 8938c5bf50c..59f10ea8cce 100644 "Junction point folder's access time does not match.\n"); CloseHandle(handle); -@@ -5446,7 +5446,7 @@ static void test_reparse_points(void) +@@ -5476,6 +5477,24 @@ static void test_reparse_points(void) + ok(bret, "Failed to create symlink! (0x%x)\n", GetLastError()); + CloseHandle(handle); + ++ /* Check the size/data of the symlink target when opened with FILE_FLAG_OPEN_REPARSE_POINT */ ++ handle = CreateFileW(target_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, ++ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); ++ if (handle == INVALID_HANDLE_VALUE) ++ { ++ win_skip("Failed to open symlink file handle (0x%x).\n", GetLastError()); ++ goto cleanup; ++ } ++ ok(GetFileSize(handle, NULL) == sizeof(fooW), "symlink target size does not match (%d != %d)\n", ++ GetFileSize(handle, NULL), sizeof(fooW)); ++ bret = ReadFile(handle, &buf, sizeof(buf), &dwLen, NULL); ++ ok(bret, "Failed to read data from the symlink target.\n"); ++ ok(dwLen == sizeof(fooW), "Length of symlink target data does not match (%d != %d).\n", ++ dwLen, sizeof(fooW)); ++ ok(!memcmp(fooW, &buf, sizeof(fooW)), "Symlink target data does not match (%s != %s).\n", ++ wine_dbgstr_wn(buf, dwLen), wine_dbgstr_w(fooW)); ++ CloseHandle(handle); ++ + /* Check deleting a file symlink as if it were a directory */ + bret = RemoveDirectoryW(reparse_path); + todo_wine ok(!bret, "Succeeded in deleting file symlink as a directory!\n"); +@@ -5539,7 +5558,7 @@ static void test_reparse_points(void) memset(&old_attrib, 0x00, sizeof(old_attrib)); old_attrib.LastAccessTime.QuadPart = 0x200deadcafebeef; dwret = NtSetInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation); @@ -39,7 +72,7 @@ index 8938c5bf50c..59f10ea8cce 100644 memset(&guid_buffer, 0x00, sizeof(guid_buffer)); guid_buffer.ReparseTag = IO_REPARSE_TAG_SYMLINK; bret = DeviceIoControl(handle, FSCTL_DELETE_REPARSE_POINT, (LPVOID)&guid_buffer, -@@ -5455,7 +5455,7 @@ static void test_reparse_points(void) +@@ -5548,7 +5567,7 @@ static void test_reparse_points(void) memset(&new_attrib, 0x00, sizeof(new_attrib)); dwret = NtQueryInformationFile(handle, &iosb, &new_attrib, sizeof(new_attrib), FileBasicInformation); ok(dwret == STATUS_SUCCESS, "Failed to get symlink folder's attributes (0x%x).\n", dwret); @@ -49,7 +82,7 @@ index 8938c5bf50c..59f10ea8cce 100644 CloseHandle(handle); diff --git a/server/fd.c b/server/fd.c -index 4f43f41fb31..a01d4c9c0f7 100644 +index 2605adf96ff..4fe7e6de53f 100644 --- a/server/fd.c +++ b/server/fd.c @@ -107,6 +107,10 @@ @@ -63,19 +96,54 @@ index 4f43f41fb31..a01d4c9c0f7 100644 #if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_EPOLL_CREATE) # include # define USE_EPOLL -@@ -1958,6 +1962,11 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam +@@ -1898,6 +1902,14 @@ void get_nt_name( struct fd *fd, struct unicode_str *name ) + name->len = fd->nt_namelen; + } + ++int check_symlink( char *name ) ++{ ++ struct stat st; ++ ++ lstat( name, &st ); ++ return S_ISLNK( st.st_mode ); ++} ++ + /* open() wrapper that returns a struct fd with no fd user set */ + struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_name, + int flags, mode_t *mode, unsigned int access, +@@ -1958,6 +1970,18 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam } else rw_mode = O_RDONLY; ++ fd->unix_name = NULL; ++ if ((path = dup_fd_name( root, name ))) ++ { ++ int is_symlink = check_symlink( path ); +#if defined(O_SYMLINK) -+ if ((options & FILE_OPEN_REPARSE_POINT) && !(flags & O_CREAT)) -+ flags |= O_SYMLINK; ++ if (is_symlink && (options & FILE_OPEN_REPARSE_POINT) && !(flags & O_CREAT)) ++ flags |= O_SYMLINK; +#endif ++ fd->unlink_name = path; ++ fd->unix_name = realpath( path, NULL ); ++ } + if ((fd->unix_fd = open( name, rw_mode | (flags & ~O_TRUNC), *mode )) == -1) { /* if we tried to open a directory for write access, retry read-only */ -@@ -2431,6 +2440,7 @@ static struct fd *get_handle_fd_obj( struct process *process, obj_handle_t handl +@@ -1975,12 +1999,6 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam + } + + fd->nt_name = dup_nt_name( root, nt_name, &fd->nt_namelen ); +- fd->unix_name = NULL; +- if ((path = dup_fd_name( root, name ))) +- { +- fd->unlink_name = path; +- fd->unix_name = realpath( path, NULL ); +- } + + closed_fd->unix_fd = fd->unix_fd; + closed_fd->unlink = 0; +@@ -2425,6 +2443,7 @@ static struct fd *get_handle_fd_obj( struct process *process, obj_handle_t handl static int is_dir_empty( int fd ) { @@ -83,7 +151,7 @@ index 4f43f41fb31..a01d4c9c0f7 100644 DIR *dir; int empty; struct dirent *de; -@@ -2438,8 +2448,13 @@ static int is_dir_empty( int fd ) +@@ -2432,8 +2451,13 @@ static int is_dir_empty( int fd ) if ((fd = dup( fd )) == -1) return -1; @@ -98,7 +166,7 @@ index 4f43f41fb31..a01d4c9c0f7 100644 close( fd ); return -1; } -@@ -2451,6 +2466,7 @@ static int is_dir_empty( int fd ) +@@ -2445,6 +2469,7 @@ static int is_dir_empty( int fd ) empty = 0; } closedir( dir ); @@ -107,5 +175,5 @@ index 4f43f41fb31..a01d4c9c0f7 100644 } -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0017-ntdll-Allow-set_file_times_precise-to-work-on-repars.patch b/patches/ntdll-Junction_Points/0017-ntdll-Allow-set_file_times_precise-to-work-on-repars.patch index 66309313..b7efbe93 100644 --- a/patches/ntdll-Junction_Points/0017-ntdll-Allow-set_file_times_precise-to-work-on-repars.patch +++ b/patches/ntdll-Junction_Points/0017-ntdll-Allow-set_file_times_precise-to-work-on-repars.patch @@ -1,4 +1,4 @@ -From 9303f780842e09a09c2e7d0a763cdd93f4289b8a Mon Sep 17 00:00:00 2001 +From 2b954893dcd3d0088f214c6a12846a3cf1149e24 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Sun, 22 Nov 2020 22:37:33 -0700 Subject: [PATCH] ntdll: Allow set_file_times_precise to work on reparse @@ -11,10 +11,10 @@ Subject: [PATCH] ntdll: Allow set_file_times_precise to work on reparse 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac -index 11f57d13274..eea5847c51f 100644 +index 7553b22e76d..7ed08b6336d 100644 --- a/configure.ac +++ b/configure.ac -@@ -2226,7 +2226,8 @@ AC_CHECK_FUNCS(\ +@@ -2227,7 +2227,8 @@ AC_CHECK_FUNCS(\ sigprocmask \ symlink \ tcdrain \ @@ -25,10 +25,10 @@ index 11f57d13274..eea5847c51f 100644 CFLAGS="$ac_save_CFLAGS" diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index 59f10ea8cce..8938c5bf50c 100644 +index f3eecbbc708..17ed907d628 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c -@@ -5299,7 +5299,7 @@ static void test_reparse_points(void) +@@ -5387,7 +5387,7 @@ static void test_reparse_points(void) memset(&old_attrib, 0x00, sizeof(old_attrib)); old_attrib.LastAccessTime.QuadPart = 0x200deadcafebeef; dwret = NtSetInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation); @@ -37,7 +37,7 @@ index 59f10ea8cce..8938c5bf50c 100644 memset(&guid_buffer, 0x00, sizeof(guid_buffer)); guid_buffer.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; bret = DeviceIoControl(handle, FSCTL_DELETE_REPARSE_POINT, (LPVOID)&guid_buffer, -@@ -5308,7 +5308,7 @@ static void test_reparse_points(void) +@@ -5396,7 +5396,7 @@ static void test_reparse_points(void) memset(&new_attrib, 0x00, sizeof(new_attrib)); dwret = NtQueryInformationFile(handle, &iosb, &new_attrib, sizeof(new_attrib), FileBasicInformation); ok(dwret == STATUS_SUCCESS, "Failed to get junction point folder's attributes (0x%x).\n", dwret); @@ -46,7 +46,7 @@ index 59f10ea8cce..8938c5bf50c 100644 "Junction point folder's access time does not match.\n"); CloseHandle(handle); -@@ -5446,7 +5446,7 @@ static void test_reparse_points(void) +@@ -5558,7 +5558,7 @@ static void test_reparse_points(void) memset(&old_attrib, 0x00, sizeof(old_attrib)); old_attrib.LastAccessTime.QuadPart = 0x200deadcafebeef; dwret = NtSetInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation); @@ -55,7 +55,7 @@ index 59f10ea8cce..8938c5bf50c 100644 memset(&guid_buffer, 0x00, sizeof(guid_buffer)); guid_buffer.ReparseTag = IO_REPARSE_TAG_SYMLINK; bret = DeviceIoControl(handle, FSCTL_DELETE_REPARSE_POINT, (LPVOID)&guid_buffer, -@@ -5455,7 +5455,7 @@ static void test_reparse_points(void) +@@ -5567,7 +5567,7 @@ static void test_reparse_points(void) memset(&new_attrib, 0x00, sizeof(new_attrib)); dwret = NtQueryInformationFile(handle, &iosb, &new_attrib, sizeof(new_attrib), FileBasicInformation); ok(dwret == STATUS_SUCCESS, "Failed to get symlink folder's attributes (0x%x).\n", dwret); @@ -65,10 +65,10 @@ index 59f10ea8cce..8938c5bf50c 100644 CloseHandle(handle); diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 5d41919267e..4fb5afc2755 100644 +index 94be474a0ff..319f42e9e0c 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -1737,6 +1737,14 @@ static int get_file_info( const char *path, struct stat *st, ULONG *attr ) +@@ -1731,6 +1731,14 @@ static int get_file_info( const char *path, struct stat *st, ULONG *attr ) } @@ -83,7 +83,7 @@ index 5d41919267e..4fb5afc2755 100644 #if defined(__ANDROID__) && !defined(HAVE_FUTIMENS) static int futimens( int fd, const struct timespec spec[2] ) { -@@ -1752,7 +1760,7 @@ static int futimens( int fd, const struct timespec spec[2] ) +@@ -1746,7 +1754,7 @@ static int futimens( int fd, const struct timespec spec[2] ) static BOOL set_file_times_precise( int fd, const LARGE_INTEGER *mtime, const LARGE_INTEGER *atime, NTSTATUS *status ) { @@ -92,26 +92,26 @@ index 5d41919267e..4fb5afc2755 100644 struct timespec tv[2]; tv[0].tv_sec = tv[1].tv_sec = 0; -@@ -1768,10 +1776,16 @@ static BOOL set_file_times_precise( int fd, const LARGE_INTEGER *mtime, +@@ -1762,10 +1770,16 @@ static BOOL set_file_times_precise( int fd, const LARGE_INTEGER *mtime, tv[1].tv_nsec = (mtime->QuadPart % 10000000) * 100; } #ifdef __APPLE__ - if (!&futimens) return FALSE; + if (!&utimensat || !&futimens) return FALSE; -+#endif + #endif +- if (futimens( fd, tv ) == -1) *status = errno_to_status( errno ); +- else *status = STATUS_SUCCESS; +#if defined(HAVE_UTIMENSAT) + /* futimens does not work on O_PATH|O_NOFOLLOW (O_SYMLINK) file descriptors, so if fd is for a + * symlink then use utimensat with an empty path (.) and do not follow the link. */ + if (utimensat(fd, ".", tv, AT_SYMLINK_NOFOLLOW) == 0) *status = STATUS_SUCCESS; + else - #endif -- if (futimens( fd, tv ) == -1) *status = errno_to_status( errno ); -- else *status = STATUS_SUCCESS; ++#endif + if (futimens(fd, tv) == 0) *status = STATUS_SUCCESS; + else *status = errno_to_status( errno ); return TRUE; #else return FALSE; -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0018-server-Properly-handle-file-symlink-deletion.patch b/patches/ntdll-Junction_Points/0018-server-Properly-handle-file-symlink-deletion.patch index 024741e2..40cfce01 100644 --- a/patches/ntdll-Junction_Points/0018-server-Properly-handle-file-symlink-deletion.patch +++ b/patches/ntdll-Junction_Points/0018-server-Properly-handle-file-symlink-deletion.patch @@ -1,4 +1,4 @@ -From b17dd0d9dbfe6aff1654c1b8fe49019d5f97d139 Mon Sep 17 00:00:00 2001 +From 4ee6ccb3ca1639d81bd9e8ce572131905e6a8df1 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Sat, 30 Mar 2019 13:41:07 -0600 Subject: [PATCH] server: Properly handle file symlink deletion. @@ -10,10 +10,10 @@ Signed-off-by: Erich E. Hoover 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index 8938c5bf50c..c5c186748b6 100644 +index 17ed907d628..a4648dd65e0 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c -@@ -5391,18 +5391,18 @@ static void test_reparse_points(void) +@@ -5497,18 +5497,18 @@ static void test_reparse_points(void) /* Check deleting a file symlink as if it were a directory */ bret = RemoveDirectoryW(reparse_path); @@ -39,11 +39,11 @@ index 8938c5bf50c..c5c186748b6 100644 /* Create a blank slate for directory symlink tests */ bret = CreateDirectoryW(reparse_path, NULL); diff --git a/server/fd.c b/server/fd.c -index a01d4c9c0f7..c4de093b40b 100644 +index 4fe7e6de53f..fcffe4a4afd 100644 --- a/server/fd.c +++ b/server/fd.c -@@ -1902,6 +1902,55 @@ void get_nt_name( struct fd *fd, struct unicode_str *name ) - name->len = fd->nt_namelen; +@@ -1910,6 +1910,55 @@ int check_symlink( char *name ) + return S_ISLNK( st.st_mode ); } +static void decode_symlink(char *name, int *is_dir) @@ -98,7 +98,7 @@ index a01d4c9c0f7..c4de093b40b 100644 /* open() wrapper that returns a struct fd with no fd user set */ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_name, int flags, mode_t *mode, unsigned int access, -@@ -2003,6 +2052,7 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam +@@ -2012,6 +2061,7 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam { unsigned int err; struct inode *inode = get_inode( st.st_dev, st.st_ino, fd->unix_fd ); @@ -106,7 +106,7 @@ index a01d4c9c0f7..c4de093b40b 100644 if (!inode) { -@@ -2017,16 +2067,20 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam +@@ -2026,16 +2076,20 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam list_add_head( &inode->open, &fd->inode_entry ); closed_fd = NULL; @@ -130,5 +130,5 @@ index a01d4c9c0f7..c4de093b40b 100644 set_error( STATUS_FILE_IS_A_DIRECTORY ); goto error; -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0019-server-Properly-handle-deleting-dangling-symlinks.patch b/patches/ntdll-Junction_Points/0019-server-Properly-handle-deleting-dangling-symlinks.patch index e8515677..eaa763a9 100644 --- a/patches/ntdll-Junction_Points/0019-server-Properly-handle-deleting-dangling-symlinks.patch +++ b/patches/ntdll-Junction_Points/0019-server-Properly-handle-deleting-dangling-symlinks.patch @@ -1,4 +1,4 @@ -From 879b893a5429ba4aa0ced3fdefd284dcca0b0a7d Mon Sep 17 00:00:00 2001 +From 4f38f2552b1d31e427ea0c45f2146485a4ade4ee Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Sat, 12 Dec 2020 17:40:27 -0700 Subject: [PATCH] server: Properly handle deleting dangling symlinks. @@ -8,18 +8,18 @@ Subject: [PATCH] server: Properly handle deleting dangling symlinks. 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/fd.c b/server/fd.c -index c4de093b40b..da5bee3e5ec 100644 +index fcffe4a4afd..4ef3c673268 100644 --- a/server/fd.c +++ b/server/fd.c -@@ -2038,6 +2038,7 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam - { +@@ -2029,6 +2029,7 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam + #endif fd->unlink_name = path; fd->unix_name = realpath( path, NULL ); + if (!fd->unix_name) fd->unix_name = dup_fd_name( root, name ); /* dangling symlink */ } - closed_fd->unix_fd = fd->unix_fd; -@@ -2548,7 +2549,7 @@ static void set_fd_disposition( struct fd *fd, int unlink ) + if ((fd->unix_fd = open( name, rw_mode | (flags & ~O_TRUNC), *mode )) == -1) +@@ -2551,7 +2552,7 @@ static void set_fd_disposition( struct fd *fd, int unlink ) file_set_error(); return; } @@ -29,5 +29,5 @@ index c4de093b40b..da5bee3e5ec 100644 if (!(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH))) { -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0020-kernelbase-Use-FILE_OPEN_REPARSE_POINT-in-RemoveDire.patch b/patches/ntdll-Junction_Points/0020-kernelbase-Use-FILE_OPEN_REPARSE_POINT-in-RemoveDire.patch index b26c8377..c241ae03 100644 --- a/patches/ntdll-Junction_Points/0020-kernelbase-Use-FILE_OPEN_REPARSE_POINT-in-RemoveDire.patch +++ b/patches/ntdll-Junction_Points/0020-kernelbase-Use-FILE_OPEN_REPARSE_POINT-in-RemoveDire.patch @@ -1,4 +1,4 @@ -From b5c33b762b57ac73bc374e8aea6199730524ea59 Mon Sep 17 00:00:00 2001 +From 948fd2c1ec52cb7921d23b3fbaaf355075928611 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Sat, 12 Dec 2020 17:35:21 -0700 Subject: [PATCH] kernelbase: Use FILE_OPEN_REPARSE_POINT in @@ -9,10 +9,10 @@ Subject: [PATCH] kernelbase: Use FILE_OPEN_REPARSE_POINT in 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c -index ad3c002d8c6..375c00c7367 100644 +index 7eabf5aa211..80497c1ac97 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c -@@ -3482,7 +3482,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH RemoveDirectoryW( LPCWSTR path ) +@@ -3484,7 +3484,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH RemoveDirectoryW( LPCWSTR path ) InitializeObjectAttributes( &attr, &nt_name, OBJ_CASE_INSENSITIVE, 0, NULL ); status = NtOpenFile( &handle, DELETE | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, @@ -22,5 +22,5 @@ index ad3c002d8c6..375c00c7367 100644 if (!status) -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0021-ntdll-Always-report-symbolic-links-as-containing-zer.patch b/patches/ntdll-Junction_Points/0021-ntdll-Always-report-symbolic-links-as-containing-zer.patch index 55a57bea..d34a4c64 100644 --- a/patches/ntdll-Junction_Points/0021-ntdll-Always-report-symbolic-links-as-containing-zer.patch +++ b/patches/ntdll-Junction_Points/0021-ntdll-Always-report-symbolic-links-as-containing-zer.patch @@ -1,29 +1,27 @@ -From 4bbc98949eb154de067f68188bb2c2702782c48c Mon Sep 17 00:00:00 2001 +From de51b2d861f5cd8c9cca5b0a6b30be6ef8f94d7a Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Wed, 1 May 2019 12:06:20 -0600 Subject: [PATCH] ntdll: Always report symbolic links as containing zero bytes. Signed-off-by: Erich E. Hoover --- - dlls/ntdll/tests/file.c | 46 +++++++++++++++++++++++++++++++++++++++-- + dlls/ntdll/tests/file.c | 45 +++++++++++++++++++++++++++++++++++++++-- dlls/ntdll/unix/file.c | 2 ++ - 2 files changed, 46 insertions(+), 2 deletions(-) + 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index c5c186748b6..fb168549641 100644 +index a4648dd65e0..6e5082980bf 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c -@@ -5217,7 +5217,9 @@ static void test_reparse_points(void) +@@ -5299,6 +5299,7 @@ static void test_reparse_points(void) static const WCHAR dotW[] = {'.',0}; REPARSE_DATA_BUFFER *buffer = NULL; DWORD dwret, dwLen, dwFlags, err; + WIN32_FILE_ATTRIBUTE_DATA fad; - INT buffer_len, string_len; -+ WCHAR buf[] = {0,0,0,0}; + WCHAR buf[] = {0,0,0,0}; HANDLE handle, token; IO_STATUS_BLOCK iosb; - UNICODE_STRING nameW; -@@ -5350,8 +5352,6 @@ static void test_reparse_points(void) +@@ -5438,8 +5439,6 @@ static void test_reparse_points(void) "Unexpected junction point attributes (0x%x != 0x410)!\n", dwret); bret = RemoveDirectoryW(target_path); ok(bret, "Failed to delete junction point target!\n"); @@ -32,7 +30,7 @@ index c5c186748b6..fb168549641 100644 /* Establish permissions for symlink creation */ bret = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token); -@@ -5376,6 +5376,13 @@ static void test_reparse_points(void) +@@ -5464,6 +5463,13 @@ static void test_reparse_points(void) /* Delete the junction point directory and create a blank slate for symlink tests */ bret = RemoveDirectoryW(reparse_path); ok(bret, "Failed to delete junction point!\n"); @@ -46,7 +44,7 @@ index c5c186748b6..fb168549641 100644 /* Create the file symlink */ HeapFree(GetProcessHeap(), 0, buffer); -@@ -5389,6 +5396,37 @@ static void test_reparse_points(void) +@@ -5477,6 +5483,37 @@ static void test_reparse_points(void) ok(bret, "Failed to create symlink! (0x%x)\n", GetLastError()); CloseHandle(handle); @@ -81,10 +79,10 @@ index c5c186748b6..fb168549641 100644 + wine_dbgstr_wn(buf, dwLen), wine_dbgstr_w(fooW)); + CloseHandle(handle); + - /* Check deleting a file symlink as if it were a directory */ - bret = RemoveDirectoryW(reparse_path); - ok(!bret, "Succeeded in deleting file symlink as a directory!\n"); -@@ -5410,6 +5448,10 @@ static void test_reparse_points(void) + /* Check the size/data of the symlink target when opened with FILE_FLAG_OPEN_REPARSE_POINT */ + handle = CreateFileW(target_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); +@@ -5516,6 +5553,10 @@ static void test_reparse_points(void) dwret = GetFileAttributesW(reparse_path); ok(dwret != (DWORD)~0, "Path doesn't exist (attributes: 0x%x)!\n", dwret); ok(!(dwret & FILE_ATTRIBUTE_REPARSE_POINT), "File is already a reparse point! (attributes: %d)\n", dwret); @@ -96,10 +94,10 @@ index c5c186748b6..fb168549641 100644 /* Create the directory symlink */ HeapFree(GetProcessHeap(), 0, buffer); diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 4fb5afc2755..f77e64ee6b4 100644 +index 319f42e9e0c..2561afd6d53 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -1703,6 +1703,8 @@ static int get_file_info( const char *path, struct stat *st, ULONG *attr ) +@@ -1697,6 +1697,8 @@ static int get_file_info( const char *path, struct stat *st, ULONG *attr ) /* return information about the destination (unless this is a dangling symlink) */ stat( path, st ); @@ -109,5 +107,5 @@ index 4fb5afc2755..f77e64ee6b4 100644 *attr |= FILE_ATTRIBUTE_REPARSE_POINT; /* whether a reparse point is a file or a directory is stored inside the link target */ -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0022-ntdll-Find-dangling-symlinks-quickly.patch b/patches/ntdll-Junction_Points/0022-ntdll-Find-dangling-symlinks-quickly.patch index ec566792..1da959a7 100644 --- a/patches/ntdll-Junction_Points/0022-ntdll-Find-dangling-symlinks-quickly.patch +++ b/patches/ntdll-Junction_Points/0022-ntdll-Find-dangling-symlinks-quickly.patch @@ -1,4 +1,4 @@ -From 42675b2cbb3460a5c9fe57f6804d1f144fe27529 Mon Sep 17 00:00:00 2001 +From 60436fb0d205508589a76cda2476013b90f5b601 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Wed, 1 May 2019 17:48:51 -0600 Subject: [PATCH] ntdll: Find dangling symlinks quickly. @@ -12,7 +12,7 @@ Signed-off-by: Erich E. Hoover 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 9654f31cf30..f5e968c369e 100644 +index 2561afd6d53..e1b3b2692ee 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -2709,7 +2709,7 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i diff --git a/patches/ntdll-Junction_Points/0028-server-Fix-obtaining-information-about-a-symlink.patch b/patches/ntdll-Junction_Points/0023-server-Fix-obtaining-information-about-a-symlink.patch similarity index 81% rename from patches/ntdll-Junction_Points/0028-server-Fix-obtaining-information-about-a-symlink.patch rename to patches/ntdll-Junction_Points/0023-server-Fix-obtaining-information-about-a-symlink.patch index 1e901a1b..84a40196 100644 --- a/patches/ntdll-Junction_Points/0028-server-Fix-obtaining-information-about-a-symlink.patch +++ b/patches/ntdll-Junction_Points/0023-server-Fix-obtaining-information-about-a-symlink.patch @@ -1,4 +1,4 @@ -From 06e0409820f530dfe425693cba954d7defbfa722 Mon Sep 17 00:00:00 2001 +From 3bbfa5b27b5d1f5f0cbac1d3551b7da5731685c4 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Sat, 18 Jul 2020 09:13:29 -0600 Subject: [PATCH] server: Fix obtaining information about a symlink. @@ -11,10 +11,10 @@ Signed-off-by: Erich E. Hoover 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 0de80ebee7b..b52f0074175 100644 +index e1b3b2692ee..996e8d029d0 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -1995,7 +1995,7 @@ static NTSTATUS fill_file_info( const struct stat *st, ULONG attr, void *ptr, +@@ -1989,7 +1989,7 @@ static NTSTATUS fill_file_info( const struct stat *st, ULONG attr, void *ptr, } @@ -23,7 +23,7 @@ index 0de80ebee7b..b52f0074175 100644 { data_size_t size = 1024; NTSTATUS ret; -@@ -2008,6 +2008,7 @@ static NTSTATUS server_get_unix_name( HANDLE handle, char **unix_name ) +@@ -2002,6 +2002,7 @@ static NTSTATUS server_get_unix_name( HANDLE handle, char **unix_name ) SERVER_START_REQ( get_handle_unix_name ) { req->handle = wine_server_obj_handle( handle ); @@ -31,7 +31,7 @@ index 0de80ebee7b..b52f0074175 100644 wine_server_set_reply( req, name, size ); ret = wine_server_call( req ); size = reply->name_len; -@@ -2182,7 +2183,7 @@ static NTSTATUS get_mountmgr_fs_info( HANDLE handle, int fd, struct mountmgr_uni +@@ -2176,7 +2177,7 @@ static NTSTATUS get_mountmgr_fs_info( HANDLE handle, int fd, struct mountmgr_uni NTSTATUS status; int letter; @@ -40,7 +40,7 @@ index 0de80ebee7b..b52f0074175 100644 letter = find_dos_device( unix_name ); free( unix_name ); -@@ -4245,7 +4246,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, +@@ -4396,7 +4397,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, if (fd_get_file_info( fd, options, &st, &attr ) == -1) io->u.Status = errno_to_status( errno ); else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) io->u.Status = STATUS_INVALID_INFO_CLASS; @@ -49,7 +49,7 @@ index 0de80ebee7b..b52f0074175 100644 { LONG name_len = len - FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName); -@@ -4306,7 +4307,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, +@@ -4457,7 +4458,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, FILE_NAME_INFORMATION *info = ptr; char *unix_name; @@ -58,7 +58,7 @@ index 0de80ebee7b..b52f0074175 100644 { LONG name_len = len - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName); io->u.Status = fill_name_info( unix_name, info, &name_len ); -@@ -4320,7 +4321,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, +@@ -4471,7 +4472,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, FILE_NETWORK_OPEN_INFORMATION *info = ptr; char *unix_name; @@ -67,7 +67,7 @@ index 0de80ebee7b..b52f0074175 100644 { ULONG attributes; struct stat st; -@@ -5920,7 +5921,7 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer) +@@ -6066,7 +6067,7 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) if ((status = server_get_unix_fd( handle, FILE_SPECIAL_ACCESS, &dest_fd, &needs_close, NULL, NULL ))) return status; @@ -76,7 +76,7 @@ index 0de80ebee7b..b52f0074175 100644 goto cleanup; src_allocated = TRUE; if (flags == SYMLINK_FLAG_RELATIVE) -@@ -6198,7 +6199,7 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s +@@ -6347,7 +6348,7 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out if ((status = server_get_unix_fd( handle, FILE_ANY_ACCESS, &dest_fd, &needs_close, NULL, NULL ))) return status; @@ -84,8 +84,8 @@ index 0de80ebee7b..b52f0074175 100644 + if ((status = server_get_unix_name( handle, &unix_src, TRUE ))) goto cleanup; - if ((status = FILE_DecodeSymlink( unix_src, unix_dest, &unix_dest_len, &buffer->ReparseTag, &flags, NULL ))) -@@ -6306,7 +6307,7 @@ NTSTATUS FILE_RemoveSymlink(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer) + if ((status = get_symlink_properties( unix_src, unix_dest, &unix_dest_len, &buffer->ReparseTag, +@@ -6465,7 +6466,7 @@ NTSTATUS remove_reparse_point(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer) if ((status = server_get_unix_fd( handle, FILE_SPECIAL_ACCESS, &dest_fd, &needs_close, NULL, NULL ))) return status; @@ -94,7 +94,7 @@ index 0de80ebee7b..b52f0074175 100644 goto cleanup; TRACE( "Deleting symlink %s\n", unix_name ); -@@ -7411,7 +7412,7 @@ NTSTATUS WINAPI NtQueryObject( HANDLE handle, OBJECT_INFORMATION_CLASS info_clas +@@ -7559,7 +7560,7 @@ NTSTATUS WINAPI NtQueryObject( HANDLE handle, OBJECT_INFORMATION_CLASS info_clas /* first try as a file object */ @@ -104,10 +104,10 @@ index 0de80ebee7b..b52f0074175 100644 if (!(status = unix_to_nt_file_name( unix_name, &nt_name ))) { diff --git a/server/fd.c b/server/fd.c -index da5bee3e5ec..9a06492c3bb 100644 +index 4ef3c673268..dfab2e71f27 100644 --- a/server/fd.c +++ b/server/fd.c -@@ -2795,11 +2795,12 @@ DECL_HANDLER(get_handle_unix_name) +@@ -2798,11 +2798,12 @@ DECL_HANDLER(get_handle_unix_name) if ((fd = get_handle_fd_obj( current->process, req->handle, 0 ))) { @@ -124,10 +124,10 @@ index da5bee3e5ec..9a06492c3bb 100644 } else set_error( STATUS_OBJECT_TYPE_MISMATCH ); diff --git a/server/protocol.def b/server/protocol.def -index 7f3b785df51..f37e03cbaea 100644 +index abfd6d70240..af6424590dc 100644 --- a/server/protocol.def +++ b/server/protocol.def -@@ -1341,6 +1341,7 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT }; +@@ -1334,6 +1334,7 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT }; /* Get the Unix name from a file handle */ @REQ(get_handle_unix_name) obj_handle_t handle; /* file handle */ @@ -136,5 +136,5 @@ index 7f3b785df51..f37e03cbaea 100644 data_size_t name_len; /* unix name length */ VARARG(name,string); /* unix name */ -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0029-ntdll-Succeed-with-no-data-for-NtReadFile-on-reparse.patch b/patches/ntdll-Junction_Points/0024-ntdll-Succeed-with-no-data-for-NtReadFile-on-reparse.patch similarity index 84% rename from patches/ntdll-Junction_Points/0029-ntdll-Succeed-with-no-data-for-NtReadFile-on-reparse.patch rename to patches/ntdll-Junction_Points/0024-ntdll-Succeed-with-no-data-for-NtReadFile-on-reparse.patch index 31ea8c84..031d32a7 100644 --- a/patches/ntdll-Junction_Points/0029-ntdll-Succeed-with-no-data-for-NtReadFile-on-reparse.patch +++ b/patches/ntdll-Junction_Points/0024-ntdll-Succeed-with-no-data-for-NtReadFile-on-reparse.patch @@ -1,4 +1,4 @@ -From b68b7725bf2bf7524bcd52c560b5fa61c98a8316 Mon Sep 17 00:00:00 2001 +From 231cc5f69845313256722c5e9736acad5ccef279 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Mon, 23 Nov 2020 13:08:02 -0700 Subject: [PATCH] ntdll: Succeed with no data for NtReadFile on reparse points. @@ -11,10 +11,10 @@ Subject: [PATCH] ntdll: Succeed with no data for NtReadFile on reparse points. 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index fb168549641..05f6f67c4d3 100644 +index 6e5082980bf..c94a112b23b 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c -@@ -5405,7 +5405,7 @@ static void test_reparse_points(void) +@@ -5492,7 +5492,7 @@ static void test_reparse_points(void) ok(handle != INVALID_HANDLE_VALUE, "Failed to open symlink file.\n"); todo_wine ok(GetFileSize(handle, NULL) == 0, "symlink size is not zero\n"); bret = ReadFile(handle, &buf, sizeof(buf), &dwLen, NULL); @@ -24,10 +24,10 @@ index fb168549641..05f6f67c4d3 100644 CloseHandle(handle); diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index b52f0074175..06a010f02ce 100644 +index 996e8d029d0..8a4dfe9a34b 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -5291,6 +5291,11 @@ NTSTATUS WINAPI NtReadFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, vo +@@ -5436,6 +5436,11 @@ NTSTATUS WINAPI NtReadFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, vo goto done; } } @@ -40,7 +40,7 @@ index b52f0074175..06a010f02ce 100644 if (type == FD_TYPE_SERIAL && async_read && length) { diff --git a/server/file.c b/server/file.c -index f9ce0106c3b..ccac535e50f 100644 +index aff4d9e09e1..53c694177df 100644 --- a/server/file.c +++ b/server/file.c @@ -296,6 +296,7 @@ static enum server_fd_type file_get_fd_type( struct fd *fd ) @@ -52,10 +52,10 @@ index f9ce0106c3b..ccac535e50f 100644 if (S_ISDIR(file->mode)) return FD_TYPE_DIR; return FD_TYPE_CHAR; diff --git a/server/protocol.def b/server/protocol.def -index f37e03cbaea..8b376c613ca 100644 +index af6424590dc..edfd4cf88d5 100644 --- a/server/protocol.def +++ b/server/protocol.def -@@ -1361,6 +1361,7 @@ enum server_fd_type +@@ -1354,6 +1354,7 @@ enum server_fd_type { FD_TYPE_INVALID, /* invalid file (no associated fd) */ FD_TYPE_FILE, /* regular file */ @@ -64,5 +64,5 @@ index f37e03cbaea..8b376c613ca 100644 FD_TYPE_SOCKET, /* socket */ FD_TYPE_SERIAL, /* serial port */ -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0025-ntdll-Support-reparse-point-properties-in-fd_get_fil.patch b/patches/ntdll-Junction_Points/0025-ntdll-Support-reparse-point-properties-in-fd_get_fil.patch new file mode 100644 index 00000000..86212a52 --- /dev/null +++ b/patches/ntdll-Junction_Points/0025-ntdll-Support-reparse-point-properties-in-fd_get_fil.patch @@ -0,0 +1,101 @@ +From c2da4e7418c498619f5e8432bccd2c32a8c97f5c Mon Sep 17 00:00:00 2001 +From: "Erich E. Hoover" +Date: Wed, 25 Nov 2020 09:05:51 -0700 +Subject: [PATCH] ntdll: Support reparse point properties in fd_get_file_info. + +--- + dlls/ntdll/tests/file.c | 2 +- + dlls/ntdll/unix/file.c | 26 +++++++++++++++++++------- + 2 files changed, 20 insertions(+), 8 deletions(-) + +diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c +index c94a112b23b..b407d0ed18d 100644 +--- a/dlls/ntdll/tests/file.c ++++ b/dlls/ntdll/tests/file.c +@@ -5490,7 +5490,7 @@ static void test_reparse_points(void) + handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); + ok(handle != INVALID_HANDLE_VALUE, "Failed to open symlink file.\n"); +- todo_wine ok(GetFileSize(handle, NULL) == 0, "symlink size is not zero\n"); ++ ok(GetFileSize(handle, NULL) == 0, "symlink size is not zero\n"); + bret = ReadFile(handle, &buf, sizeof(buf), &dwLen, NULL); + ok(bret, "Failed to read data from the symlink.\n"); + ok(dwLen == 0, "Length of symlink data is not zero.\n"); +diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c +index 8a4dfe9a34b..0a35044f739 100644 +--- a/dlls/ntdll/unix/file.c ++++ b/dlls/ntdll/unix/file.c +@@ -1606,7 +1606,7 @@ static inline int get_file_xattr( char *hexattr, int attrlen ) + return 0; + } + +-NTSTATUS get_symlink_properties(const char *unix_src, char *unix_dest, int *unix_dest_len, ++NTSTATUS get_symlink_properties(int fd, const char *unix_src, char *unix_dest, int *unix_dest_len, + DWORD *tag, ULONG *flags, BOOL *is_dir); + + /* fetch the attributes of a file */ +@@ -1640,10 +1640,22 @@ static int fd_get_file_info( int fd, unsigned int options, struct stat *st, ULON + *attr = 0; + ret = fstat( fd, st ); + if (ret == -1) return ret; +- *attr |= get_file_attributes( st ); + /* consider mount points to be reparse points (IO_REPARSE_TAG_MOUNT_POINT) */ + if ((options & FILE_OPEN_REPARSE_POINT) && fd_is_mount_point( fd, st )) + *attr |= FILE_ATTRIBUTE_REPARSE_POINT; ++ if (S_ISLNK( st->st_mode )) ++ { ++ BOOL is_dir; ++ ++ /* symbolic links (either junction points or NT symlinks) are "reparse points" */ ++ *attr |= FILE_ATTRIBUTE_REPARSE_POINT; ++ /* symbolic links always report size 0 */ ++ st->st_size = 0; ++ if (get_symlink_properties( fd, "", NULL, NULL, NULL, NULL, &is_dir ) == STATUS_SUCCESS) ++ st->st_mode = (st->st_mode & ~S_IFMT) | (is_dir ? S_IFDIR : S_IFREG); ++ } ++ *attr |= get_file_attributes( st ); ++ + return ret; + } + +@@ -1702,7 +1714,7 @@ static int get_file_info( const char *path, struct stat *st, ULONG *attr ) + /* symbolic links (either junction points or NT symlinks) are "reparse points" */ + *attr |= FILE_ATTRIBUTE_REPARSE_POINT; + /* whether a reparse point is a file or a directory is stored inside the link target */ +- if (get_symlink_properties( path, NULL, NULL, NULL, NULL, &is_dir ) == STATUS_SUCCESS) ++ if (get_symlink_properties( AT_FDCWD, path, NULL, NULL, NULL, NULL, &is_dir ) == STATUS_SUCCESS) + st->st_mode = (st->st_mode & ~S_IFMT) | (is_dir ? S_IFDIR : S_IFREG); + } + else if (S_ISDIR( st->st_mode ) && (parent_path = malloc( strlen(path) + 4 ))) +@@ -6249,7 +6261,7 @@ cleanup: + } + + +-NTSTATUS get_symlink_properties(const char *unix_src, char *unix_dest, int *unix_dest_len, ++NTSTATUS get_symlink_properties(int fd, const char *unix_src, char *unix_dest, int *unix_dest_len, + DWORD *tag, ULONG *flags, BOOL *is_dir) + { + int len = MAX_PATH; +@@ -6265,7 +6277,7 @@ NTSTATUS get_symlink_properties(const char *unix_src, char *unix_dest, int *unix + tmp = malloc( len ); + else + tmp = unix_dest; +- if ((ret = readlink( unix_src, tmp, len )) < 0) ++ if ((ret = readlinkat( fd, unix_src, tmp, len )) < 0) + { + status = errno_to_status( errno ); + goto cleanup; +@@ -6356,8 +6368,8 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out + if ((status = server_get_unix_name( handle, &unix_src, TRUE ))) + goto cleanup; + +- if ((status = get_symlink_properties( unix_src, unix_dest, &unix_dest_len, &buffer->ReparseTag, +- &flags, NULL ))) ++ if ((status = get_symlink_properties( AT_FDCWD, unix_src, unix_dest, &unix_dest_len, ++ &buffer->ReparseTag, &flags, NULL ))) + goto cleanup; + + /* convert the relative path into an absolute path */ +-- +2.30.2 + diff --git a/patches/ntdll-Junction_Points/0031-ntdll-Add-support-for-FileAttributeTagInformation.patch b/patches/ntdll-Junction_Points/0026-ntdll-Add-support-for-FileAttributeTagInformation.patch similarity index 66% rename from patches/ntdll-Junction_Points/0031-ntdll-Add-support-for-FileAttributeTagInformation.patch rename to patches/ntdll-Junction_Points/0026-ntdll-Add-support-for-FileAttributeTagInformation.patch index ce755305..177821fd 100644 --- a/patches/ntdll-Junction_Points/0031-ntdll-Add-support-for-FileAttributeTagInformation.patch +++ b/patches/ntdll-Junction_Points/0026-ntdll-Add-support-for-FileAttributeTagInformation.patch @@ -1,18 +1,18 @@ -From 69a49f474062017e89448228923e9d3736409d80 Mon Sep 17 00:00:00 2001 +From 906233fe177919711b247c7e8e6be7b4a70370d6 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Wed, 25 Nov 2020 09:19:42 -0700 Subject: [PATCH] ntdll: Add support for FileAttributeTagInformation. --- - dlls/ntdll/tests/file.c | 6 ++++++ - dlls/ntdll/unix/file.c | 14 +++++++++++++- - 2 files changed, 19 insertions(+), 1 deletion(-) + dlls/ntdll/tests/file.c | 6 ++++++ + dlls/ntdll/unix/file.c | 4 +++- + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index 20c569c0962..3f4017d2aeb 100644 +index b407d0ed18d..47df69541c3 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c -@@ -5215,6 +5215,7 @@ static void test_reparse_points(void) +@@ -5297,6 +5297,7 @@ static void test_reparse_points(void) static WCHAR volW[] = {'c',':','\\',0}; REPARSE_GUID_DATA_BUFFER guid_buffer; static const WCHAR dotW[] = {'.',0}; @@ -20,7 +20,7 @@ index 20c569c0962..3f4017d2aeb 100644 REPARSE_DATA_BUFFER *buffer = NULL; DWORD dwret, dwLen, dwFlags, err; WIN32_FILE_ATTRIBUTE_DATA fad; -@@ -5224,6 +5225,7 @@ static void test_reparse_points(void) +@@ -5305,6 +5306,7 @@ static void test_reparse_points(void) IO_STATUS_BLOCK iosb; UNICODE_STRING nameW; TOKEN_PRIVILEGES tp; @@ -28,7 +28,7 @@ index 20c569c0962..3f4017d2aeb 100644 WCHAR *dest; LUID luid; BOOL bret; -@@ -5407,6 +5409,10 @@ static void test_reparse_points(void) +@@ -5494,6 +5496,10 @@ static void test_reparse_points(void) bret = ReadFile(handle, &buf, sizeof(buf), &dwLen, NULL); ok(bret, "Failed to read data from the symlink.\n"); ok(dwLen == 0, "Length of symlink data is not zero.\n"); @@ -40,30 +40,20 @@ index 20c569c0962..3f4017d2aeb 100644 /* Check the size/data of the symlink target */ diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 61fc8e821d9..1c19a05a1c8 100644 +index 0a35044f739..66c8b98a20a 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -4389,7 +4389,19 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, +@@ -4533,7 +4533,9 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, { FILE_ATTRIBUTE_TAG_INFORMATION *info = ptr; info->FileAttributes = attr; - info->ReparseTag = 0; /* FIXME */ + info->ReparseTag = 0; + if (attr & FILE_ATTRIBUTE_REPARSE_POINT) -+ { -+ char path[MAX_PATH]; -+ ssize_t len; -+ BOOL is_dir; -+ -+ if ((len = readlinkat( fd, "", path, sizeof(path))) != -1) -+ { -+ path[len] = 0; -+ get_symlink_properties(path, len, NULL, NULL, &info->ReparseTag, NULL, &is_dir); -+ } -+ } ++ get_symlink_properties( fd, "", NULL, NULL, &info->ReparseTag, NULL, NULL ); if ((options & FILE_OPEN_REPARSE_POINT) && fd_is_mount_point( fd, &st )) info->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; } -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0023-kernel32-Implement-CreateSymbolicLink-A-W-with-ntdll.patch b/patches/ntdll-Junction_Points/0027-kernel32-Implement-CreateSymbolicLink-A-W-with-ntdll.patch similarity index 99% rename from patches/ntdll-Junction_Points/0023-kernel32-Implement-CreateSymbolicLink-A-W-with-ntdll.patch rename to patches/ntdll-Junction_Points/0027-kernel32-Implement-CreateSymbolicLink-A-W-with-ntdll.patch index 05941a09..14b0aa1b 100644 --- a/patches/ntdll-Junction_Points/0023-kernel32-Implement-CreateSymbolicLink-A-W-with-ntdll.patch +++ b/patches/ntdll-Junction_Points/0027-kernel32-Implement-CreateSymbolicLink-A-W-with-ntdll.patch @@ -1,4 +1,4 @@ -From 36d6dca595e1db08be515989d741ccd512a662a3 Mon Sep 17 00:00:00 2001 +From 2bd2870ade6cd8b048ca93a90670c744142ff3f5 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Wed, 13 Mar 2019 16:02:05 -0600 Subject: [PATCH] kernel32: Implement CreateSymbolicLink[A|W] with ntdll @@ -161,7 +161,7 @@ index f49af6d5bfe..bc2cd84a65d 100644 + test_CreateSymbolicLink(); } diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c -index 375c00c7367..6040fa18059 100644 +index 80497c1ac97..68de99a2516 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -38,6 +38,7 @@ @@ -172,7 +172,7 @@ index 375c00c7367..6040fa18059 100644 #include "kernelbase.h" #include "wine/exception.h" -@@ -936,8 +937,106 @@ done: +@@ -938,8 +939,106 @@ done: */ BOOLEAN WINAPI /* DECLSPEC_HOTPATCH */ CreateSymbolicLinkW( LPCWSTR link, LPCWSTR target, DWORD flags ) { @@ -535,5 +535,5 @@ index 8a3771842a0..a55998e0d79 100644 } -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0024-kernel32-Add-reparse-support-to-FindNextFile.patch b/patches/ntdll-Junction_Points/0028-kernel32-Add-reparse-support-to-FindNextFile.patch similarity index 57% rename from patches/ntdll-Junction_Points/0024-kernel32-Add-reparse-support-to-FindNextFile.patch rename to patches/ntdll-Junction_Points/0028-kernel32-Add-reparse-support-to-FindNextFile.patch index e09516c7..8654e2e8 100644 --- a/patches/ntdll-Junction_Points/0024-kernel32-Add-reparse-support-to-FindNextFile.patch +++ b/patches/ntdll-Junction_Points/0028-kernel32-Add-reparse-support-to-FindNextFile.patch @@ -1,53 +1,42 @@ -From 2d3399e1071d0754dd3cd7f7ddb2906e561428fb Mon Sep 17 00:00:00 2001 +From 67ee6190599a8d820f333910b7a365d3fc255e29 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Wed, 29 May 2019 15:11:42 -0600 Subject: [PATCH] kernel32: Add reparse support to FindNextFile. Signed-off-by: Erich E. Hoover --- - dlls/kernelbase/file.c | 35 +++++++++++++++++++++++++++++++++++ - 1 file changed, 35 insertions(+) + dlls/kernelbase/file.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c -index 6040fa18059..2f89f78ffd4 100644 +index 68de99a2516..820f73a38cc 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c -@@ -1495,6 +1495,41 @@ BOOL WINAPI DECLSPEC_HOTPATCH FindNextFileW( HANDLE handle, WIN32_FIND_DATAW *da +@@ -1497,6 +1497,30 @@ BOOL WINAPI DECLSPEC_HOTPATCH FindNextFileW( HANDLE handle, WIN32_FIND_DATAW *da memcpy( data->cFileName, dir_info->FileName, dir_info->FileNameLength ); data->cFileName[dir_info->FileNameLength/sizeof(WCHAR)] = 0; + /* get reparse tag */ + if (dir_info->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) + { -+ REPARSE_DATA_BUFFER *buffer = NULL; -+ INT buffer_len; -+ HANDLE hlink; -+ DWORD dwret; -+ BOOL bret; -+ INT path_len = info->path.Length + dir_info->FileNameLength + -+ sizeof(WCHAR); ++ INT path_len = info->path.Length + dir_info->FileNameLength + sizeof(WCHAR); + WCHAR *path = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, path_len ); ++ FILE_ATTRIBUTE_TAG_INFORMATION taginfo; ++ IO_STATUS_BLOCK iosb; ++ NTSTATUS status; ++ HANDLE hlink; + + if (!path) break; + + lstrcpynW( path, info->path.Buffer, info->path.Length/sizeof(WCHAR) + 1 ); + lstrcatW( path, data->cFileName ); + -+ hlink = CreateFileW( path, GENERIC_READ | GENERIC_WRITE, 0, 0, -+ OPEN_EXISTING, ++ hlink = CreateFileW( path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0 ); + HeapFree( GetProcessHeap(), 0, path ); -+ buffer_len = sizeof(*buffer) + 2*MAX_PATH*sizeof(WCHAR); -+ buffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_len ); -+ if (!buffer) -+ { -+ CloseHandle( hlink ); -+ break; -+ } -+ bret = DeviceIoControl( hlink, FSCTL_GET_REPARSE_POINT, NULL, 0, (LPVOID)buffer, -+ buffer_len, &dwret, 0 ); -+ if (bret) data->dwReserved0 = buffer->ReparseTag; -+ HeapFree( GetProcessHeap(), 0, buffer ); ++ status = NtQueryInformationFile( hlink, &iosb, &taginfo, sizeof(taginfo), ++ FileAttributeTagInformation ); ++ if (status == STATUS_SUCCESS) data->dwReserved0 = taginfo.ReparseTag; + CloseHandle( hlink ); + } + @@ -55,5 +44,5 @@ index 6040fa18059..2f89f78ffd4 100644 { memcpy( data->cAlternateFileName, dir_info->ShortName, dir_info->ShortNameLength ); -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0025-wcmd-Display-reparse-point-type-in-directory-listing.patch b/patches/ntdll-Junction_Points/0029-wcmd-Display-reparse-point-type-in-directory-listing.patch similarity index 96% rename from patches/ntdll-Junction_Points/0025-wcmd-Display-reparse-point-type-in-directory-listing.patch rename to patches/ntdll-Junction_Points/0029-wcmd-Display-reparse-point-type-in-directory-listing.patch index c124ff94..c574c72e 100644 --- a/patches/ntdll-Junction_Points/0025-wcmd-Display-reparse-point-type-in-directory-listing.patch +++ b/patches/ntdll-Junction_Points/0029-wcmd-Display-reparse-point-type-in-directory-listing.patch @@ -1,4 +1,4 @@ -From c32b14dc99d3518a015ff8acc29d710304a45fc8 Mon Sep 17 00:00:00 2001 +From babea30f268f9c25429cd441499aa6c27e9313c1 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Wed, 29 May 2019 15:18:50 -0600 Subject: [PATCH] wcmd: Display reparse point type in directory listings. @@ -46,5 +46,5 @@ index 24b18bfa81b..40554aed368 100644 dir_count++; -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0030-ntdll-Support-reparse-point-properties-in-fd_get_fil.patch b/patches/ntdll-Junction_Points/0030-ntdll-Support-reparse-point-properties-in-fd_get_fil.patch deleted file mode 100644 index 96826782..00000000 --- a/patches/ntdll-Junction_Points/0030-ntdll-Support-reparse-point-properties-in-fd_get_fil.patch +++ /dev/null @@ -1,169 +0,0 @@ -From 3a617a56abd9277e83a0c23d60cb8cba09c4082f Mon Sep 17 00:00:00 2001 -From: "Erich E. Hoover" -Date: Wed, 25 Nov 2020 09:05:51 -0700 -Subject: [PATCH] ntdll: Support reparse point properties in fd_get_file_info. - ---- - dlls/ntdll/tests/file.c | 2 +- - dlls/ntdll/unix/file.c | 85 ++++++++++++++++++++++++----------------- - 2 files changed, 52 insertions(+), 35 deletions(-) - -diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c -index 05f6f67c4d3..20c569c0962 100644 ---- a/dlls/ntdll/tests/file.c -+++ b/dlls/ntdll/tests/file.c -@@ -5403,7 +5403,7 @@ static void test_reparse_points(void) - handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); - ok(handle != INVALID_HANDLE_VALUE, "Failed to open symlink file.\n"); -- todo_wine ok(GetFileSize(handle, NULL) == 0, "symlink size is not zero\n"); -+ ok(GetFileSize(handle, NULL) == 0, "symlink size is not zero\n"); - bret = ReadFile(handle, &buf, sizeof(buf), &dwLen, NULL); - ok(bret, "Failed to read data from the symlink.\n"); - ok(dwLen == 0, "Length of symlink data is not zero.\n"); -diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 06a010f02ce..61fc8e821d9 100644 ---- a/dlls/ntdll/unix/file.c -+++ b/dlls/ntdll/unix/file.c -@@ -1614,6 +1614,8 @@ static inline int get_file_xattr( char *hexattr, int attrlen ) - - NTSTATUS FILE_DecodeSymlink(const char *unix_src, char *unix_dest, int *unix_dest_len, - DWORD *tag, ULONG *flags, BOOL *is_dir); -+NTSTATUS get_symlink_properties(const char *target, int len, char *unix_dest, int *unix_dest_len, -+ DWORD *tag, ULONG *flags, BOOL *is_dir); - - /* fetch the attributes of a file */ - static inline ULONG get_file_attributes( const struct stat *st ) -@@ -1650,6 +1652,23 @@ static int fd_get_file_info( int fd, unsigned int options, struct stat *st, ULON - /* consider mount points to be reparse points (IO_REPARSE_TAG_MOUNT_POINT) */ - if ((options & FILE_OPEN_REPARSE_POINT) && fd_is_mount_point( fd, st )) - *attr |= FILE_ATTRIBUTE_REPARSE_POINT; -+ if (S_ISLNK( st->st_mode )) -+ { -+ char path[MAX_PATH]; -+ ssize_t len; -+ BOOL is_dir; -+ -+ if ((len = readlinkat( fd, "", path, sizeof(path))) == -1) goto done; -+ path[len] = 0; -+ /* symbolic links (either junction points or NT symlinks) are "reparse points" */ -+ *attr |= FILE_ATTRIBUTE_REPARSE_POINT; -+ /* symbolic links always report size 0 */ -+ st->st_size = 0; -+ if (get_symlink_properties(path, len, NULL, NULL, NULL, NULL, &is_dir) == STATUS_SUCCESS) -+ st->st_mode = (st->st_mode & ~S_IFMT) | (is_dir ? S_IFDIR : S_IFREG); -+ } -+ -+done: - return ret; - } - -@@ -6100,42 +6119,22 @@ cleanup: - } - - --NTSTATUS FILE_DecodeSymlink(const char *unix_src, char *unix_dest, int *unix_dest_len, -- DWORD *tag, ULONG *flags, BOOL *is_dir) -+NTSTATUS get_symlink_properties(const char *target, int len, char *unix_dest, int *unix_dest_len, -+ DWORD *tag, ULONG *flags, BOOL *is_dir) - { -- int len = MAX_PATH; -+ const char *p = target; - DWORD reparse_tag; -- NTSTATUS status; - BOOL dir_flag; -- char *p, *tmp; -- ssize_t ret; - int i; - -- if (unix_dest_len) len = *unix_dest_len; -- if (!unix_dest) -- tmp = malloc( len ); -- else -- tmp = unix_dest; -- if ((ret = readlink( unix_src, tmp, len )) < 0) -- { -- status = errno_to_status( errno ); -- goto cleanup; -- } -- len = ret; -- tmp[len] = 0; -- - /* Decode the reparse tag from the symlink */ -- p = tmp; - if (*p == '.') - { - if (flags) *flags = SYMLINK_FLAG_RELATIVE; - p++; - } - if (*p++ != '/') -- { -- status = STATUS_NOT_IMPLEMENTED; -- goto cleanup; -- } -+ return STATUS_NOT_IMPLEMENTED; - reparse_tag = 0; - for (i = 0; i < sizeof(ULONG)*8; i++) - { -@@ -6147,10 +6146,7 @@ NTSTATUS FILE_DecodeSymlink(const char *unix_src, char *unix_dest, int *unix_des - else if (c == '.' && *p++ == '/') - val = 1; - else -- { -- status = STATUS_NOT_IMPLEMENTED; -- goto cleanup; -- } -+ return STATUS_NOT_IMPLEMENTED; - reparse_tag |= (val << i); - } - /* skip past the directory/file flag */ -@@ -6163,19 +6159,40 @@ NTSTATUS FILE_DecodeSymlink(const char *unix_src, char *unix_dest, int *unix_des - else if (c == '.' && *p++ == '/') - dir_flag = TRUE; - else -- { -- status = STATUS_NOT_IMPLEMENTED; -- goto cleanup; -- } -+ return STATUS_NOT_IMPLEMENTED; - } - else - dir_flag = TRUE; -- len -= (p - tmp); -+ len -= (p - target); - if (tag) *tag = reparse_tag; - if (is_dir) *is_dir = dir_flag; - if (unix_dest) memmove(unix_dest, p, len + 1); - if (unix_dest_len) *unix_dest_len = len; -- status = STATUS_SUCCESS; -+ return STATUS_SUCCESS; -+} -+ -+ -+NTSTATUS FILE_DecodeSymlink(const char *unix_src, char *unix_dest, int *unix_dest_len, -+ DWORD *tag, ULONG *flags, BOOL *is_dir) -+{ -+ int len = MAX_PATH; -+ NTSTATUS status; -+ ssize_t ret; -+ char *tmp; -+ -+ if (unix_dest_len) len = *unix_dest_len; -+ if (!unix_dest) -+ tmp = malloc( len ); -+ else -+ tmp = unix_dest; -+ if ((ret = readlink( unix_src, tmp, len )) < 0) -+ { -+ status = errno_to_status( errno ); -+ goto cleanup; -+ } -+ len = ret; -+ tmp[len] = 0; -+ status = get_symlink_properties(tmp, len, unix_dest, unix_dest_len, tag, flags, is_dir); - - cleanup: - if (!unix_dest) free( tmp ); --- -2.20.1 - diff --git a/patches/ntdll-Junction_Points/0026-wcmd-Show-reparse-point-target-in-directory-listing.patch b/patches/ntdll-Junction_Points/0030-wcmd-Show-reparse-point-target-in-directory-listing.patch similarity index 97% rename from patches/ntdll-Junction_Points/0026-wcmd-Show-reparse-point-target-in-directory-listing.patch rename to patches/ntdll-Junction_Points/0030-wcmd-Show-reparse-point-target-in-directory-listing.patch index 174742d7..21873d87 100644 --- a/patches/ntdll-Junction_Points/0026-wcmd-Show-reparse-point-target-in-directory-listing.patch +++ b/patches/ntdll-Junction_Points/0030-wcmd-Show-reparse-point-target-in-directory-listing.patch @@ -1,4 +1,4 @@ -From 652ceaf374295989dec1d32157f3f81707af08ea Mon Sep 17 00:00:00 2001 +From c36ba7d9de06abcbacdca63cdabdb2b91a17a0fb Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Wed, 29 May 2019 15:38:30 -0600 Subject: [PATCH] wcmd: Show reparse point target in directory listing. @@ -62,5 +62,5 @@ index 40554aed368..0618ffec8d1 100644 if (!((lstrcmpW(fd[i].cFileName, L".") == 0) || (lstrcmpW(fd[i].cFileName, L"..") == 0))) { -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0027-wcmd-Add-junction-point-support-to-mklink.patch b/patches/ntdll-Junction_Points/0031-wcmd-Add-junction-point-support-to-mklink.patch similarity index 93% rename from patches/ntdll-Junction_Points/0027-wcmd-Add-junction-point-support-to-mklink.patch rename to patches/ntdll-Junction_Points/0031-wcmd-Add-junction-point-support-to-mklink.patch index 1eca8822..44a76e22 100644 --- a/patches/ntdll-Junction_Points/0027-wcmd-Add-junction-point-support-to-mklink.patch +++ b/patches/ntdll-Junction_Points/0031-wcmd-Add-junction-point-support-to-mklink.patch @@ -1,4 +1,4 @@ -From 4d2c17cf2ccd327c57be77429f86221c9d984b72 Mon Sep 17 00:00:00 2001 +From c54be21fe819e7bb157a0a0edc3f9a3d3636d765 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Wed, 29 May 2019 16:01:45 -0600 Subject: [PATCH] wcmd: Add junction point support to mklink. @@ -9,7 +9,7 @@ Signed-off-by: Erich E. Hoover 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c -index 0fb40d94e49..07d34c10706 100644 +index 502694ffc46..bb1a5578911 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -31,6 +31,9 @@ @@ -22,7 +22,7 @@ index 0fb40d94e49..07d34c10706 100644 WINE_DEFAULT_DEBUG_CHANNEL(cmd); -@@ -4973,6 +4976,49 @@ void WCMD_color (void) { +@@ -4969,6 +4972,49 @@ void WCMD_color (void) { } } @@ -72,7 +72,7 @@ index 0fb40d94e49..07d34c10706 100644 /**************************************************************************** * WCMD_mklink */ -@@ -5021,7 +5067,7 @@ void WCMD_mklink(WCHAR *args) +@@ -5017,7 +5063,7 @@ void WCMD_mklink(WCHAR *args) else if(!junction) ret = CreateSymbolicLinkW(file1, file2, isdir); else @@ -82,5 +82,5 @@ index 0fb40d94e49..07d34c10706 100644 if(!ret) WCMD_output_stderr(WCMD_LoadMessage(WCMD_READFAIL), file1); -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0032-server-Properly-handle-renames-involving-symlinks.patch b/patches/ntdll-Junction_Points/0032-server-Properly-handle-renames-involving-symlinks.patch index 96478d93..71c7cd83 100644 --- a/patches/ntdll-Junction_Points/0032-server-Properly-handle-renames-involving-symlinks.patch +++ b/patches/ntdll-Junction_Points/0032-server-Properly-handle-renames-involving-symlinks.patch @@ -1,4 +1,4 @@ -From e509d8607a0c85846b8d060041f8d16704f2f749 Mon Sep 17 00:00:00 2001 +From 68254807f957ad327c12c8bfaf6b5dcfad9a4efd Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Sat, 6 Feb 2021 12:17:23 -0700 Subject: [PATCH] server: Properly handle renames involving symlinks. @@ -8,10 +8,10 @@ Subject: [PATCH] server: Properly handle renames involving symlinks. 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server/fd.c b/server/fd.c -index 9a06492c3bb..ee58aa3c8ae 100644 +index dfab2e71f27..c7c4ad280ef 100644 --- a/server/fd.c +++ b/server/fd.c -@@ -2628,7 +2628,7 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da +@@ -2631,7 +2631,7 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da goto failed; } @@ -20,7 +20,7 @@ index 9a06492c3bb..ee58aa3c8ae 100644 { if (!fstat( fd->unix_fd, &st2 ) && st.st_ino == st2.st_ino && st.st_dev == st2.st_dev) { -@@ -2644,7 +2644,7 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da +@@ -2647,7 +2647,7 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da } /* can't replace directories or special files */ @@ -29,7 +29,7 @@ index 9a06492c3bb..ee58aa3c8ae 100644 { set_error( STATUS_ACCESS_DENIED ); goto failed; -@@ -2703,6 +2703,8 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da +@@ -2706,6 +2706,8 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da free( fd->unlink_name ); free( fd->unix_name ); fd->closed->unix_name = fd->unix_name = realpath( name, NULL ); @@ -39,5 +39,5 @@ index 9a06492c3bb..ee58aa3c8ae 100644 set_error( STATUS_NO_MEMORY ); return; -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0033-kernelbase-Use-FILE_OPEN_REPARSE_POINT-in-MoveFileWi.patch b/patches/ntdll-Junction_Points/0033-kernelbase-Use-FILE_OPEN_REPARSE_POINT-in-MoveFileWi.patch index b0a0ae3d..20ccfd5e 100644 --- a/patches/ntdll-Junction_Points/0033-kernelbase-Use-FILE_OPEN_REPARSE_POINT-in-MoveFileWi.patch +++ b/patches/ntdll-Junction_Points/0033-kernelbase-Use-FILE_OPEN_REPARSE_POINT-in-MoveFileWi.patch @@ -1,4 +1,4 @@ -From 8d31be068c4e5fbf31c66b8a28a9a7a666a2e2ab Mon Sep 17 00:00:00 2001 +From 697dae8422849f3adadf523b9fa20f7db21739f8 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Sat, 6 Feb 2021 12:46:30 -0700 Subject: [PATCH] kernelbase: Use FILE_OPEN_REPARSE_POINT in @@ -9,10 +9,10 @@ Subject: [PATCH] kernelbase: Use FILE_OPEN_REPARSE_POINT in 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c -index 2f89f78ffd4..795cdcbfaf5 100644 +index 820f73a38cc..7ad352d3451 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c -@@ -2592,7 +2592,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH MoveFileWithProgressW( const WCHAR *source, const +@@ -2583,7 +2583,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH MoveFileWithProgressW( const WCHAR *source, const status = NtOpenFile( &source_handle, DELETE | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, @@ -22,5 +22,5 @@ index 2f89f78ffd4..795cdcbfaf5 100644 if (!set_ntstatus( status )) goto error; -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0034-kernelbase-Use-FILE_OPEN_REPARSE_POINT-in-DeleteFile.patch b/patches/ntdll-Junction_Points/0034-kernelbase-Use-FILE_OPEN_REPARSE_POINT-in-DeleteFile.patch index b1cc9f52..267ebab9 100644 --- a/patches/ntdll-Junction_Points/0034-kernelbase-Use-FILE_OPEN_REPARSE_POINT-in-DeleteFile.patch +++ b/patches/ntdll-Junction_Points/0034-kernelbase-Use-FILE_OPEN_REPARSE_POINT-in-DeleteFile.patch @@ -1,4 +1,4 @@ -From 0646ca34d0052611e66af79cfb1196177260e1c9 Mon Sep 17 00:00:00 2001 +From 7150cb17fa6b349530dea3a808c8cfbd55acc16c Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Sat, 6 Feb 2021 12:52:51 -0700 Subject: [PATCH] kernelbase: Use FILE_OPEN_REPARSE_POINT in DeleteFile. @@ -8,10 +8,10 @@ Subject: [PATCH] kernelbase: Use FILE_OPEN_REPARSE_POINT in DeleteFile. 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c -index 795cdcbfaf5..73655ca6ffa 100644 +index 7ad352d3451..b96de9948b8 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c -@@ -1080,7 +1080,8 @@ BOOL WINAPI DECLSPEC_HOTPATCH DeleteFileW( LPCWSTR path ) +@@ -1082,7 +1082,8 @@ BOOL WINAPI DECLSPEC_HOTPATCH DeleteFileW( LPCWSTR path ) status = NtCreateFile(&hFile, SYNCHRONIZE | DELETE, &attr, &io, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, @@ -22,5 +22,5 @@ index 795cdcbfaf5..73655ca6ffa 100644 RtlFreeUnicodeString( &nameW ); -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0035-ntdll-Treat-undecoded-unix-symlinks-as-NT-symlinks.patch b/patches/ntdll-Junction_Points/0035-ntdll-Treat-undecoded-unix-symlinks-as-NT-symlinks.patch deleted file mode 100644 index acdade65..00000000 --- a/patches/ntdll-Junction_Points/0035-ntdll-Treat-undecoded-unix-symlinks-as-NT-symlinks.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 2851b3072e7776cd87a3b79aa7edc99813fbcf2e Mon Sep 17 00:00:00 2001 -From: "Erich E. Hoover" -Date: Sat, 6 Feb 2021 16:32:44 -0700 -Subject: [PATCH] ntdll: Treat undecoded unix symlinks as NT symlinks. - ---- - dlls/ntdll/unix/file.c | 39 ++++++++++++++++++++++++++++----------- - 1 file changed, 28 insertions(+), 11 deletions(-) - -diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 1c19a05a1c8..b6e49590f62 100644 ---- a/dlls/ntdll/unix/file.c -+++ b/dlls/ntdll/unix/file.c -@@ -1614,8 +1614,8 @@ static inline int get_file_xattr( char *hexattr, int attrlen ) - - NTSTATUS FILE_DecodeSymlink(const char *unix_src, char *unix_dest, int *unix_dest_len, - DWORD *tag, ULONG *flags, BOOL *is_dir); --NTSTATUS get_symlink_properties(const char *target, int len, char *unix_dest, int *unix_dest_len, -- DWORD *tag, ULONG *flags, BOOL *is_dir); -+void get_symlink_properties(const char *target, int len, char *unix_dest, int *unix_dest_len, -+ DWORD *tag, ULONG *flags, BOOL *is_dir); - - /* fetch the attributes of a file */ - static inline ULONG get_file_attributes( const struct stat *st ) -@@ -1664,8 +1664,8 @@ static int fd_get_file_info( int fd, unsigned int options, struct stat *st, ULON - *attr |= FILE_ATTRIBUTE_REPARSE_POINT; - /* symbolic links always report size 0 */ - st->st_size = 0; -- if (get_symlink_properties(path, len, NULL, NULL, NULL, NULL, &is_dir) == STATUS_SUCCESS) -- st->st_mode = (st->st_mode & ~S_IFMT) | (is_dir ? S_IFDIR : S_IFREG); -+ get_symlink_properties(path, len, NULL, NULL, NULL, NULL, &is_dir); -+ st->st_mode = (st->st_mode & ~S_IFMT) | (is_dir ? S_IFDIR : S_IFREG); - } - - done: -@@ -6131,10 +6131,11 @@ cleanup: - } - - --NTSTATUS get_symlink_properties(const char *target, int len, char *unix_dest, int *unix_dest_len, -- DWORD *tag, ULONG *flags, BOOL *is_dir) -+void get_symlink_properties(const char *target, int len, char *unix_dest, int *unix_dest_len, -+ DWORD *tag, ULONG *flags, BOOL *is_dir) - { - const char *p = target; -+ int decoded = FALSE; - DWORD reparse_tag; - BOOL dir_flag; - int i; -@@ -6146,7 +6147,7 @@ NTSTATUS get_symlink_properties(const char *target, int len, char *unix_dest, in - p++; - } - if (*p++ != '/') -- return STATUS_NOT_IMPLEMENTED; -+ goto done; - reparse_tag = 0; - for (i = 0; i < sizeof(ULONG)*8; i++) - { -@@ -6158,7 +6159,7 @@ NTSTATUS get_symlink_properties(const char *target, int len, char *unix_dest, in - else if (c == '.' && *p++ == '/') - val = 1; - else -- return STATUS_NOT_IMPLEMENTED; -+ goto done; - reparse_tag |= (val << i); - } - /* skip past the directory/file flag */ -@@ -6171,16 +6172,31 @@ NTSTATUS get_symlink_properties(const char *target, int len, char *unix_dest, in - else if (c == '.' && *p++ == '/') - dir_flag = TRUE; - else -- return STATUS_NOT_IMPLEMENTED; -+ goto done; - } - else - dir_flag = TRUE; -+ decoded = TRUE; -+ -+done: -+ if (!decoded) -+ { -+ /* treat undecoded unix symlinks as NT symlinks */ -+ struct stat st; -+ -+ p = target; -+ if (flags && *p != '/') *flags = SYMLINK_FLAG_RELATIVE; -+ reparse_tag = IO_REPARSE_TAG_SYMLINK; -+ if (!stat( target, &st )) -+ dir_flag = S_ISDIR(st.st_mode); -+ else -+ dir_flag = FALSE; /* treat dangling symlinks as files */ -+ } - len -= (p - target); - if (tag) *tag = reparse_tag; - if (is_dir) *is_dir = dir_flag; - if (unix_dest) memmove(unix_dest, p, len + 1); - if (unix_dest_len) *unix_dest_len = len; -- return STATUS_SUCCESS; - } - - -@@ -6204,7 +6220,8 @@ NTSTATUS FILE_DecodeSymlink(const char *unix_src, char *unix_dest, int *unix_des - } - len = ret; - tmp[len] = 0; -- status = get_symlink_properties(tmp, len, unix_dest, unix_dest_len, tag, flags, is_dir); -+ get_symlink_properties(tmp, len, unix_dest, unix_dest_len, tag, flags, is_dir); -+ status = STATUS_SUCCESS; - - cleanup: - if (!unix_dest) free( tmp ); --- -2.20.1 - diff --git a/patches/ntdll-Junction_Points/0035-ntdll-Treat-undecoded-unix-symlinks-as-WSL-Linux-Uni.patch b/patches/ntdll-Junction_Points/0035-ntdll-Treat-undecoded-unix-symlinks-as-WSL-Linux-Uni.patch new file mode 100644 index 00000000..88e13869 --- /dev/null +++ b/patches/ntdll-Junction_Points/0035-ntdll-Treat-undecoded-unix-symlinks-as-WSL-Linux-Uni.patch @@ -0,0 +1,178 @@ +From ebba56121b254c640ef9fb9b2888bc9b08062080 Mon Sep 17 00:00:00 2001 +From: "Erich E. Hoover" +Date: Sat, 6 Feb 2021 16:32:44 -0700 +Subject: [PATCH] ntdll: Treat undecoded unix symlinks as WSL Linux/Unix + symlinks. + +--- + dlls/ntdll/unix/file.c | 62 ++++++++++++++++++++++++------------------ + include/ntifs.h | 4 +++ + include/winnt.h | 1 + + 3 files changed, 41 insertions(+), 26 deletions(-) + +diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c +index 66c8b98a20a..62593fa8526 100644 +--- a/dlls/ntdll/unix/file.c ++++ b/dlls/ntdll/unix/file.c +@@ -6266,9 +6266,10 @@ cleanup: + NTSTATUS get_symlink_properties(int fd, const char *unix_src, char *unix_dest, int *unix_dest_len, + DWORD *tag, ULONG *flags, BOOL *is_dir) + { ++ NTSTATUS status = STATUS_SUCCESS; + int len = MAX_PATH; ++ int decoded = FALSE; + DWORD reparse_tag; +- NTSTATUS status; + BOOL dir_flag; + char *p, *tmp; + ssize_t ret; +@@ -6295,10 +6296,7 @@ NTSTATUS get_symlink_properties(int fd, const char *unix_src, char *unix_dest, i + p++; + } + if (*p++ != '/') +- { +- status = STATUS_NOT_IMPLEMENTED; +- goto cleanup; +- } ++ goto done; + reparse_tag = 0; + for (i = 0; i < sizeof(ULONG)*8; i++) + { +@@ -6310,10 +6308,7 @@ NTSTATUS get_symlink_properties(int fd, const char *unix_src, char *unix_dest, i + else if (c == '.' && *p++ == '/') + val = 1; + else +- { +- status = STATUS_NOT_IMPLEMENTED; +- goto cleanup; +- } ++ goto done; + reparse_tag |= (val << i); + } + /* skip past the directory/file flag */ +@@ -6326,19 +6321,31 @@ NTSTATUS get_symlink_properties(int fd, const char *unix_src, char *unix_dest, i + else if (c == '.' && *p++ == '/') + dir_flag = TRUE; + else +- { +- status = STATUS_NOT_IMPLEMENTED; +- goto cleanup; +- } ++ goto done; + } + else + dir_flag = TRUE; ++ decoded = TRUE; ++ ++done: ++ if (!decoded) ++ { ++ /* treat undecoded unix symlinks as NT symlinks */ ++ struct stat st; ++ ++ p = tmp; ++ reparse_tag = IO_REPARSE_TAG_LX_SYMLINK; ++ if (flags && *p != '/') *flags = SYMLINK_FLAG_RELATIVE; ++ if (!stat( tmp, &st )) ++ dir_flag = S_ISDIR(st.st_mode); ++ else ++ dir_flag = FALSE; /* treat dangling symlinks as files */ ++ } + len -= (p - tmp); + if (tag) *tag = reparse_tag; + if (is_dir) *is_dir = dir_flag; + if (unix_dest) memmove(unix_dest, p, len + 1); + if (unix_dest_len) *unix_dest_len = len; +- status = STATUS_SUCCESS; + + cleanup: + if (!unix_dest) free( tmp ); +@@ -6352,9 +6359,9 @@ cleanup: + */ + NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_size) + { ++ VOID *subst_name = NULL, *print_name = NULL, *unix_name = NULL; + INT prefix_len, path_len, total_len; + char *unix_src, unix_dest[PATH_MAX]; +- VOID *subst_name, *print_name; + SIZE_T nt_dest_len = PATH_MAX; + int unix_dest_len = PATH_MAX; + BOOL dest_allocated = FALSE; +@@ -6419,6 +6426,7 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out + { + case IO_REPARSE_TAG_MOUNT_POINT: + max_length = out_size-FIELD_OFFSET(typeof(*buffer), MountPointReparseBuffer.PathBuffer[1]); ++ if (nt_dest_len > max_length) { status = STATUS_BUFFER_TOO_SMALL; goto cleanup; } + path_len = 0; + buffer->MountPointReparseBuffer.SubstituteNameOffset = path_len; + buffer->MountPointReparseBuffer.SubstituteNameLength = nt_dest_len; +@@ -6432,6 +6440,7 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out + break; + case IO_REPARSE_TAG_SYMLINK: + max_length = out_size-FIELD_OFFSET(typeof(*buffer), SymbolicLinkReparseBuffer.PathBuffer[1]); ++ if (nt_dest_len > max_length) { status = STATUS_BUFFER_TOO_SMALL; goto cleanup; } + path_len = 0; + buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = path_len; + buffer->SymbolicLinkReparseBuffer.SubstituteNameLength = nt_dest_len; +@@ -6445,19 +6454,20 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out + buffer->SymbolicLinkReparseBuffer.Flags = flags; + break; + default: +- /* unrecognized (regular) files should probably be treated as symlinks */ +- WARN("unrecognized symbolic link\n"); +- status = STATUS_NOT_IMPLEMENTED; +- goto cleanup; +- } +- if (nt_dest_len > max_length) +- { +- status = STATUS_BUFFER_TOO_SMALL; +- goto cleanup; ++ WARN("unrecognized symbolic link reparse tag: 0x%08x\n", buffer->ReparseTag); ++ case IO_REPARSE_TAG_LX_SYMLINK: ++ /* report links without a reparse tag as a WSL linux/unix symlink */ ++ max_length = out_size-FIELD_OFFSET(typeof(*buffer), LinuxSymbolicLinkReparseBuffer.PathBuffer[0]); ++ if (unix_dest_len > max_length) { status = STATUS_BUFFER_TOO_SMALL; goto cleanup; } ++ buffer->LinuxSymbolicLinkReparseBuffer.Version = 2; ++ unix_name = &buffer->LinuxSymbolicLinkReparseBuffer.PathBuffer[0]; ++ total_len = FIELD_OFFSET(typeof(*buffer), LinuxSymbolicLinkReparseBuffer.PathBuffer[unix_dest_len]); ++ break; + } + +- memcpy( subst_name, nt_dest, nt_dest_len ); +- memcpy( print_name, &nt_dest[prefix_len], nt_dest_len - prefix_len*sizeof(WCHAR) ); ++ if (subst_name) memcpy( subst_name, nt_dest, nt_dest_len ); ++ if (print_name) memcpy( print_name, &nt_dest[prefix_len], nt_dest_len - prefix_len*sizeof(WCHAR) ); ++ if (unix_name) memcpy( unix_name, unix_dest, unix_dest_len ); + buffer->ReparseDataLength = total_len - FIELD_OFFSET(typeof(*buffer), GenericReparseBuffer); + status = STATUS_SUCCESS; + +diff --git a/include/ntifs.h b/include/ntifs.h +index 0d02225bc4f..25af12a413a 100644 +--- a/include/ntifs.h ++++ b/include/ntifs.h +@@ -42,6 +42,10 @@ typedef struct _REPARSE_DATA_BUFFER { + USHORT PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; ++ struct { ++ ULONG Version; ++ UCHAR PathBuffer[1]; ++ } LinuxSymbolicLinkReparseBuffer; + struct { + UCHAR DataBuffer[1]; + } GenericReparseBuffer; +diff --git a/include/winnt.h b/include/winnt.h +index 0843ee3f739..52a4825781c 100644 +--- a/include/winnt.h ++++ b/include/winnt.h +@@ -2877,6 +2877,7 @@ extern struct _TEB * WINAPI NtCurrentTeb(void); + #define IO_REPARSE_TAG_CLOUD_MASK __MSABI_LONG(0x0000F000) + #define IO_REPARSE_TAG_APPEXECLINK __MSABI_LONG(0x8000001B) + #define IO_REPARSE_TAG_GVFS __MSABI_LONG(0x9000001C) ++#define IO_REPARSE_TAG_LX_SYMLINK __MSABI_LONG(0xA000001D) + #define IO_REPARSE_TAG_STORAGE_SYNC __MSABI_LONG(0x8000001E) + #define IO_REPARSE_TAG_WCI_TOMBSTONE __MSABI_LONG(0xA000001F) + #define IO_REPARSE_TAG_UNHANDLED __MSABI_LONG(0x80000020) +-- +2.30.2 + diff --git a/patches/ntdll-Junction_Points/0036-ntdll-Add-support-for-creating-Unix-Linux-symlinks.patch b/patches/ntdll-Junction_Points/0036-ntdll-Add-support-for-creating-Unix-Linux-symlinks.patch new file mode 100644 index 00000000..8066dbab --- /dev/null +++ b/patches/ntdll-Junction_Points/0036-ntdll-Add-support-for-creating-Unix-Linux-symlinks.patch @@ -0,0 +1,156 @@ +From 54b8792b895c7aaa3c2795fb9293187493b8766e Mon Sep 17 00:00:00 2001 +From: "Erich E. Hoover" +Date: Mon, 3 May 2021 09:28:08 -0600 +Subject: [PATCH] ntdll: Add support for creating Unix/Linux symlinks. + +--- + dlls/ntdll/tests/file.c | 43 +++++++++++++++++++++++++++++++++++++++++ + dlls/ntdll/unix/file.c | 30 ++++++++++++++++++++-------- + 2 files changed, 65 insertions(+), 8 deletions(-) + +diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c +index 47df69541c3..eadd5922f32 100644 +--- a/dlls/ntdll/tests/file.c ++++ b/dlls/ntdll/tests/file.c +@@ -5301,7 +5301,9 @@ static void test_reparse_points(void) + REPARSE_DATA_BUFFER *buffer = NULL; + DWORD dwret, dwLen, dwFlags, err; + WIN32_FILE_ATTRIBUTE_DATA fad; ++ UCHAR *unix_dest; + WCHAR buf[] = {0,0,0,0}; ++ char name[] = "target"; + HANDLE handle, token; + IO_STATUS_BLOCK iosb; + UNICODE_STRING nameW; +@@ -5647,6 +5649,47 @@ static void test_reparse_points(void) + wine_dbgstr_w(dest), wine_dbgstr_w(&targetW[1])); + CloseHandle(handle); + ++ /* Create a Unix/Linux symlink */ ++ HeapFree(GetProcessHeap(), 0, buffer); ++ RemoveDirectoryW(reparse_path); ++ bret = CreateDirectoryW(reparse_path, NULL); ++ handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, ++ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); ++ if (handle == INVALID_HANDLE_VALUE) ++ { ++ win_skip("Failed to open symlink directory handle (0x%x).\n", GetLastError()); ++ goto cleanup; ++ } ++ dwret = NtQueryInformationFile(handle, &iosb, &old_attrib, sizeof(old_attrib), FileBasicInformation); ++ ok(dwret == STATUS_SUCCESS, "Failed to get symlink folder's attributes (0x%x).\n", dwret); ++ path_len = strlen(name); ++ buffer_len = offsetof(REPARSE_DATA_BUFFER, LinuxSymbolicLinkReparseBuffer.PathBuffer[path_len]); ++ buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_len); ++ buffer->ReparseTag = IO_REPARSE_TAG_LX_SYMLINK; ++ buffer->ReparseDataLength = sizeof(ULONG) + path_len; ++ memcpy(buffer->LinuxSymbolicLinkReparseBuffer.PathBuffer, name, path_len); ++ bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0); ++ ok(bret, "Failed to create symlink! (0x%x)\n", GetLastError()); ++ ++ /* Read back the Unix/Linux symlink */ ++ HeapFree(GetProcessHeap(), 0, buffer); ++ handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, ++ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); ++ if (handle == INVALID_HANDLE_VALUE) ++ buffer_len = sizeof(*buffer) + MAX_PATH*sizeof(WCHAR); ++ buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_len); ++ bret = DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, (LPVOID)buffer, buffer_len, &dwret, 0); ++ ok(bret, "Failed to read symlink!\n"); ++ string_len = buffer->ReparseDataLength - sizeof(ULONG); ++ unix_dest = &buffer->LinuxSymbolicLinkReparseBuffer.PathBuffer[0]; ++ ok((memcmp(unix_dest, name, string_len) == 0), "Symlink destination does not match ('%s' != '%s')!\n", ++ unix_dest, name); ++ total_len = FIELD_OFFSET(typeof(*buffer), LinuxSymbolicLinkReparseBuffer.PathBuffer[path_len]) ++ - FIELD_OFFSET(typeof(*buffer), GenericReparseBuffer); ++ ok(buffer->ReparseDataLength == total_len, "ReparseDataLength has unexpected value (%d != %d)\n", ++ buffer->ReparseDataLength, total_len); ++ CloseHandle(handle); ++ + cleanup: + /* Cleanup */ + pRtlFreeUnicodeString(&nameW); +diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c +index 62593fa8526..e3c21bcbc66 100644 +--- a/dlls/ntdll/unix/file.c ++++ b/dlls/ntdll/unix/file.c +@@ -6049,18 +6049,18 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) + { + BOOL src_allocated = FALSE, path_allocated = FALSE, dest_allocated = FALSE; + BOOL nt_dest_allocated = FALSE, tempdir_created = FALSE; +- char *unix_src, *unix_dest, *unix_path = NULL; ++ char *unix_src, *unix_dest = NULL, *unix_path = NULL; + char tmpdir[PATH_MAX], tmplink[PATH_MAX], *d; + SIZE_T unix_dest_len = PATH_MAX; + char magic_dest[PATH_MAX]; + int dest_fd, needs_close; ++ int dest_len = 0, offset; + int relative_offset = 0; + UNICODE_STRING nt_dest; +- int dest_len, offset; + BOOL is_dir = TRUE; ++ WCHAR *dest = NULL; + NTSTATUS status; + struct stat st; +- WCHAR *dest; + ULONG flags; + int i; + +@@ -6078,6 +6078,12 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) + dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[offset]; + flags = buffer->SymbolicLinkReparseBuffer.Flags; + break; ++ case IO_REPARSE_TAG_LX_SYMLINK: ++ offset = 0; ++ flags = 0; ++ unix_dest_len = buffer->ReparseDataLength - sizeof(ULONG); ++ unix_dest = (char *) &buffer->LinuxSymbolicLinkReparseBuffer.PathBuffer[offset]; ++ break; + default: + FIXME("stub: FSCTL_SET_REPARSE_POINT(%x)\n", buffer->ReparseTag); + return STATUS_NOT_IMPLEMENTED; +@@ -6089,6 +6095,9 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) + if ((status = server_get_unix_name( handle, &unix_src, FALSE ))) + goto cleanup; + src_allocated = TRUE; ++ ++ if (unix_dest) goto have_dest; ++ + if (flags == SYMLINK_FLAG_RELATIVE) + { + SIZE_T nt_path_len = PATH_MAX, unix_path_len = PATH_MAX; +@@ -6164,6 +6173,8 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) + if (status != STATUS_SUCCESS && status != STATUS_NO_SUCH_FILE) + goto cleanup; + dest_allocated = TRUE; ++ ++have_dest: + /* check that the source and destination paths are the same up to the relative path */ + if (flags == SYMLINK_FLAG_RELATIVE) + { +@@ -6179,14 +6190,17 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer) + + /* Encode the reparse tag into the symlink */ + strcpy( magic_dest, "" ); +- if (flags == SYMLINK_FLAG_RELATIVE) +- strcat( magic_dest, "." ); +- strcat( magic_dest, "/" ); +- for (i = 0; i < sizeof(ULONG)*8; i++) ++ if (buffer->ReparseTag != IO_REPARSE_TAG_LX_SYMLINK) + { +- if ((buffer->ReparseTag >> i) & 1) ++ if (flags == SYMLINK_FLAG_RELATIVE) + strcat( magic_dest, "." ); + strcat( magic_dest, "/" ); ++ for (i = 0; i < sizeof(ULONG)*8; i++) ++ { ++ if ((buffer->ReparseTag >> i) & 1) ++ strcat( magic_dest, "." ); ++ strcat( magic_dest, "/" ); ++ } + } + /* Encode the type (file or directory) if NT symlink */ + if (buffer->ReparseTag == IO_REPARSE_TAG_SYMLINK) +-- +2.30.2 + diff --git a/patches/ntdll-Junction_Points/0036-ntdll-Strip-the-wine-prefix-from-reparse-point-paths.patch b/patches/ntdll-Junction_Points/0037-ntdll-Strip-the-wine-prefix-from-reparse-point-paths.patch similarity index 86% rename from patches/ntdll-Junction_Points/0036-ntdll-Strip-the-wine-prefix-from-reparse-point-paths.patch rename to patches/ntdll-Junction_Points/0037-ntdll-Strip-the-wine-prefix-from-reparse-point-paths.patch index 48d82a36..31eb041f 100644 --- a/patches/ntdll-Junction_Points/0036-ntdll-Strip-the-wine-prefix-from-reparse-point-paths.patch +++ b/patches/ntdll-Junction_Points/0037-ntdll-Strip-the-wine-prefix-from-reparse-point-paths.patch @@ -1,4 +1,4 @@ -From 4507201faf3a7993d4e8f214c5de081f4656ad5e Mon Sep 17 00:00:00 2001 +From 96096532f7ec6e1fb58ec5216995c944d4d7c2f6 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Sat, 6 Feb 2021 16:15:46 -0700 Subject: [PATCH] ntdll: Strip the wine prefix from reparse point paths @@ -9,10 +9,10 @@ Subject: [PATCH] ntdll: Strip the wine prefix from reparse point paths 1 file changed, 29 insertions(+) diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index b17b53146b3..614f37fb3d6 100644 +index e3c21bcbc66..346e1e8c84c 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -6051,6 +6051,33 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer, +@@ -6041,6 +6041,33 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer, } @@ -46,7 +46,7 @@ index b17b53146b3..614f37fb3d6 100644 /* * Retrieve the unix name corresponding to a file handle, remove that directory, and then symlink * the requested directory to the location of the old directory. -@@ -6183,6 +6210,8 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer) +@@ -6185,6 +6212,8 @@ have_dest: goto cleanup; } } diff --git a/patches/ntdll-Junction_Points/0037-ntdll-Add-a-marker-to-reparse-point-paths-to-indicat.patch b/patches/ntdll-Junction_Points/0038-ntdll-Add-a-marker-to-reparse-point-paths-to-indicat.patch similarity index 85% rename from patches/ntdll-Junction_Points/0037-ntdll-Add-a-marker-to-reparse-point-paths-to-indicat.patch rename to patches/ntdll-Junction_Points/0038-ntdll-Add-a-marker-to-reparse-point-paths-to-indicat.patch index bf8bc1cc..7296e793 100644 --- a/patches/ntdll-Junction_Points/0037-ntdll-Add-a-marker-to-reparse-point-paths-to-indicat.patch +++ b/patches/ntdll-Junction_Points/0038-ntdll-Add-a-marker-to-reparse-point-paths-to-indicat.patch @@ -1,4 +1,4 @@ -From d7dbc8bcef2eb27d629ecf69f3d98fbe8aab3da7 Mon Sep 17 00:00:00 2001 +From 5952a53690460f2bafac92f10dfeee15aaa709c1 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Sat, 6 Feb 2021 16:16:17 -0700 Subject: [PATCH] ntdll: Add a marker to reparse point paths to indicate the @@ -9,10 +9,10 @@ Subject: [PATCH] ntdll: Add a marker to reparse point paths to indicate the 1 file changed, 23 insertions(+) diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index 25b542cb4fc..313d17ddbf9 100644 +index 346e1e8c84c..325ac6ed8a1 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c -@@ -5938,6 +5938,26 @@ void strip_external_path( char *path, SIZE_T *len ) +@@ -6068,6 +6068,26 @@ void strip_external_path( char *path, SIZE_T *len ) } @@ -39,7 +39,7 @@ index 25b542cb4fc..313d17ddbf9 100644 /* * Retrieve the unix name corresponding to a file handle, remove that directory, and then symlink * the requested directory to the location of the old directory. -@@ -6071,7 +6091,10 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer) +@@ -6213,7 +6233,10 @@ have_dest: } } else @@ -51,5 +51,5 @@ index 25b542cb4fc..313d17ddbf9 100644 TRACE( "Linking %s to %s\n", unix_src, &unix_dest[relative_offset] ); -- -2.20.1 +2.30.2 diff --git a/patches/ntdll-Junction_Points/0038-server-Rewrite-absolute-reparse-point-targets-if-the.patch b/patches/ntdll-Junction_Points/0039-server-Rewrite-absolute-reparse-point-targets-if-the.patch similarity index 61% rename from patches/ntdll-Junction_Points/0038-server-Rewrite-absolute-reparse-point-targets-if-the.patch rename to patches/ntdll-Junction_Points/0039-server-Rewrite-absolute-reparse-point-targets-if-the.patch index a0566429..aacce002 100644 --- a/patches/ntdll-Junction_Points/0038-server-Rewrite-absolute-reparse-point-targets-if-the.patch +++ b/patches/ntdll-Junction_Points/0039-server-Rewrite-absolute-reparse-point-targets-if-the.patch @@ -1,27 +1,37 @@ -From 5f87760574f835580a0bf47962c28f6ef8f2859d Mon Sep 17 00:00:00 2001 +From dc74c7a174aac20be96cf40914bc4927256eac47 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Sat, 6 Feb 2021 16:15:03 -0700 Subject: [PATCH] server: Rewrite absolute reparse point targets if the prefix location changes. --- - server/fd.c | 87 +++++++++++++++++++++++++++++++++++++++++++++-------- - 1 file changed, 74 insertions(+), 13 deletions(-) + server/fd.c | 85 +++++++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 69 insertions(+), 16 deletions(-) diff --git a/server/fd.c b/server/fd.c -index ee58aa3c8ae..43c0d36dff9 100644 +index c7c4ad280ef..d795080cfda 100644 --- a/server/fd.c +++ b/server/fd.c -@@ -1902,7 +1902,7 @@ void get_nt_name( struct fd *fd, struct unicode_str *name ) +@@ -1902,23 +1902,16 @@ void get_nt_name( struct fd *fd, struct unicode_str *name ) name->len = fd->nt_namelen; } --static void decode_symlink(char *name, int *is_dir) +-int check_symlink( char *name ) +static char *decode_symlink(const char *name, ULONG *tag, int *is_dir) { - char link[MAX_PATH], *p; +- struct stat st; +- +- lstat( name, &st ); +- return S_ISLNK( st.st_mode ); +-} +- +-static void decode_symlink(char *name, int *is_dir) +-{ +- char link[MAX_PATH], *p; ++ static char link[MAX_PATH]; ULONG reparse_tag; -@@ -1910,7 +1910,7 @@ static void decode_symlink(char *name, int *is_dir) + int len, i; ++ char *p; len = readlink( name, link, sizeof(link) ); if (len == -1) @@ -30,7 +40,7 @@ index ee58aa3c8ae..43c0d36dff9 100644 link[len] = 0; p = link; /* skip past relative/absolute indication */ -@@ -1918,7 +1918,7 @@ static void decode_symlink(char *name, int *is_dir) +@@ -1926,7 +1919,7 @@ static void decode_symlink(char *name, int *is_dir) p++; if (*p++ != '/') { @@ -39,7 +49,7 @@ index ee58aa3c8ae..43c0d36dff9 100644 } /* decode the reparse tag */ reparse_tag = 0; -@@ -1932,7 +1932,7 @@ static void decode_symlink(char *name, int *is_dir) +@@ -1940,7 +1933,7 @@ static void decode_symlink(char *name, int *is_dir) else if (c == '.' && *p++ == '/') val = 1; else @@ -48,7 +58,7 @@ index ee58aa3c8ae..43c0d36dff9 100644 reparse_tag |= (val << i); } /* decode the directory/file flag */ -@@ -1945,10 +1945,69 @@ static void decode_symlink(char *name, int *is_dir) +@@ -1953,10 +1946,70 @@ static void decode_symlink(char *name, int *is_dir) else if (c == '.' && *p++ == '/') *is_dir = TRUE; else @@ -61,7 +71,7 @@ index ee58aa3c8ae..43c0d36dff9 100644 + return p; +} + -+static void rewrite_symlink( const char *path ) ++static int rewrite_symlink( const char *path ) +{ + static char marker[] = "////.//.//"; /* "P" (0x50) encoded as a path (0=/ 1=./) */ + char *link, *prefix_end, *local_link; @@ -76,23 +86,23 @@ index ee58aa3c8ae..43c0d36dff9 100644 + { + char tmp_dir[MAX_PATH]; + -+ if (getcwd( tmp_dir, sizeof(tmp_dir) ) == NULL) return; -+ if (fchdir( config_dir_fd ) == -1) return; -+ if (getcwd( config_dir, sizeof(config_dir) ) == NULL) return; -+ if (chdir( tmp_dir ) == -1) return; ++ if (getcwd( tmp_dir, sizeof(tmp_dir) ) == NULL) return FALSE; ++ if (fchdir( config_dir_fd ) == -1) return FALSE; ++ if (getcwd( config_dir, sizeof(config_dir) ) == NULL) return FALSE; ++ if (chdir( tmp_dir ) == -1) return FALSE; + config_dir_len = strlen( config_dir ); + } + + /* grab the current link contents */ + link = decode_symlink( path, &tag, &is_dir ); -+ if (link == NULL) return; ++ if (link == NULL) return FALSE; + + /* find out if the prefix matches, if it does then do not modify the link */ + prefix_end = strstr( link, marker ); -+ if (prefix_end == NULL) return; ++ if (prefix_end == NULL) return TRUE; + local_link = prefix_end + strlen( marker ); + len = prefix_end - link; -+ if (len == config_dir_len && strncmp( config_dir, link, len ) == 0) return; ++ if (len == config_dir_len && strncmp( config_dir, link, len ) == 0) return TRUE; + /* if the prefix does not match then re-encode the link with the new prefix */ + + /* Encode the reparse tag into the symlink */ @@ -116,40 +126,20 @@ index ee58aa3c8ae..43c0d36dff9 100644 + /* replace the symlink */ + unlink( path ); + symlink( new_target, path ); ++ return TRUE; } /* open() wrapper that returns a struct fd with no fd user set */ -@@ -2016,6 +2075,15 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam - flags |= O_SYMLINK; - #endif - -+ fd->unix_name = NULL; -+ if ((path = dup_fd_name( root, name ))) -+ { -+ rewrite_symlink( path ); -+ fd->unlink_name = path; -+ fd->unix_name = realpath( path, NULL ); -+ if (!fd->unix_name) fd->unix_name = dup_fd_name( root, name ); /* dangling symlink */ -+ } -+ - if ((fd->unix_fd = open( name, rw_mode | (flags & ~O_TRUNC), *mode )) == -1) +@@ -2022,7 +2075,7 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam + fd->unix_name = NULL; + if ((path = dup_fd_name( root, name ))) { - /* if we tried to open a directory for write access, retry read-only */ -@@ -2033,13 +2101,6 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam - } - - fd->nt_name = dup_nt_name( root, nt_name, &fd->nt_namelen ); -- fd->unix_name = NULL; -- if ((path = dup_fd_name( root, name ))) -- { -- fd->unlink_name = path; -- fd->unix_name = realpath( path, NULL ); -- if (!fd->unix_name) fd->unix_name = dup_fd_name( root, name ); /* dangling symlink */ -- } - - closed_fd->unix_fd = fd->unix_fd; - closed_fd->unlink = 0; -@@ -2073,7 +2134,7 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam +- int is_symlink = check_symlink( path ); ++ int is_symlink = rewrite_symlink( path ); + #if defined(O_SYMLINK) + if (is_symlink && (options & FILE_OPEN_REPARSE_POINT) && !(flags & O_CREAT)) + flags |= O_SYMLINK; +@@ -2082,7 +2135,7 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam *mode = st.st_mode; is_dir = S_ISDIR(st.st_mode); if (is_link) @@ -159,5 +149,5 @@ index ee58aa3c8ae..43c0d36dff9 100644 /* check directory options */ if ((options & FILE_DIRECTORY_FILE) && !is_dir) -- -2.20.1 +2.30.2 diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 7df221ac..da2bef2c 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -2131,8 +2131,8 @@ fi # | Modified files: # | * configure.ac, dlls/kernel32/path.c, dlls/kernel32/tests/path.c, dlls/kernelbase/file.c, dlls/mountmgr.sys/device.c, # | dlls/msvcp120/tests/msvcp120.c, dlls/msvcp140/tests/msvcp140.c, dlls/ntdll/tests/file.c, dlls/ntdll/unix/file.c, -# | include/Makefile.in, include/ntifs.h, include/winternl.h, programs/cmd/builtins.c, programs/cmd/directory.c, -# | server/fd.c, server/file.c, server/protocol.def +# | include/Makefile.in, include/ntifs.h, include/winnt.h, include/winternl.h, programs/cmd/builtins.c, +# | programs/cmd/directory.c, server/fd.c, server/file.c, server/protocol.def # | if test "$enable_ntdll_Junction_Points" -eq 1; then patch_apply ntdll-Junction_Points/0001-ntdll-Add-support-for-junction-point-creation.patch @@ -2157,22 +2157,23 @@ if test "$enable_ntdll_Junction_Points" -eq 1; then patch_apply ntdll-Junction_Points/0020-kernelbase-Use-FILE_OPEN_REPARSE_POINT-in-RemoveDire.patch patch_apply ntdll-Junction_Points/0021-ntdll-Always-report-symbolic-links-as-containing-zer.patch patch_apply ntdll-Junction_Points/0022-ntdll-Find-dangling-symlinks-quickly.patch - patch_apply ntdll-Junction_Points/0023-kernel32-Implement-CreateSymbolicLink-A-W-with-ntdll.patch - patch_apply ntdll-Junction_Points/0024-kernel32-Add-reparse-support-to-FindNextFile.patch - patch_apply ntdll-Junction_Points/0025-wcmd-Display-reparse-point-type-in-directory-listing.patch - patch_apply ntdll-Junction_Points/0026-wcmd-Show-reparse-point-target-in-directory-listing.patch - patch_apply ntdll-Junction_Points/0027-wcmd-Add-junction-point-support-to-mklink.patch - patch_apply ntdll-Junction_Points/0028-server-Fix-obtaining-information-about-a-symlink.patch - patch_apply ntdll-Junction_Points/0029-ntdll-Succeed-with-no-data-for-NtReadFile-on-reparse.patch - patch_apply ntdll-Junction_Points/0030-ntdll-Support-reparse-point-properties-in-fd_get_fil.patch - patch_apply ntdll-Junction_Points/0031-ntdll-Add-support-for-FileAttributeTagInformation.patch + patch_apply ntdll-Junction_Points/0023-server-Fix-obtaining-information-about-a-symlink.patch + patch_apply ntdll-Junction_Points/0024-ntdll-Succeed-with-no-data-for-NtReadFile-on-reparse.patch + patch_apply ntdll-Junction_Points/0025-ntdll-Support-reparse-point-properties-in-fd_get_fil.patch + patch_apply ntdll-Junction_Points/0026-ntdll-Add-support-for-FileAttributeTagInformation.patch + patch_apply ntdll-Junction_Points/0027-kernel32-Implement-CreateSymbolicLink-A-W-with-ntdll.patch + patch_apply ntdll-Junction_Points/0028-kernel32-Add-reparse-support-to-FindNextFile.patch + patch_apply ntdll-Junction_Points/0029-wcmd-Display-reparse-point-type-in-directory-listing.patch + patch_apply ntdll-Junction_Points/0030-wcmd-Show-reparse-point-target-in-directory-listing.patch + patch_apply ntdll-Junction_Points/0031-wcmd-Add-junction-point-support-to-mklink.patch patch_apply ntdll-Junction_Points/0032-server-Properly-handle-renames-involving-symlinks.patch patch_apply ntdll-Junction_Points/0033-kernelbase-Use-FILE_OPEN_REPARSE_POINT-in-MoveFileWi.patch patch_apply ntdll-Junction_Points/0034-kernelbase-Use-FILE_OPEN_REPARSE_POINT-in-DeleteFile.patch - patch_apply ntdll-Junction_Points/0035-ntdll-Treat-undecoded-unix-symlinks-as-NT-symlinks.patch - patch_apply ntdll-Junction_Points/0036-ntdll-Strip-the-wine-prefix-from-reparse-point-paths.patch - patch_apply ntdll-Junction_Points/0037-ntdll-Add-a-marker-to-reparse-point-paths-to-indicat.patch - patch_apply ntdll-Junction_Points/0038-server-Rewrite-absolute-reparse-point-targets-if-the.patch + patch_apply ntdll-Junction_Points/0035-ntdll-Treat-undecoded-unix-symlinks-as-WSL-Linux-Uni.patch + patch_apply ntdll-Junction_Points/0036-ntdll-Add-support-for-creating-Unix-Linux-symlinks.patch + patch_apply ntdll-Junction_Points/0037-ntdll-Strip-the-wine-prefix-from-reparse-point-paths.patch + patch_apply ntdll-Junction_Points/0038-ntdll-Add-a-marker-to-reparse-point-paths-to-indicat.patch + patch_apply ntdll-Junction_Points/0039-server-Rewrite-absolute-reparse-point-targets-if-the.patch fi # Patchset server-Key_State