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