Source code of Windows XP (NT5)
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

//+---------------------------------------------------------------------------
//
// 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;
}