2025-04-27 07:49:33 -04:00

2569 lines
62 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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 <iiscnfg.h>
#include <imd.h>
#include <inetreg.h>
#include <mb.hxx>
#include <w3svc.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
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
);
DWORD
hextointW(
WCHAR * pch
);
DWORD
hextointA(
CHAR * pch
);
BOOL
IIS_SERVER_INSTANCE::TsReadVirtualRoots(
VOID
)
/*++
Description:
NT Version
Reads the metabase key pointed at by pmb and adds each root item
Arguments:
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;
//
// Remove all of the old roots for this server
//
QueryVrootTable()->LockTable();
fRet = QueryVrootTable()->RemoveVirtualRoots() &&
TsEnumVirtualRoots( TsAddVroots, this );
QueryVrootTable()->UnlockTable();
return fRet;
}
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] == '\\') )
{
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 ))
{
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;
} // TsReadVirtualRoots
BOOL
IIS_SERVER_INSTANCE::TsEnumVirtualRoots(
PFN_VR_ENUM pfnCallback,
VOID * pvContext
)
{
MB mb( (IMDCOM*) m_Service->QueryMDObject() );
if ( !mb.Open( QueryMDPath(),
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ))
{
return FALSE;
}
return TsRecursiveEnumVirtualRoots(
pfnCallback,
pvContext,
"IIS_MD_INSTANCE_ROOT/",
m_dwLevelsToScan,
(LPVOID)&mb,
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 dwMask;
CHAR szUser[UNLEN+1];
CHAR szPassword[PWLEN+1];
CHAR szDirectory[MAX_PATH + UNLEN + 3];
DWORD cb;
CHAR nameBuf[METADATA_MAX_NAME_LEN+2];
DWORD cbCurrentPath;
VIRTUAL_ROOT vr;
DWORD i = 0;
//
// 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 {
nameBuf[cbCurrentPath-1] = '/';
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';
}
}
//
// Get Directory path
//
cb = sizeof( szDirectory );
if ( !pMB->GetString( nameBuf,
MD_VR_PATH,
IIS_MD_UT_FILE,
szDirectory,
&cb,
0 ))
{
DBGPRINTF((DBG_CONTEXT,"Error %x reading path from %s. Not a VR.\n",
GetLastError(), nameBuf));
continue;
}
//
// Get mask
//
if ( !pMB->GetDword( nameBuf,
MD_ACCESS_PERM,
IIS_MD_UT_FILE,
&dwMask,
0))
{
dwMask = VROOT_MASK_READ;
DBGPRINTF((DBG_CONTEXT,"Error %d reading mask from %s\n",
GetLastError(), nameBuf));
}
//
// Get username
//
cb = sizeof( szUser );
if ( !pMB->GetString( nameBuf,
MD_VR_USERNAME,
IIS_MD_UT_FILE,
szUser,
&cb,
0))
{
// DBGPRINTF((DBG_CONTEXT,"Error %d reading path from %s\n",
// GetLastError(), nameBuf));
szUser[0] = '\0';
}
IF_DEBUG(METABASE) {
DBGPRINTF((DBG_CONTEXT,"Reading %s: Path[%s] User[%s] Mask[%d]\n",
nameBuf, szDirectory, szUser, dwMask));
}
if ( (szUser[0] != '\0') &&
(szDirectory[0] == '\\') && (szDirectory[1] == '\\') ) {
cb = sizeof( szPassword );
//
// Retrieve the password for this address/share
//
if ( !pMB->GetString( nameBuf,
MD_VR_PASSWORD,
IIS_MD_UT_FILE,
szPassword,
&cb,
METADATA_SECURE))
{
DBGPRINTF((DBG_CONTEXT,"Error %d reading path from %s\n",
GetLastError(), nameBuf));
szPassword[0] = '\0';
}
}
else
{
szPassword[0] = '\0';
}
//
// Now set things up for the callback
//
DBG_ASSERT( nameBuf[0] == '/' && nameBuf[1] == '/' );
vr.pszAlias = nameBuf + 1;
vr.pszMetaPath = nameBuf;
vr.pszPath = szDirectory;
vr.dwAccessPerm = dwMask;
vr.pszUserName = szUser;
vr.pszPassword = szPassword;
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 ); // 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 LPIIS_INSTANCE_INFO_1 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;
DWORD dwDummy;
LPINET_INFO_VIRTUAL_ROOT_LIST pRootsList;
DWORD cch;
DWORD i;
DWORD dwMask;
DWORD sentinelValue = 7777777;
MB mb( (IMDCOM*) m_Service->QueryMDObject() );
//
// 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;
}
//
// 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];
DWORD rootLen;
//
// strings to ANSI
//
tmpRoot[0] = '/';
(VOID) ConvertUnicodeToAnsi(
pRootsList->aVirtRootEntry[i].pszRoot,
&tmpRoot[1],
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));
}
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));
}
//
// 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));
}
}
//
// Delete entries that does not have the sentinel entry
//
RemoveUnmarkedRoots( &mb );
exit:
mb.Save();
//
// If this is instance 1, mirror it to the registry
//
DBGPRINTF(( DBG_CONTEXT,
"WARNING! Downlevel assumed to be instance 1!!! Fix it!\n" ));
if ( QueryInstanceId() == 1 ) {
TsMirrorVirtualRoots( pConfig );
}
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);
}
pszEnd = strchr( pszEnd+1, '\\');
len = ( ( pszEnd == NULL) ? strlen(pszRealPath)
: (pszEnd + 1 - pszRealPath));
//
// 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 ( rgchRoot[len - 1] != '\\' ) {
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[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 (!DuplicateToken( hToken, // hSourceToken
SecurityImpersonation, // Obtain impersonation
&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( *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
)
{
#if 0
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;
DWORD dwDirBrowse;
STR strFile;
MB mb( (IMDCOM*) m_Service->QueryMDObject() );
HKEY hkey = NULL;
HKEY hkeyRoots = NULL;
HKEY hkeyExtMaps = NULL;
BUFFER bufTemp;
STR strRealm;
STR strLogonDomain;
STR strAnonUser;
BOOL fCreateProcessAsUser;
BOOL fCreateProcessWithNewConsole;
DWORD dwLogonMethod;
DWORD dwCurrentSize;
IF_DEBUG(METABASE) {
DBGPRINTF((DBG_CONTEXT,"In MoveVrootFromRegToMD\n"));
}
//
// See if we need to move
//
if ( !mb.Open( "/",
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ))
{
//
// if this fails, we're hosed.
//
DBGPRINTF((DBG_CONTEXT,"Open MD root returns %d\n",GetLastError() ));
return FALSE;
}
//
// This will fail if the metabase was already set up
//
if ( !mb.AddObject( QueryMDPath() ) &&
GetLastError() != ERROR_ALREADY_EXISTS )
{
DBGPRINTF((DBG_CONTEXT,"AddMetaObject %s failed with %d\n",
QueryMDPath(), GetLastError() ));
goto exit;
}
DBG_REQUIRE( mb.Close() );
//
// Our add worked, so that means that the metabase is empty
//
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
m_Service->QueryRegParamKey(),
0,
KEY_ALL_ACCESS,
&hkey );
if ( err != NO_ERROR ) {
DBGPRINTF(( DBG_CONTEXT, "RegOpenKeyEx returned error %d\n",err ));
goto exit;
}
dwAuthorization = ReadRegistryDword( hkey,
INETA_AUTHENTICATION,
INET_INFO_AUTH_ANONYMOUS );
dwDirBrowse = ReadRegistryDword( hkey,
"Dir Browse Control",
0x4000001e );
ReadRegistryStr( hkey,
strFile,
"Default Load File",
"Default.htm,Index.htm" );
ReadRegistryStr( hkey,
strRealm,
W3_REALM_NAME,
"" );
fCreateProcessAsUser = !!ReadRegistryDword( hkey,
"CreateProcessAsUser",
TRUE );
fCreateProcessWithNewConsole = !!ReadRegistryDword( hkey,
"CreateProcessWithNewConsole",
FALSE );
dwLogonMethod = ReadRegistryDword( hkey,
INETA_LOGON_METHOD,
INETA_DEF_LOGON_METHOD );
switch ( dwLogonMethod ) {
case INETA_LOGM_BATCH:
dwLogonMethod = LOGON32_LOGON_BATCH;
break;
case INETA_LOGM_NETWORK:
dwLogonMethod = LOGON32_LOGON_NETWORK;
break;
case INETA_LOGM_INTERACTIVE:
default:
dwLogonMethod = LOGON32_LOGON_INTERACTIVE;
break;
}
ReadRegistryStr( hkey,
strLogonDomain,
INETA_DEFAULT_LOGON_DOMAIN,
INETA_DEF_DEFAULT_LOGON_DOMAIN );
ReadRegistryStr( hkey,
strAnonUser,
INETA_ANON_USER_NAME,
INETA_DEF_ANON_USER_NAME );
if ( err = RegOpenKeyEx( hkey,
VIRTUAL_ROOTS_KEY_A,
0,
KEY_ALL_ACCESS,
&hkeyRoots )) {
IF_DEBUG(METABASE) {
DBGPRINTF((DBG_CONTEXT,"RegOpenKeyEx %s failed with %d\n",
VIRTUAL_ROOTS_KEY_A, err));
}
goto exit;
}
//
// Get the MD handle to the VR root
//
if ( !mb.Open( QueryMDPath(),
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ))
{
DBGPRINTF((DBG_CONTEXT,"Open MD path returns %d\n",GetLastError()));
goto exit;
}
//
// Now set all of the parameters which were previously on a per-instance
// basis at the instance level.
//
// Set the default authorization requirements
//
mb.SetDword( "",
MD_AUTHORIZATION,
IIS_MD_UT_FILE,
dwAuthorization );
//
// Set the directory browsing control
//
mb.SetDword( "",
MD_DIRECTORY_BROWSING,
IIS_MD_UT_FILE,
dwDirBrowse );
//
// Set the default document
//
mb.SetString( "",
MD_DEFAULT_LOAD_FILE,
IIS_MD_UT_FILE,
strFile.QueryStr());
// Set the realm.
//
if (!strRealm.IsEmpty())
{
mb.SetString( "",
MD_REALM,
IIS_MD_UT_FILE,
strRealm.QueryStr());
}
mb.SetDword( "",
MD_CREATE_PROCESS_AS_USER,
IIS_MD_UT_FILE,
(DWORD)fCreateProcessAsUser );
mb.SetDword( "",
MD_CREATE_PROC_NEW_CONSOLE,
IIS_MD_UT_FILE,
(DWORD)fCreateProcessWithNewConsole );
mb.SetDword( "",
MD_LOGON_METHOD,
IIS_MD_UT_FILE,
dwLogonMethod );
mb.SetString( "",
MD_DEFAULT_LOGON_DOMAIN,
IIS_MD_UT_FILE,
strLogonDomain.QueryStr());
mb.SetString( "",
MD_ANONYMOUS_USER_NAME,
IIS_MD_UT_FILE,
strAnonUser.QueryStr());
//
// Now enumerate all of the script mapping on this instance, and add them.
//
err = RegOpenKeyEx( hkey,
HTTP_EXT_MAPS,
0,
KEY_ALL_ACCESS,
&hkeyExtMaps );
if (err)
{
IF_DEBUG(METABASE) {
DBGPRINTF((DBG_CONTEXT,"RegOpenKeyEx %s failed with %d\n",
HTTP_EXT_MAPS, err));
}
goto exit;
}
dwCurrentSize = 0;
while (TRUE)
{
CHAR achExt[MAX_PATH+1];
CHAR achImage[MAX_PATH+1];
DWORD cchExt = sizeof( achExt );
DWORD cchImage = sizeof( achImage );
DWORD dwSizeNeeded;
CHAR *pszTemp;
// Get the next script mapping.
err = RegEnumValue( hkeyExtMaps,
i,
achExt,
&cchExt,
NULL,
&dwRegType,
(LPBYTE) achImage,
&cchImage );
if ( err == ERROR_NO_MORE_ITEMS )
{
if (bufTemp.QuerySize() < (dwCurrentSize + 1))
{
if (!bufTemp.Resize(dwCurrentSize + 1))
{
IF_DEBUG(METABASE) {
DBGPRINTF((DBG_CONTEXT,
"Unable to create script mapping string\n"));
}
fRet = FALSE;
goto exit;
}
}
pszTemp = (CHAR *)bufTemp.QueryPtr() + dwCurrentSize;
// Add the extra NULL.
*pszTemp = '\0';
break;
}
if ( dwRegType == REG_SZ )
{
// Figure the size we need. We need enough for the extension,
// (cchExt, which doesn't include the trailing NULL), space
// for the comma, space for the image name (cchImage, which
// does include the NULL) and the trailing NULL, and enough
// for what we already have.
dwSizeNeeded = cchExt + sizeof(",") - 1 + cchImage + dwCurrentSize;
if (dwSizeNeeded > bufTemp.QuerySize())
{
if (!bufTemp.Resize(dwSizeNeeded))
{
IF_DEBUG(METABASE) {
DBGPRINTF((DBG_CONTEXT,
"Unable to create script mapping string\n"));
}
fRet = FALSE;
goto exit;
}
}
pszTemp = (CHAR *)bufTemp.QueryPtr() + dwCurrentSize;
// Copy the extension...
memcpy(pszTemp, achExt, cchExt);
pszTemp += cchExt;
// ...and the comma...
*pszTemp = ',';
pszTemp++;
// ...and the image, including the trailing NULL.
memcpy(pszTemp, achImage, cchImage);
// Now update our current size.
dwCurrentSize = dwSizeNeeded;
}
i++;
}
mb.SetMultiSZ( "",
MD_SCRIPT_MAPS,
IIS_MD_UT_FILE,
(CHAR *)bufTemp.QueryPtr());
//
// Enumerate all of the listed items in the registry
// and add them
//
*pszRoot = '/';
tmpRoot = (PCHAR)pszRoot+1;
i = 0;
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';
}
//
// Write it out to the metabase
//
//
// This is the root
//
if ( !mb.AddObject( pszRoot ) &&
GetLastError() != ERROR_ALREADY_EXISTS )
{
DBGPRINTF((DBG_CONTEXT,"AddMetaObject %s failed with %d\n",
pszRoot, GetLastError() ));
goto exit;
}
//
// Set Path
//
mb.SetString( pszRoot,
MD_VR_PATH,
IIS_MD_UT_FILE,
pszDirectory );
//
// Set Username
//
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.Save();
mb.Close();
exit:
if ( hkeyRoots != NULL ) {
RegCloseKey( hkeyRoots );
}
if ( hkeyExtMaps != NULL ) {
RegCloseKey( hkeyExtMaps );
}
if ( hkey != NULL ) {
RegCloseKey( hkey );
}
return fRet;
#else
DBGPRINTF((DBG_CONTEXT,"MoveVrootFromRegToMD called!!!\n"));
return(TRUE);
#endif
} // 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(QueryInstanceId() == 1);
IF_DEBUG(METABASE) {
DBGPRINTF((DBG_CONTEXT,"Entering MoveMDToRegAtStartup.\n"));
}
//
// see if the key exists
//
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
m_Service->QueryRegParamKey( ),
0,
KEY_ALL_ACCESS,
&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_ALL_ACCESS,
NULL,
&hkeyRoots,
&dwDisp );
if ( err != NO_ERROR ) {
IF_DEBUG(METABASE) {
DBGPRINTF((DBG_CONTEXT,
"Error %d in RegCreateKeyEx\n",err));
}
goto exit;
}
if ( dwDisp == REG_OPENED_EXISTING_KEY ) {
IF_DEBUG(METABASE) {
DBGPRINTF((DBG_CONTEXT,
"Registry VR key found, aborting startup migration.\n"));
}
goto exit;
}
//
// 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;
DWORD dwDirBrowse;
STR strFile;
MB mb( (IMDCOM*) m_Service->QueryMDObject() );
HKEY hkey = NULL;
HKEY hkeyRoots = NULL;
DBG_ASSERT(QueryInstanceId() == 1);
IF_DEBUG(METABASE) {
DBGPRINTF((DBG_CONTEXT,"In MoveVrootFromRegToMD\n"));
}
//
// see if the key exists
//
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
m_Service->QueryRegParamKey( ),
0,
KEY_ALL_ACCESS,
&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_ALL_ACCESS,
&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 );
dwDirBrowse = ReadRegistryDword( hkey,
"Dir Browse Control",
0x4000001e );
ReadRegistryStr( hkey,
strFile,
"Default Load File",
"Default.htm,Index.htm" );
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 ) )
{
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 );
//
// Set Username
//
mb.SetString( pszRoot,
MD_VR_USERNAME,
IIS_MD_UT_FILE,
pszUser );
//
// Set Mask
//
mb.SetDword( pszRoot,
MD_ACCESS_PERM,
IIS_MD_UT_FILE,
dwMask );
//
// Set the default authorization requirements
//
mb.SetDword( pszRoot,
MD_AUTHORIZATION,
IIS_MD_UT_FILE,
dwAuthorization );
//
// Set the directory browsing control
//
mb.SetDword( pszRoot,
MD_DIRECTORY_BROWSING,
IIS_MD_UT_FILE,
dwDirBrowse );
//
// Set the default document
//
mb.SetString( pszRoot,
MD_DEFAULT_LOAD_FILE,
IIS_MD_UT_FILE,
strFile.QueryStr() );
}
} // while
mb.Save();
mb.Close();
exit:
if ( hkeyRoots != NULL ) {
RegCloseKey( hkeyRoots );
}
if ( hkey != NULL ) {
RegCloseKey( hkey );
}
return;
} // IIS_SERVER_INSTANCE::PdcHackVRReg2MD
VOID
IIS_SERVER_INSTANCE::TsMirrorVirtualRoots(
IN LPIIS_INSTANCE_INFO_1 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(QueryInstanceId() == 1);
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+sizeof(IIS_MD_INSTANCE_ROOT)];
CHAR szDirectory[MAX_PATH+1];
DWORD cb;
DWORD i = 0;
BOOL fProcessingRoot;
IF_DEBUG(METABASE) {
DBGPRINTF((DBG_CONTEXT,"Entering RemoveUnmarkedRoots\n"));
}
while ( TRUE ) {
strcpy(nameBuf, IIS_MD_INSTANCE_ROOT);
nameBuf[sizeof(IIS_MD_INSTANCE_ROOT) - 1] = '/';
if ( fGetRoot ) {
fProcessingRoot = TRUE;
fGetRoot = FALSE;
nameBuf[2] = '\0';
} else {
fProcessingRoot = FALSE;
if ( !pMB->EnumObjects( "IIS_MD_INSTANCE_ROOT",
&nameBuf[sizeof(IIS_MD_INSTANCE_ROOT)],
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
//
--i;
DBG_ASSERT( i >= 0 );
}
}
fGetRoot = FALSE;
}
return;
} // RemoveUnmarkedRoots