winnt-create-globalautomapper-registry-key-20010404
[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    DWORD dwDispo;
216
217    if (!pDrive)
218       return FALSE;
219
220    _stprintf(szKeyName, TEXT("%s\\GlobalAutoMapper"), AFSConfigKeyName);
221
222    if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, &dwDispo) != ERROR_SUCCESS)
223       return FALSE;
224
225    _stprintf(szValueName, TEXT("%c:"), pDrive->chDrive);
226  
227    if (bRemove) 
228       result = RegDeleteValue(hKey, szValueName);
229    else
230       result = RegSetValueEx(hKey, szValueName, 0, REG_SZ, (BYTE *)pDrive->szSubmount, lstrlen(pDrive->szSubmount) + 1);
231
232    RegCloseKey(hKey);
233    
234    return (result == ERROR_SUCCESS);
235 }
236
237
238 BOOL DefineDosDrive(DRIVEMAP *pDrive, DDDACTION dddAction)
239 {
240    TCHAR szAfsPath[MAX_PATH];
241    TCHAR szDrive[3] = TEXT("?:");
242    BOOL fResult = FALSE;
243
244    if (!pDrive)
245       return FALSE;
246
247    szDrive[0] = pDrive->chDrive;
248    _stprintf(szAfsPath, TEXT("\\Device\\LanmanRedirector\\%s\\%s-AFS\\%s"), szDrive, szHostName, pDrive->szSubmount);
249
250    if (dddAction == DDD_REMOVE) {
251       fResult = DefineDosDevice(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, szDrive, szAfsPath);
252       if (!fResult)
253          Message (MB_OK | MB_ICONHAND, IDS_ERROR_UNMAP, IDS_ERROR_UNMAP_DESC, TEXT("%08lX"), GetLastError());
254    } else if (dddAction == DDD_ADD) {
255       fResult = DefineDosDevice(DDD_RAW_TARGET_PATH, szDrive, szAfsPath);
256       if (!fResult)
257          Message (MB_OK | MB_ICONHAND, IDS_ERROR_MAP, IDS_ERROR_MAP_DESC, TEXT("%08lX"), GetLastError());
258    }
259
260    if (fResult)
261          UpdateRegistry(pDrive, dddAction == DDD_REMOVE);
262
263    return fResult;
264 }   
265
266
267 void AutoMap_OnAdd(HWND hDlg)
268 {
269         DRIVEMAP DriveMap;
270    memset(&DriveMap, 0, sizeof(DRIVEMAP));
271
272         if (ModalDialogParam (IDD_GLOBAL_DRIVES_ADDEDIT, hDlg, (DLGPROC)AutoMapEdit_DlgProc, (LPARAM)&DriveMap) != IDOK)
273                 return;
274
275         if (DriveMap.chDrive) {
276       if (DefineDosDrive(&DriveMap)) {
277                    AddToDriveList(GlobalDrives, DriveMap);
278                    ShowDriveList(hDlg, GlobalDrives);
279                 }
280         }
281
282         AutoMap_OnSelect(hDlg);
283 }
284
285
286 void AutoMap_OnSelect (HWND hDlg)
287 {
288    HWND hList = GetDlgItem (hDlg, IDC_GLOBAL_DRIVE_LIST);
289
290    BOOL bEnable = FastList_FindFirstSelected (hList) != NULL;
291         
292         EnableWindow (GetDlgItem (hDlg, IDC_REMOVE), bEnable);
293    EnableWindow (GetDlgItem (hDlg, IDC_CHANGE), bEnable);
294 }
295
296
297 DRIVEMAP *GetSelectedDrive(HWND hDlg, HLISTITEM  *pItem)
298 {
299         static DRIVEMAP DriveMap;
300    HLISTITEM hItem;
301    
302    HWND hList = GetDlgItem (hDlg, IDC_GLOBAL_DRIVE_LIST);
303
304    if (!pItem)
305       pItem = &hItem;
306
307    if ((*pItem = FastList_FindFirstSelected (hList)) == NULL)
308         return 0;
309         
310         LPCTSTR pszDrive = FastList_GetItemText (hList, *pItem, 0);
311    int nCurDrive = pszDrive[DRIVE_LETTER_INDEX] - TEXT('A');
312
313    memcpy(&DriveMap, &GlobalDrives.aDriveMap[nCurDrive], sizeof(DRIVEMAP));
314
315    return &DriveMap;
316 }
317
318    
319 void AutoMap_OnEdit (HWND hDlg)
320 {
321    DRIVEMAP *pOldDrive = GetSelectedDrive(hDlg);
322    if (!pOldDrive)
323       return;
324
325    DRIVEMAP NewDrive;
326    memcpy(&NewDrive, pOldDrive, sizeof(DRIVEMAP));
327         
328         if (ModalDialogParam (IDD_GLOBAL_DRIVES_ADDEDIT, hDlg, (DLGPROC)AutoMapEdit_DlgProc, (LPARAM)&NewDrive) != IDOK)
329                 return;
330
331    if (DefineDosDrive(pOldDrive, DDD_REMOVE)) {
332       RemoveFromDriveList(GlobalDrives, *pOldDrive);
333
334       if (DefineDosDrive(&NewDrive))
335            AddToDriveList(GlobalDrives, NewDrive);
336
337         ShowDriveList(hDlg, GlobalDrives);
338         }
339
340         AutoMap_OnSelect(hDlg);
341 }
342
343
344 void AutoMap_OnRemove (HWND hDlg)
345 {
346    HLISTITEM hItem;
347
348    HWND hList = GetDlgItem (hDlg, IDC_GLOBAL_DRIVE_LIST);
349
350    DRIVEMAP *pDrive = GetSelectedDrive(hDlg, &hItem);
351    if (pDrive == 0)
352       return;
353       
354    if (DefineDosDrive(pDrive, DDD_REMOVE)) {
355       RemoveFromDriveList(GlobalDrives, *pDrive);
356         FastList_RemoveItem (hList, hItem);
357    }
358
359         AutoMap_OnSelect(hDlg);
360 }
361
362
363 BOOL CALLBACK AutoMapEdit_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
364 {
365    switch (msg)
366       {
367       case WM_INITDIALOG:
368          SetWindowLong (hDlg, DWL_USER, lp);
369          AutoMapEdit_OnInitDialog (hDlg);
370          break;
371
372       case WM_COMMAND:
373          switch (LOWORD(wp))
374             {
375             case IDOK:
376                AutoMapEdit_OnOK (hDlg);
377                break;
378
379             case IDCANCEL:
380                EndDialog (hDlg, IDCANCEL);
381                break;
382
383             case IDC_PATH:
384                AutoMapEdit_Enable (hDlg);
385                break;
386
387             case IDHELP:
388                AutoMapEdit_DlgProc (hDlg, WM_HELP, 0, 0);
389                break;
390             }
391          break;
392
393       case WM_HELP:
394          WinHelp (hDlg, g.szHelpFile, HELP_CONTEXT, IDH_AFSCONFIG_ADVANCED_AUTOMAP_ADDEDIT);
395          break;
396       }
397    return FALSE;
398 }
399
400
401 void AutoMapEdit_OnInitDialog (HWND hDlg)
402 {
403    PDRIVEMAP pMap = (PDRIVEMAP)GetWindowLong (hDlg, DWL_USER);
404
405    DWORD dwDrives = GetLogicalDrives() | 0x07; // Always pretend A,B,C: are used
406
407    // Fill in the combo box
408    //
409
410    if (pMap->chDrive != 0)
411       dwDrives &= ~( 1 << (pMap->chDrive - chDRIVE_A) );
412
413    int iItemSel = -1;
414    HWND hCombo = GetDlgItem (hDlg, IDC_DRIVE);
415    SendMessage (hCombo, WM_SETREDRAW, FALSE, 0);
416
417    for (int ii = 0; ii < 26; ++ii)
418       {
419       if (!(dwDrives & (1<<ii)))
420          {
421          TCHAR szText[ cchRESOURCE ];
422          GetString (szText, IDS_MAP_LETTER);
423
424          LPTSTR pch;
425          if ((pch = (LPTSTR)lstrchr (szText, TEXT('*'))) != NULL)
426             *pch = TEXT('A') + ii;
427
428          int iItem = SendMessage (hCombo, CB_ADDSTRING, 0, (LPARAM)szText);
429          SendMessage (hCombo, CB_SETITEMDATA, iItem, ii);
430          if (pMap->chDrive && (ii == pMap->chDrive - chDRIVE_A))
431             iItemSel = iItem;
432          else if ((!pMap->chDrive) && (iItemSel == -1))
433             iItemSel = iItem;
434          }
435       }
436
437    SendMessage (hCombo, WM_SETREDRAW, TRUE, 0);
438    SendMessage (hCombo, CB_SETCURSEL, iItemSel, 0);
439
440    TCHAR szMapping[ MAX_PATH ];
441    AdjustAfsPath (szMapping, ((pMap->szMapping[0]) ? pMap->szMapping : TEXT("/afs")), TRUE, FALSE);
442    SetDlgItemText (hDlg, IDC_PATH, szMapping);
443    SetDlgItemText (hDlg, IDC_DESC, pMap->szSubmount);
444
445    CheckDlgButton (hDlg, IDC_PERSISTENT, (pMap->chDrive == 0) ? TRUE : (pMap->fPersistent));
446
447    AutoMapEdit_Enable (hDlg);
448 }
449
450
451 void AutoMapEdit_OnOK (HWND hDlg)
452 {
453    PDRIVEMAP pMap = (PDRIVEMAP)GetWindowLong (hDlg, DWL_USER);
454
455    int iItem = SendDlgItemMessage (hDlg, IDC_DRIVE, CB_GETCURSEL, 0, 0);
456    int iDrive = SendDlgItemMessage (hDlg, IDC_DRIVE, CB_GETITEMDATA, iItem, 0);
457
458    pMap->chDrive = chDRIVE_A + iDrive;
459    GetDlgItemText (hDlg, IDC_PATH, pMap->szMapping, MAX_PATH);
460    GetDlgItemText (hDlg, IDC_DESC, pMap->szSubmount, MAX_PATH);
461    pMap->fPersistent = IsDlgButtonChecked (hDlg, IDC_PERSISTENT);
462
463    if (pMap->szSubmount[0] && !IsValidSubmountName (pMap->szSubmount))
464       {
465       Message (MB_ICONHAND, GetErrorTitle(), IDS_BADSUB_DESC);
466       return;
467       }
468
469    if ( (lstrncmpi (pMap->szMapping, TEXT("/afs"), lstrlen(TEXT("/afs")))) &&
470         (lstrncmpi (pMap->szMapping, TEXT("\\afs"), lstrlen(TEXT("\\afs")))) )
471       {
472       Message (MB_ICONHAND, GetErrorTitle(), IDS_BADMAP_DESC);
473       return;
474       }
475
476    // First get a proper submount
477    if (pMap->szSubmount[0]) {
478       TCHAR szNewSubmount[MAX_PATH];
479       PathToSubmount (szNewSubmount, pMap->szMapping, pMap->szSubmount, 0);
480       if (lstrcmp(szNewSubmount, pMap->szSubmount) != 0) {
481          Message (MB_OK | MB_ICONASTERISK, GetCautionTitle(), IDS_NEWSUB_DESC);
482          return;
483       }
484    } else { // If no submount was specified, then get a new one
485       if (!PathToSubmount (pMap->szSubmount, pMap->szMapping, 0, 0)) {
486          return;
487       }
488    }
489
490    EndDialog (hDlg, IDOK);
491 }
492
493
494 void AutoMapEdit_Enable (HWND hDlg)
495 {
496    TCHAR szPath[ MAX_PATH ];
497    GetDlgItemText (hDlg, IDC_PATH, szPath, MAX_PATH);
498    EnableWindow (GetDlgItem (hDlg, IDOK), (szPath[0] != TEXT('\0')));
499 }
500