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