windows-nt/Source/XPSP1/NT/net/config/netcfg/engine/ienum.cpp
2020-09-26 16:20:57 +08:00

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;
}