Example #1
0
/* create a new dos drive */
NTSTATUS add_dos_device( int letter, const char *udi, const char *device,
                         const char *mount_point, enum device_type type, const GUID *guid )
{
    char *path, *p;
    HKEY hkey;
    NTSTATUS status = STATUS_SUCCESS;
    struct dos_drive *drive, *next;
    struct volume *volume;
    int notify = -1;

    if (!(path = get_dosdevices_path( &p ))) return STATUS_NO_MEMORY;

    EnterCriticalSection( &device_section );
    volume = find_matching_volume( udi, device, mount_point, type );

    if (letter == -1)  /* auto-assign a letter */
    {
        letter = add_drive( device, type );
        if (letter == -1)
        {
            status = STATUS_OBJECT_NAME_COLLISION;
            goto done;
        }

        LIST_FOR_EACH_ENTRY_SAFE( drive, next, &drives_list, struct dos_drive, entry )
        {
            if (drive->volume->udi && !strcmp( udi, drive->volume->udi )) goto found;
            if (drive->drive == letter) delete_dos_device( drive );
        }
    }
Example #2
0
static BOOL set_unix_mount_point( struct dos_drive *drive, const char *mount_point )
{
    char *path, *p;
    BOOL modified = FALSE;

    if (!(path = get_dosdevices_path( &p ))) return FALSE;
    p[0] = 'a' + drive->drive;
    p[2] = 0;

    if (mount_point && mount_point[0])
    {
        /* try to avoid unlinking if already set correctly */
        if (!drive->unix_mount || strcmp( drive->unix_mount, mount_point ))
        {
            unlink( path );
            symlink( mount_point, path );
            modified = TRUE;
        }
        RtlFreeHeap( GetProcessHeap(), 0, drive->unix_mount );
        drive->unix_mount = strdupA( mount_point );
        if (drive->dosdev) set_mount_point_id( drive->dosdev, mount_point, strlen(mount_point) + 1 );
        if (drive->volume) set_mount_point_id( drive->volume, mount_point, strlen(mount_point) + 1 );
    }
    else
    {
        if (unlink( path ) != -1) modified = TRUE;
        RtlFreeHeap( GetProcessHeap(), 0, drive->unix_mount );
        drive->unix_mount = NULL;
        if (drive->dosdev) set_mount_point_id( drive->dosdev, NULL, 0 );
        if (drive->volume) set_mount_point_id( drive->volume, NULL, 0 );
    }

    HeapFree( GetProcessHeap(), 0, path );
    return modified;
}
Example #3
0
static void set_mount_point( struct dos_drive *drive, const char *mount_point )
{
    char *path, *p;
    struct stat path_st, mnt_st;

    if (drive->drive == -1) return;
    if (!(path = get_dosdevices_path())) return;
    p = path + strlen(path) - 3;
    *p = 'a' + drive->drive;
    p[2] = 0;

    if (mount_point[0])
    {
        /* try to avoid unlinking if already set correctly */
        if (stat( path, &path_st ) == -1 || stat( mount_point, &mnt_st ) == -1 ||
            path_st.st_dev != mnt_st.st_dev || path_st.st_ino != mnt_st.st_ino)
        {
            unlink( path );
            symlink( mount_point, path );
        }
    }
    else unlink( path );

    HeapFree( GetProcessHeap(), 0, path );
}
Example #4
0
/* create devices for mapped drives */
static void create_drive_devices(void)
{
    char *path, *p, *link, *device;
    struct dos_drive *drive;
    struct volume *volume;
    unsigned int i;
    HKEY drives_key;
    enum device_type drive_type;
    WCHAR driveW[] = {'a',':',0};

    if (!(path = get_dosdevices_path( &p ))) return;
    if (RegOpenKeyW( HKEY_LOCAL_MACHINE, drives_keyW, &drives_key )) drives_key = 0;

    for (i = 0; i < MAX_DOS_DRIVES; i++)
    {
        p[0] = 'a' + i;
        p[2] = 0;
        if (!(link = read_symlink( path ))) continue;
        p[2] = ':';
        device = read_symlink( path );

        drive_type = i < 2 ? DEVICE_FLOPPY : DEVICE_HARDDISK_VOL;
        if (drives_key)
        {
            WCHAR buffer[32];
            DWORD j, type, size = sizeof(buffer);

            driveW[0] = 'a' + i;
            if (!RegQueryValueExW( drives_key, driveW, NULL, &type, (BYTE *)buffer, &size ) &&
                type == REG_SZ)
            {
                for (j = 0; j < sizeof(drive_types)/sizeof(drive_types[0]); j++)
                    if (drive_types[j][0] && !strcmpiW( buffer, drive_types[j] ))
                    {
                        drive_type = j;
                        break;
                    }
                if (drive_type == DEVICE_FLOPPY && i >= 2) drive_type = DEVICE_HARDDISK;
            }
        }

        volume = find_matching_volume( NULL, device, link, drive_type );
        if (!create_dos_device( volume, NULL, i, drive_type, &drive ))
        {
            /* don't reset uuid if we used an existing volume */
            const GUID *guid = volume ? NULL : get_default_uuid(i);
            set_volume_info( drive->volume, drive, device, link, drive_type, guid );
        }
        else
        {
            RtlFreeHeap( GetProcessHeap(), 0, link );
            RtlFreeHeap( GetProcessHeap(), 0, device );
        }
        if (volume) release_volume( volume );
    }
    RegCloseKey( drives_key );
    RtlFreeHeap( GetProcessHeap(), 0, path );
}
Example #5
0
/* create devices for mapped drives */
static void create_drive_devices(void)
{
    char *path, *p, *link, *device;
    struct dos_drive *drive;
    unsigned int i;
    HKEY drives_key;
    enum device_type drive_type;
    WCHAR driveW[] = {'a',':',0};

    if (!(path = get_dosdevices_path( &p ))) return;
    if (RegOpenKeyW( HKEY_LOCAL_MACHINE, drives_keyW, &drives_key )) drives_key = 0;

    for (i = 0; i < MAX_DOS_DRIVES; i++)
    {
        p[0] = 'a' + i;
        p[2] = 0;
        if (!(link = read_symlink( path ))) continue;
        p[2] = ':';
        device = read_symlink( path );

        drive_type = i < 2 ? DEVICE_FLOPPY : DEVICE_HARDDISK_VOL;
        if (drives_key)
        {
            WCHAR buffer[32];
            DWORD j, type, size = sizeof(buffer);

            driveW[0] = 'a' + i;
            if (!RegQueryValueExW( drives_key, driveW, NULL, &type, (BYTE *)buffer, &size ) &&
                type == REG_SZ)
            {
                for (j = 0; j < sizeof(drive_types)/sizeof(drive_types[0]); j++)
                    if (drive_types[j][0] && !strcmpiW( buffer, drive_types[j] ))
                    {
                        drive_type = j;
                        break;
                    }
                if (drive_type == DEVICE_FLOPPY && i >= 2) drive_type = DEVICE_HARDDISK;
            }
        }

        if (!create_disk_device( NULL, drive_type, &drive ))
        {
            drive->unix_mount = link;
            drive->unix_device = device;
            set_drive_letter( drive, i );
        }
        else
        {
            RtlFreeHeap( GetProcessHeap(), 0, link );
            RtlFreeHeap( GetProcessHeap(), 0, device );
        }
    }
    RegCloseKey( drives_key );
    RtlFreeHeap( GetProcessHeap(), 0, path );
}
Example #6
0
/* find or create a DOS drive for the corresponding device */
static int add_drive( const char *device, enum device_type type )
{
    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 -1;

    if (!(path = get_dosdevices_path( &p ))) return -1;

    memset( in_use, 0, sizeof(in_use) );

    switch (type)
    {
    case DEVICE_FLOPPY:
        first = 0;
        last = 2;
        break;
    case DEVICE_CDROM:
    case DEVICE_DVD:
        first = 3;
        last = 26;
        break;
    default:
        first = 2;
        last = 26;
        break;
    }

    while (avail != -1)
    {
        avail = -1;
        for (drive = first; drive < last; drive++)
        {
            if (in_use[drive]) continue;  /* already checked */
            *p = 'a' + drive;
            if (stat( path, &drive_st ) == -1)
            {
                if (lstat( path, &drive_st ) == -1 && errno == ENOENT)  /* this is a candidate */
                {
                    if (avail == -1)
                    {
                        p[2] = 0;
                        /* if mount point symlink doesn't exist either, it's available */
                        if (lstat( path, &drive_st ) == -1 && errno == ENOENT) avail = drive;
                        p[2] = ':';
                    }
                }
                else in_use[drive] = 1;
            }
            else
            {
                in_use[drive] = 1;
                if (!is_valid_device( &drive_st )) continue;
                if (dev_st.st_rdev == drive_st.st_rdev) goto done;
            }
        }
        if (avail != -1)
        {
            /* try to use the one we found */
            drive = avail;
            *p = 'a' + drive;
            if (symlink( device, path ) != -1) goto done;
            /* failed, retry the search */
        }
    }
    drive = -1;

done:
    HeapFree( GetProcessHeap(), 0, path );
    return drive;
}
Example #7
0
/* create a new dos drive */
NTSTATUS add_dos_device( int letter, const char *udi, const char *device,
                         const char *mount_point, enum device_type type )
{
    struct dos_drive *drive, *next;

    if (letter == -1)  /* auto-assign a letter */
    {
        letter = add_drive( device, type );
        if (letter == -1) return STATUS_OBJECT_NAME_COLLISION;
    }
    else  /* simply reset the device symlink */
    {
        char *path, *p;

        if (!(path = get_dosdevices_path( &p ))) return STATUS_NO_MEMORY;
        *p = 'a' + letter;
        unlink( path );
        if (device) symlink( device, path );
    }

    LIST_FOR_EACH_ENTRY_SAFE( drive, next, &drives_list, struct dos_drive, entry )
    {
        if (udi && drive->udi && !strcmp( udi, drive->udi ))
        {
            if (type == drive->type) goto found;
            delete_disk_device( drive );
            continue;
        }
        if (drive->drive == letter) delete_disk_device( drive );
    }

    if (create_disk_device( udi, type, &drive )) return STATUS_NO_MEMORY;

found:
    RtlFreeHeap( GetProcessHeap(), 0, drive->unix_device );
    drive->unix_device = strdupA( device );
    set_drive_letter( drive, letter );
    set_unix_mount_point( drive, mount_point );

    if (drive->drive != -1)
    {
        HKEY hkey;

        TRACE( "added device %c: udi %s for %s on %s type %u\n",
                    'a' + drive->drive, wine_dbgstr_a(udi), wine_dbgstr_a(device),
                    wine_dbgstr_a(mount_point), type );

        /* hack: force the drive type in the registry */
        if (!RegCreateKeyW( HKEY_LOCAL_MACHINE, drives_keyW, &hkey ))
        {
            const WCHAR *type_name = drive_types[type];
            WCHAR name[3] = {'a',':',0};

            name[0] += drive->drive;
            if (!type_name[0] && type == DEVICE_HARDDISK) type_name = drive_types[DEVICE_FLOPPY];
            if (type_name[0])
                RegSetValueExW( hkey, name, 0, REG_SZ, (const BYTE *)type_name,
                                (strlenW(type_name) + 1) * sizeof(WCHAR) );
            else
                RegDeleteValueW( hkey, name );
            RegCloseKey( hkey );
        }

        if (udi) send_notify( drive->drive, DBT_DEVICEARRIVAL );
    }
    return STATUS_SUCCESS;
}
Example #8
0
/* find or create a DOS drive for the corresponding device */
static int add_drive( const char *device, const char *type )
{
    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 || !S_ISBLK( dev_st.st_mode )) return -1;

    if (!(path = get_dosdevices_path())) return -1;
    p = path + strlen(path) - 3;

    memset( in_use, 0, sizeof(in_use) );

    first = 2;
    last = 26;
    if (type && !strcmp( type, "floppy" ))
    {
        first = 0;
        last = 2;
    }

    while (avail != -1)
    {
        avail = -1;
        for (drive = first; drive < last; drive++)
        {
            if (in_use[drive]) continue;  /* already checked */
            *p = 'a' + drive;
            if (stat( path, &drive_st ) == -1)
            {
                if (lstat( path, &drive_st ) == -1 && errno == ENOENT)  /* this is a candidate */
                {
                    if (avail == -1)
                    {
                        p[2] = 0;
                        /* if mount point symlink doesn't exist either, it's available */
                        if (lstat( path, &drive_st ) == -1 && errno == ENOENT) avail = drive;
                        p[2] = ':';
                    }
                }
                else in_use[drive] = 1;
            }
            else
            {
                in_use[drive] = 1;
                if (!S_ISBLK( drive_st.st_mode )) continue;
                if (dev_st.st_rdev == drive_st.st_rdev) goto done;
            }
        }
        if (avail != -1)
        {
            /* try to use the one we found */
            drive = avail;
            *p = 'a' + drive;
            if (symlink( device, path ) != -1) goto done;
            /* failed, retry the search */
        }
    }
    drive = -1;

done:
    HeapFree( GetProcessHeap(), 0, path );
    return drive;
}