ntdll: Fill the volume serial number in NtQueryInformationFile(FileIdInformation).

Signed-off-by: Zebediah Figura <zfigura@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2020-04-08 16:06:04 -05:00 committed by Alexandre Julliard
parent dab50548e0
commit a14cdc8ba0
1 changed files with 126 additions and 120 deletions

View File

@ -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.@]