Rebase against 6a966678e89c0c2090b7684a1c2ebfb0a295b9a8.

This commit is contained in:
Elizabeth Figura
2025-11-17 16:36:15 -06:00
parent 0229597809
commit 4741f1abc6
3 changed files with 14 additions and 131 deletions

View File

@@ -1,117 +0,0 @@
From 51373e0350ff1b507d7b47d6e5acd84b8af9d328 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
Date: Sat, 6 Feb 2021 12:46:30 -0700
Subject: [PATCH] kernelbase: Add support for moving reparse points with
MoveFile*.
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
---
dlls/kernelbase/file.c | 2 +-
dlls/ntdll/unix/file.c | 24 ++++++++++++++++++++++--
server/fd.c | 6 ++++--
3 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c
index 36045116e43..f1b1326353f 100644
--- a/dlls/kernelbase/file.c
+++ b/dlls/kernelbase/file.c
@@ -2597,7 +2597,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH MoveFileWithProgressW( const WCHAR *source, const
InitializeObjectAttributes( &attr, &nt_name, OBJ_CASE_INSENSITIVE, 0, NULL );
status = NtOpenFile( &source_handle, DELETE | SYNCHRONIZE, &attr, &io,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- FILE_SYNCHRONOUS_IO_NONALERT );
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT );
RtlFreeUnicodeString( &nt_name );
if (!set_ntstatus( status )) goto error;
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 3c341a6d702..9076da9f763 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -5572,6 +5572,8 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
unsigned int flags;
UNICODE_STRING name_str, nt_name;
OBJECT_ATTRIBUTES attr;
+ REPARSE_DATA_BUFFER *buffer = NULL;
+ ULONG buffer_len = 0;
char *unix_name;
if (class == FileRenameInformation)
@@ -5586,6 +5588,20 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
name_str.Length = info->FileNameLength;
name_str.MaximumLength = info->FileNameLength + sizeof(WCHAR);
InitializeObjectAttributes( &attr, &name_str, OBJ_CASE_INSENSITIVE, info->RootDirectory, NULL );
+
+ /* obtain all the data from the reparse point (if applicable) */
+ status = get_reparse_point( handle, NULL, &buffer_len );
+ if (status == STATUS_BUFFER_TOO_SMALL)
+ {
+ buffer = malloc( buffer_len );
+ status = get_reparse_point( handle, buffer, &buffer_len );
+ if (status != STATUS_SUCCESS)
+ {
+ free( buffer );
+ break;
+ }
+ }
+
status = get_nt_and_unix_names( &attr, &nt_name, &unix_name, FILE_OPEN_IF );
if (status == STATUS_SUCCESS || status == STATUS_NO_SUCH_FILE)
{
@@ -5602,8 +5618,13 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
}
SERVER_END_REQ;
+ /* rebuild reparse point in new location (if applicable) */
+ if (buffer && status == STATUS_SUCCESS)
+ status = create_reparse_point( handle, buffer );
+
+ free( unix_name );
}
- free( unix_name );
+ free( buffer );
free( nt_name.Buffer );
}
else status = STATUS_INVALID_PARAMETER_3;
@@ -5646,7 +5667,6 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
status = wine_server_call( req );
}
SERVER_END_REQ;
-
}
free( unix_name );
free( nt_name.Buffer );
diff --git a/server/fd.c b/server/fd.c
index 466259ae567..7f88fcd6e33 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2771,7 +2771,7 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da
goto failed;
}
- if (!stat( name, &st ))
+ if (!lstat( name, &st ))
{
if (!fstat( fd->unix_fd, &st2 ) && st.st_ino == st2.st_ino && st.st_dev == st2.st_dev)
{
@@ -2787,7 +2787,7 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da
}
/* can't replace directories or special files */
- if (!S_ISREG( st.st_mode ))
+ if (!S_ISREG( st.st_mode ) && !S_ISLNK( st.st_mode ))
{
set_error( STATUS_ACCESS_DENIED );
goto failed;
@@ -2853,6 +2853,8 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da
fd->nt_name = dup_nt_name( root, nt_name, &fd->nt_namelen );
free( fd->unix_name );
fd->closed->unix_name = fd->unix_name = realpath( name, NULL );
+ if (!fd->unix_name)
+ fd->closed->unix_name = fd->unix_name = dup_fd_name( root, name ); /* dangling symlink */
free( name );
if (!fd->unix_name)
set_error( STATUS_NO_MEMORY );
--
2.47.2