mountmgr: Put the Unix helpers in a separate Unix library.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-11-25 19:00:21 +01:00
parent af7b364a28
commit 9d293a1e9b
5 changed files with 201 additions and 65 deletions

View file

@ -1,4 +1,5 @@
MODULE = mountmgr.sys
UNIXLIB = mountmgr.so
IMPORTS = uuid advapi32 ntoskrnl
DELAYIMPORTS = user32
EXTRAINCL = $(DBUS_CFLAGS) $(HAL_CFLAGS)

View file

@ -186,10 +186,11 @@ static void get_filesystem_label( struct volume *volume )
{
char buffer[256], *p;
ULONG size = sizeof(buffer);
struct read_volume_file_params params = { volume->device->unix_mount, ".windows-label", buffer, &size };
volume->label[0] = 0;
if (!volume->device->unix_mount) return;
if (read_volume_file( volume->device->unix_mount, ".windows-label", buffer, &size )) return;
if (MOUNTMGR_CALL( read_volume_file, &params )) return;
p = buffer + size;
while (p > buffer && (p[-1] == ' ' || p[-1] == '\r' || p[-1] == '\n')) p--;
@ -203,10 +204,11 @@ static void get_filesystem_serial( struct volume *volume )
{
char buffer[32];
ULONG size = sizeof(buffer);
struct read_volume_file_params params = { volume->device->unix_mount, ".windows-serial", buffer, &size };
volume->serial = 0;
if (!volume->device->unix_mount) return;
if (read_volume_file( volume->device->unix_mount, ".windows-serial", buffer, &size )) return;
if (MOUNTMGR_CALL( read_volume_file, &params )) return;
buffer[size] = 0;
volume->serial = strtoul( buffer, NULL, 16 );
@ -974,8 +976,9 @@ static void set_dos_devices_disk_serial( struct disk_device *device )
{
unsigned int devices;
struct dos_drive *drive;
struct get_volume_dos_devices_params params = { device->unix_mount, &devices };
if (!device->serial || !device->unix_mount || get_volume_dos_devices( device->unix_mount, &devices ))
if (!device->serial || !device->unix_mount || MOUNTMGR_CALL( get_volume_dos_devices, &params ))
return;
LIST_FOR_EACH_ENTRY( drive, &drives_list, struct dos_drive, entry )
@ -1108,12 +1111,15 @@ static void create_drive_devices(void)
{
char link[4096], unix_dev[4096];
char *device = NULL;
struct get_dosdev_symlink_params params = { dosdev, link, sizeof(link) };
dosdev[0] = 'a' + i;
dosdev[2] = 0;
if (get_dosdev_symlink( dosdev, link, sizeof(link) )) continue;
if (MOUNTMGR_CALL( get_dosdev_symlink, &params )) continue;
dosdev[2] = ':';
if (!get_dosdev_symlink( dosdev, unix_dev, sizeof(unix_dev) )) device = unix_dev;
params.dest = unix_dev;
params.size = sizeof(unix_dev);
if (!MOUNTMGR_CALL( get_dosdev_symlink, &params )) device = unix_dev;
drive_type = i < 2 ? DEVICE_FLOPPY : DEVICE_HARDDISK_VOL;
if (drives_key)
@ -1310,7 +1316,8 @@ NTSTATUS add_dos_device( int letter, const char *udi, const char *device,
if (letter == -1) /* auto-assign a letter */
{
if ((status = add_drive( device, type, &letter ))) goto done;
struct add_drive_params params = { device, type, &letter };
if ((status = MOUNTMGR_CALL( add_drive, &params ))) goto done;
LIST_FOR_EACH_ENTRY_SAFE( drive, next, &drives_list, struct dos_drive, entry )
{
@ -1320,16 +1327,21 @@ NTSTATUS add_dos_device( int letter, const char *udi, const char *device,
}
else /* simply reset the device symlink */
{
struct set_dosdev_symlink_params params = { dosdev, device };
LIST_FOR_EACH_ENTRY( drive, &drives_list, struct dos_drive, entry )
if (drive->drive == letter) break;
dosdev[0] = 'a' + letter;
if (&drive->entry == &drives_list) set_dosdev_symlink( dosdev, device );
if (&drive->entry == &drives_list)
{
MOUNTMGR_CALL( set_dosdev_symlink, &params );
}
else
{
if (!device || !drive->volume->device->unix_device ||
strcmp( device, drive->volume->device->unix_device ))
set_dosdev_symlink( dosdev, device );
MOUNTMGR_CALL( set_dosdev_symlink, &params );
delete_dos_device( drive );
}
}
@ -1343,7 +1355,10 @@ found:
dosdev[0] = 'a' + drive->drive;
dosdev[2] = 0;
if (!mount_point || !volume->device->unix_mount || strcmp( mount_point, volume->device->unix_mount ))
set_dosdev_symlink( dosdev, mount_point );
{
struct set_dosdev_symlink_params params = { dosdev, mount_point };
MOUNTMGR_CALL( set_dosdev_symlink, &params );
}
set_volume_info( volume, drive, device, mount_point, type, guid, NULL );
TRACE( "added device %c: udi %s for %s on %s type %u\n",
@ -1388,6 +1403,8 @@ NTSTATUS remove_dos_device( int letter, const char *udi )
EnterCriticalSection( &device_section );
LIST_FOR_EACH_ENTRY( drive, &drives_list, struct dos_drive, entry )
{
struct set_dosdev_symlink_params params = { dosdev, NULL };
if (udi)
{
if (!drive->volume->udi) continue;
@ -1397,7 +1414,7 @@ NTSTATUS remove_dos_device( int letter, const char *udi )
else if (drive->drive != letter) continue;
dosdev[0] = 'a' + drive->drive;
set_dosdev_symlink( dosdev, NULL );
MOUNTMGR_CALL( set_dosdev_symlink, &params );
/* clear the registry key too */
if (!RegOpenKeyW( HKEY_LOCAL_MACHINE, drives_keyW, &hkey ))
@ -1455,7 +1472,8 @@ static struct volume *find_volume_by_unixdev( ULONGLONG unix_dev )
LIST_FOR_EACH_ENTRY( volume, &volumes_list, struct volume, entry )
{
if (!volume->device->unix_device || !match_unixdev( volume->device->unix_device, unix_dev ))
struct match_unixdev_params params = { volume->device->unix_device, unix_dev };
if (!volume->device->unix_device || !MOUNTMGR_CALL( match_unixdev, &params ))
continue;
TRACE( "found matching volume %s\n", debugstr_guid(&volume->guid) );
@ -1875,6 +1893,10 @@ static BOOL create_port_device( DRIVER_OBJECT *driver, int n, const char *unix_p
UNICODE_STRING nt_name, symlink_name, default_name;
DEVICE_OBJECT *dev_obj;
NTSTATUS status;
struct set_dosdev_symlink_params params = { dosdevices_path, unix_path };
/* create DOS device */
if (MOUNTMGR_CALL( set_dosdev_symlink, &params )) return FALSE;
if (driver == serial_driver)
{
@ -1895,9 +1917,6 @@ static BOOL create_port_device( DRIVER_OBJECT *driver, int n, const char *unix_p
sprintfW( dos_name, dos_name_format, n );
/* create DOS device */
if (set_dosdev_symlink( dosdevices_path, unix_path )) return FALSE;
/* create NT device */
sprintfW( nt_buffer, nt_name_format, n - 1 );
RtlInitUnicodeString( &nt_name, nt_buffer );
@ -2012,11 +2031,12 @@ static void create_port_devices( DRIVER_OBJECT *driver, const char *devices )
NTSTATUS WINAPI serial_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
{
char devices[4096];
struct detect_ports_params params = { devices, sizeof(devices) };
serial_driver = driver;
/* TODO: fill in driver->MajorFunction */
detect_serial_ports( devices, sizeof(devices) );
MOUNTMGR_CALL( detect_serial_ports, &params );
create_port_devices( driver, devices );
return STATUS_SUCCESS;
@ -2026,11 +2046,12 @@ NTSTATUS WINAPI serial_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path
NTSTATUS WINAPI parallel_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
{
char devices[4096];
struct detect_ports_params params = { devices, sizeof(devices) };
parallel_driver = driver;
/* TODO: fill in driver->MajorFunction */
detect_parallel_ports( devices, sizeof(devices) );
MOUNTMGR_CALL( detect_parallel_ports, &params );
create_port_devices( driver, devices );
return STATUS_SUCCESS;

View file

@ -50,6 +50,8 @@ struct mount_point
static struct list mount_points_list = LIST_INIT(mount_points_list);
static HKEY mount_key;
unixlib_handle_t mountmgr_handle = 0;
void set_mount_point_id( struct mount_point *mount, const void *id, unsigned int id_len )
{
RtlFreeHeap( GetProcessHeap(), 0, mount->id );
@ -286,6 +288,7 @@ static NTSTATUS define_shell_folder( const void *in_buff, SIZE_T insize )
NTSTATUS status;
ULONG size = 256;
char *buffer = NULL, *backup = NULL;
struct set_shell_folder_params params;
if (input->folder_offset >= insize || input->folder_size > insize - input->folder_offset ||
input->symlink_offset >= insize)
@ -328,7 +331,10 @@ static NTSTATUS define_shell_folder( const void *in_buff, SIZE_T insize )
strcat( backup, ".backup" );
}
status = set_shell_folder( buffer, backup, link );
params.folder = buffer;
params.backup = backup;
params.link = link;
status = MOUNTMGR_CALL( set_shell_folder, &params );
done:
HeapFree( GetProcessHeap(), 0, buffer );
@ -354,14 +360,17 @@ static NTSTATUS query_shell_folder( void *buff, SIZE_T insize, SIZE_T outsize, I
{
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size ))) return STATUS_NO_MEMORY;
status = wine_nt_to_unix_file_name( &attr, buffer, &size, FILE_OPEN );
if (!status) break;
if (!status)
{
struct get_shell_folder_params params = { buffer, output, outsize };
status = MOUNTMGR_CALL( get_shell_folder, &params );
if (!status) iosb->Information = strlen(output) + 1;
break;
}
if (status != STATUS_BUFFER_TOO_SMALL) break;
HeapFree( GetProcessHeap(), 0, buffer );
if (status != STATUS_BUFFER_TOO_SMALL) return status;
}
status = get_shell_folder( buffer, output, outsize );
if (!status) iosb->Information = strlen(output) + 1;
HeapFree( GetProcessHeap(), 0, buffer );
return status;
}
@ -593,6 +602,7 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
HKEY wow64_ports_key = NULL;
#endif
void *instance;
UNICODE_STRING nameW, linkW;
DEVICE_OBJECT *device;
HKEY devicemap_key;
@ -600,6 +610,11 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
TRACE( "%s\n", debugstr_w(path->Buffer) );
RtlPcToFileHeader( DriverEntry, &instance );
status = NtQueryVirtualMemory( GetCurrentProcess(), instance, MemoryWineUnixFuncs,
&mountmgr_handle, sizeof(mountmgr_handle), NULL );
if (status) return status;
driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = mountmgr_ioctl;
RtlInitUnicodeString( &nameW, device_mountmgrW );

View file

@ -18,6 +18,10 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#if 0
#pragma makedep unix
#endif
#include "config.h"
#include <errno.h>
@ -84,21 +88,22 @@ static void detect_devices( const char **paths, char *names, ULONG size )
}
/* find or create a DOS drive for the corresponding Unix device */
NTSTATUS add_drive( const char *device, enum device_type type, int *letter )
static NTSTATUS add_drive( void *args )
{
const struct add_drive_params *params = args;
char *path, *p;
char in_use[26];
struct stat dev_st, drive_st;
int drive, first, last, avail = 0;
if (stat( device, &dev_st ) == -1 || !is_valid_device( &dev_st )) return STATUS_NO_SUCH_DEVICE;
if (stat( params->device, &dev_st ) == -1 || !is_valid_device( &dev_st )) return STATUS_NO_SUCH_DEVICE;
if (!(path = get_dosdevices_path( "a::" ))) return STATUS_NO_MEMORY;
p = path + strlen(path) - 3;
memset( in_use, 0, sizeof(in_use) );
switch (type)
switch (params->type)
{
case DEVICE_FLOPPY:
first = 0;
@ -148,7 +153,7 @@ NTSTATUS add_drive( const char *device, enum device_type type, int *letter )
/* try to use the one we found */
drive = avail;
*p = 'a' + drive;
if (symlink( device, path ) != -1) goto done;
if (symlink( params->device, path ) != -1) goto done;
/* failed, retry the search */
}
}
@ -157,36 +162,38 @@ NTSTATUS add_drive( const char *device, enum device_type type, int *letter )
done:
free( path );
*letter = drive;
*params->letter = drive;
return STATUS_SUCCESS;
}
NTSTATUS get_dosdev_symlink( const char *dev, char *buffer, ULONG size )
static NTSTATUS get_dosdev_symlink( void *args )
{
const struct get_dosdev_symlink_params *params = args;
char *path;
int ret;
if (!(path = get_dosdevices_path( dev ))) return STATUS_NO_MEMORY;
if (!(path = get_dosdevices_path( params->dev ))) return STATUS_NO_MEMORY;
ret = readlink( path, buffer, size );
ret = readlink( path, params->dest, params->size );
free( path );
if (ret == -1) return STATUS_NO_SUCH_DEVICE;
if (ret == size) return STATUS_BUFFER_TOO_SMALL;
buffer[ret] = 0;
if (ret == params->size) return STATUS_BUFFER_TOO_SMALL;
params->dest[ret] = 0;
return STATUS_SUCCESS;
}
NTSTATUS set_dosdev_symlink( const char *dev, const char *dest )
static NTSTATUS set_dosdev_symlink( void *args )
{
const struct set_dosdev_symlink_params *params = args;
char *path;
NTSTATUS status = STATUS_SUCCESS;
if (!(path = get_dosdevices_path( dev ))) return STATUS_NO_MEMORY;
if (!(path = get_dosdevices_path( params->dev ))) return STATUS_NO_MEMORY;
if (dest && dest[0])
if (params->dest && params->dest[0])
{
unlink( path );
if (symlink( dest, path ) == -1) status = STATUS_ACCESS_DENIED;
if (symlink( params->dest, path ) == -1) status = STATUS_ACCESS_DENIED;
}
else unlink( path );
@ -194,31 +201,33 @@ NTSTATUS set_dosdev_symlink( const char *dev, const char *dest )
return status;
}
NTSTATUS get_volume_dos_devices( const char *mount_point, unsigned int *dosdev )
static NTSTATUS get_volume_dos_devices( void *args )
{
const struct get_volume_dos_devices_params *params = args;
struct stat dev_st, drive_st;
char *path;
int i;
if (stat( mount_point, &dev_st ) == -1) return STATUS_NO_SUCH_DEVICE;
if (stat( params->mount_point, &dev_st ) == -1) return STATUS_NO_SUCH_DEVICE;
if (!(path = get_dosdevices_path( "a:" ))) return STATUS_NO_MEMORY;
*dosdev = 0;
*params->dosdev = 0;
for (i = 0; i < 26; i++)
{
path[strlen(path) - 2] = 'a' + i;
if (stat( path, &drive_st ) != -1 && drive_st.st_rdev == dev_st.st_rdev) *dosdev |= 1 << i;
if (stat( path, &drive_st ) != -1 && drive_st.st_rdev == dev_st.st_rdev) *params->dosdev |= 1 << i;
}
free( path );
return STATUS_SUCCESS;
}
NTSTATUS read_volume_file( const char *volume, const char *file, void *buffer, ULONG *size )
static NTSTATUS read_volume_file( void *args )
{
const struct read_volume_file_params *params = args;
int ret, fd = -1;
char *name = malloc( strlen(volume) + strlen(file) + 2 );
char *name = malloc( strlen(params->volume) + strlen(params->file) + 2 );
sprintf( name, "%s/%s", volume, file );
sprintf( name, "%s/%s", params->volume, params->file );
if (name[0] != '/')
{
@ -230,22 +239,24 @@ NTSTATUS read_volume_file( const char *volume, const char *file, void *buffer, U
free( name );
if (fd == -1) return STATUS_NO_SUCH_FILE;
ret = read( fd, buffer, *size );
ret = read( fd, params->buffer, *params->size );
close( fd );
if (ret == -1) return STATUS_NO_SUCH_FILE;
*size = ret;
*params->size = ret;
return STATUS_SUCCESS;
}
BOOL match_unixdev( const char *device, ULONGLONG unix_dev )
static NTSTATUS match_unixdev( void *args )
{
const struct match_unixdev_params *params = args;
struct stat st;
return !stat( device, &st ) && st.st_rdev == unix_dev;
return !stat( params->device, &st ) && st.st_rdev == params->unix_dev;
}
NTSTATUS detect_serial_ports( char *names, ULONG size )
static NTSTATUS detect_serial_ports( void *args )
{
const struct detect_ports_params *params = args;
static const char *paths[] =
{
#ifdef linux
@ -260,12 +271,13 @@ NTSTATUS detect_serial_ports( char *names, ULONG size )
NULL
};
detect_devices( paths, names, size );
detect_devices( paths, params->names, params->size );
return STATUS_SUCCESS;
}
NTSTATUS detect_parallel_ports( char *names, ULONG size )
static NTSTATUS detect_parallel_ports( void *args )
{
const struct detect_ports_params *params = args;
static const char *paths[] =
{
#ifdef linux
@ -274,12 +286,16 @@ NTSTATUS detect_parallel_ports( char *names, ULONG size )
NULL
};
detect_devices( paths, names, size );
detect_devices( paths, params->names, params->size );
return STATUS_SUCCESS;
}
NTSTATUS set_shell_folder( const char *folder, const char *backup, const char *link )
static NTSTATUS set_shell_folder( void *args )
{
const struct set_shell_folder_params *params = args;
const char *folder = params->folder;
const char *backup = params->backup;
const char *link = params->link;
struct stat st;
const char *home;
char *homelink = NULL;
@ -333,11 +349,26 @@ done:
return status;
}
NTSTATUS get_shell_folder( const char *folder, char *buffer, ULONG size )
static NTSTATUS get_shell_folder( void *args )
{
int ret = readlink( folder, buffer, size - 1 );
const struct get_shell_folder_params *params = args;
int ret = readlink( params->folder, params->buffer, params->size - 1 );
if (ret < 0) return STATUS_OBJECT_NAME_NOT_FOUND;
buffer[ret] = 0;
params->buffer[ret] = 0;
return STATUS_SUCCESS;
}
const unixlib_entry_t __wine_unix_call_funcs[] =
{
add_drive,
get_dosdev_symlink,
set_dosdev_symlink,
get_volume_dos_devices,
read_volume_file,
match_unixdev,
detect_serial_ports,
detect_parallel_ports,
set_shell_folder,
get_shell_folder,
};

View file

@ -19,17 +19,85 @@
*/
#include "mountmgr.h"
#include "wine/unixlib.h"
extern NTSTATUS add_drive( const char *device, enum device_type type, int *letter ) DECLSPEC_HIDDEN;
extern NTSTATUS get_dosdev_symlink( const char *dev, char *dest, ULONG size ) DECLSPEC_HIDDEN;
extern NTSTATUS set_dosdev_symlink( const char *dev, const char *dest ) DECLSPEC_HIDDEN;
extern NTSTATUS get_volume_dos_devices( const char *mount_point, unsigned int *dosdev ) DECLSPEC_HIDDEN;
extern NTSTATUS read_volume_file( const char *volume, const char *file, void *buffer, ULONG *size ) DECLSPEC_HIDDEN;
extern BOOL match_unixdev( const char *device, ULONGLONG unix_dev ) DECLSPEC_HIDDEN;
extern NTSTATUS detect_serial_ports( char *names, ULONG size ) DECLSPEC_HIDDEN;
extern NTSTATUS detect_parallel_ports( char *names, ULONG size ) DECLSPEC_HIDDEN;
extern NTSTATUS set_shell_folder( const char *folder, const char *backup, const char *link ) DECLSPEC_HIDDEN;
extern NTSTATUS get_shell_folder( const char *folder, char *buffer, ULONG size ) DECLSPEC_HIDDEN;
struct add_drive_params
{
const char *device;
enum device_type type;
int *letter;
};
struct get_dosdev_symlink_params
{
const char *dev;
char *dest;
ULONG size;
};
struct set_dosdev_symlink_params
{
const char *dev;
const char *dest;
};
struct get_volume_dos_devices_params
{
const char *mount_point;
unsigned int *dosdev;
};
struct read_volume_file_params
{
const char *volume;
const char *file;
void *buffer;
ULONG *size;
};
struct match_unixdev_params
{
const char *device;
ULONGLONG unix_dev;
};
struct detect_ports_params
{
char *names;
ULONG size;
};
struct set_shell_folder_params
{
const char *folder;
const char *backup;
const char *link;
};
struct get_shell_folder_params
{
const char *folder;
char *buffer;
ULONG size;
};
enum mountmgr_funcs
{
unix_add_drive,
unix_get_dosdev_symlink,
unix_set_dosdev_symlink,
unix_get_volume_dos_devices,
unix_read_volume_file,
unix_match_unixdev,
unix_detect_serial_ports,
unix_detect_parallel_ports,
unix_set_shell_folder,
unix_get_shell_folder,
};
extern unixlib_handle_t mountmgr_handle;
#define MOUNTMGR_CALL( func, params ) __wine_unix_call( mountmgr_handle, unix_ ## func, params )
extern NTSTATUS query_symbol_file( void *buff, ULONG insize, ULONG outsize, ULONG *info ) DECLSPEC_HIDDEN;
extern NTSTATUS read_credential( void *buff, ULONG insize, ULONG outsize, ULONG *info ) DECLSPEC_HIDDEN;