driveui.c 24.2 KB
Newer Older
Mike Hearn's avatar
Mike Hearn committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * Drive management UI code
 *
 * Copyright 2003 Mark Westcott
 * Copyright 2004 Chris Morgan
 * Copyright 2003-2004 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
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Mike Hearn's avatar
Mike Hearn committed
21 22 23
 *
 */

24 25
#include <stdio.h>

26
#define WIN32_LEAN_AND_MEAN
27 28
#define COBJMACROS

29
#include <windows.h>
Mike Hearn's avatar
Mike Hearn committed
30 31 32 33 34 35
#include <shellapi.h>
#include <objbase.h>
#include <shlguid.h>
#include <shlwapi.h>
#include <shlobj.h>

36
#include <wine/unicode.h>
Mike Hearn's avatar
Mike Hearn committed
37 38 39 40 41 42 43
#include <wine/debug.h>

#include "winecfg.h"
#include "resource.h"

WINE_DEFAULT_DEBUG_CHANNEL(winecfg);

44 45
#define BOX_MODE_DEVICE 1
#define BOX_MODE_NORMAL 2
Mike Hearn's avatar
Mike Hearn committed
46 47 48 49 50

static BOOL advanced = FALSE;
static BOOL updating_ui = FALSE;
static struct drive* current_drive;

51
static void update_controls(HWND dialog);
Mike Hearn's avatar
Mike Hearn committed
52

53 54 55
static DWORD driveui_msgbox (HWND parent, UINT messageId, DWORD flags)
{
  WCHAR* caption = load_string (IDS_WINECFG_TITLE);
56
  WCHAR* text = load_string (messageId);
57 58 59 60 61 62
  DWORD result = MessageBoxW (parent, text, caption, flags);
  HeapFree (GetProcessHeap(), 0, caption);
  HeapFree (GetProcessHeap(), 0, text);
  return result;
}

63 64 65 66 67
/**** listview helper functions ****/

/* clears the item at index in the listview */
static void lv_clear_curr_select(HWND dialog, int index)
{
68 69 70 71 72 73
    LVITEMW item;

    item.mask = LVIF_STATE;
    item.state = 0;
    item.stateMask = LVIS_SELECTED;
    SendDlgItemMessageW( dialog, IDC_LIST_DRIVES, LVM_SETITEMSTATE, index, (LPARAM)&item );
74 75 76 77 78
}

/* selects the item at index in the listview */
static void lv_set_curr_select(HWND dialog, int index)
{
79 80
    LVITEMW item;

81 82
    /* no more than one item can be selected in our listview */
    lv_clear_curr_select(dialog, -1);
83 84 85 86
    item.mask = LVIF_STATE;
    item.state = LVIS_SELECTED;
    item.stateMask = LVIS_SELECTED;
    SendDlgItemMessageW( dialog, IDC_LIST_DRIVES, LVM_SETITEMSTATE, index, (LPARAM)&item );
87 88 89 90 91
}

