You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
806 lines
20 KiB
806 lines
20 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1999.
|
|
//
|
|
// File: I B I N D . C P P
|
|
//
|
|
// Contents: Implements the INetCfgBindingInterface and INetCfgBindingPath
|
|
// COM interfaces.
|
|
//
|
|
// Notes:
|
|
//
|
|
// Author: shaunco 15 Jan 1999
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <pch.h>
|
|
#pragma hdrstop
|
|
#include "ibind.h"
|
|
#include "ncvalid.h"
|
|
#include "netcfg.h"
|
|
#include "util.h"
|
|
|
|
|
|
//static
|
|
HRESULT
|
|
CImplINetCfgBindingInterface::HrCreateInstance (
|
|
IN CImplINetCfg* pINetCfg,
|
|
IN CImplINetCfgComponent* pUpper,
|
|
IN CImplINetCfgComponent* pLower,
|
|
OUT INetCfgBindingInterface** ppv)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
|
|
HRESULT hr = E_OUTOFMEMORY;
|
|
|
|
CImplINetCfgBindingInterface* pObj;
|
|
pObj = new CComObject <CImplINetCfgBindingInterface>;
|
|
if (pObj)
|
|
{
|
|
// Initialize our members.
|
|
//
|
|
pObj->m_pUpper = pUpper;
|
|
pObj->m_pLower = pLower;
|
|
|
|
// Do the standard CComCreator::CreateInstance stuff.
|
|
//
|
|
pObj->SetVoid (NULL);
|
|
pObj->InternalFinalConstructAddRef ();
|
|
hr = pObj->FinalConstruct ();
|
|
pObj->InternalFinalConstructRelease ();
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
hr = pObj->QueryInterface (IID_INetCfgBindingInterface,
|
|
(VOID**)ppv);
|
|
|
|
// 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 (pUpper->GetUnknown());
|
|
AddRefObj (pLower->GetUnknown());
|
|
pObj->HoldINetCfg (pINetCfg);
|
|
}
|
|
}
|
|
|
|
if (S_OK != hr)
|
|
{
|
|
delete pObj;
|
|
}
|
|
}
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CImplINetCfgBindingInterface::HrCreateInstance");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CImplINetCfgBindingInterface::HrLockAndTestForValidInterface (
|
|
DWORD dwFlags)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
|
|
HRESULT hr;
|
|
|
|
Lock();
|
|
|
|
hr = m_pUpper->HrIsValidInterface (dwFlags);
|
|
if (S_OK == hr)
|
|
{
|
|
hr = m_pLower->HrIsValidInterface (dwFlags);
|
|
}
|
|
|
|
if (S_OK != hr)
|
|
{
|
|
Unlock();
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CImplINetCfgBindingInterface::HrLockAndTestForValidInterface");
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// INetCfgBindingInterface
|
|
//
|
|
|
|
STDMETHODIMP
|
|
CImplINetCfgBindingInterface::GetName (
|
|
OUT PWSTR* ppszInterfaceName)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
|
|
HRESULT hr;
|
|
|
|
// Validate parameters.
|
|
//
|
|
if (FBadOutPtr(ppszInterfaceName))
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else
|
|
{
|
|
*ppszInterfaceName = NULL;
|
|
|
|
hr = HrLockAndTestForValidInterface (IF_NEED_COMPONENT_DATA);
|
|
if (S_OK == hr)
|
|
{
|
|
CComponent* pUpper = m_pUpper->m_pComponent;
|
|
CComponent* pLower = m_pLower->m_pComponent;
|
|
const WCHAR* pch;
|
|
ULONG cch;
|
|
|
|
if (pUpper->FCanDirectlyBindTo (pLower, &pch, &cch))
|
|
{
|
|
hr = HrCoTaskMemAllocAndDupSzLen (
|
|
pch, cch, ppszInterfaceName, MAX_INF_STRING_LENGTH);
|
|
}
|
|
else
|
|
{
|
|
AssertSz(0, "Why no match if we have a binding interface "
|
|
"created for these components?");
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
|
|
Unlock();
|
|
}
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CImplINetCfgBindingInterface::GetName");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplINetCfgBindingInterface::GetUpperComponent (
|
|
OUT INetCfgComponent** ppComp)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
|
|
HRESULT hr;
|
|
|
|
// Validate parameters.
|
|
//
|
|
if (FBadOutPtr(ppComp))
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else
|
|
{
|
|
*ppComp = NULL;
|
|
|
|
hr = HrLockAndTestForValidInterface (IF_DEFAULT);
|
|
if (S_OK == hr)
|
|
{
|
|
AddRefObj (m_pUpper->GetUnknown());
|
|
*ppComp = m_pUpper;
|
|
|
|
Unlock();
|
|
}
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CImplINetCfgBindingInterfaceGetName::GetUpperComponent");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplINetCfgBindingInterface::GetLowerComponent (
|
|
OUT INetCfgComponent** ppComp)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
|
|
HRESULT hr;
|
|
|
|
// Validate parameters.
|
|
//
|
|
if (FBadOutPtr(ppComp))
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else
|
|
{
|
|
*ppComp = NULL;
|
|
|
|
hr = HrLockAndTestForValidInterface (IF_DEFAULT);
|
|
if (S_OK == hr)
|
|
{
|
|
AddRefObj (m_pLower->GetUnknown());
|
|
*ppComp = m_pLower;
|
|
|
|
Unlock();
|
|
}
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CImplINetCfgBindingInterfaceGetName::GetLowerComponent");
|
|
return hr;
|
|
}
|
|
|
|
|
|
//static
|
|
HRESULT
|
|
CImplINetCfgBindingPath::HrCreateInstance (
|
|
IN CImplINetCfg* pINetCfg,
|
|
IN const CBindPath* pBindPath,
|
|
OUT INetCfgBindingPath** ppIPath)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
|
|
HRESULT hr;
|
|
ULONG ulDepth;
|
|
ULONG cbArray;
|
|
CComponent* pComponent;
|
|
CImplINetCfgBindingPath* pObj;
|
|
|
|
Assert (pINetCfg);
|
|
Assert (pBindPath);
|
|
Assert (ppIPath);
|
|
|
|
// Caller's are responsible for ensuring that if an interface is about
|
|
// to be handed out, and the external data has been loaded, that the
|
|
// data has been loaded successfully. If we handed out an interface
|
|
// and the data was NOT loaded successfully, it just means we are doomed
|
|
// to fail later when the client of the interface calls a method that
|
|
// requires that data.
|
|
//
|
|
Assert (pBindPath->FAllComponentsLoadedOkayIfLoadedAtAll());
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
pObj = new CComObject <CImplINetCfgBindingPath>;
|
|
|
|
if (pObj)
|
|
{
|
|
// Initialize our members.
|
|
//
|
|
|
|
ulDepth = pBindPath->CountComponents();
|
|
cbArray = ulDepth * sizeof(INetCfgComponent*);
|
|
|
|
AssertSz (0 != ulDepth, "Why are we being asked to expose an empty bindpath?");
|
|
AssertSz (1 != ulDepth, "Why are we being asked to expose a bindpath with only one component?");
|
|
|
|
// If the bindpath has more components than our static
|
|
// array has room for, we'll have to use an allocated array.
|
|
//
|
|
if (cbArray > sizeof(pObj->m_apIComp))
|
|
{
|
|
// Ensure failure of MemAlloc causes us to return the correct
|
|
// error code. (Should be set above and not changed between.)
|
|
//
|
|
Assert (E_OUTOFMEMORY == hr);
|
|
|
|
pObj->m_papIComp = (INetCfgComponent**) MemAlloc (cbArray);
|
|
|
|
if (pObj->m_papIComp)
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pObj->m_papIComp = pObj->m_apIComp;
|
|
hr = S_OK;
|
|
}
|
|
|
|
// Now get each INetCfgComponent interface for the components in
|
|
// the bindpath.
|
|
//
|
|
if (S_OK == hr)
|
|
{
|
|
UINT iComp;
|
|
|
|
ZeroMemory (pObj->m_papIComp, cbArray);
|
|
|
|
for (iComp = 0; iComp < ulDepth; iComp++)
|
|
{
|
|
pComponent = pBindPath->PGetComponentAtIndex (iComp);
|
|
Assert (pComponent);
|
|
|
|
hr = pComponent->HrGetINetCfgComponentInterface (
|
|
pINetCfg, pObj->m_papIComp + iComp);
|
|
|
|
if (S_OK != hr)
|
|
{
|
|
ReleaseIUnknownArray (iComp+1, (IUnknown**)pObj->m_papIComp);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
pObj->m_cpIComp = ulDepth;
|
|
|
|
// Do the standard CComCreator::CreateInstance stuff.
|
|
//
|
|
pObj->SetVoid (NULL);
|
|
pObj->InternalFinalConstructAddRef ();
|
|
hr = pObj->FinalConstruct ();
|
|
pObj->InternalFinalConstructRelease ();
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
hr = pObj->QueryInterface (IID_INetCfgBindingPath,
|
|
(VOID**)ppIPath);
|
|
|
|
// 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)
|
|
{
|
|
if (pObj->m_papIComp != pObj->m_apIComp)
|
|
{
|
|
MemFree (pObj->m_papIComp);
|
|
}
|
|
|
|
delete pObj;
|
|
}
|
|
}
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CImplINetCfgBindingPath::HrCreateInstance");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CImplINetCfgBindingPath::HrIsValidInterface (
|
|
IN DWORD dwFlags,
|
|
OUT CBindPath* pBindPath)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
|
|
HRESULT hr;
|
|
|
|
hr = m_pINetCfg->HrIsValidInterface (dwFlags);
|
|
|
|
if ((S_OK == hr) && pBindPath)
|
|
{
|
|
Assert (0 == pBindPath->CountComponents());
|
|
|
|
// When pBindPath is specified, it means the caller wants a
|
|
// CBindPath representation of the bindpath we represent.
|
|
// We have to build this using the array of INetCfgComponent
|
|
// pointer we maintain. Do this by verifying each one is valid
|
|
// and then adding its internal CComponent* to pBindPath.
|
|
//
|
|
hr = pBindPath->HrReserveRoomForComponents (m_cpIComp);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
CImplINetCfgComponent* pIComp;
|
|
CComponent* pComponent;
|
|
|
|
// For each INetCfgComponent* in our array...
|
|
//
|
|
for (UINT i = 0; i < m_cpIComp; i++)
|
|
{
|
|
pIComp = (CImplINetCfgComponent*)m_papIComp[i];
|
|
|
|
if (pIComp == NULL)
|
|
{
|
|
return(E_OUTOFMEMORY);
|
|
}
|
|
|
|
hr = pIComp->HrIsValidInterface (IF_DEFAULT);
|
|
|
|
if (S_OK != hr)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pComponent = pIComp->m_pComponent;
|
|
Assert (pComponent);
|
|
|
|
hr = pBindPath->HrAppendComponent (pComponent);
|
|
if (S_OK != hr)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CImplINetCfgBindingPath::HrIsValidInterface");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CImplINetCfgBindingPath::HrLockAndTestForValidInterface (
|
|
IN DWORD dwFlags,
|
|
OUT CBindPath* pBindPath)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
|
|
HRESULT hr;
|
|
|
|
Lock();
|
|
|
|
hr = HrIsValidInterface (dwFlags, pBindPath);
|
|
|
|
if (S_OK != hr)
|
|
{
|
|
Unlock();
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CImplINetCfgHolder::HrLockAndTestForValidInterface");
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// INetCfgBindingPath
|
|
//
|
|
|
|
STDMETHODIMP
|
|
CImplINetCfgBindingPath::IsSamePathAs (
|
|
IN INetCfgBindingPath* pIPath)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
|
|
HRESULT hr;
|
|
|
|
// Validate parameters.
|
|
//
|
|
if (FBadInPtr(pIPath))
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else
|
|
{
|
|
hr = HrLockAndTestForValidInterface (IF_DEFAULT, NULL);
|
|
if (S_OK == hr)
|
|
{
|
|
CImplINetCfgBindingPath* pOther = (CImplINetCfgBindingPath*)pIPath;
|
|
|
|
Assert (m_cpIComp);
|
|
Assert (m_papIComp);
|
|
Assert (pOther->m_cpIComp);
|
|
Assert (pOther->m_papIComp);
|
|
|
|
// Can't be the same if our length is not the same.
|
|
//
|
|
if (m_cpIComp != pOther->m_cpIComp)
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
else
|
|
{
|
|
UINT cb;
|
|
|
|
cb = m_cpIComp * sizeof(INetCfgComponent*);
|
|
|
|
hr = (0 == memcmp (
|
|
(BYTE*)(m_papIComp),
|
|
(BYTE*)(pOther->m_papIComp),
|
|
cb)) ? S_OK : S_FALSE;
|
|
}
|
|
|
|
Unlock();
|
|
}
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, (S_FALSE == hr),
|
|
"CImplINetCfgBindingPath::IsSamePathAs");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplINetCfgBindingPath::IsSubPathOf (
|
|
IN INetCfgBindingPath* pIPath)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
|
|
HRESULT hr;
|
|
|
|
// Validate parameters.
|
|
//
|
|
if (FBadInPtr(pIPath))
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else
|
|
{
|
|
hr = HrLockAndTestForValidInterface (IF_DEFAULT, NULL);
|
|
if (S_OK == hr)
|
|
{
|
|
CImplINetCfgBindingPath* pOther = (CImplINetCfgBindingPath*)pIPath;
|
|
|
|
Assert (m_cpIComp);
|
|
Assert (m_papIComp);
|
|
Assert (pOther->m_cpIComp);
|
|
Assert (pOther->m_papIComp);
|
|
|
|
// Can't be a subpath if our length is greater or equal.
|
|
//
|
|
if (m_cpIComp >= pOther->m_cpIComp)
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
else
|
|
{
|
|
UINT cb;
|
|
UINT unSkipComponents;
|
|
|
|
cb = m_cpIComp * sizeof(INetCfgComponent*);
|
|
|
|
Assert (pOther->m_cpIComp > m_cpIComp);
|
|
unSkipComponents = pOther->m_cpIComp - m_cpIComp;
|
|
|
|
hr = (0 == memcmp (
|
|
(BYTE*)(m_papIComp),
|
|
(BYTE*)(pOther->m_papIComp + unSkipComponents),
|
|
cb)) ? S_OK : S_FALSE;
|
|
}
|
|
|
|
// Special Case: NCF_DONTEXPOSELOWER
|
|
// If we're about to return false, let's check for a case like:
|
|
// is ms_ipx->adapter a subpath of ms_server->ms_ipx and return
|
|
// TRUE. For this case, it really is a subpath, but the binding
|
|
// has been broken because of NCF_DONTEXPOSELOWER.
|
|
//
|
|
// If the last component of pIPath, and the first component of
|
|
// this path both are NCF_DONTEXPOSELOWER, then consider this
|
|
// path a subpath of pIPath. This assumes that ms_nwipx and
|
|
// ms_nwnb are the only components with this characteristic.
|
|
//
|
|
if (S_FALSE == hr)
|
|
{
|
|
CImplINetCfgComponent* pIFirst;
|
|
CImplINetCfgComponent* pILast;
|
|
|
|
pIFirst = (CImplINetCfgComponent*)m_papIComp[0];
|
|
pILast = (CImplINetCfgComponent*)pOther->m_papIComp[pOther->m_cpIComp - 1];
|
|
|
|
if ((pIFirst == NULL) ||
|
|
(pILast == NULL))
|
|
{
|
|
return(E_OUTOFMEMORY);
|
|
}
|
|
|
|
if ((S_OK == pIFirst->HrIsValidInterface(IF_DEFAULT)) &&
|
|
(S_OK == pILast->HrIsValidInterface(IF_DEFAULT)))
|
|
{
|
|
Assert (pIFirst->m_pComponent);
|
|
Assert (pILast->m_pComponent);
|
|
|
|
if ((pIFirst->m_pComponent->m_dwCharacter & NCF_DONTEXPOSELOWER) &&
|
|
(pILast->m_pComponent->m_dwCharacter & NCF_DONTEXPOSELOWER))
|
|
{
|
|
if (0 == wcscmp(L"ms_nwipx", pIFirst->m_pComponent->m_pszInfId))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else if (pIFirst->m_pComponent == pILast->m_pComponent)
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// End Special case
|
|
|
|
Unlock();
|
|
}
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, (S_FALSE == hr),
|
|
"CImplINetCfgBindingPath::IsSubPathOf");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplINetCfgBindingPath::IsEnabled ()
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
|
|
HRESULT hr;
|
|
CBindPath BindPath;
|
|
|
|
hr = HrLockAndTestForValidInterface (IF_DEFAULT, &BindPath);
|
|
if (S_OK == hr)
|
|
{
|
|
Assert (m_pINetCfg);
|
|
|
|
if (m_pINetCfg->m_pNetConfig->Core.FIsBindPathDisabled (
|
|
&BindPath, IBD_MATCH_SUBPATHS_TOO))
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
Unlock();
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, S_FALSE == hr,
|
|
"CImplINetCfgBindingPath::IsEnabled");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplINetCfgBindingPath::Enable (
|
|
IN BOOL fEnable)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
|
|
HRESULT hr;
|
|
CBindPath BindPath;
|
|
|
|
hr = HrLockAndTestForValidInterface (IF_NEED_WRITE_LOCK, &BindPath);
|
|
if (S_OK == hr)
|
|
{
|
|
Assert (m_pINetCfg);
|
|
|
|
hr = m_pINetCfg->m_pNetConfig->ModifyCtx.HrEnableOrDisableBindPath (
|
|
(fEnable) ? NCN_ENABLE : NCN_DISABLE,
|
|
&BindPath,
|
|
this);
|
|
|
|
Unlock();
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CImplINetCfgBindingPath::Enable");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplINetCfgBindingPath::GetPathToken (
|
|
OUT PWSTR* ppszPathToken)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
|
|
HRESULT hr;
|
|
|
|
// Validate parameters.
|
|
//
|
|
if (FBadOutPtr(ppszPathToken))
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else
|
|
{
|
|
CBindPath BindPath;
|
|
|
|
*ppszPathToken = NULL;
|
|
|
|
hr = HrLockAndTestForValidInterface (IF_DEFAULT, &BindPath);
|
|
if (S_OK == hr)
|
|
{
|
|
ULONG cch;
|
|
|
|
cch = 0;
|
|
BindPath.FGetPathToken (NULL, &cch);
|
|
if (cch)
|
|
{
|
|
hr = HrCoTaskMemAlloc (
|
|
((cch + 1) * sizeof(WCHAR)),
|
|
(VOID**)ppszPathToken);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
BindPath.FGetPathToken (*ppszPathToken, &cch);
|
|
}
|
|
}
|
|
|
|
Unlock();
|
|
}
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CImplINetCfgBindingPath::GetPathToken");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplINetCfgBindingPath::GetOwner (
|
|
OUT INetCfgComponent** ppIComp)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
|
|
HRESULT hr;
|
|
|
|
// Validate parameters.
|
|
//
|
|
if (FBadOutPtr(ppIComp))
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else
|
|
{
|
|
*ppIComp = NULL;
|
|
|
|
hr = HrLockAndTestForValidInterface (IF_DEFAULT, NULL);
|
|
if (S_OK == hr)
|
|
{
|
|
Assert (m_cpIComp);
|
|
Assert (m_papIComp);
|
|
Assert (m_papIComp[0]);
|
|
|
|
AddRefObj (m_papIComp[0]);
|
|
*ppIComp = m_papIComp[0];
|
|
|
|
Unlock();
|
|
}
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CImplINetCfgBindingPath::GetOwner");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplINetCfgBindingPath::GetDepth (
|
|
OUT ULONG* pulDepth)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
|
|
HRESULT hr;
|
|
|
|
// Validate parameters.
|
|
//
|
|
if (FBadOutPtr(pulDepth))
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else
|
|
{
|
|
*pulDepth = NULL;
|
|
|
|
hr = HrLockAndTestForValidInterface (IF_DEFAULT, NULL);
|
|
if (S_OK == hr)
|
|
{
|
|
Assert (m_cpIComp);
|
|
|
|
*pulDepth = m_cpIComp;
|
|
|
|
Unlock();
|
|
}
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CImplINetCfgBindingPath::GetDepth");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CImplINetCfgBindingPath::EnumBindingInterfaces (
|
|
OUT IEnumNetCfgBindingInterface** ppIEnum)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
|
|
HRESULT hr;
|
|
|
|
// Validate parameters.
|
|
//
|
|
if (FBadOutPtr(ppIEnum))
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else
|
|
{
|
|
*ppIEnum = NULL;
|
|
|
|
hr = HrLockAndTestForValidInterface (IF_DEFAULT, NULL);
|
|
if (S_OK == hr)
|
|
{
|
|
hr = CImplIEnumNetCfgBindingInterface::HrCreateInstance (
|
|
m_pINetCfg,
|
|
this,
|
|
ppIEnum);
|
|
|
|
Unlock();
|
|
}
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CImplINetCfgBindingPath::EnumBindingInterfaces");
|
|
return hr;
|
|
}
|