mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-09-13 09:17:20 -07:00
ntdll-Junction_Points: Update with rebased patch set from Erich E. Hoover.
This commit is contained in:
parent
1a87edb76b
commit
4ffe305c90
@ -1,4 +1,4 @@
|
||||
From e043e7d570fcdc0f7bc662d794d111baaa15b015 Mon Sep 17 00:00:00 2001
|
||||
From 40fcca0f7bf71d2675bf44cdfd8f5a178d4275c3 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.
|
||||
@ -6,19 +6,19 @@ Subject: [PATCH] ntdll: Add support for junction point creation.
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
configure.ac | 2 +
|
||||
dlls/ntdll/tests/file.c | 101 ++++++++++++++++++++++++++++++++++
|
||||
dlls/ntdll/unix/file.c | 117 ++++++++++++++++++++++++++++++++++++++++
|
||||
dlls/ntdll/tests/file.c | 101 +++++++++++++++++++++++++++++++
|
||||
dlls/ntdll/unix/file.c | 129 ++++++++++++++++++++++++++++++++++++++++
|
||||
include/Makefile.in | 1 +
|
||||
include/ntifs.h | 42 +++++++++++++++
|
||||
include/wine/port.h | 9 ++++
|
||||
include/ntifs.h | 42 +++++++++++++
|
||||
include/wine/port.h | 9 +++
|
||||
libs/port/Makefile.in | 1 +
|
||||
libs/port/renameat2.c | 55 +++++++++++++++++++
|
||||
8 files changed, 328 insertions(+)
|
||||
libs/port/renameat2.c | 55 +++++++++++++++++
|
||||
8 files changed, 340 insertions(+)
|
||||
create mode 100644 include/ntifs.h
|
||||
create mode 100644 libs/port/renameat2.c
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index a403c9436ca..dbd07791de7 100644
|
||||
index f3e93b3fdb8..918f4a5253c 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -2218,6 +2218,8 @@ AC_CHECK_FUNCS(\
|
||||
@ -31,7 +31,7 @@ index a403c9436ca..dbd07791de7 100644
|
||||
select \
|
||||
setproctitle \
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index a502a8eec75..bce34f03920 100644
|
||||
index 5ca9742f0b6..1bc1af363e4 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -38,6 +38,7 @@
|
||||
@ -42,7 +42,7 @@ index a502a8eec75..bce34f03920 100644
|
||||
|
||||
#ifndef IO_COMPLETION_ALL_ACCESS
|
||||
#define IO_COMPLETION_ALL_ACCESS 0x001F0003
|
||||
@@ -4971,6 +4972,105 @@ static void test_file_readonly_access(void)
|
||||
@@ -5053,6 +5054,105 @@ static void test_file_readonly_access(void)
|
||||
DeleteFileW(path);
|
||||
}
|
||||
|
||||
@ -148,39 +148,39 @@ index a502a8eec75..bce34f03920 100644
|
||||
START_TEST(file)
|
||||
{
|
||||
HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
|
||||
@@ -5041,4 +5141,5 @@ START_TEST(file)
|
||||
test_query_attribute_information_file();
|
||||
@@ -5125,4 +5225,5 @@ START_TEST(file)
|
||||
test_ioctl();
|
||||
test_query_ea();
|
||||
test_flush_buffers_file();
|
||||
+ test_reparse_points();
|
||||
}
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index b76d07a8175..271151ed1be 100644
|
||||
index 372a8ec1248..cfa1ec0fe9c 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
+#include <libgen.h>
|
||||
#include <stdarg.h>
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@@ -122,6 +123,7 @@
|
||||
#include "ddk/wdm.h"
|
||||
#define WINE_MOUNTMGR_EXTENSIONS
|
||||
#include "ddk/mountmgr.h"
|
||||
+#include "ntifs.h"
|
||||
#include "wine/server.h"
|
||||
#include <stdio.h>
|
||||
+#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#ifdef HAVE_MNTENT_H
|
||||
#include <mntent.h>
|
||||
@@ -126,6 +127,7 @@
|
||||
#include "wine/list.h"
|
||||
#include "wine/debug.h"
|
||||
@@ -5661,6 +5663,104 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer,
|
||||
#include "unix_private.h"
|
||||
+#include "ntifs.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(file);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(winediag);
|
||||
@@ -5645,6 +5647,116 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer,
|
||||
}
|
||||
|
||||
|
||||
+/*
|
||||
+ * 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.
|
||||
+ * 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)
|
||||
+{
|
||||
@ -189,7 +189,8 @@ index b76d07a8175..271151ed1be 100644
|
||||
+ int offset = buffer->MountPointReparseBuffer.SubstituteNameOffset;
|
||||
+ WCHAR *dest = &buffer->MountPointReparseBuffer.PathBuffer[offset];
|
||||
+ char tmpdir[PATH_MAX], tmplink[PATH_MAX], *d;
|
||||
+ ANSI_STRING unix_src, unix_dest;
|
||||
+ SIZE_T unix_dest_len = PATH_MAX;
|
||||
+ char *unix_src, *unix_dest;
|
||||
+ char magic_dest[PATH_MAX];
|
||||
+ int dest_fd, needs_close;
|
||||
+ UNICODE_STRING nt_dest;
|
||||
@ -204,12 +205,23 @@ index b76d07a8175..271151ed1be 100644
|
||||
+ src_allocated = TRUE;
|
||||
+ nt_dest.Buffer = dest;
|
||||
+ nt_dest.Length = dest_len;
|
||||
+ status = nt_to_unix_file_name( &nt_dest, &unix_dest, 0 );
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ unix_dest = malloc( unix_dest_len );
|
||||
+ if (!unix_dest)
|
||||
+ {
|
||||
+ status = STATUS_NO_MEMORY;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ status = wine_nt_to_unix_file_name( &nt_dest, unix_dest, &unix_dest_len, FALSE );
|
||||
+ if (status != STATUS_BUFFER_TOO_SMALL) break;
|
||||
+ free( unix_dest );
|
||||
+ }
|
||||
+ if (status != STATUS_SUCCESS && status != STATUS_NO_SUCH_FILE)
|
||||
+ goto cleanup;
|
||||
+ dest_allocated = TRUE;
|
||||
+
|
||||
+ TRACE("Linking %s to %s\n", unix_src.Buffer, unix_dest.Buffer);
|
||||
+ TRACE( "Linking %s to %s\n", unix_src, unix_dest );
|
||||
+
|
||||
+ /* Encode the reparse tag into the symlink */
|
||||
+ strcpy( magic_dest, "/" );
|
||||
@ -219,10 +231,10 @@ index b76d07a8175..271151ed1be 100644
|
||||
+ strcat( magic_dest, "." );
|
||||
+ strcat( magic_dest, "/" );
|
||||
+ }
|
||||
+ strcat( magic_dest, unix_dest.Buffer );
|
||||
+ strcat( magic_dest, unix_dest );
|
||||
+
|
||||
+ /* Produce the link in a temporary location in the same folder */
|
||||
+ strcpy( tmpdir, unix_src.Buffer );
|
||||
+ strcpy( tmpdir, unix_src );
|
||||
+ d = dirname( tmpdir);
|
||||
+ if (d != tmpdir) strcpy( tmpdir, d );
|
||||
+ strcat( tmpdir, "/.winelink.XXXXXX" );
|
||||
@ -240,7 +252,7 @@ index b76d07a8175..271151ed1be 100644
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ /* Atomically move the link into position */
|
||||
+ if (!renameat2( -1, tmplink, -1, unix_src.Buffer, RENAME_EXCHANGE ))
|
||||
+ if (!renameat2( -1, tmplink, -1, unix_src, RENAME_EXCHANGE ))
|
||||
+ {
|
||||
+ /* success: link and folder have switched locations */
|
||||
+ rmdir( tmplink ); /* remove the folder (at link location) */
|
||||
@ -249,12 +261,12 @@ index b76d07a8175..271151ed1be 100644
|
||||
+ {
|
||||
+ FIXME( "Atomic exchange of directory with symbolic link unsupported on this system, "
|
||||
+ "using unsafe exchange instead.\n" );
|
||||
+ if (rmdir( unix_src.Buffer ))
|
||||
+ if (rmdir( unix_src ))
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ if (rename( tmplink, unix_src.Buffer ))
|
||||
+ if (rename( tmplink, unix_src ))
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup; /* not moved, orignal file/folder at destination is orphaned */
|
||||
@ -269,8 +281,8 @@ index b76d07a8175..271151ed1be 100644
|
||||
+
|
||||
+cleanup:
|
||||
+ if (tempdir_created) rmdir( tmpdir );
|
||||
+ if (dest_allocated) RtlFreeAnsiString( &unix_dest );
|
||||
+ if (src_allocated) RtlFreeAnsiString( &unix_src );
|
||||
+ if (dest_allocated) free( unix_dest );
|
||||
+ if (src_allocated) free( unix_src );
|
||||
+ if (needs_close) close( dest_fd );
|
||||
+ return status;
|
||||
+}
|
||||
@ -279,11 +291,10 @@ index b76d07a8175..271151ed1be 100644
|
||||
/******************************************************************************
|
||||
* NtFsControlFile (NTDLL.@)
|
||||
*/
|
||||
@@ -5748,6 +5848,23 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
|
||||
io->Information = 0;
|
||||
status = STATUS_SUCCESS;
|
||||
@@ -5727,6 +5839,23 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
|
||||
break;
|
||||
+
|
||||
}
|
||||
|
||||
+ case FSCTL_SET_REPARSE_POINT:
|
||||
+ {
|
||||
+ REPARSE_DATA_BUFFER *buffer = (REPARSE_DATA_BUFFER *)in_buffer;
|
||||
@ -300,9 +311,10 @@ index b76d07a8175..271151ed1be 100644
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
default:
|
||||
return server_ioctl_file( handle, event, apc, apc_context, io, code,
|
||||
in_buffer, in_size, out_buffer, out_size );
|
||||
+
|
||||
case FSCTL_SET_SPARSE:
|
||||
TRACE("FSCTL_SET_SPARSE: Ignoring request\n");
|
||||
io->Information = 0;
|
||||
diff --git a/include/Makefile.in b/include/Makefile.in
|
||||
index 216adf0d7ae..7dc16c230b6 100644
|
||||
--- a/include/Makefile.in
|
||||
|
@ -1,19 +1,19 @@
|
||||
From f601df88922fd3719b34376344488fe2a04afe6b Mon Sep 17 00:00:00 2001
|
||||
From 1c6eed5d7c8a60fb7f6a9ada5345ef2dc0c6e9ad 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.
|
||||
Subject: 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 | 106 ++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 119 insertions(+), 1 deletion(-)
|
||||
dlls/ntdll/tests/file.c | 14 ++++-
|
||||
dlls/ntdll/unix/file.c | 119 ++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 132 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 8b5ddbb0da1..938ef2026e3 100644
|
||||
index 43cf99e8e74..4fe94f58bf1 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5008,9 +5008,10 @@ static void test_reparse_points(void)
|
||||
@@ -5009,9 +5009,10 @@ static void test_reparse_points(void)
|
||||
static const WCHAR dotW[] = {'.',0};
|
||||
REPARSE_DATA_BUFFER *buffer = NULL;
|
||||
DWORD dwret, dwLen, dwFlags;
|
||||
@ -25,7 +25,7 @@ index 8b5ddbb0da1..938ef2026e3 100644
|
||||
BOOL bret;
|
||||
|
||||
/* Create a temporary folder for the junction point tests */
|
||||
@@ -5058,6 +5059,17 @@ static void test_reparse_points(void)
|
||||
@@ -5059,6 +5060,17 @@ 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());
|
||||
@ -44,10 +44,10 @@ index 8b5ddbb0da1..938ef2026e3 100644
|
||||
|
||||
cleanup:
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index 44cb12f90ee..52520f5f78f 100644
|
||||
index 48e4c38b7ba..cd523dcd313 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -5707,6 +5707,106 @@ cleanup:
|
||||
@@ -5704,6 +5704,119 @@ cleanup:
|
||||
}
|
||||
|
||||
|
||||
@ -57,13 +57,15 @@ index 44cb12f90ee..52520f5f78f 100644
|
||||
+ */
|
||||
+NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_size)
|
||||
+{
|
||||
+ ANSI_STRING unix_src, unix_dest;
|
||||
+ char *unix_src, unix_dest[PATH_MAX];
|
||||
+ VOID *subst_name, *print_name;
|
||||
+ SIZE_T nt_dest_len = PATH_MAX;
|
||||
+ BOOL dest_allocated = FALSE;
|
||||
+ int dest_fd, needs_close;
|
||||
+ UNICODE_STRING nt_dest;
|
||||
+ int unix_dest_len;
|
||||
+ DWORD max_length;
|
||||
+ NTSTATUS status;
|
||||
+ WCHAR *nt_dest;
|
||||
+ INT prefix_len;
|
||||
+ ssize_t ret;
|
||||
+ char *p;
|
||||
@ -75,19 +77,16 @@ index 44cb12f90ee..52520f5f78f 100644
|
||||
+ if ((status = server_get_unix_name( handle, &unix_src )))
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ unix_dest.Buffer = RtlAllocateHeap( GetProcessHeap(), 0, PATH_MAX );
|
||||
+ unix_dest.MaximumLength = PATH_MAX;
|
||||
+ dest_allocated = TRUE;
|
||||
+ ret = readlink( unix_src.Buffer, unix_dest.Buffer, unix_dest.MaximumLength );
|
||||
+ ret = readlink( unix_src, unix_dest, sizeof(unix_dest) );
|
||||
+ if (ret < 0)
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ unix_dest.Length = ret;
|
||||
+ unix_dest_len = ret;
|
||||
+
|
||||
+ /* Decode the reparse tag from the symlink */
|
||||
+ p = unix_dest.Buffer;
|
||||
+ p = unix_dest;
|
||||
+ if (*p++ != '/')
|
||||
+ {
|
||||
+ status = STATUS_NOT_IMPLEMENTED;
|
||||
@ -110,11 +109,25 @@ index 44cb12f90ee..52520f5f78f 100644
|
||||
+ }
|
||||
+ buffer->ReparseTag |= (val << i);
|
||||
+ }
|
||||
+ unix_dest.Length -= (p - unix_dest.Buffer);
|
||||
+ memmove(unix_dest.Buffer, p, unix_dest.Length);
|
||||
+ unix_dest_len -= (p - unix_dest);
|
||||
+ memmove(unix_dest, p, unix_dest_len);
|
||||
+
|
||||
+ if ((status = unix_to_nt_file_name( &unix_dest, &nt_dest )))
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ nt_dest = malloc( nt_dest_len * sizeof(WCHAR) );
|
||||
+ if (!nt_dest)
|
||||
+ {
|
||||
+ status = STATUS_NO_MEMORY;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ status = wine_unix_to_nt_file_name( unix_dest, nt_dest, &nt_dest_len );
|
||||
+ if (status != STATUS_BUFFER_TOO_SMALL) break;
|
||||
+ free( nt_dest );
|
||||
+ }
|
||||
+ dest_allocated = TRUE;
|
||||
+ if (status != STATUS_SUCCESS)
|
||||
+ goto cleanup;
|
||||
+ nt_dest_len *= sizeof(WCHAR);
|
||||
+
|
||||
+ prefix_len = strlen("\\??\\");
|
||||
+ switch(buffer->ReparseTag)
|
||||
@ -122,10 +135,10 @@ index 44cb12f90ee..52520f5f78f 100644
|
||||
+ case IO_REPARSE_TAG_MOUNT_POINT:
|
||||
+ max_length = out_size-FIELD_OFFSET(typeof(*buffer), MountPointReparseBuffer.PathBuffer[1]);
|
||||
+ buffer->MountPointReparseBuffer.SubstituteNameOffset = 0;
|
||||
+ buffer->MountPointReparseBuffer.SubstituteNameLength = nt_dest.Length;
|
||||
+ buffer->MountPointReparseBuffer.SubstituteNameLength = nt_dest_len;
|
||||
+ subst_name = &buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)];
|
||||
+ buffer->MountPointReparseBuffer.PrintNameOffset = nt_dest.Length + sizeof(WCHAR);
|
||||
+ buffer->MountPointReparseBuffer.PrintNameLength = nt_dest.Length - prefix_len*sizeof(WCHAR);
|
||||
+ buffer->MountPointReparseBuffer.PrintNameOffset = nt_dest_len + sizeof(WCHAR);
|
||||
+ buffer->MountPointReparseBuffer.PrintNameLength = nt_dest_len - prefix_len*sizeof(WCHAR);
|
||||
+ print_name = &buffer->MountPointReparseBuffer.PathBuffer[buffer->MountPointReparseBuffer.PrintNameOffset/sizeof(WCHAR)];
|
||||
+ break;
|
||||
+ default:
|
||||
@ -134,18 +147,18 @@ index 44cb12f90ee..52520f5f78f 100644
|
||||
+ status = STATUS_NOT_IMPLEMENTED;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ if (nt_dest.Length > max_length)
|
||||
+ if (nt_dest_len > max_length)
|
||||
+ {
|
||||
+ status = STATUS_BUFFER_TOO_SMALL;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ memcpy( subst_name, nt_dest.Buffer, nt_dest.Length );
|
||||
+ memcpy( print_name, &nt_dest.Buffer[prefix_len], nt_dest.Length - prefix_len*sizeof(WCHAR) );
|
||||
+ memcpy( subst_name, nt_dest, nt_dest_len );
|
||||
+ memcpy( print_name, &nt_dest[prefix_len], nt_dest_len - prefix_len*sizeof(WCHAR) );
|
||||
+ status = STATUS_SUCCESS;
|
||||
+
|
||||
+cleanup:
|
||||
+ if (dest_allocated) RtlFreeAnsiString( &unix_dest );
|
||||
+ if (dest_allocated) free( nt_dest );
|
||||
+ if (needs_close) close( dest_fd );
|
||||
+ return status;
|
||||
+}
|
||||
@ -154,9 +167,9 @@ index 44cb12f90ee..52520f5f78f 100644
|
||||
/******************************************************************************
|
||||
* NtFsControlFile (NTDLL.@)
|
||||
*/
|
||||
@@ -5772,6 +5872,12 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
|
||||
status = STATUS_SUCCESS;
|
||||
@@ -5786,6 +5899,12 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
|
||||
break;
|
||||
}
|
||||
|
||||
+ case FSCTL_GET_REPARSE_POINT:
|
||||
+ {
|
||||
@ -168,5 +181,5 @@ index 44cb12f90ee..52520f5f78f 100644
|
||||
{
|
||||
REPARSE_DATA_BUFFER *buffer = (REPARSE_DATA_BUFFER *)in_buffer;
|
||||
--
|
||||
2.27.0
|
||||
2.17.1
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 864570de933285164823fad9d6861dd018ff5a19 Mon Sep 17 00:00:00 2001
|
||||
From 17713b3abdd15d7a76ffec8e6376f2424829ecfa 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.
|
||||
Subject: ntdll: Add support for deleting junction points.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
@ -11,10 +11,10 @@ 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 938ef2026e3..80a532282c7 100644
|
||||
index 4fe94f58bf1..9da353bbbd2 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5003,12 +5003,15 @@ static void test_reparse_points(void)
|
||||
@@ -5004,12 +5004,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};
|
||||
@ -30,7 +30,7 @@ index 938ef2026e3..80a532282c7 100644
|
||||
UNICODE_STRING nameW;
|
||||
HANDLE handle;
|
||||
WCHAR *dest;
|
||||
@@ -5056,6 +5059,8 @@ static void test_reparse_points(void)
|
||||
@@ -5057,6 +5060,8 @@ static void test_reparse_points(void)
|
||||
win_skip("Failed to open junction point directory handle (0x%x).\n", GetLastError());
|
||||
goto cleanup;
|
||||
}
|
||||
@ -39,7 +39,7 @@ index 938ef2026e3..80a532282c7 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());
|
||||
@@ -5070,6 +5075,22 @@ static void test_reparse_points(void)
|
||||
@@ -5071,6 +5076,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));
|
||||
@ -62,7 +62,7 @@ index 938ef2026e3..80a532282c7 100644
|
||||
CloseHandle(handle);
|
||||
|
||||
cleanup:
|
||||
@@ -5077,7 +5098,7 @@ cleanup:
|
||||
@@ -5078,7 +5099,7 @@ cleanup:
|
||||
pRtlFreeUnicodeString(&nameW);
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
bret = RemoveDirectoryW(reparse_path);
|
||||
@ -72,10 +72,10 @@ index 938ef2026e3..80a532282c7 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 52520f5f78f..c65ab7de16c 100644
|
||||
index cd523dcd313..3f6dcc6ab41 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -5807,6 +5807,87 @@ cleanup:
|
||||
@@ -5817,6 +5817,87 @@ cleanup:
|
||||
}
|
||||
|
||||
|
||||
@ -88,8 +88,8 @@ index 52520f5f78f..c65ab7de16c 100644
|
||||
+ char tmpdir[PATH_MAX], tmpfile[PATH_MAX], *d;
|
||||
+ BOOL tempdir_created = FALSE;
|
||||
+ int dest_fd, needs_close;
|
||||
+ ANSI_STRING unix_name;
|
||||
+ NTSTATUS status;
|
||||
+ char *unix_name;
|
||||
+ struct stat st;
|
||||
+
|
||||
+ if ((status = server_get_unix_fd( handle, FILE_SPECIAL_ACCESS, &dest_fd, &needs_close, NULL, NULL )))
|
||||
@ -98,7 +98,7 @@ index 52520f5f78f..c65ab7de16c 100644
|
||||
+ if ((status = server_get_unix_name( handle, &unix_name )))
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ TRACE("Deleting symlink %s\n", unix_name.Buffer);
|
||||
+ TRACE( "Deleting symlink %s\n", unix_name );
|
||||
+
|
||||
+ /* Produce the directory in a temporary location in the same folder */
|
||||
+ if (fstat( dest_fd, &st ) == -1)
|
||||
@ -106,7 +106,7 @@ index 52520f5f78f..c65ab7de16c 100644
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ strcpy( tmpdir, unix_name.Buffer );
|
||||
+ strcpy( tmpdir, unix_name );
|
||||
+ d = dirname( tmpdir);
|
||||
+ if (d != tmpdir) strcpy( tmpdir, d );
|
||||
+ strcat( tmpdir, "/.winelink.XXXXXX" );
|
||||
@ -126,7 +126,7 @@ index 52520f5f78f..c65ab7de16c 100644
|
||||
+ /* attemp to retain the ownership (if possible) */
|
||||
+ lchown( tmpfile, st.st_uid, st.st_gid );
|
||||
+ /* Atomically move the directory into position */
|
||||
+ if (!renameat2( -1, tmpfile, -1, unix_name.Buffer, RENAME_EXCHANGE ))
|
||||
+ if (!renameat2( -1, tmpfile, -1, unix_name, RENAME_EXCHANGE ))
|
||||
+ {
|
||||
+ /* success: link and folder have switched locations */
|
||||
+ unlink( tmpfile ); /* remove the link (at folder location) */
|
||||
@ -135,12 +135,12 @@ index 52520f5f78f..c65ab7de16c 100644
|
||||
+ {
|
||||
+ FIXME( "Atomic exchange of directory with symbolic link unsupported on this system, "
|
||||
+ "using unsafe exchange instead.\n" );
|
||||
+ if (unlink( unix_name.Buffer ))
|
||||
+ if (unlink( unix_name ))
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ if (rename( tmpfile, unix_name.Buffer ))
|
||||
+ if (rename( tmpfile, unix_name ))
|
||||
+ {
|
||||
+ status = errno_to_status( errno );
|
||||
+ goto cleanup; /* not moved, orignal file/folder at destination is orphaned */
|
||||
@ -163,9 +163,9 @@ index 52520f5f78f..c65ab7de16c 100644
|
||||
/******************************************************************************
|
||||
* NtFsControlFile (NTDLL.@)
|
||||
*/
|
||||
@@ -5872,6 +5953,22 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
|
||||
status = STATUS_SUCCESS;
|
||||
@@ -5899,6 +5980,22 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
|
||||
break;
|
||||
}
|
||||
|
||||
+ case FSCTL_DELETE_REPARSE_POINT:
|
||||
+ {
|
||||
@ -208,5 +208,5 @@ index 21d42e17325..4539b89d583 100644
|
||||
+
|
||||
#endif /* __WINE_NTIFS_H */
|
||||
--
|
||||
2.27.0
|
||||
2.17.1
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
From c86d6453694ed2723e5eaa1c55f9e53e1b9946d8 Mon Sep 17 00:00:00 2001
|
||||
From 4b5123561e8260ed4b1421b0cf127468ac7c131f 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: 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 bc6961bc61..e1f216370d 100644
|
||||
index 9da353bbbd2..051237dd494 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -4925,6 +4925,11 @@ static void test_reparse_points(void)
|
||||
@@ -5066,6 +5066,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());
|
||||
|
||||
|
@ -1,66 +0,0 @@
|
||||
From 3473ccddec5c67bbfe1d477ce36f537493fae54b 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] kernel32,ntdll: Add support for deleting junction points with
|
||||
RemoveDirectory.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 34 +++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 33 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 6b3071f4095..1d5e0ce95b0 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5010,7 +5010,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;
|
||||
@@ -5099,6 +5099,38 @@ static void test_reparse_points(void)
|
||||
"Junction point folder's access time does not match.\n");
|
||||
CloseHandle(handle);
|
||||
|
||||
+ /* Check deleting a junction point as if it were a directory */
|
||||
+ 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);
|
||||
+ 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());
|
||||
+ CloseHandle(handle);
|
||||
+ bret = RemoveDirectoryW(reparse_path);
|
||||
+ ok(bret, "Failed to delete junction point as directory!\n");
|
||||
+ dwret = GetFileAttributesW(reparse_path);
|
||||
+ ok(dwret == (DWORD)~0, "Junction point still exists (attributes: 0x%x)!\n", dwret);
|
||||
+
|
||||
+ /* Check deleting a junction point as if it were a file */
|
||||
+ HeapFree(GetProcessHeap(), 0, buffer);
|
||||
+ bret = CreateDirectoryW(reparse_path, NULL);
|
||||
+ 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);
|
||||
+ 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());
|
||||
+ CloseHandle(handle);
|
||||
+ bret = DeleteFileW(reparse_path);
|
||||
+ ok(!bret, "Succeeded in deleting junction point as file!\n");
|
||||
+ err = GetLastError();
|
||||
+ ok(err == ERROR_ACCESS_DENIED, "Expected last error 0x%x for DeleteFile on junction point (actually 0x%x)!\n",
|
||||
+ ERROR_ACCESS_DENIED, err);
|
||||
+ dwret = GetFileAttributesW(reparse_path);
|
||||
+ 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);
|
||||
+
|
||||
cleanup:
|
||||
/* Cleanup */
|
||||
pRtlFreeUnicodeString(&nameW);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,161 @@
|
||||
From 398754456f977e063aa1c180301ce44fd5fdaf84 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: server: Add support for deleting junction points with
|
||||
RemoveDirectory.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 34 +++++++++++++++++++++++++++++++++-
|
||||
server/fd.c | 27 ++++++++++++++++++---------
|
||||
2 files changed, 51 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 051237dd494..77a1be8307b 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5010,7 +5010,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;
|
||||
@@ -5099,6 +5099,38 @@ static void test_reparse_points(void)
|
||||
"Junction point folder's access time does not match.\n");
|
||||
CloseHandle(handle);
|
||||
|
||||
+ /* Check deleting a junction point as if it were a directory */
|
||||
+ 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);
|
||||
+ 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());
|
||||
+ CloseHandle(handle);
|
||||
+ bret = RemoveDirectoryW(reparse_path);
|
||||
+ ok(bret, "Failed to delete junction point as directory!\n");
|
||||
+ dwret = GetFileAttributesW(reparse_path);
|
||||
+ ok(dwret == (DWORD)~0, "Junction point still exists (attributes: 0x%x)!\n", dwret);
|
||||
+
|
||||
+ /* Check deleting a junction point as if it were a file */
|
||||
+ HeapFree(GetProcessHeap(), 0, buffer);
|
||||
+ bret = CreateDirectoryW(reparse_path, NULL);
|
||||
+ 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);
|
||||
+ 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());
|
||||
+ CloseHandle(handle);
|
||||
+ bret = DeleteFileW(reparse_path);
|
||||
+ ok(!bret, "Succeeded in deleting junction point as file!\n");
|
||||
+ err = GetLastError();
|
||||
+ ok(err == ERROR_ACCESS_DENIED, "Expected last error 0x%x for DeleteFile on junction point (actually 0x%x)!\n",
|
||||
+ ERROR_ACCESS_DENIED, err);
|
||||
+ dwret = GetFileAttributesW(reparse_path);
|
||||
+ 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);
|
||||
+
|
||||
cleanup:
|
||||
/* Cleanup */
|
||||
pRtlFreeUnicodeString(&nameW);
|
||||
diff --git a/server/fd.c b/server/fd.c
|
||||
index 7ea8ac273e5..c0d35e2fa4c 100644
|
||||
--- a/server/fd.c
|
||||
+++ b/server/fd.c
|
||||
@@ -169,7 +169,8 @@ struct closed_fd
|
||||
struct list entry; /* entry in inode closed list */
|
||||
int unix_fd; /* the unix file descriptor */
|
||||
int unlink; /* whether to unlink on close: -1 - implicit FILE_DELETE_ON_CLOSE, 1 - explicit disposition */
|
||||
- char *unix_name; /* name to unlink on close, points to parent fd unix_name */
|
||||
+ char *unlink_name; /* name to unlink on close, points to parent fd unix_name */
|
||||
+ char *unix_name; /* name to real file path, points to parent fd unix_name */
|
||||
};
|
||||
|
||||
struct fd
|
||||
@@ -184,6 +185,7 @@ struct fd
|
||||
unsigned int access; /* file access (FILE_READ_DATA etc.) */
|
||||
unsigned int options; /* file options (FILE_DELETE_ON_CLOSE, FILE_SYNCHRONOUS...) */
|
||||
unsigned int sharing; /* file sharing mode */
|
||||
+ char *unlink_name; /* file name to unlink on close */
|
||||
char *unix_name; /* unix file name */
|
||||
int unix_fd; /* unix file descriptor */
|
||||
unsigned int no_fd_status;/* status to return when unix_fd is -1 */
|
||||
@@ -1113,6 +1115,7 @@ static void inode_close_pending( struct inode *inode, int keep_unlinks )
|
||||
if (!keep_unlinks || !fd->unlink) /* get rid of it unless there's an unlink pending on that file */
|
||||
{
|
||||
list_remove( ptr );
|
||||
+ free( fd->unlink_name );
|
||||
free( fd->unix_name );
|
||||
free( fd );
|
||||
}
|
||||
@@ -1147,12 +1150,13 @@ static void inode_destroy( struct object *obj )
|
||||
{
|
||||
/* make sure it is still the same file */
|
||||
struct stat st;
|
||||
- if (!stat( fd->unix_name, &st ) && st.st_dev == inode->device->dev && st.st_ino == inode->ino)
|
||||
+ if (!lstat( fd->unlink_name, &st ) && st.st_dev == inode->device->dev && st.st_ino == inode->ino)
|
||||
{
|
||||
- if (S_ISDIR(st.st_mode)) rmdir( fd->unix_name );
|
||||
- else unlink( fd->unix_name );
|
||||
+ if (S_ISDIR(st.st_mode)) rmdir( fd->unlink_name );
|
||||
+ else unlink( fd->unlink_name );
|
||||
}
|
||||
}
|
||||
+ free( fd->unlink_name );
|
||||
free( fd->unix_name );
|
||||
free( fd );
|
||||
}
|
||||
@@ -1903,18 +1907,19 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
fd->unix_name = NULL;
|
||||
if ((path = dup_fd_name( root, name )))
|
||||
{
|
||||
+ fd->unlink_name = path;
|
||||
fd->unix_name = realpath( path, NULL );
|
||||
- free( path );
|
||||
}
|
||||
|
||||
closed_fd->unix_fd = fd->unix_fd;
|
||||
closed_fd->unlink = 0;
|
||||
+ closed_fd->unlink_name = fd->unlink_name;
|
||||
closed_fd->unix_name = fd->unix_name;
|
||||
- fstat( fd->unix_fd, &st );
|
||||
+ lstat( fd->unlink_name, &st );
|
||||
*mode = st.st_mode;
|
||||
|
||||
/* only bother with an inode for normal files and directories */
|
||||
- if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
|
||||
+ if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))
|
||||
{
|
||||
unsigned int err;
|
||||
struct inode *inode = get_inode( st.st_dev, st.st_ino, fd->unix_fd );
|
||||
@@ -1932,6 +1937,9 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
list_add_head( &inode->open, &fd->inode_entry );
|
||||
closed_fd = NULL;
|
||||
|
||||
+ fstat( fd->unix_fd, &st );
|
||||
+ *mode = st.st_mode;
|
||||
+
|
||||
/* check directory options */
|
||||
if ((options & FILE_DIRECTORY_FILE) && !S_ISDIR(st.st_mode))
|
||||
{
|
||||
@@ -2563,10 +2571,11 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr,
|
||||
fchmod( fd->unix_fd, st.st_mode );
|
||||
}
|
||||
|
||||
+ free( fd->unlink_name );
|
||||
free( fd->unix_name );
|
||||
+ fd->closed->unlink_name = fd->unlink_name = name;
|
||||
fd->closed->unix_name = fd->unix_name = realpath( name, NULL );
|
||||
- free( name );
|
||||
- if (!fd->unix_name)
|
||||
+ if (!fd->unlink_name || !fd->unix_name)
|
||||
set_error( STATUS_NO_MEMORY );
|
||||
return;
|
||||
|
||||
--
|
||||
2.17.1
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 3ef1ecf4b3b6db13e96d6440e51c9407f8b5dcda Mon Sep 17 00:00:00 2001
|
||||
From f74db8315285e44fe21d120337fe568ed9824ae1 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.
|
||||
Subject: ntdll: Add support for absolute symlink creation.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
@ -11,10 +11,10 @@ Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
3 files changed, 143 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 541572c27ce..f91bb40a133 100644
|
||||
index 77a1be8307b..986468a1495 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -4972,26 +4972,50 @@ static void test_file_readonly_access(void)
|
||||
@@ -4973,26 +4973,50 @@ static void test_file_readonly_access(void)
|
||||
DeleteFileW(path);
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ index 541572c27ce..f91bb40a133 100644
|
||||
lstrcpyW(subst_dest, filename);
|
||||
lstrcpyW(print_dest, &filename[prefix_len]);
|
||||
*pbuffer = buffer;
|
||||
@@ -5011,10 +5035,12 @@ static void test_reparse_points(void)
|
||||
@@ -5012,10 +5036,12 @@ static void test_reparse_points(void)
|
||||
REPARSE_DATA_BUFFER *buffer = NULL;
|
||||
DWORD dwret, dwLen, dwFlags, err;
|
||||
INT buffer_len, string_len;
|
||||
@ -87,7 +87,7 @@ index 541572c27ce..f91bb40a133 100644
|
||||
BOOL bret;
|
||||
|
||||
/* Create a temporary folder for the junction point tests */
|
||||
@@ -5061,7 +5087,7 @@ static void test_reparse_points(void)
|
||||
@@ -5062,7 +5088,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 541572c27ce..f91bb40a133 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());
|
||||
|
||||
@@ -5102,7 +5128,7 @@ static void test_reparse_points(void)
|
||||
@@ -5103,7 +5129,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 541572c27ce..f91bb40a133 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);
|
||||
@@ -5117,7 +5143,7 @@ static void test_reparse_points(void)
|
||||
@@ -5118,7 +5144,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 541572c27ce..f91bb40a133 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);
|
||||
@@ -5130,14 +5156,73 @@ static void test_reparse_points(void)
|
||||
@@ -5131,14 +5157,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,10 +193,10 @@ index 541572c27ce..f91bb40a133 100644
|
||||
}
|
||||
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index c65ab7de16c..15f6a006145 100644
|
||||
index 3f6dcc6ab41..b8dc02127ba 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -5616,17 +5616,33 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer,
|
||||
@@ -5601,18 +5601,34 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer,
|
||||
NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
{
|
||||
BOOL src_allocated = FALSE, dest_allocated = FALSE, tempdir_created = FALSE;
|
||||
@ -204,7 +204,8 @@ index c65ab7de16c..15f6a006145 100644
|
||||
- int offset = buffer->MountPointReparseBuffer.SubstituteNameOffset;
|
||||
- WCHAR *dest = &buffer->MountPointReparseBuffer.PathBuffer[offset];
|
||||
char tmpdir[PATH_MAX], tmplink[PATH_MAX], *d;
|
||||
ANSI_STRING unix_src, unix_dest;
|
||||
SIZE_T unix_dest_len = PATH_MAX;
|
||||
char *unix_src, *unix_dest;
|
||||
char magic_dest[PATH_MAX];
|
||||
int dest_fd, needs_close;
|
||||
UNICODE_STRING nt_dest;
|
||||
@ -233,7 +234,7 @@ index c65ab7de16c..15f6a006145 100644
|
||||
if ((status = server_get_unix_fd( handle, FILE_SPECIAL_ACCESS, &dest_fd, &needs_close, NULL, NULL )))
|
||||
return status;
|
||||
|
||||
@@ -5650,6 +5666,18 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
@@ -5647,6 +5663,18 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
strcat( magic_dest, "." );
|
||||
strcat( magic_dest, "/" );
|
||||
}
|
||||
@ -249,10 +250,10 @@ index c65ab7de16c..15f6a006145 100644
|
||||
+ strcat( magic_dest, "." );
|
||||
+ strcat( magic_dest, "/" );
|
||||
+ }
|
||||
strcat( magic_dest, unix_dest.Buffer );
|
||||
strcat( magic_dest, unix_dest );
|
||||
|
||||
/* Produce the link in a temporary location in the same folder */
|
||||
@@ -5982,6 +6010,7 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
|
||||
@@ -6009,6 +6037,7 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
|
||||
switch(buffer->ReparseTag)
|
||||
{
|
||||
case IO_REPARSE_TAG_MOUNT_POINT:
|
||||
@ -294,5 +295,5 @@ index 4539b89d583..ab3273d3f81 100644
|
||||
typedef struct _REPARSE_GUID_DATA_BUFFER {
|
||||
DWORD ReparseTag;
|
||||
--
|
||||
2.27.0
|
||||
2.17.1
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 58371a3c2d5fed81abc2b1ae6f79133dd57a873d Mon Sep 17 00:00:00 2001
|
||||
From 3595e892dbf4d5b123ce641b6ce72490cc3d782f 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.
|
||||
Subject: ntdll: Add support for reading absolute symlinks.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
@ -10,10 +10,10 @@ Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
2 files changed, 34 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index f91bb40a133..5d3411d242e 100644
|
||||
index 986468a1495..5b7bdf7ddfd 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5207,7 +5207,6 @@ static void test_reparse_points(void)
|
||||
@@ -5208,7 +5208,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 f91bb40a133..5d3411d242e 100644
|
||||
ok(bret, "Failed to create symlink! (0x%x)\n", GetLastError());
|
||||
|
||||
/* Check the file attributes of the symlink */
|
||||
@@ -5215,6 +5214,18 @@ static void test_reparse_points(void)
|
||||
@@ -5216,6 +5215,18 @@ 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);
|
||||
|
||||
@ -41,18 +41,18 @@ index f91bb40a133..5d3411d242e 100644
|
||||
/* Cleanup */
|
||||
pRtlFreeUnicodeString(&nameW);
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index 15f6a006145..9cecf44db82 100644
|
||||
index b8dc02127ba..cd14a2e24c3 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -5748,6 +5748,7 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
UNICODE_STRING nt_dest;
|
||||
@@ -5746,6 +5746,7 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
int unix_dest_len;
|
||||
DWORD max_length;
|
||||
NTSTATUS status;
|
||||
+ ULONG flags = 0;
|
||||
WCHAR *nt_dest;
|
||||
INT prefix_len;
|
||||
ssize_t ret;
|
||||
char *p;
|
||||
@@ -5794,6 +5795,17 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
@@ -5790,6 +5791,17 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
}
|
||||
buffer->ReparseTag |= (val << i);
|
||||
}
|
||||
@ -67,20 +67,20 @@ index 15f6a006145..9cecf44db82 100644
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ }
|
||||
unix_dest.Length -= (p - unix_dest.Buffer);
|
||||
memmove(unix_dest.Buffer, p, unix_dest.Length);
|
||||
unix_dest_len -= (p - unix_dest);
|
||||
memmove(unix_dest, p, unix_dest_len);
|
||||
|
||||
@@ -5812,6 +5824,16 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
buffer->MountPointReparseBuffer.PrintNameLength = nt_dest.Length - prefix_len*sizeof(WCHAR);
|
||||
@@ -5822,6 +5834,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)];
|
||||
break;
|
||||
+ case IO_REPARSE_TAG_SYMLINK:
|
||||
+ max_length = out_size-FIELD_OFFSET(typeof(*buffer), SymbolicLinkReparseBuffer.PathBuffer[1]);
|
||||
+ buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
|
||||
+ buffer->SymbolicLinkReparseBuffer.SubstituteNameLength = nt_dest.Length;
|
||||
+ buffer->SymbolicLinkReparseBuffer.SubstituteNameLength = nt_dest_len;
|
||||
+ subst_name = &buffer->SymbolicLinkReparseBuffer.PathBuffer[buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)];
|
||||
+ buffer->SymbolicLinkReparseBuffer.PrintNameOffset = nt_dest.Length + sizeof(WCHAR);
|
||||
+ buffer->SymbolicLinkReparseBuffer.PrintNameLength = nt_dest.Length - prefix_len*sizeof(WCHAR);
|
||||
+ buffer->SymbolicLinkReparseBuffer.PrintNameOffset = nt_dest_len + sizeof(WCHAR);
|
||||
+ buffer->SymbolicLinkReparseBuffer.PrintNameLength = nt_dest_len - prefix_len*sizeof(WCHAR);
|
||||
+ print_name = &buffer->SymbolicLinkReparseBuffer.PathBuffer[buffer->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR)];
|
||||
+ buffer->SymbolicLinkReparseBuffer.Flags = flags;
|
||||
+ break;
|
||||
@ -88,5 +88,5 @@ index 15f6a006145..9cecf44db82 100644
|
||||
/* unrecognized (regular) files should probably be treated as symlinks */
|
||||
WARN("unrecognized symbolic link\n");
|
||||
--
|
||||
2.27.0
|
||||
2.17.1
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 478bca2da5a745e14d4fd16a3d4415cf08855308 Mon Sep 17 00:00:00 2001
|
||||
From 248faa7fd14b6ff0028c7762edd0bb8ad564b9ca 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.
|
||||
Subject: ntdll: Add support for deleting symlinks.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
@ -10,10 +10,10 @@ 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 5d3411d242e..df912e18496 100644
|
||||
index 5b7bdf7ddfd..b6a58c3f2a7 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5224,6 +5224,22 @@ static void test_reparse_points(void)
|
||||
@@ -5225,6 +5225,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));
|
||||
@ -37,10 +37,10 @@ index 5d3411d242e..df912e18496 100644
|
||||
|
||||
cleanup:
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index 9cecf44db82..e35ea49d17f 100644
|
||||
index cd14a2e24c3..232cbb36f42 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -6010,6 +6010,7 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
|
||||
@@ -6037,6 +6037,7 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
|
||||
switch(buffer->ReparseTag)
|
||||
{
|
||||
case IO_REPARSE_TAG_MOUNT_POINT:
|
||||
@ -49,5 +49,5 @@ index 9cecf44db82..e35ea49d17f 100644
|
||||
break;
|
||||
default:
|
||||
--
|
||||
2.27.0
|
||||
2.17.1
|
||||
|
||||
|
@ -1,20 +1,20 @@
|
||||
From 2fe2cb6a67925f22e9b3fbffefd20c2fe0040775 Mon Sep 17 00:00:00 2001
|
||||
From 9baddd14dceb102d123a6470a12e43ffd4e1e4de 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.
|
||||
Subject: ntdll: Add support for relative symlink creation.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 30 ++++++++++++++++-----
|
||||
dlls/ntdll/unix/file.c | 58 ++++++++++++++++++++++++++++++++++++-----
|
||||
include/ntifs.h | 2 ++
|
||||
3 files changed, 77 insertions(+), 13 deletions(-)
|
||||
dlls/ntdll/tests/file.c | 30 +++++++++++---
|
||||
dlls/ntdll/unix/file.c | 90 +++++++++++++++++++++++++++++++++++++----
|
||||
include/ntifs.h | 2 +
|
||||
3 files changed, 109 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index b93ba0e87ed..975a72e7103 100644
|
||||
index b6a58c3f2a7..9b510fe9057 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -4972,7 +4972,8 @@ static void test_file_readonly_access(void)
|
||||
@@ -4973,7 +4973,8 @@ static void test_file_readonly_access(void)
|
||||
DeleteFileW(path);
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ index b93ba0e87ed..975a72e7103 100644
|
||||
{
|
||||
static INT header_size = offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer);
|
||||
INT buffer_size, struct_size, data_size, string_len, prefix_len;
|
||||
@@ -4990,7 +4991,7 @@ static INT build_reparse_buffer(const WCHAR *filename, ULONG tag, REPARSE_DATA_B
|
||||
@@ -4991,7 +4992,7 @@ static INT build_reparse_buffer(const WCHAR *filename, ULONG tag, REPARSE_DATA_B
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -33,7 +33,7 @@ index b93ba0e87ed..975a72e7103 100644
|
||||
string_len = lstrlenW(&filename[prefix_len]);
|
||||
data_size = (prefix_len + 2 * string_len + 2) * sizeof(WCHAR);
|
||||
buffer_size = struct_size + data_size;
|
||||
@@ -5010,6 +5011,7 @@ static INT build_reparse_buffer(const WCHAR *filename, ULONG tag, REPARSE_DATA_B
|
||||
@@ -5011,6 +5012,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 b93ba0e87ed..975a72e7103 100644
|
||||
subst_dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[0];
|
||||
print_dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[prefix_len + string_len + 1];
|
||||
break;
|
||||
@@ -5087,7 +5089,7 @@ static void test_reparse_points(void)
|
||||
@@ -5088,7 +5090,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 b93ba0e87ed..975a72e7103 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());
|
||||
|
||||
@@ -5128,7 +5130,7 @@ static void test_reparse_points(void)
|
||||
@@ -5129,7 +5131,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 b93ba0e87ed..975a72e7103 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);
|
||||
@@ -5143,7 +5145,7 @@ static void test_reparse_points(void)
|
||||
@@ -5144,7 +5146,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 b93ba0e87ed..975a72e7103 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);
|
||||
@@ -5205,7 +5207,7 @@ static void test_reparse_points(void)
|
||||
@@ -5206,7 +5208,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 b93ba0e87ed..975a72e7103 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());
|
||||
|
||||
@@ -5242,6 +5244,22 @@ static void test_reparse_points(void)
|
||||
@@ -5243,6 +5245,22 @@ static void test_reparse_points(void)
|
||||
"Symlink folder's access time does not match.\n");
|
||||
CloseHandle(handle);
|
||||
|
||||
@ -101,19 +101,20 @@ index b93ba0e87ed..975a72e7103 100644
|
||||
/* Cleanup */
|
||||
pRtlFreeUnicodeString(&nameW);
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index fe945cef477..a1d1863133a 100644
|
||||
index 232cbb36f42..3652fbb1a0d 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -5669,16 +5669,19 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer,
|
||||
@@ -5600,17 +5600,20 @@ static void ignore_server_ioctl_struct_holes( ULONG code, const void *in_buffer,
|
||||
*/
|
||||
NTSTATUS FILE_CreateSymlink(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;
|
||||
+ BOOL nt_dest_allocated = FALSE, tempdir_created = FALSE;
|
||||
+ char *unix_src, *unix_dest, *unix_path = NULL;
|
||||
char tmpdir[PATH_MAX], tmplink[PATH_MAX], *d;
|
||||
- ANSI_STRING unix_src, unix_dest;
|
||||
+ ANSI_STRING unix_src, unix_dest, unix_path;
|
||||
SIZE_T unix_dest_len = PATH_MAX;
|
||||
- char *unix_src, *unix_dest;
|
||||
char magic_dest[PATH_MAX];
|
||||
int dest_fd, needs_close;
|
||||
+ int relative_offset = 0;
|
||||
@ -126,7 +127,7 @@ index fe945cef477..a1d1863133a 100644
|
||||
int i;
|
||||
|
||||
switch(buffer->ReparseTag)
|
||||
@@ -5687,11 +5690,13 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
@@ -5619,11 +5622,13 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
dest_len = buffer->MountPointReparseBuffer.SubstituteNameLength;
|
||||
offset = buffer->MountPointReparseBuffer.SubstituteNameOffset;
|
||||
dest = &buffer->MountPointReparseBuffer.PathBuffer[offset];
|
||||
@ -140,7 +141,7 @@ index fe945cef477..a1d1863133a 100644
|
||||
break;
|
||||
default:
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
@@ -5703,17 +5708,54 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
@@ -5635,8 +5640,64 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
if ((status = server_get_unix_name( handle, &unix_src )))
|
||||
goto cleanup;
|
||||
src_allocated = TRUE;
|
||||
@ -148,24 +149,54 @@ index fe945cef477..a1d1863133a 100644
|
||||
- nt_dest.Length = dest_len;
|
||||
+ if (flags == SYMLINK_FLAG_RELATIVE)
|
||||
+ {
|
||||
+ UNICODE_STRING nt_path;
|
||||
+ SIZE_T nt_path_len = PATH_MAX, unix_path_len = PATH_MAX;
|
||||
+ WCHAR *nt_path;
|
||||
+
|
||||
+ unix_path.MaximumLength = strlen(unix_src.Buffer) + 2;
|
||||
+ unix_path.Buffer = RtlAllocateHeap( GetProcessHeap(), 0, unix_path.MaximumLength );
|
||||
+ /* resolve the NT path of the source */
|
||||
+ unix_path = malloc( strlen(unix_src) + 2 );
|
||||
+ path_allocated = TRUE;
|
||||
+ strcpy( unix_path.Buffer, unix_src.Buffer );
|
||||
+ d = dirname( unix_path.Buffer );
|
||||
+ if (d != unix_path.Buffer) strcpy( unix_path.Buffer, d );
|
||||
+ strcat( unix_path.Buffer, "/");
|
||||
+ unix_path.Length = strlen( unix_path.Buffer );
|
||||
+ if ((status = unix_to_nt_file_name( &unix_path, &nt_path )))
|
||||
+ strcpy( unix_path, unix_src );
|
||||
+ d = dirname( unix_path );
|
||||
+ if (d != unix_path) strcpy( unix_path, d );
|
||||
+ strcat( unix_path, "/");
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ nt_path = malloc( nt_path_len * sizeof(WCHAR) );
|
||||
+ if (!nt_path)
|
||||
+ {
|
||||
+ status = STATUS_NO_MEMORY;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ status = wine_unix_to_nt_file_name( unix_path, nt_path, &nt_path_len );
|
||||
+ if (status != STATUS_BUFFER_TOO_SMALL) break;
|
||||
+ free( nt_path );
|
||||
+ }
|
||||
+ if (status != STATUS_SUCCESS)
|
||||
+ goto cleanup;
|
||||
+ nt_dest.MaximumLength = dest_len + (wcslen( nt_path.Buffer ) + 1) * sizeof(WCHAR);
|
||||
+ free(unix_path);
|
||||
+ /* re-resolve the unix path for the source */
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ UNICODE_STRING nt_path_tmp;
|
||||
+ unix_path = malloc( unix_path_len );
|
||||
+ if (!unix_path)
|
||||
+ {
|
||||
+ status = STATUS_NO_MEMORY;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ nt_path_tmp.Buffer = nt_path;
|
||||
+ nt_path_tmp.Length = lstrlenW(nt_path) * sizeof(WCHAR);
|
||||
+ status = wine_nt_to_unix_file_name( &nt_path_tmp, unix_path, &unix_path_len, FALSE );
|
||||
+ if (status != STATUS_BUFFER_TOO_SMALL) break;
|
||||
+ free( unix_path );
|
||||
+ }
|
||||
+ /* append the destination */
|
||||
+ nt_dest.MaximumLength = dest_len + (lstrlenW( nt_path ) + 1) * sizeof(WCHAR);
|
||||
+ nt_dest.Buffer = RtlAllocateHeap( GetProcessHeap(), 0, nt_dest.MaximumLength );
|
||||
+ wcscpy( nt_dest.Buffer, nt_path.Buffer );
|
||||
+ RtlFreeUnicodeString( &nt_path );
|
||||
+ memcpy( &nt_dest.Buffer[wcslen(nt_dest.Buffer)], dest, dest_len + sizeof(WCHAR));
|
||||
+ nt_dest.Length = wcslen( nt_dest.Buffer ) * sizeof(WCHAR);
|
||||
+ lstrcpyW( nt_dest.Buffer, nt_path );
|
||||
+ free( nt_path );
|
||||
+ memcpy( &nt_dest.Buffer[lstrlenW(nt_dest.Buffer)], dest, dest_len + sizeof(WCHAR));
|
||||
+ nt_dest.Length = lstrlenW( nt_dest.Buffer ) * sizeof(WCHAR);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
@ -173,22 +204,27 @@ index fe945cef477..a1d1863133a 100644
|
||||
+ nt_dest.Length = dest_len;
|
||||
+ }
|
||||
+ nt_dest_allocated = TRUE;
|
||||
status = nt_to_unix_file_name( &nt_dest, &unix_dest, 0 );
|
||||
+ /* resolve the NT path of the destination */
|
||||
for (;;)
|
||||
{
|
||||
unix_dest = malloc( unix_dest_len );
|
||||
@@ -5652,11 +5713,24 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
if (status != STATUS_SUCCESS && status != STATUS_NO_SUCH_FILE)
|
||||
goto cleanup;
|
||||
dest_allocated = TRUE;
|
||||
+ /* check that the source and destination paths are the same up to the relative path */
|
||||
+ if (flags == SYMLINK_FLAG_RELATIVE)
|
||||
+ {
|
||||
+ relative_offset = strlen(unix_path.Buffer);
|
||||
+ if (strncmp( unix_path.Buffer, unix_dest.Buffer, relative_offset ) != 0)
|
||||
+ relative_offset = strlen(unix_path);
|
||||
+ if (strncmp( unix_path, unix_dest, relative_offset ) != 0)
|
||||
+ {
|
||||
+ status = STATUS_IO_REPARSE_DATA_INVALID;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- TRACE("Linking %s to %s\n", unix_src.Buffer, unix_dest.Buffer);
|
||||
+ TRACE("Linking %s to %s\n", unix_src.Buffer, &unix_dest.Buffer[relative_offset]);
|
||||
- TRACE( "Linking %s to %s\n", unix_src, unix_dest );
|
||||
+ TRACE( "Linking %s to %s\n", unix_src, &unix_dest[relative_offset] );
|
||||
|
||||
/* Encode the reparse tag into the symlink */
|
||||
- strcpy( magic_dest, "/" );
|
||||
@ -199,23 +235,23 @@ index fe945cef477..a1d1863133a 100644
|
||||
for (i = 0; i < sizeof(ULONG)*8; i++)
|
||||
{
|
||||
if ((buffer->ReparseTag >> i) & 1)
|
||||
@@ -5732,7 +5774,7 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
@@ -5675,7 +5749,7 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
strcat( magic_dest, "." );
|
||||
strcat( magic_dest, "/" );
|
||||
}
|
||||
- strcat( magic_dest, unix_dest.Buffer );
|
||||
+ strcat( magic_dest, &unix_dest.Buffer[relative_offset] );
|
||||
- strcat( magic_dest, unix_dest );
|
||||
+ strcat( magic_dest, &unix_dest[relative_offset] );
|
||||
|
||||
/* Produce the link in a temporary location in the same folder */
|
||||
strcpy( tmpdir, unix_src.Buffer );
|
||||
@@ -5782,7 +5824,9 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
strcpy( tmpdir, unix_src );
|
||||
@@ -5725,7 +5799,9 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
|
||||
cleanup:
|
||||
if (tempdir_created) rmdir( tmpdir );
|
||||
+ if (path_allocated) RtlFreeAnsiString( &unix_path );
|
||||
if (dest_allocated) RtlFreeAnsiString( &unix_dest );
|
||||
+ if (path_allocated) free( unix_path );
|
||||
if (dest_allocated) free( unix_dest );
|
||||
+ if (nt_dest_allocated) RtlFreeUnicodeString( &nt_dest );
|
||||
if (src_allocated) RtlFreeAnsiString( &unix_src );
|
||||
if (src_allocated) free( unix_src );
|
||||
if (needs_close) close( dest_fd );
|
||||
return status;
|
||||
diff --git a/include/ntifs.h b/include/ntifs.h
|
||||
@ -230,5 +266,5 @@ index ab3273d3f81..0d02225bc4f 100644
|
||||
+
|
||||
#endif /* __WINE_NTIFS_H */
|
||||
--
|
||||
2.27.0
|
||||
2.17.1
|
||||
|
||||
|
@ -1,19 +1,19 @@
|
||||
From af4840c79a9958609575553aaf8bdf13dabe68ef Mon Sep 17 00:00:00 2001
|
||||
From 5658e73f218d01b0e11bc4575cf0502b8235ec2c 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.
|
||||
Subject: ntdll: Add support for reading relative symlinks.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 13 +++++++++++-
|
||||
dlls/ntdll/unix/file.c | 44 ++++++++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 55 insertions(+), 2 deletions(-)
|
||||
dlls/ntdll/tests/file.c | 13 ++++++++-
|
||||
dlls/ntdll/unix/file.c | 61 ++++++++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 72 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 515a84da4d6..30ab4110105 100644
|
||||
index 9b510fe9057..0db7372a0c8 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5257,9 +5257,20 @@ static void test_reparse_points(void)
|
||||
@@ -5258,9 +5258,20 @@ 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);
|
||||
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
|
||||
@ -36,21 +36,21 @@ index 515a84da4d6..30ab4110105 100644
|
||||
/* Cleanup */
|
||||
pRtlFreeUnicodeString(&nameW);
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index eb39dc0873b..d19b48d4224 100644
|
||||
index 3652fbb1a0d..e62a2529bb2 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -5790,6 +5790,7 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
@@ -5820,6 +5820,7 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
BOOL dest_allocated = FALSE;
|
||||
int dest_fd, needs_close;
|
||||
UNICODE_STRING nt_dest;
|
||||
int unix_dest_len;
|
||||
+ int path_len = 0;
|
||||
DWORD max_length;
|
||||
NTSTATUS status;
|
||||
ULONG flags = 0;
|
||||
@@ -5817,6 +5818,11 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
@@ -5845,6 +5846,11 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
|
||||
/* Decode the reparse tag from the symlink */
|
||||
p = unix_dest.Buffer;
|
||||
p = unix_dest;
|
||||
+ if (*p == '.')
|
||||
+ {
|
||||
+ flags = SYMLINK_FLAG_RELATIVE;
|
||||
@ -59,54 +59,75 @@ index eb39dc0873b..d19b48d4224 100644
|
||||
if (*p++ != '/')
|
||||
{
|
||||
status = STATUS_NOT_IMPLEMENTED;
|
||||
@@ -5853,10 +5859,46 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
unix_dest.Length -= (p - unix_dest.Buffer);
|
||||
memmove(unix_dest.Buffer, p, unix_dest.Length);
|
||||
@@ -5881,6 +5887,25 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
unix_dest_len -= (p - unix_dest);
|
||||
memmove(unix_dest, p, unix_dest_len);
|
||||
|
||||
+ /* convert the relative path into an absolute path */
|
||||
+ if (flags == SYMLINK_FLAG_RELATIVE)
|
||||
+ {
|
||||
+ int offset = unix_src.Length + 2;
|
||||
+ int unix_src_len = strlen(unix_src);
|
||||
+ int offset = unix_src_len + 2;
|
||||
+ char *d;
|
||||
+ memcpy( &unix_dest.Buffer[offset], unix_dest.Buffer, unix_dest.Length );
|
||||
+ unix_dest.Buffer[offset+unix_dest.Length] = 0;
|
||||
+ memcpy( unix_dest.Buffer, unix_src.Buffer, unix_src.Length );
|
||||
+ unix_dest.Buffer[unix_src.Length] = 0;
|
||||
+ d = dirname( unix_dest.Buffer );
|
||||
+ if (d != unix_dest.Buffer) strcpy( unix_dest.Buffer, d );
|
||||
+ strcat( unix_dest.Buffer, "/" );
|
||||
+ path_len = strlen( unix_dest.Buffer );
|
||||
+ memmove( &unix_dest.Buffer[path_len], &unix_dest.Buffer[offset], unix_dest.Length + 1 );
|
||||
+ unix_dest.Length = strlen( unix_dest.Buffer );
|
||||
+
|
||||
+ memcpy( &unix_dest[offset], unix_dest, unix_dest_len );
|
||||
+ unix_dest[offset+unix_dest_len] = 0;
|
||||
+ memcpy( unix_dest, unix_src, unix_src_len );
|
||||
+ unix_dest[unix_src_len] = 0;
|
||||
+ d = dirname( unix_dest );
|
||||
+ if (d != unix_dest) strcpy( unix_dest, d );
|
||||
+ strcat( unix_dest, "/" );
|
||||
+ path_len = strlen( unix_dest );
|
||||
+ memmove( &unix_dest[path_len], &unix_dest[offset], unix_dest_len + 1 );
|
||||
+ unix_dest_len = strlen( unix_dest );
|
||||
+ }
|
||||
if ((status = unix_to_nt_file_name( &unix_dest, &nt_dest )))
|
||||
+ /* resolve the NT path */
|
||||
for (;;)
|
||||
{
|
||||
nt_dest = malloc( nt_dest_len * sizeof(WCHAR) );
|
||||
@@ -5898,7 +5923,41 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
goto cleanup;
|
||||
nt_dest_len *= sizeof(WCHAR);
|
||||
|
||||
- prefix_len = strlen("\\??\\");
|
||||
+ /* remove the relative path from the NT path */
|
||||
+ if (flags == SYMLINK_FLAG_RELATIVE)
|
||||
+ {
|
||||
+ UNICODE_STRING nt_path;
|
||||
+ SIZE_T nt_path_len = PATH_MAX;
|
||||
+ int relative_offset;
|
||||
+ WCHAR *nt_path;
|
||||
+
|
||||
+ unix_dest.Length = path_len;
|
||||
+ if ((status = unix_to_nt_file_name( &unix_dest, &nt_path )))
|
||||
+ goto cleanup;
|
||||
+ relative_offset = wcslen( nt_path.Buffer );
|
||||
+ if (wcsncmp( nt_path.Buffer, nt_dest.Buffer, relative_offset ) != 0)
|
||||
+ unix_dest_len = path_len;
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ RtlFreeUnicodeString( &nt_path );
|
||||
+ nt_path = malloc( nt_path_len * sizeof(WCHAR) );
|
||||
+ if (!nt_path)
|
||||
+ {
|
||||
+ status = STATUS_NO_MEMORY;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ status = wine_unix_to_nt_file_name( unix_dest, nt_path, &nt_path_len );
|
||||
+ if (status != STATUS_BUFFER_TOO_SMALL) break;
|
||||
+ free( nt_path );
|
||||
+ }
|
||||
+ if (status != STATUS_SUCCESS)
|
||||
+ goto cleanup;
|
||||
+ relative_offset = lstrlenW( nt_path );
|
||||
+ if (wcsnicmp( nt_path, nt_dest, relative_offset ) != 0)
|
||||
+ {
|
||||
+ free( nt_path );
|
||||
+ status = STATUS_IO_REPARSE_DATA_INVALID;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ RtlFreeUnicodeString( &nt_path );
|
||||
+ nt_dest.Length = wcslen( &nt_dest.Buffer[relative_offset] ) * sizeof(WCHAR);
|
||||
+ memmove( nt_dest.Buffer, &nt_dest.Buffer[relative_offset], nt_dest.Length + sizeof(WCHAR) );
|
||||
+ free( nt_path );
|
||||
+ nt_dest_len = lstrlenW( &nt_dest[relative_offset] ) * sizeof(WCHAR);
|
||||
+ memmove( nt_dest, &nt_dest[relative_offset], nt_dest_len + sizeof(WCHAR) );
|
||||
+ }
|
||||
|
||||
- prefix_len = strlen("\\??\\");
|
||||
+
|
||||
+ prefix_len = (flags == SYMLINK_FLAG_RELATIVE) ? 0 : strlen("\\??\\");
|
||||
switch(buffer->ReparseTag)
|
||||
{
|
||||
case IO_REPARSE_TAG_MOUNT_POINT:
|
||||
--
|
||||
2.27.0
|
||||
2.17.1
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 13ccfb68becff81e4a9cd94654ed51facbe96bb9 Mon Sep 17 00:00:00 2001
|
||||
From d98202d50cdb09fe199414b8a313fcf954725e2d 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.
|
||||
Subject: ntdll: Add support for file symlinks.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
@ -10,10 +10,10 @@ Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
2 files changed, 51 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 30ab4110105..ebeb1ec7713 100644
|
||||
index 0db7372a0c8..58fec76bec4 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5190,6 +5190,35 @@ static void test_reparse_points(void)
|
||||
@@ -5191,6 +5191,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 30ab4110105..ebeb1ec7713 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 d19b48d4224..fb1e6bd3c1c 100644
|
||||
index e62a2529bb2..242d344e1f5 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -5624,6 +5624,7 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
@@ -5610,6 +5610,7 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
int relative_offset = 0;
|
||||
UNICODE_STRING nt_dest;
|
||||
int dest_len, offset;
|
||||
@ -61,7 +61,7 @@ index d19b48d4224..fb1e6bd3c1c 100644
|
||||
NTSTATUS status;
|
||||
struct stat st;
|
||||
WCHAR *dest;
|
||||
@@ -5716,7 +5717,8 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
@@ -5745,7 +5746,8 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
status = errno_to_status( errno );
|
||||
goto cleanup;
|
||||
}
|
||||
@ -71,9 +71,9 @@ index d19b48d4224..fb1e6bd3c1c 100644
|
||||
strcat( magic_dest, "." );
|
||||
strcat( magic_dest, "/" );
|
||||
}
|
||||
@@ -5743,8 +5745,11 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
@@ -5772,8 +5774,11 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
/* Atomically move the link into position */
|
||||
if (!renameat2( -1, tmplink, -1, unix_src.Buffer, RENAME_EXCHANGE ))
|
||||
if (!renameat2( -1, tmplink, -1, unix_src, RENAME_EXCHANGE ))
|
||||
{
|
||||
- /* success: link and folder have switched locations */
|
||||
- rmdir( tmplink ); /* remove the folder (at link location) */
|
||||
@ -85,17 +85,17 @@ index d19b48d4224..fb1e6bd3c1c 100644
|
||||
}
|
||||
else if (errno == ENOSYS)
|
||||
{
|
||||
@@ -5953,6 +5958,7 @@ NTSTATUS FILE_RemoveSymlink(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
|
||||
@@ -6011,6 +6016,7 @@ NTSTATUS FILE_RemoveSymlink(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
|
||||
char tmpdir[PATH_MAX], tmpfile[PATH_MAX], *d;
|
||||
BOOL tempdir_created = FALSE;
|
||||
int dest_fd, needs_close;
|
||||
ANSI_STRING unix_name;
|
||||
+ BOOL is_dir = TRUE;
|
||||
NTSTATUS status;
|
||||
char *unix_name;
|
||||
struct stat st;
|
||||
@@ -6023,12 +6029,13 @@ NTSTATUS FILE_RemoveSymlink(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
|
||||
|
||||
@@ -5964,12 +5970,13 @@ NTSTATUS FILE_RemoveSymlink(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
|
||||
|
||||
TRACE("Deleting symlink %s\n", unix_name.Buffer);
|
||||
TRACE( "Deleting symlink %s\n", unix_name );
|
||||
|
||||
- /* Produce the directory in a temporary location in the same folder */
|
||||
+ /* Produce the file/directory in a temporary location in the same folder */
|
||||
@ -105,10 +105,10 @@ index d19b48d4224..fb1e6bd3c1c 100644
|
||||
goto cleanup;
|
||||
}
|
||||
+ is_dir = S_ISDIR(st.st_mode);
|
||||
strcpy( tmpdir, unix_name.Buffer );
|
||||
strcpy( tmpdir, unix_name );
|
||||
d = dirname( tmpdir);
|
||||
if (d != tmpdir) strcpy( tmpdir, d );
|
||||
@@ -5982,11 +5989,21 @@ NTSTATUS FILE_RemoveSymlink(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
|
||||
@@ -6041,11 +6048,21 @@ NTSTATUS FILE_RemoveSymlink(HANDLE handle, REPARSE_GUID_DATA_BUFFER *buffer)
|
||||
tempdir_created = TRUE;
|
||||
strcpy( tmpfile, tmpdir );
|
||||
strcat( tmpfile, "/tmpfile" );
|
||||
@ -132,5 +132,5 @@ index d19b48d4224..fb1e6bd3c1c 100644
|
||||
lchown( tmpfile, st.st_uid, st.st_gid );
|
||||
/* Atomically move the directory into position */
|
||||
--
|
||||
2.27.0
|
||||
2.17.1
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
From c1f3ec8ecefd4488bd8f49da22deb2f4f56d489c Mon Sep 17 00:00:00 2001
|
||||
From 767c81a6bb76f0f852f4ba7260dc0c1b26b45e09 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
|
||||
non-existent paths.
|
||||
Subject: ntdll: Allow creation of dangling reparse points to non-existent
|
||||
paths.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
@ -11,10 +11,10 @@ Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
2 files changed, 15 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index 3cfd633df86..fc79a2fa735 100644
|
||||
index 242d344e1f5..248bda3d3ce 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -3273,6 +3273,19 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
|
||||
@@ -3154,6 +3154,19 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
|
||||
status = STATUS_OBJECT_NAME_COLLISION;
|
||||
}
|
||||
}
|
||||
@ -34,17 +34,17 @@ index 3cfd633df86..fc79a2fa735 100644
|
||||
|
||||
if (status != STATUS_SUCCESS) break;
|
||||
|
||||
@@ -5736,7 +5749,7 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
nt_dest.Length = dest_len;
|
||||
@@ -5707,7 +5720,7 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
status = STATUS_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
- status = wine_nt_to_unix_file_name( &nt_dest, unix_dest, &unix_dest_len, FALSE );
|
||||
+ status = wine_nt_to_unix_file_name( &nt_dest, unix_dest, &unix_dest_len, FILE_WINE_PATH );
|
||||
if (status != STATUS_BUFFER_TOO_SMALL) break;
|
||||
free( unix_dest );
|
||||
}
|
||||
nt_dest_allocated = TRUE;
|
||||
- status = nt_to_unix_file_name( &nt_dest, &unix_dest, 0 );
|
||||
+ status = nt_to_unix_file_name( &nt_dest, &unix_dest, FILE_WINE_PATH );
|
||||
if (status != STATUS_SUCCESS && status != STATUS_NO_SUCH_FILE)
|
||||
goto cleanup;
|
||||
dest_allocated = TRUE;
|
||||
diff --git a/include/winternl.h b/include/winternl.h
|
||||
index 4ee32d3c9e9..3d444e7485e 100644
|
||||
index b3fbb90feff..221c8e39e84 100644
|
||||
--- a/include/winternl.h
|
||||
+++ b/include/winternl.h
|
||||
@@ -1869,6 +1869,7 @@ typedef struct _RTL_HANDLE_TABLE
|
||||
@ -56,5 +56,5 @@ index 4ee32d3c9e9..3d444e7485e 100644
|
||||
/* Characteristics of a File System */
|
||||
#define FILE_REMOVABLE_MEDIA 0x00000001
|
||||
--
|
||||
2.27.0
|
||||
2.17.1
|
||||
|
||||
|
@ -1,62 +1,28 @@
|
||||
From 6ab64d5c26ab8713b2e55911540538a700580017 Mon Sep 17 00:00:00 2001
|
||||
From dcb3180f1f1569626956e51aa35b032271399390 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/tests/file.c | 8 +--
|
||||
dlls/ntdll/unix/file.c | 120 ++++++++++++++++++++++++++--------------
|
||||
2 files changed, 84 insertions(+), 44 deletions(-)
|
||||
dlls/ntdll/unix/file.c | 115 +++++++++++++++++++++++++++--------------
|
||||
1 file changed, 77 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 9530adb2a84..45cffce68ee 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5205,13 +5205,13 @@ static void test_reparse_points(void)
|
||||
|
||||
/* 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");
|
||||
+ ok(!bret, "Succeeded in deleting file symlink as a directory!\n");
|
||||
err = GetLastError();
|
||||
todo_wine ok(err == ERROR_DIRECTORY,
|
||||
"Expected last error 0x%x for RemoveDirectory on file symlink (actually 0x%x)!\n",
|
||||
ERROR_DIRECTORY, err);
|
||||
dwret = GetFileAttributesW(reparse_path);
|
||||
- todo_wine ok(dwret != (DWORD)~0, "Symlink doesn't exist (attributes: 0x%x)!\n", dwret);
|
||||
+ 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: 0x%x)\n", dwret);
|
||||
|
||||
/* Delete the symlink as a file */
|
||||
@@ -5220,10 +5220,10 @@ static void test_reparse_points(void)
|
||||
|
||||
/* Create a blank slate for directory symlink tests */
|
||||
bret = CreateDirectoryW(reparse_path, NULL);
|
||||
- ok(bret, "Failed to create junction point directory.\n");
|
||||
+ todo_wine ok(bret, "Failed to create junction point directory.\n");
|
||||
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);
|
||||
+ todo_wine ok(!(dwret & FILE_ATTRIBUTE_REPARSE_POINT), "File is already a reparse point! (attributes: %d)\n", dwret);
|
||||
|
||||
/* Create the directory symlink */
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index d77a788e0fb..9656f1eb14c 100644
|
||||
index af964cf1334..205adafcd8f 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -1470,6 +1470,9 @@ static inline int get_file_xattr( char *hexattr, int attrlen )
|
||||
@@ -1466,6 +1466,9 @@ static inline int get_file_xattr( char *hexattr, int attrlen )
|
||||
return 0;
|
||||
}
|
||||
|
||||
+NTSTATUS FILE_DecodeSymlink(const char *unix_src, char *unix_dest, USHORT *unix_dest_len,
|
||||
+NTSTATUS FILE_DecodeSymlink(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 )
|
||||
{
|
||||
@@ -1554,10 +1557,15 @@ static int get_file_info( const char *path, struct stat *st, ULONG *attr )
|
||||
@@ -1550,10 +1553,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 ))
|
||||
{
|
||||
@ -74,9 +40,9 @@ index d77a788e0fb..9656f1eb14c 100644
|
||||
+ if (FILE_DecodeSymlink( 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 = RtlAllocateHeap( GetProcessHeap(), 0, strlen(path) + 4 )))
|
||||
else if (S_ISDIR( st->st_mode ) && (parent_path = malloc( strlen(path) + 4 )))
|
||||
{
|
||||
@@ -5851,48 +5859,33 @@ cleanup:
|
||||
@@ -5879,47 +5887,34 @@ cleanup:
|
||||
}
|
||||
|
||||
|
||||
@ -85,20 +51,22 @@ index d77a788e0fb..9656f1eb14c 100644
|
||||
- * 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, USHORT *unix_dest_len,
|
||||
+NTSTATUS FILE_DecodeSymlink(const char *unix_src, char *unix_dest, int *unix_dest_len,
|
||||
+ DWORD *tag, ULONG *flags, BOOL *is_dir)
|
||||
{
|
||||
- ANSI_STRING unix_src, unix_dest;
|
||||
- char *unix_src, unix_dest[PATH_MAX];
|
||||
- VOID *subst_name, *print_name;
|
||||
- SIZE_T nt_dest_len = PATH_MAX;
|
||||
- BOOL dest_allocated = FALSE;
|
||||
- int dest_fd, needs_close;
|
||||
- UNICODE_STRING nt_dest;
|
||||
- int unix_dest_len;
|
||||
- int path_len = 0;
|
||||
- DWORD max_length;
|
||||
+ USHORT len = MAX_PATH;
|
||||
+ int len = MAX_PATH;
|
||||
+ DWORD reparse_tag;
|
||||
NTSTATUS status;
|
||||
- ULONG flags = 0;
|
||||
- WCHAR *nt_dest;
|
||||
- INT prefix_len;
|
||||
+ BOOL dir_flag;
|
||||
+ char *p, *tmp;
|
||||
@ -112,14 +80,11 @@ index d77a788e0fb..9656f1eb14c 100644
|
||||
- if ((status = server_get_unix_name( handle, &unix_src )))
|
||||
- goto cleanup;
|
||||
-
|
||||
- unix_dest.Buffer = RtlAllocateHeap( GetProcessHeap(), 0, PATH_MAX );
|
||||
- unix_dest.MaximumLength = PATH_MAX;
|
||||
- dest_allocated = TRUE;
|
||||
- ret = readlink( unix_src.Buffer, unix_dest.Buffer, unix_dest.MaximumLength );
|
||||
- ret = readlink( unix_src, unix_dest, sizeof(unix_dest) );
|
||||
- if (ret < 0)
|
||||
+ if (unix_dest_len) len = *unix_dest_len;
|
||||
+ if (!unix_dest)
|
||||
+ tmp = RtlAllocateHeap( GetProcessHeap(), 0, len );
|
||||
+ tmp = malloc( len );
|
||||
+ else
|
||||
+ tmp = unix_dest;
|
||||
+ if ((ret = readlink( unix_src, tmp, len )) < 0)
|
||||
@ -127,11 +92,11 @@ index d77a788e0fb..9656f1eb14c 100644
|
||||
status = errno_to_status( errno );
|
||||
goto cleanup;
|
||||
}
|
||||
- unix_dest.Length = ret;
|
||||
-
|
||||
- unix_dest_len = ret;
|
||||
+ len = ret;
|
||||
|
||||
/* Decode the reparse tag from the symlink */
|
||||
- p = unix_dest.Buffer;
|
||||
- p = unix_dest;
|
||||
+ p = tmp;
|
||||
if (*p == '.')
|
||||
{
|
||||
@ -140,7 +105,7 @@ index d77a788e0fb..9656f1eb14c 100644
|
||||
p++;
|
||||
}
|
||||
if (*p++ != '/')
|
||||
@@ -5900,7 +5893,7 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
@@ -5927,7 +5922,7 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
status = STATUS_NOT_IMPLEMENTED;
|
||||
goto cleanup;
|
||||
}
|
||||
@ -149,7 +114,7 @@ index d77a788e0fb..9656f1eb14c 100644
|
||||
for (i = 0; i < sizeof(ULONG)*8; i++)
|
||||
{
|
||||
char c = *p++;
|
||||
@@ -5915,21 +5908,68 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
@@ -5942,21 +5937,65 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
status = STATUS_NOT_IMPLEMENTED;
|
||||
goto cleanup;
|
||||
}
|
||||
@ -173,19 +138,19 @@ index d77a788e0fb..9656f1eb14c 100644
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
- unix_dest.Length -= (p - unix_dest.Buffer);
|
||||
- memmove(unix_dest.Buffer, p, unix_dest.Length);
|
||||
- unix_dest_len -= (p - unix_dest);
|
||||
- memmove(unix_dest, p, unix_dest_len);
|
||||
+ else
|
||||
+ dir_flag = TRUE;
|
||||
+ len -= (p - tmp);
|
||||
+ if (tag) *tag = reparse_tag;
|
||||
+ if (is_dir) *is_dir = dir_flag;
|
||||
+ if (unix_dest) memmove(unix_dest, p, len);
|
||||
+ if (unix_dest) memmove(unix_dest, p, len + 1);
|
||||
+ if (unix_dest_len) *unix_dest_len = len;
|
||||
+ status = STATUS_SUCCESS;
|
||||
+
|
||||
+cleanup:
|
||||
+ if (!unix_dest) RtlFreeHeap( GetProcessHeap(), 0, tmp );
|
||||
+ if (!unix_dest) free( tmp );
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
@ -196,15 +161,17 @@ index d77a788e0fb..9656f1eb14c 100644
|
||||
+ */
|
||||
+NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_size)
|
||||
+{
|
||||
+ ANSI_STRING unix_src, unix_dest;
|
||||
+ 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;
|
||||
+ int dest_fd, needs_close;
|
||||
+ UNICODE_STRING nt_dest;
|
||||
+ int path_len = 0;
|
||||
+ DWORD max_length;
|
||||
+ 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 )))
|
||||
@ -213,12 +180,7 @@ index d77a788e0fb..9656f1eb14c 100644
|
||||
+ if ((status = server_get_unix_name( handle, &unix_src )))
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ unix_dest.MaximumLength = PATH_MAX;
|
||||
+ unix_dest.Buffer = RtlAllocateHeap( GetProcessHeap(), 0, unix_dest.MaximumLength );
|
||||
+ unix_dest.Length = unix_dest.MaximumLength;
|
||||
+ dest_allocated = TRUE;
|
||||
+ if ((status = FILE_DecodeSymlink( unix_src.Buffer, unix_dest.Buffer, &unix_dest.Length,
|
||||
+ &buffer->ReparseTag, &flags, NULL )))
|
||||
+ if ((status = FILE_DecodeSymlink( unix_src, unix_dest, &unix_dest_len, &buffer->ReparseTag, &flags, NULL )))
|
||||
+ goto cleanup;
|
||||
|
||||
/* convert the relative path into an absolute path */
|
||||
|
@ -0,0 +1,31 @@
|
||||
From 3a96350814cd7fd9d620352e252b02aede20d1cf Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Sat, 30 Mar 2019 12:01:50 -0600
|
||||
Subject: kernel32: Set error code when attempting to delete file symlinks as
|
||||
directories.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 58fec76bec4..7f69a9116f2 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5208,9 +5208,9 @@ static void test_reparse_points(void)
|
||||
bret = RemoveDirectoryW(reparse_path);
|
||||
todo_wine ok(!bret, "Succeeded in deleting file symlink as a directory!\n");
|
||||
err = GetLastError();
|
||||
- todo_wine ok(err == ERROR_DIRECTORY,
|
||||
- "Expected last error 0x%x for RemoveDirectory on file symlink (actually 0x%x)!\n",
|
||||
- ERROR_DIRECTORY, err);
|
||||
+ ok(err == ERROR_DIRECTORY,
|
||||
+ "Expected last error 0x%x for RemoveDirectory on file symlink (actually 0x%x)!\n",
|
||||
+ ERROR_DIRECTORY, err);
|
||||
dwret = GetFileAttributesW(reparse_path);
|
||||
todo_wine 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: 0x%x)\n", dwret);
|
||||
--
|
||||
2.17.1
|
||||
|
@ -1,19 +1,32 @@
|
||||
From 9ac3c75b53eeeee76fcf4e1c1a5546ae5fc3b58a Mon Sep 17 00:00:00 2001
|
||||
From a936bfbd369e1199723b0e5f2fa1329c084561db 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.
|
||||
Subject: server: Properly handle file symlink deletion.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 6 ++--
|
||||
server/fd.c | 76 ++++++++++++++++++++++++++++++++++++++---
|
||||
2 files changed, 74 insertions(+), 8 deletions(-)
|
||||
server/fd.c | 69 +++++++++++++++++++++++++++++++++++++++--
|
||||
2 files changed, 70 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 0b7e9e230227..a6085d8de75c 100644
|
||||
index 7f69a9116f2..ddd3d693659 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5198,14 +5198,14 @@ static void test_reparse_points(void)
|
||||
@@ -5206,18 +5206,18 @@ static void test_reparse_points(void)
|
||||
|
||||
/* 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");
|
||||
+ ok(!bret, "Succeeded in deleting file symlink as a directory!\n");
|
||||
err = GetLastError();
|
||||
ok(err == ERROR_DIRECTORY,
|
||||
"Expected last error 0x%x for RemoveDirectory on file symlink (actually 0x%x)!\n",
|
||||
ERROR_DIRECTORY, err);
|
||||
dwret = GetFileAttributesW(reparse_path);
|
||||
- todo_wine ok(dwret != (DWORD)~0, "Symlink doesn't exist (attributes: 0x%x)!\n", dwret);
|
||||
+ 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: 0x%x)\n", dwret);
|
||||
|
||||
/* Delete the symlink as a file */
|
||||
bret = DeleteFileW(reparse_path);
|
||||
@ -22,20 +35,11 @@ index 0b7e9e230227..a6085d8de75c 100644
|
||||
|
||||
/* Create a blank slate for directory symlink tests */
|
||||
bret = CreateDirectoryW(reparse_path, NULL);
|
||||
- todo_wine ok(bret, "Failed to create junction point directory.\n");
|
||||
+ ok(bret, "Failed to create junction point directory.\n");
|
||||
dwret = GetFileAttributesW(reparse_path);
|
||||
ok(dwret != (DWORD)~0, "Path doesn't exist (attributes: 0x%x)!\n", dwret);
|
||||
- todo_wine ok(!(dwret & FILE_ATTRIBUTE_REPARSE_POINT), "File is already a reparse point! (attributes: %d)\n", dwret);
|
||||
+ ok(!(dwret & FILE_ATTRIBUTE_REPARSE_POINT), "File is already a reparse point! (attributes: %d)\n", dwret);
|
||||
|
||||
/* Create the directory symlink */
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
diff --git a/server/fd.c b/server/fd.c
|
||||
index 06d1d81bdb08..df0caa483827 100644
|
||||
index c0d35e2fa4c..9e087917c0d 100644
|
||||
--- a/server/fd.c
|
||||
+++ b/server/fd.c
|
||||
@@ -106,6 +106,10 @@
|
||||
@@ -107,6 +107,10 @@
|
||||
#include "winioctl.h"
|
||||
#include "ddk/wdm.h"
|
||||
|
||||
@ -46,16 +50,7 @@ index 06d1d81bdb08..df0caa483827 100644
|
||||
#if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_EPOLL_CREATE)
|
||||
# include <sys/epoll.h>
|
||||
# define USE_EPOLL
|
||||
@@ -1146,7 +1150,7 @@ static void inode_destroy( struct object *obj )
|
||||
{
|
||||
/* make sure it is still the same file */
|
||||
struct stat st;
|
||||
- if (!stat( fd->unix_name, &st ) && st.st_dev == inode->device->dev && st.st_ino == inode->ino)
|
||||
+ if (!lstat( fd->unix_name, &st ) && st.st_dev == inode->device->dev && st.st_ino == inode->ino)
|
||||
{
|
||||
if (S_ISDIR(st.st_mode)) rmdir( fd->unix_name );
|
||||
else unlink( fd->unix_name );
|
||||
@@ -1824,6 +1828,53 @@ char *dup_fd_name( struct fd *root, const char *name )
|
||||
@@ -1829,6 +1833,55 @@ char *dup_fd_name( struct fd *root, const char *name )
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -66,6 +61,8 @@ index 06d1d81bdb08..df0caa483827 100644
|
||||
+ int len, i;
|
||||
+
|
||||
+ len = readlink( name, link, sizeof(link) );
|
||||
+ if (len == -1)
|
||||
+ return;
|
||||
+ link[len] = 0;
|
||||
+ p = link;
|
||||
+ /* skip past relative/absolute indication */
|
||||
@ -109,7 +106,7 @@ index 06d1d81bdb08..df0caa483827 100644
|
||||
/* open() wrapper that returns a struct fd with no fd user set */
|
||||
struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode, unsigned int access,
|
||||
unsigned int sharing, unsigned int options )
|
||||
@@ -1891,6 +1942,13 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
@@ -1896,6 +1949,13 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
if ((access & FILE_UNIX_WRITE_ACCESS) || (flags & O_CREAT))
|
||||
fd->unix_fd = open( name, O_RDONLY | (flags & ~(O_TRUNC | O_CREAT | O_EXCL)), *mode );
|
||||
}
|
||||
@ -123,17 +120,7 @@ index 06d1d81bdb08..df0caa483827 100644
|
||||
|
||||
if (fd->unix_fd == -1)
|
||||
{
|
||||
@@ -1909,14 +1967,15 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
closed_fd->unix_fd = fd->unix_fd;
|
||||
closed_fd->unlink = 0;
|
||||
closed_fd->unix_name = fd->unix_name;
|
||||
- fstat( fd->unix_fd, &st );
|
||||
+ lstat( fd->unix_name, &st );
|
||||
*mode = st.st_mode;
|
||||
|
||||
/* only bother with an inode for normal files and directories */
|
||||
- if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
|
||||
+ if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))
|
||||
@@ -1923,6 +1983,7 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
{
|
||||
unsigned int err;
|
||||
struct inode *inode = get_inode( st.st_dev, st.st_ino, fd->unix_fd );
|
||||
@ -141,17 +128,17 @@ index 06d1d81bdb08..df0caa483827 100644
|
||||
|
||||
if (!inode)
|
||||
{
|
||||
@@ -1931,13 +1990,20 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
@@ -1937,16 +1998,20 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
list_add_head( &inode->open, &fd->inode_entry );
|
||||
closed_fd = NULL;
|
||||
|
||||
+ /* decode symlink type */
|
||||
+ fstat( fd->unix_fd, &st );
|
||||
+ *mode = st.st_mode;
|
||||
fstat( fd->unix_fd, &st );
|
||||
*mode = st.st_mode;
|
||||
+ is_dir = S_ISDIR(st.st_mode);
|
||||
+ if (is_link)
|
||||
+ decode_symlink(fd->unix_name, &is_dir);
|
||||
+
|
||||
+ decode_symlink(fd->unlink_name, &is_dir);
|
||||
|
||||
/* check directory options */
|
||||
- if ((options & FILE_DIRECTORY_FILE) && !S_ISDIR(st.st_mode))
|
||||
+ if ((options & FILE_DIRECTORY_FILE) && !is_dir)
|
||||
@ -165,5 +152,5 @@ index 06d1d81bdb08..df0caa483827 100644
|
||||
set_error( STATUS_FILE_IS_A_DIRECTORY );
|
||||
goto error;
|
||||
--
|
||||
2.26.2
|
||||
2.17.1
|
||||
|
||||
|
@ -1,19 +1,20 @@
|
||||
From 3c058e77263895ea58b25f652b82d443bcde9dcc Mon Sep 17 00:00:00 2001
|
||||
From ceb069628acc263e5c1a9ed274f8d00eeb9c4dd8 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.
|
||||
Subject: 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/unix/file.c | 2 ++
|
||||
2 files changed, 46 insertions(+), 2 deletions(-)
|
||||
server/fd.c | 3 ++-
|
||||
3 files changed, 48 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index cd2b294bceb..67d54c81fb0 100644
|
||||
index ddd3d693659..e0a6e3b3143 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -5036,7 +5036,9 @@ static void test_reparse_points(void)
|
||||
@@ -5037,7 +5037,9 @@ static void test_reparse_points(void)
|
||||
static const WCHAR dotW[] = {'.',0};
|
||||
REPARSE_DATA_BUFFER *buffer = NULL;
|
||||
DWORD dwret, dwLen, dwFlags, err;
|
||||
@ -23,7 +24,7 @@ index cd2b294bceb..67d54c81fb0 100644
|
||||
HANDLE handle, token;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
UNICODE_STRING nameW;
|
||||
@@ -5164,8 +5166,6 @@ static void test_reparse_points(void)
|
||||
@@ -5165,8 +5167,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 +33,7 @@ index cd2b294bceb..67d54c81fb0 100644
|
||||
|
||||
/* Establish permissions for symlink creation */
|
||||
bret = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token);
|
||||
@@ -5190,6 +5190,13 @@ static void test_reparse_points(void)
|
||||
@@ -5191,6 +5191,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 +47,7 @@ index cd2b294bceb..67d54c81fb0 100644
|
||||
|
||||
/* Create the file symlink */
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
@@ -5203,6 +5210,37 @@ static void test_reparse_points(void)
|
||||
@@ -5204,6 +5211,37 @@ static void test_reparse_points(void)
|
||||
ok(bret, "Failed to create symlink! (0x%x)\n", GetLastError());
|
||||
CloseHandle(handle);
|
||||
|
||||
@ -84,7 +85,7 @@ index cd2b294bceb..67d54c81fb0 100644
|
||||
/* 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");
|
||||
@@ -5224,6 +5262,10 @@ static void test_reparse_points(void)
|
||||
@@ -5225,6 +5263,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 +97,10 @@ index cd2b294bceb..67d54c81fb0 100644
|
||||
/* Create the directory symlink */
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index 7b32bac7fa3..ac4e09fc732 100644
|
||||
index ca21a799231..bdc8b8c756f 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -1511,6 +1511,8 @@ static int get_file_info( const char *path, struct stat *st, ULONG *attr )
|
||||
@@ -1507,6 +1507,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 );
|
||||
@ -108,6 +109,27 @@ index 7b32bac7fa3..ac4e09fc732 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 */
|
||||
diff --git a/server/fd.c b/server/fd.c
|
||||
index 9e087917c0d..03966cd3067 100644
|
||||
--- a/server/fd.c
|
||||
+++ b/server/fd.c
|
||||
@@ -1969,6 +1969,7 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
{
|
||||
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;
|
||||
@@ -2487,7 +2488,7 @@ static void set_fd_disposition( struct fd *fd, int unlink )
|
||||
file_set_error();
|
||||
return;
|
||||
}
|
||||
- if (S_ISREG( st.st_mode )) /* can't unlink files we don't have permission to write */
|
||||
+ if (S_ISREG( st.st_mode ) || S_ISLNK( st.st_mode )) /* can't unlink files we don't have permission to write */
|
||||
{
|
||||
if (!(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
|
||||
{
|
||||
--
|
||||
2.27.0
|
||||
2.17.1
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
From e17d27788c8368ac1d395c6e142c42249f1e02f4 Mon Sep 17 00:00:00 2001
|
||||
From bc78873be1ca0e16e7c2d5aedf15f9e09f86069c 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.
|
||||
Subject: ntdll: Find dangling symlinks quickly.
|
||||
|
||||
This is also necessary on systems (such as MacOS) that support
|
||||
case-insensitive lookups of files.
|
||||
@ -12,10 +12,10 @@ Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index a2fc2a6425b..66ce2eb5fe4 100644
|
||||
index bdc8b8c756f..a7dc12f0a3e 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -2146,7 +2146,7 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i
|
||||
@@ -2501,7 +2501,7 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i
|
||||
if (ret >= 0 && ret <= MAX_DIR_ENTRY_LEN)
|
||||
{
|
||||
unix_name[pos + ret] = 0;
|
||||
@ -24,7 +24,7 @@ index a2fc2a6425b..66ce2eb5fe4 100644
|
||||
{
|
||||
if (is_win_dir) *is_win_dir = is_same_file( &windir, &st );
|
||||
return STATUS_SUCCESS;
|
||||
@@ -2257,7 +2257,7 @@ not_found:
|
||||
@@ -2606,7 +2606,7 @@ not_found:
|
||||
return STATUS_OBJECT_PATH_NOT_FOUND;
|
||||
|
||||
success:
|
||||
@ -33,7 +33,7 @@ index a2fc2a6425b..66ce2eb5fe4 100644
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -2662,7 +2662,7 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
|
||||
@@ -3101,7 +3101,7 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer
|
||||
for (p = unix_name + pos ; *p; p++) if (*p == '\\') *p = '/';
|
||||
if (!name_len || !redirect || (!strstr( unix_name, "/windows/") && strncmp( unix_name, "windows/", 8 )))
|
||||
{
|
||||
@ -43,5 +43,5 @@ index a2fc2a6425b..66ce2eb5fe4 100644
|
||||
if (disposition == FILE_CREATE)
|
||||
return STATUS_OBJECT_NAME_COLLISION;
|
||||
--
|
||||
2.27.0
|
||||
2.17.1
|
||||
|
||||
|
@ -1,51 +1,19 @@
|
||||
From cab7c1b99de7c594083c6fd16b728a79f16b9ac8 Mon Sep 17 00:00:00 2001
|
||||
From f0eee9d4ed2009f24799a149a70e0848dda9fe14 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
|
||||
reparse points.
|
||||
Subject: kernel32: Implement CreateSymbolicLink[A|W] with ntdll reparse
|
||||
points.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/kernel32/path.c | 20 ++++++-
|
||||
dlls/kernel32/tests/path.c | 96 ++++++++++++++++++++++++++++++
|
||||
dlls/kernelbase/file.c | 105 ++++++++++++++++++++++++++++++++-
|
||||
dlls/msvcp120/tests/msvcp120.c | 75 +++++++++++------------
|
||||
dlls/kernel32/tests/path.c | 94 ++++++++++++++++++++++++++++++
|
||||
dlls/kernelbase/file.c | 103 ++++++++++++++++++++++++++++++++-
|
||||
dlls/msvcp120/tests/msvcp120.c | 75 +++++++++++-------------
|
||||
dlls/msvcp140/tests/msvcp140.c | 63 +++++++++-----------
|
||||
5 files changed, 277 insertions(+), 82 deletions(-)
|
||||
4 files changed, 256 insertions(+), 79 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c
|
||||
index 0f075d0af1c..3d17b53a829 100644
|
||||
--- a/dlls/kernel32/path.c
|
||||
+++ b/dlls/kernel32/path.c
|
||||
@@ -385,8 +385,24 @@ WCHAR * CDECL wine_get_dos_file_name( LPCSTR str )
|
||||
*/
|
||||
BOOLEAN WINAPI CreateSymbolicLinkA(LPCSTR link, LPCSTR target, DWORD flags)
|
||||
{
|
||||
- FIXME("(%s %s %d): stub\n", debugstr_a(link), debugstr_a(target), flags);
|
||||
- return TRUE;
|
||||
+ WCHAR *targetW, *linkW;
|
||||
+ BOOL ret;
|
||||
+
|
||||
+ TRACE("(%s %s %d)\n", debugstr_a(link), debugstr_a(target), flags);
|
||||
+
|
||||
+ if (!(linkW = FILE_name_AtoW( link, TRUE )))
|
||||
+ {
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ if (!(targetW = FILE_name_AtoW( target, TRUE )))
|
||||
+ {
|
||||
+ HeapFree( GetProcessHeap(), 0, linkW );
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ ret = CreateSymbolicLinkW( linkW, targetW, flags );
|
||||
+ HeapFree( GetProcessHeap(), 0, linkW );
|
||||
+ HeapFree( GetProcessHeap(), 0, targetW );
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
diff --git a/dlls/kernel32/tests/path.c b/dlls/kernel32/tests/path.c
|
||||
index 0e45ad44ff3..841353dcab8 100644
|
||||
index 0e45ad44ff3..0f8d94e2957 100644
|
||||
--- a/dlls/kernel32/tests/path.c
|
||||
+++ b/dlls/kernel32/tests/path.c
|
||||
@@ -83,6 +83,9 @@ static NTSTATUS (WINAPI *pLdrGetDllPath)(LPCWSTR,ULONG,LPWSTR*,LPWSTR*);
|
||||
@ -58,22 +26,15 @@ index 0e45ad44ff3..841353dcab8 100644
|
||||
/* a structure to deal with wine todos somewhat cleanly */
|
||||
typedef struct {
|
||||
DWORD shortlen;
|
||||
@@ -2147,11 +2150,14 @@ static void init_pointers(void)
|
||||
@@ -2147,6 +2150,7 @@ static void init_pointers(void)
|
||||
MAKEFUNC(SetDefaultDllDirectories);
|
||||
MAKEFUNC(CheckNameLegalDOS8Dot3W);
|
||||
MAKEFUNC(CheckNameLegalDOS8Dot3A);
|
||||
+ MAKEFUNC(CreateSymbolicLinkW);
|
||||
+
|
||||
mod = GetModuleHandleA("ntdll.dll");
|
||||
MAKEFUNC(LdrGetDllPath);
|
||||
MAKEFUNC(RtlGetExePath);
|
||||
MAKEFUNC(RtlGetSearchPath);
|
||||
MAKEFUNC(RtlReleasePath);
|
||||
+
|
||||
#undef MAKEFUNC
|
||||
}
|
||||
|
||||
@@ -2690,6 +2696,95 @@ static void test_LdrGetDllPath(void)
|
||||
@@ -2690,6 +2694,95 @@ static void test_LdrGetDllPath(void)
|
||||
SetEnvironmentVariableW( pathW, old_path );
|
||||
}
|
||||
|
||||
@ -104,7 +65,7 @@ index 0e45ad44ff3..841353dcab8 100644
|
||||
+ DeleteFileW( path );
|
||||
+ if (!CreateDirectoryW( path, NULL ))
|
||||
+ {
|
||||
+ win_skip("Unable to create a temporary junction point directory.\n");
|
||||
+ win_skip("Unable to create a temporary reparse point directory.\n");
|
||||
+ return;
|
||||
+ }
|
||||
+ GetCurrentDirectoryW( sizeof(old_path)/sizeof(WCHAR), old_path );
|
||||
@ -116,7 +77,7 @@ index 0e45ad44ff3..841353dcab8 100644
|
||||
+ GetVolumeInformationW( volW, 0, 0, 0, &dwLen, &dwFlags, 0, 0 );
|
||||
+ if (!(dwFlags & FILE_SUPPORTS_REPARSE_POINTS))
|
||||
+ {
|
||||
+ skip("File system does not support junction points.\n");
|
||||
+ skip("File system does not support reparse points.\n");
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
@ -169,30 +130,27 @@ index 0e45ad44ff3..841353dcab8 100644
|
||||
START_TEST(path)
|
||||
{
|
||||
CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
|
||||
@@ -2719,4 +2814,5 @@ START_TEST(path)
|
||||
@@ -2719,4 +2812,5 @@ START_TEST(path)
|
||||
test_RtlGetSearchPath();
|
||||
test_RtlGetExePath();
|
||||
test_LdrGetDllPath();
|
||||
+ test_CreateSymbolicLink();
|
||||
}
|
||||
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c
|
||||
index 905029066e4..ed6ba6ae30e 100644
|
||||
index d9b34408692..2e67f6eaa3e 100644
|
||||
--- a/dlls/kernelbase/file.c
|
||||
+++ b/dlls/kernelbase/file.c
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "wincon.h"
|
||||
#include "fileapi.h"
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "shlwapi.h"
|
||||
+#include "ntifs.h"
|
||||
#include "ddk/ntddk.h"
|
||||
#include "ddk/ntddser.h"
|
||||
+#include "ntifs.h"
|
||||
|
||||
@@ -943,10 +944,108 @@ done:
|
||||
/*************************************************************************
|
||||
* CreateSymbolicLinkW (kernelbase.@)
|
||||
#include "kernelbase.h"
|
||||
#include "wine/exception.h"
|
||||
@@ -926,8 +927,106 @@ done:
|
||||
*/
|
||||
-BOOLEAN WINAPI /* DECLSPEC_HOTPATCH */ CreateSymbolicLinkW( LPCWSTR link, LPCWSTR target, DWORD flags )
|
||||
+BOOLEAN WINAPI DECLSPEC_HOTPATCH CreateSymbolicLinkW( const WCHAR *link, const WCHAR *target, DWORD flags )
|
||||
BOOLEAN WINAPI /* DECLSPEC_HOTPATCH */ CreateSymbolicLinkW( LPCWSTR link, LPCWSTR target, DWORD flags )
|
||||
{
|
||||
- FIXME( "(%s %s %d): stub\n", debugstr_w(link), debugstr_w(target), flags );
|
||||
- return TRUE;
|
||||
@ -210,7 +168,7 @@ index 905029066e4..ed6ba6ae30e 100644
|
||||
+ HANDLE hlink;
|
||||
+ DWORD dwret;
|
||||
+
|
||||
+ TRACE("(%s %s %d)\n", debugstr_w(link), debugstr_w(target), flags);
|
||||
+ TRACE( "(%s %s %d): stub\n", debugstr_w(link), debugstr_w(target), flags );
|
||||
+
|
||||
+ is_relative = (RtlDetermineDosPathNameType_U( target ) == RELATIVE_PATH);
|
||||
+ is_dir = (flags & SYMBOLIC_LINK_FLAG_DIRECTORY);
|
||||
@ -244,11 +202,11 @@ index 905029066e4..ed6ba6ae30e 100644
|
||||
+ }
|
||||
+ /* append the target to the link path */
|
||||
+ target_path_len = nt_path.Length / sizeof(WCHAR);
|
||||
+ len = target_path_len + (wcslen( target ) + 1);
|
||||
+ len = target_path_len + (lstrlenW( target ) + 1);
|
||||
+ target_path = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len*sizeof(WCHAR) );
|
||||
+ lstrcpynW( target_path, nt_path.Buffer, target_path_len+1 );
|
||||
+ target_path[target_path_len+1] = 0;
|
||||
+ wcscat( target_path, target );
|
||||
+ lstrcatW( target_path, target );
|
||||
+ RtlFreeUnicodeString( &nt_path );
|
||||
+ }
|
||||
+ else
|
||||
@ -259,14 +217,14 @@ index 905029066e4..ed6ba6ae30e 100644
|
||||
+ SetLastError( RtlNtStatusToDosError(status) );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ if (is_relative && wcsncmp( target_path, nt_name.Buffer, target_path_len ))
|
||||
+ if (is_relative && _wcsnicmp( target_path, nt_name.Buffer, target_path_len ) != 0)
|
||||
+ {
|
||||
+ SetLastError( RtlNtStatusToDosError(status) );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ prefix_len = is_relative ? 0 : strlen("\\??\\");
|
||||
+ string = &nt_name.Buffer[target_path_len];
|
||||
+ string_len = wcslen( &string[prefix_len] );
|
||||
+ string_len = lstrlenW( &string[prefix_len] );
|
||||
+ data_size = (prefix_len + 2 * string_len + 2) * sizeof(WCHAR);
|
||||
+ buffer_size = struct_size + data_size;
|
||||
+ buffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_size );
|
||||
@ -278,10 +236,10 @@ index 905029066e4..ed6ba6ae30e 100644
|
||||
+ buffer->SymbolicLinkReparseBuffer.Flags = is_relative ? SYMLINK_FLAG_RELATIVE : 0;
|
||||
+ subst_dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[0];
|
||||
+ print_dest = &buffer->SymbolicLinkReparseBuffer.PathBuffer[prefix_len + string_len + 1];
|
||||
+ wcscpy( subst_dest, string );
|
||||
+ wcscpy( print_dest, &string[prefix_len] );
|
||||
+ lstrcpyW( subst_dest, string );
|
||||
+ lstrcpyW( print_dest, &string[prefix_len] );
|
||||
+ RtlFreeUnicodeString( &nt_name );
|
||||
+ bret = DeviceIoControl( hlink, FSCTL_SET_REPARSE_POINT, buffer, buffer_size, NULL, 0,
|
||||
+ bret = DeviceIoControl( hlink, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_size, NULL, 0,
|
||||
+ &dwret, 0 );
|
||||
+ HeapFree( GetProcessHeap(), 0, buffer );
|
||||
+
|
||||
@ -300,7 +258,7 @@ index 905029066e4..ed6ba6ae30e 100644
|
||||
|
||||
|
||||
diff --git a/dlls/msvcp120/tests/msvcp120.c b/dlls/msvcp120/tests/msvcp120.c
|
||||
index 7a382ac6faa..9775ef5e1d8 100644
|
||||
index ed632a27df2..bd2e8550d05 100644
|
||||
--- a/dlls/msvcp120/tests/msvcp120.c
|
||||
+++ b/dlls/msvcp120/tests/msvcp120.c
|
||||
@@ -1615,15 +1615,14 @@ static void test_tr2_sys__Stat(void)
|
||||
@ -552,5 +510,5 @@ index 751b1beed86..382f5732c29 100644
|
||||
}
|
||||
|
||||
--
|
||||
2.26.2
|
||||
2.17.1
|
||||
|
||||
|
@ -0,0 +1,45 @@
|
||||
From 87cc49c8ae73e17bc953b66f25be76d5c0eff153 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: kernel32: Add reparse support to FindNextFile.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/kernelbase/file.c | 21 +++++++++++++++++++++
|
||||
1 file changed, 21 insertions(+)
|
||||
|
||||
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c
|
||||
index 2e67f6eaa3e..9920b50191b 100644
|
||||
--- a/dlls/kernelbase/file.c
|
||||
+++ b/dlls/kernelbase/file.c
|
||||
@@ -1485,6 +1485,27 @@ 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;
|
||||
+
|
||||
+ hlink = CreateFileW( data->cFileName, GENERIC_READ | GENERIC_WRITE, 0, 0,
|
||||
+ OPEN_EXISTING,
|
||||
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0 );
|
||||
+ buffer_len = sizeof(*buffer) + 2*MAX_PATH*sizeof(WCHAR);
|
||||
+ buffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_len );
|
||||
+ 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 );
|
||||
+ CloseHandle( hlink );
|
||||
+ }
|
||||
+
|
||||
if (info->level != FindExInfoBasic)
|
||||
{
|
||||
memcpy( data->cAlternateFileName, dir_info->ShortName, dir_info->ShortNameLength );
|
||||
--
|
||||
2.17.1
|
||||
|
@ -0,0 +1,50 @@
|
||||
From 6eed7c952dbb0e7151723881dc26e955b9d9595d 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: wcmd: Display reparse point type in directory listings.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
programs/cmd/directory.c | 26 ++++++++++++++++++++++++++
|
||||
1 file changed, 26 insertions(+)
|
||||
|
||||
diff --git a/programs/cmd/directory.c b/programs/cmd/directory.c
|
||||
index 2d35f8eb1d1..5b7416ce72a 100644
|
||||
--- a/programs/cmd/directory.c
|
||||
+++ b/programs/cmd/directory.c
|
||||
@@ -400,6 +400,32 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
|
||||
WCMD_output(L"%1!*s!", cur_width - tmp_width, nullW);
|
||||
}
|
||||
|
||||
+ } else if (fd[i].dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
|
||||
+ if (!bare) {
|
||||
+ const WCHAR *type;
|
||||
+
|
||||
+ switch(fd[i].dwReserved0) {
|
||||
+ case IO_REPARSE_TAG_MOUNT_POINT:
|
||||
+ type = L"<JUNCTION>";
|
||||
+ break;
|
||||
+ case IO_REPARSE_TAG_SYMLINK:
|
||||
+ default:
|
||||
+ type = (fd[i].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? L"<SYMLINKD>" : L"<SYMLINK>";
|
||||
+ break;
|
||||
+ }
|
||||
+ WCMD_output (L"%1!10s! %2!8s! %3!-14s!", datestring, timestring, type);
|
||||
+ if (shortname) WCMD_output (fmt2, fd[i].cAlternateFileName);
|
||||
+ if (usernames) WCMD_output (fmt3, username);
|
||||
+ WCMD_output(fmt4,fd[i].cFileName);
|
||||
+ } else {
|
||||
+ if (!((lstrcmpW(fd[i].cFileName, dotW) == 0) ||
|
||||
+ (lstrcmpW(fd[i].cFileName, dotdotW) == 0))) {
|
||||
+ WCMD_output (fmt5, recurse?inputparms->dirName:nullW, fd[i].cFileName);
|
||||
+ } else {
|
||||
+ addNewLine = FALSE;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
} else if (fd[i].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
dir_count++;
|
||||
|
||||
--
|
||||
2.17.1
|
||||
|
@ -0,0 +1,72 @@
|
||||
From 508f77e1653e67bfa8ed54eeb25251684b495115 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: wcmd: Show reparse point target in directory listing.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
programs/cmd/directory.c | 34 ++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 34 insertions(+)
|
||||
|
||||
diff --git a/programs/cmd/directory.c b/programs/cmd/directory.c
|
||||
index 5b7416ce72a..87a5a310224 100644
|
||||
--- a/programs/cmd/directory.c
|
||||
+++ b/programs/cmd/directory.c
|
||||
@@ -23,6 +23,8 @@
|
||||
|
||||
#include "wcmd.h"
|
||||
#include "wine/debug.h"
|
||||
+#include "winioctl.h"
|
||||
+#include "ntifs.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(cmd);
|
||||
|
||||
@@ -256,6 +258,7 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
|
||||
static const WCHAR fmt3[] = {'%','1','!','-','2','3','s','!','\0'};
|
||||
static const WCHAR fmt4[] = {'%','1','\0'};
|
||||
static const WCHAR fmt5[] = {'%','1','%','2','\0'};
|
||||
+ static const WCHAR fmt6[] = {' ','[','%','1',']','\0'};
|
||||
|
||||
dir_count = 0;
|
||||
file_count = 0;
|
||||
@@ -417,6 +420,37 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le
|
||||
if (shortname) WCMD_output (fmt2, fd[i].cAlternateFileName);
|
||||
if (usernames) WCMD_output (fmt3, username);
|
||||
WCMD_output(fmt4,fd[i].cFileName);
|
||||
+ if (fd[i].dwReserved0) {
|
||||
+ REPARSE_DATA_BUFFER *buffer = NULL;
|
||||
+ WCHAR *target = NULL;
|
||||
+ INT buffer_len;
|
||||
+ HANDLE hlink;
|
||||
+ DWORD dwret;
|
||||
+ BOOL bret;
|
||||
+
|
||||
+ hlink = CreateFileW(fd[i].cFileName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
|
||||
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
+ buffer_len = sizeof(*buffer) + 2*MAX_PATH*sizeof(WCHAR);
|
||||
+ buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_len);
|
||||
+ bret = DeviceIoControl(hlink, FSCTL_GET_REPARSE_POINT, NULL, 0, (LPVOID)buffer,
|
||||
+ buffer_len, &dwret, 0);
|
||||
+ if (bret) {
|
||||
+ INT offset;
|
||||
+ switch(buffer->ReparseTag) {
|
||||
+ case IO_REPARSE_TAG_MOUNT_POINT:
|
||||
+ offset = buffer->MountPointReparseBuffer.PrintNameOffset/sizeof(WCHAR);
|
||||
+ target = &buffer->MountPointReparseBuffer.PathBuffer[offset];
|
||||
+ break;
|
||||
+ case IO_REPARSE_TAG_SYMLINK:
|
||||
+ offset = buffer->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR);
|
||||
+ target = &buffer->SymbolicLinkReparseBuffer.PathBuffer[offset];
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ CloseHandle(hlink);
|
||||
+ if (target) WCMD_output(fmt6, target);
|
||||
+ HeapFree(GetProcessHeap(), 0, buffer);
|
||||
+ }
|
||||
} else {
|
||||
if (!((lstrcmpW(fd[i].cFileName, dotW) == 0) ||
|
||||
(lstrcmpW(fd[i].cFileName, dotdotW) == 0))) {
|
||||
--
|
||||
2.17.1
|
||||
|
@ -0,0 +1,86 @@
|
||||
From c146d5ab24640039bd143ebe501755701c126a9e 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: wcmd: Add junction point support to mklink.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
programs/cmd/builtins.c | 48 ++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 47 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
|
||||
index 70ccddebc11..34de0486fdd 100644
|
||||
--- a/programs/cmd/builtins.c
|
||||
+++ b/programs/cmd/builtins.c
|
||||
@@ -31,6 +31,9 @@
|
||||
#include "wcmd.h"
|
||||
#include <shellapi.h>
|
||||
#include "wine/debug.h"
|
||||
+#include "winternl.h"
|
||||
+#include "winioctl.h"
|
||||
+#include "ntifs.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(cmd);
|
||||
|
||||
@@ -5055,6 +5058,49 @@ void WCMD_color (void) {
|
||||
}
|
||||
}
|
||||
|
||||
+BOOL WCMD_create_junction(WCHAR *link, WCHAR *target) {
|
||||
+ static INT struct_size = offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer[0]);
|
||||
+ static INT header_size = offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer);
|
||||
+ INT buffer_size, data_size, string_len, prefix_len;
|
||||
+ WCHAR *subst_dest, *print_dest, *string;
|
||||
+ REPARSE_DATA_BUFFER *buffer;
|
||||
+ UNICODE_STRING nt_name;
|
||||
+ NTSTATUS status;
|
||||
+ HANDLE hlink;
|
||||
+ DWORD dwret;
|
||||
+ BOOL ret;
|
||||
+
|
||||
+ if (!CreateDirectoryW(link, NULL ))
|
||||
+ return FALSE;
|
||||
+ hlink = CreateFileW(link, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
|
||||
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
+ if (hlink == INVALID_HANDLE_VALUE)
|
||||
+ return FALSE;
|
||||
+ status = RtlDosPathNameToNtPathName_U_WithStatus(target, &nt_name, NULL, NULL);
|
||||
+ if (status)
|
||||
+ return FALSE;
|
||||
+ prefix_len = strlen("\\??\\");
|
||||
+ string = nt_name.Buffer;
|
||||
+ string_len = lstrlenW( &string[prefix_len] );
|
||||
+ data_size = (prefix_len + 2 * string_len + 2) * sizeof(WCHAR);
|
||||
+ buffer_size = struct_size + data_size;
|
||||
+ buffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_size );
|
||||
+ buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
|
||||
+ buffer->ReparseDataLength = struct_size - header_size + data_size;
|
||||
+ buffer->MountPointReparseBuffer.SubstituteNameLength = (prefix_len + string_len) * sizeof(WCHAR);
|
||||
+ buffer->MountPointReparseBuffer.PrintNameOffset = (prefix_len + string_len + 1) * sizeof(WCHAR);
|
||||
+ buffer->MountPointReparseBuffer.PrintNameLength = string_len * sizeof(WCHAR);
|
||||
+ subst_dest = &buffer->MountPointReparseBuffer.PathBuffer[0];
|
||||
+ print_dest = &buffer->MountPointReparseBuffer.PathBuffer[prefix_len + string_len + 1];
|
||||
+ lstrcpyW(subst_dest, string);
|
||||
+ lstrcpyW(print_dest, &string[prefix_len]);
|
||||
+ RtlFreeUnicodeString(&nt_name );
|
||||
+ ret = DeviceIoControl(hlink, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_size, NULL, 0,
|
||||
+ &dwret, 0 );
|
||||
+ HeapFree(GetProcessHeap(), 0, buffer);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/****************************************************************************
|
||||
* WCMD_mklink
|
||||
*/
|
||||
@@ -5106,7 +5152,7 @@ void WCMD_mklink(WCHAR *args)
|
||||
else if(!junction)
|
||||
ret = CreateSymbolicLinkW(file1, file2, isdir);
|
||||
else
|
||||
- WINE_TRACE("Juction links currently not supported.\n");
|
||||
+ ret = WCMD_create_junction(file1, file2);
|
||||
|
||||
if(!ret)
|
||||
WCMD_output_stderr(WCMD_LoadMessage(WCMD_READFAIL), file1);
|
||||
--
|
||||
2.17.1
|
||||
|
@ -0,0 +1,140 @@
|
||||
From 7a25fabadf15c7514dec080502df19595249a3f6 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: server: Fix obtaining information about a symlink.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/ntdll/unix/file.c | 19 ++++++++++---------
|
||||
server/fd.c | 7 ++++---
|
||||
server/protocol.def | 1 +
|
||||
3 files changed, 15 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index a7dc12f0a3e..b507d575766 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -1775,7 +1775,7 @@ static NTSTATUS fill_file_info( const struct stat *st, ULONG attr, void *ptr,
|
||||
}
|
||||
|
||||
|
||||
-static NTSTATUS server_get_unix_name( HANDLE handle, char **unix_name )
|
||||
+static NTSTATUS server_get_unix_name( HANDLE handle, char **unix_name, BOOL nofollow )
|
||||
{
|
||||
data_size_t size = 1024;
|
||||
NTSTATUS ret;
|
||||
@@ -1788,6 +1788,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 );
|
||||
+ req->nofollow = nofollow;
|
||||
wine_server_set_reply( req, name, size );
|
||||
ret = wine_server_call( req );
|
||||
size = reply->name_len;
|
||||
@@ -1962,7 +1963,7 @@ static NTSTATUS get_mountmgr_fs_info( HANDLE handle, int fd, struct mountmgr_uni
|
||||
NTSTATUS status;
|
||||
int letter;
|
||||
|
||||
- if ((status = server_get_unix_name( handle, &unix_name ))) return status;
|
||||
+ if ((status = server_get_unix_name( handle, &unix_name, FALSE ))) return status;
|
||||
letter = find_dos_device( unix_name );
|
||||
free( unix_name );
|
||||
|
||||
@@ -3973,7 +3974,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;
|
||||
- else if (!(io->u.Status = server_get_unix_name( handle, &unix_name )))
|
||||
+ else if (!(io->u.Status = server_get_unix_name( handle, &unix_name, FALSE )))
|
||||
{
|
||||
LONG name_len = len - FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName);
|
||||
|
||||
@@ -4034,7 +4035,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
|
||||
FILE_NAME_INFORMATION *info = ptr;
|
||||
char *unix_name;
|
||||
|
||||
- if (!(io->u.Status = server_get_unix_name( handle, &unix_name )))
|
||||
+ if (!(io->u.Status = server_get_unix_name( handle, &unix_name, FALSE )))
|
||||
{
|
||||
LONG name_len = len - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
|
||||
io->u.Status = fill_name_info( unix_name, info, &name_len );
|
||||
@@ -4048,7 +4049,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
|
||||
FILE_NETWORK_OPEN_INFORMATION *info = ptr;
|
||||
char *unix_name;
|
||||
|
||||
- if (!(io->u.Status = server_get_unix_name( handle, &unix_name )))
|
||||
+ if (!(io->u.Status = server_get_unix_name( handle, &unix_name, FALSE )))
|
||||
{
|
||||
ULONG attributes;
|
||||
struct stat st;
|
||||
@@ -5661,7 +5662,7 @@ NTSTATUS FILE_CreateSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
|
||||
if ((status = server_get_unix_fd( handle, FILE_SPECIAL_ACCESS, &dest_fd, &needs_close, NULL, NULL )))
|
||||
return status;
|
||||
|
||||
- if ((status = server_get_unix_name( handle, &unix_src )))
|
||||
+ if ((status = server_get_unix_name( handle, &unix_src, FALSE )))
|
||||
goto cleanup;
|
||||
src_allocated = TRUE;
|
||||
if (flags == SYMLINK_FLAG_RELATIVE)
|
||||
@@ -5940,7 +5941,7 @@ NTSTATUS FILE_GetSymlink(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG out_s
|
||||
if ((status = server_get_unix_fd( handle, FILE_ANY_ACCESS, &dest_fd, &needs_close, NULL, NULL )))
|
||||
return status;
|
||||
|
||||
- if ((status = server_get_unix_name( handle, &unix_src )))
|
||||
+ 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 )))
|
||||
@@ -6078,7 +6079,7 @@ NTSTATUS FILE_RemoveSymlink(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;
|
||||
|
||||
- if ((status = server_get_unix_name( handle, &unix_name )))
|
||||
+ if ((status = server_get_unix_name( handle, &unix_name, TRUE )))
|
||||
goto cleanup;
|
||||
|
||||
TRACE( "Deleting symlink %s\n", unix_name );
|
||||
@@ -7104,7 +7105,7 @@ NTSTATUS WINAPI NtQueryObject( HANDLE handle, OBJECT_INFORMATION_CLASS info_clas
|
||||
|
||||
/* first try as a file object */
|
||||
|
||||
- if (!(status = server_get_unix_name( handle, &unix_name )))
|
||||
+ if (!(status = server_get_unix_name( handle, &unix_name, FALSE )))
|
||||
{
|
||||
if (!(status = unix_to_nt_file_name( unix_name, &nt_name )))
|
||||
{
|
||||
diff --git a/server/fd.c b/server/fd.c
|
||||
index 03966cd3067..100c3865126 100644
|
||||
--- a/server/fd.c
|
||||
+++ b/server/fd.c
|
||||
@@ -2729,11 +2729,12 @@ DECL_HANDLER(get_handle_unix_name)
|
||||
|
||||
if ((fd = get_handle_fd_obj( current->process, req->handle, 0 )))
|
||||
{
|
||||
- if (fd->unix_name)
|
||||
+ char *name = (req->nofollow ? fd->unlink_name : fd->unix_name);
|
||||
+ if (name)
|
||||
{
|
||||
- data_size_t name_len = strlen( fd->unix_name );
|
||||
+ data_size_t name_len = strlen( name );
|
||||
reply->name_len = name_len;
|
||||
- if (name_len <= get_reply_max_size()) set_reply_data( fd->unix_name, name_len );
|
||||
+ if (name_len <= get_reply_max_size()) set_reply_data( name, name_len );
|
||||
else set_error( STATUS_BUFFER_OVERFLOW );
|
||||
}
|
||||
else set_error( STATUS_OBJECT_TYPE_MISMATCH );
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index a121c371c19..faf4891a01e 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -1297,6 +1297,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 */
|
||||
+ int nofollow; /* do not follow symlinks (return the link) */
|
||||
@REPLY
|
||||
data_size_t name_len; /* unix name length */
|
||||
VARARG(name,string); /* unix name */
|
||||
--
|
||||
2.17.1
|
||||
|
@ -1,8 +1,5 @@
|
||||
Fixes: [12401] NET Framework 2.0, 3.0, 4.0 installers and other apps that make use of GAC API for managed assembly installation on NTFS filesystems need reparse point/junction API support (FSCTL_SET_REPARSE_POINT/FSCTL_GET_REPARSE_POINT)
|
||||
Fixes: [44948] Multiple apps (Spine (Mod starter for Gothic), MS Office 365 installer) need CreateSymbolicLinkW implementation
|
||||
# FIXME: patch 0006 was broken by e36a9c459d. We really want to get that information from ntdll instead, but the how is not trivial...
|
||||
# FIXME 2: patch 0019 needs to call RemoveDirectoryW() from kernelbase, but it's stuck in kernel32 for now...
|
||||
# FIXME 3: RemoveDirectory() doesn't work anymore, I think.
|
||||
Depends: ntdll-DOS_Attributes
|
||||
# Someone needs to rewrite all of this string arithmetic.
|
||||
Disabled: true
|
||||
Depends: ntdll-NtQueryEaFile
|
||||
|
@ -1,38 +1,21 @@
|
||||
From 5028b688bbe434ce83811da8251d920c7e2dba8a Mon Sep 17 00:00:00 2001
|
||||
From a796dda4d4b7676ef758245f712ed4891902043c Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Thu, 16 Jan 2014 21:03:47 -0700
|
||||
Subject: kernel32: Advertise junction point support.
|
||||
|
||||
TODO: this patch requires an update that is dependent upon obtaining
|
||||
volume information through mountmgr.
|
||||
|
||||
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
|
||||
---
|
||||
dlls/kernel32/volume.c | 85 +++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 84 insertions(+), 1 deletion(-)
|
||||
dlls/kernelbase/volume.c | 72 +++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 71 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/kernel32/volume.c b/dlls/kernel32/volume.c
|
||||
index 4fd913aa22..437832e5c9 100644
|
||||
--- a/dlls/kernel32/volume.c
|
||||
+++ b/dlls/kernel32/volume.c
|
||||
@@ -44,6 +44,19 @@
|
||||
#include "wine/unicode.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
+#ifdef HAVE_SYS_MOUNT_H
|
||||
+# include <sys/mount.h>
|
||||
+#endif
|
||||
+#ifdef HAVE_SYS_STATFS_H
|
||||
+# include <sys/statfs.h>
|
||||
+#endif
|
||||
+#ifdef HAVE_SYS_SYSCALL_H
|
||||
+# include <sys/syscall.h>
|
||||
+#endif
|
||||
+#ifdef HAVE_SYS_VFS_H
|
||||
+# include <sys/vfs.h>
|
||||
+#endif
|
||||
+
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(volume);
|
||||
|
||||
#define BLOCK_SIZE 2048
|
||||
@@ -680,6 +693,75 @@ static DWORD VOLUME_GetAudioCDSerial( const CDROM_TOC *toc )
|
||||
diff --git a/dlls/kernelbase/volume.c b/dlls/kernelbase/volume.c
|
||||
index 53cc0d49b65..f58909d321d 100644
|
||||
--- a/dlls/kernelbase/volume.c
|
||||
+++ b/dlls/kernelbase/volume.c
|
||||
@@ -646,6 +646,75 @@ static DWORD get_audiocd_serial( const CDROM_TOC *toc )
|
||||
}
|
||||
|
||||
|
||||
@ -106,11 +89,11 @@ index 4fd913aa22..437832e5c9 100644
|
||||
+
|
||||
+
|
||||
/***********************************************************************
|
||||
* GetVolumeInformationW (KERNEL32.@)
|
||||
* GetVolumeInformationW (kernelbase.@)
|
||||
*/
|
||||
@@ -824,7 +906,8 @@ fill_fs_info: /* now fill in the information that depends on the file system ty
|
||||
@@ -781,7 +850,8 @@ fill_fs_info: /* now fill in the information that depends on the file system ty
|
||||
default:
|
||||
if (fsname) lstrcpynW( fsname, ntfsW, fsname_len );
|
||||
if (fsname) lstrcpynW( fsname, L"NTFS", fsname_len );
|
||||
if (filename_len) *filename_len = 255;
|
||||
- if (flags) *flags = FILE_CASE_PRESERVED_NAMES | FILE_PERSISTENT_ACLS;
|
||||
+ if (flags) *flags = FILE_CASE_PRESERVED_NAMES | FILE_PERSISTENT_ACLS
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 2de64a6d61d01b9409ab6b61176c0a88a4838937 Mon Sep 17 00:00:00 2001
|
||||
From 4ad7e0d2a51606b323cbe2f33c64a99c3666a072 Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Sun, 28 May 2017 05:19:30 +0200
|
||||
Subject: [PATCH] ntdll: Implement NtQueryVirtualMemory(MemorySectionName).
|
||||
@ -15,35 +15,35 @@ Contains several improvements by Sebastian Lackner <sebastian@fds-team.de>.
|
||||
6 files changed, 136 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
|
||||
index b404bceb427..dcc76846c1e 100644
|
||||
index a41deb0881d..06ab827836d 100644
|
||||
--- a/dlls/ntdll/unix/file.c
|
||||
+++ b/dlls/ntdll/unix/file.c
|
||||
@@ -1763,7 +1763,7 @@ static NTSTATUS fill_file_info( const struct stat *st, ULONG attr, void *ptr,
|
||||
@@ -1835,7 +1835,7 @@ static NTSTATUS fill_file_info( const struct stat *st, ULONG attr, void *ptr,
|
||||
}
|
||||
|
||||
|
||||
-static NTSTATUS server_get_unix_name( HANDLE handle, char **unix_name )
|
||||
+NTSTATUS server_get_unix_name( HANDLE handle, char **unix_name )
|
||||
-static NTSTATUS server_get_unix_name( HANDLE handle, char **unix_name, BOOL nofollow )
|
||||
+NTSTATUS server_get_unix_name( HANDLE handle, char **unix_name, BOOL nofollow )
|
||||
{
|
||||
data_size_t size = 1024;
|
||||
NTSTATUS ret;
|
||||
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
|
||||
index 3d56ea5d408..f24ca578ce1 100644
|
||||
index 3cf9ca66736..a9ce3be82b2 100644
|
||||
--- a/dlls/ntdll/unix/unix_private.h
|
||||
+++ b/dlls/ntdll/unix/unix_private.h
|
||||
@@ -170,6 +170,7 @@ extern unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *
|
||||
@@ -171,6 +171,7 @@ extern unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *
|
||||
apc_result_t *result ) DECLSPEC_HIDDEN;
|
||||
extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
|
||||
int *needs_close, enum server_fd_type *type, unsigned int *options ) DECLSPEC_HIDDEN;
|
||||
+extern NTSTATUS server_get_unix_name( HANDLE handle, char **unix_name ) DECLSPEC_HIDDEN;
|
||||
+extern NTSTATUS server_get_unix_name( HANDLE handle, char **unix_name, BOOL nofollow ) DECLSPEC_HIDDEN;
|
||||
extern void server_init_process(void) DECLSPEC_HIDDEN;
|
||||
extern size_t server_init_thread( void *entry_point, BOOL *suspend ) DECLSPEC_HIDDEN;
|
||||
extern int server_pipe( int fd[2] ) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
|
||||
index 91989bd569e..d1c63bdb215 100644
|
||||
index 9d19a621666..9758b11de74 100644
|
||||
--- a/dlls/ntdll/unix/virtual.c
|
||||
+++ b/dlls/ntdll/unix/virtual.c
|
||||
@@ -4009,6 +4009,98 @@ static NTSTATUS get_working_set_ex( HANDLE process, LPCVOID addr,
|
||||
@@ -4060,6 +4060,98 @@ static NTSTATUS get_working_set_ex( HANDLE process, LPCVOID addr,
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ index 91989bd569e..d1c63bdb215 100644
|
||||
+
|
||||
+ if (!status && mapping)
|
||||
+ {
|
||||
+ status = server_get_unix_name( mapping, &unix_name );
|
||||
+ status = server_get_unix_name( mapping, &unix_name, FALSE );
|
||||
+ NtClose( mapping );
|
||||
+ if (!status)
|
||||
+ {
|
||||
@ -142,7 +142,7 @@ index 91989bd569e..d1c63bdb215 100644
|
||||
#define UNIMPLEMENTED_INFO_CLASS(c) \
|
||||
case c: \
|
||||
FIXME("(process=%p,addr=%p) Unimplemented information class: " #c "\n", process, addr); \
|
||||
@@ -4033,8 +4125,10 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr,
|
||||
@@ -4084,8 +4176,10 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr,
|
||||
case MemoryWorkingSetExInformation:
|
||||
return get_working_set_ex( process, addr, buffer, len, res_len );
|
||||
|
||||
@ -222,10 +222,10 @@ index db0debe0af5..6e74f5b770f 100644
|
||||
DECL_HANDLER(get_mapping_committed_range)
|
||||
{
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index 03e567c3dd4..3f0a68ccdcc 100644
|
||||
index faf4891a01e..0d98d9413e4 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -1686,6 +1686,15 @@ enum char_info_mode
|
||||
@@ -1691,6 +1691,15 @@ enum char_info_mode
|
||||
@END
|
||||
|
||||
|
||||
|
@ -2,6 +2,7 @@ Fixes: [23999] Implement MemorySectionName class in NtQueryVirtualMemory
|
||||
Fixes: [27248] Implement K32GetMappedFileName
|
||||
Depends: ntdll-NtDevicePath
|
||||
Depends: ntdll-ForceBottomUpAlloc
|
||||
Depends: ntdll-Junction_Points
|
||||
# This uses RtlDosPathNameToNtPathName_U (and RtlInitUnicodeString) from
|
||||
# ntdll.so, and needs to stop. Defer this until after we have a conversation
|
||||
# about volumes.
|
@ -176,6 +176,7 @@ patch_enable_all ()
|
||||
enable_ntdll_Heap_Improvements="$1"
|
||||
enable_ntdll_Hide_Wine_Exports="$1"
|
||||
enable_ntdll_Interrupt_0x2e="$1"
|
||||
enable_ntdll_Junction_Points="$1"
|
||||
enable_ntdll_Manifest_Range="$1"
|
||||
enable_ntdll_NtAccessCheck="$1"
|
||||
enable_ntdll_NtDevicePath="$1"
|
||||
@ -618,6 +619,9 @@ patch_enable ()
|
||||
ntdll-Interrupt-0x2e)
|
||||
enable_ntdll_Interrupt_0x2e="$2"
|
||||
;;
|
||||
ntdll-Junction_Points)
|
||||
enable_ntdll_Junction_Points="$2"
|
||||
;;
|
||||
ntdll-Manifest_Range)
|
||||
enable_ntdll_Manifest_Range="$2"
|
||||
;;
|
||||
@ -1575,6 +1579,13 @@ if test "$enable_server_Stored_ACLs" -eq 1; then
|
||||
enable_server_File_Permissions=1
|
||||
fi
|
||||
|
||||
if test "$enable_server_File_Permissions" -eq 1; then
|
||||
if test "$enable_ntdll_Junction_Points" -gt 1; then
|
||||
abort "Patchset ntdll-Junction_Points disabled, but server-File_Permissions depends on that."
|
||||
fi
|
||||
enable_ntdll_Junction_Points=1
|
||||
fi
|
||||
|
||||
if test "$enable_server_Desktop_Refcount" -eq 1; then
|
||||
if test "$enable_ws2_32_WSACleanup" -gt 1; then
|
||||
abort "Patchset ws2_32-WSACleanup disabled, but server-Desktop_Refcount depends on that."
|
||||
@ -1621,10 +1632,14 @@ if test "$enable_ntdll_NtQueryVirtualMemory" -eq 1; then
|
||||
if test "$enable_ntdll_ForceBottomUpAlloc" -gt 1; then
|
||||
abort "Patchset ntdll-ForceBottomUpAlloc disabled, but ntdll-NtQueryVirtualMemory depends on that."
|
||||
fi
|
||||
if test "$enable_ntdll_Junction_Points" -gt 1; then
|
||||
abort "Patchset ntdll-Junction_Points disabled, but ntdll-NtQueryVirtualMemory depends on that."
|
||||
fi
|
||||
if test "$enable_ntdll_NtDevicePath" -gt 1; then
|
||||
abort "Patchset ntdll-NtDevicePath disabled, but ntdll-NtQueryVirtualMemory depends on that."
|
||||
fi
|
||||
enable_ntdll_ForceBottomUpAlloc=1
|
||||
enable_ntdll_Junction_Points=1
|
||||
enable_ntdll_NtDevicePath=1
|
||||
fi
|
||||
|
||||
@ -1635,6 +1650,17 @@ if test "$enable_ntdll_NtDevicePath" -eq 1; then
|
||||
enable_ntdll_Pipe_SpecialCharacters=1
|
||||
fi
|
||||
|
||||
if test "$enable_ntdll_Junction_Points" -eq 1; then
|
||||
if test "$enable_ntdll_DOS_Attributes" -gt 1; then
|
||||
abort "Patchset ntdll-DOS_Attributes disabled, but ntdll-Junction_Points depends on that."
|
||||
fi
|
||||
if test "$enable_ntdll_NtQueryEaFile" -gt 1; then
|
||||
abort "Patchset ntdll-NtQueryEaFile disabled, but ntdll-Junction_Points depends on that."
|
||||
fi
|
||||
enable_ntdll_DOS_Attributes=1
|
||||
enable_ntdll_NtQueryEaFile=1
|
||||
fi
|
||||
|
||||
if test "$enable_ntdll_Hide_Wine_Exports" -eq 1; then
|
||||
if test "$enable_advapi32_Token_Integrity_Level" -gt 1; then
|
||||
abort "Patchset advapi32-Token_Integrity_Level disabled, but ntdll-Hide_Wine_Exports depends on that."
|
||||
@ -3631,6 +3657,86 @@ if test "$enable_ntdll_Interrupt_0x2e" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset ntdll-NtQueryEaFile
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/ntdll/tests/file.c, dlls/ntdll/unix/file.c
|
||||
# |
|
||||
if test "$enable_ntdll_NtQueryEaFile" -eq 1; then
|
||||
patch_apply ntdll-NtQueryEaFile/0001-ntdll-Improve-stub-of-NtQueryEaFile.patch
|
||||
(
|
||||
printf '%s\n' '+ { "Sebastian Lackner", "ntdll: Improve stub of NtQueryEaFile.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset ntdll-Junction_Points
|
||||
# |
|
||||
# | This patchset has the following (direct or indirect) dependencies:
|
||||
# | * ntdll-DOS_Attributes, ntdll-NtQueryEaFile
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#12401] NET Framework 2.0, 3.0, 4.0 installers and other apps that make use of GAC API for managed assembly
|
||||
# | installation on NTFS filesystems need reparse point/junction API support
|
||||
# | (FSCTL_SET_REPARSE_POINT/FSCTL_GET_REPARSE_POINT)
|
||||
# | * [#44948] Multiple apps (Spine (Mod starter for Gothic), MS Office 365 installer) need CreateSymbolicLinkW implementation
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * configure.ac, dlls/kernel32/tests/path.c, dlls/kernelbase/file.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/wine/port.h, include/winternl.h, libs/port/Makefile.in, libs/port/renameat2.c, programs/cmd/builtins.c,
|
||||
# | programs/cmd/directory.c, server/fd.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
|
||||
patch_apply ntdll-Junction_Points/0002-ntdll-Add-support-for-reading-junction-points.patch
|
||||
patch_apply ntdll-Junction_Points/0003-ntdll-Add-support-for-deleting-junction-points.patch
|
||||
patch_apply ntdll-Junction_Points/0004-ntdll-Add-a-test-for-junction-point-advertisement.patch
|
||||
patch_apply ntdll-Junction_Points/0005-server-Add-support-for-deleting-junction-points-with.patch
|
||||
patch_apply ntdll-Junction_Points/0007-ntdll-Add-support-for-absolute-symlink-creation.patch
|
||||
patch_apply ntdll-Junction_Points/0008-ntdll-Add-support-for-reading-absolute-symlinks.patch
|
||||
patch_apply ntdll-Junction_Points/0009-ntdll-Add-support-for-deleting-symlinks.patch
|
||||
patch_apply ntdll-Junction_Points/0010-ntdll-Add-support-for-relative-symlink-creation.patch
|
||||
patch_apply ntdll-Junction_Points/0011-ntdll-Add-support-for-reading-relative-symlinks.patch
|
||||
patch_apply ntdll-Junction_Points/0012-ntdll-Add-support-for-file-symlinks.patch
|
||||
patch_apply ntdll-Junction_Points/0013-ntdll-Allow-creation-of-dangling-reparse-points-to-n.patch
|
||||
patch_apply ntdll-Junction_Points/0014-ntdll-Correctly-report-file-symbolic-links-as-files.patch
|
||||
patch_apply ntdll-Junction_Points/0015-kernel32-Set-error-code-when-attempting-to-delete-fi.patch
|
||||
patch_apply ntdll-Junction_Points/0016-server-Properly-handle-file-symlink-deletion.patch
|
||||
patch_apply ntdll-Junction_Points/0017-ntdll-Always-report-symbolic-links-as-containing-zer.patch
|
||||
patch_apply ntdll-Junction_Points/0018-ntdll-Find-dangling-symlinks-quickly.patch
|
||||
patch_apply ntdll-Junction_Points/0019-kernel32-Implement-CreateSymbolicLink-A-W-with-ntdll.patch
|
||||
patch_apply ntdll-Junction_Points/0020-kernel32-Add-reparse-support-to-FindNextFile.patch
|
||||
patch_apply ntdll-Junction_Points/0021-wcmd-Display-reparse-point-type-in-directory-listing.patch
|
||||
patch_apply ntdll-Junction_Points/0022-wcmd-Show-reparse-point-target-in-directory-listing.patch
|
||||
patch_apply ntdll-Junction_Points/0023-wcmd-Add-junction-point-support-to-mklink.patch
|
||||
patch_apply ntdll-Junction_Points/0024-server-Fix-obtaining-information-about-a-symlink.patch
|
||||
(
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "ntdll: Add support for junction point creation.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "ntdll: Add support for reading junction points.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "ntdll: Add support for deleting junction points.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "ntdll: Add a test for junction point advertisement.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "server: Add support for deleting junction points with RemoveDirectory.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "ntdll: Add support for absolute symlink creation.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "ntdll: Add support for reading absolute symlinks.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "ntdll: Add support for deleting symlinks.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "ntdll: Add support for relative symlink creation.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "ntdll: Add support for reading relative symlinks.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "ntdll: Add support for file symlinks.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "ntdll: Allow creation of dangling reparse points to non-existent paths.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "ntdll: Correctly report file symbolic links as files.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "kernel32: Set error code when attempting to delete file symlinks as directories.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "server: Properly handle file symlink deletion.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "ntdll: Always report symbolic links as containing zero bytes.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "ntdll: Find dangling symlinks quickly.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "kernel32: Implement CreateSymbolicLink[A|W] with ntdll reparse points.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "kernel32: Add reparse support to FindNextFile.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "wcmd: Display reparse point type in directory listings.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "wcmd: Show reparse point target in directory listing.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "wcmd: Add junction point support to mklink.", 1 },';
|
||||
printf '%s\n' '+ { "Erich E. Hoover", "server: Fix obtaining information about a symlink.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset ntdll-Manifest_Range
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
@ -3691,18 +3797,6 @@ if test "$enable_ntdll_NtDevicePath" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset ntdll-NtQueryEaFile
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/ntdll/tests/file.c, dlls/ntdll/unix/file.c
|
||||
# |
|
||||
if test "$enable_ntdll_NtQueryEaFile" -eq 1; then
|
||||
patch_apply ntdll-NtQueryEaFile/0001-ntdll-Improve-stub-of-NtQueryEaFile.patch
|
||||
(
|
||||
printf '%s\n' '+ { "Sebastian Lackner", "ntdll: Improve stub of NtQueryEaFile.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset ntdll-NtQuerySection
|
||||
# |
|
||||
# | Modified files:
|
||||
@ -3718,7 +3812,8 @@ fi
|
||||
# Patchset ntdll-NtQueryVirtualMemory
|
||||
# |
|
||||
# | This patchset has the following (direct or indirect) dependencies:
|
||||
# | * ntdll-ForceBottomUpAlloc, ntdll-Pipe_SpecialCharacters, ntdll-NtDevicePath
|
||||
# | * ntdll-ForceBottomUpAlloc, ntdll-DOS_Attributes, ntdll-NtQueryEaFile, ntdll-Junction_Points, ntdll-
|
||||
# | Pipe_SpecialCharacters, ntdll-NtDevicePath
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#23999] Implement MemorySectionName class in NtQueryVirtualMemory
|
||||
@ -4326,6 +4421,9 @@ fi
|
||||
|
||||
# Patchset server-File_Permissions
|
||||
# |
|
||||
# | This patchset has the following (direct or indirect) dependencies:
|
||||
# | * ntdll-DOS_Attributes, ntdll-NtQueryEaFile, ntdll-Junction_Points
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#44691] Improve mapping of DACL to file permissions
|
||||
# |
|
||||
@ -4356,7 +4454,7 @@ fi
|
||||
# Patchset server-Stored_ACLs
|
||||
# |
|
||||
# | This patchset has the following (direct or indirect) dependencies:
|
||||
# | * ntdll-DOS_Attributes, server-File_Permissions
|
||||
# | * ntdll-DOS_Attributes, ntdll-NtQueryEaFile, ntdll-Junction_Points, server-File_Permissions
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#33576] Support for stored file ACLs
|
||||
@ -4387,7 +4485,7 @@ fi
|
||||
# Patchset server-Inherited_ACLs
|
||||
# |
|
||||
# | This patchset has the following (direct or indirect) dependencies:
|
||||
# | * ntdll-DOS_Attributes, server-File_Permissions, server-Stored_ACLs
|
||||
# | * ntdll-DOS_Attributes, ntdll-NtQueryEaFile, ntdll-Junction_Points, server-File_Permissions, server-Stored_ACLs
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/advapi32/tests/security.c, server/file.c
|
||||
|
@ -1,4 +1,4 @@
|
||||
From b1dcc9759921e696a554c46d7aee2c4c29d3c7ae Mon Sep 17 00:00:00 2001
|
||||
From 7f1169fde63549646dcd24d60ea648db3a11765c Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Fri, 3 Apr 2015 03:58:47 +0200
|
||||
Subject: [PATCH] server: Allow to open files without any permission bits. (try
|
||||
@ -65,10 +65,10 @@ index 825f8451904..948c257cea2 100644
|
||||
|
||||
done:
|
||||
diff --git a/server/fd.c b/server/fd.c
|
||||
index e5e1fdbbf32..188a632575f 100644
|
||||
index 819f77d041e..c1401acc1aa 100644
|
||||
--- a/server/fd.c
|
||||
+++ b/server/fd.c
|
||||
@@ -1835,6 +1835,7 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
@@ -1892,6 +1892,7 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
int root_fd = -1;
|
||||
int rw_mode;
|
||||
char *path;
|
||||
@ -76,10 +76,10 @@ index e5e1fdbbf32..188a632575f 100644
|
||||
int created = (flags & O_CREAT);
|
||||
|
||||
if (((options & FILE_DELETE_ON_CLOSE) && !(access & DELETE)) ||
|
||||
@@ -1894,10 +1895,28 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
if ((access & FILE_UNIX_WRITE_ACCESS) || (flags & O_CREAT))
|
||||
fd->unix_fd = open( name, O_RDONLY | (flags & ~(O_TRUNC | O_CREAT | O_EXCL)), *mode );
|
||||
@@ -1958,10 +1959,28 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
fd->unix_fd = open( name, rw_mode | O_SYMLINK | (flags & ~O_TRUNC), *mode );
|
||||
}
|
||||
#endif
|
||||
+ else if (errno == EACCES)
|
||||
+ {
|
||||
+ /* try to change permissions temporarily to open a file descriptor */
|
||||
@ -105,12 +105,12 @@ index e5e1fdbbf32..188a632575f 100644
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@@ -1912,6 +1931,7 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
closed_fd->unix_fd = fd->unix_fd;
|
||||
@@ -1978,6 +1997,7 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||||
closed_fd->unlink = 0;
|
||||
closed_fd->unlink_name = fd->unlink_name;
|
||||
closed_fd->unix_name = fd->unix_name;
|
||||
+ if (do_chmod) chmod( name, *mode );
|
||||
fstat( fd->unix_fd, &st );
|
||||
lstat( fd->unlink_name, &st );
|
||||
*mode = st.st_mode;
|
||||
|
||||
--
|
||||
|
@ -1,2 +1,3 @@
|
||||
Fixes: Allow to open files/directories without any access rights in order to query attributes
|
||||
Fixes: [44691] Improve mapping of DACL to file permissions
|
||||
Depends: ntdll-Junction_Points
|
||||
|
Loading…
Reference in New Issue
Block a user