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