/* returns the currently selected item in the listview */
static int lv_get_curr_select(HWND dialog)
{
92
    return SendDlgItemMessageW(dialog, IDC_LIST_DRIVES, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
93 94 95
}

/* sets the item in the listview at item->iIndex */
96
static void lv_set_item(HWND dialog, LVITEMW *item)
97
{
98
    SendDlgItemMessageW(dialog, IDC_LIST_DRIVES, LVM_SETITEMW, 0, (LPARAM) item);
99 100
}

101
/* sets specified item's text */
102
static void lv_set_item_text(HWND dialog, int item, int subItem, WCHAR *text)
103
{
104
    LVITEMW lvItem;
105 106 107 108 109
    if (item < 0 || subItem < 0) return;
    lvItem.mask = LVIF_TEXT;
    lvItem.iItem = item;
    lvItem.iSubItem = subItem;
    lvItem.pszText = text;
110
    lvItem.cchTextMax = lstrlenW(lvItem.pszText);
111 112 113
    lv_set_item(dialog, &lvItem);
}

114
/* inserts an item into the listview */
115
static void lv_insert_item(HWND dialog, LVITEMW *item)
116
{
117
    SendDlgItemMessageW(dialog, IDC_LIST_DRIVES, LVM_INSERTITEMW, 0, (LPARAM) item);
118 119 120
}

/* retrieve the item at index item->iIndex */
121
static void lv_get_item(HWND dialog, LVITEMW *item)
122
{
123
    SendDlgItemMessageW(dialog, IDC_LIST_DRIVES, LVM_GETITEMW, 0, (LPARAM) item);
124 125
}

Mike Hearn's avatar
Mike Hearn committed
126 127 128
static void set_advanced(HWND dialog)
{
    int state;
129
    WCHAR text[256];
Mike Hearn's avatar
Mike Hearn committed
130 131 132 133

    if (advanced)
    {
        state = SW_NORMAL;
134
        LoadStringW(GetModuleHandleW(NULL), IDS_HIDE_ADVANCED, text, 256);
Mike Hearn's avatar
Mike Hearn committed
135 136 137 138
    }
    else
    {
        state = SW_HIDE;
139
        LoadStringW(GetModuleHandleW(NULL), IDS_SHOW_ADVANCED, text, 256);
Mike Hearn's avatar
Mike Hearn committed
140 141 142
    }

    ShowWindow(GetDlgItem(dialog, IDC_EDIT_DEVICE), state);
143 144
    ShowWindow(GetDlgItem(dialog, IDC_STATIC_DEVICE), state);
    ShowWindow(GetDlgItem(dialog, IDC_EDIT_LABEL), state);
Mike Hearn's avatar
Mike Hearn committed
145 146 147 148
    ShowWindow(GetDlgItem(dialog, IDC_STATIC_LABEL), state);
    ShowWindow(GetDlgItem(dialog, IDC_BUTTON_BROWSE_DEVICE), state);
    ShowWindow(GetDlgItem(dialog, IDC_EDIT_SERIAL), state);
    ShowWindow(GetDlgItem(dialog, IDC_STATIC_SERIAL), state);
149 150
    ShowWindow(GetDlgItem(dialog, IDC_COMBO_TYPE), state);
    ShowWindow(GetDlgItem(dialog, IDC_STATIC_TYPE), state);
Mike Hearn's avatar
Mike Hearn committed
151 152

    /* update the button text based on the state */
153
    SetWindowTextW(GetDlgItem(dialog, IDC_BUTTON_SHOW_HIDE_ADVANCED), text);
Mike Hearn's avatar
Mike Hearn committed
154 155 156
}

struct drive_typemap {
Steven Edwards's avatar
Steven Edwards committed
157
    unsigned int sCode;
158
    UINT idDesc;
Mike Hearn's avatar
Mike Hearn committed
159 160
};

Steven Edwards's avatar
Steven Edwards committed
161
static const struct drive_typemap type_pairs[] = {
162 163 164 165 166
  { DRIVE_UNKNOWN,    IDS_DRIVE_UNKNOWN   },
  { DRIVE_FIXED,      IDS_DRIVE_FIXED     },
  { DRIVE_REMOTE,     IDS_DRIVE_REMOTE    },
  { DRIVE_REMOVABLE,  IDS_DRIVE_REMOVABLE },
  { DRIVE_CDROM,      IDS_DRIVE_CDROM     }
Mike Hearn's avatar
Mike Hearn committed
167 168
};

169
#define DRIVE_TYPE_DEFAULT 0
Mike Hearn's avatar
Mike Hearn committed
170

171
static void enable_labelserial_box(HWND dialog, int mode)
Mike Hearn's avatar
Mike Hearn committed
172 173 174 175 176
{
    WINE_TRACE("mode=%d\n", mode);

    switch (mode)
    {
177 178
        case BOX_MODE_DEVICE:
            /* FIXME: enable device editing */
Mike Hearn's avatar
Mike Hearn committed
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
            disable(IDC_EDIT_DEVICE);
            disable(IDC_BUTTON_BROWSE_DEVICE);
            disable(IDC_EDIT_SERIAL);
            disable(IDC_EDIT_LABEL);
            break;

        case BOX_MODE_NORMAL:
            disable(IDC_EDIT_DEVICE);
            disable(IDC_BUTTON_BROWSE_DEVICE);
            enable(IDC_EDIT_SERIAL);
            enable(IDC_EDIT_LABEL);
            break;
    }
}

194
static int fill_drives_list(HWND dialog)
Mike Hearn's avatar
Mike Hearn committed
195 196 197 198 199 200 201 202 203 204
{
    int count = 0;
    BOOL drivec_present = FALSE;
    int i;
    int prevsel = -1;

    WINE_TRACE("\n");

    updating_ui = TRUE;

205
    prevsel = lv_get_curr_select(dialog); 
Mike Hearn's avatar
Mike Hearn committed
206 207

    /* Clear the listbox */
208
    SendDlgItemMessageW(dialog, IDC_LIST_DRIVES, LVM_DELETEALLITEMS, 0, 0);
Mike Hearn's avatar
Mike Hearn committed
209 210 211

    for(i = 0; i < 26; i++)
    {
212 213
        LVITEMW item;
        WCHAR *path;
214
        char letter[4];
Mike Hearn's avatar
Mike Hearn committed
215 216 217 218 219 220 221 222

        /* skip over any unused drives */
        if (!drives[i].in_use)
            continue;

        if (drives[i].letter == 'C')
            drivec_present = TRUE;

223 224 225
        letter[0] = 'A' + i;
        letter[1] = ':';
        letter[2] = 0;
226

227
        item.mask = LVIF_TEXT | LVIF_PARAM;
228 229
        item.iItem = count;
        item.iSubItem = 0;
230 231
        item.pszText = strdupU2W(letter);
        item.cchTextMax = lstrlenW(item.pszText);
232
        item.lParam = (LPARAM) &drives[i];
Mike Hearn's avatar
Mike Hearn committed
233

234
        lv_insert_item(dialog, &item);
235 236 237 238 239
        HeapFree(GetProcessHeap(), 0, item.pszText);

        path = strdupU2W(drives[i].unixpath);
        lv_set_item_text(dialog, count, 1, path);
        HeapFree(GetProcessHeap(), 0, path);
Mike Hearn's avatar
Mike Hearn committed
240 241 242 243 244 245 246 247 248 249 250 251

        count++;
    }

    WINE_TRACE("loaded %d drives\n", count);

    /* show the warning if there is no Drive C */
    if (!drivec_present)
        ShowWindow(GetDlgItem(dialog, IDS_DRIVE_NO_C), SW_NORMAL);
    else
        ShowWindow(GetDlgItem(dialog, IDS_DRIVE_NO_C), SW_HIDE);

252
    lv_set_curr_select(dialog, prevsel == -1 ? 0 : prevsel);
Mike Hearn's avatar
Mike Hearn committed
253 254 255 256 257

    updating_ui = FALSE;
    return count;
}

258
static void on_options_click(HWND dialog)
259 260
{
    if (IsDlgButtonChecked(dialog, IDC_SHOW_DOT_FILES) == BST_CHECKED)
261
        set_reg_key(config_key, "", "ShowDotFiles", "Y");
262
    else
263
        set_reg_key(config_key, "", "ShowDotFiles", "N");
264

265
    SendMessageW(GetParent(dialog), PSM_CHANGED, 0, 0);
266
}
Mike Hearn's avatar
Mike Hearn committed
267

268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
static INT_PTR CALLBACK drivechoose_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    static int i, sel;
    char c;
    char drive[] = "X:";

    switch(uMsg)
    {
    case WM_INITDIALOG:
        {
        ULONG mask = ~drive_available_mask(0); /* the mask is now which drives aren't available */
        for( c = 'A'; c<= 'Z'; c++){
            drive[0] = c;
            if(!( mask & (1 << (c - 'A'))))
                SendDlgItemMessageA( hwndDlg, IDC_DRIVESA2Z, CB_ADDSTRING, 0, (LPARAM) drive);
        }
        drive[0] = lParam;
        SendDlgItemMessageA( hwndDlg, IDC_DRIVESA2Z, CB_SELECTSTRING, 0, (LPARAM) drive);
        return TRUE;
        }
    case WM_COMMAND:
        if(HIWORD(wParam) != BN_CLICKED) break;
        switch (LOWORD(wParam))
        {
        case IDOK:
            i = SendDlgItemMessageA( hwndDlg, IDC_DRIVESA2Z, CB_GETCURSEL, 0, 0);
            if( i != CB_ERR){
                SendDlgItemMessageA( hwndDlg, IDC_DRIVESA2Z, CB_GETLBTEXT, i, (LPARAM) drive);
                sel = drive[0];
            } else
                sel = -1;
            EndDialog(hwndDlg, sel);
            return TRUE;
        case IDCANCEL:
            EndDialog(hwndDlg, -1);
            return TRUE;
        }
    }
    return FALSE;
}

