2 * Copyright 2000, International Business Machines Corporation and others.
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
11 #include <afs/param.h>
14 #include <afs/fs_utils.h>
19 #include <WINNT/TaLocale.h>
28 #include <lanahelper.h>
30 extern void Config_GetLanAdapter (ULONG *pnLanAdapter);
33 * REGISTRY ___________________________________________________________________
37 #undef AFSConfigKeyName
38 const TCHAR sAFSConfigKeyName[] = TEXT("SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters");
42 * PROFILE SECTIONS ___________________________________________________________
46 #define cREALLOC_SUBMOUNTS 4
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");
52 static TCHAR cszAUTOSUBMOUNT[] = TEXT("Auto");
53 static TCHAR cszLANMANDEVICE[] = TEXT("\\Device\\LanmanRedirector\\");
57 WriteRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs, LPTSTR rhs)
64 REG_OPTION_NON_VOLATILE,
70 DWORD status = RegSetValueEx( hkSub, lhs, 0, REG_SZ, (const BYTE *)rhs, strlen(rhs)+1 );
75 return (status == ERROR_SUCCESS);
79 ReadRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs, LPTSTR rhs, DWORD * size)
86 REG_OPTION_NON_VOLATILE,
93 DWORD status = RegQueryValueEx( hkSub, lhs, 0, &dwType, (LPBYTE)rhs, size );
98 return (status == ERROR_SUCCESS);
102 DeleteRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs)
109 REG_OPTION_NON_VOLATILE,
116 DWORD status = RegDeleteValue( hkSub, lhs );
119 RegCloseKey( hkSub );
121 return (status == ERROR_SUCCESS);
125 * STRINGS ____________________________________________________________________
129 static LPTSTR AllocateStringMemory (size_t cch)
131 LPTSTR psz = (LPTSTR)Allocate (sizeof(TCHAR) * (cch+1));
132 memset (psz, 0x00, sizeof(TCHAR) * (cch+1));
136 static void FreeStringMemory (LPTSTR pszString)
141 static int lstrncmpi (LPCTSTR pszA, LPCTSTR pszB, size_t cch)
145 return (!pszB) - (!pszA); // A,!B:1, !A,B:-1, !A,!B:0
148 for ( ; cch > 0; cch--, pszA = CharNext(pszA), pszB = CharNext(pszB))
150 TCHAR chA = toupper( *pszA );
151 TCHAR chB = toupper( *pszB );
154 return (!chB) - (!chA); // A,!B:1, !A,B:-1, !A,!B:0
157 return (int)(chA) - (int)(chB); // -1:A<B, 0:A==B, 1:A>B
160 return 0; // no differences before told to stop comparing, so A==B
165 * 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)
176 if (cReq <= *pcTarget)
179 if ((cNew = cInc * ((cReq + cInc-1) / cInc)) <= 0)
182 if ((pNew = Allocate (cbElement * cNew)) == NULL)
184 memset (pNew, 0x00, cbElement * cNew);
188 memcpy (pNew, *ppTarget, cbElement * (*pcTarget));
200 * WINDOWS NT STUFF ___________________________________________________________
204 static BOOL IsWindowsNT (void)
206 static BOOL fChecked = FALSE;
207 static BOOL fIsWinNT = FALSE;
213 OSVERSIONINFO Version;
214 memset (&Version, 0x00, sizeof(Version));
215 Version.dwOSVersionInfoSize = sizeof(Version);
217 if (GetVersionEx (&Version))
219 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT)
227 /* Check if the OS is Windows 2000 or higher.
229 BOOL IsWindows2000 (void)
231 static BOOL fChecked = FALSE;
232 static BOOL fIsWin2K = FALSE;
238 OSVERSIONINFO Version;
239 memset (&Version, 0x00, sizeof(Version));
240 Version.dwOSVersionInfoSize = sizeof(Version);
242 if (GetVersionEx (&Version))
244 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
245 Version.dwMajorVersion >= 5)
254 * GENERAL ____________________________________________________________________
258 void GetClientNetbiosName (LPTSTR pszName)
260 static TCHAR szNetbiosName[32] = "";
262 if ( szNetbiosName[0] == 0 ) {
263 lana_GetNetbiosName(szNetbiosName, LANA_NETBIOS_NAME_FULL);
265 _tcscpy(pszName, szNetbiosName);
269 BOOL SubmountToPath (PDRIVEMAPLIST pList, LPTSTR pszPath, LPTSTR pszSubmount, BOOL fMarkInUse)
271 // We can't do this translation unless we're under Windows NT.
276 // \\computer-afs\all always maps to "/afs"
278 if (!lstrcmpi (pszSubmount, TEXT("all")))
280 lstrcpy (pszPath, cm_slash_mount_root);
284 // Otherwise, look up our list of submounts.
286 for (size_t ii = 0; ii < pList->cSubmounts; ++ii)
288 if (!lstrcmpi (pList->aSubmounts[ii].szSubmount, pszSubmount))
291 pList->aSubmounts[ii].fInUse = TRUE;
292 AdjustAfsPath (pszPath, pList->aSubmounts[ii].szMapping, TRUE, TRUE);
301 BOOL IsValidSubmountName (LPTSTR pszSubmount)
305 if (lstrlen (pszSubmount) > 12)
308 for ( ; *pszSubmount; ++pszSubmount)
310 if (!isprint(*pszSubmount))
312 if (*pszSubmount == TEXT(' '))
314 if (*pszSubmount == TEXT('/'))
316 if (*pszSubmount == TEXT('\\'))
318 if (*pszSubmount == TEXT('\t'))
327 * PIOCTL SUPPORT _____________________________________________________________
333 #include "../afsd/fs_utils.h"
335 #define __CM_CONFIG_INTERFACES_ONLY__
336 #include "../afsd/cm_config.h"
338 #define __CM_IOCTL_INTERFACES_ONLY__
339 #include "../afsd/cm_ioctl.h"
343 #define PIOCTL_MAXSIZE 2048
346 BOOL fCanIssuePIOCTL (void)
350 TCHAR szGateway[ 256 ] = TEXT("");
351 GetClientNetbiosName (szGateway);
352 return (szGateway[0]) ? TRUE : FALSE;
355 SERVICE_STATUS Status;
356 memset (&Status, 0x00, sizeof(Status));
357 Status.dwCurrentState = SERVICE_STOPPED;
360 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
363 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
365 QueryServiceStatus (hService, &Status);
366 CloseServiceHandle (hService);
369 CloseServiceHandle (hManager);
372 return (Status.dwCurrentState == SERVICE_RUNNING) ? TRUE : FALSE;
377 * QUERYDRIVEMAPLIST __________________________________________________________
381 void QueryDriveMapList_ReadSubmounts (PDRIVEMAPLIST pList)
387 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
388 "SOFTWARE\\OpenAFS\\Client\\Submounts",
391 REG_OPTION_NON_VOLATILE,
392 KEY_READ|KEY_QUERY_VALUE,
398 RegQueryInfoKey( hkSubmounts,
401 NULL, /* lpReserved */
402 NULL, /* lpcSubKeys */
403 NULL, /* lpcMaxSubKeyLen */
404 NULL, /* lpcMaxClassLen */
405 &dwSubmounts, /* lpcValues */
406 NULL, /* lpcMaxValueNameLen */
407 NULL, /* lpcMaxValueLen */
408 NULL, /* lpcbSecurityDescriptor */
409 NULL /* lpftLastWriteTime */
412 for ( DWORD dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) {
413 TCHAR submountPath[MAX_PATH] = "";
414 DWORD submountPathLen = MAX_PATH;
415 TCHAR submountName[MAX_PATH];
416 DWORD submountNameLen = MAX_PATH;
419 RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL,
420 &dwType, (LPBYTE)submountPath, &submountPathLen);
423 memset (&Submount, 0x00, sizeof(SUBMOUNT));
424 lstrcpy (Submount.szSubmount, submountName);
426 if ( submountPath[0] != TEXT('\0') ) {
427 AdjustAfsPath (Submount.szMapping, submountPath, FALSE, TRUE);
429 for (size_t ii = 0; ii < pList->cSubmounts; ++ii)
431 if (!pList->aSubmounts[ii].szSubmount[0])
434 if (REALLOC (pList->aSubmounts, pList->cSubmounts, 1+ii, cREALLOC_SUBMOUNTS))
436 memcpy (&pList->aSubmounts[ii], &Submount, sizeof(SUBMOUNT));
441 RegCloseKey(hkSubmounts);
446 void QueryDriveMapList_ReadMappings (PDRIVEMAPLIST pList)
449 RegCreateKeyEx( HKEY_CURRENT_USER,
450 "SOFTWARE\\OpenAFS\\Client\\Mappings",
453 REG_OPTION_NON_VOLATILE,
454 KEY_READ|KEY_QUERY_VALUE,
460 RegQueryInfoKey( hkMappings,
463 NULL, /* lpReserved */
464 NULL, /* lpcSubKeys */
465 NULL, /* lpcMaxSubKeyLen */
466 NULL, /* lpcMaxClassLen */
467 &dwMappings, /* lpcValues */
468 NULL, /* lpcMaxValueNameLen */
469 NULL, /* lpcMaxValueLen */
470 NULL, /* lpcbSecurityDescriptor */
471 NULL /* lpftLastWriteTime */
474 for ( DWORD dwIndex = 0; dwIndex < dwMappings; dwIndex ++ ) {
475 TCHAR mapping[MAX_PATH] = "";
476 DWORD mappingLen = MAX_PATH;
477 TCHAR drive[MAX_PATH];
478 DWORD driveLen = MAX_PATH;
481 RegEnumValue( hkMappings, dwIndex, drive, &driveLen, NULL,
482 &dwType, (LPBYTE)mapping, &mappingLen);
485 memset (&DriveMap, 0x00, sizeof(DRIVEMAP));
486 DriveMap.chDrive = toupper(*drive);
487 DriveMap.fPersistent = TRUE;
488 if ((DriveMap.chDrive < chDRIVE_A) || (DriveMap.chDrive > chDRIVE_Z))
491 if (mapping[0] != TEXT('\0'))
493 AdjustAfsPath (DriveMap.szMapping, mapping, TRUE, TRUE);
494 if (DriveMap.szMapping[ lstrlen(DriveMap.szMapping)-1 ] == TEXT('*'))
496 DriveMap.fPersistent = FALSE;
497 DriveMap.szMapping[ lstrlen(DriveMap.szMapping)-1 ] = TEXT('\0');
499 size_t iDrive = DriveMap.chDrive - chDRIVE_A;
500 memcpy (&pList->aDriveMap[ iDrive ], &DriveMap, sizeof(DRIVEMAP));
504 RegCloseKey(hkMappings);
507 BOOL ForceMapActive (TCHAR chDrive)
512 szDrive[0] = chDrive;
515 DWORD len = sizeof(szActive);
516 ReadRegistryString( HKEY_CURRENT_USER, cszSECTION_ACTIVE, szDrive, szActive, &len);
518 if ( !lstrcmp(szActive,"1") || !lstrcmpi(szActive,"true") || !lstrcmpi(szActive,"on") || !lstrcmpi(szActive,"yes") )
524 void WriteActiveMap (TCHAR chDrive, BOOL on)
528 szDrive[0] = chDrive;
531 WriteRegistryString(HKEY_CURRENT_USER, cszSECTION_ACTIVE, szDrive, on ? "1" : "0");
534 void QueryDriveMapList_WriteMappings (PDRIVEMAPLIST pList)
536 WriteDriveMappings (pList);
540 void WriteDriveMappings (PDRIVEMAPLIST pList)
543 RegCreateKeyEx( HKEY_CURRENT_USER,
544 "SOFTWARE\\OpenAFS\\Client\\Mappings",
547 REG_OPTION_NON_VOLATILE,
548 KEY_READ|KEY_QUERY_VALUE|KEY_WRITE,
554 RegQueryInfoKey( hkMappings,
557 NULL, /* lpReserved */
558 NULL, /* lpcSubKeys */
559 NULL, /* lpcMaxSubKeyLen */
560 NULL, /* lpcMaxClassLen */
561 &dwMappings, /* lpcValues */
562 NULL, /* lpcMaxValueNameLen */
563 NULL, /* lpcMaxValueLen */
564 NULL, /* lpcbSecurityDescriptor */
565 NULL /* lpftLastWriteTime */
568 if ( dwMappings > 0 ) {
569 for ( long dwIndex = dwMappings - 1; dwIndex >= 0; dwIndex-- ) {
570 TCHAR drive[MAX_PATH];
571 DWORD driveLen = MAX_PATH;
573 RegEnumValue( hkMappings, dwIndex, drive, &driveLen, NULL, NULL, NULL, NULL);
574 RegDeleteValue( hkMappings, drive );
578 for (size_t iDrive = 0; iDrive < 26; ++iDrive)
580 if (pList->aDriveMap[iDrive].szMapping[0] != TEXT('\0'))
582 TCHAR szLHS[] = TEXT("*");
583 szLHS[0] = pList->aDriveMap[iDrive].chDrive;
585 TCHAR szRHS[MAX_PATH];
586 AdjustAfsPath (szRHS, pList->aDriveMap[iDrive].szMapping, TRUE, TRUE);
587 if (!pList->aDriveMap[iDrive].fPersistent)
588 lstrcat (szRHS, TEXT("*"));
590 RegSetValueEx( hkMappings, szLHS, 0, REG_SZ, (const BYTE *)szRHS, lstrlen(szRHS) + 1);
593 RegCloseKey( hkMappings );
596 BOOL DriveIsGlobalAfsDrive(TCHAR chDrive)
598 TCHAR szKeyName[128];
599 TCHAR szValueName[128];
603 _stprintf(szKeyName, TEXT("%s\\GlobalAutoMapper"), sAFSConfigKeyName);
605 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
608 _stprintf(szValueName, TEXT("%c:"), chDrive);
610 DWORD dwSize = sizeof(szValue);
611 BOOL bIsGlobal = (RegQueryValueEx (hKey, szValueName, NULL, NULL, (PBYTE)szValue, &dwSize) == ERROR_SUCCESS);
619 void QueryDriveMapList_FindNetworkDrives (PDRIVEMAPLIST pList, BOOL *pfFoundNew)
621 for (TCHAR chDrive = chDRIVE_A; chDrive <= chDRIVE_Z; ++chDrive)
623 TCHAR szSubmount[ MAX_PATH ];
624 if (!GetDriveSubmount (chDrive, szSubmount))
627 // We've got a mapping! Drive {chDrive} is mapped to submount
628 // {szSubmount}. See if that submount makes sense.
632 size_t iDrive = chDrive - chDRIVE_A;
633 if (pList->aDriveMap[ iDrive ].szMapping[0] != TEXT('\0'))
635 pList->aDriveMap[ iDrive ].fActive = TRUE;
636 lstrcpy (pList->aDriveMap[ iDrive ].szSubmount, szSubmount);
640 else // (IsWindowsNT())
642 TCHAR szAfsPath[ MAX_PATH ];
643 if (!SubmountToPath (pList, szAfsPath, szSubmount, TRUE))
646 // Okay, we know that drive {chDrive} is mapped to afs path {szAfsPath}.
647 // If this drive is a global afs drive, then reject it. Otherwise, look
648 // at pList->aDriveMap, to see if this drive mapping is already in our
649 // list. If not, add it and set pfFoundNew.
651 if (DriveIsGlobalAfsDrive(chDrive))
654 size_t iDrive = chDrive - chDRIVE_A;
655 if (lstrcmpi (pList->aDriveMap[ iDrive ].szMapping, szAfsPath))
658 pList->aDriveMap[ iDrive ].fPersistent = TRUE;
660 pList->aDriveMap[ iDrive ].fActive = TRUE;
661 pList->aDriveMap[ iDrive ].chDrive = chDrive;
662 lstrcpy (pList->aDriveMap[ iDrive ].szSubmount, szSubmount);
663 AdjustAfsPath (pList->aDriveMap[ iDrive ].szMapping, szAfsPath, TRUE, TRUE);
669 void QueryDriveMapList (PDRIVEMAPLIST pList)
671 // Initialize the data structure
673 memset (pList, 0x00, sizeof(DRIVEMAPLIST));
674 for (size_t ii = 0; ii < 26; ++ii)
675 pList->aDriveMap[ii].chDrive = chDRIVE_A + ii;
677 // Read the current lists of submounts and drive letter mappings
679 QueryDriveMapList_ReadSubmounts (pList);
680 QueryDriveMapList_ReadMappings (pList);
682 // Look through the current list of network drives, and see if
683 // any are currently mapped to AFS. If we find any which are mapped
684 // into AFS unexpectedly, we'll have to rewrite the mappings list.
686 BOOL fFoundNew = FALSE;
687 QueryDriveMapList_FindNetworkDrives (pList, &fFoundNew);
691 QueryDriveMapList_WriteMappings (pList);
696 void FreeDriveMapList (PDRIVEMAPLIST pList)
698 if (pList->aSubmounts)
699 Free (pList->aSubmounts);
700 memset (pList, 0x00, sizeof(DRIVEMAPLIST));
704 BOOL PathToSubmount (LPTSTR pszSubmount, LPTSTR pszMapping, LPTSTR pszSubmountReq, ULONG *pStatus)
706 if (pszSubmountReq && !IsValidSubmountName (pszSubmountReq))
707 pszSubmountReq = NULL;
709 TCHAR szAfsPath[ MAX_PATH ];
710 AdjustAfsPath (szAfsPath, pszMapping, TRUE, TRUE);
712 // Try to ask AFSD for a new submount name.
714 if (!fCanIssuePIOCTL())
717 BYTE InData[ PIOCTL_MAXSIZE ];
718 memset (InData, 0x00, sizeof(InData));
720 LPTSTR pszInData = (LPTSTR)InData;
721 lstrcpy (pszInData, pszMapping);
722 pszInData += 1+lstrlen(pszInData);
724 lstrcpy (pszInData, pszSubmountReq);
726 BYTE OutData[ PIOCTL_MAXSIZE ];
727 memset (OutData, 0x00, sizeof(OutData));
729 struct ViceIoctl IOInfo;
730 IOInfo.in = (char *)InData;
731 IOInfo.in_size = PIOCTL_MAXSIZE;
732 IOInfo.out = (char *)OutData;
733 IOInfo.out_size = PIOCTL_MAXSIZE;
735 ULONG status = pioctl (0, VIOC_MAKESUBMOUNT, &IOInfo, 1);
742 lstrcpy (pszSubmount, (LPCTSTR)OutData);
743 return (pszSubmount[0] != TEXT('\0')) ? TRUE : FALSE;
747 BOOL ActivateDriveMap (TCHAR chDrive, LPTSTR pszMapping, LPTSTR pszSubmountReq, BOOL fPersistent, DWORD *pdwStatus)
749 // We can only map drives to places in AFS using this function.
751 if ( (lstrncmpi (pszMapping, cm_slash_mount_root, lstrlen(cm_slash_mount_root))) &&
752 (lstrncmpi (pszMapping, cm_back_slash_mount_root, lstrlen(cm_back_slash_mount_root))) )
755 *pdwStatus = ERROR_BAD_NETPATH;
759 // First we have to translate {pszMapping} into a submount, and if there is
760 // no current submount associated with this path, we'll have to make one.
763 TCHAR szSubmount[ MAX_PATH ];
764 if (!PathToSubmount (szSubmount, pszMapping, pszSubmountReq, &status))
771 // We now have a submount name and drive letter--map the network drive.
772 DWORD rc=MountDOSDrive(chDrive,szSubmount,fPersistent,NULL);
782 BOOL InactivateDriveMap (TCHAR chDrive, DWORD *pdwStatus)
784 DWORD rc = DisMountDOSDrive(chDrive, FALSE);
794 void AddSubMount (LPTSTR pszSubmount, LPTSTR pszMapping)
796 TCHAR szRHS[ MAX_PATH ];
797 AdjustAfsPath (szRHS, pszMapping, FALSE, TRUE);
799 lstrcpy (szRHS, TEXT("/"));
801 WriteRegistryString(HKEY_LOCAL_MACHINE, cszSECTION_SUBMOUNTS, pszSubmount, szRHS);
805 void RemoveSubMount (LPTSTR pszSubmount)
807 DeleteRegistryString(HKEY_LOCAL_MACHINE, cszSECTION_SUBMOUNTS, pszSubmount);
811 void AdjustAfsPath (LPTSTR pszTarget, LPCTSTR pszSource, BOOL fWantAFS, BOOL fWantForwardSlashes)
814 lstrcpy (pszTarget, (fWantAFS) ? cm_slash_mount_root : TEXT(""));
815 else if ((*pszSource != TEXT('/')) && (*pszSource != TEXT('\\')))
816 wsprintf (pszTarget, TEXT("%s/%s"),cm_slash_mount_root, pszSource);
817 // We don't want to strip afs off the start if it is part of something for example afscell.company.com
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 wsprintf (pszTarget, TEXT("%s%s"),cm_slash_mount_root, pszSource);
822 else if (!fWantAFS && (!lstrncmpi (&pszSource[1], cm_mount_root, strlen(cm_mount_root)) && ((pszSource[strlen(cm_slash_mount_root)] == TEXT('/')) ||
823 (pszSource[strlen(cm_slash_mount_root)] == TEXT('\\')) ||
824 (lstrlen(pszSource) == strlen(cm_slash_mount_root)))))
825 lstrcpy (pszTarget, &pszSource[strlen(cm_slash_mount_root)]);
827 lstrcpy (pszTarget, pszSource);
829 for (LPTSTR pch = pszTarget; *pch; ++pch)
831 if (fWantForwardSlashes)
833 *pch = (*pch == TEXT('\\')) ? TEXT('/') : (*pch);
835 else // (!fWantForwardSlashes)
837 *pch = (*pch == TEXT('/')) ? TEXT('\\') : (*pch);
841 if (lstrlen(pszTarget) &&
842 ((pszTarget[lstrlen(pszTarget)-1] == TEXT('/')) ||
843 (pszTarget[lstrlen(pszTarget)-1] == TEXT('\\'))))
845 pszTarget[lstrlen(pszTarget)-1] = TEXT('\0');
849 BOOL GetDriveSubmount (TCHAR chDrive, LPTSTR pszSubmountNow)
851 BOOL isWinNT = IsWindowsNT();
853 TCHAR szDrive[] = TEXT("*:");
854 szDrive[0] = chDrive;
856 TCHAR szMapping[ _MAX_PATH ] = TEXT("");
858 if (isWinNT && !QueryDosDevice (szDrive, szMapping, MAX_PATH))
861 LPTSTR pszSubmount = szMapping;
863 TCHAR szNetBiosName[32];
864 memset(szNetBiosName, '\0', sizeof(szNetBiosName));
865 GetClientNetbiosName(szNetBiosName);
866 _tcscat(szNetBiosName, TEXT("\\"));
870 // Now if this is an AFS network drive mapping, {szMapping} will be:
872 // \Device\LanmanRedirector\<Drive>:\<netbiosname>\submount
874 // on Windows NT. On Windows 2000, it will be:
876 // \Device\LanmanRedirector\;<Drive>:0\<netbiosname>\submount
878 // (This is presumably to support multiple drive mappings with
881 // on Windows XP and 2003, it will be :
882 // \Device\LanmanRedirector\;<Drive>:<AuthID>\<netbiosname>\submount
884 // where : <Drive> : DOS drive letter
885 // <AuthID>: Authentication ID, 16 char hex.
886 // <netbiosname>: Netbios name of server
888 if (_tcsnicmp(szMapping, cszLANMANDEVICE, _tcslen(cszLANMANDEVICE)))
890 pszSubmount = &szMapping[ _tcslen(cszLANMANDEVICE) ];
894 if (*(pszSubmount) != TEXT(';'))
899 if (toupper(*(++pszSubmount)) != chDrive)
902 if (*(++pszSubmount) != TEXT(':'))
906 // No longer a safe assumption on XP
908 if (*(++pszSubmount) != TEXT('0'))
913 while (*(++pszSubmount) != TEXT('\\'))
919 // note that szNetBiosName has a '\\' tagged in the end earlier
920 for (++pszSubmount; *pszSubmount && (*pszSubmount != TEXT('\\')); ++pszSubmount)
921 if (!_tcsncicmp(pszSubmount, szNetBiosName, _tcslen(szNetBiosName)))
923 if ((!*pszSubmount) || (*pszSubmount == TEXT('\\')))
926 pszSubmount += _tcslen(szNetBiosName);
928 else // (!IsWindowsNT())
930 DWORD dwSize = MAX_PATH;
931 if (WNetGetConnection (szDrive, szMapping, &dwSize) != NO_ERROR)
933 if (*(pszSubmount++) != TEXT('\\'))
935 if (*(pszSubmount++) != TEXT('\\'))
937 for ( ; *pszSubmount && (*pszSubmount != TEXT('\\')); ++pszSubmount)
938 if (!lstrncmpi (pszSubmount, szNetBiosName, lstrlen(szNetBiosName)))
940 if ((!*pszSubmount) || (*pszSubmount == TEXT('\\')))
942 pszSubmount += lstrlen(szNetBiosName);
945 if (!pszSubmount || !*pszSubmount)
948 lstrcpy (pszSubmountNow, pszSubmount);
952 /* Generate Random User name random acording to time*/
954 TCHAR pUserName[MAXRANDOMNAMELEN]=TEXT("");
955 BOOL fUserName=FALSE;
956 #define AFSLogonOptionName TEXT("System\\CurrentControlSet\\Services\\TransarcAFSDaemon\\NetworkProvider")
958 void SetBitLogonOption(BOOL set,DWORD value)
961 RWLogonOption(FALSE,((set)?value | RWLogonOption(TRUE,0):RWLogonOption(TRUE,0) & ~value) );
964 DWORD RWLogonOption(BOOL read,DWORD value)
966 // if read is true then if value==0 return registry value
967 // if read and value!=0 then use value to test registry, return TRUE if value bits match value read
970 DWORD LSPtype, LSPsize;
975 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSLogonOptionName, 0, KEY_QUERY_VALUE, &hk)==ERROR_SUCCESS)
977 LSPsize=sizeof(rval);
978 RegQueryValueEx(hk, "LogonOptions", NULL,
979 &LSPtype, (LPBYTE)&rval, &LSPsize);
982 return (value==0)?rval:((rval & value)==value);
985 if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, AFSLogonOptionName, 0, NULL, 0, KEY_SET_VALUE, NULL, &hk, &dwDisp) == ERROR_SUCCESS)
987 RegSetValueEx(hk,TEXT("LogonOptions"),NULL,REG_DWORD,(LPBYTE)&value,sizeof(value));
994 void MapShareName(char *pszCmdLineA)
999 while (*pszCmdLineA && (*pszCmdLineA != ' '))
1001 *p++=*pszCmdLineA++;
1005 void GenRandomName(TCHAR *pname,int len)
1008 { //user name was passed through command line, use once
1012 srand( (unsigned)time( NULL ) );
1013 for (int i=0;i<len;i++)
1014 pname[i]='a'+(rand() % 26);
1020 Make a connection using users name
1021 if fUserName then force a connection
1024 BOOL TestAndDoMapShare(DWORD dwState)
1026 if ((dwState!=SERVICE_RUNNING) || (dwOldState!=SERVICE_START_PENDING))
1031 dwOldState=SERVICE_RUNNING;
1032 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1033 return (DoMapShare() && GlobalMountDrive());
1034 return GlobalMountDrive();
1037 BOOL IsServiceActive()
1040 SERVICE_STATUS Status;
1041 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
1044 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
1046 QueryServiceStatus (hService, &Status);
1047 CloseServiceHandle (hService);
1050 CloseServiceHandle (hManager);
1053 return (Status.dwCurrentState == SERVICE_RUNNING) ? TRUE : FALSE;
1056 void TestAndDoUnMapShare()
1058 if (!RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1060 DoUnMapShare(FALSE);
1063 void DoUnMapShare(BOOL drivemap) //disconnect drivemap
1065 TCHAR szMachine[MAX_PATH],szPath[MAX_PATH];
1068 LPNETRESOURCE lpnrLocal,lpnr=NULL;
1070 DWORD cbBuffer=16384;
1074 memset(szMachine, '\0', sizeof(szMachine));
1075 GetClientNetbiosName(szMachine);
1077 // Initialize the data structure
1078 if ((res=WNetOpenEnum(RESOURCE_CONNECTED,RESOURCETYPE_DISK,RESOURCEUSAGE_CONNECTABLE,lpnr,&hEnum))!=NO_ERROR)
1080 sprintf(szPath,"\\\\%s\\",szMachine);
1082 lpnrLocal=(LPNETRESOURCE) GlobalAlloc(GPTR,cbBuffer);
1084 memset(lpnrLocal,0,cbBuffer);
1085 if ((res = WNetEnumResource(hEnum,&cEntries,lpnrLocal,&cbBuffer))==NO_ERROR)
1087 for (DWORD i=0;i<cEntries;i++)
1089 if (strstr(_strlwr(lpnrLocal[i].lpRemoteName),szPath))
1091 if ((lpnrLocal[i].lpLocalName) && (strlen(lpnrLocal[i].lpLocalName)>0))
1094 DisMountDOSDrive(*lpnrLocal[i].lpLocalName);
1095 DEBUG_EVENT1("AFS DriveUnMap","UnMap-Local=%x",res);
1098 DisMountDOSDriveFull(lpnrLocal[i].lpRemoteName);
1099 DEBUG_EVENT1("AFS DriveUnMap","UnMap-Remote=%x",res);
1104 } while (res!=ERROR_NO_MORE_ITEMS);
1105 GlobalFree((HGLOBAL)lpnrLocal);
1106 WNetCloseEnum(hEnum);
1109 BOOL DoMapShareChange()
1112 TCHAR szMachine[ MAX_PATH],szPath[MAX_PATH];
1115 LPNETRESOURCE lpnrLocal,lpnr=NULL;
1118 DWORD cbBuffer=16384;
1120 memset(szMachine, '\0', sizeof(szMachine));
1121 GetClientNetbiosName(szMachine);
1123 // Initialize the data structure
1124 if (!IsServiceActive())
1126 memset (&List, 0x00, sizeof(DRIVEMAPLIST));
1127 for (size_t ii = 0; ii < 26; ++ii)
1128 List.aDriveMap[ii].chDrive = chDRIVE_A + ii;
1129 QueryDriveMapList_ReadSubmounts (&List);
1130 if ((res=WNetOpenEnum(RESOURCE_CONNECTED,RESOURCETYPE_DISK,RESOURCEUSAGE_CONNECTABLE,lpnr,&hEnum))!=NO_ERROR)
1132 lpnrLocal=(LPNETRESOURCE) GlobalAlloc(GPTR,cbBuffer);
1133 sprintf(szPath,"\\\\%s\\",szMachine);
1136 memset(lpnrLocal,0,cbBuffer);
1137 if ((res = WNetEnumResource(hEnum,&cEntries,lpnrLocal,&cbBuffer))==NO_ERROR)
1139 for (DWORD i=0;i<cEntries;i++)
1141 if (strstr(_strlwr(lpnrLocal[i].lpRemoteName),szPath)==NULL)
1142 continue; //only look at real afs mappings
1143 CHAR * pSubmount=strrchr(lpnrLocal[i].lpRemoteName,'\\')+1;
1144 if (lstrcmpi(pSubmount,"all")==0)
1145 continue; // do not remove 'all'
1146 for (DWORD j=0;j<List.cSubmounts;j++)
1149 (List.aSubmounts[j].szSubmount[0]) &&
1150 (lstrcmpi(List.aSubmounts[j].szSubmount,pSubmount)==0)
1153 List.aSubmounts[j].fInUse=TRUE;
1157 // wasn't on list so lets remove
1158 DisMountDOSDrive(pSubmount);
1162 } while (res!=ERROR_NO_MORE_ITEMS);
1163 GlobalFree((HGLOBAL)lpnrLocal);
1164 WNetCloseEnum(hEnum);
1165 sprintf(szPath,"\\\\%s\\all",szMachine);
1167 // Lets connect all submounts that weren't connectd
1168 DWORD cbUser=MAXRANDOMNAMELEN-1;
1169 CHAR szUser[MAXRANDOMNAMELEN];
1170 CHAR * pUser = NULL;
1171 if (WNetGetUser(szPath,(LPSTR)szUser,&cbUser)!=NO_ERROR) {
1172 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY)) {
1173 if (!pUserName[0]) {
1174 GenRandomName(szUser,MAXRANDOMNAMELEN-1);
1181 if ((pUser=strchr(szUser,'\\'))!=NULL)
1185 for (DWORD j=0;j<List.cSubmounts;j++)
1187 if (List.aSubmounts[j].fInUse)
1189 DWORD res=MountDOSDrive(0,List.aSubmounts[j].szSubmount,FALSE,pUser);
1198 BOOL bMappedAll=FALSE;
1200 // Initialize the data structure
1201 DEBUG_EVENT0("AFS DoMapShare");
1202 QueryDriveMapList (&List);
1204 // All connections have been removed
1205 // Lets restore them after making the connection from the random name
1207 TCHAR szMachine[ MAX_PATH],szPath[MAX_PATH];
1208 memset(szMachine, '\0', sizeof(szMachine));
1209 GetClientNetbiosName(szMachine);
1210 sprintf(szPath,"\\\\%s\\all",szMachine);
1212 // Lets connect all submounts that weren't connectd
1213 DWORD cbUser=MAXRANDOMNAMELEN-1;
1214 CHAR szUser[MAXRANDOMNAMELEN];
1215 CHAR * pUser = NULL;
1216 if (WNetGetUser(szPath,(LPSTR)szUser,&cbUser)!=NO_ERROR) {
1217 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY)) {
1218 if (!pUserName[0]) {
1219 GenRandomName(szUser,MAXRANDOMNAMELEN-1);
1226 if ((pUser=strchr(szUser,'\\'))!=NULL)
1230 for (DWORD i=0;i<List.cSubmounts;i++)
1232 if (List.aSubmounts[i].szSubmount[0])
1234 DWORD res=MountDOSDrive(0,List.aSubmounts[i].szSubmount,FALSE,pUser);
1235 if (lstrcmpi("all",List.aSubmounts[i].szSubmount)==0)
1239 if (!bMappedAll) //make sure all is mapped also
1241 DWORD res=MountDOSDrive(0,"all",FALSE,pUser);
1242 if (res==ERROR_SESSION_CREDENTIAL_CONFLICT)
1244 DisMountDOSDrive("all");
1245 MountDOSDrive(0,"all",FALSE,pUser);
1248 for (TCHAR chDrive = chDRIVE_A; chDrive <= chDRIVE_Z; ++chDrive)
1250 if (List.aDriveMap[chDrive-chDRIVE_A].fActive ||
1251 ForceMapActive(chDrive))
1253 TCHAR szSubmount[ MAX_PATH ];
1254 if (List.aDriveMap[chDrive-chDRIVE_A].szSubmount[0])
1255 lstrcpy(szSubmount,List.aDriveMap[chDrive-chDRIVE_A].szSubmount);
1256 else if (!PathToSubmount (szSubmount, List.aDriveMap[chDrive-chDRIVE_A].szMapping, NULL, NULL))
1259 BOOL fPersistent = List.aDriveMap[chDrive-chDRIVE_A].fPersistent;
1260 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1261 fPersistent = FALSE;
1262 DWORD res=MountDOSDrive(chDrive
1264 ,fPersistent,pUser);
1270 BOOL GlobalMountDrive()
1272 char szDriveToMapTo[5];
1274 char szKeyName[256];
1278 DWORD dwSubMountSize;
1279 char unsigned szSubMount[256];
1280 char cm_HostName[200];
1281 DWORD dwType=sizeof(cm_HostName);
1282 if (!IsServiceActive())
1284 if (!GetComputerName(cm_HostName, &dwType))
1286 sprintf(szKeyName, "%s\\GlobalAutoMapper", sAFSConfigKeyName);
1288 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE,
1290 if (dwResult != ERROR_SUCCESS)
1294 dwDriveSize = sizeof(szDriveToMapTo);
1295 dwSubMountSize = sizeof(szSubMount);
1296 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize,
1297 0, &dwType, szSubMount, &dwSubMountSize);
1298 if (dwResult != ERROR_MORE_DATA) {
1299 if (dwResult != ERROR_SUCCESS) {
1300 if (dwResult != ERROR_NO_MORE_ITEMS)
1302 DEBUG_EVENT1("AFS DriveMap","Failed to read GlobalAutoMapper values: %d",dwResult);
1307 dwResult=MountDOSDrive(*szDriveToMapTo,(const char *)szSubMount,FALSE,NULL);
1313 DWORD MountDOSDrive(char chDrive,const char *szSubmount,BOOL bPersistent,const char * pUsername)
1315 TCHAR szPath[MAX_PATH];
1316 TCHAR szClient[MAX_PATH];
1317 TCHAR szDrive[3] = TEXT("?:");
1318 sprintf(szDrive,"%c:",chDrive);
1319 GetClientNetbiosName (szClient);
1320 sprintf(szPath,"\\\\%s\\%s",szClient,szSubmount);
1322 memset (&nr, 0x00, sizeof(NETRESOURCE));
1323 nr.dwType=RESOURCETYPE_DISK;
1324 nr.lpLocalName=szDrive;
1325 nr.lpRemoteName=szPath;
1326 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
1327 DWORD res=WNetAddConnection2(&nr,NULL,pUsername,(bPersistent)?CONNECT_UPDATE_PROFILE:0);
1328 DEBUG_EVENT5("AFS DriveMap","Mount %s Local[%s] Remote[%s] User[%s]=%x",
1329 (bPersistent)?"Persistant" : "NonPresistant",
1330 szDrive,szPath,pUsername?pUsername:"NULL",res);
1334 DWORD DisMountDOSDriveFull(const char *szPath,BOOL bForce)
1336 DWORD res=WNetCancelConnection(szPath,bForce);
1337 DEBUG_EVENT3("AFS DriveMap","%sDismount Remote[%s]=%x",
1338 bForce ? "Forced " : "",szPath,res);
1339 return (res==ERROR_NOT_CONNECTED)?NO_ERROR:res;
1342 DWORD DisMountDOSDrive(const char *pSubmount,BOOL bForce)
1344 TCHAR szPath[MAX_PATH];
1345 TCHAR szClient[MAX_PATH];
1346 GetClientNetbiosName (szClient);
1347 sprintf(szPath,"\\\\%s\\%s",szClient,pSubmount);
1348 return DisMountDOSDriveFull(szPath,bForce);
1352 DWORD DisMountDOSDrive(const char chDrive,BOOL bForce)
1354 TCHAR szPath[MAX_PATH];
1355 sprintf(szPath,"%c:",chDrive);
1356 return DisMountDOSDriveFull(szPath,bForce);