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