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.
326 lines
9.8 KiB
326 lines
9.8 KiB
/*++
|
|
|
|
Copyright (C) 1996-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
INTERNALMERGER.H
|
|
|
|
Abstract:
|
|
|
|
CInternalMerger class.
|
|
|
|
History:
|
|
|
|
30-Nov-00 sanjes Created.
|
|
|
|
--*/
|
|
|
|
#ifndef _INTERNALMERGER_H_
|
|
#define _INTERNALMERGER_H_
|
|
|
|
#include "mergerthrottling.h"
|
|
#include "wstlallc.h"
|
|
|
|
// Forward class definitions
|
|
class CWmiMergerRecord;
|
|
|
|
// Base class for merger sinks - all of these will be created by the
|
|
// merger and will AddRef() the merger. The merger class will be used
|
|
// to create the sinks. When the Merger is destroyed, it will delete
|
|
// all of the sink. Internal Merger objects MUST NOT AddRef these sinks
|
|
// so we don't create a circular dependency.
|
|
|
|
typedef enum
|
|
{
|
|
eMergerFinalSink,
|
|
eMergerOwnSink,
|
|
eMergerChildSink,
|
|
eMergerOwnInstanceSink
|
|
} MergerSinkType;
|
|
|
|
class CMergerSink : public CBasicObjectSink
|
|
{
|
|
protected:
|
|
CWmiMerger* m_pMerger;
|
|
long m_lRefCount;
|
|
|
|
virtual HRESULT OnFinalRelease( void ) = 0;
|
|
|
|
public:
|
|
CMergerSink( CWmiMerger* pMerger );
|
|
virtual ~CMergerSink();
|
|
|
|
/* IUnknown methods */
|
|
STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR* ppvObj);
|
|
STDMETHOD_(ULONG, AddRef)(THIS);
|
|
STDMETHOD_(ULONG, Release)(THIS);
|
|
|
|
virtual HRESULT Indicate(long lObjectCount, IWbemClassObject** pObjArray, bool bLowestLevel, long* plNumIndicated ) = 0L;
|
|
};
|
|
|
|
class CMergerTargetSink : public CMergerSink
|
|
{
|
|
protected:
|
|
IWbemObjectSink* m_pDest;
|
|
|
|
virtual HRESULT OnFinalRelease( void );
|
|
|
|
public:
|
|
CMergerTargetSink( CWmiMerger* pMerger, IWbemObjectSink* pDest );
|
|
~CMergerTargetSink();
|
|
|
|
HRESULT STDMETHODCALLTYPE Indicate(long lObjectCount, IWbemClassObject** pObjArray);
|
|
HRESULT STDMETHODCALLTYPE SetStatus( long lFlags, long lParam, BSTR strParam,
|
|
IWbemClassObject* pObjParam );
|
|
|
|
// Function allows us to track the lowest level call in the merger so we can decide
|
|
// if we need to automagically report all indicated objects to the arbitrator
|
|
HRESULT Indicate(long lObjectCount, IWbemClassObject** pObjArray, bool bLowestLevel, long* plNumIndicated );
|
|
|
|
};
|
|
|
|
// Causes the stl Map to use our allocator instead of the default
|
|
|
|
struct CInternalMergerRecord
|
|
{
|
|
CWbemInstance* m_pData;
|
|
DWORD m_dwObjSize;
|
|
BOOL m_bOwn;
|
|
};
|
|
|
|
// Defines an allocator so we can throw exceptions
|
|
class CKeyToInstRecordAlloc : public wbem_allocator<CInternalMergerRecord>
|
|
{
|
|
};
|
|
|
|
inline bool operator==(const CKeyToInstRecordAlloc&, const CKeyToInstRecordAlloc&)
|
|
{ return (true); }
|
|
inline bool operator!=(const CKeyToInstRecordAlloc&, const CKeyToInstRecordAlloc&)
|
|
{ return (false); }
|
|
|
|
typedef std::map<WString, CInternalMergerRecord, WSiless, CKeyToInstRecordAlloc> MRGRKEYTOINSTMAP;
|
|
typedef std::map<WString, CInternalMergerRecord, WSiless, CKeyToInstRecordAlloc>::iterator MRGRKEYTOINSTMAPITER;
|
|
|
|
// This is the actual workhorse class for merging instances returned from
|
|
// queries.
|
|
|
|
class CInternalMerger
|
|
{
|
|
protected:
|
|
|
|
// Helper class for scoped cleanup of memory usage
|
|
class CScopedMemoryUsage
|
|
{
|
|
CInternalMerger* m_pInternalMerger;
|
|
bool m_bCleanup;
|
|
long m_lMemUsage;
|
|
|
|
public:
|
|
CScopedMemoryUsage( CInternalMerger* pInternalMerger )
|
|
: m_pInternalMerger( pInternalMerger ), m_bCleanup( false ), m_lMemUsage( 0L ) {};
|
|
~CScopedMemoryUsage();
|
|
|
|
HRESULT ReportMemoryUsage( long lMemUsage );
|
|
HRESULT Cleanup( void );
|
|
};
|
|
|
|
class CMemberSink : public CMergerSink
|
|
{
|
|
protected:
|
|
CInternalMerger* m_pInternalMerger;
|
|
|
|
public:
|
|
CMemberSink( CInternalMerger* pMerger, CWmiMerger* pWmiMerger )
|
|
: CMergerSink( pWmiMerger ), m_pInternalMerger( pMerger )
|
|
{}
|
|
|
|
STDMETHOD_(ULONG, AddRef)(THIS);
|
|
|
|
STDMETHOD(SetStatus)(long lFlags, long lParam, BSTR strParam,
|
|
IWbemClassObject* pObjParam);
|
|
};
|
|
friend CMemberSink;
|
|
|
|
class COwnSink : public CMemberSink
|
|
{
|
|
protected:
|
|
virtual HRESULT OnFinalRelease( void );
|
|
|
|
public:
|
|
COwnSink(CInternalMerger* pMerger, CWmiMerger* pWmiMerger) : CMemberSink(pMerger, pWmiMerger){};
|
|
~COwnSink();
|
|
|
|
STDMETHOD(Indicate)(long lObjectCount, IWbemClassObject** pObjArray);
|
|
|
|
// Function allows us to track the lowest level call in the merger so we can decide
|
|
// if we need to automagically report all indicated objects to the arbitrator
|
|
HRESULT Indicate(long lObjectCount, IWbemClassObject** pObjArray, bool bLowestLevel, long* plNumIndicated );
|
|
|
|
|
|
};
|
|
friend COwnSink;
|
|
|
|
class CChildSink : public CMemberSink
|
|
{
|
|
protected:
|
|
virtual HRESULT OnFinalRelease( void );
|
|
|
|
public:
|
|
CChildSink(CInternalMerger* pMerger, CWmiMerger* pWmiMerger) : CMemberSink(pMerger, pWmiMerger){};
|
|
~CChildSink();
|
|
|
|
STDMETHOD(Indicate)(long lObjectCount, IWbemClassObject** pObjArray);
|
|
|
|
// Function allows us to track the lowest level call in the merger so we can decide
|
|
// if we need to automagically report all indicated objects to the arbitrator
|
|
HRESULT Indicate(long lObjectCount, IWbemClassObject** pObjArray, bool bLowestLevel, long* plNumIndicated );
|
|
|
|
};
|
|
|
|
class COwnInstanceSink : public CMemberSink
|
|
{
|
|
CCritSec m_cs;
|
|
WString m_wsInstPath;
|
|
IWbemClassObject* m_pMergedInstance;
|
|
bool m_bTriedRetrieve;
|
|
HRESULT m_hFinalStatus;
|
|
|
|
protected:
|
|
virtual HRESULT OnFinalRelease( void );
|
|
|
|
public:
|
|
COwnInstanceSink(CInternalMerger* pMerger, CWmiMerger* pWmiMerger)
|
|
: CMemberSink(pMerger, pWmiMerger), m_pMergedInstance( NULL ), m_wsInstPath(),
|
|
m_cs(), m_bTriedRetrieve( false ), m_hFinalStatus( WBEM_S_NO_ERROR )
|
|
{};
|
|
~COwnInstanceSink();
|
|
|
|
STDMETHOD(Indicate)(long lObjectCount, IWbemClassObject** pObjArray);
|
|
STDMETHOD(SetStatus)(long lFlags, long lParam, BSTR strParam,
|
|
IWbemClassObject* pObjParam);
|
|
|
|
// This should never be called here
|
|
HRESULT Indicate(long lObjectCount, IWbemClassObject** pObjArray, bool bLowestLevel, long* plNumIndicated );
|
|
|
|
HRESULT SetInstancePath( LPCWSTR pwszPath );
|
|
HRESULT GetObject( IWbemClassObject** ppMergedInst );
|
|
void SetFinalStatus( HRESULT hRes )
|
|
{ if ( SUCCEEDED( m_hFinalStatus ) ) m_hFinalStatus = hRes; };
|
|
};
|
|
|
|
friend CChildSink;
|
|
|
|
public:
|
|
|
|
// Helpers for creating sinks
|
|
static HRESULT CreateMergingSink( MergerSinkType eType, CInternalMerger* pMerger, CWmiMerger* pWmiMerger, CMergerSink** ppSink );
|
|
|
|
// 2 stage initialization
|
|
HRESULT Initialize( void );
|
|
|
|
protected:
|
|
COwnSink* m_pOwnSink;
|
|
CChildSink* m_pChildSink;
|
|
CMergerSink* m_pDest;
|
|
|
|
BOOL m_bDerivedFromTarget;
|
|
CWbemClass* m_pOwnClass;
|
|
CWbemNamespace* m_pNamespace;
|
|
IWbemContext* m_pContext;
|
|
CWmiMergerRecord* m_pWmiMergerRecord;
|
|
|
|
MRGRKEYTOINSTMAP m_map;
|
|
|
|
BOOL m_bOwnDone;
|
|
BOOL m_bChildrenDone;
|
|
WString m_wsClass;
|
|
long m_lRef;
|
|
|
|
IServerSecurity* m_pSecurity;
|
|
|
|
// This is set when we encounter an error condition and are cancelled
|
|
HRESULT m_hErrorRes;
|
|
|
|
// m_Throttler - sounds like a Supervillain...hmmm...
|
|
CMergerThrottling m_Throttler;
|
|
|
|
// Helps debug how much data this internal merger is consuming
|
|
long m_lTotalObjectData;
|
|
|
|
// Iterator which may require state to be kept
|
|
MRGRKEYTOINSTMAPITER m_DispatchOwnIter;
|
|
|
|
protected:
|
|
HRESULT AddOwnObjects(long lObjectCount, IWbemClassObject** pObjArray, bool bLowestLevel, long* plNumIndicated );
|
|
HRESULT AddChildObjects(long lObjectCount, IWbemClassObject** pObjArray, bool bLowestLevel, long* plNumIndicated );
|
|
HRESULT AddOwnInstance( IWbemClassObject* pObj, LPCWSTR wszTargetKey,
|
|
IWbemClassObject** ppMergedInstance);
|
|
HRESULT RemoveInstance( LPCWSTR pwszInstancePath );
|
|
|
|
HRESULT GetObjectLength( IWbemClassObject* pObj, long* plObjectSize );
|
|
|
|
// inline helper - adjusts throttler totals, then allows it to release itself if
|
|
// apropriate
|
|
void AdjustThrottle( long lNumParentObjects, long lNumChildObjects )
|
|
{
|
|
// Adjust the throttler now.
|
|
m_Throttler.AdjustNumParentObjects( lNumParentObjects );
|
|
m_Throttler.AdjustNumChildObjects( lNumChildObjects );
|
|
|
|
// Let the Throttler release itself if it can
|
|
m_Throttler.ReleaseThrottle();
|
|
}
|
|
|
|
// Helper function to perform Indicating and throttling - a lot of the code is more or
|
|
// less the same so this at least attempts to encapsulate it.
|
|
HRESULT IndicateArrayAndThrottle( long lObjectCount, CRefedPointerArray<IWbemClassObject>* pObjArray,
|
|
CWStringArray* pwsKeyArray, long lMapAdjustmentSize, long lNewObjectSize, bool bThrottle,
|
|
bool bParent, long* plNumIndicated );
|
|
|
|
void Enter() { m_Throttler.Enter(); }
|
|
void Leave() { m_Throttler.Leave(); }
|
|
|
|
long AddRef();
|
|
long Release();
|
|
|
|
void OwnIsDone();
|
|
void ChildrenAreDone();
|
|
|
|
void DispatchChildren();
|
|
void DispatchOwn();
|
|
void GetKey(IWbemClassObject* pInst, WString& wsKey);
|
|
HRESULT GetOwnInstance(LPCWSTR wszKey, IWbemClassObject** ppMergedInstance);
|
|
BOOL IsDone() {return m_bOwnDone && m_bChildrenDone;}
|
|
|
|
void AdjustLocalObjectSize( long lAdjust )
|
|
{
|
|
m_lTotalObjectData += lAdjust;
|
|
_DBG_ASSERT( m_lTotalObjectData >= 0L );
|
|
}
|
|
|
|
HRESULT ReportMemoryUsage( long lMemUsage );
|
|
|
|
public:
|
|
CInternalMerger(CWmiMergerRecord* pWmiMergerRecord, CMergerSink* pDest, CWbemClass* pOwnClass,
|
|
CWbemNamespace* pNamespace = NULL,
|
|
IWbemContext* pContext = NULL);
|
|
~CInternalMerger();
|
|
|
|
void SetIsDerivedFromTarget(BOOL bIs);
|
|
|
|
void Cancel( HRESULT hRes = WBEM_E_CALL_CANCELLED );
|
|
|
|
CMergerSink* GetOwnSink() { if ( NULL != m_pOwnSink ) m_pOwnSink->AddRef(); return m_pOwnSink;}
|
|
CMergerSink* GetChildSink() { if ( NULL != m_pChildSink ) m_pChildSink->AddRef(); return m_pChildSink; }
|
|
|
|
CWmiMerger* GetWmiMerger( void );
|
|
|
|
// Helper to cancel a child sink when we don't need one (i.e. if we're fully static).
|
|
//void CancelChildSink( void ) { ChildrenAreDone(); }
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|