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