630 lines
15 KiB
C++
630 lines
15 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1999.
|
|
//
|
|
// File: I E N U M . C P P
|
|
//
|
|
// Contents: Implements the IEnumNetCfgBindingInterface,
|
|
// IEnumNetCfgBindingPath, and IEnumNetCfgComponent COM
|
|
// interfaces.
|
|
//
|
|
// Notes:
|
|
//
|
|
// Author: shaunco 15 Jan 1999
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <pch.h>
|
|
#pragma hdrstop
|
|
#include "ibind.h"
|
|
#include "ienum.h"
|
|
#include "ncatl.h"
|
|
#include "netcfg.h"
|
|
|
|
/*
|
|
A helper function for finishing up the semantics of a IEnumXXX::Next or
|
|
IEnumXXX::Skip. Return S_OK if no error passed in and celt == celtFetched.
|
|
Return S_FALSE if no error passed in and celt != celtFetched. If returning
|
|
an error, release celt IUnknowns from rgelt.
|
|
|
|
Returns: S_OK, S_FALSE, or an error code
|
|
|
|
Author: shaunco 13 Jan 1999
|
|
*/
|
|
HRESULT
|
|
HrFinishNextOrSkipContract (
|
|
IN HRESULT hr,
|
|
IN ULONG celtFetched,
|
|
IN ULONG celt,
|
|
IN OUT IUnknown** rgelt,
|
|
OUT ULONG* pceltFetched)
|
|
{
|
|
if (S_OK == hr)
|
|
{
|
|
if (pceltFetched)
|
|
{
|
|
*pceltFetched = celtFetched;
|
|
}
|
|
hr = (celtFetched == celt) ? S_OK : S_FALSE;
|
|
}
|
|
else
|
|
{
|
|
// For any failures, we need to release what we were about to return.
|
|
// Set any output parameters to NULL.
|
|
//
|
|
if (rgelt)
|
|
{
|
|
for (ULONG ulIndex = 0; ulIndex < celt; ulIndex++)
|
|
{
|
|
ReleaseObj (rgelt[ulIndex]);
|
|
rgelt[ulIndex] = NULL;
|
|
}
|
|
}
|
|
if (pceltFetched)
|
|
{
|
|
*pceltFetched = 0;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// CImplIEnumNetCfgBindingInterface -
|
|
//
|
|
|
|
/*
|
|
Create an instance of a binding interface enumerator.
|
|
|
|
Returns: S_OK or an error code
|
|
|
|
Author: shaunco 13 Jan 1999
|
|
*/
|
|
// static
|
|
HRESULT
|
|
CImplIEnumNetCfgBindingInterface::HrCreateInstance (
|
|
IN CImplINetCfg* pINetCfg,
|
|
IN CImplINetCfgBindingPath* pIPath,
|
|
OUT IEnumNetCfgBindingInterface** ppIEnum)
|
|
{
|
|
HRESULT hr = E_OUTOFMEMORY;
|
|
|
|
CImplIEnumNetCfgBindingInterface* pObj;
|
|
pObj = new CComObject <CImplIEnumNetCfgBindingInterface>;
|
|
if (pObj)
|
|
{
|
|
hr = S_OK;
|
|
|
|
// Initialize our members.
|
|
//
|
|
pObj->m_pIPath = pIPath;
|
|
|
|
// Do the standard CComCreator::CreateInstance stuff.
|
|
//
|
|
pObj->SetVoid (NULL);
|
|
pObj->InternalFinalConstructAddRef ();
|
|
hr = pObj->FinalConstruct ();
|
|
pObj->InternalFinalConstructRelease ();
|
|
|
|
// The last thing we do is addref any interfaces we hold.
|
|
// We only do this if we are returning success.
|
|
//
|
|
if (S_OK == hr)
|
|
{
|
|
hr = pObj->QueryInterface (IID_IEnumNetCfgBindingInterface,
|
|
(VOID**)ppIEnum);
|
|
|
|
// The last thing we do is addref any interfaces we hold.
|
|
// We only do this if we are returning success.
|
|
//
|
|
if (S_OK == hr)
|
|
{
|
|
AddRefObj (pIPath->GetUnknown());
|
|
pObj->HoldINetCfg (pINetCfg);
|
|
}
|
|
}
|
|
|
|
if (S_OK != hr)
|
|
{
|
|
delete pObj;
|
|
}
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CImplIEnumNetCfgBindingInterface::HrCreateInstance");
|
|
return hr;
|
|
}
|
|
|
|
VOID
|
|
CImplIEnumNetCfgBindingInterface::FinalRelease ()
|
|
{
|
|
AssertH (m_pIPath);
|
|
ReleaseObj (m_pIPath->GetUnknown());
|
|
|
|
CImplINetCfgHolder::FinalRelease();
|
|
}
|
|
|
|
HRESULT
|
|
CImplIEnumNetCfgBindingInterface::HrNextOrSkip (
|
|
IN ULONG celt,
|
|
OUT INetCfgBindingInterface** rgelt,
|
|
OUT ULONG* pceltFetched)
|
|
{
|
|
HRESULT hr;
|
|
|
|
Assert (m_unIndex >= 1);
|
|
|
|
// Important to initialize rgelt so that in case we fail, we can
|
|
// release only what we put in rgelt.
|
|
//
|
|
if (rgelt)
|
|
{
|
|
ZeroMemory (rgelt, sizeof (*rgelt) * celt);
|
|
}
|
|
|
|
hr = HrLockAndTestForValidInterface (IF_DEFAULT);
|
|
if (S_OK == hr)
|
|
{
|
|
// Enumerate the requested number of elements or stop short
|
|
// if we don't have that many left to enumerate.
|
|
//
|
|
ULONG celtFetched = 0;
|
|
while ((S_OK == hr)
|
|
&& (celtFetched < celt)
|
|
&& (m_unIndex < m_pIPath->m_cpIComp))
|
|
{
|
|
if (rgelt)
|
|
{
|
|
hr = CImplINetCfgBindingInterface::HrCreateInstance (
|
|
m_pINetCfg,
|
|
(CImplINetCfgComponent*)m_pIPath->
|
|
m_papIComp[m_unIndex-1],
|
|
|
|
(CImplINetCfgComponent*)m_pIPath->
|
|
m_papIComp[m_unIndex],
|
|
rgelt + celtFetched);
|
|
}
|
|
|
|
celtFetched++;
|
|
m_unIndex++;
|
|
}
|
|
Unlock();
|
|
|
|
hr = HrFinishNextOrSkipContract (hr, celtFetched, celt,
|
|
reinterpret_cast<IUnknown**>(rgelt), pceltFetched);
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, S_FALSE == hr,
|
|
"CImplIEnumNetCfgBindingInterface::HrNextOrSkip");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplIEnumNetCfgBindingInterface::Next (
|
|
IN ULONG celt,
|
|
OUT INetCfgBindingInterface** rgelt,
|
|
OUT ULONG* pceltFetched)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Validate parameters.
|
|
//
|
|
if (!rgelt || (!pceltFetched && (1 != celt)))
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else if (rgelt && IsBadWritePtr(rgelt, celt * sizeof(*rgelt)))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
hr = HrNextOrSkip (celt, rgelt, pceltFetched);
|
|
}
|
|
TraceHr (ttidError, FAL, hr, S_FALSE == hr,
|
|
"CImplIEnumNetCfgBindingInterface::Next");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplIEnumNetCfgBindingInterface::Skip (
|
|
IN ULONG celt)
|
|
{
|
|
HRESULT hr = HrNextOrSkip (celt, NULL, NULL);
|
|
|
|
TraceHr (ttidError, FAL, hr, S_FALSE == hr,
|
|
"CImplIEnumNetCfgBindingInterface::Skip");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplIEnumNetCfgBindingInterface::Reset ()
|
|
{
|
|
Lock();
|
|
Assert (m_pIPath);
|
|
m_unIndex = 1;
|
|
Unlock();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplIEnumNetCfgBindingInterface::Clone (
|
|
OUT IEnumNetCfgBindingInterface** ppIEnum)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// CImplIEnumNetCfgBindingPath -
|
|
//
|
|
|
|
// static
|
|
HRESULT
|
|
CImplIEnumNetCfgBindingPath::HrCreateInstance (
|
|
IN CImplINetCfg* pINetCfg,
|
|
IN const CBindingSet* pBindSet OPTIONAL,
|
|
IN DWORD dwFlags,
|
|
OUT CImplIEnumNetCfgBindingPath** ppIEnum)
|
|
{
|
|
HRESULT hr = E_OUTOFMEMORY;
|
|
|
|
Assert (dwFlags);
|
|
if (pBindSet)
|
|
{
|
|
pINetCfg->m_pNetConfig->Core.DbgVerifyBindingSet (pBindSet);
|
|
}
|
|
|
|
CImplIEnumNetCfgBindingPath* pObj;
|
|
pObj = new CComObject <CImplIEnumNetCfgBindingPath>;
|
|
if (pObj)
|
|
{
|
|
hr = S_OK;
|
|
|
|
// Initialize our members.
|
|
//
|
|
if (dwFlags & EBPC_TAKE_OWNERSHIP)
|
|
{
|
|
Assert (pBindSet);
|
|
pObj->m_pBindSet = pBindSet;
|
|
pObj->m_iter = pBindSet->begin();
|
|
}
|
|
else if (dwFlags & EBPC_COPY_BINDSET)
|
|
{
|
|
Assert (pBindSet);
|
|
hr = pObj->m_InternalBindSet.HrCopyBindingSet(pBindSet);
|
|
pObj->m_pBindSet = &pObj->m_InternalBindSet;
|
|
pObj->m_iter = pObj->m_InternalBindSet.begin();
|
|
}
|
|
else
|
|
{
|
|
Assert (dwFlags & EBPC_CREATE_EMPTY);
|
|
pObj->m_pBindSet = &pObj->m_InternalBindSet;
|
|
pObj->m_iter = pObj->m_InternalBindSet.begin();
|
|
}
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
// Do the standard CComCreator::CreateInstance stuff.
|
|
//
|
|
pObj->SetVoid (NULL);
|
|
pObj->InternalFinalConstructAddRef ();
|
|
hr = pObj->FinalConstruct ();
|
|
pObj->InternalFinalConstructRelease ();
|
|
|
|
// The last thing we do is addref any interfaces we hold.
|
|
// We only do this if we are returning success.
|
|
//
|
|
if (S_OK == hr)
|
|
{
|
|
pObj->HoldINetCfg (pINetCfg);
|
|
|
|
AddRefObj (pObj->GetUnknown());
|
|
*ppIEnum = pObj;
|
|
}
|
|
}
|
|
|
|
if (S_OK != hr)
|
|
{
|
|
delete pObj;
|
|
}
|
|
}
|
|
|
|
if ((S_OK != hr) && (dwFlags & EBPC_TAKE_OWNERSHIP))
|
|
{
|
|
delete pBindSet;
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CImplIEnumNetCfgBindingPath::HrCreateInstance");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CImplIEnumNetCfgBindingPath::HrNextOrSkip (
|
|
IN ULONG celt,
|
|
OUT INetCfgBindingPath** rgelt,
|
|
OUT ULONG* pceltFetched)
|
|
{
|
|
HRESULT hr;
|
|
|
|
Assert(m_iter >= m_pBindSet->begin());
|
|
|
|
// Important to initialize rgelt so that in case we fail, we can
|
|
// release only what we put in rgelt.
|
|
//
|
|
if (rgelt)
|
|
{
|
|
ZeroMemory (rgelt, sizeof (*rgelt) * celt);
|
|
}
|
|
|
|
hr = HrLockAndTestForValidInterface (IF_DEFAULT);
|
|
if (S_OK == hr)
|
|
{
|
|
// Enumerate the requested number of elements or stop short
|
|
// if we don't have that many left to enumerate.
|
|
//
|
|
ULONG celtFetched = 0;
|
|
while ((S_OK == hr)
|
|
&& (celtFetched < celt)
|
|
&& (m_iter != m_pBindSet->end()))
|
|
{
|
|
// Don't return interfaces to bindpaths that contain
|
|
// components that have had problem loading.
|
|
//
|
|
if (m_iter->FAllComponentsLoadedOkayIfLoadedAtAll())
|
|
{
|
|
if (rgelt)
|
|
{
|
|
hr = CImplINetCfgBindingPath::HrCreateInstance (
|
|
m_pINetCfg,
|
|
m_iter,
|
|
rgelt + celtFetched);
|
|
}
|
|
|
|
celtFetched++;
|
|
}
|
|
|
|
m_iter++;
|
|
}
|
|
|
|
Unlock();
|
|
|
|
hr = HrFinishNextOrSkipContract (hr, celtFetched, celt,
|
|
reinterpret_cast<IUnknown**>(rgelt), pceltFetched);
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, S_FALSE == hr,
|
|
"CImplIEnumNetCfgBindingPath::HrNextOrSkip");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplIEnumNetCfgBindingPath::Next (
|
|
IN ULONG celt,
|
|
OUT INetCfgBindingPath** rgelt,
|
|
OUT ULONG* pceltFetched)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Validate parameters.
|
|
//
|
|
if (!rgelt || (!pceltFetched && (1 != celt)))
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else if (rgelt && IsBadWritePtr(rgelt, celt * sizeof(*rgelt)))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
hr = HrNextOrSkip (celt, rgelt, pceltFetched);
|
|
}
|
|
TraceHr (ttidError, FAL, hr, S_FALSE == hr,
|
|
"CImplIEnumNetCfgBindingPath::Next");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplIEnumNetCfgBindingPath::Skip (
|
|
IN ULONG celt)
|
|
{
|
|
HRESULT hr = HrNextOrSkip (celt, NULL, NULL);
|
|
|
|
TraceHr (ttidError, FAL, hr, S_FALSE == hr,
|
|
"CImplIEnumNetCfgBindingPath::Skip");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplIEnumNetCfgBindingPath::Reset ()
|
|
{
|
|
Lock();
|
|
Assert (m_pBindSet);
|
|
m_iter = m_pBindSet->begin();
|
|
Unlock();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplIEnumNetCfgBindingPath::Clone (
|
|
OUT IEnumNetCfgBindingPath** ppIEnum)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// CImplIEnumNetCfgComponent -
|
|
//
|
|
|
|
// static
|
|
HRESULT
|
|
CImplIEnumNetCfgComponent::HrCreateInstance (
|
|
IN CImplINetCfg* pINetCfg,
|
|
IN NETCLASS Class,
|
|
OUT IEnumNetCfgComponent** ppIEnum)
|
|
{
|
|
HRESULT hr = E_OUTOFMEMORY;
|
|
|
|
CImplIEnumNetCfgComponent* pObj;
|
|
pObj = new CComObject <CImplIEnumNetCfgComponent>;
|
|
if (pObj)
|
|
{
|
|
// Initialize our members.
|
|
//
|
|
pObj->m_unIndex = 0;
|
|
pObj->m_Class = Class;
|
|
|
|
// Do the standard CComCreator::CreateInstance stuff.
|
|
//
|
|
pObj->SetVoid (NULL);
|
|
pObj->InternalFinalConstructAddRef ();
|
|
hr = pObj->FinalConstruct ();
|
|
pObj->InternalFinalConstructRelease ();
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
hr = pObj->QueryInterface (IID_IEnumNetCfgComponent,
|
|
(VOID**)ppIEnum);
|
|
|
|
// The last thing we do is addref any interfaces we hold.
|
|
// We only do this if we are returning success.
|
|
//
|
|
if (S_OK == hr)
|
|
{
|
|
pObj->HoldINetCfg (pINetCfg);
|
|
}
|
|
}
|
|
|
|
if (S_OK != hr)
|
|
{
|
|
delete pObj;
|
|
}
|
|
}
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CImplIEnumNetCfgComponent::HrCreateInstance");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CImplIEnumNetCfgComponent::HrNextOrSkip (
|
|
IN ULONG celt,
|
|
OUT INetCfgComponent** rgelt,
|
|
OUT ULONG* pceltFetched)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Important to initialize rgelt so that in case we fail, we can
|
|
// release only what we put in rgelt.
|
|
//
|
|
if (rgelt)
|
|
{
|
|
ZeroMemory (rgelt, sizeof (*rgelt) * celt);
|
|
}
|
|
|
|
hr = HrLockAndTestForValidInterface (IF_DEFAULT);
|
|
if (S_OK == hr)
|
|
{
|
|
CComponentList* pComponents;
|
|
CComponent* pComponent;
|
|
|
|
pComponents = &m_pINetCfg->m_pNetConfig->Core.Components;
|
|
|
|
// Enumerate the requested number of elements or stop short
|
|
// if we don't have that many left to enumerate.
|
|
//
|
|
ULONG celtFetched = 0;
|
|
while ((S_OK == hr)
|
|
&& (celtFetched < celt)
|
|
&& (NULL != (pComponent = pComponents->PGetComponentAtIndex(
|
|
m_unIndex))))
|
|
{
|
|
// Don't return interfaces to components that have had
|
|
// problem loading.
|
|
//
|
|
if (((NC_INVALID == m_Class) ||
|
|
(m_Class == pComponent->Class())) &&
|
|
pComponent->Ext.FLoadedOkayIfLoadedAtAll())
|
|
{
|
|
if (rgelt)
|
|
{
|
|
hr = pComponent->HrGetINetCfgComponentInterface(
|
|
m_pINetCfg, rgelt + celtFetched);
|
|
}
|
|
|
|
celtFetched++;
|
|
}
|
|
|
|
m_unIndex++;
|
|
}
|
|
|
|
Unlock();
|
|
|
|
hr = HrFinishNextOrSkipContract (hr, celtFetched, celt,
|
|
reinterpret_cast<IUnknown**>(rgelt), pceltFetched);
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, S_FALSE == hr,
|
|
"CImplIEnumNetCfgComponent::HrNextOrSkip");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplIEnumNetCfgComponent::Next (
|
|
IN ULONG celt,
|
|
OUT INetCfgComponent** rgelt,
|
|
OUT ULONG* pceltFetched)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Validate parameters.
|
|
//
|
|
if (!rgelt || (!pceltFetched && (1 != celt)))
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else if (rgelt && IsBadWritePtr(rgelt, celt * sizeof(*rgelt)))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
hr = HrNextOrSkip (celt, rgelt, pceltFetched);
|
|
}
|
|
TraceHr (ttidError, FAL, hr, S_FALSE == hr,
|
|
"CImplIEnumNetCfgComponent::Next");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplIEnumNetCfgComponent::Skip (
|
|
IN ULONG celt)
|
|
{
|
|
HRESULT hr = HrNextOrSkip (celt, NULL, NULL);
|
|
|
|
TraceHr (ttidError, FAL, hr, S_FALSE == hr,
|
|
"CImplIEnumNetCfgComponent::Skip");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplIEnumNetCfgComponent::Reset ()
|
|
{
|
|
Lock();
|
|
m_unIndex = 0;
|
|
Unlock();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplIEnumNetCfgComponent::Clone (
|
|
OUT IEnumNetCfgComponent** ppIEnum)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|