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
This commit is contained in:
Zebediah Figura 2021-05-08 15:13:53 -05:00
parent 7c888e7fee
commit 8e5c8cc63b
42 changed files with 960 additions and 733 deletions

View File

@ -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" <erich.e.hoover@gmail.com>
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 <erich.e.hoover@gmail.com>
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

View File

@ -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" <erich.e.hoover@gmail.com>
Date: Thu, 16 Jan 2014 20:57:57 -0700
Subject: [PATCH] ntdll: Add support for reading junction points.
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
---
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

View File

@ -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" <erich.e.hoover@gmail.com>
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 <erich.e.hoover@gmail.com>
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

View File

@ -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" <erich.e.hoover@gmail.com>
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 <erich.e.hoover@gmail.com>
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

View File

@ -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" <erich.e.hoover@gmail.com>
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 <erich.e.hoover@gmail.com>
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

View File

@ -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" <erich.e.hoover@wine-staging.com>
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

View File

@ -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" <erich.e.hoover@gmail.com>
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 <erich.e.hoover@gmail.com>
---
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

View File

@ -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" <erich.e.hoover@gmail.com>
Date: Wed, 13 Mar 2019 12:55:20 -0600
Subject: [PATCH] ntdll: Add support for reading absolute symlinks.
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
---
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

View File

@ -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" <erich.e.hoover@gmail.com>
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 <erich.e.hoover@gmail.com>
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

View File

@ -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" <erich.e.hoover@gmail.com>
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 <erich.e.hoover@gmail.com>
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

View File

@ -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" <erich.e.hoover@gmail.com>
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 <erich.e.hoover@gmail.com>
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

View File

@ -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" <erich.e.hoover@gmail.com>
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 <erich.e.hoover@gmail.com>
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

View File

@ -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" <erich.e.hoover@gmail.com>
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 <erich.e.hoover@gmail.com>
---
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

View File

@ -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" <erich.e.hoover@gmail.com>
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 <erich.e.hoover@gmail.com>
---
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

View File

@ -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" <erich.e.hoover@wine-staging.com>
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

View File

@ -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" <erich.e.hoover@wine-staging.com>
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 <sys/epoll.h>
# 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

View File

@ -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" <erich.e.hoover@wine-staging.com>
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

View File

@ -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" <erich.e.hoover@gmail.com>
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 <erich.e.hoover@gmail.com>
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

View File

@ -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" <erich.e.hoover@wine-staging.com>
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

View File

@ -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" <erich.e.hoover@wine-staging.com>
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

View File

@ -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" <erich.e.hoover@gmail.com>
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 <erich.e.hoover@gmail.com>
---
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

View File

@ -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" <erich.e.hoover@gmail.com>
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 <erich.e.hoover@gmail.com>
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

View File

@ -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" <erich.e.hoover@gmail.com>
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 <erich.e.hoover@gmail.com>
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

View File

@ -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" <erich.e.hoover@wine-staging.com>
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

View File

@ -0,0 +1,101 @@
From c2da4e7418c498619f5e8432bccd2c32a8c97f5c Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
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

View File

@ -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" <erich.e.hoover@wine-staging.com>
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

View File

@ -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" <erich.e.hoover@gmail.com>
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

View File

@ -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" <erich.e.hoover@gmail.com>
Date: Wed, 29 May 2019 15:11:42 -0600
Subject: [PATCH] kernel32: Add reparse support to FindNextFile.
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
---
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

View File

@ -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" <erich.e.hoover@gmail.com>
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

View File

@ -1,169 +0,0 @@
From 3a617a56abd9277e83a0c23d60cb8cba09c4082f Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
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

View File

@ -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" <erich.e.hoover@gmail.com>
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

View File

@ -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" <erich.e.hoover@gmail.com>
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 <erich.e.hoover@gmail.com>
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

View File

@ -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" <erich.e.hoover@wine-staging.com>
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

View File

@ -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" <erich.e.hoover@wine-staging.com>
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

View File

@ -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" <erich.e.hoover@wine-staging.com>
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

View File

@ -1,114 +0,0 @@
From 2851b3072e7776cd87a3b79aa7edc99813fbcf2e Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
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

View File

@ -0,0 +1,178 @@
From ebba56121b254c640ef9fb9b2888bc9b08062080 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
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

View File

@ -0,0 +1,156 @@
From 54b8792b895c7aaa3c2795fb9293187493b8766e Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
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

View File

@ -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" <erich.e.hoover@wine-staging.com>
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;
}
}

View File

@ -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" <erich.e.hoover@wine-staging.com>
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

View File

@ -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" <erich.e.hoover@wine-staging.com>
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

View File

@ -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