|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
pusher.cpp
Abstract:
This file contains the implementation of the CPusher class. This class contains the logic for pushing schema to the repository.
Author:
Mohit Srivastava 28-Nov-00
Revision History:
--*/
#include "iisprov.h"
#include "pusher.h"
#include "MultiSzData.h"
#include "schema.h"
extern CDynSchema* g_pDynSch; // Initialized to NULL in schemadynamic.cpp
HRESULT CPusher::RepositoryInSync( const CSchemaExtensions* i_pCatalog, bool* io_pbInSync) { DBG_ASSERT(m_bInitSuccessful == true); DBG_ASSERT(io_pbInSync != NULL); DBG_ASSERT(i_pCatalog != NULL);
HRESULT hr = WBEM_S_NO_ERROR;
CComBSTR sbstrTemp; CComVariant svtTimeStamp; CComPtr<IWbemClassObject> spObjIIsComputer;
sbstrTemp = WMI_CLASS_DATA::s_Computer.pszClassName; if(sbstrTemp.m_str == NULL) { return WBEM_E_OUT_OF_MEMORY; } hr = m_pNamespace->GetObject(sbstrTemp, 0, m_pCtx, &spObjIIsComputer, NULL); if(FAILED(hr)) { return hr; }
//
// Try to get timestamp from repository
//
hr = CUtils::GetQualifiers(spObjIIsComputer, &g_wszCq_SchemaTS, &svtTimeStamp, 1); if(FAILED(hr) || svtTimeStamp.vt != VT_BSTR) { *io_pbInSync = false; return WBEM_S_NO_ERROR; }
//
// Get timestamp of mbschema.xml
//
FILETIME FileTime; hr = i_pCatalog->GetMbSchemaTimeStamp(&FileTime); if(FAILED(hr)) { return hr; }
//
// Finally, compare the timestamps
//
WCHAR wszFileTime[30]; CUtils::FileTimeToWchar(&FileTime, wszFileTime); if(_wcsicmp(wszFileTime, svtTimeStamp.bstrVal) == 0) { *io_pbInSync = true; } else { *io_pbInSync = false; } return hr; }
HRESULT CPusher::SetTimeStamp( const CSchemaExtensions* i_pCatalog) { DBG_ASSERT(m_bInitSuccessful == true); DBG_ASSERT(i_pCatalog != NULL);
HRESULT hr = WBEM_S_NO_ERROR;
CComBSTR sbstrTemp; CComVariant svtTimeStamp; CComPtr<IWbemClassObject> spObjIIsComputer;
sbstrTemp = WMI_CLASS_DATA::s_Computer.pszClassName; if(sbstrTemp.m_str == NULL) { return WBEM_E_OUT_OF_MEMORY; } hr = m_pNamespace->GetObject(sbstrTemp, 0, m_pCtx, &spObjIIsComputer, NULL); if(FAILED(hr)) { return hr; }
//
// Get timestamp of mbschema.xml
//
FILETIME FileTime; hr = i_pCatalog->GetMbSchemaTimeStamp(&FileTime); if(FAILED(hr)) { return hr; } WCHAR wszFileTime[30]; CUtils::FileTimeToWchar(&FileTime, wszFileTime);
//
// Finally, Set the timestamp in the repository
//
svtTimeStamp = wszFileTime; if(svtTimeStamp.vt != VT_BSTR || svtTimeStamp.bstrVal == NULL) { return WBEM_E_OUT_OF_MEMORY; } hr = CUtils::SetQualifiers( spObjIIsComputer, &g_wszCq_SchemaTS, &svtTimeStamp, 1, 0); if(FAILED(hr)) { return hr; }
//
// Finally, put the class
//
hr = m_pNamespace->PutClass(spObjIIsComputer, WBEM_FLAG_OWNER_UPDATE, m_pCtx, NULL); if(FAILED(hr)) { return hr; }
return hr; }
HRESULT CPusher::Initialize(CWbemServices* i_pNamespace, IWbemContext* i_pCtx) /*++
Synopsis: Only call once.
Arguments: [i_pNamespace] - [i_pCtx] - Return Value:
--*/ { DBG_ASSERT(i_pNamespace != NULL); DBG_ASSERT(i_pCtx != NULL); DBG_ASSERT(m_bInitCalled == false); DBG_ASSERT(m_bInitSuccessful == false);
HRESULT hr = WBEM_S_NO_ERROR; CComBSTR bstrTemp;
m_bInitCalled = true; m_pCtx = i_pCtx; m_pNamespace = i_pNamespace; m_awszClassQualNames[1] = g_wszCq_Dynamic; m_avtClassQualValues[1] = (bool)true; m_awszClassQualNames[0] = g_wszCq_Provider; m_avtClassQualValues[0] = g_wszCqv_Provider;; if(m_avtClassQualValues[0].bstrVal == NULL) { hr = WBEM_E_OUT_OF_MEMORY; DBGPRINTF((DBG_CONTEXT, "CPusher::Initialize failed, hr=0x%x\n", hr)); goto exit; }
//
// Get pointers to most commonly used base classes
//
bstrTemp = g_wszExtElementParent; if(bstrTemp.m_str == NULL) { hr = WBEM_E_OUT_OF_MEMORY; DBGPRINTF((DBG_CONTEXT, "CPusher::Initialize failed, hr=0x%x\n", hr)); goto exit; } hr = m_pNamespace->GetObject(bstrTemp, 0, m_pCtx, &m_spBaseElementObject, NULL); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::Initialize failed, hr=0x%x\n", hr)); goto exit; }
bstrTemp = g_wszExtSettingParent; if(bstrTemp.m_str == NULL) { hr = WBEM_E_OUT_OF_MEMORY; DBGPRINTF((DBG_CONTEXT, "CPusher::Initialize failed, hr=0x%x\n", hr)); goto exit; } hr = m_pNamespace->GetObject(bstrTemp, 0, m_pCtx, &m_spBaseSettingObject, NULL); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::Initialize failed, hr=0x%x\n", hr)); goto exit; }
bstrTemp = g_wszExtElementSettingAssocParent; if(bstrTemp.m_str == NULL) { hr = WBEM_E_OUT_OF_MEMORY; DBGPRINTF((DBG_CONTEXT, "CPusher::Initialize failed, hr=0x%x\n", hr)); goto exit; } hr = m_pNamespace->GetObject(bstrTemp, 0, m_pCtx, &m_spBaseElementSettingObject, NULL); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::Initialize failed, hr=0x%x\n", hr)); goto exit; }
bstrTemp = g_wszExtGroupPartAssocParent; if(bstrTemp.m_str == NULL) { hr = WBEM_E_OUT_OF_MEMORY; DBGPRINTF((DBG_CONTEXT, "CPusher::Initialize failed, hr=0x%x\n", hr)); goto exit; } hr = m_pNamespace->GetObject(bstrTemp, 0, m_pCtx, &m_spBaseGroupPartObject, NULL); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::Initialize failed, hr=0x%x\n", hr)); goto exit; }
exit: if(SUCCEEDED(hr)) { m_bInitSuccessful = true; } return hr; }
CPusher::~CPusher() { }
HRESULT CPusher::Push( const CSchemaExtensions* i_pCatalog, CHashTable<WMI_CLASS *>* i_phashClasses, CHashTable<WMI_ASSOCIATION*>* i_phashAssocs) { DBG_ASSERT(i_pCatalog != NULL); DBG_ASSERT(i_phashClasses != NULL); DBG_ASSERT(i_phashAssocs != NULL); DBG_ASSERT(m_bInitSuccessful == true);
HRESULT hr = WBEM_S_NO_ERROR;
bool bInSync= false;
hr = RepositoryInSync(i_pCatalog, &bInSync); if(FAILED(hr)) { return hr; }
if(!bInSync) { hr = PushClasses(i_phashClasses); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::Push failed, hr=0x%x\n", hr)); return hr; } hr = PushAssocs(i_phashAssocs); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::Push failed, hr=0x%x\n", hr)); return hr; } hr = SetTimeStamp(i_pCatalog); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::Push failed, hr=0x%x\n", hr)); return hr; } }
return hr; }
HRESULT CPusher::PushClasses( CHashTable<WMI_CLASS *>* i_phashTable) /*++
Synopsis: Public function to push classes to repository. 1) Precondition: All USER_DEFINED_TO_REPOSITORY classes are not in repository. 2) Pushes all USER_DEFINED_TO_REPOSITORY classes to repository. 3) Deletes and recreates SHIPPED_TO_MOF, SHIPPED_NOT_TO_MOF, and EXTENDED classes if necessary.
Arguments: [i_phashTable] - Return Value:
--*/ { DBG_ASSERT(i_phashTable != NULL); DBG_ASSERT(m_pNamespace != NULL); DBG_ASSERT(m_bInitSuccessful == true);
HRESULT hr = WBEM_S_NO_ERROR; CComPtr<IWbemClassObject> spObject = NULL; CComPtr<IWbemClassObject> spChildObject = NULL;
//
// Vars needed for iteration
//
CHashTable<WMI_CLASS*>::Record* pRec = NULL; CHashTable<WMI_CLASS*>::iterator iter; CHashTable<WMI_CLASS*>::iterator iterEnd;
CComVariant v;
//
// DeleteChildren of extended base classes
//
LPWSTR awszBaseClasses[] = { g_wszExtElementParent, g_wszExtSettingParent, NULL };
for(ULONG idx = 0; awszBaseClasses[idx] != NULL; idx++) { hr = DeleteChildren(awszBaseClasses[idx]); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::PushClasses failed, hr=0x%x\n", hr)); goto exit; } }
//
// Walk thru the hashtable of classes
//
bool bPutNeeded; iterEnd = i_phashTable->end(); for(iter = i_phashTable->begin(); iter != iterEnd; ++iter) { pRec = iter.Record(); DBG_ASSERT(pRec != NULL);
//
// Deletes SHIPPED_TO_MOF, SHIPPED_NOT_TO_MOF, EXTENDED classes if necessary.
//
hr = PrepareForPutClass(pRec->m_data, &bPutNeeded); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::PushClasses failed, hr=0x%x\n", hr)); goto exit; }
if(bPutNeeded) { hr = GetObject(pRec->m_data->pszParentClass, &spObject); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::PushClasses failed, hr=0x%x\n", hr)); goto exit; }
hr = spObject->SpawnDerivedClass(0, &spChildObject); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::PushClasses failed, hr=0x%x\n", hr)); goto exit; } spObject = NULL;
//
// Push class qualifiers and special __CLASS property.
//
hr = SetClassInfo( spChildObject, pRec->m_wszKey, pRec->m_data->dwExtended); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::PushClasses failed, hr=0x%x\n", hr)); goto exit; }
//
// Name property and corresponding qualifier
// Base class may contain Name. Handle this case
//
bool bPutNameProperty = true; for(ULONG j = 0; g_awszParentClassWithNamePK[j] != NULL; j++) { //
// Deliberate ==
//
if(g_awszParentClassWithNamePK[j] == pRec->m_data->pszParentClass) { bPutNameProperty = false; } } if( bPutNameProperty ) { hr = spChildObject->Put(g_wszProp_Name, 0, NULL, CIM_STRING); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::PushClasses failed, hr=0x%x\n", hr)); goto exit; } v = (bool)true; hr = CUtils::SetPropertyQualifiers( spChildObject, g_wszProp_Name, // Property name
&g_wszPq_Key, // Array of qual names
&v, // Array of qual values
1 // Nr of quals
); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::PushClasses failed, hr=0x%x\n", hr)); goto exit; } }
//
// All other properties
//
hr = SetProperties(pRec->m_data, spChildObject); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::PushClasses failed, hr=0x%x\n", hr)); goto exit; }
//
// Any methods
//
hr = SetMethods(pRec->m_data, spChildObject); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::PushClasses failed, hr=0x%x\n", hr)); goto exit; }
//
// Finally, put the class
//
hr = m_pNamespace->PutClass(spChildObject, WBEM_FLAG_OWNER_UPDATE, m_pCtx, NULL); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::PushClasses failed, hr=0x%x\n", hr)); goto exit; }
spChildObject = NULL; } }
exit: return hr; }
HRESULT CPusher::PushAssocs( CHashTable<WMI_ASSOCIATION*>* i_phashTable) /*++
Synopsis: Public function to push assocs to repository. - Precondition: All USER_DEFINED_TO_REPOSITORY assocs are not in repository. - Pushes all USER_DEFINED_TO_REPOSITORY assocs to repository.
Arguments: [i_phashTable] - Return Value:
--*/ { DBG_ASSERT(i_phashTable != NULL); DBG_ASSERT(m_pNamespace != NULL); DBG_ASSERT(m_bInitSuccessful == true);
HRESULT hr = WBEM_S_NO_ERROR; CComPtr<IWbemClassObject> spObject = NULL; CComPtr<IWbemClassObject> spChildObject = NULL;
//
// Vars needed for iteration
//
CHashTable<WMI_ASSOCIATION*>::Record* pRec = NULL; CHashTable<WMI_ASSOCIATION*>::iterator iter; CHashTable<WMI_ASSOCIATION*>::iterator iterEnd;
//
// DeleteChildren of extended base classes
//
LPWSTR awszBaseClasses[] = { g_wszExtElementSettingAssocParent, g_wszExtGroupPartAssocParent, NULL };
for(ULONG idx = 0; awszBaseClasses[idx] != NULL; idx++) { hr = DeleteChildren(awszBaseClasses[idx]); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::PushAssocs failed, hr=0x%x\n", hr)); goto exit; } }
//
// Walk thru the hashtable of assocs
//
for(iter = i_phashTable->begin(), iterEnd = i_phashTable->end(); iter != iterEnd; ++iter) { pRec = iter.Record(); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::PushAssocs failed, hr=0x%x\n", hr)); goto exit; }
if(pRec->m_data->dwExtended == USER_DEFINED_TO_REPOSITORY) { hr = GetObject(pRec->m_data->pszParentClass, &spObject); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::PushAssocs failed, hr=0x%x\n", hr)); goto exit; }
hr = spObject->SpawnDerivedClass(0, &spChildObject); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::PushAssocs failed, hr=0x%x\n", hr)); goto exit; } spObject = NULL;
//
// Push class qualifiers and special __CLASS property.
//
hr = SetClassInfo( spChildObject, pRec->m_wszKey, pRec->m_data->dwExtended); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::PushAssocs failed, hr=0x%x\n", hr)); goto exit; }
//
// Push the two ref properties of the association.
//
hr = SetAssociationComponent( spChildObject, pRec->m_data->pType->pszLeft, pRec->m_data->pcLeft->pszClassName); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::PushAssocs failed, hr=0x%x\n", hr)); goto exit; } hr = SetAssociationComponent( spChildObject, pRec->m_data->pType->pszRight, pRec->m_data->pcRight->pszClassName); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::PushAssocs failed, hr=0x%x\n", hr)); goto exit; }
hr = m_pNamespace->PutClass( spChildObject, WBEM_FLAG_OWNER_UPDATE | WBEM_FLAG_CREATE_ONLY, m_pCtx, NULL); if(FAILED(hr)) { if(hr == WBEM_E_ALREADY_EXISTS) { hr = WBEM_S_NO_ERROR; } else { DBGPRINTF((DBG_CONTEXT, "CPusher::PushAssocs failed, hr=0x%x\n", hr)); goto exit; } }
spChildObject = NULL; } }
exit: return hr; }
HRESULT CPusher::PrepareForPutClass( const WMI_CLASS* i_pClass, bool* io_pbPutNeeded) /*++
Synopsis: Deletes and recreates SHIPPED_TO_MOF, SHIPPED_NOT_TO_MOF, and EXTENDED classes if necessary. Sets io_pbPutNeeded accordingly.
Arguments: [i_pClass] - Return Value:
--*/ { DBG_ASSERT(m_bInitSuccessful == true); DBG_ASSERT(i_pClass != NULL); DBG_ASSERT(io_pbPutNeeded != NULL);
HRESULT hr = WBEM_S_NO_ERROR; CComPtr<IWbemClassObject> spObj; CComBSTR bstrClass = i_pClass->pszClassName; if(bstrClass.m_str == NULL) { return WBEM_E_OUT_OF_MEMORY; } bool bExtendedQual = false; bool bPutNeeded = false;
HRESULT hrGetObject = m_pNamespace->GetObject( bstrClass, WBEM_FLAG_RETURN_WBEM_COMPLETE, m_pCtx, &spObj, NULL); if( hrGetObject != WBEM_E_INVALID_CLASS && hrGetObject != WBEM_E_NOT_FOUND) { hr = hrGetObject; } if(FAILED(hr)) { return hr; }
//
// Determine if the [extended] qualifier is set.
//
if(SUCCEEDED(hrGetObject)) { VARIANT vtExtended; VariantInit(&vtExtended);
HRESULT hrGetQuals = CUtils::GetQualifiers(spObj, &g_wszCq_Extended, &vtExtended, 1); if(FAILED(hrGetQuals)) { bExtendedQual = false; } else if(vtExtended.vt == VT_BOOL) { bExtendedQual = vtExtended.boolVal ? true : false; } }
//
// Pretty much, don't do a Put class if both the catalog and repository
// versions are shipped. This is an optimization for the normal case.
//
switch(i_pClass->dwExtended) { case EXTENDED: if( hrGetObject != WBEM_E_INVALID_CLASS && hrGetObject != WBEM_E_NOT_FOUND) { hr = m_pNamespace->DeleteClass( bstrClass, WBEM_FLAG_OWNER_UPDATE, m_pCtx, NULL); if(FAILED(hr)) { return hr; } } bPutNeeded = true; break; case USER_DEFINED_NOT_TO_REPOSITORY: bPutNeeded = false; break; case USER_DEFINED_TO_REPOSITORY: if( hrGetObject != WBEM_E_INVALID_CLASS && hrGetObject != WBEM_E_NOT_FOUND) { //
// There is already a class in the repository with the same name
// as this user-defined class.
// TODO: Log an error.
//
bPutNeeded = false; } else { bPutNeeded = true; } break; case SHIPPED_TO_MOF: case SHIPPED_NOT_TO_MOF: if(bExtendedQual) { if( hrGetObject != WBEM_E_INVALID_CLASS && hrGetObject != WBEM_E_NOT_FOUND) { hr = m_pNamespace->DeleteClass( bstrClass, WBEM_FLAG_OWNER_UPDATE, m_pCtx, NULL); if(FAILED(hr)) { return hr; } } bPutNeeded = true; } else { bPutNeeded = (hrGetObject == WBEM_E_INVALID_CLASS || hrGetObject == WBEM_E_NOT_FOUND) ? true : false; } break; default: DBG_ASSERT(false && "Unknown i_pClass->dwExtended"); break; }
*io_pbPutNeeded = bPutNeeded;
return hr; }
HRESULT CPusher::SetClassInfo( IWbemClassObject* i_pObj, LPCWSTR i_wszClassName, ULONG i_iShipped) /*++
Synopsis: Sets class qualifiers and special __CLASS property on i_pObj
Arguments: [i_pObj] - The class or association [i_wszClassName] - Will be value of __CLASS property [i_iShipped] - Determines if we set g_wszCq_Extended qualifier Return Value:
--*/ { DBG_ASSERT(i_pObj != NULL); DBG_ASSERT(i_wszClassName != NULL); DBG_ASSERT(m_bInitSuccessful == true); HRESULT hr; CComVariant v;
//
// Class qualifiers (propagated to instance)
//
hr = CUtils::SetQualifiers( i_pObj, m_awszClassQualNames, m_avtClassQualValues, 2, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE); if(FAILED(hr)) { goto exit; }
//
// Another class qualifier (not propagated to instance)
//
if(i_iShipped == EXTENDED) { v = (bool)true; hr = CUtils::SetQualifiers( i_pObj, &g_wszCq_Extended, &v, 1, 0); if(FAILED(hr)) { goto exit; } }
//
// Special __CLASS property
//
v = i_wszClassName; if(v.bstrVal == NULL) { hr = WBEM_E_OUT_OF_MEMORY; goto exit; } hr = i_pObj->Put(g_wszProp_Class, 0, &v, 0); if(FAILED(hr)) { goto exit; }
exit: return hr; }
HRESULT CPusher::SetMethods( const WMI_CLASS* i_pElement, IWbemClassObject* i_pObject) const /*++
Synopsis: Called by PushClasses. Sets the methods in i_pObject using i_pElement
Arguments: [i_pElement] - [i_pObject] - Return Value:
--*/ { DBG_ASSERT(i_pElement != NULL); DBG_ASSERT(i_pObject != NULL); DBG_ASSERT(m_bInitSuccessful == true);
HRESULT hr = WBEM_S_NO_ERROR;
if(i_pElement->ppMethod == NULL) { return WBEM_S_NO_ERROR; }
CComPtr<IWbemClassObject> spParamsIn; CComPtr<IWbemClassObject> spParamsOut;
//
// Run thru all the methods
//
WMI_METHOD* pMethCurrent = NULL; for(ULONG i = 0; i_pElement->ppMethod[i] != NULL; i++) { pMethCurrent = i_pElement->ppMethod[i]; spParamsIn = NULL; spParamsOut = NULL;
if(pMethCurrent->ppParams != NULL) { WMI_METHOD_PARAM* pParamCur = NULL;
//
// The index to indicate to WMI the order of the parameters
// wszId is the qualifier name. svtId is a variant so we can give to WMI.
//
static LPCWSTR wszId = L"ID"; static LPCWSTR wszOpt = L"OPTIONAL"; CComVariant svtId = (int)0; CComVariant svtOpt = (bool)true;
//
// Run thru all the parameters
//
for(ULONG j = 0; pMethCurrent->ppParams[j] != NULL; j++) { //
// This will just hold spParamsIn and spParamsOut so we
// don't need to duplicate the code.
//
IWbemClassObject* apParamInOut[] = { NULL, NULL };
//
// Create the WMI instance for the in and/or out params as needed.
//
pParamCur = pMethCurrent->ppParams[j]; if( pParamCur->iInOut == PARAM_IN || pParamCur->iInOut == PARAM_INOUT ) { if(spParamsIn == NULL) { hr = m_pNamespace->GetObject(L"__Parameters", 0, m_pCtx, &spParamsIn, NULL); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::SetMethods failed, hr=0x%x\n", hr)); goto exit; } } apParamInOut[0] = spParamsIn; } if( pParamCur->iInOut == PARAM_OUT || pParamCur->iInOut == PARAM_INOUT ) { if(spParamsOut == NULL) { hr = m_pNamespace->GetObject(L"__Parameters", 0, m_pCtx, &spParamsOut, NULL); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::SetMethods failed, hr=0x%x\n", hr)); goto exit; } } apParamInOut[1] = spParamsOut; }
//
// Finally set them. First ins then outs.
//
for(ULONG k = 0; k < 2; k++) { if(apParamInOut[k] == NULL) { continue; } hr = apParamInOut[k]->Put( pParamCur->pszParamName, 0, NULL, pParamCur->type); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::SetMethods failed, hr=0x%x\n", hr)); goto exit; }
hr = CUtils::SetPropertyQualifiers( apParamInOut[k], pParamCur->pszParamName, &wszId, &svtId, 1); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::SetMethods failed, hr=0x%x\n", hr)); goto exit; } }
// set Optional qualifier on CreateNewSite param ServerId
if (pMethCurrent == &(WMI_METHOD_DATA::s_ServiceCreateNewServer) && pParamCur == &(WMI_METHOD_PARAM_DATA::s_ServerId)) {
DBG_ASSERT(apParamInOut[0] != NULL);
hr = CUtils::SetPropertyQualifiers( apParamInOut[0], pParamCur->pszParamName, &wszOpt, &svtOpt, 1);
if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::SetMethods failed, hr=0x%x\n", hr)); goto exit; } }
if(apParamInOut[0] || apParamInOut[1]) { svtId.lVal++; } } }
//
// Special: Return Value
//
if(pMethCurrent->typeRetVal) { if(spParamsOut == NULL) { hr = m_pNamespace->GetObject(L"__Parameters", 0, m_pCtx, &spParamsOut, NULL); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::SetMethods failed, hr=0x%x\n", hr)); goto exit; } } hr = spParamsOut->Put( L"ReturnValue", 0, NULL, pMethCurrent->typeRetVal); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "%s failed, hr=0x%x\n", __FUNCTION__, hr)); goto exit; } }
//
// Put the method.
//
hr = i_pObject->PutMethod( pMethCurrent->pszMethodName, 0, spParamsIn, spParamsOut); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::SetMethods failed, hr=0x%x\n", hr)); goto exit; }
// Set the qualifiers on the method
LPCWSTR aQuals[2] = { g_wszMq_Implemented, g_wszMq_Bypass_Getobject };
VARIANT vTrue; vTrue.boolVal = VARIANT_TRUE; vTrue.vt = VT_BOOL; VARIANT aVariants[2]; aVariants[0] = vTrue; aVariants[1] = vTrue;
hr = CUtils::SetMethodQualifiers( i_pObject, pMethCurrent->pszMethodName, aQuals, aVariants, 2); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::SetMethods failed, hr=0x%x\n", hr)); goto exit; }
/*if(pMethCurrent->pszDescription)
{ VARIANT vDesc; vDesc.bstrVal = pMethCurrent->pszDescription; vDesc.vt = VT_BSTR; hr = CUtils::SetMethodQualifiers( i_pObject, pMethCurrent->pszMethodName, &g_wszMq_Description, &vDesc, 1); if(FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "CPusher::SetMethods failed, hr=0x%x\n", hr)); goto exit; } }*/ }
exit: return hr; }
HRESULT CPusher::SetProperties( const WMI_CLASS* i_pElement, IWbemClassObject* i_pObject) const /*++
Synopsis: Called by PushClasses. Sets the properties in i_pObject using i_pElement
Arguments: [i_pElement] - [i_pObject] - Return Value:
--*/ { DBG_ASSERT(i_pElement != NULL); DBG_ASSERT(i_pObject != NULL); DBG_ASSERT(m_bInitSuccessful == true);
HRESULT hr = WBEM_S_NO_ERROR; METABASE_PROPERTY* pPropCurrent = NULL; TFormattedMultiSz* pFormattedMultiSz = NULL; CIMTYPE typeProp;
CComPtr<IWbemQualifierSet> spQualSet; VARIANT v; VariantInit(&v);
if(i_pElement->ppmbp == NULL) { return hr; }
for(ULONG i = 0; i_pElement->ppmbp[i] != NULL; i++) { pPropCurrent = i_pElement->ppmbp[i]; pFormattedMultiSz = NULL; switch(pPropCurrent->dwMDDataType) { case DWORD_METADATA: if(pPropCurrent->dwMDMask != 0) { typeProp = CIM_BOOLEAN; } else { typeProp = CIM_SINT32; } break; case STRING_METADATA: case EXPANDSZ_METADATA: typeProp = CIM_STRING; break; case MULTISZ_METADATA: typeProp = VT_ARRAY | CIM_STRING; pFormattedMultiSz = TFormattedMultiSzData::Find(pPropCurrent->dwMDIdentifier); if(pFormattedMultiSz) { typeProp = VT_ARRAY | CIM_OBJECT; } break; case BINARY_METADATA: typeProp = VT_ARRAY | CIM_UINT8; break; default: //
// Non fatal if we cannot recognize type
//
continue; }
hr = i_pObject->Put(pPropCurrent->pszPropName, 0, NULL, typeProp); if(FAILED(hr)) { goto exit; }
//
// qualifiers
//
hr = i_pObject->GetPropertyQualifierSet(pPropCurrent->pszPropName, &spQualSet); if(FAILED(hr)) { goto exit; }
//
// qualifier for read-only
//
V_VT(&v) = VT_BOOL; V_BOOL(&v) = (pPropCurrent->fReadOnly) ? VARIANT_FALSE : VARIANT_TRUE; hr = spQualSet->Put(g_wszPq_Write, &v, 0); if(FAILED(hr)) { goto exit; } V_BOOL(&v) = VARIANT_TRUE; hr = spQualSet->Put(g_wszPq_Read, &v, 0); if(FAILED(hr)) { goto exit; } VariantClear(&v);
//
// CIMType qualifier
//
if(pFormattedMultiSz) { DBG_ASSERT(typeProp == (VT_ARRAY | CIM_OBJECT));
CComBSTR sbstrValue = L"object:"; if(sbstrValue.m_str == NULL) { hr = WBEM_E_OUT_OF_MEMORY; goto exit; } sbstrValue += pFormattedMultiSz->wszWmiClassName; if(sbstrValue.m_str == NULL) { hr = WBEM_E_OUT_OF_MEMORY; goto exit; }
//
// Deliberately not smart variant. We will let sbstrValue do deconstruction.
//
VARIANT vValue; vValue.vt = VT_BSTR; vValue.bstrVal = sbstrValue; hr = spQualSet->Put(g_wszPq_CimType, &vValue, 0); if(FAILED(hr)) { goto exit; } }
spQualSet = NULL; }
exit: VariantClear(&v); return hr; }
HRESULT CPusher::SetAssociationComponent( IWbemClassObject* i_pObject, LPCWSTR i_wszComp, LPCWSTR i_wszClass) const /*++
Synopsis: Called by PushAssocs Sets a ref property of an association, i_pObj, using i_wszComp and i_wszClass
Arguments: [i_pObject] - the association [i_wszComp] - property name (Eg. Group, Part) [i_wszClass] - the class we are "ref"fing to. Return Value:
--*/ { DBG_ASSERT(i_pObject != NULL); DBG_ASSERT(i_wszComp != NULL); DBG_ASSERT(i_wszClass != NULL); DBG_ASSERT(m_bInitSuccessful == true);
HRESULT hr = WBEM_S_NO_ERROR; CComPtr<IWbemQualifierSet> spQualSet; VARIANT v; VariantInit(&v);
//
// Store "Ref:[class name]" in a bstr.
//
ULONG cchClass = wcslen(i_wszClass); CComBSTR sbstrClass(4 + cchClass); if(sbstrClass.m_str == NULL) { hr = WBEM_E_OUT_OF_MEMORY; goto exit; } memcpy(sbstrClass.m_str , L"Ref:", sizeof(WCHAR)*4); memcpy(sbstrClass.m_str + 4, i_wszClass, sizeof(WCHAR)*(cchClass+1));
//
// Put the property (Eg. Group, Part, etc.)
//
hr = i_pObject->Put(i_wszComp, 0, NULL, CIM_REFERENCE); if(FAILED(hr)) { goto exit; }
//
// Set Qualifiers on the property
//
hr = i_pObject->GetPropertyQualifierSet(i_wszComp, &spQualSet); if(FAILED(hr)) { goto exit; }
V_VT(&v) = VT_BOOL; V_BOOL(&v) = VARIANT_TRUE; hr = spQualSet->Put(g_wszPq_Key, &v, 0); if(FAILED(hr)) { goto exit; }
V_VT(&v) = VT_BSTR; V_BSTR(&v) = sbstrClass.m_str; if(V_BSTR(&v) == NULL) { V_VT(&v) = VT_EMPTY; hr = WBEM_E_OUT_OF_MEMORY; goto exit; } hr = spQualSet->Put(g_wszPq_CimType, &v, 0); V_VT(&v) = VT_EMPTY; V_BSTR(&v) = NULL; if(FAILED(hr)) { goto exit; }
exit: return hr; }
bool CPusher::NeedToDeleteAssoc( IWbemClassObject* i_pObj) const /*++
Synopsis: Sees if the association i_pObj is already in hashtable. If it is, no point in deleting i_pObj from repository only to recreate it later.
Arguments: [i_pObj] - An IWbemClassObject representation of an assoc Return Value: true if i_pObj not in hashtable false otherwise
--*/ { DBG_ASSERT(i_pObj != NULL); DBG_ASSERT(g_pDynSch != NULL); DBG_ASSERT(m_bInitSuccessful == true);
HRESULT hr = WBEM_S_NO_ERROR; bool bMatch = false; CComVariant vt; LPWSTR wsz;
CComPtr<IWbemQualifierSet> spQualSet;
CHashTable<WMI_ASSOCIATION *>* pHash = g_pDynSch->GetHashAssociations(); WMI_ASSOCIATION* pAssoc;
DBG_ASSERT(pHash != NULL);
//
// Compare the association names
//
hr = i_pObj->Get(g_wszProp_Class, 0, &vt, NULL, NULL); if(FAILED(hr) || vt.vt != VT_BSTR) { goto exit; } hr = pHash->Wmi_GetByKey(vt.bstrVal, &pAssoc); if(FAILED(hr)) { goto exit; } vt.Clear();
//
// This is the only case we care about
//
if(pAssoc->dwExtended != USER_DEFINED_TO_REPOSITORY) { goto exit; }
//
// Compare the left association component
//
hr = i_pObj->GetPropertyQualifierSet( pAssoc->pType->pszLeft, &spQualSet); if(FAILED(hr)) { goto exit; } spQualSet->Get(g_wszPq_CimType, 0, &vt, NULL); spQualSet = NULL; if(FAILED(hr) || vt.vt != VT_BSTR) { goto exit; } if( (wsz = wcschr(vt.bstrVal, L':')) == NULL ) { goto exit; } wsz++; if(_wcsicmp(wsz, pAssoc->pcLeft->pszClassName) != 0) { goto exit; } vt.Clear();
//
// Compare the right association component
//
hr = i_pObj->GetPropertyQualifierSet( pAssoc->pType->pszRight, &spQualSet); if(FAILED(hr)) { goto exit; } spQualSet->Get(g_wszPq_CimType, 0, &vt, NULL); spQualSet = NULL; if(FAILED(hr) || vt.vt != VT_BSTR) { goto exit; } if( (wsz = wcschr(vt.bstrVal, L':')) == NULL ) { goto exit; } wsz++; if(_wcsicmp(wsz, pAssoc->pcRight->pszClassName) != 0) { goto exit; } vt.Clear();
bMatch = true; pAssoc->dwExtended = USER_DEFINED_NOT_TO_REPOSITORY;
exit: return !bMatch; }
HRESULT CPusher::DeleteChildren(LPCWSTR i_wszExtSuperClass) { DBG_ASSERT(i_wszExtSuperClass != NULL); DBG_ASSERT(m_bInitSuccessful == true);
//
// Only can be called from inside Initialize
//
DBG_ASSERT(m_bInitCalled == true); DBG_ASSERT(m_bInitSuccessful == true);
IEnumWbemClassObject*pEnum = NULL; HRESULT hr = WBEM_S_NO_ERROR;
IWbemClassObject* apObj[10] = {0}; ULONG nrObj = 0; ULONG i = 0;
VARIANT v; VariantInit(&v);
CComBSTR bstrExtSuperClass = i_wszExtSuperClass; if(bstrExtSuperClass.m_str == NULL) { hr = WBEM_E_OUT_OF_MEMORY; goto exit; }
hr = m_pNamespace->CreateClassEnum( bstrExtSuperClass, WBEM_FLAG_FORWARD_ONLY, m_pCtx, &pEnum); if(FAILED(hr)) { goto exit; }
hr = pEnum->Next(WBEM_INFINITE, 10, apObj, &nrObj); while(SUCCEEDED(hr) && nrObj > 0) { for(i = 0; i < nrObj; i++) { bool bDelete; if( i_wszExtSuperClass == g_wszExtElementSettingAssocParent || i_wszExtSuperClass == g_wszExtGroupPartAssocParent) { bDelete = NeedToDeleteAssoc(apObj[i]); } else { bDelete = true; } if(bDelete) { hr = apObj[i]->Get(g_wszProp_Class, 0, &v, NULL, NULL); if(FAILED(hr)) { goto exit; }
hr = m_pNamespace->DeleteClass(v.bstrVal, WBEM_FLAG_OWNER_UPDATE, m_pCtx, NULL); if(FAILED(hr)) { goto exit; }
VariantClear(&v); } apObj[i]->Release(); apObj[i] = NULL; } hr = pEnum->Next(WBEM_INFINITE, 10, apObj, &nrObj); } if(FAILED(hr)) { goto exit; }
exit: if(pEnum) { pEnum->Release(); pEnum = NULL; } VariantClear(&v); for(i = 0; i < 10; i++) { if(apObj[i]) { apObj[i]->Release(); } } return hr; }
HRESULT CPusher::GetObject( LPCWSTR i_wszClass, IWbemClassObject** o_ppObj) { DBG_ASSERT(o_ppObj != NULL); DBG_ASSERT(m_bInitCalled == true); DBG_ASSERT(m_bInitSuccessful == true);
HRESULT hr = WBEM_S_NO_ERROR; IWbemClassObject* pObject;
if(i_wszClass == g_wszExtElementParent) { *o_ppObj = m_spBaseElementObject; (*o_ppObj)->AddRef(); } else if(i_wszClass == g_wszExtSettingParent) { *o_ppObj = m_spBaseSettingObject; (*o_ppObj)->AddRef(); } else if(i_wszClass == g_wszExtElementSettingAssocParent) { *o_ppObj = m_spBaseElementSettingObject; (*o_ppObj)->AddRef(); } else if(i_wszClass == g_wszExtGroupPartAssocParent) { *o_ppObj = m_spBaseGroupPartObject; (*o_ppObj)->AddRef(); } else { const CComBSTR sbstrClass = i_wszClass; if(sbstrClass.m_str == NULL) { hr = WBEM_E_OUT_OF_MEMORY; goto exit; } hr = m_pNamespace->GetObject(sbstrClass, 0, m_pCtx, &pObject, NULL); if(FAILED(hr)) { goto exit; } *o_ppObj = pObject; }
exit: return hr; }
|