windows-nt/Source/XPSP1/NT/net/config/netcfg/engine/lanamap.cpp

1203 lines
32 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1999.
//
// File: L A N A M A P . C P P
//
// Contents: NetBios Lana map routines.
//
// Notes:
//
// Author: billbe 17 Feb 1999
//
//----------------------------------------------------------------------------
#include <pch.h>
#pragma hdrstop
#include "lanamap.h"
#include "nceh.h"
#include "ncerror.h"
#include "ncreg.h"
#include "ncsetup.h"
#include "netsetup.h"
#include "persist.h"
const WCHAR c_szRegKeyNetBiosLinkage[] =
L"System\\CurrentControlSet\\Services\\NetBios\\Linkage";
const WCHAR c_szRegKeyNetBiosParameters[] =
L"System\\CurrentControlSet\\Services\\NetBIOS\\Parameters";
const WCHAR c_szRegValueLanaMap[] = L"LanaMap";
const WCHAR c_szRegValueMaxLana[] = L"MaxLana";
#if DBG
VOID DbgVerifyBindPathString (PCWSTR pszBindPath);
#else
VOID DbgVerifyBindPathString (PCWSTR /*pszBindPath*/) {}
#endif
typedef vector<const GUID*> VECTOR_OF_GUIDS;
struct LANA_BIND_PATH
{
VECTOR_OF_GUIDS GuidsOfComponentsOnPath;
BYTE LanaNumber;
};
VOID
GetFirstComponentFromBindPath (
IN PCWSTR pszBindPath,
OUT PCWSTR* ppszComponentStart,
OUT DWORD* pcchComponent)
{
PCWSTR pszComponentEnd;
PCWSTR pszComponentStart;
Assert (pszBindPath);
Assert (ppszComponentStart);
Assert (pcchComponent);
*pcchComponent = 0;
// The Bind path is of the form \Device\<component>_<component>_<etc.>
//
pszComponentEnd = wcschr (pszBindPath, L'_');
if (!pszComponentEnd)
{
// There is no underscore so set the end pointer
// to the end of the string.
pszComponentEnd = pszBindPath + wcslen (pszBindPath);
}
for (pszComponentStart = pszComponentEnd;
pszComponentStart != pszBindPath; pszComponentStart--)
{
// Backup from the end until we get to the slash.
// If we don't find a slash, the loop will stop when
// we hit the beginning.
//
if (L'\\' == *pszComponentStart)
{
// We hit the slash. The Component start is one character
// past that.
pszComponentStart++;
break;
}
}
*ppszComponentStart = pszComponentStart;
*pcchComponent = pszComponentEnd - pszComponentStart;
}
VOID
CLanaMap::Dump (
OUT CWideString* pstr) const
{
Assert (this);
Assert (pstr);
WCHAR pszBuf[1024];
pstr->erase();
const CLanaEntry* pEntry;
for (pEntry = begin(); pEntry != end(); pEntry++)
{
swprintf (pszBuf, L"Lana: %3d Export: %d Path: %s\n",
pEntry->RegLanaEntry.LanaNumber,
pEntry->RegLanaEntry.Exported, pEntry->pszBindPath);
pstr->append (pszBuf);
}
}
HRESULT
CLanaMap::HrLoadLanaMap()
{
HRESULT hr;
HKEY hkey;
// The lana map is stored in Netbios's linkage key.
//
hr = HrRegOpenKeyEx (HKEY_LOCAL_MACHINE, c_szRegKeyNetBiosLinkage,
KEY_READ, &hkey);
if (S_OK == hr)
{
REG_LANA_ENTRY* pRegEntries;
DWORD cbLanaEntries;
// Read in the lana map binary blob.
hr = HrRegQueryBinaryWithAlloc (hkey, c_szRegValueLanaMap,
(BYTE**)&pRegEntries, &cbLanaEntries);
if (S_OK == hr)
{
DWORD cEntries = cbLanaEntries / sizeof (REG_LANA_ENTRY);
PWSTR pmszBindPaths;
// Grab the bind paths for NetBios so we can match them
// up with the lana map.
hr = HrRegQueryMultiSzWithAlloc (hkey, L"Bind", &pmszBindPaths);
if (S_OK == hr)
{
PCWSTR pszScan;
DWORD cPaths;
for (pszScan = pmszBindPaths, cPaths = 0;
*pszScan;
pszScan += wcslen(pszScan) + 1)
{
++cPaths;
}
m_pszBindPathsBuffer = pmszBindPaths;
hr = HrReserveRoomForEntries (cPaths);
if (S_OK == hr)
{
DWORD dw = 0;
CLanaEntry Entry;
for (pszScan = pmszBindPaths;
*pszScan;
pszScan += wcslen(pszScan) + 1)
{
Entry.pszBindPath = pszScan;
if (dw < cEntries)
{
Entry.RegLanaEntry.LanaNumber =
pRegEntries[dw].LanaNumber;
Entry.RegLanaEntry.Exported =
pRegEntries[dw].Exported;
}
else
{
// We have more bind paths but no more
// lana map entries to correlate.
// Now we assign available lanas.
//
BYTE* location = find (m_LanasInUse,
m_LanasInUse + MAX_LANA, 0);
if (location != m_LanasInUse + MAX_LANA)
{
Entry.RegLanaEntry.LanaNumber =
location - m_LanasInUse;
Entry.RegLanaEntry.Exported = 1;
}
}
// Mark this Lana as taken.
m_LanasInUse[Entry.RegLanaEntry.LanaNumber] = 1;
hr = HrAppendEntry (&Entry);
if (S_OK != hr)
{
break;
}
dw++;
}
}
}
MemFree (pRegEntries);
}
// If lana map or bind is not there, it is okay since we will be
// recreating the info.
//
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
{
hr = S_OK;
}
RegCloseKey (hkey);
}
else
{
// If the linkage has not been created yet, it is okay since it will
// be creating after the lanamap is written out. This occurs when
// NetBios is first installed.
//
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
{
hr = S_OK;
}
}
TraceHr (ttidError, FAL, hr, FALSE, "CLanaMap::HrLoadLanaMap");
return hr;
}
#if DBG
VOID
DbgVerifyBindPathString (
PCWSTR pszBindPath)
{
const WCHAR c_szDevice[] = L"\\Device\\";
Assert (pszBindPath);
Assert (0 == _wcsnicmp (pszBindPath, c_szDevice, celems(c_szDevice)-1));
}
#endif // DBG
BOOL
FBindPathContainsMultipleInterface (
IN const CComponentList& Components,
IN PCWSTR pszBindPath)
{
BOOL fContainsMultipleInterface = FALSE;
PCWSTR pszLastDevice = wcsrchr (pszBindPath, L'{');
if (pszLastDevice)
{
GUID Guid;
if (S_OK == IIDFromString ((PWSTR)pszLastDevice, &Guid))
{
// If this is a multiple interface, it will not exist
// as a component.
//
CComponent* pComponent;
pComponent = Components.
PFindComponentByInstanceGuid (&Guid);
if (!pComponent)
{
// This means the path contains a multiple interface.
fContainsMultipleInterface = TRUE;
}
}
}
return fContainsMultipleInterface;
}
HRESULT
CLanaMap::HrAppendEntry (
IN CLanaEntry* pEntry)
{
HRESULT hr;
Assert (pEntry);
Assert (pEntry->pszBindPath && *(pEntry->pszBindPath));
DbgVerifyBindPathString (pEntry->pszBindPath);
NC_TRY
{
push_back (*pEntry);
hr = S_OK;
}
NC_CATCH_ALL
{
hr = E_OUTOFMEMORY;
}
if (S_OK == hr)
{
// Update out lanas in use map.
m_LanasInUse[pEntry->RegLanaEntry.LanaNumber] = 1;
}
TraceHr (ttidError, FAL, hr, FALSE, "CLanaMap::HrAppendLanaEntry");
return hr;
}
HRESULT
CLanaMap::HrCreateRegistryMap()
{
HRESULT hr;
CLanaEntry* pEntry;
if (m_RegistryLanaMap.CountOfBytesUsed())
{
m_RegistryLanaMap.Clear();
}
hr = m_RegistryLanaMap.HrReserveBytes (
CountEntries() * sizeof (REG_LANA_ENTRY));
if (S_OK == hr)
{
for (pEntry = begin(); pEntry != end(); pEntry++)
{
hr = m_RegistryLanaMap.HrCopyBytes ((BYTE*)&pEntry->RegLanaEntry,
sizeof (REG_LANA_ENTRY));
}
}
TraceHr (ttidError, FAL, hr, FALSE, "CLanaEntry::HrCreateRegistryMap");
return hr;
}
HRESULT
CLanaMap::HrReserveRoomForEntries (
IN UINT cEntries)
{
HRESULT hr;
NC_TRY
{
reserve (cEntries);
hr = S_OK;
}
NC_CATCH_ALL
{
hr = E_OUTOFMEMORY;
}
TraceHr (ttidError, FAL, hr, FALSE, "CLanaMap::HrReserveRoomForEntries");
return hr;
}
BYTE
CLanaMap::GetExportValue (
IN const CComponentList& Components,
IN PCWSTR pszBindPath)
{
const WCHAR c_szNdisWanNbfIn[] = L"NdisWanNbfIn{";
BYTE Exported = 1;
PCWSTR pszLastDevice;
Assert (pszBindPath && *pszBindPath);
// Get the last "device" on the bind path.
// If it matches NbfIn, we don't export.
//
pszLastDevice = wcsrchr (pszBindPath, L'_');
if (!pszLastDevice)
{
pszLastDevice = wcsrchr (pszBindPath, L'\\');
if (!pszLastDevice)
{
pszLastDevice = pszBindPath;
}
}
if (pszLastDevice != pszBindPath)
{
pszLastDevice++;
}
if (0 == _wcsnicmp (pszLastDevice, c_szNdisWanNbfIn,
wcslen (c_szNdisWanNbfIn)))
{
Exported = 0;
}
// If we haven't turned off export, check to see if this bind path
// contains a multiple interface.
//
if (0 != Exported && FBindPathContainsMultipleInterface (Components,
pszBindPath))
{
Exported = 0;
}
return Exported;
}
VOID
CLanaMap::GetLanaEntry (
IN const CComponentList& Components,
IN CLanaEntry* pEntry)
{
CLanaEntry* pCurrentEntry;
BOOL fFound = FALSE;
Assert (pEntry->pszBindPath);
// Check the map for the entry
//
for (pCurrentEntry = begin(); pCurrentEntry != end(); pCurrentEntry++)
{
if (0 == _wcsicmp (pEntry->pszBindPath, pCurrentEntry->pszBindPath))
{
// Found the entry, set the lana number and figure out
// if this entry should be exported.
//
pEntry->RegLanaEntry.Exported =
GetExportValue (Components, pEntry->pszBindPath);
pEntry->RegLanaEntry.LanaNumber =
pCurrentEntry->RegLanaEntry.LanaNumber;
fFound = TRUE;
break;
}
}
if (!fFound)
{
// no match, get next available lana number
BYTE* location = find (m_LanasInUse, m_LanasInUse + MAX_LANA, 0);
if (location != m_LanasInUse + MAX_LANA)
{
pEntry->RegLanaEntry.Exported =
GetExportValue (Components, pEntry->pszBindPath);
pEntry->RegLanaEntry.LanaNumber = location - m_LanasInUse;
m_LanasInUse[location - m_LanasInUse] = 1;
}
else
{
// They tell me this is impossible.
AssertSz (FALSE, "No more available Lanas.");
pEntry->RegLanaEntry.Exported = 0;
pEntry->RegLanaEntry.LanaNumber = MAX_LANA + 1;
}
}
}
HRESULT
CLanaMap::HrWriteLanaMapConfig()
{
HKEY hkeyLinkage;
HRESULT hr;
hr = HrRegCreateKeyEx (HKEY_LOCAL_MACHINE, c_szRegKeyNetBiosLinkage,
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkeyLinkage, NULL);
if (S_OK == hr)
{
const BYTE* pbBuffer;
DWORD cbBuffer = m_RegistryLanaMap.CountOfBytesUsed();
if (cbBuffer > 0)
{
pbBuffer = m_RegistryLanaMap.PbBuffer();
}
else
{
pbBuffer = NULL;
}
hr = HrRegSetBinary (hkeyLinkage, c_szRegValueLanaMap,
pbBuffer, cbBuffer);
RegCloseKey (hkeyLinkage);
}
if (S_OK == hr)
{
HKEY hkeyParams;
hr = HrRegCreateKeyEx (HKEY_LOCAL_MACHINE,
c_szRegKeyNetBiosParameters, REG_OPTION_NON_VOLATILE,
KEY_WRITE, NULL, &hkeyParams, NULL);
if (S_OK == hr)
{
hr = HrRegSetDword (hkeyParams, c_szRegValueMaxLana,
GetMaxLana());
RegCloseKey (hkeyParams);
}
}
TraceHr (ttidError, FAL, hr, FALSE, "CLanaMap::HrWriteLanaMapConfig");
return hr;
}
HRESULT
HrGetNetBiosProviderName (
IN CComponent* pComponent,
OUT PWSTR pszName)
{
HRESULT hr;
Assert (pComponent);
Assert (pszName);
// The netbios provider name for a component is stored in its
// <service>\Parameters key.
//
HKEY hkeyService;
hr = pComponent->HrOpenServiceKey (KEY_READ, &hkeyService);
if (S_OK == hr)
{
HKEY hkeyParams;
hr = HrRegOpenKeyEx (hkeyService, L"Parameters", KEY_READ,
&hkeyParams);
if (S_OK == hr)
{
DWORD cbBuffer = _MAX_PATH;
hr = HrRegQuerySzBuffer (hkeyParams, L"NbProvider", pszName,
&cbBuffer);
RegCloseKey (hkeyParams);
}
RegCloseKey (hkeyService);
}
TraceHr (ttidError, FAL, hr,
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr,
"HrGetNetBiosProviderName");
return hr;
}
HRESULT
CLanaMap::HrSetLanaNumber (
IN BYTE OldLanaNumber,
IN BYTE NewLanaNumber)
{
HRESULT hr = S_OK;
if (0 == m_LanasInUse[NewLanaNumber])
{
CLanaEntry* pEntry;
for (pEntry = begin(); pEntry != end(); pEntry++)
{
if (OldLanaNumber == pEntry->RegLanaEntry.LanaNumber)
{
// free up the lana number this entry had.
m_LanasInUse[pEntry->RegLanaEntry.LanaNumber] = 0;
// Give the entry the new lana number.
pEntry->RegLanaEntry.LanaNumber = NewLanaNumber;
m_LanasInUse[NewLanaNumber] = 1;
break;
}
}
if (pEntry == end())
{
hr = HRESULT_FROM_WIN32 (ERROR_OBJECT_NOT_FOUND);
}
}
else
{
// The lana is not free. We will swap the lanas used by the
// two paths.
//
CLanaEntry* pEntry;
CLanaEntry* pEntryToSet = NULL;
CLanaEntry* pEntryUsingLana = NULL;
for (pEntry = begin(); pEntry != end(); pEntry++)
{
if (!pEntryToSet &&
(OldLanaNumber == pEntry->RegLanaEntry.LanaNumber))
{
pEntryToSet = pEntry;
}
else if (!pEntryUsingLana &&
(NewLanaNumber == pEntry->RegLanaEntry.LanaNumber))
{
pEntryUsingLana = pEntry;
}
if (pEntryToSet && pEntryUsingLana)
{
// Give the entry the new lana number.
pEntryToSet->RegLanaEntry.LanaNumber = NewLanaNumber;
// Give the old lana number to the entry that was using the
// new lana number.
pEntryUsingLana->RegLanaEntry.LanaNumber = OldLanaNumber;
break;
}
}
if (!pEntryToSet || !pEntryUsingLana)
{
hr = HRESULT_FROM_WIN32 (ERROR_OBJECT_NOT_FOUND);
}
}
TraceHr (ttidError, FAL, hr, FALSE, "CLanaMap::HrSetLanaNumber");
return hr;
}
BYTE
CLanaMap::GetMaxLana()
{
for (BYTE b = MAX_LANA; b; b--)
{
if (m_LanasInUse[b]) return b;
}
return 0;
}
HRESULT
CLanaMap::HrWriteLanaConfiguration (
IN const CComponentList& Components)
{
HRESULT hr;
// Create the registry map that will be stored.
hr = HrCreateRegistryMap();
if (S_OK == hr)
{
// Write out the map and other lana info.
hr = HrWriteLanaMapConfig();
}
TraceHr (ttidError, FAL, hr, FALSE, "HrWriteLanaConfiguration");
return hr;
}
VOID
DumpLanaBindPaths (
IN LANA_BIND_PATH* pBindSet,
IN DWORD cPaths)
{
LANA_BIND_PATH* pPath = pBindSet;
DWORD dw = 0;
VECTOR_OF_GUIDS::iterator iter;
for (dw = 0; dw < cPaths; dw++)
{
TraceTag (ttidNetcfgBase, "Path %d", dw);
for (iter = pPath->GuidsOfComponentsOnPath.begin();
iter != pPath->GuidsOfComponentsOnPath.end();
iter++)
{
const GUID* guid = *iter;
TraceTag (ttidNetcfgBase, " %lX", guid->Data1);
}
pPath++;
}
}
VOID
UpdateLanaConfigWithAnswerFileInfo (
IN CLanaMap* pLanaMap,
IN DWORD cAfPaths,
IN LANA_BIND_PATH* pOriginalBindSet,
IN LANA_BIND_PATH* pAnswerFileBindSet)
{
DWORD dwAnswerFile;
DWORD dwPaths;
DWORD dwComponents;
DWORD dwNumberOfComponents;
BOOL fEqual;
LANA_BIND_PATH* pAfEntry;
LANA_BIND_PATH* pOEntry;
Assert (pLanaMap);
Assert (pOriginalBindSet);
Assert (pAnswerFileBindSet);
TraceTag (ttidNetcfgBase, "Dumping original bind set");
DumpLanaBindPaths (pOriginalBindSet, pLanaMap->CountEntries());
TraceTag (ttidNetcfgBase, "Dumping af bind set");
DumpLanaBindPaths (pAnswerFileBindSet, cAfPaths);
pAfEntry = pAnswerFileBindSet;
for (dwAnswerFile = 0; dwAnswerFile < cAfPaths; dwAnswerFile++)
{
// Do we have a valid path?
if (!pAfEntry->GuidsOfComponentsOnPath.empty())
{
pOEntry = pOriginalBindSet;
for (dwPaths = 0; dwPaths < pLanaMap->CountEntries(); dwPaths++)
{
if (pAfEntry->GuidsOfComponentsOnPath.size() ==
pOEntry->GuidsOfComponentsOnPath.size())
{
dwNumberOfComponents =
pAfEntry->GuidsOfComponentsOnPath.size();
fEqual = TRUE;
for (dwComponents = 0;
dwComponents < dwNumberOfComponents;
dwComponents++)
{
if (pAfEntry->GuidsOfComponentsOnPath[dwComponents] !=
pOEntry->GuidsOfComponentsOnPath[dwComponents])
{
fEqual = FALSE;
}
}
if (fEqual)
{
HRESULT hr;
hr = pLanaMap->HrSetLanaNumber (
pOEntry->LanaNumber,
pAfEntry->LanaNumber);
TraceTag (ttidNetcfgBase, "af path %d matches %d",
dwAnswerFile, dwPaths);
TraceTag (ttidNetcfgBase, "Changing lana number "
"from %X to %X", pOEntry->LanaNumber,
pAfEntry->LanaNumber);
TraceHr (ttidError, FAL, hr, FALSE, "Setting lana");
}
}
pOEntry++;
}
}
pAfEntry++;
}
}
VOID
ConvertAnswerFileComponentsToGuids (
IN const CComponentList& Components,
IN PCWSTR mszComponents,
OUT VECTOR_OF_GUIDS* pvector)
{
CComponent* pComponent;
PCWSTR pszScan;
const GUID* pguid;
GUID guidTemp;
Assert (mszComponents);
Assert (pvector);
for (pszScan = mszComponents; *pszScan; pszScan += wcslen (pszScan) + 1)
{
TraceTag (ttidNetcfgBase, " Looking for af component %S", pszScan);
// Look for the component in our installed components list.
//
pComponent = Components.PFindComponentByInfId (pszScan, NULL);
if (pComponent)
{
pguid = &pComponent->m_InstanceGuid;
}
else
{
TraceTag (ttidNetcfgBase, " Id did not match installed ids. "
"Checking af map");
// The component wasn't listed in our installed list. The inf
// id might be something that the answerfile processor has mapped
// to the component's instance guid. This happens for adapters.
// e.g. Id is listed as Adapter01 so netsetup uses an alogrithm
// to determine which adapter it is and then save off its
// instance guid in a map.
//
if (FGetInstanceGuidOfComponentFromAnswerFileMap (
pszScan, &guidTemp))
{
pComponent = Components.PFindComponentByInstanceGuid (
&guidTemp);
}
else
{
TraceTag (ttidError, " Component %S not found in answerfile "
"map", pszScan);
}
// If we found the component, store a reference to its
// instance guid
//
if (pComponent)
{
TraceTag (ttidNetcfgBase, " Found component");
pguid = &pComponent->m_InstanceGuid;
}
else
{
// We didn't find the component. Store GUID_NULL.
pguid = &GUID_NULL;
}
}
TraceTag (ttidNetcfgBase, " Using GUID %lX", pguid->Data1);
pvector->push_back (pguid);
}
}
HRESULT
HrConvertAnswerFileParamsToLanaBindSet (
IN INFCONTEXT& ctxLana,
IN const CComponentList& Components,
IN DWORD cPaths,
OUT LANA_BIND_PATH* pBindSet)
{
DWORD cchField = _MAX_PATH;
DWORD cchRequired;
INT LanaCode;
PWSTR mszComponents;
HRESULT hr;
DWORD dw;
INFCONTEXT ctx = ctxLana;
LANA_BIND_PATH* pPath;
hr = S_OK;
mszComponents = (PWSTR)MemAlloc (cchField * sizeof (WCHAR));
pPath = pBindSet;
for (dw = 0; dw < cPaths; dw++)
{
if (mszComponents && (S_OK == hr))
{
hr = HrSetupGetMultiSzField (ctx, 1, mszComponents, cchField,
&cchRequired);
if (S_OK == hr)
{
TraceTag (ttidNetcfgBase, "Path %ld", dw);
ConvertAnswerFileComponentsToGuids (Components,
mszComponents,
&(pPath->GuidsOfComponentsOnPath));
hr = HrSetupFindNextLine (ctx, &ctx);
if (S_OK == hr)
{
hr = HrSetupGetIntField (ctx, 1, &LanaCode);
if (S_OK == hr)
{
pPath->LanaNumber = LanaCode & 0xff;
TraceTag (ttidNetcfgBase, " Using LanaNumber %X for "
"path", pPath->LanaNumber);
}
else
{
TraceTag (ttidNetcfgBase, " Bad lana code");
// Bad lana number, clear the guids so we won't match
// this path and use this info.
//
pPath->GuidsOfComponentsOnPath.erase(
pPath->GuidsOfComponentsOnPath.begin(),
pPath->GuidsOfComponentsOnPath.end());
}
}
hr = HrSetupFindNextMatchLine (ctx, L"LanaPath", &ctx);
if (S_FALSE == hr)
{
break;
}
pPath++;
}
else if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
{
// Reallocate the buffer.
//
hr = S_OK;
MemFree (mszComponents);
mszComponents = (PWSTR)MemAlloc (cchRequired * sizeof(WCHAR));
cchField = cchRequired;
}
}
else
{
hr = E_OUTOFMEMORY;
break;
}
}
if (S_FALSE == hr)
{
// Check to see if we were really finished.
if ((dw + 1) < cPaths)
{
TraceTag (ttidError, "Answerfile specified %d lana paths "
"but only %d were found", cPaths, (dw + 1));
}
// This fcn only returns S_OK on success.
hr = S_OK;
}
TraceHr (ttidError, FAL, hr, FALSE,
"HrConvertAnswerFileParamsToLanaBindSet");
return hr;
}
HRESULT
HrProcessAnswerFile (
IN PCWSTR pszAnswerFile,
IN PCWSTR pszSection,
IN const CComponentList& Components,
OUT LANA_BIND_PATH** ppBindSet,
OUT DWORD* pcPaths)
{
HINF hinf;
PCWSTR pszBindPath;
WCHAR szBindName[_MAX_PATH];
HRESULT hr;
Assert (pszAnswerFile);
Assert (pszSection);
Assert (ppBindSet);
Assert (pcPaths);
*pcPaths = 0;
*ppBindSet = NULL;
hr = HrSetupOpenInfFile (pszAnswerFile, NULL,
INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL, &hinf);
if (S_OK == hr)
{
hr = HrSetupGetFirstDword (hinf, pszSection,
L"NumberOfPaths", pcPaths);
if (S_OK == hr)
{
TraceTag (ttidNetcfgBase, "\n\n");
TraceTag (ttidNetcfgBase, "%d paths found in answerfile",
*pcPaths);
hr = E_OUTOFMEMORY;
*ppBindSet = new LANA_BIND_PATH[*pcPaths];
if (*ppBindSet)
{
hr = S_OK;
}
}
if (S_OK == hr)
{
INFCONTEXT ctx;
hr = HrSetupFindFirstLine (hinf, pszSection, L"LanaPath", &ctx);
if (S_OK == hr)
{
hr = HrConvertAnswerFileParamsToLanaBindSet (ctx, Components,
*pcPaths, *ppBindSet);
}
}
}
TraceHr (ttidError, FAL, hr, FALSE, "HrProcessAnswerFile");
return hr;
}
HRESULT
HrConvertBindingsToLanaBindSet (
IN const CComponentList& Components,
IN const CLanaMap& LanaMap,
OUT LANA_BIND_PATH** ppBindSet)
{
PCWSTR pszBindPath;
WCHAR szBindName[_MAX_PATH];
HRESULT hr;
DWORD cPaths;
Assert (ppBindSet);
cPaths = LanaMap.CountEntries();
TraceTag (ttidNetcfgBase, "%d paths in system", cPaths);
hr = E_OUTOFMEMORY;
*ppBindSet = new LANA_BIND_PATH[cPaths];
if (*ppBindSet)
{
LANA_BIND_PATH* pBindPath = *ppBindSet;
CComponent* pComponent;
PCWSTR pszCompStart;
PCWSTR pszCompEnd;
DWORD cchComp;
hr = S_OK;
const CLanaEntry* pEntry;
for (pEntry = LanaMap.begin(); pEntry != LanaMap.end(); pEntry++)
{
pszBindPath = pEntry->pszBindPath;
TraceTag (ttidNetcfgBase, "BindPath %S", pszBindPath);
pBindPath->LanaNumber = pEntry->RegLanaEntry.LanaNumber;
TraceTag (ttidNetcfgBase, "Lana %X", pBindPath->LanaNumber);
GetFirstComponentFromBindPath (pszBindPath, &pszCompStart,
&cchComp);
while (*pszCompStart)
{
wcsncpy (szBindName, pszCompStart, cchComp);
szBindName[cchComp] = L'\0';
TraceTag (ttidNetcfgBase, " Searching for component with bind name %S",
szBindName);
pComponent = Components.PFindComponentByBindName (NC_INVALID,
szBindName);
if (pComponent)
{
TraceTag (ttidNetcfgBase, " Found component. Guid = %lX",
pComponent->m_InstanceGuid.Data1);
pBindPath->GuidsOfComponentsOnPath.push_back (&pComponent->m_InstanceGuid);
}
else
{
if (*pszCompEnd)
{
AssertSz (FALSE, " Bind Name not found in component list");
pBindPath->GuidsOfComponentsOnPath.push_back (&GUID_NULL);
}
}
pszCompStart = pszCompStart + cchComp;
if (*pszCompStart)
{
pszCompStart++;
pszCompEnd = wcschr (pszCompStart, L'_');
if (!pszCompEnd)
{
// There is no underscore so set the end pointer
// to the end of the string.
pszCompEnd = pszBindPath + wcslen (pszBindPath);
}
}
cchComp = pszCompEnd - pszCompStart;
}
pBindPath++;
}
}
TraceHr (ttidError, FAL, hr, FALSE, "HrConvertBindingsToLanaBindSet");
return hr;
}
HRESULT
HrUpdateLanaConfig (
IN const CComponentList& Components,
IN PCWSTR pszBindPaths,
IN UINT cPaths)
{
CLanaMap CurrentLanaMap;
CLanaMap NewLanaMap;
HRESULT hr;
hr = CurrentLanaMap.HrLoadLanaMap();
if (S_OK == hr)
{
hr = NewLanaMap.HrReserveRoomForEntries (cPaths);
if (S_OK == hr)
{
PCWSTR pszScan;
CLanaEntry LanaEntry;
for (pszScan = pszBindPaths;
*pszScan;
pszScan += wcslen (pszScan) + 1)
{
LanaEntry.pszBindPath = pszScan;
CurrentLanaMap.GetLanaEntry (Components, &LanaEntry);
hr = NewLanaMap.HrAppendEntry (&LanaEntry);
if (S_OK != hr)
{
break;
}
}
if (S_OK == hr)
{
hr = NewLanaMap.HrWriteLanaConfiguration (Components);
}
}
}
TraceHr (ttidError, FAL, hr, FALSE, "HrUpdateLanaConfig");
return hr;
}
EXTERN_C
VOID
WINAPI
UpdateLanaConfigUsingAnswerfile (
IN PCWSTR pszAnswerFile,
IN PCWSTR pszSection)
{
HRESULT hr;
CLanaMap LanaMap;
// Load the current lanamap information.
hr = LanaMap.HrLoadLanaMap();
if (S_OK == hr)
{
TraceTag (ttidNetcfgBase, "Answerfile params %S:%S",
pszAnswerFile, pszSection);
// Load up the current network configuration.
//
CNetConfig NetConfig;
hr = HrLoadNetworkConfigurationFromRegistry (KEY_READ, &NetConfig);
if (S_OK == hr)
{
hr = NetConfig.HrEnsureExternalDataLoadedForAllComponents();
if (S_OK == hr)
{
// Convert our current lana bind paths to a lana bind set.
//
LANA_BIND_PATH* pBindSet;
hr = HrConvertBindingsToLanaBindSet (
NetConfig.Core.Components, LanaMap, &pBindSet);
if (S_OK == hr)
{
// Convert the answerfile lana bind paths
// to a lana bind set.
//
LANA_BIND_PATH* pAnswerFileBindSet;
DWORD cAnswerFilePaths;
hr = HrProcessAnswerFile (
pszAnswerFile, pszSection,
NetConfig.Core.Components, &pAnswerFileBindSet,
&cAnswerFilePaths);
if (S_OK == hr)
{
// Now update the config using the answerfile info.
//
UpdateLanaConfigWithAnswerFileInfo (
&LanaMap, cAnswerFilePaths,
pBindSet, pAnswerFileBindSet);
// Write out the information.
hr = LanaMap.HrWriteLanaConfiguration (
NetConfig.Core.Components);
delete [] pAnswerFileBindSet;
}
delete [] pBindSet;
}
}
}
}
TraceHr (ttidError, FAL, hr, FALSE, "UpdateLanaConfigUsingAnswerfile");
}