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
9 /* AFSIFS portions copyright (c) 2005
10 * the regents of the university of michigan
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.
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.
38 #include <afs/param.h>
41 #include <afs/fs_utils.h>
46 #include <WINNT/TaLocale.h>
47 #include <WINNT/afsreg.h>
56 #include <lanahelper.h>
59 extern void Config_GetLanAdapter (ULONG *pnLanAdapter);
62 * REGISTRY ___________________________________________________________________
68 * PROFILE SECTIONS ___________________________________________________________
72 #define cREALLOC_SUBMOUNTS 4
74 static TCHAR cszSECTION_SUBMOUNTS[] = TEXT(AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts");
75 static TCHAR cszSECTION_MAPPINGS[] = TEXT(AFSREG_CLT_OPENAFS_SUBKEY "\\Mappings");
76 static TCHAR cszSECTION_ACTIVE[] = TEXT(AFSREG_CLT_OPENAFS_SUBKEY "\\Active Maps");
78 static TCHAR cszAUTOSUBMOUNT[] = TEXT("Auto");
79 static TCHAR cszLANMANDEVICE[] = TEXT("\\Device\\LanmanRedirector\\");
83 WriteRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs, LPTSTR rhs)
90 REG_OPTION_NON_VOLATILE,
96 DWORD status = RegSetValueEx( hkSub, lhs, 0, REG_SZ, (const BYTE *)rhs, strlen(rhs)+1 );
101 return (status == ERROR_SUCCESS);
105 WriteExpandedRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs, LPTSTR rhs)
112 REG_OPTION_NON_VOLATILE,
118 DWORD status = RegSetValueEx( hkSub, lhs, 0, REG_EXPAND_SZ, (const BYTE *)rhs, strlen(rhs)+1 );
121 RegCloseKey( hkSub );
123 return (status == ERROR_SUCCESS);
127 ReadRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs, LPTSTR rhs, DWORD * size)
134 REG_OPTION_NON_VOLATILE,
141 DWORD localSize = *size;
143 DWORD status = RegQueryValueEx( hkSub, lhs, 0, &dwType, (LPBYTE)rhs, &localSize);
144 if (status == 0 && dwType == REG_EXPAND_SZ) {
145 TCHAR * buf = (TCHAR *)malloc((*size) * sizeof(TCHAR));
146 memcpy(buf, rhs, (*size) * sizeof(TCHAR));
147 localSize = ExpandEnvironmentStrings(buf, rhs, *size);
149 if ( localSize > *size )
150 status = !ERROR_SUCCESS;
155 RegCloseKey( hkSub );
157 return (status == ERROR_SUCCESS);
161 DeleteRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs)
168 REG_OPTION_NON_VOLATILE,
174 DWORD status = RegDeleteValue( hkSub, lhs );
177 RegCloseKey( hkSub );
179 return (status == ERROR_SUCCESS);
183 * STRINGS ____________________________________________________________________
187 static LPTSTR AllocateStringMemory (size_t cch)
189 LPTSTR psz = (LPTSTR)Allocate (sizeof(TCHAR) * (cch+1));
190 memset (psz, 0x00, sizeof(TCHAR) * (cch+1));
194 static void FreeStringMemory (LPTSTR pszString)
200 static int lstrncmpi (LPCTSTR pszA, LPCTSTR pszB, size_t cch)
204 return (!pszB) - (!pszA); // A,!B:1, !A,B:-1, !A,!B:0
207 for ( ; cch > 0; cch--, pszA = CharNext(pszA), pszB = CharNext(pszB))
209 TCHAR chA = toupper( *pszA );
210 TCHAR chB = toupper( *pszB );
213 return (!chB) - (!chA); // A,!B:1, !A,B:-1, !A,!B:0
216 return (int)(chA) - (int)(chB); // -1:A<B, 0:A==B, 1:A>B
219 return 0; // no differences before told to stop comparing, so A==B
224 * REALLOC ____________________________________________________________________
229 #define REALLOC(_a,_c,_r,_i) DriveMapReallocFunction ((LPVOID*)&_a,sizeof(*_a),&_c,_r,_i)
230 BOOL DriveMapReallocFunction (LPVOID *ppTarget, size_t cbElement, size_t *pcTarget, size_t cReq, size_t cInc)
235 if (cReq <= *pcTarget)
238 if ((cNew = cInc * ((cReq + cInc-1) / cInc)) <= 0)
241 if ((pNew = Allocate (cbElement * cNew)) == NULL)
243 memset (pNew, 0x00, cbElement * cNew);
247 memcpy (pNew, *ppTarget, cbElement * (*pcTarget));
259 * WINDOWS NT STUFF ___________________________________________________________
263 static BOOL IsWindowsNT (void)
265 static BOOL fChecked = FALSE;
266 static BOOL fIsWinNT = FALSE;
272 OSVERSIONINFO Version;
273 memset (&Version, 0x00, sizeof(Version));
274 Version.dwOSVersionInfoSize = sizeof(Version);
276 if (GetVersionEx (&Version))
278 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT)
286 /* Check if the OS is Windows 2000 or higher.
288 BOOL IsWindows2000 (void)
290 static BOOL fChecked = FALSE;
291 static BOOL fIsWin2K = FALSE;
297 OSVERSIONINFO Version;
298 memset (&Version, 0x00, sizeof(Version));
299 Version.dwOSVersionInfoSize = sizeof(Version);
301 if (GetVersionEx (&Version))
303 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
304 Version.dwMajorVersion >= 5)
313 * GENERAL ____________________________________________________________________
317 void GetClientNetbiosName (LPTSTR pszName)
319 static TCHAR szNetbiosName[32] = "";
321 if ( szNetbiosName[0] == 0 ) {
322 lana_GetNetbiosName(szNetbiosName, LANA_NETBIOS_NAME_FULL);
324 _tcscpy(pszName, szNetbiosName);
328 BOOL SubmountToPath (PDRIVEMAPLIST pList, LPTSTR pszPath, LPTSTR pszSubmount, BOOL fMarkInUse)
330 // We can't do this translation unless we're under Windows NT.
335 // \\computer-afs\all always maps to "/afs"
337 if (!lstrcmpi (pszSubmount, TEXT("all")))
339 lstrcpy (pszPath, cm_slash_mount_root);
343 // Otherwise, look up our list of submounts.
346 AdjustAfsPath (pszPath, pszSubmount, TRUE, TRUE);
348 for (size_t ii = 0; ii < pList->cSubmounts; ++ii)
352 b = !lstrcmpi (pList->aSubmounts[ii].szSubmount, pszSubmount);
354 b = !lstrcmpi (pList->aSubmounts[ii].szMapping, pszPath);
359 pList->aSubmounts[ii].fInUse = TRUE;
360 AdjustAfsPath (pszPath, pList->aSubmounts[ii].szMapping, TRUE, TRUE);
369 BOOL IsValidSubmountName (LPTSTR pszSubmount)
373 if (lstrlen (pszSubmount) > 12)
376 for ( ; *pszSubmount; ++pszSubmount)
378 if (!isprint(*pszSubmount))
380 if (*pszSubmount == TEXT(' '))
382 if (*pszSubmount == TEXT('/'))
384 if (*pszSubmount == TEXT('\\'))
386 if (*pszSubmount == TEXT('\t'))
395 * PIOCTL SUPPORT _____________________________________________________________
401 #include "../afsd/fs_utils.h"
403 #define __CM_CONFIG_INTERFACES_ONLY__
404 #include "../afsd/cm_config.h"
406 #include "../afsd/cm_nls.h"
407 #define __CM_IOCTL_INTERFACES_ONLY__
408 #include "../afsd/cm_ioctl.h"
412 #define PIOCTL_MAXSIZE 2048
415 BOOL fCanIssuePIOCTL (void)
419 TCHAR szGateway[ 256 ] = TEXT("");
420 GetClientNetbiosName (szGateway);
421 return (szGateway[0]) ? TRUE : FALSE;
424 SERVICE_STATUS Status;
425 memset (&Status, 0x00, sizeof(Status));
426 Status.dwCurrentState = SERVICE_STOPPED;
429 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
432 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
434 QueryServiceStatus (hService, &Status);
435 CloseServiceHandle (hService);
438 CloseServiceHandle (hManager);
441 return (Status.dwCurrentState == SERVICE_RUNNING) ? TRUE : FALSE;
446 * QUERYDRIVEMAPLIST __________________________________________________________
450 void QueryDriveMapList_ReadSubmounts (PDRIVEMAPLIST pList)
456 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
457 cszSECTION_SUBMOUNTS,
460 REG_OPTION_NON_VOLATILE,
461 KEY_READ|KEY_QUERY_VALUE,
467 RegQueryInfoKey( hkSubmounts,
470 NULL, /* lpReserved */
471 NULL, /* lpcSubKeys */
472 NULL, /* lpcMaxSubKeyLen */
473 NULL, /* lpcMaxClassLen */
474 &dwSubmounts, /* lpcValues */
475 NULL, /* lpcMaxValueNameLen */
476 NULL, /* lpcMaxValueLen */
477 NULL, /* lpcbSecurityDescriptor */
478 NULL /* lpftLastWriteTime */
481 for ( DWORD dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) {
482 TCHAR submountPath[MAX_PATH] = "";
483 DWORD submountPathLen = MAX_PATH;
484 TCHAR submountName[MAX_PATH];
485 DWORD submountNameLen = MAX_PATH;
488 RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL,
489 &dwType, (LPBYTE)submountPath, &submountPathLen);
491 if (dwType == REG_EXPAND_SZ) {
493 StringCbCopyA(buf, MAX_PATH, submountPath);
494 submountPathLen = ExpandEnvironmentStrings(buf, submountPath, MAX_PATH);
495 if (submountPathLen > MAX_PATH)
500 memset (&Submount, 0x00, sizeof(SUBMOUNT));
501 lstrcpy (Submount.szSubmount, submountName);
503 if ( submountPath[0] != TEXT('\0') ) {
504 AdjustAfsPath (Submount.szMapping, submountPath, FALSE, TRUE);
507 for (ii = 0; ii < pList->cSubmounts; ++ii)
509 if (!pList->aSubmounts[ii].szSubmount[0])
512 if (REALLOC (pList->aSubmounts, pList->cSubmounts, 1+ii, cREALLOC_SUBMOUNTS))
514 memcpy (&pList->aSubmounts[ii], &Submount, sizeof(SUBMOUNT));
519 RegCloseKey(hkSubmounts);
524 void QueryDriveMapList_ReadMappings (PDRIVEMAPLIST pList)
527 RegCreateKeyEx( HKEY_CURRENT_USER,
531 REG_OPTION_NON_VOLATILE,
532 KEY_READ|KEY_QUERY_VALUE,
538 RegQueryInfoKey( hkMappings,
541 NULL, /* lpReserved */
542 NULL, /* lpcSubKeys */
543 NULL, /* lpcMaxSubKeyLen */
544 NULL, /* lpcMaxClassLen */
545 &dwMappings, /* lpcValues */
546 NULL, /* lpcMaxValueNameLen */
547 NULL, /* lpcMaxValueLen */
548 NULL, /* lpcbSecurityDescriptor */
549 NULL /* lpftLastWriteTime */
552 for ( DWORD dwIndex = 0; dwIndex < dwMappings; dwIndex ++ ) {
553 TCHAR mapping[MAX_PATH] = "";
554 DWORD mappingLen = MAX_PATH;
555 TCHAR drive[MAX_PATH];
556 DWORD driveLen = MAX_PATH;
559 RegEnumValue( hkMappings, dwIndex, drive, &driveLen, NULL,
560 &dwType, (LPBYTE)mapping, &mappingLen);
561 if ( dwType == REG_EXPAND_SZ ) {
563 DWORD dummyLen = ExpandEnvironmentStrings(mapping, buf, MAX_PATH);
564 if (dummyLen > MAX_PATH)
566 _tcsncpy(mapping, buf, MAX_PATH);
570 memset (&DriveMap, 0x00, sizeof(DRIVEMAP));
571 DriveMap.chDrive = toupper(*drive);
572 DriveMap.fPersistent = TRUE;
573 if ((DriveMap.chDrive < chDRIVE_A) || (DriveMap.chDrive > chDRIVE_Z))
576 if (mapping[0] != TEXT('\0'))
578 AdjustAfsPath (DriveMap.szMapping, mapping, TRUE, TRUE);
579 if (DriveMap.szMapping[ lstrlen(DriveMap.szMapping)-1 ] == TEXT('*'))
581 DriveMap.fPersistent = FALSE;
582 DriveMap.szMapping[ lstrlen(DriveMap.szMapping)-1 ] = TEXT('\0');
584 size_t iDrive = DriveMap.chDrive - chDRIVE_A;
585 memcpy (&pList->aDriveMap[ iDrive ], &DriveMap, sizeof(DRIVEMAP));
589 RegCloseKey(hkMappings);
592 BOOL ForceMapActive (TCHAR chDrive)
597 szDrive[0] = chDrive;
600 DWORD len = sizeof(szActive);
601 ReadRegistryString( HKEY_CURRENT_USER, cszSECTION_ACTIVE, szDrive, szActive, &len);
603 if ( !lstrcmp(szActive,"1") || !lstrcmpi(szActive,"true") || !lstrcmpi(szActive,"on") || !lstrcmpi(szActive,"yes") )
609 void WriteActiveMap (TCHAR chDrive, BOOL on)
613 szDrive[0] = chDrive;
616 WriteRegistryString(HKEY_CURRENT_USER, cszSECTION_ACTIVE, szDrive, on ? "1" : "0");
619 void QueryDriveMapList_WriteMappings (PDRIVEMAPLIST pList)
621 WriteDriveMappings (pList);
625 void WriteDriveMappings (PDRIVEMAPLIST pList)
628 RegCreateKeyEx( HKEY_CURRENT_USER,
632 REG_OPTION_NON_VOLATILE,
633 KEY_READ|KEY_QUERY_VALUE|KEY_WRITE,
639 RegQueryInfoKey( hkMappings,
642 NULL, /* lpReserved */
643 NULL, /* lpcSubKeys */
644 NULL, /* lpcMaxSubKeyLen */
645 NULL, /* lpcMaxClassLen */
646 &dwMappings, /* lpcValues */
647 NULL, /* lpcMaxValueNameLen */
648 NULL, /* lpcMaxValueLen */
649 NULL, /* lpcbSecurityDescriptor */
650 NULL /* lpftLastWriteTime */
653 if ( dwMappings > 0 ) {
654 for ( long dwIndex = dwMappings - 1; dwIndex >= 0; dwIndex-- ) {
655 TCHAR drive[MAX_PATH];
656 DWORD driveLen = MAX_PATH;
658 RegEnumValue( hkMappings, dwIndex, drive, &driveLen, NULL, NULL, NULL, NULL);
659 RegDeleteValue( hkMappings, drive );
663 for (size_t iDrive = 0; iDrive < 26; ++iDrive)
665 if (pList->aDriveMap[iDrive].szMapping[0] != TEXT('\0'))
667 TCHAR szLHS[] = TEXT("*");
668 szLHS[0] = pList->aDriveMap[iDrive].chDrive;
670 TCHAR szRHS[MAX_PATH];
671 AdjustAfsPath (szRHS, pList->aDriveMap[iDrive].szMapping, TRUE, TRUE);
672 if (!pList->aDriveMap[iDrive].fPersistent)
673 lstrcat (szRHS, TEXT("*"));
675 RegSetValueEx( hkMappings, szLHS, 0, REG_EXPAND_SZ, (const BYTE *)szRHS, lstrlen(szRHS) + 1);
678 RegCloseKey( hkMappings );
681 BOOL DriveIsGlobalAfsDrive(TCHAR chDrive)
683 TCHAR szKeyName[128];
684 TCHAR szValueName[128];
688 _stprintf(szKeyName, TEXT("%s\\GlobalAutoMapper"), AFSREG_CLT_SVC_PARAM_SUBKEY);
690 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
693 _stprintf(szValueName, TEXT("%c:"), chDrive);
695 DWORD dwSize = sizeof(szValue);
696 BOOL bIsGlobal = (RegQueryValueEx (hKey, szValueName, NULL, NULL, (PBYTE)szValue, &dwSize) == ERROR_SUCCESS);
704 void QueryDriveMapList_FindNetworkDrives (PDRIVEMAPLIST pList, BOOL *pfFoundNew)
706 for (TCHAR chDrive = chDRIVE_A; chDrive <= chDRIVE_Z; ++chDrive)
708 TCHAR szSubmount[ MAX_PATH ];
709 if (!GetDriveSubmount (chDrive, szSubmount))
712 // We've got a mapping! Drive {chDrive} is mapped to submount
713 // {szSubmount}. See if that submount makes sense.
717 size_t iDrive = chDrive - chDRIVE_A;
718 if (pList->aDriveMap[ iDrive ].szMapping[0] != TEXT('\0'))
720 pList->aDriveMap[ iDrive ].fActive = TRUE;
721 lstrcpy (pList->aDriveMap[ iDrive ].szSubmount, szSubmount);
725 else // (IsWindowsNT())
727 TCHAR szAfsPath[ MAX_PATH ];
728 if (!SubmountToPath (pList, szAfsPath, szSubmount, TRUE))
731 // Okay, we know that drive {chDrive} is mapped to afs path {szAfsPath}.
732 // If this drive is a global afs drive, then reject it. Otherwise, look
733 // at pList->aDriveMap, to see if this drive mapping is already in our
734 // list. If not, add it and set pfFoundNew.
736 if (DriveIsGlobalAfsDrive(chDrive))
739 size_t iDrive = chDrive - chDRIVE_A;
740 if (lstrcmpi (pList->aDriveMap[ iDrive ].szMapping, szAfsPath))
743 pList->aDriveMap[ iDrive ].fPersistent = TRUE;
745 pList->aDriveMap[ iDrive ].fActive = TRUE;
746 pList->aDriveMap[ iDrive ].chDrive = chDrive;
747 lstrcpy (pList->aDriveMap[ iDrive ].szSubmount, szSubmount);
748 AdjustAfsPath (pList->aDriveMap[ iDrive ].szMapping, szAfsPath, TRUE, TRUE);
754 void QueryDriveMapList (PDRIVEMAPLIST pList)
756 // Initialize the data structure
758 memset (pList, 0x00, sizeof(DRIVEMAPLIST));
759 for (size_t ii = 0; ii < 26; ++ii)
760 pList->aDriveMap[ii].chDrive = chDRIVE_A + ii;
762 // Read the current lists of submounts and drive letter mappings
764 QueryDriveMapList_ReadSubmounts (pList);
765 QueryDriveMapList_ReadMappings (pList);
767 // Look through the current list of network drives, and see if
768 // any are currently mapped to AFS. If we find any which are mapped
769 // into AFS unexpectedly, we'll have to rewrite the mappings list.
771 BOOL fFoundNew = FALSE;
772 QueryDriveMapList_FindNetworkDrives (pList, &fFoundNew);
776 QueryDriveMapList_WriteMappings (pList);
781 void FreeDriveMapList (PDRIVEMAPLIST pList)
783 if (pList->aSubmounts)
784 Free (pList->aSubmounts);
785 memset (pList, 0x00, sizeof(DRIVEMAPLIST));
790 BOOL PathToSubmount (LPTSTR pszSubmount, LPTSTR pszMapping, LPTSTR pszSubmountReq, ULONG *pStatus)
792 // pszSubmount is MAX_PATH in length
794 if (pszSubmountReq && !IsValidSubmountName (pszSubmountReq))
795 pszSubmountReq = NULL;
797 TCHAR szAfsPath[ MAX_PATH ];
798 AdjustAfsPath (szAfsPath, pszMapping, TRUE, TRUE);
800 // Try to ask AFSD for a new submount name.
802 if (!fCanIssuePIOCTL())
805 BYTE InData[ PIOCTL_MAXSIZE ];
806 memset (InData, 0x00, sizeof(InData));
808 LPTSTR pszInData = (LPTSTR)InData;
809 lstrcpy (pszInData, pszMapping);
810 pszInData += 1+lstrlen(pszInData);
812 lstrcpy (pszInData, pszSubmountReq);
814 BYTE OutData[ PIOCTL_MAXSIZE ];
815 memset (OutData, 0x00, sizeof(OutData));
817 struct ViceIoctl IOInfo;
818 IOInfo.in = (char *)InData;
819 IOInfo.in_size = PIOCTL_MAXSIZE;
820 IOInfo.out = (char *)OutData;
821 IOInfo.out_size = PIOCTL_MAXSIZE;
823 ULONG status = pioctl (0, VIOC_MAKESUBMOUNT, &IOInfo, 1);
831 OutData[min(PIOCTL_MAXSIZE, MAX_PATH) - 1] = '\0';
832 lstrcpy (pszSubmount, (LPCTSTR)OutData);
833 return (pszSubmount[0] != TEXT('\0')) ? TRUE : FALSE;
837 BOOL ActivateDriveMap (TCHAR chDrive, LPTSTR pszMapping, LPTSTR pszSubmountReq, BOOL fPersistent, DWORD *pdwStatus)
839 // We can only map drives to places in AFS using this function.
841 if ( (lstrncmpi (pszMapping, cm_slash_mount_root, lstrlen(cm_slash_mount_root))) &&
842 (lstrncmpi (pszMapping, cm_back_slash_mount_root, lstrlen(cm_back_slash_mount_root))) )
845 *pdwStatus = ERROR_BAD_NETPATH;
849 // First we have to translate {pszMapping} into a submount, and if there is
850 // no current submount associated with this path, we'll have to make one.
853 TCHAR szSubmount[ MAX_PATH ];
854 if (!PathToSubmount (szSubmount, pszMapping, pszSubmountReq, &status))
861 // We now have a submount name and drive letter--map the network drive.
864 rc=MountDOSDrive(chDrive,szSubmount,fPersistent,NULL);
866 rc=MountDOSDrive(chDrive,/*szSubmount*/pszMapping,fPersistent,NULL);
877 BOOL InactivateDriveMap (TCHAR chDrive, DWORD *pdwStatus)
879 DWORD rc = DisMountDOSDrive(chDrive, FALSE);
889 void AddSubMount (LPTSTR pszSubmount, LPTSTR pszMapping)
891 TCHAR szRHS[ MAX_PATH ];
892 AdjustAfsPath (szRHS, pszMapping, FALSE, TRUE);
894 lstrcpy (szRHS, TEXT("/"));
896 WriteExpandedRegistryString(HKEY_LOCAL_MACHINE, cszSECTION_SUBMOUNTS, pszSubmount, szRHS);
900 void RemoveSubMount (LPTSTR pszSubmount)
902 DeleteRegistryString(HKEY_LOCAL_MACHINE, cszSECTION_SUBMOUNTS, pszSubmount);
906 void AdjustAfsPath (LPTSTR pszTarget, LPCTSTR pszSource, BOOL fWantAFS, BOOL fWantForwardSlashes)
909 lstrcpy (pszTarget, (fWantAFS) ? cm_slash_mount_root : TEXT(""));
910 else if ((*pszSource != TEXT('/')) && (*pszSource != TEXT('\\')))
911 wsprintf (pszTarget, TEXT("%s/%s"),cm_slash_mount_root, pszSource);
912 // We don't want to strip afs off the start if it is part of something for example afscell.company.com
913 else if (fWantAFS && (lstrncmpi (&pszSource[1], cm_mount_root, strlen(cm_mount_root))) || !((pszSource[strlen(cm_slash_mount_root)] == TEXT('/')) ||
914 (pszSource[strlen(cm_slash_mount_root)] == TEXT('\\')) ||
915 (lstrlen(pszSource) == strlen(cm_slash_mount_root))))
916 wsprintf (pszTarget, TEXT("%s%s"),cm_slash_mount_root, pszSource);
917 else if (!fWantAFS && (!lstrncmpi (&pszSource[1], cm_mount_root, strlen(cm_mount_root)) && ((pszSource[strlen(cm_slash_mount_root)] == TEXT('/')) ||
918 (pszSource[strlen(cm_slash_mount_root)] == TEXT('\\')) ||
919 (lstrlen(pszSource) == strlen(cm_slash_mount_root)))))
920 lstrcpy (pszTarget, &pszSource[strlen(cm_slash_mount_root)]);
922 lstrcpy (pszTarget, pszSource);
924 for (LPTSTR pch = pszTarget; *pch; ++pch)
926 if (fWantForwardSlashes)
928 *pch = (*pch == TEXT('\\')) ? TEXT('/') : (*pch);
930 else // (!fWantForwardSlashes)
932 *pch = (*pch == TEXT('/')) ? TEXT('\\') : (*pch);
936 if (lstrlen(pszTarget) &&
937 ((pszTarget[lstrlen(pszTarget)-1] == TEXT('/')) ||
938 (pszTarget[lstrlen(pszTarget)-1] == TEXT('\\'))))
940 pszTarget[lstrlen(pszTarget)-1] = TEXT('\0');
944 BOOL GetDriveSubmount (TCHAR chDrive, LPTSTR pszSubmountNow)
946 BOOL isWinNT = IsWindowsNT();
948 TCHAR szDrive[] = TEXT("*:");
949 szDrive[0] = chDrive;
951 TCHAR szMapping[ _MAX_PATH ] = TEXT("");
953 if (isWinNT && !QueryDosDevice (szDrive, szMapping, MAX_PATH))
956 LPTSTR pszSubmount = szMapping;
958 TCHAR szNetBiosName[32];
959 memset(szNetBiosName, '\0', sizeof(szNetBiosName));
960 GetClientNetbiosName(szNetBiosName);
961 _tcscat(szNetBiosName, TEXT("\\"));
965 // Now if this is an AFS network drive mapping, {szMapping} will be:
967 // \Device\LanmanRedirector\<Drive>:\<netbiosname>\submount
969 // on Windows NT. On Windows 2000, it will be:
971 // \Device\LanmanRedirector\;<Drive>:0\<netbiosname>\submount
973 // (This is presumably to support multiple drive mappings with
976 // on Windows XP and 2003, it will be :
977 // \Device\LanmanRedirector\;<Drive>:<AuthID>\<netbiosname>\submount
979 // where : <Drive> : DOS drive letter
980 // <AuthID>: Authentication ID, 16 char hex.
981 // <netbiosname>: Netbios name of server
985 b = _tcsnicmp(szMapping, cszLANMANDEVICE, _tcslen(cszLANMANDEVICE));
987 const TCHAR ker_sub_path[] = "\\Device\\afsrdr\\";
988 b = _tcsnicmp(szMapping, ker_sub_path, _tcslen(ker_sub_path));
993 pszSubmount = &szMapping[ _tcslen(cszLANMANDEVICE) ];
995 pszSubmount = &szMapping[ _tcslen(ker_sub_path) ];
999 if (*(pszSubmount) < '0' ||
1000 *(pszSubmount) > '9')
1004 if (IsWindows2000())
1006 if (*(pszSubmount) != TEXT(';'))
1011 if (toupper(*(++pszSubmount)) != chDrive)
1014 if (*(++pszSubmount) != TEXT(':'))
1018 // No longer a safe assumption on XP
1019 if (IsWindows2000())
1020 if (*(++pszSubmount) != TEXT('0'))
1024 // scan for next "\"
1025 while (*(++pszSubmount) != TEXT('\\'))
1027 if (*pszSubmount==0)
1031 // note that szNetBiosName has a '\\' tagged in the end earlier
1032 for (++pszSubmount; *pszSubmount && (*pszSubmount != TEXT('\\')); ++pszSubmount)
1033 if (!_tcsncicmp(pszSubmount, szNetBiosName, _tcslen(szNetBiosName)))
1035 if ((!*pszSubmount) || (*pszSubmount == TEXT('\\')))
1038 pszSubmount += _tcslen(szNetBiosName);
1041 else // (!IsWindowsNT())
1043 DWORD dwSize = MAX_PATH;
1044 if (WNetGetConnection (szDrive, szMapping, &dwSize) != NO_ERROR)
1046 if (*(pszSubmount++) != TEXT('\\'))
1048 if (*(pszSubmount++) != TEXT('\\'))
1050 for ( ; *pszSubmount && (*pszSubmount != TEXT('\\')); ++pszSubmount)
1051 if (!lstrncmpi (pszSubmount, szNetBiosName, lstrlen(szNetBiosName)))
1053 if ((!*pszSubmount) || (*pszSubmount == TEXT('\\')))
1055 pszSubmount += lstrlen(szNetBiosName);
1058 if (!pszSubmount || !*pszSubmount)
1062 lstrcpy (pszSubmountNow, pszSubmount);
1064 lstrcpy (pszSubmountNow, "\\afs");
1065 lstrcat (pszSubmountNow, pszSubmount);
1070 /* Generate Random User name random acording to time*/
1072 TCHAR pUserName[MAXRANDOMNAMELEN]=TEXT("");
1073 BOOL fUserName=FALSE;
1074 #define AFSLogonOptionName TEXT(AFSREG_CLT_SVC_PROVIDER_SUBKEY)
1076 void SetBitLogonOption(BOOL set,DWORD value)
1079 RWLogonOption(FALSE,((set)?value | RWLogonOption(TRUE,0):RWLogonOption(TRUE,0) & ~value) );
1082 DWORD RWLogonOption(BOOL read,DWORD value)
1084 // if read is true then if value==0 return registry value
1085 // if read and value!=0 then use value to test registry, return TRUE if value bits match value read
1088 DWORD LSPtype, LSPsize;
1094 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSLogonOptionName, 0, KEY_QUERY_VALUE, &hk)==ERROR_SUCCESS)
1096 LSPsize=sizeof(rval);
1097 RegQueryValueEx(hk, "LogonOptions", NULL,
1098 &LSPtype, (LPBYTE)&rval, &LSPsize);
1101 return (value==0)?rval:((rval & value)==value);
1103 if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, AFSLogonOptionName, 0, NULL, 0, KEY_SET_VALUE, NULL, &hk, &dwDisp) == ERROR_SUCCESS)
1105 RegSetValueEx(hk,TEXT("LogonOptions"),NULL,REG_DWORD,(LPBYTE)&value,sizeof(value));
1112 void MapShareName(char *pszCmdLineA)
1117 while (*pszCmdLineA && (*pszCmdLineA != ' '))
1119 *p++=*pszCmdLineA++;
1123 void GenRandomName(TCHAR *pname,int len)
1126 { //user name was passed through command line, use once
1130 srand( (unsigned)time( NULL ) );
1131 for (int i=0;i<len;i++)
1132 pname[i]='a'+(rand() % 26);
1138 Make a connection using users name
1139 if fUserName then force a connection
1142 BOOL TestAndDoMapShare(DWORD dwState)
1144 if ((dwState!=SERVICE_RUNNING) || (dwOldState!=SERVICE_START_PENDING))
1149 dwOldState=SERVICE_RUNNING;
1150 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1151 return (DoMapShare() && GlobalMountDrive());
1152 return GlobalMountDrive();
1155 BOOL IsServiceActive()
1158 SERVICE_STATUS Status;
1159 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
1162 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
1164 QueryServiceStatus (hService, &Status);
1165 CloseServiceHandle (hService);
1168 CloseServiceHandle (hManager);
1171 return (Status.dwCurrentState == SERVICE_RUNNING) ? TRUE : FALSE;
1174 void TestAndDoUnMapShare()
1176 if (!RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1178 DoUnMapShare(FALSE);
1181 void DoUnMapShare(BOOL drivemap) //disconnect drivemap
1183 TCHAR szMachine[MAX_PATH],szPath[MAX_PATH];
1186 LPNETRESOURCE lpnrLocal,lpnr=NULL;
1188 DWORD cbBuffer=16384;
1192 memset(szMachine, '\0', sizeof(szMachine));
1193 GetClientNetbiosName(szMachine);
1195 // Initialize the data structure
1196 if ((res=WNetOpenEnum(RESOURCE_CONNECTED,RESOURCETYPE_DISK,RESOURCEUSAGE_CONNECTABLE,lpnr,&hEnum))!=NO_ERROR)
1198 sprintf(szPath,"\\\\%s\\",szMachine);
1200 lpnrLocal=(LPNETRESOURCE) GlobalAlloc(GPTR,cbBuffer);
1202 memset(lpnrLocal,0,cbBuffer);
1203 if ((res = WNetEnumResource(hEnum,&cEntries,lpnrLocal,&cbBuffer))==NO_ERROR)
1205 for (DWORD i=0;i<cEntries;i++)
1207 if (strstr(_strlwr(lpnrLocal[i].lpRemoteName),szPath))
1209 if ((lpnrLocal[i].lpLocalName) && (strlen(lpnrLocal[i].lpLocalName)>0))
1212 DisMountDOSDrive(*lpnrLocal[i].lpLocalName);
1213 DEBUG_EVENT1("AFS DriveUnMap","UnMap-Local=%x",res);
1216 DisMountDOSDriveFull(lpnrLocal[i].lpRemoteName);
1217 DEBUG_EVENT1("AFS DriveUnMap","UnMap-Remote=%x",res);
1222 } while (res!=ERROR_NO_MORE_ITEMS);
1223 GlobalFree((HGLOBAL)lpnrLocal);
1224 WNetCloseEnum(hEnum);
1227 BOOL DoMapShareChange(BOOL removeUnknown)
1230 TCHAR szMachine[ MAX_PATH],szPath[MAX_PATH];
1233 LPNETRESOURCE lpnrLocal,lpnr=NULL;
1236 DWORD cbBuffer=16384;
1238 memset(szMachine, '\0', sizeof(szMachine));
1239 GetClientNetbiosName(szMachine);
1241 // Initialize the data structure
1242 if (!IsServiceActive())
1244 memset (&List, 0x00, sizeof(DRIVEMAPLIST));
1245 for (size_t ii = 0; ii < 26; ++ii)
1246 List.aDriveMap[ii].chDrive = chDRIVE_A + ii;
1247 QueryDriveMapList_ReadSubmounts (&List);
1248 if ((res=WNetOpenEnum(RESOURCE_CONNECTED,RESOURCETYPE_DISK,RESOURCEUSAGE_CONNECTABLE,lpnr,&hEnum))!=NO_ERROR)
1250 lpnrLocal=(LPNETRESOURCE) GlobalAlloc(GPTR,cbBuffer);
1251 sprintf(szPath,"\\\\%s\\",szMachine);
1254 memset(lpnrLocal,0,cbBuffer);
1255 if ((res = WNetEnumResource(hEnum,&cEntries,lpnrLocal,&cbBuffer))==NO_ERROR)
1257 for (DWORD i=0;i<cEntries;i++)
1259 if (strstr(_strlwr(lpnrLocal[i].lpRemoteName),szPath)==NULL)
1260 continue; //only look at real afs mappings
1261 CHAR * pSubmount=strrchr(lpnrLocal[i].lpRemoteName,'\\')+1;
1262 if (lstrcmpi(pSubmount,"all")==0)
1263 continue; // do not remove 'all'
1264 for (DWORD j=0;j<List.cSubmounts;j++)
1266 if ((List.aSubmounts[j].szSubmount[0]) &&
1267 (lstrcmpi(List.aSubmounts[j].szSubmount,pSubmount)==0)
1270 List.aSubmounts[j].fInUse=TRUE;
1274 // wasn't on list so lets remove
1275 DisMountDOSDrive(pSubmount);
1279 } while (res!=ERROR_NO_MORE_ITEMS);
1280 GlobalFree((HGLOBAL)lpnrLocal);
1281 WNetCloseEnum(hEnum);
1282 sprintf(szPath,"\\\\%s\\all",szMachine);
1284 // Lets connect all submounts that weren't connectd
1285 DWORD cbUser=MAXRANDOMNAMELEN-1;
1286 CHAR szUser[MAXRANDOMNAMELEN];
1287 CHAR * pUser = NULL;
1288 if (WNetGetUser(szPath,(LPSTR)szUser,&cbUser)!=NO_ERROR) {
1289 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY)) {
1290 if (!pUserName[0]) {
1291 GenRandomName(szUser,MAXRANDOMNAMELEN-1);
1298 if ((pUser=strchr(szUser,'\\'))!=NULL)
1302 for (DWORD j=0;j<List.cSubmounts;j++)
1304 if (List.aSubmounts[j].fInUse)
1306 DWORD res=MountDOSDrive(0,List.aSubmounts[j].szSubmount,FALSE,pUser);
1315 BOOL bMappedAll=FALSE;
1317 // Initialize the data structure
1318 DEBUG_EVENT0("AFS DoMapShare");
1319 QueryDriveMapList (&List);
1321 // All connections have been removed
1322 // Lets restore them after making the connection from the random name
1324 TCHAR szMachine[ MAX_PATH],szPath[MAX_PATH];
1325 memset(szMachine, '\0', sizeof(szMachine));
1326 GetClientNetbiosName(szMachine);
1327 sprintf(szPath,"\\\\%s\\all",szMachine);
1329 // Lets connect all submounts that weren't connectd
1330 DWORD cbUser=MAXRANDOMNAMELEN-1;
1331 CHAR szUser[MAXRANDOMNAMELEN];
1332 CHAR * pUser = NULL;
1333 if (WNetGetUser(szPath,(LPSTR)szUser,&cbUser)!=NO_ERROR) {
1334 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY)) {
1335 if (!pUserName[0]) {
1336 GenRandomName(szUser,MAXRANDOMNAMELEN-1);
1343 if ((pUser=strchr(szUser,'\\'))!=NULL)
1347 for (DWORD i=0;i<List.cSubmounts;i++)
1349 if (List.aSubmounts[i].szSubmount[0])
1351 DWORD res=MountDOSDrive(0,List.aSubmounts[i].szSubmount,FALSE,pUser);
1352 if (lstrcmpi("all",List.aSubmounts[i].szSubmount)==0)
1356 if (!bMappedAll) //make sure all is mapped also
1358 DWORD res=MountDOSDrive(0,"all",FALSE,pUser);
1359 if (res==ERROR_SESSION_CREDENTIAL_CONFLICT)
1361 DisMountDOSDrive("all");
1362 MountDOSDrive(0,"all",FALSE,pUser);
1365 for (TCHAR chDrive = chDRIVE_A; chDrive <= chDRIVE_Z; ++chDrive)
1367 if (List.aDriveMap[chDrive-chDRIVE_A].fActive ||
1368 ForceMapActive(chDrive))
1370 TCHAR szSubmount[ MAX_PATH ];
1371 if (List.aDriveMap[chDrive-chDRIVE_A].szSubmount[0])
1372 lstrcpy(szSubmount,List.aDriveMap[chDrive-chDRIVE_A].szSubmount);
1373 else if (!PathToSubmount (szSubmount, List.aDriveMap[chDrive-chDRIVE_A].szMapping, NULL, NULL))
1376 BOOL fPersistent = List.aDriveMap[chDrive-chDRIVE_A].fPersistent;
1377 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1378 fPersistent = FALSE;
1379 DWORD res=MountDOSDrive(chDrive
1381 ,fPersistent,pUser);
1387 BOOL GlobalMountDrive()
1389 char szDriveToMapTo[5];
1391 char szKeyName[256];
1395 DWORD dwSubMountSize;
1396 char unsigned szSubMount[256];
1397 char cm_HostName[200];
1398 DWORD dwType=sizeof(cm_HostName);
1399 if (!IsServiceActive())
1401 if (!GetComputerName(cm_HostName, &dwType))
1403 sprintf(szKeyName, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY);
1405 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE,
1407 if (dwResult != ERROR_SUCCESS)
1411 dwDriveSize = sizeof(szDriveToMapTo);
1412 dwSubMountSize = sizeof(szSubMount);
1413 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize,
1414 0, &dwType, szSubMount, &dwSubMountSize);
1415 if (dwResult != ERROR_MORE_DATA) {
1416 if (dwResult != ERROR_SUCCESS) {
1417 if (dwResult != ERROR_NO_MORE_ITEMS)
1419 DEBUG_EVENT1("AFS DriveMap","Failed to read GlobalAutoMapper values: %d",dwResult);
1424 dwResult=MountDOSDrive(*szDriveToMapTo,(const char *)szSubMount,FALSE,NULL);
1430 DWORD MountDOSDrive(char chDrive,const char *szSubmount,BOOL bPersistent,const char * pUsername)
1435 TCHAR szTokens[MAX_PATH], *tok;
1437 TCHAR szPath[MAX_PATH];
1438 TCHAR szClient[MAX_PATH];
1439 TCHAR szDrive[3] = TEXT("?:");
1442 int pathCount, currPos, lastPos, x;
1447 strcpy(szTokens, szSubmount);
1448 tok = strtok(szTokens, "/\\");
1452 if (pathCount || stricmp(tok, "afs"))
1454 strcat(szPath, "\\");
1455 strcat(szPath, tok);
1458 tok = strtok(NULL, "/\\");
1461 sprintf(szDrive,"%c:",chDrive);
1462 strcpy(szTokens, szPath);
1463 sprintf(szPath,"\\Device\\afsrdr\\%d%s",pathCount,szTokens);
1464 //succ = DefineDosDevice(DDD_RAW_TARGET_PATH, "J:", "\\Device\\afsrdr\\2\\ericjw\\test");
1465 succ = DefineDosDevice(DDD_RAW_TARGET_PATH, szDrive, szPath);
1466 err = GetLastError();
1468 return succ ? NO_ERROR : ERROR_DEVICE_IN_USE;
1470 sprintf(szDrive,"%c:",chDrive);
1471 GetClientNetbiosName (szClient);
1472 sprintf(szPath,"\\\\%s\\%s",szClient,szSubmount);
1474 memset (&nr, 0x00, sizeof(NETRESOURCE));
1475 nr.dwType=RESOURCETYPE_DISK;
1476 nr.lpLocalName=szDrive;
1477 nr.lpRemoteName=szPath;
1478 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; /* ignored parameter */
1479 DWORD res=WNetAddConnection2(&nr,NULL,pUsername,(bPersistent)?CONNECT_UPDATE_PROFILE:0);
1480 DEBUG_EVENT5("AFS DriveMap","Mount %s Local[%s] Remote[%s] User[%s]=%x",
1481 (bPersistent)?"Persistant" : "NonPresistant",
1482 szDrive,szPath,pUsername?pUsername:"NULL",res);
1487 DWORD DisMountDOSDriveFull(const char *szPath,BOOL bForce)
1490 DWORD res=WNetCancelConnection(szPath,bForce);
1493 res = ERROR_DEVICE_IN_USE;
1494 // must handle drive letters and afs paths
1495 // DDD_REMOVE_DEFINITION
1497 DEBUG_EVENT3("AFS DriveMap","%sDismount Remote[%s]=%x",
1498 bForce ? "Forced " : "",szPath,res);
1499 return (res==ERROR_NOT_CONNECTED)?NO_ERROR:res;
1502 DWORD DisMountDOSDrive(const char *pSubmount,BOOL bForce)
1504 TCHAR szPath[MAX_PATH];
1505 TCHAR szClient[MAX_PATH];
1506 GetClientNetbiosName (szClient);
1507 sprintf(szPath,"\\\\%s\\%s",szClient,pSubmount);
1508 return DisMountDOSDriveFull(szPath,bForce);
1512 DWORD DisMountDOSDrive(const char chDrive,BOOL bForce)
1514 TCHAR szPath[MAX_PATH];
1518 sprintf(szPath,"%c:",chDrive);
1520 succ = DefineDosDevice(DDD_REMOVE_DEFINITION, szPath, NULL);
1521 return (!succ) ? GetLastError() : 0;
1523 return DisMountDOSDriveFull(szPath,bForce);