2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 #include <afs/param.h>
14 #include <afs/fs_utils.h>
19 #include <WINNT/TaLocale.h>
28 #include <lanahelper.h>
30 extern void Config_GetLanAdapter (ULONG *pnLanAdapter);
33 * REGISTRY ___________________________________________________________________
37 #undef AFSConfigKeyName
38 const TCHAR sAFSConfigKeyName[] = TEXT("SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters");
42 * PROFILE SECTIONS ___________________________________________________________
46 #define cREALLOC_SUBMOUNTS 4
48 static TCHAR cszSECTION_SUBMOUNTS[] = TEXT("SOFTWARE\\OpenAFS\\Client\\Submounts");
49 static TCHAR cszSECTION_MAPPINGS[] = TEXT("SOFTWARE\\OpenAFS\\Client\\Mappings");
50 static TCHAR cszSECTION_ACTIVE[] = TEXT("SOFTWARE\\OpenAFS\\Client\\Active Maps");
52 static TCHAR cszAUTOSUBMOUNT[] = TEXT("Auto");
53 static TCHAR cszLANMANDEVICE[] = TEXT("\\Device\\LanmanRedirector\\");
57 WriteRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs, LPTSTR rhs)
64 REG_OPTION_NON_VOLATILE,
70 DWORD status = RegSetValueEx( hkSub, lhs, 0, REG_SZ, (const BYTE *)rhs, strlen(rhs)+1 );
75 return (status == ERROR_SUCCESS);
79 ReadRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs, LPTSTR rhs, DWORD * size)
86 REG_OPTION_NON_VOLATILE,
93 DWORD status = RegQueryValueEx( hkSub, lhs, 0, &dwType, (LPBYTE)rhs, size );
98 return (status == ERROR_SUCCESS);
102 DeleteRegistryString(HKEY key, TCHAR * subkey, LPTSTR lhs)
109 REG_OPTION_NON_VOLATILE,
116 DWORD status = RegDeleteValue( hkSub, lhs );
119 RegCloseKey( hkSub );
121 return (status == ERROR_SUCCESS);
125 * STRINGS ____________________________________________________________________
129 static LPTSTR AllocateStringMemory (size_t cch)
131 LPTSTR psz = (LPTSTR)Allocate (sizeof(TCHAR) * (cch+1));
132 memset (psz, 0x00, sizeof(TCHAR) * (cch+1));
136 static void FreeStringMemory (LPTSTR pszString)
141 static int lstrncmpi (LPCTSTR pszA, LPCTSTR pszB, size_t cch)
145 return (!pszB) - (!pszA); // A,!B:1, !A,B:-1, !A,!B:0
148 for ( ; cch > 0; cch--, pszA = CharNext(pszA), pszB = CharNext(pszB))
150 TCHAR chA = toupper( *pszA );
151 TCHAR chB = toupper( *pszB );
154 return (!chB) - (!chA); // A,!B:1, !A,B:-1, !A,!B:0
157 return (int)(chA) - (int)(chB); // -1:A<B, 0:A==B, 1:A>B
160 return 0; // no differences before told to stop comparing, so A==B
165 * REALLOC ____________________________________________________________________
170 #define REALLOC(_a,_c,_r,_i) DriveMapReallocFunction ((LPVOID*)&_a,sizeof(*_a),&_c,_r,_i)
171 BOOL DriveMapReallocFunction (LPVOID *ppTarget, size_t cbElement, size_t *pcTarget, size_t cReq, size_t cInc)
176 if (cReq <= *pcTarget)
179 if ((cNew = cInc * ((cReq + cInc-1) / cInc)) <= 0)
182 if ((pNew = Allocate (cbElement * cNew)) == NULL)
184 memset (pNew, 0x00, cbElement * cNew);
188 memcpy (pNew, *ppTarget, cbElement * (*pcTarget));
200 * WINDOWS NT STUFF ___________________________________________________________
204 static BOOL IsWindowsNT (void)
206 static BOOL fChecked = FALSE;
207 static BOOL fIsWinNT = FALSE;
213 OSVERSIONINFO Version;
214 memset (&Version, 0x00, sizeof(Version));
215 Version.dwOSVersionInfoSize = sizeof(Version);
217 if (GetVersionEx (&Version))
219 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT)
227 /* Check if the OS is Windows 2000 or higher.
229 BOOL IsWindows2000 (void)
231 static BOOL fChecked = FALSE;
232 static BOOL fIsWin2K = FALSE;
238 OSVERSIONINFO Version;
239 memset (&Version, 0x00, sizeof(Version));
240 Version.dwOSVersionInfoSize = sizeof(Version);
242 if (GetVersionEx (&Version))
244 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT &&
245 Version.dwMajorVersion >= 5)
254 * GENERAL ____________________________________________________________________
258 void GetClientNetbiosName (LPTSTR pszName)
260 static TCHAR szNetbiosName[32] = "";
262 if ( szNetbiosName[0] == 0 ) {
263 lana_GetNetbiosName(szNetbiosName, LANA_NETBIOS_NAME_FULL);
265 _tcscpy(pszName, szNetbiosName);
269 BOOL SubmountToPath (PDRIVEMAPLIST pList, LPTSTR pszPath, LPTSTR pszSubmount, BOOL fMarkInUse)
271 // We can't do this translation unless we're under Windows NT.
276 // \\computer-afs\all always maps to "/afs"
278 if (!lstrcmpi (pszSubmount, TEXT("all")))
280 lstrcpy (pszPath, cm_slash_mount_root);
284 // Otherwise, look up our list of submounts.
286 for (size_t ii = 0; ii < pList->cSubmounts; ++ii)
288 if (!lstrcmpi (pList->aSubmounts[ii].szSubmount, pszSubmount))
291 pList->aSubmounts[ii].fInUse = TRUE;
292 AdjustAfsPath (pszPath, pList->aSubmounts[ii].szMapping, TRUE, TRUE);
301 BOOL IsValidSubmountName (LPTSTR pszSubmount)
305 if (lstrlen (pszSubmount) > 12)
308 for ( ; *pszSubmount; ++pszSubmount)
310 if (!isprint(*pszSubmount))
312 if (*pszSubmount == TEXT(' '))
314 if (*pszSubmount == TEXT('\t'))
323 * PIOCTL SUPPORT _____________________________________________________________
329 #include "../afsd/fs_utils.h"
331 #define __CM_CONFIG_INTERFACES_ONLY__
332 #include "../afsd/cm_config.h"
334 #define __CM_IOCTL_INTERFACES_ONLY__
335 #include "../afsd/cm_ioctl.h"
339 #define PIOCTL_MAXSIZE 2048
342 BOOL fCanIssuePIOCTL (void)
346 TCHAR szGateway[ 256 ] = TEXT("");
347 GetClientNetbiosName (szGateway);
348 return (szGateway[0]) ? TRUE : FALSE;
351 SERVICE_STATUS Status;
352 memset (&Status, 0x00, sizeof(Status));
353 Status.dwCurrentState = SERVICE_STOPPED;
356 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
359 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
361 QueryServiceStatus (hService, &Status);
362 CloseServiceHandle (hService);
365 CloseServiceHandle (hManager);
368 return (Status.dwCurrentState == SERVICE_RUNNING) ? TRUE : FALSE;
373 * QUERYDRIVEMAPLIST __________________________________________________________
377 void QueryDriveMapList_ReadSubmounts (PDRIVEMAPLIST pList)
383 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
384 "SOFTWARE\\OpenAFS\\Client\\Submounts",
387 REG_OPTION_NON_VOLATILE,
388 KEY_READ|KEY_QUERY_VALUE,
394 RegQueryInfoKey( hkSubmounts,
397 NULL, /* lpReserved */
398 NULL, /* lpcSubKeys */
399 NULL, /* lpcMaxSubKeyLen */
400 NULL, /* lpcMaxClassLen */
401 &dwSubmounts, /* lpcValues */
402 NULL, /* lpcMaxValueNameLen */
403 NULL, /* lpcMaxValueLen */
404 NULL, /* lpcbSecurityDescriptor */
405 NULL /* lpftLastWriteTime */
408 for ( DWORD dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) {
409 TCHAR submountPath[MAX_PATH] = "";
410 DWORD submountPathLen = MAX_PATH;
411 TCHAR submountName[MAX_PATH];
412 DWORD submountNameLen = MAX_PATH;
415 RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL,
416 &dwType, (LPBYTE)submountPath, &submountPathLen);
419 memset (&Submount, 0x00, sizeof(SUBMOUNT));
420 lstrcpy (Submount.szSubmount, submountName);
422 if ( submountPath[0] != TEXT('\0') ) {
423 AdjustAfsPath (Submount.szMapping, submountPath, FALSE, TRUE);
425 for (size_t ii = 0; ii < pList->cSubmounts; ++ii)
427 if (!pList->aSubmounts[ii].szSubmount[0])
430 if (REALLOC (pList->aSubmounts, pList->cSubmounts, 1+ii, cREALLOC_SUBMOUNTS))
432 memcpy (&pList->aSubmounts[ii], &Submount, sizeof(SUBMOUNT));
437 RegCloseKey(hkSubmounts);
442 void QueryDriveMapList_ReadMappings (PDRIVEMAPLIST pList)
445 RegCreateKeyEx( HKEY_CURRENT_USER,
446 "SOFTWARE\\OpenAFS\\Client\\Mappings",
449 REG_OPTION_NON_VOLATILE,
450 KEY_READ|KEY_QUERY_VALUE,
456 RegQueryInfoKey( hkMappings,
459 NULL, /* lpReserved */
460 NULL, /* lpcSubKeys */
461 NULL, /* lpcMaxSubKeyLen */
462 NULL, /* lpcMaxClassLen */
463 &dwMappings, /* lpcValues */
464 NULL, /* lpcMaxValueNameLen */
465 NULL, /* lpcMaxValueLen */
466 NULL, /* lpcbSecurityDescriptor */
467 NULL /* lpftLastWriteTime */
470 for ( DWORD dwIndex = 0; dwIndex < dwMappings; dwIndex ++ ) {
471 TCHAR mapping[MAX_PATH] = "";
472 DWORD mappingLen = MAX_PATH;
473 TCHAR drive[MAX_PATH];
474 DWORD driveLen = MAX_PATH;
477 RegEnumValue( hkMappings, dwIndex, drive, &driveLen, NULL,
478 &dwType, (LPBYTE)mapping, &mappingLen);
481 memset (&DriveMap, 0x00, sizeof(DRIVEMAP));
482 DriveMap.chDrive = toupper(*drive);
483 DriveMap.fPersistent = TRUE;
484 if ((DriveMap.chDrive < chDRIVE_A) || (DriveMap.chDrive > chDRIVE_Z))
487 if (mapping[0] != TEXT('\0'))
489 AdjustAfsPath (DriveMap.szMapping, mapping, TRUE, TRUE);
490 if (DriveMap.szMapping[ lstrlen(DriveMap.szMapping)-1 ] == TEXT('*'))
492 DriveMap.fPersistent = FALSE;
493 DriveMap.szMapping[ lstrlen(DriveMap.szMapping)-1 ] = TEXT('\0');
495 size_t iDrive = DriveMap.chDrive - chDRIVE_A;
496 memcpy (&pList->aDriveMap[ iDrive ], &DriveMap, sizeof(DRIVEMAP));
500 RegCloseKey(hkMappings);
503 BOOL ForceMapActive (TCHAR chDrive)
508 szDrive[0] = chDrive;
511 DWORD len = sizeof(szActive);
512 ReadRegistryString( HKEY_CURRENT_USER, cszSECTION_ACTIVE, szDrive, szActive, &len);
514 if ( !lstrcmp(szActive,"1") || !lstrcmpi(szActive,"true") || !lstrcmpi(szActive,"on") || !lstrcmpi(szActive,"yes") )
520 void WriteActiveMap (TCHAR chDrive, BOOL on)
524 szDrive[0] = chDrive;
527 WriteRegistryString(HKEY_CURRENT_USER, cszSECTION_ACTIVE, szDrive, on ? "1" : "0");
530 void QueryDriveMapList_WriteMappings (PDRIVEMAPLIST pList)
532 WriteDriveMappings (pList);
536 void WriteDriveMappings (PDRIVEMAPLIST pList)
539 RegCreateKeyEx( HKEY_CURRENT_USER,
540 "SOFTWARE\\OpenAFS\\Client\\Mappings",
543 REG_OPTION_NON_VOLATILE,
544 KEY_READ|KEY_QUERY_VALUE|KEY_WRITE,
550 RegQueryInfoKey( hkMappings,
553 NULL, /* lpReserved */
554 NULL, /* lpcSubKeys */
555 NULL, /* lpcMaxSubKeyLen */
556 NULL, /* lpcMaxClassLen */
557 &dwMappings, /* lpcValues */
558 NULL, /* lpcMaxValueNameLen */
559 NULL, /* lpcMaxValueLen */
560 NULL, /* lpcbSecurityDescriptor */
561 NULL /* lpftLastWriteTime */
564 if ( dwMappings > 0 ) {
565 for ( long dwIndex = dwMappings - 1; dwIndex >= 0; dwIndex-- ) {
566 TCHAR drive[MAX_PATH];
567 DWORD driveLen = MAX_PATH;
569 RegEnumValue( hkMappings, dwIndex, drive, &driveLen, NULL, NULL, NULL, NULL);
570 RegDeleteValue( hkMappings, drive );
574 for (size_t iDrive = 0; iDrive < 26; ++iDrive)
576 if (pList->aDriveMap[iDrive].szMapping[0] != TEXT('\0'))
578 TCHAR szLHS[] = TEXT("*");
579 szLHS[0] = pList->aDriveMap[iDrive].chDrive;
581 TCHAR szRHS[MAX_PATH];
582 AdjustAfsPath (szRHS, pList->aDriveMap[iDrive].szMapping, TRUE, TRUE);
583 if (!pList->aDriveMap[iDrive].fPersistent)
584 lstrcat (szRHS, TEXT("*"));
586 RegSetValueEx( hkMappings, szLHS, 0, REG_SZ, (const BYTE *)szRHS, lstrlen(szRHS) + 1);
589 RegCloseKey( hkMappings );
592 BOOL DriveIsGlobalAfsDrive(TCHAR chDrive)
594 TCHAR szKeyName[128];
595 TCHAR szValueName[128];
599 _stprintf(szKeyName, TEXT("%s\\GlobalAutoMapper"), sAFSConfigKeyName);
601 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
604 _stprintf(szValueName, TEXT("%c:"), chDrive);
606 DWORD dwSize = sizeof(szValue);
607 BOOL bIsGlobal = (RegQueryValueEx (hKey, szValueName, NULL, NULL, (PBYTE)szValue, &dwSize) == ERROR_SUCCESS);
615 void QueryDriveMapList_FindNetworkDrives (PDRIVEMAPLIST pList, BOOL *pfFoundNew)
617 for (TCHAR chDrive = chDRIVE_A; chDrive <= chDRIVE_Z; ++chDrive)
619 TCHAR szSubmount[ MAX_PATH ];
620 if (!GetDriveSubmount (chDrive, szSubmount))
623 // We've got a mapping! Drive {chDrive} is mapped to submount
624 // {szSubmount}. See if that submount makes sense.
628 size_t iDrive = chDrive - chDRIVE_A;
629 if (pList->aDriveMap[ iDrive ].szMapping[0] != TEXT('\0'))
631 pList->aDriveMap[ iDrive ].fActive = TRUE;
632 lstrcpy (pList->aDriveMap[ iDrive ].szSubmount, szSubmount);
636 else // (IsWindowsNT())
638 TCHAR szAfsPath[ MAX_PATH ];
639 if (!SubmountToPath (pList, szAfsPath, szSubmount, TRUE))
642 // Okay, we know that drive {chDrive} is mapped to afs path {szAfsPath}.
643 // If this drive is a global afs drive, then reject it. Otherwise, look
644 // at pList->aDriveMap, to see if this drive mapping is already in our
645 // list. If not, add it and set pfFoundNew.
647 if (DriveIsGlobalAfsDrive(chDrive))
650 size_t iDrive = chDrive - chDRIVE_A;
651 if (lstrcmpi (pList->aDriveMap[ iDrive ].szMapping, szAfsPath))
654 pList->aDriveMap[ iDrive ].fPersistent = TRUE;
656 pList->aDriveMap[ iDrive ].fActive = TRUE;
657 pList->aDriveMap[ iDrive ].chDrive = chDrive;
658 lstrcpy (pList->aDriveMap[ iDrive ].szSubmount, szSubmount);
659 AdjustAfsPath (pList->aDriveMap[ iDrive ].szMapping, szAfsPath, TRUE, TRUE);
665 void QueryDriveMapList (PDRIVEMAPLIST pList)
667 // Initialize the data structure
669 memset (pList, 0x00, sizeof(DRIVEMAPLIST));
670 for (size_t ii = 0; ii < 26; ++ii)
671 pList->aDriveMap[ii].chDrive = chDRIVE_A + ii;
673 // Read the current lists of submounts and drive letter mappings
675 QueryDriveMapList_ReadSubmounts (pList);
676 QueryDriveMapList_ReadMappings (pList);
678 // Look through the current list of network drives, and see if
679 // any are currently mapped to AFS. If we find any which are mapped
680 // into AFS unexpectedly, we'll have to rewrite the mappings list.
682 BOOL fFoundNew = FALSE;
683 QueryDriveMapList_FindNetworkDrives (pList, &fFoundNew);
687 QueryDriveMapList_WriteMappings (pList);
692 void FreeDriveMapList (PDRIVEMAPLIST pList)
694 if (pList->aSubmounts)
695 Free (pList->aSubmounts);
696 memset (pList, 0x00, sizeof(DRIVEMAPLIST));
700 BOOL PathToSubmount (LPTSTR pszSubmount, LPTSTR pszMapping, LPTSTR pszSubmountReq, ULONG *pStatus)
702 if (pszSubmountReq && !IsValidSubmountName (pszSubmountReq))
703 pszSubmountReq = NULL;
705 TCHAR szAfsPath[ MAX_PATH ];
706 AdjustAfsPath (szAfsPath, pszMapping, TRUE, TRUE);
708 // Try to ask AFSD for a new submount name.
710 if (!fCanIssuePIOCTL())
713 BYTE InData[ PIOCTL_MAXSIZE ];
714 memset (InData, 0x00, sizeof(InData));
716 LPTSTR pszInData = (LPTSTR)InData;
717 lstrcpy (pszInData, pszMapping);
718 pszInData += 1+lstrlen(pszInData);
720 lstrcpy (pszInData, pszSubmountReq);
722 BYTE OutData[ PIOCTL_MAXSIZE ];
723 memset (OutData, 0x00, sizeof(OutData));
725 struct ViceIoctl IOInfo;
726 IOInfo.in = (char *)InData;
727 IOInfo.in_size = PIOCTL_MAXSIZE;
728 IOInfo.out = (char *)OutData;
729 IOInfo.out_size = PIOCTL_MAXSIZE;
731 ULONG status = pioctl (0, VIOC_MAKESUBMOUNT, &IOInfo, 1);
738 lstrcpy (pszSubmount, (LPCTSTR)OutData);
739 return (pszSubmount[0] != TEXT('\0')) ? TRUE : FALSE;
743 BOOL ActivateDriveMap (TCHAR chDrive, LPTSTR pszMapping, LPTSTR pszSubmountReq, BOOL fPersistent, DWORD *pdwStatus)
745 // We can only map drives to places in AFS using this function.
747 if ( (lstrncmpi (pszMapping, cm_slash_mount_root, lstrlen(cm_slash_mount_root))) &&
748 (lstrncmpi (pszMapping, cm_back_slash_mount_root, lstrlen(cm_back_slash_mount_root))) )
751 *pdwStatus = ERROR_BAD_NETPATH;
755 // First we have to translate {pszMapping} into a submount, and if there is
756 // no current submount associated with this path, we'll have to make one.
759 TCHAR szSubmount[ MAX_PATH ];
760 if (!PathToSubmount (szSubmount, pszMapping, pszSubmountReq, &status))
767 // We now have a submount name and drive letter--map the network drive.
768 DWORD rc=MountDOSDrive(chDrive,szSubmount,fPersistent,NULL);
778 BOOL InactivateDriveMap (TCHAR chDrive, DWORD *pdwStatus)
780 DWORD rc = DisMountDOSDrive(chDrive, FALSE);
790 void AddSubMount (LPTSTR pszSubmount, LPTSTR pszMapping)
792 TCHAR szRHS[ MAX_PATH ];
793 AdjustAfsPath (szRHS, pszMapping, FALSE, TRUE);
795 lstrcpy (szRHS, TEXT("/"));
797 WriteRegistryString(HKEY_LOCAL_MACHINE, cszSECTION_SUBMOUNTS, pszSubmount, szRHS);
801 void RemoveSubMount (LPTSTR pszSubmount)
803 DeleteRegistryString(HKEY_LOCAL_MACHINE, cszSECTION_SUBMOUNTS, pszSubmount);
807 void AdjustAfsPath (LPTSTR pszTarget, LPCTSTR pszSource, BOOL fWantAFS, BOOL fWantForwardSlashes)
810 lstrcpy (pszTarget, (fWantAFS) ? cm_slash_mount_root : TEXT(""));
811 else if ((*pszSource != TEXT('/')) && (*pszSource != TEXT('\\')))
812 wsprintf (pszTarget, TEXT("%s/%s"),cm_slash_mount_root, pszSource);
813 // We don't want to strip afs off the start if it is part of something for example afscell.company.com
814 else if (fWantAFS && (lstrncmpi (&pszSource[1], cm_mount_root, strlen(cm_mount_root))) || !((pszSource[strlen(cm_slash_mount_root)] == TEXT('/')) ||
815 (pszSource[strlen(cm_slash_mount_root)] == TEXT('\\')) ||
816 (lstrlen(pszSource) == strlen(cm_slash_mount_root))))
817 wsprintf (pszTarget, TEXT("%s%s"),cm_slash_mount_root, pszSource);
818 else if (!fWantAFS && (!lstrncmpi (&pszSource[1], cm_mount_root, strlen(cm_mount_root)) && ((pszSource[strlen(cm_slash_mount_root)] == TEXT('/')) ||
819 (pszSource[strlen(cm_slash_mount_root)] == TEXT('\\')) ||
820 (lstrlen(pszSource) == strlen(cm_slash_mount_root)))))
821 lstrcpy (pszTarget, &pszSource[strlen(cm_slash_mount_root)]);
823 lstrcpy (pszTarget, pszSource);
825 for (LPTSTR pch = pszTarget; *pch; ++pch)
827 if (fWantForwardSlashes)
829 *pch = (*pch == TEXT('\\')) ? TEXT('/') : (*pch);
831 else // (!fWantForwardSlashes)
833 *pch = (*pch == TEXT('/')) ? TEXT('\\') : (*pch);
837 if (lstrlen(pszTarget) &&
838 ((pszTarget[lstrlen(pszTarget)-1] == TEXT('/')) ||
839 (pszTarget[lstrlen(pszTarget)-1] == TEXT('\\'))))
841 pszTarget[lstrlen(pszTarget)-1] = TEXT('\0');
845 BOOL GetDriveSubmount (TCHAR chDrive, LPTSTR pszSubmountNow)
847 BOOL isWinNT = IsWindowsNT();
849 TCHAR szDrive[] = TEXT("*:");
850 szDrive[0] = chDrive;
852 TCHAR szMapping[ _MAX_PATH ] = TEXT("");
854 if (isWinNT && !QueryDosDevice (szDrive, szMapping, MAX_PATH))
857 LPTSTR pszSubmount = szMapping;
859 TCHAR szNetBiosName[32];
860 memset(szNetBiosName, '\0', sizeof(szNetBiosName));
861 GetClientNetbiosName(szNetBiosName);
862 _tcscat(szNetBiosName, TEXT("\\"));
866 // Now if this is an AFS network drive mapping, {szMapping} will be:
868 // \Device\LanmanRedirector\<Drive>:\<netbiosname>\submount
870 // on Windows NT. On Windows 2000, it will be:
872 // \Device\LanmanRedirector\;<Drive>:0\<netbiosname>\submount
874 // (This is presumably to support multiple drive mappings with
877 // on Windows XP and 2003, it will be :
878 // \Device\LanmanRedirector\;<Drive>:<AuthID>\<netbiosname>\submount
880 // where : <Drive> : DOS drive letter
881 // <AuthID>: Authentication ID, 16 char hex.
882 // <netbiosname>: Netbios name of server
884 if (_tcsnicmp(szMapping, cszLANMANDEVICE, _tcslen(cszLANMANDEVICE)))
886 pszSubmount = &szMapping[ _tcslen(cszLANMANDEVICE) ];
890 if (*(pszSubmount) != TEXT(';'))
895 if (toupper(*(++pszSubmount)) != chDrive)
898 if (*(++pszSubmount) != TEXT(':'))
902 // No longer a safe assumption on XP
904 if (*(++pszSubmount) != TEXT('0'))
909 while (*(++pszSubmount) != TEXT('\\'))
915 // note that szNetBiosName has a '\\' tagged in the end earlier
916 for (++pszSubmount; *pszSubmount && (*pszSubmount != TEXT('\\')); ++pszSubmount)
917 if (!_tcsncicmp(pszSubmount, szNetBiosName, _tcslen(szNetBiosName)))
919 if ((!*pszSubmount) || (*pszSubmount == TEXT('\\')))
922 pszSubmount += _tcslen(szNetBiosName);
924 else // (!IsWindowsNT())
926 DWORD dwSize = MAX_PATH;
927 if (WNetGetConnection (szDrive, szMapping, &dwSize) != NO_ERROR)
929 if (*(pszSubmount++) != TEXT('\\'))
931 if (*(pszSubmount++) != TEXT('\\'))
933 for ( ; *pszSubmount && (*pszSubmount != TEXT('\\')); ++pszSubmount)
934 if (!lstrncmpi (pszSubmount, szNetBiosName, lstrlen(szNetBiosName)))
936 if ((!*pszSubmount) || (*pszSubmount == TEXT('\\')))
938 pszSubmount += lstrlen(szNetBiosName);
941 if (!pszSubmount || !*pszSubmount)
944 lstrcpy (pszSubmountNow, pszSubmount);
948 /* Generate Random User name random acording to time*/
950 TCHAR pUserName[MAXRANDOMNAMELEN]=TEXT("");
951 BOOL fUserName=FALSE;
952 #define AFSLogonOptionName TEXT("System\\CurrentControlSet\\Services\\TransarcAFSDaemon\\NetworkProvider")
954 void SetBitLogonOption(BOOL set,DWORD value)
957 RWLogonOption(FALSE,((set)?value | RWLogonOption(TRUE,0):RWLogonOption(TRUE,0) & ~value) );
960 DWORD RWLogonOption(BOOL read,DWORD value)
962 // if read is true then if value==0 return registry value
963 // if read and value!=0 then use value to test registry, return TRUE if value bits match value read
966 DWORD LSPtype, LSPsize;
971 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSLogonOptionName, 0, KEY_QUERY_VALUE, &hk)==ERROR_SUCCESS)
973 LSPsize=sizeof(rval);
974 RegQueryValueEx(hk, "LogonOptions", NULL,
975 &LSPtype, (LPBYTE)&rval, &LSPsize);
978 return (value==0)?rval:((rval & value)==value);
981 if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, AFSLogonOptionName, 0, NULL, 0, KEY_SET_VALUE, NULL, &hk, &dwDisp) == ERROR_SUCCESS)
983 RegSetValueEx(hk,TEXT("LogonOptions"),NULL,REG_DWORD,(LPBYTE)&value,sizeof(value));
990 void MapShareName(char *pszCmdLineA)
995 while (*pszCmdLineA && (*pszCmdLineA != ' '))
1001 void GenRandomName(TCHAR *pname,int len)
1004 { //user name was passed through command line, use once
1008 srand( (unsigned)time( NULL ) );
1009 for (int i=0;i<len;i++)
1010 pname[i]='a'+(rand() % 26);
1016 Make a connection using users name
1017 if fUserName then force a connection
1020 BOOL TestAndDoMapShare(DWORD dwState)
1022 if ((dwState!=SERVICE_RUNNING) || (dwOldState!=SERVICE_START_PENDING))
1027 dwOldState=SERVICE_RUNNING;
1028 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1029 return (DoMapShare() && GlobalMountDrive());
1030 return GlobalMountDrive();
1033 BOOL IsServiceActive()
1036 SERVICE_STATUS Status;
1037 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
1040 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
1042 QueryServiceStatus (hService, &Status);
1043 CloseServiceHandle (hService);
1046 CloseServiceHandle (hManager);
1049 return (Status.dwCurrentState == SERVICE_RUNNING) ? TRUE : FALSE;
1052 void TestAndDoUnMapShare()
1054 if (!RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1056 DoUnMapShare(FALSE);
1059 void DoUnMapShare(BOOL drivemap) //disconnect drivemap
1061 TCHAR szMachine[MAX_PATH],szPath[MAX_PATH];
1064 LPNETRESOURCE lpnrLocal,lpnr=NULL;
1066 DWORD cbBuffer=16384;
1070 memset(szMachine, '\0', sizeof(szMachine));
1071 GetClientNetbiosName(szMachine);
1073 // Initialize the data structure
1074 if ((res=WNetOpenEnum(RESOURCE_CONNECTED,RESOURCETYPE_DISK,RESOURCEUSAGE_CONNECTABLE,lpnr,&hEnum))!=NO_ERROR)
1076 sprintf(szPath,"\\\\%s\\",szMachine);
1078 lpnrLocal=(LPNETRESOURCE) GlobalAlloc(GPTR,cbBuffer);
1080 memset(lpnrLocal,0,cbBuffer);
1081 if ((res = WNetEnumResource(hEnum,&cEntries,lpnrLocal,&cbBuffer))==NO_ERROR)
1083 for (DWORD i=0;i<cEntries;i++)
1085 if (strstr(_strlwr(lpnrLocal[i].lpRemoteName),szPath))
1087 if ((lpnrLocal[i].lpLocalName) && (strlen(lpnrLocal[i].lpLocalName)>0))
1090 DisMountDOSDrive(*lpnrLocal[i].lpLocalName);
1091 DEBUG_EVENT1("AFS DriveUnMap","UnMap-Local=%x",res);
1094 DisMountDOSDriveFull(lpnrLocal[i].lpRemoteName);
1095 DEBUG_EVENT1("AFS DriveUnMap","UnMap-Remote=%x",res);
1100 } while (res!=ERROR_NO_MORE_ITEMS);
1101 GlobalFree((HGLOBAL)lpnrLocal);
1102 WNetCloseEnum(hEnum);
1105 BOOL DoMapShareChange()
1108 TCHAR szMachine[ MAX_PATH],szPath[MAX_PATH];
1111 LPNETRESOURCE lpnrLocal,lpnr=NULL;
1114 DWORD cbBuffer=16384;
1116 memset(szMachine, '\0', sizeof(szMachine));
1117 GetClientNetbiosName(szMachine);
1119 // Initialize the data structure
1120 if (!IsServiceActive())
1122 memset (&List, 0x00, sizeof(DRIVEMAPLIST));
1123 for (size_t ii = 0; ii < 26; ++ii)
1124 List.aDriveMap[ii].chDrive = chDRIVE_A + ii;
1125 QueryDriveMapList_ReadSubmounts (&List);
1126 if ((res=WNetOpenEnum(RESOURCE_CONNECTED,RESOURCETYPE_DISK,RESOURCEUSAGE_CONNECTABLE,lpnr,&hEnum))!=NO_ERROR)
1128 lpnrLocal=(LPNETRESOURCE) GlobalAlloc(GPTR,cbBuffer);
1129 sprintf(szPath,"\\\\%s\\",szMachine);
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)==NULL)
1138 continue; //only look at real afs mappings
1139 CHAR * pSubmount=strrchr(lpnrLocal[i].lpRemoteName,'\\')+1;
1140 if (lstrcmpi(pSubmount,"all")==0)
1141 continue; // do not remove 'all'
1142 for (DWORD j=0;j<List.cSubmounts;j++)
1145 (List.aSubmounts[j].szSubmount[0]) &&
1146 (lstrcmpi(List.aSubmounts[j].szSubmount,pSubmount)==0)
1149 List.aSubmounts[j].fInUse=TRUE;
1153 // wasn't on list so lets remove
1154 DisMountDOSDrive(pSubmount);
1158 } while (res!=ERROR_NO_MORE_ITEMS);
1159 GlobalFree((HGLOBAL)lpnrLocal);
1160 WNetCloseEnum(hEnum);
1161 sprintf(szPath,"\\\\%s\\all",szMachine);
1163 // Lets connect all submounts that weren't connectd
1164 DWORD cbUser=MAXRANDOMNAMELEN-1;
1165 CHAR szUser[MAXRANDOMNAMELEN];
1166 CHAR * pUser = NULL;
1167 if (WNetGetUser(szPath,(LPSTR)szUser,&cbUser)!=NO_ERROR) {
1168 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY)) {
1169 if (!pUserName[0]) {
1170 GenRandomName(szUser,MAXRANDOMNAMELEN-1);
1177 if ((pUser=strchr(szUser,'\\'))!=NULL)
1181 for (DWORD j=0;j<List.cSubmounts;j++)
1183 if (List.aSubmounts[j].fInUse)
1185 DWORD res=MountDOSDrive(0,List.aSubmounts[j].szSubmount,FALSE,pUser);
1194 BOOL bMappedAll=FALSE;
1196 // Initialize the data structure
1197 DEBUG_EVENT0("AFS DoMapShare");
1198 QueryDriveMapList (&List);
1200 // All connections have been removed
1201 // Lets restore them after making the connection from the random name
1203 TCHAR szMachine[ MAX_PATH],szPath[MAX_PATH];
1204 memset(szMachine, '\0', sizeof(szMachine));
1205 GetClientNetbiosName(szMachine);
1206 sprintf(szPath,"\\\\%s\\all",szMachine);
1208 // Lets connect all submounts that weren't connectd
1209 DWORD cbUser=MAXRANDOMNAMELEN-1;
1210 CHAR szUser[MAXRANDOMNAMELEN];
1211 CHAR * pUser = NULL;
1212 if (WNetGetUser(szPath,(LPSTR)szUser,&cbUser)!=NO_ERROR) {
1213 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY)) {
1214 if (!pUserName[0]) {
1215 GenRandomName(szUser,MAXRANDOMNAMELEN-1);
1222 if ((pUser=strchr(szUser,'\\'))!=NULL)
1226 for (DWORD i=0;i<List.cSubmounts;i++)
1228 if (List.aSubmounts[i].szSubmount[0])
1230 DWORD res=MountDOSDrive(0,List.aSubmounts[i].szSubmount,FALSE,pUser);
1231 if (lstrcmpi("all",List.aSubmounts[i].szSubmount)==0)
1235 if (!bMappedAll) //make sure all is mapped also
1237 DWORD res=MountDOSDrive(0,"all",FALSE,pUser);
1238 if (res==ERROR_SESSION_CREDENTIAL_CONFLICT)
1240 DisMountDOSDrive("all");
1241 MountDOSDrive(0,"all",FALSE,pUser);
1244 for (TCHAR chDrive = chDRIVE_A; chDrive <= chDRIVE_Z; ++chDrive)
1246 if (List.aDriveMap[chDrive-chDRIVE_A].fActive ||
1247 ForceMapActive(chDrive))
1249 TCHAR szSubmount[ MAX_PATH ];
1250 if (List.aDriveMap[chDrive-chDRIVE_A].szSubmount[0])
1251 lstrcpy(szSubmount,List.aDriveMap[chDrive-chDRIVE_A].szSubmount);
1252 else if (!PathToSubmount (szSubmount, List.aDriveMap[chDrive-chDRIVE_A].szMapping, NULL, NULL))
1255 BOOL fPersistent = List.aDriveMap[chDrive-chDRIVE_A].fPersistent;
1256 if (RWLogonOption(TRUE,LOGON_OPTION_HIGHSECURITY))
1257 fPersistent = FALSE;
1258 DWORD res=MountDOSDrive(chDrive
1260 ,fPersistent,pUser);
1266 BOOL GlobalMountDrive()
1268 char szDriveToMapTo[5];
1270 char szKeyName[256];
1274 DWORD dwSubMountSize;
1275 char unsigned szSubMount[256];
1276 char cm_HostName[200];
1277 DWORD dwType=sizeof(cm_HostName);
1278 if (!IsServiceActive())
1280 if (!GetComputerName(cm_HostName, &dwType))
1282 sprintf(szKeyName, "%s\\GlobalAutoMapper", sAFSConfigKeyName);
1284 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_QUERY_VALUE,
1286 if (dwResult != ERROR_SUCCESS)
1290 dwDriveSize = sizeof(szDriveToMapTo);
1291 dwSubMountSize = sizeof(szSubMount);
1292 dwResult = RegEnumValue(hKey, dwIndex++, szDriveToMapTo, &dwDriveSize,
1293 0, &dwType, szSubMount, &dwSubMountSize);
1294 if (dwResult != ERROR_MORE_DATA) {
1295 if (dwResult != ERROR_SUCCESS) {
1296 if (dwResult != ERROR_NO_MORE_ITEMS)
1298 DEBUG_EVENT1("AFS DriveMap","Failed to read GlobalAutoMapper values: %d",dwResult);
1303 dwResult=MountDOSDrive(*szDriveToMapTo,(const char *)szSubMount,FALSE,NULL);
1309 DWORD MountDOSDrive(char chDrive,const char *szSubmount,BOOL bPersistent,const char * pUsername)
1311 TCHAR szPath[MAX_PATH];
1312 TCHAR szClient[MAX_PATH];
1313 TCHAR szDrive[3] = TEXT("?:");
1314 sprintf(szDrive,"%c:",chDrive);
1315 GetClientNetbiosName (szClient);
1316 sprintf(szPath,"\\\\%s\\%s",szClient,szSubmount);
1318 memset (&nr, 0x00, sizeof(NETRESOURCE));
1319 nr.dwType=RESOURCETYPE_DISK;
1320 nr.lpLocalName=szDrive;
1321 nr.lpRemoteName=szPath;
1322 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
1323 DWORD res=WNetAddConnection2(&nr,NULL,pUsername,(bPersistent)?CONNECT_UPDATE_PROFILE:0);
1324 DEBUG_EVENT5("AFS DriveMap","Mount %s Local[%s] Remote[%s] User[%s]=%x",
1325 (bPersistent)?"Persistant" : "NonPresistant",
1326 szDrive,szPath,pUsername?pUsername:"NULL",res);
1330 DWORD DisMountDOSDriveFull(const char *szPath,BOOL bForce)
1332 DWORD res=WNetCancelConnection(szPath,bForce);
1333 DEBUG_EVENT3("AFS DriveMap","%sDismount Remote[%s]=%x",
1334 bForce ? "Forced " : "",szPath,res);
1335 return (res==ERROR_NOT_CONNECTED)?NO_ERROR:res;
1338 DWORD DisMountDOSDrive(const char *pSubmount,BOOL bForce)
1340 TCHAR szPath[MAX_PATH];
1341 TCHAR szClient[MAX_PATH];
1342 GetClientNetbiosName (szClient);
1343 sprintf(szPath,"\\\\%s\\%s",szClient,pSubmount);
1344 return DisMountDOSDriveFull(szPath,bForce);
1348 DWORD DisMountDOSDrive(const char chDrive,BOOL bForce)
1350 TCHAR szPath[MAX_PATH];
1351 sprintf(szPath,"%c:",chDrive);
1352 return DisMountDOSDriveFull(szPath,bForce);