309
static void on_add_click(HWND dialog)
Mike Hearn's avatar
Mike Hearn committed
310 311 312 313 314 315 316 317
{
    /* 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. */

    char new = 'C'; /* we skip A and B, they are historically floppy drives */
318
    ULONG mask = ~drive_available_mask(0); /* the mask is now which drives aren't available */
Mike Hearn's avatar
Mike Hearn committed
319
    int i, c;
320
    INT_PTR ret;
Mike Hearn's avatar
Mike Hearn committed
321 322 323 324 325 326

    while (mask & (1 << (new - 'A')))
    {
        new++;
        if (new > 'Z')
        {
327
            driveui_msgbox (dialog, IDS_DRIVE_LETTERS_EXCEEDED, MB_OK | MB_ICONEXCLAMATION);
Mike Hearn's avatar
Mike Hearn committed
328 329 330 331
            return;
        }
    }

332

333
    ret = DialogBoxParamW(0, MAKEINTRESOURCEW(IDD_DRIVECHOOSE), dialog, drivechoose_dlgproc, new);
334

335 336
    if( ret == -1) return;
    new = ret;
337 338

    WINE_TRACE("selected drive letter %c\n", new);
Mike Hearn's avatar
Mike Hearn committed
339

340 341
    if (new == 'C')
    {
342
        WCHAR label[64];
343
        LoadStringW (GetModuleHandleW(NULL), IDS_SYSTEM_DRIVE_LABEL, label,
344
                     sizeof(label)/sizeof(label[0]));
345
        add_drive(new, "../drive_c", NULL, label, 0, DRIVE_FIXED);
346
    }
347
    else add_drive(new, "/", NULL, NULL, 0, DRIVE_UNKNOWN);
Mike Hearn's avatar
Mike Hearn committed
348 349 350 351 352 353 354 355 356 357 358

    fill_drives_list(dialog);

    /* select the newly created drive */
    mask = ~drive_available_mask(0);
    c = 0;
    for (i = 0; i < 26; i++)
    {
        if ('A' + i == new) break;
        if ((1 << i) & mask) c++;
    }
359
    lv_set_curr_select(dialog, c);
Mike Hearn's avatar
Mike Hearn committed
360 361

    SetFocus(GetDlgItem(dialog, IDC_LIST_DRIVES));
362 363

    update_controls(dialog);
364
    SendMessageW(GetParent(dialog), PSM_CHANGED, (WPARAM) dialog, 0);
Mike Hearn's avatar
Mike Hearn committed
365 366
}

