mirror of https://github.com/tongzx/nt5src
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.
1039 lines
32 KiB
1039 lines
32 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1999.
|
|
//
|
|
// File: R E G B I N D . C P P
|
|
//
|
|
// Contents: This module is responsible for writing bindings to the
|
|
// registry so that they may be consumed by NDIS and TDI.
|
|
//
|
|
// Notes:
|
|
//
|
|
// Author: shaunco 1 Feb 1999
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "pch.h"
|
|
#pragma hdrstop
|
|
#include "filtdevs.h"
|
|
#include "lanamap.h"
|
|
#include "netcfg.h"
|
|
#include "ncreg.h"
|
|
#include "ndispnp.h"
|
|
|
|
|
|
HRESULT
|
|
HrRegSetMultiSzAndLogDifference (
|
|
IN HKEY hkey,
|
|
IN PCWSTR pszValueName,
|
|
IN PCWSTR pmszValue,
|
|
IN const CComponent* pComponent
|
|
)
|
|
{
|
|
// Only log the difference if we're operating under the appropriate
|
|
// diagnostic context.
|
|
//
|
|
if (g_pDiagCtx->Flags() & DF_REPAIR_REGISTRY_BINDINGS)
|
|
{
|
|
HRESULT hr;
|
|
DWORD cbCurrent;
|
|
PWSTR pmszCurrent = (PWSTR)g_pDiagCtx->GetScratchBuffer(&cbCurrent);
|
|
|
|
// Read the current value into the diagnostic context's scratch
|
|
// buffer.
|
|
//
|
|
hr = HrRegQueryTypeSzBuffer (hkey, pszValueName, REG_MULTI_SZ,
|
|
pmszCurrent, &cbCurrent);
|
|
|
|
// Grow the scratch buffer and retry if the value is bigger than
|
|
// than will fit.
|
|
//
|
|
if ((HRESULT_FROM_WIN32(ERROR_MORE_DATA) == hr) ||
|
|
((NULL == pmszCurrent) && (S_OK == hr)))
|
|
{
|
|
pmszCurrent = (PWSTR)g_pDiagCtx->GrowScratchBuffer(&cbCurrent);
|
|
if (pmszCurrent)
|
|
{
|
|
hr = HrRegQueryTypeSzBuffer (hkey, pszValueName, REG_MULTI_SZ,
|
|
pmszCurrent, &cbCurrent);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
DWORD cbValue = CbOfMultiSzAndTermSafe(pmszValue);
|
|
|
|
// Compare the values and log if they are different.
|
|
//
|
|
if ((cbValue != cbCurrent) ||
|
|
(memcmp(pmszValue, pmszCurrent, cbCurrent)))
|
|
{
|
|
FILE *LogFile = g_pDiagCtx->LogFile();
|
|
|
|
fprintf(LogFile,
|
|
"reset Linkage\\%S for %S. bad value was:\n",
|
|
pszValueName, pComponent->PszGetPnpIdOrInfId());
|
|
|
|
fprintf(LogFile, " REG_MULTI_SZ =\n");
|
|
if (*pmszCurrent)
|
|
{
|
|
while (*pmszCurrent)
|
|
{
|
|
fprintf(LogFile, " %S\n", pmszCurrent);
|
|
pmszCurrent += wcslen(pmszCurrent) + 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf(LogFile, " <empty>\n");
|
|
}
|
|
fprintf(LogFile, "\n");
|
|
}
|
|
else
|
|
{
|
|
// The value is correct. No need to write it.
|
|
//
|
|
return S_OK;
|
|
}
|
|
}
|
|
else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
|
|
{
|
|
fprintf(g_pDiagCtx->LogFile(),
|
|
"added Linkage\\%S for %S\n",
|
|
pszValueName, pComponent->PszGetPnpIdOrInfId());
|
|
}
|
|
}
|
|
|
|
// N.B. success or failure of the diagnostic portion of this routine
|
|
// (above) should NOT affect the return value of this routine.
|
|
//
|
|
return HrRegSetMultiSz (hkey, pszValueName, pmszValue);
|
|
}
|
|
|
|
HRESULT
|
|
HrCreateLinkageKey (
|
|
IN const CComponent* pComponent,
|
|
IN CFilterDevice* pDevice,
|
|
IN HDEVINFO hdi,
|
|
OUT HKEY* phKey)
|
|
{
|
|
HRESULT hr = E_UNEXPECTED;
|
|
HKEY hkeyParent = NULL;
|
|
CONST REGSAM samDesired = KEY_READ | KEY_WRITE;
|
|
|
|
Assert (pComponent || pDevice);
|
|
Assert (!(pComponent && pDevice));
|
|
Assert (FIff(pDevice, hdi));
|
|
Assert (phKey);
|
|
|
|
if (pComponent)
|
|
{
|
|
// Open the parent of the linkage key. This is the instance key if
|
|
// the component is enumerated or does not have a service.
|
|
//
|
|
if (FIsEnumerated (pComponent->Class()) || !pComponent->FHasService())
|
|
{
|
|
hr = pComponent->HrOpenInstanceKey (samDesired,
|
|
&hkeyParent,
|
|
NULL, NULL);
|
|
|
|
if ((S_OK == hr) && FIsEnumerated (pComponent->Class()))
|
|
{
|
|
// Write out the netcfg instance id. Connections will use
|
|
// this to determine if the device is known by net config
|
|
// and will create the <instance guid> key under network
|
|
// to store its connection info. We only need to do this
|
|
// for enumerated components.
|
|
//
|
|
hr = HrRegSetGuidAsSz (hkeyParent, L"NetCfgInstanceId",
|
|
pComponent->m_InstanceGuid);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = pComponent->HrOpenServiceKey (samDesired, &hkeyParent);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Assert (pDevice);
|
|
Assert (hdi);
|
|
|
|
hr = HrSetupDiOpenDevRegKey (
|
|
hdi,
|
|
&pDevice->m_deid,
|
|
DICS_FLAG_GLOBAL,
|
|
0,
|
|
DIREG_DRV,
|
|
samDesired,
|
|
&hkeyParent);
|
|
}
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
Assert (hkeyParent);
|
|
|
|
hr = HrRegCreateKeyEx (
|
|
hkeyParent,
|
|
L"Linkage",
|
|
REG_OPTION_NON_VOLATILE,
|
|
samDesired,
|
|
NULL,
|
|
phKey,
|
|
NULL);
|
|
|
|
RegCloseKey (hkeyParent);
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr,
|
|
(SPAPI_E_NO_SUCH_DEVINST == hr),
|
|
"HrCreateLinkageKey");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
HrWriteLinkageValues (
|
|
IN const CComponent* pComponent,
|
|
IN PCWSTR pmszBind,
|
|
IN PCWSTR pmszExport,
|
|
IN PCWSTR pmszRoute)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hkeyLinkage;
|
|
PCWSTR pmsz;
|
|
|
|
Assert (pmszBind);
|
|
Assert (pmszExport);
|
|
Assert (pmszRoute);
|
|
|
|
g_pDiagCtx->Printf (ttidBeDiag, " %S (%S)\n",
|
|
pComponent->Ext.PszBindName(),
|
|
pComponent->PszGetPnpIdOrInfId());
|
|
|
|
if (FIsEnumerated (pComponent->Class()))
|
|
{
|
|
g_pDiagCtx->Printf (ttidBeDiag, " UpperBind:\n");
|
|
}
|
|
else
|
|
{
|
|
g_pDiagCtx->Printf (ttidBeDiag, " Bind:\n");
|
|
}
|
|
|
|
pmsz = pmszBind;
|
|
while (*pmsz)
|
|
{
|
|
g_pDiagCtx->Printf (ttidBeDiag, " %S\n", pmsz);
|
|
pmsz += wcslen (pmsz) + 1;
|
|
}
|
|
|
|
g_pDiagCtx->Printf (ttidBeDiag, " Export:\n");
|
|
pmsz = pmszExport;
|
|
while (*pmsz)
|
|
{
|
|
g_pDiagCtx->Printf (ttidBeDiag, " %S\n", pmsz);
|
|
pmsz += wcslen (pmsz) + 1;
|
|
}
|
|
g_pDiagCtx->Printf (ttidBeDiag, "\n");
|
|
|
|
hr = HrCreateLinkageKey (pComponent, NULL, NULL, &hkeyLinkage);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
// For enumerated components, write RootDevice, UpperBind, and Export.
|
|
// For non-enumerated components, write Bind and Export.
|
|
//
|
|
if (FIsEnumerated (pComponent->Class()))
|
|
{
|
|
// Create the root device multi-sz from the bindname.
|
|
//
|
|
WCHAR mszRootDevice [_MAX_PATH];
|
|
wcscpy (mszRootDevice, pComponent->Ext.PszBindName());
|
|
mszRootDevice [wcslen(mszRootDevice) + 1] = 0;
|
|
|
|
hr = HrRegSetMultiSzAndLogDifference (
|
|
hkeyLinkage, L"RootDevice", mszRootDevice, pComponent);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
hr = HrRegSetMultiSzAndLogDifference (
|
|
hkeyLinkage, L"UpperBind", pmszBind, pComponent);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HrRegSetMultiSzAndLogDifference (
|
|
hkeyLinkage, L"Bind", pmszBind, pComponent);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
hr = HrRegSetMultiSzAndLogDifference (
|
|
hkeyLinkage, L"Route", pmszRoute, pComponent);
|
|
}
|
|
}
|
|
|
|
if ((S_OK == hr) && *pmszExport)
|
|
{
|
|
hr = HrRegSetMultiSzAndLogDifference (
|
|
hkeyLinkage, L"Export", pmszExport, pComponent);
|
|
}
|
|
|
|
RegCloseKey (hkeyLinkage);
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr,
|
|
(SPAPI_E_NO_SUCH_DEVINST == hr),
|
|
"HrWriteLinkageValues");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
HrWriteFilterDeviceLinkage (
|
|
IN CFilterDevice* pDevice,
|
|
IN HDEVINFO hdi,
|
|
IN PCWSTR pmszExport,
|
|
IN PCWSTR pmszRootDevice,
|
|
IN PCWSTR pmszUpperBind)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hkeyLinkage;
|
|
PCWSTR pmsz;
|
|
|
|
g_pDiagCtx->Printf (ttidBeDiag, " %S filter over %S adapter\n",
|
|
pDevice->m_pFilter->m_pszInfId,
|
|
pDevice->m_pAdapter->m_pszPnpId);
|
|
|
|
g_pDiagCtx->Printf (ttidBeDiag, " Export:\n");
|
|
pmsz = pmszExport;
|
|
while (*pmsz)
|
|
{
|
|
g_pDiagCtx->Printf (ttidBeDiag, " %S\n", pmsz);
|
|
pmsz += wcslen (pmsz) + 1;
|
|
}
|
|
|
|
g_pDiagCtx->Printf (ttidBeDiag, " RootDevice:\n");
|
|
pmsz = pmszRootDevice;
|
|
while (*pmsz)
|
|
{
|
|
g_pDiagCtx->Printf (ttidBeDiag, " %S\n", pmsz);
|
|
pmsz += wcslen (pmsz) + 1;
|
|
}
|
|
|
|
g_pDiagCtx->Printf (ttidBeDiag, " UpperBind:\n");
|
|
pmsz = pmszUpperBind;
|
|
while (*pmsz)
|
|
{
|
|
g_pDiagCtx->Printf (ttidBeDiag, " %S\n", pmsz);
|
|
pmsz += wcslen (pmsz) + 1;
|
|
}
|
|
g_pDiagCtx->Printf (ttidBeDiag, "\n");
|
|
|
|
hr = HrCreateLinkageKey (NULL, pDevice, hdi, &hkeyLinkage);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
hr = HrRegSetMultiSz (hkeyLinkage, L"Export", pmszExport);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
hr = HrRegSetMultiSz (hkeyLinkage, L"RootDevice", pmszRootDevice);
|
|
}
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
hr = HrRegSetMultiSz (hkeyLinkage, L"UpperBind", pmszUpperBind);
|
|
}
|
|
|
|
// Delete values used by the previous binding engine that are
|
|
// not needed any longer.
|
|
//
|
|
RegDeleteValue (hkeyLinkage, L"BindPath");
|
|
RegDeleteValue (hkeyLinkage, L"Bind");
|
|
RegDeleteValue (hkeyLinkage, L"Route");
|
|
RegDeleteKey (hkeyLinkage, L"Disabled");
|
|
|
|
RegCloseKey (hkeyLinkage);
|
|
}
|
|
|
|
// Now write to the standard filter parameter registry layout under
|
|
// the filter's service key.
|
|
//
|
|
|
|
if (pDevice->m_pFilter->Ext.PszService())
|
|
{
|
|
HKEY hkeyAdapterParams;
|
|
WCHAR szRegPath [_MAX_PATH];
|
|
|
|
Assert (pDevice->m_pFilter->Ext.PszService());
|
|
Assert (pDevice->m_pAdapter->Ext.PszBindName());
|
|
|
|
wsprintfW (
|
|
szRegPath,
|
|
L"System\\CurrentControlSet\\Services\\%s\\Parameters\\Adapters\\%s",
|
|
pDevice->m_pFilter->Ext.PszService(),
|
|
pDevice->m_pAdapter->Ext.PszBindName());
|
|
|
|
hr = HrRegCreateKeyEx (
|
|
HKEY_LOCAL_MACHINE,
|
|
szRegPath,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_WRITE,
|
|
NULL,
|
|
&hkeyAdapterParams,
|
|
NULL);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
// UpperBindings is a REG_SZ, not a REG_MULTI_SZ.
|
|
//
|
|
hr = HrRegSetSz (hkeyAdapterParams, L"UpperBindings", pmszExport);
|
|
|
|
RegCloseKey (hkeyAdapterParams);
|
|
}
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE, "HrWriteFilterDeviceLinkage");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
HrWriteFilteredAdapterUpperBind (
|
|
IN const CComponent* pAdapter,
|
|
IN PCWSTR pmszUpperBind)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hkeyLinkage;
|
|
|
|
hr = HrCreateLinkageKey (pAdapter, NULL, NULL, &hkeyLinkage);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
hr = HrRegSetMultiSz (hkeyLinkage, L"UpperBind", pmszUpperBind);
|
|
|
|
RegCloseKey (hkeyLinkage);
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE, "HrWriteFilteredAdapterUpperBind");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CRegistryBindingsContext::HrPrepare (
|
|
IN CNetConfig* pNetConfig)
|
|
{
|
|
HRESULT hr;
|
|
|
|
Assert (pNetConfig);
|
|
m_pNetConfig = pNetConfig;
|
|
|
|
hr = m_BindValue.HrReserveBytes (4096);
|
|
if (S_OK != hr)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = m_ExportValue.HrReserveBytes (4096);
|
|
if (S_OK != hr)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = m_RouteValue.HrReserveBytes (4096);
|
|
if (S_OK != hr)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
// Ensure all of the external data for all components is loaded.
|
|
//
|
|
hr = m_pNetConfig->HrEnsureExternalDataLoadedForAllComponents ();
|
|
if (S_OK != hr)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
// Ensure all of the notify objects have been initialized.
|
|
//
|
|
hr = m_pNetConfig->Notify.HrEnsureNotifyObjectsInitialized ();
|
|
if (S_OK != hr)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CRegistryBindingsContext::HrDeleteBindingsForComponent (
|
|
IN const CComponent* pComponent)
|
|
{
|
|
return HrWriteLinkageValues (pComponent, L"", L"", L"");
|
|
}
|
|
|
|
HRESULT
|
|
CRegistryBindingsContext::HrGetAdapterUpperBindValue (
|
|
IN const CComponent* pAdapter)
|
|
{
|
|
HRESULT hr;
|
|
const CBindPath* pBindPath;
|
|
|
|
m_BindValue.Clear();
|
|
|
|
// Get the upper bindings of the component. This returns a bindset
|
|
// with binpaths only 2 levels deep. That is, the bindpaths begin
|
|
// with the components one level above pComponent.
|
|
//
|
|
hr = m_pNetConfig->Core.HrGetComponentUpperBindings (
|
|
pAdapter,
|
|
GBF_PRUNE_DISABLED_BINDINGS,
|
|
&m_BindSet);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
for (pBindPath = m_BindSet.begin();
|
|
pBindPath != m_BindSet.end();
|
|
pBindPath++)
|
|
{
|
|
// Don't put filters in the UpperBind of an adapter.
|
|
//
|
|
if (pBindPath->POwner()->FIsFilter())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
hr = m_BindValue.HrCopyString (
|
|
pBindPath->POwner()->Ext.PszBindName());
|
|
if (S_OK != hr)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
hr = m_BindValue.HrCopyString (L"");
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CRegistryBindingsContext::HrGetAdapterUpperBindValue");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CRegistryBindingsContext::HrWriteBindingsForComponent (
|
|
IN const CComponent* pComponent)
|
|
{
|
|
HRESULT hr;
|
|
const CBindPath* pBindPath;
|
|
CBindPath::const_iterator iter;
|
|
const CComponent* pUpper;
|
|
const CComponent* pLower;
|
|
WCHAR szBind [_MAX_BIND_LENGTH];
|
|
WCHAR szExport [_MAX_BIND_LENGTH];
|
|
WCHAR szRoute [_MAX_BIND_LENGTH];
|
|
PWCHAR pchBind;
|
|
PWCHAR pchExport;
|
|
|
|
Assert (pComponent);
|
|
pComponent->Ext.DbgVerifyExternalDataLoaded ();
|
|
|
|
// If the component is not bindable, we have nothing to do.
|
|
//
|
|
if (!pComponent->FIsBindable())
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
m_BindValue.Clear ();
|
|
m_ExportValue.Clear ();
|
|
m_RouteValue.Clear ();
|
|
|
|
wcscpy (szExport, L"\\Device\\");
|
|
wcscat (szExport, pComponent->Ext.PszBindName());
|
|
hr = m_ExportValue.HrCopyString (szExport);
|
|
Assert (S_OK == hr);
|
|
hr = m_ExportValue.HrCopyString (L"");
|
|
Assert (S_OK == hr);
|
|
|
|
if (FIsEnumerated (pComponent->Class()))
|
|
{
|
|
// UpperBind
|
|
//
|
|
hr = HrGetAdapterUpperBindValue (pComponent);
|
|
}
|
|
else
|
|
{
|
|
// Bind, Export
|
|
//
|
|
hr = m_pNetConfig->Core.HrGetComponentBindings (
|
|
pComponent,
|
|
GBF_PRUNE_DISABLED_BINDINGS,
|
|
&m_BindSet);
|
|
|
|
if ((S_OK == hr) && (m_BindSet.CountBindPaths() > 0))
|
|
{
|
|
// Since the component has bindings, it's export value will be
|
|
// different from the default one we initialized with above.
|
|
//
|
|
m_ExportValue.Clear ();
|
|
|
|
for (pBindPath = m_BindSet.begin();
|
|
pBindPath != m_BindSet.end();
|
|
pBindPath++)
|
|
{
|
|
Assert (pBindPath->CountComponents() > 1);
|
|
|
|
wcscpy (szBind, L"\\Device\\");
|
|
wcscpy (szExport, L"\\Device\\");
|
|
*szRoute = 0;
|
|
|
|
for (iter = pBindPath->begin();
|
|
iter != pBindPath->end();
|
|
iter++)
|
|
{
|
|
pUpper = *iter;
|
|
Assert (pUpper);
|
|
|
|
// For the bind value, skip the first component in each
|
|
// path because it is the component we are writing the
|
|
// bindings for.
|
|
//
|
|
if (iter != pBindPath->begin())
|
|
{
|
|
Assert (wcslen(szBind) + 1 +
|
|
wcslen(pUpper->Ext.PszBindName())
|
|
< celems(szBind));
|
|
|
|
// If this isn't the first component to come after
|
|
// \Device\, add underscores to seperate the
|
|
// components.
|
|
//
|
|
if (iter != (pBindPath->begin() + 1))
|
|
{
|
|
wcscat (szBind, L"_");
|
|
wcscat (szRoute, L" ");
|
|
}
|
|
wcscat (szBind, pUpper->Ext.PszBindName());
|
|
|
|
wcscat (szRoute, L"\"");
|
|
wcscat (szRoute, pUpper->Ext.PszBindName());
|
|
wcscat (szRoute, L"\"");
|
|
}
|
|
|
|
Assert (wcslen(szExport) + 1 +
|
|
wcslen(pUpper->Ext.PszBindName())
|
|
< celems(szExport));
|
|
|
|
// If this isn't the first component to come after
|
|
// \Device\, add underscores to seperate the
|
|
// components.
|
|
//
|
|
if (iter != pBindPath->begin())
|
|
{
|
|
wcscat (szExport, L"_");
|
|
}
|
|
wcscat (szExport, pUpper->Ext.PszBindName());
|
|
|
|
// If the next component in the bindpath is the last
|
|
// component, it is an adapter (by convention). Check
|
|
// to see if there are multiple interfaces to be expanded
|
|
// for the current component over this adapter.
|
|
//
|
|
if ((iter + 1) == (pBindPath->end() - 1))
|
|
{
|
|
DWORD cInterfaces;
|
|
GUID* pguidInterfaceIds;
|
|
|
|
pLower = *(iter + 1);
|
|
|
|
hr = pUpper->Notify.HrGetInterfaceIdsForAdapter (
|
|
m_pNetConfig->Notify.PINetCfg(),
|
|
pLower,
|
|
&cInterfaces,
|
|
&pguidInterfaceIds);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (cInterfaces)
|
|
{
|
|
Assert (pguidInterfaceIds);
|
|
|
|
if (iter != pBindPath->begin())
|
|
{
|
|
wcscat (szBind, L"_");
|
|
pchBind = szBind + wcslen(szBind);
|
|
Assert (wcslen(szBind) +
|
|
c_cchGuidWithTerm < celems(szBind));
|
|
}
|
|
else
|
|
{
|
|
// The first component in the bindpath is
|
|
// one that has multiple interfaces over the
|
|
// adapter. The bind value should be as
|
|
// normal, the export value will have the
|
|
// expand interfaces.
|
|
//
|
|
Assert (wcslen(szBind) +
|
|
wcslen(pLower->Ext.PszBindName())
|
|
< celems(szBind));
|
|
|
|
wcscat (szBind, pLower->Ext.PszBindName());
|
|
|
|
hr = m_BindValue.HrCopyString (szBind);
|
|
if (S_OK != hr)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
wcscat (szExport, L"_");
|
|
pchExport = szExport + wcslen(szExport);
|
|
Assert (wcslen(szExport) +
|
|
c_cchGuidWithTerm < celems(szExport));
|
|
|
|
for (UINT i = 0; i < cInterfaces; i++)
|
|
{
|
|
if (iter != pBindPath->begin())
|
|
{
|
|
StringFromGUID2 (
|
|
pguidInterfaceIds[i],
|
|
pchBind, c_cchGuidWithTerm);
|
|
|
|
hr = m_BindValue.HrCopyString (szBind);
|
|
if (S_OK != hr)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
StringFromGUID2 (
|
|
pguidInterfaceIds[i],
|
|
pchExport, c_cchGuidWithTerm);
|
|
|
|
hr = m_ExportValue.HrCopyString (szExport);
|
|
if (S_OK != hr)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
CoTaskMemFree (pguidInterfaceIds);
|
|
|
|
if (iter != pBindPath->begin())
|
|
{
|
|
wcscat (szRoute, L" ");
|
|
}
|
|
wcscat (szRoute, L"\"");
|
|
wcscat (szRoute, pLower->Ext.PszBindName());
|
|
wcscat (szRoute, L"\"");
|
|
|
|
hr = m_RouteValue.HrCopyString (szRoute);
|
|
if (S_OK != hr)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// We only allow one component in a bindpath
|
|
// to support mutliple interfaces and it always
|
|
// comes at the end of the bindpath. Therefore,
|
|
// after expanding them, we are done with the
|
|
// bindpath and proceed to the next. (Hence, the
|
|
// 'break').
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If we exited the loop because we traversed the entire
|
|
// bindpath (as opposed to expanding multiple interfaces,
|
|
// where we would have stopped short), then add the bind
|
|
// and export strings for this bindpath to the buffer and
|
|
// proceed to the next bindpath.
|
|
//
|
|
if (iter == pBindPath->end())
|
|
{
|
|
hr = m_BindValue.HrCopyString (szBind);
|
|
if (S_OK != hr)
|
|
{
|
|
break;
|
|
}
|
|
|
|
hr = m_ExportValue.HrCopyString (szExport);
|
|
if (S_OK != hr)
|
|
{
|
|
break;
|
|
}
|
|
|
|
hr = m_RouteValue.HrCopyString (szRoute);
|
|
if (S_OK != hr)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// The bind and export values are multi-sz, so make sure they
|
|
// are double null-terminiated.
|
|
//
|
|
hr = m_BindValue.HrCopyString (L"");
|
|
if (S_OK == hr)
|
|
{
|
|
hr = m_ExportValue.HrCopyString (L"");
|
|
}
|
|
if (S_OK == hr)
|
|
{
|
|
hr = m_RouteValue.HrCopyString (L"");
|
|
}
|
|
}
|
|
|
|
// Special case: NCF_DONTEXPOSELOWER
|
|
//
|
|
if ((S_OK == hr) &&
|
|
((pComponent->m_dwCharacter & NCF_DONTEXPOSELOWER) ||
|
|
(0 == wcscmp(L"ms_nwspx", pComponent->m_pszInfId))))
|
|
{
|
|
wcscpy (szExport, L"\\Device\\");
|
|
wcscat (szExport, pComponent->Ext.PszBindName());
|
|
|
|
m_ExportValue.Clear ();
|
|
hr = m_ExportValue.HrCopyString (szExport);
|
|
Assert (S_OK == hr);
|
|
hr = m_ExportValue.HrCopyString (L"");
|
|
Assert (S_OK == hr);
|
|
}
|
|
// End Special case
|
|
}
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
// Need to write out lanamap before writing new bindings since
|
|
// we need the old binding information to persist lana numbers.
|
|
//
|
|
if (0 == wcscmp (pComponent->m_pszInfId, L"ms_netbios"))
|
|
{
|
|
(VOID) HrUpdateLanaConfig (
|
|
m_pNetConfig->Core.Components,
|
|
(PCWSTR)m_BindValue.PbBuffer(),
|
|
m_BindSet.CountBindPaths());
|
|
}
|
|
|
|
hr = HrWriteLinkageValues (
|
|
pComponent,
|
|
(PCWSTR)m_BindValue.PbBuffer(),
|
|
(PCWSTR)m_ExportValue.PbBuffer(),
|
|
(PCWSTR)m_RouteValue.PbBuffer());
|
|
|
|
if(S_OK == hr)
|
|
{
|
|
// mbend June 20, 2000
|
|
// RAID 23275: Default gateway isn't respecting the adapter order specified under connections->advanced->properties
|
|
// Notify NDIS when the binding list for a component changes.
|
|
//
|
|
UNICODE_STRING LowerComponent;
|
|
UNICODE_STRING UpperComponent;
|
|
UNICODE_STRING BindList;
|
|
|
|
BOOL bOk = TRUE;
|
|
if (FIsEnumerated(pComponent->Class()))
|
|
{
|
|
RtlInitUnicodeString(&BindList, NULL);
|
|
RtlInitUnicodeString(&LowerComponent, NULL);
|
|
RtlInitUnicodeString(&UpperComponent, pComponent->Ext.PszBindName());
|
|
bOk = NdisHandlePnPEvent(
|
|
NDIS,
|
|
BIND_LIST,
|
|
&LowerComponent,
|
|
&UpperComponent,
|
|
&BindList,
|
|
const_cast<PBYTE>(m_BindValue.PbBuffer()),
|
|
m_BindValue.CountOfBytesUsed());
|
|
|
|
}
|
|
else
|
|
{
|
|
RtlInitUnicodeString(&BindList, NULL);
|
|
RtlInitUnicodeString(&LowerComponent, NULL);
|
|
RtlInitUnicodeString(&UpperComponent, pComponent->Ext.PszBindName());
|
|
|
|
TraceTag(ttidBeDiag, "BindName (TDI Client): %S", pComponent->Ext.PszBindName());
|
|
|
|
bOk = NdisHandlePnPEvent(
|
|
TDI,
|
|
RECONFIGURE,
|
|
&LowerComponent,
|
|
&UpperComponent,
|
|
&BindList,
|
|
const_cast<PBYTE>(m_BindValue.PbBuffer()),
|
|
m_BindValue.CountOfBytesUsed());
|
|
}
|
|
|
|
if(!bOk)
|
|
{
|
|
// hr = HrFromLastWin32Error();
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CRegistryBindingsContext::HrWriteBindingsForComponent");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CRegistryBindingsContext::HrWriteBindingsForFilterDevices (
|
|
IN CFilterDevices* pFilterDevices)
|
|
{
|
|
HRESULT hr;
|
|
CFilterDevices::iterator iter;
|
|
CFilterDevices::iterator next;
|
|
CFilterDevice* pDevice;
|
|
CFilterDevice* pNextDevice;
|
|
CFilterDevice* pPrevDevice;
|
|
PCWSTR pmszRootDevice;
|
|
PCWSTR pmszUpperBind;
|
|
|
|
#define SZ_DEVICE_LEN 8 // characters in L"\\Device\\"
|
|
WCHAR mszExport [SZ_DEVICE_LEN + c_cchGuidWithTerm + 1];
|
|
WCHAR* const pchExportGuid = mszExport + SZ_DEVICE_LEN;
|
|
|
|
// Pre-fill the beginning of the Export string.
|
|
// Set the terminating NULL for the mutli-sz too.
|
|
//
|
|
wcscpy (mszExport, L"\\Device\\");
|
|
Assert (SZ_DEVICE_LEN == wcslen(mszExport));
|
|
mszExport[celems(mszExport) - 1] = 0;
|
|
|
|
hr = S_OK;
|
|
|
|
// Sort the filter devices by pAdapter and then by
|
|
// pFilter->m_dwFilterClassOrdinal. We will then iterate all filter
|
|
// devices to write the bindings. Because of the sort, we'll iterate
|
|
// all filter devices for a given adapter in class order from smallest
|
|
// to largest. (Smaller class ordinals have affinity for the protocol.)
|
|
//
|
|
pFilterDevices->SortForWritingBindings ();
|
|
|
|
pPrevDevice = NULL;
|
|
|
|
for (iter = pFilterDevices->begin();
|
|
iter != pFilterDevices->end();
|
|
iter++)
|
|
{
|
|
pDevice = *iter;
|
|
Assert (pDevice);
|
|
|
|
// Generate the rest of the Export string.
|
|
// \Device\{GUID}
|
|
//
|
|
Assert ((c_cchGuidWithTerm - 1) == wcslen(pDevice->m_szInstanceGuid));
|
|
|
|
wcscpy (pchExportGuid, pDevice->m_szInstanceGuid);
|
|
|
|
// If this device's adapter is different than the previous device's
|
|
// adapter, we are dealing with the top of a new chain. We need
|
|
// to initialize RootDevice which will be the multi-sz of all
|
|
// bindnames in the chain including the adapter.
|
|
//
|
|
if (!pPrevDevice ||
|
|
(pDevice->m_pAdapter != pPrevDevice->m_pAdapter))
|
|
{
|
|
// Compute RootDevice.
|
|
// We'll use m_ExportValue as the buffer.
|
|
//
|
|
m_ExportValue.Clear();
|
|
m_ExportValue.HrCopyString (pDevice->m_szInstanceGuid);
|
|
|
|
for (next = iter + 1;
|
|
next != pFilterDevices->end();
|
|
next++)
|
|
{
|
|
pNextDevice = *next;
|
|
Assert (pNextDevice);
|
|
|
|
// We're done when we reach the next filter chain.
|
|
//
|
|
if (pNextDevice->m_pAdapter != pDevice->m_pAdapter)
|
|
{
|
|
break;
|
|
}
|
|
|
|
m_ExportValue.HrCopyString (pNextDevice->m_szInstanceGuid);
|
|
}
|
|
|
|
m_ExportValue.HrCopyString (pDevice->m_pAdapter->Ext.PszBindName());
|
|
m_ExportValue.HrCopyString (L"");
|
|
pmszRootDevice = (PCWSTR)m_ExportValue.PbBuffer();
|
|
Assert (*pmszRootDevice);
|
|
|
|
// Compute UpperBind.
|
|
// We'll use m_BindValue as the buffer.
|
|
//
|
|
hr = HrGetAdapterUpperBindValue (pDevice->m_pAdapter);
|
|
}
|
|
// We're continuing in the filter chain and this device is not
|
|
// the topmost. (not closest to the protocol).
|
|
//
|
|
else
|
|
{
|
|
// Since RootDevice was built up for the top device in the chain,
|
|
// each successive device just needs to skip past the next
|
|
// string in the mutli-sz.
|
|
//
|
|
Assert (*pmszRootDevice);
|
|
pmszRootDevice += wcslen(pmszRootDevice) + 1;
|
|
|
|
// UpperBind is the previous device's filter's bind name.
|
|
//
|
|
m_BindValue.Clear();
|
|
m_BindValue.HrCopyString (pPrevDevice->m_pFilter->Ext.PszBindName());
|
|
m_BindValue.HrCopyString (L"");
|
|
}
|
|
|
|
pmszUpperBind = (PCWSTR)m_BindValue.PbBuffer();
|
|
|
|
// We now have:
|
|
// Export in mszExport
|
|
// RootDevice at pmszRootDevice (in m_ExportValue)
|
|
// UpperBind at pmszUpperBind (in m_BindValue)
|
|
//
|
|
hr = HrWriteFilterDeviceLinkage (
|
|
pDevice, pFilterDevices->m_hdi,
|
|
mszExport, pmszRootDevice, pmszUpperBind);
|
|
|
|
// If this is the last device in the chain, we need to write
|
|
// the UpperBind of the adapter to be this filter device.
|
|
//
|
|
next = iter + 1;
|
|
if ((next == pFilterDevices->end()) ||
|
|
(*next)->m_pAdapter != pDevice->m_pAdapter)
|
|
{
|
|
// UpperBind is this last device's filter's bind name.
|
|
//
|
|
m_BindValue.Clear();
|
|
m_BindValue.HrCopyString (pDevice->m_pFilter->Ext.PszBindName());
|
|
m_BindValue.HrCopyString (L"");
|
|
pmszUpperBind = (PCWSTR)m_BindValue.PbBuffer();
|
|
|
|
hr = HrWriteFilteredAdapterUpperBind (
|
|
pDevice->m_pAdapter,
|
|
pmszUpperBind);
|
|
}
|
|
|
|
// Remember the previous device so that when we go to the next
|
|
// device, we'll know we're dealing with a different chain if
|
|
// the next device's adapter is different than this one.
|
|
//
|
|
pPrevDevice = pDevice;
|
|
}
|
|
|
|
TraceHr (ttidError, FAL, hr, FALSE,
|
|
"CRegistryBindingsContext::HrWriteBindingsForFilterDevices");
|
|
return hr;
|
|
}
|
|
|