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.
1105 lines
30 KiB
1105 lines
30 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1997.
|
|
//
|
|
// File: T C P I P O B J . C P P
|
|
//
|
|
// Contents: TCP/IP notify object
|
|
//
|
|
// Notes:
|
|
//
|
|
// Author: tongl
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "pch.h"
|
|
#pragma hdrstop
|
|
|
|
#include "ncreg.h"
|
|
#include "ncstl.h"
|
|
#include "tcpconst.h"
|
|
#include "tcpipobj.h"
|
|
#include "tcputil.h"
|
|
#include "tcprsvp.h"
|
|
|
|
extern const WCHAR c_szBiNdisAtm[];
|
|
|
|
extern const WCHAR c_szInfId_MS_NetBT[];
|
|
extern const WCHAR c_szInfId_MS_NetBT_SMB[];
|
|
extern const WCHAR c_szInfId_MS_RSVP[];
|
|
|
|
|
|
HICON g_hiconUpArrow;
|
|
HICON g_hiconDownArrow;
|
|
|
|
// Constructor
|
|
CTcpipcfg::CTcpipcfg()
|
|
: m_ipaddr(NULL),
|
|
m_pUnkContext(NULL),
|
|
m_pnc(NULL),
|
|
m_pnccTcpip(NULL),
|
|
m_pTcpipPrivate(NULL),
|
|
m_pnccWins(NULL),
|
|
m_fRemoving(FALSE),
|
|
m_fInstalling(FALSE),
|
|
m_fUpgradeCleanupDnsKey(FALSE),
|
|
m_fUpgradeGlobalDnsDomain(FALSE),
|
|
m_pSecondMemoryAdapterInfo(NULL)
|
|
{ }
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// INetCfgComponentControl
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
// Member: CTcpipcfg::Initialize
|
|
//
|
|
STDMETHODIMP CTcpipcfg::Initialize(INetCfgComponent * pnccTcpip,
|
|
INetCfg * pncNetCfg,
|
|
BOOL fInstalling)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
Assert(pncNetCfg);
|
|
Assert(pnccTcpip);
|
|
|
|
m_fRemoving = FALSE;
|
|
m_fInstalling = FALSE;
|
|
|
|
m_fSaveRegistry = FALSE;
|
|
|
|
m_ConnType = CONNECTION_UNSET;
|
|
m_fReconfig = FALSE;
|
|
|
|
// we havn't changed LmHost file
|
|
m_fLmhostsFileSet = FALSE;
|
|
|
|
// IPSec is removed from connection UI
|
|
// we have not change ipsec policy
|
|
//m_fIpsecPolicySet = FALSE;
|
|
|
|
// by default, this should be an admin
|
|
m_fRasNotAdmin = FALSE;
|
|
|
|
Validate_INetCfgNotify_Initialize(pnccTcpip, pncNetCfg, fInstalling);
|
|
|
|
do // psudo loop ( so we don't use goto's on err )
|
|
{
|
|
// in case of Initialize called twice, for resurect the component
|
|
ReleaseObj(m_pnc);
|
|
m_pnc = NULL;
|
|
|
|
ReleaseObj(m_pnccTcpip);
|
|
m_pnccTcpip = NULL;
|
|
|
|
ReleaseObj(m_pTcpipPrivate);
|
|
m_pTcpipPrivate = NULL;
|
|
|
|
ReleaseObj(m_pnccWins);
|
|
m_pnccWins = NULL;
|
|
|
|
// store reference to the INetCfg in our object
|
|
m_pnc = pncNetCfg;
|
|
m_pnc->AddRef();
|
|
|
|
// Store a reference to the INetCfgComponent for tcpip in our object
|
|
m_pnccTcpip = pnccTcpip;
|
|
m_pnccTcpip->AddRef();
|
|
|
|
hr = pnccTcpip->QueryInterface(
|
|
IID_INetCfgComponentPrivate,
|
|
reinterpret_cast<void**>(&m_pTcpipPrivate));
|
|
if (FAILED(hr))
|
|
break;
|
|
|
|
// Get a copy of the WINS component and store in our object
|
|
|
|
// NOTE: WINS client is not necessarily installed yet!
|
|
// we also try to get a pointer at the Install sections
|
|
hr = pncNetCfg->FindComponent(c_szInfId_MS_NetBT,
|
|
&m_pnccWins);
|
|
if (FAILED(hr))
|
|
break;
|
|
|
|
if (S_FALSE == hr) // NetBt not found
|
|
{
|
|
if (!fInstalling) // We are in trouble if NetBt is not there
|
|
{
|
|
TraceError("CTcpipcfg::Initialize - NetBt has not been installed yet", hr);
|
|
break;
|
|
}
|
|
else // We are ok since tcpip will install netbt
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
// Set default global parameters
|
|
hr = m_glbGlobalInfo.HrSetDefaults();
|
|
if (FAILED(hr))
|
|
break;
|
|
|
|
// If tcpip is being installed, we don't have any cards to load
|
|
if (!fInstalling)
|
|
{
|
|
// Get list of cards which are currently in the system + if they are bound
|
|
hr = HrGetNetCards();
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Let's read parameters from registry
|
|
hr = HrLoadSettings();
|
|
}
|
|
}
|
|
} while(FALSE);
|
|
|
|
// Have we got any bound cards ?
|
|
m_fHasBoundCardOnInit = FHasBoundCard();
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
Validate_INetCfgNotify_Initialize_Return(hr);
|
|
|
|
TraceError("CTcpipcfg::Initialize", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Member: CTcpipcfg::Validate
|
|
//
|
|
STDMETHODIMP CTcpipcfg::Validate()
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Member: CTcpipcfg::Cancel
|
|
//
|
|
STDMETHODIMP CTcpipcfg::CancelChanges()
|
|
{
|
|
// Note: first memory state is release in destructor
|
|
|
|
// If the lmhosts file was set, we need to roll it back to the backup
|
|
if (m_fLmhostsFileSet)
|
|
{
|
|
ResetLmhostsFile();
|
|
m_fLmhostsFileSet = FALSE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Member: CTcpipcfg::ApplyRegistryChanges
|
|
//
|
|
STDMETHODIMP CTcpipcfg::ApplyRegistryChanges()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HRESULT hrTmp = S_OK;
|
|
|
|
if (m_fRemoving)
|
|
{
|
|
// (nsun) we should remove the Nt4 duplicate registry here because the cards
|
|
// may have been marked as deleted
|
|
hr = HrRemoveNt4DuplicateRegistry();
|
|
|
|
ReleaseObj(m_pnccWins);
|
|
m_pnccWins = NULL;
|
|
|
|
// $REVIEW(tongl 9/29/97): Removing ServiceProvider value from registry
|
|
// Remove "Tcpip" from the:
|
|
// System\CurrentControlSet\Control\ServiceProvider\Order\ProviderOrder value
|
|
hrTmp = ::HrRegRemoveStringFromMultiSz(c_szTcpip,
|
|
HKEY_LOCAL_MACHINE,
|
|
c_szSrvProvOrderKey,
|
|
c_szProviderOrderVal,
|
|
STRING_FLAG_REMOVE_ALL);
|
|
if (SUCCEEDED(hr))
|
|
hr = hrTmp;
|
|
|
|
// Remove RSVP providers
|
|
//
|
|
RemoveRsvpProvider();
|
|
}
|
|
else
|
|
{
|
|
// Cleanup the adapters marked as for deletion from the memory structure
|
|
// Change made for #95637
|
|
for(size_t i = 0 ; i < m_vcardAdapterInfo.size() ; ++i)
|
|
{
|
|
if (m_vcardAdapterInfo[i]->m_fDeleted)
|
|
{
|
|
//delete it
|
|
FreeVectorItem(m_vcardAdapterInfo, i);
|
|
i--; //move the pointer back ?
|
|
}
|
|
}
|
|
|
|
// install RSVP providers
|
|
//
|
|
if (m_fInstalling)
|
|
{
|
|
hr = HrInstallRsvpProvider();
|
|
TraceError("CTcpipcfg::ApplyRegistryChanges: HrInstallRsvpProvider failed", hr);
|
|
|
|
// if RSVP install fails, we still want to continue apply
|
|
//
|
|
hr = S_OK;
|
|
}
|
|
|
|
if (m_fSaveRegistry)
|
|
{
|
|
// Save info in first memory state to registry
|
|
// m_glbGlobalInfo and m_vcardAdapterInfo
|
|
hrTmp = HrSaveSettings();
|
|
if (SUCCEEDED(hr))
|
|
hr = hrTmp;
|
|
}
|
|
else
|
|
{
|
|
// No change
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
Validate_INetCfgNotify_Apply_Return(hr);
|
|
|
|
TraceError("CTcpipcfg::ApplyRegistryChanges", (hr == S_FALSE) ? S_OK : hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Member: CTcpipcfg::ApplyPnpChanges
|
|
//
|
|
STDMETHODIMP CTcpipcfg::ApplyPnpChanges(IN INetCfgPnpReconfigCallback* pICallback)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HRESULT hrTmp = S_OK;
|
|
|
|
Assert(pICallback);
|
|
|
|
if (!m_fRemoving)
|
|
{
|
|
if(!m_fInstalling)
|
|
{
|
|
if (m_fReconfig)
|
|
{
|
|
// Notify protocols/services of changes
|
|
|
|
// Notify Tcpip of any changes in the IP Addresses
|
|
hrTmp = HrNotifyDhcp();
|
|
if (S_OK == hr)
|
|
hr = hrTmp;
|
|
|
|
// reconfig tcpip
|
|
hrTmp = HrReconfigIp(pICallback);
|
|
if (S_OK == hr)
|
|
hr = hrTmp;
|
|
|
|
// reconfig netbt
|
|
hrTmp = HrReconfigNbt(pICallback);
|
|
if (S_OK == hr)
|
|
hr = hrTmp;
|
|
|
|
// reconfig dns
|
|
hrTmp = HrReconfigDns();
|
|
if (S_OK == hr)
|
|
hr = hrTmp;
|
|
}
|
|
|
|
if (IsBindOrderChanged())
|
|
{
|
|
//notify DNS cache of binding order changes
|
|
hrTmp = HrReconfigDns(TRUE);
|
|
if (S_OK == hr)
|
|
hr = hrTmp;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//IPSec is removed from connection UI
|
|
// if (m_fIpsecPolicySet)
|
|
// hrTmp = HrSetActiveIpsecPolicy();
|
|
|
|
if (S_OK == hr)
|
|
hr = hrTmp;
|
|
}
|
|
|
|
// Current state has been applied, reset the flags and
|
|
// "Old" value of parameters
|
|
if (S_OK == hr)
|
|
{
|
|
ReInitializeInternalState();
|
|
}
|
|
|
|
TraceError("CTcpipcfg::ApplyPnpChanges", hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// INetCfgComponentSetUp
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
// Member: CTcpipcfg::Install
|
|
//
|
|
STDMETHODIMP CTcpipcfg::Install(DWORD dwSetupFlags)
|
|
{
|
|
HRESULT hr;
|
|
|
|
Validate_INetCfgNotify_Install(dwSetupFlags);
|
|
|
|
m_fSaveRegistry = TRUE;
|
|
m_fInstalling = TRUE;
|
|
|
|
// Install the WINS client on behalf of TCPIP.
|
|
Assert(!m_pnccWins);
|
|
hr = HrInstallComponentOboComponent(m_pnc, NULL,
|
|
GUID_DEVCLASS_NETTRANS,
|
|
c_szInfId_MS_NetBT, m_pnccTcpip,
|
|
&m_pnccWins);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
Assert(m_pnccWins);
|
|
|
|
hr = HrInstallComponentOboComponent(m_pnc, NULL,
|
|
GUID_DEVCLASS_NETTRANS,
|
|
c_szInfId_MS_NetBT_SMB, m_pnccTcpip,
|
|
NULL);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Install RSVP client on behalf of TCPIP.
|
|
hr = HrInstallComponentOboComponent(m_pnc, NULL,
|
|
GUID_DEVCLASS_NETSERVICE,
|
|
c_szInfId_MS_RSVP, m_pnccTcpip,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
TraceError("CTcpipcfg::Install", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Member: CTcpipcfg::Upgrade
|
|
//
|
|
STDMETHODIMP CTcpipcfg::Upgrade(DWORD dwSetupFlags,
|
|
DWORD dwUpgradeFomBuildNo )
|
|
{
|
|
HrCleanUpPerformRouterDiscoveryFromRegistry();
|
|
return S_FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Member: CTcpipcfg::ReadAnswerFile
|
|
//
|
|
// Purpose: Reads the appropriate fields from the given answer file into
|
|
// our in-memory state.
|
|
//
|
|
// Arguments:
|
|
// pszAnswerFile [in] Filename of answer file for upgrade.
|
|
// pszAnswerSection [in] Comma-separated list of sections in the
|
|
// file appropriate to this component.
|
|
//
|
|
// Returns: HRESULT, Error code.
|
|
//
|
|
// Author: tongl 7 May 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
STDMETHODIMP CTcpipcfg::ReadAnswerFile( PCWSTR pszAnswerFile,
|
|
PCWSTR pszAnswerSection)
|
|
{
|
|
m_fSaveRegistry = TRUE;
|
|
|
|
if (pszAnswerFile && pszAnswerSection)
|
|
{
|
|
// Process answer file
|
|
(void) HrProcessAnswerFile(pszAnswerFile, pszAnswerSection);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Member: CTcpipcfg::Removing
|
|
//
|
|
STDMETHODIMP CTcpipcfg::Removing()
|
|
{
|
|
HRESULT hr;
|
|
|
|
m_fRemoving = TRUE;
|
|
|
|
// Remove NetBt protocol. This doesn't actually remove the
|
|
// component, it simply marks it as needing to be removed,
|
|
// and in Apply() it will be fully removed.
|
|
hr = HrRemoveComponentOboComponent(
|
|
m_pnc, GUID_DEVCLASS_NETTRANS,
|
|
c_szInfId_MS_NetBT, m_pnccTcpip);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// remove NetBt_SMB
|
|
hr = HrRemoveComponentOboComponent(
|
|
m_pnc, GUID_DEVCLASS_NETTRANS,
|
|
c_szInfId_MS_NetBT_SMB, m_pnccTcpip);
|
|
|
|
}
|
|
|
|
// Also remove RSVP
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HrRemoveComponentOboComponent(
|
|
m_pnc, GUID_DEVCLASS_NETSERVICE,
|
|
c_szInfId_MS_RSVP, m_pnccTcpip);
|
|
}
|
|
|
|
TraceError("CTcpipcfg::Removing", hr);
|
|
return hr;
|
|
}
|
|
|
|
// INetCfgProperties
|
|
STDMETHODIMP CTcpipcfg::SetContext(IUnknown * pUnk)
|
|
{
|
|
// release previous context, if any
|
|
ReleaseObj(m_pUnkContext);
|
|
m_pUnkContext = NULL;
|
|
|
|
if (pUnk) // set the new context
|
|
{
|
|
m_pUnkContext = pUnk;
|
|
m_pUnkContext->AddRef();
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CTcpipcfg::MergePropPages(
|
|
IN OUT DWORD* pdwDefPages,
|
|
OUT LPBYTE* pahpspPrivate,
|
|
OUT UINT* pcPages,
|
|
IN HWND hwndParent,
|
|
OUT PCWSTR* pszStartPage)
|
|
{
|
|
Validate_INetCfgProperties_MergePropPages (
|
|
pdwDefPages, pahpspPrivate, pcPages, hwndParent, pszStartPage);
|
|
|
|
// Initialize output parameter
|
|
HPROPSHEETPAGE *ahpsp = NULL;
|
|
int cPages = 0;
|
|
|
|
// We don't want any default pages to be shown
|
|
*pdwDefPages = 0;
|
|
*pcPages = NULL;
|
|
*pahpspPrivate = NULL;
|
|
|
|
// get the connection context in which we are bringing up the UI
|
|
HRESULT hr = HrSetConnectionContext();
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
AssertSz(((CONNECTION_LAN == m_ConnType)||
|
|
(CONNECTION_RAS_PPP == m_ConnType)||
|
|
(CONNECTION_RAS_SLIP == m_ConnType)||
|
|
(CONNECTION_RAS_VPN == m_ConnType)),
|
|
"How come we don't know the connection type yet on MergePropPages?");
|
|
|
|
// Initialize the common controls library
|
|
INITCOMMONCONTROLSEX icc;
|
|
icc.dwSize = sizeof(icc);
|
|
icc.dwICC = ICC_INTERNET_CLASSES;
|
|
|
|
SideAssert(InitCommonControlsEx(&icc));
|
|
|
|
hr = HrSetupPropSheets(&ahpsp, &cPages);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*pahpspPrivate = (LPBYTE)ahpsp;
|
|
*pcPages = cPages;
|
|
|
|
// Set the global up\down arrows
|
|
if (!g_hiconUpArrow && !g_hiconDownArrow)
|
|
{
|
|
g_hiconUpArrow = (HICON)LoadImage(_Module.GetResourceInstance(),
|
|
MAKEINTRESOURCE(IDI_UP_ARROW),
|
|
IMAGE_ICON, 16, 16, 0);
|
|
g_hiconDownArrow = (HICON)LoadImage(_Module.GetResourceInstance(),
|
|
MAKEINTRESOURCE(IDI_DOWN_ARROW),
|
|
IMAGE_ICON, 16, 16, 0);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
*pcPages = 0;
|
|
CoTaskMemFree(ahpsp);
|
|
|
|
}
|
|
}
|
|
|
|
Validate_INetCfgProperties_MergePropPages_Return(hr);
|
|
|
|
TraceError("CTcpipcfg::MergePropPages", hr);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CTcpipcfg::ValidateProperties(HWND hwndSheet)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CTcpipcfg::CancelProperties()
|
|
{
|
|
// If the lmhosts file was set, we need to roll it back to the backup
|
|
if (m_fSecondMemoryLmhostsFileReset)
|
|
{
|
|
ResetLmhostsFile();
|
|
}
|
|
|
|
// Release second memory state
|
|
ExitProperties();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CTcpipcfg::ApplyProperties()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!m_fReconfig)
|
|
{
|
|
m_fReconfig = m_fSecondMemoryModified ||
|
|
m_fSecondMemoryLmhostsFileReset;
|
|
|
|
//IPSec is removed from connection UI
|
|
// || m_fSecondMemoryIpsecPolicySet;
|
|
}
|
|
|
|
if (!m_fLmhostsFileSet)
|
|
m_fLmhostsFileSet = m_fSecondMemoryLmhostsFileReset;
|
|
|
|
//IPSec is removed from connection UI
|
|
//if (!m_fIpsecPolicySet)
|
|
// m_fIpsecPolicySet = m_fSecondMemoryIpsecPolicySet;
|
|
|
|
if (!m_fSaveRegistry)
|
|
m_fSaveRegistry = m_fSecondMemoryModified;
|
|
|
|
// Copy info from second memory state to first memory state
|
|
if (m_fSecondMemoryModified)
|
|
{
|
|
m_glbGlobalInfo = m_glbSecondMemoryGlobalInfo;
|
|
hr = HrSaveAdapterInfo();
|
|
}
|
|
|
|
// Release second memory state
|
|
ExitProperties();
|
|
|
|
Validate_INetCfgProperties_ApplyProperties_Return(hr);
|
|
|
|
TraceError("CTcpipcfg::ApplyProperties", hr);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CTcpipcfg::QueryBindingPath(DWORD dwChangeFlag,
|
|
INetCfgBindingPath * pncbp)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// If the binding is to an atm adapter (i.e. interface = ndisatm),
|
|
// then return NETCFG_S_DISABLE_QUERY
|
|
//
|
|
if (dwChangeFlag & NCN_ADD)
|
|
{
|
|
|
|
INetCfgComponent* pnccLastComponent;
|
|
PWSTR pszInterfaceName;
|
|
|
|
hr = HrGetLastComponentAndInterface(pncbp,
|
|
&pnccLastComponent,
|
|
&pszInterfaceName);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// If adding an adapter through interface ndisatm,
|
|
// we want to disable the binding interface since it's
|
|
// the IP over ATM direct binding
|
|
if (0 == lstrcmpW(c_szBiNdisAtm, pszInterfaceName))
|
|
{
|
|
hr = NETCFG_S_DISABLE_QUERY;
|
|
}
|
|
|
|
ReleaseObj (pnccLastComponent);
|
|
CoTaskMemFree (pszInterfaceName);
|
|
}
|
|
}
|
|
|
|
TraceError("CTcpipcfg::QueryBindingPath",
|
|
(NETCFG_S_DISABLE_QUERY == hr) ? S_OK : hr);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CTcpipcfg::NotifyBindingPath(
|
|
DWORD dwChangeFlag,
|
|
INetCfgBindingPath * pncbp)
|
|
{
|
|
Assert(!(dwChangeFlag & NCN_ADD && dwChangeFlag & NCN_REMOVE));
|
|
Assert(!(dwChangeFlag & NCN_ENABLE && dwChangeFlag & NCN_DISABLE));
|
|
|
|
// If we are told to add a card, we must be told at the same time whether the
|
|
// binding is enabled or disabled
|
|
Assert(FImplies((dwChangeFlag & NCN_ADD),
|
|
((dwChangeFlag & NCN_ENABLE)||(dwChangeFlag & NCN_DISABLE))));
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
Validate_INetCfgBindNotify_NotifyBindingPath(dwChangeFlag, pncbp);
|
|
|
|
INetCfgComponent * pnccLastComponent;
|
|
PWSTR pszInterfaceName;
|
|
hr = HrGetLastComponentAndInterface(pncbp,
|
|
&pnccLastComponent,
|
|
&pszInterfaceName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
#if DBG
|
|
GUID guidNetClass;
|
|
hr = pnccLastComponent->GetClassGuid (&guidNetClass);
|
|
|
|
AssertSz(
|
|
SUCCEEDED(hr) &&
|
|
IsEqualGUID(guidNetClass, GUID_DEVCLASS_NET),
|
|
"Why the last component on the path is not an adapter?");
|
|
#endif
|
|
|
|
// If we are adding/removing cards, set m_fSaveRegistry
|
|
// so we apply the changes to registry
|
|
|
|
if (dwChangeFlag & (NCN_ADD | NCN_REMOVE))
|
|
m_fSaveRegistry = TRUE;
|
|
|
|
hr = HrAdapterBindNotify(pnccLastComponent,
|
|
dwChangeFlag,
|
|
pszInterfaceName);
|
|
|
|
ReleaseObj (pnccLastComponent);
|
|
CoTaskMemFree (pszInterfaceName);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
hr = S_OK;
|
|
|
|
Validate_INetCfgBindNotify_NotifyBindingPath_Return(hr);
|
|
|
|
TraceError("CTcpipcfg::NotifyBindingPath", hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// INetCfgComponentUpperEdge
|
|
//
|
|
|
|
// Return an array of interface ids for an adapter bound to
|
|
// this component. If the specified adapter does not have explicit
|
|
// interfaces exported from it, S_FALSE is returned.
|
|
// pAdapter is the adapter in question.
|
|
// pdwNumInterfaces is the address of a DWORD where the count of elements
|
|
// returned via ppguidInterfaceIds is stored.
|
|
// ppguidInterfaceIds is the address of a pointer where an allocated
|
|
// block of memory is returned. This memory is an array of interface ids.
|
|
// *ppguidInterfaceIds should be free with CoTaskMemFree if S_OK is returned.
|
|
// if S_FALSE is returned, *pdwNumInterfaces and *ppguidInterfaceIds should
|
|
// be NULL.
|
|
//
|
|
|
|
HRESULT
|
|
CTcpipcfg::GetInterfaceIdsForAdapter (
|
|
INetCfgComponent* pnccAdapter,
|
|
DWORD* pdwNumInterfaces,
|
|
GUID** ppguidInterfaceIds)
|
|
{
|
|
Assert (pnccAdapter);
|
|
Assert (pdwNumInterfaces);
|
|
|
|
HRESULT hr = S_FALSE;
|
|
|
|
// Initialize output parameters.
|
|
//
|
|
*pdwNumInterfaces = 0;
|
|
if (ppguidInterfaceIds)
|
|
{
|
|
*ppguidInterfaceIds = NULL;
|
|
}
|
|
|
|
ADAPTER_INFO* pAdapterInfo = PAdapterFromNetcfgComponent(pnccAdapter);
|
|
|
|
if (pAdapterInfo &&
|
|
pAdapterInfo->m_fIsWanAdapter &&
|
|
pAdapterInfo->m_fIsMultipleIfaceMode)
|
|
{
|
|
hr = GetGuidArrayFromIfaceColWithCoTaskMemAlloc(
|
|
pAdapterInfo->m_IfaceIds,
|
|
ppguidInterfaceIds,
|
|
pdwNumInterfaces);
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, (S_FALSE == hr),
|
|
"CTcpipcfg::GetInterfaceIdsForAdapter");
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Add the specified number of new interfaces to the specified adapter.
|
|
// The implementation will choose the interface ids.
|
|
//
|
|
HRESULT
|
|
CTcpipcfg::AddInterfacesToAdapter (
|
|
INetCfgComponent* pnccAdapter,
|
|
DWORD dwNumInterfaces)
|
|
{
|
|
Assert (pnccAdapter);
|
|
|
|
HRESULT hr = S_FALSE;
|
|
ADAPTER_INFO* pAdapterInfo;
|
|
|
|
if ((NULL == pnccAdapter) || (0 == dwNumInterfaces))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto end_AddInterfacesToAdapter;
|
|
}
|
|
|
|
pAdapterInfo = PAdapterFromNetcfgComponent(pnccAdapter);
|
|
|
|
if (pAdapterInfo &&
|
|
pAdapterInfo->m_fIsWanAdapter)
|
|
{
|
|
AddInterfacesToAdapterInfo(
|
|
pAdapterInfo,
|
|
dwNumInterfaces);
|
|
|
|
pAdapterInfo->m_fIsMultipleIfaceMode = TRUE;
|
|
pAdapterInfo->m_fNewlyChanged = TRUE;
|
|
m_fSaveRegistry = TRUE;
|
|
m_fReconfig = TRUE;
|
|
|
|
// Notify the binding engine that our upper edge has changed.
|
|
//
|
|
(VOID)m_pTcpipPrivate->NotifyUpperEdgeConfigChange ();
|
|
hr = S_OK;
|
|
}
|
|
|
|
end_AddInterfacesToAdapter:
|
|
TraceErrorSkip1("CTcpipcfg::AddInterfacesToAdapter", hr, S_FALSE);
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Remove the specified interface ids from the specified adapter.
|
|
// pguidInterfaceIds is the array of ids to be removed. dwNumInterfaces
|
|
// is the count in that array.
|
|
//
|
|
HRESULT
|
|
CTcpipcfg::RemoveInterfacesFromAdapter (
|
|
INetCfgComponent* pnccAdapter,
|
|
DWORD dwNumInterfaces,
|
|
const GUID* pguidInterfaceIds)
|
|
{
|
|
Assert (pnccAdapter);
|
|
Assert (pguidInterfaceIds);
|
|
|
|
HRESULT hr = E_UNEXPECTED;
|
|
ADAPTER_INFO* pAdapterInfo;
|
|
|
|
if ((NULL == pnccAdapter) ||
|
|
(0 == dwNumInterfaces) ||
|
|
(NULL == pguidInterfaceIds))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto end_RemoveInterfacesFromAdapter;
|
|
}
|
|
|
|
pAdapterInfo = PAdapterFromNetcfgComponent(pnccAdapter);
|
|
|
|
AssertSz( pAdapterInfo,
|
|
"CTcpipcfg::AddInterfacesToAdapter cannot find the adapter "
|
|
"GUID from the adapter list");
|
|
|
|
if (pAdapterInfo &&
|
|
pAdapterInfo->m_fIsWanAdapter &&
|
|
pAdapterInfo->m_fIsMultipleIfaceMode)
|
|
{
|
|
DWORD dwNumRemoved = 0;
|
|
IFACEITER iter;
|
|
for (DWORD i = 0; i < dwNumInterfaces; i++)
|
|
{
|
|
iter = find(pAdapterInfo->m_IfaceIds.begin(),
|
|
pAdapterInfo->m_IfaceIds.end(),
|
|
pguidInterfaceIds[i]);
|
|
|
|
if (iter != pAdapterInfo->m_IfaceIds.end())
|
|
{
|
|
pAdapterInfo->m_IfaceIds.erase(iter);
|
|
dwNumRemoved++;
|
|
}
|
|
}
|
|
|
|
//$REVIEW (nsun) mark the adapter as NewlyAdded so that we will re-write its adapter registry
|
|
if (dwNumRemoved > 0)
|
|
{
|
|
pAdapterInfo->m_fNewlyChanged = TRUE;
|
|
m_fSaveRegistry = TRUE;
|
|
}
|
|
|
|
// Notify the binding engine that our upper edge has changed.
|
|
//
|
|
(VOID)m_pTcpipPrivate->NotifyUpperEdgeConfigChange ();
|
|
|
|
hr = (dwNumRemoved == dwNumInterfaces) ? S_OK : S_FALSE;
|
|
}
|
|
|
|
end_RemoveInterfacesFromAdapter:
|
|
TraceError("CTcpipcfg::RemoveInterfacesFromAdapter", hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// ITcpipProperties
|
|
//
|
|
|
|
// The following two methods are for remote tcpip configuration.
|
|
/*
|
|
typedef struct tagREMOTE_IPINFO
|
|
{
|
|
DWORD dwEnableDhcp;
|
|
PWSTR pszIpAddrList;
|
|
PWSTR pszSubnetMaskList;
|
|
PWSTR pszOptionList;
|
|
|
|
} REMOTE_IPINFO;
|
|
*/
|
|
|
|
HRESULT CTcpipcfg::GetIpInfoForAdapter(const GUID* pguidAdapter,
|
|
REMOTE_IPINFO** ppRemoteIpInfo)
|
|
{
|
|
Assert(pguidAdapter);
|
|
Assert(ppRemoteIpInfo);
|
|
|
|
// Initialize the output parameter.
|
|
//
|
|
*ppRemoteIpInfo = NULL;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
ADAPTER_INFO* pAdapter = PAdapterFromInstanceGuid(pguidAdapter);
|
|
if (pAdapter)
|
|
{
|
|
// get the strings from the list
|
|
tstring strIpAddressList;
|
|
ConvertColStringToString(pAdapter->m_vstrIpAddresses,
|
|
c_chListSeparator,
|
|
strIpAddressList);
|
|
|
|
tstring strSubnetMaskList;
|
|
ConvertColStringToString(pAdapter->m_vstrSubnetMask,
|
|
c_chListSeparator,
|
|
strSubnetMaskList);
|
|
|
|
//bug 272647 add gateway metric and interface metric into REMOTE_IPINFO
|
|
tstring strOptionList;
|
|
ConstructOptionListString(pAdapter,
|
|
strOptionList);
|
|
|
|
// allocate buffer for the output param
|
|
DWORD dwBytes = sizeof(REMOTE_IPINFO) +
|
|
sizeof(WCHAR)*(strIpAddressList.length() + 1) +
|
|
sizeof(WCHAR)*(strSubnetMaskList.length() + 1) +
|
|
sizeof(WCHAR)*(strOptionList.length() + 1);
|
|
|
|
PVOID pbBuf;
|
|
hr = HrCoTaskMemAlloc(dwBytes, &pbBuf);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ZeroMemory(pbBuf, dwBytes);
|
|
|
|
REMOTE_IPINFO * pRemoteIpInfo = reinterpret_cast<REMOTE_IPINFO *>(pbBuf);
|
|
pRemoteIpInfo->dwEnableDhcp = pAdapter->m_fEnableDhcp;
|
|
|
|
BYTE* pbByte = reinterpret_cast<BYTE*>(pbBuf);
|
|
|
|
// ip address
|
|
pbByte+= sizeof(REMOTE_IPINFO);
|
|
pRemoteIpInfo->pszwIpAddrList = reinterpret_cast<WCHAR *>(pbByte);
|
|
lstrcpyW(pRemoteIpInfo->pszwIpAddrList, strIpAddressList.c_str());
|
|
|
|
// subnet mask
|
|
pbByte += sizeof(WCHAR)*(strIpAddressList.length() + 1);
|
|
pRemoteIpInfo->pszwSubnetMaskList = reinterpret_cast<WCHAR *>(pbByte);
|
|
lstrcpyW(pRemoteIpInfo->pszwSubnetMaskList, strSubnetMaskList.c_str());
|
|
|
|
// default gateway
|
|
pbByte += sizeof(WCHAR)*(strSubnetMaskList.length() + 1);
|
|
pRemoteIpInfo->pszwOptionList = reinterpret_cast<WCHAR *>(pbByte);
|
|
lstrcpyW(pRemoteIpInfo->pszwOptionList, strOptionList.c_str());
|
|
|
|
*ppRemoteIpInfo = pRemoteIpInfo;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
|
}
|
|
|
|
TraceError("CTcpipcfg::GetIpInfoForAdapter", hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CTcpipcfg::SetIpInfoForAdapter(const GUID* pguidAdapter,
|
|
REMOTE_IPINFO* pRemoteIpInfo)
|
|
{
|
|
Assert(pguidAdapter);
|
|
Assert(pRemoteIpInfo);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
ADAPTER_INFO* pAdapter = PAdapterFromInstanceGuid(pguidAdapter);
|
|
if (pAdapter)
|
|
{
|
|
|
|
// Tell INetCfg that our component is dirty
|
|
Assert(m_pTcpipPrivate);
|
|
m_pTcpipPrivate->SetDirty();
|
|
|
|
// set the flags so we write this to registry & send notification
|
|
// at apply
|
|
m_fSaveRegistry = TRUE;
|
|
m_fReconfig = TRUE;
|
|
|
|
// copy over the info to our data structure
|
|
pAdapter->m_fEnableDhcp = !!pRemoteIpInfo->dwEnableDhcp;
|
|
|
|
ConvertStringToColString(pRemoteIpInfo->pszwIpAddrList,
|
|
c_chListSeparator,
|
|
pAdapter->m_vstrIpAddresses);
|
|
|
|
ConvertStringToColString(pRemoteIpInfo->pszwSubnetMaskList,
|
|
c_chListSeparator,
|
|
pAdapter->m_vstrSubnetMask);
|
|
|
|
hr = HrParseOptionList(pRemoteIpInfo->pszwOptionList, pAdapter);
|
|
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
|
}
|
|
|
|
TraceError("CTcpipcfg::SetIpInfoForAdapter", hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CTcpipcfg::GetUiInfo (
|
|
RASCON_IPUI* pIpui)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Validate parameters.
|
|
//
|
|
if (!pIpui)
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else
|
|
{
|
|
ZeroMemory (pIpui, sizeof(*pIpui));
|
|
|
|
ADAPTER_INFO* pAdapter = PAdapterFromInstanceGuid(
|
|
&m_guidCurrentConnection);
|
|
if (pAdapter)
|
|
{
|
|
if (!pAdapter->m_fEnableDhcp &&
|
|
pAdapter->m_vstrIpAddresses.size())
|
|
{
|
|
pIpui->dwFlags |= RCUIF_USE_IP_ADDR;
|
|
|
|
lstrcpyW(pIpui->pszwIpAddr,
|
|
pAdapter->m_vstrIpAddresses[0]->c_str());
|
|
}
|
|
|
|
if (pAdapter->m_vstrDnsServerList.size() > 0)
|
|
{
|
|
pIpui->dwFlags |= RCUIF_USE_NAME_SERVERS;
|
|
|
|
lstrcpyW(pIpui->pszwDnsAddr,
|
|
pAdapter->m_vstrDnsServerList[0]->c_str());
|
|
|
|
if (pAdapter->m_vstrDnsServerList.size() > 1)
|
|
{
|
|
lstrcpyW(pIpui->pszwDns2Addr,
|
|
pAdapter->m_vstrDnsServerList[1]->c_str());
|
|
}
|
|
}
|
|
|
|
if (pAdapter->m_vstrWinsServerList.size() > 0)
|
|
{
|
|
pIpui->dwFlags |= RCUIF_USE_NAME_SERVERS;
|
|
|
|
lstrcpyW(pIpui->pszwWinsAddr,
|
|
pAdapter->m_vstrWinsServerList[0]->c_str());
|
|
|
|
if (pAdapter->m_vstrWinsServerList.size() > 1)
|
|
{
|
|
lstrcpyW(pIpui->pszwWins2Addr,
|
|
pAdapter->m_vstrWinsServerList[1]->c_str());
|
|
}
|
|
}
|
|
|
|
if (pAdapter->m_fUseRemoteGateway)
|
|
{
|
|
pIpui->dwFlags |= RCUIF_USE_REMOTE_GATEWAY;
|
|
}
|
|
|
|
if (pAdapter->m_fUseIPHeaderCompression)
|
|
{
|
|
pIpui->dwFlags |= RCUIF_USE_HEADER_COMPRESSION;
|
|
}
|
|
|
|
if (pAdapter->m_fDisableDynamicUpdate)
|
|
{
|
|
pIpui->dwFlags |= RCUIF_USE_DISABLE_REGISTER_DNS;
|
|
}
|
|
|
|
if (pAdapter->m_fEnableNameRegistration)
|
|
{
|
|
pIpui->dwFlags |= RCUIF_USE_PRIVATE_DNS_SUFFIX;
|
|
}
|
|
|
|
if (c_dwEnableNetbios == pAdapter->m_dwNetbiosOptions)
|
|
{
|
|
pIpui->dwFlags |= RCUIF_ENABLE_NBT;
|
|
}
|
|
|
|
lstrcpynW(pIpui->pszwDnsSuffix,
|
|
pAdapter->m_strDnsDomain.c_str(),
|
|
sizeof(pIpui->pszwDnsSuffix)/sizeof(pIpui->pszwDnsSuffix[0]));
|
|
|
|
pIpui->dwFrameSize = pAdapter->m_dwFrameSize;
|
|
}
|
|
else
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
}
|
|
TraceError("CTcpipcfg::GetUiInfo", hr);
|
|
return hr;
|
|
}
|