367
static void on_remove_click(HWND dialog)
Mike Hearn's avatar
Mike Hearn committed
368
{
369
    int itemIndex;
Mike Hearn's avatar
Mike Hearn committed
370
    struct drive *drive;
371
    LVITEMW item;
372 373 374 375 376 377 378 379 380 381 382

    itemIndex = lv_get_curr_select(dialog);
    if (itemIndex == -1) return; /* no selection */

    item.mask = LVIF_PARAM;
    item.iItem = itemIndex;
    item.iSubItem = 0;

    lv_get_item(dialog, &item);

    drive = (struct drive *) item.lParam;
Mike Hearn's avatar
Mike Hearn committed
383

384
    WINE_TRACE("unixpath: %s\n", drive->unixpath);
Mike Hearn's avatar
Mike Hearn committed
385 386 387

    if (drive->letter == 'C')
    {
388
        DWORD result = driveui_msgbox (dialog, IDS_CONFIRM_DELETE_C, MB_YESNO | MB_ICONEXCLAMATION);
Mike Hearn's avatar
Mike Hearn committed
389 390 391 392 393 394 395
        if (result == IDNO) return;
    }

    delete_drive(drive);

    fill_drives_list(dialog);

396 397 398
    itemIndex = itemIndex - 1;
    if (itemIndex < 0) itemIndex = 0;
    lv_set_curr_select(dialog, itemIndex);   /* previous item */
Mike Hearn's avatar
Mike Hearn committed
399 400

    SetFocus(GetDlgItem(dialog, IDC_LIST_DRIVES));
401 402

    update_controls(dialog);
403
    SendMessageW(GetParent(dialog), PSM_CHANGED, (WPARAM) dialog, 0);
Mike Hearn's avatar
Mike Hearn committed
404 405
}

