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.
1790 lines
47 KiB
1790 lines
47 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
schemadynamic.cpp
|
|
|
|
Abstract:
|
|
|
|
This file contains the implementation of the CDynSchema class.
|
|
This class contains the dynamic schema structures.
|
|
It also contains the rules for populating the schema structures.
|
|
|
|
Author:
|
|
|
|
Mohit Srivastava 28-Nov-00
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "iisprov.h"
|
|
|
|
#define USE_DEFAULT_VALUES
|
|
#define USE_DEFAULT_BINARY_VALUES
|
|
|
|
CDynSchema* g_pDynSch = NULL;
|
|
|
|
HRESULT CDynSchema::Initialize()
|
|
/*++
|
|
|
|
Synopsis:
|
|
If fails, object must be destroyed.
|
|
If succeeds, object is ready for use.
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(m_bInitCalled == false);
|
|
DBG_ASSERT(m_bInitSuccessful == false);
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
m_bInitCalled = true;
|
|
|
|
hr = m_hashProps.Wmi_Initialize();
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = m_hashClasses.Wmi_Initialize();
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = m_hashAssociations.Wmi_Initialize();
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = m_hashKeyTypes.Wmi_Initialize();
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = m_poolAssociations.Initialize(10);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = m_poolClasses.Initialize(10);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = m_poolProps.Initialize(10);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = m_poolKeyTypes.Initialize(10);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = m_poolKeyTypeNodes.Initialize(10);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = m_spoolStrings.Initialize();
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = m_apoolPMbp.Initialize();
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = m_apoolBytes.Initialize();
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
m_bInitSuccessful = true;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
void CDynSchema::LogConflicts(LPCWSTR wszSettingsClassName)
|
|
// Logs an error in system events if a schema conflict occurs
|
|
{
|
|
WMI_ASSOCIATION *pWmiAssoc = NULL;
|
|
WMI_CLASS* pWmiSettingsClass = NULL;
|
|
|
|
if (SUCCEEDED(m_hashClasses.Wmi_GetByKey(wszSettingsClassName, &pWmiSettingsClass)) ||
|
|
SUCCEEDED(m_hashAssociations.Wmi_GetByKey(wszSettingsClassName, &pWmiAssoc))) {
|
|
|
|
const WCHAR * EventLogStrings[2];
|
|
const LPCWSTR wszErrorString = L"WMI Schema warning - class already exists";
|
|
|
|
EventLogStrings[0] = wszSettingsClassName;
|
|
EventLogStrings[1] = wszErrorString;
|
|
|
|
EVENT_LOG m_EventLog(L"WMI Schema");
|
|
|
|
m_EventLog.LogEvent(
|
|
TYPE_E_NAMECONFLICT, // message id
|
|
2, // count of strings
|
|
EventLogStrings, // array of strings
|
|
0 // error code
|
|
);
|
|
}
|
|
}
|
|
|
|
HRESULT CDynSchema::RulePopulateFromStatic()
|
|
/*++
|
|
|
|
Synopsis:
|
|
Populates hashtables with pointers to hardcoded schema.
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(m_bInitCalled == true);
|
|
DBG_ASSERT(m_bInitSuccessful == true);
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
//
|
|
// Populate Properties
|
|
//
|
|
if(METABASE_PROPERTY_DATA::s_MetabaseProperties != NULL)
|
|
{
|
|
METABASE_PROPERTY* pStatMbpCurrent;
|
|
for(ULONG i = 0; ; i++)
|
|
{
|
|
pStatMbpCurrent = METABASE_PROPERTY_DATA::s_MetabaseProperties[i];
|
|
if(pStatMbpCurrent == NULL)
|
|
{
|
|
break;
|
|
}
|
|
hr = m_hashProps.Wmi_Insert(pStatMbpCurrent->pszPropName, pStatMbpCurrent);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Populate KeyTypes
|
|
//
|
|
METABASE_KEYTYPE** apMetabaseKeyTypes;
|
|
apMetabaseKeyTypes = METABASE_KEYTYPE_DATA::s_MetabaseKeyTypes;
|
|
for(ULONG i = 0; apMetabaseKeyTypes[i] != NULL; i++)
|
|
{
|
|
if( apMetabaseKeyTypes[i]->m_pszName != NULL )
|
|
{
|
|
apMetabaseKeyTypes[i]->m_pKtListInverseCCL = NULL;
|
|
hr = m_hashKeyTypes.Wmi_Insert(apMetabaseKeyTypes[i]->m_pszName,
|
|
apMetabaseKeyTypes[i]);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDynSchema::Rule2PopulateFromStatic()
|
|
/*++
|
|
|
|
Synopsis:
|
|
Populates hashtables with pointers to hardcoded schema.
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(m_bInitCalled == true);
|
|
DBG_ASSERT(m_bInitSuccessful == true);
|
|
|
|
HRESULT hr = S_OK;
|
|
int i;
|
|
|
|
//
|
|
// Populate Classes
|
|
//
|
|
WMI_CLASS* pStatWmiClassCurrent;
|
|
for(i = 0; ; i++)
|
|
{
|
|
pStatWmiClassCurrent = WMI_CLASS_DATA::s_WmiClasses[i];
|
|
if(pStatWmiClassCurrent == NULL)
|
|
{
|
|
break;
|
|
}
|
|
hr = m_hashClasses.Wmi_Insert(
|
|
pStatWmiClassCurrent->pszClassName,
|
|
pStatWmiClassCurrent);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Populate Associations
|
|
//
|
|
WMI_ASSOCIATION* pStatWmiAssocCurrent;
|
|
for(i = 0; ; i++)
|
|
{
|
|
pStatWmiAssocCurrent = WMI_ASSOCIATION_DATA::s_WmiAssociations[i];
|
|
if(pStatWmiAssocCurrent == NULL)
|
|
{
|
|
break;
|
|
}
|
|
hr = m_hashAssociations.Wmi_Insert(
|
|
pStatWmiAssocCurrent->pszAssociationName,
|
|
pStatWmiAssocCurrent);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDynSchema::RuleKeyType(
|
|
const CTableMeta *i_pTableMeta)
|
|
/*++
|
|
|
|
Synopsis:
|
|
If not already in hashtable of keytypes, a keytype structure
|
|
is allocated thru the keytype pool. Then, a pointer to it is inserted
|
|
in hashtable.
|
|
|
|
Arguments: [i_pTableMeta] -
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(m_bInitCalled == true);
|
|
DBG_ASSERT(m_bInitSuccessful == true);
|
|
DBG_ASSERT(i_pTableMeta != NULL);
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
HRESULT hrTemp = WBEM_S_NO_ERROR;
|
|
METABASE_KEYTYPE* pktNew;
|
|
LPWSTR wszNew;
|
|
|
|
hrTemp = m_hashKeyTypes.Wmi_GetByKey(
|
|
i_pTableMeta->TableMeta.pInternalName,
|
|
&pktNew);
|
|
if(FAILED(hrTemp))
|
|
{
|
|
hr = m_spoolStrings.GetNewString(i_pTableMeta->TableMeta.pInternalName, &wszNew);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
hr = m_poolKeyTypes.GetNewElement(&pktNew);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
pktNew->m_pszName = wszNew;
|
|
pktNew->m_pKtListInverseCCL = NULL;
|
|
m_hashKeyTypes.Wmi_Insert(wszNew, pktNew);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDynSchema::RuleWmiClassDescription(
|
|
const CTableMeta* i_pTableMeta,
|
|
WMI_CLASS* i_pElementClass,
|
|
WMI_CLASS* i_pSettingClass) const
|
|
/*++
|
|
|
|
Synopsis:
|
|
Sets WMI_CLASS::pDescription if needed.
|
|
This pointer will be invalid after initialization since it points to
|
|
catalog.
|
|
|
|
Arguments: [i_pTableMeta] -
|
|
[i_pElementClass] -
|
|
[i_pSettingClass] -
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(m_bInitCalled == true);
|
|
DBG_ASSERT(m_bInitSuccessful == true);
|
|
DBG_ASSERT(i_pTableMeta != NULL);
|
|
DBG_ASSERT(i_pElementClass != NULL);
|
|
DBG_ASSERT(i_pSettingClass != NULL);
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
if(i_pTableMeta->TableMeta.pDescription != NULL)
|
|
{
|
|
i_pElementClass->pszDescription = i_pTableMeta->TableMeta.pDescription;
|
|
i_pSettingClass->pszDescription = i_pTableMeta->TableMeta.pDescription;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDynSchema::RuleWmiClass(
|
|
const CTableMeta* i_pTableMeta,
|
|
WMI_CLASS** o_ppElementClass,
|
|
WMI_CLASS** o_ppSettingClass,
|
|
DWORD io_adwIgnoredProps[],
|
|
BOOL i_bUserDefined)
|
|
/*++
|
|
|
|
Synopsis:
|
|
Creates an Element and Setting class based on
|
|
i_pTableMeta->TableMeta.pInternalName. If not in hashtable of classes,
|
|
these classes are inserted.
|
|
|
|
At bottom,
|
|
RuleProperties is called to set up list of properties for each class.
|
|
|
|
Arguments: [i_pTableMeta] -
|
|
[o_ppElementClass] - can be NULL
|
|
[o_ppSettingClass] - can be NULL
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(m_bInitCalled == true);
|
|
DBG_ASSERT(m_bInitSuccessful == true);
|
|
DBG_ASSERT(i_pTableMeta != NULL);
|
|
|
|
WMI_CLASS* pWmiClass = NULL;
|
|
WMI_CLASS* pWmiSettingsClass = NULL;
|
|
LPWSTR wszClassName, wszSettingsClassName;
|
|
LPWSTR wszParentClassName, wszParentSettingsClassName;
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
HRESULT hrTemp = WBEM_S_NO_ERROR;
|
|
|
|
ULONG cPropsAndTagsRW = 0;
|
|
ULONG cPropsAndTagsRO = 0;
|
|
|
|
ULONG iShipped = 0;
|
|
|
|
CColumnMeta* pColumnMeta;
|
|
ULONG cchTable;
|
|
|
|
//
|
|
// Ignore table if it has no name
|
|
//
|
|
if(i_pTableMeta->TableMeta.pInternalName == NULL)
|
|
{
|
|
hr = WBEM_S_NO_ERROR;
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Determine iShipped and Parent Classes
|
|
//
|
|
if(fTABLEMETA_USERDEFINED & *i_pTableMeta->TableMeta.pSchemaGeneratorFlags)
|
|
{
|
|
iShipped = USER_DEFINED_TO_REPOSITORY;
|
|
DBG_ASSERT(iShipped != USER_DEFINED_NOT_TO_REPOSITORY);
|
|
wszParentClassName = g_wszExtElementParent;
|
|
wszParentSettingsClassName = g_wszExtSettingParent;
|
|
}
|
|
else
|
|
{
|
|
if(fTABLEMETA_EXTENDED & *i_pTableMeta->TableMeta.pSchemaGeneratorFlags)
|
|
{
|
|
iShipped = EXTENDED;
|
|
}
|
|
else
|
|
{
|
|
iShipped = SHIPPED_TO_MOF;
|
|
}
|
|
wszParentClassName = g_wszElementParent;
|
|
wszParentSettingsClassName = g_wszSettingParent;
|
|
}
|
|
|
|
//
|
|
// Determine number of RO and RW properties
|
|
//
|
|
for(ULONG idxProps = 0; idxProps < i_pTableMeta->ColCount(); idxProps++)
|
|
{
|
|
pColumnMeta = i_pTableMeta->paColumns[idxProps];
|
|
if(*pColumnMeta->ColumnMeta.pSchemaGeneratorFlags &
|
|
fCOLUMNMETA_CACHE_PROPERTY_MODIFIED)
|
|
{
|
|
cPropsAndTagsRW += pColumnMeta->cNrTags + 1;
|
|
}
|
|
else
|
|
{
|
|
cPropsAndTagsRO += pColumnMeta->cNrTags + 1;
|
|
}
|
|
}
|
|
|
|
cchTable = wcslen(i_pTableMeta->TableMeta.pInternalName);
|
|
|
|
//
|
|
// The keytype should already exist.
|
|
//
|
|
METABASE_KEYTYPE* pktTemp;
|
|
hrTemp = m_hashKeyTypes.Wmi_GetByKey(i_pTableMeta->TableMeta.pInternalName, &pktTemp);
|
|
if( FAILED(hrTemp) )
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// The Element class (named PrefixC)
|
|
//
|
|
hr = m_spoolStrings.GetNewArray(g_cchIIs_+cchTable+1, &wszClassName);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
memcpy(wszClassName, g_wszIIs_, sizeof(WCHAR)*g_cchIIs_);
|
|
memcpy(&wszClassName[g_cchIIs_],
|
|
i_pTableMeta->TableMeta.pInternalName,
|
|
sizeof(WCHAR)*(cchTable+1));
|
|
|
|
if (i_bUserDefined) {
|
|
LogConflicts(wszClassName);
|
|
}
|
|
|
|
if(FAILED(m_hashClasses.Wmi_GetByKey(wszClassName, &pWmiClass)))
|
|
{
|
|
hr = m_poolClasses.GetNewElement(&pWmiClass);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
pWmiClass->pkt = pktTemp;
|
|
pWmiClass->pszClassName = wszClassName;
|
|
pWmiClass->pszMetabaseKey = L"/LM";
|
|
pWmiClass->pszKeyName = L"Name";
|
|
pWmiClass->ppMethod = NULL;
|
|
pWmiClass->pszParentClass = wszParentClassName;
|
|
pWmiClass->bCreateAllowed = true;
|
|
pWmiClass->pszDescription = NULL;
|
|
|
|
hr = m_hashClasses.Wmi_Insert(wszClassName, pWmiClass);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
pWmiClass->ppmbp = NULL;
|
|
pWmiClass->dwExtended = iShipped;
|
|
|
|
//
|
|
// The Settings class (named PrefixCSetting)
|
|
//
|
|
hr = m_spoolStrings.GetNewArray(g_cchIIs_+cchTable+g_cchSettings+1, &wszSettingsClassName);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
memcpy(wszSettingsClassName, g_wszIIs_, sizeof(WCHAR)*g_cchIIs_);
|
|
memcpy(&wszSettingsClassName[g_cchIIs_],
|
|
i_pTableMeta->TableMeta.pInternalName,
|
|
sizeof(WCHAR)*cchTable);
|
|
memcpy(&wszSettingsClassName[g_cchIIs_+cchTable],
|
|
g_wszSettings,
|
|
sizeof(WCHAR)*(g_cchSettings+1));
|
|
|
|
if (i_bUserDefined) {
|
|
LogConflicts(wszSettingsClassName);
|
|
}
|
|
|
|
if(FAILED(m_hashClasses.Wmi_GetByKey(wszSettingsClassName, &pWmiSettingsClass)))
|
|
{
|
|
hr = m_poolClasses.GetNewElement(&pWmiSettingsClass);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
pWmiSettingsClass->pkt = pktTemp;
|
|
pWmiSettingsClass->pszClassName = wszSettingsClassName;
|
|
pWmiSettingsClass->pszMetabaseKey = L"/LM";
|
|
pWmiSettingsClass->pszKeyName = L"Name";
|
|
pWmiSettingsClass->ppMethod = NULL;
|
|
pWmiSettingsClass->pszParentClass = wszParentSettingsClassName;
|
|
pWmiSettingsClass->bCreateAllowed = true;
|
|
pWmiSettingsClass->pszDescription = NULL;
|
|
|
|
hr = m_hashClasses.Wmi_Insert(wszSettingsClassName, pWmiSettingsClass);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
pWmiSettingsClass->ppmbp = NULL;
|
|
pWmiSettingsClass->dwExtended = iShipped;
|
|
|
|
//
|
|
// Fill in the ppmbp field
|
|
//
|
|
hr = RuleProperties(
|
|
i_pTableMeta,
|
|
cPropsAndTagsRO,
|
|
pWmiClass,
|
|
cPropsAndTagsRW,
|
|
pWmiSettingsClass,
|
|
io_adwIgnoredProps);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(o_ppElementClass != NULL)
|
|
{
|
|
*o_ppElementClass = pWmiClass;
|
|
}
|
|
if(o_ppSettingClass != NULL)
|
|
{
|
|
*o_ppSettingClass = pWmiSettingsClass;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDynSchema::RuleProperties(
|
|
const CTableMeta* i_pTableMeta,
|
|
ULONG i_cPropsAndTagsRO,
|
|
WMI_CLASS* io_pWmiClass,
|
|
ULONG i_cPropsAndTagsRW,
|
|
WMI_CLASS* io_pWmiSettingsClass,
|
|
DWORD io_adwIgnoredProps[])
|
|
/*++
|
|
|
|
Synopsis:
|
|
Given i_pTableMeta, puts the properties either under the Element class
|
|
or under the Setting class.
|
|
|
|
Arguments: [i_pTableMeta] -
|
|
[i_cPropsAndTagsRO] -
|
|
[o_papMbp] -
|
|
[i_cPropsAndTagsRW] -
|
|
[o_papMbpSettings] -
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(m_bInitCalled == true);
|
|
DBG_ASSERT(m_bInitSuccessful == true);
|
|
DBG_ASSERT(i_pTableMeta != NULL);
|
|
DBG_ASSERT(io_pWmiClass != NULL);
|
|
DBG_ASSERT(io_pWmiSettingsClass != NULL);
|
|
// DBG_ASSERT(sizeof(io_awszIgnoredProps) >= sizeof(g_awszPropIgnoreList));
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
CColumnMeta* pColumnMeta = NULL;
|
|
METABASE_PROPERTY* pMbp;
|
|
ULONG idxProps = 0;
|
|
ULONG idxTags = 0;
|
|
|
|
ULONG idxPropsAndTagsRO = 0;
|
|
ULONG idxPropsAndTagsRW = 0;
|
|
|
|
METABASE_PROPERTY*** papMbp = &io_pWmiClass->ppmbp;
|
|
METABASE_PROPERTY*** papMbpSettings = &io_pWmiSettingsClass->ppmbp;
|
|
|
|
//
|
|
// Allocate enough memory for the RO properties
|
|
//
|
|
if(i_cPropsAndTagsRO > 0)
|
|
{
|
|
hr = m_apoolPMbp.GetNewArray(i_cPropsAndTagsRO+1, papMbp);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
memset(*papMbp, 0, (1+i_cPropsAndTagsRO)*sizeof(METABASE_PROPERTY*));
|
|
}
|
|
|
|
//
|
|
// Allocate enough memory for the RW properties
|
|
//
|
|
if(i_cPropsAndTagsRW > 0)
|
|
{
|
|
hr = m_apoolPMbp.GetNewArray(i_cPropsAndTagsRW+1, papMbpSettings);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
memset(*papMbpSettings, 0, (1+i_cPropsAndTagsRW)*sizeof(METABASE_PROPERTY*));
|
|
}
|
|
|
|
//
|
|
// Walk thru all the properties
|
|
//
|
|
for (idxProps=0, idxPropsAndTagsRO = 0, idxPropsAndTagsRW = 0;
|
|
idxProps < i_pTableMeta->ColCount();
|
|
++idxProps)
|
|
{
|
|
pColumnMeta = i_pTableMeta->paColumns[idxProps];
|
|
|
|
//
|
|
// Ignore property if its in g_adwPropIgnoreList and store the prop in
|
|
// io_adwIgnoredProps
|
|
//
|
|
if( (*pColumnMeta->ColumnMeta.pSchemaGeneratorFlags & fCOLUMNMETA_HIDDEN) ||
|
|
IgnoreProperty(io_pWmiClass->pkt, *(pColumnMeta->ColumnMeta.pID), io_adwIgnoredProps) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Call RulePropertiesHelper if Property is not already in the
|
|
// properties hashtable
|
|
//
|
|
if(FAILED(m_hashProps.Wmi_GetByKey(pColumnMeta->ColumnMeta.pInternalName, &pMbp)))
|
|
{
|
|
hr = RulePropertiesHelper(pColumnMeta, &pMbp, NULL);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If RW, put pointer to property in Setting class, else in Element
|
|
// class.
|
|
//
|
|
if(*pColumnMeta->ColumnMeta.pSchemaGeneratorFlags &
|
|
fCOLUMNMETA_CACHE_PROPERTY_MODIFIED)
|
|
{
|
|
(*papMbpSettings)[idxPropsAndTagsRW] = pMbp;
|
|
idxPropsAndTagsRW++;
|
|
}
|
|
else
|
|
{
|
|
(*papMbp)[idxPropsAndTagsRO] = pMbp;
|
|
idxPropsAndTagsRO++;
|
|
}
|
|
|
|
//
|
|
// Same steps as above, except for the tags.
|
|
//
|
|
for(idxTags=0; idxTags < pColumnMeta->cNrTags; idxTags++)
|
|
{
|
|
if(FAILED(m_hashProps.Wmi_GetByKey(pColumnMeta->paTags[idxTags]->pInternalName, &pMbp)))
|
|
{
|
|
hr = RulePropertiesHelper(pColumnMeta, &pMbp, &idxTags);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
if(*pColumnMeta->ColumnMeta.pSchemaGeneratorFlags &
|
|
fCOLUMNMETA_CACHE_PROPERTY_MODIFIED)
|
|
{
|
|
(*papMbpSettings)[idxPropsAndTagsRW] = pMbp;
|
|
idxPropsAndTagsRW++;
|
|
}
|
|
else
|
|
{
|
|
(*papMbp)[idxPropsAndTagsRO] = pMbp;
|
|
idxPropsAndTagsRO++;
|
|
}
|
|
}
|
|
}
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDynSchema::RulePropertiesHelper(
|
|
const CColumnMeta* i_pColumnMeta,
|
|
METABASE_PROPERTY** o_ppMbp,
|
|
ULONG* i_idxTag)
|
|
/*++
|
|
|
|
Synopsis:
|
|
This class creates a property and inserts it into the hashtable of props.
|
|
PRECONDITION: The property does not exist in the hashtable yet.
|
|
i_idxTag is null if you want to insert the property. else you want to
|
|
insert a tag, and *i_idxTag is the index of the tag
|
|
|
|
Arguments: [i_pColumnMeta] -
|
|
[o_ppMbp] -
|
|
[i_idxTag] -
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(m_bInitCalled == true);
|
|
DBG_ASSERT(m_bInitSuccessful == true);
|
|
DBG_ASSERT(i_pColumnMeta != NULL);
|
|
DBG_ASSERT(o_ppMbp != NULL);
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
METABASE_PROPERTY* pMbp = NULL;
|
|
|
|
hr = m_poolProps.GetNewElement(&pMbp);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
if(i_idxTag == NULL)
|
|
{
|
|
pMbp->dwMDMask = 0;
|
|
hr = m_spoolStrings.GetNewString(
|
|
i_pColumnMeta->ColumnMeta.pInternalName,
|
|
&(pMbp->pszPropName));
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pMbp->dwMDMask = *(i_pColumnMeta->paTags[*i_idxTag]->pValue);
|
|
hr = m_spoolStrings.GetNewString(
|
|
i_pColumnMeta->paTags[*i_idxTag]->pInternalName,
|
|
&(pMbp->pszPropName));
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
pMbp->dwMDIdentifier = *(i_pColumnMeta->ColumnMeta.pID);
|
|
pMbp->dwMDUserType = *(i_pColumnMeta->ColumnMeta.pUserType);
|
|
|
|
switch(*(i_pColumnMeta->ColumnMeta.pType))
|
|
{
|
|
case eCOLUMNMETA_int32:
|
|
if(fCOLUMNMETA_BOOL & *(i_pColumnMeta->ColumnMeta.pMetaFlags))
|
|
{
|
|
if(pMbp->dwMDMask == 0)
|
|
{
|
|
pMbp->dwMDMask = ALL_BITS_ON;
|
|
}
|
|
}
|
|
pMbp->dwMDDataType = DWORD_METADATA;
|
|
pMbp->pDefaultValue = NULL;
|
|
#ifdef USE_DEFAULT_VALUES
|
|
if(i_pColumnMeta->ColumnMeta.pDefaultValue != NULL)
|
|
{
|
|
pMbp->dwDefaultValue = *((DWORD*)(i_pColumnMeta->ColumnMeta.pDefaultValue));
|
|
pMbp->pDefaultValue = &pMbp->dwDefaultValue;
|
|
}
|
|
#endif
|
|
break;
|
|
case eCOLUMNMETA_String:
|
|
if(fCOLUMNMETA_MULTISTRING & *(i_pColumnMeta->ColumnMeta.pMetaFlags))
|
|
{
|
|
pMbp->dwMDDataType = MULTISZ_METADATA;
|
|
}
|
|
else if(fCOLUMNMETA_EXPANDSTRING & *(i_pColumnMeta->ColumnMeta.pMetaFlags))
|
|
{
|
|
pMbp->dwMDDataType = EXPANDSZ_METADATA;
|
|
}
|
|
else
|
|
{
|
|
pMbp->dwMDDataType = STRING_METADATA;
|
|
}
|
|
//
|
|
// Default values.
|
|
//
|
|
pMbp->pDefaultValue = NULL;
|
|
#ifdef USE_DEFAULT_VALUES
|
|
if(i_pColumnMeta->ColumnMeta.pDefaultValue != NULL)
|
|
{
|
|
if(pMbp->dwMDDataType != MULTISZ_METADATA)
|
|
{
|
|
hr = m_spoolStrings.GetNewString(
|
|
(LPWSTR)i_pColumnMeta->ColumnMeta.pDefaultValue,
|
|
(LPWSTR*)&pMbp->pDefaultValue);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bool bLastCharNull = false;
|
|
ULONG idx = 0;
|
|
ULONG iLen = 0;
|
|
LPWSTR msz = (LPWSTR)i_pColumnMeta->ColumnMeta.pDefaultValue;
|
|
|
|
do
|
|
{
|
|
bLastCharNull = msz[idx] == L'\0' ? true : false;
|
|
}
|
|
while( !(msz[++idx] == L'\0' && bLastCharNull) );
|
|
iLen = idx+1;
|
|
|
|
hr = m_spoolStrings.GetNewArray(
|
|
iLen,
|
|
(LPWSTR*)&pMbp->pDefaultValue);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
memcpy(
|
|
pMbp->pDefaultValue,
|
|
i_pColumnMeta->ColumnMeta.pDefaultValue,
|
|
sizeof(WCHAR)*iLen);
|
|
}
|
|
}
|
|
#endif
|
|
break;
|
|
case eCOLUMNMETA_BYTES:
|
|
pMbp->dwMDDataType = BINARY_METADATA;
|
|
pMbp->pDefaultValue = NULL;
|
|
#ifdef USE_DEFAULT_VALUES
|
|
#ifdef USE_DEFAULT_BINARY_VALUES
|
|
if( i_pColumnMeta->ColumnMeta.pDefaultValue != NULL )
|
|
{
|
|
hr = m_apoolBytes.GetNewArray(
|
|
i_pColumnMeta->cbDefaultValue,
|
|
(BYTE**)&pMbp->pDefaultValue);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
memcpy(
|
|
pMbp->pDefaultValue,
|
|
i_pColumnMeta->ColumnMeta.pDefaultValue,
|
|
i_pColumnMeta->cbDefaultValue);
|
|
//
|
|
// Use dwDefaultValue to store the length.
|
|
//
|
|
pMbp->dwDefaultValue = i_pColumnMeta->cbDefaultValue;
|
|
}
|
|
#endif
|
|
#endif
|
|
break;
|
|
default:
|
|
pMbp->dwMDDataType = -1;
|
|
pMbp->pDefaultValue = NULL;
|
|
break;
|
|
}
|
|
pMbp->dwMDAttributes = *(i_pColumnMeta->ColumnMeta.pAttributes);
|
|
if(*i_pColumnMeta->ColumnMeta.pSchemaGeneratorFlags &
|
|
fCOLUMNMETA_CACHE_PROPERTY_MODIFIED)
|
|
{
|
|
pMbp->fReadOnly = FALSE;
|
|
}
|
|
else
|
|
{
|
|
pMbp->fReadOnly = TRUE;
|
|
}
|
|
|
|
hr = m_hashProps.Wmi_Insert(pMbp->pszPropName, pMbp);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
*o_ppMbp = pMbp;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
bool CDynSchema::IgnoreProperty(
|
|
METABASE_KEYTYPE* io_pkt,
|
|
DWORD i_dwPropId,
|
|
DWORD io_adwIgnored[])
|
|
/*++
|
|
|
|
Synopsis:
|
|
Checks to see if i_wszProp is in g_adwPropIgnoreList.
|
|
If it is, sets next free element in io_adwIgnored to point to this.
|
|
|
|
Arguments: [i_wszProp] -
|
|
[io_adwIgnored] - Must be as big as g_adwPropIgnoreList.
|
|
Allocated AND must be memset to 0 by caller.
|
|
|
|
Return Value:
|
|
true if property is in the ignore list.
|
|
false otherwise.
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(io_pkt);
|
|
|
|
if(g_adwPropIgnoreList == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if( io_pkt == &METABASE_KEYTYPE_DATA::s_IIsObject &&
|
|
i_dwPropId == MD_KEY_TYPE )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
for(ULONG i = 0; i < g_cElemPropIgnoreList; i++)
|
|
{
|
|
if(i_dwPropId == g_adwPropIgnoreList[i])
|
|
{
|
|
for(ULONG j = 0; j < g_cElemPropIgnoreList; j++)
|
|
{
|
|
if(io_adwIgnored[j] == NULL)
|
|
{
|
|
io_adwIgnored[j] = g_adwPropIgnoreList[i];
|
|
break;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
#if 0
|
|
bool CDynSchema::IgnoreProperty(LPCWSTR i_wszProp)
|
|
/*++
|
|
|
|
Synopsis:
|
|
Checks to see if i_wszProp is in g_adwPropIgnoreList
|
|
|
|
Arguments: [i_wszProp] -
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(i_wszProp != NULL);
|
|
|
|
if(g_adwPropIgnoreList == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
for(ULONG i = 0; i < g_cElemPropIgnoreList; i++)
|
|
{
|
|
if(_wcsicmp(i_wszProp, g_adwPropIgnoreList[i]) == 0)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
|
|
HRESULT CDynSchema::RuleGenericAssociations(
|
|
WMI_CLASS* i_pcElement,
|
|
WMI_CLASS* i_pcSetting,
|
|
WMI_ASSOCIATION_TYPE* i_pAssocType,
|
|
ULONG i_iShipped)
|
|
/*++
|
|
|
|
Synopsis:
|
|
Create the Element/Setting association.
|
|
|
|
Arguments: [i_pcElement] -
|
|
[i_pcSetting] -
|
|
[i_iShipped] -
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(m_bInitCalled == true);
|
|
DBG_ASSERT(m_bInitSuccessful == true);
|
|
DBG_ASSERT(i_pcElement != NULL);
|
|
DBG_ASSERT(i_pcSetting != NULL);
|
|
DBG_ASSERT(i_pAssocType != NULL);
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
LPWSTR wszElement = i_pcElement->pszClassName;
|
|
LPWSTR wszSetting = i_pcSetting->pszClassName;
|
|
LPWSTR wszParent = NULL;
|
|
LPWSTR wszAssocName;
|
|
WMI_ASSOCIATION* pWmiAssoc;
|
|
|
|
ULONG cchElement = wcslen(wszElement);
|
|
ULONG cchSetting = wcslen(wszSetting);
|
|
|
|
hr = m_spoolStrings.GetNewArray(cchElement+cchSetting+2+1, &wszAssocName);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
wcscpy(wszAssocName, wszElement);
|
|
wcscat(wszAssocName, L"_");
|
|
wcscat(wszAssocName, wszSetting);
|
|
|
|
hr = m_poolAssociations.GetNewElement(&pWmiAssoc);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
if(i_iShipped == USER_DEFINED_TO_REPOSITORY ||
|
|
i_iShipped == USER_DEFINED_NOT_TO_REPOSITORY)
|
|
{
|
|
wszParent = i_pAssocType->pszExtParent;
|
|
}
|
|
else
|
|
{
|
|
wszParent = i_pAssocType->pszParent;
|
|
}
|
|
|
|
pWmiAssoc->pszAssociationName = wszAssocName;
|
|
pWmiAssoc->pcLeft = i_pcElement;
|
|
pWmiAssoc->pcRight = i_pcSetting;
|
|
pWmiAssoc->pType = i_pAssocType;
|
|
pWmiAssoc->fFlags = 0;
|
|
pWmiAssoc->pszParentClass = wszParent;
|
|
pWmiAssoc->dwExtended = i_iShipped;
|
|
|
|
hr = m_hashAssociations.Wmi_Insert(wszAssocName, pWmiAssoc);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
void CDynSchema::RuleWmiClassServices(
|
|
WMI_CLASS* i_pElement,
|
|
WMI_CLASS* i_pSetting)
|
|
/*++
|
|
|
|
Synopsis:
|
|
Sets the bCreateAllowed fields to false if necessary.
|
|
i_pSetting must be the corresponding Setting class to i_pElement.
|
|
|
|
Also sets i_pElement->pszParentClass
|
|
|
|
Arguments: [i_pElement] -
|
|
[i_pSetting] -
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(i_pElement != NULL);
|
|
DBG_ASSERT(i_pSetting != NULL);
|
|
DBG_ASSERT(m_bInitSuccessful == true);
|
|
|
|
//
|
|
// Element Class Suffixes for which Create will be disallowed
|
|
//
|
|
static LPCWSTR const wszService = L"Service";
|
|
static const ULONG cchService = wcslen(wszService);
|
|
|
|
//
|
|
// We only care about shipped classes
|
|
//
|
|
if( i_pElement->dwExtended != SHIPPED_TO_MOF &&
|
|
i_pElement->dwExtended != SHIPPED_NOT_TO_MOF )
|
|
{
|
|
return;
|
|
}
|
|
|
|
ULONG cchElement = wcslen(i_pElement->pszClassName);
|
|
|
|
if( cchElement >= cchService &&
|
|
_wcsicmp(wszService, &i_pElement->pszClassName[cchElement-cchService]) == 0 )
|
|
{
|
|
i_pElement->bCreateAllowed = false;
|
|
i_pElement->pszParentClass = L"Win32_Service";
|
|
i_pSetting->bCreateAllowed = false;
|
|
}
|
|
}
|
|
|
|
HRESULT CDynSchema::RuleWmiClassInverseCCL(
|
|
const METABASE_KEYTYPE* pktGroup,
|
|
METABASE_KEYTYPE* pktPart)
|
|
/*++
|
|
|
|
Synopsis:
|
|
Adds pktGroup to pktPart's inverse container class list
|
|
|
|
Arguments: [pktGroup] -
|
|
[pktPart] -
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(m_bInitCalled == true);
|
|
DBG_ASSERT(m_bInitSuccessful == true);
|
|
DBG_ASSERT(pktGroup != NULL);
|
|
DBG_ASSERT(pktPart != NULL);
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
METABASE_KEYTYPE_NODE* pktnode = NULL;
|
|
|
|
hr = m_poolKeyTypeNodes.GetNewElement(&pktnode);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
pktnode->m_pKt = pktGroup;
|
|
pktnode->m_pKtNext = pktPart->m_pKtListInverseCCL;
|
|
|
|
pktPart->m_pKtListInverseCCL = pktnode;
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDynSchema::RuleGroupPartAssociations(
|
|
const CTableMeta *i_pTableMeta)
|
|
/*++
|
|
|
|
Synopsis:
|
|
Walks thru container class list to create Group/Part associations.
|
|
Also calls RuleWmiClassInverseCCL for each contained class to create inverse
|
|
container class list.
|
|
|
|
Arguments: [i_pTableMeta] -
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(m_bInitCalled == true);
|
|
DBG_ASSERT(m_bInitSuccessful == true);
|
|
DBG_ASSERT(i_pTableMeta != NULL);
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
WMI_ASSOCIATION *pWmiAssoc;
|
|
WMI_CLASS *pWmiClassLeft;
|
|
WMI_CLASS *pWmiClassRight;
|
|
|
|
LPWSTR wszCCL = NULL; // Needs to be cleaned up
|
|
LPWSTR wszGroupClass = NULL; // Ptr to catalog
|
|
LPWSTR wszPartClass = NULL; // Ptr to catalog
|
|
LPWSTR wszAssocName = NULL; // Ptr to pool
|
|
LPWSTR wszTemp = NULL; // Needs to be cleaned up
|
|
|
|
static LPCWSTR wszSeps = L", ";
|
|
|
|
ULONG cchGroupClass = 0;
|
|
ULONG cchPartClass = 0;
|
|
ULONG cchCCL = 0;
|
|
|
|
wszGroupClass = i_pTableMeta->TableMeta.pInternalName;
|
|
cchGroupClass = wcslen(wszGroupClass);
|
|
hr = m_hashClasses.Wmi_GetByKey(wszGroupClass, &pWmiClassLeft);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
if(i_pTableMeta->TableMeta.pContainerClassList &&
|
|
i_pTableMeta->TableMeta.pContainerClassList[0] != L'\0')
|
|
{
|
|
//
|
|
// Make copy of CCL so we can wcstok
|
|
//
|
|
cchCCL = wcslen(i_pTableMeta->TableMeta.pContainerClassList);
|
|
wszCCL = new WCHAR[cchCCL+1];
|
|
if(wszCCL == NULL)
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
goto exit;
|
|
}
|
|
memcpy(wszCCL, i_pTableMeta->TableMeta.pContainerClassList, sizeof(WCHAR)*(cchCCL+1));
|
|
|
|
//
|
|
// we will use wszTemp to construct assoc name (GroupClass_PartClass)
|
|
//
|
|
wszTemp = new WCHAR[cchGroupClass+1+cchCCL+1];
|
|
if(wszTemp == NULL)
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
for(wszPartClass = wcstok(wszCCL, wszSeps);
|
|
wszPartClass != NULL;
|
|
wszPartClass = wcstok(NULL, wszSeps))
|
|
{
|
|
hr = m_hashClasses.Wmi_GetByKey(wszPartClass, &pWmiClassRight);
|
|
if(FAILED(hr))
|
|
{
|
|
//
|
|
// This just means there is a class in the container list that
|
|
// doesn't exist.
|
|
//
|
|
hr = WBEM_S_NO_ERROR;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Construct association name
|
|
//
|
|
cchPartClass = wcslen(wszPartClass);
|
|
memcpy(wszTemp, wszGroupClass, sizeof(WCHAR)*cchGroupClass);
|
|
memcpy(wszTemp+cchGroupClass, L"_", sizeof(WCHAR));
|
|
memcpy(
|
|
wszTemp + cchGroupClass + 1,
|
|
wszPartClass,
|
|
sizeof(WCHAR)*(cchPartClass+1));
|
|
|
|
hr = m_hashAssociations.Wmi_GetByKey(wszTemp, &pWmiAssoc);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if( pWmiClassLeft->dwExtended != USER_DEFINED_TO_REPOSITORY &&
|
|
pWmiClassLeft->dwExtended != USER_DEFINED_NOT_TO_REPOSITORY &&
|
|
pWmiClassRight->dwExtended != USER_DEFINED_TO_REPOSITORY &&
|
|
pWmiClassRight->dwExtended != USER_DEFINED_NOT_TO_REPOSITORY )
|
|
{
|
|
//
|
|
// This means we already put this shipped association in, but it is
|
|
// not a conflict.
|
|
// We need this because this method is called twice for each
|
|
// group class.
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
hr = WBEM_S_NO_ERROR;
|
|
|
|
//
|
|
// TODO: Move this outside?
|
|
//
|
|
hr = RuleWmiClassInverseCCL(pWmiClassLeft->pkt, pWmiClassRight->pkt);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = m_spoolStrings.GetNewString(
|
|
wszTemp,
|
|
cchGroupClass+1+cchPartClass, // cch
|
|
&wszAssocName);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = m_poolAssociations.GetNewElement(&pWmiAssoc);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
pWmiAssoc->pszAssociationName = wszAssocName;
|
|
pWmiAssoc->pcLeft = pWmiClassLeft;
|
|
pWmiAssoc->pcRight = pWmiClassRight;
|
|
pWmiAssoc->pType = &WMI_ASSOCIATION_TYPE_DATA::s_Component;
|
|
pWmiAssoc->fFlags = 0;
|
|
|
|
if( pWmiClassLeft->dwExtended == EXTENDED ||
|
|
pWmiClassLeft->dwExtended == USER_DEFINED_TO_REPOSITORY ||
|
|
pWmiClassRight->dwExtended == EXTENDED ||
|
|
pWmiClassRight->dwExtended == USER_DEFINED_TO_REPOSITORY)
|
|
{
|
|
pWmiAssoc->pszParentClass = g_wszExtGroupPartAssocParent;
|
|
pWmiAssoc->dwExtended = USER_DEFINED_TO_REPOSITORY;
|
|
}
|
|
else
|
|
{
|
|
pWmiAssoc->pszParentClass = g_wszGroupPartAssocParent;
|
|
pWmiAssoc->dwExtended = SHIPPED_TO_MOF;
|
|
}
|
|
hr = m_hashAssociations.Wmi_Insert(wszAssocName, pWmiAssoc);
|
|
if(FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
exit:
|
|
delete [] wszCCL;
|
|
delete [] wszTemp;
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDynSchema::RuleSpecialAssociations(
|
|
DWORD i_adwIgnoredProps[],
|
|
WMI_CLASS* i_pElement)
|
|
/*++
|
|
|
|
Synopsis:
|
|
Creates IPSecurity and AdminACL associations
|
|
|
|
Arguments: [i_adwIgnoredProps[]] -
|
|
[i_pElement] -
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(i_pElement != NULL);
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
bool bCreateIPSecAssoc = false;
|
|
bool bCreateAdminACLAssoc = false;
|
|
DWORD dwExtended = SHIPPED_TO_MOF;
|
|
|
|
if(i_pElement->dwExtended != SHIPPED_TO_MOF && i_pElement->dwExtended != EXTENDED &&
|
|
i_pElement->dwExtended != USER_DEFINED_TO_REPOSITORY)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (USER_DEFINED_TO_REPOSITORY == i_pElement->dwExtended)
|
|
{
|
|
dwExtended = USER_DEFINED_TO_REPOSITORY;
|
|
}
|
|
|
|
for(ULONG i = 0;
|
|
i < g_cElemPropIgnoreList && i_adwIgnoredProps[i] != 0;
|
|
i++)
|
|
{
|
|
if(i_adwIgnoredProps[i] == MD_IP_SEC)
|
|
{
|
|
bCreateIPSecAssoc = true;
|
|
}
|
|
else if(i_adwIgnoredProps[i] == MD_ADMIN_ACL)
|
|
{
|
|
bCreateAdminACLAssoc = true;
|
|
}
|
|
}
|
|
|
|
if(bCreateIPSecAssoc)
|
|
{
|
|
hr = RuleGenericAssociations(
|
|
i_pElement,
|
|
&WMI_CLASS_DATA::s_IPSecurity,
|
|
&WMI_ASSOCIATION_TYPE_DATA::s_IPSecurity,
|
|
dwExtended);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
if(bCreateAdminACLAssoc)
|
|
{
|
|
hr = RuleGenericAssociations(
|
|
i_pElement,
|
|
&WMI_CLASS_DATA::s_AdminACL,
|
|
&WMI_ASSOCIATION_TYPE_DATA::s_AdminACL,
|
|
dwExtended);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDynSchema::ConstructFlatInverseContainerList()
|
|
/*++
|
|
|
|
Synopsis:
|
|
Constructs an "inverse flat container class list".
|
|
This list is stored in m_abKtContainers, an array of size iNumKeys*iNumKeys.
|
|
The first iNumKeys entries are for Key #1 and then so on. Let's call this row 1.
|
|
In row 1, entry i corresponds to Key #i.
|
|
This entry [1,i] is set to true if Key #1 can be contained somewhere under Key #i.
|
|
For instance, [IIsWebDirectory, IIsWebService] is true since an IIsWebService
|
|
can contain an IIsWebServer which can contain an IIsWebDirectory.
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(m_bInitCalled == true);
|
|
DBG_ASSERT(m_bInitSuccessful == true);
|
|
|
|
ULONG iNumKeys = m_hashKeyTypes.Wmi_GetNumElements();
|
|
|
|
m_abKtContainers = new bool[iNumKeys * iNumKeys];
|
|
if(m_abKtContainers == NULL)
|
|
{
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
memset(m_abKtContainers, 0, iNumKeys * iNumKeys * sizeof(bool));
|
|
|
|
CHashTable<METABASE_KEYTYPE*>::iterator iter;
|
|
CHashTable<METABASE_KEYTYPE*>::iterator iterEnd = m_hashKeyTypes.end();
|
|
for (iter = m_hashKeyTypes.begin(); iter != iterEnd; ++iter)
|
|
{
|
|
CHashTable<METABASE_KEYTYPE*>::Record* pRec = iter.Record();
|
|
METABASE_KEYTYPE_NODE* pktnode = pRec->m_data->m_pKtListInverseCCL;
|
|
while(pktnode != NULL)
|
|
{
|
|
ConstructFlatInverseContainerListHelper(
|
|
pktnode->m_pKt,
|
|
&m_abKtContainers[pRec->m_idx * iNumKeys]);
|
|
pktnode = pktnode->m_pKtNext;
|
|
}
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// TODO: Prove this will always terminate.
|
|
//
|
|
void CDynSchema::ConstructFlatInverseContainerListHelper(
|
|
const METABASE_KEYTYPE* i_pkt,
|
|
bool* io_abList)
|
|
/*++
|
|
|
|
Synopsis:
|
|
This walks the inverse container class list of i_pkt.
|
|
For each entry, we call ConstructFlatInverseContainerListHelper and mark all the keytypes
|
|
we see on the way.
|
|
We terminate when we hit a keytype we've already seen or if there are no more keytypes
|
|
in the inverse container class list.
|
|
|
|
Arguments: [i_pkt] -
|
|
[io_abList] -
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(m_bInitCalled == true);
|
|
DBG_ASSERT(m_bInitSuccessful == true);
|
|
DBG_ASSERT(i_pkt != NULL);
|
|
DBG_ASSERT(io_abList != NULL);
|
|
|
|
ULONG idx;
|
|
METABASE_KEYTYPE* pktDummy;
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
hr = m_hashKeyTypes.Wmi_GetByKey(i_pkt->m_pszName, &pktDummy, &idx);
|
|
if(FAILED(hr))
|
|
{
|
|
DBG_ASSERT(false && "Keytype should be in hashtable of keytypes");
|
|
return;
|
|
}
|
|
if(io_abList[idx] == true) return;
|
|
|
|
io_abList[idx] = true;
|
|
|
|
METABASE_KEYTYPE_NODE* pktnode = i_pkt->m_pKtListInverseCCL;
|
|
while(pktnode != NULL)
|
|
{
|
|
ConstructFlatInverseContainerListHelper(pktnode->m_pKt, io_abList);
|
|
pktnode = pktnode->m_pKtNext;
|
|
}
|
|
}
|
|
|
|
bool CDynSchema::IsContainedUnder(METABASE_KEYTYPE* i_pktParent, METABASE_KEYTYPE* i_pktChild)
|
|
/*++
|
|
|
|
Synopsis:
|
|
Uses m_abKtContainers described above to determine whether i_pktChild can
|
|
be contained somewhere under i_pktParent.
|
|
|
|
Arguments: [i_pktParent] -
|
|
[i_pktChild] -
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(m_bInitCalled == true);
|
|
DBG_ASSERT(m_bInitSuccessful == true);
|
|
DBG_ASSERT(i_pktParent != NULL);
|
|
DBG_ASSERT(i_pktChild != NULL);
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
METABASE_KEYTYPE* pktDummy;
|
|
ULONG idxParent;
|
|
ULONG idxChild;
|
|
|
|
hr = m_hashKeyTypes.Wmi_GetByKey(i_pktParent->m_pszName, &pktDummy, &idxParent);
|
|
if(FAILED(hr))
|
|
{
|
|
return false;
|
|
}
|
|
hr = m_hashKeyTypes.Wmi_GetByKey(i_pktChild->m_pszName, &pktDummy, &idxChild);
|
|
if(FAILED(hr))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return m_abKtContainers[idxChild * m_hashKeyTypes.Wmi_GetNumElements() + idxParent];
|
|
}
|
|
|
|
void CDynSchema::ToConsole()
|
|
{
|
|
DBG_ASSERT(m_bInitCalled == true);
|
|
DBG_ASSERT(m_bInitSuccessful == true);
|
|
|
|
/*CHashTableElement<WMI_CLASS *>* pElement;
|
|
m_hashClasses.Enum(NULL, &pElement);
|
|
while(pElement != NULL)
|
|
{
|
|
wprintf(L"%s\n", pElement->m_data->pszClassName);
|
|
// wprintf(L"\tShipped: %d\n", pElement->m_iShipped);
|
|
wprintf(L"\tKT: %s\n", pElement->m_data->pkt->m_pszName);
|
|
wprintf(L"\tKN: %s\n", pElement->m_data->pszKeyName);
|
|
wprintf(L"\tMK: %s\n", pElement->m_data->pszMetabaseKey);
|
|
METABASE_PROPERTY** ppmbp = pElement->m_data->ppmbp;
|
|
for(ULONG q = 0; ppmbp != NULL && ppmbp[q] != NULL; q++)
|
|
{
|
|
wprintf(L"\tProp: %s\n", ppmbp[q]->pszPropName);
|
|
}
|
|
pElement = pElement->m_pNext;
|
|
}
|
|
|
|
|
|
ULONG i;
|
|
|
|
m_hashKeyTypes.ToConsole();
|
|
|
|
WMI_CLASS *pWmiClass;
|
|
for(i = 0; i < m_poolClasses.GetUsed(); i++)
|
|
{
|
|
pWmiClass = m_poolClasses.Lookup(i);
|
|
wprintf( L"%s KT: %d\n", pWmiClass->pszClassName, pWmiClass->pkt );
|
|
for(ULONG j = 0; ; j++)
|
|
{
|
|
if(pWmiClass->ppmbp[j] == NULL)
|
|
{
|
|
break;
|
|
}
|
|
wprintf(L"\t%s\tId: %d\tUT: %d\tDT: %d\tMSK: %d\tAttr: %d\tRO: %d\n",
|
|
pWmiClass->ppmbp[j]->pszPropName,
|
|
pWmiClass->ppmbp[j]->dwMDIdentifier,
|
|
pWmiClass->ppmbp[j]->dwMDUserType,
|
|
pWmiClass->ppmbp[j]->dwMDDataType,
|
|
pWmiClass->ppmbp[j]->dwMDMask,
|
|
pWmiClass->ppmbp[j]->dwMDAttributes,
|
|
pWmiClass->ppmbp[j]->fReadOnly);
|
|
}
|
|
}
|
|
WMI_ASSOCIATION *pWmiAssoc;
|
|
for(i = 0; i < m_poolAssociations.GetUsed(); i++)
|
|
{
|
|
pWmiAssoc = m_poolAssociations.Lookup(i);
|
|
wprintf(L"%s\n", pWmiAssoc->pszAssociationName);
|
|
wprintf(L"\t%s\n\t%s\n",
|
|
pWmiAssoc->pcLeft->pszClassName,
|
|
pWmiAssoc->pcRight->pszClassName);
|
|
}
|
|
|
|
for(unsigned int q = 0; q < m_poolProps.GetUsed(); q++)
|
|
{
|
|
METABASE_PROPERTY* qt = m_poolProps.Lookup(q);
|
|
wprintf(L"%s\n", qt->pszPropName);
|
|
}*/
|
|
}
|
|
|
|
HRESULT CDynSchema::RulePopulateFromDynamic(
|
|
CSchemaExtensions* i_pCatalog,
|
|
BOOL i_bUserDefined)
|
|
{
|
|
DBG_ASSERT(m_bInitSuccessful == true);
|
|
DBG_ASSERT(i_pCatalog != NULL);
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
ULONG i = 0;
|
|
CTableMeta* pTableMeta = NULL;
|
|
WMI_CLASS* pElementClass = NULL;
|
|
WMI_CLASS* pSettingClass = NULL;
|
|
DWORD adwIgnoredProps[g_cElemPropIgnoreList];
|
|
|
|
DWORD dwUserDefined = 0;
|
|
|
|
while(pTableMeta = i_pCatalog->EnumTables(&i))
|
|
{
|
|
dwUserDefined =
|
|
(fTABLEMETA_USERDEFINED & *pTableMeta->TableMeta.pSchemaGeneratorFlags);
|
|
if( (i_bUserDefined && !dwUserDefined) || (!i_bUserDefined && dwUserDefined) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
memset(adwIgnoredProps, 0, g_cElemPropIgnoreList*sizeof(DWORD));
|
|
pElementClass = NULL;
|
|
pSettingClass = NULL;
|
|
|
|
hr = RuleKeyType(pTableMeta);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
DBG_ASSERT(pTableMeta->TableMeta.pInternalName);
|
|
hr = RuleWmiClass(
|
|
pTableMeta,
|
|
&pElementClass,
|
|
&pSettingClass,
|
|
adwIgnoredProps,
|
|
i_bUserDefined);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
DBG_ASSERT(pElementClass != NULL);
|
|
DBG_ASSERT(pSettingClass != NULL);
|
|
|
|
if ( (NULL == pElementClass) || (NULL == pSettingClass) )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
hr = RuleGenericAssociations(
|
|
pElementClass,
|
|
pSettingClass,
|
|
&WMI_ASSOCIATION_TYPE_DATA::s_ElementSetting,
|
|
pElementClass->dwExtended);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = RuleSpecialAssociations(
|
|
adwIgnoredProps,
|
|
pElementClass);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
RuleWmiClassServices(pElementClass, pSettingClass);
|
|
|
|
hr = RuleWmiClassDescription(pTableMeta, pElementClass, pSettingClass);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
i = 0;
|
|
while(pTableMeta = i_pCatalog->EnumTables(&i))
|
|
{
|
|
dwUserDefined =
|
|
(fTABLEMETA_USERDEFINED & *pTableMeta->TableMeta.pSchemaGeneratorFlags);
|
|
|
|
if(!i_bUserDefined && dwUserDefined)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
hr = RuleGroupPartAssociations(pTableMeta);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDynSchema::RunRules(
|
|
CSchemaExtensions* i_pCatalog,
|
|
bool i_bUseExtensions)
|
|
/*++
|
|
|
|
Synopsis:
|
|
Does all the work
|
|
|
|
Arguments: [i_pCatalog] - This function calls Initialize.
|
|
Don't call Init outside this function.
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DBG_ASSERT(m_bInitCalled == true);
|
|
DBG_ASSERT(m_bInitSuccessful == true);
|
|
DBG_ASSERT(i_pCatalog != NULL);
|
|
|
|
HRESULT hr = S_OK;
|
|
ULONG i = 0;
|
|
|
|
//
|
|
// TODO: Don't think I need this
|
|
//
|
|
if(m_bRulesRun)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = RulePopulateFromStatic();
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = Rule2PopulateFromStatic();
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = i_pCatalog->Initialize(i_bUseExtensions);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = RulePopulateFromDynamic(
|
|
i_pCatalog,
|
|
false); // shipped schema
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
hr = RulePopulateFromDynamic(
|
|
i_pCatalog,
|
|
true); // user-defined schema
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = ConstructFlatInverseContainerList();
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
m_bRulesRun = true;
|
|
}
|
|
|
|
return hr;
|
|
}
|