350004bbe811eb6611801ad8ef22f1ddc668cc6c
[openafs.git] / src / WINNT / client_config / drivemap.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 <rx/rxkad.h>
14 #include <afs/fs_utils.h>
15 }
16 #include <windows.h>
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <WINNT/TaLocale.h>
20 #undef REALLOC
21 #include "drivemap.h"
22 #include <time.h>
23 #include <adssts.h>
24 #ifdef DEBUG
25 #define DEBUG_VERBOSE
26 #endif
27 #include <osilog.h>
28 #include <lanahelper.h>
29
30 extern void Config_GetLanAdapter (ULONG *pnLanAdapter);
31
32 /*
33  * REGISTRY ___________________________________________________________________
34  *
35  */
36
37 #undef AFSConfigKeyName
38 const TCHAR sAFSConfigKeyName[] = TEXT("SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters");
39
40
41 /*
42  * PROFILE SECTIONS ___________________________________________________________
43  *
44  */
45
46 #define cREALLOC_SUBMOUNTS   4
47
48 static TCHAR cszSECTION_SUBMOUNTS[] = TEXT("SOFTWARE\\OpenAFS\\Client\\Submounts");
49 static TCHAR cszSECTION_MAPPINGS[] = TEXT("SOFTWARE\\OpenAFS\\Client\\Mappings");
50 static TCHAR cszSECTION_ACTIVE[] = TEXT("SOFTWARE\\OpenAFS\\Client\\Active Maps");
51
52 static TCHAR cszAUTOSUBMOUNT[] = TEXT("Auto");
53 static TCHAR cszLANMANDEVICE[] = TEXT("\\Device\\LanmanRedirector\\");
54
55
56 static BOOL 
57 WriteRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs, LPTSTR rhs)
58 {
59     HKEY hkSub = NULL;
60     RegCreateKeyEx( key,
61                     subkey,
62                     0,
63                     NULL,
64                     REG_OPTION_NON_VOLATILE,
65                     KEY_WRITE,
66                     NULL,
67                     &hkSub,
68                     NULL);
69
70     DWORD status = RegSetValueEx( hkSub, lhs, 0, REG_SZ, (const BYTE *)rhs, strlen(rhs)+1 );
71
72     if ( hkSub )
73         RegCloseKey( hkSub );
74
75     return (status == ERROR_SUCCESS);
76 }
77
78 static BOOL 
79 ReadRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs, LPTSTR rhs, DWORD * size)
80 {
81     HKEY hkSub = NULL;
82     RegCreateKeyEx( key,
83                     subkey,
84                     0,
85                     NULL,
86                     REG_OPTION_NON_VOLATILE,
87                     KEY_READ,
88                     NULL,
89                     &hkSub,
90                     NULL);
91
92     DWORD dwType;
93     DWORD status = RegQueryValueEx( hkSub, lhs, 0, &dwType, (LPBYTE)rhs, size );
94
95     if ( hkSub )
96         RegCloseKey( hkSub );
97
98     return (status == ERROR_SUCCESS);
99 }
100
101 static BOOL 
102 DeleteRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs)
103 {
104     HKEY hkSub = NULL;
105     RegCreateKeyEx( key,
106                     subkey,
107                     0,
108                     NULL,
109                     REG_OPTION_NON_VOLATILE,
110                     KEY_READ,
111                     NULL,
112                     &hkSub,
113                     NULL);
114
115     DWORD dwType;
116     DWORD status = RegDeleteValue( hkSub, lhs );
117
118     if ( hkSub )
119         RegCloseKey( hkSub );
120
121     return (status == ERROR_SUCCESS);
122 }
123
124 /*
125  * STRINGS ____________________________________________________________________
126  *
127  */
128
129 static LPTSTR AllocateStringMemory (size_t cch)
130 {
131    LPTSTR psz = (LPTSTR)Allocate (sizeof(TCHAR) * (cch+1));
132    memset (psz, 0x00, sizeof(TCHAR) * (cch+1));
133    return psz;
134 }
135
136 static void FreeStringMemory (LPTSTR pszString)
137 {
138    Free (pszString);
139 }
140
141 static int lstrncmpi (LPCTSTR pszA, LPCTSTR pszB, size_t cch)
142 {
143    if (!pszA || !pszB)
144       {
145       return (!pszB) - (!pszA);   // A,!B:1, !A,B:-1, !A,!B:0
146       }
147
148    for ( ; cch > 0; cch--, pszA = CharNext(pszA), pszB = CharNext(pszB))
149       {
150       TCHAR chA = toupper( *pszA );
151       TCHAR chB = toupper( *pszB );
152
153       if (!chA || !chB)
154          return (!chB) - (!chA);    // A,!B:1, !A,B:-1, !A,!B:0
155
156       if (chA != chB)
157          return (int)(chA) - (int)(chB);   // -1:A<B, 0:A==B, 1:A>B
158       }
159
160    return 0;  // no differences before told to stop comparing, so A==B
161 }
162
163
164 /*
165  * REALLOC ____________________________________________________________________
166  *
167  */
168
169 #ifndef REALLOC
170 #define REALLOC(_a,_c,_r,_i) DriveMapReallocFunction ((LPVOID*)&_a,sizeof(*_a),&_c,_r,_i)
171 BOOL DriveMapReallocFunction (LPVOID *ppTarget, size_t cbElement, size_t *pcTarget, size_t cReq, size_t cInc)
172 {
173    LPVOID pNew;
174    size_t cNew;
175
176    if (cReq <= *pcTarget)
177       return TRUE;
178
179    if ((cNew = cInc * ((cReq + cInc-1) / cInc)) <= 0)
180       return FALSE;
181
182    if ((pNew = Allocate (cbElement * cNew)) == NULL)
183       return FALSE;
184    memset (pNew, 0x00, cbElement * cNew);
185
186    if (*pcTarget != 0)
187    {
188       memcpy (pNew, *ppTarget, cbElement * (*pcTarget));
189       Free (*ppTarget);
190    }
191
192    *ppTarget = pNew;
193    *pcTarget = cNew;
194    return TRUE;
195 }
196 #endif
197
198
199 /*
200  * WINDOWS NT STUFF ___________________________________________________________
201  *
202  */
203
204 static BOOL IsWindowsNT (void)
205 {
206    static BOOL fChecked = FALSE;
207    static BOOL fIsWinNT = FALSE;
208
209    if (!fChecked)
210       {
211       fChecked = TRUE;
212
213       OSVERSIONINFO Version;
214       memset (&Version, 0x00, sizeof(Version));
215       Version.dwOSVersionInfoSize = sizeof(Version);
216
217       if (GetVersionEx (&Version))
218          {
219          if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT)
220             fIsWinNT = TRUE;
221          }
222       }
223
224    return fIsWinNT;
225 }
226
227 /* Check if the OS is Windows 2000 or higher.
228 */
229 BOOL IsWindows2000 (void)
230 {
231    static BOOL fChecked = FALSE;
232    static BOOL fIsWin2K = FALSE;
233
234    if (!fChecked)
235       {
236       fChecked = TRUE;
237
238       OSVERSIONINFO Version;
239       memset (&Version, 0x00, sizeof(Version));
240       Version.dwOSVersionInfoSize = sizeof(Version);
241
242       if (GetVersionEx (&Version))
243          {
244          if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
245              Version.dwMajorVersion >= 5)
246              fIsWin2K = TRUE;
247          }
248       }
249
250    return fIsWin2K;
251 }
252
253 /*
254  * GENERAL ____________________________________________________________________
255  *
256  */
257
258 void GetClientNetbiosName (LPTSTR pszName)
259 {
260     static TCHAR szNetbiosName[32] = "";
261
262     if ( szNetbiosName[0] == 0 ) {
263         lana_GetNetbiosName(szNetbiosName, LANA_NETBIOS_NAME_FULL);
264     }
265     _tcscpy(pszName, szNetbiosName);
266 }
267
268
269 BOOL SubmountToPath (PDRIVEMAPLIST pList, LPTSTR pszPath, LPTSTR pszSubmount, BOOL fMarkInUse)
270 {
271    // We can't do this translation unless we're under Windows NT.
272    //
273    if (!IsWindowsNT())
274       return FALSE;
275
276    // \\computer-afs\all always maps to "/afs"
277    //
278    if (!lstrcmpi (pszSubmount, TEXT("all")))
279       {
280       lstrcpy (pszPath, cm_slash_mount_root);
281       return TRUE;
282       }
283
284    // Otherwise, look up our list of submounts.
285    //
286    for (size_t ii = 0; ii < pList->cSubmounts; ++ii)
287       {
288       if (!lstrcmpi (pList->aSubmounts[ii].szSubmount, pszSubmount))
289          {
290          if (fMarkInUse)
291             pList->aSubmounts[ii].fInUse = TRUE;
292          AdjustAfsPath (pszPath, pList->aSubmounts[ii].szMapping, TRUE, TRUE);
293          return TRUE;
294          }
295       }
296
297    return FALSE;
298 }
299
300
301 BOOL IsValidSubmountName (LPTSTR pszSubmount)
302 {
303    if (!*pszSubmount)
304       return FALSE;
305    if (lstrlen (pszSubmount) > 12)
306       return FALSE;
307
308    for ( ; *pszSubmount; ++pszSubmount)
309    {
310        if (!isprint(*pszSubmount))
311            return FALSE;
312        if (*pszSubmount == TEXT(' '))
313            return FALSE;
314        if (*pszSubmount == TEXT('/'))
315            return FALSE;
316        if (*pszSubmount == TEXT('\\'))
317            return FALSE;
318        if (*pszSubmount == TEXT('\t'))
319            return FALSE;
320    }
321
322    return TRUE;
323 }
324
325
326 /*
327  * PIOCTL SUPPORT _____________________________________________________________
328  *
329  */
330
331 extern "C" {
332
333 #include "../afsd/fs_utils.h"
334
335 #define __CM_CONFIG_INTERFACES_ONLY__
336 #include "../afsd/cm_config.h"
337
338 #define __CM_IOCTL_INTERFACES_ONLY__
339 #include "../afsd/cm_ioctl.h"
340
341 } // extern "C"
342
343 #define PIOCTL_MAXSIZE     2048
344
345
346 BOOL fCanIssuePIOCTL (void)
347 {
348    if (!IsWindowsNT())
349       {
350       TCHAR szGateway[ 256 ] = TEXT("");
351       GetClientNetbiosName (szGateway);
352       return (szGateway[0]) ? TRUE : FALSE;
353       }
354
355    SERVICE_STATUS Status;
356    memset (&Status, 0x00, sizeof(Status));
357    Status.dwCurrentState = SERVICE_STOPPED;
358
359    SC_HANDLE hManager;
360    if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
361       {
362       SC_HANDLE hService;
363       if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
364          {
365          QueryServiceStatus (hService, &Status);
366          CloseServiceHandle (hService);
367          }
368
369       CloseServiceHandle (hManager);
370       }
371
372    return (Status.dwCurrentState == SERVICE_RUNNING) ? TRUE : FALSE;
373 }
374
375
376 /*
377  * QUERYDRIVEMAPLIST __________________________________________________________
378  *
379  */
380
381 void QueryDriveMapList_ReadSubmounts (PDRIVEMAPLIST pList)
382 {
383     if (IsWindowsNT())
384     {
385         HKEY hkSubmounts;
386
387         RegCreateKeyEx( HKEY_LOCAL_MACHINE, 
388                         "SOFTWARE\\OpenAFS\\Client\\Submounts",
389                         0, 
390                         "AFS", 
391                         REG_OPTION_NON_VOLATILE,
392                         KEY_READ|KEY_QUERY_VALUE,
393                         NULL, 
394                         &hkSubmounts,
395                         NULL );
396
397         DWORD dwSubmounts;
398         RegQueryInfoKey( hkSubmounts,
399                          NULL,  /* lpClass */
400                          NULL,  /* lpcClass */
401                          NULL,  /* lpReserved */
402                          NULL,  /* lpcSubKeys */
403                          NULL,  /* lpcMaxSubKeyLen */
404                          NULL,  /* lpcMaxClassLen */
405                          &dwSubmounts, /* lpcValues */
406                          NULL,  /* lpcMaxValueNameLen */
407                          NULL,  /* lpcMaxValueLen */
408                          NULL,  /* lpcbSecurityDescriptor */
409                          NULL   /* lpftLastWriteTime */
410                          );
411
412         for ( DWORD dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) {
413             TCHAR submountPath[MAX_PATH] = "";
414             DWORD submountPathLen = MAX_PATH;
415             TCHAR submountName[MAX_PATH];
416             DWORD submountNameLen = MAX_PATH;
417             DWORD dwType;
418
419             RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL,
420                           &dwType, (LPBYTE)submountPath, &submountPathLen);
421
422             SUBMOUNT Submount;
423             memset (&Submount, 0x00, sizeof(SUBMOUNT));
424             lstrcpy (Submount.szSubmount, submountName);
425
426             if ( submountPath[0] != TEXT('\0') ) {
427                 AdjustAfsPath (Submount.szMapping, submountPath, FALSE, TRUE);
428
429                 for (size_t ii = 0; ii < pList->cSubmounts; ++ii)
430                 {
431                     if (!pList->aSubmounts[ii].szSubmount[0])
432                         break;
433                 }
434                 if (REALLOC (pList->aSubmounts, pList->cSubmounts, 1+ii, cREALLOC_SUBMOUNTS))
435                 {
436                     memcpy (&pList->aSubmounts[ii], &Submount, sizeof(SUBMOUNT));
437                 }
438             }
439
440         }
441         RegCloseKey(hkSubmounts);
442     }
443 }
444
445
446 void QueryDriveMapList_ReadMappings (PDRIVEMAPLIST pList)
447 {
448     HKEY hkMappings;
449     RegCreateKeyEx( HKEY_CURRENT_USER,
450                     "SOFTWARE\\OpenAFS\\Client\\Mappings",
451                     0, 
452                     "AFS", 
453                     REG_OPTION_NON_VOLATILE,
454                     KEY_READ|KEY_QUERY_VALUE,
455                     NULL, 
456                     &hkMappings,
457                     NULL );
458
459     DWORD dwMappings;
460     RegQueryInfoKey( hkMappings,
461                      NULL,  /* lpClass */
462                      NULL,  /* lpcClass */
463                      NULL,  /* lpReserved */
464                      NULL,  /* lpcSubKeys */
465                      NULL,  /* lpcMaxSubKeyLen */
466                      NULL,  /* lpcMaxClassLen */
467                      &dwMappings, /* lpcValues */
468                      NULL,  /* lpcMaxValueNameLen */
469                      NULL,  /* lpcMaxValueLen */
470                      NULL,  /* lpcbSecurityDescriptor */
471                      NULL   /* lpftLastWriteTime */
472                      );
473
474     for ( DWORD dwIndex = 0; dwIndex < dwMappings; dwIndex ++ ) {
475         TCHAR mapping[MAX_PATH] = "";
476         DWORD mappingLen = MAX_PATH;
477         TCHAR drive[MAX_PATH];
478         DWORD driveLen = MAX_PATH;
479         DWORD dwType;
480
481         RegEnumValue( hkMappings, dwIndex, drive, &driveLen, NULL,
482                       &dwType, (LPBYTE)mapping, &mappingLen);
483
484        DRIVEMAP DriveMap;
485        memset (&DriveMap, 0x00, sizeof(DRIVEMAP));
486        DriveMap.chDrive = toupper(*drive);
487        DriveMap.fPersistent = TRUE;
488        if ((DriveMap.chDrive < chDRIVE_A) || (DriveMap.chDrive > chDRIVE_Z))
489            continue;
490
491        if (mapping[0] != TEXT('\0'))
492        {
493            AdjustAfsPath (DriveMap.szMapping, mapping, TRUE, TRUE);
494            if (DriveMap.szMapping[ lstrlen(DriveMap.szMapping)-1 ] == TEXT('*'))
495            {
496                DriveMap.fPersistent = FALSE;
497                DriveMap.szMapping[ lstrlen(DriveMap.szMapping)-1 ] = TEXT('\0');
498            }
499            size_t iDrive = DriveMap.chDrive - chDRIVE_A;
500            memcpy (&pList->aDriveMap[ iDrive ], &DriveMap, sizeof(DRIVEMAP));
501        }
502     }
503
504     RegCloseKey(hkMappings);
505 }
506
507 BOOL ForceMapActive (TCHAR chDrive)
508 {
509     TCHAR szDrive[2];
510     TCHAR szActive[32];
511
512     szDrive[0] = chDrive;
513     szDrive[1] = 0;
514
515     DWORD len = sizeof(szActive);
516     ReadRegistryString( HKEY_CURRENT_USER, cszSECTION_ACTIVE, szDrive, szActive, &len);
517
518     if ( !lstrcmp(szActive,"1") || !lstrcmpi(szActive,"true") || !lstrcmpi(szActive,"on") || !lstrcmpi(szActive,"yes") )
519         return TRUE;
520     return FALSE;
521 }
522
523
524 void WriteActiveMap (TCHAR chDrive, BOOL on)
525 {
526     TCHAR szDrive[2];
527
528     szDrive[0] = chDrive;
529     szDrive[1] = 0;
530
531     WriteRegistryString(HKEY_CURRENT_USER, cszSECTION_ACTIVE, szDrive, on ? "1" : "0");
532 }
533
534 void QueryDriveMapList_WriteMappings (PDRIVEMAPLIST pList)
535 {
536     WriteDriveMappings (pList);
537 }
538
539
540 void WriteDriveMappings (PDRIVEMAPLIST pList)
541 {
542     HKEY hkMappings;
543     RegCreateKeyEx( HKEY_CURRENT_USER, 
544                     "SOFTWARE\\OpenAFS\\Client\\Mappings",
545                     0, 
546                     "AFS", 
547                     REG_OPTION_NON_VOLATILE,
548                     KEY_READ|KEY_QUERY_VALUE|KEY_WRITE,
549                     NULL, 
550                     &hkMappings,
551                     NULL );
552
553     DWORD dwMappings;
554     RegQueryInfoKey( hkMappings,
555                      NULL,  /* lpClass */
556                      NULL,  /* lpcClass */
557                      NULL,  /* lpReserved */
558                      NULL,  /* lpcSubKeys */
559                      NULL,  /* lpcMaxSubKeyLen */
560                      NULL,  /* lpcMaxClassLen */
561                      &dwMappings, /* lpcValues */
562                      NULL,  /* lpcMaxValueNameLen */
563                      NULL,  /* lpcMaxValueLen */
564                      NULL,  /* lpcbSecurityDescriptor */
565                      NULL   /* lpftLastWriteTime */
566                      );
567
568     if ( dwMappings > 0 ) {
569         for ( long dwIndex = dwMappings - 1; dwIndex >= 0; dwIndex-- ) {
570             TCHAR drive[MAX_PATH];
571             DWORD driveLen = MAX_PATH;
572
573             RegEnumValue( hkMappings, dwIndex, drive, &driveLen, NULL, NULL, NULL, NULL);
574             RegDeleteValue( hkMappings, drive );
575         }
576     }
577
578    for (size_t iDrive = 0; iDrive < 26; ++iDrive)
579    {
580        if (pList->aDriveMap[iDrive].szMapping[0] != TEXT('\0'))
581        {
582            TCHAR szLHS[] = TEXT("*");
583            szLHS[0] = pList->aDriveMap[iDrive].chDrive;
584
585            TCHAR szRHS[MAX_PATH];
586            AdjustAfsPath (szRHS, pList->aDriveMap[iDrive].szMapping, TRUE, TRUE);
587            if (!pList->aDriveMap[iDrive].fPersistent)
588                lstrcat (szRHS, TEXT("*"));
589
590            RegSetValueEx( hkMappings, szLHS, 0, REG_SZ, (const BYTE *)szRHS, lstrlen(szRHS) + 1);
591        }
592    }
593    RegCloseKey( hkMappings );
594 }
595
596 BOOL DriveIsGlobalAfsDrive(TCHAR chDrive)
597 {
598    TCHAR szKeyName[128];
599    TCHAR szValueName[128];
600    TCHAR szValue[128];
601    HKEY hKey;
602
603    _stprintf(szKeyName, TEXT("%s\\GlobalAutoMapper"), sAFSConfigKeyName);
604
605    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
606       return FALSE;
607
608    _stprintf(szValueName, TEXT("%c:"), chDrive);
609
610    DWORD dwSize = sizeof(szValue);
611    BOOL bIsGlobal = (RegQueryValueEx (hKey, szValueName, NULL, NULL, (PBYTE)szValue, &dwSize) == ERROR_SUCCESS);
612
613    RegCloseKey (hKey);
614    
615    return bIsGlobal;
616 }
617
618
619 void QueryDriveMapList_FindNetworkDrives (PDRIVEMAPLIST pList, BOOL *pfFoundNew)
620 {
621    for (TCHAR chDrive = chDRIVE_A; chDrive <= chDRIVE_Z; ++chDrive)
622       {
623       TCHAR szSubmount[ MAX_PATH ];
624       if (!GetDriveSubmount (chDrive, szSubmount))
625          continue;
626
627       // We've got a mapping!  Drive {chDrive} is mapped to submount
628       // {szSubmount}. See if that submount makes sense.
629       //
630       if (!IsWindowsNT())
631          {
632          size_t iDrive = chDrive - chDRIVE_A;
633          if (pList->aDriveMap[ iDrive ].szMapping[0] != TEXT('\0'))
634             {
635             pList->aDriveMap[ iDrive ].fActive = TRUE;
636             lstrcpy (pList->aDriveMap[ iDrive ].szSubmount, szSubmount);
637             }
638          continue;
639          }
640       else // (IsWindowsNT())
641          {
642          TCHAR szAfsPath[ MAX_PATH ];
643          if (!SubmountToPath (pList, szAfsPath, szSubmount, TRUE))
644             continue;
645
646          // Okay, we know that drive {chDrive} is mapped to afs path {szAfsPath}.
647          // If this drive is a global afs drive, then reject it.  Otherwise, look 
648          // at pList->aDriveMap, to see if this drive mapping is already in our 
649          // list. If not, add it and set pfFoundNew.
650          //
651          if (DriveIsGlobalAfsDrive(chDrive))
652             continue;
653          
654          size_t iDrive = chDrive - chDRIVE_A;
655          if (lstrcmpi (pList->aDriveMap[ iDrive ].szMapping, szAfsPath))
656             {
657             *pfFoundNew = TRUE;
658             pList->aDriveMap[ iDrive ].fPersistent = TRUE;
659             }
660          pList->aDriveMap[ iDrive ].fActive = TRUE;
661          pList->aDriveMap[ iDrive ].chDrive = chDrive;
662          lstrcpy (pList->aDriveMap[ iDrive ].szSubmount, szSubmount);
663          AdjustAfsPath (pList->aDriveMap[ iDrive ].szMapping, szAfsPath, TRUE, TRUE);
664          }
665       }
666 }
667
668
669 void QueryDriveMapList (PDRIVEMAPLIST pList)
670 {
671    // Initialize the data structure
672    //
673    memset (pList, 0x00, sizeof(DRIVEMAPLIST));
674    for (size_t ii = 0; ii < 26; ++ii)
675       pList->aDriveMap[ii].chDrive = chDRIVE_A + ii;
676
677    // Read the current lists of submounts and drive letter mappings
678    //
679    QueryDriveMapList_ReadSubmounts (pList);
680    QueryDriveMapList_ReadMappings (pList);
681
682    // Look through the current list of network drives, and see if
683    // any are currently mapped to AFS. If we find any which are mapped
684    // into AFS unexpectedly, we'll have to rewrite the mappings list.
685    //
686    BOOL fFoundNew = FALSE;
687    QueryDriveMapList_FindNetworkDrives (pList, &fFoundNew);
688
689    if (fFoundNew)
690       {
691       QueryDriveMapList_WriteMappings (pList);
692       }
693 }
694
695
696 void FreeDriveMapList (PDRIVEMAPLIST pList)
697 {
698    if (pList->aSubmounts)
699       Free (pList->aSubmounts);
700    memset (pList, 0x00, sizeof(DRIVEMAPLIST));
701 }
702
703
704 BOOL PathToSubmount (LPTSTR pszSubmount, LPTSTR pszMapping, LPTSTR pszSubmountReq, ULONG *pStatus)
705 {
706    if (pszSubmountReq && !IsValidSubmountName (pszSubmountReq))
707       pszSubmountReq = NULL;
708
709    TCHAR szAfsPath[ MAX_PATH ];
710    AdjustAfsPath (szAfsPath, pszMapping, TRUE, TRUE);
711
712    // Try to ask AFSD for a new submount name.
713    //
714    if (!fCanIssuePIOCTL())
715       return FALSE;
716
717    BYTE InData[ PIOCTL_MAXSIZE ];
718    memset (InData, 0x00, sizeof(InData));
719
720    LPTSTR pszInData = (LPTSTR)InData;
721    lstrcpy (pszInData, pszMapping);
722    pszInData += 1+lstrlen(pszInData);
723    if (pszSubmountReq)
724       lstrcpy (pszInData, pszSubmountReq);
725
726    BYTE OutData[ PIOCTL_MAXSIZE ];
727    memset (OutData, 0x00, sizeof(OutData));
728
729    struct ViceIoctl IOInfo;
730    IOInfo.in = (char *)InData;
731    IOInfo.in_size = PIOCTL_MAXSIZE;
732    IOInfo.out = (char *)OutData;
733    IOInfo.out_size = PIOCTL_MAXSIZE;
734
735    ULONG status = pioctl (0, VIOC_MAKESUBMOUNT, &IOInfo, 1);
736    if (pStatus)
737        *pStatus = status;
738
739    if (status)
740       return FALSE;
741
742    lstrcpy (pszSubmount, (LPCTSTR)OutData);
743    return (pszSubmount[0] != TEXT('\0')) ? TRUE : FALSE;
744 }
745
746
747 BOOL ActivateDriveMap (TCHAR chDrive, LPTSTR pszMapping, LPTSTR pszSubmountReq, BOOL fPersistent, DWORD *pdwStatus)
748 {
749    // We can only map drives to places in AFS using this function.
750    //
751    if ( (lstrncmpi (pszMapping, cm_slash_mount_root, lstrlen(cm_slash_mount_root))) &&
752         (lstrncmpi (pszMapping, cm_back_slash_mount_root, lstrlen(cm_back_slash_mount_root))) )
753       {
754       if (pdwStatus)
755          *pdwStatus = ERROR_BAD_NETPATH;
756       return FALSE;
757       }
758
759    // First we have to translate {pszMapping} into a submount, and if there is
760    // no current submount associated with this path, we'll have to make one.
761    //
762    ULONG status;
763    TCHAR szSubmount[ MAX_PATH ];
764    if (!PathToSubmount (szSubmount, pszMapping, pszSubmountReq, &status))
765       {
766       if (pdwStatus)
767          *pdwStatus = status;
768       return FALSE;
769       }
770
771    // We now have a submount name and drive letter--map the network drive.
772    DWORD rc=MountDOSDrive(chDrive,szSubmount,fPersistent,NULL);
773    if (rc == NO_ERROR)
774       return TRUE;
775
776    if (pdwStatus)
777       *pdwStatus = rc;
778    return FALSE;
779 }
780
781
782 BOOL InactivateDriveMap (TCHAR chDrive, DWORD *pdwStatus)
783 {
784     DWORD rc = DisMountDOSDrive(chDrive, FALSE);
785     if (rc == NO_ERROR)
786         return TRUE;
787
788     if (pdwStatus)
789         *pdwStatus = rc;
790     return FALSE;
791 }
792
793
794 void AddSubMount (LPTSTR pszSubmount, LPTSTR pszMapping)
795 {
796     TCHAR szRHS[ MAX_PATH ];
797     AdjustAfsPath (szRHS, pszMapping, FALSE, TRUE);
798     if (!szRHS[0])
799         lstrcpy (szRHS, TEXT("/"));
800
801     WriteRegistryString(HKEY_LOCAL_MACHINE, cszSECTION_SUBMOUNTS, pszSubmount, szRHS);
802 }
803
804
805 void RemoveSubMount (LPTSTR pszSubmount)
806 {
807     DeleteRegistryString(HKEY_LOCAL_MACHINE, cszSECTION_SUBMOUNTS, pszSubmount);
808 }
809
810
811 void AdjustAfsPath (LPTSTR pszTarget, LPCTSTR pszSource, BOOL fWantAFS, BOOL fWantForwardSlashes)
812 {
813     if (!*pszSource)
814         lstrcpy (pszTarget, (fWantAFS) ? cm_slash_mount_root : TEXT(""));
815     else if ((*pszSource != TEXT('/')) && (*pszSource != TEXT('\\')))
816         wsprintf (pszTarget, TEXT("%s/%s"),cm_slash_mount_root, pszSource);
817     // We don't want to strip afs off the start if it is part of something for example afscell.company.com
818     else if (fWantAFS && (lstrncmpi (&pszSource[1], cm_mount_root, strlen(cm_mount_root))) || !((pszSource[strlen(cm_slash_mount_root)] == TEXT('/')) ||
819                                                                                                  (pszSource[strlen(cm_slash_mount_root)] == TEXT('\\')) ||
820                                                                                                  (lstrlen(pszSource) == strlen(cm_slash_mount_root))))
821         wsprintf (pszTarget, TEXT("%s%s"),cm_slash_mount_root, pszSource);
822     else if (!fWantAFS && (!lstrncmpi (&pszSource[1], cm_mount_root, strlen(cm_mount_root)) && ((pszSource[strlen(cm_slash_mount_root)] == TEXT('/')) ||
823                                                                                                  (pszSource[strlen(cm_slash_mount_root)] == TEXT('\\')) ||
824                                                                                                  (lstrlen(pszSource) == strlen(cm_slash_mount_root)))))
825         lstrcpy (pszTarget, &pszSource[strlen(cm_slash_mount_root)]);
826     else
827         lstrcpy (pszTarget, pszSource);
828
829    for (LPTSTR pch = pszTarget; *pch; ++pch)
830       {
831       if (fWantForwardSlashes)
832          {
833          *pch = (*pch == TEXT('\\')) ? TEXT('/') : (*pch);
834          }
835       else // (!fWantForwardSlashes)
836          {
837          *pch = (*pch == TEXT('/')) ? TEXT('\\') : (*pch);
838          }
839       }
840
841    if (lstrlen(pszTarget) &&
842        ((pszTarget[lstrlen(pszTarget)-1] == TEXT('/')) ||
843         (pszTarget[lstrlen(pszTarget)-1] == TEXT('\\'))))
844       {
845       pszTarget[lstrlen(pszTarget)-1] = TEXT('\0');
846       }
847 }
848
849 BOOL GetDriveSubmount (TCHAR chDrive, LPTSTR pszSubmountNow)
850 {
851         BOOL isWinNT = IsWindowsNT();
852
853         TCHAR szDrive[] = TEXT("*:");
854     szDrive[0] = chDrive;
855
856     TCHAR szMapping[ _MAX_PATH ] = TEXT("");
857
858     if (isWinNT && !QueryDosDevice (szDrive, szMapping, MAX_PATH))
859            return FALSE;
860
861     LPTSTR pszSubmount = szMapping;
862     
863         TCHAR szNetBiosName[32];
864     memset(szNetBiosName, '\0', sizeof(szNetBiosName));
865     GetClientNetbiosName(szNetBiosName);
866     _tcscat(szNetBiosName, TEXT("\\"));
867
868    if (isWinNT)
869    {
870       // Now if this is an AFS network drive mapping, {szMapping} will be:
871       //
872       //   \Device\LanmanRedirector\<Drive>:\<netbiosname>\submount
873       //
874       // on Windows NT. On Windows 2000, it will be:
875       //
876       //   \Device\LanmanRedirector\;<Drive>:0\<netbiosname>\submount
877       //
878       // (This is presumably to support multiple drive mappings with
879       // Terminal Server).
880       //
881       // on Windows XP and 2003, it will be :
882       //   \Device\LanmanRedirector\;<Drive>:<AuthID>\<netbiosname>\submount
883       //
884       //   where : <Drive> : DOS drive letter
885       //           <AuthID>: Authentication ID, 16 char hex.
886       //           <netbiosname>: Netbios name of server
887       //
888       if (_tcsnicmp(szMapping, cszLANMANDEVICE, _tcslen(cszLANMANDEVICE)))
889          return FALSE;
890       pszSubmount = &szMapping[ _tcslen(cszLANMANDEVICE) ];
891
892       if (IsWindows2000())
893           {
894           if (*(pszSubmount) != TEXT(';'))
895              return FALSE;
896           } else 
897                 --pszSubmount;
898
899       if (toupper(*(++pszSubmount)) != chDrive)
900          return FALSE;
901
902       if (*(++pszSubmount) != TEXT(':'))
903          return FALSE;
904
905 #ifdef COMMENT
906        // No longer a safe assumption on XP
907       if (IsWindows2000())
908           if (*(++pszSubmount) != TEXT('0'))
909              return FALSE;
910 #endif
911
912       // scan for next "\"
913       while (*(++pszSubmount) != TEXT('\\'))
914       {
915           if (*pszSubmount==0)
916               return FALSE;
917       }
918
919        // note that szNetBiosName has a '\\' tagged in the end earlier
920       for (++pszSubmount; *pszSubmount && (*pszSubmount != TEXT('\\')); ++pszSubmount)
921          if (!_tcsncicmp(pszSubmount, szNetBiosName, _tcslen(szNetBiosName)))
922             break;
923       if ((!*pszSubmount) || (*pszSubmount == TEXT('\\')))
924          return FALSE;
925
926        pszSubmount += _tcslen(szNetBiosName);
927       }
928    else // (!IsWindowsNT())
929       {
930       DWORD dwSize = MAX_PATH;
931       if (WNetGetConnection (szDrive, szMapping, &dwSize) != NO_ERROR)
932          return FALSE;
933       if (*(pszSubmount++) != TEXT('\\'))
934          return FALSE;
935       if (*(pszSubmount++) != TEXT('\\'))
936          return FALSE;
937       for ( ; *pszSubmount && (*pszSubmount != TEXT('\\')); ++pszSubmount)
938          if (!lstrncmpi (pszSubmount, szNetBiosName, lstrlen(szNetBiosName)))
939             break;
940       if ((!*pszSubmount) || (*pszSubmount == TEXT('\\')))
941          return FALSE;
942       pszSubmount += lstrlen(szNetBiosName);
943       }
944
945    if (!pszSubmount || !*pszSubmount)
946       return FALSE;
947
948    lstrcpy (pszSubmountNow, pszSubmount);
949    return TRUE;
950 }
951
952 /* Generate Random User name random acording to time*/
953 DWORD dwOldState=0;
954 TCHAR pUserName[MAXRANDOMNAMELEN]=TEXT("");
955 BOOL fUserName=FALSE;
956 #define AFSLogonOptionName TEXT("System\\CurrentControlSet\\Services\\TransarcAFSDaemon\\NetworkProvider")
957
958 void SetBitLogonOption(BOOL set,DWORD value)
959 {
960
961    RWLogonOption(FALSE,((set)?value | RWLogonOption(TRUE,0):RWLogonOption(TRUE,0) & ~value) );  
962 }
963
964 DWORD RWLogonOption(BOOL read,DWORD value)
965 {
966         // if read is true then if value==0 return registry value
967         // if read and value!=0 then use value to test registry, return TRUE if value bits match value read
968    HKEY hk;
969    DWORD dwDisp;
970         DWORD LSPtype, LSPsize;
971         DWORD rval;
972    if (read)
973    {
974            rval=0;
975                 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSLogonOptionName, 0, KEY_QUERY_VALUE, &hk)==ERROR_SUCCESS)
976                 {
977                         LSPsize=sizeof(rval);
978                         RegQueryValueEx(hk, "LogonOptions", NULL,
979                                                 &LSPtype, (LPBYTE)&rval, &LSPsize);
980                         RegCloseKey (hk);
981                 }
982                 return (value==0)?rval:((rval & value)==value);
983
984    } else {     //write
985                 if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, AFSLogonOptionName, 0, NULL, 0, KEY_SET_VALUE, NULL, &hk, &dwDisp) == ERROR_SUCCESS)
986                 {
987                         RegSetValueEx(hk,TEXT("LogonOptions"),NULL,REG_DWORD,(LPBYTE)&value,sizeof(value));
988                         RegCloseKey (hk);
989                 }
990                 return TRUE;
991    }
992 }
993
994 void MapShareName(char *pszCmdLineA)
995 {
996         fUserName = TRUE;
997         TCHAR *p=pUserName;
998         pszCmdLineA++;
999         while (*pszCmdLineA && (*pszCmdLineA != ' '))
1000         {
1001           *p++=*pszCmdLineA++;
1002         }
1003 }
1004
1005 void GenRandomName(TCHAR *pname,int len)
1006 {
1007         if (fUserName)
1008         {               //user name was passed through command line, use once
1009                 fUserName=FALSE;
1010                 return;
1011         }
1012         srand( (unsigned)time( NULL ) );
1013         for (int i=0;i<len;i++)
1014                 pname[i]='a'+(rand() % 26);
1015         pname[len]=0;
1016         return;
1017 }
1018
1019 /*
1020         Make a connection using users name
1021         if fUserName then force a connection
1022 */
1023
1024 BOOL TestAndDoMapShare(DWORD dwState)
1025 {
1026     if ((dwState!=SERVICE_RUNNING) || (dwOldState!=SERVICE_START_PENDING))
1027         {
1028                 dwOldState=dwState;
1029                 return TRUE;
1030         }
1031         dwOldState=SERVICE_RUNNING;
1032         if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1033             return (DoMapShare() && GlobalMountDrive());
1034         return GlobalMountDrive();
1035 }
1036
1037 BOOL IsServiceActive()
1038 {
1039    SC_HANDLE hManager;
1040    SERVICE_STATUS Status;
1041    if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
1042       {
1043       SC_HANDLE hService;
1044       if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
1045          {
1046          QueryServiceStatus (hService, &Status);
1047          CloseServiceHandle (hService);
1048          }
1049
1050       CloseServiceHandle (hManager);
1051       }
1052
1053    return (Status.dwCurrentState == SERVICE_RUNNING) ? TRUE : FALSE;
1054 }
1055
1056 void TestAndDoUnMapShare()
1057 {
1058         if (!RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1059                 return;
1060         DoUnMapShare(FALSE);    
1061 }
1062
1063 void DoUnMapShare(BOOL drivemap)        //disconnect drivemap 
1064 {
1065         TCHAR szMachine[MAX_PATH],szPath[MAX_PATH];
1066         DWORD rc=28;
1067         HANDLE hEnum;
1068         LPNETRESOURCE lpnrLocal,lpnr=NULL;
1069         DWORD res;
1070         DWORD cbBuffer=16384;
1071         DWORD cEntries=-1;
1072         CHAR *pSubmount="";
1073
1074     memset(szMachine, '\0', sizeof(szMachine));
1075     GetClientNetbiosName(szMachine);
1076
1077    // Initialize the data structure
1078         if ((res=WNetOpenEnum(RESOURCE_CONNECTED,RESOURCETYPE_DISK,RESOURCEUSAGE_CONNECTABLE,lpnr,&hEnum))!=NO_ERROR)
1079                 return;
1080         sprintf(szPath,"\\\\%s\\",szMachine);
1081         _strlwr(szPath);
1082         lpnrLocal=(LPNETRESOURCE) GlobalAlloc(GPTR,cbBuffer);
1083         do {
1084                 memset(lpnrLocal,0,cbBuffer);
1085                 if ((res = WNetEnumResource(hEnum,&cEntries,lpnrLocal,&cbBuffer))==NO_ERROR)
1086                 {
1087                         for (DWORD i=0;i<cEntries;i++)
1088                         {
1089                                 if (strstr(_strlwr(lpnrLocal[i].lpRemoteName),szPath))
1090                                 {
1091                                         if ((lpnrLocal[i].lpLocalName) && (strlen(lpnrLocal[i].lpLocalName)>0))
1092                                         {
1093                                                 if (drivemap) {
1094                                                     DisMountDOSDrive(*lpnrLocal[i].lpLocalName);
1095                             DEBUG_EVENT1("AFS DriveUnMap","UnMap-Local=%x",res);
1096                         }
1097                                         } else {
1098                                             DisMountDOSDriveFull(lpnrLocal[i].lpRemoteName);
1099                         DEBUG_EVENT1("AFS DriveUnMap","UnMap-Remote=%x",res);
1100                     }
1101                                 }
1102                         }
1103                 }
1104         } while (res!=ERROR_NO_MORE_ITEMS);
1105         GlobalFree((HGLOBAL)lpnrLocal);
1106         WNetCloseEnum(hEnum);
1107 }
1108
1109 BOOL DoMapShareChange()
1110 {
1111         DRIVEMAPLIST List;
1112         TCHAR szMachine[ MAX_PATH],szPath[MAX_PATH];
1113         DWORD rc=28;
1114         HANDLE hEnum;
1115         LPNETRESOURCE lpnrLocal,lpnr=NULL;
1116         DWORD res;
1117         DWORD cEntries=-1;
1118     DWORD cbBuffer=16384;
1119
1120     memset(szMachine, '\0', sizeof(szMachine));
1121     GetClientNetbiosName(szMachine);
1122
1123     // Initialize the data structure
1124         if (!IsServiceActive())
1125                 return TRUE;
1126         memset (&List, 0x00, sizeof(DRIVEMAPLIST));
1127         for (size_t ii = 0; ii < 26; ++ii)
1128                 List.aDriveMap[ii].chDrive = chDRIVE_A + ii;
1129         QueryDriveMapList_ReadSubmounts (&List);
1130         if ((res=WNetOpenEnum(RESOURCE_CONNECTED,RESOURCETYPE_DISK,RESOURCEUSAGE_CONNECTABLE,lpnr,&hEnum))!=NO_ERROR)
1131                 return FALSE;
1132         lpnrLocal=(LPNETRESOURCE) GlobalAlloc(GPTR,cbBuffer);
1133         sprintf(szPath,"\\\\%s\\",szMachine);
1134         _strlwr(szPath);
1135         do {
1136                 memset(lpnrLocal,0,cbBuffer);
1137                 if ((res = WNetEnumResource(hEnum,&cEntries,lpnrLocal,&cbBuffer))==NO_ERROR)
1138                 {
1139                         for (DWORD i=0;i<cEntries;i++)
1140                         {
1141                                 if (strstr(_strlwr(lpnrLocal[i].lpRemoteName),szPath)==NULL)
1142                                         continue;       //only look at real afs mappings
1143                                 CHAR * pSubmount=strrchr(lpnrLocal[i].lpRemoteName,'\\')+1;
1144                                 if (lstrcmpi(pSubmount,"all")==0) 
1145                                         continue;                               // do not remove 'all'
1146                                 for (DWORD j=0;j<List.cSubmounts;j++)
1147                                 {
1148                                         if (
1149                                                 (List.aSubmounts[j].szSubmount[0]) &&
1150                                                 (lstrcmpi(List.aSubmounts[j].szSubmount,pSubmount)==0)
1151                                                 ) 
1152                                         {
1153                                                 List.aSubmounts[j].fInUse=TRUE; 
1154                                                 goto nextname;
1155                                         }
1156                                 }
1157                                 // wasn't on list so lets remove
1158                                 DisMountDOSDrive(pSubmount);
1159                                 nextname:;
1160                         }
1161                 }
1162         } while (res!=ERROR_NO_MORE_ITEMS);
1163         GlobalFree((HGLOBAL)lpnrLocal);
1164         WNetCloseEnum(hEnum);
1165         sprintf(szPath,"\\\\%s\\all",szMachine);
1166
1167         // Lets connect all submounts that weren't connectd
1168     DWORD cbUser=MAXRANDOMNAMELEN-1;
1169         CHAR szUser[MAXRANDOMNAMELEN];
1170     CHAR * pUser = NULL;
1171         if (WNetGetUser(szPath,(LPSTR)szUser,&cbUser)!=NO_ERROR) {
1172         if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY)) {
1173             if (!pUserName[0]) {
1174                 GenRandomName(szUser,MAXRANDOMNAMELEN-1);
1175                 pUser = szUser;
1176             } else {
1177                 pUser = pUserName;
1178             }
1179         }
1180     } else {
1181                 if ((pUser=strchr(szUser,'\\'))!=NULL)
1182             pUser++;
1183         }
1184
1185     for (DWORD j=0;j<List.cSubmounts;j++)
1186         {
1187                 if (List.aSubmounts[j].fInUse)
1188                         continue;
1189                 DWORD res=MountDOSDrive(0,List.aSubmounts[j].szSubmount,FALSE,pUser);
1190         }
1191         return TRUE;
1192 }
1193
1194 BOOL DoMapShare()
1195 {
1196         DRIVEMAPLIST List;
1197         DWORD rc=28;
1198         BOOL bMappedAll=FALSE;
1199
1200    // Initialize the data structure
1201         DEBUG_EVENT0("AFS DoMapShare");
1202         QueryDriveMapList (&List);
1203         DoUnMapShare(TRUE);
1204         // All connections have been removed
1205         // Lets restore them after making the connection from the random name
1206
1207         TCHAR szMachine[ MAX_PATH],szPath[MAX_PATH];
1208     memset(szMachine, '\0', sizeof(szMachine));
1209     GetClientNetbiosName(szMachine);
1210     sprintf(szPath,"\\\\%s\\all",szMachine);
1211
1212     // Lets connect all submounts that weren't connectd
1213     DWORD cbUser=MAXRANDOMNAMELEN-1;
1214         CHAR szUser[MAXRANDOMNAMELEN];
1215     CHAR * pUser = NULL;
1216         if (WNetGetUser(szPath,(LPSTR)szUser,&cbUser)!=NO_ERROR) {
1217         if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY)) {
1218             if (!pUserName[0]) {
1219                 GenRandomName(szUser,MAXRANDOMNAMELEN-1);
1220                 pUser = szUser;
1221             } else {
1222                 pUser = pUserName;
1223             }
1224         }
1225     } else {
1226                 if ((pUser=strchr(szUser,'\\'))!=NULL)
1227             pUser++;
1228         }
1229
1230         for (DWORD i=0;i<List.cSubmounts;i++)
1231         {
1232                 if (List.aSubmounts[i].szSubmount[0])
1233                 {
1234                         DWORD res=MountDOSDrive(0,List.aSubmounts[i].szSubmount,FALSE,pUser);
1235                         if (lstrcmpi("all",List.aSubmounts[i].szSubmount)==0)
1236                                 bMappedAll=TRUE;
1237                 }
1238         }
1239         if (!bMappedAll)        //make sure all is mapped also
1240         {
1241         DWORD res=MountDOSDrive(0,"all",FALSE,pUser);
1242         if (res==ERROR_SESSION_CREDENTIAL_CONFLICT)
1243         {
1244             DisMountDOSDrive("all");
1245             MountDOSDrive(0,"all",FALSE,pUser);
1246         }
1247         }
1248         for (TCHAR chDrive = chDRIVE_A; chDrive <= chDRIVE_Z; ++chDrive)
1249         {
1250                 if (List.aDriveMap[chDrive-chDRIVE_A].fActive ||
1251             ForceMapActive(chDrive))
1252                 {
1253             TCHAR szSubmount[ MAX_PATH ];
1254             if (List.aDriveMap[chDrive-chDRIVE_A].szSubmount[0])
1255                 lstrcpy(szSubmount,List.aDriveMap[chDrive-chDRIVE_A].szSubmount);
1256             else if (!PathToSubmount (szSubmount, List.aDriveMap[chDrive-chDRIVE_A].szMapping, NULL, NULL))
1257                 continue;
1258
1259             BOOL fPersistent = List.aDriveMap[chDrive-chDRIVE_A].fPersistent;
1260             if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1261                 fPersistent = FALSE;
1262                     DWORD res=MountDOSDrive(chDrive
1263                                             ,szSubmount
1264                                             ,fPersistent,pUser);
1265                 }
1266         }
1267         return TRUE;
1268 }
1269
1270 BOOL GlobalMountDrive()
1271 {
1272     char szDriveToMapTo[5];
1273     DWORD dwResult;
1274     char szKeyName[256];
1275     HKEY hKey;
1276     DWORD dwIndex = 0;
1277     DWORD dwDriveSize;
1278     DWORD dwSubMountSize;
1279     char unsigned szSubMount[256];
1280     char cm_HostName[200];
1281     DWORD dwType=sizeof(cm_HostName);
1282     if (!IsServiceActive())
1283         return TRUE;
1284     if (!GetComputerName(cm_HostName, &dwType))
1285         return TRUE;
1286     sprintf(szKeyName, "%s\\GlobalAutoMapper", sAFSConfigKeyName);
1287     
1288     dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE,
1289                             &hKey);
1290     if (dwResult != ERROR_SUCCESS)
1291         return TRUE;
1292     
1293     while (1) {
1294         dwDriveSize = sizeof(szDriveToMapTo);
1295         dwSubMountSize = sizeof(szSubMount);
1296         dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 
1297                                 0, &dwType, szSubMount, &dwSubMountSize);
1298         if (dwResult != ERROR_MORE_DATA) {
1299             if (dwResult != ERROR_SUCCESS) {
1300                 if (dwResult != ERROR_NO_MORE_ITEMS)
1301                 {
1302                     DEBUG_EVENT1("AFS DriveMap","Failed to read GlobalAutoMapper values: %d",dwResult);
1303                 }
1304                 break;
1305             }
1306         }
1307         dwResult=MountDOSDrive(*szDriveToMapTo,(const char *)szSubMount,FALSE,NULL);
1308     }
1309     RegCloseKey(hKey);
1310     return TRUE;
1311 }
1312
1313 DWORD MountDOSDrive(char chDrive,const char *szSubmount,BOOL bPersistent,const char * pUsername)
1314 {
1315     TCHAR szPath[MAX_PATH];
1316     TCHAR szClient[MAX_PATH];
1317     TCHAR szDrive[3] = TEXT("?:");
1318     sprintf(szDrive,"%c:",chDrive);
1319     GetClientNetbiosName (szClient);
1320     sprintf(szPath,"\\\\%s\\%s",szClient,szSubmount);
1321     NETRESOURCE nr;
1322     memset (&nr, 0x00, sizeof(NETRESOURCE));
1323     nr.dwType=RESOURCETYPE_DISK;
1324     nr.lpLocalName=szDrive;
1325     nr.lpRemoteName=szPath;
1326     nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
1327     DWORD res=WNetAddConnection2(&nr,NULL,pUsername,(bPersistent)?CONNECT_UPDATE_PROFILE:0);
1328     DEBUG_EVENT5("AFS DriveMap","Mount %s Local[%s] Remote[%s] User[%s]=%x",
1329                   (bPersistent)?"Persistant" : "NonPresistant",
1330                   szDrive,szPath,pUsername?pUsername:"NULL",res);
1331     return res;
1332 }
1333
1334 DWORD DisMountDOSDriveFull(const char *szPath,BOOL bForce)
1335 {
1336     DWORD res=WNetCancelConnection(szPath,bForce);
1337     DEBUG_EVENT3("AFS DriveMap","%sDismount Remote[%s]=%x",
1338                   bForce ? "Forced " : "",szPath,res);
1339     return (res==ERROR_NOT_CONNECTED)?NO_ERROR:res;
1340 }
1341
1342 DWORD DisMountDOSDrive(const char *pSubmount,BOOL bForce)
1343 {
1344     TCHAR szPath[MAX_PATH];
1345     TCHAR szClient[MAX_PATH];
1346     GetClientNetbiosName (szClient);
1347     sprintf(szPath,"\\\\%s\\%s",szClient,pSubmount);
1348     return DisMountDOSDriveFull(szPath,bForce);
1349 }
1350
1351
1352 DWORD DisMountDOSDrive(const char chDrive,BOOL bForce)
1353 {
1354     TCHAR szPath[MAX_PATH];
1355     sprintf(szPath,"%c:",chDrive);
1356     return DisMountDOSDriveFull(szPath,bForce);
1357 }