372 lines
8.3 KiB
C
372 lines
8.3 KiB
C
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1997 - 2000
|
||
|
//
|
||
|
// File: H N C E N U M . H
|
||
|
//
|
||
|
// Contents: Generic WMI enumerator template
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
// Author: jonburs 20 June 2000
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
template<
|
||
|
class EnumInterface,
|
||
|
class ItemInterface,
|
||
|
class WrapperClass
|
||
|
>
|
||
|
class CHNCEnum :
|
||
|
public CComObjectRootEx<CComMultiThreadModel>,
|
||
|
public EnumInterface
|
||
|
{
|
||
|
private:
|
||
|
typedef CHNCEnum<EnumInterface, ItemInterface, WrapperClass> _ThisClass;
|
||
|
|
||
|
//
|
||
|
// The IEnumWbemClassObject we're wrapping
|
||
|
//
|
||
|
|
||
|
IEnumWbemClassObject *m_pwcoEnum;
|
||
|
|
||
|
//
|
||
|
// The IWbemServices for our namespace
|
||
|
//
|
||
|
|
||
|
IWbemServices *m_pwsNamespace;
|
||
|
|
||
|
public:
|
||
|
|
||
|
BEGIN_COM_MAP(_ThisClass)
|
||
|
COM_INTERFACE_ENTRY(EnumInterface)
|
||
|
END_COM_MAP()
|
||
|
|
||
|
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||
|
|
||
|
//
|
||
|
// Object Creation
|
||
|
//
|
||
|
|
||
|
CHNCEnum()
|
||
|
{
|
||
|
m_pwcoEnum = NULL;
|
||
|
m_pwsNamespace = NULL;
|
||
|
};
|
||
|
|
||
|
HRESULT
|
||
|
Initialize(
|
||
|
IWbemServices *pwsNamespace,
|
||
|
IEnumWbemClassObject *pwcoEnum
|
||
|
)
|
||
|
{
|
||
|
_ASSERT(NULL == m_pwsNamespace);
|
||
|
_ASSERT(NULL == m_pwcoEnum);
|
||
|
_ASSERT(NULL != pwsNamespace);
|
||
|
_ASSERT(NULL != pwcoEnum);
|
||
|
|
||
|
m_pwcoEnum = pwcoEnum;
|
||
|
m_pwcoEnum->AddRef();
|
||
|
m_pwsNamespace = pwsNamespace;
|
||
|
m_pwsNamespace->AddRef();
|
||
|
|
||
|
return S_OK;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Object Destruction
|
||
|
//
|
||
|
|
||
|
HRESULT
|
||
|
FinalRelease()
|
||
|
{
|
||
|
if (NULL != m_pwcoEnum)
|
||
|
{
|
||
|
m_pwcoEnum->Release();
|
||
|
}
|
||
|
|
||
|
if (NULL != m_pwsNamespace)
|
||
|
{
|
||
|
m_pwsNamespace->Release();
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// EnumInterface methods
|
||
|
//
|
||
|
|
||
|
STDMETHODIMP
|
||
|
Next(
|
||
|
ULONG cElt,
|
||
|
ItemInterface **rgElt,
|
||
|
ULONG *pcEltFetched
|
||
|
)
|
||
|
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
ULONG cInstancesFetched = 0;
|
||
|
IWbemClassObject **rgpwcoInstances = NULL;
|
||
|
CComObject<WrapperClass> *pWrapper = NULL;
|
||
|
LONG i;
|
||
|
|
||
|
_ASSERT(NULL != m_pwcoEnum);
|
||
|
|
||
|
if (NULL == rgElt)
|
||
|
{
|
||
|
hr = E_POINTER;
|
||
|
}
|
||
|
else if (0 == cElt)
|
||
|
{
|
||
|
hr = E_INVALIDARG;
|
||
|
}
|
||
|
else if (1 != cElt && NULL == pcEltFetched)
|
||
|
{
|
||
|
hr = E_POINTER;
|
||
|
}
|
||
|
|
||
|
if (S_OK == hr)
|
||
|
{
|
||
|
//
|
||
|
// Zero the output array
|
||
|
//
|
||
|
|
||
|
ZeroMemory(rgElt, cElt * sizeof(ItemInterface*));
|
||
|
|
||
|
//
|
||
|
// Allocate enough memory to hold pointers to the instances we
|
||
|
// were asked to fetch.
|
||
|
//
|
||
|
|
||
|
rgpwcoInstances = new IWbemClassObject*[cElt];
|
||
|
if (NULL != rgpwcoInstances)
|
||
|
{
|
||
|
ZeroMemory(rgpwcoInstances, sizeof(IWbemClassObject*) * cElt);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (S_OK == hr)
|
||
|
{
|
||
|
//
|
||
|
// Grab the requested number of instances from the contained
|
||
|
// WMI enumeration.
|
||
|
//
|
||
|
|
||
|
hr = m_pwcoEnum->Next(
|
||
|
WBEM_INFINITE,
|
||
|
cElt,
|
||
|
rgpwcoInstances,
|
||
|
&cInstancesFetched
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
//
|
||
|
// For each instance we retrieved, create the wrapper
|
||
|
// object.
|
||
|
//
|
||
|
|
||
|
for (i = 0;
|
||
|
static_cast<ULONG>(i) < cInstancesFetched;
|
||
|
i++)
|
||
|
{
|
||
|
hr = CComObject<WrapperClass>::CreateInstance(&pWrapper);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
pWrapper->AddRef();
|
||
|
hr = pWrapper->Initialize(
|
||
|
m_pwsNamespace,
|
||
|
rgpwcoInstances[i]
|
||
|
);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
//
|
||
|
// QI for the desired interface, and place into
|
||
|
// the output array
|
||
|
//
|
||
|
|
||
|
hr = pWrapper->QueryInterface(
|
||
|
IID_PPV_ARG(ItemInterface, &rgElt[i])
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// This can only fail if we were given incorrect
|
||
|
// template arguments.
|
||
|
//
|
||
|
|
||
|
_ASSERT(SUCCEEDED(hr));
|
||
|
}
|
||
|
|
||
|
pWrapper->Release();
|
||
|
}
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
//
|
||
|
// Something went wrong, and we destroy all of the objects
|
||
|
// we just created and QI'd. (The position of the last object
|
||
|
// created is one less than the current value of i.)
|
||
|
//
|
||
|
|
||
|
for (i-- ; i >= 0; i--)
|
||
|
{
|
||
|
if (NULL != rgElt[i])
|
||
|
{
|
||
|
rgElt[i]->Release();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Release all of the instances we retrieved
|
||
|
//
|
||
|
|
||
|
for (ULONG j = 0; j < cInstancesFetched; j++)
|
||
|
{
|
||
|
if (NULL != rgpwcoInstances[j])
|
||
|
{
|
||
|
rgpwcoInstances[j]->Release();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If necessary, release the memory we used to hold the
|
||
|
// instance pointers.
|
||
|
//
|
||
|
|
||
|
if (NULL != rgpwcoInstances)
|
||
|
{
|
||
|
delete [] rgpwcoInstances;
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
//
|
||
|
// Set the number of items we retrieved
|
||
|
//
|
||
|
|
||
|
if (NULL != pcEltFetched)
|
||
|
{
|
||
|
*pcEltFetched = cInstancesFetched;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Normalize return value
|
||
|
//
|
||
|
|
||
|
if (cInstancesFetched == cElt)
|
||
|
{
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = S_FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
};
|
||
|
|
||
|
STDMETHODIMP
|
||
|
Clone(
|
||
|
EnumInterface **ppEnum
|
||
|
)
|
||
|
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
IEnumWbemClassObject *pwcoClonedEnum;
|
||
|
CComObject<_ThisClass> *pNewEnum;
|
||
|
|
||
|
if (NULL == ppEnum)
|
||
|
{
|
||
|
hr = E_POINTER;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Attempt to clone the embedded enumeration.
|
||
|
//
|
||
|
|
||
|
pwcoClonedEnum = NULL;
|
||
|
hr = m_pwcoEnum->Clone(&pwcoClonedEnum);
|
||
|
}
|
||
|
|
||
|
if (WBEM_S_NO_ERROR == hr)
|
||
|
{
|
||
|
//
|
||
|
// Create an initialized a new instance of ourselves
|
||
|
//
|
||
|
|
||
|
hr = CComObject<_ThisClass>::CreateInstance(&pNewEnum);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
pNewEnum->AddRef();
|
||
|
hr = pNewEnum->Initialize(m_pwsNamespace, pwcoClonedEnum);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = pNewEnum->QueryInterface(
|
||
|
IID_PPV_ARG(EnumInterface, ppEnum)
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// This QI should never fail, unless we were given
|
||
|
// bogus template arguments.
|
||
|
//
|
||
|
|
||
|
_ASSERT(SUCCEEDED(hr));
|
||
|
}
|
||
|
|
||
|
pNewEnum->Release();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Release the cloned enum. New enum object will have
|
||
|
// AddReffed it...
|
||
|
//
|
||
|
|
||
|
pwcoClonedEnum->Release();
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Skip and Reset simply delegate to the contained enumeration.
|
||
|
//
|
||
|
|
||
|
STDMETHODIMP
|
||
|
Reset()
|
||
|
|
||
|
{
|
||
|
_ASSERT(NULL != m_pwcoEnum);
|
||
|
return m_pwcoEnum->Reset();
|
||
|
};
|
||
|
|
||
|
STDMETHODIMP
|
||
|
Skip(
|
||
|
ULONG cElt
|
||
|
)
|
||
|
|
||
|
{
|
||
|
_ASSERT(NULL != m_pwcoEnum);
|
||
|
return m_pwcoEnum->Skip(WBEM_INFINITE, cElt);
|
||
|
};
|
||
|
};
|