tab-drives-20040319
[openafs.git] / src / WINNT / client_config / tab_drives.cpp
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 extern "C" {
11 #include <afs/param.h>
12 #include <afs/stds.h>
13 #include <afs/fs_utils.h>
14 }
15
16 #include "afs_config.h"
17 #include "tab_drives.h"
18 #include <lanahelper.h>
19
20 /*
21  * PROTOTYPES _________________________________________________________________
22  *
23  */
24
25 void DrivesTab_OnInitDialog (HWND hDlg);
26 void DrivesTab_OnSelect (HWND hDlg);
27 void DrivesTab_OnCheck (HWND hDlg);
28 void DrivesTab_OnAdd (HWND hDlg);
29 void DrivesTab_OnEdit (HWND hDlg);
30 void DrivesTab_OnRemove (HWND hDlg);
31 void DrivesTab_OnAdvanced (HWND hDlg);
32
33 void DrivesTab_Enable (HWND hDlg);
34 int DrivesTab_DriveFromItem (HWND hDlg, int iItem);
35 void DrivesTab_FillList (HWND hDlg);
36 void DrivesTab_EditMapping (HWND hDlg, int iDrive);
37
38 BOOL CALLBACK DriveEdit_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
39 void DriveEdit_OnInitDialog (HWND hDlg);
40 void DriveEdit_OnOK (HWND hDlg);
41 void DriveEdit_Enable (HWND hDlg);
42
43 BOOL CALLBACK Submounts_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
44 void Submounts_OnInitDialog (HWND hDlg);
45 void Submounts_OnApply (HWND hDlg);
46 void Submounts_OnSelect (HWND hDlg);
47 void Submounts_OnAdd (HWND hDlg);
48 void Submounts_OnEdit (HWND hDlg);
49 void Submounts_OnRemove (HWND hDlg);
50 void Submounts_EditSubmount (HWND hDlg, PSUBMOUNT pSubmount);
51
52 BOOL CALLBACK SubEdit_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
53 void SubEdit_OnInitDialog (HWND hDlg);
54 void SubEdit_OnOK (HWND hDlg);
55 void SubEdit_Enable (HWND hDlg);
56
57
58 /*
59  * ROUTINES ___________________________________________________________________
60  *
61  */
62
63 BOOL CALLBACK DrivesTab_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
64 {
65    switch (msg)
66       {
67       case WM_INITDIALOG:
68          DrivesTab_OnInitDialog (hDlg);
69          break;
70
71       case WM_COMMAND:
72          switch (LOWORD(wp))
73             {
74             case IDC_REFRESH:
75                DrivesTab_Enable (hDlg);
76                break;
77
78             case IDC_LIST:
79                if (HIWORD(wp) == LBN_CLICKED)
80                   DrivesTab_OnCheck (hDlg);
81                else if ((HIWORD(wp) == LBN_SELCHANGE) || (HIWORD(wp) == LBN_SELCANCEL))
82                   DrivesTab_OnSelect (hDlg);
83                break;
84
85             case IDC_ADD:
86                DrivesTab_OnAdd (hDlg);
87                break;
88
89             case IDC_EDIT:
90                DrivesTab_OnEdit (hDlg);
91                break;
92
93             case IDC_REMOVE:
94                DrivesTab_OnRemove (hDlg);
95                break;
96
97             case IDC_ADVANCED:
98                DrivesTab_OnAdvanced (hDlg);
99                break;
100
101             case IDHELP:
102                DrivesTab_DlgProc (hDlg, WM_HELP, 0, 0);
103                break;
104             }
105          break;
106
107       case WM_HELP:
108          WinHelp (hDlg, g.szHelpFile, HELP_CONTEXT, IDH_AFSCONFIG_DRIVES);
109          break;
110       }
111
112    return FALSE;
113 }
114
115
116 void DrivesTab_OnInitDialog (HWND hDlg)
117 {
118    ShowWindow (GetDlgItem (hDlg, IDC_ADVANCED), g.fIsWinNT);
119
120    DrivesTab_FillList (hDlg);
121 }
122
123
124 void DrivesTab_OnSelect (HWND hDlg)
125 {
126    if (IsWindowEnabled (GetDlgItem (hDlg, IDC_LIST)))
127       {
128       UINT iSel = SendDlgItemMessage (hDlg, IDC_LIST, LB_GETCURSEL, 0, 0);
129
130       EnableWindow (GetDlgItem (hDlg, IDC_EDIT), (iSel != -1));
131       EnableWindow (GetDlgItem (hDlg, IDC_REMOVE), (iSel != -1));
132       }
133 }
134
135
136 void DrivesTab_OnCheck (HWND hDlg)
137 {
138    HWND hList = GetDlgItem (hDlg, IDC_LIST);
139    int iItemSel = SendMessage (hList, LB_GETCURSEL, 0, 0);
140    int iDriveSel = DrivesTab_DriveFromItem (hDlg, iItemSel);
141    BOOL fChecked = SendMessage (hList, LB_GETITEMDATA, iItemSel, 0);
142
143    if (iDriveSel != -1)
144       {
145       DWORD dwStatus;
146       if (fChecked && g.Configuration.NetDrives.aDriveMap[ iDriveSel ].szMapping[0] && !g.Configuration.NetDrives.aDriveMap[ iDriveSel ].fActive)
147          {
148          if (!ActivateDriveMap (g.Configuration.NetDrives.aDriveMap[ iDriveSel ].chDrive, g.Configuration.NetDrives.aDriveMap[ iDriveSel ].szMapping, g.Configuration.NetDrives.aDriveMap[ iDriveSel ].szSubmount, g.Configuration.NetDrives.aDriveMap[ iDriveSel ].fPersistent, &dwStatus))
149             Message (MB_OK | MB_ICONHAND, IDS_ERROR_MAP, IDS_ERROR_MAP_DESC, TEXT("%08lX"), dwStatus);
150          DrivesTab_FillList (hDlg);
151          }
152       else if (!fChecked && g.Configuration.NetDrives.aDriveMap[ iDriveSel ].fActive)
153          {
154          if (!InactivateDriveMap (g.Configuration.NetDrives.aDriveMap[ iDriveSel ].chDrive, &dwStatus))
155             Message (MB_OK | MB_ICONHAND, IDS_ERROR_UNMAP, IDS_ERROR_UNMAP_DESC, TEXT("%08lX"), dwStatus);
156          DrivesTab_FillList (hDlg);
157          }
158       }
159 }
160
161
162 void DrivesTab_OnAdd (HWND hDlg)
163 {
164    DrivesTab_EditMapping (hDlg, -1);
165 }
166
167
168 void DrivesTab_OnEdit (HWND hDlg)
169 {
170    HWND hList = GetDlgItem (hDlg, IDC_LIST);
171    int iItemSel = SendMessage (hList, LB_GETCURSEL, 0, 0);
172    int iDriveSel = DrivesTab_DriveFromItem (hDlg, iItemSel);
173
174    DrivesTab_EditMapping (hDlg, iDriveSel);
175 }
176
177
178 void DrivesTab_OnRemove (HWND hDlg)
179 {
180    HWND hList = GetDlgItem (hDlg, IDC_LIST);
181    int iItemSel = SendMessage (hList, LB_GETCURSEL, 0, 0);
182    int iDriveSel = DrivesTab_DriveFromItem (hDlg, iItemSel);
183
184    if (iDriveSel != -1)
185       {
186       if (g.Configuration.NetDrives.aDriveMap[ iDriveSel ].szMapping[0])
187          {
188          if (g.Configuration.NetDrives.aDriveMap[ iDriveSel ].fActive)
189             {
190             DWORD dwStatus;
191             if (!InactivateDriveMap (g.Configuration.NetDrives.aDriveMap[ iDriveSel ].chDrive, &dwStatus))
192                {
193                Message (MB_OK | MB_ICONHAND, IDS_ERROR_UNMAP, IDS_ERROR_UNMAP_DESC, TEXT("%08lX"), dwStatus);
194                return;
195                }
196             }
197          g.Configuration.NetDrives.aDriveMap[ iDriveSel ].szMapping[0] = TEXT('\0');
198          WriteDriveMappings (&g.Configuration.NetDrives);
199
200          DrivesTab_FillList (hDlg);
201          }
202       }
203 }
204
205
206 void DrivesTab_OnAdvanced (HWND hDlg)
207 {
208    TCHAR szTitle[ cchRESOURCE ];
209    GetString (szTitle, IDS_SUBMOUNTS_TITLE);
210
211    LPPROPSHEET psh = PropSheet_Create (szTitle, FALSE, GetParent(hDlg), 0);
212    psh->sh.dwFlags |= PSH_NOAPPLYNOW;  // Remove the Apply button
213    psh->sh.dwFlags |= PSH_HASHELP;     // Add a Help button instead
214    PropSheet_AddTab (psh, szTitle, IDD_SUBMOUNTS, (DLGPROC)Submounts_DlgProc, 0, TRUE);
215    PropSheet_ShowModal (psh);
216 }
217
218
219 void DrivesTab_Enable (HWND hDlg)
220 {
221    BOOL fRunning = (Config_GetServiceState() == SERVICE_RUNNING);
222
223    EnableWindow (GetDlgItem (hDlg, IDC_LIST), fRunning);
224    EnableWindow (GetDlgItem (hDlg, IDC_ADD), fRunning);
225    EnableWindow (GetDlgItem (hDlg, IDC_EDIT), fRunning);
226    EnableWindow (GetDlgItem (hDlg, IDC_REMOVE), fRunning);
227
228    TCHAR szText[ cchRESOURCE ];
229    GetString (szText, (fRunning) ? IDS_TIP_DRIVES : IDS_WARN_STOPPED);
230    SetDlgItemText (hDlg, IDC_WARN, szText);
231 }
232
233
234 int DrivesTab_DriveFromItem (HWND hDlg, int iItem)
235 {
236    TCHAR szItem[ 1024 ] = TEXT("");
237    SendDlgItemMessage (hDlg, IDC_LIST, LB_GETTEXT, iItem, (LPARAM)szItem);
238
239    LPTSTR pch;
240    if ((pch = (LPTSTR)lstrchr (szItem, TEXT(':'))) != NULL)
241       {
242       if (pch > szItem)
243          {
244          pch--;
245          if ((*pch >= TEXT('A')) && (*pch <= TEXT('Z')))
246             return (*pch) - TEXT('A');
247          }
248       }
249
250    return -1;
251 }
252
253
254 void DrivesTab_FillList (HWND hDlg)
255 {
256    FreeDriveMapList (&g.Configuration.NetDrives);
257    QueryDriveMapList (&g.Configuration.NetDrives);
258
259    HWND hList = GetDlgItem (hDlg, IDC_LIST);
260    int iItemSel = SendMessage (hList, LB_GETCURSEL, 0, 0);
261    int iDriveSel = DrivesTab_DriveFromItem (hDlg, iItemSel);
262    SendMessage (hList, WM_SETREDRAW, FALSE, 0);
263    SendMessage (hList, LB_RESETCONTENT, 0, 0);
264
265    iItemSel = -1;
266
267    for (int iDrive = 0; iDrive < 26; ++iDrive)
268       {
269       if (!g.Configuration.NetDrives.aDriveMap[ iDrive ].szMapping[0])
270          continue;
271
272       TCHAR szAfsPath[ MAX_PATH ];
273       AdjustAfsPath (szAfsPath, g.Configuration.NetDrives.aDriveMap[ iDrive ].szMapping, TRUE, FALSE);
274
275       LPTSTR psz = FormatString (IDS_DRIVE_MAP, TEXT("%c%s"), g.Configuration.NetDrives.aDriveMap[ iDrive ].chDrive, szAfsPath);
276       int iItem = SendMessage (hList, LB_ADDSTRING, 0, (LPARAM)psz);
277       SendMessage (hList, LB_SETITEMDATA, iItem, g.Configuration.NetDrives.aDriveMap[ iDrive ].fActive);
278
279       if (iDrive == iDriveSel)
280          iItemSel = iItem;
281       }
282
283    SendMessage (hList, WM_SETREDRAW, TRUE, 0);
284    if (iItemSel != -1)
285       SendMessage (hList, LB_SETCURSEL, iItemSel, 0);
286
287    DrivesTab_Enable (hDlg);
288    DrivesTab_OnSelect (hDlg);
289 }
290
291
292 void DrivesTab_EditMapping (HWND hDlg, int iDrive)
293 {
294    DRIVEMAP DriveMapOrig;
295    memset (&DriveMapOrig, 0x00, sizeof(DRIVEMAP));
296
297    if (iDrive != -1)
298       {
299       memcpy (&DriveMapOrig, &g.Configuration.NetDrives.aDriveMap[ iDrive ], sizeof(DRIVEMAP));
300       }
301
302    DRIVEMAP DriveMap;
303    memcpy (&DriveMap, &DriveMapOrig, sizeof(DRIVEMAP));
304
305    if (ModalDialogParam (IDD_DRIVE_EDIT, GetParent(hDlg), (DLGPROC)DriveEdit_DlgProc, (LPARAM)&DriveMap) == IDOK)
306       {
307       TCHAR szAfsPathOrig[ MAX_PATH ] = TEXT("");
308       if (iDrive != -1)
309          AdjustAfsPath (szAfsPathOrig, DriveMapOrig.szMapping, TRUE, TRUE);
310
311       TCHAR szAfsPathNew[ MAX_PATH ];
312       AdjustAfsPath (szAfsPathNew, DriveMap.szMapping, TRUE, TRUE);
313
314       if ( (lstrcmpi (szAfsPathOrig, szAfsPathNew)) ||
315            (lstrcmpi (DriveMapOrig.szSubmount, DriveMap.szSubmount)) ||
316            (DriveMapOrig.chDrive != DriveMap.chDrive) ||
317            (DriveMapOrig.fPersistent != DriveMap.fPersistent) )
318          {
319          DWORD dwStatus;
320
321          if ((iDrive != -1) && (DriveMapOrig.fActive))
322             {
323             if (!InactivateDriveMap (DriveMapOrig.chDrive, &dwStatus))
324                {
325                Message (MB_OK | MB_ICONHAND, IDS_ERROR_UNMAP, IDS_ERROR_UNMAP_DESC, TEXT("%08lX"), dwStatus);
326                DrivesTab_FillList (hDlg);
327                return;
328                }
329             }
330
331          if (!ActivateDriveMap (DriveMap.chDrive, szAfsPathNew, DriveMap.szSubmount, DriveMap.fPersistent, &dwStatus))
332             {
333             Message (MB_OK | MB_ICONHAND, IDS_ERROR_MAP, IDS_ERROR_MAP_DESC, TEXT("%08lX"), dwStatus);
334             DrivesTab_FillList (hDlg);
335             return;
336             }
337
338          if (DriveMap.szSubmount[0])
339             {
340             TCHAR szSubmountNow[ MAX_PATH ];
341             if (GetDriveSubmount (DriveMap.chDrive, szSubmountNow))
342                {
343                if (lstrcmpi (DriveMap.szSubmount, szSubmountNow))
344                   Message (MB_OK | MB_ICONASTERISK, GetCautionTitle(), IDS_NEWSUB_DESC);
345                }
346             }
347
348          if (iDrive != -1)
349             memset (&g.Configuration.NetDrives.aDriveMap[ iDrive ], 0x00, sizeof(DRIVEMAP));
350          memcpy (&g.Configuration.NetDrives.aDriveMap[ DriveMap.chDrive-chDRIVE_A ], &DriveMap, sizeof(DRIVEMAP));
351          lstrcpy (g.Configuration.NetDrives.aDriveMap[ DriveMap.chDrive-chDRIVE_A ].szMapping, szAfsPathNew);
352          WriteDriveMappings (&g.Configuration.NetDrives);
353
354          DrivesTab_FillList (hDlg);
355          }
356       }
357 }
358
359
360 BOOL CALLBACK DriveEdit_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
361 {
362    switch (msg)
363       {
364       case WM_INITDIALOG:
365          SetWindowLong (hDlg, DWL_USER, lp);
366          DriveEdit_OnInitDialog (hDlg);
367          break;
368
369       case WM_COMMAND:
370          switch (LOWORD(wp))
371             {
372             case IDOK:
373                DriveEdit_OnOK (hDlg);
374                break;
375
376             case IDCANCEL:
377                EndDialog (hDlg, IDCANCEL);
378                break;
379
380             case IDC_PATH:
381                DriveEdit_Enable (hDlg);
382                break;
383
384             case IDHELP:
385                DriveEdit_DlgProc (hDlg, WM_HELP, 0, 0);
386                break;
387             }
388          break;
389
390       case WM_HELP:
391          WinHelp (hDlg, g.szHelpFile, HELP_CONTEXT, IDH_AFSCONFIG_DRIVES_ADDEDIT);
392          break;
393       }
394    return FALSE;
395 }
396
397 void DriveEdit_OnInitDialog (HWND hDlg)
398 {
399    PDRIVEMAP pMap = (PDRIVEMAP)GetWindowLong (hDlg, DWL_USER);
400
401    // Fill in the combo box
402    //
403    DWORD dwDrives = GetLogicalDrives() | 0x07; // Always pretend A,B,C: are used
404
405    if (pMap->chDrive != 0)
406       dwDrives &= ~( 1 << (pMap->chDrive - chDRIVE_A) );
407
408    int iItemSel = -1;
409    HWND hCombo = GetDlgItem (hDlg, IDC_DRIVE);
410    SendMessage (hCombo, WM_SETREDRAW, FALSE, 0);
411
412    for (int ii = 0; ii < 26; ++ii)
413       {
414       if (!(dwDrives & (1<<ii)))
415          {
416          TCHAR szText[ cchRESOURCE ];
417          GetString (szText, IDS_MAP_LETTER);
418
419          LPTSTR pch;
420          if ((pch = (LPTSTR)lstrchr (szText, TEXT('*'))) != NULL)
421             *pch = TEXT('A') + ii;
422
423          int iItem = SendMessage (hCombo, CB_ADDSTRING, 0, (LPARAM)szText);
424          SendMessage (hCombo, CB_SETITEMDATA, iItem, ii);
425          if (pMap->chDrive && (ii == pMap->chDrive - chDRIVE_A))
426             iItemSel = iItem;
427          else if ((!pMap->chDrive) && (iItemSel == -1))
428             iItemSel = iItem;
429          }
430       }
431
432    SendMessage (hCombo, WM_SETREDRAW, TRUE, 0);
433    SendMessage (hCombo, CB_SETCURSEL, iItemSel, 0);
434
435    TCHAR szMapping[ MAX_PATH ];
436    AdjustAfsPath (szMapping, ((pMap->szMapping[0]) ? pMap->szMapping : cm_slash_mount_root), TRUE, FALSE);
437    
438    CHAR msg[256], msgf[256];
439    if (GetDlgItemText(hDlg,IDC_STATICSUBMOUNT,(LPSTR)msg,sizeof(msg)-1)>0)
440    {
441        wsprintf(msgf,msg,cm_back_slash_mount_root,cm_back_slash_mount_root);
442        SetDlgItemText (hDlg, IDC_STATICSUBMOUNT, msgf);
443    }
444    SetDlgItemText (hDlg, IDC_PATH, szMapping);
445    SetDlgItemText (hDlg, IDC_DESC, pMap->szSubmount);
446
447    CheckDlgButton (hDlg, IDC_PERSISTENT, (pMap->chDrive == 0) ? TRUE : (pMap->fPersistent));
448
449    DriveEdit_Enable (hDlg);
450 }
451
452
453 void DriveEdit_OnOK (HWND hDlg)
454 {
455    PDRIVEMAP pMap = (PDRIVEMAP)GetWindowLong (hDlg, DWL_USER);
456
457    int iItem = SendDlgItemMessage (hDlg, IDC_DRIVE, CB_GETCURSEL, 0, 0);
458    int iDrive = SendDlgItemMessage (hDlg, IDC_DRIVE, CB_GETITEMDATA, iItem, 0);
459
460    pMap->chDrive = chDRIVE_A + iDrive;
461    GetDlgItemText (hDlg, IDC_PATH, pMap->szMapping, MAX_PATH);
462    GetDlgItemText (hDlg, IDC_DESC, pMap->szSubmount, MAX_PATH);
463    pMap->fPersistent = IsDlgButtonChecked (hDlg, IDC_PERSISTENT);
464
465    if (pMap->szSubmount[0] && !IsValidSubmountName (pMap->szSubmount))
466       {
467       Message (MB_ICONHAND, GetErrorTitle(), IDS_BADSUB_DESC);
468       return;
469       }
470
471     if ( (lstrncmpi (pMap->szMapping, cm_slash_mount_root, lstrlen(cm_slash_mount_root))) &&
472          (lstrncmpi (pMap->szMapping, cm_back_slash_mount_root, lstrlen(cm_back_slash_mount_root))) )
473     {
474       Message (MB_ICONHAND, GetErrorTitle(), IDS_BADMAP_DESC);
475       return;
476       }
477
478    EndDialog (hDlg, IDOK);
479 }
480
481
482 void DriveEdit_Enable (HWND hDlg)
483 {
484    TCHAR szPath[ MAX_PATH ];
485    GetDlgItemText (hDlg, IDC_PATH, szPath, MAX_PATH);
486    EnableWindow (GetDlgItem (hDlg, IDOK), (szPath[0] != TEXT('\0')));
487 }
488
489
490 BOOL CALLBACK Submounts_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
491 {
492    switch (msg)
493       {
494       case WM_INITDIALOG:
495          Submounts_OnInitDialog (hDlg);
496          break;
497
498       case WM_COMMAND:
499          switch (LOWORD(wp))
500             {
501             case IDAPPLY:
502                Submounts_OnApply (hDlg);
503                break;
504
505             case IDC_ADD:
506                Submounts_OnAdd (hDlg);
507                break;
508
509             case IDC_EDIT:
510                Submounts_OnEdit (hDlg);
511                break;
512
513             case IDC_REMOVE:
514                Submounts_OnRemove (hDlg);
515                break;
516
517             case IDHELP:
518                Submounts_DlgProc (hDlg, WM_HELP, 0, 0);
519                break;
520             }
521          break;
522
523       case WM_HELP:
524          WinHelp (hDlg, g.szHelpFile, HELP_CONTEXT, IDH_AFSCONFIG_SUBMOUNTS_NT);
525          break;
526
527       case WM_NOTIFY:
528          switch (((LPNMHDR)lp)->code)
529             {
530             case FLN_ITEMSELECT:
531                Submounts_OnSelect (hDlg);
532                break;
533
534             case FLN_LDBLCLICK:
535                if (IsWindowEnabled (GetDlgItem (hDlg, IDC_EDIT)))
536                   Submounts_OnEdit (hDlg);
537                break;
538             }
539          break;
540       }
541
542    return FALSE;
543 }
544
545
546 void Submounts_OnInitDialog (HWND hDlg)
547 {
548    // Prepare the columns on the server list
549    //
550    HWND hList = GetDlgItem (hDlg, IDC_LIST);
551
552    FASTLISTCOLUMN Column;
553    Column.dwFlags = FLCF_JUSTIFY_LEFT;
554    Column.cxWidth = 100;
555    GetString (Column.szText, IDS_SUBCOL_SHARE);
556    FastList_SetColumn (hList, 0, &Column);
557
558    Column.dwFlags = FLCF_JUSTIFY_LEFT;
559    Column.cxWidth = 200;
560    GetString (Column.szText, IDS_SUBCOL_PATH);
561    FastList_SetColumn (hList, 1, &Column);
562
563    // Remove the Context Help [?] thing from the title bar
564    //
565    DWORD dwStyle = GetWindowLong (GetParent (hDlg), GWL_STYLE);
566    dwStyle &= ~DS_CONTEXTHELP;
567    SetWindowLong (GetParent (hDlg), GWL_STYLE, dwStyle);
568
569    dwStyle = GetWindowLong (GetParent (hDlg), GWL_EXSTYLE);
570    dwStyle &= ~WS_EX_CONTEXTHELP;
571    SetWindowLong (GetParent (hDlg), GWL_EXSTYLE, dwStyle);
572
573    // Fill in the list of submounts
574    //
575    FastList_Begin (hList);
576
577    for (size_t ii = 0; ii < g.Configuration.NetDrives.cSubmounts; ++ii)
578       {
579       if (!g.Configuration.NetDrives.aSubmounts[ ii ].szSubmount[0])
580          continue;
581
582       FASTLISTADDITEM ai;
583       memset (&ai, 0x00, sizeof(FASTLISTADDITEM));
584       ai.iFirstImage = IMAGE_NOIMAGE;
585       ai.iSecondImage = IMAGE_NOIMAGE;
586       ai.pszText = g.Configuration.NetDrives.aSubmounts[ ii ].szSubmount;
587       ai.lParam = 0;
588       HLISTITEM hItem = FastList_AddItem (hList, &ai);
589
590       TCHAR szMapping[ MAX_PATH ];
591       AdjustAfsPath (szMapping, g.Configuration.NetDrives.aSubmounts[ ii ].szMapping, TRUE, FALSE);
592       FastList_SetItemText (hList, hItem, 1, szMapping);
593       }
594
595    FastList_End (hList);
596    Submounts_OnSelect (hDlg);
597 }
598
599
600 void Submounts_OnApply (HWND hDlg)
601 {
602    HWND hList = GetDlgItem (hDlg, IDC_LIST);
603
604    // Remove our current list of submounts
605    //
606    for (size_t ii = 0; ii < g.Configuration.NetDrives.cSubmounts; ++ii)
607       {
608       RemoveSubMount (g.Configuration.NetDrives.aSubmounts[ ii ].szSubmount);
609       }
610
611    // Add back all our new submounts
612    //
613    HLISTITEM hItem;
614    for (hItem = FastList_FindFirst (hList); hItem; hItem = FastList_FindNext (hList, hItem))
615       {
616       LPCTSTR pszSubmount;
617       if ((pszSubmount = FastList_GetItemText (hList, hItem, 0)) == NULL)
618          continue;
619       LPCTSTR pszMapping;
620       if ((pszMapping = FastList_GetItemText (hList, hItem, 1)) == NULL)
621          continue;
622
623       AddSubMount ((LPTSTR)pszSubmount, (LPTSTR)pszMapping);
624       }
625
626    FreeDriveMapList (&g.Configuration.NetDrives);
627    QueryDriveMapList (&g.Configuration.NetDrives);
628    if (g.Configuration.fLogonAuthent)
629            DoMapShareChange();
630 }
631
632
633 void Submounts_OnSelect (HWND hDlg)
634 {
635    HWND hList = GetDlgItem (hDlg, IDC_LIST);
636
637    size_t cSelected = 0;
638    size_t cSelectedInUse = 0;
639
640    HLISTITEM hItem;
641    for (hItem = FastList_FindFirstSelected (hList); hItem; hItem = FastList_FindNextSelected (hList, hItem))
642       {
643       cSelected++;
644
645       LPCTSTR pszSubmount;
646       if ((pszSubmount = FastList_GetItemText (hList, hItem, 0)) != NULL)
647          {
648          for (size_t ii = 0; ii < g.Configuration.NetDrives.cSubmounts; ++ii)
649             {
650             if (!lstrcmpi (pszSubmount, g.Configuration.NetDrives.aSubmounts[ii].szSubmount))
651                {
652                if (g.Configuration.NetDrives.aSubmounts[ii].fInUse)
653                   cSelectedInUse++;
654                }
655             }
656          }
657       }
658
659    EnableWindow (GetDlgItem (hDlg, IDC_REMOVE), (cSelected != 0) && (!cSelectedInUse));
660    EnableWindow (GetDlgItem (hDlg, IDC_EDIT), (cSelected == 1) && (!cSelectedInUse));
661 }
662
663
664 void Submounts_OnAdd (HWND hDlg)
665 {
666    HWND hList = GetDlgItem (hDlg, IDC_LIST);
667
668    SUBMOUNT Submount;
669    memset (&Submount, 0x00, sizeof(Submount));
670
671    Submounts_EditSubmount (hDlg, &Submount);
672 }
673
674
675 void Submounts_OnEdit (HWND hDlg)
676 {
677    HWND hList = GetDlgItem (hDlg, IDC_LIST);
678
679    HLISTITEM hItem;
680    if ((hItem = FastList_FindFirstSelected (hList)) != NULL)
681       {
682       LPCTSTR pszSubmount = FastList_GetItemText (hList, hItem, 0);
683       LPCTSTR pszMapping = FastList_GetItemText (hList, hItem, 1);
684
685       SUBMOUNT Submount;
686       memset (&Submount, 0x00, sizeof(Submount));
687       lstrcpy (Submount.szSubmount, pszSubmount);
688       lstrcpy (Submount.szMapping, pszMapping);
689
690       Submounts_EditSubmount (hDlg, &Submount);
691       }
692 }
693
694 // Action - On Remove submount item
695
696 void Submounts_OnRemove (HWND hDlg)
697 {
698    HWND hList = GetDlgItem (hDlg, IDC_LIST);
699    FastList_Begin (hList);
700
701    HLISTITEM hItem;
702    while ((hItem = FastList_FindFirstSelected (hList)) != NULL)
703       {
704       FastList_RemoveItem (hList, hItem);
705       }
706
707    FastList_End (hList);
708 }
709
710
711 // Action - On Add or On Edit a submount item
712 void Submounts_EditSubmount (HWND hDlg, PSUBMOUNT pSubmount)
713 {
714    HWND hList = GetDlgItem (hDlg, IDC_LIST);
715
716    if (ModalDialogParam (IDD_SUBMOUNT_EDIT, GetParent(hDlg), (DLGPROC)SubEdit_DlgProc, (LPARAM)pSubmount) == IDOK)
717       {
718       TCHAR szMapping[ MAX_PATH ];
719       AdjustAfsPath (szMapping, pSubmount->szMapping, TRUE, FALSE);
720
721       HLISTITEM hItem;
722       for (hItem = FastList_FindFirst (hList); hItem; hItem = FastList_FindNext (hList, hItem))
723          {
724          LPCTSTR pszSubmount;
725          if ((pszSubmount = FastList_GetItemText (hList, hItem, 0)) == NULL)
726             continue;
727
728          if (!lstrcmpi (pszSubmount, pSubmount->szSubmount))
729             break;
730          }
731
732       if (!hItem)
733          {
734          FASTLISTADDITEM ai;
735          memset (&ai, 0x00, sizeof(FASTLISTADDITEM));
736          ai.iFirstImage = IMAGE_NOIMAGE;
737          ai.iSecondImage = IMAGE_NOIMAGE;
738          ai.pszText = pSubmount->szSubmount;
739          ai.lParam = 0;
740          hItem = FastList_AddItem (hList, &ai);
741          }
742
743       FastList_SetItemText (hList, hItem, 1, szMapping);
744       }
745 }
746
747
748 BOOL CALLBACK SubEdit_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
749 {
750    switch (msg)
751       {
752       case WM_INITDIALOG:
753          SetWindowLong (hDlg, DWL_USER, lp);
754          SubEdit_OnInitDialog (hDlg);
755          SubEdit_Enable (hDlg);
756          break;
757
758       case WM_COMMAND:
759          switch (LOWORD(wp))
760             {
761             case IDOK:
762                SubEdit_OnOK (hDlg);
763                break;
764
765             case IDCANCEL:
766                EndDialog (hDlg, IDCANCEL);
767                break;
768
769             case IDC_SUBMOUNT:
770             case IDC_MAPPING:
771                SubEdit_Enable (hDlg);
772                break;
773
774             case IDHELP:
775                SubEdit_DlgProc (hDlg, WM_HELP, 0, 0);
776                break;
777             }
778          break;
779
780       case WM_HELP:
781          WinHelp (hDlg, g.szHelpFile, HELP_CONTEXT, IDH_AFSCONFIG_SUBMOUNTS_NT_ADDEDIT);
782          break;
783       }
784
785    return 0;
786 }
787
788
789 void SubEdit_OnInitDialog (HWND hDlg)
790 {
791     CHAR msg[256], msgf[256];
792     PSUBMOUNT pSubmount = (PSUBMOUNT)GetWindowLong (hDlg, DWL_USER);
793     if (GetDlgItemText(hDlg,IDC_STATICSUBMOUNT,(LPSTR)msg,sizeof(msg)-1)>0)
794     {
795                 wsprintf(msgf,msg,cm_back_slash_mount_root,cm_back_slash_mount_root);
796                 SetDlgItemText (hDlg, IDC_STATICSUBMOUNT, msgf);
797    }
798
799    SetDlgItemText (hDlg, IDC_SUBMOUNT, pSubmount->szSubmount);
800    
801    SetDlgItemText (hDlg, IDC_MAPPING, pSubmount->szMapping);
802 }
803
804
805 void SubEdit_OnOK (HWND hDlg)
806 {
807    PSUBMOUNT pSubmount = (PSUBMOUNT)GetWindowLong (hDlg, DWL_USER);
808    GetDlgItemText (hDlg, IDC_SUBMOUNT, pSubmount->szSubmount, MAX_PATH);
809    GetDlgItemText (hDlg, IDC_MAPPING, pSubmount->szMapping, MAX_PATH);
810    EndDialog (hDlg, IDOK);
811 }
812
813
814 void SubEdit_Enable (HWND hDlg)
815 {
816    BOOL fEnable = TRUE;
817
818    TCHAR szText[ MAX_PATH ];
819    GetDlgItemText (hDlg, IDC_SUBMOUNT, szText, MAX_PATH);
820    if (!szText[0])
821       fEnable = FALSE;
822
823    GetDlgItemText (hDlg, IDC_MAPPING, szText, MAX_PATH);
824    if (!szText[0])
825       fEnable = FALSE;
826
827    EnableWindow (GetDlgItem (hDlg, IDOK), fEnable);
828 }
829