801 lines
17 KiB
C++
801 lines
17 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1999.
|
|
//
|
|
// File: B I N D I N G S . C P P
|
|
//
|
|
// Contents: The basic datatypes for binding objects. Bindpaths are
|
|
// ordered collections of component pointers. Bindsets
|
|
// are a collection of bindpaths. This module implements
|
|
// the operations that are valid on binpaths and bindsets.
|
|
//
|
|
// Notes:
|
|
//
|
|
// Author: shaunco 15 Jan 1999
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <pch.h>
|
|
#pragma hdrstop
|
|
#include "bindings.h"
|
|
#include "complist.h"
|
|
#include "diagctx.h"
|
|
#include "nceh.h"
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// CBindPath -
|
|
//
|
|
|
|
bool
|
|
CBindPath::operator< (
|
|
const CBindPath& OtherPath) const
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
|
|
const_iterator iterThis;
|
|
const_iterator iterOther;
|
|
NETCLASS Class;
|
|
NETCLASS OtherClass;
|
|
|
|
for (iterThis = begin(), iterOther = OtherPath.begin();
|
|
(iterThis != end()) && (iterOther != OtherPath.end());
|
|
iterThis++, iterOther++)
|
|
{
|
|
Class = (*iterThis)->Class();
|
|
OtherClass = (*iterOther)->Class();
|
|
|
|
if (Class > OtherClass)
|
|
{
|
|
return TRUE;
|
|
}
|
|
else if (Class < OtherClass)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return size() > OtherPath.size();
|
|
}
|
|
|
|
bool
|
|
CBindPath::operator> (
|
|
const CBindPath& OtherPath) const
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
const_iterator iterThis;
|
|
const_iterator iterOther;
|
|
NETCLASS Class;
|
|
NETCLASS OtherClass;
|
|
|
|
for (iterThis = begin(), iterOther = OtherPath.begin();
|
|
(iterThis != end()) && (iterOther != OtherPath.end());
|
|
iterThis++, iterOther++)
|
|
{
|
|
Class = (*iterThis)->Class();
|
|
OtherClass = (*iterOther)->Class();
|
|
|
|
if (Class < OtherClass)
|
|
{
|
|
return TRUE;
|
|
}
|
|
else if (Class > OtherClass)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return size() < OtherPath.size();
|
|
}
|
|
|
|
BOOL
|
|
CBindPath::FAllComponentsLoadedOkayIfLoadedAtAll () const
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
CBindPath::const_iterator iter;
|
|
const CComponent* pComponent;
|
|
|
|
Assert (this);
|
|
|
|
for (iter = begin(); iter != end(); iter++)
|
|
{
|
|
pComponent = *iter;
|
|
Assert (pComponent);
|
|
|
|
if (!pComponent->Ext.FLoadedOkayIfLoadedAtAll())
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
CBindPath::FGetPathToken (
|
|
OUT PWSTR pszToken,
|
|
IN OUT ULONG* pcchToken) const
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
const_iterator iter;
|
|
const CComponent* pComponent;
|
|
ULONG cchIn;
|
|
ULONG cch;
|
|
BOOL fFirstTime;
|
|
|
|
Assert (this);
|
|
Assert (pcchToken);
|
|
|
|
if (pszToken)
|
|
{
|
|
*pszToken = 0;
|
|
}
|
|
cchIn = *pcchToken;
|
|
cch = 0;
|
|
|
|
for (iter = begin(), fFirstTime = TRUE; iter != end(); iter++)
|
|
{
|
|
if (!fFirstTime)
|
|
{
|
|
cch += 2;
|
|
if (pszToken && (cch <= cchIn))
|
|
{
|
|
wcscat (pszToken, L"->");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fFirstTime = FALSE;
|
|
}
|
|
|
|
pComponent = *iter;
|
|
Assert (pComponent);
|
|
|
|
cch += wcslen (pComponent->PszGetPnpIdOrInfId());
|
|
if (pszToken && (cch <= cchIn))
|
|
{
|
|
wcscat (pszToken, pComponent->PszGetPnpIdOrInfId());
|
|
}
|
|
}
|
|
|
|
*pcchToken = cch;
|
|
return cch <= cchIn;
|
|
}
|
|
|
|
BOOL
|
|
CBindPath::FIsSameBindPathAs (
|
|
IN const CBindPath* pOtherPath) const
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
UINT unThisSize;
|
|
UINT unOtherSize;
|
|
UINT cb;
|
|
|
|
Assert (this);
|
|
Assert (pOtherPath);
|
|
|
|
unThisSize = this->size();
|
|
unOtherSize = pOtherPath->size();
|
|
|
|
if ((0 == unThisSize) || (0 == unOtherSize) || (unThisSize != unOtherSize))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Sizes are non-zero and equal. Compare the data.
|
|
//
|
|
cb = (UINT)((BYTE*)(end()) - (BYTE*)(begin()));
|
|
Assert (cb == unThisSize * sizeof(CComponent*));
|
|
|
|
return (0 == memcmp (
|
|
(BYTE*)(this->begin()),
|
|
(BYTE*)(pOtherPath->begin()),
|
|
cb));
|
|
}
|
|
|
|
BOOL
|
|
CBindPath::FIsSubPathOf (
|
|
IN const CBindPath* pOtherPath) const
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
UINT unThisSize;
|
|
UINT unOtherSize;
|
|
UINT unSkipComponents;
|
|
UINT cb;
|
|
|
|
Assert (this);
|
|
Assert (pOtherPath);
|
|
|
|
unThisSize = this->size();
|
|
unOtherSize = pOtherPath->size();
|
|
|
|
if ((0 == unThisSize) || (0 == unOtherSize) || (unThisSize >= unOtherSize))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// This size is less than other. Compare the data starting at the
|
|
// component pointer in the other path that will have the same depth
|
|
// as this path.
|
|
//
|
|
cb = (UINT)((BYTE*)(end()) - (BYTE*)(begin()));
|
|
|
|
// The component pointer in the other path that we start comparing at
|
|
// is at an offset equal to the difference in path sizes.
|
|
//
|
|
// e.g. other path: a->b->c->d->e size=5
|
|
// this path: c->d->e size=3
|
|
// start comparing after skipping 5-3=2 components of the other path
|
|
//
|
|
Assert (unOtherSize > unThisSize);
|
|
unSkipComponents = unOtherSize - unThisSize;
|
|
|
|
return (0 == memcmp (
|
|
(BYTE*)(this->begin()),
|
|
(BYTE*)(pOtherPath->begin() + unSkipComponents),
|
|
cb));
|
|
}
|
|
|
|
HRESULT
|
|
CBindPath::HrAppendBindPath (
|
|
IN const CBindPath* pBindPath)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
HRESULT hr;
|
|
|
|
Assert (this);
|
|
Assert (pBindPath);
|
|
|
|
NC_TRY
|
|
{
|
|
insert (end(), pBindPath->begin(), pBindPath->end());
|
|
DbgVerifyBindpath ();
|
|
hr = S_OK;
|
|
}
|
|
NC_CATCH_ALL
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE, "CBindPath::HrAppendBindPath");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CBindPath::HrAppendComponent (
|
|
IN const CComponent* pComponent)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
HRESULT hr;
|
|
|
|
Assert (this);
|
|
Assert (pComponent);
|
|
Assert (!FContainsComponent (pComponent));
|
|
|
|
NC_TRY
|
|
{
|
|
push_back (const_cast<CComponent*>(pComponent));
|
|
DbgVerifyBindpath ();
|
|
hr = S_OK;
|
|
}
|
|
NC_CATCH_ALL
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE, "CBindPath::HrAppendComponent");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CBindPath::HrGetComponentsInBindPath (
|
|
IN OUT CComponentList* pComponents) const
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
HRESULT hr;
|
|
CBindPath::const_iterator iter;
|
|
const CComponent* pComponent;
|
|
|
|
Assert (this);
|
|
Assert (pComponents);
|
|
|
|
for (iter = begin(); iter != end(); iter++)
|
|
{
|
|
pComponent = *iter;
|
|
Assert (pComponent);
|
|
|
|
hr = pComponents->HrInsertComponent (pComponent,
|
|
INS_IGNORE_IF_DUP | INS_SORTED);
|
|
|
|
if (S_OK != hr)
|
|
{
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CBindPath::HrGetComponentsInBindPath");
|
|
return hr;
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CBindPath::HrInsertComponent (
|
|
IN const CComponent* pComponent)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
HRESULT hr;
|
|
|
|
Assert (this);
|
|
Assert (pComponent);
|
|
Assert (!FContainsComponent (pComponent));
|
|
|
|
NC_TRY
|
|
{
|
|
insert (begin(), const_cast<CComponent*>(pComponent));
|
|
DbgVerifyBindpath ();
|
|
hr = S_OK;
|
|
}
|
|
NC_CATCH_ALL
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE, "CBindPath::HrInsertComponent");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CBindPath::HrReserveRoomForComponents (
|
|
IN UINT cComponents)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
HRESULT hr;
|
|
|
|
NC_TRY
|
|
{
|
|
reserve (cComponents);
|
|
hr = S_OK;
|
|
}
|
|
NC_CATCH_ALL
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CBindPath::HrReserveRoomForComponents");
|
|
return hr;
|
|
}
|
|
|
|
#if DBG
|
|
VOID
|
|
CBindPath::DbgVerifyBindpath ()
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
const_iterator iter;
|
|
const_iterator iterOther;
|
|
const CComponent* pComponent;
|
|
const CComponent* pOtherComponent;
|
|
|
|
Assert (this);
|
|
|
|
// Make sure the bindpath does not contain any duplicate component
|
|
// pointers.
|
|
//
|
|
for (iter = begin(); iter != end(); iter++)
|
|
{
|
|
pComponent = *iter;
|
|
Assert (pComponent);
|
|
|
|
for (iterOther = begin(); iterOther != end(); iterOther++)
|
|
{
|
|
pOtherComponent = *iterOther;
|
|
Assert (pOtherComponent);
|
|
|
|
if (iter == iterOther)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Assert (pComponent != pOtherComponent);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// CBindingSet -
|
|
//
|
|
|
|
VOID
|
|
CBindingSet::Printf (
|
|
TRACETAGID ttid,
|
|
PCSTR pszPrefixLine) const
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
WCHAR pszBuf [1024];
|
|
WCHAR* pch;
|
|
ULONG cch;
|
|
|
|
Assert (this);
|
|
|
|
if (pszPrefixLine)
|
|
{
|
|
g_pDiagCtx->Printf (ttid, pszPrefixLine);
|
|
}
|
|
|
|
const CBindPath* pBindPath;
|
|
INT nIndex = 1;
|
|
|
|
for (pBindPath = begin(); pBindPath != end(); pBindPath++, nIndex++)
|
|
{
|
|
pch = pszBuf + wsprintfW (pszBuf, L"%2i: ", nIndex);
|
|
|
|
cch = celems(pszBuf) - wcslen(pszBuf) - 1;
|
|
if (pBindPath->FGetPathToken (pch, &cch))
|
|
{
|
|
g_pDiagCtx->Printf (ttid, "%S\n", pszBuf);
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
CBindingSet::FContainsBindPath (
|
|
IN const CBindPath* pBindPathToCheckFor) const
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
const CBindPath* pBindPath;
|
|
|
|
Assert (this);
|
|
Assert (pBindPathToCheckFor);
|
|
|
|
for (pBindPath = begin(); pBindPath != end(); pBindPath++)
|
|
{
|
|
if (pBindPath->FIsSameBindPathAs (pBindPathToCheckFor))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
CBindingSet::FContainsComponent (
|
|
IN const CComponent* pComponent) const
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
const CBindPath* pBindPath;
|
|
|
|
Assert (this);
|
|
Assert (pComponent);
|
|
|
|
for (pBindPath = begin(); pBindPath != end(); pBindPath++)
|
|
{
|
|
if (pBindPath->FContainsComponent (pComponent))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
HRESULT
|
|
CBindingSet::HrAppendBindingSet (
|
|
IN const CBindingSet* pBindSet)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
HRESULT hr;
|
|
const CBindPath* pSrcPath;
|
|
|
|
Assert (this);
|
|
Assert (pBindSet);
|
|
|
|
hr = S_OK;
|
|
|
|
NC_TRY
|
|
{
|
|
for (pSrcPath = pBindSet->begin();
|
|
pSrcPath != pBindSet->end();
|
|
pSrcPath++)
|
|
{
|
|
if (!FContainsBindPath (pSrcPath))
|
|
{
|
|
insert (end(), *pSrcPath);
|
|
}
|
|
}
|
|
}
|
|
NC_CATCH_ALL
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE, "CBindingSet::HrAppendBindingSet");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CBindingSet::HrAddBindPath (
|
|
IN const CBindPath* pBindPath,
|
|
IN DWORD dwFlags)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
HRESULT hr;
|
|
|
|
Assert (this);
|
|
Assert (pBindPath);
|
|
Assert (!pBindPath->FIsEmpty());
|
|
Assert ((dwFlags & INS_ASSERT_IF_DUP) || (dwFlags & INS_IGNORE_IF_DUP));
|
|
Assert ((dwFlags & INS_APPEND) || (dwFlags & INS_INSERT));
|
|
Assert (!(INS_SORTED & dwFlags) && !(INS_NON_SORTED & dwFlags));
|
|
|
|
if (FContainsBindPath (pBindPath))
|
|
{
|
|
// If the caller didn't tell us to ignore duplicates, we assert
|
|
// if there is one because it is bad, bad, bad to have duplicate
|
|
// bindpaths in the set.
|
|
//
|
|
// If we have a dup, we want the caller to be aware that it
|
|
// is possible, and pass us the flag telling us to ignore it.
|
|
// Otherwise, we assert to let them know. (And we still ignore
|
|
// it.)
|
|
Assert (dwFlags & INS_IGNORE_IF_DUP);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
NC_TRY
|
|
{
|
|
// Either insert the bindpath or append it.
|
|
//
|
|
iterator iter = begin();
|
|
|
|
if (dwFlags & INS_APPEND)
|
|
{
|
|
iter = end();
|
|
}
|
|
|
|
insert (iter, *pBindPath);
|
|
hr = S_OK;
|
|
}
|
|
NC_CATCH_ALL
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE, "CBindingSet::HrAddBindPath");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CBindingSet::HrAddBindPathsInSet1ButNotInSet2 (
|
|
IN const CBindingSet* pSet1,
|
|
IN const CBindingSet* pSet2)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
HRESULT hr;
|
|
const CBindPath* pBindPath;
|
|
|
|
Assert (this);
|
|
Assert (pSet1);
|
|
Assert (pSet2);
|
|
Assert ((this != pSet1) && (this != pSet2));
|
|
|
|
hr = S_OK;
|
|
|
|
for (pBindPath = pSet1->begin();
|
|
pBindPath != pSet1->end();
|
|
pBindPath++)
|
|
{
|
|
if (pSet2->FContainsBindPath (pBindPath))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
hr = HrAddBindPath (pBindPath, INS_IGNORE_IF_DUP | INS_APPEND);
|
|
if (S_OK != hr)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CBindingSet::HrAddBindPathsInSet1ButNotInSet2");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CBindingSet::HrCopyBindingSet (
|
|
IN const CBindingSet* pSourceSet)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
HRESULT hr;
|
|
|
|
Assert (this);
|
|
Assert (pSourceSet);
|
|
|
|
NC_TRY
|
|
{
|
|
*this = *pSourceSet;
|
|
hr = S_OK;
|
|
}
|
|
NC_CATCH_ALL
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE, "CBindingSet::HrCopyBindingSet");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CBindingSet::HrGetAffectedComponentsInBindingSet (
|
|
IN OUT CComponentList* pComponents) const
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
HRESULT hr;
|
|
const CBindPath* pBindPath;
|
|
|
|
Assert (this);
|
|
Assert (pComponents);
|
|
|
|
hr = S_OK;
|
|
|
|
for (pBindPath = begin(); pBindPath != end(); pBindPath++)
|
|
{
|
|
hr = pComponents->HrInsertComponent (pBindPath->POwner(),
|
|
INS_IGNORE_IF_DUP | INS_SORTED);
|
|
|
|
if (S_OK != hr)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// For bindpaths from a protocol to an adpater, we want to
|
|
// add the adapter to the component list because it will need
|
|
// to have its upper bind changed.
|
|
//
|
|
if (pBindPath->CountComponents() == 2)
|
|
{
|
|
const CComponent* pAdapter;
|
|
|
|
pAdapter = pBindPath->PLastComponent();
|
|
if (FIsEnumerated (pAdapter->Class()))
|
|
{
|
|
hr = pComponents->HrInsertComponent (pAdapter,
|
|
INS_IGNORE_IF_DUP | INS_SORTED);
|
|
|
|
if (S_OK != hr)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CBindingSet::HrGetAffectedComponentsInBindingSet");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CBindingSet::HrReserveRoomForBindPaths (
|
|
IN UINT cBindPaths)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
HRESULT hr;
|
|
|
|
NC_TRY
|
|
{
|
|
reserve (cBindPaths);
|
|
hr = S_OK;
|
|
}
|
|
NC_CATCH_ALL
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CBindingSet::HrReserveRoomForBindPaths");
|
|
return hr;
|
|
}
|
|
|
|
VOID
|
|
CBindingSet::RemoveBindPath (
|
|
IN const CBindPath* pBindPath)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
CBindPath* pScan;
|
|
|
|
for (pScan = begin(); pScan != end(); pScan++)
|
|
{
|
|
if (pScan->FIsSameBindPathAs (pBindPath))
|
|
{
|
|
erase (pScan);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
CBindingSet::RemoveBindPathsWithComponent (
|
|
IN const CComponent* pComponent)
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
CBindPath* pBindPath;
|
|
|
|
Assert (this);
|
|
Assert (pComponent);
|
|
|
|
pBindPath = begin();
|
|
while (pBindPath != end())
|
|
{
|
|
if (pBindPath->FContainsComponent(pComponent))
|
|
{
|
|
erase (pBindPath);
|
|
}
|
|
else
|
|
{
|
|
pBindPath++;
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
CBindingSet::RemoveSubpaths ()
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
CBindPath* pCandidate;
|
|
CBindPath* pBindPath;
|
|
|
|
Assert (this);
|
|
|
|
for (pBindPath = begin(); pBindPath != end(); pBindPath++)
|
|
{
|
|
pCandidate = begin();
|
|
|
|
while (pCandidate != end())
|
|
{
|
|
if (pCandidate->FIsSubPathOf (pBindPath))
|
|
{
|
|
// FIsSubPathOf returns FALSE when asked if a bindpath
|
|
// is a subpath of itself. (Set-theorectially, this is
|
|
// incorrect, but having it return FALSE for this case
|
|
// prevents us from having to make another check.
|
|
//
|
|
Assert (pCandidate != pBindPath);
|
|
|
|
erase (pCandidate);
|
|
|
|
// If erasing a bindpath that occurs before the current
|
|
// outer loop enumerator, we need to back it up because
|
|
// the erase would move everything up by one, but we still
|
|
// want to finish the inner loop for this current outer
|
|
// bindpath.
|
|
//
|
|
if (pCandidate < pBindPath)
|
|
{
|
|
pBindPath--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pCandidate++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
CBindingSet::SortForPnpBind ()
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
// Sort where bindpaths closes to the adapters come first.
|
|
//
|
|
sort<iterator> (begin(), end(), greater<CBindPath>());
|
|
}
|
|
|
|
VOID
|
|
CBindingSet::SortForPnpUnbind ()
|
|
{
|
|
TraceFileFunc(ttidNetCfgBind);
|
|
// Sort where bindpaths furthest from the adapters come first.
|
|
//
|
|
sort<iterator> (begin(), end(), less<CBindPath>());
|
|
}
|
|
|