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>
20 #include <WINNT/afsreg.h>
29 #include <lanahelper.h>
32 extern void Config_GetLanAdapter (ULONG *pnLanAdapter);
35 * REGISTRY ___________________________________________________________________
41 * PROFILE SECTIONS ___________________________________________________________
45 #define cREALLOC_SUBMOUNTS 4
47 static TCHAR cszSECTION_SUBMOUNTS[] = TEXT(AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts");
48 static TCHAR cszSECTION_MAPPINGS[] = TEXT(AFSREG_CLT_OPENAFS_SUBKEY "\\Mappings");
49 static TCHAR cszSECTION_ACTIVE[] = TEXT(AFSREG_CLT_OPENAFS_SUBKEY "\\Active Maps");
51 static TCHAR cszAUTOSUBMOUNT[] = TEXT("Auto");
52 static TCHAR cszLANMANDEVICE[] = TEXT("\\Device\\LanmanRedirector\\");
56 WriteRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs, LPTSTR rhs)
63 REG_OPTION_NON_VOLATILE,
69 DWORD status = RegSetValueEx( hkSub, lhs, 0, REG_SZ, (const BYTE *)rhs, strlen(rhs)+1 );
74 return (status == ERROR_SUCCESS);
78 WriteExpandedRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs, LPTSTR rhs)
85 REG_OPTION_NON_VOLATILE,
91 DWORD status = RegSetValueEx( hkSub, lhs, 0, REG_EXPAND_SZ, (const BYTE *)rhs, strlen(rhs)+1 );
96 return (status == ERROR_SUCCESS);
100 ReadRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs, LPTSTR rhs, DWORD * size)
107 REG_OPTION_NON_VOLATILE,
114 DWORD localSize = *size;
116 DWORD status = RegQueryValueEx( hkSub, lhs, 0, &dwType, (LPBYTE)rhs, &localSize);
117 if (status == 0 && dwType == REG_EXPAND_SZ) {
118 TCHAR * buf = (TCHAR *)malloc((*size) * sizeof(TCHAR));
119 memcpy(buf, rhs, (*size) * sizeof(TCHAR));
120 localSize = ExpandEnvironmentStrings(buf, rhs, *size);
122 if ( localSize > *size )
123 status = !ERROR_SUCCESS;
128 RegCloseKey( hkSub );
130 return (status == ERROR_SUCCESS);
134 DeleteRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs)
141 REG_OPTION_NON_VOLATILE,
147 DWORD status = RegDeleteValue( hkSub, lhs );
150 RegCloseKey( hkSub );
152 return (status == ERROR_SUCCESS);
156 * STRINGS ____________________________________________________________________
160 static LPTSTR AllocateStringMemory (size_t cch)
162 LPTSTR psz = (LPTSTR)Allocate (sizeof(TCHAR) * (cch+1));
163 memset (psz, 0x00, sizeof(TCHAR) * (cch+1));
167 static void FreeStringMemory (LPTSTR pszString)
172 static int lstrncmpi (LPCTSTR pszA, LPCTSTR pszB, size_t cch)
176 return (!pszB) - (!pszA); // A,!B:1, !A,B:-1, !A,!B:0
179 for ( ; cch > 0; cch--, pszA = CharNext(pszA), pszB = CharNext(pszB))
181 TCHAR chA = toupper( *pszA );
182 TCHAR chB = toupper( *pszB );
185 return (!chB) - (!chA); // A,!B:1, !A,B:-1, !A,!B:0
188 return (int)(chA) - (int)(chB); // -1:A<B, 0:A==B, 1:A>B
191 return 0; // no differences before told to stop comparing, so A==B
196 * REALLOC ____________________________________________________________________
201 #define REALLOC(_a,_c,_r,_i) DriveMapReallocFunction ((LPVOID*)&_a,sizeof(*_a),&_c,_r,_i)
202 BOOL DriveMapReallocFunction (LPVOID *ppTarget, size_t cbElement, size_t *pcTarget, size_t cReq, size_t cInc)
207 if (cReq <= *pcTarget)
210 if ((cNew = cInc * ((cReq + cInc-1) / cInc)) <= 0)
213 if ((pNew = Allocate (cbElement * cNew)) == NULL)
215 memset (pNew, 0x00, cbElement * cNew);
219 memcpy (pNew, *ppTarget, cbElement * (*pcTarget));
231 * WINDOWS NT STUFF ___________________________________________________________
235 static BOOL IsWindowsNT (void)
237 static BOOL fChecked = FALSE;
238 static BOOL fIsWinNT = FALSE;
244 OSVERSIONINFO Version;
245 memset (&Version, 0x00, sizeof(Version));
246 Version.dwOSVersionInfoSize = sizeof(Version);
248 if (GetVersionEx (&Version))
250 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT)
258 /* Check if the OS is Windows 2000 or higher.
260 BOOL IsWindows2000 (void)
262 static BOOL fChecked = FALSE;
263 static BOOL fIsWin2K = FALSE;
269 OSVERSIONINFO Version;
270 memset (&Version, 0x00, sizeof(Version));
271 Version.dwOSVersionInfoSize = sizeof(Version);
273 if (GetVersionEx (&Version))
275 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
276 Version.dwMajorVersion >= 5)
285 * GENERAL ____________________________________________________________________
289 void GetClientNetbiosName (LPTSTR pszName)
291 static TCHAR szNetbiosName[32] = "";
293 if ( szNetbiosName[0] == 0 ) {
294 lana_GetNetbiosName(szNetbiosName, LANA_NETBIOS_NAME_FULL);
296 _tcscpy(pszName, szNetbiosName);
300 BOOL SubmountToPath (PDRIVEMAPLIST pList, LPTSTR pszPath, LPTSTR pszSubmount, BOOL fMarkInUse)
302 // We can't do this translation unless we're under Windows NT.
307 // \\computer-afs\all always maps to "/afs"
309 if (!lstrcmpi (pszSubmount, TEXT("all")))
311 lstrcpy (pszPath, cm_slash_mount_root);
315 // Otherwise, look up our list of submounts.
317 for (size_t ii = 0; ii < pList->cSubmounts; ++ii)
319 if (!lstrcmpi (pList->aSubmounts[ii].szSubmount, pszSubmount))
322 pList->aSubmounts[ii].fInUse = TRUE;
323 AdjustAfsPath (pszPath, pList->aSubmounts[ii].szMapping, TRUE, TRUE);
332 BOOL IsValidSubmountName (LPTSTR pszSubmount)
336 if (lstrlen (pszSubmount) > 12)
339 for ( ; *pszSubmount; ++pszSubmount)
341 if (!isprint(*pszSubmount))
343 if (*pszSubmount == TEXT(' '))
345 if (*pszSubmount == TEXT('/'))
347 if (*pszSubmount == TEXT('\\'))
349 if (*pszSubmount == TEXT('\t'))
358 * PIOCTL SUPPORT _____________________________________________________________
364 #include "../afsd/fs_utils.h"
366 #define __CM_CONFIG_INTERFACES_ONLY__
367 #include "../afsd/cm_config.h"
369 #define __CM_IOCTL_INTERFACES_ONLY__
370 #include "../afsd/cm_ioctl.h"
374 #define PIOCTL_MAXSIZE 2048
377 BOOL fCanIssuePIOCTL (void)
381 TCHAR szGateway[ 256 ] = TEXT("");
382 GetClientNetbiosName (szGateway);
383 return (szGateway[0]) ? TRUE : FALSE;
386 SERVICE_STATUS Status;
387 memset (&Status, 0x00, sizeof(Status));
388 Status.dwCurrentState = SERVICE_STOPPED;
391 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
394 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
396 QueryServiceStatus (hService, &Status);
397 CloseServiceHandle (hService);
400 CloseServiceHandle (hManager);
403 return (Status.dwCurrentState == SERVICE_RUNNING) ? TRUE : FALSE;
408 * QUERYDRIVEMAPLIST __________________________________________________________
412 void QueryDriveMapList_ReadSubmounts (PDRIVEMAPLIST pList)
418 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
419 cszSECTION_SUBMOUNTS,
422 REG_OPTION_NON_VOLATILE,
423 KEY_READ|KEY_QUERY_VALUE,
429 RegQueryInfoKey( hkSubmounts,
432 NULL, /* lpReserved */
433 NULL, /* lpcSubKeys */
434 NULL, /* lpcMaxSubKeyLen */
435 NULL, /* lpcMaxClassLen */
436 &dwSubmounts, /* lpcValues */
437 NULL, /* lpcMaxValueNameLen */
438 NULL, /* lpcMaxValueLen */
439 NULL, /* lpcbSecurityDescriptor */
440 NULL /* lpftLastWriteTime */
443 for ( DWORD dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) {
444 TCHAR submountPath[MAX_PATH] = "";
445 DWORD submountPathLen = MAX_PATH;
446 TCHAR submountName[MAX_PATH];
447 DWORD submountNameLen = MAX_PATH;
450 RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL,
451 &dwType, (LPBYTE)submountPath, &submountPathLen);
453 if (dwType == REG_EXPAND_SZ) {
455 StringCbCopyA(buf, MAX_PATH, submountPath);
456 submountPathLen = ExpandEnvironmentStrings(buf, submountPath, MAX_PATH);
457 if (submountPathLen > MAX_PATH)
462 memset (&Submount, 0x00, sizeof(SUBMOUNT));
463 lstrcpy (Submount.szSubmount, submountName);
465 if ( submountPath[0] != TEXT('\0') ) {
466 AdjustAfsPath (Submount.szMapping, submountPath, FALSE, TRUE);
468 for (size_t ii = 0; ii < pList->cSubmounts; ++ii)
470 if (!pList->aSubmounts[ii].szSubmount[0])
473 if (REALLOC (pList->aSubmounts, pList->cSubmounts, 1+ii, cREALLOC_SUBMOUNTS))
475 memcpy (&pList->aSubmounts[ii], &Submount, sizeof(SUBMOUNT));
480 RegCloseKey(hkSubmounts);
485 void QueryDriveMapList_ReadMappings (PDRIVEMAPLIST pList)
488 RegCreateKeyEx( HKEY_CURRENT_USER,
492 REG_OPTION_NON_VOLATILE,
493 KEY_READ|KEY_QUERY_VALUE,
499 RegQueryInfoKey( hkMappings,
502 NULL, /* lpReserved */
503 NULL, /* lpcSubKeys */
504 NULL, /* lpcMaxSubKeyLen */
505 NULL, /* lpcMaxClassLen */
506 &dwMappings, /* lpcValues */
507 NULL, /* lpcMaxValueNameLen */
508 NULL, /* lpcMaxValueLen */
509 NULL, /* lpcbSecurityDescriptor */
510 NULL /* lpftLastWriteTime */
513 for ( DWORD dwIndex = 0; dwIndex < dwMappings; dwIndex ++ ) {
514 TCHAR mapping[MAX_PATH] = "";
515 DWORD mappingLen = MAX_PATH;
516 TCHAR drive[MAX_PATH];
517 DWORD driveLen = MAX_PATH;
520 RegEnumValue( hkMappings, dwIndex, drive, &driveLen, NULL,
521 &dwType, (LPBYTE)mapping, &mappingLen);
522 if ( dwType == REG_EXPAND_SZ ) {
524 DWORD dummyLen = ExpandEnvironmentStrings(mapping, buf, MAX_PATH);
525 if (dummyLen > MAX_PATH)
527 _tcsncpy(mapping, buf, MAX_PATH);
531 memset (&DriveMap, 0x00, sizeof(DRIVEMAP));
532 DriveMap.chDrive = toupper(*drive);
533 DriveMap.fPersistent = TRUE;
534 if ((DriveMap.chDrive < chDRIVE_A) || (DriveMap.chDrive > chDRIVE_Z))
537 if (mapping[0] != TEXT('\0'))
539 AdjustAfsPath (DriveMap.szMapping, mapping, TRUE, TRUE);
540 if (DriveMap.szMapping[ lstrlen(DriveMap.szMapping)-1 ] == TEXT('*'))
542 DriveMap.fPersistent = FALSE;
543 DriveMap.szMapping[ lstrlen(DriveMap.szMapping)-1 ] = TEXT('\0');
545 size_t iDrive = DriveMap.chDrive - chDRIVE_A;
546 memcpy (&pList->aDriveMap[ iDrive ], &DriveMap, sizeof(DRIVEMAP));
550 RegCloseKey(hkMappings);
553 BOOL ForceMapActive (TCHAR chDrive)
558 szDrive[0] = chDrive;
561 DWORD len = sizeof(szActive);
562 ReadRegistryString( HKEY_CURRENT_USER, cszSECTION_ACTIVE, szDrive, szActive, &len);
564 if ( !lstrcmp(szActive,"1") || !lstrcmpi(szActive,"true") || !lstrcmpi(szActive,"on") || !lstrcmpi(szActive,"yes") )
570 void WriteActiveMap (TCHAR chDrive, BOOL on)
574 szDrive[0] = chDrive;
577 WriteRegistryString(HKEY_CURRENT_USER, cszSECTION_ACTIVE, szDrive, on ? "1" : "0");
580 void QueryDriveMapList_WriteMappings (PDRIVEMAPLIST pList)
582 WriteDriveMappings (pList);
586 void WriteDriveMappings (PDRIVEMAPLIST pList)
589 RegCreateKeyEx( HKEY_CURRENT_USER,
593 REG_OPTION_NON_VOLATILE,
594 KEY_READ|KEY_QUERY_VALUE|KEY_WRITE,
600 RegQueryInfoKey( hkMappings,
603 NULL, /* lpReserved */
604 NULL, /* lpcSubKeys */
605 NULL, /* lpcMaxSubKeyLen */
606 NULL, /* lpcMaxClassLen */
607 &dwMappings, /* lpcValues */
608 NULL, /* lpcMaxValueNameLen */
609 NULL, /* lpcMaxValueLen */
610 NULL, /* lpcbSecurityDescriptor */
611 NULL /* lpftLastWriteTime */
614 if ( dwMappings > 0 ) {
615 for ( long dwIndex = dwMappings - 1; dwIndex >= 0; dwIndex-- ) {
616 TCHAR drive[MAX_PATH];
617 DWORD driveLen = MAX_PATH;
619 RegEnumValue( hkMappings, dwIndex, drive, &driveLen, NULL, NULL, NULL, NULL);
620 RegDeleteValue( hkMappings, drive );
624 for (size_t iDrive = 0; iDrive < 26; ++iDrive)
626 if (pList->aDriveMap[iDrive].szMapping[0] != TEXT('\0'))
628 TCHAR szLHS[] = TEXT("*");
629 szLHS[0] = pList->aDriveMap[iDrive].chDrive;
631 TCHAR szRHS[MAX_PATH];
632 AdjustAfsPath (szRHS, pList->aDriveMap[iDrive].szMapping, TRUE, TRUE);
633 if (!pList->aDriveMap[iDrive].fPersistent)
634 lstrcat (szRHS, TEXT("*"));
636 RegSetValueEx( hkMappings, szLHS, 0, REG_EXPAND_SZ, (const BYTE *)szRHS, lstrlen(szRHS) + 1);
639 RegCloseKey( hkMappings );
642 BOOL DriveIsGlobalAfsDrive(TCHAR chDrive)
644 TCHAR szKeyName[128];
645 TCHAR szValueName[128];
649 _stprintf(szKeyName, TEXT("%s\\GlobalAutoMapper"), AFSREG_CLT_SVC_PARAM_SUBKEY);
651 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
654 _stprintf(szValueName, TEXT("%c:"), chDrive);
656 DWORD dwSize = sizeof(szValue);
657 BOOL bIsGlobal = (RegQueryValueEx (hKey, szValueName, NULL, NULL, (PBYTE)szValue, &dwSize) == ERROR_SUCCESS);
665 void QueryDriveMapList_FindNetworkDrives (PDRIVEMAPLIST pList, BOOL *pfFoundNew)
667 for (TCHAR chDrive = chDRIVE_A; chDrive <= chDRIVE_Z; ++chDrive)
669 TCHAR szSubmount[ MAX_PATH ];
670 if (!GetDriveSubmount (chDrive, szSubmount))
673 // We've got a mapping! Drive {chDrive} is mapped to submount
674 // {szSubmount}. See if that submount makes sense.
678 size_t iDrive = chDrive - chDRIVE_A;
679 if (pList->aDriveMap[ iDrive ].szMapping[0] != TEXT('\0'))
681 pList->aDriveMap[ iDrive ].fActive = TRUE;
682 lstrcpy (pList->aDriveMap[ iDrive ].szSubmount, szSubmount);
686 else // (IsWindowsNT())
688 TCHAR szAfsPath[ MAX_PATH ];
689 if (!SubmountToPath (pList, szAfsPath, szSubmount, TRUE))
692 // Okay, we know that drive {chDrive} is mapped to afs path {szAfsPath}.
693 // If this drive is a global afs drive, then reject it. Otherwise, look
694 // at pList->aDriveMap, to see if this drive mapping is already in our
695 // list. If not, add it and set pfFoundNew.
697 if (DriveIsGlobalAfsDrive(chDrive))
700 size_t iDrive = chDrive - chDRIVE_A;
701 if (lstrcmpi (pList->aDriveMap[ iDrive ].szMapping, szAfsPath))
704 pList->aDriveMap[ iDrive ].fPersistent = TRUE;
706 pList->aDriveMap[ iDrive ].fActive = TRUE;
707 pList->aDriveMap[ iDrive ].chDrive = chDrive;
708 lstrcpy (pList->aDriveMap[ iDrive ].szSubmount, szSubmount);
709 AdjustAfsPath (pList->aDriveMap[ iDrive ].szMapping, szAfsPath, TRUE, TRUE);
715 void QueryDriveMapList (PDRIVEMAPLIST pList)
717 // Initialize the data structure
719 memset (pList, 0x00, sizeof(DRIVEMAPLIST));
720 for (size_t ii = 0; ii < 26; ++ii)
721 pList->aDriveMap[ii].chDrive = chDRIVE_A + ii;
723 // Read the current lists of submounts and drive letter mappings
725 QueryDriveMapList_ReadSubmounts (pList);
726 QueryDriveMapList_ReadMappings (pList);
728 // Look through the current list of network drives, and see if
729 // any are currently mapped to AFS. If we find any which are mapped
730 // into AFS unexpectedly, we'll have to rewrite the mappings list.
732 BOOL fFoundNew = FALSE;
733 QueryDriveMapList_FindNetworkDrives (pList, &fFoundNew);
737 QueryDriveMapList_WriteMappings (pList);
742 void FreeDriveMapList (PDRIVEMAPLIST pList)
744 if (pList->aSubmounts)
745 Free (pList->aSubmounts);
746 memset (pList, 0x00, sizeof(DRIVEMAPLIST));
750 BOOL PathToSubmount (LPTSTR pszSubmount, LPTSTR pszMapping, LPTSTR pszSubmountReq, ULONG *pStatus)
752 if (pszSubmountReq && !IsValidSubmountName (pszSubmountReq))
753 pszSubmountReq = NULL;
755 TCHAR szAfsPath[ MAX_PATH ];
756 AdjustAfsPath (szAfsPath, pszMapping, TRUE, TRUE);
758 // Try to ask AFSD for a new submount name.
760 if (!fCanIssuePIOCTL())
763 BYTE InData[ PIOCTL_MAXSIZE ];
764 memset (InData, 0x00, sizeof(InData));
766 LPTSTR pszInData = (LPTSTR)InData;
767 lstrcpy (pszInData, pszMapping);
768 pszInData += 1+lstrlen(pszInData);
770 lstrcpy (pszInData, pszSubmountReq);
772 BYTE OutData[ PIOCTL_MAXSIZE ];
773 memset (OutData, 0x00, sizeof(OutData));
775 struct ViceIoctl IOInfo;
776 IOInfo.in = (char *)InData;
777 IOInfo.in_size = PIOCTL_MAXSIZE;
778 IOInfo.out = (char *)OutData;
779 IOInfo.out_size = PIOCTL_MAXSIZE;
781 ULONG status = pioctl (0, VIOC_MAKESUBMOUNT, &IOInfo, 1);
788 lstrcpy (pszSubmount, (LPCTSTR)OutData);
789 return (pszSubmount[0] != TEXT('\0')) ? TRUE : FALSE;
793 BOOL ActivateDriveMap (TCHAR chDrive, LPTSTR pszMapping, LPTSTR pszSubmountReq, BOOL fPersistent, DWORD *pdwStatus)
795 // We can only map drives to places in AFS using this function.
797 if ( (lstrncmpi (pszMapping, cm_slash_mount_root, lstrlen(cm_slash_mount_root))) &&
798 (lstrncmpi (pszMapping, cm_back_slash_mount_root, lstrlen(cm_back_slash_mount_root))) )
801 *pdwStatus = ERROR_BAD_NETPATH;
805 // First we have to translate {pszMapping} into a submount, and if there is
806 // no current submount associated with this path, we'll have to make one.
809 TCHAR szSubmount[ MAX_PATH ];
810 if (!PathToSubmount (szSubmount, pszMapping, pszSubmountReq, &status))
817 // We now have a submount name and drive letter--map the network drive.
818 DWORD rc=MountDOSDrive(chDrive,szSubmount,fPersistent,NULL);
828 BOOL InactivateDriveMap (TCHAR chDrive, DWORD *pdwStatus)
830 DWORD rc = DisMountDOSDrive(chDrive, FALSE);
840 void AddSubMount (LPTSTR pszSubmount, LPTSTR pszMapping)
842 TCHAR szRHS[ MAX_PATH ];
843 AdjustAfsPath (szRHS, pszMapping, FALSE, TRUE);
845 lstrcpy (szRHS, TEXT("/"));
847 WriteExpandedRegistryString(HKEY_LOCAL_MACHINE, cszSECTION_SUBMOUNTS, pszSubmount, szRHS);
851 void RemoveSubMount (LPTSTR pszSubmount)
853 DeleteRegistryString(HKEY_LOCAL_MACHINE, cszSECTION_SUBMOUNTS, pszSubmount);
857 void AdjustAfsPath (LPTSTR pszTarget, LPCTSTR pszSource, BOOL fWantAFS, BOOL fWantForwardSlashes)
860 lstrcpy (pszTarget, (fWantAFS) ? cm_slash_mount_root : TEXT(""));
861 else if ((*pszSource != TEXT('/')) && (*pszSource != TEXT('\\')))
862 wsprintf (pszTarget, TEXT("%s/%s"),cm_slash_mount_root, pszSource);
863 // We don't want to strip afs off the start if it is part of something for example afscell.company.com
864 else if (fWantAFS && (lstrncmpi (&pszSource[1], cm_mount_root, strlen(cm_mount_root))) || !((pszSource[strlen(cm_slash_mount_root)] == TEXT('/')) ||
865 (pszSource[strlen(cm_slash_mount_root)] == TEXT('\\')) ||
866 (lstrlen(pszSource) == strlen(cm_slash_mount_root))))
867 wsprintf (pszTarget, TEXT("%s%s"),cm_slash_mount_root, pszSource);
868 else if (!fWantAFS && (!lstrncmpi (&pszSource[1], cm_mount_root, strlen(cm_mount_root)) && ((pszSource[strlen(cm_slash_mount_root)] == TEXT('/')) ||
869 (pszSource[strlen(cm_slash_mount_root)] == TEXT('\\')) ||
870 (lstrlen(pszSource) == strlen(cm_slash_mount_root)))))
871 lstrcpy (pszTarget, &pszSource[strlen(cm_slash_mount_root)]);
873 lstrcpy (pszTarget, pszSource);
875 for (LPTSTR pch = pszTarget; *pch; ++pch)
877 if (fWantForwardSlashes)
879 *pch = (*pch == TEXT('\\')) ? TEXT('/') : (*pch);
881 else // (!fWantForwardSlashes)
883 *pch = (*pch == TEXT('/')) ? TEXT('\\') : (*pch);
887 if (lstrlen(pszTarget) &&
888 ((pszTarget[lstrlen(pszTarget)-1] == TEXT('/')) ||
889 (pszTarget[lstrlen(pszTarget)-1] == TEXT('\\'))))
891 pszTarget[lstrlen(pszTarget)-1] = TEXT('\0');
895 BOOL GetDriveSubmount (TCHAR chDrive, LPTSTR pszSubmountNow)
897 BOOL isWinNT = IsWindowsNT();
899 TCHAR szDrive[] = TEXT("*:");
900 szDrive[0] = chDrive;
902 TCHAR szMapping[ _MAX_PATH ] = TEXT("");
904 if (isWinNT && !QueryDosDevice (szDrive, szMapping, MAX_PATH))
907 LPTSTR pszSubmount = szMapping;
909 TCHAR szNetBiosName[32];
910 memset(szNetBiosName, '\0', sizeof(szNetBiosName));
911 GetClientNetbiosName(szNetBiosName);
912 _tcscat(szNetBiosName, TEXT("\\"));
916 // Now if this is an AFS network drive mapping, {szMapping} will be:
918 // \Device\LanmanRedirector\<Drive>:\<netbiosname>\submount
920 // on Windows NT. On Windows 2000, it will be:
922 // \Device\LanmanRedirector\;<Drive>:0\<netbiosname>\submount
924 // (This is presumably to support multiple drive mappings with
927 // on Windows XP and 2003, it will be :
928 // \Device\LanmanRedirector\;<Drive>:<AuthID>\<netbiosname>\submount
930 // where : <Drive> : DOS drive letter
931 // <AuthID>: Authentication ID, 16 char hex.
932 // <netbiosname>: Netbios name of server
934 if (_tcsnicmp(szMapping, cszLANMANDEVICE, _tcslen(cszLANMANDEVICE)))
936 pszSubmount = &szMapping[ _tcslen(cszLANMANDEVICE) ];
940 if (*(pszSubmount) != TEXT(';'))
945 if (toupper(*(++pszSubmount)) != chDrive)
948 if (*(++pszSubmount) != TEXT(':'))
952 // No longer a safe assumption on XP
954 if (*(++pszSubmount) != TEXT('0'))
959 while (*(++pszSubmount) != TEXT('\\'))
965 // note that szNetBiosName has a '\\' tagged in the end earlier
966 for (++pszSubmount; *pszSubmount && (*pszSubmount != TEXT('\\')); ++pszSubmount)
967 if (!_tcsncicmp(pszSubmount, szNetBiosName, _tcslen(szNetBiosName)))
969 if ((!*pszSubmount) || (*pszSubmount == TEXT('\\')))
972 pszSubmount += _tcslen(szNetBiosName);
974 else // (!IsWindowsNT())
976 DWORD dwSize = MAX_PATH;
977 if (WNetGetConnection (szDrive, szMapping, &dwSize) != NO_ERROR)
979 if (*(pszSubmount++) != TEXT('\\'))
981 if (*(pszSubmount++) != TEXT('\\'))
983 for ( ; *pszSubmount && (*pszSubmount != TEXT('\\')); ++pszSubmount)
984 if (!lstrncmpi (pszSubmount, szNetBiosName, lstrlen(szNetBiosName)))
986 if ((!*pszSubmount) || (*pszSubmount == TEXT('\\')))
988 pszSubmount += lstrlen(szNetBiosName);
991 if (!pszSubmount || !*pszSubmount)
994 lstrcpy (pszSubmountNow, pszSubmount);
998 /* Generate Random User name random acording to time*/
1000 TCHAR pUserName[MAXRANDOMNAMELEN]=TEXT("");
1001 BOOL fUserName=FALSE;
1002 #define AFSLogonOptionName TEXT(AFSREG_CLT_SVC_PROVIDER_SUBKEY)
1004 void SetBitLogonOption(BOOL set,DWORD value)
1007 RWLogonOption(FALSE,((set)?value | RWLogonOption(TRUE,0):RWLogonOption(TRUE,0) & ~value) );
1010 DWORD RWLogonOption(BOOL read,DWORD value)
1012 // if read is true then if value==0 return registry value
1013 // if read and value!=0 then use value to test registry, return TRUE if value bits match value read
1016 DWORD LSPtype, LSPsize;
1022 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSLogonOptionName, 0, KEY_QUERY_VALUE, &hk)==ERROR_SUCCESS)
1024 LSPsize=sizeof(rval);
1025 RegQueryValueEx(hk, "LogonOptions", NULL,
1026 &LSPtype, (LPBYTE)&rval, &LSPsize);
1029 return (value==0)?rval:((rval & value)==value);
1031 if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, AFSLogonOptionName, 0, NULL, 0, KEY_SET_VALUE, NULL, &hk, &dwDisp) == ERROR_SUCCESS)
1033 RegSetValueEx(hk,TEXT("LogonOptions"),NULL,REG_DWORD,(LPBYTE)&value,sizeof(value));
1040 void MapShareName(char *pszCmdLineA)
1045 while (*pszCmdLineA && (*pszCmdLineA != ' '))
1047 *p++=*pszCmdLineA++;
1051 void GenRandomName(TCHAR *pname,int len)
1054 { //user name was passed through command line, use once
1058 srand( (unsigned)time( NULL ) );
1059 for (int i=0;i<len;i++)
1060 pname[i]='a'+(rand() % 26);
1066 Make a connection using users name
1067 if fUserName then force a connection
1070 BOOL TestAndDoMapShare(DWORD dwState)
1072 if ((dwState!=SERVICE_RUNNING) || (dwOldState!=SERVICE_START_PENDING))
1077 dwOldState=SERVICE_RUNNING;
1078 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1079 return (DoMapShare() && GlobalMountDrive());
1080 return GlobalMountDrive();
1083 BOOL IsServiceActive()
1086 SERVICE_STATUS Status;
1087 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
1090 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
1092 QueryServiceStatus (hService, &Status);
1093 CloseServiceHandle (hService);
1096 CloseServiceHandle (hManager);
1099 return (Status.dwCurrentState == SERVICE_RUNNING) ? TRUE : FALSE;
1102 void TestAndDoUnMapShare()
1104 if (!RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1106 DoUnMapShare(FALSE);
1109 void DoUnMapShare(BOOL drivemap) //disconnect drivemap
1111 TCHAR szMachine[MAX_PATH],szPath[MAX_PATH];
1114 LPNETRESOURCE lpnrLocal,lpnr=NULL;
1116 DWORD cbBuffer=16384;
1120 memset(szMachine, '\0', sizeof(szMachine));
1121 GetClientNetbiosName(szMachine);
1123 // Initialize the data structure
1124 if ((res=WNetOpenEnum(RESOURCE_CONNECTED,RESOURCETYPE_DISK,RESOURCEUSAGE_CONNECTABLE,lpnr,&hEnum))!=NO_ERROR)
1126 sprintf(szPath,"\\\\%s\\",szMachine);
1128 lpnrLocal=(LPNETRESOURCE) GlobalAlloc(GPTR,cbBuffer);
1130 memset(lpnrLocal,0,cbBuffer);
1131 if ((res = WNetEnumResource(hEnum,&cEntries,lpnrLocal,&cbBuffer))==NO_ERROR)
1133 for (DWORD i=0;i<cEntries;i++)
1135 if (strstr(_strlwr(lpnrLocal[i].lpRemoteName),szPath))
1137 if ((lpnrLocal[i].lpLocalName) && (strlen(lpnrLocal[i].lpLocalName)>0))
1140 DisMountDOSDrive(*lpnrLocal[i].lpLocalName);
1141 DEBUG_EVENT1("AFS DriveUnMap","UnMap-Local=%x",res);
1144 DisMountDOSDriveFull(lpnrLocal[i].lpRemoteName);
1145 DEBUG_EVENT1("AFS DriveUnMap","UnMap-Remote=%x",res);
1150 } while (res!=ERROR_NO_MORE_ITEMS);
1151 GlobalFree((HGLOBAL)lpnrLocal);
1152 WNetCloseEnum(hEnum);
1155 BOOL DoMapShareChange()
1158 TCHAR szMachine[ MAX_PATH],szPath[MAX_PATH];
1161 LPNETRESOURCE lpnrLocal,lpnr=NULL;
1164 DWORD cbBuffer=16384;
1166 memset(szMachine, '\0', sizeof(szMachine));
1167 GetClientNetbiosName(szMachine);
1169 // Initialize the data structure
1170 if (!IsServiceActive())
1172 memset (&List, 0x00, sizeof(DRIVEMAPLIST));
1173 for (size_t ii = 0; ii < 26; ++ii)
1174 List.aDriveMap[ii].chDrive = chDRIVE_A + ii;
1175 QueryDriveMapList_ReadSubmounts (&List);
1176 if ((res=WNetOpenEnum(RESOURCE_CONNECTED,RESOURCETYPE_DISK,RESOURCEUSAGE_CONNECTABLE,lpnr,&hEnum))!=NO_ERROR)
1178 lpnrLocal=(LPNETRESOURCE) GlobalAlloc(GPTR,cbBuffer);
1179 sprintf(szPath,"\\\\%s\\",szMachine);
1182 memset(lpnrLocal,0,cbBuffer);
1183 if ((res = WNetEnumResource(hEnum,&cEntries,lpnrLocal,&cbBuffer))==NO_ERROR)
1185 for (DWORD i=0;i<cEntries;i++)
1187 if (strstr(_strlwr(lpnrLocal[i].lpRemoteName),szPath)==NULL)
1188 continue; //only look at real afs mappings
1189 CHAR * pSubmount=strrchr(lpnrLocal[i].lpRemoteName,'\\')+1;
1190 if (lstrcmpi(pSubmount,"all")==0)
1191 continue; // do not remove 'all'
1192 for (DWORD j=0;j<List.cSubmounts;j++)
1195 (List.aSubmounts[j].szSubmount[0]) &&
1196 (lstrcmpi(List.aSubmounts[j].szSubmount,pSubmount)==0)
1199 List.aSubmounts[j].fInUse=TRUE;
1203 // wasn't on list so lets remove
1204 DisMountDOSDrive(pSubmount);
1208 } while (res!=ERROR_NO_MORE_ITEMS);
1209 GlobalFree((HGLOBAL)lpnrLocal);
1210 WNetCloseEnum(hEnum);
1211 sprintf(szPath,"\\\\%s\\all",szMachine);
1213 // Lets connect all submounts that weren't connectd
1214 DWORD cbUser=MAXRANDOMNAMELEN-1;
1215 CHAR szUser[MAXRANDOMNAMELEN];
1216 CHAR * pUser = NULL;
1217 if (WNetGetUser(szPath,(LPSTR)szUser,&cbUser)!=NO_ERROR) {
1218 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY)) {
1219 if (!pUserName[0]) {
1220 GenRandomName(szUser,MAXRANDOMNAMELEN-1);
1227 if ((pUser=strchr(szUser,'\\'))!=NULL)
1231 for (DWORD j=0;j<List.cSubmounts;j++)
1233 if (List.aSubmounts[j].fInUse)
1235 DWORD res=MountDOSDrive(0,List.aSubmounts[j].szSubmount,FALSE,pUser);
1244 BOOL bMappedAll=FALSE;
1246 // Initialize the data structure
1247 DEBUG_EVENT0("AFS DoMapShare");
1248 QueryDriveMapList (&List);
1250 // All connections have been removed
1251 // Lets restore them after making the connection from the random name
1253 TCHAR szMachine[ MAX_PATH],szPath[MAX_PATH];
1254 memset(szMachine, '\0', sizeof(szMachine));
1255 GetClientNetbiosName(szMachine);
1256 sprintf(szPath,"\\\\%s\\all",szMachine);
1258 // Lets connect all submounts that weren't connectd
1259 DWORD cbUser=MAXRANDOMNAMELEN-1;
1260 CHAR szUser[MAXRANDOMNAMELEN];
1261 CHAR * pUser = NULL;
1262 if (WNetGetUser(szPath,(LPSTR)szUser,&cbUser)!=NO_ERROR) {
1263 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY)) {
1264 if (!pUserName[0]) {
1265 GenRandomName(szUser,MAXRANDOMNAMELEN-1);
1272 if ((pUser=strchr(szUser,'\\'))!=NULL)
1276 for (DWORD i=0;i<List.cSubmounts;i++)
1278 if (List.aSubmounts[i].szSubmount[0])
1280 DWORD res=MountDOSDrive(0,List.aSubmounts[i].szSubmount,FALSE,pUser);
1281 if (lstrcmpi("all",List.aSubmounts[i].szSubmount)==0)
1285 if (!bMappedAll) //make sure all is mapped also
1287 DWORD res=MountDOSDrive(0,"all",FALSE,pUser);
1288 if (res==ERROR_SESSION_CREDENTIAL_CONFLICT)
1290 DisMountDOSDrive("all");
1291 MountDOSDrive(0,"all",FALSE,pUser);
1294 for (TCHAR chDrive = chDRIVE_A; chDrive <= chDRIVE_Z; ++chDrive)
1296 if (List.aDriveMap[chDrive-chDRIVE_A].fActive ||
1297 ForceMapActive(chDrive))
1299 TCHAR szSubmount[ MAX_PATH ];
1300 if (List.aDriveMap[chDrive-chDRIVE_A].szSubmount[0])
1301 lstrcpy(szSubmount,List.aDriveMap[chDrive-chDRIVE_A].szSubmount);
1302 else if (!PathToSubmount (szSubmount, List.aDriveMap[chDrive-chDRIVE_A].szMapping, NULL, NULL))
1305 BOOL fPersistent = List.aDriveMap[chDrive-chDRIVE_A].fPersistent;
1306 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1307 fPersistent = FALSE;
1308 DWORD res=MountDOSDrive(chDrive
1310 ,fPersistent,pUser);
1316 BOOL GlobalMountDrive()
1318 char szDriveToMapTo[5];
1320 char szKeyName[256];
1324 DWORD dwSubMountSize;
1325 char unsigned szSubMount[256];
1326 char cm_HostName[200];
1327 DWORD dwType=sizeof(cm_HostName);
1328 if (!IsServiceActive())
1330 if (!GetComputerName(cm_HostName, &dwType))
1332 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
1334 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE,
1336 if (dwResult != ERROR_SUCCESS)
1340 dwDriveSize = sizeof(szDriveToMapTo);
1341 dwSubMountSize = sizeof(szSubMount);
1342 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize,
1343 0, &dwType, szSubMount, &dwSubMountSize);
1344 if (dwResult != ERROR_MORE_DATA) {
1345 if (dwResult != ERROR_SUCCESS) {
1346 if (dwResult != ERROR_NO_MORE_ITEMS)
1348 DEBUG_EVENT1("AFS DriveMap","Failed to read GlobalAutoMapper values: %d",dwResult);
1353 dwResult=MountDOSDrive(*szDriveToMapTo,(const char *)szSubMount,FALSE,NULL);
1359 DWORD MountDOSDrive(char chDrive,const char *szSubmount,BOOL bPersistent,const char * pUsername)
1361 TCHAR szPath[MAX_PATH];
1362 TCHAR szClient[MAX_PATH];
1363 TCHAR szDrive[3] = TEXT("?:");
1364 sprintf(szDrive,"%c:",chDrive);
1365 GetClientNetbiosName (szClient);
1366 sprintf(szPath,"\\\\%s\\%s",szClient,szSubmount);
1368 memset (&nr, 0x00, sizeof(NETRESOURCE));
1369 nr.dwType=RESOURCETYPE_DISK;
1370 nr.lpLocalName=szDrive;
1371 nr.lpRemoteName=szPath;
1372 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
1373 DWORD res=WNetAddConnection2(&nr,NULL,pUsername,(bPersistent)?CONNECT_UPDATE_PROFILE:0);
1374 DEBUG_EVENT5("AFS DriveMap","Mount %s Local[%s] Remote[%s] User[%s]=%x",
1375 (bPersistent)?"Persistant" : "NonPresistant",
1376 szDrive,szPath,pUsername?pUsername:"NULL",res);
1380 DWORD DisMountDOSDriveFull(const char *szPath,BOOL bForce)
1382 DWORD res=WNetCancelConnection(szPath,bForce);
1383 DEBUG_EVENT3("AFS DriveMap","%sDismount Remote[%s]=%x",
1384 bForce ? "Forced " : "",szPath,res);
1385 return (res==ERROR_NOT_CONNECTED)?NO_ERROR:res;
1388 DWORD DisMountDOSDrive(const char *pSubmount,BOOL bForce)
1390 TCHAR szPath[MAX_PATH];
1391 TCHAR szClient[MAX_PATH];
1392 GetClientNetbiosName (szClient);
1393 sprintf(szPath,"\\\\%s\\%s",szClient,pSubmount);
1394 return DisMountDOSDriveFull(szPath,bForce);
1398 DWORD DisMountDOSDrive(const char chDrive,BOOL bForce)
1400 TCHAR szPath[MAX_PATH];
1401 sprintf(szPath,"%c:",chDrive);
1402 return DisMountDOSDriveFull(szPath,bForce);