406 407
static void update_controls(HWND dialog)
{
408
    static const WCHAR emptyW[1];
409
    WCHAR *path;
Steven Edwards's avatar
Steven Edwards committed
410
    unsigned int type;
411
    char serial[16];
Mike Hearn's avatar
Mike Hearn committed
412
    int i, selection = -1;
413
    LVITEMW item;
Mike Hearn's avatar
Mike Hearn committed
414 415 416

    updating_ui = TRUE;

417
    i = lv_get_curr_select(dialog);
Mike Hearn's avatar
Mike Hearn committed
418 419 420
    if (i == -1)
    {
        /* no selection? let's select something for the user. this will re-enter */
421
        lv_set_curr_select(dialog, i);
Mike Hearn's avatar
Mike Hearn committed
422 423
        return;
    }
424 425 426 427 428 429 430

    item.mask = LVIF_PARAM;
    item.iItem = i;
    item.iSubItem = 0;

    lv_get_item(dialog, &item);
    current_drive = (struct drive *) item.lParam;
Mike Hearn's avatar
Mike Hearn committed
431 432 433 434

    WINE_TRACE("Updating sheet for drive %c\n", current_drive->letter);

    /* path */
435 436 437 438
    WINE_TRACE("set path control text to '%s'\n", current_drive->unixpath);
    path = strdupU2W(current_drive->unixpath);
    set_textW(dialog, IDC_EDIT_PATH, path);
    HeapFree(GetProcessHeap(), 0, path);
Mike Hearn's avatar
Mike Hearn committed
439 440 441

    /* drive type */
    type = current_drive->type;
442
    SendDlgItemMessageW(dialog, IDC_COMBO_TYPE, CB_RESETCONTENT, 0, 0);
443 444

    for (i = 0; i < sizeof(type_pairs) / sizeof(struct drive_typemap); i++)
Mike Hearn's avatar
Mike Hearn committed
445
    {
446
        WCHAR driveDesc[64];
447
        LoadStringW (GetModuleHandleW(NULL), type_pairs[i].idDesc, driveDesc,
448 449
            sizeof(driveDesc)/sizeof(driveDesc[0]));
        SendDlgItemMessageW (dialog, IDC_COMBO_TYPE, CB_ADDSTRING, 0, (LPARAM)driveDesc);
Mike Hearn's avatar
Mike Hearn committed
450

451 452 453
        if (type_pairs[i].sCode ==  type)
        {
            selection = i;
Mike Hearn's avatar
Mike Hearn committed
454
        }
455
    }
Mike Hearn's avatar
Mike Hearn committed
456

457
    if (selection == -1) selection = DRIVE_TYPE_DEFAULT;
458
    SendDlgItemMessageW(dialog, IDC_COMBO_TYPE, CB_SETCURSEL, selection, 0);
Mike Hearn's avatar
Mike Hearn committed
459

460 461 462 463 464
    EnableWindow( GetDlgItem( dialog, IDC_BUTTON_REMOVE ), (current_drive->letter != 'C') );
    EnableWindow( GetDlgItem( dialog, IDC_EDIT_PATH ), (current_drive->letter != 'C') );
    EnableWindow( GetDlgItem( dialog, IDC_BUTTON_BROWSE_PATH ), (current_drive->letter != 'C') );
    EnableWindow( GetDlgItem( dialog, IDC_COMBO_TYPE ), (current_drive->letter != 'C') );

465
    /* removable media properties */
466
    set_textW(dialog, IDC_EDIT_LABEL, current_drive->label ? current_drive->label : emptyW);
Mike Hearn's avatar
Mike Hearn committed
467 468

    /* set serial edit text */
469
    sprintf( serial, "%X", current_drive->serial );
Mike Hearn's avatar
Mike Hearn committed
470 471
    set_text(dialog, IDC_EDIT_SERIAL, serial);

472
    set_text(dialog, IDC_EDIT_DEVICE, current_drive->device);
Mike Hearn's avatar
Mike Hearn committed
473 474

    if ((type == DRIVE_CDROM) || (type == DRIVE_REMOVABLE))
475
        enable_labelserial_box(dialog, BOX_MODE_DEVICE);
Mike Hearn's avatar
Mike Hearn committed
476 477 478 479 480 481 482 483
    else
        enable_labelserial_box(dialog, BOX_MODE_NORMAL);

    updating_ui = FALSE;

    return;
}

