Commit a6cdfea1 authored by Alex Henrie's avatar Alex Henrie Committed by Alexandre Julliard

mountmgr: Create devices and registry entries for serial ports.

parent 4bf58b6e
......@@ -42,6 +42,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(mountmgr);
#define MAX_DOS_DRIVES 26
#define MAX_PORTS 256
static const WCHAR drive_types[][8] =
{
......@@ -57,6 +58,8 @@ static const WCHAR drive_types[][8] =
static const WCHAR drives_keyW[] = {'S','o','f','t','w','a','r','e','\\',
'W','i','n','e','\\','D','r','i','v','e','s',0};
static const WCHAR ports_keyW[] = {'S','o','f','t','w','a','r','e','\\',
'W','i','n','e','\\','P','o','r','t','s',0};
struct disk_device
{
......@@ -91,6 +94,7 @@ static struct list drives_list = LIST_INIT(drives_list);
static struct list volumes_list = LIST_INIT(volumes_list);
static DRIVER_OBJECT *harddisk_driver;
static DRIVER_OBJECT *serial_driver;
static CRITICAL_SECTION device_section;
static CRITICAL_SECTION_DEBUG critsect_debug =
......@@ -101,16 +105,16 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
};
static CRITICAL_SECTION device_section = { &critsect_debug, -1, 0, 0, 0, 0 };
static char *get_dosdevices_path( char **drive )
static char *get_dosdevices_path( char **device )
{
const char *config_dir = wine_get_config_dir();
size_t len = strlen(config_dir) + sizeof("/dosdevices/a::");
size_t len = strlen(config_dir) + sizeof("/dosdevices/com256");
char *path = HeapAlloc( GetProcessHeap(), 0, len );
if (path)
{
strcpy( path, config_dir );
strcat( path, "/dosdevices/a::" );
*drive = path + len - 4;
*device = path + len - sizeof("com256");
}
return path;
}
......@@ -987,3 +991,148 @@ NTSTATUS WINAPI harddisk_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *pa
return STATUS_SUCCESS;
}
/* create a serial or parallel port */
static BOOL create_port_device( DRIVER_OBJECT *driver, int n, const char *unix_path, const char *dosdevices_path, char *p,
HKEY wine_ports_key, HKEY windows_ports_key )
{
static const WCHAR comW[] = {'C','O','M','%','u',0};
static const WCHAR device_serialW[] = {'\\','D','e','v','i','c','e','\\','S','e','r','i','a','l','%','u',0};
const WCHAR *dos_name_format, *nt_name_format, *reg_value_format;
WCHAR dos_name[7], reg_value[256], nt_buffer[32];
DWORD type, size;
char override_path[256];
UNICODE_STRING nt_name;
DEVICE_OBJECT *dev_obj;
NTSTATUS status;
dos_name_format = comW;
nt_name_format = device_serialW;
reg_value_format = comW;
/* TODO: support parallel ports */
sprintfW( dos_name, dos_name_format, n );
/* check for override */
size = sizeof(reg_value);
if (RegQueryValueExW( wine_ports_key, dos_name, NULL, &type, (BYTE *)reg_value, &size ) == 0 && type == REG_SZ)
{
if (!reg_value[0] || !WideCharToMultiByte( CP_UNIXCP, WC_ERR_INVALID_CHARS, reg_value, size/sizeof(WCHAR),
override_path, sizeof(override_path), NULL, NULL))
return FALSE;
unix_path = override_path;
}
if (!unix_path)
return FALSE;
/* create DOS device */
sprintf( p, "%u", n );
if (symlink( unix_path, dosdevices_path ) != 0)
return FALSE;
/* create NT device */
sprintfW( nt_buffer, nt_name_format, n - 1 );
RtlInitUnicodeString( &nt_name, nt_buffer );
status = IoCreateDevice( driver, 0, &nt_name, 0, 0, FALSE, &dev_obj );
if (status != STATUS_SUCCESS)
{
FIXME( "IoCreateDevice %s got %x\n", debugstr_w(nt_name.Buffer), status );
return FALSE;
}
/* TODO: store information about the Unix device in the NT device */
/* create registry entry */
sprintfW( reg_value, reg_value_format, n );
RegSetValueExW( windows_ports_key, nt_name.Buffer, 0, REG_SZ,
(BYTE *)reg_value, (strlenW( reg_value ) + 1) * sizeof(WCHAR) );
return TRUE;
}
/* find and create serial or parallel ports */
static void create_port_devices( DRIVER_OBJECT *driver )
{
static const char *serial_search_paths[] = {
#ifdef linux
"/dev/ttyS%u",
"/dev/ttyUSB%u",
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
"/dev/cuau%u",
#elif defined(__DragonFly__)
"/dev/cuaa%u",
#else
"",
#endif
};
static const WCHAR serialcomm_keyW[] = {'H','A','R','D','W','A','R','E','\\',
'D','E','V','I','C','E','M','A','P','\\',
'S','E','R','I','A','L','C','O','M','M',0};
const char **search_paths;
const WCHAR *windows_ports_key_name;
char *dosdevices_path, *p;
HKEY wine_ports_key = NULL, windows_ports_key = NULL;
char unix_path[256];
int num_search_paths, i, j, n;
if (!(dosdevices_path = get_dosdevices_path( &p )))
return;
p[0] = 'c';
p[1] = 'o';
p[2] = 'm';
search_paths = serial_search_paths;
num_search_paths = sizeof(serial_search_paths)/sizeof(serial_search_paths[0]);
windows_ports_key_name = serialcomm_keyW;
/* TODO: support parallel ports */
p += 3;
RegOpenKeyExW( HKEY_LOCAL_MACHINE, ports_keyW, 0, KEY_QUERY_VALUE, &wine_ports_key );
RegOpenKeyExW( HKEY_LOCAL_MACHINE, windows_ports_key_name, 0, KEY_SET_VALUE, &windows_ports_key );
/* remove old symlinks */
for (n = 1; n <= MAX_PORTS; n++)
{
sprintf( p, "%u", n );
if (unlink( dosdevices_path ) != 0 && errno == ENOENT)
break;
}
/* look for ports in the usual places */
n = 1;
for (i = 0; i < num_search_paths; i++)
{
for (j = 0; n <= MAX_PORTS; j++)
{
sprintf( unix_path, search_paths[i], j );
if (access( unix_path, F_OK ) != 0)
break;
create_port_device( driver, n, unix_path, dosdevices_path, p, wine_ports_key, windows_ports_key );
n++;
}
}
/* add any extra user-defined serial ports */
while (n <= MAX_PORTS)
{
if (!create_port_device( driver, n, NULL, dosdevices_path, p, wine_ports_key, windows_ports_key ))
break;
n++;
}
RegCloseKey( wine_ports_key );
RegCloseKey( windows_ports_key );
HeapFree( GetProcessHeap(), 0, dosdevices_path );
}
/* driver entry point for the serial port driver */
NTSTATUS WINAPI serial_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
{
serial_driver = driver;
/* TODO: fill in driver->MajorFunction */
create_port_devices( driver );
return STATUS_SUCCESS;
}
......@@ -419,6 +419,7 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
static const WCHAR device_mountmgrW[] = {'\\','D','e','v','i','c','e','\\','M','o','u','n','t','P','o','i','n','t','M','a','n','a','g','e','r',0};
static const WCHAR link_mountmgrW[] = {'\\','?','?','\\','M','o','u','n','t','P','o','i','n','t','M','a','n','a','g','e','r',0};
static const WCHAR harddiskW[] = {'\\','D','r','i','v','e','r','\\','H','a','r','d','d','i','s','k',0};
static const WCHAR driver_serialW[] = {'\\','D','r','i','v','e','r','\\','S','e','r','i','a','l',0};
static const WCHAR devicemapW[] = {'H','A','R','D','W','A','R','E','\\','D','E','V','I','C','E','M','A','P',0};
static const WCHAR parallelW[] = {'P','A','R','A','L','L','E','L',' ','P','O','R','T','S',0};
static const WCHAR serialW[] = {'S','E','R','I','A','L','C','O','M','M',0};
......@@ -463,5 +464,8 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
initialize_dbus();
initialize_diskarbitration();
RtlInitUnicodeString( &nameW, driver_serialW );
IoCreateDriver( &nameW, serial_driver_entry );
return status;
}
......@@ -57,6 +57,7 @@ extern NTSTATUS add_dos_device( int letter, const char *udi, const char *device,
extern NTSTATUS remove_dos_device( int letter, const char *udi ) DECLSPEC_HIDDEN;
extern NTSTATUS query_dos_device( int letter, enum device_type *type, char **device, char **mount_point ) DECLSPEC_HIDDEN;
extern NTSTATUS WINAPI harddisk_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) DECLSPEC_HIDDEN;
extern NTSTATUS WINAPI serial_driver_entry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) DECLSPEC_HIDDEN;
/* mount point functions */
......
......@@ -435,35 +435,6 @@ static void flush_dir_queue(void)
/***********************************************************************
* get_default_com_device
*
* Return the default device to use for serial ports.
*/
static char *get_default_com_device( int num )
{
char *ret = NULL;
if (num < 1 || num > 256) return NULL;
#ifdef linux
ret = RtlAllocateHeap( GetProcessHeap(), 0, sizeof("/dev/ttyS256") );
if (!ret) return NULL;
sprintf( ret, "/dev/ttyS%d", num - 1 );
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
ret = RtlAllocateHeap( GetProcessHeap(), 0, sizeof("/dev/cuau256") );
if (!ret) return NULL;
sprintf( ret, "/dev/cuau%d", num - 1 );
#elif defined(__DragonFly__)
ret = RtlAllocateHeap( GetProcessHeap(), 0, sizeof("/dev/cuaa256") );
if (!ret) return NULL;
sprintf( ret, "/dev/cuaa%d", num - 1 );
#else
FIXME( "no known default for device com%d\n", num );
#endif
return ret;
}
/***********************************************************************
* get_default_lpt_device
*
* Return the default device to use for parallel ports.
......@@ -2505,7 +2476,6 @@ static NTSTATUS get_dos_device( const WCHAR *name, UINT name_len, ANSI_STRING *u
dev[2] = 0; /* remove last ':' to get the drive mount point symlink */
new_name = get_default_drive_device( unix_name );
}
else if (!strncmp( dev, "com", 3 )) new_name = get_default_com_device( atoi(dev + 3 ));
else if (!strncmp( dev, "lpt", 3 )) new_name = get_default_lpt_device( atoi(dev + 3 ));
if (!new_name) break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment