//+--------------------------------------------------------------------------- // // 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 // sigh... llinfo.h is needed by ddwanarp.h #include #include extern const WCHAR c_szBiNdisAtm[]; extern const WCHAR c_szBiNdis1394[]; 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(&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(&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( 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; } else if (0 == lstrcmpW(pszInterfaceName, c_szBiNdis1394)) { pAdapter->m_fIs1394Adapter = TRUE; } } 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\ 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\ 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(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\" // 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; } else if (pAdapter->m_fIs1394Adapter) { pszArpModule = c_sz1394Arp; } 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); } else if (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hrTmp) { //for netcfg operators, we will get access denied error when opening this key //however, it's ok because we don't need to touch the key when just updating the IP settings hrTmp = S_OK; } if (SUCCEEDED(hr)) hr = hrTmp; // 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\" // 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); } else if (pAdapter->m_fIs1394Adapter) { // For new NIC1394 cards // (nothing to do). hrTmp = S_OK; } 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; } } else if (pAdapter->m_fIs1394Adapter) { // $REVIEW JosephJ: I don't think we need to do // anything here, because we have no parameters to // change. } // 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(pvBuf); // 1) fillup ip reconfig structure IP_PNP_RECONFIG_REQUEST * pIpReconfig = reinterpret_cast(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(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(pbByte); Assert (strIpConfigString.length() <= USHRT_MAX); *puCount = (USHORT)strIpConfigString.length(); pbByte += sizeof(USHORT); WCHAR * pwszBindName = reinterpret_cast(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(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; //Grant Network service and Netcfg OP the access to the NT4 key if //this is a newly created key //if the keys already have the ACEs, then the APIs wont add duplicate ones //We ignore the return value since nothing can be done if it failed //Also this is not critical for the system to run if (REG_CREATED_NEW_KEY == dwDisposition) { HrSetSecurityForNetConfigOpsOnSubkeys(hkeyServices, strNt4SubKey.c_str()); HrSetSecurityForNetSvcOnSubkeys(hkeyServices, strNt4SubKey.c_str()); } 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.c_str(), 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 = (DWORD)(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.GrantRightsOnRegKey(psidGroup, KEY_READ_WRITE_DELETE, KEY_ALL); } rkSecurity.RegCloseKey(); } FreeSid(psidGroup); } return hr; } HRESULT CTcpipcfg::HrSetSecurityForNetSvcOnSubkeys(HKEY hkeyRoot, LPCWSTR strKeyName) { PSID psidNetSvc = NULL; SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY; HRESULT hr = S_OK; if (AllocateAndInitializeSid(&sidAuth, 1, SECURITY_NETWORK_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0, &psidNetSvc)) { CRegKeySecurity rkSecurity; hr = rkSecurity.RegOpenKey(hkeyRoot, strKeyName); if (SUCCEEDED(hr)) { hr = rkSecurity.GetKeySecurity(); if (SUCCEEDED(hr)) { hr = rkSecurity.GrantRightsOnRegKey(psidNetSvc, KEY_READ_WRITE_DELETE, KEY_ALL); } rkSecurity.RegCloseKey(); } FreeSid(psidNetSvc); } return hr; } //Update the NT4 registry permission to grant Netcfg Op and Network Service access //This is called during upgrade HRESULT CTcpipcfg::HrUpdateNt4RegistryPermission() { HRESULT hr = S_OK; HKEY hkeyServices = NULL; tstring strNt4SubKey; hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegServices, KEY_READ, &hkeyServices); if (FAILED(hr)) { TraceTag(ttidTcpip, "HrUpdateNt4RegistryPermission: Failed to open the Services reg key, hr: %x", hr); return hr; } for(VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin(); iterAdapter != m_vcardAdapterInfo.end(); iterAdapter ++) { ADAPTER_INFO * pAdapter = *iterAdapter; if (pAdapter->m_fIsRasFakeAdapter || pAdapter->m_fIsWanAdapter) { continue; } strNt4SubKey = pAdapter->m_strBindName; strNt4SubKey += c_szRegParamsTcpip; //Grant Network service and Netcfg OP the access to the NT4 key //if the keys already have the ACEs, then the APIs wont add duplicate ones // //We ignore the return value since nothing can be done if it failed //Also this is not critical for the system to run HrSetSecurityForNetConfigOpsOnSubkeys(hkeyServices, strNt4SubKey.c_str()); HrSetSecurityForNetSvcOnSubkeys(hkeyServices, strNt4SubKey.c_str()); } RegSafeCloseKey(hkeyServices); return hr; }