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