2398 lines
56 KiB
C++
2398 lines
56 KiB
C++
/*++
|
||
Copyright (c) 1994 Microsoft Corporation
|
||
|
||
Module Name:
|
||
vroots.cxx
|
||
|
||
Abstract:
|
||
|
||
This module contains the front end to the virtual roots interface
|
||
|
||
|
||
|
||
Author:
|
||
|
||
John Ludeman (johnl) 16-Mar-1995
|
||
|
||
Project:
|
||
|
||
Internet Servers Common Server DLL
|
||
|
||
Revisions:
|
||
|
||
--*/
|
||
|
||
//
|
||
// Include Headers
|
||
//
|
||
|
||
#include <tcpdllp.hxx>
|
||
#include <tsunami.hxx>
|
||
#include <iistypes.hxx>
|
||
#include <inetinfo.h>
|
||
#include <imd.h>
|
||
#include <inetreg.h>
|
||
#include <mb.hxx>
|
||
#include <w3svc.h>
|
||
#if 1 // DBCS
|
||
#include <mbstring.h>
|
||
#endif
|
||
#include <initguid.h>
|
||
#include <iwamreg.h>
|
||
|
||
|
||
BOOL
|
||
RetrieveRootPassword(
|
||
PCHAR pszRoot,
|
||
PCHAR pszPassword,
|
||
WCHAR * pszSecret
|
||
);
|
||
|
||
DWORD
|
||
GetFileSystemType(
|
||
IN LPCSTR pszRealPath,
|
||
OUT LPDWORD lpdwFileSystem
|
||
);
|
||
|
||
VOID
|
||
LogRootAddFailure(
|
||
IN PIIS_SERVER_INSTANCE psi,
|
||
PCHAR pszRoot,
|
||
PCHAR pszDirectory,
|
||
DWORD err,
|
||
IN PCHAR pszMetaPath,
|
||
IN MB * pmb
|
||
);
|
||
|
||
BOOL
|
||
TsAddVrootsWithScmUpdate(
|
||
PVOID pvContext,
|
||
MB * pmb,
|
||
VIRTUAL_ROOT * pvr
|
||
);
|
||
|
||
BOOL
|
||
TsAddVroots(
|
||
PVOID pvContext,
|
||
MB * pmb,
|
||
VIRTUAL_ROOT * pvr
|
||
);
|
||
|
||
HANDLE
|
||
VrootLogonUser(
|
||
IN CHAR * pszUser,
|
||
IN CHAR * pszPassword
|
||
);
|
||
|
||
BOOL
|
||
CrackUserAndDomain(
|
||
CHAR * pszDomainAndUser,
|
||
CHAR * * ppszUser,
|
||
CHAR * * ppszDomain
|
||
);
|
||
|
||
VOID
|
||
ClearSentinelEntry(
|
||
IN MB * pMB
|
||
);
|
||
|
||
VOID
|
||
RemoveUnmarkedRoots(
|
||
IN MB * pMB
|
||
);
|
||
|
||
BOOL
|
||
ReadVrootConfig(
|
||
LPVOID pvMB,
|
||
LPSTR szVRPath,
|
||
LPSTR szDirectory,
|
||
DWORD cbDirectory,
|
||
LPSTR szUser,
|
||
DWORD cbUser,
|
||
LPSTR szPassword,
|
||
DWORD cbPassword,
|
||
DWORD *pdwMask,
|
||
BOOL *pfDoCache
|
||
);
|
||
|
||
DWORD
|
||
hextointW(
|
||
WCHAR * pch
|
||
);
|
||
|
||
DWORD
|
||
hextointA(
|
||
CHAR * pch
|
||
);
|
||
|
||
BOOL
|
||
IIS_SERVER_INSTANCE::TsReadVirtualRoots(
|
||
MD_CHANGE_OBJECT * pcoChangeList
|
||
)
|
||
/*++
|
||
Description:
|
||
|
||
NT Version
|
||
|
||
This function is overloaded. The behavaior keys on pcoChangeList
|
||
being NULL or not.
|
||
|
||
If pcoChangeList is NULL (default value), it reads the metabase
|
||
key pointed at by pmb and adds each root item.
|
||
|
||
If pcoChangeList is not NULL then it only reads the necessary values.
|
||
|
||
Arguments:
|
||
|
||
pcoChangeList : pointer to metabase changes.
|
||
|
||
Note:
|
||
Failure to add a virtual root is not fatal. An appropriate event
|
||
will be logged listing the error and root.
|
||
|
||
Returns:
|
||
TRUE on success and FALSE if any failure.
|
||
|
||
--*/
|
||
{
|
||
BOOL fRet;
|
||
MB mb( (IMDCOM*) m_Service->QueryMDObject() );
|
||
|
||
//
|
||
// Unfortunately rename doesn't give us the name of the old object.
|
||
// So treat it as default processing
|
||
//
|
||
|
||
if ((NULL == pcoChangeList) ||
|
||
(MD_CHANGE_TYPE_RENAME_OBJECT == pcoChangeList->dwMDChangeType))
|
||
{
|
||
//
|
||
// Default processing. Remove & Re-Read all VRoots. Expensive.
|
||
//
|
||
|
||
if ( !mb.Open( QueryMDPath(),
|
||
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Remove all of the old roots for this server
|
||
//
|
||
|
||
fRet = QueryVrootTable()->RemoveVirtualRoots();
|
||
|
||
if ( fRet )
|
||
{
|
||
QueryVrootTable()->LockExclusive();
|
||
if (NULL == pcoChangeList)
|
||
{
|
||
fRet = TsEnumVirtualRoots( TsAddVrootsWithScmUpdate, this, &mb );
|
||
}
|
||
else
|
||
{
|
||
fRet = TsEnumVirtualRoots( TsAddVroots, this, &mb );
|
||
}
|
||
QueryVrootTable()->Unlock();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
VIRTUAL_ROOT vr;
|
||
|
||
CHAR szUser[UNLEN+1];
|
||
CHAR szPassword[PWLEN+1];
|
||
CHAR szDirectory[MAX_PATH + UNLEN + 3];
|
||
DWORD dwMask;
|
||
BOOL fDoCache;
|
||
|
||
if (MD_CHANGE_TYPE_DELETE_OBJECT == pcoChangeList->dwMDChangeType)
|
||
{
|
||
return QueryVrootTable()->RemoveVirtualRoot(
|
||
(LPSTR)pcoChangeList->pszMDPath + QueryMDPathLen()
|
||
+ sizeof(IIS_MD_INSTANCE_ROOT)
|
||
);
|
||
}
|
||
|
||
if ( !mb.Open( (LPCSTR)pcoChangeList->pszMDPath,
|
||
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
if (!ReadVrootConfig( &mb,
|
||
"",
|
||
szDirectory,
|
||
sizeof(szDirectory),
|
||
szUser,
|
||
sizeof(szUser),
|
||
szPassword,
|
||
sizeof(szPassword),
|
||
&dwMask,
|
||
&fDoCache
|
||
))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
vr.pszAlias = (LPSTR)pcoChangeList->pszMDPath + QueryMDPathLen()
|
||
+ sizeof(IIS_MD_INSTANCE_ROOT);
|
||
vr.pszMetaPath = "";
|
||
vr.pszPath = szDirectory;
|
||
vr.dwAccessPerm = dwMask;
|
||
vr.pszUserName = szUser;
|
||
vr.pszPassword = szPassword;
|
||
vr.fDoCache = fDoCache;
|
||
|
||
if (pcoChangeList->dwMDChangeType & MD_CHANGE_TYPE_ADD_OBJECT)
|
||
{
|
||
fRet = TsAddVroots(this, &mb, &vr);
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Remove the original entry & re-read
|
||
//
|
||
|
||
if (!QueryVrootTable()->RemoveVirtualRoot(vr.pszAlias))
|
||
{
|
||
DBGPRINTF((DBG_CONTEXT,"Error %x removing vroot %s. \n",
|
||
GetLastError(), vr.pszMetaPath ));
|
||
}
|
||
|
||
fRet = TsAddVroots(this, &mb, &vr);
|
||
}
|
||
}
|
||
|
||
return fRet;
|
||
|
||
} // TsReadVirtualRoots
|
||
|
||
|
||
|
||
BOOL
|
||
TsAddVrootsWithScmUpdate(
|
||
PVOID pvContext,
|
||
MB * pmb,
|
||
VIRTUAL_ROOT * pvr
|
||
)
|
||
{
|
||
((IIS_SERVER_INSTANCE *) pvContext)->m_Service->StartUpIndicateClientActivity();
|
||
return TsAddVroots(pvContext,pmb,pvr);
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
TsAddVroots(
|
||
PVOID pvContext,
|
||
MB * pmb,
|
||
VIRTUAL_ROOT * pvr
|
||
)
|
||
{
|
||
DWORD err = NO_ERROR;
|
||
DWORD dwFileSystem;
|
||
BOOL fRet = FALSE;
|
||
HANDLE hToken = NULL;
|
||
|
||
|
||
|
||
//
|
||
// Clear this virtual directory's error status
|
||
//
|
||
|
||
if ( !pmb->SetDword( pvr->pszMetaPath,
|
||
MD_WIN32_ERROR,
|
||
IIS_MD_UT_SERVER,
|
||
NO_ERROR ))
|
||
{
|
||
DBGPRINTF((DBG_CONTEXT,"Error %x setting win32 status from %s. \n",
|
||
GetLastError(), pvr->pszMetaPath ));
|
||
return FALSE;
|
||
}
|
||
|
||
#if 0
|
||
if ( (pvr->pszUserName[0] != '\0') &&
|
||
(pvr->pszPath[0] == '\\') && (pvr->pszPath[1] == '\\') ) {
|
||
|
||
NETRESOURCE nr;
|
||
nr.dwScope = RESOURCE_CONNECTED;
|
||
nr.dwDisplayType = RESOURCEDISPLAYTYPE_GENERIC;
|
||
nr.dwType = RESOURCETYPE_DISK;
|
||
nr.lpLocalName = NULL;
|
||
nr.lpRemoteName = pvr->pszPath;
|
||
nr.lpComment = "";
|
||
nr.lpProvider = NULL;
|
||
|
||
//
|
||
// try disconnecting from the distant resource 1st
|
||
// (in case credentials have changed )
|
||
//
|
||
|
||
WNetCancelConnection2( pvr->pszPath, 0, TRUE );
|
||
|
||
//
|
||
// Connect to distant disk using specified account
|
||
//
|
||
|
||
if ( err = WNetAddConnection2( &nr,
|
||
pvr->pszPassword,
|
||
pvr->pszUserName,
|
||
0 ) )
|
||
{
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"Adding path %s err %d, user=%s, pwd=%d\n",
|
||
pvr->pszPath, err, pvr->pszUserName, pvr->pszPassword ));
|
||
|
||
//
|
||
// Log error
|
||
//
|
||
|
||
LogRootAddFailure( (IIS_SERVER_INSTANCE *) pvContext,
|
||
pvr->pszAlias,
|
||
pvr->pszPath,
|
||
err,
|
||
pvr->pszMetaPath,
|
||
pmb );
|
||
}
|
||
}
|
||
|
||
#else
|
||
|
||
if ( (pvr->pszUserName[0] != '\0') &&
|
||
(pvr->pszPath[0] == '\\') && (pvr->pszPath[1] == '\\') )
|
||
{
|
||
if ( g_fW3OnlyNoAuth )
|
||
{
|
||
hToken = NULL;
|
||
}
|
||
else
|
||
{
|
||
hToken = VrootLogonUser( pvr->pszUserName,
|
||
pvr->pszPassword );
|
||
|
||
if ( hToken == NULL)
|
||
{
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"Adding path %s err %d, user=%s, pwd=%d\n",
|
||
pvr->pszPath, GetLastError(), pvr->pszUserName, pvr->pszPassword ));
|
||
|
||
//
|
||
// Log error
|
||
//
|
||
|
||
LogRootAddFailure( (IIS_SERVER_INSTANCE *) pvContext,
|
||
pvr->pszAlias,
|
||
pvr->pszPath,
|
||
GetLastError(),
|
||
pvr->pszMetaPath,
|
||
pmb );
|
||
}
|
||
|
||
|
||
// Impersonate as user for GetFileSystemType()
|
||
if ( hToken != NULL && !ImpersonateLoggedOnUser(hToken))
|
||
{
|
||
err = GetLastError();
|
||
}
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
if ( err == NO_ERROR )
|
||
{
|
||
|
||
err = GetFileSystemType( pvr->pszPath, &dwFileSystem);
|
||
|
||
if ( err != NO_ERROR) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
" GetFileSystemType(%s) failed.Error = %u.\n",
|
||
pvr->pszPath,
|
||
err));
|
||
|
||
LogRootAddFailure( (IIS_SERVER_INSTANCE *) pvContext,
|
||
pvr->pszAlias,
|
||
pvr->pszPath,
|
||
err,
|
||
pvr->pszMetaPath,
|
||
pmb );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Don't add roots that are invalid
|
||
//
|
||
|
||
if ( err == NO_ERROR )
|
||
{
|
||
if ( !((IIS_SERVER_INSTANCE *) pvContext)->QueryVrootTable()->AddVirtualRoot(
|
||
pvr->pszAlias,
|
||
pvr->pszPath,
|
||
pvr->dwAccessPerm,
|
||
pvr->pszUserName,
|
||
hToken,
|
||
dwFileSystem,
|
||
pvr->fDoCache ))
|
||
{
|
||
err = GetLastError();
|
||
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
" AddVirtualRoot() failed. Error = %u.\n", err));
|
||
|
||
LogRootAddFailure( (IIS_SERVER_INSTANCE *) pvContext,
|
||
pvr->pszAlias,
|
||
pvr->pszPath,
|
||
err,
|
||
pvr->pszMetaPath,
|
||
pmb );
|
||
}
|
||
}
|
||
|
||
if ( hToken != NULL)
|
||
{
|
||
RevertToSelf();
|
||
}
|
||
|
||
if ( err == NO_ERROR )
|
||
{
|
||
fRet = TRUE;
|
||
}
|
||
|
||
return fRet;
|
||
|
||
} // TsAddVroots
|
||
|
||
|
||
BOOL
|
||
IIS_SERVER_INSTANCE::TsEnumVirtualRoots(
|
||
PFN_VR_ENUM pfnCallback,
|
||
VOID * pvContext,
|
||
MB * pmbWebSite
|
||
)
|
||
{
|
||
return TsRecursiveEnumVirtualRoots(
|
||
pfnCallback,
|
||
pvContext,
|
||
IIS_MD_INSTANCE_ROOT "/",
|
||
m_dwLevelsToScan,
|
||
(LPVOID)pmbWebSite,
|
||
TRUE );
|
||
}
|
||
|
||
|
||
BOOL
|
||
IIS_SERVER_INSTANCE::TsRecursiveEnumVirtualRoots(
|
||
PFN_VR_ENUM pfnCallback,
|
||
VOID * pvContext,
|
||
LPSTR pszCurrentPath,
|
||
DWORD dwLevelsToScan,
|
||
LPVOID pvMB,
|
||
BOOL fGetRoot
|
||
)
|
||
/*++
|
||
Description:
|
||
|
||
Enumerates all of the virtual directories defined for this server
|
||
instance
|
||
|
||
Arguments:
|
||
pfnCallback - Enumeration callback to call for each virtual directory
|
||
pvContext - Context pfnCallback receives
|
||
pszCurrentPath - path where to start scanning for VRoots
|
||
dwLevelsToScan - # of levels to scan recursively for vroots
|
||
pvMB - ptr to MB to access metabase. Is LPVOID to avoid having to include
|
||
mb.hxx before any ref to iistypes.hxx
|
||
fGetRoot - TRUE if pszCurrentPath is to be considered as vroot to process
|
||
|
||
Returns:
|
||
TRUE on success and FALSE if any failure.
|
||
|
||
--*/
|
||
{
|
||
|
||
DWORD err;
|
||
MB* pMB = (MB*)pvMB;
|
||
|
||
DWORD cb;
|
||
|
||
CHAR nameBuf[METADATA_MAX_NAME_LEN+2];
|
||
CHAR tmpBuf[sizeof(nameBuf)];
|
||
|
||
DWORD cbCurrentPath;
|
||
DWORD i = 0;
|
||
|
||
VIRTUAL_ROOT vr;
|
||
|
||
CHAR szUser[UNLEN+1];
|
||
CHAR szPassword[PWLEN+1];
|
||
CHAR szDirectory[MAX_PATH + UNLEN + 3];
|
||
DWORD dwMask;
|
||
BOOL fDoCache;
|
||
|
||
//
|
||
// Enumerate all of the listed items in the metabase
|
||
// and add them
|
||
//
|
||
|
||
cbCurrentPath = strlen( pszCurrentPath );
|
||
CopyMemory( nameBuf, pszCurrentPath, cbCurrentPath + 1);
|
||
|
||
while ( TRUE ) {
|
||
|
||
METADATA_RECORD mdRecord;
|
||
DWORD dwFileSystem = FS_ERROR;
|
||
|
||
err = NO_ERROR;
|
||
|
||
if ( fGetRoot ) {
|
||
|
||
fGetRoot = FALSE;
|
||
|
||
} else {
|
||
|
||
if ( !pMB->EnumObjects( pszCurrentPath,
|
||
nameBuf + cbCurrentPath,
|
||
i++ ))
|
||
{
|
||
break;
|
||
}
|
||
|
||
if ( dwLevelsToScan > 1 )
|
||
{
|
||
cb = strlen( nameBuf );
|
||
nameBuf[ cb ] = '/';
|
||
nameBuf[ cb + 1 ] = '\0';
|
||
|
||
if ( !TsRecursiveEnumVirtualRoots(
|
||
pfnCallback,
|
||
pvContext,
|
||
nameBuf,
|
||
dwLevelsToScan - 1,
|
||
pMB,
|
||
FALSE ) )
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
nameBuf[ cb ] = '\0';
|
||
}
|
||
}
|
||
|
||
if (!ReadVrootConfig( pvMB,
|
||
nameBuf,
|
||
szDirectory,
|
||
sizeof(szDirectory),
|
||
szUser,
|
||
sizeof(szUser),
|
||
szPassword,
|
||
sizeof(szPassword),
|
||
&dwMask,
|
||
&fDoCache
|
||
))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// Now set things up for the callback
|
||
//
|
||
|
||
DBG_ASSERT( !_strnicmp( nameBuf, IIS_MD_INSTANCE_ROOT, sizeof(IIS_MD_INSTANCE_ROOT) - 1));
|
||
|
||
//
|
||
// Add can modify the root - don't modify the working vroot path
|
||
//
|
||
|
||
strcpy( tmpBuf, nameBuf );
|
||
|
||
vr.pszAlias = tmpBuf + sizeof(IIS_MD_INSTANCE_ROOT) - 1;
|
||
vr.pszMetaPath = tmpBuf;
|
||
vr.pszPath = szDirectory;
|
||
vr.dwAccessPerm = dwMask;
|
||
vr.pszUserName = szUser;
|
||
vr.pszPassword = szPassword;
|
||
vr.fDoCache = fDoCache;
|
||
|
||
if ( !pfnCallback( pvContext, pMB, &vr ))
|
||
{
|
||
//
|
||
// !!! so what do we do here?
|
||
//
|
||
|
||
DBGPRINTF((DBG_CONTEXT,"EnumCallback returns FALSE\n"));
|
||
}
|
||
|
||
} // while
|
||
|
||
return TRUE;
|
||
|
||
} // Enum
|
||
|
||
|
||
|
||
VOID
|
||
LogRootAddFailure(
|
||
IN PIIS_SERVER_INSTANCE psi,
|
||
IN PCHAR pszRoot,
|
||
IN PCHAR pszDirectory,
|
||
IN DWORD err,
|
||
IN PCHAR pszMetaPath,
|
||
IN MB * pmb
|
||
)
|
||
{
|
||
const CHAR * apsz[3];
|
||
STR strError;
|
||
|
||
psi->LoadStr( strError, err, FALSE ); // loads ANSI message. Convert to UNICODE
|
||
|
||
apsz[0] = pszRoot;
|
||
apsz[1] = pszDirectory;
|
||
apsz[2] = strError.QueryStrA();
|
||
|
||
psi->m_Service->LogEvent( INET_SVC_ADD_VIRTUAL_ROOT_FAILED,
|
||
3,
|
||
apsz,
|
||
err );
|
||
|
||
//
|
||
// Indicate the error on this virtual directory
|
||
//
|
||
|
||
if ( !pmb->SetDword( pszMetaPath,
|
||
MD_WIN32_ERROR,
|
||
IIS_MD_UT_SERVER,
|
||
err ))
|
||
{
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"LogRootAddFailure: Unable to set win32 status\n" ));
|
||
}
|
||
} // LogRootAddFailure
|
||
|
||
|
||
BOOL
|
||
RetrieveRootPassword(
|
||
PCHAR pszRoot,
|
||
PCHAR pszPassword,
|
||
PWCHAR pszSecret
|
||
)
|
||
/*++
|
||
Description:
|
||
|
||
This function retrieves the password for the specified root & address
|
||
|
||
Arguments:
|
||
|
||
pszRoot - Name of root + address in the form "/root,<address>".
|
||
pszPassword - Receives password, must be at least PWLEN+1 characters
|
||
pszSecret - Virtual Root password secret name
|
||
|
||
Returns:
|
||
TRUE on success and FALSE if any failure.
|
||
|
||
--*/
|
||
{
|
||
BUFFER bufSecret;
|
||
WCHAR * psz;
|
||
WCHAR * pszTerm;
|
||
WCHAR * pszNextLine;
|
||
WCHAR wsRoot[MAX_PATH+1];
|
||
|
||
DWORD cch;
|
||
|
||
if ( !TsGetSecretW( pszSecret,
|
||
&bufSecret ))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Convert root to WCHAR
|
||
//
|
||
|
||
cch = MultiByteToWideChar( CP_ACP,
|
||
MB_PRECOMPOSED,
|
||
pszRoot,
|
||
-1,
|
||
wsRoot,
|
||
MAX_PATH+1 );
|
||
|
||
wsRoot[cch] = L'\0';
|
||
if ( cch == 0 ) {
|
||
return FALSE;
|
||
}
|
||
|
||
psz = (WCHAR *) bufSecret.QueryPtr();
|
||
|
||
//
|
||
// Scan the list of roots looking for a match. The list looks like:
|
||
//
|
||
// <root>,<address>=<password>\0
|
||
// <root>,<address>=<password>\0
|
||
// \0
|
||
//
|
||
|
||
while ( *psz )
|
||
{
|
||
PWCHAR pszComma;
|
||
|
||
pszNextLine = psz + wcslen(psz) + 1;
|
||
|
||
pszTerm = wcschr( psz, L'=' );
|
||
|
||
if ( !pszTerm )
|
||
goto NextLine;
|
||
|
||
*pszTerm = L'\0';
|
||
|
||
//
|
||
// remove the ,
|
||
//
|
||
|
||
pszComma = wcschr( psz, L',' );
|
||
if ( pszComma != NULL ) {
|
||
*pszComma = '\0';
|
||
}
|
||
|
||
if ( !_wcsicmp( wsRoot, psz ) )
|
||
{
|
||
|
||
//
|
||
// We found a match, copy the password
|
||
//
|
||
|
||
(VOID) ConvertUnicodeToAnsi(
|
||
pszTerm + 1,
|
||
pszPassword,
|
||
PWLEN + sizeof(CHAR));
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
NextLine:
|
||
psz = pszNextLine;
|
||
}
|
||
|
||
//
|
||
// If the matching root wasn't found, default to the empty password
|
||
//
|
||
|
||
*pszPassword = '\0';
|
||
return TRUE;
|
||
|
||
} // RetrieveRootPassword
|
||
|
||
|
||
|
||
BOOL
|
||
IIS_SERVER_INSTANCE::TsSetVirtualRoots(
|
||
IN LPINETA_CONFIG_INFO pConfig
|
||
)
|
||
/*++
|
||
Description:
|
||
|
||
Writes the virtual roots specified in the config structure to the
|
||
registry
|
||
|
||
NOTE: This is basically legacy code for the IIS 3.0 RPC interface.
|
||
|
||
Arguments:
|
||
pConfig - new list of virtual
|
||
|
||
Returns:
|
||
TRUE on success and FALSE if any failure.
|
||
|
||
--*/
|
||
{
|
||
DWORD err;
|
||
DWORD dwDummy;
|
||
LPINET_INFO_VIRTUAL_ROOT_LIST pRootsList;
|
||
DWORD cch;
|
||
DWORD i;
|
||
DWORD dwMask;
|
||
DWORD sentinelValue = 7777777;
|
||
IWamAdmin* pIWamAdmin = NULL;
|
||
MB mb( (IMDCOM*) m_Service->QueryMDObject() );
|
||
HRESULT hr = NOERROR;
|
||
STR strTmp;
|
||
|
||
//
|
||
// Do the metabase
|
||
//
|
||
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"Setting VR data on %s\n",
|
||
QueryMDPath()));
|
||
}
|
||
|
||
if ( !mb.Open( QueryMDPath(),
|
||
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ))
|
||
{
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"Open MD instance root %s returns %d\n",
|
||
QueryMDPath(), GetLastError() ));
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// We need to create an application for each new virtual root set via
|
||
// the IIS 3.0 RPC interface for ASP compatability
|
||
//
|
||
|
||
hr = CoCreateInstance(CLSID_WamAdmin,
|
||
NULL,
|
||
CLSCTX_SERVER,
|
||
IID_IWamAdmin,
|
||
(void **)&pIWamAdmin);
|
||
|
||
if ( FAILED(hr) )
|
||
{
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"Failed to create WamAdmin interface, error %08lx\n",
|
||
hr ));
|
||
|
||
SetLastError( hr );
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// See if we need to delete any VRs
|
||
//
|
||
|
||
pRootsList = pConfig->VirtualRoots;
|
||
|
||
if ( (pRootsList == NULL) || (pRootsList->cEntries == 0) ) {
|
||
|
||
//
|
||
// NO VRs. Delete the entire VR tree
|
||
//
|
||
|
||
if ( !mb.DeleteObject( IIS_MD_INSTANCE_ROOT ) )
|
||
{
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,
|
||
"Deleting VR root returns %d\n",GetLastError()));
|
||
}
|
||
}
|
||
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"Empty list set on %s\n", QueryMDPath()));
|
||
}
|
||
|
||
goto exit;
|
||
|
||
} else {
|
||
|
||
//
|
||
// Remove our secret value
|
||
//
|
||
|
||
ClearSentinelEntry( &mb );
|
||
}
|
||
|
||
for ( i = 0; i < pRootsList->cEntries; i++ ) {
|
||
|
||
CHAR tmpRoot[MAX_PATH+1];
|
||
CHAR tmpBuffer[MAX_PATH+1];
|
||
BOOL fCreateApp = FALSE;
|
||
|
||
DWORD rootLen;
|
||
|
||
//
|
||
// strings to ANSI
|
||
//
|
||
|
||
#define VROOT_ROOT IIS_MD_INSTANCE_ROOT
|
||
#define CCH_VROOT_ROOT (sizeof(VROOT_ROOT) - 1)
|
||
|
||
strcpy( tmpRoot, VROOT_ROOT );
|
||
|
||
(VOID) ConvertUnicodeToAnsi(
|
||
pRootsList->aVirtRootEntry[i].pszRoot,
|
||
&tmpRoot[CCH_VROOT_ROOT],
|
||
MAX_PATH);
|
||
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"Setting data for root %s\n",tmpRoot));
|
||
}
|
||
|
||
rootLen = strlen(tmpRoot);
|
||
|
||
//
|
||
// Create the root
|
||
//
|
||
|
||
if ( !mb.AddObject( tmpRoot ) &&
|
||
(GetLastError() != ERROR_ALREADY_EXISTS) )
|
||
{
|
||
|
||
DBGPRINTF((DBG_CONTEXT,"AddMetaObject %s failed with %d\n",
|
||
tmpRoot, GetLastError() ));
|
||
goto exit;
|
||
}
|
||
|
||
//
|
||
// Set sentinel entry
|
||
//
|
||
|
||
if ( !mb.SetDword( tmpRoot,
|
||
MD_VR_UPDATE,
|
||
IIS_MD_UT_FILE,
|
||
sentinelValue,
|
||
0 ))
|
||
{
|
||
DBGPRINTF((DBG_CONTEXT,
|
||
"Error %d setting sentinel value %x for %s\n",
|
||
GetLastError(), sentinelValue, tmpRoot));
|
||
|
||
goto exit;
|
||
}
|
||
|
||
//
|
||
// Set Path
|
||
//
|
||
|
||
(VOID) ConvertUnicodeToAnsi(
|
||
pRootsList->aVirtRootEntry[i].pszDirectory,
|
||
tmpBuffer,
|
||
MAX_PATH+1);
|
||
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"Directory path is %s\n",tmpBuffer));
|
||
}
|
||
|
||
//
|
||
// Check to see if the path property already exists - if it does
|
||
// then we won't create the application - only new virtual directories
|
||
// get an application created for them
|
||
//
|
||
|
||
if ( !mb.GetStr( tmpRoot,
|
||
MD_VR_PATH,
|
||
IIS_MD_UT_FILE,
|
||
&strTmp,
|
||
METADATA_NO_ATTRIBUTES ))
|
||
{
|
||
fCreateApp = TRUE;
|
||
}
|
||
|
||
if ( !mb.SetString( tmpRoot,
|
||
MD_VR_PATH,
|
||
IIS_MD_UT_FILE,
|
||
tmpBuffer ))
|
||
{
|
||
DBGPRINTF((DBG_CONTEXT,"Error %d setting path[%s] for %s\n",
|
||
GetLastError(), tmpBuffer, tmpRoot));
|
||
}
|
||
|
||
if ( !mb.SetString( tmpRoot,
|
||
MD_KEY_TYPE,
|
||
IIS_MD_UT_SERVER,
|
||
"IIsWebVirtualDir" ))
|
||
{
|
||
DBGPRINTF((DBG_CONTEXT,"Error %d setting ADSI type for %s\n",
|
||
GetLastError(), tmpRoot));
|
||
}
|
||
|
||
|
||
//
|
||
// Set Username
|
||
//
|
||
|
||
(VOID) ConvertUnicodeToAnsi(
|
||
pRootsList->aVirtRootEntry[i].pszAccountName,
|
||
tmpBuffer,
|
||
MAX_PATH+1);
|
||
|
||
if ( !mb.SetString( tmpRoot,
|
||
MD_VR_USERNAME,
|
||
IIS_MD_UT_FILE,
|
||
tmpBuffer ))
|
||
{
|
||
DBGPRINTF((DBG_CONTEXT,"Error %d setting username for %s\n",
|
||
GetLastError(), tmpRoot));
|
||
}
|
||
|
||
//
|
||
// Set Mask
|
||
//
|
||
|
||
if ( !mb.SetDword( tmpRoot,
|
||
MD_ACCESS_PERM,
|
||
IIS_MD_UT_FILE,
|
||
pRootsList->aVirtRootEntry[i].dwMask ))
|
||
{
|
||
DBGPRINTF((DBG_CONTEXT,"Error %d setting mask for %s\n",
|
||
GetLastError(), tmpRoot));
|
||
}
|
||
|
||
if ( fCreateApp )
|
||
{
|
||
WCHAR wchFullPath[MAX_PATH];
|
||
|
||
strcpy( tmpRoot, QueryMDPath() );
|
||
strcat( tmpRoot, "/" VROOT_ROOT );
|
||
|
||
if ( MultiByteToWideChar( CP_ACP,
|
||
MB_PRECOMPOSED,
|
||
tmpRoot,
|
||
-1,
|
||
wchFullPath,
|
||
sizeof( wchFullPath ) / sizeof(WCHAR) ))
|
||
{
|
||
wcscat( wchFullPath, pRootsList->aVirtRootEntry[i].pszRoot );
|
||
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"Creating application at %S\n",
|
||
wchFullPath ));
|
||
|
||
//
|
||
// We need to close our metabase handle so WAM can create
|
||
// the in process application
|
||
//
|
||
|
||
DBG_REQUIRE( mb.Close() );
|
||
|
||
hr = pIWamAdmin->AppCreate( wchFullPath, TRUE);
|
||
|
||
if ( FAILED( hr ))
|
||
{
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"Failed to create application, error %08lx\n",
|
||
hr ));
|
||
}
|
||
|
||
//
|
||
// Reopen the metabase for the next vroot
|
||
//
|
||
|
||
if ( !mb.Open( QueryMDPath(),
|
||
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ))
|
||
{
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"Open MD instance root %s returns %d\n",
|
||
QueryMDPath(), GetLastError() ));
|
||
}
|
||
|
||
goto exit;
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Delete entries that do not have the sentinel entry
|
||
//
|
||
|
||
RemoveUnmarkedRoots( &mb );
|
||
|
||
exit:
|
||
|
||
//
|
||
// If this is the downlevel instance, mirror it to the registry
|
||
//
|
||
|
||
if ( IsDownLevelInstance() ) {
|
||
TsMirrorVirtualRoots( pConfig );
|
||
}
|
||
|
||
if ( pIWamAdmin ) {
|
||
pIWamAdmin->Release();
|
||
}
|
||
|
||
return TRUE;
|
||
|
||
} // IIS_SERVER_INSTANCE::TsSetVirtualRoots
|
||
|
||
|
||
DWORD
|
||
GetFileSystemType(
|
||
IN LPCSTR pszRealPath,
|
||
OUT LPDWORD lpdwFileSystem
|
||
)
|
||
/*++
|
||
Gets file system specific information for a given path.
|
||
It uses GetVolumeInfomration() to query the file system type
|
||
and file system flags.
|
||
On success the flags and file system type are returned in
|
||
passed in pointers.
|
||
|
||
Arguments:
|
||
|
||
pszRealPath pointer to buffer containing path for which
|
||
we are inquiring the file system details.
|
||
|
||
lpdwFileSystem
|
||
pointer to buffer to fill in the type of file system.
|
||
|
||
Returns:
|
||
NO_ERROR on success and Win32 error code if any error.
|
||
|
||
--*/
|
||
{
|
||
# define MAX_FILE_SYSTEM_NAME_SIZE ( MAX_PATH)
|
||
|
||
CHAR rgchBuf[MAX_FILE_SYSTEM_NAME_SIZE];
|
||
CHAR rgchRoot[MAX_FILE_SYSTEM_NAME_SIZE];
|
||
int i;
|
||
DWORD dwReturn = ERROR_PATH_NOT_FOUND;
|
||
DWORD len;
|
||
|
||
if ( (pszRealPath == NULL) || (lpdwFileSystem == NULL)) {
|
||
return ( ERROR_INVALID_PARAMETER);
|
||
}
|
||
|
||
ZeroMemory( rgchRoot, sizeof(rgchRoot) );
|
||
*lpdwFileSystem = FS_ERROR;
|
||
|
||
//
|
||
// Copy just the root directory to rgchRoot for querying
|
||
//
|
||
|
||
IF_DEBUG( DLL_VIRTUAL_ROOTS) {
|
||
DBGPRINTF( ( DBG_CONTEXT, " GetFileSystemType(%s).\n", pszRealPath));
|
||
}
|
||
|
||
if ( (pszRealPath[0] == '\\') &&
|
||
(pszRealPath[1] == '\\')) {
|
||
|
||
PCHAR pszEnd;
|
||
|
||
//
|
||
// this is an UNC name. Extract just the first two components
|
||
//
|
||
//
|
||
|
||
pszEnd = strchr( pszRealPath+2, '\\');
|
||
|
||
if ( pszEnd == NULL) {
|
||
|
||
// just the server name present
|
||
|
||
return ( ERROR_INVALID_PARAMETER);
|
||
}
|
||
|
||
#if 1 // DBCS enabling for share name
|
||
pszEnd = (PCHAR)_mbschr( (PUCHAR)pszEnd+1, '\\');
|
||
#else
|
||
pszEnd = strchr( pszEnd+1, '\\');
|
||
#endif
|
||
|
||
len = ( ( pszEnd == NULL) ? strlen(pszRealPath)
|
||
: (DIFF(pszEnd - pszRealPath) + 1) );
|
||
|
||
//
|
||
// Copy till the end of UNC Name only (exclude all other path info)
|
||
//
|
||
|
||
if ( len < (MAX_FILE_SYSTEM_NAME_SIZE - 1) ) {
|
||
|
||
CopyMemory( rgchRoot, pszRealPath, len);
|
||
rgchRoot[len] = '\0';
|
||
} else {
|
||
|
||
return ( ERROR_INVALID_NAME);
|
||
}
|
||
|
||
#if 1 // DBCS enabling for share name
|
||
if ( *CharPrev( rgchRoot, rgchRoot + len ) != '\\' ) {
|
||
#else
|
||
if ( rgchRoot[len - 1] != '\\' ) {
|
||
#endif
|
||
|
||
if ( len < MAX_FILE_SYSTEM_NAME_SIZE - 2 ) {
|
||
rgchRoot[len] = '\\';
|
||
rgchRoot[len+1] = '\0';
|
||
} else {
|
||
|
||
return (ERROR_INVALID_NAME);
|
||
}
|
||
}
|
||
} else {
|
||
|
||
//
|
||
// This is non UNC name.
|
||
// Copy just the root directory to rgchRoot for querying
|
||
//
|
||
|
||
|
||
for( i = 0; i < 9 && pszRealPath[i] != '\0'; i++) {
|
||
|
||
if ( (rgchRoot[i] = pszRealPath[i]) == ':') {
|
||
|
||
break;
|
||
}
|
||
} // for
|
||
|
||
|
||
if ( rgchRoot[i] != ':') {
|
||
|
||
//
|
||
// we could not find the root directory.
|
||
// return with error value
|
||
//
|
||
|
||
return ( ERROR_INVALID_PARAMETER);
|
||
}
|
||
|
||
rgchRoot[i+1] = '\\'; // terminate the drive spec with a slash
|
||
rgchRoot[i+2] = '\0'; // terminate the drive spec with null char
|
||
|
||
} // else
|
||
|
||
IF_DEBUG( DLL_VIRTUAL_ROOTS) {
|
||
DBGPRINTF( ( DBG_CONTEXT, " GetVolumeInformation(%s).\n",
|
||
rgchRoot));
|
||
}
|
||
|
||
//
|
||
// The rgchRoot should end with a "\" (slash)
|
||
// otherwise, the call will fail.
|
||
//
|
||
|
||
if ( GetVolumeInformation( rgchRoot, // lpRootPathName
|
||
NULL, // lpVolumeNameBuffer
|
||
0, // len of volume name buffer
|
||
NULL, // lpdwVolSerialNumber
|
||
NULL, // lpdwMaxComponentLength
|
||
NULL, // lpdwSystemFlags
|
||
rgchBuf, // lpFileSystemNameBuff
|
||
sizeof(rgchBuf)
|
||
) ) {
|
||
|
||
|
||
|
||
dwReturn = NO_ERROR;
|
||
|
||
if ( strcmp( rgchBuf, "FAT") == 0) {
|
||
|
||
*lpdwFileSystem = FS_FAT;
|
||
|
||
} else if ( strcmp( rgchBuf, "NTFS") == 0) {
|
||
|
||
*lpdwFileSystem = FS_NTFS;
|
||
|
||
} else if ( strcmp( rgchBuf, "HPFS") == 0) {
|
||
|
||
*lpdwFileSystem = FS_HPFS;
|
||
|
||
} else if ( strcmp( rgchBuf, "CDFS") == 0) {
|
||
|
||
*lpdwFileSystem = FS_CDFS;
|
||
|
||
} else if ( strcmp( rgchBuf, "OFS") == 0) {
|
||
|
||
*lpdwFileSystem = FS_OFS;
|
||
|
||
} else {
|
||
|
||
*lpdwFileSystem = FS_FAT;
|
||
}
|
||
|
||
} else {
|
||
|
||
dwReturn = GetLastError();
|
||
|
||
IF_DEBUG( DLL_VIRTUAL_ROOTS) {
|
||
|
||
DBGPRINTF( ( DBG_CONTEXT,
|
||
" GetVolumeInformation( %s) failed with error %d\n",
|
||
rgchRoot, dwReturn));
|
||
}
|
||
|
||
}
|
||
|
||
return ( dwReturn);
|
||
} // GetFileSystemType()
|
||
|
||
|
||
HANDLE
|
||
VrootLogonUser(
|
||
IN CHAR * pszUser,
|
||
IN CHAR * pszPassword
|
||
)
|
||
/*++
|
||
This function uses the given parameters and logs on to generate
|
||
a user handle for the account.
|
||
|
||
Arguments:
|
||
pszUser - pointer to string containing the user name.
|
||
pszPassword - pointer to string containing the password.
|
||
|
||
Returns:
|
||
Handle for the logged on user on success.
|
||
Returns NULL for errors.
|
||
|
||
History:
|
||
MuraliK 18-Jan-1996 Created.
|
||
--*/
|
||
{
|
||
CHAR szDomainAndUser[IIS_DNLEN+UNLEN+2];
|
||
CHAR * pszUserOnly;
|
||
CHAR * pszDomain;
|
||
HANDLE hToken = NULL;
|
||
BOOL fReturn;
|
||
|
||
//
|
||
// Validate parameters & state.
|
||
//
|
||
|
||
DBG_ASSERT( pszUser != NULL && *pszUser != '\0');
|
||
DBG_ASSERT( strlen(pszUser) < sizeof(szDomainAndUser) );
|
||
DBG_ASSERT( pszPassword != NULL);
|
||
DBG_ASSERT( strlen(pszPassword) <= PWLEN );
|
||
|
||
//
|
||
// Save a copy of the domain\user so we can squirrel around
|
||
// with it a bit.
|
||
//
|
||
|
||
strcpy( szDomainAndUser, pszUser );
|
||
|
||
//
|
||
// Crack the name into domain/user components.
|
||
// Then try and logon as the specified user.
|
||
//
|
||
|
||
fReturn = ( CrackUserAndDomain( szDomainAndUser,
|
||
&pszUserOnly,
|
||
&pszDomain ) &&
|
||
LogonUserA(pszUserOnly,
|
||
pszDomain,
|
||
pszPassword,
|
||
LOGON32_LOGON_INTERACTIVE, //LOGON32_LOGON_NETWORK,
|
||
LOGON32_PROVIDER_DEFAULT,
|
||
&hToken )
|
||
);
|
||
|
||
if ( !fReturn) {
|
||
|
||
//
|
||
// Logon user failed.
|
||
//
|
||
|
||
IF_DEBUG( DLL_SECURITY) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
" CrachUserAndDomain/LogonUser (%s) failed Error=%d\n",
|
||
pszUser, GetLastError()));
|
||
}
|
||
|
||
hToken = NULL;
|
||
} else {
|
||
HANDLE hImpersonation = NULL;
|
||
|
||
// we need to obtain the impersonation token, the primary token cannot
|
||
// be used for a lot of purposes :(
|
||
if (!pfnDuplicateTokenEx( hToken, // hSourceToken
|
||
TOKEN_ALL_ACCESS,
|
||
NULL,
|
||
SecurityImpersonation, // Obtain impersonation
|
||
TokenImpersonation,
|
||
&hImpersonation) // hDestinationToken
|
||
) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"Creating ImpersonationToken failed. Error = %d\n",
|
||
GetLastError()
|
||
));
|
||
|
||
// cleanup and exit.
|
||
hImpersonation = NULL;
|
||
|
||
// Fall through for cleanup
|
||
}
|
||
|
||
//
|
||
// close original token. If Duplicate was successful,
|
||
// we should have ref in the hImpersonation.
|
||
// Send the impersonation token to the client.
|
||
//
|
||
CloseHandle( hToken);
|
||
hToken = hImpersonation;
|
||
}
|
||
|
||
|
||
//
|
||
// Success!
|
||
//
|
||
|
||
return hToken;
|
||
|
||
} // VrootLogonUser()
|
||
|
||
DWORD
|
||
hextointW(
|
||
WCHAR * pch
|
||
)
|
||
{
|
||
WCHAR * pchStart;
|
||
DWORD sum = 0;
|
||
DWORD mult = 1;
|
||
|
||
while ( *pch == L' ' )
|
||
pch++;
|
||
|
||
pchStart = pch;
|
||
|
||
while ( iswxdigit( *pch ) )
|
||
pch++;
|
||
|
||
while ( --pch >= pchStart )
|
||
{
|
||
sum += mult * ( *pch >= L'A' ? *pch + 10 - L'A' :
|
||
*pch - L'0' );
|
||
mult *= 16;
|
||
}
|
||
|
||
return sum;
|
||
}
|
||
|
||
|
||
|
||
DWORD
|
||
hextointA(
|
||
CHAR * pch
|
||
)
|
||
{
|
||
CHAR * pchStart;
|
||
DWORD sum = 0;
|
||
DWORD mult = 1;
|
||
|
||
while ( *pch == ' ' )
|
||
pch++;
|
||
|
||
pchStart = pch;
|
||
|
||
while ( isxdigit( (UCHAR)(*pch) ) )
|
||
pch++;
|
||
|
||
while ( --pch >= pchStart )
|
||
{
|
||
sum += mult * ( *pch >= 'A' ? *pch + 10 - 'A' :
|
||
*pch - '0' );
|
||
mult *= 16;
|
||
}
|
||
|
||
return sum;
|
||
|
||
} // hextointA
|
||
|
||
|
||
|
||
|
||
BOOL
|
||
IIS_SERVER_INSTANCE::MoveVrootFromRegToMD(
|
||
VOID
|
||
)
|
||
{
|
||
DBGPRINTF((DBG_CONTEXT,"MoveVrootFromRegToMD called!!!\n"));
|
||
return(TRUE);
|
||
|
||
} // IIS_SERVER_INSTANCE::MoveVrootFromRegToMD
|
||
|
||
|
||
BOOL
|
||
TsCopyVrootToRegistry(
|
||
PVOID pvContext,
|
||
MB * pmb,
|
||
VIRTUAL_ROOT * pvr
|
||
)
|
||
{
|
||
|
||
DWORD cch;
|
||
DWORD err;
|
||
HKEY hkey = (HKEY)pvContext;
|
||
CHAR szValue[ MAX_PATH + UNLEN + 2 ];
|
||
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"CopyVrootToReg: Adding %s to registry\n",
|
||
pvr->pszAlias));
|
||
}
|
||
|
||
cch = wsprintfA( szValue,
|
||
"%s,%s,%X",
|
||
pvr->pszPath,
|
||
pvr->pszUserName,
|
||
pvr->dwAccessPerm );
|
||
|
||
DBG_ASSERT( cch < sizeof( szValue ) );
|
||
|
||
err = WriteRegistryStringA(hkey,
|
||
pvr->pszAlias,
|
||
szValue,
|
||
strlen(szValue),
|
||
REG_SZ);
|
||
|
||
DBG_ASSERT(err == NO_ERROR);
|
||
|
||
return(TRUE);
|
||
|
||
} // TsCopyVrootToRegistry
|
||
|
||
|
||
|
||
BOOL
|
||
IIS_SERVER_INSTANCE::MoveMDVroots2Registry(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Moves MD VR entries to the registry if registry VR key
|
||
does not exist at startup.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
|
||
HKEY hkey = NULL;
|
||
HKEY hkeyRoots = NULL;
|
||
DWORD dwDisp;
|
||
DWORD err;
|
||
BOOL fMigrated = FALSE;
|
||
|
||
MB mb( (IMDCOM*) m_Service->QueryMDObject() );
|
||
|
||
DBG_ASSERT(IsDownLevelInstance());
|
||
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"Entering MoveMDToRegAtStartup.\n"));
|
||
}
|
||
|
||
//
|
||
// see if the key exists
|
||
//
|
||
|
||
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
||
m_Service->QueryRegParamKey( ),
|
||
0,
|
||
KEY_READ|KEY_WRITE,
|
||
&hkey );
|
||
|
||
if ( err != NO_ERROR ) {
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"RegOpenKeyEx %s returned error %d\n",
|
||
m_Service->QueryRegParamKey(), err ));
|
||
|
||
goto exit;
|
||
}
|
||
|
||
//
|
||
// VR key?
|
||
//
|
||
|
||
err = RegCreateKeyEx( hkey,
|
||
VIRTUAL_ROOTS_KEY_A,
|
||
0,
|
||
NULL,
|
||
0,
|
||
KEY_READ|KEY_WRITE,
|
||
NULL,
|
||
&hkeyRoots,
|
||
&dwDisp );
|
||
|
||
if ( err != NO_ERROR ) {
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,
|
||
"Error %d in RegCreateKeyEx\n",err));
|
||
}
|
||
|
||
goto exit;
|
||
}
|
||
|
||
#if 0
|
||
Removing this if will mean everytime the server starts we migrate the registry
|
||
keys to the metabase. The only side effect this has is if somebody deleted the
|
||
a virtual directory from the metabase w/o the server started, that key will be
|
||
migrated back from the registry. With the server running it's not a big deal
|
||
since the server always mirrors the metabase to the registry on vroot changes.
|
||
|
||
if ( dwDisp == REG_OPENED_EXISTING_KEY ) {
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,
|
||
"Registry VR key found, aborting startup migration.\n"));
|
||
}
|
||
|
||
goto exit;
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Get the MD handle to the VR root
|
||
//
|
||
|
||
if ( !mb.Open( QueryMDPath(),
|
||
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ))
|
||
{
|
||
DBGPRINTF((DBG_CONTEXT,"Open MD vr root returns %d\n",GetLastError()));
|
||
goto exit;
|
||
}
|
||
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"Opening MD path[%s]\n",QueryMDPath()));
|
||
}
|
||
|
||
TsRecursiveEnumVirtualRoots(
|
||
TsCopyVrootToRegistry,
|
||
hkeyRoots,
|
||
IIS_MD_INSTANCE_ROOT "/",
|
||
1,
|
||
(LPVOID)&mb,
|
||
TRUE );
|
||
|
||
mb.Close();
|
||
fMigrated = TRUE;
|
||
|
||
exit:
|
||
|
||
if ( hkey != NULL ) {
|
||
RegCloseKey(hkey);
|
||
}
|
||
|
||
if ( hkeyRoots != NULL ) {
|
||
RegCloseKey(hkeyRoots);
|
||
}
|
||
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"Leaving MoveMDToRegAtStartup.\n"));
|
||
}
|
||
return(fMigrated);
|
||
|
||
} // IIS_SERVER_INSTANCE::MoveMDVroots2Registry
|
||
|
||
|
||
|
||
VOID
|
||
IIS_SERVER_INSTANCE::PdcHackVRReg2MD(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Moves VR entries to the MD at startup.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
DWORD err;
|
||
CHAR pszRoot[MAX_LENGTH_VIRTUAL_ROOT + MAX_LENGTH_ROOT_ADDR + 2];
|
||
CHAR pszDirectory[MAX_PATH + UNLEN + 3];
|
||
|
||
CHAR * pszUser;
|
||
DWORD cchRoot;
|
||
DWORD cchDir;
|
||
DWORD cch;
|
||
BOOL fRet = TRUE;
|
||
DWORD i = 0;
|
||
DWORD dwRegType;
|
||
|
||
DWORD dwMask;
|
||
PCHAR pszMask;
|
||
PCHAR tmpRoot;
|
||
DWORD dwAuthorization;
|
||
MB mb( (IMDCOM*) m_Service->QueryMDObject() );
|
||
|
||
HKEY hkey = NULL;
|
||
HKEY hkeyRoots = NULL;
|
||
|
||
DBG_ASSERT(IsDownLevelInstance());
|
||
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"In MoveVrootFromRegToMD\n"));
|
||
}
|
||
|
||
//
|
||
// see if the key exists
|
||
//
|
||
|
||
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
||
m_Service->QueryRegParamKey( ),
|
||
0,
|
||
KEY_READ,
|
||
&hkey );
|
||
|
||
if ( err != NO_ERROR ) {
|
||
DBGPRINTF(( DBG_CONTEXT, "RegOpenKeyEx returned error %d\n",err ));
|
||
return;
|
||
}
|
||
|
||
//
|
||
// VR key?
|
||
//
|
||
|
||
if ( err = RegOpenKeyEx( hkey,
|
||
VIRTUAL_ROOTS_KEY_A,
|
||
0,
|
||
KEY_READ,
|
||
&hkeyRoots )) {
|
||
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"RegOpenKeyEx %s failed with %d\n",
|
||
VIRTUAL_ROOTS_KEY_A, err));
|
||
}
|
||
goto exit;
|
||
}
|
||
|
||
//
|
||
// Key exists. Get the authorization key
|
||
//
|
||
|
||
{
|
||
HKEY instanceKey;
|
||
|
||
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
||
QueryRegParamKey(),
|
||
0,
|
||
KEY_ALL_ACCESS,
|
||
&instanceKey );
|
||
|
||
if ( err != NO_ERROR ) {
|
||
goto exit;
|
||
}
|
||
|
||
dwAuthorization = ReadRegistryDword( instanceKey,
|
||
INETA_AUTHENTICATION,
|
||
INET_INFO_AUTH_ANONYMOUS );
|
||
|
||
RegCloseKey( instanceKey );
|
||
}
|
||
|
||
//
|
||
// Get the MD handle to the VR root
|
||
//
|
||
|
||
if ( !mb.Open( QueryMDPath(),
|
||
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ))
|
||
{
|
||
DBGPRINTF((DBG_CONTEXT,"Open MD vr root returns %d\n",GetLastError()));
|
||
goto exit;
|
||
}
|
||
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"Adding MD path[%s]\n",QueryMDPath()));
|
||
}
|
||
|
||
//
|
||
// Enumerate all of the listed items in the registry
|
||
// and add them
|
||
//
|
||
|
||
strcpy( pszRoot, IIS_MD_INSTANCE_ROOT );
|
||
tmpRoot = (PCHAR)pszRoot+sizeof( IIS_MD_INSTANCE_ROOT ) - 1;
|
||
|
||
while ( TRUE ) {
|
||
|
||
PCHAR pszComma;
|
||
|
||
cchRoot = sizeof( pszRoot ) - 1;
|
||
cchDir = sizeof( pszDirectory );
|
||
|
||
err = RegEnumValue( hkeyRoots,
|
||
i++,
|
||
tmpRoot,
|
||
&cchRoot,
|
||
NULL,
|
||
&dwRegType,
|
||
(LPBYTE) pszDirectory,
|
||
&cchDir );
|
||
|
||
if ( err == ERROR_NO_MORE_ITEMS ) {
|
||
break;
|
||
}
|
||
|
||
if ( dwRegType == REG_SZ ) {
|
||
|
||
//
|
||
// The optional user name is kept after the directory.
|
||
// Only used for UNC roots, ignore for others
|
||
//
|
||
|
||
if ( pszUser = strchr( pszDirectory, ',' ) )
|
||
{
|
||
*pszUser = '\0';
|
||
pszUser++;
|
||
} else {
|
||
pszUser = "";
|
||
}
|
||
|
||
//
|
||
// The optional access mask is kept after the user name. It must
|
||
// appear in upper case hex.
|
||
//
|
||
|
||
if ( pszUser && (pszMask = strchr( pszUser, ',' )) ) {
|
||
|
||
*pszMask = '\0';
|
||
pszMask++;
|
||
|
||
dwMask = hextointA( pszMask );
|
||
} else {
|
||
dwMask = VROOT_MASK_READ;
|
||
}
|
||
|
||
//
|
||
// Remove commas from the root
|
||
//
|
||
|
||
pszComma = strchr(tmpRoot, ',');
|
||
if ( pszComma != NULL ) {
|
||
*pszComma = '\0';
|
||
cchRoot--;
|
||
}
|
||
|
||
//
|
||
// Write it out to the metabase
|
||
//
|
||
|
||
cchRoot++;
|
||
|
||
//
|
||
// This is the root
|
||
//
|
||
|
||
if ( !mb.AddObject( pszRoot ) )
|
||
{
|
||
if ( GetLastError() != ERROR_ALREADY_EXISTS )
|
||
{
|
||
DBGPRINTF((DBG_CONTEXT,"AddMetaObject %s failed with %d\n",
|
||
pszRoot, GetLastError() ));
|
||
}
|
||
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// Set Path
|
||
//
|
||
|
||
mb.SetString( pszRoot,
|
||
MD_VR_PATH,
|
||
IIS_MD_UT_FILE,
|
||
pszDirectory );
|
||
|
||
mb.SetString( pszRoot,
|
||
MD_KEY_TYPE,
|
||
IIS_MD_UT_SERVER,
|
||
"IIsWebVirtualDir" );
|
||
|
||
//
|
||
// Set Username
|
||
//
|
||
|
||
if ( pszUser && *pszUser )
|
||
{
|
||
mb.SetString( pszRoot,
|
||
MD_VR_USERNAME,
|
||
IIS_MD_UT_FILE,
|
||
pszUser );
|
||
}
|
||
|
||
//
|
||
// Set Mask
|
||
//
|
||
|
||
mb.SetDword( pszRoot,
|
||
MD_ACCESS_PERM,
|
||
IIS_MD_UT_FILE,
|
||
dwMask );
|
||
}
|
||
|
||
} // while
|
||
|
||
mb.Close();
|
||
|
||
exit:
|
||
|
||
if ( hkeyRoots != NULL ) {
|
||
RegCloseKey( hkeyRoots );
|
||
}
|
||
|
||
if ( hkey != NULL ) {
|
||
RegCloseKey( hkey );
|
||
}
|
||
|
||
return;
|
||
|
||
} // IIS_SERVER_INSTANCE::PdcHackVRReg2MD
|
||
|
||
|
||
VOID
|
||
IIS_SERVER_INSTANCE::TsMirrorVirtualRoots(
|
||
IN LPINETA_CONFIG_INFO pConfig
|
||
)
|
||
/*++
|
||
Description:
|
||
|
||
Writes the virtual roots specified in the config structure to the
|
||
registry
|
||
|
||
Arguments:
|
||
pConfig - new list of virtual
|
||
|
||
Returns:
|
||
TRUE on success and FALSE if any failure.
|
||
|
||
--*/
|
||
{
|
||
DWORD err;
|
||
HKEY hkey = NULL;
|
||
HKEY hkeyRoots = NULL;
|
||
|
||
DWORD dwDummy;
|
||
LPINET_INFO_VIRTUAL_ROOT_LIST pRootsList;
|
||
DWORD cch;
|
||
DWORD i;
|
||
|
||
DBG_ASSERT(IsDownLevelInstance());
|
||
|
||
pRootsList = pConfig->VirtualRoots;
|
||
|
||
//
|
||
// Write it to the root key
|
||
//
|
||
|
||
err = RegOpenKeyEx(
|
||
HKEY_LOCAL_MACHINE,
|
||
m_Service->QueryRegParamKey(),
|
||
0,
|
||
KEY_ALL_ACCESS,
|
||
&hkey );
|
||
|
||
if ( err != NO_ERROR ) {
|
||
DBGPRINTF(( DBG_CONTEXT, "RegOpenKeyEx for returned error %d\n",err ));
|
||
return;
|
||
}
|
||
|
||
//
|
||
// First delete the key to remove any old values
|
||
//
|
||
|
||
if (err = RegDeleteKey( hkey,
|
||
VIRTUAL_ROOTS_KEY_A ))
|
||
{
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"[TsMirrorVRoots] Unable to remove old values\n"));
|
||
|
||
}
|
||
|
||
if ( err = RegCreateKeyEx( hkey,
|
||
VIRTUAL_ROOTS_KEY_A,
|
||
0,
|
||
NULL,
|
||
0,
|
||
KEY_ALL_ACCESS,
|
||
NULL,
|
||
&hkeyRoots,
|
||
&dwDummy ))
|
||
{
|
||
goto exit;
|
||
}
|
||
|
||
//
|
||
// Permit empty list
|
||
//
|
||
|
||
if ( pRootsList == NULL ) {
|
||
goto exit;
|
||
}
|
||
|
||
for ( i = 0; i < pRootsList->cEntries; i++ ) {
|
||
|
||
WCHAR achValue[ MAX_PATH + UNLEN + 2 ];
|
||
|
||
cch = wsprintfW( achValue,
|
||
L"%s,%s,%X",
|
||
pRootsList->aVirtRootEntry[i].pszDirectory,
|
||
pRootsList->aVirtRootEntry[i].pszAccountName,
|
||
pRootsList->aVirtRootEntry[i].dwMask );
|
||
|
||
DBG_ASSERT( cch < sizeof( achValue ) / sizeof(WCHAR) );
|
||
|
||
err = WriteRegistryStringW(hkeyRoots,
|
||
pRootsList->aVirtRootEntry[i].pszRoot,
|
||
achValue,
|
||
(wcslen(achValue) + 1) * sizeof(WCHAR),
|
||
REG_SZ);
|
||
|
||
if ( err != NO_ERROR ) {
|
||
goto exit;
|
||
}
|
||
}
|
||
|
||
exit:
|
||
|
||
if ( hkeyRoots != NULL ) {
|
||
RegCloseKey( hkeyRoots );
|
||
}
|
||
|
||
if ( hkey != NULL ) {
|
||
RegCloseKey( hkey );
|
||
}
|
||
|
||
return;
|
||
|
||
} // IIS_SERVER_INSTANCE::TsMirrorVirtualRoots
|
||
|
||
|
||
VOID
|
||
ClearSentinelEntry(
|
||
IN MB * pMB
|
||
)
|
||
/*++
|
||
Description:
|
||
|
||
Removes the sentinel entry from all VR for this instance
|
||
|
||
Arguments:
|
||
pMD - pointer to metabase helper object that points to the
|
||
instance metadatabase root.
|
||
|
||
Returns:
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
BOOL fGetRoot = TRUE;
|
||
CHAR nameBuf[METADATA_MAX_NAME_LEN+2];
|
||
DWORD i = 0;
|
||
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"Entering ClearSentinelEntry\n"));
|
||
}
|
||
|
||
while ( TRUE ) {
|
||
|
||
METADATA_RECORD mdRecord;
|
||
|
||
nameBuf[0] = nameBuf[1] = '/';
|
||
|
||
if ( fGetRoot ) {
|
||
|
||
fGetRoot = FALSE;
|
||
nameBuf[2] = '\0';
|
||
|
||
} else {
|
||
|
||
if ( !pMB->EnumObjects( IIS_MD_INSTANCE_ROOT,
|
||
&nameBuf[2],
|
||
i++ ))
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Delete sentinel value
|
||
//
|
||
|
||
if ( !pMB->DeleteData( nameBuf,
|
||
MD_VR_UPDATE,
|
||
IIS_MD_UT_FILE,
|
||
DWORD_METADATA
|
||
))
|
||
{
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"Error %x deleting sentinel from %s\n",
|
||
GetLastError(), nameBuf));
|
||
}
|
||
}
|
||
}
|
||
|
||
return;
|
||
|
||
} // ClearSentinelEntry
|
||
|
||
|
||
VOID
|
||
RemoveUnmarkedRoots(
|
||
IN MB * pMB
|
||
)
|
||
/*++
|
||
Description:
|
||
|
||
Removes roots that are not marked by sentinel
|
||
|
||
Arguments:
|
||
pMD - pointer to metabase helper object that points to the
|
||
instance metadatabase root.
|
||
|
||
Returns:
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
BOOL fGetRoot = TRUE;
|
||
CHAR nameBuf[METADATA_MAX_NAME_LEN+2];
|
||
CHAR szDirectory[MAX_PATH+1];
|
||
DWORD cb;
|
||
DWORD i = 0;
|
||
BOOL fProcessingRoot;
|
||
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"Entering RemoveUnmarkedRoots\n"));
|
||
}
|
||
|
||
while ( TRUE ) {
|
||
|
||
if ( fGetRoot ) {
|
||
|
||
strcpy( nameBuf, IIS_MD_INSTANCE_ROOT );
|
||
fProcessingRoot = TRUE;
|
||
fGetRoot = FALSE;
|
||
|
||
} else {
|
||
|
||
strcpy( nameBuf, IIS_MD_INSTANCE_ROOT "/" );
|
||
|
||
|
||
fProcessingRoot = FALSE;
|
||
if ( !pMB->EnumObjects( IIS_MD_INSTANCE_ROOT,
|
||
&nameBuf[strlen(nameBuf)],
|
||
i++ ))
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Delete sentinel value. If delete successful, leave alone
|
||
//
|
||
|
||
if ( pMB->DeleteData( nameBuf,
|
||
MD_VR_UPDATE,
|
||
IIS_MD_UT_FILE,
|
||
DWORD_METADATA
|
||
))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"Error %x deleting sentinel from %s\n",
|
||
GetLastError(), nameBuf));
|
||
}
|
||
|
||
//
|
||
// See if it has the path parameter
|
||
//
|
||
|
||
cb = sizeof( szDirectory );
|
||
|
||
if ( !pMB->GetString( nameBuf,
|
||
MD_VR_PATH,
|
||
IIS_MD_UT_FILE,
|
||
szDirectory,
|
||
&cb,
|
||
0 ))
|
||
{
|
||
//
|
||
// Not a VR
|
||
//
|
||
|
||
DBGPRINTF((DBG_CONTEXT,
|
||
"Error %x reading path from %s. Not a VR.\n",
|
||
GetLastError(), nameBuf));
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// Unmarked, delete the VR
|
||
//
|
||
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"Deleting vroot %s[%d]\n",
|
||
nameBuf, fGetRoot));
|
||
}
|
||
|
||
if ( fProcessingRoot ) {
|
||
|
||
//
|
||
// if this is the root, just remove the path. Deleting the
|
||
// root is a potentially dangerous undertaking!
|
||
//
|
||
|
||
if ( !pMB->DeleteData( nameBuf,
|
||
MD_VR_PATH,
|
||
IIS_MD_UT_FILE,
|
||
STRING_METADATA
|
||
))
|
||
{
|
||
DBGPRINTF((DBG_CONTEXT,"Error %x deleting root path\n",
|
||
GetLastError()));
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// Delete the Vroot
|
||
//
|
||
|
||
if ( !pMB->DeleteObject( nameBuf ) )
|
||
{
|
||
DBGPRINTF((DBG_CONTEXT,"Error %x deleting %s\n",
|
||
GetLastError(), nameBuf));
|
||
|
||
} else {
|
||
|
||
//
|
||
// the delete moved the index back by 1
|
||
//
|
||
|
||
DBG_ASSERT( i != 0 );
|
||
|
||
--i;
|
||
|
||
}
|
||
}
|
||
|
||
fGetRoot = FALSE;
|
||
}
|
||
|
||
return;
|
||
|
||
} // RemoveUnmarkedRoots
|
||
|
||
|
||
BOOL
|
||
ReadVrootConfig(
|
||
LPVOID pvMB,
|
||
LPSTR szVRPath,
|
||
LPSTR szDirectory,
|
||
DWORD cbDirectory,
|
||
LPSTR szUser,
|
||
DWORD cbUser,
|
||
LPSTR szPassword,
|
||
DWORD cbPassword,
|
||
DWORD *pdwMask,
|
||
BOOL *pfDoCache
|
||
)
|
||
{
|
||
|
||
DWORD cb;
|
||
DWORD dwNoCache = 0;
|
||
|
||
MB* pMB = (MB*)pvMB;
|
||
|
||
//
|
||
// Get Directory path
|
||
//
|
||
|
||
cb = cbDirectory;
|
||
|
||
if ( !pMB->GetString( szVRPath,
|
||
MD_VR_PATH,
|
||
IIS_MD_UT_FILE,
|
||
szDirectory,
|
||
&cb,
|
||
0 ))
|
||
{
|
||
#if DBG
|
||
if ( GetLastError() != MD_ERROR_DATA_NOT_FOUND )
|
||
{
|
||
DBGPRINTF((DBG_CONTEXT,"Error %x reading path from %s. Not a VR.\n",
|
||
GetLastError(), szVRPath));
|
||
}
|
||
#endif
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Get mask
|
||
//
|
||
|
||
if ( !pMB->GetDword( szVRPath,
|
||
MD_ACCESS_PERM,
|
||
IIS_MD_UT_FILE,
|
||
pdwMask,
|
||
0))
|
||
{
|
||
*pdwMask = VROOT_MASK_READ;
|
||
|
||
IF_DEBUG(ERROR) {
|
||
DBGPRINTF((DBG_CONTEXT,"Error %x reading mask from %s\n",
|
||
GetLastError(), szVRPath));
|
||
}
|
||
}
|
||
|
||
//
|
||
// Get username
|
||
//
|
||
|
||
cb = cbUser;
|
||
|
||
if ( !pMB->GetString( szVRPath,
|
||
MD_VR_USERNAME,
|
||
IIS_MD_UT_FILE,
|
||
szUser,
|
||
&cb,
|
||
0))
|
||
{
|
||
szUser[0] = '\0';
|
||
}
|
||
|
||
IF_DEBUG(METABASE) {
|
||
DBGPRINTF((DBG_CONTEXT,"Read %s: Path[%s] User[%s] Mask[%d]\n",
|
||
szVRPath, szDirectory, szUser, *pdwMask));
|
||
}
|
||
|
||
if ( (szUser[0] != '\0') &&
|
||
(szDirectory[0] == '\\') && (szDirectory[1] == '\\') ) {
|
||
|
||
cb = cbPassword;
|
||
|
||
//
|
||
// Retrieve the password for this address/share
|
||
//
|
||
|
||
if ( !pMB->GetString( szVRPath,
|
||
MD_VR_PASSWORD,
|
||
IIS_MD_UT_FILE,
|
||
szPassword,
|
||
&cb,
|
||
METADATA_SECURE))
|
||
{
|
||
szPassword[0] = '\0';
|
||
}
|
||
}
|
||
else
|
||
{
|
||
szPassword[0] = '\0';
|
||
}
|
||
|
||
//
|
||
// Should we cache this vdir
|
||
//
|
||
|
||
pMB->GetDword( szVRPath,
|
||
MD_VR_NO_CACHE,
|
||
IIS_MD_UT_FILE,
|
||
&dwNoCache,
|
||
0 );
|
||
|
||
*pfDoCache = !dwNoCache;
|
||
|
||
return TRUE;
|
||
}
|
||
|