2025-04-27 07:49:33 -04:00

2204 lines
63 KiB
C++

//***************************************************************************
//
// (c) 1997-2001 by Microsoft Corporation
//
// SINKS.CPP
//
// raymcc 3-Mar-99 Updated for separately threaded proxies
//
//***************************************************************************
#include "precomp.h"
#include <stdio.h>
#include <wbemcore.h>
#include <thrpool.h>
#include <evtlog.h>
#include <oahelp.inl>
#include <genutils.h>
#include <stdarg.h>
#include <autoptr.h>
#define LOWER_AUTH_LEVEL_NOTSET 0xFFFFFFFF
HRESULT LowerAuthLevel( IWbemObjectSink * psink, DWORD* pdwLastAuthnLevel );
static HRESULT ZapWriteOnlyProps(IWbemClassObject *pObj);
extern LONG g_nSinkCount;
extern LONG g_nStdSinkCount;
extern LONG g_nSynchronousSinkCount;
extern LONG g_nProviderSinkCount;
int _Trace(char *pFile, const char *fmt, ...);
//***************************************************************************
//
//***************************************************************************
CBasicObjectSink::CBasicObjectSink()
{
InterlockedIncrement(&g_nSinkCount);
}
CBasicObjectSink::~CBasicObjectSink()
{
InterlockedDecrement(&g_nSinkCount);
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CBasicObjectSink::QueryInterface(REFIID riid, LPVOID* ppvObj)
{
if(riid == CLSID_WbemLocator)
{
// internal test
*ppvObj = NULL;
return S_OK;
}
if(riid == IID_IUnknown || riid == IID_IWbemObjectSink)
{
*ppvObj = (IWbemObjectSink*)this;
AddRef();
return S_OK;
}
else return E_NOINTERFACE;
}
//***************************************************************************
//
//***************************************************************************
ULONG STDMETHODCALLTYPE CObjectSink::AddRef()
{
return InterlockedIncrement(&m_lRef);
}
//***************************************************************************
//
//***************************************************************************
ULONG STDMETHODCALLTYPE CObjectSink::Release()
{
long lRef = InterlockedDecrement(&m_lRef);
if(lRef == 0)
delete this;
return lRef;
}
//***************************************************************************
//
//***************************************************************************
CSynchronousSink::CSynchronousSink(IWbemObjectSink* pProxy) :
m_hEvent(CreateEvent(NULL, FALSE, FALSE, NULL)),
m_str(NULL), m_pErrorObj(NULL), m_hres(WBEM_E_CRITICAL_ERROR)
{
if(pProxy)
{
m_pCurrentProxy = pProxy;
pProxy->AddRef();
}
else
m_pCurrentProxy = NULL;
InterlockedIncrement(&g_nSynchronousSinkCount);
};
//***************************************************************************
//
//***************************************************************************
CSynchronousSink::~CSynchronousSink()
{
if(m_pCurrentProxy)
m_pCurrentProxy->Release();
CloseHandle(m_hEvent);
SysFreeString(m_str);
if(m_pErrorObj)
m_pErrorObj->Release();
InterlockedDecrement(&g_nSynchronousSinkCount);
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CSynchronousSink::Indicate(long lNumObjects,
IWbemClassObject** apObj)
{
CInCritSec ics(&m_cs);
for(long i = 0; i < lNumObjects; i++)
{
m_apObjects.Add(apObj[i]);
}
return WBEM_S_NO_ERROR;
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CSynchronousSink::SetStatus(long lFlags, long lParam,
BSTR strParam, IWbemClassObject* pObjParam)
{
if(lFlags == WBEM_STATUS_PROGRESS)
{
if(m_pCurrentProxy)
return m_pCurrentProxy->SetStatus(lFlags, lParam, strParam, pObjParam);
else
return S_OK;
}
if(lFlags != 0) return WBEM_S_NO_ERROR;
CInCritSec ics(&m_cs);
m_hres = lParam;
m_str = SysAllocString(strParam);
if (m_pErrorObj)
m_pErrorObj->Release();
m_pErrorObj = pObjParam;
if(m_pErrorObj)
m_pErrorObj->AddRef();
SetEvent(m_hEvent);
return WBEM_S_NO_ERROR;
}
//***************************************************************************
//
//***************************************************************************
void CSynchronousSink::Block()
{
if(m_hres != WBEM_E_CRITICAL_ERROR)
return;
CCoreQueue::QueueWaitForSingleObject(m_hEvent, INFINITE);
}
//***************************************************************************
//
//***************************************************************************
void CSynchronousSink::GetStatus(HRESULT* phres, BSTR* pstrParam,
IWbemClassObject** ppErrorObj)
{
CInCritSec ics(&m_cs);
if(phres)
*phres = m_hres;
if(pstrParam)
*pstrParam = SysAllocString(m_str);
if(ppErrorObj)
{
*ppErrorObj = m_pErrorObj;
if(m_pErrorObj)
m_pErrorObj->AddRef();
}
}
HRESULT LowerAuthLevel(IWbemObjectSink * psink, DWORD* pdwLastAuthnLevel )
{
IClientSecurity * pFromSec = NULL;
SCODE sc = psink->QueryInterface(IID_IClientSecurity, (void **) &pFromSec);
if(sc == S_OK)
{
OLECHAR * pPrincipal = NULL;
DWORD dwAuthnSvc, dwAuthzSvc, dwAuthnLevel, dwImpLevel, dwCapabilities;
sc = pFromSec->QueryBlanket(psink, &dwAuthnSvc, &dwAuthzSvc,
&pPrincipal,
&dwAuthnLevel, &dwImpLevel,
NULL, &dwCapabilities);
// If we have never retrieved the authentication level before, then we
// should record what it currently is
if ( LOWER_AUTH_LEVEL_NOTSET == *pdwLastAuthnLevel )
{
*pdwLastAuthnLevel = dwAuthnLevel;
}
if (FAILED(sc))
return sc;
if(*pdwLastAuthnLevel == RPC_C_AUTHN_LEVEL_NONE)
return WBEM_E_FAILED;
if(*pdwLastAuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
*pdwLastAuthnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
else
(*pdwLastAuthnLevel)--; // normal case is to try one lower
sc = pFromSec->SetBlanket(psink, dwAuthnSvc, dwAuthzSvc,
pPrincipal,
*pdwLastAuthnLevel, dwImpLevel,
NULL, dwCapabilities);
if(pPrincipal)
CoTaskMemFree(pPrincipal);
pFromSec->Release();
}
return sc;
}
//***************************************************************************
//
//***************************************************************************
CForwardingSink::CForwardingSink(CBasicObjectSink* pDest, long lRef)
: CObjectSink(lRef),
m_pDestIndicate(pDest->GetIndicateSink()),
m_pDestStatus(pDest->GetStatusSink()),
m_pDest(pDest)
{
m_pDestIndicate->AddRef();
m_pDestStatus->AddRef();
m_pDest->AddRef();
}
//***************************************************************************
//
//***************************************************************************
CForwardingSink::~CForwardingSink()
{
if(m_pDestIndicate)
m_pDestIndicate->Release();
if(m_pDestStatus)
m_pDestStatus->Release();
if(m_pDest)
m_pDest->Release();
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CForwardingSink::Indicate(long lObjectCount,
IWbemClassObject** pObjArray)
{
return m_pDestIndicate->Indicate(lObjectCount, pObjArray);
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CForwardingSink::SetStatus(long lFlags, long lParam,
BSTR strParam, IWbemClassObject* pObjParam)
{
return m_pDestStatus->SetStatus(lFlags, lParam, strParam, pObjParam);
}
//***************************************************************************
//
//***************************************************************************
CCombiningSink::CCombiningSink(CBasicObjectSink* pDest, HRESULT hresToIgnore)
: CForwardingSink(pDest, 0), m_hresToIgnore(hresToIgnore),
m_hres(WBEM_S_NO_ERROR), m_pErrorObj(NULL), m_strParam(NULL)
{
}
//***************************************************************************
//
//***************************************************************************
CCombiningSink::~CCombiningSink()
{
// Time to call SetStatus on the destination
// =========================================
m_pDestStatus->SetStatus(0, m_hres,
(SUCCEEDED(m_hres)?m_strParam:NULL),
(SUCCEEDED(m_hres)?NULL:m_pErrorObj)
);
if(m_pErrorObj)
m_pErrorObj->Release();
SysFreeString(m_strParam);
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CCombiningSink::SetStatus(long lFlags, long lParam, BSTR strParam,
IWbemClassObject* pObjParam)
{
if(lFlags != 0)
return m_pDestStatus->SetStatus(lFlags, lParam, strParam, pObjParam);
// An error occurred. For now, only store one
// ==========================================
if(strParam)
{
SysFreeString(m_strParam);
m_strParam = SysAllocString(strParam);
}
CInCritSec ics(&m_cs);
if(SUCCEEDED(m_hres) || (m_pErrorObj == NULL && pObjParam != NULL))
{
// This error needs to be recorded
// ===============================
if(FAILED(lParam))
{
// Record the error code, unless it is to be ignored
// =================================================
if(lParam != m_hresToIgnore)
{
m_hres = lParam;
}
// Record the error object anyway
// ==============================
if(m_pErrorObj)
m_pErrorObj->Release();
m_pErrorObj = pObjParam;
if(m_pErrorObj)
m_pErrorObj->AddRef();
}
else
{
if(lParam != m_hresToIgnore)
{
m_hres = lParam;
}
}
}
return WBEM_S_NO_ERROR;
}
//***************************************************************************
//
//***************************************************************************
CAnySuccessSink::~CAnySuccessSink()
{
// If no real success occurred, report a failure
// =============================================
if(!m_bSuccess && SUCCEEDED(m_hres))
{
// We must report a failure since there were no successes, but there
// were no real failures either, so we must create an error code.
// =================================================================
if(m_hresIgnored == 0)
m_hres = m_hresNotError1;
else
m_hres = m_hresIgnored;
}
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CAnySuccessSink::SetStatus(long lFlags, long lParam, BSTR strParam,
IWbemClassObject* pObjParam)
{
if(lFlags == 0)
{
if(SUCCEEDED(lParam))
m_bSuccess = TRUE;
else if(lParam == m_hresNotError1 && m_hresIgnored == 0)
{
m_hresIgnored = m_hresNotError1;
lParam = WBEM_S_NO_ERROR;
}
else if(lParam == m_hresNotError2)
{
m_hresIgnored = m_hresNotError2;
lParam = WBEM_S_NO_ERROR;
}
}
return CCombiningSink::SetStatus(lFlags, lParam, strParam, pObjParam);
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP COperationErrorSink::SetStatus(long lFlags, long lParam,
BSTR strParam, IWbemClassObject* pObjParam)
{
if(lFlags == 0 && FAILED(lParam))
{
HRESULT hres = WBEM_S_NO_ERROR;
IWbemClassObject* pErrorObj = NULL;
bool bErr = false;
try
{
CErrorObject Error(pObjParam);
Error.SetOperation(m_wsOperation);
Error.SetParamInformation(m_wsParameter);
Error.SetProviderName(m_wsProviderName);
pErrorObj = Error.GetObject();
}
// If an exception occurs, send the error to the client and
// return an error from the call.
catch ( CX_MemoryException )
{
lParam = WBEM_E_OUT_OF_MEMORY;
bErr = true;
}
catch(...)
{
ExceptionCounter c;
lParam = WBEM_E_CRITICAL_ERROR;
bErr = true;
}
hres = m_pDestStatus->SetStatus(lFlags, lParam, strParam, pErrorObj);
if ( NULL != pErrorObj )
{
pErrorObj->Release();
}
if ( bErr )
{
hres = lParam;
}
return hres;
}
else if(m_bFinal &&
lFlags != WBEM_STATUS_COMPLETE && lFlags != WBEM_STATUS_PROGRESS)
{
DEBUGTRACE((LOG_WBEMCORE, "Ignoring internal SetStatus call to the "
"client: 0x%X 0x%X %S\n", lFlags, lParam, strParam));
return WBEM_S_FALSE;
}
else if(lFlags == 0 && strParam &&
!m_wsOperation.EqualNoCase(L"PutInstance"))
{
ERRORTRACE((LOG_WBEMCORE, "Provider used strParam in SetStatus "
"outside of PutInstance! Actual operation was <%S>, string was <%S>. Ignoring\n", (const wchar_t*)m_wsOperation, strParam));
return m_pDestStatus->SetStatus(lFlags, lParam, NULL, pObjParam);
}
else
{
return m_pDestStatus->SetStatus(lFlags, lParam, strParam, pObjParam);
}
}
//***************************************************************************
//
//***************************************************************************
void COperationErrorSink::SetProviderName(LPCWSTR wszName)
{
m_wsProviderName = wszName;
}
//***************************************************************************
//
//***************************************************************************
void COperationErrorSink::SetParameterInfo(LPCWSTR wszParam)
{
m_wsParameter = wszParam;
}
//***************************************************************************
//
//***************************************************************************
CDecoratingSink::CDecoratingSink(CBasicObjectSink* pDest,
CWbemNamespace* pNamespace)
: CForwardingSink(pDest, 0), m_pNamespace(pNamespace)
{
m_pNamespace->AddRef();
}
//***************************************************************************
//
//***************************************************************************
CDecoratingSink::~CDecoratingSink()
{
m_pNamespace->Release();
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CDecoratingSink::Indicate(long lNumObjects,
IWbemClassObject** apObjects)
{
// Clone the indicated objects before decorating
HRESULT hres = WBEM_S_NO_ERROR;
if ( lNumObjects > 0 )
{
// We will optimize for indicates of a single object (which will probably
// be the most likely type of indicate. In which case we won't allocate any
// memory for the cloned object array, and rather will just use a stack variable.
IWbemClassObject* pClonedObject = NULL;
IWbemClassObject** apClonedObjects = &pClonedObject;
if ( lNumObjects > 1 )
{
try
{
// Allocate an array and zero it out
apClonedObjects = new IWbemClassObject*[lNumObjects];
if ( NULL != apClonedObjects )
{
ZeroMemory( apClonedObjects, lNumObjects * sizeof(IWbemClassObject*) );
}
else
{
hres = WBEM_E_OUT_OF_MEMORY;
}
}
catch( CX_MemoryException )
{
hres = WBEM_E_OUT_OF_MEMORY;
}
catch(...)
{
ExceptionCounter c;
hres = WBEM_E_FAILED;
}
}
if ( SUCCEEDED( hres ) )
{
// Clone the objects into the array (error out if this fails)
for ( long lCtr = 0; SUCCEEDED( hres ) && lCtr < lNumObjects; lCtr++ )
{
if ( NULL != apObjects[lCtr] )
{
hres = apObjects[lCtr]->Clone( &apClonedObjects[lCtr] );
}
else
{
apClonedObjects[lCtr] = NULL;
}
}
// Now decorate the cloned objects and indicate them
if ( SUCCEEDED( hres ) )
{
for(int i = 0; i < lNumObjects; i++)
{
m_pNamespace->DecorateObject(apClonedObjects[i]);
}
hres = m_pDestIndicate->Indicate(lNumObjects, apClonedObjects);
}
// Clean up the array
for ( lCtr = 0; lCtr < lNumObjects; lCtr++ )
{
// Check for NULLs
if ( NULL != apClonedObjects[lCtr] )
{
apClonedObjects[lCtr]->Release();
}
}
// If we actually allocated memory, we need to clean it up here
if ( apClonedObjects != &pClonedObject )
{
delete [] apClonedObjects;
}
} // IF we allocated our block appropriately
}
else
{
hres = m_pDestIndicate->Indicate(lNumObjects, apObjects);
}
return hres;
}
//***************************************************************************
//
//***************************************************************************
CSingleMergingSink::~CSingleMergingSink()
{
if(SUCCEEDED(m_hres))
{
if(m_pResult == NULL)
{
// Nobody succeeded, but nobody failed either. Not found
// =====================================================
m_hres = WBEM_E_NOT_FOUND;
}
else if(m_pResult->InheritsFrom(m_wsTargetClass) == S_OK)
{
m_pDestIndicate->Indicate(1, &m_pResult);
}
else
{
// Found somewhere, but not in this class
// ======================================
m_hres = WBEM_E_NOT_FOUND;
}
}
if(m_pResult)
m_pResult->Release();
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CSingleMergingSink::Indicate(long lNumObjects,
IWbemClassObject** apObjects)
{
CInCritSec ics(&m_cs);
if(lNumObjects != 1)
{
ERRORTRACE((LOG_WBEMCORE, "Provider gave %d objects for GetObject!\n",
lNumObjects));
return WBEM_S_NO_ERROR;
}
if(m_pResult == NULL)
{
apObjects[0]->Clone(&m_pResult);
return WBEM_S_NO_ERROR;
}
CVar vName;
((CWbemInstance*)m_pResult)->GetClassName(&vName);
if(apObjects[0]->InheritsFrom(vName.GetLPWSTR()) == S_OK)
{
IWbemClassObject* pClone;
apObjects[0]->Clone(&pClone);
HRESULT hres = CWbemInstance::AsymmetricMerge((CWbemInstance*)m_pResult,
(CWbemInstance*)pClone);
if(FAILED(hres))
{
ERRORTRACE((LOG_WBEMCORE, "Failed to merge instances!!\n"));
pClone->Release();
}
else
{
m_pResult->Release();
m_pResult = pClone; // already AddRefed
}
}
else
{
HRESULT hres = CWbemInstance::AsymmetricMerge(
(CWbemInstance*)apObjects[0], (CWbemInstance*)m_pResult);
if(FAILED(hres))
{
ERRORTRACE((LOG_WBEMCORE, "Failed to merge instances!!\n"));
}
}
return WBEM_S_NO_ERROR;
}
//***************************************************************************
//
//***************************************************************************
CLocaleMergingSink::CLocaleMergingSink(CBasicObjectSink *pDest, LPCWSTR wszLocale, LPCWSTR pNamespace)
: CCombiningSink(pDest, WBEM_S_NO_ERROR),
m_wsLocale(wszLocale),
m_pPrimaryNs(NULL),
m_pPrimarySession(NULL),
m_pPrimaryDriver(NULL),
m_pDefaultNs(NULL),
m_pDefaultSession(NULL),
m_pDefaultDriver(NULL)
{
GetDbPtr(pNamespace);
}
CLocaleMergingSink::~CLocaleMergingSink()
{
releaseNS();
}
//***************************************************************************
//
//***************************************************************************
HRESULT CLocaleMergingSink::LocalizeQualifiers(bool bInstance, bool bParentLocalized,
IWbemQualifierSet *pBase, IWbemQualifierSet *pLocalized, bool &bChg)
{
HRESULT hrInner;
HRESULT hr = WBEM_S_NO_ERROR;
pLocalized->BeginEnumeration(0);
BSTR strName = NULL;
VARIANT vVal;
VariantInit(&vVal);
long lFlavor;
while(pLocalized->Next(0, &strName, &vVal, &lFlavor) == S_OK)
{
// Ignore if this is an instance.
if (bInstance && !(lFlavor & WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE))
{
VariantClear(&vVal);
SysFreeString(strName);
continue;
}
if (!_wcsicmp(strName, L"amendment") ||
!_wcsicmp(strName, L"key") ||
!_wcsicmp(strName, L"singleton") ||
!_wcsicmp(strName, L"dynamic") ||
!_wcsicmp(strName, L"indexed") ||
!_wcsicmp(strName, L"cimtype") ||
!_wcsicmp(strName, L"static") ||
!_wcsicmp(strName, L"implemented") ||
!_wcsicmp(strName, L"abstract"))
{
VariantClear(&vVal);
SysFreeString(strName);
continue;
}
// If this is not a propagated qualifier,
// ignore it. (Bug #45799)
// =====================================
if (bParentLocalized &&
!(lFlavor & WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS))
{
VariantClear(&vVal);
SysFreeString(strName);
continue;
}
// Now, we need to test for this in the other
// class.
// The only localized qualifiers that do not override the
// default are where only parent qualifiers exist, but the
// child has overriden its own parent.
// =======================================================
VARIANT vBasicVal;
VariantInit(&vBasicVal);
long lBasicFlavor;
hrInner = pBase->Get(strName, 0, &vBasicVal, &lBasicFlavor);
if (hrInner != WBEM_E_NOT_FOUND)
{
if (bParentLocalized && // If there is no localized copy of this class
(lBasicFlavor & WBEM_FLAVOR_OVERRIDABLE) && // .. and this is an overridable qualifier
(lBasicFlavor & WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS) && // and this is propogated
(lBasicFlavor & WBEM_FLAVOR_ORIGIN_LOCAL)) // .. and this was actualy overridden
{
VariantClear(&vVal); // .. DON'T DO IT.
VariantClear(&vBasicVal);
SysFreeString(strName);
continue;
}
if (bParentLocalized &&
!(lBasicFlavor & WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS))
{
VariantClear(&vVal);
VariantClear(&vBasicVal);
SysFreeString(strName);
continue;
}
}
pBase->Put(strName, &vVal, (lFlavor&~WBEM_FLAVOR_ORIGIN_PROPAGATED) | WBEM_FLAVOR_AMENDED);
bChg = true;
VariantClear(&vVal);
VariantClear(&vBasicVal);
SysFreeString(strName);
}
return hr;
}
//***************************************************************************
//
//***************************************************************************
HRESULT CLocaleMergingSink::LocalizeProperties(bool bInstance, bool bParentLocalized, IWbemClassObject *pOriginal,
IWbemClassObject *pLocalized, bool &bChg)
{
HRESULT hr = WBEM_S_NO_ERROR;
pLocalized->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
BSTR strPropName;
LONG lLong;
CIMTYPE ct;
VARIANT vNewVal;
while(pLocalized->Next(0, &strPropName, &vNewVal, &ct, &lLong) == S_OK)
{
IWbemQualifierSet *pLocalizedQs = NULL, *pThisQs = NULL;
VARIANT vBasicVal;
VariantInit(&vBasicVal);
if (FAILED(pLocalized->GetPropertyQualifierSet(strPropName,&pLocalizedQs)))
{
SysFreeString(strPropName);
VariantClear(&vNewVal);
continue;
}
CReleaseMe rm1(pLocalizedQs);
if (FAILED(pOriginal->GetPropertyQualifierSet(strPropName, &pThisQs)))
{
SysFreeString(strPropName);
VariantClear(&vNewVal);
continue;
}
CReleaseMe rm2(pThisQs);
hr = LocalizeQualifiers(bInstance, bParentLocalized, pThisQs, pLocalizedQs, bChg);
if (FAILED(hr))
{
SysFreeString(strPropName);
VariantClear(&vNewVal);
continue;
}
SysFreeString(strPropName);
VariantClear(&vNewVal);
}
pLocalized->EndEnumeration();
return hr;
}
//***************************************************************************
//
//***************************************************************************
// This function sets up the pointer to the localized namespace.
void CLocaleMergingSink::GetDbPtr(const wchar_t * name_space)
{
if (m_pThisNamespace.EqualNoCase(name_space))
return;
releaseNS();
m_pThisNamespace = name_space;
if (wcslen(name_space) == 0)
return;
WString sNsName;
sNsName = m_pThisNamespace;
sNsName += L"\\";
sNsName += m_wsLocale;
IWmiDbSession *pTempSession = NULL;
HRESULT hRes = CRepository::GetDefaultSession(&pTempSession);
if (FAILED(hRes))
return;
hRes = CRepository::OpenScope(pTempSession, sNsName, 0, &m_pPrimaryDriver, &m_pPrimarySession, 0, &m_pPrimaryNs);
if (_wcsicmp(m_wsLocale, L"ms_409"))
{
sNsName = m_pThisNamespace;
sNsName += L"\\ms_409";
hRes = CRepository::OpenScope(pTempSession, sNsName, 0, &m_pDefaultDriver, &m_pDefaultSession, 0, &m_pDefaultNs);
}
pTempSession->Release();
}
void CLocaleMergingSink::releaseNS(void)
{
ReleaseIfNotNULL(m_pPrimarySession);
ReleaseIfNotNULL(m_pDefaultSession);
ReleaseIfNotNULL(m_pPrimaryNs);
ReleaseIfNotNULL(m_pPrimaryDriver);
ReleaseIfNotNULL(m_pDefaultNs);
ReleaseIfNotNULL(m_pDefaultDriver);
m_pPrimarySession = 0;
m_pDefaultSession = 0;
m_pPrimaryNs = 0;
m_pPrimaryDriver = 0;
m_pDefaultNs = 0;
m_pDefaultDriver = 0;
};
bool CLocaleMergingSink::hasLocale(const wchar_t * name_space)
{
GetDbPtr(name_space) ;
return (m_pPrimaryNs || m_pDefaultNs);
};
//***************************************************************************
//
//***************************************************************************
// Do the work.
STDMETHODIMP CLocaleMergingSink::Indicate(long lNumObjects,
IWbemClassObject** apObjects)
{
CInCritSec ics(&m_cs);
IWbemQualifierSet *pLocalizedQs = NULL, *pThisQs = NULL;
bool bParentLocalized = false;
bool bInstance = false;
HRESULT hr = WBEM_S_NO_ERROR;
HRESULT hRes;
for (int i = 0; i < lNumObjects; i++)
{
CWbemObject *pResult = (CWbemObject *)apObjects[i];
CVar vServer;
if (FAILED(pResult->GetProperty(L"__SERVER", &vServer)) || vServer.IsNull())
continue;
if (_wcsicmp(LPWSTR(vServer), ConfigMgr::GetMachineName())!=0)
continue;
VARIANT name_space;
VariantInit(&name_space);
CClearMe cm(&name_space);
HRESULT hres = pResult->Get(L"__NAMESPACE", 0, &name_space, NULL, NULL);
if (FAILED(hres) || hasLocale (V_BSTR(&name_space)) == false)
continue;
if (pResult->IsInstance())
bInstance = true;
CVar vName, vDeriv;
if (FAILED(pResult->GetClassName(&vName)))
continue;
WString wKey;
int nRes = 0;
bool bChg = false;
// Does this instance exist in the localized namespace?
// Does this class exist in the localized namespace?
// If not, loop through all the parents until we
// run out or we have a hit.
// =================================================
CWbemObject *pClassDef = NULL;
if (wcslen(vName.GetLPWSTR()) > 0)
{
WString sName = vName.GetLPWSTR();
hRes = WBEM_E_NOT_FOUND;
if (m_pPrimaryNs)
hRes = CRepository::GetObject(m_pPrimarySession, m_pPrimaryNs, sName, 0, (IWbemClassObject **) &pClassDef);
if (FAILED(hRes) && m_pDefaultNs)
hRes = CRepository::GetObject(m_pDefaultSession, m_pDefaultNs, sName, 0, (IWbemClassObject **) &pClassDef);
if (hRes == WBEM_E_NOT_FOUND)
{
bParentLocalized = TRUE;
pResult->GetDerivation(&vDeriv);
CVarVector *pvTemp = vDeriv.GetVarVector();
for (int j = 0; j < pvTemp->Size(); j++)
{
CVar vParentName = pvTemp->GetAt(j);
WString sParentName = vParentName.GetLPWSTR();
hRes = WBEM_E_NOT_FOUND;
if (m_pPrimaryNs)
hRes = CRepository::GetObject(m_pPrimarySession, m_pPrimaryNs, sParentName, 0, (IWbemClassObject **) &pClassDef);
if (FAILED(hRes) && m_pDefaultNs)
hRes = CRepository::GetObject(m_pDefaultSession, m_pDefaultNs, sParentName, 0, (IWbemClassObject **) &pClassDef);
}
}
}
if (pClassDef == NULL)
{
nRes = WBEM_S_NO_ERROR;
continue;
}
CReleaseMe rm11((IWbemClassObject*)pClassDef);
// At this point, we have the localized copy, and are
// ready to combine qualifiers. Start with class qualifiers.
// ============================================================
if (FAILED(pClassDef->GetQualifierSet(&pLocalizedQs)))
continue;
if (FAILED(pResult->GetQualifierSet(&pThisQs)))
{
pLocalizedQs->Release();
continue;
}
hr = LocalizeQualifiers(bInstance, bParentLocalized, pThisQs, pLocalizedQs, bChg);
pLocalizedQs->EndEnumeration();
pLocalizedQs->Release();
pThisQs->Release();
if (FAILED(hr))
break;
hr = LocalizeProperties(bInstance, bParentLocalized, pResult, pClassDef, bChg);
// Methods.
// Putting a method cancels enumeration, so we have to enumerate first.
IWbemClassObject *pLIn = NULL, *pLOut = NULL;
IWbemClassObject *pOIn = NULL, *pOOut = NULL;
BSTR bstrMethodName = NULL ;
int iPos = 0;
pClassDef->BeginMethodEnumeration(0);
while ( pClassDef->NextMethod(0, &bstrMethodName, 0, 0) == S_OK )
{
pLIn = NULL;
pOIn = NULL;
pLOut = NULL;
pOOut = NULL;
pClassDef->GetMethod(bstrMethodName, 0, &pLIn, &pLOut);
hr = pResult->GetMethod(bstrMethodName, 0, &pOIn, &pOOut);
CSysFreeMe fm(bstrMethodName);
CReleaseMe rm0(pLIn);
CReleaseMe rm1(pOIn);
CReleaseMe rm2(pLOut);
CReleaseMe rm3(pOOut);
// METHOD IN PARAMETERS
if (pLIn)
if (pOIn)
hr = LocalizeProperties(bInstance, bParentLocalized, pOIn, pLIn, bChg);
if (pLOut)
if (pOOut)
hr = LocalizeProperties(bInstance, bParentLocalized, pOOut, pLOut, bChg);
// METHOD QUALIFIERS
hr = pResult->GetMethodQualifierSet(bstrMethodName, &pThisQs);
if (FAILED(hr))
{
continue;
}
hr = pClassDef->GetMethodQualifierSet(bstrMethodName, &pLocalizedQs);
if (FAILED(hr))
{
pThisQs->Release();
continue;
}
hr = LocalizeQualifiers(bInstance, bParentLocalized, pThisQs, pLocalizedQs, bChg);
pResult->PutMethod(bstrMethodName, 0, pOIn, pOOut);
pThisQs->Release();
pLocalizedQs->Release();
}
pClassDef->EndMethodEnumeration();
if (bChg)
pResult->SetLocalized(true);
}
for(int i = 0; i < lNumObjects; i++)
{
CWbemObject *pResult = (CWbemObject *)apObjects[i];
if (FAILED(pResult->ValidateObject(WMIOBJECT_VALIDATEOBJECT_FLAG_FORCE)))
DebugBreak();
}
m_pDestIndicate->Indicate(lNumObjects, apObjects);
return WBEM_S_NO_ERROR;
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CCountedSink::Indicate(long lNumObjects,
IWbemClassObject** apObjects)
{
if(lNumObjects != 1)
return WBEM_E_UNEXPECTED;
DWORD dwNewSent = (DWORD)InterlockedIncrement((LONG*)&m_dwSent);
if(dwNewSent > m_dwMax)
return WBEM_E_UNEXPECTED;
m_pDestIndicate->Indicate(1, apObjects);
if(dwNewSent == m_dwMax)
{
m_pDestStatus->SetStatus(0, WBEM_S_NO_ERROR, NULL, NULL);
return WBEM_S_FALSE;
}
else return WBEM_S_NO_ERROR;
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CCountedSink::SetStatus(long lFlags, long lParam,
BSTR strParam, IWbemClassObject* pObjParam)
{
// If SetStatus is 0, indicating that the enum is finished, but we
// didn't send back the requested number of objects, we should
// SetStatus to WBEM_S_FALSE.
if ( WBEM_S_NO_ERROR == lParam )
{
if ( m_dwSent != m_dwMax )
{
lParam = WBEM_S_FALSE;
}
}
return m_pDestStatus->SetStatus( lFlags, lParam, strParam, pObjParam );
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CFilteringSink::Indicate(long lObjectCount,
IWbemClassObject** apObjects)
{
try
{
// Allocate new array
// ==================
IWbemClassObject** apNewArray = new IWbemClassObject*[lObjectCount];
wmilib::auto_buffer<IWbemClassObject*> rm_(apNewArray);
if (!apNewArray)
return WBEM_E_OUT_OF_MEMORY;
long lNewIndex = 0;
for(int i = 0; i < lObjectCount; i++)
{
if(Test((CWbemObject*)apObjects[i]))
{
apNewArray[lNewIndex++] = apObjects[i];
}
}
HRESULT hres = WBEM_S_NO_ERROR;
if(lNewIndex > 0)
{
hres = m_pDestIndicate->Indicate(lNewIndex, apNewArray);
}
return hres;
}
catch (CX_MemoryException &) // becasue Test uses CStack that throws
{
return WBEM_E_OUT_OF_MEMORY;
}
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CErrorChangingSink::SetStatus(long lFlags, long lParam,
BSTR strParam, IWbemClassObject* pObjParam)
{
if(lFlags == 0 && lParam == m_hresFrom)
return m_pDestStatus->SetStatus(0, m_hresTo, NULL, NULL);
else
return m_pDestStatus->SetStatus(lFlags, lParam, strParam, pObjParam);
}
//***************************************************************************
//
//***************************************************************************
CNoDuplicatesSink::CNoDuplicatesSink(CBasicObjectSink* pDest)
: CFilteringSink(pDest), m_strDupClass(NULL)
{
}
//***************************************************************************
//
//***************************************************************************
CNoDuplicatesSink::~CNoDuplicatesSink()
{
SysFreeString(m_strDupClass);
}
//***************************************************************************
//
//***************************************************************************
BOOL CNoDuplicatesSink::Test(CWbemObject* pObj)
{
CInCritSec ics(&m_cs);
// Get the path
// ============
CVar vPath;
if(FAILED(pObj->GetPath(&vPath)) || vPath.IsNull()) return FALSE;
if(m_mapPaths.find(vPath.GetLPWSTR()) == m_mapPaths.end())
{
m_mapPaths[vPath.GetLPWSTR()] = true;
return TRUE;
}
else
{
// Duplicate!
// ==========
ERRORTRACE((LOG_WBEMCORE, "Duplicate objects returned with path %S\n",
vPath.GetLPWSTR()));
ConfigMgr::GetEventLog()->Report(EVENTLOG_ERROR_TYPE,
WBEM_MC_DUPLICATE_OBJECTS, vPath.GetLPWSTR());
if(m_strDupClass == NULL)
{
m_strDupClass = SysAllocString(vPath.GetLPWSTR());
}
return FALSE;
}
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CNoDuplicatesSink::SetStatus(long lFlags, long lParam,
BSTR strParam, IWbemClassObject* pObjParam)
{
if(lFlags == WBEM_STATUS_COMPLETE && lParam == WBEM_S_NO_ERROR &&
m_strDupClass != NULL)
{
// Success is being reported, but we have seen duplications
// ========================================================
return CFilteringSink::SetStatus(lFlags, WBEM_S_DUPLICATE_OBJECTS,
m_strDupClass, pObjParam);
}
else
{
return CFilteringSink::SetStatus(lFlags, lParam, strParam, pObjParam);
}
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CHandleClassProvErrorsSink::SetStatus(long lFlags, long lParam,
BSTR strParam, IWbemClassObject* pObjParam)
{
if(lFlags == WBEM_STATUS_COMPLETE && FAILED(lParam) &&
lParam != WBEM_E_NOT_FOUND)
{
// Log an error into the event log
// ===============================
ERRORTRACE((LOG_WBEMCORE,
"Class provider '%S' installed in namespace '%S' failed to enumerate classes, "
"returning error code 0x%lx. Operations will continue as if the class provider "
"had no classes. This provider-specific error condition needs to be corrected "
"before this class provider can contribute to this namespace.\n",
(LPWSTR)m_wsProvider, (LPWSTR) m_wsNamespace, lParam));
lParam = WBEM_E_NOT_FOUND;
}
return CForwardingSink::SetStatus(lFlags, lParam, strParam, pObjParam);
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CSuccessSuppressionSink::SetStatus(long lFlags, long lParam,
BSTR strParam, IWbemClassObject* pObjParam)
{
if(lFlags != WBEM_STATUS_COMPLETE ||
(FAILED(lParam) && lParam != m_hresNotError1 &&
lParam != m_hresNotError2))
{
return CForwardingSink::SetStatus(lFlags, lParam, strParam, pObjParam);
}
else
{
return WBEM_S_NO_ERROR;
}
}
//***************************************************************************
//
//***************************************************************************
#ifdef OLD
CWrapperMap::CWrapperMap()
{
}
//***************************************************************************
//
//***************************************************************************
CWrapperMap::~CWrapperMap()
{
}
//***************************************************************************
//
//***************************************************************************
void CWrapperMap::Map(const REQUESTID& id, IWbemObjectSink* pSink,
CWrapperSink* pWrapper)
{
CInCritSec ics(&m_cs);
m_mapSink.insert(TValueType(pSink, id));
m_mapGuid[id] = pWrapper;
}
//***************************************************************************
//
//***************************************************************************
RELEASE_ME CWrapperSink* CWrapperMap::FindWrapper(const GUID& id)
{
CInCritSec ics(&m_cs);
CWrapperSink* pWrapper = NULL;
if(m_mapGuid.find(id) != m_mapGuid.end())
{
pWrapper = m_mapGuid[id];
pWrapper->AddRef();
}
return pWrapper;
}
//***************************************************************************
//
//***************************************************************************
HRESULT CWrapperMap::FindWrappers(IWbemObjectSink* pSink,
CRefedPointerArray<CWrapperSink>& apWrappers)
{
CInCritSec ics(&m_cs);
TIterator it = m_mapSink.find(pSink);
while(it != m_mapSink.end() && it->first == pSink)
{
GUID& rguid = it->second;
apWrappers.Add(m_mapGuid[rguid]);
it++;
}
return WBEM_S_NO_ERROR;
}
//***************************************************************************
//
//***************************************************************************
void CWrapperMap::Unmap(const REQUESTID& id, IWbemObjectSink* pSink)
{
CInCritSec ics(&m_cs);
m_mapGuid.erase(id);
TIterator it = m_mapSink.find(pSink);
while(it != m_mapSink.end() && it->first == pSink)
{
if(it->second == id)
{
m_mapSink.erase(it);
return;
}
it++;
}
ERRORTRACE((LOG_WBEMCORE, "Unable to unmap a sink --- not found\n"));
}
#endif
//***************************************************************************
//
//***************************************************************************
CDynPropsSink::CDynPropsSink(CBasicObjectSink* pDest, CWbemNamespace * pNs, long lRef) : CForwardingSink(pDest, lRef)
{
m_pNs = pNs;
if(m_pNs)
m_pNs->AddRef();
}
//***************************************************************************
//
//***************************************************************************
CDynPropsSink::~CDynPropsSink()
{
//
// Removing the impersonation at this point. There is no need to impersonate
// at this point since the sink below it is the CCombiningSink eventually
// ending up at the finalizer which correctly makes the calls to the client
//
//CAutoImpersonate ai;
//
// Send all the cached entries
DWORD dwCacheSize = m_UnsentCache.GetSize();
for(DWORD dwCnt = 0; dwCnt < dwCacheSize; dwCnt++)
{
IWbemClassObject* pObj = m_UnsentCache[dwCnt];
if(m_pNs)
m_pNs->GetOrPutDynProps((CWbemObject *)pObj, CWbemNamespace::GET);
m_pDestIndicate->Indicate(1, &pObj);
}
if(m_pNs)
m_pNs->Release();
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CDynPropsSink::Indicate(long lObjectCount,
IWbemClassObject** pObjArray)
{
// If there are no dyn props then immediately do the indicate
IWbemClassObject** apNewArray = new IWbemClassObject*[lObjectCount];
if (!apNewArray)
return WBEM_E_OUT_OF_MEMORY;
CVar vDynTest;
HRESULT hRes = S_OK;
long lIndex = 0 ;
for(long lCnt = 0; lCnt < lObjectCount; lCnt++)
{
CWbemObject *pWbemObj = (CWbemObject *)pObjArray[lCnt];
HRESULT hres = pWbemObj->GetQualifier(L"DYNPROPS", &vDynTest);
if (hres == S_OK && vDynTest.GetBool() == VARIANT_TRUE)
{
hRes = m_UnsentCache.Add(pWbemObj);
}
else
{
apNewArray[lIndex++] = pObjArray[lCnt] ;
}
}
if ( lIndex )
{
CAutoImpersonate ai;
hRes = m_pDestIndicate->Indicate(lIndex, apNewArray);
if ( FAILED ( ai.Impersonate ( ) ) )
{
hRes = WBEM_E_FAILED ;
}
}
delete [] apNewArray ;
return hRes;
}
//***************************************************************************
//
//***************************************************************************
STDMETHODIMP CMethodSink::Indicate(long lObjectCount,
IWbemClassObject** pObjArray)
{
if(lObjectCount == 1 && m_pRes == NULL)
{
pObjArray[0]->Clone(&m_pRes);
}
return S_OK;
}
STDMETHODIMP CMethodSink::SetStatus(long lFlags, long lParam,
BSTR strParam, IWbemClassObject* pObjParam)
{
if(lParam == S_OK && m_pRes)
{
m_pDestIndicate->Indicate(1, &m_pRes);
}
if(m_pRes)
m_pRes->Release();
return CForwardingSink::SetStatus(lFlags, lParam, strParam, pObjParam);
}
//***************************************************************************
//
// ZapWriteOnlyProps
//
// Removes write-only properties from an object.
// Precondition: Object has been tested for presence of "HasWriteOnlyProps"
// on the object itself.
//
//***************************************************************************
static HRESULT ZapWriteOnlyProps(IWbemClassObject *pObj)
{
VARIANT v;
VariantInit(&v);
V_VT(&v) = VT_NULL;
SAFEARRAY *pNames = 0;
pObj->GetNames(L"WriteOnly", WBEM_FLAG_ONLY_IF_TRUE, 0, &pNames);
LONG lUpper;
SafeArrayGetUBound(pNames, 1, &lUpper);
for (long i = 0; i <= lUpper; i++)
{
BSTR strName = 0;
SafeArrayGetElement(pNames, &i, &strName);
pObj->Put(strName, 0, &v, 0);
}
SafeArrayDestroy(pNames);
return WBEM_S_NO_ERROR;
}
//***************************************************************************
//
//***************************************************************************
//
CStdSink::CStdSink(IWbemObjectSink *pRealDest)
{
m_pDest = pRealDest;
m_hRes = 0;
m_bCancelForwarded = FALSE;
m_lRefCount = 0L;
if ( NULL != m_pDest )
m_pDest->AddRef();
InterlockedIncrement(&g_nStdSinkCount);
}
//***************************************************************************
//
//***************************************************************************
//
CStdSink::~CStdSink()
{
if ( NULL != m_pDest )
m_pDest->Release();
InterlockedDecrement(&g_nStdSinkCount);
}
//***************************************************************************
//
//***************************************************************************
//
HRESULT CStdSink::Cancel()
{
HRESULT hResTmp;
m_hRes = WBEM_E_CALL_CANCELLED;
if (m_bCancelForwarded)
return m_hRes;
try
{
hResTmp = m_pDest->SetStatus(0, m_hRes, 0, 0);
}
catch (...) // untrusted code ?
{
ExceptionCounter c;
m_hRes = WBEM_E_CRITICAL_ERROR;
}
m_bCancelForwarded = TRUE;
return m_hRes;
}
//***************************************************************************
//
//***************************************************************************
//
ULONG STDMETHODCALLTYPE CStdSink::AddRef()
{
return InterlockedIncrement( &m_lRefCount );
}
//***************************************************************************
//
//***************************************************************************
//
ULONG STDMETHODCALLTYPE CStdSink::Release()
{
LONG lRes = InterlockedDecrement( &m_lRefCount );
if (lRes == 0)
delete this;
return lRes;
}
//***************************************************************************
//
//***************************************************************************
//
HRESULT STDMETHODCALLTYPE CStdSink::QueryInterface(REFIID riid, LPVOID* ppvObj)
{
return m_pDest->QueryInterface(riid, ppvObj);
}
//***************************************************************************
//
//***************************************************************************
//
HRESULT STDMETHODCALLTYPE CStdSink::Indicate(
long lObjectCount,
IWbemClassObject** pObjArray
)
{
HRESULT hRes;
if (m_hRes == WBEM_E_CALL_CANCELLED)
{
return Cancel();
}
try
{
hRes = m_pDest->Indicate(lObjectCount, pObjArray);
}
catch (...) // untrusted code ?
{
ExceptionCounter c;
hRes = Cancel();
}
return hRes;
}
//***************************************************************************
//
//***************************************************************************
//
HRESULT STDMETHODCALLTYPE CStdSink::SetStatus(
long lFlags,
long lParam,
BSTR strParam,
IWbemClassObject* pObjParam
)
{
HRESULT hRes;
if (m_hRes == WBEM_E_CALL_CANCELLED)
{
return Cancel();
}
try
{
hRes = m_pDest->SetStatus(lFlags, lParam, strParam, pObjParam);
}
catch (...) // untrusted code ?
{
ExceptionCounter c;
hRes = Cancel();
}
return hRes;
}
//***************************************************************************
//
//***************************************************************************
//
CFlexArray g_aProviderSinks;
CCritSec g_csProvSinkCs;
//***************************************************************************
//
//***************************************************************************
//
HRESULT WINAPI CProviderSink::Dump(FILE *f)
{
CInCritSec ics(&g_csProvSinkCs);
fprintf(f, "---Begin Provider Sink Info---\n");
for (int i = 0; i < g_aProviderSinks.Size(); i++)
{
CProviderSink *pSink = (CProviderSink *) g_aProviderSinks[i];
if (pSink)
{
fprintf(f, "Provider Sink 0x%p\n", pSink);
fprintf(f, " Total Indicates = %d\n", pSink->m_lIndicateCount);
// Check that this is non-NULL
if ( NULL != pSink->m_pszDebugInfo )
{
fprintf(f, " Debug Info = %S\n", pSink->m_pszDebugInfo);
}
else
{
fprintf(f, " Debug Info = NULL\n");
}
fprintf(f, " SetStatus called? %d\n", pSink->m_bDone);
fprintf(f, " hRes = 0x%X\n", pSink->m_hRes);
fprintf(f, " m_pNextSink = 0x%p\n", pSink->m_pNextSink);
}
}
fprintf(f, "---End Provider Sink Info---\n");
return 0;
}
//***************************************************************************
//
//***************************************************************************
//
CProviderSink::CProviderSink(
LONG lStartingRefCount,
LPWSTR pszDebugInf
):m_pNextSink(0)
{
m_lRefCount = lStartingRefCount;
InterlockedIncrement(&g_nSinkCount);
InterlockedIncrement(&g_nProviderSinkCount);
m_hRes = 0;
m_bDone = FALSE;
__try
{
InitializeCriticalSection(&m_cs);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
throw CX_MemoryException();
}
m_lIndicateCount = 0;
m_pszDebugInfo = 0;
if (pszDebugInf)
{
int nStrLen = wcslen(pszDebugInf);
m_pszDebugInfo = new wchar_t[nStrLen+1];
if (m_pszDebugInfo)
wcscpy(m_pszDebugInfo, pszDebugInf);
}
EnterCriticalSection(&g_csProvSinkCs);
g_aProviderSinks.Add(this);
LeaveCriticalSection(&g_csProvSinkCs);
}
//***************************************************************************
//
//***************************************************************************
//
CProviderSink::~CProviderSink()
{
{
CInCritSec ics(&g_csProvSinkCs);
for (int i = 0; i < g_aProviderSinks.Size(); i++)
{
if (this == (CProviderSink *) g_aProviderSinks[i])
{
g_aProviderSinks.RemoveAt(i);
break;
}
}
}
// Cleanup AFTER we remove from the array so the Diagnostic Thread won't
// crash.
ReleaseIfNotNULL(m_pNextSink);
InterlockedDecrement(&g_nSinkCount);
InterlockedDecrement(&g_nProviderSinkCount);
DeleteCriticalSection(&m_cs);
delete [] m_pszDebugInfo;
}
//***************************************************************************
//
//***************************************************************************
//
ULONG CProviderSink::AddRef()
{
LONG lRes = InterlockedIncrement(&m_lRefCount);
return (ULONG) lRes;
}
//***************************************************************************
//
//***************************************************************************
//
ULONG CProviderSink::LocalAddRef()
{
LONG lRes = InterlockedIncrement(&m_lRefCount);
return lRes;
}
//***************************************************************************
//
//***************************************************************************
//
ULONG CProviderSink::LocalRelease()
{
LONG lRes = InterlockedDecrement(&m_lRefCount);
if (lRes == 0)
delete this;
return lRes;
}
//***************************************************************************
//
//***************************************************************************
//
ULONG CProviderSink::Release()
{
LONG lRes = InterlockedDecrement(&m_lRefCount);
if (lRes == 0)
delete this;
return (ULONG) lRes;
}
//***************************************************************************
//
//***************************************************************************
//
HRESULT CProviderSink::QueryInterface(REFIID riid, LPVOID* ppvObj)
{
if (riid == IID_IUnknown || riid == IID_IWbemObjectSink)
{
*ppvObj = (IWbemObjectSink*)this;
AddRef();
return S_OK;
}
else return E_NOINTERFACE;
}
//***************************************************************************
//
//***************************************************************************
//
HRESULT CProviderSink::Indicate(
long lObjectCount,
IWbemClassObject** pObjArray
)
{
if (m_hRes)
return m_hRes;
IWbemObjectSink* pNextSink = NULL;
{
CInCritSec ics(&m_cs);
pNextSink = m_pNextSink;
if ( NULL != pNextSink )
{
pNextSink->AddRef();
}
}
// AutoRelease
CReleaseMe rm( pNextSink );
HRESULT hRes;
if ( NULL != pNextSink )
{
m_lIndicateCount += lObjectCount;
hRes = pNextSink->Indicate(lObjectCount, pObjArray);
}
else
{
hRes = WBEM_E_CRITICAL_ERROR;
}
return hRes;
}
//***************************************************************************
//
//***************************************************************************
//
void CProviderSink::Cancel()
{
if (m_bDone)
return;
IWbemObjectSink* pNextSink = NULL;
EnterCriticalSection(&m_cs);
m_hRes = WBEM_E_CALL_CANCELLED;
pNextSink = m_pNextSink;
if ( NULL != m_pNextSink )
{
// We will release it outside the critical section
m_pNextSink = NULL;
}
LeaveCriticalSection(&m_cs);
// Auto Release
CReleaseMe rm( pNextSink );
if ( pNextSink )
{
pNextSink->SetStatus(0, WBEM_E_CALL_CANCELLED, 0, 0);
}
}
//***************************************************************************
//
//***************************************************************************
//
HRESULT CProviderSink::SetStatus(
long lFlags,
long lParam,
BSTR strParam,
IWbemClassObject* pObjParam
)
{
if (m_hRes)
return m_hRes;
IWbemObjectSink* pNextSink = NULL;
EnterCriticalSection(&m_cs);
pNextSink = m_pNextSink;
if ( NULL != m_pNextSink )
{
// We will always release it outside the critical section
// If this is the completion status, then we should go ahead and set
// the member variable to NULL. We're done with the sink.
if ( lFlags == WBEM_STATUS_COMPLETE )
{
m_pNextSink = NULL;
}
else
{
pNextSink->AddRef();
}
}
LeaveCriticalSection(&m_cs);
// Auto Release
CReleaseMe rm( pNextSink );
HRESULT hRes = WBEM_S_NO_ERROR;
if ( NULL != pNextSink )
{
pNextSink->SetStatus(lFlags, lParam, strParam, pObjParam);
m_bDone = TRUE;
}
return hRes;
}
//***************************************************************************
//
//***************************************************************************
//
long g_lNumStatusSinks = 0L;
CStatusSink::CStatusSink( void )
: m_hRes( WBEM_S_NO_ERROR ),
m_lRefCount( 1 )
{
InterlockedIncrement( &g_lNumStatusSinks );
}
//***************************************************************************
//
//***************************************************************************
//
CStatusSink::~CStatusSink()
{
InterlockedDecrement( &g_lNumStatusSinks );
}
//***************************************************************************
//
//***************************************************************************
//
ULONG STDMETHODCALLTYPE CStatusSink::AddRef()
{
return InterlockedIncrement( &m_lRefCount );
}
//***************************************************************************
//
//***************************************************************************
//
ULONG STDMETHODCALLTYPE CStatusSink::Release()
{
LONG lRes = InterlockedDecrement( &m_lRefCount );
if (lRes == 0)
delete this;
return lRes;
}
//***************************************************************************
//
//***************************************************************************
//
HRESULT STDMETHODCALLTYPE CStatusSink::QueryInterface(REFIID riid, LPVOID* ppvObj)
{
if( riid == IID_IUnknown || riid == IID_IWbemObjectSink )
{
*ppvObj = (IWbemObjectSink*)this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
//***************************************************************************
//
//***************************************************************************
//
HRESULT STDMETHODCALLTYPE CStatusSink::Indicate(
long lObjectCount,
IWbemClassObject** pObjArray
)
{
// Why are we even here??!?!?!?
_DBG_ASSERT( 0 );
return WBEM_E_FAILED;
}
//***************************************************************************
//
//***************************************************************************
//
HRESULT STDMETHODCALLTYPE CStatusSink::SetStatus(
long lFlags,
long lParam,
BSTR strParam,
IWbemClassObject* pObjParam
)
{
if ( lFlags == WBEM_STATUS_COMPLETE )
{
if ( SUCCEEDED( m_hRes ) && FAILED( lParam ) )
{
m_hRes = lParam;
}
}
return WBEM_S_NO_ERROR;
}