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