2003-08-30 02:49:00 +02:00
/*
* Drive management UI code
*
* Copyright 2003 Mark Westcott
* Copyright 2003 Mike Hearn
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
*/
2003-09-06 01:08:26 +02:00
# include <assert.h>
# include <stdarg.h>
2003-08-30 02:49:00 +02:00
# include <stdlib.h>
# include <stdio.h>
2003-09-06 01:08:26 +02:00
# include <string.h>
# include <windef.h>
# include <winbase.h>
# include <winreg.h>
# include <wine/debug.h>
2003-08-30 02:49:00 +02:00
# include <shellapi.h>
2003-09-06 01:08:26 +02:00
# include <objbase.h>
2003-08-30 02:49:00 +02:00
# include <shlguid.h>
# include <shlwapi.h>
# include <shlobj.h>
# include "winecfg.h"
# include "resource.h"
WINE_DEFAULT_DEBUG_CHANNEL ( winecfg ) ;
2003-09-08 21:29:28 +02:00
static BOOL updatingUI = FALSE ;
static char editWindowLetter ; /* drive letter of the drive we are currently editing */
2003-09-18 00:40:38 +02:00
static int lastSel = 0 ; /* the last drive selected in the property sheet */
2003-08-30 02:49:00 +02:00
2003-09-08 21:29:28 +02:00
/* returns NULL on failure. caller is responsible for freeing result */
2003-10-09 06:39:01 +02:00
char * getDriveValue ( char letter , const char * valueName ) {
2003-09-08 21:29:28 +02:00
HKEY hkDrive = 0 ;
char * subKeyName ;
char * result = NULL ;
HRESULT hr ;
DWORD bufferSize ;
WINE_TRACE ( " letter=%c, valueName=%s \n " , letter , valueName ) ;
2003-08-30 02:49:00 +02:00
2003-09-10 05:41:44 +02:00
subKeyName = malloc ( strlen ( " Drive X " ) + 1 ) ;
2003-09-08 21:29:28 +02:00
sprintf ( subKeyName , " Drive %c " , letter ) ;
2003-08-30 02:49:00 +02:00
2003-09-08 21:29:28 +02:00
hr = RegOpenKeyEx ( configKey , subKeyName , 0 , KEY_READ , & hkDrive ) ;
if ( hr ! = ERROR_SUCCESS ) goto end ;
2003-08-30 02:49:00 +02:00
2003-09-08 21:29:28 +02:00
hr = RegQueryValueEx ( hkDrive , valueName , NULL , NULL , NULL , & bufferSize ) ;
if ( hr ! = ERROR_SUCCESS ) goto end ;
2003-08-30 02:49:00 +02:00
2003-09-08 21:29:28 +02:00
result = malloc ( bufferSize ) ;
hr = RegQueryValueEx ( hkDrive , valueName , NULL , NULL , result , & bufferSize ) ;
if ( hr ! = ERROR_SUCCESS ) goto end ;
end :
if ( hkDrive ) RegCloseKey ( hkDrive ) ;
free ( subKeyName ) ;
return result ;
2003-08-30 02:49:00 +02:00
}
2003-09-18 00:40:38 +02:00
/* call with newValue == NULL to remove a value */
2003-10-09 06:39:01 +02:00
void setDriveValue ( char letter , const char * valueName , const char * newValue ) {
2003-09-10 05:41:44 +02:00
char * driveSection = malloc ( strlen ( " Drive X " ) + 1 ) ;
sprintf ( driveSection , " Drive %c " , letter ) ;
2003-09-18 00:40:38 +02:00
if ( newValue )
addTransaction ( driveSection , valueName , ACTION_SET , newValue ) ;
else
addTransaction ( driveSection , valueName , ACTION_REMOVE , NULL ) ;
2003-09-10 05:41:44 +02:00
free ( driveSection ) ;
}
2003-09-18 00:40:38 +02:00
/* copies a drive configuration branch */
void copyDrive ( char srcLetter , char destLetter ) {
char * driveSection = alloca ( strlen ( " Drive X " ) + 1 ) ;
char * path , * label , * type , * serial , * fs ;
WINE_TRACE ( " srcLetter=%c, destLetter=%c \n " , srcLetter , destLetter ) ;
sprintf ( driveSection , " Drive %c " , srcLetter ) ;
path = getDriveValue ( srcLetter , " Path " ) ;
label = getDriveValue ( srcLetter , " Label " ) ;
type = getDriveValue ( srcLetter , " Type " ) ;
serial = getDriveValue ( srcLetter , " Serial " ) ;
fs = getDriveValue ( srcLetter , " FileSystem " ) ;
sprintf ( driveSection , " Drive %c " , destLetter ) ;
if ( path ) addTransaction ( driveSection , " Path " , ACTION_SET , path ) ;
if ( label ) addTransaction ( driveSection , " Label " , ACTION_SET , label ) ;
if ( type ) addTransaction ( driveSection , " Type " , ACTION_SET , type ) ;
if ( serial ) addTransaction ( driveSection , " Serial " , ACTION_SET , serial ) ;
if ( fs ) addTransaction ( driveSection , " FileSystem " , ACTION_SET , fs ) ;
if ( path ) free ( path ) ;
if ( label ) free ( label ) ;
if ( type ) free ( type ) ;
if ( serial ) free ( serial ) ;
if ( fs ) free ( fs ) ;
}
void removeDrive ( char letter ) {
char * driveSection = alloca ( strlen ( " Drive X " ) + 1 ) ;
sprintf ( driveSection , " Drive %c " , letter ) ;
addTransaction ( driveSection , NULL , ACTION_REMOVE , NULL ) ;
}
int refreshDriveDlg ( HWND hDlg )
2003-09-08 21:29:28 +02:00
{
int i ;
char * subKeyName = malloc ( MAX_NAME_LENGTH ) ;
int driveCount = 0 ;
2003-09-18 00:40:38 +02:00
DWORD sizeOfSubKeyName = MAX_NAME_LENGTH ;
int doesDriveCExist = FALSE ;
2003-09-08 21:29:28 +02:00
WINE_TRACE ( " \n " ) ;
2003-08-30 02:49:00 +02:00
2003-09-08 21:29:28 +02:00
updatingUI = TRUE ;
/* Clear the listbox */
SendMessageA ( GetDlgItem ( hDlg , IDC_LIST_DRIVES ) , LB_RESETCONTENT , 0 , 0 ) ;
for ( i = 0 ;
RegEnumKeyExA ( configKey , i , subKeyName , & sizeOfSubKeyName , NULL , NULL , NULL , NULL ) ! = ERROR_NO_MORE_ITEMS ;
2003-09-18 00:40:38 +02:00
+ + i , sizeOfSubKeyName = MAX_NAME_LENGTH ) {
2003-09-08 21:29:28 +02:00
HKEY hkDrive ;
char returnBuffer [ MAX_NAME_LENGTH ] ;
DWORD sizeOfReturnBuffer = sizeof ( returnBuffer ) ;
LONG r ;
2003-09-18 00:40:38 +02:00
WINE_TRACE ( " %s \n " , subKeyName ) ;
2003-09-08 21:29:28 +02:00
if ( ! strncmp ( " Drive " , subKeyName , 5 ) ) {
char driveLetter = ' \0 ' ;
char * label ;
char * title ;
2003-09-18 00:40:38 +02:00
char * device ;
2003-09-08 21:29:28 +02:00
int titleLen ;
const char * itemLabel = " Drive %s (%s) " ;
int itemIndex ;
if ( RegOpenKeyExA ( configKey , subKeyName , 0 , KEY_READ , & hkDrive ) ! = ERROR_SUCCESS ) {
WINE_ERR ( " unable to open drive registry key " ) ;
RegCloseKey ( configKey ) ;
2003-09-18 00:40:38 +02:00
return - 1 ;
2003-09-08 21:29:28 +02:00
}
/* extract the drive letter, force to upper case */
driveLetter = subKeyName [ strlen ( subKeyName ) - 1 ] ;
2003-09-18 00:40:38 +02:00
if ( driveLetter ) driveLetter = toupper ( driveLetter ) ;
if ( driveLetter = = ' C ' ) doesDriveCExist = TRUE ;
2003-09-08 21:29:28 +02:00
ZeroMemory ( returnBuffer , sizeof ( * returnBuffer ) ) ;
sizeOfReturnBuffer = sizeof ( returnBuffer ) ;
r = RegQueryValueExA ( hkDrive , " Label " , NULL , NULL , returnBuffer , & sizeOfReturnBuffer ) ;
if ( r = = ERROR_SUCCESS ) {
label = malloc ( sizeOfReturnBuffer ) ;
strncpy ( label , returnBuffer , sizeOfReturnBuffer ) ;
} else {
WINE_WARN ( " label not loaded: %ld \n " , r ) ;
label = NULL ;
}
2003-09-18 00:40:38 +02:00
device = getDriveValue ( driveLetter , " Device " ) ;
2003-09-08 21:29:28 +02:00
/* We now know the label and drive letter, so we can add to the list. The list items will have the letter associated
* with them , which acts as the key . We can then use that letter to get / set the properties of the drive . */
2003-09-18 00:40:38 +02:00
WINE_TRACE ( " Adding %c: label=%s to the listbox, device=%s \n " , driveLetter , label , device ) ;
/* fixup label */
if ( ! label & & device ) {
label = malloc ( strlen ( " [label read from device ] " ) + 1 + strlen ( device ) ) ;
sprintf ( label , " [label read from device %s] " , device ) ;
}
if ( ! label ) label = strdup ( " (no label) " ) ;
2003-09-08 21:29:28 +02:00
titleLen = strlen ( itemLabel ) - 1 + strlen ( label ) - 2 + 1 ;
title = malloc ( titleLen ) ;
/* the %s in the item label will be replaced by the drive letter, so -1, then
- 2 for the second % s which will be expanded to the label , finally + 1 for terminating # 0 */
2003-09-18 00:40:38 +02:00
snprintf ( title , titleLen , " Drive %c: %s " , driveLetter , label ) ;
2003-09-08 21:29:28 +02:00
/* the first SendMessage call adds the string and returns the index, the second associates that index with it */
itemIndex = SendMessageA ( GetDlgItem ( hDlg , IDC_LIST_DRIVES ) , LB_ADDSTRING , ( WPARAM ) - 1 , ( LPARAM ) title ) ;
SendMessageA ( GetDlgItem ( hDlg , IDC_LIST_DRIVES ) , LB_SETITEMDATA , itemIndex , ( LPARAM ) driveLetter ) ;
free ( title ) ;
2003-09-18 00:40:38 +02:00
free ( label ) ;
2003-09-08 21:29:28 +02:00
driveCount + + ;
}
}
WINE_TRACE ( " loaded %d drives \n " , driveCount ) ;
2003-09-18 00:40:38 +02:00
SendDlgItemMessage ( hDlg , IDC_LIST_DRIVES , LB_SETSEL , TRUE , lastSel ) ;
/* show the warning if there is no Drive C */
if ( ! doesDriveCExist )
ShowWindow ( GetDlgItem ( hDlg , IDS_DRIVE_NO_C ) , SW_NORMAL ) ;
else
ShowWindow ( GetDlgItem ( hDlg , IDS_DRIVE_NO_C ) , SW_HIDE ) ;
2003-09-08 21:29:28 +02:00
free ( subKeyName ) ;
updatingUI = FALSE ;
2003-09-18 00:40:38 +02:00
return driveCount ;
2003-09-08 21:29:28 +02:00
}
2003-08-30 02:49:00 +02:00
/******************************************************************************/
/* The Drive Editing Dialog */
/******************************************************************************/
# define DRIVE_MASK_BIT(B) 1<<(toupper(B)-'A')
2003-09-18 00:40:38 +02:00
typedef struct {
2003-10-09 06:39:01 +02:00
const char * sCode ;
const char * sDesc ;
2003-08-30 02:49:00 +02:00
} code_desc_pair ;
static code_desc_pair type_pairs [ ] = {
{ " hd " , " Local hard disk " } ,
{ " network " , " Network share " } ,
{ " floppy " , " Floppy disk " } ,
{ " cdrom " , " CD-ROM " }
} ;
# define DRIVE_TYPE_DEFAULT 1
static code_desc_pair fs_pairs [ ] = {
{ " win95 " , " Long file names " } ,
{ " msdos " , " MS-DOS 8 character file names " } ,
{ " unix " , " UNIX file names " }
} ;
2003-09-08 21:29:28 +02:00
2003-08-30 02:49:00 +02:00
# define DRIVE_FS_DEFAULT 0
2003-09-08 21:29:28 +02:00
void fill_drive_droplist ( long mask , char currentLetter , HWND hDlg )
2003-08-30 02:49:00 +02:00
{
int i ;
int selection ;
int count ;
int next_letter ;
char sName [ 4 ] = " A: " ;
for ( i = 0 , count = 0 , selection = - 1 , next_letter = - 1 ; i < = ' Z ' - ' A ' ; + + i ) {
if ( mask & DRIVE_MASK_BIT ( ' A ' + i ) ) {
2003-09-18 00:40:38 +02:00
int index ;
2003-08-30 02:49:00 +02:00
2003-09-18 00:40:38 +02:00
sName [ 0 ] = ' A ' + i ;
index = SendDlgItemMessage ( hDlg , IDC_COMBO_LETTER , CB_ADDSTRING , 0 , ( LPARAM ) sName ) ;
2003-09-08 21:29:28 +02:00
if ( toupper ( currentLetter ) = = ' A ' + i ) {
2003-08-30 02:49:00 +02:00
selection = count ;
}
if ( i > = 2 & & next_letter = = - 1 ) { /*default drive is first one of C-Z */
next_letter = count ;
}
count + + ;
}
}
if ( selection = = - 1 ) {
selection = next_letter ;
}
SendDlgItemMessage ( hDlg , IDC_COMBO_LETTER , CB_SETCURSEL , selection , 0 ) ;
}
2003-09-18 00:40:38 +02:00
# define BOX_MODE_CD_ASSIGN 1
# define BOX_MODE_CD_AUTODETECT 2
# define BOX_MODE_NONE 3
# define BOX_MODE_NORMAL 4
2003-09-30 02:27:55 +02:00
void enable_labelserial_box ( HWND dialog , int mode )
2003-08-30 02:49:00 +02:00
{
2003-09-18 00:40:38 +02:00
WINE_TRACE ( " mode=%d \n " , mode ) ;
switch ( mode ) {
case BOX_MODE_CD_ASSIGN :
2003-09-30 02:27:55 +02:00
enable ( IDC_RADIO_AUTODETECT ) ;
enable ( IDC_RADIO_ASSIGN ) ;
disable ( IDC_EDIT_DEVICE ) ;
disable ( IDC_BUTTON_BROWSE_DEVICE ) ;
enable ( IDC_EDIT_SERIAL ) ;
enable ( IDC_EDIT_LABEL ) ;
enable ( IDC_STATIC_SERIAL ) ;
enable ( IDC_STATIC_LABEL ) ;
2003-09-18 00:40:38 +02:00
break ;
case BOX_MODE_CD_AUTODETECT :
2003-09-30 02:27:55 +02:00
enable ( IDC_RADIO_AUTODETECT ) ;
enable ( IDC_RADIO_ASSIGN ) ;
enable ( IDC_EDIT_DEVICE ) ;
enable ( IDC_BUTTON_BROWSE_DEVICE ) ;
disable ( IDC_EDIT_SERIAL ) ;
disable ( IDC_EDIT_LABEL ) ;
disable ( IDC_STATIC_SERIAL ) ;
disable ( IDC_STATIC_LABEL ) ;
2003-09-18 00:40:38 +02:00
break ;
case BOX_MODE_NONE :
2003-09-30 02:27:55 +02:00
disable ( IDC_RADIO_AUTODETECT ) ;
disable ( IDC_RADIO_ASSIGN ) ;
disable ( IDC_EDIT_DEVICE ) ;
disable ( IDC_BUTTON_BROWSE_DEVICE ) ;
disable ( IDC_EDIT_SERIAL ) ;
disable ( IDC_EDIT_LABEL ) ;
disable ( IDC_STATIC_SERIAL ) ;
disable ( IDC_STATIC_LABEL ) ;
2003-09-18 00:40:38 +02:00
break ;
case BOX_MODE_NORMAL :
2003-09-30 02:27:55 +02:00
disable ( IDC_RADIO_AUTODETECT ) ;
enable ( IDC_RADIO_ASSIGN ) ;
disable ( IDC_EDIT_DEVICE ) ;
disable ( IDC_BUTTON_BROWSE_DEVICE ) ;
enable ( IDC_EDIT_SERIAL ) ;
enable ( IDC_EDIT_LABEL ) ;
enable ( IDC_STATIC_SERIAL ) ;
enable ( IDC_STATIC_LABEL ) ;
2003-09-18 00:40:38 +02:00
break ;
}
2003-08-30 02:49:00 +02:00
}
2003-09-08 21:29:28 +02:00
/* This function produces a mask for each drive letter that isn't currently used. Each bit of the long result
* represents a letter , with A being the least significant bit , and Z being the most significant .
*
* To calculate this , we loop over each letter , and see if we can get a drive entry for it . If so , we
* set the appropriate bit . At the end , we flip each bit , to give the desired result .
*
* The letter parameter is always marked as being available . This is so the edit dialog can display the
* currently used drive letter alongside the available ones .
*/
long drive_available_mask ( char letter )
{
long result = 0 ;
char curLetter ;
char * slop ;
WINE_TRACE ( " \n " ) ;
for ( curLetter = ' A ' ; curLetter < ' Z ' ; curLetter + + ) {
slop = getDriveValue ( curLetter , " Path " ) ;
if ( slop ! = NULL ) {
result | = DRIVE_MASK_BIT ( curLetter ) ;
free ( slop ) ;
}
}
2003-09-10 05:41:44 +02:00
result = ~ result ;
if ( letter ) result | = DRIVE_MASK_BIT ( letter ) ;
2003-09-08 21:29:28 +02:00
WINE_TRACE ( " finished drive letter loop with %lx \n " , result ) ;
return result ;
}
void refreshDriveEditDialog ( HWND hDlg ) {
char * path ;
char * type ;
char * fs ;
char * serial ;
char * label ;
char * device ;
int i , selection ;
updatingUI = TRUE ;
/* Drive letters */
fill_drive_droplist ( drive_available_mask ( editWindowLetter ) , editWindowLetter , hDlg ) ;
/* path */
path = getDriveValue ( editWindowLetter , " Path " ) ;
if ( path ) {
SetWindowText ( GetDlgItem ( hDlg , IDC_EDIT_PATH ) , path ) ;
} else WINE_WARN ( " no Path field? \n " ) ;
/* drive type */
type = getDriveValue ( editWindowLetter , " Type " ) ;
if ( type ) {
for ( i = 0 , selection = - 1 ; i < sizeof ( type_pairs ) / sizeof ( code_desc_pair ) ; i + + ) {
SendDlgItemMessage ( hDlg , IDC_COMBO_TYPE , CB_ADDSTRING , 0 ,
( LPARAM ) type_pairs [ i ] . sDesc ) ;
if ( strcasecmp ( type_pairs [ i ] . sCode , type ) = = 0 ) {
selection = i ;
}
}
if ( selection = = - 1 ) selection = DRIVE_TYPE_DEFAULT ;
SendDlgItemMessage ( hDlg , IDC_COMBO_TYPE , CB_SETCURSEL , selection , 0 ) ;
} else WINE_WARN ( " no Type field? \n " ) ;
/* FileSystem name handling */
fs = getDriveValue ( editWindowLetter , " FileSystem " ) ;
if ( fs ) {
for ( i = 0 , selection = - 1 ; i < sizeof ( fs_pairs ) / sizeof ( code_desc_pair ) ; i + + ) {
SendDlgItemMessage ( hDlg , IDC_COMBO_NAMES , CB_ADDSTRING , 0 ,
( LPARAM ) fs_pairs [ i ] . sDesc ) ;
if ( strcasecmp ( fs_pairs [ i ] . sCode , fs ) = = 0 ) {
selection = i ;
}
}
if ( selection = = - 1 ) selection = DRIVE_FS_DEFAULT ;
SendDlgItemMessage ( hDlg , IDC_COMBO_NAMES , CB_SETCURSEL , selection , 0 ) ;
} else WINE_WARN ( " no FileSystem field? \n " ) ;
/* removeable media properties */
serial = getDriveValue ( editWindowLetter , " Serial " ) ;
if ( serial ) {
SendDlgItemMessage ( hDlg , IDC_EDIT_SERIAL , WM_SETTEXT , 0 , ( LPARAM ) serial ) ;
} else WINE_WARN ( " no Serial field? \n " ) ;
label = getDriveValue ( editWindowLetter , " Label " ) ;
if ( label ) {
SendDlgItemMessage ( hDlg , IDC_EDIT_LABEL , WM_SETTEXT , 0 , ( LPARAM ) label ) ;
} else WINE_WARN ( " no Label field? \n " ) ;
device = getDriveValue ( editWindowLetter , " Device " ) ;
if ( device ) {
SendDlgItemMessage ( hDlg , IDC_EDIT_DEVICE , WM_SETTEXT , 0 , ( LPARAM ) device ) ;
} else WINE_WARN ( " no Device field? \n " ) ;
2003-09-10 05:41:44 +02:00
selection = IDC_RADIO_ASSIGN ;
2003-09-18 00:40:38 +02:00
if ( ( type & & strcmp ( " cdrom " , type ) = = 0 ) | | ( type & & strcmp ( " floppy " , type ) = = 0 ) ) {
if ( device ) {
2003-09-08 21:29:28 +02:00
selection = IDC_RADIO_AUTODETECT ;
2003-09-18 00:40:38 +02:00
enable_labelserial_box ( hDlg , BOX_MODE_CD_AUTODETECT ) ;
} else {
selection = IDC_RADIO_ASSIGN ;
enable_labelserial_box ( hDlg , BOX_MODE_CD_ASSIGN ) ;
2003-09-08 21:29:28 +02:00
}
2003-09-18 00:40:38 +02:00
} else {
enable_labelserial_box ( hDlg , BOX_MODE_NORMAL ) ;
2003-09-08 21:29:28 +02:00
selection = IDC_RADIO_ASSIGN ;
}
CheckRadioButton ( hDlg , IDC_RADIO_AUTODETECT , IDC_RADIO_ASSIGN , selection ) ;
2003-09-10 05:41:44 +02:00
if ( path ) SendDlgItemMessage ( hDlg , IDC_EDIT_PATH , WM_SETTEXT , 0 , ( LPARAM ) path ) ;
2003-09-08 21:29:28 +02:00
if ( path ) free ( path ) ;
if ( type ) free ( type ) ;
if ( fs ) free ( fs ) ;
if ( serial ) free ( serial ) ;
if ( label ) free ( label ) ;
if ( device ) free ( device ) ;
2003-09-10 05:41:44 +02:00
2003-09-08 21:29:28 +02:00
updatingUI = FALSE ;
return ;
}
2003-08-30 02:49:00 +02:00
2003-09-10 05:41:44 +02:00
/* storing the drive propsheet HWND here is a bit ugly, but the simplest solution for now */
static HWND driveDlgHandle ;
void onEditChanged ( HWND hDlg , WORD controlID ) {
WINE_TRACE ( " controlID=%d \n " , controlID ) ;
switch ( controlID ) {
2003-09-18 00:40:38 +02:00
case IDC_EDIT_LABEL : {
2003-09-10 05:41:44 +02:00
char * label = getDialogItemText ( hDlg , controlID ) ;
setDriveValue ( editWindowLetter , " Label " , label ) ;
refreshDriveDlg ( driveDlgHandle ) ;
2003-09-18 00:40:38 +02:00
if ( label ) free ( label ) ;
2003-09-10 05:41:44 +02:00
break ;
}
2003-09-18 00:40:38 +02:00
case IDC_EDIT_PATH : {
char * path = getDialogItemText ( hDlg , controlID ) ;
if ( ! path ) path = strdup ( " fake_windows " ) ; /* default to assuming fake_windows in the .wine directory */
setDriveValue ( editWindowLetter , " Path " , path ) ;
free ( path ) ;
break ;
}
case IDC_EDIT_SERIAL : {
char * serial = getDialogItemText ( hDlg , controlID ) ;
setDriveValue ( editWindowLetter , " Serial " , serial ) ;
if ( serial ) free ( serial ) ;
break ;
}
case IDC_EDIT_DEVICE : {
char * device = getDialogItemText ( hDlg , controlID ) ;
setDriveValue ( editWindowLetter , " Device " , device ) ;
if ( device ) free ( device ) ;
refreshDriveDlg ( driveDlgHandle ) ;
break ;
}
2003-09-10 05:41:44 +02:00
}
}
2003-08-30 02:49:00 +02:00
INT_PTR CALLBACK DriveEditDlgProc ( HWND hDlg , UINT uMsg , WPARAM wParam , LPARAM lParam )
{
int selection ;
2003-09-18 00:40:38 +02:00
2003-08-30 02:49:00 +02:00
switch ( uMsg ) {
2003-09-08 21:29:28 +02:00
case WM_INITDIALOG : {
editWindowLetter = ( char ) lParam ;
refreshDriveEditDialog ( hDlg ) ;
2003-08-30 02:49:00 +02:00
}
case WM_COMMAND :
2003-09-08 21:29:28 +02:00
switch ( LOWORD ( wParam ) ) {
case IDC_COMBO_TYPE :
2003-09-18 00:40:38 +02:00
if ( HIWORD ( wParam ) ! = CBN_SELCHANGE ) break ;
selection = SendDlgItemMessage ( hDlg , IDC_COMBO_TYPE , CB_GETCURSEL , 0 , 0 ) ;
if ( selection = = 2 | | selection = = 3 ) { /* cdrom or floppy */
if ( IsDlgButtonChecked ( hDlg , IDC_RADIO_AUTODETECT ) )
enable_labelserial_box ( hDlg , BOX_MODE_CD_AUTODETECT ) ;
else
enable_labelserial_box ( hDlg , BOX_MODE_CD_ASSIGN ) ;
}
else {
enable_labelserial_box ( hDlg , BOX_MODE_NORMAL ) ;
2003-08-30 02:49:00 +02:00
}
2003-09-18 00:40:38 +02:00
setDriveValue ( editWindowLetter , " Type " , type_pairs [ selection ] . sCode ) ;
break ;
case IDC_COMBO_LETTER : {
int item = SendDlgItemMessage ( hDlg , IDC_COMBO_LETTER , CB_GETCURSEL , 0 , 0 ) ;
char newLetter ;
SendDlgItemMessage ( hDlg , IDC_COMBO_LETTER , CB_GETLBTEXT , item , ( LPARAM ) & newLetter ) ;
if ( HIWORD ( wParam ) ! = CBN_SELCHANGE ) break ;
if ( newLetter = = editWindowLetter ) break ;
WINE_TRACE ( " changing drive letter to %c \n " , newLetter ) ;
copyDrive ( editWindowLetter , newLetter ) ;
removeDrive ( editWindowLetter ) ;
editWindowLetter = newLetter ;
refreshDriveDlg ( driveDlgHandle ) ;
break ;
}
case IDC_BUTTON_BROWSE_PATH :
WRITEME ( hDlg ) ;
break ;
case IDC_RADIO_AUTODETECT : {
setDriveValue ( editWindowLetter , " Label " , NULL ) ;
setDriveValue ( editWindowLetter , " Serial " , NULL ) ;
setDriveValue ( editWindowLetter , " Device " , getDialogItemText ( hDlg , IDC_EDIT_DEVICE ) ) ;
enable_labelserial_box ( hDlg , BOX_MODE_CD_AUTODETECT ) ;
refreshDriveDlg ( driveDlgHandle ) ;
break ;
}
case IDC_RADIO_ASSIGN :
setDriveValue ( editWindowLetter , " Device " , NULL ) ;
setDriveValue ( editWindowLetter , " Label " , getDialogItemText ( hDlg , IDC_EDIT_LABEL ) ) ;
setDriveValue ( editWindowLetter , " Serial " , getDialogItemText ( hDlg , IDC_EDIT_SERIAL ) ) ;
enable_labelserial_box ( hDlg , BOX_MODE_CD_ASSIGN ) ;
refreshDriveDlg ( driveDlgHandle ) ;
2003-09-08 21:29:28 +02:00
break ;
2003-08-30 02:49:00 +02:00
2003-09-10 05:41:44 +02:00
case ID_BUTTON_OK :
2003-09-08 21:29:28 +02:00
EndDialog ( hDlg , wParam ) ;
return TRUE ;
}
2003-09-10 05:41:44 +02:00
if ( HIWORD ( wParam ) = = EN_CHANGE ) onEditChanged ( hDlg , LOWORD ( wParam ) ) ;
break ;
2003-09-08 21:29:28 +02:00
}
2003-08-30 02:49:00 +02:00
return FALSE ;
}
2003-09-10 05:41:44 +02:00
void onAddDriveClicked ( HWND hDlg ) {
/* we should allocate a drive letter automatically. We also need some way to let the user choose the mapping point,
for now we will just force them to enter a path automatically , with / being the default . In future we should
be able to temporarily map / then invoke the directory chooser dialog . */
2003-09-18 00:40:38 +02:00
char newLetter = ' C ' ; /* we skip A and B, they are historically floppy drives */
2003-09-10 05:41:44 +02:00
long mask = ~ drive_available_mask ( 0 ) ; /* the mask is now which drives aren't available */
char * sectionName ;
while ( mask & ( 1 < < ( newLetter - ' A ' ) ) ) {
newLetter + + ;
if ( newLetter > ' Z ' ) {
MessageBox ( NULL , " You cannot add any more drives. \n \n Each drive must have a letter, from A to Z, so you cannot have more than 26 " , " " , MB_OK | MB_ICONEXCLAMATION ) ;
return ;
}
}
WINE_TRACE ( " allocating drive letter %c \n " , newLetter ) ;
sectionName = malloc ( strlen ( " Drive X " ) + 1 ) ;
sprintf ( sectionName , " Drive %c " , newLetter ) ;
2003-09-18 00:40:38 +02:00
if ( newLetter = = ' C ' ) {
addTransaction ( sectionName , " Path " , ACTION_SET , " fake_windows " ) ;
addTransaction ( sectionName , " Label " , ACTION_SET , " System Drive " ) ;
} else
addTransaction ( sectionName , " Path " , ACTION_SET , " / " ) ; /* default to root path */
2003-09-10 05:41:44 +02:00
addTransaction ( sectionName , " Type " , ACTION_SET , " hd " ) ;
processTransQueue ( ) ; /* make sure the drive has been added, even if we are not in instant apply mode */
free ( sectionName ) ;
refreshDriveDlg ( driveDlgHandle ) ;
2003-09-18 00:40:38 +02:00
DialogBoxParam ( NULL , MAKEINTRESOURCE ( IDD_DRIVE_EDIT ) , NULL , ( DLGPROC ) DriveEditDlgProc , ( LPARAM ) newLetter ) ;
2003-09-10 05:41:44 +02:00
}
2003-08-30 02:49:00 +02:00
INT_PTR CALLBACK
DriveDlgProc ( HWND hDlg , UINT uMsg , WPARAM wParam , LPARAM lParam )
{
int selection = - 1 ;
2003-09-18 00:40:38 +02:00
int nItem ;
char letter ;
2003-09-08 21:29:28 +02:00
switch ( uMsg ) {
case WM_COMMAND :
switch ( LOWORD ( wParam ) ) {
case IDC_LIST_DRIVES :
2003-09-18 00:40:38 +02:00
if ( HIWORD ( wParam ) = = LBN_DBLCLK ) selection = - 1 ;
if ( HIWORD ( wParam ) = = LBN_SELCHANGE ) lastSel = SendDlgItemMessage ( hDlg , IDC_LIST_DRIVES , LB_GETCURSEL , 0 , 0 ) ;
2003-09-10 05:41:44 +02:00
break ;
2003-09-08 21:29:28 +02:00
case IDC_BUTTON_ADD :
2003-09-10 05:41:44 +02:00
onAddDriveClicked ( hDlg ) ;
2003-09-08 21:29:28 +02:00
break ;
case IDC_BUTTON_REMOVE :
2003-09-18 00:40:38 +02:00
if ( HIWORD ( wParam ) ! = BN_CLICKED ) break ;
nItem = SendDlgItemMessage ( hDlg , IDC_LIST_DRIVES , LB_GETCURSEL , 0 , 0 ) ;
letter = SendDlgItemMessage ( hDlg , IDC_LIST_DRIVES , LB_GETITEMDATA , nItem , 0 ) ;
removeDrive ( letter ) ;
refreshDriveDlg ( driveDlgHandle ) ;
2003-09-08 21:29:28 +02:00
break ;
case IDC_BUTTON_EDIT :
2003-09-18 00:40:38 +02:00
if ( HIWORD ( wParam ) ! = BN_CLICKED ) break ;
nItem = SendMessage ( GetDlgItem ( hDlg , IDC_LIST_DRIVES ) , LB_GETCURSEL , 0 , 0 ) ;
letter = SendMessage ( GetDlgItem ( hDlg , IDC_LIST_DRIVES ) , LB_GETITEMDATA , nItem , 0 ) ;
DialogBoxParam ( NULL , MAKEINTRESOURCE ( IDD_DRIVE_EDIT ) , NULL , ( DLGPROC ) DriveEditDlgProc , ( LPARAM ) letter ) ;
break ;
case IDC_BUTTON_AUTODETECT :
WRITEME ( hDlg ) ;
2003-08-30 02:49:00 +02:00
break ;
}
2003-09-08 21:29:28 +02:00
break ;
case WM_NOTIFY : switch ( ( ( LPNMHDR ) lParam ) - > code ) {
case PSN_KILLACTIVE :
SetWindowLong ( hDlg , DWL_MSGRESULT , FALSE ) ;
break ;
case PSN_APPLY :
SetWindowLong ( hDlg , DWL_MSGRESULT , PSNRET_NOERROR ) ;
break ;
case PSN_SETACTIVE :
2003-09-10 05:41:44 +02:00
driveDlgHandle = hDlg ;
refreshDriveDlg ( driveDlgHandle ) ;
2003-09-08 21:29:28 +02:00
break ;
2003-08-30 02:49:00 +02:00
}
2003-09-08 21:29:28 +02:00
break ;
2003-08-30 02:49:00 +02:00
2003-09-08 21:29:28 +02:00
}
2003-08-30 02:49:00 +02:00
return FALSE ;
}