[PATCH v3 3/6] ntdll: Fill the volume serial number in NtQueryInformationFile(FileIdInformation).
Zebediah Figura
z.figura12 at gmail.com
Wed Apr 8 16:06:04 CDT 2020
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
My apologies for forgetting to move those functions upwards in the first
place...
dlls/ntdll/file.c | 246 ++++++++++++++++++++++++----------------------
1 file changed, 126 insertions(+), 120 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index dac8538add8..a9770290e0c 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -2237,6 +2237,124 @@ static NTSTATUS server_get_file_info( HANDLE handle, IO_STATUS_BLOCK *io, void *
}
+/* Find a DOS device which can act as the root of "path".
+ * Similar to find_drive_root(), but returns -1 instead of crossing volumes. */
+static int find_dos_device( const char *path )
+{
+ int len = strlen(path);
+ int drive;
+ char *buffer;
+ struct stat st;
+ struct drive_info info[MAX_DOS_DRIVES];
+ dev_t dev_id;
+
+ if (!DIR_get_drives_info( info )) return -1;
+
+ if (stat( path, &st ) < 0) return -1;
+ dev_id = st.st_dev;
+
+ /* strip off trailing slashes */
+ while (len > 1 && path[len - 1] == '/') len--;
+
+ /* make a copy of the path */
+ if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, len + 1 ))) return -1;
+ memcpy( buffer, path, len );
+ buffer[len] = 0;
+
+ for (;;)
+ {
+ if (!stat( buffer, &st ) && S_ISDIR( st.st_mode ))
+ {
+ if (st.st_dev != dev_id) break;
+
+ for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
+ {
+ if ((info[drive].dev == st.st_dev) && (info[drive].ino == st.st_ino))
+ {
+ if (len == 1) len = 0; /* preserve root slash in returned path */
+ TRACE( "%s -> drive %c:, root=%s, name=%s\n",
+ debugstr_a(path), 'A' + drive, debugstr_a(buffer), debugstr_a(path + len));
+ RtlFreeHeap( GetProcessHeap(), 0, buffer );
+ return drive;
+ }
+ }
+ }
+ if (len <= 1) break; /* reached root */
+ while (path[len - 1] != '/') len--;
+ while (path[len - 1] == '/') len--;
+ buffer[len] = 0;
+ }
+ RtlFreeHeap( GetProcessHeap(), 0, buffer );
+ return -1;
+}
+
+static struct mountmgr_unix_drive *get_mountmgr_fs_info( HANDLE handle, int fd )
+{
+ struct mountmgr_unix_drive *drive;
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING string;
+ ANSI_STRING unix_name;
+ IO_STATUS_BLOCK io;
+ HANDLE mountmgr;
+ NTSTATUS status;
+ int letter;
+
+ if (server_get_unix_name( handle, &unix_name ))
+ return NULL;
+
+ letter = find_dos_device( unix_name.Buffer );
+ RtlFreeAnsiString( &unix_name );
+
+ if (!(drive = RtlAllocateHeap( GetProcessHeap(), 0, 1024 )))
+ return NULL;
+
+ if (letter == -1)
+ {
+ struct stat st;
+
+ if (fstat( fd, &st ) == -1)
+ {
+ RtlFreeHeap( GetProcessHeap(), 0, drive );
+ return NULL;
+ }
+
+ drive->unix_dev = st.st_dev;
+ drive->letter = 0;
+ }
+ else
+ drive->letter = 'a' + letter;
+
+ RtlInitUnicodeString( &string, MOUNTMGR_DEVICE_NAME );
+ InitializeObjectAttributes( &attr, &string, 0, NULL, NULL );
+ if (NtOpenFile( &mountmgr, GENERIC_READ | SYNCHRONIZE, &attr, &io,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT ))
+ return NULL;
+
+ status = NtDeviceIoControlFile( mountmgr, NULL, NULL, NULL, &io, IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE,
+ drive, sizeof(*drive), drive, 1024 );
+ if (status == STATUS_BUFFER_OVERFLOW)
+ {
+ if (!(drive = RtlReAllocateHeap( GetProcessHeap(), 0, drive, drive->size )))
+ {
+ RtlFreeHeap( GetProcessHeap(), 0, drive );
+ NtClose( mountmgr );
+ return NULL;
+ }
+ status = NtDeviceIoControlFile( mountmgr, NULL, NULL, NULL, &io, IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE,
+ drive, sizeof(*drive), drive, drive->size );
+ }
+ NtClose( mountmgr );
+
+ if (status)
+ {
+ WARN("failed to retrieve filesystem type from mountmgr, status %#x\n", status);
+ RtlFreeHeap( GetProcessHeap(), 0, drive );
+ return NULL;
+ }
+
+ return drive;
+}
+
/******************************************************************************
* NtQueryInformationFile [NTDLL.@]
* ZwQueryInformationFile [NTDLL.@]
@@ -2507,8 +2625,15 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
if (fd_get_file_info( fd, options, &st, &attr ) == -1) io->u.Status = FILE_GetNtStatus();
else
{
+ struct mountmgr_unix_drive *drive;
FILE_ID_INFORMATION *info = ptr;
- info->VolumeSerialNumber = 0; /* FIXME */
+
+ info->VolumeSerialNumber = 0;
+ if ((drive = get_mountmgr_fs_info( hFile, fd )))
+ {
+ info->VolumeSerialNumber = drive->serial;
+ RtlFreeHeap( GetProcessHeap(), 0, drive );
+ }
memset( &info->FileId, 0, sizeof(info->FileId) );
*(ULONGLONG *)&info->FileId = st.st_ino;
}
@@ -3120,125 +3245,6 @@ static NTSTATUS get_device_info( int fd, FILE_FS_DEVICE_INFORMATION *info )
return STATUS_SUCCESS;
}
-/* Find a DOS device which can act as the root of "path".
- * Similar to find_drive_root(), but returns -1 instead of crossing volumes. */
-static int find_dos_device( const char *path )
-{
- int len = strlen(path);
- int drive;
- char *buffer;
- struct stat st;
- struct drive_info info[MAX_DOS_DRIVES];
- dev_t dev_id;
-
- if (!DIR_get_drives_info( info )) return -1;
-
- if (stat( path, &st ) < 0) return -1;
- dev_id = st.st_dev;
-
- /* strip off trailing slashes */
- while (len > 1 && path[len - 1] == '/') len--;
-
- /* make a copy of the path */
- if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, len + 1 ))) return -1;
- memcpy( buffer, path, len );
- buffer[len] = 0;
-
- for (;;)
- {
- if (!stat( buffer, &st ) && S_ISDIR( st.st_mode ))
- {
- if (st.st_dev != dev_id) break;
-
- for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
- {
- if ((info[drive].dev == st.st_dev) && (info[drive].ino == st.st_ino))
- {
- if (len == 1) len = 0; /* preserve root slash in returned path */
- TRACE( "%s -> drive %c:, root=%s, name=%s\n",
- debugstr_a(path), 'A' + drive, debugstr_a(buffer), debugstr_a(path + len));
- RtlFreeHeap( GetProcessHeap(), 0, buffer );
- return drive;
- }
- }
- }
- if (len <= 1) break; /* reached root */
- while (path[len - 1] != '/') len--;
- while (path[len - 1] == '/') len--;
- buffer[len] = 0;
- }
- RtlFreeHeap( GetProcessHeap(), 0, buffer );
- return -1;
-}
-
-static struct mountmgr_unix_drive *get_mountmgr_fs_info( HANDLE handle, int fd )
-{
- struct mountmgr_unix_drive *drive;
- OBJECT_ATTRIBUTES attr;
- UNICODE_STRING string;
- ANSI_STRING unix_name;
- IO_STATUS_BLOCK io;
- HANDLE mountmgr;
- NTSTATUS status;
- int letter;
-
- if (server_get_unix_name( handle, &unix_name ))
- return NULL;
-
- letter = find_dos_device( unix_name.Buffer );
- RtlFreeAnsiString( &unix_name );
-
- if (!(drive = RtlAllocateHeap( GetProcessHeap(), 0, 1024 )))
- return NULL;
-
- if (letter == -1)
- {
- struct stat st;
-
- if (fstat( fd, &st ) == -1)
- {
- RtlFreeHeap( GetProcessHeap(), 0, drive );
- return NULL;
- }
-
- drive->unix_dev = st.st_dev;
- drive->letter = 0;
- }
- else
- drive->letter = 'a' + letter;
-
- RtlInitUnicodeString( &string, MOUNTMGR_DEVICE_NAME );
- InitializeObjectAttributes( &attr, &string, 0, NULL, NULL );
- if (NtOpenFile( &mountmgr, GENERIC_READ | SYNCHRONIZE, &attr, &io,
- FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT ))
- return NULL;
-
- status = NtDeviceIoControlFile( mountmgr, NULL, NULL, NULL, &io, IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE,
- drive, sizeof(*drive), drive, 1024 );
- if (status == STATUS_BUFFER_OVERFLOW)
- {
- if (!(drive = RtlReAllocateHeap( GetProcessHeap(), 0, drive, drive->size )))
- {
- RtlFreeHeap( GetProcessHeap(), 0, drive );
- NtClose( mountmgr );
- return NULL;
- }
- status = NtDeviceIoControlFile( mountmgr, NULL, NULL, NULL, &io, IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE,
- drive, sizeof(*drive), drive, drive->size );
- }
- NtClose( mountmgr );
-
- if (status)
- {
- WARN("failed to retrieve filesystem type from mountmgr, status %#x\n", status);
- RtlFreeHeap( GetProcessHeap(), 0, drive );
- return NULL;
- }
-
- return drive;
-}
-
-
/******************************************************************************
* NtQueryVolumeInformationFile [NTDLL.@]
* ZwQueryVolumeInformationFile [NTDLL.@]
--
2.26.0
More information about the wine-devel
mailing list