484
static void on_edit_changed(HWND dialog, WORD id)
Mike Hearn's avatar
Mike Hearn committed
485 486 487 488 489 490 491 492 493
{
    if (updating_ui) return;

    WINE_TRACE("edit id %d changed\n", id);

    switch (id)
    {
        case IDC_EDIT_LABEL:
        {
494
            WCHAR *label = get_textW(dialog, id);
495
            HeapFree(GetProcessHeap(), 0, current_drive->label);
496
            current_drive->label = label;
497
            current_drive->modified = TRUE;
Mike Hearn's avatar
Mike Hearn committed
498

499
            WINE_TRACE("set label to %s\n", wine_dbgstr_w(current_drive->label));
Mike Hearn's avatar
Mike Hearn committed
500

501
            /* enable the apply button  */
502
            SendMessageW(GetParent(dialog), PSM_CHANGED, (WPARAM) dialog, 0);
Mike Hearn's avatar
Mike Hearn committed
503 504 505 506 507
            break;
        }

        case IDC_EDIT_PATH:
        {
508
            WCHAR *wpath;
Mike Hearn's avatar
Mike Hearn committed
509
            char *path;
510 511 512 513 514 515 516 517 518 519 520 521 522
            int lenW;

            wpath = get_textW(dialog, id);
            if( (lenW = WideCharToMultiByte(CP_UNIXCP, 0, wpath, -1, NULL, 0, NULL, NULL)) )
            {
                path = HeapAlloc(GetProcessHeap(), 0, lenW);
                WideCharToMultiByte(CP_UNIXCP, 0, wpath, -1, path, lenW, NULL, NULL);
            }
            else
            {
                path = NULL;
                wpath = strdupU2W("drive_c");
            }
Mike Hearn's avatar
Mike Hearn committed
523

524
            HeapFree(GetProcessHeap(), 0, current_drive->unixpath);
Mike Hearn's avatar
Mike Hearn committed
525
            current_drive->unixpath = path ? path : strdupA("drive_c");
526
            current_drive->modified = TRUE;
Mike Hearn's avatar
Mike Hearn committed
527 528 529

            WINE_TRACE("set path to %s\n", current_drive->unixpath);

530
            lv_set_item_text(dialog, lv_get_curr_select(dialog), 1,
531 532
                             wpath);
            HeapFree(GetProcessHeap(), 0, wpath);
533 534

            /* enable the apply button  */
535
            SendMessageW(GetParent(dialog), PSM_CHANGED, (WPARAM) dialog, 0);
Mike Hearn's avatar
Mike Hearn committed
536 537 538 539 540 541 542 543
            break;
        }

        case IDC_EDIT_SERIAL:
        {
            char *serial;

            serial = get_text(dialog, id);
544 545
            current_drive->serial = serial ? strtoul( serial, NULL, 16 ) : 0;
            HeapFree(GetProcessHeap(), 0, serial);
546
            current_drive->modified = TRUE;
Mike Hearn's avatar
Mike Hearn committed
547

548
            WINE_TRACE("set serial to %08X\n", current_drive->serial);
Mike Hearn's avatar
Mike Hearn committed
549

550
            /* enable the apply button  */
551
            SendMessageW(GetParent(dialog), PSM_CHANGED, (WPARAM) dialog, 0);
Mike Hearn's avatar
Mike Hearn committed
552 553 554 555 556 557 558
            break;
        }

        case IDC_EDIT_DEVICE:
        {
            char *device = get_text(dialog, id);
            /* TODO: handle device if/when it makes sense to do so.... */
559
            HeapFree(GetProcessHeap(), 0, device);
Mike Hearn's avatar
Mike Hearn committed
560 561 562 563 564
            break;
        }
    }
}

565
BOOL browse_for_unix_folder(HWND dialog, WCHAR *pszPath)
566 567 568
{
    static WCHAR wszUnixRootDisplayName[] = 
        { ':',':','{','C','C','7','0','2','E','B','2','-','7','D','C','5','-','1','1','D','9','-',
569
          'C','6','8','7','-','0','0','0','4','2','3','8','A','0','1','C','D','}', 0 };
570 571
    WCHAR pszChoosePath[FILENAME_MAX];
    BROWSEINFOW bi = {
572 573 574
        dialog,
        NULL,
        NULL,
575
        pszChoosePath,
576 577 578 579 580 581 582 583
        0,
        NULL,
        0,
        0
    };
    IShellFolder *pDesktop;
    LPITEMIDLIST pidlUnixRoot, pidlSelectedPath;
    HRESULT hr;
584 585 586

    LoadStringW(GetModuleHandleW(NULL), IDS_CHOOSE_PATH, pszChoosePath, FILENAME_MAX);

587
    hr = SHGetDesktopFolder(&pDesktop);
588
    if (FAILED(hr)) return FALSE;
589

590 591
    hr = IShellFolder_ParseDisplayName(pDesktop, NULL, NULL, wszUnixRootDisplayName, NULL, 
                                       &pidlUnixRoot, NULL);
592
    if (FAILED(hr)) {
593
        IShellFolder_Release(pDesktop);
594
        return FALSE;
595 596 597
    }

    bi.pidlRoot = pidlUnixRoot;
598
    pidlSelectedPath = SHBrowseForFolderW(&bi);
599 600 601 602
    SHFree(pidlUnixRoot);
    
    if (pidlSelectedPath) {
        STRRET strSelectedPath;
603
        WCHAR *pszSelectedPath;
604 605
        HRESULT hr;
        
606 607 608
        hr = IShellFolder_GetDisplayNameOf(pDesktop, pidlSelectedPath, SHGDN_FORPARSING, 
                                           &strSelectedPath);
        IShellFolder_Release(pDesktop);
609
        if (FAILED(hr)) {
610
            SHFree(pidlSelectedPath);
611
            return FALSE;
612 613
        }

614
        hr = StrRetToStrW(&strSelectedPath, pidlSelectedPath, &pszSelectedPath);
615
        SHFree(pidlSelectedPath);
616
        if (FAILED(hr)) return FALSE;
617

618
        lstrcpyW(pszPath, pszSelectedPath);
619 620
        
        CoTaskMemFree(pszSelectedPath);
621
        return TRUE;
622
    }
623
    return FALSE;
624 625
}

