expand-drive-mappings-20040823
[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                     cszSECTION_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         if ( dwType == REG_EXPAND_SZ ) {
484             TCHAR buf[MAX_PATH];
485             DWORD dummyLen = ExpandEnvironmentStrings(buf, mapping, MAX_PATH);
486             if (dummyLen > MAX_PATH)
487                 continue;
488             _tcsncpy(mapping, buf, MAX_PATH);
489         }
490
491         DRIVEMAP DriveMap;
492         memset (&DriveMap, 0x00, sizeof(DRIVEMAP));
493         DriveMap.chDrive = toupper(*drive);
494         DriveMap.fPersistent = TRUE;
495         if ((DriveMap.chDrive < chDRIVE_A) || (DriveMap.chDrive > chDRIVE_Z))
496             continue;
497
498        if (mapping[0] != TEXT('\0'))
499        {
500            AdjustAfsPath (DriveMap.szMapping, mapping, TRUE, TRUE);
501            if (DriveMap.szMapping[ lstrlen(DriveMap.szMapping)-1 ] == TEXT('*'))
502            {
503                DriveMap.fPersistent = FALSE;
504                DriveMap.szMapping[ lstrlen(DriveMap.szMapping)-1 ] = TEXT('\0');
505            }
506            size_t iDrive = DriveMap.chDrive - chDRIVE_A;
507            memcpy (&pList->aDriveMap[ iDrive ], &DriveMap, sizeof(DRIVEMAP));
508        }
509     }
510
511     RegCloseKey(hkMappings);
512 }
513
514 BOOL ForceMapActive (TCHAR chDrive)
515 {
516     TCHAR szDrive[2];
517     TCHAR szActive[32];
518
519     szDrive[0] = chDrive;
520     szDrive[1] = 0;
521
522     DWORD len = sizeof(szActive);
523     ReadRegistryString( HKEY_CURRENT_USER, cszSECTION_ACTIVE, szDrive, szActive, &len);
524
525     if ( !lstrcmp(szActive,"1") || !lstrcmpi(szActive,"true") || !lstrcmpi(szActive,"on") || !lstrcmpi(szActive,"yes") )
526         return TRUE;
527     return FALSE;
528 }
529
530
531 void WriteActiveMap (TCHAR chDrive, BOOL on)
532 {
533     TCHAR szDrive[2];
534
535     szDrive[0] = chDrive;
536     szDrive[1] = 0;
537
538     WriteRegistryString(HKEY_CURRENT_USER, cszSECTION_ACTIVE, szDrive, on ? "1" : "0");
539 }
540
541 void QueryDriveMapList_WriteMappings (PDRIVEMAPLIST pList)
542 {
543     WriteDriveMappings (pList);
544 }
545
546
547 void WriteDriveMappings (PDRIVEMAPLIST pList)
548 {
549     HKEY hkMappings;
550     RegCreateKeyEx( HKEY_CURRENT_USER, 
551                     cszSECTION_MAPPINGS,
552                     0, 
553                     "AFS", 
554                     REG_OPTION_NON_VOLATILE,
555                     KEY_READ|KEY_QUERY_VALUE|KEY_WRITE,
556                     NULL, 
557                     &hkMappings,
558                     NULL );
559
560     DWORD dwMappings;
561     RegQueryInfoKey( hkMappings,
562                      NULL,  /* lpClass */
563                      NULL,  /* lpcClass */
564                      NULL,  /* lpReserved */
565                      NULL,  /* lpcSubKeys */
566                      NULL,  /* lpcMaxSubKeyLen */
567                      NULL,  /* lpcMaxClassLen */
568                      &dwMappings, /* lpcValues */
569                      NULL,  /* lpcMaxValueNameLen */
570                      NULL,  /* lpcMaxValueLen */
571                      NULL,  /* lpcbSecurityDescriptor */
572                      NULL   /* lpftLastWriteTime */
573                      );
574
575     if ( dwMappings > 0 ) {
576         for ( long dwIndex = dwMappings - 1; dwIndex >= 0; dwIndex-- ) {
577             TCHAR drive[MAX_PATH];
578             DWORD driveLen = MAX_PATH;
579
580             RegEnumValue( hkMappings, dwIndex, drive, &driveLen, NULL, NULL, NULL, NULL);
581             RegDeleteValue( hkMappings, drive );
582         }
583     }
584
585    for (size_t iDrive = 0; iDrive < 26; ++iDrive)
586    {
587        if (pList->aDriveMap[iDrive].szMapping[0] != TEXT('\0'))
588        {
589            TCHAR szLHS[] = TEXT("*");
590            szLHS[0] = pList->aDriveMap[iDrive].chDrive;
591
592            TCHAR szRHS[MAX_PATH];
593            AdjustAfsPath (szRHS, pList->aDriveMap[iDrive].szMapping, TRUE, TRUE);
594            if (!pList->aDriveMap[iDrive].fPersistent)
595                lstrcat (szRHS, TEXT("*"));
596
597            RegSetValueEx( hkMappings, szLHS, 0, REG_EXPAND_SZ, (const BYTE *)szRHS, lstrlen(szRHS) + 1);
598        }
599    }
600    RegCloseKey( hkMappings );
601 }
602
603 BOOL DriveIsGlobalAfsDrive(TCHAR chDrive)
604 {
605    TCHAR szKeyName[128];
606    TCHAR szValueName[128];
607    TCHAR szValue[128];
608    HKEY hKey;
609
610    _stprintf(szKeyName, TEXT("%s\\GlobalAutoMapper"), sAFSConfigKeyName);
611
612    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
613       return FALSE;
614
615    _stprintf(szValueName, TEXT("%c:"), chDrive);
616
617    DWORD dwSize = sizeof(szValue);
618    BOOL bIsGlobal = (RegQueryValueEx (hKey, szValueName, NULL, NULL, (PBYTE)szValue, &dwSize) == ERROR_SUCCESS);
619
620    RegCloseKey (hKey);
621    
622    return bIsGlobal;
623 }
624
625
626 void QueryDriveMapList_FindNetworkDrives (PDRIVEMAPLIST pList, BOOL *pfFoundNew)
627 {
628    for (TCHAR chDrive = chDRIVE_A; chDrive <= chDRIVE_Z; ++chDrive)
629       {
630       TCHAR szSubmount[ MAX_PATH ];
631       if (!GetDriveSubmount (chDrive, szSubmount))
632          continue;
633
634       // We've got a mapping!  Drive {chDrive} is mapped to submount
635       // {szSubmount}. See if that submount makes sense.
636       //
637       if (!IsWindowsNT())
638          {
639          size_t iDrive = chDrive - chDRIVE_A;
640          if (pList->aDriveMap[ iDrive ].szMapping[0] != TEXT('\0'))
641             {
642             pList->aDriveMap[ iDrive ].fActive = TRUE;
643             lstrcpy (pList->aDriveMap[ iDrive ].szSubmount, szSubmount);
644             }
645          continue;
646          }
647       else // (IsWindowsNT())
648          {
649          TCHAR szAfsPath[ MAX_PATH ];
650          if (!SubmountToPath (pList, szAfsPath, szSubmount, TRUE))
651             continue;
652
653          // Okay, we know that drive {chDrive} is mapped to afs path {szAfsPath}.
654          // If this drive is a global afs drive, then reject it.  Otherwise, look 
655          // at pList->aDriveMap, to see if this drive mapping is already in our 
656          // list. If not, add it and set pfFoundNew.
657          //
658          if (DriveIsGlobalAfsDrive(chDrive))
659             continue;
660          
661          size_t iDrive = chDrive - chDRIVE_A;
662          if (lstrcmpi (pList->aDriveMap[ iDrive ].szMapping, szAfsPath))
663             {
664             *pfFoundNew = TRUE;
665             pList->aDriveMap[ iDrive ].fPersistent = TRUE;
666             }
667          pList->aDriveMap[ iDrive ].fActive = TRUE;
668          pList->aDriveMap[ iDrive ].chDrive = chDrive;
669          lstrcpy (pList->aDriveMap[ iDrive ].szSubmount, szSubmount);
670          AdjustAfsPath (pList->aDriveMap[ iDrive ].szMapping, szAfsPath, TRUE, TRUE);
671          }
672       }
673 }
674
675
676 void QueryDriveMapList (PDRIVEMAPLIST pList)
677 {
678    // Initialize the data structure
679    //
680    memset (pList, 0x00, sizeof(DRIVEMAPLIST));
681    for (size_t ii = 0; ii < 26; ++ii)
682       pList->aDriveMap[ii].chDrive = chDRIVE_A + ii;
683
684    // Read the current lists of submounts and drive letter mappings
685    //
686    QueryDriveMapList_ReadSubmounts (pList);
687    QueryDriveMapList_ReadMappings (pList);
688
689    // Look through the current list of network drives, and see if
690    // any are currently mapped to AFS. If we find any which are mapped
691    // into AFS unexpectedly, we'll have to rewrite the mappings list.
692    //
693    BOOL fFoundNew = FALSE;
694    QueryDriveMapList_FindNetworkDrives (pList, &fFoundNew);
695
696    if (fFoundNew)
697       {
698       QueryDriveMapList_WriteMappings (pList);
699       }
700 }
701
702
703 void FreeDriveMapList (PDRIVEMAPLIST pList)
704 {
705    if (pList->aSubmounts)
706       Free (pList->aSubmounts);
707    memset (pList, 0x00, sizeof(DRIVEMAPLIST));
708 }
709
710
711 BOOL PathToSubmount (LPTSTR pszSubmount, LPTSTR pszMapping, LPTSTR pszSubmountReq, ULONG *pStatus)
712 {
713    if (pszSubmountReq && !IsValidSubmountName (pszSubmountReq))
714       pszSubmountReq = NULL;
715
716    TCHAR szAfsPath[ MAX_PATH ];
717    AdjustAfsPath (szAfsPath, pszMapping, TRUE, TRUE);
718
719    // Try to ask AFSD for a new submount name.
720    //
721    if (!fCanIssuePIOCTL())
722       return FALSE;
723
724    BYTE InData[ PIOCTL_MAXSIZE ];
725    memset (InData, 0x00, sizeof(InData));
726
727    LPTSTR pszInData = (LPTSTR)InData;
728    lstrcpy (pszInData, pszMapping);
729    pszInData += 1+lstrlen(pszInData);
730    if (pszSubmountReq)
731       lstrcpy (pszInData, pszSubmountReq);
732
733    BYTE OutData[ PIOCTL_MAXSIZE ];
734    memset (OutData, 0x00, sizeof(OutData));
735
736    struct ViceIoctl IOInfo;
737    IOInfo.in = (char *)InData;
738    IOInfo.in_size = PIOCTL_MAXSIZE;
739    IOInfo.out = (char *)OutData;
740    IOInfo.out_size = PIOCTL_MAXSIZE;
741
742    ULONG status = pioctl (0, VIOC_MAKESUBMOUNT, &IOInfo, 1);
743    if (pStatus)
744        *pStatus = status;
745
746    if (status)
747       return FALSE;
748
749    lstrcpy (pszSubmount, (LPCTSTR)OutData);
750    return (pszSubmount[0] != TEXT('\0')) ? TRUE : FALSE;
751 }
752
753
754 BOOL ActivateDriveMap (TCHAR chDrive, LPTSTR pszMapping, LPTSTR pszSubmountReq, BOOL fPersistent, DWORD *pdwStatus)
755 {
756    // We can only map drives to places in AFS using this function.
757    //
758    if ( (lstrncmpi (pszMapping, cm_slash_mount_root, lstrlen(cm_slash_mount_root))) &&
759         (lstrncmpi (pszMapping, cm_back_slash_mount_root, lstrlen(cm_back_slash_mount_root))) )
760       {
761       if (pdwStatus)
762          *pdwStatus = ERROR_BAD_NETPATH;
763       return FALSE;
764       }
765
766    // First we have to translate {pszMapping} into a submount, and if there is
767    // no current submount associated with this path, we'll have to make one.
768    //
769    ULONG status;
770    TCHAR szSubmount[ MAX_PATH ];
771    if (!PathToSubmount (szSubmount, pszMapping, pszSubmountReq, &status))
772       {
773       if (pdwStatus)
774          *pdwStatus = status;
775       return FALSE;
776       }
777
778    // We now have a submount name and drive letter--map the network drive.
779    DWORD rc=MountDOSDrive(chDrive,szSubmount,fPersistent,NULL);
780    if (rc == NO_ERROR)
781       return TRUE;
782
783    if (pdwStatus)
784       *pdwStatus = rc;
785    return FALSE;
786 }
787
788
789 BOOL InactivateDriveMap (TCHAR chDrive, DWORD *pdwStatus)
790 {
791     DWORD rc = DisMountDOSDrive(chDrive, FALSE);
792     if (rc == NO_ERROR)
793         return TRUE;
794
795     if (pdwStatus)
796         *pdwStatus = rc;
797     return FALSE;
798 }
799
800
801 void AddSubMount (LPTSTR pszSubmount, LPTSTR pszMapping)
802 {
803     TCHAR szRHS[ MAX_PATH ];
804     AdjustAfsPath (szRHS, pszMapping, FALSE, TRUE);
805     if (!szRHS[0])
806         lstrcpy (szRHS, TEXT("/"));
807
808     WriteRegistryString(HKEY_LOCAL_MACHINE, cszSECTION_SUBMOUNTS, pszSubmount, szRHS);
809 }
810
811
812 void RemoveSubMount (LPTSTR pszSubmount)
813 {
814     DeleteRegistryString(HKEY_LOCAL_MACHINE, cszSECTION_SUBMOUNTS, pszSubmount);
815 }
816
817
818 void AdjustAfsPath (LPTSTR pszTarget, LPCTSTR pszSource, BOOL fWantAFS, BOOL fWantForwardSlashes)
819 {
820     if (!*pszSource)
821         lstrcpy (pszTarget, (fWantAFS) ? cm_slash_mount_root : TEXT(""));
822     else if ((*pszSource != TEXT('/')) && (*pszSource != TEXT('\\')))
823         wsprintf (pszTarget, TEXT("%s/%s"),cm_slash_mount_root, pszSource);
824     // We don't want to strip afs off the start if it is part of something for example afscell.company.com
825     else if (fWantAFS && (lstrncmpi (&pszSource[1], cm_mount_root, strlen(cm_mount_root))) || !((pszSource[strlen(cm_slash_mount_root)] == TEXT('/')) ||
826                                                                                                  (pszSource[strlen(cm_slash_mount_root)] == TEXT('\\')) ||
827                                                                                                  (lstrlen(pszSource) == strlen(cm_slash_mount_root))))
828         wsprintf (pszTarget, TEXT("%s%s"),cm_slash_mount_root, pszSource);
829     else if (!fWantAFS && (!lstrncmpi (&pszSource[1], cm_mount_root, strlen(cm_mount_root)) && ((pszSource[strlen(cm_slash_mount_root)] == TEXT('/')) ||
830                                                                                                  (pszSource[strlen(cm_slash_mount_root)] == TEXT('\\')) ||
831                                                                                                  (lstrlen(pszSource) == strlen(cm_slash_mount_root)))))
832         lstrcpy (pszTarget, &pszSource[strlen(cm_slash_mount_root)]);
833     else
834         lstrcpy (pszTarget, pszSource);
835
836    for (LPTSTR pch = pszTarget; *pch; ++pch)
837       {
838       if (fWantForwardSlashes)
839          {
840          *pch = (*pch == TEXT('\\')) ? TEXT('/') : (*pch);
841          }
842       else // (!fWantForwardSlashes)
843          {
844          *pch = (*pch == TEXT('/')) ? TEXT('\\') : (*pch);
845          }
846       }
847
848    if (lstrlen(pszTarget) &&
849        ((pszTarget[lstrlen(pszTarget)-1] == TEXT('/')) ||
850         (pszTarget[lstrlen(pszTarget)-1] == TEXT('\\'))))
851       {
852       pszTarget[lstrlen(pszTarget)-1] = TEXT('\0');
853       }
854 }
855
856 BOOL GetDriveSubmount (TCHAR chDrive, LPTSTR pszSubmountNow)
857 {
858         BOOL isWinNT = IsWindowsNT();
859
860         TCHAR szDrive[] = TEXT("*:");
861     szDrive[0] = chDrive;
862
863     TCHAR szMapping[ _MAX_PATH ] = TEXT("");
864
865     if (isWinNT && !QueryDosDevice (szDrive, szMapping, MAX_PATH))
866            return FALSE;
867
868     LPTSTR pszSubmount = szMapping;
869     
870         TCHAR szNetBiosName[32];
871     memset(szNetBiosName, '\0', sizeof(szNetBiosName));
872     GetClientNetbiosName(szNetBiosName);
873     _tcscat(szNetBiosName, TEXT("\\"));
874
875    if (isWinNT)
876    {
877       // Now if this is an AFS network drive mapping, {szMapping} will be:
878       //
879       //   \Device\LanmanRedirector\<Drive>:\<netbiosname>\submount
880       //
881       // on Windows NT. On Windows 2000, it will be:
882       //
883       //   \Device\LanmanRedirector\;<Drive>:0\<netbiosname>\submount
884       //
885       // (This is presumably to support multiple drive mappings with
886       // Terminal Server).
887       //
888       // on Windows XP and 2003, it will be :
889       //   \Device\LanmanRedirector\;<Drive>:<AuthID>\<netbiosname>\submount
890       //
891       //   where : <Drive> : DOS drive letter
892       //           <AuthID>: Authentication ID, 16 char hex.
893       //           <netbiosname>: Netbios name of server
894       //
895       if (_tcsnicmp(szMapping, cszLANMANDEVICE, _tcslen(cszLANMANDEVICE)))
896          return FALSE;
897       pszSubmount = &szMapping[ _tcslen(cszLANMANDEVICE) ];
898
899       if (IsWindows2000())
900           {
901           if (*(pszSubmount) != TEXT(';'))
902              return FALSE;
903           } else 
904                 --pszSubmount;
905
906       if (toupper(*(++pszSubmount)) != chDrive)
907          return FALSE;
908
909       if (*(++pszSubmount) != TEXT(':'))
910          return FALSE;
911
912 #ifdef COMMENT
913        // No longer a safe assumption on XP
914       if (IsWindows2000())
915           if (*(++pszSubmount) != TEXT('0'))
916              return FALSE;
917 #endif
918
919       // scan for next "\"
920       while (*(++pszSubmount) != TEXT('\\'))
921       {
922           if (*pszSubmount==0)
923               return FALSE;
924       }
925
926        // note that szNetBiosName has a '\\' tagged in the end earlier
927       for (++pszSubmount; *pszSubmount && (*pszSubmount != TEXT('\\')); ++pszSubmount)
928          if (!_tcsncicmp(pszSubmount, szNetBiosName, _tcslen(szNetBiosName)))
929             break;
930       if ((!*pszSubmount) || (*pszSubmount == TEXT('\\')))
931          return FALSE;
932
933        pszSubmount += _tcslen(szNetBiosName);
934       }
935    else // (!IsWindowsNT())
936       {
937       DWORD dwSize = MAX_PATH;
938       if (WNetGetConnection (szDrive, szMapping, &dwSize) != NO_ERROR)
939          return FALSE;
940       if (*(pszSubmount++) != TEXT('\\'))
941          return FALSE;
942       if (*(pszSubmount++) != TEXT('\\'))
943          return FALSE;
944       for ( ; *pszSubmount && (*pszSubmount != TEXT('\\')); ++pszSubmount)
945          if (!lstrncmpi (pszSubmount, szNetBiosName, lstrlen(szNetBiosName)))
946             break;
947       if ((!*pszSubmount) || (*pszSubmount == TEXT('\\')))
948          return FALSE;
949       pszSubmount += lstrlen(szNetBiosName);
950       }
951
952    if (!pszSubmount || !*pszSubmount)
953       return FALSE;
954
955    lstrcpy (pszSubmountNow, pszSubmount);
956    return TRUE;
957 }
958
959 /* Generate Random User name random acording to time*/
960 DWORD dwOldState=0;
961 TCHAR pUserName[MAXRANDOMNAMELEN]=TEXT("");
962 BOOL fUserName=FALSE;
963 #define AFSLogonOptionName TEXT("System\\CurrentControlSet\\Services\\TransarcAFSDaemon\\NetworkProvider")
964
965 void SetBitLogonOption(BOOL set,DWORD value)
966 {
967
968    RWLogonOption(FALSE,((set)?value | RWLogonOption(TRUE,0):RWLogonOption(TRUE,0) & ~value) );  
969 }
970
971 DWORD RWLogonOption(BOOL read,DWORD value)
972 {
973         // if read is true then if value==0 return registry value
974         // if read and value!=0 then use value to test registry, return TRUE if value bits match value read
975    HKEY hk;
976    DWORD dwDisp;
977         DWORD LSPtype, LSPsize;
978         DWORD rval;
979    if (read)
980    {
981            rval=0;
982                 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSLogonOptionName, 0, KEY_QUERY_VALUE, &hk)==ERROR_SUCCESS)
983                 {
984                         LSPsize=sizeof(rval);
985                         RegQueryValueEx(hk, "LogonOptions", NULL,
986                                                 &LSPtype, (LPBYTE)&rval, &LSPsize);
987                         RegCloseKey (hk);
988                 }
989                 return (value==0)?rval:((rval & value)==value);
990
991    } else {     //write
992                 if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, AFSLogonOptionName, 0, NULL, 0, KEY_SET_VALUE, NULL, &hk, &dwDisp) == ERROR_SUCCESS)
993                 {
994                         RegSetValueEx(hk,TEXT("LogonOptions"),NULL,REG_DWORD,(LPBYTE)&value,sizeof(value));
995                         RegCloseKey (hk);
996                 }
997                 return TRUE;
998    }
999 }
1000
1001 void MapShareName(char *pszCmdLineA)
1002 {
1003         fUserName = TRUE;
1004         TCHAR *p=pUserName;
1005         pszCmdLineA++;
1006         while (*pszCmdLineA && (*pszCmdLineA != ' '))
1007         {
1008           *p++=*pszCmdLineA++;
1009         }
1010 }
1011
1012 void GenRandomName(TCHAR *pname,int len)
1013 {
1014         if (fUserName)
1015         {               //user name was passed through command line, use once
1016                 fUserName=FALSE;
1017                 return;
1018         }
1019         srand( (unsigned)time( NULL ) );
1020         for (int i=0;i<len;i++)
1021                 pname[i]='a'+(rand() % 26);
1022         pname[len]=0;
1023         return;
1024 }
1025
1026 /*
1027         Make a connection using users name
1028         if fUserName then force a connection
1029 */
1030
1031 BOOL TestAndDoMapShare(DWORD dwState)
1032 {
1033     if ((dwState!=SERVICE_RUNNING) || (dwOldState!=SERVICE_START_PENDING))
1034         {
1035                 dwOldState=dwState;
1036                 return TRUE;
1037         }
1038         dwOldState=SERVICE_RUNNING;
1039         if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1040             return (DoMapShare() && GlobalMountDrive());
1041         return GlobalMountDrive();
1042 }
1043
1044 BOOL IsServiceActive()
1045 {
1046    SC_HANDLE hManager;
1047    SERVICE_STATUS Status;
1048    if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
1049       {
1050       SC_HANDLE hService;
1051       if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
1052          {
1053          QueryServiceStatus (hService, &Status);
1054          CloseServiceHandle (hService);
1055          }
1056
1057       CloseServiceHandle (hManager);
1058       }
1059
1060    return (Status.dwCurrentState == SERVICE_RUNNING) ? TRUE : FALSE;
1061 }
1062
1063 void TestAndDoUnMapShare()
1064 {
1065         if (!RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1066                 return;
1067         DoUnMapShare(FALSE);    
1068 }
1069
1070 void DoUnMapShare(BOOL drivemap)        //disconnect drivemap 
1071 {
1072         TCHAR szMachine[MAX_PATH],szPath[MAX_PATH];
1073         DWORD rc=28;
1074         HANDLE hEnum;
1075         LPNETRESOURCE lpnrLocal,lpnr=NULL;
1076         DWORD res;
1077         DWORD cbBuffer=16384;
1078         DWORD cEntries=-1;
1079         CHAR *pSubmount="";
1080
1081     memset(szMachine, '\0', sizeof(szMachine));
1082     GetClientNetbiosName(szMachine);
1083
1084    // Initialize the data structure
1085         if ((res=WNetOpenEnum(RESOURCE_CONNECTED,RESOURCETYPE_DISK,RESOURCEUSAGE_CONNECTABLE,lpnr,&hEnum))!=NO_ERROR)
1086                 return;
1087         sprintf(szPath,"\\\\%s\\",szMachine);
1088         _strlwr(szPath);
1089         lpnrLocal=(LPNETRESOURCE) GlobalAlloc(GPTR,cbBuffer);
1090         do {
1091                 memset(lpnrLocal,0,cbBuffer);
1092                 if ((res = WNetEnumResource(hEnum,&cEntries,lpnrLocal,&cbBuffer))==NO_ERROR)
1093                 {
1094                         for (DWORD i=0;i<cEntries;i++)
1095                         {
1096                                 if (strstr(_strlwr(lpnrLocal[i].lpRemoteName),szPath))
1097                                 {
1098                                         if ((lpnrLocal[i].lpLocalName) && (strlen(lpnrLocal[i].lpLocalName)>0))
1099                                         {
1100                                                 if (drivemap) {
1101                                                     DisMountDOSDrive(*lpnrLocal[i].lpLocalName);
1102                             DEBUG_EVENT1("AFS DriveUnMap","UnMap-Local=%x",res);
1103                         }
1104                                         } else {
1105                                             DisMountDOSDriveFull(lpnrLocal[i].lpRemoteName);
1106                         DEBUG_EVENT1("AFS DriveUnMap","UnMap-Remote=%x",res);
1107                     }
1108                                 }
1109                         }
1110                 }
1111         } while (res!=ERROR_NO_MORE_ITEMS);
1112         GlobalFree((HGLOBAL)lpnrLocal);
1113         WNetCloseEnum(hEnum);
1114 }
1115
1116 BOOL DoMapShareChange()
1117 {
1118         DRIVEMAPLIST List;
1119         TCHAR szMachine[ MAX_PATH],szPath[MAX_PATH];
1120         DWORD rc=28;
1121         HANDLE hEnum;
1122         LPNETRESOURCE lpnrLocal,lpnr=NULL;
1123         DWORD res;
1124         DWORD cEntries=-1;
1125     DWORD cbBuffer=16384;
1126
1127     memset(szMachine, '\0', sizeof(szMachine));
1128     GetClientNetbiosName(szMachine);
1129
1130     // Initialize the data structure
1131         if (!IsServiceActive())
1132                 return TRUE;
1133         memset (&List, 0x00, sizeof(DRIVEMAPLIST));
1134         for (size_t ii = 0; ii < 26; ++ii)
1135                 List.aDriveMap[ii].chDrive = chDRIVE_A + ii;
1136         QueryDriveMapList_ReadSubmounts (&List);
1137         if ((res=WNetOpenEnum(RESOURCE_CONNECTED,RESOURCETYPE_DISK,RESOURCEUSAGE_CONNECTABLE,lpnr,&hEnum))!=NO_ERROR)
1138                 return FALSE;
1139         lpnrLocal=(LPNETRESOURCE) GlobalAlloc(GPTR,cbBuffer);
1140         sprintf(szPath,"\\\\%s\\",szMachine);
1141         _strlwr(szPath);
1142         do {
1143                 memset(lpnrLocal,0,cbBuffer);
1144                 if ((res = WNetEnumResource(hEnum,&cEntries,lpnrLocal,&cbBuffer))==NO_ERROR)
1145                 {
1146                         for (DWORD i=0;i<cEntries;i++)
1147                         {
1148                                 if (strstr(_strlwr(lpnrLocal[i].lpRemoteName),szPath)==NULL)
1149                                         continue;       //only look at real afs mappings
1150                                 CHAR * pSubmount=strrchr(lpnrLocal[i].lpRemoteName,'\\')+1;
1151                                 if (lstrcmpi(pSubmount,"all")==0) 
1152                                         continue;                               // do not remove 'all'
1153                                 for (DWORD j=0;j<List.cSubmounts;j++)
1154                                 {
1155                                         if (
1156                                                 (List.aSubmounts[j].szSubmount[0]) &&
1157                                                 (lstrcmpi(List.aSubmounts[j].szSubmount,pSubmount)==0)
1158                                                 ) 
1159                                         {
1160                                                 List.aSubmounts[j].fInUse=TRUE; 
1161                                                 goto nextname;
1162                                         }
1163                                 }
1164                                 // wasn't on list so lets remove
1165                                 DisMountDOSDrive(pSubmount);
1166                                 nextname:;
1167                         }
1168                 }
1169         } while (res!=ERROR_NO_MORE_ITEMS);
1170         GlobalFree((HGLOBAL)lpnrLocal);
1171         WNetCloseEnum(hEnum);
1172         sprintf(szPath,"\\\\%s\\all",szMachine);
1173
1174         // Lets connect all submounts that weren't connectd
1175     DWORD cbUser=MAXRANDOMNAMELEN-1;
1176         CHAR szUser[MAXRANDOMNAMELEN];
1177     CHAR * pUser = NULL;
1178         if (WNetGetUser(szPath,(LPSTR)szUser,&cbUser)!=NO_ERROR) {
1179         if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY)) {
1180             if (!pUserName[0]) {
1181                 GenRandomName(szUser,MAXRANDOMNAMELEN-1);
1182                 pUser = szUser;
1183             } else {
1184                 pUser = pUserName;
1185             }
1186         }
1187     } else {
1188                 if ((pUser=strchr(szUser,'\\'))!=NULL)
1189             pUser++;
1190         }
1191
1192     for (DWORD j=0;j<List.cSubmounts;j++)
1193         {
1194                 if (List.aSubmounts[j].fInUse)
1195                         continue;
1196                 DWORD res=MountDOSDrive(0,List.aSubmounts[j].szSubmount,FALSE,pUser);
1197         }
1198         return TRUE;
1199 }
1200
1201 BOOL DoMapShare()
1202 {
1203         DRIVEMAPLIST List;
1204         DWORD rc=28;
1205         BOOL bMappedAll=FALSE;
1206
1207    // Initialize the data structure
1208         DEBUG_EVENT0("AFS DoMapShare");
1209         QueryDriveMapList (&List);
1210         DoUnMapShare(TRUE);
1211         // All connections have been removed
1212         // Lets restore them after making the connection from the random name
1213
1214         TCHAR szMachine[ MAX_PATH],szPath[MAX_PATH];
1215     memset(szMachine, '\0', sizeof(szMachine));
1216     GetClientNetbiosName(szMachine);
1217     sprintf(szPath,"\\\\%s\\all",szMachine);
1218
1219     // Lets connect all submounts that weren't connectd
1220     DWORD cbUser=MAXRANDOMNAMELEN-1;
1221         CHAR szUser[MAXRANDOMNAMELEN];
1222     CHAR * pUser = NULL;
1223         if (WNetGetUser(szPath,(LPSTR)szUser,&cbUser)!=NO_ERROR) {
1224         if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY)) {
1225             if (!pUserName[0]) {
1226                 GenRandomName(szUser,MAXRANDOMNAMELEN-1);
1227                 pUser = szUser;
1228             } else {
1229                 pUser = pUserName;
1230             }
1231         }
1232     } else {
1233                 if ((pUser=strchr(szUser,'\\'))!=NULL)
1234             pUser++;
1235         }
1236
1237         for (DWORD i=0;i<List.cSubmounts;i++)
1238         {
1239                 if (List.aSubmounts[i].szSubmount[0])
1240                 {
1241                         DWORD res=MountDOSDrive(0,List.aSubmounts[i].szSubmount,FALSE,pUser);
1242                         if (lstrcmpi("all",List.aSubmounts[i].szSubmount)==0)
1243                                 bMappedAll=TRUE;
1244                 }
1245         }
1246         if (!bMappedAll)        //make sure all is mapped also
1247         {
1248         DWORD res=MountDOSDrive(0,"all",FALSE,pUser);
1249         if (res==ERROR_SESSION_CREDENTIAL_CONFLICT)
1250         {
1251             DisMountDOSDrive("all");
1252             MountDOSDrive(0,"all",FALSE,pUser);
1253         }
1254         }
1255         for (TCHAR chDrive = chDRIVE_A; chDrive <= chDRIVE_Z; ++chDrive)
1256         {
1257                 if (List.aDriveMap[chDrive-chDRIVE_A].fActive ||
1258             ForceMapActive(chDrive))
1259                 {
1260             TCHAR szSubmount[ MAX_PATH ];
1261             if (List.aDriveMap[chDrive-chDRIVE_A].szSubmount[0])
1262                 lstrcpy(szSubmount,List.aDriveMap[chDrive-chDRIVE_A].szSubmount);
1263             else if (!PathToSubmount (szSubmount, List.aDriveMap[chDrive-chDRIVE_A].szMapping, NULL, NULL))
1264                 continue;
1265
1266             BOOL fPersistent = List.aDriveMap[chDrive-chDRIVE_A].fPersistent;
1267             if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1268                 fPersistent = FALSE;
1269                     DWORD res=MountDOSDrive(chDrive
1270                                             ,szSubmount
1271                                             ,fPersistent,pUser);
1272                 }
1273         }
1274         return TRUE;
1275 }
1276
1277 BOOL GlobalMountDrive()
1278 {
1279     char szDriveToMapTo[5];
1280     DWORD dwResult;
1281     char szKeyName[256];
1282     HKEY hKey;
1283     DWORD dwIndex = 0;
1284     DWORD dwDriveSize;
1285     DWORD dwSubMountSize;
1286     char unsigned szSubMount[256];
1287     char cm_HostName[200];
1288     DWORD dwType=sizeof(cm_HostName);
1289     if (!IsServiceActive())
1290         return TRUE;
1291     if (!GetComputerName(cm_HostName, &dwType))
1292         return TRUE;
1293     sprintf(szKeyName, "%s\\GlobalAutoMapper", sAFSConfigKeyName);
1294     
1295     dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE,
1296                             &hKey);
1297     if (dwResult != ERROR_SUCCESS)
1298         return TRUE;
1299     
1300     while (1) {
1301         dwDriveSize = sizeof(szDriveToMapTo);
1302         dwSubMountSize = sizeof(szSubMount);
1303         dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize, 
1304                                 0, &dwType, szSubMount, &dwSubMountSize);
1305         if (dwResult != ERROR_MORE_DATA) {
1306             if (dwResult != ERROR_SUCCESS) {
1307                 if (dwResult != ERROR_NO_MORE_ITEMS)
1308                 {
1309                     DEBUG_EVENT1("AFS DriveMap","Failed to read GlobalAutoMapper values: %d",dwResult);
1310                 }
1311                 break;
1312             }
1313         }
1314         dwResult=MountDOSDrive(*szDriveToMapTo,(const char *)szSubMount,FALSE,NULL);
1315     }
1316     RegCloseKey(hKey);
1317     return TRUE;
1318 }
1319
1320 DWORD MountDOSDrive(char chDrive,const char *szSubmount,BOOL bPersistent,const char * pUsername)
1321 {
1322     TCHAR szPath[MAX_PATH];
1323     TCHAR szClient[MAX_PATH];
1324     TCHAR szDrive[3] = TEXT("?:");
1325     sprintf(szDrive,"%c:",chDrive);
1326     GetClientNetbiosName (szClient);
1327     sprintf(szPath,"\\\\%s\\%s",szClient,szSubmount);
1328     NETRESOURCE nr;
1329     memset (&nr, 0x00, sizeof(NETRESOURCE));
1330     nr.dwType=RESOURCETYPE_DISK;
1331     nr.lpLocalName=szDrive;
1332     nr.lpRemoteName=szPath;
1333     nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
1334     DWORD res=WNetAddConnection2(&nr,NULL,pUsername,(bPersistent)?CONNECT_UPDATE_PROFILE:0);
1335     DEBUG_EVENT5("AFS DriveMap","Mount %s Local[%s] Remote[%s] User[%s]=%x",
1336                   (bPersistent)?"Persistant" : "NonPresistant",
1337                   szDrive,szPath,pUsername?pUsername:"NULL",res);
1338     return res;
1339 }
1340
1341 DWORD DisMountDOSDriveFull(const char *szPath,BOOL bForce)
1342 {
1343     DWORD res=WNetCancelConnection(szPath,bForce);
1344     DEBUG_EVENT3("AFS DriveMap","%sDismount Remote[%s]=%x",
1345                   bForce ? "Forced " : "",szPath,res);
1346     return (res==ERROR_NOT_CONNECTED)?NO_ERROR:res;
1347 }
1348
1349 DWORD DisMountDOSDrive(const char *pSubmount,BOOL bForce)
1350 {
1351     TCHAR szPath[MAX_PATH];
1352     TCHAR szClient[MAX_PATH];
1353     GetClientNetbiosName (szClient);
1354     sprintf(szPath,"\\\\%s\\%s",szClient,pSubmount);
1355     return DisMountDOSDriveFull(szPath,bForce);
1356 }
1357
1358
1359 DWORD DisMountDOSDrive(const char chDrive,BOOL bForce)
1360 {
1361     TCHAR szPath[MAX_PATH];
1362     sprintf(szPath,"%c:",chDrive);
1363     return DisMountDOSDriveFull(szPath,bForce);
1364 }