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