|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: T C P I P F U N C . C P P
//
// Contents: Various CTcpipcfg member functions that are not interface
// methods
//
// Notes:
//
// Author: tongl 1 May 1997
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "tcpipobj.h"
#include "ncatlui.h"
#include "ncmisc.h"
#include "ncpnp.h"
#include "ncreg.h"
#include "ncstl.h"
#include "ncui.h"
#include "tcpconst.h"
#include "tcphelp.h"
#include "tcputil.h"
#include "dhcpcsdk.h"
#include "dlgaddr.h"
#include "atmcommon.h"
#include "regkysec.h"
#include "netconp.h"
#define _PNP_POWER_
#include "ntddip.h"
#undef _PNP_POWER_
#include <atmarpif.h>
// sigh... llinfo.h is needed by ddwanarp.h
#include <llinfo.h>
#include <ddwanarp.h>
extern const WCHAR c_szBiNdisAtm[]; #if ENABLE_1394
extern const WCHAR c_szBiNdis1394[]; #endif // ENABLE_1394
extern const WCHAR c_szBiNdisWanIp[]; extern const WCHAR c_szEmpty[]; extern const WCHAR c_szSvcDnscache[];
extern void CopyVstr(VSTR * vstrDest, const VSTR & vstrSrc);
typedef struct { PCWSTR pszValueName; DWORD dwType; } ValueType;
const ValueType s_rgNt4Values[] = { {RGAS_ENABLE_DHCP, REG_DWORD}, {RGAS_IPADDRESS, REG_MULTI_SZ}, {RGAS_SUBNETMASK, REG_MULTI_SZ}, {RGAS_DEFAULTGATEWAY, REG_MULTI_SZ} };
//+---------------------------------------------------------------------------
//
// Member: CTcpipcfg::PAdapterFromInstanceGuid
//
// Purpose: Search the adapter info array for an entry with a matching
// instance guid. Return a pointer to the ADAPTER_INFO if found.
//
// Arguments:
// pGuid [in] pointer to instance guid to search for
//
// Returns: Valid pointer if found, NULL if not.
//
// Author: shaunco 1 Oct 1998
//
// Notes:
//
ADAPTER_INFO* CTcpipcfg::PAdapterFromInstanceGuid ( const GUID* pGuid) { Assert (pGuid);
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end(); iterAdapter++) { ADAPTER_INFO* pAdapter = *iterAdapter;
if (pAdapter->m_guidInstanceId == *pGuid) { return pAdapter; } } return NULL; }
//+---------------------------------------------------------------------------
//
// Member: CTcpipcfg::PAdapterFromNetcfgComponent
//
// Purpose: Search the adapter info array for an entry with an instance
// guid matching that of the specified INetCfgComponent.
// Return a pointer to the ADAPTER_INFO if found.
//
// Arguments:
// pncc [in] INetCfgComponent who's instance guid we are looking for.
//
// Returns: Valid pointer if found, NULL if not.
//
// Author: shaunco 1 Oct 1998
//
// Notes:
//
ADAPTER_INFO* CTcpipcfg::PAdapterFromNetcfgComponent ( INetCfgComponent* pncc) { Assert (pncc);
HRESULT hr; GUID guidAdapter;
hr = pncc->GetInstanceGuid (&guidAdapter); if (SUCCEEDED(hr)) { return PAdapterFromInstanceGuid (&guidAdapter); } return NULL; }
// Called by CTcpipcfg::Initialize.
// We walk the binding path from tcpip and load to first memory state
// all netcards ( both physical cards and Wan adapters )
HRESULT CTcpipcfg::HrGetNetCards() { HRESULT hr = S_OK;
CIterNetCfgBindingPath ncbpIter(m_pnccTcpip); INetCfgBindingPath * pncbp;
// Go through all binding paths in search of tcpip to netcard bindings
while(SUCCEEDED(hr) && (hr = ncbpIter.HrNext(&pncbp)) == S_OK) { INetCfgComponent * pnccNetComponent; PWSTR pszInterfaceName;
hr = HrGetLastComponentAndInterface(pncbp, &pnccNetComponent, &pszInterfaceName); if (SUCCEEDED(hr)) { Assert(pnccNetComponent);
// The last component should be of NET CLASS
GUID guidClass; hr = pnccNetComponent->GetClassGuid(&guidClass); if (SUCCEEDED(hr) && IsEqualGUID(guidClass, GUID_DEVCLASS_NET)) { PWSTR pszNetCardTcpipBindPath; hr = pnccNetComponent->GetBindName(&pszNetCardTcpipBindPath);
AssertSz(SUCCEEDED(hr), "Net card on binding path with no bind path name!!");
m_vstrBindOrder.push_back(new tstring(pszNetCardTcpipBindPath));
hr = HrAddCard(pnccNetComponent, pszNetCardTcpipBindPath, pszInterfaceName);
if (SUCCEEDED(hr)) { GUID guidNetCard; hr = pnccNetComponent->GetInstanceGuid(&guidNetCard); if (SUCCEEDED(hr)) { // Is the binding enabled?
hr = pncbp->IsEnabled();
// hr == S_OK if the card is enabled (ie: bound)
if (S_OK == hr) { // bind the card in our data strucutres
hr = HrBindCard(&guidNetCard, TRUE); } else if (S_FALSE == hr) { hr = HrUnBindCard(&guidNetCard, TRUE); } } }
CoTaskMemFree(pszNetCardTcpipBindPath); }
ReleaseObj(pnccNetComponent); CoTaskMemFree(pszInterfaceName); }
ReleaseObj(pncbp); }
if (S_FALSE == hr) // We just got to the end of the loop
hr = S_OK;
TraceError("CTcpipcfg::HrGetNetCards", hr); return hr; }
BOOL CTcpipcfg::IsBindOrderChanged() { HRESULT hr = S_OK;
VSTR vstrCurrentBindOrder; BOOL fChanged = FALSE; hr = HrLoadBindingOrder(&vstrCurrentBindOrder);
if (SUCCEEDED(hr)) { fChanged = !fIsSameVstr(vstrCurrentBindOrder, m_vstrBindOrder); FreeCollectionAndItem(vstrCurrentBindOrder); }
return fChanged; }
HRESULT CTcpipcfg::HrLoadBindingOrder(VSTR *pvstrBindOrder) {
Assert(pvstrBindOrder);
HRESULT hr = S_OK;
CIterNetCfgBindingPath ncbpIter(m_pnccTcpip); INetCfgBindingPath * pncbp; INetCfgComponent * pnccLast;
while (SUCCEEDED(hr) && S_OK == (hr = ncbpIter.HrNext(&pncbp))) { hr = HrGetLastComponentAndInterface(pncbp, &pnccLast, NULL);
if (SUCCEEDED(hr)) { Assert(pnccLast);
// The last component should be of NET CLASS
GUID guidClass; hr = pnccLast->GetClassGuid(&guidClass); if (SUCCEEDED(hr) && IsEqualGUID(guidClass, GUID_DEVCLASS_NET)) { PWSTR pszNetCardTcpipBindPath; hr = pnccLast->GetBindName(&pszNetCardTcpipBindPath);
AssertSz(SUCCEEDED(hr), "Net card on binding path with no bind path name!!");
if (SUCCEEDED(hr)) { pvstrBindOrder->push_back(new tstring(pszNetCardTcpipBindPath)); CoTaskMemFree(pszNetCardTcpipBindPath); } }
ReleaseObj(pnccLast); }
ReleaseObj(pncbp); }
if (S_FALSE == hr) // We just got to the end of the loop
{ hr = S_OK; }
//if failed, clean up what we added
if (FAILED(hr)) { FreeCollectionAndItem(*pvstrBindOrder); }
TraceError("CBindingsDlg::HrGetBindOrder", hr); return hr; }
// Called by CTcpipcfg::CancelProperties and CTcpipcfg::ApplyProperties
// Release second memory state
void CTcpipcfg::ExitProperties() { delete m_pSecondMemoryAdapterInfo; m_pSecondMemoryAdapterInfo = NULL; }
// Called by CTcpipcfg's destructor
// Release all memory states
void CTcpipcfg::FinalFree() { FreeCollectionAndItem(m_vcardAdapterInfo);
FreeCollectionAndItem(m_vstrBindOrder);
delete m_pSecondMemoryAdapterInfo;
delete m_ipaddr;
DeleteObject(g_hiconUpArrow); DeleteObject(g_hiconDownArrow);
ReleaseObj(m_pnc); ReleaseObj(m_pTcpipPrivate); ReleaseObj(m_pnccTcpip); ReleaseObj(m_pnccWins);
// Just a safty check to make sure the context is released.
AssertSz((m_pUnkContext == NULL), "Why is context not released ?"); ReleaseObj(m_pUnkContext) ; }
// Called by CTcpipcfg::HrSetupPropSheets
// Creates the second memory adapter info from the first
// memory structure
// Note: Bound cards only
HRESULT CTcpipcfg::HrLoadAdapterInfo() { HRESULT hr = HRESULT_FROM_WIN32(ERROR_NO_MATCH);
delete m_pSecondMemoryAdapterInfo; m_pSecondMemoryAdapterInfo = NULL;
ADAPTER_INFO* pAdapter = PAdapterFromInstanceGuid(&m_guidCurrentConnection); if (pAdapter) { // enabled LAN adapter or any RAS Fake adapter
if ((pAdapter->m_BindingState == BINDING_ENABLE) || pAdapter->m_fIsRasFakeAdapter) { m_pSecondMemoryAdapterInfo = new ADAPTER_INFO; if (NULL == m_pSecondMemoryAdapterInfo) { hr = E_OUTOFMEMORY; } else { *m_pSecondMemoryAdapterInfo = *pAdapter; hr = S_OK; } } }
AssertSz((S_OK == hr), "Can not raise UI on a disabled or non-exist adapter !"); TraceError("CTcpipcfg::HrLoadAdapterInfo", hr); return hr; }
// Called by CTcpipcfg::ApplyProperties
// Saves the second memory state back into the first
HRESULT CTcpipcfg::HrSaveAdapterInfo() { HRESULT hr = HRESULT_FROM_WIN32(ERROR_NO_MATCH);
ADAPTER_INFO* pAdapter = PAdapterFromInstanceGuid( &m_pSecondMemoryAdapterInfo->m_guidInstanceId); if (pAdapter) { #ifdef DBG
// The card can not get unbound while in tcpip's properties UI!
if (!pAdapter->m_fIsRasFakeAdapter) { Assert(pAdapter->m_BindingState == BINDING_ENABLE); Assert(m_pSecondMemoryAdapterInfo->m_BindingState == BINDING_ENABLE); } #endif
*pAdapter = *m_pSecondMemoryAdapterInfo; hr = S_OK;
} AssertSz((S_OK == hr), "Adapter in second memory not found in first memory!");
TraceError("CTcpipcfg::HrSaveAdapterInfo", hr); return hr; }
// Called by CTcpipcfg::MergePropPages
// Set the context in which the UI is brought up
HRESULT CTcpipcfg::HrSetConnectionContext() { AssertSz(m_pUnkContext, "Invalid IUnknown pointer passed to CTcpipcfg::SetContext?");
if (!m_pUnkContext) { return E_UNEXPECTED; }
// Is this a lan connection ?
GUID guidConn; INetLanConnectionUiInfo * pLanConnUiInfo; HRESULT hr = m_pUnkContext->QueryInterface( IID_INetLanConnectionUiInfo, reinterpret_cast<PVOID *>(&pLanConnUiInfo)); if (SUCCEEDED(hr)) { // yes, lan connection
m_ConnType = CONNECTION_LAN;
hr = pLanConnUiInfo->GetDeviceGuid(&guidConn);
ReleaseObj(pLanConnUiInfo); } else { INetRasConnectionIpUiInfo * pRasConnUiInfo;
// Is this a wan connection ?
hr = m_pUnkContext->QueryInterface(IID_INetRasConnectionIpUiInfo, reinterpret_cast<PVOID *>(&pRasConnUiInfo)); if (SUCCEEDED(hr)) { // yes, RAS connection
RASCON_IPUI info; if (SUCCEEDED(pRasConnUiInfo->GetUiInfo(&info))) { guidConn = info.guidConnection;
//currently VPN connections only supports PPP frames, so
//if RCUIF_VPN is set, RCUIF_PPP should also be there.
//RCUIF_PPP and RCUIF_SLIP are mutually exclusive
//m_ConnType is only used to show/hide the controls in the RAS
//config UI.
if (info.dwFlags & RCUIF_VPN) { m_ConnType = CONNECTION_RAS_VPN; } else { if (info.dwFlags & RCUIF_PPP) { m_ConnType = CONNECTION_RAS_PPP; } else if (info.dwFlags & RCUIF_SLIP) { m_ConnType = CONNECTION_RAS_SLIP; } }
m_fRasNotAdmin = !!(info.dwFlags & RCUIF_NOT_ADMIN);
AssertSz(((CONNECTION_RAS_PPP == m_ConnType)|| (CONNECTION_RAS_SLIP == m_ConnType) || (CONNECTION_RAS_VPN == m_ConnType)), "RAS connection type unknown ?");
UpdateRasAdapterInfo (info); } }
ReleaseObj(pRasConnUiInfo); }
if (SUCCEEDED(hr)) { m_guidCurrentConnection = guidConn; }
AssertSz(((CONNECTION_LAN == m_ConnType)|| (CONNECTION_RAS_PPP == m_ConnType)|| (CONNECTION_RAS_SLIP == m_ConnType)|| (CONNECTION_RAS_VPN == m_ConnType)), "How come this is neither a LAN connection nor a RAS connection?");
TraceError("CTcpipcfg::HrSetConnectionContext", hr); return hr; }
// Called by CTcpipcfg::MergePropPages
// Allocate property pages
HRESULT CTcpipcfg::HrSetupPropSheets(HPROPSHEETPAGE ** pahpsp, INT * pcPages) { HRESULT hr = S_OK; int cPages = 0; HPROPSHEETPAGE *ahpsp = NULL;
m_fSecondMemoryLmhostsFileReset = FALSE; m_fSecondMemoryModified = FALSE;
//IPSec is removed from connection UI
// m_fSecondMemoryIpsecPolicySet = FALSE;
// copy in memory state to tcpip dialog memory state
// Copy global Info
m_glbSecondMemoryGlobalInfo = m_glbGlobalInfo;
// Copy adapter card specific info
hr = HrLoadAdapterInfo();
// If we have found the matching adapter
if (SUCCEEDED(hr)) { cPages = 1;
delete m_ipaddr; m_ipaddr = new CTcpAddrPage(this, g_aHelpIDs_IDD_TCP_IPADDR);
// Allocate a buffer large enough to hold the handles to all of our
// property pages.
ahpsp = (HPROPSHEETPAGE *)CoTaskMemAlloc(sizeof(HPROPSHEETPAGE) * cPages); if (!ahpsp) { hr = E_OUTOFMEMORY; goto err; }
cPages =0;
Assert(m_ConnType != CONNECTION_UNSET);
if (m_ConnType == CONNECTION_LAN) ahpsp[cPages++] = m_ipaddr->CreatePage(IDD_TCP_IPADDR, 0); else ahpsp[cPages++] = m_ipaddr->CreatePage(IDD_TCP_IPADDR_RAS, 0);
*pahpsp = ahpsp; *pcPages = cPages; } else // if we don't have any bound cards, pop-up message box and don't show UI
{ NcMsgBox(::GetActiveWindow(), IDS_MSFT_TCP_TEXT, IDS_NO_BOUND_CARDS, MB_APPLMODAL | MB_ICONEXCLAMATION | MB_OK);
AssertSz((0== *pcPages), "Invalid page number when no bound cards"); AssertSz((NULL == *pahpsp), "Invalid page array pointer when no bound cards"); }
err:
TraceError("CTcpipcfg::HrSetupPropSheets", hr); return hr; }
// Is there any bound card on the list of physical adapters
BOOL CTcpipcfg::FHasBoundCard() { BOOL fRet = FALSE;
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end(); iterAdapter++) { ADAPTER_INFO* pAdapter = *iterAdapter;
if (pAdapter->m_BindingState == BINDING_ENABLE) { fRet = TRUE; break; } }
return fRet; }
// Called by CTcpipcfg::NotifyBindingPath
// Handle bind notification of a physical card
HRESULT CTcpipcfg::HrAdapterBindNotify(INetCfgComponent *pnccNetCard, DWORD dwChangeFlag, PCWSTR pszInterfaceName) { Assert(!(dwChangeFlag & NCN_ADD && dwChangeFlag & NCN_REMOVE)); Assert(!(dwChangeFlag & NCN_ENABLE && dwChangeFlag & NCN_DISABLE));
Assert(FImplies((dwChangeFlag & NCN_ADD), ((dwChangeFlag & NCN_ENABLE)||(dwChangeFlag & NCN_DISABLE))));
Assert(pnccNetCard);
GUID guidNetCard; HRESULT hr = pnccNetCard->GetInstanceGuid(&guidNetCard); if (SUCCEEDED(hr)) { if (dwChangeFlag & NCN_ADD) { PWSTR pszNetCardTcpipBindPath; hr = pnccNetCard->GetBindName(&pszNetCardTcpipBindPath); AssertSz( SUCCEEDED(hr), "Net card on binding path with no bind path name!!");
hr = HrAddCard(pnccNetCard, pszNetCardTcpipBindPath, pszInterfaceName);
CoTaskMemFree(pszNetCardTcpipBindPath); }
if (dwChangeFlag & NCN_ENABLE) { hr = HrBindCard(&guidNetCard); }
if (dwChangeFlag & NCN_DISABLE) { hr = HrUnBindCard(&guidNetCard); }
if (dwChangeFlag & NCN_REMOVE) { hr = HrDeleteCard(&guidNetCard); }
}
TraceError("CTcpipCfg::HrPhysicalCardBindNotify", hr); return hr; }
// HrAddCard
// Adds a card to the list of cards installed in the system
// pnccNetCard the netcard's GUID in string form
// szNetCardTcpipBindPath the bind path name from Tcpip to the card
// strInterfaceName the upper interface name of the card
HRESULT CTcpipcfg::HrAddCard(INetCfgComponent * pnccNetCard, PCWSTR pszCardTcpipBindPath, PCWSTR pszInterfaceName) { GUID guidNetCard; HRESULT hr = pnccNetCard->GetInstanceGuid(&guidNetCard); if (SUCCEEDED(hr)) { // Get card bind name
PWSTR pszNetCardBindName; hr = pnccNetCard->GetBindName(&pszNetCardBindName);
AssertSz(SUCCEEDED(hr), "Net card on binding path with no bind name!!");
// Get card description
// This is only needed for physical cards
//
BOOL fFreeDescription = TRUE; PWSTR pszDescription;
// If we can't get a description then give it a default one
if (FAILED(pnccNetCard->GetDisplayName(&pszDescription))) { pszDescription = const_cast<PWSTR>( SzLoadIds(IDS_UNKNOWN_NETWORK_CARD)); fFreeDescription = FALSE; } Assert (pszDescription);
ADAPTER_INFO* pAdapter = PAdapterFromInstanceGuid(&guidNetCard); if (!pAdapter) { pAdapter = new ADAPTER_INFO;
if (NULL == pAdapter) { return E_OUTOFMEMORY; }
hr = pAdapter->HrSetDefaults(&guidNetCard, pszDescription, pszNetCardBindName, pszCardTcpipBindPath); if (SUCCEEDED(hr)) { // add new card to our data structures and initialize it to default values
m_vcardAdapterInfo.push_back(pAdapter); } else { delete pAdapter; pAdapter = NULL; } } else { // Set the flag that this card is now on the binding path
pAdapter->m_fIsFromAnswerFile = FALSE; pAdapter->m_fDeleted = FALSE;
// reset binding state
pAdapter->m_BindingState = BINDING_UNSET; pAdapter->m_InitialBindingState = BINDING_UNSET;
// Set CardDescription, BindName and BindPathName
pAdapter->m_strDescription = pszDescription; pAdapter->m_strBindName = pszNetCardBindName; pAdapter->m_strTcpipBindPath = pszCardTcpipBindPath;
pAdapter->m_strNetBtBindPath = c_szTcpip_; pAdapter->m_strNetBtBindPath += pAdapter->m_strTcpipBindPath; }
if (SUCCEEDED(hr)) { Assert(pAdapter);
// set flags if ATM card or Wan adapter
if (0 == lstrcmpW(pszInterfaceName, c_szBiNdisAtm)) { pAdapter->m_fIsAtmAdapter = TRUE; } else if (0 == lstrcmpW(pszInterfaceName, c_szBiNdisWanIp)) { pAdapter->m_fIsWanAdapter = TRUE; } #if ENABLE_1394
else if (0 == lstrcmpW(pszInterfaceName, c_szBiNdis1394)) { pAdapter->m_fIs1394Adapter = TRUE; } #endif // ENABLE_1394
}
if (fFreeDescription) { CoTaskMemFree(pszDescription); } CoTaskMemFree(pszNetCardBindName); }
TraceError("CTcpipcfg::HrAddCard", hr); return hr; }
//HrBindCard sets the state of a netcard in the list of installed
// netcards to BOUND
//
// Note: fInitialize is only TRUE when this is called from Initialize,
// the default is FALSE.
//
HRESULT CTcpipcfg::HrBindCard(const GUID* pguid, BOOL fInitialize) { ADAPTER_INFO* pAdapter = PAdapterFromInstanceGuid(pguid); if (pAdapter) { AssertSz(pAdapter->m_BindingState != BINDING_ENABLE, "the same netcard was bound twice to TCPIP");
// Set binding state
pAdapter->m_BindingState = BINDING_ENABLE;
if (fInitialize) pAdapter->m_InitialBindingState = BINDING_ENABLE; } else { AssertSz(FALSE, "Attempt to bind a card which wasn't installed"); } return S_OK; }
//HrUnBindCard sets the state of a netcard in the list of installed
// netcards to UNBOUND
//
// Note: fInitialize is only TRUE when this is called from Initialize,
// the default is FALSE.
//
HRESULT CTcpipcfg::HrUnBindCard(const GUID* pguid, BOOL fInitialize) { ADAPTER_INFO* pAdapter = PAdapterFromInstanceGuid(pguid); if (pAdapter) { AssertSz(pAdapter->m_BindingState != BINDING_DISABLE, "attempt to unbind an unbound card");
// Set binding state to disable
pAdapter->m_BindingState = BINDING_DISABLE;
if (fInitialize) pAdapter->m_InitialBindingState = BINDING_DISABLE; } else { AssertSz(FALSE, "Attempt to unbind a card which wasn't installed"); } return S_OK; }
// HrDeleteCard
// Deletes a card from the list of cards installed in the system
//
HRESULT CTcpipcfg::HrDeleteCard(const GUID* pguid) { ADAPTER_INFO* pAdapter = PAdapterFromInstanceGuid(pguid); if (pAdapter) { pAdapter->m_fDeleted = TRUE; } else { AssertSz(FALSE, "A delete attempt was made on a card which doesn't exist"); } return S_OK; }
//Function to get the list of cards which have been added to the system
//hkeyTcpipParam "Services\Tcpip\Parameters"
HRESULT CTcpipcfg::MarkNewlyAddedCards(const HKEY hkeyTcpipParam) {
//(08/19/98 nsun) changed from Tcpip\Parameters\Interfaces to Tcpip\Parameters\Adapters key
// to support multiple interfaces
HKEY hkeyAdapters; HRESULT hr = HrRegOpenKeyEx(hkeyTcpipParam, c_szAdaptersRegKey, KEY_READ, &hkeyAdapters); if (SUCCEEDED(hr)) { VSTR vstrAdaptersInRegistry; Assert(vstrAdaptersInRegistry.empty());
// Get the list of keys
hr = HrLoadSubkeysFromRegistry(hkeyAdapters, &vstrAdaptersInRegistry); if (SUCCEEDED(hr)) { //Go through the list of cards we currently have
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end(); iterAdapter++) { ADAPTER_INFO* pAdapter = *iterAdapter;
BOOL fAdded = TRUE;
// If we have a card in the list which isn't in registry
// then we add that card to the list of added cards
for(VSTR_CONST_ITER iter = vstrAdaptersInRegistry.begin(); iter != vstrAdaptersInRegistry.end() ; ++iter) { if (lstrcmpiW((**iter).c_str(), pAdapter->m_strBindName.c_str()) == 0) { fAdded = FALSE; break; } }
// if the card is new then mark it
if (fAdded) { pAdapter->m_fNewlyChanged = TRUE; } }
FreeCollectionAndItem(vstrAdaptersInRegistry); } RegCloseKey(hkeyAdapters); } else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) { TraceTag(ttidTcpip, "No existing card found."); hr = S_OK; }
TraceError("CTcpipcfg::MarkNewlyAddedCards", hr); return hr; }
//+------------------------------------------------------------------------------
//
// Function: HrLoadSettings, HrLoadTcpipRegistry, HrLoadWinsRegistry
//
// HrSaveSettings, HrSaveTcpipRegistry, HrSaveTcpipNdisWanRegistry,
// HrSetMisc
//
// Purpose: Functions to Load/Set registry settings and other system info
// during Initialize and Apply time
//
// Author: tongl 5/5/97
//-------------------------------------------------------------------------------
// Called by CTcpipcfg::Initialize
// Load registry settings for a list of net cards
HRESULT CTcpipcfg::HrLoadSettings() { HKEY hkey = NULL;
// Load Tcpip's parameters
HRESULT hrTcpip = S_OK; hrTcpip = m_pnccTcpip->OpenParamKey(&hkey); if (hrTcpip == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) hrTcpip = S_OK; else if (SUCCEEDED(hrTcpip)) { Assert(hkey); hrTcpip = HrLoadTcpipRegistry(hkey); RegCloseKey(hkey); } else Assert(!hkey);
// Load NetBt's parameters
HRESULT hrWins = S_OK;
if (m_pnccWins) { // If Wins is not installed don't get WINS information
hkey = NULL; hrWins = m_pnccWins->OpenParamKey(&hkey); if (hrWins == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) hrWins = S_OK; else if (SUCCEEDED(hrWins)) { Assert(hkey); hrWins = HrLoadWinsRegistry(hkey); RegCloseKey(hkey); } else Assert(!hkey); }
HRESULT hr = S_OK; hr = SUCCEEDED(hrTcpip) ? hr : hrTcpip; hr = SUCCEEDED(hrWins) ? hr : hrWins;
TraceError("CTcpipcfg::HrLoadSettings", hr); return hr; }
// Called by CTcpipcfg::HrLoadSettings
// Loads all information under the Services\Tcpip\Parameters registry key
//
// const HKEY hkeyTcpipParam : Handle to Services\Tcpip\Parameters
HRESULT CTcpipcfg::HrLoadTcpipRegistry(const HKEY hkeyTcpipParam) { HRESULT hr = S_OK; HRESULT hrTmp = S_OK;
Assert(hkeyTcpipParam);
// Load global parameters
// DNS server
// For bug #147476: in NT5 upgrades, somehow the
// global DNS server list is deleted, but not until after initialize exits
// So I'm reading in the value here if it exists
// DNS server list moved from global to per adapter
hrTmp = HrRegQueryString(hkeyTcpipParam, RGAS_NAMESERVER, &m_strDnsServerList);
tstring strDnsSuffixList; if FAILED(hrTmp = HrRegQueryString(hkeyTcpipParam, c_szSearchList, &strDnsSuffixList)) { TraceTag(ttidTcpip, "CTcpipcfg::HrLoadTcpipRegistry"); TraceTag(ttidTcpip, "Failed on loading SearchList, hr: %x", hr); hr = S_OK; } else { ConvertStringToColString(strDnsSuffixList.c_str(), c_chListSeparator, m_glbGlobalInfo.m_vstrDnsSuffixList); }
m_glbGlobalInfo.m_fUseDomainNameDevolution = FRegQueryBool(hkeyTcpipParam, c_szUseDomainNameDevolution, m_glbGlobalInfo.m_fUseDomainNameDevolution);
m_glbGlobalInfo.m_fEnableRouter = FRegQueryBool(hkeyTcpipParam, c_szIpEnableRouter, m_glbGlobalInfo.m_fEnableRouter);
//(nsun 11/02/98) gloabl RRAS settings
m_glbGlobalInfo.m_fEnableIcmpRedirect = FRegQueryBool(hkeyTcpipParam, c_szEnableICMPRedirect, m_glbGlobalInfo.m_fEnableIcmpRedirect);
//PerformRouterDiscoveryDefault was removed to fix bug 405636
m_glbGlobalInfo.m_fDeadGWDetectDefault = FRegQueryBool(hkeyTcpipParam, c_szDeadGWDetectDefault, m_glbGlobalInfo.m_fDeadGWDetectDefault);
m_glbGlobalInfo.m_fDontAddDefaultGatewayDefault = FRegQueryBool(hkeyTcpipParam, c_szDontAddDefaultGatewayDefault, m_glbGlobalInfo.m_fDontAddDefaultGatewayDefault);
m_glbGlobalInfo.m_fEnableFiltering = FRegQueryBool(hkeyTcpipParam, RGAS_SECURITY_ENABLE, m_glbGlobalInfo.m_fEnableFiltering);
// Save old values
m_glbGlobalInfo.ResetOldValues();
// (08/18/98 nsun) read multiple interface settings for WAN adapters
// Open CCS\Services\Tcpip\Parameters\Adapters key
HKEY hkeyAdapters; hr = HrRegOpenKeyEx(hkeyTcpipParam, c_szAdaptersRegKey, KEY_READ, &hkeyAdapters); if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) // no adapters key
hr = S_OK; else if (SUCCEEDED(hr)) { for(VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end() && SUCCEEDED(hr) ; iterAdapter ++) { //multiple interface only valid for WAN adapters
if (!((*iterAdapter)->m_fIsWanAdapter)) continue;
ADAPTER_INFO * pAdapter = *iterAdapter; HKEY hkeyAdapterParam;
hr = HrRegOpenKeyEx(hkeyAdapters, pAdapter->m_strBindName.c_str(), KEY_READ, &hkeyAdapterParam);
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) { Assert("No registry settings for a WAN adapter on the " "bind path?!");
TraceTag(ttidTcpip, "CTcpipcfg::HrLoadTcpipRegistry"); TraceTag(ttidTcpip, "No registry settings for a WAN adapter " "on the bind path, set to defaults"); // We just use the default values
hr = S_OK; } else if (SUCCEEDED(hr)) { TraceTag(ttidTcpip, "CTcpipcfg::HrLoadTcpipRegistry"); TraceTag(ttidTcpip, "Loading multiple interface parameters " "for Adapter '%S'", pAdapter->m_strBindName.c_str());
DWORD dwNumInterfaces; hr = HrRegQueryDword(hkeyAdapterParam, RGAS_NUMINTERFACES, &dwNumInterfaces);
if (FAILED(hr)) { // the Wan adapter is NOT in mode of supporting multiple
// interfaces
TraceTag(ttidTcpip, "No mutliple interface for the WAN " "adapter '%S'", pAdapter->m_strBindName.c_str());
pAdapter->m_fIsMultipleIfaceMode = FALSE; hr = S_OK; } else { pAdapter->m_fIsMultipleIfaceMode = TRUE;
// the WAN adapter supports multiple interface but not
// interface is defined yet
//
if (0 != dwNumInterfaces) { GUID* aguidIds; DWORD cb;
hr = HrRegQueryBinaryWithAlloc(hkeyAdapterParam, RGAS_IPINTERFACES, (LPBYTE*)&aguidIds, &cb); if (FAILED(hr)) { AssertSz(FALSE, "NumInterfaces and IpInterfaces " "values conflicts"); // the Wan adapter is NOT in mode of supporting
// multiple interfaces
//
TraceTag(ttidTcpip, "NumInterfaces and IpInterfaces " "values conflicts for the WAN adapter '%S'", pAdapter->m_strBindName.c_str());
hr = S_OK; } else if (NULL != aguidIds) { dwNumInterfaces = cb / sizeof(GUID);
for(DWORD i = 0; i < dwNumInterfaces; i++) { pAdapter->m_IfaceIds.push_back(aguidIds[i]); }
MemFree(aguidIds); } } }
RegCloseKey(hkeyAdapterParam); } } RegCloseKey(hkeyAdapters); }
// Get per adapter parameters
// Open CCS\Services\Tcpip\Parameters\Interfaces key
HKEY hkeyInterfaces; hr = HrRegOpenKeyEx(hkeyTcpipParam, c_szInterfacesRegKey, KEY_READ, &hkeyInterfaces);
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) //no adapter interfaces
hr = S_OK; else if (SUCCEEDED(hr)) { // Get all the subkeys currently in registry
for(VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end() && SUCCEEDED(hr) ; iterAdapter ++) { ADAPTER_INFO * pAdapter = *iterAdapter;
if (pAdapter->m_fIsWanAdapter) { continue; }
HKEY hkeyInterfaceParam; // Open CCS\Services\Tcpip\Parameters\Interfaces\<card bind path> key
hr = HrRegOpenKeyEx(hkeyInterfaces, pAdapter->m_strTcpipBindPath.c_str(), KEY_READ, &hkeyInterfaceParam);
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) { Assert("No registry settings for a card on the bind path?!");
TraceTag(ttidTcpip, "CTcpipcfg::HrLoadTcpipRegistry"); TraceTag(ttidTcpip, "No registry settings for a card on the bind path, set to defaults"); // We just use the default values
hr = S_OK; } else if (SUCCEEDED(hr)) { TraceTag(ttidTcpip, "CTcpipcfg::HrLoadTcpipRegistry"); TraceTag(ttidTcpip, "Loading parameters for Interface '%S'", pAdapter->m_strTcpipBindPath.c_str());
pAdapter->m_fEnableDhcp = FRegQueryBool(hkeyInterfaceParam, RGAS_ENABLE_DHCP, pAdapter->m_fEnableDhcp);
// Get ip address
if (FAILED(hr = HrRegQueryColString(hkeyInterfaceParam, RGAS_IPADDRESS, &(pAdapter->m_vstrIpAddresses)))) { TraceTag(ttidTcpip, "Failed on loading IpAddress, hr: %x", hr); hr = S_OK; }
// Set subnet mask information
if (FAILED(hr = HrRegQueryColString(hkeyInterfaceParam, RGAS_SUBNETMASK, &(pAdapter->m_vstrSubnetMask)))) { TraceTag(ttidTcpip, "Failed on loading SubnetMask, hr: %x", hr); hr = S_OK; }
// Set default gateway
if (FAILED(hr = HrRegQueryColString(hkeyInterfaceParam, RGAS_DEFAULTGATEWAY, &(pAdapter->m_vstrDefaultGateway)))) { TraceTag(ttidTcpip, "Failed on loading Default Gateway, hr: %x", hr); hr = S_OK; }
if (FAILED(hr = HrRegQueryColString(hkeyInterfaceParam, RGAS_DEFAULTGATEWAYMETRIC, &(pAdapter->m_vstrDefaultGatewayMetric)))) { TraceTag(ttidTcpip, "Failed on Loading Default Gateway Metric, hr: %x", hr); hr = S_OK; }
// Dns domain
if (FAILED(hr = HrRegQueryString(hkeyInterfaceParam, RGAS_DOMAIN, &(pAdapter->m_strDnsDomain)))) { TraceTag(ttidTcpip, "Failed on loading DnsDomain, hr: %x", hr); hr = S_OK; }
// Dns ip address dynamic update
pAdapter->m_fDisableDynamicUpdate = !DnsIsDynamicRegistrationEnabled( (LPWSTR)pAdapter->m_strTcpipBindPath.c_str());
// adapter Dns domain name registration
pAdapter->m_fEnableNameRegistration = DnsIsAdapterDomainNameRegistrationEnabled( (LPWSTR)pAdapter->m_strTcpipBindPath.c_str());
// Dns server search list
tstring strDnsServerList; if (FAILED(hr = HrRegQueryString(hkeyInterfaceParam, RGAS_NAMESERVER, &strDnsServerList))) { TraceTag(ttidTcpip, "Failed on loading Dns NameServer list, hr: %x", hr); hr = S_OK; } else { ConvertStringToColString(strDnsServerList.c_str(), c_chListSeparator, pAdapter->m_vstrDnsServerList);
}
// Interface metric
if FAILED(hr = HrRegQueryDword(hkeyInterfaceParam, c_szInterfaceMetric, &(pAdapter->m_dwInterfaceMetric))) { TraceTag(ttidTcpip, "Failed on loading InterfaceMetric, hr: %x", hr); hr = S_OK; }
// TCP port filter
VSTR vstrTcpFilterList; if (FAILED(hr = HrRegQueryColString(hkeyInterfaceParam, RGAS_FILTERING_TCP, &vstrTcpFilterList))) { TraceTag(ttidTcpip, "Failed on loading TCP filter list, hr: %x", hr); hr = S_OK; } else { CopyVstr(&pAdapter->m_vstrTcpFilterList, vstrTcpFilterList); FreeCollectionAndItem(vstrTcpFilterList); }
// UDP port filter
VSTR vstrUdpFilterList; if (FAILED(hr = HrRegQueryColString(hkeyInterfaceParam, RGAS_FILTERING_UDP, &vstrUdpFilterList))) { TraceTag(ttidTcpip, "Failed on loading UDP filter list, hr: %x", hr); hr = S_OK; } else { CopyVstr(&pAdapter->m_vstrUdpFilterList, vstrUdpFilterList); FreeCollectionAndItem(vstrUdpFilterList); }
// IP port filter
VSTR vstrIpFilterList; if (FAILED(hr = HrRegQueryColString(hkeyInterfaceParam, RGAS_FILTERING_IP, &vstrIpFilterList))) { TraceTag(ttidTcpip, "Failed on loading IP filter list, hr: %x", hr); hr = S_OK; } else { CopyVstr(&pAdapter->m_vstrIpFilterList, vstrIpFilterList); FreeCollectionAndItem(vstrIpFilterList); }
if (FAILED(HrLoadBackupTcpSettings(hkeyInterfaceParam, pAdapter))) { TraceTag(ttidTcpip, "Failed on loading Backup IP settings, hr: %x", hr); hr = S_OK; }
// ATM ARP client configurable parameters
if (pAdapter->m_fIsAtmAdapter) { HKEY hkeyAtmarpc = NULL;
// Open the Atmarpc subkey
hr = HrRegOpenKeyEx(hkeyInterfaceParam, c_szAtmarpc, KEY_READ, &hkeyAtmarpc);
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) { AssertSz(FALSE,"No atmarpc subkey for an atm adapter on the bind path?!");
TraceTag(ttidTcpip, "Failed on opening atmarpc subkey, defaults will be used, hr: %x", hr); hr = S_OK; } else if (SUCCEEDED(hr)) { // ARP server address list
if (FAILED(hr = HrRegQueryColString(hkeyAtmarpc, c_szREG_ARPServerList, &(pAdapter->m_vstrARPServerList)))) { TraceTag(ttidTcpip, "Failed on loading ARPServerList, hr: %x", hr); hr = S_OK; }
// MAR server address list
if (FAILED(hr = HrRegQueryColString(hkeyAtmarpc, c_szREG_MARServerList, &(pAdapter->m_vstrMARServerList)))) { TraceTag(ttidTcpip, "Failed on loading MARServerList, hr: %x", hr); hr = S_OK; }
// Max Transmit Unit
if (FAILED(hr = HrRegQueryDword(hkeyAtmarpc, c_szREG_MTU, &(pAdapter->m_dwMTU)))) { TraceTag(ttidTcpip, "Failed on loading MTU, hr: %x", hr); hr = S_OK; }
// PVC Only
pAdapter->m_fPVCOnly = FRegQueryBool(hkeyAtmarpc, c_szREG_PVCOnly, pAdapter->m_fPVCOnly);
RegCloseKey(hkeyAtmarpc); } }
(*iterAdapter)->ResetOldValues();
RegCloseKey(hkeyInterfaceParam); } } RegCloseKey(hkeyInterfaces); }
TraceError("CTcpipcfg::HrLoadTcpipRegistry", hr); return hr; }
// Called by CTcpipcfg::HrLoadSettings
// Loads all information under the Services\NetBt\Parameters registry key
//
// const HKEY hkeyWinsParam : Handle to Services\NetBt\Parameters
HRESULT CTcpipcfg::HrLoadWinsRegistry(const HKEY hkeyWinsParam) { HRESULT hr = S_OK;
// Global parameters
m_glbGlobalInfo.m_fEnableLmHosts = FRegQueryBool( hkeyWinsParam, RGAS_ENABLE_LMHOSTS, m_glbGlobalInfo.m_fEnableLmHosts);
// Save a copy of these values for non-reboot reconfiguration notification
m_glbGlobalInfo.m_fOldEnableLmHosts = m_glbGlobalInfo.m_fEnableLmHosts;
HKEY hkeyInterfaces; hr = HrRegOpenKeyEx(hkeyWinsParam, c_szInterfacesRegKey, KEY_READ, &hkeyInterfaces);
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) hr = S_OK; else if (SUCCEEDED(hr)) { for(VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end(); iterAdapter ++) { ADAPTER_INFO * pAdapter = *iterAdapter;
// $REIVEW (nsun 10/05/98) We don't need to read NetBT settings the WAN adapter
if (pAdapter->m_fIsWanAdapter) { continue; }
// Open the NetBt\Interfaces\<Something> to get per
// adapter NetBt settings
HKEY hkeyInterfaceParam; hr = HrRegOpenKeyEx(hkeyInterfaces, pAdapter->m_strNetBtBindPath.c_str(), KEY_READ, &hkeyInterfaceParam);
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) hr = S_OK; else if (SUCCEEDED(hr)) { TraceTag(ttidTcpip, "CTcpipcfg::HrLoadWinsRegistry"); TraceTag(ttidTcpip, "Interface '%S'", pAdapter->m_strNetBtBindPath.c_str());
// load wins server address list
if (FAILED(hr = HrRegQueryColString(hkeyInterfaceParam, RGAS_NETBT_NAMESERVERLIST, &(pAdapter->m_vstrWinsServerList)))) { TraceTag(ttidTcpip, "Failed on loading NameServerList, hr: %x", hr); hr = S_OK; }
// Save a copy in m_strOldWinsServerList
CopyVstr(&(pAdapter->m_vstrOldWinsServerList), pAdapter->m_vstrWinsServerList);
// load Netbios options
if (FAILED(hr = HrRegQueryDword(hkeyInterfaceParam, RGAS_NETBT_NETBIOSOPTIONS, &(pAdapter->m_dwNetbiosOptions)))) { TraceTag(ttidTcpip, "Failed on loading NetbiosOptions, hr: %x", hr); hr = S_OK; }
// Save a copy in m_dwOldNetbiosOptions
pAdapter->m_dwOldNetbiosOptions = pAdapter->m_dwNetbiosOptions;
RegCloseKey(hkeyInterfaceParam); } } RegCloseKey(hkeyInterfaces); }
TraceError("CTcpipcfg::HrLoadWinsRegistry", hr); return hr; }
// Called by CTcpipcfg::Apply
// This function writes all changes to the registy and makes other
// appropriate changes to the system
HRESULT CTcpipcfg::HrSaveSettings() { HRESULT hr = S_OK;
HRESULT hrTcpip = S_OK; HKEY hkeyTcpipParam = NULL; Assert(m_pnccTcpip);
if (m_pnccTcpip) { hrTcpip = m_pnccTcpip->OpenParamKey(&hkeyTcpipParam);
// We use hr instead of hrTcpip because this operation is NOT part of
// HrSaveTcpipRegistry.
// We must get the list of Added Cards before anything else because
// otherwise the Adapter GUID keys will be written later and we will
// not know if they didn't exist in the system before.
if (SUCCEEDED(hrTcpip)) { hrTcpip = MarkNewlyAddedCards(hkeyTcpipParam);
if (SUCCEEDED(hrTcpip)) { Assert(hkeyTcpipParam); hrTcpip = HrSaveTcpipRegistry(hkeyTcpipParam); } else Assert(!hkeyTcpipParam); } }
HRESULT hrWins = S_OK; HKEY hkeyWinsParam = NULL;
Assert(m_pnccWins);
if (m_pnccWins) { hrWins = m_pnccWins->OpenParamKey(&hkeyWinsParam); if (SUCCEEDED(hrWins)) { Assert(hkeyWinsParam); hrWins = HrSaveWinsRegistry(hkeyWinsParam); } else Assert(!hkeyWinsParam); }
HRESULT hrMisc = S_OK;
//if hrTcpip == E_? then this is possible (thus no Assert)
// yes because hrTcpip can be set to E_? from HrSaveTcpipRegistry
if ((hkeyTcpipParam) && (hkeyWinsParam)) { hrMisc = HrSetMisc(hkeyTcpipParam, hkeyWinsParam); }
RegSafeCloseKey(hkeyTcpipParam); RegSafeCloseKey(hkeyWinsParam);
hr = SUCCEEDED(hr) ? hrTcpip : hr; hr = SUCCEEDED(hr) ? hrWins : hr; hr = SUCCEEDED(hr) ? hrMisc : hr;
TraceError("CTcpipcfg::HrSaveSettings", hr); return hr; }
// Set global and adapter specific parameters under
// CCS\Services\TCpip\Parameters
// hkeyTcpipParam handle to reg key HKLM\Systems\CCS\Services\TCpip\Parameters
HRESULT CTcpipcfg::HrSaveTcpipRegistry(const HKEY hkeyTcpipParam) { // hr is the first error occurred,
// but we don't want to stop at the first error
HRESULT hr = S_OK; HRESULT hrTmp = S_OK;
// Save global info
// DNS host name ( only on installing )
if (m_fInstalling) { if (!m_fUpgradeGlobalDnsDomain) { // Bug 299038, during install of tcpip, try to get the primary dns domain name
// create the global DNS domain as an empty string during clean install if
// we couldn't find the primary dns domain name (219090).
// if we already got the global Dns Domain when processing the answer file, we should
// use the value from the answer file
tstring strTmpDomain; hrTmp = HrRegQueryString(hkeyTcpipParam, RGAS_DOMAIN, &strTmpDomain); if (FAILED(hrTmp)) { hrTmp = HrGetPrimaryDnsDomain(&strTmpDomain);
if (SUCCEEDED(hrTmp)) { if (!SetComputerNameEx(ComputerNamePhysicalDnsDomain, strTmpDomain.c_str())) { hrTmp = GetLastError(); TraceError("CTcpipcfg::HrSaveTcpipRegistry: SetComputerNameEx failed.", hrTmp); } } else { //Bug #335626, some SrvApp directly retrive this value, so we need to create it for
//standalone machines
strTmpDomain = c_szEmpty; } //SetComputerNameEx() will write to "Domain" reg value after reboot. Per GlennC, it's ok to write
//the Domain value here to solve the SrvApp compatibility issue.
HrRegSetString(hkeyTcpipParam, RGAS_DOMAIN, strTmpDomain); }
//the hrTmp get from this section should not affect the
//final return value
}
//
// 391590: We've saved the hostname from NT4 into the answerfile so that
// we can remember the exact (case-sensitive) string. If the
// saved DNS hostname is the same (except for case) as the current
// COMPUTERNAME, we set the NT5 DNS hostname to be the saved one,
// for SAP compatibility (they make case-sensitive comparisons).
// Otherwise, we use the regular COMPUTERNAME, lowercased, as the
// DNS hostname.
//
if (!lstrcmpiW(m_glbGlobalInfo.m_strHostName.c_str(), m_glbGlobalInfo.m_strHostNameFromAnswerFile.c_str())) { hrTmp = HrRegSetString(hkeyTcpipParam, RGAS_HOSTNAME, m_glbGlobalInfo.m_strHostNameFromAnswerFile); if (S_OK == hrTmp) { hrTmp = HrRegSetString(hkeyTcpipParam, RGAS_NVHOSTNAME, m_glbGlobalInfo.m_strHostNameFromAnswerFile); } } else { hrTmp = HrRegSetString(hkeyTcpipParam, RGAS_HOSTNAME, m_glbGlobalInfo.m_strHostName); if (S_OK == hrTmp) { hrTmp = HrRegSetString(hkeyTcpipParam, RGAS_NVHOSTNAME, m_glbGlobalInfo.m_strHostName); } }
TraceError("CTcpipcfg::HrSaveTcpipRegistry: Failed to set HostName.", hrTmp);
//the hrTmp get from this section should not affect the
//final return value
}
// Added per request from Stuart Kwan:
// only when the global DNS domain is read from answerfile
if (m_fUpgradeGlobalDnsDomain) { if (!SetComputerNameEx(ComputerNamePhysicalDnsDomain, m_strUpgradeGlobalDnsDomain.c_str())) { hrTmp = GetLastError(); TraceError("CTcpipcfg::HrSaveTcpipRegistry: SetComputerNameEx failed.", hrTmp); }
//If the registry value Services\Tcpip\Parameters\SyncDomainWithMembership != 0,
//Netlogon will try to overwirte the value with the member domain name when joining
//into the domain. (See NT bug 310143
//
//Due to bug WinSE 7317, most users don't want us to manually set SyncDomainWithMembership
//reg value as 0 here.
//
//As a workaround in order to upgarde the gloabl Dns domain name, the user has to
//add SyncDomainWithMembership reg value under tcpip parameters and make it as 0.
//In the unattended install case, there needs to be a line
// SyncDomainWithMembership=0
//in the global tcpip parameters section if the user want to specify a global DNS
//domain name that is different with the membership domain name.
//the hrTmp get from this section should not affect the
//final return value
}
// Dns suffix list
tstring strSearchList; ConvertColStringToString(m_glbGlobalInfo.m_vstrDnsSuffixList, c_chListSeparator, strSearchList);
hrTmp = HrRegSetString(hkeyTcpipParam, RGAS_SEARCHLIST, strSearchList);
if (SUCCEEDED(hr)) hr = hrTmp;
// UseDomainNameDevolution
hrTmp = HrRegSetBool(hkeyTcpipParam, c_szUseDomainNameDevolution, m_glbGlobalInfo.m_fUseDomainNameDevolution); if (SUCCEEDED(hr)) hr = hrTmp;
// IpEnableRouter
hrTmp = HrRegSetBool(hkeyTcpipParam, c_szIpEnableRouter, m_glbGlobalInfo.m_fEnableRouter); if (SUCCEEDED(hr)) hr = hrTmp;
//(nsun 11/02/98) parameters of RRAS for unattended install
hrTmp = HrRegSetBool(hkeyTcpipParam, c_szEnableICMPRedirect, m_glbGlobalInfo.m_fEnableIcmpRedirect); if (SUCCEEDED(hr)) hr = hrTmp;
hrTmp = HrRegSetBool(hkeyTcpipParam, c_szDeadGWDetectDefault, m_glbGlobalInfo.m_fDeadGWDetectDefault); if (SUCCEEDED(hr)) hr = hrTmp;
hrTmp = HrRegSetBool(hkeyTcpipParam, c_szDontAddDefaultGatewayDefault, m_glbGlobalInfo.m_fDontAddDefaultGatewayDefault); if (SUCCEEDED(hr)) hr = hrTmp;
hrTmp = HrRegSetBool(hkeyTcpipParam, RGAS_SECURITY_ENABLE, m_glbGlobalInfo.m_fEnableFiltering); if (SUCCEEDED(hr)) hr = hrTmp;
// Adapter specific info (physical cards)
HKEY hkeyAdapters = NULL; DWORD dwDisposition;
// Create or open the "Adapters" key under "Services\Tcpip\Parameters"
hrTmp = HrRegCreateKeyEx(hkeyTcpipParam, c_szAdaptersRegKey, REG_OPTION_NON_VOLATILE, KEY_READ_WRITE_DELETE, NULL, &hkeyAdapters, &dwDisposition); if (SUCCEEDED(hr)) hr = hrTmp;
if (SUCCEEDED(hrTmp)) { Assert(hkeyAdapters); for(VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end(); iterAdapter ++) { ADAPTER_INFO * pAdapter = *iterAdapter;
// No need to do this for RAS fake adapters
if (pAdapter->m_fIsRasFakeAdapter) { continue; }
// Create specific card bindname key under
// "Services\Tcpip\Parameters\Adapters\<card bind name>"
//
HKEY hkeyAdapterParam; hrTmp = HrRegCreateKeyEx(hkeyAdapters, pAdapter->m_strBindName.c_str(), REG_OPTION_NON_VOLATILE, KEY_READ_WRITE_DELETE, NULL, &hkeyAdapterParam, &dwDisposition);
if (SUCCEEDED(hr)) hr = hrTmp;
if (SUCCEEDED(hrTmp)) { Assert(hkeyAdapterParam);
// Set LLInterface and IpConfig for new cards
//
if (pAdapter->m_fNewlyChanged) { PCWSTR pszArpModule = c_szEmpty;
if (pAdapter->m_fIsWanAdapter) { pszArpModule = c_szWanArp; } else if (pAdapter->m_fIsAtmAdapter) { pszArpModule = c_szAtmArp; } #if ENABLE_1394
else if (pAdapter->m_fIs1394Adapter) { pszArpModule = c_sz1394Arp; } #endif // ENABLE_1394
hrTmp = HrRegSetSz(hkeyAdapterParam, RGAS_LLINTERFACE, pszArpModule); if (SUCCEEDED(hr)) hr = hrTmp;
// (08/18/98 nsun) modified to support multiple interfaces of WAN adapter
VSTR vstrIpConfig;
if (!pAdapter->m_fIsMultipleIfaceMode) { HrRegDeleteValue(hkeyAdapterParam, RGAS_NUMINTERFACES);
tstring* pstr = new tstring(RGAS_TCPIP_PARAM_INTERFACES);
if (pstr == NULL) { return(E_OUTOFMEMORY); }
pstr->append(pAdapter->m_strTcpipBindPath); vstrIpConfig.push_back(pstr);
hrTmp = HrRegSetColString(hkeyAdapterParam, RGAS_IPCONFIG, vstrIpConfig); } else { AssertSz(pAdapter->m_fIsWanAdapter, "The card is not WAN adapter, but how can it support multiple interface.");
tstring strInterfaceName; IFACEITER iterId;
for(iterId = pAdapter->m_IfaceIds.begin(); iterId != pAdapter->m_IfaceIds.end(); iterId++) { GetInterfaceName( pAdapter->m_strTcpipBindPath.c_str(), *iterId, &strInterfaceName);
tstring* pstr = new tstring(RGAS_TCPIP_PARAM_INTERFACES); pstr->append(strInterfaceName);
vstrIpConfig.push_back(pstr); }
hrTmp = HrRegSetColString(hkeyAdapterParam, RGAS_IPCONFIG, vstrIpConfig);
if (SUCCEEDED(hr)) hr = hrTmp;
//$REVIEW (nsun 09/15/98) use NumInterfaces value to identify if the adapter is in the
//mode of supporting multiple interfaces. If the NumInterfaces
//exists, the adapter supports multiple interfaces.
//If NumInterfaces == 0, it means the adapter supports multiple interfaces
// but no interface is associated with it. So the IpInterfaces should not
// exists. The NumInterfaces and IpInterfaces should alwasy be consistent.
DWORD dwNumInterfaces = pAdapter->m_IfaceIds.size(); hrTmp = HrRegSetDword(hkeyAdapterParam, RGAS_NUMINTERFACES, dwNumInterfaces);
if (SUCCEEDED(hr)) hr = hrTmp;
if ( 0 != dwNumInterfaces ) { GUID* aguid; DWORD cguid; hrTmp = GetGuidArrayFromIfaceColWithCoTaskMemAlloc( pAdapter->m_IfaceIds, &aguid, &cguid); if (SUCCEEDED(hr)) hr = hrTmp;
Assert(aguid); hrTmp = HrRegSetBinary(hkeyAdapterParam, RGAS_IPINTERFACES, (BYTE*) aguid, cguid * sizeof(GUID)); CoTaskMemFree(aguid); } else { hrTmp = HrRegDeleteValue(hkeyAdapterParam, RGAS_IPINTERFACES);
//It's fine that the IpInterfaces does not exist at all if
// the WAN adapter does not support multiple interfaces.
if (hrTmp == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) hrTmp = S_OK; }
}
FreeCollectionAndItem(vstrIpConfig); if (SUCCEEDED(hr)) hr = hrTmp; }
RegCloseKey(hkeyAdapterParam); } }
RegCloseKey(hkeyAdapters); }
// Create or open the "Interfaces" key under "Services\Tcpip\Parameters"
//
HKEY hkeyInterfaces; hrTmp = HrRegCreateKeyEx(hkeyTcpipParam, c_szInterfacesRegKey, REG_OPTION_NON_VOLATILE, KEY_READ_WRITE_DELETE, NULL, &hkeyInterfaces, &dwDisposition); if (SUCCEEDED(hr)) hr = hrTmp;
if (SUCCEEDED(hrTmp)) { Assert(hkeyInterfaces); for(VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end(); iterAdapter ++) { if ((*iterAdapter)->m_fIsRasFakeAdapter) { continue; }
ADAPTER_INFO * pAdapter = *iterAdapter;
//(08/20/98 nsun) modified to support multiple interfaces of WAN adapter
// NULL != pAdapter->m_IfaceIds means it's in multiple interface mode
if (pAdapter->m_fIsWanAdapter && pAdapter->m_fIsMultipleIfaceMode) { if (pAdapter->m_fNewlyChanged) { HrSaveMultipleInterfaceWanRegistry(hkeyInterfaces, pAdapter); } continue; }
// Create specific card interface key under
// "Services\Tcpip\Parameters\Interfaces\<card bind path>"
//
HKEY hkeyInterfaceParam; hrTmp = HrRegCreateKeyEx(hkeyInterfaces, pAdapter->m_strTcpipBindPath.c_str(), REG_OPTION_NON_VOLATILE, KEY_READ_WRITE_DELETE, NULL, &hkeyInterfaceParam, &dwDisposition);
if (SUCCEEDED(hr)) hr = hrTmp;
if (SUCCEEDED(hrTmp)) { Assert(hkeyInterfaceParam);
if (pAdapter->m_fNewlyChanged) { //Bug306259 If UseZeroBroadCast already exists (which means it is from the answer
// file), we should not overwrite it with the default value.
DWORD dwTmp; hrTmp = HrRegQueryDword(hkeyInterfaceParam, RGAS_USEZEROBROADCAST, &dwTmp); if (FAILED(hrTmp)) { // ZeroBroadcast
hrTmp = HrRegSetDword(hkeyInterfaceParam, RGAS_USEZEROBROADCAST, 0); if (SUCCEEDED(hr)) hr = hrTmp; }
if (pAdapter->m_fIsWanAdapter) { // For new RAS cards
hrTmp = HrSaveStaticWanRegistry(hkeyInterfaceParam); } else if (pAdapter->m_fIsAtmAdapter) { // For new ATM cards
hrTmp = HrSaveStaticAtmRegistry(hkeyInterfaceParam); } #if ENABLE_1394
else if (pAdapter->m_fIs1394Adapter) { // For new NIC1394 cards
// (nothing to do).
hrTmp = S_OK; } #endif // ENABLE_1394
else { //(nsun 11/02/98) set static RRAS parameters for unattended install
//if the values exists, that means they have been set as an unconfigurable
//parameter during upgrade,
//we should not set the default value.
DWORD dwTmp;
hrTmp = HrRegQueryDword(hkeyInterfaceParam, c_szDeadGWDetect, &dwTmp); if (FAILED(hrTmp)) { hrTmp = HrRegSetBool(hkeyInterfaceParam, c_szDeadGWDetect, m_glbGlobalInfo.m_fDeadGWDetectDefault); } }
if (SUCCEEDED(hr)) hr = hrTmp; }
// For LAN cards and RAS fake guids
if (!pAdapter->m_fIsWanAdapter) { // Ip address etc
hrTmp = HrRegSetBool(hkeyInterfaceParam, RGAS_ENABLE_DHCP, pAdapter->m_fEnableDhcp); if (SUCCEEDED(hr)) hr = hrTmp;
//warning: these VSTRs will contain pointers to strings
//that are either local to this function or
//that are also pointed to in another VSTR
// DO NOT call FreeCollectionAndItem on them!
VSTR vstrIpAddresses; VSTR vstrSubnetMask; tstring ZeroAddress(ZERO_ADDRESS);
if (pAdapter->m_fEnableDhcp) { vstrIpAddresses.push_back(&ZeroAddress); vstrSubnetMask.push_back(&ZeroAddress); } else { vstrIpAddresses = pAdapter->m_vstrIpAddresses; vstrSubnetMask = pAdapter->m_vstrSubnetMask; }
hrTmp = HrRegSetColString(hkeyInterfaceParam, RGAS_IPADDRESS, vstrIpAddresses); if (SUCCEEDED(hr)) hr = hrTmp;
hrTmp = HrRegSetColString(hkeyInterfaceParam, RGAS_SUBNETMASK, vstrSubnetMask); if (SUCCEEDED(hr)) hr = hrTmp;
hrTmp = HrRegSetColString(hkeyInterfaceParam, RGAS_DEFAULTGATEWAY, pAdapter->m_vstrDefaultGateway); if (SUCCEEDED(hr)) hr = hrTmp;
hrTmp = HrRegSetColString(hkeyInterfaceParam, RGAS_DEFAULTGATEWAYMETRIC, pAdapter->m_vstrDefaultGatewayMetric); if (SUCCEEDED(hr)) hr = hrTmp;
// DNS name server list
tstring strNameServer; ConvertColStringToString(pAdapter->m_vstrDnsServerList, c_chListSeparator, strNameServer);
hrTmp = HrRegSetString(hkeyInterfaceParam, RGAS_NAMESERVER, strNameServer); if (SUCCEEDED(hr)) hr = hrTmp;
// DNS domain
hrTmp = HrRegSetString(hkeyInterfaceParam, RGAS_DOMAIN, pAdapter->m_strDnsDomain); if (SUCCEEDED(hr)) hr = hrTmp;
// Dns ip address dynamic update
if (pAdapter->m_fDisableDynamicUpdate) { DnsDisableDynamicRegistration( (LPWSTR)pAdapter->m_strTcpipBindPath.c_str()); } else { DnsEnableDynamicRegistration( (LPWSTR)pAdapter->m_strTcpipBindPath.c_str()); }
// adapter Dns domain name registration
if (pAdapter->m_fEnableNameRegistration) { DnsEnableAdapterDomainNameRegistration( (LPWSTR)pAdapter->m_strTcpipBindPath.c_str()); } else { DnsDisableAdapterDomainNameRegistration( (LPWSTR)pAdapter->m_strTcpipBindPath.c_str()); }
// InterfaceMetric
if (c_dwDefaultIfMetric != pAdapter->m_dwInterfaceMetric) { hrTmp = HrRegSetDword(hkeyInterfaceParam, c_szInterfaceMetric, pAdapter->m_dwInterfaceMetric); } else { //The interface metric is default, remove that value.
//In such way, it would be much easier to upgrade if the default is changed
//in the future
hrTmp = HrRegDeleteValue(hkeyInterfaceParam, c_szInterfaceMetric);
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hrTmp) hrTmp = S_OK; } if (SUCCEEDED(hr)) hr = hrTmp;
// TCPAllowedPorts
hrTmp = HrRegSetColString(hkeyInterfaceParam, RGAS_FILTERING_TCP, pAdapter->m_vstrTcpFilterList); if (SUCCEEDED(hr)) hr = hrTmp;
// UDPAllowedPorts
hrTmp = HrRegSetColString(hkeyInterfaceParam, RGAS_FILTERING_UDP, pAdapter->m_vstrUdpFilterList); if (SUCCEEDED(hr)) hr = hrTmp;
// IPAllowedPorts
hrTmp = HrRegSetColString(hkeyInterfaceParam, RGAS_FILTERING_IP, pAdapter->m_vstrIpFilterList); if (SUCCEEDED(hr)) hr = hrTmp;
// For ATM cards only
if (pAdapter->m_fIsAtmAdapter) { HKEY hkeyAtmarpc;
// Open the Atmarpc subkey
hrTmp = HrRegCreateKeyEx(hkeyInterfaceParam, c_szAtmarpc, REG_OPTION_NON_VOLATILE, KEY_READ_WRITE, NULL, &hkeyAtmarpc, &dwDisposition);
if (SUCCEEDED(hrTmp)) { hrTmp = HrRegSetColString(hkeyAtmarpc, c_szREG_ARPServerList, pAdapter->m_vstrARPServerList); if (SUCCEEDED(hr)) hr = hrTmp;
hrTmp = HrRegSetColString(hkeyAtmarpc, c_szREG_MARServerList, pAdapter->m_vstrMARServerList); if (SUCCEEDED(hr)) hr = hrTmp;
hrTmp = HrRegSetDword(hkeyAtmarpc, c_szREG_MTU, pAdapter->m_dwMTU); if (SUCCEEDED(hr)) hr = hrTmp;
hrTmp = HrRegSetBool(hkeyAtmarpc, c_szREG_PVCOnly, pAdapter->m_fPVCOnly); if (SUCCEEDED(hr)) hr = hrTmp;
RegCloseKey(hkeyAtmarpc); } }
hrTmp = HrDuplicateToNT4Location(hkeyInterfaceParam, pAdapter); if (SUCCEEDED(hr)) hr = hrTmp;
hrTmp = HrSaveBackupTcpSettings(hkeyInterfaceParam, pAdapter); if (SUCCEEDED(hr)) hr = hrTmp;
} // For LAN cards and RAS fake guids only
RegCloseKey(hkeyInterfaceParam); } }
RegCloseKey(hkeyInterfaces); }
TraceError("CTcpipcfg::HrSaveTcpipRegistry", hr); return hr; }
HRESULT CTcpipcfg::HrSaveWinsRegistry(const HKEY hkeyWinsParam) { // hr is the first error occurred,
// but we don't want to stop at the first error
HRESULT hr = S_OK; HRESULT hrTmp = S_OK;
// Global parameters
hrTmp = HrRegSetBool(hkeyWinsParam, RGAS_ENABLE_LMHOSTS, m_glbGlobalInfo.m_fEnableLmHosts); if (SUCCEEDED(hr)) hr = hrTmp; /*$REVIEW (nsun 2/17/98) Bug #293643 We don't want to change any unconfigurable values
// $REVIEW(tongl 8/3/97): Added NodeType settings #97364.
// If no adapter has static WINS address, then remove NodeType.
// otherwise, the user has specified the WINs server address for
// at least one adapters, set NodeType = 0x08 (H-NODE)
BOOL fNoWinsAddress = TRUE;
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end(); iterAdapter++) { ADAPTER_INFO * pAdapter = *iterAdapter;
if ((!pAdapter->m_fIsWanAdapter)&& (BINDING_ENABLE == pAdapter->m_BindingState)&& (pAdapter->m_vstrWinsServerList.size()>0)) { fNoWinsAddress = FALSE; } }
DWORD dwNodeType; hrTmp = HrRegQueryDword(hkeyWinsParam, c_szNodeType, &dwNodeType); // dwNodeType ==0 means the key did not exist before we apply
if (hrTmp == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) dwNodeType =0;
if (!m_fAnswerFileBasedInstall || (hrTmp == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))) { if (!fNoWinsAddress) // set NodeType to 0x08
{ if (dwNodeType != c_dwHNode) { hrTmp = HrRegSetDword(hkeyWinsParam, c_szNodeType, c_dwHNode); if (SUCCEEDED(hr)) hr = hrTmp; } } else // remove NodeType key
{ if (dwNodeType != 0) { hrTmp = HrRegDeleteValue(hkeyWinsParam, c_szNodeType);
if (SUCCEEDED(hr)) hr = hrTmp; } } } */ // $REVIEW(tongl 12\1\97): Per agreement with Malam today(see email),
// NetBt will re-read NodeType when notified of wins address list change.
// Thus no need to notify change separately below.
/*
if (fNodeTypeChanged) { // Send notification to NetBt
TraceTag(ttidTcpip,"NodeType parameter changed, send notification on apply."); SetReconfig(); // SetReconfigNbt();
} */
// Adapter interface specific parameters
// Create the "Services\NetBt\Interfacess" key
HKEY hkeyInterfaces; DWORD dwDisposition; hrTmp = HrRegCreateKeyEx(hkeyWinsParam, c_szInterfacesRegKey, REG_OPTION_NON_VOLATILE, KEY_READ_WRITE, NULL, &hkeyInterfaces, &dwDisposition); if (SUCCEEDED(hr)) hr = hrTmp;
if (SUCCEEDED(hrTmp)) { for(VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end(); iterAdapter++) { ADAPTER_INFO * pAdapter = *iterAdapter;
//(10/05/98 nsun) modified to support multiple interfaces of WAN adapter
// NULL != pAdapter->m_IfaceIds means it's in multiple interface mode
if (pAdapter->m_fNewlyChanged && pAdapter->m_fIsWanAdapter && pAdapter->m_fIsMultipleIfaceMode) { HrSaveWinsMultipleInterfaceWanRegistry(hkeyInterfaces, pAdapter); continue; }
HKEY hkeyInterfaceParam; hrTmp = HrRegCreateKeyEx(hkeyInterfaces, pAdapter->m_strNetBtBindPath.c_str(), REG_OPTION_NON_VOLATILE, KEY_READ_WRITE, NULL, &hkeyInterfaceParam, &dwDisposition);
if (SUCCEEDED(hr)) hr = hrTmp;
if (SUCCEEDED(hrTmp)) { // For new RAS cards, only set static values
if (pAdapter->m_fIsWanAdapter && pAdapter->m_fNewlyChanged) { hrTmp = HrRegSetMultiSz(hkeyInterfaceParam, RGAS_NETBT_NAMESERVERLIST, L"\0"); if (SUCCEEDED(hr)) hr = hrTmp; } else // if not RAS adapter
{ // set wins server address list
hrTmp = HrRegSetColString(hkeyInterfaceParam, RGAS_NETBT_NAMESERVERLIST, pAdapter->m_vstrWinsServerList); if (SUCCEEDED(hr)) hr = hrTmp;
// set NetbiosOptions
hrTmp = HrRegSetDword(hkeyInterfaceParam, RGAS_NETBT_NETBIOSOPTIONS, pAdapter->m_dwNetbiosOptions); if (SUCCEEDED(hr)) hr = hrTmp; }
RegCloseKey(hkeyInterfaceParam); } }
RegCloseKey(hkeyInterfaces); }
TraceError("CTcpipcfg::HrSaveWinsRegistry", hr); return hr; }
// Called by CTcpipcfg::SaveSettings
// Does a lot of miscelaneous actions when Apply is called
// Including cleaning up registry and remove isolated cards
//
// HKEY hkeyTcpipParam Serviess\Tcpip\Parameters
// HKEY hkeyWinsParam Services\NetBt\Parameters
HRESULT CTcpipcfg::HrSetMisc(const HKEY hkeyTcpipParam, const HKEY hkeyWinsParam) { HRESULT hr = S_OK; HRESULT hrTmp = S_OK;
// Registry Cleanup !!
// We remove DNS domain and DNS server list in NT5 upgrades
if (m_fUpgradeCleanupDnsKey) { hrTmp = HrRegDeleteValue(hkeyTcpipParam, RGAS_NAMESERVER);
// $REVIEW(tongl 3/22/98): Per Stuart Kwan, global DNSDomain key
// is also used.
// hrTmp = HrRegDeleteValue(hkeyTcpipParam, RGAS_DOMAIN);
}
// remove all keys under the "Services\Tcpip\Parameters\Adapters" reg key
// that aren't in the list of net cards.
VSTR vstrNetCardsInTcpipReg; HKEY hkeyAdapters = NULL;
hrTmp = HrRegOpenKeyEx(hkeyTcpipParam, c_szAdaptersRegKey, KEY_READ, &hkeyAdapters);
if (SUCCEEDED(hrTmp)) { hrTmp = HrLoadSubkeysFromRegistry(hkeyAdapters, &vstrNetCardsInTcpipReg); } if (SUCCEEDED(hr)) hr = hrTmp;
if (SUCCEEDED(hr) && vstrNetCardsInTcpipReg.size() > 0) { // Step through the names of all the registry keys found
//
for (VSTR_CONST_ITER iter = vstrNetCardsInTcpipReg.begin(); iter != vstrNetCardsInTcpipReg.end(); ++iter) { // Find out if this particular key is in the list
// of installed Adapters
//
BOOL fFound = FALSE;
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end(); iterAdapter++) { ADAPTER_INFO* pAdapter = *iterAdapter;
if (lstrcmpiW(pAdapter->m_strBindName.c_str(), (**iter).c_str()) == 0) { fFound = TRUE; break; } }
if (!fFound) { // if it wasn't in the list of installed adapters
// then delete it
//
if (SUCCEEDED(hrTmp)) hrTmp = HrRegDeleteKeyTree(hkeyAdapters, (*iter)->c_str());
//maybe the key is not there. so we don't check whether this will fail.
HrDeleteBackupSettingsInDhcp((*iter)->c_str());
if (SUCCEEDED(hr)) hr = hrTmp;
} } } FreeCollectionAndItem(vstrNetCardsInTcpipReg); RegSafeCloseKey(hkeyAdapters);
//we also need to delete the duplicate reg values under Services\{adapter GUID}
HRESULT hrNt4 = S_OK; HKEY hkeyServices = NULL; DWORD dwDisposition;
hrNt4 = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegServices, KEY_READ, &hkeyServices);
if (FAILED(hrNt4)) { TraceTag(ttidTcpip, "HrSetMisc: Failed to open the Services reg key, hr: %x", hr); }
// We remove all keys under the "Services\Tcpip\Parameters\Interfaces" reg key
// that aren't in our list of net cards.
VSTR vstrNetCardInterfacesInTcpipReg;
// Get a list of all keys under the "Services\Tcpip\Parameters\Interfaces" key
HKEY hkeyInterfaces = NULL;
hrTmp = HrRegOpenKeyEx(hkeyTcpipParam, c_szInterfacesRegKey, KEY_READ_WRITE_DELETE, &hkeyInterfaces);
if (SUCCEEDED(hrTmp)) { hrTmp = HrLoadSubkeysFromRegistry(hkeyInterfaces, &vstrNetCardInterfacesInTcpipReg); }
if (SUCCEEDED(hr)) hr = hrTmp;
if (SUCCEEDED(hrTmp) && vstrNetCardInterfacesInTcpipReg.size() > 0 ) { // step through the names of all the registry keys found
for (VSTR_CONST_ITER iterTcpipReg = vstrNetCardInterfacesInTcpipReg.begin() ; iterTcpipReg != vstrNetCardInterfacesInTcpipReg.end() ; ++iterTcpipReg) { // Find out if this particular key is in the list
// of installed Adapters
BOOL fFound = FALSE;
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end(); iterAdapter++) { ADAPTER_INFO* pAdapter = *iterAdapter;
//(08/18/98 nsun) special case for WAN adapters with multiple interfaces
if (pAdapter->m_fIsWanAdapter && pAdapter->m_fIsMultipleIfaceMode) { IFACEITER iterId; tstring strInterfaceName;
for(iterId = pAdapter->m_IfaceIds.begin(); iterId != pAdapter->m_IfaceIds.end(); iterId++) { GetInterfaceName( pAdapter->m_strTcpipBindPath.c_str(), *iterId, &strInterfaceName);
if (lstrcmpiW(strInterfaceName.c_str(), (**iterTcpipReg).c_str()) == 0) { fFound = TRUE; break; } }
if (fFound) break; } else if (lstrcmpiW(pAdapter->m_strTcpipBindPath.c_str(), (**iterTcpipReg).c_str()) == 0) { fFound = TRUE; break; } }
// if it wasn't in the list of installed adapters then delete it
if (!fFound) { // remove the key
if (SUCCEEDED(hrTmp)) hrTmp = HrRegDeleteKeyTree(hkeyInterfaces, (*iterTcpipReg)->c_str());
if (SUCCEEDED(hr)) hr = hrTmp;
if (SUCCEEDED(hrNt4)) { hrTmp = HrRegDeleteKeyTree(hkeyServices, (*iterTcpipReg)->c_str()); if (FAILED(hrTmp)) { TraceTag(ttidTcpip, "CTcpipcfg::SetMisc"); TraceTag(ttidTcpip, "Failed on deleting duplicated Nt4 layout key: Services\\%S, hr: %x", (*iterTcpipReg)->c_str(), hrTmp); hrTmp = S_OK; } } } } } RegSafeCloseKey(hkeyInterfaces); RegSafeCloseKey(hkeyServices); FreeCollectionAndItem(vstrNetCardInterfacesInTcpipReg);
// Now we remove all keys under the "SERVICES\NetBt\Parameters\Interfaces" reg key
// that aren't in our list of net cards.
VSTR vstrNetCardInterfacesInWinsReg;
// Get a list of all keys under the "Services\NetBt\Parameters\Interfaces" key
HKEY hkeyWinsInterfaces = NULL;
hrTmp = HrRegOpenKeyEx(hkeyWinsParam, c_szInterfacesRegKey, KEY_READ, &hkeyWinsInterfaces);
// Get a list of all keys under the "SERVICES\NetBt\Parameters\Interfaces" key
hrTmp = HrLoadSubkeysFromRegistry( hkeyWinsInterfaces, &vstrNetCardInterfacesInWinsReg); if (SUCCEEDED(hr)) hr = hrTmp;
if (SUCCEEDED(hrTmp) && vstrNetCardInterfacesInWinsReg.size()>0 ) { // Step through the names of all the registry keys found
for (VSTR_CONST_ITER iterWinsReg = vstrNetCardInterfacesInWinsReg.begin() ; iterWinsReg != vstrNetCardInterfacesInWinsReg.end() ; ++iterWinsReg) { // Find out if this particular key is in the list
// of installed Adapters
BOOL fFound = FALSE;
// All net cards
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end(); iterAdapter++) { ADAPTER_INFO* pAdapter = *iterAdapter;
//(10/05/98 nsun) special case for WAN adapters with multiple interfaces
if (pAdapter->m_fIsWanAdapter && pAdapter->m_fIsMultipleIfaceMode) { IFACEITER iterId; tstring strNetBtBindPath;
for (iterId = pAdapter->m_IfaceIds.begin(); iterId != pAdapter->m_IfaceIds.end(); iterId++) { GetInterfaceName( pAdapter->m_strNetBtBindPath.c_str(), *iterId, &strNetBtBindPath);
strNetBtBindPath.insert(0, c_szTcpip_);
if (lstrcmpiW(strNetBtBindPath.c_str(), (**iterWinsReg).c_str()) == 0) { fFound = TRUE; break; } }
if (fFound) break; } else if (lstrcmpiW(pAdapter->m_strNetBtBindPath.c_str(), (**iterWinsReg).c_str()) == 0) { fFound = TRUE; break; } }
// if it wasn't in the list of installed adapters then delete it
if (!fFound) { hrTmp = HrRegDeleteKeyTree(hkeyWinsInterfaces, (*iterWinsReg)->c_str());
if (SUCCEEDED(hr)) hr = hrTmp; } } } FreeCollectionAndItem(vstrNetCardInterfacesInWinsReg); RegSafeCloseKey(hkeyWinsInterfaces);
TraceError("CTcpipcfg::HrSetMisc", hr); return hr; }
// CTcpipcfg::HrGetDhcpOptions
//
// Gets the list of netcard dependend and netcard independent
// values to delete when DHCP is disabled. This list is obtained from:
// "Services\DHCP\Parameters\Options\#\RegLocation"
//
// GlobalOptions returns the non-netcard specific reg keys
// PerAdapterOptions returns the netcard specific reg keys
HRESULT CTcpipcfg::HrGetDhcpOptions(OUT VSTR * const GlobalOptions, OUT VSTR * const PerAdapterOptions) { HRESULT hr = S_OK; HRESULT hrTmp = S_OK; HKEY hkeyDhcpOptions;
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, RGAS_DHCP_OPTIONS, KEY_ENUMERATE_SUB_KEYS, &hkeyDhcpOptions);
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) hr = S_OK;
else if (SUCCEEDED(hr)) { WCHAR szBuf[256]; FILETIME time; DWORD dwSize = celems(szBuf); DWORD dwRegIndex = 0;
while(SUCCEEDED(hrTmp = HrRegEnumKeyEx(hkeyDhcpOptions, dwRegIndex++, szBuf, &dwSize, NULL, NULL, &time))) { dwSize = celems(szBuf);
HKEY hkeyRegLocation; hrTmp = HrRegOpenKeyEx(hkeyDhcpOptions, szBuf, KEY_QUERY_VALUE, &hkeyRegLocation);
if (hrTmp == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) hrTmp = S_OK;
if (SUCCEEDED(hr)) hr = hrTmp;
if (hkeyRegLocation) { tstring strRegLocation; hrTmp = HrRegQueryString(hkeyRegLocation, RGAS_REG_LOCATION, &strRegLocation);
if (hrTmp == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) hrTmp = S_OK;
if (SUCCEEDED(hr)) hr = hrTmp;
if (SUCCEEDED(hrTmp)) { if (strRegLocation.find(TCH_QUESTION_MARK) == tstring::npos) { GlobalOptions->push_back(new tstring(strRegLocation)); } else { PerAdapterOptions->push_back(new tstring(strRegLocation)); } }
RegCloseKey(hkeyRegLocation); } }
if (hrTmp == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS)) hrTmp = S_OK;
if (SUCCEEDED(hr)) hr = hrTmp;
RegCloseKey(hkeyDhcpOptions); }
// Add default PerAdapterOption
// $REVIEW(tongl 5/11): This is directly from ncpa1.1
// What about DhcpNameServer under NetBt ??
//"System\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\?\\DhcpIPAddress"
PerAdapterOptions->push_back(new tstring(RGAS_DHCP_OPTION_IPADDRESS));
//"System\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\?\\DhcpSubnetMask"
PerAdapterOptions->push_back(new tstring(RGAS_DHCP_OPTION_SUBNETMASK));
//"System\\CurrentControlSet\\Services\\NetBT\\Parameters\\Interfaces\\?\\DhcpNameServerBackup"
PerAdapterOptions->push_back(new tstring(RGAS_DHCP_OPTION_NAMESERVERBACKUP));
TraceError("HrGetDhcpOptions", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CTcpipcfg::ReconfigIp
//
// Purpose: Notify Tcpip of configuration changes
//
// Arguments: INetCfgPnpReconfigCallback* pICallback
// the call back interface to handle Ndis Pnp reconfig
//
// Returns: HRESULT, S_OK on success, NETCFG_S_REBOOT otherwise
//
HRESULT CTcpipcfg::HrReconfigIp(INetCfgPnpReconfigCallback* pICallback) { HRESULT hr = S_OK; HRESULT hrReconfig = S_OK;
//$$REVIEW bug 329542, we remove the Pnp notification on "EnableSecurityFilters".
//And then global PnP notification to tcp stack is not needed at all.
if (m_glbGlobalInfo.m_fEnableFiltering != m_glbGlobalInfo.m_fOldEnableFiltering) { hr = NETCFG_S_REBOOT; }
IP_PNP_RECONFIG_REQUEST IpReconfigRequest;
ZeroMemory(&IpReconfigRequest, sizeof(IpReconfigRequest));
// DWORD version
IpReconfigRequest.version = IP_PNP_RECONFIG_VERSION; IpReconfigRequest.arpConfigOffset = 0;
//we are only interested in gateway and interface metric, because other
//parameters cannot be changed from the UI
IpReconfigRequest.Flags = IP_PNP_FLAG_GATEWAY_LIST_UPDATE | IP_PNP_FLAG_INTERFACE_METRIC_UPDATE ;
// Submit per adapter reconfig notifications
// gatewayListUpdate, filterListUpdate
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end(); iterAdapter ++) // for each adapter
{
ADAPTER_INFO * pAdapter = *iterAdapter;
// If not wan adapter or RAS fake guid, and adapter is enabled
if ((!pAdapter->m_fIsWanAdapter) && (!pAdapter->m_fIsRasFakeAdapter) && (pAdapter->m_BindingState == BINDING_ENABLE) && (pAdapter->m_InitialBindingState != BINDING_DISABLE)) { // gateway list
IpReconfigRequest.gatewayListUpdate = !fIsSameVstr(pAdapter->m_vstrDefaultGateway, pAdapter->m_vstrOldDefaultGateway) || !fIsSameVstr(pAdapter->m_vstrDefaultGatewayMetric, pAdapter->m_vstrOldDefaultGatewayMetric);
IpReconfigRequest.InterfaceMetricUpdate = !!(pAdapter->m_dwInterfaceMetric != pAdapter->m_dwOldInterfaceMetric);
if ((IpReconfigRequest.gatewayListUpdate) || (IpReconfigRequest.InterfaceMetricUpdate)) { TraceTag(ttidTcpip, "Sending notification to Tcpip about parameter changes for adapter %S.", pAdapter->m_strBindName.c_str()); TraceTag(ttidTcpip, "Gateway list update: %d", IpReconfigRequest.gatewayListUpdate); TraceTag(ttidTcpip, "Interface metric update: %d", IpReconfigRequest.InterfaceMetricUpdate);
hrReconfig = pICallback->SendPnpReconfig(NCRL_NDIS, c_szTcpip, pAdapter->m_strTcpipBindPath.c_str(), &IpReconfigRequest, sizeof(IP_PNP_RECONFIG_REQUEST));
//we dont want to request reboot if the error is ERROR_FILE_NOT_FOUND
//because that means the card is not loaded by the stack yet. Usually this is
//because the card was disabled from the connection UI. When the card is re-enabled,
//the statck will reload the card and load all settings from the registry. So a reboot
//is not needed
if (FAILED(hrReconfig) && HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hrReconfig) { TraceTag(ttidTcpip,"Notifying tcpip of adapter specific parameter change returns failure, prompt for reboot ..."); hr = NETCFG_S_REBOOT; } }
// if ATM adapter, notify atmarp if any parameter has changed
if (pAdapter->m_fIsAtmAdapter) { hrReconfig = HrReconfigAtmArp(pAdapter, pICallback);
if (hrReconfig != S_OK) { TraceTag(ttidTcpip,"Notifying tcpip of ATM ARP cleint of parameter change returns failure, prompt for reboot ..."); hr = NETCFG_S_REBOOT; } } #if ENABLE_1394
else if (pAdapter->m_fIs1394Adapter) { // $REVIEW JosephJ: I don't think we need to do
// anything here, because we have no parameters to
// change.
} #endif // ENABLE_1394
// ask for reboot if filter list has changed
if (m_glbGlobalInfo.m_fEnableFiltering) { if (!fIsSameVstr(pAdapter->m_vstrTcpFilterList, pAdapter->m_vstrOldTcpFilterList) || !fIsSameVstr(pAdapter->m_vstrUdpFilterList, pAdapter->m_vstrOldUdpFilterList) || !fIsSameVstr(pAdapter->m_vstrIpFilterList, pAdapter->m_vstrOldIpFilterList)) { TraceTag(ttidTcpip, "This is temporary, filter list changed, ask for reboot"); hr = NETCFG_S_REBOOT; } } }
// Send Wanarp reconfig notification if necessary
//
else if (pAdapter->m_fIsWanAdapter && pAdapter->m_fNewlyChanged) { if (FAILED(HrReconfigWanarp(pAdapter, pICallback))) { TraceTag(ttidTcpip, "Wanarp failed its reconfig. Need to reboot."); hr = NETCFG_S_REBOOT; } } }
TraceError("CTcpipcfg::HrReconfigIp",hr); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CTcpipcfg::HrReconfigAtmArp
//
// Purpose: Notify ATM ARP of configuration changes
//
// Arguments: none
//
// Returns: S_OK if success, NETCFG_S_REBOOT if failure
//
HRESULT CTcpipcfg::HrReconfigAtmArp(ADAPTER_INFO *pAdapterInfo, INetCfgPnpReconfigCallback* pICallback) { HRESULT hr = S_OK;
// check if any parameter has changed
DWORD dwFlag = 0;
// arp server list
if (!fIsSameVstr(pAdapterInfo->m_vstrARPServerList, pAdapterInfo->m_vstrOldARPServerList)) { dwFlag |= ATMARPC_RECONFIG_FLAG_ARPS_LIST_CHANGED; }
// mar server list
if (!fIsSameVstr(pAdapterInfo->m_vstrMARServerList, pAdapterInfo->m_vstrOldMARServerList)) { dwFlag |= ATMARPC_RECONFIG_FLAG_MARS_LIST_CHANGED; }
// MTU
if (pAdapterInfo->m_dwMTU != pAdapterInfo->m_dwOldMTU) { dwFlag |= ATMARPC_RECONFIG_FLAG_MTU_CHANGED; }
// PVC Only
if (pAdapterInfo->m_fPVCOnly != pAdapterInfo->m_fOldPVCOnly) { dwFlag |= ATMARPC_RECONFIG_FLAG_PVC_MODE_CHANGED; }
if (dwFlag) // yep, some parameter has changed
{
tstring strIpConfigString = RGAS_TCPIP_PARAM_INTERFACES; strIpConfigString += pAdapterInfo->m_strTcpipBindPath;
DWORD dwBytes = sizeof(IP_PNP_RECONFIG_REQUEST) + sizeof(ATMARPC_PNP_RECONFIG_REQUEST) + sizeof(USHORT) + sizeof(WCHAR)*(strIpConfigString.length() + 1);
PVOID pvBuf; hr = HrMalloc (dwBytes, &pvBuf); if (SUCCEEDED(hr)) { BYTE* pbByte = reinterpret_cast<BYTE*>(pvBuf);
// 1) fillup ip reconfig structure
IP_PNP_RECONFIG_REQUEST * pIpReconfig = reinterpret_cast<IP_PNP_RECONFIG_REQUEST *>(pbByte);
pIpReconfig->version =1; // set valid offset
pIpReconfig->arpConfigOffset = sizeof(IP_PNP_RECONFIG_REQUEST);
// set rest to default
// pIpReconfig->securityEnabled =0;
// pIpReconfig->filterListUpdate =0;
pIpReconfig->gatewayListUpdate =0; pIpReconfig->IPEnableRouter =0;
// 2) fill up atmarp reconfig structure
pbByte += sizeof(IP_PNP_RECONFIG_REQUEST);
ATMARPC_PNP_RECONFIG_REQUEST * pAtmarpcReconfig = reinterpret_cast<ATMARPC_PNP_RECONFIG_REQUEST *>(pbByte);
pAtmarpcReconfig->Version = ATMARPC_RECONFIG_VERSION; pAtmarpcReconfig->OpType = ATMARPC_RECONFIG_OP_MOD_INTERFACE;
// now set specifically what has changed
pAtmarpcReconfig->Flags = dwFlag;
// set the interface
pAtmarpcReconfig->IfKeyOffset = sizeof(ATMARPC_PNP_RECONFIG_REQUEST); pbByte += sizeof(ATMARPC_PNP_RECONFIG_REQUEST);
USHORT* puCount = reinterpret_cast<USHORT *>(pbByte); Assert (strIpConfigString.length() <= USHRT_MAX); *puCount = (USHORT)strIpConfigString.length(); pbByte += sizeof(USHORT);
WCHAR * pwszBindName = reinterpret_cast<WCHAR *>(pbByte); lstrcpyW(pwszBindName, strIpConfigString.c_str());
TraceTag(ttidTcpip, "Sending notification to AtmArpC for adapter %S", pwszBindName); TraceTag(ttidTcpip, "OpType: %d", pAtmarpcReconfig->OpType); TraceTag(ttidTcpip, "Flags: %d", pAtmarpcReconfig->Flags); TraceTag(ttidTcpip, "WChar Count: %d", *puCount);
// now send the notification
hr = pICallback->SendPnpReconfig(NCRL_NDIS, c_szTcpip, pAdapterInfo->m_strTcpipBindPath.c_str(), pvBuf, dwBytes);
//we dont want to request reboot if the error is ERROR_FILE_NOT_FOUND
//because that means the card is not loaded by the stack yet. Usually this is
//because the card was disabled from the connection UI. When the card is re-enabled,
//the statck will reload the card and load all settings from the registry. So a reboot
//is not needed
if (FAILED(hr) && HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr) { TraceError("pICallback->SendPnpReconfig to AtmArpC returns failure:", hr); hr = NETCFG_S_REBOOT; }
MemFree(pvBuf); } }
TraceError("CTcpipcfg::HrReconfigAtmArp",hr); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CTcpipcfg::ReconfigNbt
//
// Purpose: Notify NetBt of configuration changes
//
// Arguments: none
//
// Returns: S_OK if success, NETCFG_S_REBOOT if failure
//
HRESULT CTcpipcfg::HrReconfigNbt(INetCfgPnpReconfigCallback* pICallback) { HRESULT hr = S_OK;
NETBT_PNP_RECONFIG_REQUEST NetbtReconfigRequest;
// DWORD version
NetbtReconfigRequest.version = 1;
// Notify NetBt of any wins address changes (per adapter)
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end(); iterAdapter++) // for each adapter
{ ADAPTER_INFO * pAdapter = *iterAdapter;
// If not wan adapter, and adapter is enabled
if ((!pAdapter->m_fIsWanAdapter) && (!pAdapter->m_fIsRasFakeAdapter) && (pAdapter->m_BindingState == BINDING_ENABLE) && (pAdapter->m_InitialBindingState != BINDING_DISABLE)) { if ( (!fIsSameVstr(pAdapter->m_vstrWinsServerList, pAdapter->m_vstrOldWinsServerList)) || (pAdapter->m_dwNetbiosOptions != pAdapter->m_dwOldNetbiosOptions)) { TraceTag(ttidTcpip, "Sending notification to NetBt for per adapter parameter changes."); if ( FAILED( pICallback->SendPnpReconfig(NCRL_TDI, c_szNetBt, pAdapter->m_strNetBtBindPath.c_str(), NULL, 0))) { TraceTag(ttidTcpip,"Notifying NetBt of Wins address change returns failure, prompt for reboot ..."); hr = NETCFG_S_REBOOT; }; } } }
// Notify NetBt of any global parameter changes
if (m_fLmhostsFileSet || (m_glbGlobalInfo.m_fEnableLmHosts != m_glbGlobalInfo.m_fOldEnableLmHosts)) { TraceTag(ttidTcpip, "Sending notification to NetBt about NetBt parameter changes.");
// $REVIEW(tongl 11/14/97): since we do need to send some notification to tcpip,
// we need to read the correct value of "EnableDns" from registry
// This is a temporary thing so Malam can keep the ability to reconfigure these
// settings that used to be configurable in NT5 Beta1.
// $REVIEW(nsun 04/14/99): Per MalaM, most users don't use this value and NetBT
// will ignore this value. We should remove it from the data struct after Beta3.
NetbtReconfigRequest.enumDnsOption = WinsThenDns; // m_glbGlobalInfo.m_fDnsEnableWins ? WinsThenDns : DnsOnly;
NetbtReconfigRequest.fScopeIdUpdated = FALSE;
NetbtReconfigRequest.fLmhostsEnabled = !!m_glbGlobalInfo.m_fEnableLmHosts; NetbtReconfigRequest.fLmhostsFileSet = !!m_fLmhostsFileSet;
TraceTag(ttidTcpip, "Sending notification to NetBt for global parameter changes."); TraceTag(ttidTcpip, "fLmhostsEnabled: %d", NetbtReconfigRequest.fLmhostsEnabled); TraceTag(ttidTcpip, "fLmhostsFileSet: %d", NetbtReconfigRequest.fLmhostsFileSet);
if ( FAILED(pICallback->SendPnpReconfig(NCRL_TDI, c_szNetBt, c_szEmpty, &NetbtReconfigRequest, sizeof(NETBT_PNP_RECONFIG_REQUEST))) ) { TraceTag(ttidTcpip,"Notifying NetBt component of DNS parameter change returns failure, prompt for reboot ..."); hr = NETCFG_S_REBOOT; }; } return hr; }
//+---------------------------------------------------------------------------
//
// Member: CTcpipcfg::ReconfigDns
//
// Purpose: Notify DNS Cache resolver service of configuration changes
//
// Arguments: fDoReconfigWithoutCheckingParams
// default is FALSE
// if TRUE, then will do Dns reconfig with checking if there
// is paramter changes or not
//
// Returns: S_OK if success, NETCFG_S_REBOOT otherwise
//
HRESULT CTcpipcfg::HrReconfigDns(BOOL fDoReconfigWithoutCheckingParams) { // Submit a generic reconfig notification to the service
// if any of the DNS related parameters have changed.
BOOL fDnsParamChanged = fDoReconfigWithoutCheckingParams;
if (!fDnsParamChanged) { // Suffix list and UseDomainNameDevolution changed ?
BOOL fDnsSuffixChanged = !fIsSameVstr(m_glbGlobalInfo.m_vstrDnsSuffixList, m_glbGlobalInfo.m_vstrOldDnsSuffixList);
if (fDnsSuffixChanged) // suffix changed
{ fDnsParamChanged = TRUE; } else if (m_glbGlobalInfo.m_vstrDnsSuffixList.size() == 0) { if (m_glbGlobalInfo.m_fUseDomainNameDevolution != m_glbGlobalInfo.m_fOldUseDomainNameDevolution) fDnsParamChanged = TRUE; } }
// $REVIEW(tongl 6/19/98): DNS also cares about IP address, subnet mask & gateway changes
if (!fDnsParamChanged) { // Has any IP setting changed ?
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end(); iterAdapter++) { ADAPTER_INFO* pAdapter = *iterAdapter;
// If not wan adapter
if (!pAdapter->m_fIsWanAdapter) { if ( ((!!pAdapter->m_fEnableDhcp) != (!!pAdapter->m_fOldEnableDhcp)) || (!fIsSameVstr(pAdapter->m_vstrIpAddresses, pAdapter->m_vstrOldIpAddresses)) || (!fIsSameVstr(pAdapter->m_vstrSubnetMask, pAdapter->m_vstrOldSubnetMask)) || (!fIsSameVstr(pAdapter->m_vstrDefaultGateway, pAdapter->m_vstrOldDefaultGateway)) || (!fIsSameVstr(pAdapter->m_vstrDefaultGatewayMetric, pAdapter->m_vstrOldDefaultGatewayMetric)) ) { fDnsParamChanged = TRUE; break; } } } }
HRESULT hr = S_OK; if (fDnsParamChanged) { TraceTag(ttidTcpip, "Sending notification to Dns about Dns and IP parameter changes.");
hr = HrSendServicePnpEvent(c_szSvcDnscache, SERVICE_CONTROL_PARAMCHANGE); if (FAILED(hr)) { if (HRESULT_FROM_WIN32(ERROR_SERVICE_NOT_ACTIVE) == hr) { TraceTag(ttidTcpip,"Notifying dnscache service of parameter change failed because DNS cache is not active."); hr = S_OK; } else { TraceTag(ttidTcpip,"Notifying dnscache service of parameter change failed, prompt for reboot ..."); hr = NETCFG_S_REBOOT; } } }
TraceError("CTcpipcfg::HrReconfigDns",hr); return hr; }
HRESULT CTcpipcfg::HrReconfigWanarp(ADAPTER_INFO *pAdapterInfo, INetCfgPnpReconfigCallback* pICallback) { HRESULT hr; DWORD cbInfo; WANARP_RECONFIGURE_INFO* pInfo;
const IFACECOL& Ifaces = pAdapterInfo->m_IfaceIds;
cbInfo = sizeof(WANARP_RECONFIGURE_INFO) + (sizeof(GUID) * Ifaces.size());
hr = HrMalloc(cbInfo, (PVOID*)&pInfo); if (SUCCEEDED(hr)) { // Populate the data in the WANARP_RECONFIGURE_INFO structure.
//
INT nIndex;
pInfo->dwVersion = WANARP_RECONFIGURE_VERSION; pInfo->wrcOperation = WRC_ADD_INTERFACES; pInfo->ulNumInterfaces = Ifaces.size();
IFACECOL::const_iterator iter; for (iter = Ifaces.begin(), nIndex = 0; iter != Ifaces.end(); iter++, nIndex++) { pInfo->rgInterfaces[nIndex] = *iter; }
TraceTag(ttidNetCfgPnp, "Sending NDIS reconfig Pnp event to Upper:%S " "lower: %S for %d interfaces", c_szTcpip, pAdapterInfo->m_strTcpipBindPath.c_str(), pInfo->ulNumInterfaces);
hr = pICallback->SendPnpReconfig(NCRL_NDIS, c_szTcpip, pAdapterInfo->m_strTcpipBindPath.c_str(), pInfo, cbInfo);
// Send the notification.
//
MemFree(pInfo); }
TraceError("CTcpipcfg::HrReconfigWanarp",hr); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CTcpipcfg::HrSetActiveIpsecPolicy
//
// Purpose: Set a user chosen local policy
//
// Arguments: none
//
// Returns: S_OK if success, NETCFG_S_REBOOT otherwise
//
//IPSec is removed from connection UI
/*
HRESULT CTcpipcfg::HrSetActiveIpsecPolicy() { HRESULT hr = S_OK;
AssertSz(m_glbGlobalInfo.m_strIpsecPol != c_szIpsecUnset, "Ipsec policy unset ?");
if (m_glbGlobalInfo.m_strIpsecPol != c_szIpsecUnset) { // load the polstore dll & get export function
typedef HRESULT (WINAPI * PFNHrSetAssignedLocalPolicy)(GUID * pActivePolId);
HMODULE hPolStore; FARPROC pfn;
hr = HrLoadLibAndGetProc (L"polstore.dll", "HrSetAssignedLocalPolicy", &hPolStore, &pfn);
if (S_OK == hr) { Assert(hPolStore != NULL); Assert(pfn != NULL);
PFNHrSetAssignedLocalPolicy pfnHrSetAssignedLocalPolicy = reinterpret_cast<PFNHrSetAssignedLocalPolicy>(pfn);
if (m_glbGlobalInfo.m_strIpsecPol == c_szIpsecNoPol) { // no ipsec
TraceTag(ttidTcpip, "Calling HrSetAssignedLocalPolicy with NULL."); hr = (*pfnHrSetAssignedLocalPolicy)(NULL); TraceTag(ttidTcpip, "HrSetActivePolicy returns hr: %x", hr); } else { WCHAR szPolicyGuid[c_cchGuidWithTerm]; BOOL fSucceeded = StringFromGUID2(m_glbGlobalInfo.m_guidIpsecPol, szPolicyGuid, c_cchGuidWithTerm);
TraceTag(ttidTcpip, "Calling HrSetActivePolicy with %S.", szPolicyGuid); hr = (*pfnHrSetAssignedLocalPolicy)(&(m_glbGlobalInfo.m_guidIpsecPol)); TraceTag(ttidTcpip, "HrSetAssignedLocalPolicy returns hr: %x", hr); }
if (FAILED(hr)) { TraceError("Failed setting active ipsec policy.", hr); NcMsgBoxWithWin32ErrorText(DwWin32ErrorFromHr(hr), _Module.GetResourceInstance(), ::GetActiveWindow(), IDS_MSFT_TCP_TEXT, IDS_WIN32_ERROR_FORMAT, IDS_SET_IPSEC_FAILED, MB_APPLMODAL | MB_ICONEXCLAMATION | MB_OK); hr = S_OK; }
FreeLibrary (hPolStore); } else { TraceTag(ttidTcpip,"Failed to get function HrSetActivePolicy from polstore.dll"); hr = S_OK; } }
TraceError("CTcpipcfg::HrSetActiveIpsecPolicy", hr); return hr; } */
//+---------------------------------------------------------------------------
//
// Member: CTcpipcfg::HrSaveMultipleInterfaceWanRegistry
//
// Purpose: For WAN adapters with multiple interfaces, we need to check every
// interface to see if it is newly added. If so, create the interface
// subkey and set the default settings
//
// Arguments: hkeyInterface CCS\Services\Tcpip\Parameters\Interfaces key
// pAdapter ADAPTER_INFO pointer to settings of the WAN adapter
//
// Returns: S_OK if success, E_FAIL otherwise
//
// Author: nsun 08/29/98
HRESULT CTcpipcfg::HrSaveMultipleInterfaceWanRegistry(const HKEY hkeyInterfaces, ADAPTER_INFO* pAdapter) { HRESULT hr = S_OK;
IFACEITER iterId; tstring strInterfaceName;
for (iterId = pAdapter->m_IfaceIds.begin(); iterId != pAdapter->m_IfaceIds.end(); iterId ++) { GetInterfaceName( pAdapter->m_strTcpipBindPath.c_str(), *iterId, &strInterfaceName);
HRESULT hrTmp; HKEY hkeyInterfaceParam; DWORD dwDisposition;
hrTmp = HrRegCreateKeyEx(hkeyInterfaces, strInterfaceName.c_str(), REG_OPTION_NON_VOLATILE, KEY_READ_WRITE, NULL, &hkeyInterfaceParam, &dwDisposition); if (SUCCEEDED(hrTmp)) { //We don't set default settings if the WAN interface is NOT newly added.
if (REG_CREATED_NEW_KEY == dwDisposition) { hrTmp = HrRegSetDword(hkeyInterfaceParam, RGAS_USEZEROBROADCAST, 0); if (SUCCEEDED(hr)) hr = hrTmp;
if (SUCCEEDED(hrTmp)) hrTmp = HrSaveStaticWanRegistry(hkeyInterfaceParam); }
RegCloseKey(hkeyInterfaceParam); }
if (SUCCEEDED(hr)) hr = hrTmp; }
TraceError("CTcpipcfg::HrSaveTcpipRegistry", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CTcpipcfg::HrSaveWinsMultipleInterfaceWanRegistry
//
// Purpose: For WAN adapters with multiple interfaces, create the interface
// subkeys and set the default settings
//
// Arguments: hkeyInterface CCS\Services\NetBT\Parameters\Interfaces key
// pAdapter ADAPTER_INFO pointer to settings of the WAN adapter
//
// Returns: S_OK if success, E_FAIL otherwise
//
// Author: nsun 10/05/98
HRESULT CTcpipcfg::HrSaveWinsMultipleInterfaceWanRegistry(const HKEY hkeyInterfaces, ADAPTER_INFO* pAdapter) { HRESULT hr = S_OK; IFACEITER iterId; tstring strInterfaceName;
for (iterId = pAdapter->m_IfaceIds.begin(); iterId != pAdapter->m_IfaceIds.end(); iterId++) { GetInterfaceName( pAdapter->m_strNetBtBindPath.c_str(), *iterId, &strInterfaceName);
strInterfaceName.insert(0, c_szTcpip_);
HRESULT hrTmp; HKEY hkeyInterfaceParam; DWORD dwDisposition;
hrTmp = HrRegCreateKeyEx(hkeyInterfaces, strInterfaceName.c_str(), REG_OPTION_NON_VOLATILE, KEY_READ_WRITE, NULL, &hkeyInterfaceParam, &dwDisposition); if (SUCCEEDED(hrTmp)) { //We don't set default settings if the WAN interface is NOT newly added.
if (REG_CREATED_NEW_KEY == dwDisposition) { VSTR vstrNameServerList;
hrTmp = HrRegSetColString(hkeyInterfaceParam, RGAS_NETBT_NAMESERVERLIST, vstrNameServerList); if (SUCCEEDED(hr)) hr = hrTmp; }
RegCloseKey(hkeyInterfaceParam); }
if (SUCCEEDED(hr)) hr = hrTmp; }
TraceError("CTcpipcfg::HrSaveTcpipRegistry", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CTcpipcfg::HrSaveStaticWanRegistry
//
// Purpose: Write static parameters for Wan adapters to registry
//
// Arguments: none
//
// Returns: S_OK if success, E_FAIL otherwise
//
HRESULT CTcpipcfg::HrSaveStaticWanRegistry(HKEY hkeyInterfaceParam) { HRESULT hr = S_OK; HRESULT hrTmp;
// EnableDHCP = 0
// IPAddress = 0.0.0.0
// SubnetMask = 0.0.0.0
// DefaultGateWay =
hrTmp = HrRegSetBool(hkeyInterfaceParam, RGAS_ENABLE_DHCP, FALSE);
hr = hrTmp;
hrTmp = HrRegSetMultiSz(hkeyInterfaceParam, RGAS_IPADDRESS, L"0.0.0.0\0");
if (SUCCEEDED(hr)) hr = hrTmp;
hrTmp = HrRegSetMultiSz(hkeyInterfaceParam, RGAS_SUBNETMASK, L"0.0.0.0\0");
if (SUCCEEDED(hr)) hr = hrTmp;
hrTmp = HrRegSetMultiSz(hkeyInterfaceParam, RGAS_DEFAULTGATEWAY, L"\0");
if (SUCCEEDED(hr)) hr = hrTmp;
//(nsun 11/02/98) set static RRAS parameters for unattended install
hrTmp = HrRegSetBool(hkeyInterfaceParam, c_szDeadGWDetect, m_glbGlobalInfo.m_fDeadGWDetectDefault); if (SUCCEEDED(hr)) hr = hrTmp;
hrTmp = HrRegSetBool(hkeyInterfaceParam, c_szDontAddDefaultGateway, m_glbGlobalInfo.m_fDontAddDefaultGatewayDefault);
if (SUCCEEDED(hr)) hr = hrTmp;
TraceError("CTcpipcfg::HrSaveStaticWanRegistry", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CTcpipcfg::HrSaveStaticAtmRegistry
//
// Purpose: Write static parameters for Wan adapters to registry
//
// Arguments: none
//
// Returns: S_OK if success, E_FAIL otherwise
//
HRESULT CTcpipcfg::HrSaveStaticAtmRegistry(HKEY hkeyInterfaceParam) { HRESULT hr = S_OK; HRESULT hrTmp = S_OK;
HKEY hkeyAtmarpc; DWORD dwDisposition;
// Open the Atmarpc subkey
hrTmp = HrRegCreateKeyEx(hkeyInterfaceParam, c_szAtmarpc, REG_OPTION_NON_VOLATILE, KEY_READ_WRITE, NULL, &hkeyAtmarpc, &dwDisposition);
if (SUCCEEDED(hrTmp)) { // SapSelector
hrTmp = HrRegSetDword(hkeyAtmarpc, c_szREG_SapSelector, c_dwSapSelector); hr = hrTmp;
// AddressResolutionTimeout
hrTmp = HrRegSetDword(hkeyAtmarpc, c_szREG_AddressResolutionTimeout, c_dwAddressResolutionTimeout); if (SUCCEEDED(hr)) hr = hrTmp;
// ARPEntryAgingTimeout
hrTmp = HrRegSetDword(hkeyAtmarpc, c_szREG_ARPEntryAgingTimeout, c_dwARPEntryAgingTimeout); if (SUCCEEDED(hr)) hr = hrTmp;
// InARPWaitTimeout
hrTmp = HrRegSetDword(hkeyAtmarpc, c_szREG_SapSelector, c_dwSapSelector); if (SUCCEEDED(hr)) hr = hrTmp;
// MaxRegistrationAttempts
hrTmp = HrRegSetDword(hkeyAtmarpc, c_szREG_InARPWaitTimeout, c_dwInARPWaitTimeout); if (SUCCEEDED(hr)) hr = hrTmp;
// MaxResolutionAttempts
hrTmp = HrRegSetDword(hkeyAtmarpc, c_szREG_MaxResolutionAttempts, c_dwMaxResolutionAttempts); if (SUCCEEDED(hr)) hr = hrTmp;
// MinWaitAfterNak
hrTmp = HrRegSetDword(hkeyAtmarpc, c_szREG_SapSelector, c_dwSapSelector); if (SUCCEEDED(hr)) hr = hrTmp;
// ServerConnectInterval
hrTmp = HrRegSetDword(hkeyAtmarpc, c_szREG_MinWaitAfterNak, c_dwMinWaitAfterNak); if (SUCCEEDED(hr)) hr = hrTmp;
// ServerRefreshTimeout
hrTmp = HrRegSetDword(hkeyAtmarpc, c_szREG_ServerRefreshTimeout, c_dwServerRefreshTimeout); if (SUCCEEDED(hr)) hr = hrTmp;
// ServerRegistrationTimeout
hrTmp = HrRegSetDword(hkeyAtmarpc, c_szREG_ServerRegistrationTimeout, c_dwServerRegistrationTimeout); if (SUCCEEDED(hr)) hr = hrTmp;
// DefaultVcAgingTimeout
hrTmp = HrRegSetDword(hkeyAtmarpc, c_szREG_DefaultVcAgingTimeout, c_dwDefaultVcAgingTimeout); if (SUCCEEDED(hr)) hr = hrTmp;
// MARSConnectInterval
hrTmp = HrRegSetDword(hkeyAtmarpc, c_szREG_MARSConnectInterval, c_dwMARSConnectInterval); if (SUCCEEDED(hr)) hr = hrTmp;
// MARSRegistrationTimeout
hrTmp = HrRegSetDword(hkeyAtmarpc, c_szREG_MARSRegistrationTimeout, c_dwMARSRegistrationTimeout); if (SUCCEEDED(hr)) hr = hrTmp;
// JoinTimeout
hrTmp = HrRegSetDword(hkeyAtmarpc, c_szREG_JoinTimeout, c_dwJoinTimeout); if (SUCCEEDED(hr)) hr = hrTmp;
// LeaveTimeout
hrTmp = HrRegSetDword(hkeyAtmarpc, c_szREG_LeaveTimeout, c_dwLeaveTimeout); if (SUCCEEDED(hr)) hr = hrTmp;
// MaxDelayBetweenMULTIs
hrTmp = HrRegSetDword(hkeyAtmarpc, c_szREG_MaxDelayBetweenMULTIs, c_dwMaxDelayBetweenMULTIs); if (SUCCEEDED(hr)) hr = hrTmp;
RegCloseKey(hkeyAtmarpc); }
TraceError("CTcpipcfg::HrSaveStaticAtmRegistry", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Name: ReInitializeInternalState
//
// Purpose: Reinitialize internal state at the end of Apply if Apply SUCCEEDED
//
// Arguments:
//
// Returns: None
// Author: tongl 4 Sept 1997
// Notes: Fix bug# 105383
//
//
void CTcpipcfg::ReInitializeInternalState() { // Reset global and adapter parameter values if necessary
if (m_fSaveRegistry || m_fReconfig) { m_glbGlobalInfo.ResetOldValues();
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end(); iterAdapter++) { ADAPTER_INFO* pAdapter = *iterAdapter; pAdapter->ResetOldValues(); } }
// Reset internal flags
m_fRemoving = FALSE; m_fInstalling = FALSE;
m_fSaveRegistry = FALSE; m_fReconfig = FALSE;
// Initialize the netbt_pnp_reconfig_request structure
m_fLmhostsFileSet = FALSE; }
// This functions adds a new RAS fake GUID directly to our memory structure,
// and loads info from the RAS phone book.
HRESULT CTcpipcfg::UpdateRasAdapterInfo( const RASCON_IPUI& RasInfo) { HRESULT hr; ADAPTER_INFO* pAdapter;
hr = S_OK; m_fSaveRegistry = TRUE;
WCHAR szGuid [c_cchGuidWithTerm]; StringFromGUID2(RasInfo.guidConnection, szGuid, c_cchGuidWithTerm);
pAdapter = PAdapterFromInstanceGuid(&RasInfo.guidConnection); if (!pAdapter) { pAdapter = new ADAPTER_INFO; hr = pAdapter->HrSetDefaults(&RasInfo.guidConnection, c_szRasFakeAdapterDesc, szGuid, szGuid); if (SUCCEEDED(hr)) { m_vcardAdapterInfo.push_back(pAdapter);
pAdapter->m_fIsRasFakeAdapter = TRUE; } else { delete pAdapter; pAdapter = NULL; Assert (FAILED(hr)); } } else { //We need to set default even if the ras connection is already in our adapter list
//because we should update all the paramters based on the phone book
hr = pAdapter->HrSetDefaults(&RasInfo.guidConnection, c_szRasFakeAdapterDesc, szGuid, szGuid); pAdapter->m_fIsRasFakeAdapter = TRUE; }
if (SUCCEEDED(hr)) { Assert (pAdapter);
// Now see if we should overwrite some of the parameters
// from what's in the phone book
if (RasInfo.dwFlags & RCUIF_USE_IP_ADDR) { // use static IP address
pAdapter->m_fEnableDhcp = FALSE; pAdapter->m_fOldEnableDhcp = FALSE;
pAdapter->m_vstrIpAddresses.push_back(new tstring(RasInfo.pszwIpAddr)); CopyVstr(&pAdapter->m_vstrOldIpAddresses, pAdapter->m_vstrIpAddresses);
// generate the subnet mask
tstring strIpAddress = RasInfo.pszwIpAddr; tstring strSubnetMask; DWORD adwIpAddress[4];
GetNodeNum(strIpAddress.c_str(), adwIpAddress); DWORD nValue = adwIpAddress[0];
if (nValue <= SUBNET_RANGE_1_MAX) { strSubnetMask = c_szBASE_SUBNET_MASK_1; } else if (nValue <= SUBNET_RANGE_2_MAX) { strSubnetMask = c_szBASE_SUBNET_MASK_2; } else if (nValue <= SUBNET_RANGE_3_MAX) { strSubnetMask = c_szBASE_SUBNET_MASK_3; } else { AssertSz(FALSE, "Invaid IP address ?"); }
pAdapter->m_vstrSubnetMask.push_back(new tstring(strSubnetMask.c_str())); CopyVstr(&pAdapter->m_vstrOldSubnetMask, pAdapter->m_vstrSubnetMask); }
if (RasInfo.dwFlags & RCUIF_USE_NAME_SERVERS) { // use DNS and WINS addresses
if (RasInfo.pszwDnsAddr && lstrlenW(RasInfo.pszwDnsAddr)) pAdapter->m_vstrDnsServerList.push_back(new tstring(RasInfo.pszwDnsAddr));
if (RasInfo.pszwDns2Addr && lstrlenW(RasInfo.pszwDns2Addr)) pAdapter->m_vstrDnsServerList.push_back(new tstring(RasInfo.pszwDns2Addr));
CopyVstr(&pAdapter->m_vstrOldDnsServerList, pAdapter->m_vstrDnsServerList);
if (RasInfo.pszwWinsAddr && lstrlenW(RasInfo.pszwWinsAddr)) pAdapter->m_vstrWinsServerList.push_back(new tstring(RasInfo.pszwWinsAddr));
if (RasInfo.pszwWins2Addr && lstrlenW(RasInfo.pszwWins2Addr)) pAdapter->m_vstrWinsServerList.push_back(new tstring(RasInfo.pszwWins2Addr));
CopyVstr(&pAdapter->m_vstrOldWinsServerList, pAdapter->m_vstrWinsServerList); }
pAdapter->m_fUseRemoteGateway = !!(RasInfo.dwFlags & RCUIF_USE_REMOTE_GATEWAY); pAdapter->m_fUseIPHeaderCompression = !!(RasInfo.dwFlags & RCUIF_USE_HEADER_COMPRESSION); pAdapter->m_dwFrameSize = RasInfo.dwFrameSize; pAdapter->m_fIsDemandDialInterface = !!(RasInfo.dwFlags & RCUIF_DEMAND_DIAL); pAdapter->m_fDisableDynamicUpdate = !!(RasInfo.dwFlags & RCUIF_USE_DISABLE_REGISTER_DNS); pAdapter->m_fOldDisableDynamicUpdate = pAdapter->m_fDisableDynamicUpdate; pAdapter->m_fEnableNameRegistration = !!(RasInfo.dwFlags & RCUIF_USE_PRIVATE_DNS_SUFFIX); pAdapter->m_fOldEnableNameRegistration = pAdapter->m_fEnableNameRegistration;
if (RasInfo.dwFlags & RCUIF_ENABLE_NBT) { pAdapter->m_dwNetbiosOptions = c_dwEnableNetbios; pAdapter->m_dwOldNetbiosOptions = c_dwEnableNetbios; } else { pAdapter->m_dwNetbiosOptions = c_dwDisableNetbios; pAdapter->m_dwOldNetbiosOptions = c_dwDisableNetbios; }
pAdapter->m_strDnsDomain = RasInfo.pszwDnsSuffix; pAdapter->m_strOldDnsDomain = pAdapter->m_strDnsDomain; }
TraceError("CTcpipcfg::UpdateRasAdapterInfo", hr); return hr; }
HRESULT CTcpipcfg::HrDuplicateToNT4Location(HKEY hkeyInterface, ADAPTER_INFO * pAdapter) { Assert(hkeyInterface); Assert(pAdapter);
HRESULT hr = S_OK;
HKEY hkeyServices = NULL; HKEY hkeyNt4 = NULL;
DWORD dwDisposition; tstring strNt4SubKey = pAdapter->m_strBindName; strNt4SubKey += c_szRegParamsTcpip;
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegServices, KEY_READ, &hkeyServices);
if (FAILED(hr)) { TraceTag(ttidTcpip, "HrRemoveNt4DuplicateRegistry: Failed to open the Services reg key, hr: %x", hr); goto LERROR; }
hr = HrRegCreateKeyEx(hkeyServices, strNt4SubKey.c_str(), REG_OPTION_NON_VOLATILE, KEY_READ_WRITE_DELETE, NULL, &hkeyNt4, &dwDisposition);
if (SUCCEEDED(hr)) { HRESULT hrRead = S_OK; HRESULT hrWrite = S_OK;
if (REG_CREATED_NEW_KEY == dwDisposition) { hr = HrSetSecurityForNetConfigOpsOnSubkeys(hkeyServices, strNt4SubKey.c_str()); hr = S_OK; }
UINT cValues = sizeof(s_rgNt4Values)/sizeof(*s_rgNt4Values); VSTR vstrTmp; tstring strTmp; DWORD dwTmp; BOOL fTmp;
for (UINT i = 0; i < cValues; i++) { switch(s_rgNt4Values[i].dwType) { case REG_BOOL: hrRead = HrRegQueryDword(hkeyInterface, s_rgNt4Values[i].pszValueName, &dwTmp); if (SUCCEEDED(hrRead)) { fTmp = !!dwTmp; hrWrite = HrRegSetBool(hkeyNt4, s_rgNt4Values[i].pszValueName, fTmp); } break;
case REG_DWORD: hrRead = HrRegQueryDword(hkeyInterface, s_rgNt4Values[i].pszValueName, &dwTmp); if (SUCCEEDED(hrRead)) hrWrite = HrRegSetDword(hkeyNt4, s_rgNt4Values[i].pszValueName, dwTmp);
break;
case REG_SZ: hrRead = HrRegQueryString(hkeyInterface, s_rgNt4Values[i].pszValueName, &strTmp); if (SUCCEEDED(hrRead)) hrWrite = HrRegSetString(hkeyNt4, s_rgNt4Values[i].pszValueName, strTmp); break;
case REG_MULTI_SZ: hrRead = HrRegQueryColString( hkeyInterface, s_rgNt4Values[i].pszValueName, &vstrTmp);
if (SUCCEEDED(hrRead)) { hrWrite = HrRegSetColString(hkeyNt4, s_rgNt4Values[i].pszValueName, vstrTmp); DeleteColString(&vstrTmp); } break; }
#ifdef ENABLETRACE
if(FAILED(hrRead)) { TraceTag(ttidTcpip, "HrDuplicateToNT4Location: Failed on loading %S, hr: %x", s_rgNt4Values[i].pszValueName, hr); }
if(FAILED(hrWrite)) { TraceTag(ttidError, "HrDuplicateToNT4Location: failed to write %S to the registry. hr = %x.", s_rgNt4Values[i].pszValueName, hrWrite); } #endif
if (SUCCEEDED(hr)) hr = hrWrite; }
RegSafeCloseKey(hkeyNt4); }
RegSafeCloseKey(hkeyServices);
LERROR: TraceError("CTcpipcfg::HrDuplicateToNT4Location", hr); return hr; }
//To solve the compatibility issues of non-nt5 applications, we duplicate some important
//per interface tcpip parameters to the old NT4 location: Services\{adapter GUID}\Parameters\Tcpip
//We need to clean it up when removing tcpip
HRESULT CTcpipcfg::HrRemoveNt4DuplicateRegistry() { //we also need to delete the duplicate reg values under Services\{adapter GUID}
HRESULT hr = S_OK; HRESULT hrTmp = S_OK; HKEY hkeyServices = NULL;
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegServices, KEY_READ_WRITE_DELETE, &hkeyServices);
if (FAILED(hr)) { TraceTag(ttidTcpip, "HrRemoveNt4DuplicateRegistry: Failed to open the Services reg key, hr: %x", hr); } else { for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end(); iterAdapter++) { ADAPTER_INFO* pAdapter = *iterAdapter;
if (!pAdapter->m_fIsWanAdapter && !pAdapter->m_fIsRasFakeAdapter) { hrTmp = HrRegDeleteKeyTree(hkeyServices, pAdapter->m_strBindName.c_str());
#ifdef ENABLETRACE
if (FAILED(hrTmp)) { TraceTag(ttidTcpip, "CTcpipcfg::HrRemoveNt4DuplicateRegistry"); TraceTag(ttidTcpip, "Failed on deleting duplicated Nt4 layout key: Services\\%S, hr: %x", pAdapter->m_strBindName, hrTmp); } #endif
} }
RegSafeCloseKey(hkeyServices); }
TraceError("CTcpipcfg::HrRemoveNt4DuplicateRegistry", hr); return hr; }
HRESULT CTcpipcfg::HrCleanUpPerformRouterDiscoveryFromRegistry() { HRESULT hr = S_OK; HKEY hkey = NULL;
hr = m_pnccTcpip->OpenParamKey(&hkey); if (SUCCEEDED(hr)) { Assert(hkey);
HRESULT hrTemp = S_OK; //delete the global PerformRouterDiscoveryDefault value
hrTemp = HrRegDeleteValue(hkey, c_szPerformRouterDiscoveryDefault); if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hrTemp) hrTemp = S_OK;
if (SUCCEEDED(hr)) hr = hrTemp;
HKEY hkeyInterfaces = NULL; hrTemp = HrRegOpenKeyEx(hkey, c_szInterfacesRegKey, KEY_READ, &hkeyInterfaces);
if (SUCCEEDED(hrTemp) && hkeyInterfaces) { WCHAR szBuf[256]; DWORD dwSize = celems(szBuf); FILETIME time; DWORD dwRegIndex = 0;
while (SUCCEEDED(hrTemp = HrRegEnumKeyEx(hkeyInterfaces, dwRegIndex++, szBuf, &dwSize, NULL, NULL, &time))) { HKEY hkeyIf = NULL;
dwSize = celems(szBuf); hrTemp = HrRegOpenKeyEx(hkeyInterfaces, szBuf, KEY_READ_WRITE_DELETE, &hkeyIf); if (SUCCEEDED(hr)) hr = hrTemp;
if (SUCCEEDED(hrTemp)) { Assert(hkeyIf);
DWORD dwTemp = 0; hrTemp = HrRegQueryDword(hkeyIf, c_szPerformRouterDiscovery, &dwTemp); if (SUCCEEDED(hrTemp)) { if (IP_IRDP_DISABLED != dwTemp) { hrTemp = HrRegDeleteValue(hkeyIf, c_szPerformRouterDiscovery);
if (SUCCEEDED(hr)) hr = hrTemp; }
} else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hrTemp) { hrTemp = S_OK; } if (SUCCEEDED(hr)) hr = hrTemp;
RegSafeCloseKey(hkeyIf); }
}
if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hrTemp) hrTemp = S_OK;
if (SUCCEEDED(hr)) hr = hrTemp;
RegSafeCloseKey(hkeyInterfaces); }
RegSafeCloseKey(hkey); } else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) { hr = S_OK; }
TraceError("CTcpipcfg::HrCleanUpPerformRouterDiscoveryFromRegistry", hr); return hr; }
HRESULT CTcpipcfg::HrSaveBackupTcpSettings(HKEY hkeyInterfaceParam, ADAPTER_INFO * pAdapter) { HRESULT hr = S_OK;
HKEY hkeyDhcpConfigs = NULL; HKEY hkeyDhcpCfg = NULL; DWORD dwDisposition = 0; tstring strConfigurationName; tstring strReg;
if (!pAdapter->m_BackupInfo.m_fAutoNet) { //Set the Configuration option name as "Alternate_{Interface GUID}"
strConfigurationName = c_szAlternate; strConfigurationName += pAdapter->m_strBindName;
//construct the NULL terminator for the Multi_SZ
int cch = strConfigurationName.length() + 2; WCHAR * pwsz = new WCHAR[cch]; if (NULL == pwsz) return E_OUTOFMEMORY;
ZeroMemory(pwsz, sizeof(pwsz[0]) * cch); lstrcpyW(pwsz, strConfigurationName.c_str());
hr = HrRegSetMultiSz(hkeyInterfaceParam, c_szActiveConfigurations, pwsz);
delete [] pwsz; } else { hr = HrRegDeleteValue(hkeyInterfaceParam, c_szActiveConfigurations);
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) hr = S_OK; }
if (FAILED(hr)) { TraceTag(ttidTcpip, "HrSaveBackupTcpSettings: Failed to create ActiveConfigurations value, hr: %x", hr); goto LERROR; }
hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szDhcpConfigurations, REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hkeyDhcpConfigs, &dwDisposition);
if (FAILED(hr)) { TraceTag(ttidTcpip, "HrSaveBackupTcpSettings: Failed to open the Services reg key, hr: %x", hr); goto LERROR; }
hr = HrRegCreateKeyEx(hkeyDhcpConfigs, strConfigurationName.c_str(), REG_OPTION_NON_VOLATILE, KEY_READ_WRITE, NULL, &hkeyDhcpCfg, &dwDisposition);
if (SUCCEEDED(hr)) { DWORD pdwOptionData[2]; // buffer holding the option's Dwords
DWORD dwIdxData; // actual data to be saved into blob for each option
LPBYTE pRegRaw = NULL; // buffer holding the blob
DWORD cb = 0; // blob size in the pRegRaw buffer
DWORD cbMax = 0; // pRegRaw buffer size (assert(cb<=cbMax))
// fill in the blob pRegRaw to be written to the registry
//
// fill in option 50 (requested IpAddress = Fallback IpAddress)
pdwOptionData[0] = htonl(IPStringToDword(pAdapter->m_BackupInfo.m_strIpAddr.c_str())); // the adapter's address can't be an empty string hence a 0.0.0.0 address
hr = HrSaveBackupDwordOption ( OPTION_REQUESTED_ADDRESS, pdwOptionData, 1, &pRegRaw, &cb, &cbMax); // fill in option 1 (Fallback subnet mask)
if (hr == S_OK) { pdwOptionData[0] = htonl(IPStringToDword(pAdapter->m_BackupInfo.m_strSubnetMask.c_str())); // the adapter's subnet mask can't be an empty string, hence a 0.0.0.0 address
hr = HrSaveBackupDwordOption ( OPTION_SUBNET_MASK, pdwOptionData, 1, &pRegRaw, &cb, &cbMax); }
// fill in option 3 if any Fallback gateway is specified
if (hr == S_OK) { dwIdxData = 0; pdwOptionData[dwIdxData] = htonl(IPStringToDword(pAdapter->m_BackupInfo.m_strDefGw.c_str())); dwIdxData += (pdwOptionData[dwIdxData] != 0);
hr = HrSaveBackupDwordOption ( OPTION_ROUTER_ADDRESS, pdwOptionData, dwIdxData, &pRegRaw, &cb, &cbMax);
}
// fill in option 6 if any Fallback DNS servers (maximum 2 supported for now) is specified
if (hr == S_OK) { dwIdxData = 0; pdwOptionData[dwIdxData] = htonl(IPStringToDword(pAdapter->m_BackupInfo.m_strPreferredDns.c_str())); dwIdxData += (pdwOptionData[dwIdxData] != 0); pdwOptionData[dwIdxData] = htonl(IPStringToDword(pAdapter->m_BackupInfo.m_strAlternateDns.c_str())); dwIdxData += (pdwOptionData[dwIdxData] != 0);
hr = HrSaveBackupDwordOption ( OPTION_DOMAIN_NAME_SERVERS, pdwOptionData, dwIdxData, &pRegRaw, &cb, &cbMax); }
// fill in option 44 if any Fallback WINS servers (maximum 2 supported for now) is specified
if (hr == S_OK) { dwIdxData = 0; pdwOptionData[dwIdxData] = htonl(IPStringToDword(pAdapter->m_BackupInfo.m_strPreferredWins.c_str())); dwIdxData += (pdwOptionData[dwIdxData] != 0); pdwOptionData[dwIdxData] = htonl(IPStringToDword(pAdapter->m_BackupInfo.m_strAlternateWins.c_str())); dwIdxData += (pdwOptionData[dwIdxData] != 0);
hr = HrSaveBackupDwordOption ( OPTION_NETBIOS_NAME_SERVER, pdwOptionData, dwIdxData, &pRegRaw, &cb, &cbMax); }
// write the blob to the registry
if (hr == S_OK) { hr = HrRegSetBinary(hkeyDhcpCfg, c_szConfigOptions, pRegRaw, cb); }
// free whatever mem was allocated
if (pRegRaw != NULL) CoTaskMemFree(pRegRaw);
RegSafeCloseKey(hkeyDhcpCfg); }
RegSafeCloseKey(hkeyDhcpConfigs);
LERROR: return hr; }
///////////////////////////////////////////////////////////////////
// Fills in a DHCP DWORD option into a blob. Adjusts the size of
// the buffer holding the blob if needed and returns through the
// out params the new buffer, its size and the size of the blob
// it contains.
HRESULT CTcpipcfg::HrSaveBackupDwordOption ( /*IN*/ DWORD Option, /*IN*/ DWORD OptionData[], /*IN*/ DWORD OptionDataSz, /*IN OUT*/ LPBYTE *ppBuffer, /*IN OUT*/ LPDWORD pdwBlobSz, /*IN OUT*/ LPDWORD pdwBufferSz) { DWORD dwBlobSz; REG_BACKUP_INFO *pRegBackupInfo; DWORD dwOptIdx;
// if no data is available at all, then don't save anything
if (OptionDataSz == 0) return S_OK;
// calculate the memory size needed for the new updated blob.
// don't forget, REG_BACKUP_INFO already contains one DWORD from the Option's data
dwBlobSz = (*pdwBlobSz) + sizeof(REG_BACKUP_INFO) + (OptionDataSz-1)*sizeof(DWORD);
// check whether the buffer is large enough to hold the new blob
if ((*pdwBufferSz) < dwBlobSz) { HRESULT hr; LPBYTE pNewBuffer; DWORD dwBuffSz;
// get the expected size of the new buffer
dwBuffSz = max((*pdwBufferSz) + BUFFER_ENLARGEMENT_CHUNK, dwBlobSz);
// if the pointer provided is NULL...
if (*ppBuffer == NULL) { // ...this means we have to do the initial allocation
pNewBuffer = (LPBYTE)CoTaskMemAlloc(dwBuffSz); } else { // ...otherwise is just a buffer enlargement so do a
// realloc in order to keep the original payload
pNewBuffer = (LPBYTE)CoTaskMemRealloc((*ppBuffer), dwBuffSz); }
if (pNewBuffer == NULL) return E_OUTOFMEMORY;
// starting from this point we don't expect any other errors
// so start update the output parameters
(*ppBuffer) = pNewBuffer; (*pdwBufferSz) += dwBuffSz; }
// get the mem storage seen as a REG_BACKUP_INFO struct
pRegBackupInfo = (REG_BACKUP_INFO *)((*ppBuffer) + (*pdwBlobSz)); (*pdwBlobSz) = dwBlobSz; // update the blob by adding the new option
pRegBackupInfo->dwOptionId = Option; pRegBackupInfo->dwClassLen = 0; // fallback options don't have a class
pRegBackupInfo->dwDataLen = OptionDataSz * sizeof(DWORD); pRegBackupInfo->dwIsVendor = 0; // fallback options are not vendor options
pRegBackupInfo->dwExpiryTime = 0x7fffffff; // fallback options don't expire
// add all the Option's data
for (dwOptIdx = 0; dwOptIdx < OptionDataSz; dwOptIdx++) { pRegBackupInfo->dwData[dwOptIdx] = OptionData[dwOptIdx]; } return S_OK; }
HRESULT CTcpipcfg::HrLoadBackupTcpSettings(HKEY hkeyInterfaceParam, ADAPTER_INFO * pAdapter) { HRESULT hr = S_OK; //construct the string "Alternate_{Interface GUID}"
tstring strConfigurationName = c_szAlternate; strConfigurationName += pAdapter->m_strBindName;
// if ActiveConfigurations contain a string "Alternate_{Interface GUID}"
// then there is customized fall-back settings, otherwise Autonet
VSTR vstrTmp;
pAdapter->m_BackupInfo.m_fAutoNet = TRUE; hr = HrRegQueryColString( hkeyInterfaceParam, c_szActiveConfigurations, &vstrTmp); if (SUCCEEDED(hr)) { BOOL fFound = FALSE; for (int i = 0; i < (int)vstrTmp.size(); i++) { if (strConfigurationName == *vstrTmp[i]) { pAdapter->m_BackupInfo.m_fAutoNet = FALSE; break; } }
DeleteColString(&vstrTmp); }
tstring strReg = c_szDhcpConfigurations; strReg += _T("\\"); strReg += strConfigurationName;
HKEY hkeyDhcpConfig = NULL; hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, strReg.c_str(), KEY_READ, &hkeyDhcpConfig); if (SUCCEEDED(hr)) { LPBYTE pBackupInfoForReg = NULL; DWORD cb = 0; hr = HrRegQueryBinaryWithAlloc(hkeyDhcpConfig, c_szConfigOptions, &pBackupInfoForReg, &cb);
if (SUCCEEDED(hr)) { LPBYTE pRaw;
pRaw = pBackupInfoForReg; while (cb >= sizeof(REG_BACKUP_INFO)) { REG_BACKUP_INFO *pOption;
pOption = (REG_BACKUP_INFO *)pRaw;
// don't forget REG_BACKUP_INFO already contains one DWORD from
// the data section. Although the statememnts below are somehow identical
// the compiler is expected to optimize the code: one constant generated
// at compile time for sizeof(REG_BACKUP_INFO) - sizeof(DWORD), and one
// register only used in both lines below.
cb -= sizeof(REG_BACKUP_INFO) - sizeof(DWORD); pRaw += sizeof(REG_BACKUP_INFO) - sizeof(DWORD);
// since cb is DWORD take special care to avoid roll over
if (cb < pOption->dwDataLen) break;
cb -= pOption->dwDataLen; pRaw += pOption->dwDataLen;
HrLoadBackupOption(pOption, &pAdapter->m_BackupInfo); }
MemFree(pBackupInfoForReg); }
RegSafeCloseKey(hkeyDhcpConfig); }
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) { //it's ok if the reg values are missing
hr = S_OK; }
return hr; }
///////////////////////////////////////////////////////////////////
// transfers data from the registry raw representation of the option
// to the corresponding fields from the BACKUP_CFG_INFO structure
//
HRESULT CTcpipcfg::HrLoadBackupOption( /*IN*/ REG_BACKUP_INFO *pOption, /*OUT*/ BACKUP_CFG_INFO *pBackupInfo) { tstring *pIp1 = NULL; tstring *pIp2 = NULL; HRESULT hr = S_OK;
// depending on what the option is, have pIp1 & pIp2 point to the
// fields to be filled in from BACKUP_CFG_INFO
switch(pOption->dwOptionId) { case OPTION_REQUESTED_ADDRESS: pIp1 = &pBackupInfo->m_strIpAddr; break; case OPTION_SUBNET_MASK: pIp1 = &pBackupInfo->m_strSubnetMask; break; case OPTION_ROUTER_ADDRESS: pIp1 = &pBackupInfo->m_strDefGw; break; case OPTION_DOMAIN_NAME_SERVERS: pIp1 = &pBackupInfo->m_strPreferredDns; pIp2 = &pBackupInfo->m_strAlternateDns; break; case OPTION_NETBIOS_NAME_SERVER: pIp1 = &pBackupInfo->m_strPreferredWins; pIp2 = &pBackupInfo->m_strAlternateWins; break; default: return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); }
// each option has at least one IpAddress value
DwordToIPString(ntohl(pOption->dwData[0]), *pIp1);
// if the option has more than one IpAddress (meaning two :-)
// and if it is supposed to allow 2 addresses to be specified
// then fill up the second field as well.
if (pOption->dwDataLen > sizeof(DWORD) && pIp2 != NULL) DwordToIPString(ntohl(pOption->dwData[1]), *pIp2);
return hr; }
//Cleanup the backup settings registry under System\Services\dhcp
// wszAdapterName GUID of the adapter of which we want to delete the registry
HRESULT CTcpipcfg::HrDeleteBackupSettingsInDhcp(LPCWSTR wszAdapterName) { HRESULT hr = S_OK; HKEY hkeyDhcpConfigs = NULL; HKEY hkeyDhcpCfg = NULL; DWORD dwDisposition = 0; tstring strConfigurationName = c_szAlternate; strConfigurationName += wszAdapterName;;
hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szDhcpConfigurations, REG_OPTION_NON_VOLATILE, KEY_READ_WRITE_DELETE, NULL, &hkeyDhcpConfigs, &dwDisposition);
if (FAILED(hr)) { TraceTag(ttidTcpip, "HrDeleteBackupSettingsInDhcp: Failed to open the Services reg key, hr: %x", hr); goto LERROR; }
hr = HrRegDeleteKeyTree(hkeyDhcpConfigs, strConfigurationName.c_str());
RegSafeCloseKey(hkeyDhcpConfigs); LERROR: return hr; }
HRESULT CTcpipcfg::HrSetSecurityForNetConfigOpsOnSubkeys(HKEY hkeyRoot, LPCWSTR strKeyName) { PSID psidGroup = NULL; SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY; HRESULT hr = S_OK;
if (AllocateAndInitializeSid(&sidAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS, 0, 0, 0, 0, 0, 0, &psidGroup)) { CRegKeySecurity rkSecurity;
hr = rkSecurity.RegOpenKey(hkeyRoot, strKeyName);
if (SUCCEEDED(hr)) { hr = rkSecurity.GetKeySecurity(); if (SUCCEEDED(hr)) { hr = rkSecurity.GetSecurityDescriptorDacl(); if (SUCCEEDED(hr)) { hr = rkSecurity.GrantRightsOnRegKey(psidGroup, KEY_READ_WRITE_DELETE, KEY_ALL); } } rkSecurity.RegCloseKey(); }
FreeSid(psidGroup); }
return hr; }
|