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.
540 lines
13 KiB
540 lines
13 KiB
|
|
/*++
|
|
|
|
Copyright (C) 1996-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
MERGERREQ.CPP
|
|
|
|
Abstract:
|
|
|
|
Implementations of the various merger request classes.
|
|
|
|
History:
|
|
|
|
sanjes 28-Feb-01 Created.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#pragma warning (disable : 4786)
|
|
#include <wbemcore.h>
|
|
#include <map>
|
|
#include <vector>
|
|
#include <genutils.h>
|
|
#include <oahelp.inl>
|
|
#include <wqllex.h>
|
|
#include "wmimerger.h"
|
|
#include <helper.h>
|
|
|
|
//
|
|
// Merger Request implementations.
|
|
//
|
|
|
|
CMergerClassReq::CMergerClassReq( CWmiMerger* pMerger, CWmiMergerRecord* pParentRecord,
|
|
CWbemNamespace* pNamespace, CBasicObjectSink* pHandler,
|
|
IWbemContext* pContext)
|
|
: CMergerReq( pNamespace, pHandler, pContext ),
|
|
m_pMerger( pMerger ),
|
|
m_pParentRecord( pParentRecord ),
|
|
m_pSink( pHandler )
|
|
{
|
|
if ( NULL != m_pMerger )
|
|
{
|
|
m_pMerger->AddRef();
|
|
}
|
|
|
|
if ( NULL != m_pSink )
|
|
{
|
|
m_pSink->AddRef();
|
|
}
|
|
SetForceRun(1);
|
|
SetPriority(PriorityForceRunRequests);
|
|
}
|
|
|
|
CMergerClassReq::~CMergerClassReq()
|
|
{
|
|
if ( NULL != m_pMerger )
|
|
{
|
|
m_pMerger->Release();
|
|
}
|
|
|
|
if ( NULL != m_pSink )
|
|
{
|
|
m_pSink->Release();
|
|
}
|
|
}
|
|
|
|
void CMergerClassReq::DumpError()
|
|
{
|
|
// none
|
|
}
|
|
|
|
// Pass off execution to the merger
|
|
HRESULT CMergerParentReq::Execute ()
|
|
{
|
|
try
|
|
{
|
|
// m_pParentRecord is NULL for the original CMergerParentRquest
|
|
//
|
|
return m_pMerger->Exec_MergerParentRequest( m_pParentRecord, m_pSink ); // throw
|
|
}
|
|
catch (CX_MemoryException &)
|
|
{
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
HRESULT CMergerChildReq::Execute ()
|
|
{
|
|
HRESULT hRes = m_pMerger->Exec_MergerChildRequest( m_pParentRecord, m_pSink );
|
|
return hRes;
|
|
}
|
|
|
|
// Merger Requests
|
|
CMergerDynReq::CMergerDynReq( CWbemObject* pClassDef, CWbemNamespace* pNamespace, IWbemObjectSink* pHandler,
|
|
IWbemContext* pContext )
|
|
: CMergerReq( pNamespace, pHandler, pContext )
|
|
{
|
|
HRESULT hr = pClassDef->GetClassName( &m_varClassName );
|
|
|
|
if ( FAILED( hr ) || m_varClassName.IsNull())
|
|
{
|
|
throw CX_MemoryException();
|
|
}
|
|
}
|
|
|
|
HRESULT CMergerDynReq_DynAux_GetInstances :: Execute ()
|
|
{
|
|
HRESULT hRes = m_pNamespace->Exec_DynAux_GetInstances (
|
|
|
|
m_pClassDef ,
|
|
m_lFlags ,
|
|
m_pContext ,
|
|
m_pSink
|
|
) ;
|
|
|
|
return hRes;
|
|
}
|
|
|
|
void CMergerDynReq_DynAux_GetInstances ::DumpError()
|
|
{
|
|
// none
|
|
}
|
|
|
|
HRESULT CMergerDynReq_DynAux_ExecQueryAsync :: Execute ()
|
|
{
|
|
HRESULT hRes = m_pNamespace->Exec_DynAux_ExecQueryAsync (
|
|
|
|
m_pClassDef ,
|
|
m_Query,
|
|
m_QueryFormat,
|
|
m_lFlags ,
|
|
m_pContext ,
|
|
m_pSink
|
|
) ;
|
|
|
|
return hRes;
|
|
}
|
|
|
|
void CMergerDynReq_DynAux_ExecQueryAsync ::DumpError()
|
|
{
|
|
// none
|
|
}
|
|
|
|
// Static Requests
|
|
CMergerDynReq_Static_GetInstances::CMergerDynReq_Static_GetInstances (
|
|
|
|
CWbemNamespace *pNamespace ,
|
|
CWbemObject *pClassDef ,
|
|
long lFlags ,
|
|
IWbemContext *pCtx ,
|
|
CBasicObjectSink *pSink ,
|
|
QL_LEVEL_1_RPN_EXPRESSION* pParsedQuery
|
|
|
|
) : CMergerDynReq (
|
|
pClassDef ,
|
|
pNamespace ,
|
|
pSink ,
|
|
pCtx
|
|
) ,
|
|
m_pClassDef(pClassDef),
|
|
m_pCtx(pCtx),
|
|
m_pSink(pSink),
|
|
m_lFlags(lFlags),
|
|
m_pParsedQuery( pParsedQuery )
|
|
{
|
|
if ( m_pParsedQuery )
|
|
{
|
|
m_pParsedQuery->AddRef();
|
|
}
|
|
|
|
if (m_pClassDef)
|
|
{
|
|
m_pClassDef->AddRef () ;
|
|
}
|
|
|
|
if (m_pCtx)
|
|
{
|
|
m_pCtx->AddRef () ;
|
|
}
|
|
|
|
if (m_pSink)
|
|
{
|
|
m_pSink->AddRef () ;
|
|
}
|
|
|
|
}
|
|
|
|
CMergerDynReq_Static_GetInstances::~CMergerDynReq_Static_GetInstances ()
|
|
{
|
|
if (m_pClassDef)
|
|
{
|
|
m_pClassDef->Release () ;
|
|
}
|
|
|
|
if (m_pCtx)
|
|
{
|
|
m_pCtx->Release () ;
|
|
}
|
|
|
|
if (m_pSink)
|
|
{
|
|
m_pSink->Release () ;
|
|
}
|
|
|
|
if ( NULL != m_pParsedQuery )
|
|
{
|
|
m_pParsedQuery->Release();
|
|
}
|
|
}
|
|
|
|
// Calls into the query engine
|
|
HRESULT CMergerDynReq_Static_GetInstances::Execute()
|
|
{
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
IWbemClassObject * pErrObj = NULL;
|
|
|
|
CSetStatusOnMe SetStatusOnMe(m_pSink,hr,pErrObj);
|
|
|
|
int nRes = CQueryEngine::ExecAtomicDbQuery(
|
|
m_pNamespace->GetNsSession(),
|
|
m_pNamespace->GetNsHandle(),
|
|
m_pNamespace->GetScope(),
|
|
GetName(),
|
|
m_pParsedQuery,
|
|
m_pSink,
|
|
m_pNamespace );
|
|
|
|
if (CQueryEngine::invalid_query == nRes)
|
|
hr = WBEM_E_INVALID_QUERY;
|
|
else if(0 == nRes)
|
|
hr = WBEM_S_NO_ERROR;
|
|
|
|
return hr;
|
|
}
|
|
|
|
void CMergerDynReq_Static_GetInstances ::DumpError()
|
|
{
|
|
// none
|
|
}
|
|
|
|
//
|
|
// CWmiMergerRequestMgr implementation.
|
|
//
|
|
|
|
CWmiMergerRequestMgr::CWmiMergerRequestMgr( CWmiMerger* pMerger )
|
|
: m_pMerger( pMerger ),
|
|
m_HierarchyArray(),
|
|
m_dwNumRequests( 0 ),
|
|
m_dwMinLevel( 0xFFFFFFFF ),
|
|
m_dwMaxLevel( 0 )
|
|
{
|
|
}
|
|
|
|
CWmiMergerRequestMgr::~CWmiMergerRequestMgr()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
// Clears the manager of ALL arrays
|
|
HRESULT CWmiMergerRequestMgr::Clear( void )
|
|
{
|
|
for ( int x = 0; x < m_HierarchyArray.Size(); x++ )
|
|
{
|
|
CSortedUniquePointerArray<CMergerDynReq>* pArray =
|
|
(CSortedUniquePointerArray<CMergerDynReq>*) m_HierarchyArray[x];
|
|
|
|
if ( NULL != pArray )
|
|
{
|
|
delete pArray;
|
|
m_HierarchyArray.SetAt( x, NULL );
|
|
}
|
|
}
|
|
|
|
// Set to 0
|
|
m_dwNumRequests = 0L;
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
// Adds a new request to the manager
|
|
HRESULT CWmiMergerRequestMgr::AddRequest( CMergerDynReq* pReq, DWORD dwLevel )
|
|
{
|
|
// Locate the array for the level. If we need to allocate one, do so.
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
CSortedUniquePointerArray<CMergerDynReq>* pArray = NULL;
|
|
|
|
// Check first if we have built out to this level, then if so, do we have
|
|
// an array for the level.
|
|
if ( dwLevel >= m_HierarchyArray.Size() || NULL == m_HierarchyArray[dwLevel] )
|
|
{
|
|
pArray = new CSortedUniquePointerArray<CMergerDynReq>; // SEC:REVIEWED 2002-03-22 : Needs EH
|
|
|
|
if ( NULL != pArray )
|
|
{
|
|
// First, if we're not built out to the required size,
|
|
// NULL out the elements from size to our level
|
|
|
|
if ( dwLevel >= m_HierarchyArray.Size() )
|
|
{
|
|
for ( int x = m_HierarchyArray.Size(); SUCCEEDED( hr ) && x <= dwLevel; x++ )
|
|
{
|
|
if ( m_HierarchyArray.Add( NULL ) != CFlexArray::no_error )
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
if ( dwLevel < m_dwMinLevel )
|
|
{
|
|
m_dwMinLevel = dwLevel;
|
|
}
|
|
else if ( dwLevel > m_dwMaxLevel )
|
|
{
|
|
m_dwMaxLevel = dwLevel;
|
|
}
|
|
|
|
}
|
|
} // FOR enum elements
|
|
|
|
} // IF dwLevel >= Array size
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
m_HierarchyArray.SetAt( dwLevel, pArray );
|
|
}
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
delete pArray;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// This should NEVER be NULL
|
|
pArray = (CSortedUniquePointerArray<CMergerDynReq>*) m_HierarchyArray[dwLevel];
|
|
|
|
_DBG_ASSERT( pArray != NULL );
|
|
|
|
if ( NULL == pArray )
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
|
|
// Finally, add the request to the array. Subsequent worker threads
|
|
// will locate requests and execute them.
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
if ( pArray->Insert( pReq ) < 0 )
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
++m_dwNumRequests;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
DWORD CWmiMergerRequestMgr::GetNumRequestsAtLevel( DWORD dwLevel )
|
|
{
|
|
if ( dwLevel >= m_HierarchyArray.Size() ) return 0;
|
|
CSortedUniquePointerArray<CMergerDynReq>* pArray = (CSortedUniquePointerArray<CMergerDynReq>*) m_HierarchyArray[dwLevel];
|
|
if ( NULL == pArray ) return 0;
|
|
return pArray->GetSize();
|
|
}
|
|
|
|
//
|
|
// this function removes the first request in the array of the requests
|
|
// for a given level of the hierarchy
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL CWmiMergerRequestMgr::GetRequestAtLevel( DWORD dwLevel, wmilib::auto_ptr<CMergerReq> & pReq )
|
|
{
|
|
if ( dwLevel >= m_HierarchyArray.Size() ) return FALSE;
|
|
CSortedUniquePointerArray<CMergerDynReq>* pArray = (CSortedUniquePointerArray<CMergerDynReq>*) m_HierarchyArray[dwLevel];
|
|
if ( NULL == pArray ) return FALSE;
|
|
if (0 == pArray->GetSize()) return FALSE;
|
|
CMergerDynReq * pRealReq = NULL;
|
|
pArray->RemoveAt(0,&pRealReq);
|
|
pReq.reset(pRealReq);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Removes a request from the manager and returns it to the caller.
|
|
// The caller is responsible for cleaning up the request.
|
|
|
|
HRESULT CWmiMergerRequestMgr::RemoveRequest( DWORD dwLevel, LPCWSTR pwszName,
|
|
wmilib::auto_ptr<CMergerReq> & pReq )
|
|
{
|
|
// Locate the array for the level.
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
if ( dwLevel < m_HierarchyArray.Size() )
|
|
{
|
|
CSortedUniquePointerArray<CMergerDynReq>* pArray =
|
|
(CSortedUniquePointerArray<CMergerDynReq>*) m_HierarchyArray[dwLevel];
|
|
|
|
// pArray is NULL if the class hierarchy combine static with dynamic
|
|
|
|
if ( NULL != pArray )
|
|
{
|
|
int nIndex;
|
|
|
|
// Under certain race conditions, another thread
|
|
// can actually remove a request before one thread
|
|
// processes it, so if it's not there, the assumption
|
|
// is that it was already removed.
|
|
pReq.reset(pArray->Find( pwszName, &nIndex )); // SEC:REVIEWED 2002-03-22 : Should have EH in case <ppReq> is NULL
|
|
|
|
if ( NULL != pReq.get() )
|
|
{
|
|
// Now remove the element from the array, the caller
|
|
// is responsible for deleting it
|
|
pArray->RemoveAtNoDelete( nIndex );
|
|
--m_dwNumRequests;
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_NOT_FOUND;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWmiMergerRequestMgr::GetTopmostParentReqName( WString& wsClassName )
|
|
{
|
|
HRESULT hr = WBEM_E_NOT_FOUND;
|
|
|
|
if ( m_dwNumRequests > 0 )
|
|
{
|
|
for ( int x = 0; WBEM_E_NOT_FOUND == hr && x < m_HierarchyArray.Size(); x++ )
|
|
{
|
|
CSortedUniquePointerArray<CMergerDynReq>* pArray =
|
|
(CSortedUniquePointerArray<CMergerDynReq>*) m_HierarchyArray[x];
|
|
|
|
// The Array must exist and have elements
|
|
if ( NULL != pArray && pArray->GetSize() > 0 )
|
|
{
|
|
// Get the class name from the first request
|
|
try
|
|
{
|
|
wsClassName = pArray->GetAt( 0 )->GetName();
|
|
hr = WBEM_S_NO_ERROR;
|
|
}
|
|
catch(...)
|
|
{
|
|
ExceptionCounter c;
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
} // For enum arrays
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
BOOL CWmiMergerRequestMgr::HasSingleStaticRequest( void )
|
|
{
|
|
BOOL fRet = FALSE;
|
|
|
|
if ( 1 == m_dwNumRequests )
|
|
{
|
|
HRESULT hr = WBEM_E_NOT_FOUND;
|
|
|
|
for ( int x = 0; WBEM_E_NOT_FOUND == hr && x < m_HierarchyArray.Size(); x++ )
|
|
{
|
|
CSortedUniquePointerArray<CMergerDynReq>* pArray =
|
|
(CSortedUniquePointerArray<CMergerDynReq>*) m_HierarchyArray[x];
|
|
|
|
// The Array must exist and have elements
|
|
if ( NULL != pArray && pArray->GetSize() > 0 )
|
|
{
|
|
// Get the class name from the first request
|
|
fRet = pArray->GetAt(0)->IsStatic();
|
|
hr = WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
} // For enum arrays
|
|
|
|
} // Must be 1 and only 1 request
|
|
|
|
return fRet;
|
|
}
|
|
|
|
#ifdef __DEBUG_MERGER_THROTTLING
|
|
void CWmiMergerRequestMgr::DumpRequestHierarchy( void )
|
|
{
|
|
HRESULT hr = WBEM_E_NOT_FOUND;
|
|
|
|
if ( m_dwNumRequests > 0 )
|
|
{
|
|
for ( int x = 0; FAILED( hr ) && x < m_HierarchyArray.Size(); x++ )
|
|
{
|
|
CSortedUniquePointerArray<CMergerDynReq>* pArray =
|
|
(CSortedUniquePointerArray<CMergerDynReq>*) m_HierarchyArray[x];
|
|
|
|
// The Array must exist and have elements
|
|
if ( NULL != pArray && pArray->GetSize() > 0 )
|
|
{
|
|
for ( int y = 0; y < pArray->GetSize(); y++ )
|
|
{
|
|
DbgPrintfA(0,"Merger Request, Level %d, Class Name: %s\n", x, pArray->GetAt(y)->GetName() );
|
|
}
|
|
}
|
|
|
|
} // For enum arrays
|
|
}
|
|
|
|
}
|
|
#else
|
|
void CWmiMergerRequestMgr::DumpRequestHierarchy( void )
|
|
{
|
|
}
|
|
#endif
|