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