626 627
static void init_listview_columns(HWND dialog)
{
628
    LVCOLUMNW listColumn;
629 630
    RECT viewRect;
    int width;
631
    WCHAR column[64];
632 633 634 635

    GetClientRect(GetDlgItem(dialog, IDC_LIST_DRIVES), &viewRect);
    width = (viewRect.right - viewRect.left) / 6 - 5;

636
    LoadStringW (GetModuleHandleW(NULL), IDS_COL_DRIVELETTER, column,
637
        sizeof(column)/sizeof(column[0]));
638
    listColumn.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
639 640
    listColumn.pszText = column;
    listColumn.cchTextMax = lstrlenW (listColumn.pszText);
641 642
    listColumn.cx = width;

643
    SendDlgItemMessageW (dialog, IDC_LIST_DRIVES, LVM_INSERTCOLUMNW, 0, (LPARAM) &listColumn);
644

645
    LoadStringW (GetModuleHandleW(NULL), IDS_COL_DRIVEMAPPING, column,
646
        sizeof(column)/sizeof(column[0]));
647
    listColumn.cx = viewRect.right - viewRect.left - width;
648 649
    listColumn.pszText = column;
    listColumn.cchTextMax = lstrlenW (listColumn.pszText);
650

651
    SendDlgItemMessageW (dialog, IDC_LIST_DRIVES, LVM_INSERTCOLUMNW, 1, (LPARAM) &listColumn);
652 653
}

654 655
static void load_drive_options(HWND dialog)
{
656
    if (!strcmp(get_reg_key(config_key, "", "ShowDotFiles", "N"), "Y"))
657 658
        CheckDlgButton(dialog, IDC_SHOW_DOT_FILES, BST_CHECKED);
}
659

