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>
31 extern void Config_GetLanAdapter (ULONG *pnLanAdapter);
34 * REGISTRY ___________________________________________________________________
38 #undef AFSConfigKeyName
39 const TCHAR sAFSConfigKeyName[] = TEXT("SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters");
43 * PROFILE SECTIONS ___________________________________________________________
47 #define cREALLOC_SUBMOUNTS 4
49 static TCHAR cszSECTION_SUBMOUNTS[] = TEXT("SOFTWARE\\OpenAFS\\Client\\Submounts");
50 static TCHAR cszSECTION_MAPPINGS[] = TEXT("SOFTWARE\\OpenAFS\\Client\\Mappings");
51 static TCHAR cszSECTION_ACTIVE[] = TEXT("SOFTWARE\\OpenAFS\\Client\\Active Maps");
53 static TCHAR cszAUTOSUBMOUNT[] = TEXT("Auto");
54 static TCHAR cszLANMANDEVICE[] = TEXT("\\Device\\LanmanRedirector\\");
58 WriteRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs, LPTSTR rhs)
65 REG_OPTION_NON_VOLATILE,
71 DWORD status = RegSetValueEx( hkSub, lhs, 0, REG_SZ, (const BYTE *)rhs, strlen(rhs)+1 );
76 return (status == ERROR_SUCCESS);
80 WriteExpandedRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs, LPTSTR rhs)
87 REG_OPTION_NON_VOLATILE,
93 DWORD status = RegSetValueEx( hkSub, lhs, 0, REG_EXPAND_SZ, (const BYTE *)rhs, strlen(rhs)+1 );
98 return (status == ERROR_SUCCESS);
102 ReadRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs, LPTSTR rhs, DWORD * size)
109 REG_OPTION_NON_VOLATILE,
116 DWORD localSize = *size;
118 DWORD status = RegQueryValueEx( hkSub, lhs, 0, &dwType, (LPBYTE)rhs, &localSize);
119 if (status == 0 && dwType == REG_EXPAND_SZ) {
120 TCHAR * buf = (TCHAR *)malloc((*size) * sizeof(TCHAR));
121 memcpy(buf, rhs, (*size) * sizeof(TCHAR));
122 localSize = ExpandEnvironmentStrings(buf, rhs, *size);
124 if ( localSize > *size )
125 status = !ERROR_SUCCESS;
130 RegCloseKey( hkSub );
132 return (status == ERROR_SUCCESS);
136 DeleteRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs)
143 REG_OPTION_NON_VOLATILE,
149 DWORD status = RegDeleteValue( hkSub, lhs );
152 RegCloseKey( hkSub );
154 return (status == ERROR_SUCCESS);
158 * STRINGS ____________________________________________________________________
162 static LPTSTR AllocateStringMemory (size_t cch)
164 LPTSTR psz = (LPTSTR)Allocate (sizeof(TCHAR) * (cch+1));
165 memset (psz, 0x00, sizeof(TCHAR) * (cch+1));
169 static void FreeStringMemory (LPTSTR pszString)
174 static int lstrncmpi (LPCTSTR pszA, LPCTSTR pszB, size_t cch)
178 return (!pszB) - (!pszA); // A,!B:1, !A,B:-1, !A,!B:0
181 for ( ; cch > 0; cch--, pszA = CharNext(pszA), pszB = CharNext(pszB))
183 TCHAR chA = toupper( *pszA );
184 TCHAR chB = toupper( *pszB );
187 return (!chB) - (!chA); // A,!B:1, !A,B:-1, !A,!B:0
190 return (int)(chA) - (int)(chB); // -1:A<B, 0:A==B, 1:A>B
193 return 0; // no differences before told to stop comparing, so A==B
198 * REALLOC ____________________________________________________________________
203 #define REALLOC(_a,_c,_r,_i) DriveMapReallocFunction ((LPVOID*)&_a,sizeof(*_a),&_c,_r,_i)
204 BOOL DriveMapReallocFunction (LPVOID *ppTarget, size_t cbElement, size_t *pcTarget, size_t cReq, size_t cInc)
209 if (cReq <= *pcTarget)
212 if ((cNew = cInc * ((cReq + cInc-1) / cInc)) <= 0)
215 if ((pNew = Allocate (cbElement * cNew)) == NULL)
217 memset (pNew, 0x00, cbElement * cNew);
221 memcpy (pNew, *ppTarget, cbElement * (*pcTarget));
233 * WINDOWS NT STUFF ___________________________________________________________
237 static BOOL IsWindowsNT (void)
239 static BOOL fChecked = FALSE;
240 static BOOL fIsWinNT = FALSE;
246 OSVERSIONINFO Version;
247 memset (&Version, 0x00, sizeof(Version));
248 Version.dwOSVersionInfoSize = sizeof(Version);
250 if (GetVersionEx (&Version))
252 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT)
260 /* Check if the OS is Windows 2000 or higher.
262 BOOL IsWindows2000 (void)
264 static BOOL fChecked = FALSE;
265 static BOOL fIsWin2K = FALSE;
271 OSVERSIONINFO Version;
272 memset (&Version, 0x00, sizeof(Version));
273 Version.dwOSVersionInfoSize = sizeof(Version);
275 if (GetVersionEx (&Version))
277 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
278 Version.dwMajorVersion >= 5)
287 * GENERAL ____________________________________________________________________
291 void GetClientNetbiosName (LPTSTR pszName)
293 static TCHAR szNetbiosName[32] = "";
295 if ( szNetbiosName[0] == 0 ) {
296 lana_GetNetbiosName(szNetbiosName, LANA_NETBIOS_NAME_FULL);
298 _tcscpy(pszName, szNetbiosName);
302 BOOL SubmountToPath (PDRIVEMAPLIST pList, LPTSTR pszPath, LPTSTR pszSubmount, BOOL fMarkInUse)
304 // We can't do this translation unless we're under Windows NT.
309 // \\computer-afs\all always maps to "/afs"
311 if (!lstrcmpi (pszSubmount, TEXT("all")))
313 lstrcpy (pszPath, cm_slash_mount_root);
317 // Otherwise, look up our list of submounts.
319 for (size_t ii = 0; ii < pList->cSubmounts; ++ii)
321 if (!lstrcmpi (pList->aSubmounts[ii].szSubmount, pszSubmount))
324 pList->aSubmounts[ii].fInUse = TRUE;
325 AdjustAfsPath (pszPath, pList->aSubmounts[ii].szMapping, TRUE, TRUE);
334 BOOL IsValidSubmountName (LPTSTR pszSubmount)
338 if (lstrlen (pszSubmount) > 12)
341 for ( ; *pszSubmount; ++pszSubmount)
343 if (!isprint(*pszSubmount))
345 if (*pszSubmount == TEXT(' '))
347 if (*pszSubmount == TEXT('/'))
349 if (*pszSubmount == TEXT('\\'))
351 if (*pszSubmount == TEXT('\t'))
360 * PIOCTL SUPPORT _____________________________________________________________
366 #include "../afsd/fs_utils.h"
368 #define __CM_CONFIG_INTERFACES_ONLY__
369 #include "../afsd/cm_config.h"
371 #define __CM_IOCTL_INTERFACES_ONLY__
372 #include "../afsd/cm_ioctl.h"
376 #define PIOCTL_MAXSIZE 2048
379 BOOL fCanIssuePIOCTL (void)
383 TCHAR szGateway[ 256 ] = TEXT("");
384 GetClientNetbiosName (szGateway);
385 return (szGateway[0]) ? TRUE : FALSE;
388 SERVICE_STATUS Status;
389 memset (&Status, 0x00, sizeof(Status));
390 Status.dwCurrentState = SERVICE_STOPPED;
393 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
396 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
398 QueryServiceStatus (hService, &Status);
399 CloseServiceHandle (hService);
402 CloseServiceHandle (hManager);
405 return (Status.dwCurrentState == SERVICE_RUNNING) ? TRUE : FALSE;
410 * QUERYDRIVEMAPLIST __________________________________________________________
414 void QueryDriveMapList_ReadSubmounts (PDRIVEMAPLIST pList)
420 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
421 cszSECTION_SUBMOUNTS,
424 REG_OPTION_NON_VOLATILE,
425 KEY_READ|KEY_QUERY_VALUE,
431 RegQueryInfoKey( hkSubmounts,
434 NULL, /* lpReserved */
435 NULL, /* lpcSubKeys */
436 NULL, /* lpcMaxSubKeyLen */
437 NULL, /* lpcMaxClassLen */
438 &dwSubmounts, /* lpcValues */
439 NULL, /* lpcMaxValueNameLen */
440 NULL, /* lpcMaxValueLen */
441 NULL, /* lpcbSecurityDescriptor */
442 NULL /* lpftLastWriteTime */
445 for ( DWORD dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) {
446 TCHAR submountPath[MAX_PATH] = "";
447 DWORD submountPathLen = MAX_PATH;
448 TCHAR submountName[MAX_PATH];
449 DWORD submountNameLen = MAX_PATH;
452 RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL,
453 &dwType, (LPBYTE)submountPath, &submountPathLen);
455 if (dwType == REG_EXPAND_SZ) {
457 StringCbCopyA(buf, MAX_PATH, submountPath);
458 submountPathLen = ExpandEnvironmentStrings(buf, submountPath, MAX_PATH);
459 if (submountPathLen > MAX_PATH)
464 memset (&Submount, 0x00, sizeof(SUBMOUNT));
465 lstrcpy (Submount.szSubmount, submountName);
467 if ( submountPath[0] != TEXT('\0') ) {
468 AdjustAfsPath (Submount.szMapping, submountPath, FALSE, TRUE);
470 for (size_t ii = 0; ii < pList->cSubmounts; ++ii)
472 if (!pList->aSubmounts[ii].szSubmount[0])
475 if (REALLOC (pList->aSubmounts, pList->cSubmounts, 1+ii, cREALLOC_SUBMOUNTS))
477 memcpy (&pList->aSubmounts[ii], &Submount, sizeof(SUBMOUNT));
482 RegCloseKey(hkSubmounts);
487 void QueryDriveMapList_ReadMappings (PDRIVEMAPLIST pList)
490 RegCreateKeyEx( HKEY_CURRENT_USER,
494 REG_OPTION_NON_VOLATILE,
495 KEY_READ|KEY_QUERY_VALUE,
501 RegQueryInfoKey( hkMappings,
504 NULL, /* lpReserved */
505 NULL, /* lpcSubKeys */
506 NULL, /* lpcMaxSubKeyLen */
507 NULL, /* lpcMaxClassLen */
508 &dwMappings, /* lpcValues */
509 NULL, /* lpcMaxValueNameLen */
510 NULL, /* lpcMaxValueLen */
511 NULL, /* lpcbSecurityDescriptor */
512 NULL /* lpftLastWriteTime */
515 for ( DWORD dwIndex = 0; dwIndex < dwMappings; dwIndex ++ ) {
516 TCHAR mapping[MAX_PATH] = "";
517 DWORD mappingLen = MAX_PATH;
518 TCHAR drive[MAX_PATH];
519 DWORD driveLen = MAX_PATH;
522 RegEnumValue( hkMappings, dwIndex, drive, &driveLen, NULL,
523 &dwType, (LPBYTE)mapping, &mappingLen);
524 if ( dwType == REG_EXPAND_SZ ) {
526 DWORD dummyLen = ExpandEnvironmentStrings(buf, mapping, MAX_PATH);
527 if (dummyLen > MAX_PATH)
529 _tcsncpy(mapping, buf, MAX_PATH);
533 memset (&DriveMap, 0x00, sizeof(DRIVEMAP));
534 DriveMap.chDrive = toupper(*drive);
535 DriveMap.fPersistent = TRUE;
536 if ((DriveMap.chDrive < chDRIVE_A) || (DriveMap.chDrive > chDRIVE_Z))
539 if (mapping[0] != TEXT('\0'))
541 AdjustAfsPath (DriveMap.szMapping, mapping, TRUE, TRUE);
542 if (DriveMap.szMapping[ lstrlen(DriveMap.szMapping)-1 ] == TEXT('*'))
544 DriveMap.fPersistent = FALSE;
545 DriveMap.szMapping[ lstrlen(DriveMap.szMapping)-1 ] = TEXT('\0');
547 size_t iDrive = DriveMap.chDrive - chDRIVE_A;
548 memcpy (&pList->aDriveMap[ iDrive ], &DriveMap, sizeof(DRIVEMAP));
552 RegCloseKey(hkMappings);
555 BOOL ForceMapActive (TCHAR chDrive)
560 szDrive[0] = chDrive;
563 DWORD len = sizeof(szActive);
564 ReadRegistryString( HKEY_CURRENT_USER, cszSECTION_ACTIVE, szDrive, szActive, &len);
566 if ( !lstrcmp(szActive,"1") || !lstrcmpi(szActive,"true") || !lstrcmpi(szActive,"on") || !lstrcmpi(szActive,"yes") )
572 void WriteActiveMap (TCHAR chDrive, BOOL on)
576 szDrive[0] = chDrive;
579 WriteRegistryString(HKEY_CURRENT_USER, cszSECTION_ACTIVE, szDrive, on ? "1" : "0");
582 void QueryDriveMapList_WriteMappings (PDRIVEMAPLIST pList)
584 WriteDriveMappings (pList);
588 void WriteDriveMappings (PDRIVEMAPLIST pList)
591 RegCreateKeyEx( HKEY_CURRENT_USER,
595 REG_OPTION_NON_VOLATILE,
596 KEY_READ|KEY_QUERY_VALUE|KEY_WRITE,
602 RegQueryInfoKey( hkMappings,
605 NULL, /* lpReserved */
606 NULL, /* lpcSubKeys */
607 NULL, /* lpcMaxSubKeyLen */
608 NULL, /* lpcMaxClassLen */
609 &dwMappings, /* lpcValues */
610 NULL, /* lpcMaxValueNameLen */
611 NULL, /* lpcMaxValueLen */
612 NULL, /* lpcbSecurityDescriptor */
613 NULL /* lpftLastWriteTime */
616 if ( dwMappings > 0 ) {
617 for ( long dwIndex = dwMappings - 1; dwIndex >= 0; dwIndex-- ) {
618 TCHAR drive[MAX_PATH];
619 DWORD driveLen = MAX_PATH;
621 RegEnumValue( hkMappings, dwIndex, drive, &driveLen, NULL, NULL, NULL, NULL);
622 RegDeleteValue( hkMappings, drive );
626 for (size_t iDrive = 0; iDrive < 26; ++iDrive)
628 if (pList->aDriveMap[iDrive].szMapping[0] != TEXT('\0'))
630 TCHAR szLHS[] = TEXT("*");
631 szLHS[0] = pList->aDriveMap[iDrive].chDrive;
633 TCHAR szRHS[MAX_PATH];
634 AdjustAfsPath (szRHS, pList->aDriveMap[iDrive].szMapping, TRUE, TRUE);
635 if (!pList->aDriveMap[iDrive].fPersistent)
636 lstrcat (szRHS, TEXT("*"));
638 RegSetValueEx( hkMappings, szLHS, 0, REG_EXPAND_SZ, (const BYTE *)szRHS, lstrlen(szRHS) + 1);
641 RegCloseKey( hkMappings );
644 BOOL DriveIsGlobalAfsDrive(TCHAR chDrive)
646 TCHAR szKeyName[128];
647 TCHAR szValueName[128];
651 _stprintf(szKeyName, TEXT("%s\\GlobalAutoMapper"), sAFSConfigKeyName);
653 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
656 _stprintf(szValueName, TEXT("%c:"), chDrive);
658 DWORD dwSize = sizeof(szValue);
659 BOOL bIsGlobal = (RegQueryValueEx (hKey, szValueName, NULL, NULL, (PBYTE)szValue, &dwSize) == ERROR_SUCCESS);
667 void QueryDriveMapList_FindNetworkDrives (PDRIVEMAPLIST pList, BOOL *pfFoundNew)
669 for (TCHAR chDrive = chDRIVE_A; chDrive <= chDRIVE_Z; ++chDrive)
671 TCHAR szSubmount[ MAX_PATH ];
672 if (!GetDriveSubmount (chDrive, szSubmount))
675 // We've got a mapping! Drive {chDrive} is mapped to submount
676 // {szSubmount}. See if that submount makes sense.
680 size_t iDrive = chDrive - chDRIVE_A;
681 if (pList->aDriveMap[ iDrive ].szMapping[0] != TEXT('\0'))
683 pList->aDriveMap[ iDrive ].fActive = TRUE;
684 lstrcpy (pList->aDriveMap[ iDrive ].szSubmount, szSubmount);
688 else // (IsWindowsNT())
690 TCHAR szAfsPath[ MAX_PATH ];
691 if (!SubmountToPath (pList, szAfsPath, szSubmount, TRUE))
694 // Okay, we know that drive {chDrive} is mapped to afs path {szAfsPath}.
695 // If this drive is a global afs drive, then reject it. Otherwise, look
696 // at pList->aDriveMap, to see if this drive mapping is already in our
697 // list. If not, add it and set pfFoundNew.
699 if (DriveIsGlobalAfsDrive(chDrive))
702 size_t iDrive = chDrive - chDRIVE_A;
703 if (lstrcmpi (pList->aDriveMap[ iDrive ].szMapping, szAfsPath))
706 pList->aDriveMap[ iDrive ].fPersistent = TRUE;
708 pList->aDriveMap[ iDrive ].fActive = TRUE;
709 pList->aDriveMap[ iDrive ].chDrive = chDrive;
710 lstrcpy (pList->aDriveMap[ iDrive ].szSubmount, szSubmount);
711 AdjustAfsPath (pList->aDriveMap[ iDrive ].szMapping, szAfsPath, TRUE, TRUE);
717 void QueryDriveMapList (PDRIVEMAPLIST pList)
719 // Initialize the data structure
721 memset (pList, 0x00, sizeof(DRIVEMAPLIST));
722 for (size_t ii = 0; ii < 26; ++ii)
723 pList->aDriveMap[ii].chDrive = chDRIVE_A + ii;
725 // Read the current lists of submounts and drive letter mappings
727 QueryDriveMapList_ReadSubmounts (pList);
728 QueryDriveMapList_ReadMappings (pList);
730 // Look through the current list of network drives, and see if
731 // any are currently mapped to AFS. If we find any which are mapped
732 // into AFS unexpectedly, we'll have to rewrite the mappings list.
734 BOOL fFoundNew = FALSE;
735 QueryDriveMapList_FindNetworkDrives (pList, &fFoundNew);
739 QueryDriveMapList_WriteMappings (pList);
744 void FreeDriveMapList (PDRIVEMAPLIST pList)
746 if (pList->aSubmounts)
747 Free (pList->aSubmounts);
748 memset (pList, 0x00, sizeof(DRIVEMAPLIST));
752 BOOL PathToSubmount (LPTSTR pszSubmount, LPTSTR pszMapping, LPTSTR pszSubmountReq, ULONG *pStatus)
754 if (pszSubmountReq && !IsValidSubmountName (pszSubmountReq))
755 pszSubmountReq = NULL;
757 TCHAR szAfsPath[ MAX_PATH ];
758 AdjustAfsPath (szAfsPath, pszMapping, TRUE, TRUE);
760 // Try to ask AFSD for a new submount name.
762 if (!fCanIssuePIOCTL())
765 BYTE InData[ PIOCTL_MAXSIZE ];
766 memset (InData, 0x00, sizeof(InData));
768 LPTSTR pszInData = (LPTSTR)InData;
769 lstrcpy (pszInData, pszMapping);
770 pszInData += 1+lstrlen(pszInData);
772 lstrcpy (pszInData, pszSubmountReq);
774 BYTE OutData[ PIOCTL_MAXSIZE ];
775 memset (OutData, 0x00, sizeof(OutData));
777 struct ViceIoctl IOInfo;
778 IOInfo.in = (char *)InData;
779 IOInfo.in_size = PIOCTL_MAXSIZE;
780 IOInfo.out = (char *)OutData;
781 IOInfo.out_size = PIOCTL_MAXSIZE;
783 ULONG status = pioctl (0, VIOC_MAKESUBMOUNT, &IOInfo, 1);
790 lstrcpy (pszSubmount, (LPCTSTR)OutData);
791 return (pszSubmount[0] != TEXT('\0')) ? TRUE : FALSE;
795 BOOL ActivateDriveMap (TCHAR chDrive, LPTSTR pszMapping, LPTSTR pszSubmountReq, BOOL fPersistent, DWORD *pdwStatus)
797 // We can only map drives to places in AFS using this function.
799 if ( (lstrncmpi (pszMapping, cm_slash_mount_root, lstrlen(cm_slash_mount_root))) &&
800 (lstrncmpi (pszMapping, cm_back_slash_mount_root, lstrlen(cm_back_slash_mount_root))) )
803 *pdwStatus = ERROR_BAD_NETPATH;
807 // First we have to translate {pszMapping} into a submount, and if there is
808 // no current submount associated with this path, we'll have to make one.
811 TCHAR szSubmount[ MAX_PATH ];
812 if (!PathToSubmount (szSubmount, pszMapping, pszSubmountReq, &status))
819 // We now have a submount name and drive letter--map the network drive.
820 DWORD rc=MountDOSDrive(chDrive,szSubmount,fPersistent,NULL);
830 BOOL InactivateDriveMap (TCHAR chDrive, DWORD *pdwStatus)
832 DWORD rc = DisMountDOSDrive(chDrive, FALSE);
842 void AddSubMount (LPTSTR pszSubmount, LPTSTR pszMapping)
844 TCHAR szRHS[ MAX_PATH ];
845 AdjustAfsPath (szRHS, pszMapping, FALSE, TRUE);
847 lstrcpy (szRHS, TEXT("/"));
849 WriteExpandedRegistryString(HKEY_LOCAL_MACHINE, cszSECTION_SUBMOUNTS, pszSubmount, szRHS);
853 void RemoveSubMount (LPTSTR pszSubmount)
855 DeleteRegistryString(HKEY_LOCAL_MACHINE, cszSECTION_SUBMOUNTS, pszSubmount);
859 void AdjustAfsPath (LPTSTR pszTarget, LPCTSTR pszSource, BOOL fWantAFS, BOOL fWantForwardSlashes)
862 lstrcpy (pszTarget, (fWantAFS) ? cm_slash_mount_root : TEXT(""));
863 else if ((*pszSource != TEXT('/')) && (*pszSource != TEXT('\\')))
864 wsprintf (pszTarget, TEXT("%s/%s"),cm_slash_mount_root, pszSource);
865 // We don't want to strip afs off the start if it is part of something for example afscell.company.com
866 else if (fWantAFS && (lstrncmpi (&pszSource[1], cm_mount_root, strlen(cm_mount_root))) || !((pszSource[strlen(cm_slash_mount_root)] == TEXT('/')) ||
867 (pszSource[strlen(cm_slash_mount_root)] == TEXT('\\')) ||
868 (lstrlen(pszSource) == strlen(cm_slash_mount_root))))
869 wsprintf (pszTarget, TEXT("%s%s"),cm_slash_mount_root, pszSource);
870 else if (!fWantAFS && (!lstrncmpi (&pszSource[1], cm_mount_root, strlen(cm_mount_root)) && ((pszSource[strlen(cm_slash_mount_root)] == TEXT('/')) ||
871 (pszSource[strlen(cm_slash_mount_root)] == TEXT('\\')) ||
872 (lstrlen(pszSource) == strlen(cm_slash_mount_root)))))
873 lstrcpy (pszTarget, &pszSource[strlen(cm_slash_mount_root)]);
875 lstrcpy (pszTarget, pszSource);
877 for (LPTSTR pch = pszTarget; *pch; ++pch)
879 if (fWantForwardSlashes)
881 *pch = (*pch == TEXT('\\')) ? TEXT('/') : (*pch);
883 else // (!fWantForwardSlashes)
885 *pch = (*pch == TEXT('/')) ? TEXT('\\') : (*pch);
889 if (lstrlen(pszTarget) &&
890 ((pszTarget[lstrlen(pszTarget)-1] == TEXT('/')) ||
891 (pszTarget[lstrlen(pszTarget)-1] == TEXT('\\'))))
893 pszTarget[lstrlen(pszTarget)-1] = TEXT('\0');
897 BOOL GetDriveSubmount (TCHAR chDrive, LPTSTR pszSubmountNow)
899 BOOL isWinNT = IsWindowsNT();
901 TCHAR szDrive[] = TEXT("*:");
902 szDrive[0] = chDrive;
904 TCHAR szMapping[ _MAX_PATH ] = TEXT("");
906 if (isWinNT && !QueryDosDevice (szDrive, szMapping, MAX_PATH))
909 LPTSTR pszSubmount = szMapping;
911 TCHAR szNetBiosName[32];
912 memset(szNetBiosName, '\0', sizeof(szNetBiosName));
913 GetClientNetbiosName(szNetBiosName);
914 _tcscat(szNetBiosName, TEXT("\\"));
918 // Now if this is an AFS network drive mapping, {szMapping} will be:
920 // \Device\LanmanRedirector\<Drive>:\<netbiosname>\submount
922 // on Windows NT. On Windows 2000, it will be:
924 // \Device\LanmanRedirector\;<Drive>:0\<netbiosname>\submount
926 // (This is presumably to support multiple drive mappings with
929 // on Windows XP and 2003, it will be :
930 // \Device\LanmanRedirector\;<Drive>:<AuthID>\<netbiosname>\submount
932 // where : <Drive> : DOS drive letter
933 // <AuthID>: Authentication ID, 16 char hex.
934 // <netbiosname>: Netbios name of server
936 if (_tcsnicmp(szMapping, cszLANMANDEVICE, _tcslen(cszLANMANDEVICE)))
938 pszSubmount = &szMapping[ _tcslen(cszLANMANDEVICE) ];
942 if (*(pszSubmount) != TEXT(';'))
947 if (toupper(*(++pszSubmount)) != chDrive)
950 if (*(++pszSubmount) != TEXT(':'))
954 // No longer a safe assumption on XP
956 if (*(++pszSubmount) != TEXT('0'))
961 while (*(++pszSubmount) != TEXT('\\'))
967 // note that szNetBiosName has a '\\' tagged in the end earlier
968 for (++pszSubmount; *pszSubmount && (*pszSubmount != TEXT('\\')); ++pszSubmount)
969 if (!_tcsncicmp(pszSubmount, szNetBiosName, _tcslen(szNetBiosName)))
971 if ((!*pszSubmount) || (*pszSubmount == TEXT('\\')))
974 pszSubmount += _tcslen(szNetBiosName);
976 else // (!IsWindowsNT())
978 DWORD dwSize = MAX_PATH;
979 if (WNetGetConnection (szDrive, szMapping, &dwSize) != NO_ERROR)
981 if (*(pszSubmount++) != TEXT('\\'))
983 if (*(pszSubmount++) != TEXT('\\'))
985 for ( ; *pszSubmount && (*pszSubmount != TEXT('\\')); ++pszSubmount)
986 if (!lstrncmpi (pszSubmount, szNetBiosName, lstrlen(szNetBiosName)))
988 if ((!*pszSubmount) || (*pszSubmount == TEXT('\\')))
990 pszSubmount += lstrlen(szNetBiosName);
993 if (!pszSubmount || !*pszSubmount)
996 lstrcpy (pszSubmountNow, pszSubmount);
1000 /* Generate Random User name random acording to time*/
1002 TCHAR pUserName[MAXRANDOMNAMELEN]=TEXT("");
1003 BOOL fUserName=FALSE;
1004 #define AFSLogonOptionName TEXT("System\\CurrentControlSet\\Services\\TransarcAFSDaemon\\NetworkProvider")
1006 void SetBitLogonOption(BOOL set,DWORD value)
1009 RWLogonOption(FALSE,((set)?value | RWLogonOption(TRUE,0):RWLogonOption(TRUE,0) & ~value) );
1012 DWORD RWLogonOption(BOOL read,DWORD value)
1014 // if read is true then if value==0 return registry value
1015 // if read and value!=0 then use value to test registry, return TRUE if value bits match value read
1018 DWORD LSPtype, LSPsize;
1023 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSLogonOptionName, 0, KEY_QUERY_VALUE, &hk)==ERROR_SUCCESS)
1025 LSPsize=sizeof(rval);
1026 RegQueryValueEx(hk, "LogonOptions", NULL,
1027 &LSPtype, (LPBYTE)&rval, &LSPsize);
1030 return (value==0)?rval:((rval & value)==value);
1033 if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, AFSLogonOptionName, 0, NULL, 0, KEY_SET_VALUE, NULL, &hk, &dwDisp) == ERROR_SUCCESS)
1035 RegSetValueEx(hk,TEXT("LogonOptions"),NULL,REG_DWORD,(LPBYTE)&value,sizeof(value));
1042 void MapShareName(char *pszCmdLineA)
1047 while (*pszCmdLineA && (*pszCmdLineA != ' '))
1049 *p++=*pszCmdLineA++;
1053 void GenRandomName(TCHAR *pname,int len)
1056 { //user name was passed through command line, use once
1060 srand( (unsigned)time( NULL ) );
1061 for (int i=0;i<len;i++)
1062 pname[i]='a'+(rand() % 26);
1068 Make a connection using users name
1069 if fUserName then force a connection
1072 BOOL TestAndDoMapShare(DWORD dwState)
1074 if ((dwState!=SERVICE_RUNNING) || (dwOldState!=SERVICE_START_PENDING))
1079 dwOldState=SERVICE_RUNNING;
1080 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1081 return (DoMapShare() && GlobalMountDrive());
1082 return GlobalMountDrive();
1085 BOOL IsServiceActive()
1088 SERVICE_STATUS Status;
1089 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
1092 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
1094 QueryServiceStatus (hService, &Status);
1095 CloseServiceHandle (hService);
1098 CloseServiceHandle (hManager);
1101 return (Status.dwCurrentState == SERVICE_RUNNING) ? TRUE : FALSE;
1104 void TestAndDoUnMapShare()
1106 if (!RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1108 DoUnMapShare(FALSE);
1111 void DoUnMapShare(BOOL drivemap) //disconnect drivemap
1113 TCHAR szMachine[MAX_PATH],szPath[MAX_PATH];
1116 LPNETRESOURCE lpnrLocal,lpnr=NULL;
1118 DWORD cbBuffer=16384;
1122 memset(szMachine, '\0', sizeof(szMachine));
1123 GetClientNetbiosName(szMachine);
1125 // Initialize the data structure
1126 if ((res=WNetOpenEnum(RESOURCE_CONNECTED,RESOURCETYPE_DISK,RESOURCEUSAGE_CONNECTABLE,lpnr,&hEnum))!=NO_ERROR)
1128 sprintf(szPath,"\\\\%s\\",szMachine);
1130 lpnrLocal=(LPNETRESOURCE) GlobalAlloc(GPTR,cbBuffer);
1132 memset(lpnrLocal,0,cbBuffer);
1133 if ((res = WNetEnumResource(hEnum,&cEntries,lpnrLocal,&cbBuffer))==NO_ERROR)
1135 for (DWORD i=0;i<cEntries;i++)
1137 if (strstr(_strlwr(lpnrLocal[i].lpRemoteName),szPath))
1139 if ((lpnrLocal[i].lpLocalName) && (strlen(lpnrLocal[i].lpLocalName)>0))
1142 DisMountDOSDrive(*lpnrLocal[i].lpLocalName);
1143 DEBUG_EVENT1("AFS DriveUnMap","UnMap-Local=%x",res);
1146 DisMountDOSDriveFull(lpnrLocal[i].lpRemoteName);
1147 DEBUG_EVENT1("AFS DriveUnMap","UnMap-Remote=%x",res);
1152 } while (res!=ERROR_NO_MORE_ITEMS);
1153 GlobalFree((HGLOBAL)lpnrLocal);
1154 WNetCloseEnum(hEnum);
1157 BOOL DoMapShareChange()
1160 TCHAR szMachine[ MAX_PATH],szPath[MAX_PATH];
1163 LPNETRESOURCE lpnrLocal,lpnr=NULL;
1166 DWORD cbBuffer=16384;
1168 memset(szMachine, '\0', sizeof(szMachine));
1169 GetClientNetbiosName(szMachine);
1171 // Initialize the data structure
1172 if (!IsServiceActive())
1174 memset (&List, 0x00, sizeof(DRIVEMAPLIST));
1175 for (size_t ii = 0; ii < 26; ++ii)
1176 List.aDriveMap[ii].chDrive = chDRIVE_A + ii;
1177 QueryDriveMapList_ReadSubmounts (&List);
1178 if ((res=WNetOpenEnum(RESOURCE_CONNECTED,RESOURCETYPE_DISK,RESOURCEUSAGE_CONNECTABLE,lpnr,&hEnum))!=NO_ERROR)
1180 lpnrLocal=(LPNETRESOURCE) GlobalAlloc(GPTR,cbBuffer);
1181 sprintf(szPath,"\\\\%s\\",szMachine);
1184 memset(lpnrLocal,0,cbBuffer);
1185 if ((res = WNetEnumResource(hEnum,&cEntries,lpnrLocal,&cbBuffer))==NO_ERROR)
1187 for (DWORD i=0;i<cEntries;i++)
1189 if (strstr(_strlwr(lpnrLocal[i].lpRemoteName),szPath)==NULL)
1190 continue; //only look at real afs mappings
1191 CHAR * pSubmount=strrchr(lpnrLocal[i].lpRemoteName,'\\')+1;
1192 if (lstrcmpi(pSubmount,"all")==0)
1193 continue; // do not remove 'all'
1194 for (DWORD j=0;j<List.cSubmounts;j++)
1197 (List.aSubmounts[j].szSubmount[0]) &&
1198 (lstrcmpi(List.aSubmounts[j].szSubmount,pSubmount)==0)
1201 List.aSubmounts[j].fInUse=TRUE;
1205 // wasn't on list so lets remove
1206 DisMountDOSDrive(pSubmount);
1210 } while (res!=ERROR_NO_MORE_ITEMS);
1211 GlobalFree((HGLOBAL)lpnrLocal);
1212 WNetCloseEnum(hEnum);
1213 sprintf(szPath,"\\\\%s\\all",szMachine);
1215 // Lets connect all submounts that weren't connectd
1216 DWORD cbUser=MAXRANDOMNAMELEN-1;
1217 CHAR szUser[MAXRANDOMNAMELEN];
1218 CHAR * pUser = NULL;
1219 if (WNetGetUser(szPath,(LPSTR)szUser,&cbUser)!=NO_ERROR) {
1220 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY)) {
1221 if (!pUserName[0]) {
1222 GenRandomName(szUser,MAXRANDOMNAMELEN-1);
1229 if ((pUser=strchr(szUser,'\\'))!=NULL)
1233 for (DWORD j=0;j<List.cSubmounts;j++)
1235 if (List.aSubmounts[j].fInUse)
1237 DWORD res=MountDOSDrive(0,List.aSubmounts[j].szSubmount,FALSE,pUser);
1246 BOOL bMappedAll=FALSE;
1248 // Initialize the data structure
1249 DEBUG_EVENT0("AFS DoMapShare");
1250 QueryDriveMapList (&List);
1252 // All connections have been removed
1253 // Lets restore them after making the connection from the random name
1255 TCHAR szMachine[ MAX_PATH],szPath[MAX_PATH];
1256 memset(szMachine, '\0', sizeof(szMachine));
1257 GetClientNetbiosName(szMachine);
1258 sprintf(szPath,"\\\\%s\\all",szMachine);
1260 // Lets connect all submounts that weren't connectd
1261 DWORD cbUser=MAXRANDOMNAMELEN-1;
1262 CHAR szUser[MAXRANDOMNAMELEN];
1263 CHAR * pUser = NULL;
1264 if (WNetGetUser(szPath,(LPSTR)szUser,&cbUser)!=NO_ERROR) {
1265 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY)) {
1266 if (!pUserName[0]) {
1267 GenRandomName(szUser,MAXRANDOMNAMELEN-1);
1274 if ((pUser=strchr(szUser,'\\'))!=NULL)
1278 for (DWORD i=0;i<List.cSubmounts;i++)
1280 if (List.aSubmounts[i].szSubmount[0])
1282 DWORD res=MountDOSDrive(0,List.aSubmounts[i].szSubmount,FALSE,pUser);
1283 if (lstrcmpi("all",List.aSubmounts[i].szSubmount)==0)
1287 if (!bMappedAll) //make sure all is mapped also
1289 DWORD res=MountDOSDrive(0,"all",FALSE,pUser);
1290 if (res==ERROR_SESSION_CREDENTIAL_CONFLICT)
1292 DisMountDOSDrive("all");
1293 MountDOSDrive(0,"all",FALSE,pUser);
1296 for (TCHAR chDrive = chDRIVE_A; chDrive <= chDRIVE_Z; ++chDrive)
1298 if (List.aDriveMap[chDrive-chDRIVE_A].fActive ||
1299 ForceMapActive(chDrive))
1301 TCHAR szSubmount[ MAX_PATH ];
1302 if (List.aDriveMap[chDrive-chDRIVE_A].szSubmount[0])
1303 lstrcpy(szSubmount,List.aDriveMap[chDrive-chDRIVE_A].szSubmount);
1304 else if (!PathToSubmount (szSubmount, List.aDriveMap[chDrive-chDRIVE_A].szMapping, NULL, NULL))
1307 BOOL fPersistent = List.aDriveMap[chDrive-chDRIVE_A].fPersistent;
1308 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1309 fPersistent = FALSE;
1310 DWORD res=MountDOSDrive(chDrive
1312 ,fPersistent,pUser);
1318 BOOL GlobalMountDrive()
1320 char szDriveToMapTo[5];
1322 char szKeyName[256];
1326 DWORD dwSubMountSize;
1327 char unsigned szSubMount[256];
1328 char cm_HostName[200];
1329 DWORD dwType=sizeof(cm_HostName);
1330 if (!IsServiceActive())
1332 if (!GetComputerName(cm_HostName, &dwType))
1334 sprintf(szKeyName, "%s\\GlobalAutoMapper", sAFSConfigKeyName);
1336 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE,
1338 if (dwResult != ERROR_SUCCESS)
1342 dwDriveSize = sizeof(szDriveToMapTo);
1343 dwSubMountSize = sizeof(szSubMount);
1344 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize,
1345 0, &dwType, szSubMount, &dwSubMountSize);
1346 if (dwResult != ERROR_MORE_DATA) {
1347 if (dwResult != ERROR_SUCCESS) {
1348 if (dwResult != ERROR_NO_MORE_ITEMS)
1350 DEBUG_EVENT1("AFS DriveMap","Failed to read GlobalAutoMapper values: %d",dwResult);
1355 dwResult=MountDOSDrive(*szDriveToMapTo,(const char *)szSubMount,FALSE,NULL);
1361 DWORD MountDOSDrive(char chDrive,const char *szSubmount,BOOL bPersistent,const char * pUsername)
1363 TCHAR szPath[MAX_PATH];
1364 TCHAR szClient[MAX_PATH];
1365 TCHAR szDrive[3] = TEXT("?:");
1366 sprintf(szDrive,"%c:",chDrive);
1367 GetClientNetbiosName (szClient);
1368 sprintf(szPath,"\\\\%s\\%s",szClient,szSubmount);
1370 memset (&nr, 0x00, sizeof(NETRESOURCE));
1371 nr.dwType=RESOURCETYPE_DISK;
1372 nr.lpLocalName=szDrive;
1373 nr.lpRemoteName=szPath;
1374 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
1375 DWORD res=WNetAddConnection2(&nr,NULL,pUsername,(bPersistent)?CONNECT_UPDATE_PROFILE:0);
1376 DEBUG_EVENT5("AFS DriveMap","Mount %s Local[%s] Remote[%s] User[%s]=%x",
1377 (bPersistent)?"Persistant" : "NonPresistant",
1378 szDrive,szPath,pUsername?pUsername:"NULL",res);
1382 DWORD DisMountDOSDriveFull(const char *szPath,BOOL bForce)
1384 DWORD res=WNetCancelConnection(szPath,bForce);
1385 DEBUG_EVENT3("AFS DriveMap","%sDismount Remote[%s]=%x",
1386 bForce ? "Forced " : "",szPath,res);
1387 return (res==ERROR_NOT_CONNECTED)?NO_ERROR:res;
1390 DWORD DisMountDOSDrive(const char *pSubmount,BOOL bForce)
1392 TCHAR szPath[MAX_PATH];
1393 TCHAR szClient[MAX_PATH];
1394 GetClientNetbiosName (szClient);
1395 sprintf(szPath,"\\\\%s\\%s",szClient,pSubmount);
1396 return DisMountDOSDriveFull(szPath,bForce);
1400 DWORD DisMountDOSDrive(const char chDrive,BOOL bForce)
1402 TCHAR szPath[MAX_PATH];
1403 sprintf(szPath,"%c:",chDrive);
1404 return DisMountDOSDriveFull(szPath,bForce);