[PATCH 4/5] ntdll: Report Unix mount points as Win32 mount points in NtQueryInformationFile().
Zebediah Figura
z.figura12 at gmail.com
Sat Mar 14 10:41:00 CDT 2020
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
dlls/ntdll/file.c | 31 ++++++++++++++++++++++---------
include/winternl.h | 2 +-
2 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index d4bc712d9d3..7b2e102e536 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -136,8 +136,15 @@ static inline ULONG get_file_attributes( const struct stat *st )
return attr;
}
+static BOOL fd_is_mount_point( int fd, const struct stat *st )
+{
+ struct stat parent;
+ return S_ISDIR( st->st_mode ) && !fstatat( fd, "..", &parent, 0 )
+ && (parent.st_dev != st->st_dev || parent.st_ino == st->st_ino);
+}
+
/* get the stat info and file attributes for a file (by file descriptor) */
-int fd_get_file_info( int fd, struct stat *st, ULONG *attr )
+int fd_get_file_info( int fd, unsigned int options, struct stat *st, ULONG *attr )
{
int ret;
@@ -145,6 +152,9 @@ int fd_get_file_info( int fd, struct stat *st, ULONG *attr )
ret = fstat( fd, st );
if (ret == -1) return ret;
*attr |= get_file_attributes( st );
+ /* consider mount points to be reparse points (IO_REPARSE_TAG_MOUNT_POINT) */
+ if ((options & FILE_OPEN_REPARSE_POINT) && fd_is_mount_point( fd, st ))
+ *attr |= FILE_ATTRIBUTE_REPARSE_POINT;
return ret;
}
@@ -2318,6 +2328,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
struct stat st;
int fd, needs_close = FALSE;
ULONG attr;
+ unsigned int options;
TRACE("(%p,%p,%p,0x%08x,0x%08x)\n", hFile, io, ptr, len, class);
@@ -2330,7 +2341,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
if (len < info_sizes[class])
return io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
- if ((io->u.Status = server_get_unix_fd( hFile, 0, &fd, &needs_close, NULL, NULL )))
+ if ((io->u.Status = server_get_unix_fd( hFile, 0, &fd, &needs_close, NULL, &options )))
{
if (io->u.Status != STATUS_BAD_DEVICE_TYPE) return io->u.Status;
return server_get_file_info( hFile, io, ptr, len, class );
@@ -2339,7 +2350,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
switch (class)
{
case FileBasicInformation:
- if (fd_get_file_info( fd, &st, &attr ) == -1)
+ if (fd_get_file_info( fd, options, &st, &attr ) == -1)
io->u.Status = FILE_GetNtStatus();
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
io->u.Status = STATUS_INVALID_INFO_CLASS;
@@ -2350,7 +2361,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
{
FILE_STANDARD_INFORMATION *info = ptr;
- if (fd_get_file_info( fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
+ if (fd_get_file_info( fd, options, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
else
{
fill_file_info( &st, attr, info, class );
@@ -2367,7 +2378,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
}
break;
case FileInternalInformation:
- if (fd_get_file_info( fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
+ if (fd_get_file_info( fd, options, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
else fill_file_info( &st, attr, ptr, class );
break;
case FileEaInformation:
@@ -2377,7 +2388,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
}
break;
case FileEndOfFileInformation:
- if (fd_get_file_info( fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
+ if (fd_get_file_info( fd, options, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
else fill_file_info( &st, attr, ptr, class );
break;
case FileAllInformation:
@@ -2385,7 +2396,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
FILE_ALL_INFORMATION *info = ptr;
ANSI_STRING unix_name;
- if (fd_get_file_info( fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
+ if (fd_get_file_info( fd, options, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
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( hFile, &unix_name )))
@@ -2493,7 +2504,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
}
break;
case FileIdInformation:
- if (fd_get_file_info( fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
+ if (fd_get_file_info( fd, options, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
else
{
FILE_ID_INFORMATION *info = ptr;
@@ -2503,12 +2514,14 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
}
break;
case FileAttributeTagInformation:
- if (fd_get_file_info( fd, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
+ if (fd_get_file_info( fd, options, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
else
{
FILE_ATTRIBUTE_TAG_INFORMATION *info = ptr;
info->FileAttributes = attr;
info->ReparseTag = 0; /* FIXME */
+ if ((options & FILE_OPEN_REPARSE_POINT) && fd_is_mount_point( fd, &st ))
+ info->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
}
break;
default:
diff --git a/include/winternl.h b/include/winternl.h
index d9809c7ad31..19e8965e99f 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -1795,7 +1795,7 @@ typedef struct _RTL_HANDLE_TABLE
#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000
#define FILE_NO_COMPRESSION 0x00008000
#define FILE_RESERVE_OPFILTER 0x00100000
-#define FILE_TRANSACTED_MODE 0x00200000
+#define FILE_OPEN_REPARSE_POINT 0x00200000
#define FILE_OPEN_OFFLINE_FILE 0x00400000
#define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000
--
2.25.1
More information about the wine-devel
mailing list