Leaked source code of windows server 2003
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.
 
 
 
 
 
 

820 lines
22 KiB

//***************************************************************************
//
// ENUM.CPP
//
// Module: WBEM Instance provider
//
// Purpose: Enumerate metabase tree
//
// Copyright (c)1998 Microsoft Corporation, All Rights Reserved
//
//***************************************************************************
#include "iisprov.h"
///////////////////////////////////////
//
// 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);
if(m_pInstMgr)
delete m_pInstMgr;
}
void CEnum::Init(
IWbemObjectSink FAR* a_pHandler,
CWbemServices* a_pNamespace,
ParsedObjectPath* a_pParsedObject,
LPWSTR a_pszKey,
WMI_ASSOCIATION* a_pAssociation
)
{
if (!a_pHandler || !a_pNamespace || !a_pParsedObject)
throw WBEM_E_FAILED;
m_pInstMgr = new CWbemInstanceMgr(a_pHandler);
THROW_ON_FALSE(m_pInstMgr);
m_pNamespace = a_pNamespace;
m_pAssociation = a_pAssociation;
m_pParsedObject = a_pParsedObject;
m_hKey = m_metabase.OpenKey(a_pszKey, false); // read only
}
void CEnum::SetObjectPath(
LPCWSTR a_pszPropertyName,
LPCWSTR a_pszObjectPath,
IWbemClassObject* a_pObj
)
{
_bstr_t t_bstr(a_pszPropertyName);
_variant_t t_v(a_pszObjectPath);
HRESULT t_hr = a_pObj->Put(t_bstr, 0, &t_v, 0);
THROW_ON_ERROR(t_hr);
}
void CEnum::PingObject()
{
IWbemClassObject* t_pObj = NULL;
try
{
CUtils obj;
HRESULT hr = obj.GetObjectAsync(m_pNamespace, &t_pObj, m_pParsedObject, m_metabase);
if(SUCCEEDED(hr) && t_pObj)
{
m_pInstMgr->Indicate(t_pObj);
t_pObj->Release();
}
}
catch(...)
{
}
}
void CEnum::PingAssociation(
LPCWSTR a_pszLeftKeyPath
)
{
HRESULT t_hr;
IWbemClassObject* t_pObj = NULL;
IWbemClassObject* t_pClass = NULL;
LPWSTR t_pszObjectPath = NULL;
CObjectPathParser t_PathParser(e_ParserAcceptRelativeNamespace);
WCHAR t_LeftName[20];
WCHAR t_RightName[20];
if(m_pAssociation->at == at_ElementSetting)
{
lstrcpyW(t_LeftName, L"Element");
lstrcpyW(t_RightName, L"Setting");
}
else if(m_pAssociation->at == at_Component)
{
lstrcpyW(t_LeftName, L"GroupComponent");
lstrcpyW(t_RightName, L"PartComponent");
}
else
return;
try
{
t_hr = m_pNamespace->GetObject(
m_pAssociation->pszAssociationName,
0,
NULL,
&t_pClass,
NULL
);
THROW_ON_ERROR(t_hr);
t_hr = t_pClass->SpawnInstance(0, &t_pObj);
t_pClass->Release();
THROW_ON_ERROR(t_hr);
//
// first right side
//
if (!m_pParsedObject->SetClassName(m_pAssociation->pcRight->pszClassName))
throw WBEM_E_FAILED;
if (t_PathParser.Unparse(m_pParsedObject,&t_pszObjectPath))
throw WBEM_E_FAILED;
SetObjectPath(t_RightName, t_pszObjectPath, t_pObj);
if(t_pszObjectPath)
{
delete [] t_pszObjectPath;
t_pszObjectPath = NULL;
}
//
// then left side
//
if (m_pAssociation->at == at_Component || m_pAssociation->fFlags & ASSOC_EXTRAORDINARY)
{
// clear keyref first
m_pParsedObject->ClearKeys();
// add a keyref
_variant_t t_vt;
if(m_pAssociation->pcLeft->eKeyType == IIsComputer)
t_vt = L"LM"; // IIsComputer.Name = "LM"
else
t_vt = a_pszLeftKeyPath;
THROW_ON_FALSE(m_pParsedObject->AddKeyRef(m_pAssociation->pcLeft->pszKeyName,&t_vt));
}
if (!m_pParsedObject->SetClassName(m_pAssociation->pcLeft->pszClassName))
throw WBEM_E_FAILED;
if (t_PathParser.Unparse(m_pParsedObject,&t_pszObjectPath))
throw WBEM_E_FAILED;
SetObjectPath(t_LeftName, t_pszObjectPath, t_pObj);
if(t_pszObjectPath)
{
delete [] t_pszObjectPath;
t_pszObjectPath = NULL;
}
if(t_pObj)
{
m_pInstMgr->Indicate(t_pObj);
t_pObj->Release();
t_pObj = NULL;
}
}
catch (...)
{
if(t_pszObjectPath)
delete [] t_pszObjectPath;
if(t_pObj)
t_pObj->Release();
}
}
void CEnum::DoPing(
LPCWSTR a_pszKeyName,
LPCWSTR a_pszKeyPath,
LPCWSTR a_pszParentKeyPath
)
{
// add keyref
_variant_t t_v(a_pszKeyPath);
THROW_ON_FALSE(m_pParsedObject->AddKeyRef(a_pszKeyName,&t_v));
// ping
if (!m_pAssociation)
PingObject();
else
PingAssociation(a_pszParentKeyPath);
// clear keyref
m_pParsedObject->ClearKeys();
}
void CEnum::Recurse(
LPCWSTR a_pszMetabasePath,
enum_KEY_TYPE a_eParentKeyType,
LPCWSTR a_pszLeftPath,
LPCWSTR a_pszKeyName,
enum_KEY_TYPE a_eKeyType
)
{
DWORD t_i = 0;
HRESULT t_hr;
WCHAR t_szSubKey[METADATA_MAX_NAME_LEN];
enum_KEY_TYPE t_eSubKeyType;
do
{
t_eSubKeyType = a_eKeyType;
t_hr = m_metabase.EnumKeys(
m_hKey,
a_pszMetabasePath,
t_szSubKey,
&t_i,
t_eSubKeyType
);
t_i++;
if( t_hr == ERROR_SUCCESS)
{
_bstr_t t_bstrMetabasePath;
if(a_pszMetabasePath)
{
t_bstrMetabasePath = a_pszMetabasePath;
t_bstrMetabasePath += L"/";
}
t_bstrMetabasePath += t_szSubKey;
if( t_eSubKeyType == a_eKeyType &&
!( m_pAssociation &&
(m_pAssociation->at == at_Component || m_pAssociation->fFlags & ASSOC_EXTRAORDINARY) &&
m_pAssociation->pcLeft->eKeyType != a_eParentKeyType
)
)
{
DoPing(a_pszKeyName, t_bstrMetabasePath, a_pszLeftPath);
}
else if( a_eKeyType == TYPE_AdminACL || // AdminACL
a_eKeyType == TYPE_AdminACE
)
{
if( !(m_pAssociation &&
m_pAssociation->at == at_AdminACL &&
m_pAssociation->pcLeft->eKeyType != t_eSubKeyType &&
lstrcmpiW(m_pAssociation->pszAssociationName, L"IIs_AdminACL_ACE")
)
)
{
DoPingAdminACL(a_eKeyType, a_pszKeyName, t_bstrMetabasePath);
}
}
else if( a_eKeyType == TYPE_IPSecurity ) // IPSecurity
{
if( !(m_pAssociation &&
m_pAssociation->at == at_IPSecurity &&
m_pAssociation->pcLeft->eKeyType != t_eSubKeyType
)
)
{
DoPingIPSecurity(a_eKeyType, a_pszKeyName, t_bstrMetabasePath);
}
}
// recusive
if(ContinueRecurse(t_eSubKeyType, a_eKeyType))
{
LPCWSTR t_pszLeftPath = a_pszLeftPath;
// if the association is extraordinary (see schema.h for explanation)
if (m_pAssociation && m_pAssociation->fFlags & ASSOC_EXTRAORDINARY)
{
// When the left endpoint of the assoc. is found freeze the
// parent key type and path.
if (a_pszLeftPath != NULL || (a_eParentKeyType == IIsComputer && a_eParentKeyType == m_pAssociation->pcLeft->eKeyType))
{
t_eSubKeyType = a_eParentKeyType;
}
if (t_eSubKeyType == m_pAssociation->pcLeft->eKeyType && a_pszLeftPath == NULL)
{
t_pszLeftPath = t_bstrMetabasePath;
}
}
else
{
// this is the parent path, because the next thing we are doing is
// calling recurse.
t_pszLeftPath = t_bstrMetabasePath;
}
Recurse(t_bstrMetabasePath, t_eSubKeyType, t_pszLeftPath, a_pszKeyName, a_eKeyType);
}
}
}while(t_hr == ERROR_SUCCESS);
}
// 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(
enum_KEY_TYPE a_eParentKeyType,
enum_KEY_TYPE a_eKeyType
)
{
bool bRet = false;
switch(a_eKeyType)
{
case IIsLogModule:
if( a_eParentKeyType == IIsLogModules )
bRet = true;
break;
case IIsFtpInfo:
if( a_eParentKeyType == IIsFtpService )
bRet = true;
break;
case IIsFtpServer:
if( a_eParentKeyType == IIsFtpService )
bRet = true;
break;
case IIsFtpVirtualDir:
if( a_eParentKeyType == IIsFtpService ||
a_eParentKeyType == IIsFtpServer ||
a_eParentKeyType == IIsFtpVirtualDir
)
bRet = true;
break;
case IIsWebInfo:
if( a_eParentKeyType == IIsWebService )
bRet = true;
break;
case IIsFilters:
if( a_eParentKeyType == IIsWebService ||
a_eParentKeyType == IIsWebServer
)
bRet = true;
break;
case IIsFilter:
if( a_eParentKeyType == IIsWebService ||
a_eParentKeyType == IIsWebServer ||
a_eParentKeyType == IIsFilters
)
bRet = true;
break;
case IIsCompressionSchemes:
if( a_eParentKeyType == IIsWebService ||
a_eParentKeyType == IIsWebServer ||
a_eParentKeyType == IIsFilters
)
bRet = true;
break;
case IIsCompressionScheme:
if( a_eParentKeyType == IIsWebService ||
a_eParentKeyType == IIsWebServer ||
a_eParentKeyType == IIsFilters ||
a_eParentKeyType == IIsCompressionSchemes )
bRet = true;
break;
case IIsWebServer:
if( a_eParentKeyType == IIsWebService )
bRet = true;
break;
case IIsCertMapper:
if( a_eParentKeyType == IIsWebService ||
a_eParentKeyType == IIsWebServer
)
bRet = true;
break;
case IIsWebVirtualDir:
if( a_eParentKeyType == IIsWebService ||
a_eParentKeyType == IIsWebServer ||
a_eParentKeyType == IIsWebVirtualDir ||
a_eParentKeyType == IIsWebDirectory
)
bRet = true;
break;
case IIsWebDirectory:
if( a_eParentKeyType == IIsWebService ||
a_eParentKeyType == IIsWebServer ||
a_eParentKeyType == IIsWebVirtualDir ||
a_eParentKeyType == IIsWebDirectory
)
bRet = true;
break;
case IIsWebFile:
if( a_eParentKeyType == IIsWebService ||
a_eParentKeyType == IIsWebServer ||
a_eParentKeyType == IIsWebVirtualDir ||
a_eParentKeyType == IIsWebDirectory
)
bRet = true;
break;
case TYPE_AdminACL:
case TYPE_AdminACE:
if( a_eParentKeyType == IIsWebService ||
a_eParentKeyType == IIsWebServer ||
a_eParentKeyType == IIsWebVirtualDir ||
a_eParentKeyType == IIsWebDirectory ||
a_eParentKeyType == IIsFtpService ||
a_eParentKeyType == IIsFtpServer ||
a_eParentKeyType == IIsFtpVirtualDir
)
bRet = true;
break;
case TYPE_IPSecurity:
if( a_eParentKeyType == IIsWebService ||
a_eParentKeyType == IIsWebServer ||
a_eParentKeyType == IIsWebVirtualDir ||
a_eParentKeyType == IIsWebDirectory ||
a_eParentKeyType == IIsFtpService ||
a_eParentKeyType == IIsFtpServer ||
a_eParentKeyType == IIsFtpVirtualDir
)
bRet = true;
break;
default:
break;
}
return bRet;
}
void CEnum::DoPingAdminACL(
enum_KEY_TYPE a_eKeyType,
LPCWSTR a_pszKeyName,
LPCWSTR a_pszKeyPath
)
{
// add keyref
_variant_t t_v(a_pszKeyPath);
THROW_ON_FALSE(m_pParsedObject->AddKeyRef(a_pszKeyName,&t_v));
if(a_eKeyType == TYPE_AdminACE)
{
EnumACE(a_pszKeyPath);
}
else if(a_eKeyType == 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;
IEnumVARIANT* pEnum = NULL;
ULONG lFetch;
BSTR bstrTrustee;
IDispatch* pDisp = NULL;
IADsAccessControlEntry* pACE = NULL;
_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(&pEnum);
if ( FAILED(hr) )
return;
//////////////////////////////////////////////
// Enumerate ACEs
//////////////////////////////////////////////
hr = pEnum->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**)&pACE
);
if ( SUCCEEDED(hr) )
{
hr = pACE->get_Trustee(&bstrTrustee);
if( SUCCEEDED(hr) )
{
// add keyref
_variant_t t_v(bstrTrustee);
//m_pParsedObject->RemoveKeyRef(L"Trustee");
THROW_ON_FALSE(m_pParsedObject->AddKeyRefEx(L"Trustee",&t_v));
// ping
if (!m_pAssociation)
PingObject();
else
PingAssociationAdminACL(pszKeyPath);
}
SysFreeString(bstrTrustee);
pACE->Release();
}
}
hr = pEnum->Next( 1, &var, &lFetch );
}
pEnum->Release();
}
void CEnum::PingAssociationAdminACL(
LPCWSTR a_pszLeftKeyPath
)
{
HRESULT t_hr;
IWbemClassObject* t_pObj = NULL;
IWbemClassObject* t_pClass = NULL;
LPWSTR t_pszObjectPath = NULL;
CObjectPathParser t_PathParser(e_ParserAcceptRelativeNamespace);
WCHAR t_LeftName[20];
WCHAR t_RightName[20];
_bstr_t bstrMbPath;
WMI_CLASS* pWMIClass;
if(m_pAssociation->at != at_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;
t_hr = objACL.OpenSD(bstrMbPath);
objACL.CloseSD();
if(FAILED(t_hr))
return;
// set the key name
lstrcpyW(t_LeftName, L"GroupComponent");
lstrcpyW(t_RightName, L"PartComponent");
try
{
t_hr = m_pNamespace->GetObject(
m_pAssociation->pszAssociationName,
0,
NULL,
&t_pClass,
NULL
);
THROW_ON_ERROR(t_hr);
t_hr = t_pClass->SpawnInstance(0, &t_pObj);
t_pClass->Release();
THROW_ON_ERROR(t_hr);
//
// first right side
//
if (!m_pParsedObject->SetClassName(m_pAssociation->pcRight->pszClassName))
throw WBEM_E_FAILED;
if (t_PathParser.Unparse(m_pParsedObject,&t_pszObjectPath))
throw WBEM_E_FAILED;
SetObjectPath(t_RightName, t_pszObjectPath, t_pObj);
if(t_pszObjectPath)
{
delete [] t_pszObjectPath;
t_pszObjectPath = NULL;
}
//
// then left side
//
if(!lstrcmpiW(m_pAssociation->pszAssociationName, L"IIs_AdminACL_ACE"))
{
// clear keyref first
m_pParsedObject->ClearKeys();
// add a keyref
_variant_t t_vt = a_pszLeftKeyPath;
THROW_ON_FALSE(m_pParsedObject->AddKeyRef(m_pAssociation->pcLeft->pszKeyName,&t_vt));
}
if (!m_pParsedObject->SetClassName(m_pAssociation->pcLeft->pszClassName))
throw WBEM_E_FAILED;
if (t_PathParser.Unparse(m_pParsedObject,&t_pszObjectPath))
throw WBEM_E_FAILED;
SetObjectPath(t_LeftName, t_pszObjectPath, t_pObj);
if(t_pszObjectPath)
{
delete [] t_pszObjectPath;
t_pszObjectPath = NULL;
}
if(t_pObj)
{
m_pInstMgr->Indicate(t_pObj);
t_pObj->Release();
t_pObj = NULL;
}
}
catch (...)
{
if(t_pszObjectPath)
delete [] t_pszObjectPath;
if(t_pObj)
t_pObj->Release();
}
}
// for IPSecurity
void CEnum::DoPingIPSecurity(
enum_KEY_TYPE a_eKeyType,
LPCWSTR a_pszKeyName,
LPCWSTR a_pszKeyPath
)
{
// add keyref
_variant_t t_v(a_pszKeyPath);
THROW_ON_FALSE(m_pParsedObject->AddKeyRef(a_pszKeyName,&t_v));
// ping
if (!m_pAssociation)
PingObject();
else
PingAssociationIPSecurity(a_pszKeyPath);
// clear keyref
m_pParsedObject->ClearKeys();
}
// for IPSecurity
void CEnum::PingAssociationIPSecurity(
LPCWSTR a_pszLeftKeyPath
)
{
HRESULT t_hr;
IWbemClassObject* t_pObj = NULL;
IWbemClassObject* t_pClass = NULL;
LPWSTR t_pszObjectPath = NULL;
CObjectPathParser t_PathParser(e_ParserAcceptRelativeNamespace);
WCHAR t_LeftName[20];
WCHAR t_RightName[20];
_bstr_t bstrMbPath;
WMI_CLASS* pWMIClass;
if(m_pAssociation->at != at_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;
t_hr = objIPsec.OpenSD(bstrMbPath);
objIPsec.CloseSD();
if(FAILED(t_hr))
return;
// set the key name
lstrcpyW(t_LeftName, L"Element");
lstrcpyW(t_RightName, L"Setting");
try
{
t_hr = m_pNamespace->GetObject(
m_pAssociation->pszAssociationName,
0,
NULL,
&t_pClass,
NULL
);
THROW_ON_ERROR(t_hr);
t_hr = t_pClass->SpawnInstance(0, &t_pObj);
t_pClass->Release();
THROW_ON_ERROR(t_hr);
//
// first right side
//
if (!m_pParsedObject->SetClassName(m_pAssociation->pcRight->pszClassName))
throw WBEM_E_FAILED;
if (t_PathParser.Unparse(m_pParsedObject,&t_pszObjectPath))
throw WBEM_E_FAILED;
SetObjectPath(t_RightName, t_pszObjectPath, t_pObj);
if(t_pszObjectPath)
{
delete [] t_pszObjectPath;
t_pszObjectPath = NULL;
}
//
// then left side
//
if (!m_pParsedObject->SetClassName(m_pAssociation->pcLeft->pszClassName))
throw WBEM_E_FAILED;
if (t_PathParser.Unparse(m_pParsedObject,&t_pszObjectPath))
throw WBEM_E_FAILED;
SetObjectPath(t_LeftName, t_pszObjectPath, t_pObj);
if(t_pszObjectPath)
{
delete [] t_pszObjectPath;
t_pszObjectPath = NULL;
}
if(t_pObj)
{
m_pInstMgr->Indicate(t_pObj);
t_pObj->Release();
t_pObj = NULL;
}
}
catch (...)
{
if(t_pszObjectPath)
delete [] t_pszObjectPath;
if(t_pObj)
t_pObj->Release();
}
}