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