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