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