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