Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

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