615 lines
18 KiB
C++
615 lines
18 KiB
C++
/*++
|
|
|
|
Copyright (C) 1998-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
CLOADHPENUM.CPP
|
|
|
|
Abstract:
|
|
|
|
Client Loadable Hi-Perf Enumerator
|
|
|
|
History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <stdio.h>
|
|
#include <wbemcomn.h>
|
|
#include <fastall.h>
|
|
#include <hiperfenum.h>
|
|
#include "cloadhpenum.h"
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function:
|
|
// CClientLoadableHiPerfEnum::CClientLoadableHiPerfEnum
|
|
//
|
|
// Purpose:
|
|
// Constructor.
|
|
//
|
|
// Inputs:
|
|
// CLifeControl* pLifeControl - Controls the DLL lifetime.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// WBEM_S_NO_ERROR if successful
|
|
//
|
|
// Comments:
|
|
// None.
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
CClientLoadableHiPerfEnum::CClientLoadableHiPerfEnum( CLifeControl* pLifeControl )
|
|
: CHiPerfEnum(),
|
|
m_pLifeControl( pLifeControl ),
|
|
m_apRemoteObj()
|
|
{
|
|
if ( NULL != m_pLifeControl )
|
|
{
|
|
m_pLifeControl->ObjectCreated( this );
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function:
|
|
// CClientLoadableHiPerfEnum::~CClientLoadableHiPerfEnum
|
|
//
|
|
// Purpose:
|
|
// Destructor.
|
|
//
|
|
// Inputs:
|
|
// None.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// WBEM_S_NO_ERROR if successful
|
|
//
|
|
// Comments:
|
|
// None.
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
CClientLoadableHiPerfEnum::~CClientLoadableHiPerfEnum()
|
|
{
|
|
if ( NULL != m_pLifeControl )
|
|
{
|
|
m_pLifeControl->ObjectDestroyed( this );
|
|
}
|
|
|
|
// Release all the pointers in this array
|
|
IWbemClassObject* pObj = NULL;
|
|
for( DWORD dwCtr = 0; dwCtr < m_apRemoteObj.Size(); dwCtr++ )
|
|
{
|
|
pObj = (IWbemClassObject*) m_apRemoteObj[dwCtr];
|
|
if ( NULL != pObj )
|
|
{
|
|
pObj->Release();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function:
|
|
// CClientLoadableHiPerfEnum::Copy
|
|
//
|
|
// Purpose:
|
|
// Copies objects from one enumerator into this one.
|
|
//
|
|
// Inputs:
|
|
// CClientLoadableHiPerfEnum* pEnumToCopy - Enumerator to copy.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// WBEM_S_NO_ERROR if successful
|
|
//
|
|
// Comments:
|
|
// New Objects are cloned from a template.
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT CClientLoadableHiPerfEnum::Copy( CClientLoadableHiPerfEnum* pEnumToCopy )
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
CHiPerfLockAccess lock( &m_Lock );
|
|
CHiPerfLockAccess lockSrc( &pEnumToCopy->m_Lock );
|
|
|
|
// Get through both locks first
|
|
if ( lock.IsLocked() && lockSrc.IsLocked() )
|
|
{
|
|
// Make sure we have enough object data and BLOBs to handle data copying
|
|
hr = EnsureObjectData( pEnumToCopy->m_aIdToObject.Size() );
|
|
|
|
// Now copy out the BLOBs
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
|
|
DWORD dwCtr = 0;
|
|
|
|
// Write the objects and ids out to the array
|
|
for ( dwCtr = 0; SUCCEEDED( hr ) && dwCtr < pEnumToCopy->m_aIdToObject.Size(); dwCtr++ )
|
|
{
|
|
// Make sure the object is not-NULL, otherwise we need to clone the supplied
|
|
// object. It may be NULL because someone used the standard Remove methods
|
|
// on the HiPerf Enumerator
|
|
|
|
if ( ((CHiPerfEnumData*) m_aIdToObject[dwCtr])->m_pObj != NULL )
|
|
{
|
|
hr = ((CWbemInstance*) ((CHiPerfEnumData*) m_aIdToObject[dwCtr])->m_pObj)->CopyBlobOf(
|
|
(CWbemObject*) ((CHiPerfEnumData*) pEnumToCopy->m_aIdToObject[dwCtr])->m_pObj );
|
|
}
|
|
else
|
|
{
|
|
// Clone the object
|
|
IWbemClassObject* pObj = NULL;
|
|
IWbemObjectAccess* pAccess = NULL;
|
|
hr = ((CWbemObject*)
|
|
((CHiPerfEnumData*) pEnumToCopy->m_aIdToObject[dwCtr])->m_pObj)->Clone( &pObj );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pObj->QueryInterface( IID_IWbemObjectAccess, (void**) &pAccess );
|
|
|
|
// Clean up the objects
|
|
pObj->Release();
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
// It's sleazy, but quicker than a QI
|
|
((CHiPerfEnumData*) m_aIdToObject[dwCtr])->SetObject( pAccess );
|
|
|
|
// Data object should have the AddRef() here.
|
|
pAccess->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
((CHiPerfEnumData*) m_aIdToObject[dwCtr])->m_lId =
|
|
((CHiPerfEnumData*) pEnumToCopy->m_aIdToObject[dwCtr])->m_lId;
|
|
}
|
|
|
|
// if everything is okay, go ahead and do any necessary garbage collection on
|
|
// our arrays.
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
m_aReusable.GarbageCollect();
|
|
pEnumToCopy->m_aReusable.GarbageCollect();
|
|
|
|
// We don't use remote objects here, so don't worry about garbage
|
|
// collecting that array here.
|
|
|
|
|
|
}
|
|
|
|
} // IF EnsureObjectData
|
|
|
|
}
|
|
else
|
|
{
|
|
// If we can't get access to the enumerator to figure out the objects
|
|
// we need to add to enumeration, something is pretty badly wrong.
|
|
|
|
hr = WBEM_E_REFRESHER_BUSY;
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function:
|
|
// CClientLoadableHiPerfEnum::Copy
|
|
//
|
|
// Purpose:
|
|
// Resets this enumerator using a transfer BLOB and other
|
|
// data. This is so we can support remote refreshable
|
|
// enumerations.
|
|
//
|
|
// Inputs:
|
|
// long lBlobType - Blob Type
|
|
// long lBlobLen - Blob Length
|
|
// BYTE* pBlob - Raw Data to initialize from
|
|
//
|
|
// Outputs:
|
|
// None
|
|
//
|
|
// Returns:
|
|
// WBEM_S_NO_ERROR if success
|
|
//
|
|
// Comments:
|
|
// Internal function
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT CClientLoadableHiPerfEnum::Copy( long lBlobType, long lBlobLen, BYTE* pBlob )
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
CHiPerfLockAccess lock( &m_Lock );
|
|
|
|
if ( lock.IsLocked() )
|
|
{
|
|
|
|
long lNumObjects = 0;
|
|
|
|
hr = CWbemInstance::CopyTransferArrayBlob( m_pInstTemplate, lBlobType, lBlobLen, pBlob, m_apRemoteObj, &lNumObjects );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
// The objects cloned above will do quite nicely
|
|
hr = EnsureObjectData( lNumObjects, FALSE );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
// Now walk the array of remote objects and the Object-To-ID Array, and reset objects
|
|
// and ids
|
|
|
|
IWbemObjectAccess* pAccess = NULL;
|
|
|
|
for ( long lCtr = 0; lCtr < lNumObjects; lCtr++ )
|
|
{
|
|
// It's sleazy, but quicker than a QI
|
|
((CHiPerfEnumData*) m_aIdToObject[lCtr])->SetObject(
|
|
(IWbemObjectAccess*) m_apRemoteObj[lCtr] );
|
|
((CHiPerfEnumData*) m_aIdToObject[lCtr])->SetId( lCtr );
|
|
}
|
|
|
|
// if everything is okay, go ahead and do any necessary garbage collection on
|
|
// our arrays.
|
|
|
|
m_aReusable.GarbageCollect();
|
|
|
|
// On this one, since the remote object array should contain the same
|
|
// number of objects as what is in the main array the number of objects
|
|
// to garbage collect is the difference between the two.
|
|
m_apRemoteObj.GarbageCollect(
|
|
m_apRemoteObj.Size() - m_aIdToObject.Size() );
|
|
|
|
|
|
} // IF EnsureObjectData
|
|
|
|
} // IF CopyTransferArray Blob
|
|
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_S_TIMEDOUT;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function:
|
|
// CClientLoadableHiPerfEnum::EnsureObjectData
|
|
//
|
|
// Purpose:
|
|
// Ensures that we have enough objects and object data
|
|
// pointers to handle the requested number of objects.
|
|
//
|
|
// Inputs:
|
|
// DWORD dwNumRequestedObjects - Number of requested objects.
|
|
// BOOL fClone - Indicates whether we should clone objects
|
|
// when we allocate object data pointers.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// WBEM_S_NO_ERROR if successful
|
|
//
|
|
// Comments:
|
|
// New Objects are cloned from a template if necessary.
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT CClientLoadableHiPerfEnum::EnsureObjectData( DWORD dwNumRequestedObjects, BOOL fClone /*=TRUE*/ )
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
DWORD dwNumObjects = m_aIdToObject.Size() + m_aReusable.Size();
|
|
|
|
// See if we will have enough hiperfenum data pointers to handle the objects
|
|
if ( dwNumRequestedObjects > dwNumObjects )
|
|
{
|
|
DWORD dwNumNewObjects = dwNumRequestedObjects - dwNumObjects;
|
|
CHiPerfEnumData* pData = NULL;
|
|
IWbemClassObject* pObj = NULL;
|
|
IWbemObjectAccess* pAccess = NULL;
|
|
|
|
// Clone new instance objects and stick them in the id to object array
|
|
for ( DWORD dwCtr = 0; SUCCEEDED( hr ) && dwCtr < dwNumNewObjects; dwCtr++ )
|
|
{
|
|
if ( fClone )
|
|
{
|
|
hr = m_pInstTemplate->Clone( &pObj );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pObj->QueryInterface( IID_IWbemObjectAccess, (void**) &pAccess );
|
|
|
|
// Release the object
|
|
pObj->Release();
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
pData = new CHiPerfEnumData( 0, pAccess );
|
|
|
|
// Should be AddRefd by data objects
|
|
if ( NULL != pAccess )
|
|
{
|
|
pAccess->Release();
|
|
}
|
|
|
|
if ( NULL != pData )
|
|
{
|
|
if ( m_aIdToObject.Add( (void*) pData ) != CFlexArray::no_error )
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
} // IF Clone
|
|
|
|
} // FOR allocate new objects
|
|
|
|
} // IF we need new objects
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
// Move objects from the reusable array if we don't have enough
|
|
// or move them into the reusable array if we have to many
|
|
|
|
if ( dwNumRequestedObjects > m_aIdToObject.Size() )
|
|
{
|
|
DWORD dwNumObjectsNeeded = dwNumRequestedObjects - m_aIdToObject.Size();
|
|
|
|
/*
|
|
// Copy from the end, so we just need to zero out and set size
|
|
DWORD dwReusableIndex = m_aReusable.Size() - dwNumObjectsNeeded;
|
|
|
|
// This means we can pull the pointers en masse from m_aReusable
|
|
void** pReusable = m_aReusable.GetArrayPtr();
|
|
void** pIdToObject = m_aIdToObject.GetArrayPtr();
|
|
|
|
// A Quick append, then zero out the memory and set the size
|
|
// accounting for the pointers we just "stole".
|
|
CopyMemory( &pIdToObject[m_aIdToObject.Size()],
|
|
&pReusable[dwReusableIndex],
|
|
dwNumObjectsNeeded * sizeof(void*) );
|
|
|
|
ZeroMemory( &pReusable[dwReusableIndex], dwNumObjectsNeeded * sizeof(void*) );
|
|
m_aReusable.SetSize( m_aReusable.Size() - dwNumObjectsNeeded );
|
|
m_aIdToObject.SetSize( m_aIdToObject.Size() + dwNumObjectsNeeded );
|
|
*/
|
|
for ( DWORD dwCtr = 0; SUCCEEDED( hr ) && dwCtr < dwNumObjectsNeeded; dwCtr++ )
|
|
{
|
|
if ( m_aIdToObject.Add( m_aReusable[m_aReusable.Size() - 1] ) != CFlexArray::no_error )
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
m_aReusable.RemoveAt( m_aReusable.Size() - 1 );
|
|
}
|
|
}
|
|
|
|
}
|
|
else if ( dwNumRequestedObjects < m_aIdToObject.Size() )
|
|
{
|
|
DWORD dwNumExtraObjects = m_aIdToObject.Size() - dwNumRequestedObjects;
|
|
|
|
/*
|
|
// Copy from the end, so we just need to zero out and set size
|
|
DWORD dwExtraIndex = m_aIdToObject.Size() - dwNumExtraObjects;
|
|
|
|
// This means we can pull the pointers en masse from m_aReusable
|
|
void** pReusable = m_aReusable.GetArrayPtr();
|
|
void** pIdToObject = m_aIdToObject.GetArrayPtr();
|
|
|
|
// A Quick append, then zero out the memory and set the size
|
|
// accounting for the pointers we just "stole".
|
|
CopyMemory( &pReusable[m_aReusable.Size()],
|
|
&pIdToObject[dwExtraIndex],
|
|
dwNumExtraObjects * sizeof(void*) );
|
|
|
|
ZeroMemory( &pIdToObject[dwExtraIndex], dwNumExtraObjects * sizeof(void*) );
|
|
m_aIdToObject.SetSize( m_aIdToObject.Size() - dwNumExtraObjects );
|
|
m_aReusable.SetSize( m_aReusable.Size() + dwNumExtraObjects );
|
|
*/
|
|
for ( DWORD dwCtr = 0; SUCCEEDED( hr ) && dwCtr < dwNumExtraObjects; dwCtr++ )
|
|
{
|
|
if ( m_aReusable.Add( m_aIdToObject[m_aIdToObject.Size() - 1] ) != CFlexArray::no_error )
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
m_aIdToObject.RemoveAt( m_aIdToObject.Size() - 1 );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
} // IF we ensured enough Object Data Pointers
|
|
|
|
return hr;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function:
|
|
// CReadOnlyHiPerfEnum::CReadOnlyHiPerfEnum
|
|
//
|
|
// Purpose:
|
|
// Constructor.
|
|
//
|
|
// Inputs:
|
|
// CLifeControl* pLifeControl - Controls the DLL lifetime.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// WBEM_S_NO_ERROR if successful
|
|
//
|
|
// Comments:
|
|
// None.
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
CReadOnlyHiPerfEnum::CReadOnlyHiPerfEnum( CLifeControl* pLifeControl )
|
|
: CClientLoadableHiPerfEnum( pLifeControl )
|
|
{
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function:
|
|
// CReadOnlyHiPerfEnum::~CReadOnlyHiPerfEnum
|
|
//
|
|
// Purpose:
|
|
// Destructor.
|
|
//
|
|
// Inputs:
|
|
// None.
|
|
//
|
|
// Outputs:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// WBEM_S_NO_ERROR if successful
|
|
//
|
|
// Comments:
|
|
// None.
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
CReadOnlyHiPerfEnum::~CReadOnlyHiPerfEnum()
|
|
{
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function:
|
|
// CReadOnlyHiPerfEnum::AddObjects
|
|
//
|
|
// Purpose:
|
|
// Adds new objects to the enumeration
|
|
//
|
|
// Inputs:
|
|
// long lFlags - Flags (must be 0)
|
|
// ULONG uNumObjects - Number of Objects
|
|
// long* apIds - Object Ids
|
|
// IWbemObjectAccess** apObj - Array of object pointers
|
|
//
|
|
// Outputs:
|
|
// None
|
|
//
|
|
// Returns:
|
|
// WBEM_E_ACCESS_DENIED
|
|
//
|
|
// Comments:
|
|
// We are read-only
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP CReadOnlyHiPerfEnum::AddObjects( long lFlags, ULONG uNumObjects, long* apIds, IWbemObjectAccess** apObj )
|
|
{
|
|
return WBEM_E_ACCESS_DENIED;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function:
|
|
// CReadOnlyHiPerfEnum::Remove
|
|
//
|
|
// Purpose:
|
|
// Removes specified objects from the enumeration
|
|
//
|
|
// Inputs:
|
|
// long lFlags - Flags (must be 0)
|
|
// ULONG uNumObjects - Number of Objects
|
|
// long* apIds - Object Ids
|
|
//
|
|
// Outputs:
|
|
// None
|
|
//
|
|
// Returns:
|
|
// WBEM_E_ACCESS_DENIED
|
|
//
|
|
// Comments:
|
|
// We are read-only
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP CReadOnlyHiPerfEnum::RemoveObjects( long lFlags, ULONG uNumObjects, long* apIds )
|
|
{
|
|
return WBEM_E_ACCESS_DENIED;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Function:
|
|
// CHiPerfEnum::RemoveAll
|
|
//
|
|
// Purpose:
|
|
// Removes all objects from the enumeration
|
|
//
|
|
// Inputs:
|
|
// long lFlags - Flags (must be 0)
|
|
//
|
|
// Outputs:
|
|
// None
|
|
//
|
|
// Returns:
|
|
// WBEM_E_ACCESS_DENIED
|
|
//
|
|
// Comments:
|
|
// We are read-only
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP CReadOnlyHiPerfEnum::RemoveAll( long lFlags )
|
|
{
|
|
return WBEM_E_ACCESS_DENIED;
|
|
}
|
|
|
|
// Walks the array and cleans up the specified number of elements
|
|
void CHPRemoteObjectArray::ClearElements( int nNumToClear )
|
|
{
|
|
|
|
// We need to clear from the end
|
|
for ( int nCtr = ( m_nSize - nNumToClear ); nCtr < m_nSize; nCtr++ )
|
|
{
|
|
IWbemObjectAccess* pAcc = (IWbemObjectAccess*) GetAt(nCtr);
|
|
|
|
_ASSERT( NULL != pAcc, "Tried to clear a NULL Element!" );
|
|
if ( NULL != pAcc )
|
|
{
|
|
pAcc->Release();
|
|
}
|
|
}
|
|
|
|
}
|