//+--------------------------------------------------------------------------- // // 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 #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 ; 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(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 ; 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(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 ; 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(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; }