Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1838 lines
54 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997 - 2000.
//
// File: cimbmgr.cxx
//
// Contents: Content Index Meta Base Manager
//
// Classes: CMetaDataMgr
//
// History: 07-Feb-1997 dlee Created
// 24-Apr-1997 dlee Converted to new Unicode interface
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <cimbmgr.hxx>
#define MYDEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
EXTERN_C const GUID name \
= { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
MYDEFINE_GUID(CLSID_MSAdminBase_W, 0xa9e69610, 0xb80d, 0x11d0, 0xb9, 0xb9, 0x0, 0xa0, 0xc9, 0x22, 0xe7, 0x50);
MYDEFINE_GUID(IID_IMSAdminBase_W, 0x70b51430, 0xb6ca, 0x11d0, 0xb9, 0xb9, 0x0, 0xa0, 0xc9, 0x22, 0xe7, 0x50);
MYDEFINE_GUID(CLSID_MSAdminBaseExe_W, 0xa9e69611, 0xb80d, 0x11d0, 0xb9, 0xb9, 0x0, 0xa0, 0xc9, 0x22, 0xe7, 0x50);
MYDEFINE_GUID(IID_IMSAdminBaseSink_W, 0xa9e69612, 0xb80d, 0x11d0, 0xb9, 0xb9, 0x0, 0xa0, 0xc9, 0x22, 0xe7, 0x50);
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::CMetaDataMgr, public
//
// Synopsis: Creates an object for talking to the IIS metabase.
//
// Arguments: [fTopLevel] - TRUE for the top level, FALSE for a
// vserver instance
// [dwInstance] - instance # of the server
// [eType] - type of vroot provider -- W3, NNTP, or IMAP
// [pwcMachine] - the machine to open, L"." for local machine
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
CMetaDataMgr::CMetaDataMgr(
BOOL fTopLevel,
CiVRootTypeEnum eType,
DWORD dwInstance,
WCHAR const * pwcMachine ) :
_fNotifyEnabled( FALSE ),
_fTopLevel( fTopLevel )
{
// -1 is a valid instance number, so this is a bogus assert, but it'll
// never be hit unless something else is broken or someone hacked the
// registry.
#if CIDBG == 1
if ( fTopLevel )
Win4Assert( 0xffffffff == dwInstance );
else
Win4Assert( 0xffffffff != dwInstance );
#endif // CIDBG == 1
if ( fTopLevel )
swprintf( _awcInstance, L"/lm/%ws", GetVRootService( eType ) );
else
swprintf( _awcInstance,
L"/lm/%ws/%d",
GetVRootService( eType ),
dwInstance );
IMSAdminBase * pcAdmCom;
if ( !_wcsicmp( pwcMachine, L"." ) )
{
SCODE sc = CoCreateInstance( GETAdminBaseCLSID(TRUE),
NULL,
CLSCTX_ALL,
IID_IMSAdminBase,
(void **) &pcAdmCom );
if ( FAILED(sc) )
{
ciDebugOut(( DEB_WARN, "CMetaDataMgr can't CoCreateInstance: %x\n", sc ));
THROW( CException(sc) );
}
}
else
{
COSERVERINFO info;
RtlZeroMemory( &info, sizeof info );
info.pwszName = (WCHAR *) pwcMachine;
XInterface<IClassFactory> xFactory;
SCODE sc = CoGetClassObject( GETAdminBaseCLSID(TRUE),
CLSCTX_SERVER,
&info,
IID_IClassFactory,
xFactory.GetQIPointer() );
if ( FAILED(sc) )
{
ciDebugOut(( DEB_WARN, "CMetaDataMgr can't CoGetClassObject: %x\n", sc ));
THROW( CException(sc) );
}
sc = xFactory->CreateInstance( 0, IID_IMSAdminBase, (void**) &pcAdmCom );
if ( FAILED(sc) )
{
ciDebugOut(( DEB_WARN, "CMetaDataMgr can't CreateInstance: %x\n", sc ));
THROW( CException(sc) );
}
}
_xAdminBase.Set( pcAdmCom );
} //CMetaDataMgr
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::~CMetaDataMgr, public
//
// Synopsis: Destroys an object for talking to the IIS metabase
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
CMetaDataMgr::~CMetaDataMgr()
{
if ( !_xAdminBase.IsNull() )
{
// just in case we are still connected
DisableVPathNotify();
}
} //~CMetaDataMgr
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::IsIISAdminUp, public/static
//
// Synopsis: Returns TRUE if iisadmin svc is up
//
// Arguments: [fIISAdminInstalled] - returns TRUE if it's installed,
// FALSE otherwise
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
BOOL CMetaDataMgr::IsIISAdminUp(
BOOL & fIISAdminInstalled )
{
fIISAdminInstalled = TRUE;
BOOL fIsUp = TRUE;
TRY
{
// The constructor will throw if the iisadmin svc is unavailable.
CMetaDataMgr( TRUE, W3VRoot );
}
CATCH( CException, e )
{
fIsUp = FALSE;
if ( REGDB_E_CLASSNOTREG == e.GetErrorCode() )
fIISAdminInstalled = FALSE;
}
END_CATCH
return fIsUp;
} //IsIISAdminUp
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::EnumVPaths, public
//
// Synopsis: Enumerates vpaths by calling the callback
//
// Arguments: [callBack] - called for each vpath
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
void CMetaDataMgr::EnumVPaths(
CMetaDataCallBack & callBack )
{
Win4Assert( !_fTopLevel );
CMetaDataHandle mdRoot( _xAdminBase, _awcInstance );
CVRootStack vrootStack;
Enum( vrootStack, callBack, mdRoot, L"" );
} //EnumVPaths
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::AddVRoot, public
//
// Synopsis: Adds a VRoot to the metabase
//
// Arguments: [pwcVRoot] - name of the vroot, e.g.: /here
// [pwcPRoot] - physical path of the vroot, e.g.: x:\here
// [dwAccess] - access rights to the vroot
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
void CMetaDataMgr::AddVRoot(
WCHAR const * pwcVRoot,
WCHAR const * pwcPRoot,
DWORD dwAccess )
{
Win4Assert( !_fTopLevel );
// blow it away if it currently exists
RemoveVRoot( pwcVRoot );
{
unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" );
if ( cwc >= METADATA_MAX_NAME_LEN )
THROW( CException( E_INVALIDARG ) );
WCHAR awc[ METADATA_MAX_NAME_LEN ];
wcscpy( awc, _awcInstance );
wcscat( awc, L"/Root" );
CMetaDataHandle mdRoot( _xAdminBase, awc, TRUE );
_xAdminBase->AddKey( mdRoot.Get(), pwcVRoot );
}
WCHAR awcVRootPath[ METADATA_MAX_NAME_LEN ];
unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" ) + wcslen( pwcVRoot );
if ( cwc >= METADATA_MAX_NAME_LEN )
THROW( CException( E_INVALIDARG ) );
wcscpy( awcVRootPath, _awcInstance );
wcscat( awcVRootPath, L"/Root" );
wcscat( awcVRootPath, pwcVRoot );
CMetaDataHandle mdVRoot( _xAdminBase, awcVRootPath, TRUE );
{
METADATA_RECORD mdr;
RtlZeroMemory( &mdr, sizeof mdr );
mdr.dwMDIdentifier = MD_VR_PATH;
mdr.dwMDAttributes = METADATA_INHERIT;
mdr.dwMDUserType = IIS_MD_UT_FILE;
mdr.dwMDDataType = STRING_METADATA;
mdr.pbMDData = (BYTE *) pwcPRoot;
mdr.dwMDDataLen = sizeof WCHAR * ( 1 + wcslen( pwcPRoot ) );
DWORD cbRequired = 0;
SCODE sc = _xAdminBase->SetData( mdVRoot.Get(),
L"",
&mdr );
if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "SetData PRoot failed: 0x%x\n", sc ));
THROW( CException( sc ) );
}
}
{
// must set a null username to enforce metadata consistency
METADATA_RECORD mdr;
RtlZeroMemory( &mdr, sizeof mdr );
mdr.dwMDIdentifier = MD_VR_USERNAME;
mdr.dwMDAttributes = METADATA_INHERIT;
mdr.dwMDUserType = IIS_MD_UT_SERVER;
mdr.dwMDDataType = STRING_METADATA;
mdr.pbMDData = (BYTE *) L"";
mdr.dwMDDataLen = sizeof WCHAR;
DWORD cbRequired = 0;
SCODE sc = _xAdminBase->SetData( mdVRoot.Get(),
L"",
&mdr );
if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "SetData user failed: 0x%x\n", sc ));
THROW( CException( sc ) );
}
}
{
METADATA_RECORD mdr;
RtlZeroMemory( &mdr, sizeof mdr );
mdr.dwMDIdentifier = MD_ACCESS_PERM;
mdr.dwMDAttributes = METADATA_INHERIT;
mdr.dwMDUserType = IIS_MD_UT_FILE;
mdr.dwMDDataType = DWORD_METADATA;
mdr.pbMDData = (BYTE *) &dwAccess;
mdr.dwMDDataLen = sizeof dwAccess;
DWORD cbRequired = 0;
SCODE sc = _xAdminBase->SetData( mdVRoot.Get(),
L"",
&mdr );
if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "SetData accessperm failed: 0x%x\n", sc ));
THROW( CException( sc ) );
}
}
} //AddVRoot
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::Flush, public
//
// Synopsis: Flushes the metabase, since it's not robust.
//
// History: 4-Dec-1998 dlee Created
//
//--------------------------------------------------------------------------
void CMetaDataMgr::Flush()
{
SCODE sc = _xAdminBase->SaveData();
if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "CMetaDataMgr::Flush failed: %#x\n", sc ));
THROW( CException( sc ) );
}
} //Flush
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::RemoveVRoot, public
//
// Synopsis: Removes a VRoot from the metabase
//
// Arguments: [pwcVRoot] - name of the vroot. e.g.: /scripts
//
// Notes: Doesn't throw on failure to remove the root.
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
SCODE CMetaDataMgr::RemoveVRoot(
WCHAR const * pwcVRoot )
{
Win4Assert( !_fTopLevel );
unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" );
if ( cwc >= METADATA_MAX_NAME_LEN )
THROW( CException( E_INVALIDARG ) );
WCHAR awcRoot[ METADATA_MAX_NAME_LEN ];
wcscpy( awcRoot, _awcInstance );
wcscat( awcRoot, L"/Root" );
CMetaDataHandle mdRoot( _xAdminBase, awcRoot, TRUE );
// don't throw on error deleting vroot -- the root may not exist
return _xAdminBase->DeleteKey( mdRoot.Get(), pwcVRoot );
} //RemoveVRoot
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::WriteRootValue, private
//
// Synopsis: Retrieves data for the key and identifier
//
// Arguments: [mdRoot] - Metabase key where data reside
// [mdr] - Scratch pad for the record. On output, can be
// used to write the data, since all the
// fields are initialized properly.
// [xData] - Where data is written
// [dwIdentifier] - The metabase id
//
// History: 24-Feb-1998 dlee Created
//
//--------------------------------------------------------------------------
void CMetaDataMgr::ReadRootValue(
CMetaDataHandle & mdRoot,
METADATA_RECORD & mdr,
XGrowable<WCHAR> & xData,
DWORD dwIdentifier )
{
RtlZeroMemory( &mdr, sizeof mdr );
mdr.dwMDIdentifier = dwIdentifier;
// script maps, etc. can be enormous due to bugs in ISV apps
do
{
mdr.pbMDData = (BYTE *) xData.Get();
mdr.dwMDDataLen = xData.SizeOf();
DWORD cbRequired = 0;
SCODE sc = _xAdminBase->GetData( mdRoot.Get(),
L"",
&mdr,
&cbRequired );
if ( HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) == sc )
{
xData.SetSizeInBytes( cbRequired );
continue;
}
else if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "GetData root value failed: 0x%x\n", sc ));
THROW( CException( sc ) );
}
break;
} while ( TRUE );
} //ReadRootValue
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::WriteRootValue, private
//
// Synopsis: Writes data to the key
//
// Arguments: [mdRoot] - Metabase key where data resides
// [mdr] - Metadata record suitable for writing data
// [pwcData] - Multi-sz string with data
// [cwcData] - Total length including all terminating nulls
//
// History: 24-Feb-1998 dlee Created
//
//--------------------------------------------------------------------------
void CMetaDataMgr::WriteRootValue(
CMetaDataHandle & mdRoot,
METADATA_RECORD & mdr,
WCHAR const * pwcData,
unsigned cwcData )
{
// note: the other fields in mdr were initialized properly by a call
// to ReadRootValue.
mdr.dwMDDataLen = sizeof WCHAR * cwcData;
mdr.pbMDData = (BYTE *) pwcData;
SCODE sc = _xAdminBase->SetData( mdRoot.Get(),
L"",
&mdr );
if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "SetData root value failed: 0x%x\n", sc ));
THROW( CException( sc ) );
}
} //WriteRootValue
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::AddScriptMap, public
//
// Synopsis: Adds a script map to the metabase
//
// Arguments: [pwcMap] - script map of the form:
// L".idq,d:\\winnt\\system32\\idq.dll,0"
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
void CMetaDataMgr::AddScriptMap(
WCHAR const * pwcMap )
{
// remove the existing script map if it exists. have to get the
// extension first.
if ( wcslen( pwcMap ) > MAX_PATH )
THROW( CException( HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ) ) );
WCHAR awcExt[ MAX_PATH ];
wcscpy( awcExt, pwcMap );
WCHAR *pwc = wcschr( awcExt, L',' );
if ( !pwc )
THROW( CException( HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ) ) );
*pwc = 0;
RemoveScriptMap( awcExt );
CMetaDataHandle mdRoot( _xAdminBase, L"/lm/w3svc", TRUE );
XGrowable<WCHAR> xMaps;
METADATA_RECORD mdr;
ReadRootValue( mdRoot, mdr, xMaps, MD_SCRIPT_MAPS );
// add the new script map to the existing ones
XGrowable<WCHAR> xTemp;
xTemp.SetSize( xMaps.Count() + wcslen( pwcMap ) + 1 );
WCHAR *pwcTemp = xTemp.Get();
wcscpy( pwcTemp, pwcMap );
pwcTemp += ( 1 + wcslen( pwcTemp ) );
WCHAR * pwcOldMaps = xMaps.Get();
while ( 0 != *pwcOldMaps )
{
wcscpy( pwcTemp, pwcOldMaps );
int x = 1 + wcslen( pwcOldMaps );
pwcTemp += x;
pwcOldMaps += x;
}
*pwcTemp++ = 0;
// write the new set of script maps
WriteRootValue( mdRoot, mdr, xTemp.Get(), (UINT)( pwcTemp - xTemp.Get() ) );
} //AddScriptMap
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::RemoveScriptMap, public
//
// Synopsis: Removes a script map from the metabase
//
// Arguments: [pwcExt] - extension of map to remove: L".idq"
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
void CMetaDataMgr::RemoveScriptMap(
WCHAR const * pwcExt )
{
// retrieve the existing script maps
CMetaDataHandle mdRoot( _xAdminBase, L"/lm/w3svc", TRUE );
XGrowable<WCHAR> xMaps;
METADATA_RECORD mdr;
ReadRootValue( mdRoot, mdr, xMaps, MD_SCRIPT_MAPS );
// awcMaps is a multi-sz string
XGrowable<WCHAR> xNew( xMaps.Count() );
WCHAR *pwcNew = xNew.Get();
pwcNew[0] = 0;
int cwcExt = wcslen( pwcExt );
BOOL fFound = FALSE;
// re-add all mappings other than pwcExt
WCHAR const *pwcCur = xMaps.Get();
while ( 0 != *pwcCur )
{
if ( _wcsnicmp( pwcCur, pwcExt, cwcExt ) ||
L',' != pwcCur[cwcExt] )
{
wcscpy( pwcNew, pwcCur );
pwcNew += ( 1 + wcslen( pwcNew ) );
}
else
{
fFound = TRUE;
}
int cwc = wcslen( pwcCur );
pwcCur += ( cwc + 1 );
}
// If the script map wasn't found, don't do the write
if ( !fFound )
return;
*pwcNew++ = 0;
// got the string, now pound it in the metabase
WriteRootValue( mdRoot, mdr, xNew.Get(), (UINT)(pwcNew - xNew.Get()) );
} //RemoveScriptMap
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::ExtensionHasScriptMap, public
//
// Synopsis: Finds a script map in the metabase
//
// Arguments: [pwcExt] - extension of map to lookup: L".idq"
//
// Returns: TRUE if the extension has a script map association
// FALSE otherwise
//
// History: 10-Jul-1997 dlee Created
//
//--------------------------------------------------------------------------
BOOL CMetaDataMgr::ExtensionHasScriptMap(
WCHAR const * pwcExt )
{
CMetaDataHandle mdRoot( _xAdminBase, L"/lm/w3svc", FALSE );
XGrowable<WCHAR> xMaps;
METADATA_RECORD mdr;
ReadRootValue( mdRoot, mdr, xMaps, MD_SCRIPT_MAPS );
// xMaps is a multi-sz string, look for pwcExt
int cwcExt = wcslen( pwcExt );
WCHAR *pwcCur = xMaps.Get();
while ( 0 != *pwcCur )
{
if ( !_wcsnicmp( pwcCur, pwcExt, cwcExt ) &&
L',' == pwcCur[cwcExt] )
return TRUE;
int cwc = wcslen( pwcCur );
pwcCur += ( cwc + 1 );
}
return FALSE;
} //ExtensionHasScriptMap
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::ExtensionHasTargetScriptMap, public
//
// Synopsis: Sees if a scriptmap is pointing at a given dll
//
// Arguments: [pwcExt] - extension of map to lookup: L".idq"
// [pwcDll] - DLL to check, e.g. L"idq.dll"
//
// Returns: TRUE if the extension has a script map association
// FALSE otherwise
//
// History: 10-Jul-1997 dlee Created
//
// Note: scriptmaps look like ".idq,c:\\windows\\system32\\idq.dll,3,GET,HEAD,POST"
//
//--------------------------------------------------------------------------
BOOL CMetaDataMgr::ExtensionHasTargetScriptMap(
WCHAR const * pwcExt,
WCHAR const * pwcDll )
{
CMetaDataHandle mdRoot( _xAdminBase, L"/lm/w3svc", FALSE );
XGrowable<WCHAR> xMaps;
METADATA_RECORD mdr;
ReadRootValue( mdRoot, mdr, xMaps, MD_SCRIPT_MAPS );
// xMaps is a multi-sz string, look for pwcExt
int cwcExt = wcslen( pwcExt );
WCHAR *pwcCur = xMaps.Get();
int cwcDll = wcslen( pwcDll );
while ( 0 != *pwcCur )
{
if ( !_wcsnicmp( pwcCur, pwcExt, cwcExt ) &&
L',' == pwcCur[cwcExt] )
{
// Skip to the end of the full path and check the dll name
WCHAR const * pwcSlash = wcsrchr( pwcCur, L'\\' );
if ( 0 != pwcSlash )
{
if ( !_wcsnicmp( pwcSlash + 1, pwcDll, cwcDll ) )
return TRUE;
}
}
int cwc = wcslen( pwcCur );
pwcCur += ( cwc + 1 );
}
return FALSE;
} //ExtensionHasTargetScriptMap
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::AddInProcessApp, public
//
// Synopsis: Adds an app to the list of in-process apps
//
// Arguments: [pwcApp] - App in the form "d:\\winnt\\system32\\idq.dll"
//
// History: 09-Dec-1998 dlee Created
//
//--------------------------------------------------------------------------
void CMetaDataMgr::AddInProcessIsapiApp( WCHAR const * pwcApp )
{
//
// Read the existing multi-sz value
//
CMetaDataHandle mdRoot( _xAdminBase, L"/lm/w3svc", TRUE );
XGrowable<WCHAR> xApps;
METADATA_RECORD mdr;
ReadRootValue( mdRoot, mdr, xApps, MD_IN_PROCESS_ISAPI_APPS );
WCHAR *pwcCur = xApps.Get();
//
// Look for an existing entry so a duplicate isn't added
//
while ( 0 != *pwcCur )
{
//
// If it's already there, leave it alone
//
if ( !_wcsicmp( pwcCur, pwcApp ) )
return;
int cwc = wcslen( pwcCur );
pwcCur += ( cwc + 1 );
}
unsigned cwcOld = 1 + (unsigned) ( pwcCur - xApps.Get() );
//
// It wasn't found, so add it
//
unsigned cwc = wcslen( pwcApp ) + 1;
XGrowable<WCHAR> xNew( cwcOld + cwc );
RtlCopyMemory( xNew.Get(), pwcApp, cwc * sizeof WCHAR );
RtlCopyMemory( xNew.Get() + cwc, xApps.Get(), cwcOld * sizeof WCHAR );
WriteRootValue( mdRoot, mdr, xNew.Get(), cwcOld + cwc );
} //AddInProcessIsapiApp
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::EnableVPathNotify, public
//
// Synopsis: Enables notification of vpaths
//
// Arguments: [pCallBack] - called on a change to any vpaths
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
void CMetaDataMgr::EnableVPathNotify(
CMetaDataVPathChangeCallBack *pCallBack )
{
Win4Assert( !_fTopLevel );
Win4Assert( !_fNotifyEnabled );
if ( _fNotifyEnabled )
THROW( CException( HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ) ) );
ciDebugOut(( DEB_WARN,
"enabling vpath notifications on '%ws'\n",
_awcInstance ));
Win4Assert( _xSink.IsNull() );
//
// NOTE: This new will be reported as a leak if iisamin dies or fails
// to call Release() on the sink the right number of times.
//
XInterface<CMetaDataComSink> xSink( new CMetaDataComSink() );
xSink->SetCallBack( pCallBack );
xSink->SetInstance( _awcInstance );
XInterface< IConnectionPointContainer > xCPC;
SCODE sc = _xAdminBase->QueryInterface( IID_IConnectionPointContainer,
xCPC.GetQIPointer() );
if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "could not get cpc: 0x%x\n", sc ));
THROW( CException( sc ) );
}
XInterface< IConnectionPoint> xCP;
sc = xCPC->FindConnectionPoint( IID_IMSAdminBaseSink, xCP.GetPPointer() );
if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "could not get cp: 0x%x\n", sc ));
THROW( CException( sc ) );
}
//
// Tell COM to impersonate at IMPERSONATE level instead of the default
// IDENTITY level. This is to work-around a change made in IIS in
// Windows 2000 SP1.
//
sc = CoSetProxyBlanket( xCP.GetPointer(),
RPC_C_AUTHN_WINNT, // use NT default security
RPC_C_AUTHZ_NONE, // use NT default authentication
NULL, // must be null if default
RPC_C_AUTHN_LEVEL_CALL, // call
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, // use process token
EOAC_STATIC_CLOAKING );
if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "could not set proxy blanket: %#x\n", sc ));
THROW( CException( sc ) );
}
sc = xCP->Advise( xSink.GetPointer(), &_dwCookie);
if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "could not advise cp: 0x%x\n", sc ));
THROW( CException( sc ) );
}
_xCP.Set( xCP.Acquire() );
_xSink.Set( xSink.Acquire() );
_fNotifyEnabled = TRUE;
} //EnableVPathNotify
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::DisableVPathNotify, public
//
// Synopsis: Disables notification on VPaths
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
void CMetaDataMgr::DisableVPathNotify()
{
if ( _fNotifyEnabled )
{
SCODE sc = _xCP->Unadvise( _dwCookie );
ciDebugOut(( DEB_ITRACE, "result of unadvise: 0x%x\n", sc ));
_fNotifyEnabled = FALSE;
//
// Note: The sink may still have a refcount after the free if
// iisadmin has a bug or their process died. We can't just
// delete it here because CoUninitialize() will realize
// iisadmin messed up and try to help by calling Release()
// for iisadmin.
//
_xSink.Free();
_xCP.Free();
}
} //DisableVPathNotify
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::ReportVPath, private
//
// Synopsis: Helper method for reporting a vpath via callback
//
// Arguments: [vrootStack] - stack of vroots for depth-first search
// [mdRoot] - handle to the root of the enumeration
// [callBack] - callback to call for vpath
// [pwcRelative] - relative path in metabase
//
// Returns: TRUE if the vpath is a vroot and was pushed on vrootStack
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
BOOL CMetaDataMgr::ReportVPath(
CVRootStack & vrootStack,
CMetaDataCallBack & callBack,
CMetaDataHandle & mdRoot,
WCHAR const * pwcRelative )
{
Win4Assert( !_fTopLevel );
// read the path, username, access permissions, and password
WCHAR awcPPath[ METADATA_MAX_NAME_LEN ];
awcPPath[0] = 0;
WCHAR awcUser[ METADATA_MAX_NAME_LEN ];
awcUser[0] = 0;
DWORD dwAccess = 0;
WCHAR awcPassword[ METADATA_MAX_NAME_LEN ];
awcPassword[0] = 0;
BOOL fIsIndexed = TRUE;
BOOL fVRoot = TRUE;
// Get the metabase access permission mask
{
METADATA_RECORD mdr;
RtlZeroMemory( &mdr, sizeof mdr );
mdr.dwMDIdentifier = MD_ACCESS_PERM;
mdr.dwMDAttributes = METADATA_INHERIT;
mdr.pbMDData = (BYTE *) &dwAccess;
mdr.dwMDDataLen = sizeof dwAccess;
DWORD cbRequired = 0;
SCODE sc = _xAdminBase->GetData( mdRoot.Get(),
pwcRelative,
&mdr,
&cbRequired );
if ( ( FAILED( sc ) ) &&
( (MD_ERROR_DATA_NOT_FOUND) != sc ) )
{
ciDebugOut(( DEB_WARN, "GetData awccessperm failed: 0x%x\n", sc ));
THROW( CException( sc ) );
}
}
// Get the physical path if one exists
{
METADATA_RECORD mdr;
RtlZeroMemory( &mdr, sizeof mdr );
mdr.dwMDIdentifier = MD_VR_PATH;
mdr.pbMDData = (BYTE *) awcPPath;
mdr.dwMDDataLen = sizeof awcPPath;
DWORD cbRequired = 0;
SCODE sc = _xAdminBase->GetData( mdRoot.Get(),
pwcRelative,
&mdr,
&cbRequired );
if ( ( FAILED( sc ) ) &&
( (MD_ERROR_DATA_NOT_FOUND) != sc ) )
{
ciDebugOut(( DEB_WARN, "GetData PRoot failed: 0x%x\n", sc ));
THROW( CException( sc ) );
}
}
//
// Only look for a username/access/password if there is a physical path,
// since it can only be a virtual root if it has a physical path.
//
if ( 0 != awcPPath[0] )
{
// Trim any trailing backslash from the physical path
unsigned cwcPRoot = wcslen( awcPPath );
Win4Assert( 0 != cwcPRoot );
if ( L'\\' == awcPPath[ cwcPRoot - 1 ] )
awcPPath[ cwcPRoot - 1 ] = 0;
{
METADATA_RECORD mdr;
RtlZeroMemory( &mdr, sizeof mdr );
mdr.dwMDIdentifier = MD_VR_USERNAME;
mdr.pbMDData = (BYTE *) awcUser;
mdr.dwMDDataLen = sizeof awcUser;
DWORD cbRequired = 0;
SCODE sc = _xAdminBase->GetData( mdRoot.Get(),
pwcRelative,
&mdr,
&cbRequired );
if ( ( FAILED( sc ) ) &&
( (MD_ERROR_DATA_NOT_FOUND) != sc ) )
{
ciDebugOut(( DEB_WARN, "GetData user failed: 0x%x\n", sc ));
THROW( CException( sc ) );
}
}
{
METADATA_RECORD mdr;
RtlZeroMemory( &mdr, sizeof mdr );
mdr.dwMDIdentifier = MD_VR_PASSWORD;
mdr.pbMDData = (BYTE *) awcPassword;
mdr.dwMDDataLen = sizeof awcPassword;
DWORD cbRequired = 0;
SCODE sc = _xAdminBase->GetData( mdRoot.Get(),
pwcRelative,
&mdr,
&cbRequired );
if ( ( FAILED( sc ) ) &&
( (MD_ERROR_DATA_NOT_FOUND) != sc ) )
{
ciDebugOut(( DEB_WARN, "GetData password failed: 0x%x\n", sc ));
THROW( CException( sc ) );
}
}
}
{
METADATA_RECORD mdr;
RtlZeroMemory( &mdr, sizeof mdr );
mdr.dwMDIdentifier = MD_IS_CONTENT_INDEXED;
mdr.dwMDAttributes = METADATA_INHERIT;
mdr.pbMDData = (BYTE *) &fIsIndexed;
mdr.dwMDDataLen = sizeof fIsIndexed;
DWORD cbRequired = 0;
SCODE sc = _xAdminBase->GetData( mdRoot.Get(),
pwcRelative,
&mdr,
&cbRequired );
if ( MD_ERROR_DATA_NOT_FOUND == sc )
{
fIsIndexed = FALSE;
}
else if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "GetData isindexed failed: 0x%x\n", sc ));
THROW( CException( sc ) );
}
}
WCHAR awcVPath[METADATA_MAX_NAME_LEN];
wcscpy( awcVPath, pwcRelative );
WCHAR *pwcVPath = awcVPath;
// Important: The metabase names root "/Root" the rest of the world
// names root "/".
if ( !_wcsicmp( awcVPath, L"/Root" ) )
awcVPath[1] = 0;
else if ( !_wcsnicmp( awcVPath, L"/Root", 5 ) )
{
Win4Assert( L'/' == awcVPath[5] );
pwcVPath = awcVPath + 5;
}
if ( 0 == awcPPath[0] )
{
// if there isn't a physical path, it isn't a virtual root.
fVRoot = FALSE;
if ( vrootStack.IsEmpty() )
{
awcPPath[0] = 0;
}
else
{
// generate a physical path based on the virtual path and
// the most recent vroot parent on the stack
ciDebugOut(( DEB_ITRACE,
"making vpath from vroot '%ws' proot '%ws' vpath '%ws'\n",
vrootStack.PeekTopVRoot(),
vrootStack.PeekTopPRoot(),
pwcVPath ));
wcscpy( awcPPath, vrootStack.PeekTopPRoot() );
unsigned cwcVRoot = wcslen( vrootStack.PeekTopVRoot() );
unsigned cwcPRoot = wcslen( vrootStack.PeekTopPRoot() );
// The metabase can contain trailing backslashes in physical paths
if ( L'\\' == awcPPath[ cwcPRoot - 1 ] )
cwcPRoot--;
wcscpy( awcPPath + cwcPRoot,
pwcVPath + ( ( 1 == cwcVRoot ) ? 0 : cwcVRoot ) );
for ( WCHAR *pwc = awcPPath + cwcPRoot;
0 != *pwc;
pwc++ )
{
if ( L'/' == *pwc )
*pwc = L'\\';
}
ciDebugOut(( DEB_ITRACE, "resulting ppath: '%ws'\n", awcPPath ));
}
}
// now we can finally call the callback
if ( 0 != awcPPath[0] )
callBack.CallBack( pwcVPath,
awcPPath,
fIsIndexed,
dwAccess,
awcUser,
awcPassword,
fVRoot );
if ( fVRoot )
vrootStack.Push( pwcVPath, awcPPath, dwAccess );
return fVRoot;
} //ReportVPath
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::EnumVServers, public
//
// Synopsis: Enumerates virtual servers by calling the callback
//
// Arguments: [callBack] - called for each vroot
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
void CMetaDataMgr::EnumVServers( CMetaDataVirtualServerCallBack & callBack )
{
Win4Assert( _fTopLevel );
CMetaDataHandle mdRoot( _xAdminBase, _awcInstance );
Enum( callBack, mdRoot, L"" );
} //EnumVRoots
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::ReportVirtualServer, private
//
// Synopsis: Helper method for reporting a virtual server via callback
//
// Arguments: [callBack] - callback to call for virtual server
// [pwcRelative] - relative path in metabase
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
void CMetaDataMgr::ReportVirtualServer(
CMetaDataVirtualServerCallBack & callBack,
CMetaDataHandle & mdRoot,
WCHAR const * pwcRelative )
{
Win4Assert( _fTopLevel );
// read the comment
WCHAR awcComment[ METADATA_MAX_NAME_LEN ];
awcComment[0] = 0;
{
METADATA_RECORD mdr;
RtlZeroMemory( &mdr, sizeof mdr );
mdr.dwMDIdentifier = MD_SERVER_COMMENT;
mdr.pbMDData = (BYTE *) awcComment;
mdr.dwMDDataLen = sizeof awcComment;
DWORD cbRequired = 0;
SCODE sc = _xAdminBase->GetData( mdRoot.Get(),
pwcRelative,
&mdr,
&cbRequired );
if ( ( FAILED( sc ) ) &&
( (MD_ERROR_DATA_NOT_FOUND) != sc ) )
{
ciDebugOut(( DEB_WARN, "GetData virtual server failed: 0x%x\n", sc ));
THROW( CException( sc ) );
}
}
//
// Convert ID to integer
//
DWORD iInstance = wcstoul( pwcRelative, 0, 10 );
// now we can finally call the callback
callBack.CallBack( iInstance, awcComment );
} //ReportVirtualServer
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::Enum, private
//
// Synopsis: Helper method for enumerating vpaths
//
// Arguments: [vrootStack] - stack of vroots for depth-first search
// [callBack] - callback to call when a vpath is found
// [mdRoot] - root of the enumeration
// [pwcRelative] - relative location in enumeration
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
void CMetaDataMgr::Enum(
CVRootStack & vrootStack,
CMetaDataCallBack & callBack,
CMetaDataHandle & mdRoot,
WCHAR const * pwcRelative )
{
// enumerate looking for vpaths
int c = wcslen( pwcRelative );
WCHAR awcNewRelPath[ METADATA_MAX_NAME_LEN ];
RtlCopyMemory( awcNewRelPath, pwcRelative, (c + 1) * sizeof WCHAR );
if ( 0 == c ||
L'/' != pwcRelative[c-1] )
{
wcscpy( awcNewRelPath + c, L"/" );
c++;
}
for ( int i = 0; ; i++ )
{
WCHAR NameBuf[METADATA_MAX_NAME_LEN];
SCODE sc =_xAdminBase->EnumKeys( mdRoot.Get(),
pwcRelative,
NameBuf,
i );
if ( RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS) == sc )
break;
if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "EnumKeys error 0x%x\n", sc ));
THROW( CException( sc ) );
}
Win4Assert( 0 != NameBuf[0] );
Win4Assert( ( c + wcslen( NameBuf ) ) < METADATA_MAX_NAME_LEN );
wcscpy( awcNewRelPath + c, NameBuf );
BOOL fVRoot = ReportVPath( vrootStack,
callBack,
mdRoot,
awcNewRelPath );
Enum( vrootStack, callBack, mdRoot, awcNewRelPath );
if ( fVRoot )
vrootStack.Pop();
}
} //Enum
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::Enum, private
//
// Synopsis: Helper method for enumerating virtual servers
//
// Arguments: [callBack] - callback to call when a vserver is found
// [mdRoot] - root of the enumeration
// [pwcRelative] - relative location in enumeration
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
void CMetaDataMgr::Enum(
CMetaDataVirtualServerCallBack & callBack,
CMetaDataHandle & mdRoot,
WCHAR const * pwcRelative )
{
// enumerate looking for virtual servers
for ( int i = 0; ; i++ )
{
WCHAR NameBuf[METADATA_MAX_NAME_LEN];
SCODE sc =_xAdminBase->EnumKeys( mdRoot.Get(),
pwcRelative,
NameBuf,
i );
if ( RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS) == sc )
break;
if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "EnumKeys error 0x%x\n", sc ));
THROW( CException( sc ) );
}
ciDebugOut(( DEB_WARN, "Key: %ws\n", NameBuf ));
//
// Ignore things that don't look like virtual servers.
//
if ( !isdigit( NameBuf[0] ) )
continue;
//
// Assume we just got a virtual server.
//
ReportVirtualServer( callBack, mdRoot, NameBuf );
}
} //Enum
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::GetVRoot, public
//
// Synopsis: Returns the physical root corresponding to a virtual root
//
// Arguments: [pwcVRoot] - VRoot to lookup
// [pwcPRoot] - where pwcVRoot's physical root is returned
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
void CMetaDataMgr::GetVRoot(
WCHAR const * pwcVRoot,
WCHAR * pwcPRoot )
{
Win4Assert( !_fTopLevel );
unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" ) + wcslen( pwcVRoot );
if ( cwc >= METADATA_MAX_NAME_LEN )
THROW( CException( E_INVALIDARG ) );
WCHAR awcVRootPath[ METADATA_MAX_NAME_LEN ];
wcscpy( awcVRootPath, _awcInstance );
wcscat( awcVRootPath, L"/Root" );
wcscat( awcVRootPath, pwcVRoot );
CMetaDataHandle mdVRoot( _xAdminBase, awcVRootPath, FALSE );
*pwcPRoot = 0;
{
METADATA_RECORD mdr;
RtlZeroMemory( &mdr, sizeof mdr );
mdr.dwMDIdentifier = MD_VR_PATH;
mdr.pbMDData = (BYTE *) pwcPRoot;
mdr.dwMDDataLen = METADATA_MAX_NAME_LEN * sizeof WCHAR;
DWORD cbRequired = 0;
SCODE sc = _xAdminBase->GetData( mdVRoot.Get(),
L"",
&mdr,
&cbRequired );
if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "GetData PRoot failed: 0x%x\n", sc ));
THROW( CException( sc ) );
}
}
} //GetVRoot
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::GetVRootPW, public
//
// Synopsis: Returns the physical root corresponding to a virtual root
//
// Arguments: [pwcVRoot] - VRoot to lookup
// [pwcPRoot] - where pwcVRoot's physical root is returned
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
void CMetaDataMgr::GetVRootPW(
WCHAR const * pwcVRoot,
WCHAR * pwcPW )
{
Win4Assert( !_fTopLevel );
unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" ) + wcslen( pwcVRoot );
if ( cwc >= METADATA_MAX_NAME_LEN )
THROW( CException( E_INVALIDARG ) );
WCHAR awcVRootPath[ METADATA_MAX_NAME_LEN ];
wcscpy( awcVRootPath, _awcInstance );
wcscat( awcVRootPath, L"/Root" );
wcscat( awcVRootPath, pwcVRoot );
CMetaDataHandle mdVRoot( _xAdminBase, awcVRootPath, FALSE );
*pwcPW = 0;
{
METADATA_RECORD mdr;
RtlZeroMemory( &mdr, sizeof mdr );
mdr.dwMDIdentifier = MD_VR_PASSWORD;
mdr.pbMDData = (BYTE *) pwcPW;
mdr.dwMDDataLen = METADATA_MAX_NAME_LEN * sizeof WCHAR;
DWORD cbRequired = 0;
SCODE sc = _xAdminBase->GetData( mdVRoot.Get(),
L"",
&mdr,
&cbRequired );
//char ac[ 1000 ];
//sprintf( ac, "result: 0x%x, cbResult: 0x%x, string: '%ws', char 1: 0x%x\n",
// sc, mdr.dwMDDataLen, pwcPW, (ULONG) *pwcPW );
//DbgPrint( ac );
if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "GetData PRoot failed: 0x%x\n", sc ));
THROW( CException( sc ) );
}
}
} //GetVRootPW
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::SetIsIndexed, public
//
// Synopsis: Sets the indexed state of a virtual path
//
// Arguments: [pwcPath] - Virtual path (optionally a vroot) to set
// [fIsIndexed] - if TRUE, path is indexed, if FALSE it isn't
//
// History: 19-Mar-1997 dlee Created
//
//--------------------------------------------------------------------------
void CMetaDataMgr::SetIsIndexed(
WCHAR const * pwcVPath,
BOOL fIsIndexed )
{
// Add the key if it doesn't exist yet
{
unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" );
if ( cwc >= METADATA_MAX_NAME_LEN )
THROW( CException( E_INVALIDARG ) );
WCHAR awc[ METADATA_MAX_NAME_LEN ];
wcscpy( awc, _awcInstance );
wcscat( awc, L"/Root" );
CMetaDataHandle mdRoot( _xAdminBase, awc, TRUE );
_xAdminBase->AddKey( mdRoot.Get(), pwcVPath );
}
unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" ) + wcslen( pwcVPath );
if ( cwc >= METADATA_MAX_NAME_LEN )
THROW( CException( E_INVALIDARG ) );
WCHAR awcCompleteVPath[ METADATA_MAX_NAME_LEN ];
wcscpy( awcCompleteVPath, _awcInstance );
wcscat( awcCompleteVPath, L"/Root" );
wcscat( awcCompleteVPath, pwcVPath );
CMetaDataHandle mdVRoot( _xAdminBase, awcCompleteVPath, TRUE );
{
METADATA_RECORD mdr;
RtlZeroMemory( &mdr, sizeof mdr );
mdr.dwMDIdentifier = MD_IS_CONTENT_INDEXED;
mdr.dwMDAttributes = METADATA_INHERIT;
mdr.dwMDUserType = IIS_MD_UT_FILE;
mdr.dwMDDataType = DWORD_METADATA;
mdr.pbMDData = (BYTE *) &fIsIndexed;
mdr.dwMDDataLen = sizeof fIsIndexed;
DWORD cbRequired = 0;
SCODE sc = _xAdminBase->SetData( mdVRoot.Get(),
L"",
&mdr );
if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "SetData isindexed failed: 0x%x\n", sc ));
THROW( CException( sc ) );
}
}
} //SetIsIndexed
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::IsIndexed, public
//
// Synopsis: Checks the path to return the state of the IsIndexed flag.
// The default for no value is TRUE. No checking is made to
// if a parent directory is indexed or not.
//
// Arguments: [pwcVPath] - Virtual path (optionally a vroot) to check
//
// History: 19-Mar-1997 dlee Created
//
//--------------------------------------------------------------------------
BOOL CMetaDataMgr::IsIndexed(
WCHAR const * pwcVPath )
{
BOOL fIsIndexed = TRUE;
unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" ) + wcslen( pwcVPath );
if ( cwc >= METADATA_MAX_NAME_LEN )
THROW( CException( E_INVALIDARG ) );
WCHAR awcCompletePath[ METADATA_MAX_NAME_LEN ];
wcscpy( awcCompletePath, _awcInstance );
wcscat( awcCompletePath, L"/Root" );
wcscat( awcCompletePath, pwcVPath );
TRY
{
CMetaDataHandle mdVRoot( _xAdminBase, awcCompletePath, FALSE );
{
METADATA_RECORD mdr;
RtlZeroMemory( &mdr, sizeof mdr );
mdr.dwMDIdentifier = MD_IS_CONTENT_INDEXED;
mdr.dwMDAttributes = METADATA_INHERIT;
mdr.pbMDData = (BYTE *) &fIsIndexed;
mdr.dwMDDataLen = sizeof fIsIndexed;
DWORD cbRequired = 0;
SCODE sc = _xAdminBase->GetData( mdVRoot.Get(),
L"",
&mdr,
&cbRequired );
if ( MD_ERROR_DATA_NOT_FOUND == sc )
{
fIsIndexed = FALSE;
}
else if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "GetData isindexed failed: 0x%x\n", sc ));
THROW( CException( sc ) );
}
}
}
CATCH( CException, e )
{
// ignore -- assume IsIndexed
}
END_CATCH;
return fIsIndexed;
} //IsIndexed
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::GetVPathFlags, public
//
// Synopsis: Returns flag settings on a virtual path
//
// Arguments: [pwcVPath] - Virtual path (optionally a vroot) to check
// [mdID] - MD_x constant for the data
// [ulDefault] - Default if no value is in the metabase
//
// History: 18-Aug-1997 dlee Created
//
//--------------------------------------------------------------------------
ULONG CMetaDataMgr::GetVPathFlags(
WCHAR const * pwcVPath,
ULONG mdID,
ULONG ulDefault )
{
unsigned cwc = wcslen( _awcInstance ) + wcslen( L"/Root" ) + wcslen( pwcVPath );
if ( cwc >= METADATA_MAX_NAME_LEN )
THROW( CException( E_INVALIDARG ) );
WCHAR awcCompletePath[ METADATA_MAX_NAME_LEN ];
wcscpy( awcCompletePath, _awcInstance );
wcscat( awcCompletePath, L"/Root" );
wcscat( awcCompletePath, pwcVPath );
DWORD dwFlags = ulDefault;
// Keep removing path components on the right of the path until
// either out of path or the metabase recognizes the path.
METADATA_HANDLE h;
do
{
SCODE sc = _xAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
awcCompletePath,
METADATA_PERMISSION_READ,
cmsCIMetabaseTimeout,
&h );
if ( S_OK == sc )
{
break;
}
else if ( HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == sc )
{
WCHAR * pwc = wcsrchr( awcCompletePath, L'/' );
if ( 0 == pwc )
THROW( CException( sc ) );
*pwc = 0;
}
else
THROW( CException( sc ) );
} while ( TRUE );
CMetaDataHandle mdVRoot( _xAdminBase, h );
{
METADATA_RECORD mdr;
RtlZeroMemory( &mdr, sizeof mdr );
mdr.dwMDIdentifier = mdID;
mdr.dwMDAttributes = METADATA_INHERIT;
mdr.pbMDData = (BYTE *) &dwFlags;
mdr.dwMDDataLen = sizeof dwFlags;
DWORD cbRequired = 0;
SCODE sc = _xAdminBase->GetData( mdVRoot.Get(),
L"",
&mdr,
&cbRequired );
if ( MD_ERROR_DATA_NOT_FOUND == sc )
{
// no value specified for this flag; use default
dwFlags = ulDefault;
}
else if ( FAILED( sc ) )
{
ciDebugOut(( DEB_WARN, "GetData mdid %d failed: 0x%x on '%ws'\n",
mdID, sc, awcCompletePath ));
THROW( CException( sc ) );
}
}
return dwFlags;
} //GetVPathFlags
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::GetVPathAccess, public
//
// Synopsis: Returns access permission settings on a virtual path
//
// Arguments: [pwcVPath] - Virtual path (optionally a vroot) to check
//
// History: 18-Aug-1997 dlee Created
//
//--------------------------------------------------------------------------
ULONG CMetaDataMgr::GetVPathAccess(
WCHAR const * pwcVPath )
{
// note: the default of 0 is from IIS' metabase guru
return GetVPathFlags( pwcVPath, MD_ACCESS_PERM, 0 );
} //GetVPathAccess
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::GetVPathSSLAccess, public
//
// Synopsis: Returns SSL access permission settings on a virtual path
//
// Arguments: [pwcVPath] - Virtual path (optionally a vroot) to check
//
// History: 18-Aug-1997 dlee Created
//
//--------------------------------------------------------------------------
ULONG CMetaDataMgr::GetVPathSSLAccess(
WCHAR const * pwcVPath )
{
// note: the default of 0 is from IIS' metabase guru
return GetVPathFlags( pwcVPath, MD_SSL_ACCESS_PERM, 0 );
} //GetVPathSSLAccess
//+-------------------------------------------------------------------------
//
// Member: CMetaDataMgr::GetVPathAuthorization, public
//
// Synopsis: Returns authorization on a virtual path
//
// Arguments: [pwcVPath] - Virtual path (optionally a vroot) to check
//
// History: 18-Aug-1997 dlee Created
//
//--------------------------------------------------------------------------
ULONG CMetaDataMgr::GetVPathAuthorization(
WCHAR const * pwcVPath )
{
// note: the default of MD_AUTH_ANONYMOUS is from IIS' metabase guru
return GetVPathFlags( pwcVPath, MD_AUTHORIZATION, MD_AUTH_ANONYMOUS );
} //GetVPathAuthorization
//+-------------------------------------------------------------------------
//
// Member: CMetaDataComSink::SinkNotify, public
//
// Synopsis: Called for any metadata change
//
// Arguments: [cChanges] - # of changes in pcoChangeList
// [pcoChangeList] - list of changes
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE CMetaDataComSink::SinkNotify(
DWORD cChanges,
MD_CHANGE_OBJECT pcoChangeList[] )
{
// This is called by an RPC worker thread -- assimilate it
TRANSLATE_EXCEPTIONS;
TRY
{
int cwcInstance = wcslen( _awcInstance );
BOOL fInterestingChange = FALSE;
ciDebugOut(( DEB_WARN, "iis sinknotify '%ws', cchanges: %d\n",
_awcInstance, cChanges ));
for ( DWORD i = 0; !fInterestingChange && i < cChanges; i++ )
{
MD_CHANGE_OBJECT & co = pcoChangeList[i];
// we only care about notifications to our instance
if ( _wcsnicmp( co.pszMDPath, _awcInstance, cwcInstance ) != 0 ||
( L'/' != co.pszMDPath[cwcInstance] &&
L'\0' != co.pszMDPath[cwcInstance] ) )
continue;
// Ignore adds of vroots -- we'll get a set_data for its
// parameters and trigger on that.
if ( ( MD_CHANGE_TYPE_DELETE_OBJECT & co.dwMDChangeType ) ||
( MD_CHANGE_TYPE_RENAME_OBJECT & co.dwMDChangeType ) )
{
// guess that the deletion was a vroot
fInterestingChange = TRUE;
}
else if ( ( MD_CHANGE_TYPE_SET_DATA & co.dwMDChangeType ) ||
( MD_CHANGE_TYPE_DELETE_DATA & co.dwMDChangeType ) )
{
for ( DWORD x = 0; x < co.dwMDNumDataIDs; x++ )
{
DWORD id = co.pdwMDDataIDs[x];
if ( MD_VR_PATH == id ||
MD_VR_USERNAME == id ||
MD_VR_PASSWORD == id ||
MD_ACCESS_PERM == id ||
MD_IS_CONTENT_INDEXED == id )
{
fInterestingChange = TRUE;
break;
}
}
}
}
if ( fInterestingChange && ( 0 != _pCallBack ) )
_pCallBack->CallBack( FALSE );
}
CATCH (CException, e)
{
ciDebugOut(( DEB_WARN,
"SinkNotify caught 0x%x\n",
e.GetErrorCode() ));
}
END_CATCH
UNTRANSLATE_EXCEPTIONS;
return S_OK;
} //SinkNotify
//+-------------------------------------------------------------------------
//
// Member: CMetaDataComSink::ShutdownNotify, public
//
// Synopsis: Called when iisadmin is going down cleanly
//
// History: 07-Feb-1997 dlee Created
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE CMetaDataComSink::ShutdownNotify()
{
// This is called by an RPC worker thread -- assimilate it
TRANSLATE_EXCEPTIONS;
TRY
{
ciDebugOut(( DEB_WARN, "iis shutdownnotify '%ws'\n", _awcInstance ));
// in case we get more random notifications, ignore them
CMetaDataVPathChangeCallBack * pCallBack = _pCallBack;
_pCallBack = 0;
pCallBack->CallBack( TRUE );
}
CATCH (CException, e)
{
ciDebugOut(( DEB_WARN,
"ShutdownNotify caught 0x%x\n",
e.GetErrorCode() ));
}
END_CATCH
UNTRANSLATE_EXCEPTIONS;
return S_OK;
} //ShutdownNotify