Mike Hearn's avatar
Mike Hearn committed
660 661 662 663 664 665 666 667
INT_PTR CALLBACK
DriveDlgProc (HWND dialog, UINT msg, WPARAM wParam, LPARAM lParam)
{
    int item;

    switch (msg)
    {
        case WM_INITDIALOG:
668
            init_listview_columns(dialog);
669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
            if (!load_drives())
            {
                ShowWindow( GetDlgItem( dialog, IDC_STATIC_MOUNTMGR_ERROR ), SW_SHOW );
                ShowWindow( GetDlgItem( dialog, IDC_LIST_DRIVES ), SW_HIDE );
                ShowWindow( GetDlgItem( dialog, IDC_BUTTON_ADD ), SW_HIDE );
                ShowWindow( GetDlgItem( dialog, IDC_BUTTON_REMOVE ), SW_HIDE );
                ShowWindow( GetDlgItem( dialog, IDC_BUTTON_AUTODETECT ), SW_HIDE );
                ShowWindow( GetDlgItem( dialog, IDC_STATIC_PATH ), SW_HIDE );
                ShowWindow( GetDlgItem( dialog, IDC_EDIT_PATH ), SW_HIDE );
                ShowWindow( GetDlgItem( dialog, IDC_BUTTON_BROWSE_PATH ), SW_HIDE );
                ShowWindow( GetDlgItem( dialog, IDC_COMBO_TYPE ), SW_HIDE );
                ShowWindow( GetDlgItem( dialog, IDC_BUTTON_SHOW_HIDE_ADVANCED ), SW_HIDE );
                set_advanced(dialog);
                break;
            }
            ShowWindow( GetDlgItem( dialog, IDC_STATIC_MOUNTMGR_ERROR ), SW_HIDE );
685
            load_drive_options(dialog);
Mike Hearn's avatar
Mike Hearn committed
686 687

            if (!drives[2].in_use)
688
                driveui_msgbox (dialog, IDS_NO_DRIVE_C, MB_OK | MB_ICONEXCLAMATION);
Mike Hearn's avatar
Mike Hearn committed
689 690 691 692 693 694 695 696 697 698 699 700

            fill_drives_list(dialog);
            update_controls(dialog);
            /* put in non-advanced mode by default  */
            set_advanced(dialog);
            break;

        case WM_SHOWWINDOW:
            set_window_title(dialog);
            break;

        case WM_COMMAND:
701
            switch (HIWORD(wParam))
Mike Hearn's avatar
Mike Hearn committed
702
            {
703 704 705 706 707 708 709 710 711 712 713 714
                case EN_CHANGE:
                    on_edit_changed(dialog, LOWORD(wParam));
                    break;

                case BN_CLICKED:
                    switch (LOWORD(wParam))
                    {
                        case IDC_SHOW_DOT_FILES:
                            on_options_click(dialog);
                        break;
                    }
                    break;
715 716

                case CBN_SELCHANGE:
717
                    SendMessageW(GetParent(dialog), PSM_CHANGED, 0, 0);
718
                    break;
Mike Hearn's avatar
Mike Hearn committed
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
            }

            switch (LOWORD(wParam))
            {
                case IDC_BUTTON_ADD:
                    if (HIWORD(wParam) != BN_CLICKED) break;
                    on_add_click(dialog);
                    break;

                case IDC_BUTTON_REMOVE:
                    if (HIWORD(wParam) != BN_CLICKED) break;
                    on_remove_click(dialog);
                    break;

                case IDC_BUTTON_EDIT:
                    if (HIWORD(wParam) != BN_CLICKED) break;
735 736
                    item = SendMessageW(GetDlgItem(dialog, IDC_LIST_DRIVES),  LB_GETCURSEL, 0, 0);
                    SendMessageW(GetDlgItem(dialog, IDC_LIST_DRIVES), LB_GETITEMDATA, item, 0);
Mike Hearn's avatar
Mike Hearn committed
737 738 739 740 741
                    break;

                case IDC_BUTTON_AUTODETECT:
                    autodetect_drives();
                    fill_drives_list(dialog);
742
                    SendMessageW(GetParent(dialog), PSM_CHANGED, 0, 0);
Mike Hearn's avatar
Mike Hearn committed
743 744 745 746 747 748 749 750
                    break;

                case IDC_BUTTON_SHOW_HIDE_ADVANCED:
                    advanced = !advanced;
                    set_advanced(dialog);
                    break;

                case IDC_BUTTON_BROWSE_PATH:
751
                {
752
                    WCHAR szTargetPath[FILENAME_MAX];
753
                    if (browse_for_unix_folder(dialog, szTargetPath)) 
754
                        set_textW(dialog, IDC_EDIT_PATH, szTargetPath);
Mike Hearn's avatar
Mike Hearn committed
755
                    break;
756
                }
Mike Hearn's avatar
Mike Hearn committed
757 758 759 760 761 762 763 764

                case IDC_COMBO_TYPE:
                {
                    int mode = BOX_MODE_NORMAL;
                    int selection;

                    if (HIWORD(wParam) != CBN_SELCHANGE) break;

765
                    selection = SendDlgItemMessageW(dialog, IDC_COMBO_TYPE, CB_GETCURSEL, 0, 0);
Mike Hearn's avatar
Mike Hearn committed
766

767 768 769
                    if (selection >= 0 &&
                        (type_pairs[selection].sCode == DRIVE_CDROM ||
                         type_pairs[selection].sCode == DRIVE_REMOVABLE))
770 771 772
                        mode = BOX_MODE_DEVICE;
                    else
                        mode = BOX_MODE_NORMAL;
Mike Hearn's avatar
Mike Hearn committed
773 774 775 776

                    enable_labelserial_box(dialog, mode);

                    current_drive->type = type_pairs[selection].sCode;
777
                    current_drive->modified = TRUE;
Mike Hearn's avatar
Mike Hearn committed
778 779 780 781 782 783 784 785 786 787 788
                    break;
                }

            }
            break;

        case WM_NOTIFY:
            switch (((LPNMHDR)lParam)->code)
            {
                case PSN_KILLACTIVE:
                    WINE_TRACE("PSN_KILLACTIVE\n");
789
                    SetWindowLongPtrW(dialog, DWLP_MSGRESULT, FALSE);
Mike Hearn's avatar
Mike Hearn committed
790 791 792
                    break;
                case PSN_APPLY:
                    apply_drive_changes();
793
                    SetWindowLongPtrW(dialog, DWLP_MSGRESULT, PSNRET_NOERROR);
Mike Hearn's avatar
Mike Hearn committed
794 795 796
                    break;
                case PSN_SETACTIVE:
                    break;
797 798 799 800 801
                case LVN_ITEMCHANGED:
                {
                    LPNMLISTVIEW lpnm = (LPNMLISTVIEW)lParam;
                    if (!(lpnm->uOldState & LVIS_SELECTED) &&
                         (lpnm->uNewState & LVIS_SELECTED))
802 803
                    update_controls(dialog);
                    break;
804
                }
805
            }
Mike Hearn's avatar
Mike Hearn committed
806 807 808 809 810
            break;
    }

    return FALSE;
}