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 <afsconfig.h>
39 #include <afs/param.h>
43 #include <afs/fs_utils.h>
48 #include <WINNT/TaLocale.h>
49 #include <WINNT/afsreg.h>
58 #include <lanahelper.h>
61 extern void Config_GetLanAdapter (ULONG
*pnLanAdapter
);
64 * REGISTRY ___________________________________________________________________
70 * PROFILE SECTIONS ___________________________________________________________
74 #define cREALLOC_SUBMOUNTS 4
76 static TCHAR cszSECTION_SUBMOUNTS
[] = TEXT(AFSREG_CLT_OPENAFS_SUBKEY
"\\Submounts");
77 static TCHAR cszSECTION_MAPPINGS
[] = TEXT(AFSREG_CLT_OPENAFS_SUBKEY
"\\Mappings");
78 static TCHAR cszSECTION_ACTIVE
[] = TEXT(AFSREG_CLT_OPENAFS_SUBKEY
"\\Active Maps");
80 static TCHAR cszAUTOSUBMOUNT
[] = TEXT("Auto");
81 static TCHAR cszLANMANDEVICE
[] = TEXT("\\Device\\LanmanRedirector\\");
85 WriteRegistryString(HKEY key
, TCHAR
* subkey
, LPTSTR lhs
, LPTSTR rhs
)
92 REG_OPTION_NON_VOLATILE
,
98 DWORD status
= RegSetValueEx( hkSub
, lhs
, 0, REG_SZ
, (const BYTE
*)rhs
, strlen(rhs
)+1 );
101 RegCloseKey( hkSub
);
103 return (status
== ERROR_SUCCESS
);
107 WriteExpandedRegistryString(HKEY key
, TCHAR
* subkey
, LPTSTR lhs
, LPTSTR rhs
)
114 REG_OPTION_NON_VOLATILE
,
120 DWORD status
= RegSetValueEx( hkSub
, lhs
, 0, REG_EXPAND_SZ
, (const BYTE
*)rhs
, strlen(rhs
)+1 );
123 RegCloseKey( hkSub
);
125 return (status
== ERROR_SUCCESS
);
129 ReadRegistryString(HKEY key
, TCHAR
* subkey
, LPTSTR lhs
, LPTSTR rhs
, DWORD
* size
)
136 REG_OPTION_NON_VOLATILE
,
143 DWORD localSize
= *size
;
145 DWORD status
= RegQueryValueEx( hkSub
, lhs
, 0, &dwType
, (LPBYTE
)rhs
, &localSize
);
146 if (status
== 0 && dwType
== REG_EXPAND_SZ
) {
147 TCHAR
* buf
= (TCHAR
*)malloc((*size
) * sizeof(TCHAR
));
148 memcpy(buf
, rhs
, (*size
) * sizeof(TCHAR
));
149 localSize
= ExpandEnvironmentStrings(buf
, rhs
, *size
);
151 if ( localSize
> *size
)
152 status
= !ERROR_SUCCESS
;
157 RegCloseKey( hkSub
);
159 return (status
== ERROR_SUCCESS
);
163 DeleteRegistryString(HKEY key
, TCHAR
* subkey
, LPTSTR lhs
)
170 REG_OPTION_NON_VOLATILE
,
176 DWORD status
= RegDeleteValue( hkSub
, lhs
);
179 RegCloseKey( hkSub
);
181 return (status
== ERROR_SUCCESS
);
185 * STRINGS ____________________________________________________________________
189 static LPTSTR
AllocateStringMemory (size_t cch
)
191 LPTSTR psz
= (LPTSTR
)Allocate (sizeof(TCHAR
) * (cch
+1));
192 memset (psz
, 0x00, sizeof(TCHAR
) * (cch
+1));
196 static void FreeStringMemory (LPTSTR pszString
)
202 static int lstrncmpi (LPCTSTR pszA
, LPCTSTR pszB
, size_t cch
)
206 return (!pszB
) - (!pszA
); // A,!B:1, !A,B:-1, !A,!B:0
209 for ( ; cch
> 0; cch
--, pszA
= CharNext(pszA
), pszB
= CharNext(pszB
))
211 TCHAR chA
= toupper( *pszA
);
212 TCHAR chB
= toupper( *pszB
);
215 return (!chB
) - (!chA
); // A,!B:1, !A,B:-1, !A,!B:0
218 return (int)(chA
) - (int)(chB
); // -1:A<B, 0:A==B, 1:A>B
221 return 0; // no differences before told to stop comparing, so A==B
226 * REALLOC ____________________________________________________________________
231 #define REALLOC(_a,_c,_r,_i) DriveMapReallocFunction ((LPVOID*)&_a,sizeof(*_a),&_c,_r,_i)
232 BOOL
DriveMapReallocFunction (LPVOID
*ppTarget
, size_t cbElement
, size_t *pcTarget
, size_t cReq
, size_t cInc
)
237 if (cReq
<= *pcTarget
)
240 if ((cNew
= cInc
* ((cReq
+ cInc
-1) / cInc
)) <= 0)
243 if ((pNew
= Allocate (cbElement
* cNew
)) == NULL
)
245 memset (pNew
, 0x00, cbElement
* cNew
);
249 memcpy (pNew
, *ppTarget
, cbElement
* (*pcTarget
));
261 * WINDOWS NT STUFF ___________________________________________________________
265 static BOOL
IsWindowsNT (void)
267 static BOOL fChecked
= FALSE
;
268 static BOOL fIsWinNT
= FALSE
;
274 OSVERSIONINFO Version
;
275 memset (&Version
, 0x00, sizeof(Version
));
276 Version
.dwOSVersionInfoSize
= sizeof(Version
);
278 if (GetVersionEx (&Version
))
280 if (Version
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
288 /* Check if the OS is Windows 2000 or higher.
290 BOOL
IsWindows2000 (void)
292 static BOOL fChecked
= FALSE
;
293 static BOOL fIsWin2K
= FALSE
;
299 OSVERSIONINFO Version
;
300 memset (&Version
, 0x00, sizeof(Version
));
301 Version
.dwOSVersionInfoSize
= sizeof(Version
);
303 if (GetVersionEx (&Version
))
305 if (Version
.dwPlatformId
== VER_PLATFORM_WIN32_NT
&&
306 Version
.dwMajorVersion
>= 5)
315 * GENERAL ____________________________________________________________________
319 void GetClientNetbiosName (LPTSTR pszName
)
321 static TCHAR szNetbiosName
[32] = "";
323 if ( szNetbiosName
[0] == 0 ) {
324 lana_GetNetbiosName(szNetbiosName
, LANA_NETBIOS_NAME_FULL
);
326 _tcscpy(pszName
, szNetbiosName
);
330 BOOL
SubmountToPath (PDRIVEMAPLIST pList
, LPTSTR pszPath
, LPTSTR pszSubmount
, BOOL fMarkInUse
)
332 // We can't do this translation unless we're under Windows NT.
337 // \\computer-afs\all always maps to "/afs"
339 if (!lstrcmpi (pszSubmount
, TEXT("all")))
341 lstrcpy (pszPath
, cm_slash_mount_root
);
345 // Otherwise, look up our list of submounts.
348 AdjustAfsPath (pszPath
, pszSubmount
, TRUE
, TRUE
);
350 for (size_t ii
= 0; ii
< pList
->cSubmounts
; ++ii
)
354 b
= !lstrcmpi (pList
->aSubmounts
[ii
].szSubmount
, pszSubmount
);
356 b
= !lstrcmpi (pList
->aSubmounts
[ii
].szMapping
, pszPath
);
361 pList
->aSubmounts
[ii
].fInUse
= TRUE
;
362 AdjustAfsPath (pszPath
, pList
->aSubmounts
[ii
].szMapping
, TRUE
, TRUE
);
371 BOOL
IsValidSubmountName (LPTSTR pszSubmount
)
375 if (lstrlen (pszSubmount
) > 12)
378 for ( ; *pszSubmount
; ++pszSubmount
)
380 if (!isprint(*pszSubmount
))
382 if (*pszSubmount
== TEXT(' '))
384 if (*pszSubmount
== TEXT('/'))
386 if (*pszSubmount
== TEXT('\\'))
388 if (*pszSubmount
== TEXT('\t'))
397 * PIOCTL SUPPORT _____________________________________________________________
403 #include "../afsd/fs_utils.h"
405 #define __CM_CONFIG_INTERFACES_ONLY__
406 #include "../afsd/cm_config.h"
408 #include "../afsd/cm_nls.h"
409 #define __CM_IOCTL_INTERFACES_ONLY__
410 #include "../afsd/cm_ioctl.h"
414 #define PIOCTL_MAXSIZE 2048
417 BOOL
fCanIssuePIOCTL (void)
421 TCHAR szGateway
[ 256 ] = TEXT("");
422 GetClientNetbiosName (szGateway
);
423 return (szGateway
[0]) ? TRUE
: FALSE
;
426 SERVICE_STATUS Status
;
427 memset (&Status
, 0x00, sizeof(Status
));
428 Status
.dwCurrentState
= SERVICE_STOPPED
;
431 if ((hManager
= OpenSCManager (NULL
, NULL
, GENERIC_READ
)) != NULL
)
434 if ((hService
= OpenService (hManager
, TEXT("TransarcAFSDaemon"), GENERIC_READ
)) != NULL
)
436 QueryServiceStatus (hService
, &Status
);
437 CloseServiceHandle (hService
);
440 CloseServiceHandle (hManager
);
443 return (Status
.dwCurrentState
== SERVICE_RUNNING
) ? TRUE
: FALSE
;
448 * QUERYDRIVEMAPLIST __________________________________________________________
452 void QueryDriveMapList_ReadSubmounts (PDRIVEMAPLIST pList
)
458 RegCreateKeyEx( HKEY_LOCAL_MACHINE
,
459 cszSECTION_SUBMOUNTS
,
462 REG_OPTION_NON_VOLATILE
,
463 KEY_READ
|KEY_QUERY_VALUE
,
469 RegQueryInfoKey( hkSubmounts
,
472 NULL
, /* lpReserved */
473 NULL
, /* lpcSubKeys */
474 NULL
, /* lpcMaxSubKeyLen */
475 NULL
, /* lpcMaxClassLen */
476 &dwSubmounts
, /* lpcValues */
477 NULL
, /* lpcMaxValueNameLen */
478 NULL
, /* lpcMaxValueLen */
479 NULL
, /* lpcbSecurityDescriptor */
480 NULL
/* lpftLastWriteTime */
483 for ( DWORD dwIndex
= 0; dwIndex
< dwSubmounts
; dwIndex
++ ) {
484 TCHAR submountPath
[MAX_PATH
] = "";
485 DWORD submountPathLen
= MAX_PATH
;
486 TCHAR submountName
[MAX_PATH
];
487 DWORD submountNameLen
= MAX_PATH
;
490 RegEnumValue( hkSubmounts
, dwIndex
, submountName
, &submountNameLen
, NULL
,
491 &dwType
, (LPBYTE
)submountPath
, &submountPathLen
);
493 if (dwType
== REG_EXPAND_SZ
) {
495 StringCbCopyA(buf
, MAX_PATH
, submountPath
);
496 submountPathLen
= ExpandEnvironmentStrings(buf
, submountPath
, MAX_PATH
);
497 if (submountPathLen
> MAX_PATH
)
502 memset (&Submount
, 0x00, sizeof(SUBMOUNT
));
503 lstrcpy (Submount
.szSubmount
, submountName
);
505 if ( submountPath
[0] != TEXT('\0') ) {
506 AdjustAfsPath (Submount
.szMapping
, submountPath
, FALSE
, TRUE
);
509 for (ii
= 0; ii
< pList
->cSubmounts
; ++ii
)
511 if (!pList
->aSubmounts
[ii
].szSubmount
[0])
514 if (REALLOC (pList
->aSubmounts
, pList
->cSubmounts
, 1+ii
, cREALLOC_SUBMOUNTS
))
516 memcpy (&pList
->aSubmounts
[ii
], &Submount
, sizeof(SUBMOUNT
));
521 RegCloseKey(hkSubmounts
);
526 void QueryDriveMapList_ReadMappings (PDRIVEMAPLIST pList
)
529 RegCreateKeyEx( HKEY_CURRENT_USER
,
533 REG_OPTION_NON_VOLATILE
,
534 KEY_READ
|KEY_QUERY_VALUE
,
540 RegQueryInfoKey( hkMappings
,
543 NULL
, /* lpReserved */
544 NULL
, /* lpcSubKeys */
545 NULL
, /* lpcMaxSubKeyLen */
546 NULL
, /* lpcMaxClassLen */
547 &dwMappings
, /* lpcValues */
548 NULL
, /* lpcMaxValueNameLen */
549 NULL
, /* lpcMaxValueLen */
550 NULL
, /* lpcbSecurityDescriptor */
551 NULL
/* lpftLastWriteTime */
554 for ( DWORD dwIndex
= 0; dwIndex
< dwMappings
; dwIndex
++ ) {
555 TCHAR mapping
[MAX_PATH
] = "";
556 DWORD mappingLen
= MAX_PATH
;
557 TCHAR drive
[MAX_PATH
];
558 DWORD driveLen
= MAX_PATH
;
561 RegEnumValue( hkMappings
, dwIndex
, drive
, &driveLen
, NULL
,
562 &dwType
, (LPBYTE
)mapping
, &mappingLen
);
563 if ( dwType
== REG_EXPAND_SZ
) {
565 DWORD dummyLen
= ExpandEnvironmentStrings(mapping
, buf
, MAX_PATH
);
566 if (dummyLen
> MAX_PATH
)
568 _tcsncpy(mapping
, buf
, MAX_PATH
);
572 memset (&DriveMap
, 0x00, sizeof(DRIVEMAP
));
573 DriveMap
.chDrive
= toupper(*drive
);
574 DriveMap
.fPersistent
= TRUE
;
575 if ((DriveMap
.chDrive
< chDRIVE_A
) || (DriveMap
.chDrive
> chDRIVE_Z
))
578 if (mapping
[0] != TEXT('\0'))
580 AdjustAfsPath (DriveMap
.szMapping
, mapping
, TRUE
, TRUE
);
581 if (DriveMap
.szMapping
[ lstrlen(DriveMap
.szMapping
)-1 ] == TEXT('*'))
583 DriveMap
.fPersistent
= FALSE
;
584 DriveMap
.szMapping
[ lstrlen(DriveMap
.szMapping
)-1 ] = TEXT('\0');
586 size_t iDrive
= DriveMap
.chDrive
- chDRIVE_A
;
587 memcpy (&pList
->aDriveMap
[ iDrive
], &DriveMap
, sizeof(DRIVEMAP
));
591 RegCloseKey(hkMappings
);
594 BOOL
ForceMapActive (TCHAR chDrive
)
599 szDrive
[0] = chDrive
;
602 DWORD len
= sizeof(szActive
);
603 ReadRegistryString( HKEY_CURRENT_USER
, cszSECTION_ACTIVE
, szDrive
, szActive
, &len
);
605 if ( !lstrcmp(szActive
,"1") || !lstrcmpi(szActive
,"true") || !lstrcmpi(szActive
,"on") || !lstrcmpi(szActive
,"yes") )
611 void WriteActiveMap (TCHAR chDrive
, BOOL on
)
615 szDrive
[0] = chDrive
;
618 WriteRegistryString(HKEY_CURRENT_USER
, cszSECTION_ACTIVE
, szDrive
, on
? "1" : "0");
621 void QueryDriveMapList_WriteMappings (PDRIVEMAPLIST pList
)
623 WriteDriveMappings (pList
);
627 void WriteDriveMappings (PDRIVEMAPLIST pList
)
630 RegCreateKeyEx( HKEY_CURRENT_USER
,
634 REG_OPTION_NON_VOLATILE
,
635 KEY_READ
|KEY_QUERY_VALUE
|KEY_WRITE
,
641 RegQueryInfoKey( hkMappings
,
644 NULL
, /* lpReserved */
645 NULL
, /* lpcSubKeys */
646 NULL
, /* lpcMaxSubKeyLen */
647 NULL
, /* lpcMaxClassLen */
648 &dwMappings
, /* lpcValues */
649 NULL
, /* lpcMaxValueNameLen */
650 NULL
, /* lpcMaxValueLen */
651 NULL
, /* lpcbSecurityDescriptor */
652 NULL
/* lpftLastWriteTime */
655 if ( dwMappings
> 0 ) {
656 for ( long dwIndex
= dwMappings
- 1; dwIndex
>= 0; dwIndex
-- ) {
657 TCHAR drive
[MAX_PATH
];
658 DWORD driveLen
= MAX_PATH
;
660 RegEnumValue( hkMappings
, dwIndex
, drive
, &driveLen
, NULL
, NULL
, NULL
, NULL
);
661 RegDeleteValue( hkMappings
, drive
);
665 for (size_t iDrive
= 0; iDrive
< 26; ++iDrive
)
667 if (pList
->aDriveMap
[iDrive
].szMapping
[0] != TEXT('\0'))
669 TCHAR szLHS
[] = TEXT("*");
670 szLHS
[0] = pList
->aDriveMap
[iDrive
].chDrive
;
672 TCHAR szRHS
[MAX_PATH
];
673 AdjustAfsPath (szRHS
, pList
->aDriveMap
[iDrive
].szMapping
, TRUE
, TRUE
);
674 if (!pList
->aDriveMap
[iDrive
].fPersistent
)
675 lstrcat (szRHS
, TEXT("*"));
677 RegSetValueEx( hkMappings
, szLHS
, 0, REG_EXPAND_SZ
, (const BYTE
*)szRHS
, lstrlen(szRHS
) + 1);
680 RegCloseKey( hkMappings
);
683 BOOL
DriveIsGlobalAfsDrive(TCHAR chDrive
)
685 TCHAR szKeyName
[128];
686 TCHAR szValueName
[128];
690 _stprintf(szKeyName
, TEXT("%s\\GlobalAutoMapper"), AFSREG_CLT_SVC_PARAM_SUBKEY
);
692 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE
, szKeyName
, 0, KEY_QUERY_VALUE
, &hKey
) != ERROR_SUCCESS
)
695 _stprintf(szValueName
, TEXT("%c:"), chDrive
);
697 DWORD dwSize
= sizeof(szValue
);
698 BOOL bIsGlobal
= (RegQueryValueEx (hKey
, szValueName
, NULL
, NULL
, (PBYTE
)szValue
, &dwSize
) == ERROR_SUCCESS
);
706 void QueryDriveMapList_FindNetworkDrives (PDRIVEMAPLIST pList
, BOOL
*pfFoundNew
)
708 for (TCHAR chDrive
= chDRIVE_A
; chDrive
<= chDRIVE_Z
; ++chDrive
)
710 TCHAR szSubmount
[ MAX_PATH
];
711 if (!GetDriveSubmount (chDrive
, szSubmount
))
714 // We've got a mapping! Drive {chDrive} is mapped to submount
715 // {szSubmount}. See if that submount makes sense.
719 size_t iDrive
= chDrive
- chDRIVE_A
;
720 if (pList
->aDriveMap
[ iDrive
].szMapping
[0] != TEXT('\0'))
722 pList
->aDriveMap
[ iDrive
].fActive
= TRUE
;
723 lstrcpy (pList
->aDriveMap
[ iDrive
].szSubmount
, szSubmount
);
727 else // (IsWindowsNT())
729 TCHAR szAfsPath
[ MAX_PATH
];
730 if (!SubmountToPath (pList
, szAfsPath
, szSubmount
, TRUE
))
733 // Okay, we know that drive {chDrive} is mapped to afs path {szAfsPath}.
734 // If this drive is a global afs drive, then reject it. Otherwise, look
735 // at pList->aDriveMap, to see if this drive mapping is already in our
736 // list. If not, add it and set pfFoundNew.
738 if (DriveIsGlobalAfsDrive(chDrive
))
741 size_t iDrive
= chDrive
- chDRIVE_A
;
742 if (lstrcmpi (pList
->aDriveMap
[ iDrive
].szMapping
, szAfsPath
))
745 pList
->aDriveMap
[ iDrive
].fPersistent
= TRUE
;
747 pList
->aDriveMap
[ iDrive
].fActive
= TRUE
;
748 pList
->aDriveMap
[ iDrive
].chDrive
= chDrive
;
749 lstrcpy (pList
->aDriveMap
[ iDrive
].szSubmount
, szSubmount
);
750 AdjustAfsPath (pList
->aDriveMap
[ iDrive
].szMapping
, szAfsPath
, TRUE
, TRUE
);
756 void QueryDriveMapList (PDRIVEMAPLIST pList
)
758 // Initialize the data structure
760 memset (pList
, 0x00, sizeof(DRIVEMAPLIST
));
761 for (size_t ii
= 0; ii
< 26; ++ii
)
762 pList
->aDriveMap
[ii
].chDrive
= chDRIVE_A
+ ii
;
764 // Read the current lists of submounts and drive letter mappings
766 QueryDriveMapList_ReadSubmounts (pList
);
767 QueryDriveMapList_ReadMappings (pList
);
769 // Look through the current list of network drives, and see if
770 // any are currently mapped to AFS. If we find any which are mapped
771 // into AFS unexpectedly, we'll have to rewrite the mappings list.
773 BOOL fFoundNew
= FALSE
;
774 QueryDriveMapList_FindNetworkDrives (pList
, &fFoundNew
);
778 QueryDriveMapList_WriteMappings (pList
);
783 void FreeDriveMapList (PDRIVEMAPLIST pList
)
785 if (pList
->aSubmounts
)
786 Free (pList
->aSubmounts
);
787 memset (pList
, 0x00, sizeof(DRIVEMAPLIST
));
792 BOOL
PathToSubmount (LPTSTR pszSubmount
, LPTSTR pszMapping
, LPTSTR pszSubmountReq
, ULONG
*pStatus
)
794 // pszSubmount is MAX_PATH in length
796 if (pszSubmountReq
&& !IsValidSubmountName (pszSubmountReq
))
797 pszSubmountReq
= NULL
;
799 TCHAR szAfsPath
[ MAX_PATH
];
800 AdjustAfsPath (szAfsPath
, pszMapping
, TRUE
, TRUE
);
802 // Try to ask AFSD for a new submount name.
804 if (!fCanIssuePIOCTL())
807 BYTE InData
[ PIOCTL_MAXSIZE
];
808 memset (InData
, 0x00, sizeof(InData
));
810 LPTSTR pszInData
= (LPTSTR
)InData
;
811 lstrcpy (pszInData
, pszMapping
);
812 pszInData
+= 1+lstrlen(pszInData
);
814 lstrcpy (pszInData
, pszSubmountReq
);
816 BYTE OutData
[ PIOCTL_MAXSIZE
];
817 memset (OutData
, 0x00, sizeof(OutData
));
819 struct ViceIoctl IOInfo
;
820 IOInfo
.in
= (char *)InData
;
821 IOInfo
.in_size
= PIOCTL_MAXSIZE
;
822 IOInfo
.out
= (char *)OutData
;
823 IOInfo
.out_size
= PIOCTL_MAXSIZE
;
825 ULONG status
= pioctl (0, VIOC_MAKESUBMOUNT
, &IOInfo
, 1);
833 OutData
[min(PIOCTL_MAXSIZE
, MAX_PATH
) - 1] = '\0';
834 lstrcpy (pszSubmount
, (LPCTSTR
)OutData
);
835 return (pszSubmount
[0] != TEXT('\0')) ? TRUE
: FALSE
;
839 BOOL
ActivateDriveMap (TCHAR chDrive
, LPTSTR pszMapping
, LPTSTR pszSubmountReq
, BOOL fPersistent
, DWORD
*pdwStatus
)
841 // We can only map drives to places in AFS using this function.
843 if ( (lstrncmpi (pszMapping
, cm_slash_mount_root
, lstrlen(cm_slash_mount_root
))) &&
844 (lstrncmpi (pszMapping
, cm_back_slash_mount_root
, lstrlen(cm_back_slash_mount_root
))) )
847 *pdwStatus
= ERROR_BAD_NETPATH
;
851 // First we have to translate {pszMapping} into a submount, and if there is
852 // no current submount associated with this path, we'll have to make one.
855 TCHAR szSubmount
[ MAX_PATH
];
856 if (!PathToSubmount (szSubmount
, pszMapping
, pszSubmountReq
, &status
))
863 // We now have a submount name and drive letter--map the network drive.
866 rc
=MountDOSDrive(chDrive
,szSubmount
,fPersistent
,NULL
);
868 rc
=MountDOSDrive(chDrive
,/*szSubmount*/pszMapping
,fPersistent
,NULL
);
879 BOOL
InactivateDriveMap (TCHAR chDrive
, DWORD
*pdwStatus
)
881 DWORD rc
= DisMountDOSDrive(chDrive
, FALSE
);
891 void AddSubMount (LPTSTR pszSubmount
, LPTSTR pszMapping
)
893 TCHAR szRHS
[ MAX_PATH
];
894 AdjustAfsPath (szRHS
, pszMapping
, FALSE
, TRUE
);
896 lstrcpy (szRHS
, TEXT("/"));
898 WriteExpandedRegistryString(HKEY_LOCAL_MACHINE
, cszSECTION_SUBMOUNTS
, pszSubmount
, szRHS
);
902 void RemoveSubMount (LPTSTR pszSubmount
)
904 DeleteRegistryString(HKEY_LOCAL_MACHINE
, cszSECTION_SUBMOUNTS
, pszSubmount
);
908 void AdjustAfsPath (LPTSTR pszTarget
, LPCTSTR pszSource
, BOOL fWantAFS
, BOOL fWantForwardSlashes
)
911 lstrcpy (pszTarget
, (fWantAFS
) ? cm_slash_mount_root
: TEXT(""));
912 else if ((*pszSource
!= TEXT('/')) && (*pszSource
!= TEXT('\\')))
913 wsprintf (pszTarget
, TEXT("%s/%s"),cm_slash_mount_root
, pszSource
);
914 // We don't want to strip afs off the start if it is part of something for example afscell.company.com
915 else if (fWantAFS
&& (lstrncmpi (&pszSource
[1], cm_mount_root
, strlen(cm_mount_root
))) || !((pszSource
[strlen(cm_slash_mount_root
)] == TEXT('/')) ||
916 (pszSource
[strlen(cm_slash_mount_root
)] == TEXT('\\')) ||
917 (lstrlen(pszSource
) == strlen(cm_slash_mount_root
))))
918 wsprintf (pszTarget
, TEXT("%s%s"),cm_slash_mount_root
, pszSource
);
919 else if (!fWantAFS
&& (!lstrncmpi (&pszSource
[1], cm_mount_root
, strlen(cm_mount_root
)) && ((pszSource
[strlen(cm_slash_mount_root
)] == TEXT('/')) ||
920 (pszSource
[strlen(cm_slash_mount_root
)] == TEXT('\\')) ||
921 (lstrlen(pszSource
) == strlen(cm_slash_mount_root
)))))
922 lstrcpy (pszTarget
, &pszSource
[strlen(cm_slash_mount_root
)]);
924 lstrcpy (pszTarget
, pszSource
);
926 for (LPTSTR pch
= pszTarget
; *pch
; ++pch
)
928 if (fWantForwardSlashes
)
930 *pch
= (*pch
== TEXT('\\')) ? TEXT('/') : (*pch
);
932 else // (!fWantForwardSlashes)
934 *pch
= (*pch
== TEXT('/')) ? TEXT('\\') : (*pch
);
938 if (lstrlen(pszTarget
) &&
939 ((pszTarget
[lstrlen(pszTarget
)-1] == TEXT('/')) ||
940 (pszTarget
[lstrlen(pszTarget
)-1] == TEXT('\\'))))
942 pszTarget
[lstrlen(pszTarget
)-1] = TEXT('\0');
946 BOOL
GetDriveSubmount (TCHAR chDrive
, LPTSTR pszSubmountNow
)
948 BOOL isWinNT
= IsWindowsNT();
950 TCHAR szDrive
[] = TEXT("*:");
951 szDrive
[0] = chDrive
;
953 TCHAR szMapping
[ _MAX_PATH
] = TEXT("");
955 if (isWinNT
&& !QueryDosDevice (szDrive
, szMapping
, MAX_PATH
))
958 LPTSTR pszSubmount
= szMapping
;
960 TCHAR szNetBiosName
[32];
961 memset(szNetBiosName
, '\0', sizeof(szNetBiosName
));
962 GetClientNetbiosName(szNetBiosName
);
963 _tcscat(szNetBiosName
, TEXT("\\"));
967 // Now if this is an AFS network drive mapping, {szMapping} will be:
969 // \Device\LanmanRedirector\<Drive>:\<netbiosname>\submount
971 // on Windows NT. On Windows 2000, it will be:
973 // \Device\LanmanRedirector\;<Drive>:0\<netbiosname>\submount
975 // (This is presumably to support multiple drive mappings with
978 // on Windows XP and 2003, it will be :
979 // \Device\LanmanRedirector\;<Drive>:<AuthID>\<netbiosname>\submount
981 // where : <Drive> : DOS drive letter
982 // <AuthID>: Authentication ID, 16 char hex.
983 // <netbiosname>: Netbios name of server
987 b
= _tcsnicmp(szMapping
, cszLANMANDEVICE
, _tcslen(cszLANMANDEVICE
));
989 const TCHAR ker_sub_path
[] = "\\Device\\afsrdr\\";
990 b
= _tcsnicmp(szMapping
, ker_sub_path
, _tcslen(ker_sub_path
));
995 pszSubmount
= &szMapping
[ _tcslen(cszLANMANDEVICE
) ];
997 pszSubmount
= &szMapping
[ _tcslen(ker_sub_path
) ];
1001 if (*(pszSubmount
) < '0' ||
1002 *(pszSubmount
) > '9')
1006 if (IsWindows2000())
1008 if (*(pszSubmount
) != TEXT(';'))
1013 if (toupper(*(++pszSubmount
)) != chDrive
)
1016 if (*(++pszSubmount
) != TEXT(':'))
1020 // No longer a safe assumption on XP
1021 if (IsWindows2000())
1022 if (*(++pszSubmount
) != TEXT('0'))
1026 // scan for next "\"
1027 while (*(++pszSubmount
) != TEXT('\\'))
1029 if (*pszSubmount
==0)
1033 // note that szNetBiosName has a '\\' tagged in the end earlier
1034 for (++pszSubmount
; *pszSubmount
&& (*pszSubmount
!= TEXT('\\')); ++pszSubmount
)
1035 if (!_tcsncicmp(pszSubmount
, szNetBiosName
, _tcslen(szNetBiosName
)))
1037 if ((!*pszSubmount
) || (*pszSubmount
== TEXT('\\')))
1040 pszSubmount
+= _tcslen(szNetBiosName
);
1043 else // (!IsWindowsNT())
1045 DWORD dwSize
= MAX_PATH
;
1046 if (WNetGetConnection (szDrive
, szMapping
, &dwSize
) != NO_ERROR
)
1048 if (*(pszSubmount
++) != TEXT('\\'))
1050 if (*(pszSubmount
++) != TEXT('\\'))
1052 for ( ; *pszSubmount
&& (*pszSubmount
!= TEXT('\\')); ++pszSubmount
)
1053 if (!lstrncmpi (pszSubmount
, szNetBiosName
, lstrlen(szNetBiosName
)))
1055 if ((!*pszSubmount
) || (*pszSubmount
== TEXT('\\')))
1057 pszSubmount
+= lstrlen(szNetBiosName
);
1060 if (!pszSubmount
|| !*pszSubmount
)
1064 lstrcpy (pszSubmountNow
, pszSubmount
);
1066 lstrcpy (pszSubmountNow
, "\\afs");
1067 lstrcat (pszSubmountNow
, pszSubmount
);
1072 /* Generate Random User name random acording to time*/
1074 TCHAR pUserName
[MAXRANDOMNAMELEN
]=TEXT("");
1075 BOOL fUserName
=FALSE
;
1076 #define AFSLogonOptionName TEXT(AFSREG_CLT_SVC_PROVIDER_SUBKEY)
1078 void SetBitLogonOption(BOOL set
,DWORD value
)
1081 RWLogonOption(FALSE
,((set
)?value
| RWLogonOption(TRUE
,0):RWLogonOption(TRUE
,0) & ~value
) );
1084 DWORD
RWLogonOption(BOOL read
,DWORD value
)
1086 // if read is true then if value==0 return registry value
1087 // if read and value!=0 then use value to test registry, return TRUE if value bits match value read
1090 DWORD LSPtype
, LSPsize
;
1096 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE
, AFSLogonOptionName
, 0, KEY_QUERY_VALUE
, &hk
)==ERROR_SUCCESS
)
1098 LSPsize
=sizeof(rval
);
1099 RegQueryValueEx(hk
, "LogonOptions", NULL
,
1100 &LSPtype
, (LPBYTE
)&rval
, &LSPsize
);
1103 return (value
==0)?rval
:((rval
& value
)==value
);
1105 if (RegCreateKeyEx (HKEY_LOCAL_MACHINE
, AFSLogonOptionName
, 0, NULL
, 0, KEY_SET_VALUE
, NULL
, &hk
, &dwDisp
) == ERROR_SUCCESS
)
1107 RegSetValueEx(hk
,TEXT("LogonOptions"),NULL
,REG_DWORD
,(LPBYTE
)&value
,sizeof(value
));
1114 void MapShareName(char *pszCmdLineA
)
1119 while (*pszCmdLineA
&& (*pszCmdLineA
!= ' '))
1121 *p
++=*pszCmdLineA
++;
1125 void GenRandomName(TCHAR
*pname
,int len
)
1128 { //user name was passed through command line, use once
1132 srand( (unsigned)time( NULL
) );
1133 for (int i
=0;i
<len
;i
++)
1134 pname
[i
]='a'+(rand() % 26);
1140 Make a connection using users name
1141 if fUserName then force a connection
1144 BOOL
TestAndDoMapShare(DWORD dwState
)
1146 if ((dwState
!=SERVICE_RUNNING
) || (dwOldState
!=SERVICE_START_PENDING
))
1151 dwOldState
=SERVICE_RUNNING
;
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()
1179 void DoUnMapShare(BOOL drivemap
) //disconnect drivemap
1181 TCHAR szMachine
[MAX_PATH
],szPath
[MAX_PATH
];
1184 LPNETRESOURCE lpnrLocal
,lpnr
=NULL
;
1186 DWORD cbBuffer
=16384;
1190 memset(szMachine
, '\0', sizeof(szMachine
));
1191 GetClientNetbiosName(szMachine
);
1193 // Initialize the data structure
1194 if ((res
=WNetOpenEnum(RESOURCE_CONNECTED
,RESOURCETYPE_DISK
,RESOURCEUSAGE_CONNECTABLE
,lpnr
,&hEnum
))!=NO_ERROR
)
1196 sprintf(szPath
,"\\\\%s\\",szMachine
);
1198 lpnrLocal
=(LPNETRESOURCE
) GlobalAlloc(GPTR
,cbBuffer
);
1200 /* Reset lpnrLocal and cEntries before each call */
1201 memset(lpnrLocal
,0,cbBuffer
);
1204 if ((res
= WNetEnumResource(hEnum
,&cEntries
,lpnrLocal
,&cbBuffer
))==NO_ERROR
)
1206 for (DWORD i
=0;i
<cEntries
;i
++)
1208 if (strstr(_strlwr(lpnrLocal
[i
].lpRemoteName
),szPath
))
1210 if ((lpnrLocal
[i
].lpLocalName
) && (strlen(lpnrLocal
[i
].lpLocalName
)>0))
1213 DisMountDOSDrive(*lpnrLocal
[i
].lpLocalName
);
1214 DEBUG_EVENT1("AFS DriveUnMap","UnMap-Local=%x",res
);
1217 DisMountDOSDriveFull(lpnrLocal
[i
].lpRemoteName
);
1218 DEBUG_EVENT1("AFS DriveUnMap","UnMap-Remote=%x",res
);
1223 } while (res
== NO_ERROR
);
1224 GlobalFree((HGLOBAL
)lpnrLocal
);
1225 WNetCloseEnum(hEnum
);
1228 BOOL
DoMapShareChange(BOOL removeUnknown
)
1231 TCHAR szMachine
[ MAX_PATH
],szPath
[MAX_PATH
];
1234 LPNETRESOURCE lpnrLocal
,lpnr
=NULL
;
1237 DWORD cbBuffer
=16384;
1239 memset(szMachine
, '\0', sizeof(szMachine
));
1240 GetClientNetbiosName(szMachine
);
1242 // Initialize the data structure
1243 if (!IsServiceActive())
1245 memset (&List
, 0x00, sizeof(DRIVEMAPLIST
));
1246 for (size_t ii
= 0; ii
< 26; ++ii
)
1247 List
.aDriveMap
[ii
].chDrive
= chDRIVE_A
+ ii
;
1248 QueryDriveMapList_ReadSubmounts (&List
);
1249 if ((res
=WNetOpenEnum(RESOURCE_CONNECTED
,RESOURCETYPE_DISK
,RESOURCEUSAGE_CONNECTABLE
,lpnr
,&hEnum
))!=NO_ERROR
)
1251 lpnrLocal
=(LPNETRESOURCE
) GlobalAlloc(GPTR
,cbBuffer
);
1252 sprintf(szPath
,"\\\\%s\\",szMachine
);
1255 /* Reset lpnrLocal and cEntries before each call */
1256 memset(lpnrLocal
,0,cbBuffer
);
1259 if ((res
= WNetEnumResource(hEnum
,&cEntries
,lpnrLocal
,&cbBuffer
))==NO_ERROR
)
1261 for (DWORD i
=0;i
<cEntries
;i
++)
1263 if (strstr(_strlwr(lpnrLocal
[i
].lpRemoteName
),szPath
)==NULL
)
1264 continue; //only look at real afs mappings
1265 CHAR
* pSubmount
=strrchr(lpnrLocal
[i
].lpRemoteName
,'\\')+1;
1266 if (lstrcmpi(pSubmount
,"all")==0)
1267 continue; // do not remove 'all'
1268 for (DWORD j
=0;j
<List
.cSubmounts
;j
++)
1270 if ((List
.aSubmounts
[j
].szSubmount
[0]) &&
1271 (lstrcmpi(List
.aSubmounts
[j
].szSubmount
,pSubmount
)==0)
1274 List
.aSubmounts
[j
].fInUse
=TRUE
;
1278 // wasn't on list so lets remove
1279 DisMountDOSDrive(pSubmount
);
1283 } while (res
== NO_ERROR
);
1284 GlobalFree((HGLOBAL
)lpnrLocal
);
1285 WNetCloseEnum(hEnum
);
1286 sprintf(szPath
,"\\\\%s\\all",szMachine
);
1288 // Lets connect all submounts that weren't connectd
1289 DWORD cbUser
=MAXRANDOMNAMELEN
-1;
1290 CHAR szUser
[MAXRANDOMNAMELEN
];
1291 CHAR
* pUser
= NULL
;
1292 if (WNetGetUser(szPath
,(LPSTR
)szUser
,&cbUser
)==NO_ERROR
) {
1293 if ((pUser
=strchr(szUser
,'\\'))!=NULL
)
1297 for (DWORD j
=0;j
<List
.cSubmounts
;j
++)
1299 if (List
.aSubmounts
[j
].fInUse
)
1301 DWORD res
=MountDOSDrive(0,List
.aSubmounts
[j
].szSubmount
,FALSE
,pUser
);
1310 BOOL bMappedAll
=FALSE
;
1312 // Initialize the data structure
1313 DEBUG_EVENT0("AFS DoMapShare");
1314 QueryDriveMapList (&List
);
1316 // All connections have been removed
1317 // Lets restore them after making the connection from the random name
1319 TCHAR szMachine
[ MAX_PATH
],szPath
[MAX_PATH
];
1320 memset(szMachine
, '\0', sizeof(szMachine
));
1321 GetClientNetbiosName(szMachine
);
1322 sprintf(szPath
,"\\\\%s\\all",szMachine
);
1324 // Lets connect all submounts that weren't connectd
1325 DWORD cbUser
=MAXRANDOMNAMELEN
-1;
1326 CHAR szUser
[MAXRANDOMNAMELEN
];
1327 CHAR
* pUser
= NULL
;
1328 if (WNetGetUser(szPath
,(LPSTR
)szUser
,&cbUser
)==NO_ERROR
) {
1329 if ((pUser
=strchr(szUser
,'\\'))!=NULL
)
1333 for (DWORD i
=0;i
<List
.cSubmounts
;i
++)
1335 if (List
.aSubmounts
[i
].szSubmount
[0])
1337 DWORD res
=MountDOSDrive(0,List
.aSubmounts
[i
].szSubmount
,FALSE
,pUser
);
1338 if (lstrcmpi("all",List
.aSubmounts
[i
].szSubmount
)==0)
1342 if (!bMappedAll
) //make sure all is mapped also
1344 DWORD res
=MountDOSDrive(0,"all",FALSE
,pUser
);
1345 if (res
==ERROR_SESSION_CREDENTIAL_CONFLICT
)
1347 DisMountDOSDrive("all");
1348 MountDOSDrive(0,"all",FALSE
,pUser
);
1351 for (TCHAR chDrive
= chDRIVE_A
; chDrive
<= chDRIVE_Z
; ++chDrive
)
1353 if (List
.aDriveMap
[chDrive
-chDRIVE_A
].fActive
||
1354 ForceMapActive(chDrive
))
1356 TCHAR szSubmount
[ MAX_PATH
];
1357 if (List
.aDriveMap
[chDrive
-chDRIVE_A
].szSubmount
[0])
1358 lstrcpy(szSubmount
,List
.aDriveMap
[chDrive
-chDRIVE_A
].szSubmount
);
1359 else if (!PathToSubmount (szSubmount
, List
.aDriveMap
[chDrive
-chDRIVE_A
].szMapping
, NULL
, NULL
))
1362 BOOL fPersistent
= List
.aDriveMap
[chDrive
-chDRIVE_A
].fPersistent
;
1363 DWORD res
=MountDOSDrive(chDrive
1365 ,fPersistent
,pUser
);
1371 BOOL
GlobalMountDrive()
1373 char szDriveToMapTo
[5];
1375 char szKeyName
[256];
1379 DWORD dwSubMountSize
;
1380 char unsigned szSubMount
[256];
1381 char cm_HostName
[200];
1382 DWORD dwType
=sizeof(cm_HostName
);
1383 if (!IsServiceActive())
1385 if (!GetComputerName(cm_HostName
, &dwType
))
1387 sprintf(szKeyName
, "%s\\GlobalAutoMapper", AFSREG_CLT_SVC_PARAM_SUBKEY
);
1389 dwResult
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
, szKeyName
, 0, KEY_QUERY_VALUE
,
1391 if (dwResult
!= ERROR_SUCCESS
)
1395 dwDriveSize
= sizeof(szDriveToMapTo
);
1396 dwSubMountSize
= sizeof(szSubMount
);
1397 dwResult
= RegEnumValue(hKey
, dwIndex
++, szDriveToMapTo
, &dwDriveSize
,
1398 0, &dwType
, szSubMount
, &dwSubMountSize
);
1399 if (dwResult
!= ERROR_MORE_DATA
) {
1400 if (dwResult
!= ERROR_SUCCESS
) {
1401 if (dwResult
!= ERROR_NO_MORE_ITEMS
)
1403 DEBUG_EVENT1("AFS DriveMap","Failed to read GlobalAutoMapper values: %d",dwResult
);
1408 dwResult
=MountDOSDrive(*szDriveToMapTo
,(const char *)szSubMount
,FALSE
,NULL
);
1414 DWORD
MountDOSDrive(char chDrive
,const char *szSubmount
,BOOL bPersistent
,const char * pUsername
)
1419 TCHAR szTokens
[MAX_PATH
], *tok
;
1421 TCHAR szPath
[MAX_PATH
];
1422 TCHAR szClient
[MAX_PATH
];
1423 TCHAR szDrive
[3] = TEXT("?:");
1426 int pathCount
, currPos
, lastPos
, x
;
1431 strcpy(szTokens
, szSubmount
);
1432 tok
= strtok(szTokens
, "/\\");
1436 if (pathCount
|| stricmp(tok
, "afs"))
1438 strcat(szPath
, "\\");
1439 strcat(szPath
, tok
);
1442 tok
= strtok(NULL
, "/\\");
1445 sprintf(szDrive
,"%c:",chDrive
);
1446 strcpy(szTokens
, szPath
);
1447 sprintf(szPath
,"\\Device\\afsrdr\\%d%s",pathCount
,szTokens
);
1448 //succ = DefineDosDevice(DDD_RAW_TARGET_PATH, "J:", "\\Device\\afsrdr\\2\\ericjw\\test");
1449 succ
= DefineDosDevice(DDD_RAW_TARGET_PATH
, szDrive
, szPath
);
1450 err
= GetLastError();
1452 return succ
? NO_ERROR
: ERROR_DEVICE_IN_USE
;
1454 sprintf(szDrive
,"%c:",chDrive
);
1455 GetClientNetbiosName (szClient
);
1456 sprintf(szPath
,"\\\\%s\\%s",szClient
,szSubmount
);
1458 memset (&nr
, 0x00, sizeof(NETRESOURCE
));
1459 nr
.dwType
=RESOURCETYPE_DISK
;
1460 nr
.lpLocalName
=szDrive
;
1461 nr
.lpRemoteName
=szPath
;
1462 nr
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
; /* ignored parameter */
1463 DWORD res
=WNetAddConnection2(&nr
,NULL
,pUsername
,(bPersistent
)?CONNECT_UPDATE_PROFILE
:0);
1464 DEBUG_EVENT5("AFS DriveMap","Mount %s Local[%s] Remote[%s] User[%s]=%x",
1465 (bPersistent
)?"Persistant" : "NonPresistant",
1466 szDrive
,szPath
,pUsername
?pUsername
:"NULL",res
);
1471 DWORD
DisMountDOSDriveFull(const char *szPath
,BOOL bForce
)
1474 DWORD res
=WNetCancelConnection(szPath
,bForce
);
1477 res
= ERROR_DEVICE_IN_USE
;
1478 // must handle drive letters and afs paths
1479 // DDD_REMOVE_DEFINITION
1481 DEBUG_EVENT3("AFS DriveMap","%sDismount Remote[%s]=%x",
1482 bForce
? "Forced " : "",szPath
,res
);
1483 return (res
==ERROR_NOT_CONNECTED
)?NO_ERROR
:res
;
1486 DWORD
DisMountDOSDrive(const char *pSubmount
,BOOL bForce
)
1488 TCHAR szPath
[MAX_PATH
];
1489 TCHAR szClient
[MAX_PATH
];
1490 GetClientNetbiosName (szClient
);
1491 sprintf(szPath
,"\\\\%s\\%s",szClient
,pSubmount
);
1492 return DisMountDOSDriveFull(szPath
,bForce
);
1496 DWORD
DisMountDOSDrive(const char chDrive
,BOOL bForce
)
1498 TCHAR szPath
[MAX_PATH
];
1502 sprintf(szPath
,"%c:",chDrive
);
1504 succ
= DefineDosDevice(DDD_REMOVE_DEFINITION
, szPath
, NULL
);
1505 return (!succ
) ? GetLastError() : 0;
1507 return DisMountDOSDriveFull(szPath
,bForce
);