windows-nt/Source/XPSP1/NT/inetsrv/iis/admin/wmiprov_dynamic/enum.cpp
2020-09-26 16:20:57 +08:00

766 lines
21 KiB
C++

/*++
Copyright (c) 1998-2001 Microsoft Corporation
Module Name:
enum.cpp
Abstract:
Enumerates metabase tree.
Author:
???
Revision History:
Mohit Srivastava 18-Dec-00
--*/
#include "iisprov.h"
#include "enum.h"
#include "ipsecurity.h"
#include "adminacl.h"
#include "WbemObjectSink.h"
#include "instancehelper.h"
#include "SmartPointer.h"
#include <adserr.h>
extern CDynSchema* g_pDynSch;
///////////////////////////////////////
//
// CEnum class
//
///////////////////////////////////////
CEnum::CEnum()
{
m_pInstMgr = NULL;
m_pNamespace = NULL;
m_pAssociation = NULL;
m_pParsedObject = NULL;
m_hKey = NULL;
}
CEnum::~CEnum()
{
if(m_hKey)
m_metabase.CloseKey(m_hKey);
delete m_pInstMgr;
}
void CEnum::Init(
IWbemObjectSink FAR* a_pHandler,
CWbemServices* a_pNamespace,
ParsedObjectPath* a_pParsedObject,
LPWSTR a_pszKey,
WMI_ASSOCIATION* a_pAssociation,
SQL_LEVEL_1_RPN_EXPRESSION_EXT* a_pExp) // default(NULL)
{
if (!a_pHandler || !a_pNamespace || !a_pParsedObject)
throw WBEM_E_FAILED;
m_pInstMgr = new CWbemObjectSink(a_pHandler);
if(!m_pInstMgr)
{
THROW_ON_ERROR(WBEM_E_OUT_OF_MEMORY);
}
m_pNamespace = a_pNamespace;
m_pAssociation = a_pAssociation;
m_pParsedObject = a_pParsedObject;
m_pExp = a_pExp;
m_hKey = m_metabase.OpenKey(a_pszKey, false); // read only
}
void CEnum::SetObjectPath(
LPCWSTR a_pszPropertyName,
LPCWSTR a_pszObjectPath,
IWbemClassObject* a_pObj
)
{
_bstr_t bstr(a_pszPropertyName);
_variant_t v(a_pszObjectPath);
HRESULT hr = a_pObj->Put(bstr, 0, &v, 0);
THROW_ON_ERROR(hr);
}
void CEnum::PingObject()
{
CComPtr<IWbemClassObject> spObj;
CInstanceHelper InstanceHelper(m_pParsedObject, m_pNamespace);
DBG_ASSERT(!InstanceHelper.IsAssoc());
try
{
InstanceHelper.GetInstance(false, &m_metabase, &spObj, m_pExp);
}
catch(HRESULT hr)
{
if(hr != E_ADS_PROPERTY_NOT_SUPPORTED && hr != WBEM_E_NOT_FOUND)
{
throw;
}
}
if(spObj != NULL)
{
m_pInstMgr->Indicate(spObj);
}
}
void CEnum::PingAssociation(
LPCWSTR a_pszLeftKeyPath
)
{
HRESULT hr;
CComPtr<IWbemClassObject> spObj;
CComPtr<IWbemClassObject> spClass;
TSmartPointerArray<WCHAR> swszObjectPath;
CObjectPathParser PathParser(e_ParserAcceptRelativeNamespace);
if( m_pAssociation->pType != &WMI_ASSOCIATION_TYPE_DATA::s_ElementSetting &&
m_pAssociation->pType != &WMI_ASSOCIATION_TYPE_DATA::s_Component )
{
return;
}
hr = m_pNamespace->GetObject(
m_pAssociation->pszAssociationName,
0,
NULL,
&spClass,
NULL
);
THROW_ON_ERROR(hr);
hr = spClass->SpawnInstance(0, &spObj);
THROW_ON_ERROR(hr);
//
// first right side
//
if (!m_pParsedObject->SetClassName(m_pAssociation->pcRight->pszClassName))
throw WBEM_E_FAILED;
if (PathParser.Unparse(m_pParsedObject,&swszObjectPath))
throw WBEM_E_FAILED;
SetObjectPath(m_pAssociation->pType->pszRight, swszObjectPath, spObj);
swszObjectPath.Delete();
//
// then left side
//
if (m_pAssociation->pType == &WMI_ASSOCIATION_TYPE_DATA::s_Component)
{
// clear keyref first
m_pParsedObject->ClearKeys();
// add a keyref
_variant_t vt;
if(m_pAssociation->pcLeft->pkt == &METABASE_KEYTYPE_DATA::s_IIsComputer)
vt = L"LM"; // IIsComputer.Name = "LM"
else
vt = a_pszLeftKeyPath;
THROW_ON_FALSE(m_pParsedObject->AddKeyRef(m_pAssociation->pcLeft->pszKeyName,&vt));
}
if (!m_pParsedObject->SetClassName(m_pAssociation->pcLeft->pszClassName))
throw WBEM_E_FAILED;
if (PathParser.Unparse(m_pParsedObject,&swszObjectPath))
throw WBEM_E_FAILED;
SetObjectPath(m_pAssociation->pType->pszLeft, swszObjectPath, spObj);
swszObjectPath.Delete();
m_pInstMgr->Indicate(spObj);
}
void CEnum::DoPing(
LPCWSTR a_pszKeyName,
LPCWSTR a_pszKeyPath,
LPCWSTR a_pszParentKeyPath
)
{
// add keyref
_variant_t v(a_pszKeyPath);
THROW_ON_FALSE(m_pParsedObject->AddKeyRef(a_pszKeyName,&v));
// ping
if (!m_pAssociation)
PingObject();
else
PingAssociation(a_pszParentKeyPath);
// clear keyref
m_pParsedObject->ClearKeys();
}
void CEnum::Recurse(
LPCWSTR a_pszMetabasePath, // Current metabase location relative to m_hKey
METABASE_KEYTYPE* a_pktParentKeyType,// Current keytype
LPCWSTR a_pszLeftPath,
LPCWSTR a_pszWmiPrimaryKey,// "Name" - WMI only - nothing to do with MB
METABASE_KEYTYPE* a_pktSearch // the kt we are looking for
)
{
DWORD i = 0;
HRESULT hr;
WCHAR szSubKey[METADATA_MAX_NAME_LEN];
METABASE_KEYTYPE* pktCurrent;
DBGPRINTF((DBG_CONTEXT, "Recurse (Path = %ws, Left = %ws)\n", a_pszMetabasePath, a_pszLeftPath));
do
{
pktCurrent = a_pktSearch;
//
// Enumerate all subkeys of a_pszMetabasePath until we find a potential
// (grand*)parent of pktCurrent
//
hr = m_metabase.EnumKeys(
m_hKey,
a_pszMetabasePath,
szSubKey,
&i,
pktCurrent
);
i++;
if( hr == ERROR_SUCCESS)
{
_bstr_t bstrMetabasePath;
if(a_pszMetabasePath)
{
bstrMetabasePath = a_pszMetabasePath;
bstrMetabasePath += L"/";
}
bstrMetabasePath += szSubKey;
//
// With the exception of AdminACL, AdminACE, IPSecurity, we will only
// ping the object if we have found a keytype match in the metabase.
//
if( pktCurrent == a_pktSearch &&
!( m_pAssociation &&
m_pAssociation->pType == &WMI_ASSOCIATION_TYPE_DATA::s_Component &&
m_pAssociation->pcLeft->pkt != a_pktParentKeyType
)
)
{
DoPing(a_pszWmiPrimaryKey, bstrMetabasePath, a_pszLeftPath);
}
else if( a_pktSearch == &METABASE_KEYTYPE_DATA::s_TYPE_AdminACL || // AdminACL
a_pktSearch == &METABASE_KEYTYPE_DATA::s_TYPE_AdminACE
)
{
if( (m_pAssociation == NULL || // should never be
m_pAssociation->pType != &WMI_ASSOCIATION_TYPE_DATA::s_AdminACL ||
m_pAssociation->pcLeft->pkt == pktCurrent ||
m_pAssociation == &WMI_ASSOCIATION_DATA::s_AdminACLToACE) )
{
DoPingAdminACL(a_pktSearch, a_pszWmiPrimaryKey, bstrMetabasePath);
}
}
else if( a_pktSearch == &METABASE_KEYTYPE_DATA::s_TYPE_IPSecurity ) // IPSecurity
{
if( !(m_pAssociation &&
m_pAssociation->pType == &WMI_ASSOCIATION_TYPE_DATA::s_IPSecurity &&
m_pAssociation->pcLeft->pkt != pktCurrent
)
)
{
DoPingIPSecurity(a_pktSearch, a_pszWmiPrimaryKey, bstrMetabasePath);
}
}
// recusive
if(ContinueRecurse(pktCurrent, a_pktSearch))
{
Recurse(
bstrMetabasePath,
pktCurrent,
bstrMetabasePath,
a_pszWmiPrimaryKey,
a_pktSearch);
}
}
}while(hr == ERROR_SUCCESS);
DBGPRINTF((DBG_CONTEXT, "Recurse Exited\n"));
}
// DESC: You are looking for a_eKeyType by traversing thru the tree. You are
// currently at a_eParentKeyType and need to determine if you should keep
// on going.
// COMM: This seems very similar to CMetabase::CheckKey
bool CEnum::ContinueRecurse(
METABASE_KEYTYPE* a_pktParentKeyType,
METABASE_KEYTYPE* a_pktKeyType
)
{
bool bRet = false;
if( a_pktKeyType == &METABASE_KEYTYPE_DATA::s_TYPE_AdminACL ||
a_pktKeyType == &METABASE_KEYTYPE_DATA::s_TYPE_AdminACE ||
a_pktKeyType == &METABASE_KEYTYPE_DATA::s_TYPE_IPSecurity )
{
return true;
}
return g_pDynSch->IsContainedUnder(a_pktParentKeyType, a_pktKeyType);
/*switch(a_pktKeyType)
{
case &METABASE_KEYTYPE_DATA::s_IIsLogModule:
if( a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsLogModules )
bRet = true;
break;
case &METABASE_KEYTYPE_DATA::s_IIsFtpInfo:
if( a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsFtpService )
bRet = true;
break;
case &METABASE_KEYTYPE_DATA::s_IIsFtpServer:
if( a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsFtpService )
bRet = true;
break;
case &METABASE_KEYTYPE_DATA::s_IIsFtpVirtualDir:
if( a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsFtpService ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsFtpServer ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsFtpVirtualDir
)
bRet = true;
break;
case &METABASE_KEYTYPE_DATA::s_IIsWebInfo:
if( a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebService )
bRet = true;
break;
case &METABASE_KEYTYPE_DATA::s_IIsFilters:
if( a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebService ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebServer
)
bRet = true;
break;
case &METABASE_KEYTYPE_DATA::s_IIsFilter:
if( a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebService ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebServer ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsFilters
)
bRet = true;
break;
case &METABASE_KEYTYPE_DATA::s_IIsCompressionSchemes:
if( a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebService ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebServer ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsFilters
)
bRet = true;
break;
case &METABASE_KEYTYPE_DATA::s_IIsCompressionScheme:
if( a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebService ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebServer ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsFilters ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsCompressionSchemes )
bRet = true;
break;
case &METABASE_KEYTYPE_DATA::s_IIsWebServer:
if( a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebService )
bRet = true;
break;
case &METABASE_KEYTYPE_DATA::s_IIsCertMapper:
if( a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebService ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebServer
)
bRet = true;
break;
case &METABASE_KEYTYPE_DATA::s_IIsWebVirtualDir:
if( a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebService ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebServer ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebVirtualDir ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebDirectory
)
bRet = true;
break;
case &METABASE_KEYTYPE_DATA::s_IIsWebDirectory:
if( a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebService ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebServer ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebVirtualDir ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebDirectory
)
bRet = true;
break;
case &METABASE_KEYTYPE_DATA::s_IIsWebFile:
if( a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebService ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebServer ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebVirtualDir ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebDirectory
)
bRet = true;
break;
case TYPE_AdminACL:
case TYPE_AdminACE:
if( a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebService ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebServer ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebVirtualDir ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebDirectory ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsFtpService ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsFtpServer ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsFtpVirtualDir
)
bRet = true;
break;
case TYPE_IPSecurity:
if( a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebService ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebServer ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebVirtualDir ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsWebDirectory ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsFtpService ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsFtpServer ||
a_pktParentKeyType == &METABASE_KEYTYPE_DATA::s_IIsFtpVirtualDir
)
bRet = true;
break;
default:
break;
}*/
//return bRet;
//return true;
}
void CEnum::DoPingAdminACL(
METABASE_KEYTYPE* a_pktKeyType, // Search key
LPCWSTR a_pszKeyName, // Wmi Primary key - nothing to do with MB
LPCWSTR a_pszKeyPath // Current metabase path relative to m_hKey
)
{
// add keyref
_variant_t v(a_pszKeyPath);
THROW_ON_FALSE(m_pParsedObject->AddKeyRef(a_pszKeyName,&v));
if(a_pktKeyType == &METABASE_KEYTYPE_DATA::s_TYPE_AdminACE)
{
EnumACE(a_pszKeyPath);
}
else if(a_pktKeyType == &METABASE_KEYTYPE_DATA::s_TYPE_AdminACL)
{
// ping
if (!m_pAssociation)
PingObject();
else
PingAssociationAdminACL(a_pszKeyPath);
}
// clear keyref
m_pParsedObject->ClearKeys();
}
// for AdminACL
void CEnum::EnumACE(
LPCWSTR pszKeyPath
)
{
HRESULT hr = S_OK;
_variant_t var;
CComPtr<IEnumVARIANT> spEnum;
ULONG lFetch;
CComBSTR bstrTrustee;
IDispatch* pDisp = NULL;
CComPtr<IADsAccessControlEntry> spACE;
_bstr_t bstrMbPath;
WMI_CLASS* pWMIClass;
// get the metabase path of the object
BOOL fClass = FALSE;
if(m_pAssociation)
fClass = CUtils::GetClass(m_pAssociation->pcLeft->pszClassName,&pWMIClass);
else
fClass = CUtils::GetClass(m_pParsedObject->m_pClass,&pWMIClass);
if(!fClass)
return;
CUtils::GetMetabasePath(NULL,m_pParsedObject,pWMIClass,bstrMbPath);
// open ADSI
CAdminACL objACL;
hr = objACL.OpenSD(bstrMbPath);
if(SUCCEEDED(hr))
hr = objACL.GetACEEnum(&spEnum);
if ( FAILED(hr) )
return;
//////////////////////////////////////////////
// Enumerate ACEs
//////////////////////////////////////////////
hr = spEnum->Next( 1, &var, &lFetch );
while( hr == S_OK )
{
if ( lFetch == 1 )
{
if ( VT_DISPATCH != V_VT(&var) )
{
break;
}
pDisp = V_DISPATCH(&var);
/////////////////////////////
// Get the individual ACE
/////////////////////////////
hr = pDisp->QueryInterface(
IID_IADsAccessControlEntry,
(void**)&spACE
);
if ( SUCCEEDED(hr) )
{
hr = spACE->get_Trustee(&bstrTrustee);
if( SUCCEEDED(hr) )
{
// add keyref
_variant_t v(bstrTrustee);
//m_pParsedObject->RemoveKeyRef(L"Trustee");
THROW_ON_FALSE(m_pParsedObject->AddKeyRefEx(L"Trustee",&v));
// ping
if (!m_pAssociation)
PingObject();
else
PingAssociationAdminACL(pszKeyPath);
}
bstrTrustee = (LPWSTR)NULL;
spACE = NULL;
}
}
hr = spEnum->Next( 1, &var, &lFetch );
}
}
void CEnum::PingAssociationAdminACL(
LPCWSTR a_pszLeftKeyPath
)
{
HRESULT hr;
CComPtr<IWbemClassObject> spObj;
CComPtr<IWbemClassObject> spClass;
TSmartPointerArray<WCHAR> swszObjectPath;
CObjectPathParser PathParser(e_ParserAcceptRelativeNamespace);
_bstr_t bstrMbPath;
WMI_CLASS* pWMIClass;
if(m_pAssociation->pType != &WMI_ASSOCIATION_TYPE_DATA::s_AdminACL)
{
return;
}
// get the metabase path of the object
if (CUtils::GetClass(m_pAssociation->pcLeft->pszClassName,&pWMIClass))
{
CUtils::GetMetabasePath(NULL,m_pParsedObject,pWMIClass,bstrMbPath);
}
else
{
return;
}
// check if AdminACL existed
CAdminACL objACL;
hr = objACL.OpenSD(bstrMbPath);
objACL.CloseSD();
if(FAILED(hr))
{
return;
}
hr = m_pNamespace->GetObject(
m_pAssociation->pszAssociationName,
0,
NULL,
&spClass,
NULL
);
THROW_ON_ERROR(hr);
hr = spClass->SpawnInstance(0, &spObj);
THROW_ON_ERROR(hr);
//
// first right side
//
if (!m_pParsedObject->SetClassName(m_pAssociation->pcRight->pszClassName))
{
throw WBEM_E_FAILED;
}
if (PathParser.Unparse(m_pParsedObject,&swszObjectPath))
{
throw WBEM_E_FAILED;
}
SetObjectPath(m_pAssociation->pType->pszRight, swszObjectPath, spObj);
swszObjectPath.Delete();
//
// then left side
//
if(m_pAssociation == &WMI_ASSOCIATION_DATA::s_AdminACLToACE)
{
// clear keyref first
m_pParsedObject->ClearKeys();
// add a keyref
_variant_t vt = a_pszLeftKeyPath;
THROW_ON_FALSE(m_pParsedObject->AddKeyRef(m_pAssociation->pcLeft->pszKeyName,&vt));
}
if (!m_pParsedObject->SetClassName(m_pAssociation->pcLeft->pszClassName))
{
throw WBEM_E_FAILED;
}
if (PathParser.Unparse(m_pParsedObject,&swszObjectPath))
{
throw WBEM_E_FAILED;
}
SetObjectPath(m_pAssociation->pType->pszLeft, swszObjectPath, spObj);
swszObjectPath.Delete();
m_pInstMgr->Indicate(spObj);
}
// for IPSecurity
void CEnum::DoPingIPSecurity(
METABASE_KEYTYPE* a_pktKeyType,
LPCWSTR a_pszKeyName,
LPCWSTR a_pszKeyPath
)
{
// add keyref
_variant_t v(a_pszKeyPath);
THROW_ON_FALSE(m_pParsedObject->AddKeyRef(a_pszKeyName,&v));
// ping
if (!m_pAssociation)
PingObject();
else
PingAssociationIPSecurity(a_pszKeyPath);
// clear keyref
m_pParsedObject->ClearKeys();
}
// for IPSecurity
void CEnum::PingAssociationIPSecurity(
LPCWSTR a_pszLeftKeyPath
)
{
HRESULT hr;
CComPtr<IWbemClassObject> spObj;
CComPtr<IWbemClassObject> spClass;
TSmartPointerArray<WCHAR> swszObjectPath;
CObjectPathParser PathParser(e_ParserAcceptRelativeNamespace);
_bstr_t bstrMbPath;
WMI_CLASS* pWMIClass;
if(m_pAssociation->pType != &WMI_ASSOCIATION_TYPE_DATA::s_IPSecurity)
return;
// get the metabase path of the object
if (CUtils::GetClass(m_pAssociation->pcLeft->pszClassName,&pWMIClass))
{
CUtils::GetMetabasePath(NULL,m_pParsedObject,pWMIClass,bstrMbPath);
}
else
return;
// check if IPSecurity existed
CIPSecurity objIPsec;
hr = objIPsec.OpenSD(bstrMbPath, m_metabase);
objIPsec.CloseSD();
if(FAILED(hr))
return;
hr = m_pNamespace->GetObject(
m_pAssociation->pszAssociationName,
0,
NULL,
&spClass,
NULL
);
THROW_ON_ERROR(hr);
hr = spClass->SpawnInstance(0, &spObj);
THROW_ON_ERROR(hr);
//
// first right side
//
if (!m_pParsedObject->SetClassName(m_pAssociation->pcRight->pszClassName))
throw WBEM_E_FAILED;
if (PathParser.Unparse(m_pParsedObject,&swszObjectPath))
{
throw WBEM_E_FAILED;
}
SetObjectPath(m_pAssociation->pType->pszRight, swszObjectPath, spObj);
swszObjectPath.Delete();
//
// then left side
//
if (!m_pParsedObject->SetClassName(m_pAssociation->pcLeft->pszClassName))
throw WBEM_E_FAILED;
if (PathParser.Unparse(m_pParsedObject,&swszObjectPath))
throw WBEM_E_FAILED;
SetObjectPath(m_pAssociation->pType->pszLeft, swszObjectPath, spObj);
swszObjectPath.Delete();
m_pInstMgr->Indicate(spObj);
}