global-mapping-20040325
[openafs.git] / src / WINNT / client_config / dlg_automap.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 <stdio.h>
18 #include <lanahelper.h>
19
20 /*
21  * DEFINITIONS ________________________________________________________________
22  *
23  */
24 static DRIVEMAPLIST GlobalDrives;
25 static TCHAR szHostName[128];
26
27 // DefineDosDrive actions
28 enum DDDACTION  { DDD_ADD, DDD_REMOVE };
29
30 #define DRIVE_LETTER_INDEX 2
31
32
33 /*
34  * PROTOTYPES _________________________________________________________________
35  *
36  */
37 void AutoMap_OnInitDialog (HWND hDlg);
38 void AutoMap_OnAdd (HWND hDlg);
39 void AutoMap_OnSelect (HWND hDlg);
40 void AutoMap_OnEdit (HWND hDlg);
41 void AutoMap_OnRemove (HWND hDlg);
42
43 void ShowDriveList(HWND hDlg, DRIVEMAPLIST& drives);
44 void AddToDriveList(DRIVEMAPLIST& DriveMapList, DRIVEMAP& DriveMap);
45 void RemoveFromDriveList(DRIVEMAPLIST& DriveMapList, DRIVEMAP& DriveMap);
46 DRIVEMAP *GetSelectedDrive(HWND hDlg, HLISTITEM  *pItem = 0);
47 BOOL DefineDosDrive(DRIVEMAP *pDrive, DDDACTION dddAction = DDD_ADD);
48
49 BOOL CALLBACK AutoMapEdit_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
50 void AutoMapEdit_OnInitDialog (HWND hDlg);
51 void AutoMapEdit_OnOK (HWND hDlg);
52 void AutoMapEdit_Enable (HWND hDlg);
53
54
55 /*
56  * ROUTINES ___________________________________________________________________
57  *
58  */
59
60 BOOL CALLBACK AutoMap_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
61 {
62    switch (msg)
63       {
64       case WM_INITDIALOG:
65          AutoMap_OnInitDialog (hDlg);
66          break;
67
68       case WM_CTLCOLORSTATIC:
69          if ((HWND)lp == GetDlgItem (hDlg, IDC_CHUNK_SIZE))
70             {
71             if (IsWindowEnabled ((HWND)lp))
72                {
73                static HBRUSH hbrStatic = CreateSolidBrush (GetSysColor (COLOR_WINDOW));
74                SetTextColor ((HDC)wp, GetSysColor (COLOR_WINDOWTEXT));
75                SetBkColor ((HDC)wp, GetSysColor (COLOR_WINDOW));
76                return (BOOL)hbrStatic;
77                }
78             }
79          break;
80
81       case WM_COMMAND:
82          switch (LOWORD(wp))
83             {
84             case IDHELP:
85                AutoMap_DlgProc (hDlg, WM_HELP, 0, 0);
86                break;
87
88             case IDOK:
89                EndDialog(hDlg, IDOK);
90                break;
91                 
92             case IDCANCEL:
93                EndDialog(hDlg, IDCANCEL);
94                break;
95
96                                 case IDC_ADD:
97                                         AutoMap_OnAdd(hDlg);
98                                         break;
99
100                                 case IDC_CHANGE:
101                                         AutoMap_OnEdit(hDlg);
102                                         break;
103
104                                 case IDC_REMOVE:
105                                         AutoMap_OnRemove(hDlg);
106                                         break;
107             }
108          break;
109
110       case WM_NOTIFY:
111          switch (((LPNMHDR)lp)->code)
112                 {
113             case FLN_ITEMSELECT:
114                AutoMap_OnSelect (hDlg);
115                break;
116
117             case FLN_LDBLCLICK:
118                if (IsWindowEnabled (GetDlgItem (hDlg, IDC_EDIT)))
119                   AutoMap_OnEdit (hDlg);
120                break;
121             }
122          break;
123
124       case WM_HELP:
125          WinHelp (hDlg, g.szHelpFile, HELP_CONTEXT, IDH_AFSCONFIG_ADVANCED_AUTOMAP);
126          break;
127       }
128
129    return FALSE;
130 }
131
132
133 void AddToDriveList(DRIVEMAPLIST& DriveMapList, DRIVEMAP& DriveMap)
134 {
135    int nCurDrive = DriveMap.chDrive - TEXT('A');
136    
137    memcpy(&DriveMapList.aDriveMap[nCurDrive], &DriveMap, sizeof(DRIVEMAP));
138 }
139
140
141 void RemoveFromDriveList(DRIVEMAPLIST& DriveMapList, DRIVEMAP& DriveMap)
142 {
143    int nCurDrive = DriveMap.chDrive - TEXT('A');
144    
145    memset(&DriveMapList.aDriveMap[nCurDrive], 0, sizeof(DRIVEMAP));
146 }
147
148
149 void AutoMap_OnInitDialog (HWND hDlg)
150 {
151    // Prepare the columns
152    HWND hList = GetDlgItem (hDlg, IDC_GLOBAL_DRIVE_LIST);
153
154    FASTLISTCOLUMN Column;
155    Column.dwFlags = FLCF_JUSTIFY_LEFT;
156    Column.cxWidth = 65;
157    GetString (Column.szText, IDS_DRIVE);
158    FastList_SetColumn (hList, 0, &Column);
159
160    Column.dwFlags = FLCF_JUSTIFY_LEFT;
161    Column.cxWidth = 266;
162    GetString (Column.szText, IDS_SUBCOL_PATH);
163    FastList_SetColumn (hList, 1, &Column);
164
165         gethostname(szHostName, sizeof(szHostName));
166
167    Config_GetGlobalDriveList(&GlobalDrives);
168
169    ShowDriveList(hDlg, GlobalDrives);
170 }
171
172
173 void ShowDriveList(HWND hDlg, DRIVEMAPLIST& drives)
174 {
175    // Prepare the columns
176    HWND hList = GetDlgItem (hDlg, IDC_GLOBAL_DRIVE_LIST);
177
178    // Fill in the list of drives
179    FastList_Begin (hList);
180
181    FastList_RemoveAll(hList);
182
183    for (size_t ii = 0; ii < 26; ++ii) {
184       if (!GlobalDrives.aDriveMap[ ii ].chDrive)
185          continue;
186
187       HWND hList = GetDlgItem (hDlg, IDC_GLOBAL_DRIVE_LIST);
188    
189         FASTLISTADDITEM ai;
190         memset (&ai, 0x00, sizeof(FASTLISTADDITEM));
191         ai.iFirstImage = IMAGE_NOIMAGE;
192         ai.iSecondImage = IMAGE_NOIMAGE;
193         // There must be DRIVE_LETTER_INDEX number of spaces before the ? character
194         ai.pszText = _tcsdup(TEXT("  ?:"));
195         ai.pszText[DRIVE_LETTER_INDEX] = GlobalDrives.aDriveMap[ ii ].chDrive;
196         ai.lParam = 0;
197         
198         HLISTITEM hItem = FastList_AddItem (hList, &ai);
199    
200       TCHAR szAfsPath[ MAX_PATH ];
201       AdjustAfsPath (szAfsPath, GlobalDrives.aDriveMap[ ii ].szMapping, TRUE, FALSE);
202    
203         FastList_SetItemText (hList, hItem, 1, szAfsPath);
204    }
205
206    FastList_End (hList);
207 }
208
209
210 BOOL UpdateRegistry(DRIVEMAP *pDrive, BOOL bRemove)
211 {
212    TCHAR szKeyName[128];
213    TCHAR szValueName[128];
214    HKEY hKey;
215    LONG result;
216    DWORD dwDispo;
217
218    if (!pDrive)
219       return FALSE;
220
221    _stprintf(szKeyName, TEXT("%s\\GlobalAutoMapper"), AFSDConfigKeyName);
222
223    if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, &dwDispo) != ERROR_SUCCESS)
224       return FALSE;
225
226    _stprintf(szValueName, TEXT("%c:"), pDrive->chDrive);
227  
228    if (bRemove) 
229       result = RegDeleteValue(hKey, szValueName);
230    else
231       result = RegSetValueEx(hKey, szValueName, 0, REG_SZ, (BYTE *)pDrive->szSubmount, lstrlen(pDrive->szSubmount) + 1);
232
233    RegCloseKey(hKey);
234    
235    return (result == ERROR_SUCCESS);
236 }
237
238
239 BOOL DefineDosDrive(DRIVEMAP *pDrive, DDDACTION dddAction)
240 {
241     // TCHAR szAfsPath[MAX_PATH];
242     // TCHAR szDrive[3] = TEXT("?:");
243    BOOL fResult = FALSE;
244
245    if (!pDrive)
246       return FALSE;
247
248    if (dddAction == DDD_REMOVE) {
249        if (!(fResult=(DisMountDOSDrive(pDrive->chDrive)==NO_ERROR)))
250            Message (MB_OK | MB_ICONHAND, IDS_ERROR_UNMAP, IDS_ERROR_UNMAP_DESC, TEXT("%08lX"), GetLastError());
251    } else if (dddAction == DDD_ADD) {
252        if (!(fResult=(MountDOSDrive(pDrive->chDrive, pDrive->szSubmount,FALSE)==NO_ERROR)))
253            Message (MB_OK | MB_ICONHAND, IDS_ERROR_MAP, IDS_ERROR_MAP_DESC, TEXT("%08lX"), GetLastError());
254    }
255    /*
256      Replace this code with Drive mapping routine that doesn't require different formats for each OS
257      szDrive[0] = pDrive->chDrive;
258      _stprintf(szAfsPath, TEXT("\\Device\\LanmanRedirector\\%s\\%s-AFS\\%s"), szDrive, szHostName, pDrive->szSubmount);
259
260      if (dddAction == DDD_REMOVE) {
261          fResult = DefineDosDevice(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, szDrive, szAfsPath);
262          if (!fResult)
263              Message (MB_OK | MB_ICONHAND, IDS_ERROR_UNMAP, IDS_ERROR_UNMAP_DESC, TEXT("%08lX"), GetLastError());
264      } else if (dddAction == DDD_ADD) {
265           fResult = DefineDosDevice(DDD_RAW_TARGET_PATH, szDrive, szAfsPath);
266           if (!fResult)
267               Message (MB_OK | MB_ICONHAND, IDS_ERROR_MAP, IDS_ERROR_MAP_DESC, TEXT("%08lX"), GetLastError());
268      }
269
270     */
271    if (fResult)
272        UpdateRegistry(pDrive, dddAction == DDD_REMOVE);
273    
274    return fResult;
275 }   
276
277
278 void AutoMap_OnAdd(HWND hDlg)
279 {
280         DRIVEMAP DriveMap;
281    memset(&DriveMap, 0, sizeof(DRIVEMAP));
282
283         if (ModalDialogParam (IDD_GLOBAL_DRIVES_ADDEDIT, hDlg, (DLGPROC)AutoMapEdit_DlgProc, (LPARAM)&DriveMap) != IDOK)
284                 return;
285
286         if (DriveMap.chDrive) {
287       if (DefineDosDrive(&DriveMap)) {
288                    AddToDriveList(GlobalDrives, DriveMap);
289                    ShowDriveList(hDlg, GlobalDrives);
290                 }
291         }
292
293         AutoMap_OnSelect(hDlg);
294 }
295
296
297 void AutoMap_OnSelect (HWND hDlg)
298 {
299    HWND hList = GetDlgItem (hDlg, IDC_GLOBAL_DRIVE_LIST);
300
301    BOOL bEnable = FastList_FindFirstSelected (hList) != NULL;
302         
303         EnableWindow (GetDlgItem (hDlg, IDC_REMOVE), bEnable);
304    EnableWindow (GetDlgItem (hDlg, IDC_CHANGE), bEnable);
305 }
306
307
308 DRIVEMAP *GetSelectedDrive(HWND hDlg, HLISTITEM  *pItem)
309 {
310         static DRIVEMAP DriveMap;
311    HLISTITEM hItem;
312    
313    HWND hList = GetDlgItem (hDlg, IDC_GLOBAL_DRIVE_LIST);
314
315    if (!pItem)
316       pItem = &hItem;
317
318    if ((*pItem = FastList_FindFirstSelected (hList)) == NULL)
319         return 0;
320         
321         LPCTSTR pszDrive = FastList_GetItemText (hList, *pItem, 0);
322    int nCurDrive = pszDrive[DRIVE_LETTER_INDEX] - TEXT('A');
323
324    memcpy(&DriveMap, &GlobalDrives.aDriveMap[nCurDrive], sizeof(DRIVEMAP));
325
326    return &DriveMap;
327 }
328
329    
330 void AutoMap_OnEdit (HWND hDlg)
331 {
332    DRIVEMAP *pOldDrive = GetSelectedDrive(hDlg);
333    if (!pOldDrive)
334       return;
335
336    DRIVEMAP NewDrive;
337    memcpy(&NewDrive, pOldDrive, sizeof(DRIVEMAP));
338         
339         if (ModalDialogParam (IDD_GLOBAL_DRIVES_ADDEDIT, hDlg, (DLGPROC)AutoMapEdit_DlgProc, (LPARAM)&NewDrive) != IDOK)
340                 return;
341
342    if (DefineDosDrive(pOldDrive, DDD_REMOVE)) {
343       RemoveFromDriveList(GlobalDrives, *pOldDrive);
344
345       if (DefineDosDrive(&NewDrive))
346            AddToDriveList(GlobalDrives, NewDrive);
347
348         ShowDriveList(hDlg, GlobalDrives);
349         }
350
351         AutoMap_OnSelect(hDlg);
352 }
353
354
355 void AutoMap_OnRemove (HWND hDlg)
356 {
357    HLISTITEM hItem;
358
359    HWND hList = GetDlgItem (hDlg, IDC_GLOBAL_DRIVE_LIST);
360
361    DRIVEMAP *pDrive = GetSelectedDrive(hDlg, &hItem);
362    if (pDrive == 0)
363       return;
364       
365    if (DefineDosDrive(pDrive, DDD_REMOVE)) {
366       RemoveFromDriveList(GlobalDrives, *pDrive);
367         FastList_RemoveItem (hList, hItem);
368    }
369
370         AutoMap_OnSelect(hDlg);
371 }
372
373
374 BOOL CALLBACK AutoMapEdit_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
375 {
376    switch (msg)
377       {
378       case WM_INITDIALOG:
379          SetWindowLong (hDlg, DWL_USER, lp);
380          AutoMapEdit_OnInitDialog (hDlg);
381          break;
382
383       case WM_COMMAND:
384          switch (LOWORD(wp))
385             {
386             case IDOK:
387                AutoMapEdit_OnOK (hDlg);
388                break;
389
390             case IDCANCEL:
391                EndDialog (hDlg, IDCANCEL);
392                break;
393
394             case IDC_PATH:
395                AutoMapEdit_Enable (hDlg);
396                break;
397
398             case IDHELP:
399                AutoMapEdit_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_ADVANCED_AUTOMAP_ADDEDIT);
406          break;
407       }
408    return FALSE;
409 }
410
411
412 void AutoMapEdit_OnInitDialog (HWND hDlg)
413 {
414    PDRIVEMAP pMap = (PDRIVEMAP)GetWindowLong (hDlg, DWL_USER);
415
416    DWORD dwDrives = GetLogicalDrives() | 0x07; // Always pretend A,B,C: are used
417
418    // Fill in the combo box
419    //
420
421    if (pMap->chDrive != 0)
422       dwDrives &= ~( 1 << (pMap->chDrive - chDRIVE_A) );
423
424    int iItemSel = -1;
425    HWND hCombo = GetDlgItem (hDlg, IDC_DRIVE);
426    SendMessage (hCombo, WM_SETREDRAW, FALSE, 0);
427
428    for (int ii = 0; ii < 26; ++ii)
429       {
430       if (!(dwDrives & (1<<ii)))
431          {
432          TCHAR szText[ cchRESOURCE ];
433          GetString (szText, IDS_MAP_LETTER);
434
435          LPTSTR pch;
436          if ((pch = (LPTSTR)lstrchr (szText, TEXT('*'))) != NULL)
437             *pch = TEXT('A') + ii;
438
439          int iItem = SendMessage (hCombo, CB_ADDSTRING, 0, (LPARAM)szText);
440          SendMessage (hCombo, CB_SETITEMDATA, iItem, ii);
441          if (pMap->chDrive && (ii == pMap->chDrive - chDRIVE_A))
442             iItemSel = iItem;
443          else if ((!pMap->chDrive) && (iItemSel == -1))
444             iItemSel = iItem;
445          }
446       }
447
448    SendMessage (hCombo, WM_SETREDRAW, TRUE, 0);
449    SendMessage (hCombo, CB_SETCURSEL, iItemSel, 0);
450
451    TCHAR szMapping[ MAX_PATH ];
452    AdjustAfsPath (szMapping, ((pMap->szMapping[0]) ? pMap->szMapping : cm_slash_mount_root), TRUE, FALSE);
453    SetDlgItemText (hDlg, IDC_PATH, szMapping);
454    SetDlgItemText (hDlg, IDC_DESC, pMap->szSubmount);
455
456    CheckDlgButton (hDlg, IDC_PERSISTENT, (pMap->chDrive == 0) ? TRUE : (pMap->fPersistent));
457
458    AutoMapEdit_Enable (hDlg);
459 }
460
461
462 void AutoMapEdit_OnOK (HWND hDlg)
463 {
464    PDRIVEMAP pMap = (PDRIVEMAP)GetWindowLong (hDlg, DWL_USER);
465
466    int iItem = SendDlgItemMessage (hDlg, IDC_DRIVE, CB_GETCURSEL, 0, 0);
467    int iDrive = SendDlgItemMessage (hDlg, IDC_DRIVE, CB_GETITEMDATA, iItem, 0);
468
469    pMap->chDrive = chDRIVE_A + iDrive;
470    GetDlgItemText (hDlg, IDC_PATH, pMap->szMapping, MAX_PATH);
471    GetDlgItemText (hDlg, IDC_DESC, pMap->szSubmount, MAX_PATH);
472    pMap->fPersistent = IsDlgButtonChecked (hDlg, IDC_PERSISTENT);
473
474    if (pMap->szSubmount[0] && !IsValidSubmountName (pMap->szSubmount))
475       {
476       Message (MB_ICONHAND, GetErrorTitle(), IDS_BADSUB_DESC);
477       return;
478       }
479
480     if ( (lstrncmpi (pMap->szMapping, cm_slash_mount_root, lstrlen(cm_slash_mount_root))) &&
481          (lstrncmpi (pMap->szMapping, cm_back_slash_mount_root, lstrlen(cm_back_slash_mount_root))) )
482     {
483         Message (MB_ICONHAND, GetErrorTitle(), IDS_BADMAP_DESC);
484         return;
485     }
486
487    // First get a proper submount
488    if (pMap->szSubmount[0]) {
489       TCHAR szNewSubmount[MAX_PATH];
490       PathToSubmount (szNewSubmount, pMap->szMapping, pMap->szSubmount, 0);
491       if (lstrcmp(szNewSubmount, pMap->szSubmount) != 0) {
492          Message (MB_OK | MB_ICONASTERISK, GetCautionTitle(), IDS_NEWSUB_DESC);
493          return;
494       }
495    } else { // If no submount was specified, then get a new one
496       if (!PathToSubmount (pMap->szSubmount, pMap->szMapping, 0, 0)) {
497          return;
498       }
499    }
500
501    EndDialog (hDlg, IDOK);
502 }
503
504
505 void AutoMapEdit_Enable (HWND hDlg)
506 {
507    TCHAR szPath[ MAX_PATH ];
508    GetDlgItemText (hDlg, IDC_PATH, szPath, MAX_PATH);
509    EnableWindow (GetDlgItem (hDlg, IDOK), (szPath[0] != TEXT('\0')));
510 }
511