//+--------------------------------------------------------------------------- // // 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 #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 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\__ // 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 // \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"); }