diff --git a/patches/ntdll-Junction_Points/0006-kernelbase-Add-support-for-deleting-reparse-points-w.patch b/patches/ntdll-Junction_Points/0006-kernelbase-Add-support-for-deleting-reparse-points-w.patch deleted file mode 100644 index c25e89b7..00000000 --- a/patches/ntdll-Junction_Points/0006-kernelbase-Add-support-for-deleting-reparse-points-w.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0423cf43baf2938b4b1e7d705c20af11fb13f82c Mon Sep 17 00:00:00 2001 -From: "Erich E. Hoover" -Date: Sat, 12 Dec 2020 17:35:21 -0700 -Subject: kernelbase: Add support for deleting reparse points with - RemoveDirectory. - -Signed-off-by: Erich E. Hoover ---- - dlls/kernelbase/file.c | 2 +- - 2 files changed, 28 insertions(+), 2 deletions(-) - -diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c -index bfb291fa925..6214f549406 100644 ---- a/dlls/kernelbase/file.c -+++ b/dlls/kernelbase/file.c -@@ -3493,7 +3493,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH RemoveDirectoryW( LPCWSTR path ) - InitializeObjectAttributes( &attr, &nt_name, OBJ_CASE_INSENSITIVE, 0, NULL ); - status = NtOpenFile( &handle, DELETE | SYNCHRONIZE, &attr, &io, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, -- FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); -+ FILE_OPEN_REPARSE_POINT | FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); - RtlFreeUnicodeString( &nt_name ); - - if (!status) --- -2.17.1 - diff --git a/patches/ntdll-Junction_Points/0007-kernelbase-Add-support-for-deleting-reparse-points-w.patch b/patches/ntdll-Junction_Points/0007-kernelbase-Add-support-for-deleting-reparse-points-w.patch deleted file mode 100644 index aff615be..00000000 --- a/patches/ntdll-Junction_Points/0007-kernelbase-Add-support-for-deleting-reparse-points-w.patch +++ /dev/null @@ -1,28 +0,0 @@ -From afd4ad0f6725f49daaa0fe2351c98faa6a57519a Mon Sep 17 00:00:00 2001 -From: "Erich E. Hoover" -Date: Sat, 6 Feb 2021 12:52:51 -0700 -Subject: [PATCH] kernelbase: Add support for deleting reparse points with - DeleteFile. - -Signed-off-by: Erich E. Hoover ---- - dlls/kernelbase/file.c | 3 ++- - 2 files changed, 11 insertions(+), 3 deletions(-) - -diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c -index 36b43d345d6..b7d16410d75 100644 ---- a/dlls/kernelbase/file.c -+++ b/dlls/kernelbase/file.c -@@ -1002,7 +1002,8 @@ BOOL WINAPI DECLSPEC_HOTPATCH DeleteFileW( LPCWSTR path ) - InitializeObjectAttributes( &attr, &nameW, OBJ_CASE_INSENSITIVE, 0, NULL ); - status = NtCreateFile(&hFile, SYNCHRONIZE | DELETE, &attr, &io, NULL, 0, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, -- FILE_OPEN, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE, NULL, 0); -+ FILE_OPEN, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT, -+ NULL, 0); - if (status == STATUS_SUCCESS) status = NtClose(hFile); - - RtlFreeUnicodeString( &nameW ); --- -2.47.2 - diff --git a/patches/ntdll-Junction_Points/0011-ntdll-Follow-reparse-points-during-path-resolution.patch b/patches/ntdll-Junction_Points/0011-ntdll-Follow-reparse-points-during-path-resolution.patch deleted file mode 100644 index 9e8a169e..00000000 --- a/patches/ntdll-Junction_Points/0011-ntdll-Follow-reparse-points-during-path-resolution.patch +++ /dev/null @@ -1,349 +0,0 @@ -From a9773394980e77b017dcb797766ec422b384a5cc Mon Sep 17 00:00:00 2001 -From: "Erich E. Hoover" -Date: Sat, 3 Sep 2022 11:23:31 -0600 -Subject: [PATCH] ntdll: Follow reparse points during path resolution. - -Signed-off-by: Erich E. Hoover ---- - dlls/ntdll/unix/file.c | 196 +++++++++++++++++++++++++++++++++++----- - 2 files changed, 184 insertions(+), 23 deletions(-) - -diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c -index f3274478ae2..860e563f69d 100644 ---- a/dlls/ntdll/unix/file.c -+++ b/dlls/ntdll/unix/file.c -@@ -3741,6 +3741,35 @@ done: - } - - -+static NTSTATUS get_reparse_target( UNICODE_STRING *nt_target, REPARSE_DATA_BUFFER *buffer, -+ int *is_relative ) -+{ -+ int target_len, offset; -+ WCHAR *target; -+ -+ switch( buffer->ReparseTag ) -+ { -+ case IO_REPARSE_TAG_MOUNT_POINT: -+ offset = buffer->MountPointReparseBuffer.SubstituteNameOffset/sizeof(WCHAR); -+ target = &buffer->MountPointReparseBuffer.PathBuffer[offset]; -+ target_len = buffer->MountPointReparseBuffer.SubstituteNameLength; -+ *is_relative = FALSE; -+ break; -+ case IO_REPARSE_TAG_SYMLINK: -+ offset = buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof(WCHAR); -+ target = &buffer->SymbolicLinkReparseBuffer.PathBuffer[offset]; -+ target_len = buffer->SymbolicLinkReparseBuffer.SubstituteNameLength; -+ *is_relative = (buffer->SymbolicLinkReparseBuffer.Flags & SYMLINK_FLAG_RELATIVE) == SYMLINK_FLAG_RELATIVE; -+ break; -+ default: -+ return STATUS_IO_REPARSE_TAG_NOT_HANDLED; -+ } -+ nt_target->Buffer = target; -+ nt_target->Length = target_len; -+ return STATUS_REPARSE; -+} -+ -+ - /* - * 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. -@@ -3917,16 +3946,14 @@ cleanup: - - - /* -- * Retrieve the unix name corresponding to a file handle and use that to find the destination of the -- * symlink corresponding to that file handle. -+ * Obtain the reparse point buffer from the unix filename for the reparse point. - */ --NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG *size) -+NTSTATUS get_reparse_point_unix(const char *unix_name, REPARSE_DATA_BUFFER *buffer, ULONG *size) - { - char link_dir[PATH_MAX], link_path[PATH_MAX], *d; - int link_path_len, buffer_len, encoded_len; - REPARSE_DATA_BUFFER header; - ULONG out_size = *size; -- char *unix_name = NULL; - char *encoded = NULL; - int link_dir_fd = -1; - NTSTATUS status; -@@ -3934,9 +3961,6 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG *si - int depth; - char *p; - -- if ((status = server_get_unix_name( handle, &unix_name ))) -- goto cleanup; -- - ret = readlink( unix_name, link_path, sizeof(link_path) ); - if (ret < 0) - { -@@ -4036,12 +4060,76 @@ NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG *si - - cleanup: - if (link_dir_fd != -1) close( link_dir_fd ); -- free( unix_name ); - free( encoded ); - return status; - } - - -+/* -+ * Retrieve the unix name corresponding to a file handle and use that to find the destination of the -+ * symlink corresponding to that file handle. -+ */ -+NTSTATUS get_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer, ULONG *size) -+{ -+ char *unix_name = NULL; -+ NTSTATUS status; -+ -+ if ((status = server_get_unix_name( handle, &unix_name ))) -+ return status; -+ status = get_reparse_point_unix( unix_name, buffer, size ); -+ free( unix_name ); -+ return status; -+} -+ -+ -+/* find the NT target of a reparse point */ -+static NTSTATUS find_reparse_target( const char *unix_name, const WCHAR *parent, int parent_len, -+ WCHAR **new_name, int *new_name_len) -+{ -+ REPARSE_DATA_BUFFER *buffer = NULL; -+ UNICODE_STRING nt_target; -+ ULONG buffer_len = 0; -+ int is_relative; -+ NTSTATUS status; -+ -+ status = get_reparse_point_unix( unix_name, NULL, &buffer_len ); -+ if (status != STATUS_BUFFER_TOO_SMALL) -+ return status; -+ -+ buffer = malloc( buffer_len ); -+ if (!buffer) -+ return STATUS_NO_MEMORY; -+ if ((status = get_reparse_point_unix( unix_name, buffer, &buffer_len )) != STATUS_SUCCESS) -+ { -+ free( buffer ); -+ return status; -+ } -+ if ((status = get_reparse_target( &nt_target, buffer, &is_relative )) == STATUS_REPARSE) -+ { -+ WCHAR *p; -+ -+ p = *new_name = malloc( nt_target.Length + parent_len*sizeof(WCHAR) ); -+ if (!p) -+ { -+ status = STATUS_NO_MEMORY; -+ goto done; -+ } -+ if (is_relative) -+ { -+ memcpy( p, parent, parent_len*sizeof(WCHAR) ); -+ p += parent_len; -+ } -+ memcpy( p, nt_target.Buffer, nt_target.Length ); -+ p += nt_target.Length/sizeof(WCHAR); -+ *new_name_len = p - *new_name; -+ } -+ -+done: -+ free( buffer ); -+ return status; -+} -+ -+ - /* - * Retrieve the unix name corresponding to a file handle, remove that symlink, and then recreate - * a directory at the location of the old filename. -@@ -4135,15 +4223,24 @@ cleanup: - } - - -+static NTSTATUS IoReplaceFileObjectName( FILE_OBJECT *fileobj, PWSTR name, USHORT name_len ) -+{ -+ fileobj->FileName.Buffer = name; -+ fileobj->FileName.Length = name_len; -+ return STATUS_SUCCESS; -+} -+ -+ - /****************************************************************************** - * lookup_unix_name - * - * Helper for nt_to_unix_file_name - */ --static NTSTATUS lookup_unix_name( int root_fd, const WCHAR *name, int name_len, char **buffer, int unix_len, -+static NTSTATUS lookup_unix_name( FILE_OBJECT *fileobj, int root_fd, const WCHAR *name, int name_len, char **buffer, int unix_len, - int pos, UINT disposition, BOOL is_unix ) - { - static const WCHAR invalid_charsW[] = { INVALID_NT_CHARS, '/', 0 }; -+ const WCHAR *fullname = fileobj->FileName.Buffer; - NTSTATUS status; - int ret; - struct stat st; -@@ -4200,6 +4297,8 @@ static NTSTATUS lookup_unix_name( int root_fd, const WCHAR *name, int name_len, - while (name_len) - { - const WCHAR *end, *next; -+ WCHAR *target = NULL; -+ int target_len = 0; - - end = name; - while (end < name + name_len && *end != '\\') end++; -@@ -4219,8 +4318,31 @@ static NTSTATUS lookup_unix_name( int root_fd, const WCHAR *name, int name_len, - - status = find_file_in_dir( root_fd, unix_name, pos, name, end - name, is_unix ); - -+ /* follow reparse point and restart from there (if applicable) */ -+ if (name_len && find_reparse_target( unix_name, fullname, name - fullname, &target, &target_len ) == STATUS_REPARSE) -+ { -+ int new_name_len = target_len + name_len + 1; -+ WCHAR *p, *new_name; -+ -+ if (!(p = new_name = malloc( new_name_len*sizeof(WCHAR) ))) -+ { -+ free( target ); -+ status = STATUS_NO_MEMORY; -+ break; -+ } -+ memcpy( p, target, target_len*sizeof(WCHAR) ); -+ p += target_len; -+ (p++)[0] = '\\'; -+ memcpy( p, next, name_len*sizeof(WCHAR) ); -+ TRACE( "Follow reparse point %s => %s\n", debugstr_wn(fullname, end-fullname), -+ debugstr_wn(new_name, new_name_len) ); -+ free( target ); -+ if (IoReplaceFileObjectName( fileobj, new_name, new_name_len*sizeof(WCHAR) )) -+ free( new_name ); -+ return STATUS_REPARSE; -+ } - /* if this is the last element, not finding it is not necessarily fatal */ -- if (!name_len) -+ else if (!name_len) - { - if (status == STATUS_OBJECT_NAME_NOT_FOUND) - { -@@ -4259,12 +4381,12 @@ static NTSTATUS lookup_unix_name( int root_fd, const WCHAR *name, int name_len, - /****************************************************************************** - * nt_to_unix_file_name_no_root - */ --static NTSTATUS nt_to_unix_file_name_no_root( const UNICODE_STRING *nameW, char **unix_name_ret, -+static NTSTATUS nt_to_unix_file_name_no_root( FILE_OBJECT *fileobj, char **unix_name_ret, - UINT disposition ) - { - static const WCHAR unixW[] = {'u','n','i','x'}; - static const WCHAR invalid_charsW[] = { INVALID_NT_CHARS, 0 }; -- -+ const UNICODE_STRING *nameW = &fileobj->FileName; - NTSTATUS status = STATUS_SUCCESS; - const WCHAR *name; - struct stat st; -@@ -4354,7 +4476,7 @@ static NTSTATUS nt_to_unix_file_name_no_root( const UNICODE_STRING *nameW, char - name += prefix_len; - name_len -= prefix_len; - -- status = lookup_unix_name( AT_FDCWD, name, name_len, &unix_name, unix_len, pos, disposition, is_unix ); -+ status = lookup_unix_name( fileobj, AT_FDCWD, name, name_len, &unix_name, unix_len, pos, disposition, is_unix ); - if (status == STATUS_SUCCESS || status == STATUS_NO_SUCH_FILE) - { - TRACE( "%s -> %s\n", debugstr_us(nameW), debugstr_a(unix_name) ); -@@ -4362,7 +4484,8 @@ static NTSTATUS nt_to_unix_file_name_no_root( const UNICODE_STRING *nameW, char - } - else - { -- TRACE( "%s not found in %s\n", debugstr_w(name), debugstr_an(unix_name, pos) ); -+ if (status != STATUS_REPARSE) -+ TRACE( "%s not found in %s\n", debugstr_w(name), debugstr_an(unix_name, pos) ); - free( unix_name ); - } - return status; -@@ -4380,18 +4503,30 @@ static NTSTATUS nt_to_unix_file_name_no_root( const UNICODE_STRING *nameW, char - */ - static NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret, UINT disposition ) - { -+ HANDLE rootdir = attr->RootDirectory; - enum server_fd_type type; -- int root_fd, needs_close; -+ int old_cwd, root_fd, needs_close; -+ int reparse_count = 0; -+ FILE_OBJECT fileobj; - const WCHAR *name; - char *unix_name; - int name_len, unix_len; - NTSTATUS status; - -- if (!attr->RootDirectory) /* without root dir fall back to normal lookup */ -- return nt_to_unix_file_name_no_root( attr->ObjectName, name_ret, disposition ); -+ fileobj.FileName = *attr->ObjectName; -+reparse: -+ if (reparse_count++ == 31) -+ return STATUS_REPARSE_POINT_NOT_RESOLVED; -+ if (!rootdir) /* without root dir fall back to normal lookup */ -+ { -+ status = nt_to_unix_file_name_no_root( &fileobj, name_ret, disposition ); -+ if (status == STATUS_REPARSE) goto reparse; -+ if (fileobj.FileName.Buffer != attr->ObjectName->Buffer) free( fileobj.FileName.Buffer); -+ return status; -+ } - -- name = attr->ObjectName->Buffer; -- name_len = attr->ObjectName->Length / sizeof(WCHAR); -+ name = fileobj.FileName.Buffer; -+ name_len = fileobj.FileName.Length / sizeof(WCHAR); - - if (name_len && name[0] == '\\') return STATUS_INVALID_PARAMETER; - -@@ -4399,7 +4534,7 @@ static NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name - if (!(unix_name = malloc( unix_len ))) return STATUS_NO_MEMORY; - unix_name[0] = '.'; - -- if (!(status = server_get_unix_fd( attr->RootDirectory, 0, &root_fd, &needs_close, &type, NULL ))) -+ if (!(status = server_get_unix_fd( rootdir, 0, &root_fd, &needs_close, &type, NULL ))) - { - if (type != FD_TYPE_DIR) - { -@@ -4408,7 +4543,16 @@ static NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name - } - else - { -- status = lookup_unix_name( root_fd, name, name_len, &unix_name, unix_len, 1, disposition, FALSE ); -+ mutex_lock( &dir_mutex ); -+ if ((old_cwd = open( ".", O_RDONLY )) != -1 && fchdir( root_fd ) != -1) -+ { -+ status = lookup_unix_name( &fileobj, root_fd, name, name_len, &unix_name, unix_len, 1, -+ disposition, FALSE ); -+ if (fchdir( old_cwd ) == -1) chdir( "/" ); -+ } -+ else status = errno_to_status( errno ); -+ mutex_unlock( &dir_mutex ); -+ if (old_cwd != -1) close( old_cwd ); - if (needs_close) close( root_fd ); - } - } -@@ -4416,14 +4560,22 @@ static NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name - - if (status == STATUS_SUCCESS || status == STATUS_NO_SUCH_FILE) - { -- TRACE( "%s -> %s\n", debugstr_us(attr->ObjectName), debugstr_a(unix_name) ); -+ TRACE( "%s -> %s\n", debugstr_us(&fileobj.FileName), debugstr_a(unix_name) ); - *name_ret = unix_name; - } -+ else if (status == STATUS_REPARSE) -+ { -+ if (fileobj.FileName.Buffer[0] == '\\') rootdir = 0; -+ free( unix_name ); -+ goto reparse; -+ } - else - { - TRACE( "%s not found in %s\n", debugstr_w(name), unix_name ); - free( unix_name ); - } -+ -+ if (fileobj.FileName.Buffer != attr->ObjectName->Buffer) free( fileobj.FileName.Buffer); - return status; - } - --- -2.47.2 - diff --git a/staging/upstream-commit b/staging/upstream-commit index 28753d88..0c325118 100644 --- a/staging/upstream-commit +++ b/staging/upstream-commit @@ -1 +1 @@ -76e7e90c3679766ac327b138e3269fb61ead6e4a +fe1175af410d04f806dda770502d0476a8ccbef6