Leaked source code of windows server 2003
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.
 
 
 
 
 
 

4659 lines
163 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[];
extern const WCHAR c_szBiNdis1394[];
extern const WCHAR c_szBiNdisWanIp[];
extern const WCHAR c_szEmpty[];
extern const WCHAR c_szSvcDnscache[];
extern void CopyVstr(VSTR * vstrDest, const VSTR & vstrSrc);
typedef struct {
PCWSTR pszValueName;
DWORD dwType;
} ValueType;
const ValueType s_rgNt4Values[] = {
{RGAS_ENABLE_DHCP, REG_DWORD},
{RGAS_IPADDRESS, REG_MULTI_SZ},
{RGAS_SUBNETMASK, REG_MULTI_SZ},
{RGAS_DEFAULTGATEWAY, REG_MULTI_SZ}
};
//+---------------------------------------------------------------------------
//
// Member: CTcpipcfg::PAdapterFromInstanceGuid
//
// Purpose: Search the adapter info array for an entry with a matching
// instance guid. Return a pointer to the ADAPTER_INFO if found.
//
// Arguments:
// pGuid [in] pointer to instance guid to search for
//
// Returns: Valid pointer if found, NULL if not.
//
// Author: shaunco 1 Oct 1998
//
// Notes:
//
ADAPTER_INFO*
CTcpipcfg::PAdapterFromInstanceGuid (
const GUID* pGuid)
{
Assert (pGuid);
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin();
iterAdapter != m_vcardAdapterInfo.end();
iterAdapter++)
{
ADAPTER_INFO* pAdapter = *iterAdapter;
if (pAdapter->m_guidInstanceId == *pGuid)
{
return pAdapter;
}
}
return NULL;
}
//+---------------------------------------------------------------------------
//
// Member: CTcpipcfg::PAdapterFromNetcfgComponent
//
// Purpose: Search the adapter info array for an entry with an instance
// guid matching that of the specified INetCfgComponent.
// Return a pointer to the ADAPTER_INFO if found.
//
// Arguments:
// pncc [in] INetCfgComponent who's instance guid we are looking for.
//
// Returns: Valid pointer if found, NULL if not.
//
// Author: shaunco 1 Oct 1998
//
// Notes:
//
ADAPTER_INFO*
CTcpipcfg::PAdapterFromNetcfgComponent (
INetCfgComponent* pncc)
{
Assert (pncc);
HRESULT hr;
GUID guidAdapter;
hr = pncc->GetInstanceGuid (&guidAdapter);
if (SUCCEEDED(hr))
{
return PAdapterFromInstanceGuid (&guidAdapter);
}
return NULL;
}
// Called by CTcpipcfg::Initialize.
// We walk the binding path from tcpip and load to first memory state
// all netcards ( both physical cards and Wan adapters )
HRESULT CTcpipcfg::HrGetNetCards()
{
HRESULT hr = S_OK;
CIterNetCfgBindingPath ncbpIter(m_pnccTcpip);
INetCfgBindingPath * pncbp;
// Go through all binding paths in search of tcpip to netcard bindings
while(SUCCEEDED(hr) && (hr = ncbpIter.HrNext(&pncbp)) == S_OK)
{
INetCfgComponent * pnccNetComponent;
PWSTR pszInterfaceName;
hr = HrGetLastComponentAndInterface(pncbp,
&pnccNetComponent,
&pszInterfaceName);
if (SUCCEEDED(hr))
{
Assert(pnccNetComponent);
// The last component should be of NET CLASS
GUID guidClass;
hr = pnccNetComponent->GetClassGuid(&guidClass);
if (SUCCEEDED(hr) && IsEqualGUID(guidClass, GUID_DEVCLASS_NET))
{
PWSTR pszNetCardTcpipBindPath;
hr = pnccNetComponent->GetBindName(&pszNetCardTcpipBindPath);
AssertSz(SUCCEEDED(hr),
"Net card on binding path with no bind path name!!");
m_vstrBindOrder.push_back(new tstring(pszNetCardTcpipBindPath));
hr = HrAddCard(pnccNetComponent,
pszNetCardTcpipBindPath,
pszInterfaceName);
if (SUCCEEDED(hr))
{
GUID guidNetCard;
hr = pnccNetComponent->GetInstanceGuid(&guidNetCard);
if (SUCCEEDED(hr))
{
// Is the binding enabled?
hr = pncbp->IsEnabled();
// hr == S_OK if the card is enabled (ie: bound)
if (S_OK == hr)
{ // bind the card in our data strucutres
hr = HrBindCard(&guidNetCard, TRUE);
}
else if (S_FALSE == hr)
{
hr = HrUnBindCard(&guidNetCard, TRUE);
}
}
}
CoTaskMemFree(pszNetCardTcpipBindPath);
}
ReleaseObj(pnccNetComponent);
CoTaskMemFree(pszInterfaceName);
}
ReleaseObj(pncbp);
}
if (S_FALSE == hr) // We just got to the end of the loop
hr = S_OK;
TraceError("CTcpipcfg::HrGetNetCards", hr);
return hr;
}
BOOL CTcpipcfg::IsBindOrderChanged()
{
HRESULT hr = S_OK;
VSTR vstrCurrentBindOrder;
BOOL fChanged = FALSE;
hr = HrLoadBindingOrder(&vstrCurrentBindOrder);
if (SUCCEEDED(hr))
{
fChanged = !fIsSameVstr(vstrCurrentBindOrder, m_vstrBindOrder);
FreeCollectionAndItem(vstrCurrentBindOrder);
}
return fChanged;
}
HRESULT CTcpipcfg::HrLoadBindingOrder(VSTR *pvstrBindOrder)
{
Assert(pvstrBindOrder);
HRESULT hr = S_OK;
CIterNetCfgBindingPath ncbpIter(m_pnccTcpip);
INetCfgBindingPath * pncbp;
INetCfgComponent * pnccLast;
while (SUCCEEDED(hr) && S_OK == (hr = ncbpIter.HrNext(&pncbp)))
{
hr = HrGetLastComponentAndInterface(pncbp, &pnccLast, NULL);
if (SUCCEEDED(hr))
{
Assert(pnccLast);
// The last component should be of NET CLASS
GUID guidClass;
hr = pnccLast->GetClassGuid(&guidClass);
if (SUCCEEDED(hr) && IsEqualGUID(guidClass, GUID_DEVCLASS_NET))
{
PWSTR pszNetCardTcpipBindPath;
hr = pnccLast->GetBindName(&pszNetCardTcpipBindPath);
AssertSz(SUCCEEDED(hr),
"Net card on binding path with no bind path name!!");
if (SUCCEEDED(hr))
{
pvstrBindOrder->push_back(new tstring(pszNetCardTcpipBindPath));
CoTaskMemFree(pszNetCardTcpipBindPath);
}
}
ReleaseObj(pnccLast);
}
ReleaseObj(pncbp);
}
if (S_FALSE == hr) // We just got to the end of the loop
{
hr = S_OK;
}
//if failed, clean up what we added
if (FAILED(hr))
{
FreeCollectionAndItem(*pvstrBindOrder);
}
TraceError("CBindingsDlg::HrGetBindOrder", hr);
return hr;
}
// Called by CTcpipcfg::CancelProperties and CTcpipcfg::ApplyProperties
// Release second memory state
void CTcpipcfg::ExitProperties()
{
delete m_pSecondMemoryAdapterInfo;
m_pSecondMemoryAdapterInfo = NULL;
}
// Called by CTcpipcfg's destructor
// Release all memory states
void CTcpipcfg::FinalFree()
{
FreeCollectionAndItem(m_vcardAdapterInfo);
FreeCollectionAndItem(m_vstrBindOrder);
delete m_pSecondMemoryAdapterInfo;
delete m_ipaddr;
DeleteObject(g_hiconUpArrow);
DeleteObject(g_hiconDownArrow);
ReleaseObj(m_pnc);
ReleaseObj(m_pTcpipPrivate);
ReleaseObj(m_pnccTcpip);
ReleaseObj(m_pnccWins);
// Just a safty check to make sure the context is released.
AssertSz((m_pUnkContext == NULL), "Why is context not released ?");
ReleaseObj(m_pUnkContext) ;
}
// Called by CTcpipcfg::HrSetupPropSheets
// Creates the second memory adapter info from the first
// memory structure
// Note: Bound cards only
HRESULT CTcpipcfg::HrLoadAdapterInfo()
{
HRESULT hr = HRESULT_FROM_WIN32(ERROR_NO_MATCH);
delete m_pSecondMemoryAdapterInfo;
m_pSecondMemoryAdapterInfo = NULL;
ADAPTER_INFO* pAdapter = PAdapterFromInstanceGuid(&m_guidCurrentConnection);
if (pAdapter)
{
// enabled LAN adapter or any RAS Fake adapter
if ((pAdapter->m_BindingState == BINDING_ENABLE) ||
pAdapter->m_fIsRasFakeAdapter)
{
m_pSecondMemoryAdapterInfo = new ADAPTER_INFO;
if (NULL == m_pSecondMemoryAdapterInfo)
{
hr = E_OUTOFMEMORY;
}
else
{
*m_pSecondMemoryAdapterInfo = *pAdapter;
hr = S_OK;
}
}
}
AssertSz((S_OK == hr), "Can not raise UI on a disabled or non-exist adapter !");
TraceError("CTcpipcfg::HrLoadAdapterInfo", hr);
return hr;
}
// Called by CTcpipcfg::ApplyProperties
// Saves the second memory state back into the first
HRESULT CTcpipcfg::HrSaveAdapterInfo()
{
HRESULT hr = HRESULT_FROM_WIN32(ERROR_NO_MATCH);
ADAPTER_INFO* pAdapter = PAdapterFromInstanceGuid(
&m_pSecondMemoryAdapterInfo->m_guidInstanceId);
if (pAdapter)
{
#ifdef DBG
// The card can not get unbound while in tcpip's properties UI!
if (!pAdapter->m_fIsRasFakeAdapter)
{
Assert(pAdapter->m_BindingState == BINDING_ENABLE);
Assert(m_pSecondMemoryAdapterInfo->m_BindingState == BINDING_ENABLE);
}
#endif
*pAdapter = *m_pSecondMemoryAdapterInfo;
hr = S_OK;
}
AssertSz((S_OK == hr),
"Adapter in second memory not found in first memory!");
TraceError("CTcpipcfg::HrSaveAdapterInfo", hr);
return hr;
}
// Called by CTcpipcfg::MergePropPages
// Set the context in which the UI is brought up
HRESULT CTcpipcfg::HrSetConnectionContext()
{
AssertSz(m_pUnkContext, "Invalid IUnknown pointer passed to CTcpipcfg::SetContext?");
if (!m_pUnkContext)
{
return E_UNEXPECTED;
}
// Is this a lan connection ?
GUID guidConn;
INetLanConnectionUiInfo * pLanConnUiInfo;
HRESULT hr = m_pUnkContext->QueryInterface( IID_INetLanConnectionUiInfo,
reinterpret_cast<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;
}
else if (0 == lstrcmpW(pszInterfaceName, c_szBiNdis1394))
{
pAdapter->m_fIs1394Adapter = TRUE;
}
}
if (fFreeDescription)
{
CoTaskMemFree(pszDescription);
}
CoTaskMemFree(pszNetCardBindName);
}
TraceError("CTcpipcfg::HrAddCard", hr);
return hr;
}
//HrBindCard sets the state of a netcard in the list of installed
// netcards to BOUND
//
// Note: fInitialize is only TRUE when this is called from Initialize,
// the default is FALSE.
//
HRESULT CTcpipcfg::HrBindCard(const GUID* pguid, BOOL fInitialize)
{
ADAPTER_INFO* pAdapter = PAdapterFromInstanceGuid(pguid);
if (pAdapter)
{
AssertSz(pAdapter->m_BindingState != BINDING_ENABLE,
"the same netcard was bound twice to TCPIP");
// Set binding state
pAdapter->m_BindingState = BINDING_ENABLE;
if (fInitialize)
pAdapter->m_InitialBindingState = BINDING_ENABLE;
}
else
{
AssertSz(FALSE, "Attempt to bind a card which wasn't installed");
}
return S_OK;
}
//HrUnBindCard sets the state of a netcard in the list of installed
// netcards to UNBOUND
//
// Note: fInitialize is only TRUE when this is called from Initialize,
// the default is FALSE.
//
HRESULT CTcpipcfg::HrUnBindCard(const GUID* pguid, BOOL fInitialize)
{
ADAPTER_INFO* pAdapter = PAdapterFromInstanceGuid(pguid);
if (pAdapter)
{
AssertSz(pAdapter->m_BindingState != BINDING_DISABLE,
"attempt to unbind an unbound card");
// Set binding state to disable
pAdapter->m_BindingState = BINDING_DISABLE;
if (fInitialize)
pAdapter->m_InitialBindingState = BINDING_DISABLE;
}
else
{
AssertSz(FALSE, "Attempt to unbind a card which wasn't installed");
}
return S_OK;
}
// HrDeleteCard
// Deletes a card from the list of cards installed in the system
//
HRESULT CTcpipcfg::HrDeleteCard(const GUID* pguid)
{
ADAPTER_INFO* pAdapter = PAdapterFromInstanceGuid(pguid);
if (pAdapter)
{
pAdapter->m_fDeleted = TRUE;
}
else
{
AssertSz(FALSE, "A delete attempt was made on a card which doesn't exist");
}
return S_OK;
}
//Function to get the list of cards which have been added to the system
//hkeyTcpipParam "Services\Tcpip\Parameters"
HRESULT CTcpipcfg::MarkNewlyAddedCards(const HKEY hkeyTcpipParam)
{
//(08/19/98 nsun) changed from Tcpip\Parameters\Interfaces to Tcpip\Parameters\Adapters key
// to support multiple interfaces
HKEY hkeyAdapters;
HRESULT hr = HrRegOpenKeyEx(hkeyTcpipParam,
c_szAdaptersRegKey,
KEY_READ, &hkeyAdapters);
if (SUCCEEDED(hr))
{
VSTR vstrAdaptersInRegistry;
Assert(vstrAdaptersInRegistry.empty());
// Get the list of keys
hr = HrLoadSubkeysFromRegistry(hkeyAdapters,
&vstrAdaptersInRegistry);
if (SUCCEEDED(hr))
{
//Go through the list of cards we currently have
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin();
iterAdapter != m_vcardAdapterInfo.end();
iterAdapter++)
{
ADAPTER_INFO* pAdapter = *iterAdapter;
BOOL fAdded = TRUE;
// If we have a card in the list which isn't in registry
// then we add that card to the list of added cards
for(VSTR_CONST_ITER iter = vstrAdaptersInRegistry.begin();
iter != vstrAdaptersInRegistry.end() ; ++iter)
{
if (lstrcmpiW((**iter).c_str(), pAdapter->m_strBindName.c_str()) == 0)
{
fAdded = FALSE;
break;
}
}
// if the card is new then mark it
if (fAdded)
{
pAdapter->m_fNewlyChanged = TRUE;
}
}
FreeCollectionAndItem(vstrAdaptersInRegistry);
}
RegCloseKey(hkeyAdapters);
}
else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
{
TraceTag(ttidTcpip, "No existing card found.");
hr = S_OK;
}
TraceError("CTcpipcfg::MarkNewlyAddedCards", hr);
return hr;
}
//+------------------------------------------------------------------------------
//
// Function: HrLoadSettings, HrLoadTcpipRegistry, HrLoadWinsRegistry
//
// HrSaveSettings, HrSaveTcpipRegistry, HrSaveTcpipNdisWanRegistry,
// HrSetMisc
//
// Purpose: Functions to Load/Set registry settings and other system info
// during Initialize and Apply time
//
// Author: tongl 5/5/97
//-------------------------------------------------------------------------------
// Called by CTcpipcfg::Initialize
// Load registry settings for a list of net cards
HRESULT CTcpipcfg::HrLoadSettings()
{
HKEY hkey = NULL;
// Load Tcpip's parameters
HRESULT hrTcpip = S_OK;
hrTcpip = m_pnccTcpip->OpenParamKey(&hkey);
if (hrTcpip == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
hrTcpip = S_OK;
else if (SUCCEEDED(hrTcpip))
{
Assert(hkey);
hrTcpip = HrLoadTcpipRegistry(hkey);
RegCloseKey(hkey);
}
else
Assert(!hkey);
// Load NetBt's parameters
HRESULT hrWins = S_OK;
if (m_pnccWins)
{ // If Wins is not installed don't get WINS information
hkey = NULL;
hrWins = m_pnccWins->OpenParamKey(&hkey);
if (hrWins == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
hrWins = S_OK;
else if (SUCCEEDED(hrWins))
{
Assert(hkey);
hrWins = HrLoadWinsRegistry(hkey);
RegCloseKey(hkey);
}
else
Assert(!hkey);
}
HRESULT hr = S_OK;
hr = SUCCEEDED(hrTcpip) ? hr : hrTcpip;
hr = SUCCEEDED(hrWins) ? hr : hrWins;
TraceError("CTcpipcfg::HrLoadSettings", hr);
return hr;
}
// Called by CTcpipcfg::HrLoadSettings
// Loads all information under the Services\Tcpip\Parameters registry key
//
// const HKEY hkeyTcpipParam : Handle to Services\Tcpip\Parameters
HRESULT CTcpipcfg::HrLoadTcpipRegistry(const HKEY hkeyTcpipParam)
{
HRESULT hr = S_OK;
HRESULT hrTmp = S_OK;
Assert(hkeyTcpipParam);
// Load global parameters
// DNS server
// For bug #147476: in NT5 upgrades, somehow the
// global DNS server list is deleted, but not until after initialize exits
// So I'm reading in the value here if it exists
// DNS server list moved from global to per adapter
hrTmp = HrRegQueryString(hkeyTcpipParam, RGAS_NAMESERVER, &m_strDnsServerList);
tstring strDnsSuffixList;
if FAILED(hrTmp = HrRegQueryString(hkeyTcpipParam, c_szSearchList,
&strDnsSuffixList))
{
TraceTag(ttidTcpip, "CTcpipcfg::HrLoadTcpipRegistry");
TraceTag(ttidTcpip, "Failed on loading SearchList, hr: %x", hr);
hr = S_OK;
}
else
{
ConvertStringToColString(strDnsSuffixList.c_str(),
c_chListSeparator,
m_glbGlobalInfo.m_vstrDnsSuffixList);
}
m_glbGlobalInfo.m_fUseDomainNameDevolution =
FRegQueryBool(hkeyTcpipParam,
c_szUseDomainNameDevolution,
m_glbGlobalInfo.m_fUseDomainNameDevolution);
m_glbGlobalInfo.m_fEnableRouter = FRegQueryBool(hkeyTcpipParam, c_szIpEnableRouter,
m_glbGlobalInfo.m_fEnableRouter);
//(nsun 11/02/98) gloabl RRAS settings
m_glbGlobalInfo.m_fEnableIcmpRedirect = FRegQueryBool(hkeyTcpipParam,
c_szEnableICMPRedirect,
m_glbGlobalInfo.m_fEnableIcmpRedirect);
//PerformRouterDiscoveryDefault was removed to fix bug 405636
m_glbGlobalInfo.m_fDeadGWDetectDefault = FRegQueryBool(hkeyTcpipParam,
c_szDeadGWDetectDefault,
m_glbGlobalInfo.m_fDeadGWDetectDefault);
m_glbGlobalInfo.m_fDontAddDefaultGatewayDefault = FRegQueryBool(hkeyTcpipParam,
c_szDontAddDefaultGatewayDefault,
m_glbGlobalInfo.m_fDontAddDefaultGatewayDefault);
m_glbGlobalInfo.m_fEnableFiltering = FRegQueryBool(hkeyTcpipParam,
RGAS_SECURITY_ENABLE,
m_glbGlobalInfo.m_fEnableFiltering);
// Save old values
m_glbGlobalInfo.ResetOldValues();
// (08/18/98 nsun) read multiple interface settings for WAN adapters
// Open CCS\Services\Tcpip\Parameters\Adapters key
HKEY hkeyAdapters;
hr = HrRegOpenKeyEx(hkeyTcpipParam, c_szAdaptersRegKey, KEY_READ,
&hkeyAdapters);
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) // no adapters key
hr = S_OK;
else if (SUCCEEDED(hr))
{
for(VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin();
iterAdapter != m_vcardAdapterInfo.end() && SUCCEEDED(hr) ;
iterAdapter ++)
{
//multiple interface only valid for WAN adapters
if (!((*iterAdapter)->m_fIsWanAdapter))
continue;
ADAPTER_INFO * pAdapter = *iterAdapter;
HKEY hkeyAdapterParam;
hr = HrRegOpenKeyEx(hkeyAdapters,
pAdapter->m_strBindName.c_str(),
KEY_READ,
&hkeyAdapterParam);
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
{
Assert("No registry settings for a WAN adapter on the "
"bind path?!");
TraceTag(ttidTcpip, "CTcpipcfg::HrLoadTcpipRegistry");
TraceTag(ttidTcpip, "No registry settings for a WAN adapter "
"on the bind path, set to defaults");
// We just use the default values
hr = S_OK;
}
else if (SUCCEEDED(hr))
{
TraceTag(ttidTcpip, "CTcpipcfg::HrLoadTcpipRegistry");
TraceTag(ttidTcpip, "Loading multiple interface parameters "
"for Adapter '%S'", pAdapter->m_strBindName.c_str());
DWORD dwNumInterfaces;
hr = HrRegQueryDword(hkeyAdapterParam,
RGAS_NUMINTERFACES,
&dwNumInterfaces);
if (FAILED(hr))
{
// the Wan adapter is NOT in mode of supporting multiple
// interfaces
TraceTag(ttidTcpip, "No mutliple interface for the WAN "
"adapter '%S'", pAdapter->m_strBindName.c_str());
pAdapter->m_fIsMultipleIfaceMode = FALSE;
hr = S_OK;
}
else
{
pAdapter->m_fIsMultipleIfaceMode = TRUE;
// the WAN adapter supports multiple interface but not
// interface is defined yet
//
if (0 != dwNumInterfaces)
{
GUID* aguidIds;
DWORD cb;
hr = HrRegQueryBinaryWithAlloc(hkeyAdapterParam,
RGAS_IPINTERFACES,
(LPBYTE*)&aguidIds,
&cb);
if (FAILED(hr))
{
AssertSz(FALSE, "NumInterfaces and IpInterfaces "
"values conflicts");
// the Wan adapter is NOT in mode of supporting
// multiple interfaces
//
TraceTag(ttidTcpip, "NumInterfaces and IpInterfaces "
"values conflicts for the WAN adapter '%S'",
pAdapter->m_strBindName.c_str());
hr = S_OK;
}
else if (NULL != aguidIds)
{
dwNumInterfaces = cb / sizeof(GUID);
for(DWORD i = 0; i < dwNumInterfaces; i++)
{
pAdapter->m_IfaceIds.push_back(aguidIds[i]);
}
MemFree(aguidIds);
}
}
}
RegCloseKey(hkeyAdapterParam);
}
}
RegCloseKey(hkeyAdapters);
}
// Get per adapter parameters
// Open CCS\Services\Tcpip\Parameters\Interfaces key
HKEY hkeyInterfaces;
hr = HrRegOpenKeyEx(hkeyTcpipParam, c_szInterfacesRegKey, KEY_READ,
&hkeyInterfaces);
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) //no adapter interfaces
hr = S_OK;
else if (SUCCEEDED(hr))
{
// Get all the subkeys currently in registry
for(VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin();
iterAdapter != m_vcardAdapterInfo.end() && SUCCEEDED(hr) ;
iterAdapter ++)
{
ADAPTER_INFO * pAdapter = *iterAdapter;
if (pAdapter->m_fIsWanAdapter)
{
continue;
}
HKEY hkeyInterfaceParam;
// Open CCS\Services\Tcpip\Parameters\Interfaces\<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(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;
}
else if (pAdapter->m_fIs1394Adapter)
{
pszArpModule = c_sz1394Arp;
}
hrTmp = HrRegSetSz(hkeyAdapterParam,
RGAS_LLINTERFACE,
pszArpModule);
if (SUCCEEDED(hr))
hr = hrTmp;
// (08/18/98 nsun) modified to support multiple interfaces of WAN adapter
VSTR vstrIpConfig;
if (!pAdapter->m_fIsMultipleIfaceMode)
{
HrRegDeleteValue(hkeyAdapterParam, RGAS_NUMINTERFACES);
tstring* pstr = new tstring(RGAS_TCPIP_PARAM_INTERFACES);
if (pstr == NULL)
{
return(E_OUTOFMEMORY);
}
pstr->append(pAdapter->m_strTcpipBindPath);
vstrIpConfig.push_back(pstr);
hrTmp = HrRegSetColString(hkeyAdapterParam,
RGAS_IPCONFIG,
vstrIpConfig);
}
else
{
AssertSz(pAdapter->m_fIsWanAdapter, "The card is not WAN adapter, but how can it support multiple interface.");
tstring strInterfaceName;
IFACEITER iterId;
for(iterId = pAdapter->m_IfaceIds.begin();
iterId != pAdapter->m_IfaceIds.end();
iterId++)
{
GetInterfaceName(
pAdapter->m_strTcpipBindPath.c_str(),
*iterId,
&strInterfaceName);
tstring* pstr = new tstring(RGAS_TCPIP_PARAM_INTERFACES);
pstr->append(strInterfaceName);
vstrIpConfig.push_back(pstr);
}
hrTmp = HrRegSetColString(hkeyAdapterParam,
RGAS_IPCONFIG,
vstrIpConfig);
if (SUCCEEDED(hr))
hr = hrTmp;
//$REVIEW (nsun 09/15/98) use NumInterfaces value to identify if the adapter is in the
//mode of supporting multiple interfaces. If the NumInterfaces
//exists, the adapter supports multiple interfaces.
//If NumInterfaces == 0, it means the adapter supports multiple interfaces
// but no interface is associated with it. So the IpInterfaces should not
// exists. The NumInterfaces and IpInterfaces should alwasy be consistent.
DWORD dwNumInterfaces = pAdapter->m_IfaceIds.size();
hrTmp = HrRegSetDword(hkeyAdapterParam,
RGAS_NUMINTERFACES,
dwNumInterfaces);
if (SUCCEEDED(hr))
hr = hrTmp;
if ( 0 != dwNumInterfaces )
{
GUID* aguid;
DWORD cguid;
hrTmp = GetGuidArrayFromIfaceColWithCoTaskMemAlloc(
pAdapter->m_IfaceIds,
&aguid,
&cguid);
if (SUCCEEDED(hr))
hr = hrTmp;
Assert(aguid);
hrTmp = HrRegSetBinary(hkeyAdapterParam,
RGAS_IPINTERFACES,
(BYTE*) aguid,
cguid * sizeof(GUID));
CoTaskMemFree(aguid);
}
else
{
hrTmp = HrRegDeleteValue(hkeyAdapterParam, RGAS_IPINTERFACES);
//It's fine that the IpInterfaces does not exist at all if
// the WAN adapter does not support multiple interfaces.
if (hrTmp == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
hrTmp = S_OK;
}
}
FreeCollectionAndItem(vstrIpConfig);
if (SUCCEEDED(hr))
hr = hrTmp;
}
RegCloseKey(hkeyAdapterParam);
}
}
RegCloseKey(hkeyAdapters);
}
else if (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hrTmp)
{
//for netcfg operators, we will get access denied error when opening this key
//however, it's ok because we don't need to touch the key when just updating the IP settings
hrTmp = S_OK;
}
if (SUCCEEDED(hr))
hr = hrTmp;
// Create or open the "Interfaces" key under "Services\Tcpip\Parameters"
//
HKEY hkeyInterfaces;
hrTmp = HrRegCreateKeyEx(hkeyTcpipParam, c_szInterfacesRegKey,
REG_OPTION_NON_VOLATILE, KEY_READ_WRITE_DELETE, NULL,
&hkeyInterfaces, &dwDisposition);
if (SUCCEEDED(hr))
hr = hrTmp;
if (SUCCEEDED(hrTmp))
{
Assert(hkeyInterfaces);
for(VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin();
iterAdapter != m_vcardAdapterInfo.end();
iterAdapter ++)
{
if ((*iterAdapter)->m_fIsRasFakeAdapter)
{
continue;
}
ADAPTER_INFO * pAdapter = *iterAdapter;
//(08/20/98 nsun) modified to support multiple interfaces of WAN adapter
// NULL != pAdapter->m_IfaceIds means it's in multiple interface mode
if (pAdapter->m_fIsWanAdapter && pAdapter->m_fIsMultipleIfaceMode)
{
if (pAdapter->m_fNewlyChanged)
{
HrSaveMultipleInterfaceWanRegistry(hkeyInterfaces, pAdapter);
}
continue;
}
// Create specific card interface key under
// "Services\Tcpip\Parameters\Interfaces\<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);
}
else if (pAdapter->m_fIs1394Adapter)
{
// For new NIC1394 cards
// (nothing to do).
hrTmp = S_OK;
}
else
{
//(nsun 11/02/98) set static RRAS parameters for unattended install
//if the values exists, that means they have been set as an unconfigurable
//parameter during upgrade,
//we should not set the default value.
DWORD dwTmp;
hrTmp = HrRegQueryDword(hkeyInterfaceParam,
c_szDeadGWDetect,
&dwTmp);
if (FAILED(hrTmp))
{
hrTmp = HrRegSetBool(hkeyInterfaceParam,
c_szDeadGWDetect,
m_glbGlobalInfo.m_fDeadGWDetectDefault);
}
}
if (SUCCEEDED(hr))
hr = hrTmp;
}
// For LAN cards and RAS fake guids
if (!pAdapter->m_fIsWanAdapter)
{
// Ip address etc
hrTmp = HrRegSetBool(hkeyInterfaceParam,
RGAS_ENABLE_DHCP,
pAdapter->m_fEnableDhcp);
if (SUCCEEDED(hr))
hr = hrTmp;
//warning: these VSTRs will contain pointers to strings
//that are either local to this function or
//that are also pointed to in another VSTR
// DO NOT call FreeCollectionAndItem on them!
VSTR vstrIpAddresses;
VSTR vstrSubnetMask;
tstring ZeroAddress(ZERO_ADDRESS);
if (pAdapter->m_fEnableDhcp)
{
vstrIpAddresses.push_back(&ZeroAddress);
vstrSubnetMask.push_back(&ZeroAddress);
}
else
{
vstrIpAddresses = pAdapter->m_vstrIpAddresses;
vstrSubnetMask = pAdapter->m_vstrSubnetMask;
}
hrTmp = HrRegSetColString(hkeyInterfaceParam,
RGAS_IPADDRESS,
vstrIpAddresses);
if (SUCCEEDED(hr))
hr = hrTmp;
hrTmp = HrRegSetColString(hkeyInterfaceParam,
RGAS_SUBNETMASK,
vstrSubnetMask);
if (SUCCEEDED(hr))
hr = hrTmp;
hrTmp = HrRegSetColString(hkeyInterfaceParam,
RGAS_DEFAULTGATEWAY,
pAdapter->m_vstrDefaultGateway);
if (SUCCEEDED(hr))
hr = hrTmp;
hrTmp = HrRegSetColString(hkeyInterfaceParam,
RGAS_DEFAULTGATEWAYMETRIC,
pAdapter->m_vstrDefaultGatewayMetric);
if (SUCCEEDED(hr))
hr = hrTmp;
// DNS name server list
tstring strNameServer;
ConvertColStringToString(pAdapter->m_vstrDnsServerList,
c_chListSeparator,
strNameServer);
hrTmp = HrRegSetString(hkeyInterfaceParam,
RGAS_NAMESERVER,
strNameServer);
if (SUCCEEDED(hr))
hr = hrTmp;
// DNS domain
hrTmp = HrRegSetString(hkeyInterfaceParam,
RGAS_DOMAIN,
pAdapter->m_strDnsDomain);
if (SUCCEEDED(hr))
hr = hrTmp;
// Dns ip address dynamic update
if (pAdapter->m_fDisableDynamicUpdate)
{
DnsDisableDynamicRegistration(
(LPWSTR)pAdapter->m_strTcpipBindPath.c_str());
}
else
{
DnsEnableDynamicRegistration(
(LPWSTR)pAdapter->m_strTcpipBindPath.c_str());
}
// adapter Dns domain name registration
if (pAdapter->m_fEnableNameRegistration)
{
DnsEnableAdapterDomainNameRegistration(
(LPWSTR)pAdapter->m_strTcpipBindPath.c_str());
}
else
{
DnsDisableAdapterDomainNameRegistration(
(LPWSTR)pAdapter->m_strTcpipBindPath.c_str());
}
// InterfaceMetric
if (c_dwDefaultIfMetric != pAdapter->m_dwInterfaceMetric)
{
hrTmp = HrRegSetDword(hkeyInterfaceParam,
c_szInterfaceMetric,
pAdapter->m_dwInterfaceMetric);
}
else
{
//The interface metric is default, remove that value.
//In such way, it would be much easier to upgrade if the default is changed
//in the future
hrTmp = HrRegDeleteValue(hkeyInterfaceParam,
c_szInterfaceMetric);
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hrTmp)
hrTmp = S_OK;
}
if (SUCCEEDED(hr))
hr = hrTmp;
// TCPAllowedPorts
hrTmp = HrRegSetColString(hkeyInterfaceParam,
RGAS_FILTERING_TCP,
pAdapter->m_vstrTcpFilterList);
if (SUCCEEDED(hr))
hr = hrTmp;
// UDPAllowedPorts
hrTmp = HrRegSetColString(hkeyInterfaceParam,
RGAS_FILTERING_UDP,
pAdapter->m_vstrUdpFilterList);
if (SUCCEEDED(hr))
hr = hrTmp;
// IPAllowedPorts
hrTmp = HrRegSetColString(hkeyInterfaceParam,
RGAS_FILTERING_IP,
pAdapter->m_vstrIpFilterList);
if (SUCCEEDED(hr))
hr = hrTmp;
// For ATM cards only
if (pAdapter->m_fIsAtmAdapter)
{
HKEY hkeyAtmarpc;
// Open the Atmarpc subkey
hrTmp = HrRegCreateKeyEx(hkeyInterfaceParam,
c_szAtmarpc,
REG_OPTION_NON_VOLATILE,
KEY_READ_WRITE,
NULL,
&hkeyAtmarpc,
&dwDisposition);
if (SUCCEEDED(hrTmp))
{
hrTmp = HrRegSetColString(hkeyAtmarpc,
c_szREG_ARPServerList,
pAdapter->m_vstrARPServerList);
if (SUCCEEDED(hr))
hr = hrTmp;
hrTmp = HrRegSetColString(hkeyAtmarpc,
c_szREG_MARServerList,
pAdapter->m_vstrMARServerList);
if (SUCCEEDED(hr))
hr = hrTmp;
hrTmp = HrRegSetDword(hkeyAtmarpc,
c_szREG_MTU,
pAdapter->m_dwMTU);
if (SUCCEEDED(hr))
hr = hrTmp;
hrTmp = HrRegSetBool(hkeyAtmarpc,
c_szREG_PVCOnly,
pAdapter->m_fPVCOnly);
if (SUCCEEDED(hr))
hr = hrTmp;
RegCloseKey(hkeyAtmarpc);
}
}
hrTmp = HrDuplicateToNT4Location(hkeyInterfaceParam,
pAdapter);
if (SUCCEEDED(hr))
hr = hrTmp;
hrTmp = HrSaveBackupTcpSettings(hkeyInterfaceParam,
pAdapter);
if (SUCCEEDED(hr))
hr = hrTmp;
} // For LAN cards and RAS fake guids only
RegCloseKey(hkeyInterfaceParam);
}
}
RegCloseKey(hkeyInterfaces);
}
TraceError("CTcpipcfg::HrSaveTcpipRegistry", hr);
return hr;
}
HRESULT CTcpipcfg::HrSaveWinsRegistry(const HKEY hkeyWinsParam)
{
// hr is the first error occurred,
// but we don't want to stop at the first error
HRESULT hr = S_OK;
HRESULT hrTmp = S_OK;
// Global parameters
hrTmp = HrRegSetBool(hkeyWinsParam,
RGAS_ENABLE_LMHOSTS,
m_glbGlobalInfo.m_fEnableLmHosts);
if (SUCCEEDED(hr))
hr = hrTmp;
/*$REVIEW (nsun 2/17/98) Bug #293643 We don't want to change any unconfigurable values
// $REVIEW(tongl 8/3/97): Added NodeType settings #97364.
// If no adapter has static WINS address, then remove NodeType.
// otherwise, the user has specified the WINs server address for
// at least one adapters, set NodeType = 0x08 (H-NODE)
BOOL fNoWinsAddress = TRUE;
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin();
iterAdapter != m_vcardAdapterInfo.end();
iterAdapter++)
{
ADAPTER_INFO * pAdapter = *iterAdapter;
if ((!pAdapter->m_fIsWanAdapter)&&
(BINDING_ENABLE == pAdapter->m_BindingState)&&
(pAdapter->m_vstrWinsServerList.size()>0))
{
fNoWinsAddress = FALSE;
}
}
DWORD dwNodeType;
hrTmp = HrRegQueryDword(hkeyWinsParam,
c_szNodeType,
&dwNodeType);
// dwNodeType ==0 means the key did not exist before we apply
if (hrTmp == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
dwNodeType =0;
if (!m_fAnswerFileBasedInstall ||
(hrTmp == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)))
{
if (!fNoWinsAddress) // set NodeType to 0x08
{
if (dwNodeType != c_dwHNode)
{
hrTmp = HrRegSetDword(hkeyWinsParam,
c_szNodeType,
c_dwHNode);
if (SUCCEEDED(hr))
hr = hrTmp;
}
}
else // remove NodeType key
{
if (dwNodeType != 0)
{
hrTmp = HrRegDeleteValue(hkeyWinsParam,
c_szNodeType);
if (SUCCEEDED(hr))
hr = hrTmp;
}
}
}
*/
// $REVIEW(tongl 12\1\97): Per agreement with Malam today(see email),
// NetBt will re-read NodeType when notified of wins address list change.
// Thus no need to notify change separately below.
/*
if (fNodeTypeChanged)
{
// Send notification to NetBt
TraceTag(ttidTcpip,"NodeType parameter changed, send notification on apply.");
SetReconfig();
// SetReconfigNbt();
}
*/
// Adapter interface specific parameters
// Create the "Services\NetBt\Interfacess" key
HKEY hkeyInterfaces;
DWORD dwDisposition;
hrTmp = HrRegCreateKeyEx(hkeyWinsParam, c_szInterfacesRegKey,
REG_OPTION_NON_VOLATILE, KEY_READ_WRITE, NULL,
&hkeyInterfaces, &dwDisposition);
if (SUCCEEDED(hr))
hr = hrTmp;
if (SUCCEEDED(hrTmp))
{
for(VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin();
iterAdapter != m_vcardAdapterInfo.end();
iterAdapter++)
{
ADAPTER_INFO * pAdapter = *iterAdapter;
//(10/05/98 nsun) modified to support multiple interfaces of WAN adapter
// NULL != pAdapter->m_IfaceIds means it's in multiple interface mode
if (pAdapter->m_fNewlyChanged &&
pAdapter->m_fIsWanAdapter &&
pAdapter->m_fIsMultipleIfaceMode)
{
HrSaveWinsMultipleInterfaceWanRegistry(hkeyInterfaces, pAdapter);
continue;
}
HKEY hkeyInterfaceParam;
hrTmp = HrRegCreateKeyEx(hkeyInterfaces,
pAdapter->m_strNetBtBindPath.c_str(),
REG_OPTION_NON_VOLATILE, KEY_READ_WRITE, NULL,
&hkeyInterfaceParam, &dwDisposition);
if (SUCCEEDED(hr))
hr = hrTmp;
if (SUCCEEDED(hrTmp))
{
// For new RAS cards, only set static values
if (pAdapter->m_fIsWanAdapter && pAdapter->m_fNewlyChanged)
{
hrTmp = HrRegSetMultiSz(hkeyInterfaceParam,
RGAS_NETBT_NAMESERVERLIST,
L"\0");
if (SUCCEEDED(hr))
hr = hrTmp;
}
else // if not RAS adapter
{
// set wins server address list
hrTmp = HrRegSetColString(hkeyInterfaceParam,
RGAS_NETBT_NAMESERVERLIST,
pAdapter->m_vstrWinsServerList);
if (SUCCEEDED(hr))
hr = hrTmp;
// set NetbiosOptions
hrTmp = HrRegSetDword(hkeyInterfaceParam,
RGAS_NETBT_NETBIOSOPTIONS,
pAdapter->m_dwNetbiosOptions);
if (SUCCEEDED(hr))
hr = hrTmp;
}
RegCloseKey(hkeyInterfaceParam);
}
}
RegCloseKey(hkeyInterfaces);
}
TraceError("CTcpipcfg::HrSaveWinsRegistry", hr);
return hr;
}
// Called by CTcpipcfg::SaveSettings
// Does a lot of miscelaneous actions when Apply is called
// Including cleaning up registry and remove isolated cards
//
// HKEY hkeyTcpipParam Serviess\Tcpip\Parameters
// HKEY hkeyWinsParam Services\NetBt\Parameters
HRESULT CTcpipcfg::HrSetMisc(const HKEY hkeyTcpipParam, const HKEY hkeyWinsParam)
{
HRESULT hr = S_OK;
HRESULT hrTmp = S_OK;
// Registry Cleanup !!
// We remove DNS domain and DNS server list in NT5 upgrades
if (m_fUpgradeCleanupDnsKey)
{
hrTmp = HrRegDeleteValue(hkeyTcpipParam, RGAS_NAMESERVER);
// $REVIEW(tongl 3/22/98): Per Stuart Kwan, global DNSDomain key
// is also used.
// hrTmp = HrRegDeleteValue(hkeyTcpipParam, RGAS_DOMAIN);
}
// remove all keys under the "Services\Tcpip\Parameters\Adapters" reg key
// that aren't in the list of net cards.
VSTR vstrNetCardsInTcpipReg;
HKEY hkeyAdapters = NULL;
hrTmp = HrRegOpenKeyEx(hkeyTcpipParam, c_szAdaptersRegKey, KEY_READ,
&hkeyAdapters);
if (SUCCEEDED(hrTmp))
{
hrTmp = HrLoadSubkeysFromRegistry(hkeyAdapters,
&vstrNetCardsInTcpipReg);
}
if (SUCCEEDED(hr))
hr = hrTmp;
if (SUCCEEDED(hr) && vstrNetCardsInTcpipReg.size() > 0)
{
// Step through the names of all the registry keys found
//
for (VSTR_CONST_ITER iter = vstrNetCardsInTcpipReg.begin();
iter != vstrNetCardsInTcpipReg.end();
++iter)
{
// Find out if this particular key is in the list
// of installed Adapters
//
BOOL fFound = FALSE;
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin();
iterAdapter != m_vcardAdapterInfo.end();
iterAdapter++)
{
ADAPTER_INFO* pAdapter = *iterAdapter;
if (lstrcmpiW(pAdapter->m_strBindName.c_str(), (**iter).c_str()) == 0)
{
fFound = TRUE;
break;
}
}
if (!fFound)
{
// if it wasn't in the list of installed adapters
// then delete it
//
if (SUCCEEDED(hrTmp))
hrTmp = HrRegDeleteKeyTree(hkeyAdapters, (*iter)->c_str());
//maybe the key is not there. so we don't check whether this will fail.
HrDeleteBackupSettingsInDhcp((*iter)->c_str());
if (SUCCEEDED(hr))
hr = hrTmp;
}
}
}
FreeCollectionAndItem(vstrNetCardsInTcpipReg);
RegSafeCloseKey(hkeyAdapters);
//we also need to delete the duplicate reg values under Services\{adapter GUID}
HRESULT hrNt4 = S_OK;
HKEY hkeyServices = NULL;
DWORD dwDisposition;
hrNt4 = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegServices,
KEY_READ, &hkeyServices);
if (FAILED(hrNt4))
{
TraceTag(ttidTcpip, "HrSetMisc: Failed to open the Services reg key, hr: %x", hr);
}
// We remove all keys under the "Services\Tcpip\Parameters\Interfaces" reg key
// that aren't in our list of net cards.
VSTR vstrNetCardInterfacesInTcpipReg;
// Get a list of all keys under the "Services\Tcpip\Parameters\Interfaces" key
HKEY hkeyInterfaces = NULL;
hrTmp = HrRegOpenKeyEx(hkeyTcpipParam, c_szInterfacesRegKey, KEY_READ_WRITE_DELETE,
&hkeyInterfaces);
if (SUCCEEDED(hrTmp))
{
hrTmp = HrLoadSubkeysFromRegistry(hkeyInterfaces,
&vstrNetCardInterfacesInTcpipReg);
}
if (SUCCEEDED(hr))
hr = hrTmp;
if (SUCCEEDED(hrTmp) && vstrNetCardInterfacesInTcpipReg.size() > 0 )
{
// step through the names of all the registry keys found
for (VSTR_CONST_ITER iterTcpipReg = vstrNetCardInterfacesInTcpipReg.begin() ;
iterTcpipReg != vstrNetCardInterfacesInTcpipReg.end() ; ++iterTcpipReg)
{
// Find out if this particular key is in the list
// of installed Adapters
BOOL fFound = FALSE;
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin();
iterAdapter != m_vcardAdapterInfo.end();
iterAdapter++)
{
ADAPTER_INFO* pAdapter = *iterAdapter;
//(08/18/98 nsun) special case for WAN adapters with multiple interfaces
if (pAdapter->m_fIsWanAdapter && pAdapter->m_fIsMultipleIfaceMode)
{
IFACEITER iterId;
tstring strInterfaceName;
for(iterId = pAdapter->m_IfaceIds.begin();
iterId != pAdapter->m_IfaceIds.end();
iterId++)
{
GetInterfaceName(
pAdapter->m_strTcpipBindPath.c_str(),
*iterId,
&strInterfaceName);
if (lstrcmpiW(strInterfaceName.c_str(), (**iterTcpipReg).c_str()) == 0)
{
fFound = TRUE;
break;
}
}
if (fFound)
break;
}
else if (lstrcmpiW(pAdapter->m_strTcpipBindPath.c_str(), (**iterTcpipReg).c_str()) == 0)
{
fFound = TRUE;
break;
}
}
// if it wasn't in the list of installed adapters then delete it
if (!fFound)
{
// remove the key
if (SUCCEEDED(hrTmp))
hrTmp = HrRegDeleteKeyTree(hkeyInterfaces, (*iterTcpipReg)->c_str());
if (SUCCEEDED(hr))
hr = hrTmp;
if (SUCCEEDED(hrNt4))
{
hrTmp = HrRegDeleteKeyTree(hkeyServices, (*iterTcpipReg)->c_str());
if (FAILED(hrTmp))
{
TraceTag(ttidTcpip, "CTcpipcfg::SetMisc");
TraceTag(ttidTcpip, "Failed on deleting duplicated Nt4 layout key: Services\\%S, hr: %x",
(*iterTcpipReg)->c_str(), hrTmp);
hrTmp = S_OK;
}
}
}
}
}
RegSafeCloseKey(hkeyInterfaces);
RegSafeCloseKey(hkeyServices);
FreeCollectionAndItem(vstrNetCardInterfacesInTcpipReg);
// Now we remove all keys under the "SERVICES\NetBt\Parameters\Interfaces" reg key
// that aren't in our list of net cards.
VSTR vstrNetCardInterfacesInWinsReg;
// Get a list of all keys under the "Services\NetBt\Parameters\Interfaces" key
HKEY hkeyWinsInterfaces = NULL;
hrTmp = HrRegOpenKeyEx(hkeyWinsParam, c_szInterfacesRegKey, KEY_READ,
&hkeyWinsInterfaces);
// Get a list of all keys under the "SERVICES\NetBt\Parameters\Interfaces" key
hrTmp = HrLoadSubkeysFromRegistry( hkeyWinsInterfaces,
&vstrNetCardInterfacesInWinsReg);
if (SUCCEEDED(hr))
hr = hrTmp;
if (SUCCEEDED(hrTmp) && vstrNetCardInterfacesInWinsReg.size()>0 )
{
// Step through the names of all the registry keys found
for (VSTR_CONST_ITER iterWinsReg = vstrNetCardInterfacesInWinsReg.begin() ;
iterWinsReg != vstrNetCardInterfacesInWinsReg.end() ; ++iterWinsReg)
{
// Find out if this particular key is in the list
// of installed Adapters
BOOL fFound = FALSE;
// All net cards
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin();
iterAdapter != m_vcardAdapterInfo.end();
iterAdapter++)
{
ADAPTER_INFO* pAdapter = *iterAdapter;
//(10/05/98 nsun) special case for WAN adapters with multiple interfaces
if (pAdapter->m_fIsWanAdapter && pAdapter->m_fIsMultipleIfaceMode)
{
IFACEITER iterId;
tstring strNetBtBindPath;
for (iterId = pAdapter->m_IfaceIds.begin();
iterId != pAdapter->m_IfaceIds.end();
iterId++)
{
GetInterfaceName(
pAdapter->m_strNetBtBindPath.c_str(),
*iterId,
&strNetBtBindPath);
strNetBtBindPath.insert(0, c_szTcpip_);
if (lstrcmpiW(strNetBtBindPath.c_str(), (**iterWinsReg).c_str()) == 0)
{
fFound = TRUE;
break;
}
}
if (fFound)
break;
}
else if (lstrcmpiW(pAdapter->m_strNetBtBindPath.c_str(), (**iterWinsReg).c_str()) == 0)
{
fFound = TRUE;
break;
}
}
// if it wasn't in the list of installed adapters then delete it
if (!fFound)
{
hrTmp = HrRegDeleteKeyTree(hkeyWinsInterfaces, (*iterWinsReg)->c_str());
if (SUCCEEDED(hr))
hr = hrTmp;
}
}
}
FreeCollectionAndItem(vstrNetCardInterfacesInWinsReg);
RegSafeCloseKey(hkeyWinsInterfaces);
TraceError("CTcpipcfg::HrSetMisc", hr);
return hr;
}
// CTcpipcfg::HrGetDhcpOptions
//
// Gets the list of netcard dependend and netcard independent
// values to delete when DHCP is disabled. This list is obtained from:
// "Services\DHCP\Parameters\Options\#\RegLocation"
//
// GlobalOptions returns the non-netcard specific reg keys
// PerAdapterOptions returns the netcard specific reg keys
HRESULT CTcpipcfg::HrGetDhcpOptions(OUT VSTR * const GlobalOptions,
OUT VSTR * const PerAdapterOptions)
{
HRESULT hr = S_OK;
HRESULT hrTmp = S_OK;
HKEY hkeyDhcpOptions;
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE,
RGAS_DHCP_OPTIONS,
KEY_ENUMERATE_SUB_KEYS,
&hkeyDhcpOptions);
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
hr = S_OK;
else if (SUCCEEDED(hr))
{
WCHAR szBuf[256];
FILETIME time;
DWORD dwSize = celems(szBuf);
DWORD dwRegIndex = 0;
while(SUCCEEDED(hrTmp = HrRegEnumKeyEx(hkeyDhcpOptions,
dwRegIndex++,
szBuf, &dwSize,
NULL, NULL, &time)))
{
dwSize = celems(szBuf);
HKEY hkeyRegLocation;
hrTmp = HrRegOpenKeyEx(hkeyDhcpOptions, szBuf,
KEY_QUERY_VALUE,
&hkeyRegLocation);
if (hrTmp == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
hrTmp = S_OK;
if (SUCCEEDED(hr))
hr = hrTmp;
if (hkeyRegLocation)
{
tstring strRegLocation;
hrTmp = HrRegQueryString(hkeyRegLocation,
RGAS_REG_LOCATION,
&strRegLocation);
if (hrTmp == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
hrTmp = S_OK;
if (SUCCEEDED(hr))
hr = hrTmp;
if (SUCCEEDED(hrTmp))
{
if (strRegLocation.find(TCH_QUESTION_MARK) == tstring::npos)
{
GlobalOptions->push_back(new tstring(strRegLocation));
}
else
{
PerAdapterOptions->push_back(new tstring(strRegLocation));
}
}
RegCloseKey(hkeyRegLocation);
}
}
if (hrTmp == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS))
hrTmp = S_OK;
if (SUCCEEDED(hr))
hr = hrTmp;
RegCloseKey(hkeyDhcpOptions);
}
// Add default PerAdapterOption
// $REVIEW(tongl 5/11): This is directly from ncpa1.1
// What about DhcpNameServer under NetBt ??
//"System\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\?\\DhcpIPAddress"
PerAdapterOptions->push_back(new tstring(RGAS_DHCP_OPTION_IPADDRESS));
//"System\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\?\\DhcpSubnetMask"
PerAdapterOptions->push_back(new tstring(RGAS_DHCP_OPTION_SUBNETMASK));
//"System\\CurrentControlSet\\Services\\NetBT\\Parameters\\Interfaces\\?\\DhcpNameServerBackup"
PerAdapterOptions->push_back(new tstring(RGAS_DHCP_OPTION_NAMESERVERBACKUP));
TraceError("HrGetDhcpOptions", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: CTcpipcfg::ReconfigIp
//
// Purpose: Notify Tcpip of configuration changes
//
// Arguments: INetCfgPnpReconfigCallback* pICallback
// the call back interface to handle Ndis Pnp reconfig
//
// Returns: HRESULT, S_OK on success, NETCFG_S_REBOOT otherwise
//
HRESULT CTcpipcfg::HrReconfigIp(INetCfgPnpReconfigCallback* pICallback)
{
HRESULT hr = S_OK;
HRESULT hrReconfig = S_OK;
//$$REVIEW bug 329542, we remove the Pnp notification on "EnableSecurityFilters".
//And then global PnP notification to tcp stack is not needed at all.
if (m_glbGlobalInfo.m_fEnableFiltering != m_glbGlobalInfo.m_fOldEnableFiltering)
{
hr = NETCFG_S_REBOOT;
}
IP_PNP_RECONFIG_REQUEST IpReconfigRequest;
ZeroMemory(&IpReconfigRequest, sizeof(IpReconfigRequest));
// DWORD version
IpReconfigRequest.version = IP_PNP_RECONFIG_VERSION;
IpReconfigRequest.arpConfigOffset = 0;
//we are only interested in gateway and interface metric, because other
//parameters cannot be changed from the UI
IpReconfigRequest.Flags = IP_PNP_FLAG_GATEWAY_LIST_UPDATE |
IP_PNP_FLAG_INTERFACE_METRIC_UPDATE ;
// Submit per adapter reconfig notifications
// gatewayListUpdate, filterListUpdate
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin();
iterAdapter != m_vcardAdapterInfo.end();
iterAdapter ++) // for each adapter
{
ADAPTER_INFO * pAdapter = *iterAdapter;
// If not wan adapter or RAS fake guid, and adapter is enabled
if ((!pAdapter->m_fIsWanAdapter) &&
(!pAdapter->m_fIsRasFakeAdapter) &&
(pAdapter->m_BindingState == BINDING_ENABLE) &&
(pAdapter->m_InitialBindingState != BINDING_DISABLE))
{
// gateway list
IpReconfigRequest.gatewayListUpdate =
!fIsSameVstr(pAdapter->m_vstrDefaultGateway,
pAdapter->m_vstrOldDefaultGateway) ||
!fIsSameVstr(pAdapter->m_vstrDefaultGatewayMetric,
pAdapter->m_vstrOldDefaultGatewayMetric);
IpReconfigRequest.InterfaceMetricUpdate =
!!(pAdapter->m_dwInterfaceMetric !=
pAdapter->m_dwOldInterfaceMetric);
if ((IpReconfigRequest.gatewayListUpdate) ||
(IpReconfigRequest.InterfaceMetricUpdate))
{
TraceTag(ttidTcpip, "Sending notification to Tcpip about parameter changes for adapter %S.", pAdapter->m_strBindName.c_str());
TraceTag(ttidTcpip, "Gateway list update: %d", IpReconfigRequest.gatewayListUpdate);
TraceTag(ttidTcpip, "Interface metric update: %d", IpReconfigRequest.InterfaceMetricUpdate);
hrReconfig = pICallback->SendPnpReconfig(NCRL_NDIS, c_szTcpip,
pAdapter->m_strTcpipBindPath.c_str(),
&IpReconfigRequest,
sizeof(IP_PNP_RECONFIG_REQUEST));
//we dont want to request reboot if the error is ERROR_FILE_NOT_FOUND
//because that means the card is not loaded by the stack yet. Usually this is
//because the card was disabled from the connection UI. When the card is re-enabled,
//the statck will reload the card and load all settings from the registry. So a reboot
//is not needed
if (FAILED(hrReconfig) &&
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hrReconfig)
{
TraceTag(ttidTcpip,"Notifying tcpip of adapter specific parameter change returns failure, prompt for reboot ...");
hr = NETCFG_S_REBOOT;
}
}
// if ATM adapter, notify atmarp if any parameter has changed
if (pAdapter->m_fIsAtmAdapter)
{
hrReconfig = HrReconfigAtmArp(pAdapter, pICallback);
if (hrReconfig != S_OK)
{
TraceTag(ttidTcpip,"Notifying tcpip of ATM ARP cleint of parameter change returns failure, prompt for reboot ...");
hr = NETCFG_S_REBOOT;
}
}
else if (pAdapter->m_fIs1394Adapter)
{
// $REVIEW JosephJ: I don't think we need to do
// anything here, because we have no parameters to
// change.
}
// ask for reboot if filter list has changed
if (m_glbGlobalInfo.m_fEnableFiltering)
{
if (!fIsSameVstr(pAdapter->m_vstrTcpFilterList, pAdapter->m_vstrOldTcpFilterList) ||
!fIsSameVstr(pAdapter->m_vstrUdpFilterList, pAdapter->m_vstrOldUdpFilterList) ||
!fIsSameVstr(pAdapter->m_vstrIpFilterList, pAdapter->m_vstrOldIpFilterList))
{
TraceTag(ttidTcpip, "This is temporary, filter list changed, ask for reboot");
hr = NETCFG_S_REBOOT;
}
}
}
// Send Wanarp reconfig notification if necessary
//
else if (pAdapter->m_fIsWanAdapter && pAdapter->m_fNewlyChanged)
{
if (FAILED(HrReconfigWanarp(pAdapter, pICallback)))
{
TraceTag(ttidTcpip, "Wanarp failed its reconfig. Need to reboot.");
hr = NETCFG_S_REBOOT;
}
}
}
TraceError("CTcpipcfg::HrReconfigIp",hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: CTcpipcfg::HrReconfigAtmArp
//
// Purpose: Notify ATM ARP of configuration changes
//
// Arguments: none
//
// Returns: S_OK if success, NETCFG_S_REBOOT if failure
//
HRESULT CTcpipcfg::HrReconfigAtmArp(ADAPTER_INFO *pAdapterInfo,
INetCfgPnpReconfigCallback* pICallback)
{
HRESULT hr = S_OK;
// check if any parameter has changed
DWORD dwFlag = 0;
// arp server list
if (!fIsSameVstr(pAdapterInfo->m_vstrARPServerList,
pAdapterInfo->m_vstrOldARPServerList))
{
dwFlag |= ATMARPC_RECONFIG_FLAG_ARPS_LIST_CHANGED;
}
// mar server list
if (!fIsSameVstr(pAdapterInfo->m_vstrMARServerList,
pAdapterInfo->m_vstrOldMARServerList))
{
dwFlag |= ATMARPC_RECONFIG_FLAG_MARS_LIST_CHANGED;
}
// MTU
if (pAdapterInfo->m_dwMTU != pAdapterInfo->m_dwOldMTU)
{
dwFlag |= ATMARPC_RECONFIG_FLAG_MTU_CHANGED;
}
// PVC Only
if (pAdapterInfo->m_fPVCOnly != pAdapterInfo->m_fOldPVCOnly)
{
dwFlag |= ATMARPC_RECONFIG_FLAG_PVC_MODE_CHANGED;
}
if (dwFlag) // yep, some parameter has changed
{
tstring strIpConfigString = RGAS_TCPIP_PARAM_INTERFACES;
strIpConfigString += pAdapterInfo->m_strTcpipBindPath;
DWORD dwBytes = sizeof(IP_PNP_RECONFIG_REQUEST) +
sizeof(ATMARPC_PNP_RECONFIG_REQUEST) +
sizeof(USHORT) +
sizeof(WCHAR)*(strIpConfigString.length() + 1);
PVOID pvBuf;
hr = HrMalloc (dwBytes, &pvBuf);
if (SUCCEEDED(hr))
{
BYTE* pbByte = reinterpret_cast<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;
//Grant Network service and Netcfg OP the access to the NT4 key if
//this is a newly created key
//if the keys already have the ACEs, then the APIs wont add duplicate ones
//We ignore the return value since nothing can be done if it failed
//Also this is not critical for the system to run
if (REG_CREATED_NEW_KEY == dwDisposition)
{
HrSetSecurityForNetConfigOpsOnSubkeys(hkeyServices, strNt4SubKey.c_str());
HrSetSecurityForNetSvcOnSubkeys(hkeyServices, strNt4SubKey.c_str());
}
UINT cValues = sizeof(s_rgNt4Values)/sizeof(*s_rgNt4Values);
VSTR vstrTmp;
tstring strTmp;
DWORD dwTmp;
BOOL fTmp;
for (UINT i = 0; i < cValues; i++)
{
switch(s_rgNt4Values[i].dwType)
{
case REG_BOOL:
hrRead = HrRegQueryDword(hkeyInterface,
s_rgNt4Values[i].pszValueName,
&dwTmp);
if (SUCCEEDED(hrRead))
{
fTmp = !!dwTmp;
hrWrite = HrRegSetBool(hkeyNt4,
s_rgNt4Values[i].pszValueName,
fTmp);
}
break;
case REG_DWORD:
hrRead = HrRegQueryDword(hkeyInterface,
s_rgNt4Values[i].pszValueName,
&dwTmp);
if (SUCCEEDED(hrRead))
hrWrite = HrRegSetDword(hkeyNt4,
s_rgNt4Values[i].pszValueName,
dwTmp);
break;
case REG_SZ:
hrRead = HrRegQueryString(hkeyInterface,
s_rgNt4Values[i].pszValueName,
&strTmp);
if (SUCCEEDED(hrRead))
hrWrite = HrRegSetString(hkeyNt4,
s_rgNt4Values[i].pszValueName,
strTmp);
break;
case REG_MULTI_SZ:
hrRead = HrRegQueryColString( hkeyInterface,
s_rgNt4Values[i].pszValueName,
&vstrTmp);
if (SUCCEEDED(hrRead))
{
hrWrite = HrRegSetColString(hkeyNt4,
s_rgNt4Values[i].pszValueName,
vstrTmp);
DeleteColString(&vstrTmp);
}
break;
}
#ifdef ENABLETRACE
if(FAILED(hrRead))
{
TraceTag(ttidTcpip, "HrDuplicateToNT4Location: Failed on loading %S, hr: %x",
s_rgNt4Values[i].pszValueName, hr);
}
if(FAILED(hrWrite))
{
TraceTag(ttidError,
"HrDuplicateToNT4Location: failed to write %S to the registry. hr = %x.",
s_rgNt4Values[i].pszValueName, hrWrite);
}
#endif
if (SUCCEEDED(hr))
hr = hrWrite;
}
RegSafeCloseKey(hkeyNt4);
}
RegSafeCloseKey(hkeyServices);
LERROR:
TraceError("CTcpipcfg::HrDuplicateToNT4Location", hr);
return hr;
}
//To solve the compatibility issues of non-nt5 applications, we duplicate some important
//per interface tcpip parameters to the old NT4 location: Services\{adapter GUID}\Parameters\Tcpip
//We need to clean it up when removing tcpip
HRESULT CTcpipcfg::HrRemoveNt4DuplicateRegistry()
{
//we also need to delete the duplicate reg values under Services\{adapter GUID}
HRESULT hr = S_OK;
HRESULT hrTmp = S_OK;
HKEY hkeyServices = NULL;
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegServices,
KEY_READ_WRITE_DELETE, &hkeyServices);
if (FAILED(hr))
{
TraceTag(ttidTcpip, "HrRemoveNt4DuplicateRegistry: Failed to open the Services reg key, hr: %x", hr);
}
else
{
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin();
iterAdapter != m_vcardAdapterInfo.end();
iterAdapter++)
{
ADAPTER_INFO* pAdapter = *iterAdapter;
if (!pAdapter->m_fIsWanAdapter && !pAdapter->m_fIsRasFakeAdapter)
{
hrTmp = HrRegDeleteKeyTree(hkeyServices, pAdapter->m_strBindName.c_str());
#ifdef ENABLETRACE
if (FAILED(hrTmp))
{
TraceTag(ttidTcpip, "CTcpipcfg::HrRemoveNt4DuplicateRegistry");
TraceTag(ttidTcpip, "Failed on deleting duplicated Nt4 layout key: Services\\%S, hr: %x",
pAdapter->m_strBindName.c_str(), hrTmp);
}
#endif
}
}
RegSafeCloseKey(hkeyServices);
}
TraceError("CTcpipcfg::HrRemoveNt4DuplicateRegistry", hr);
return hr;
}
HRESULT CTcpipcfg::HrCleanUpPerformRouterDiscoveryFromRegistry()
{
HRESULT hr = S_OK;
HKEY hkey = NULL;
hr = m_pnccTcpip->OpenParamKey(&hkey);
if (SUCCEEDED(hr))
{
Assert(hkey);
HRESULT hrTemp = S_OK;
//delete the global PerformRouterDiscoveryDefault value
hrTemp = HrRegDeleteValue(hkey,
c_szPerformRouterDiscoveryDefault);
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hrTemp)
hrTemp = S_OK;
if (SUCCEEDED(hr))
hr = hrTemp;
HKEY hkeyInterfaces = NULL;
hrTemp = HrRegOpenKeyEx(hkey,
c_szInterfacesRegKey,
KEY_READ,
&hkeyInterfaces);
if (SUCCEEDED(hrTemp) && hkeyInterfaces)
{
WCHAR szBuf[256];
DWORD dwSize = celems(szBuf);
FILETIME time;
DWORD dwRegIndex = 0;
while (SUCCEEDED(hrTemp = HrRegEnumKeyEx(hkeyInterfaces,
dwRegIndex++,
szBuf,
&dwSize,
NULL,
NULL,
&time)))
{
HKEY hkeyIf = NULL;
dwSize = celems(szBuf);
hrTemp = HrRegOpenKeyEx(hkeyInterfaces,
szBuf,
KEY_READ_WRITE_DELETE,
&hkeyIf);
if (SUCCEEDED(hr))
hr = hrTemp;
if (SUCCEEDED(hrTemp))
{
Assert(hkeyIf);
DWORD dwTemp = 0;
hrTemp = HrRegQueryDword(hkeyIf,
c_szPerformRouterDiscovery,
&dwTemp);
if (SUCCEEDED(hrTemp))
{
if (IP_IRDP_DISABLED != dwTemp)
{
hrTemp = HrRegDeleteValue(hkeyIf,
c_szPerformRouterDiscovery);
if (SUCCEEDED(hr))
hr = hrTemp;
}
}
else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hrTemp)
{
hrTemp = S_OK;
}
if (SUCCEEDED(hr))
hr = hrTemp;
RegSafeCloseKey(hkeyIf);
}
}
if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hrTemp)
hrTemp = S_OK;
if (SUCCEEDED(hr))
hr = hrTemp;
RegSafeCloseKey(hkeyInterfaces);
}
RegSafeCloseKey(hkey);
}
else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
{
hr = S_OK;
}
TraceError("CTcpipcfg::HrCleanUpPerformRouterDiscoveryFromRegistry", hr);
return hr;
}
HRESULT CTcpipcfg::HrSaveBackupTcpSettings(HKEY hkeyInterfaceParam, ADAPTER_INFO * pAdapter)
{
HRESULT hr = S_OK;
HKEY hkeyDhcpConfigs = NULL;
HKEY hkeyDhcpCfg = NULL;
DWORD dwDisposition = 0;
tstring strConfigurationName;
tstring strReg;
if (!pAdapter->m_BackupInfo.m_fAutoNet)
{
//Set the Configuration option name as "Alternate_{Interface GUID}"
strConfigurationName = c_szAlternate;
strConfigurationName += pAdapter->m_strBindName;
//construct the NULL terminator for the Multi_SZ
int cch = strConfigurationName.length() + 2;
WCHAR * pwsz = new WCHAR[cch];
if (NULL == pwsz)
return E_OUTOFMEMORY;
ZeroMemory(pwsz, sizeof(pwsz[0]) * cch);
lstrcpyW(pwsz, strConfigurationName.c_str());
hr = HrRegSetMultiSz(hkeyInterfaceParam,
c_szActiveConfigurations,
pwsz);
delete [] pwsz;
}
else
{
hr = HrRegDeleteValue(hkeyInterfaceParam,
c_szActiveConfigurations);
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
hr = S_OK;
}
if (FAILED(hr))
{
TraceTag(ttidTcpip, "HrSaveBackupTcpSettings: Failed to create ActiveConfigurations value, hr: %x", hr);
goto LERROR;
}
hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szDhcpConfigurations,
REG_OPTION_NON_VOLATILE, KEY_READ, NULL,
&hkeyDhcpConfigs, &dwDisposition);
if (FAILED(hr))
{
TraceTag(ttidTcpip, "HrSaveBackupTcpSettings: Failed to open the Services reg key, hr: %x", hr);
goto LERROR;
}
hr = HrRegCreateKeyEx(hkeyDhcpConfigs, strConfigurationName.c_str(),
REG_OPTION_NON_VOLATILE, KEY_READ_WRITE, NULL,
&hkeyDhcpCfg, &dwDisposition);
if (SUCCEEDED(hr))
{
DWORD pdwOptionData[2]; // buffer holding the option's Dwords
DWORD dwIdxData; // actual data to be saved into blob for each option
LPBYTE pRegRaw = NULL; // buffer holding the blob
DWORD cb = 0; // blob size in the pRegRaw buffer
DWORD cbMax = 0; // pRegRaw buffer size (assert(cb<=cbMax))
// fill in the blob pRegRaw to be written to the registry
//
// fill in option 50 (requested IpAddress = Fallback IpAddress)
pdwOptionData[0] = htonl(IPStringToDword(pAdapter->m_BackupInfo.m_strIpAddr.c_str()));
// the adapter's address can't be an empty string hence a 0.0.0.0 address
hr = HrSaveBackupDwordOption (
OPTION_REQUESTED_ADDRESS,
pdwOptionData,
1,
&pRegRaw,
&cb,
&cbMax);
// fill in option 1 (Fallback subnet mask)
if (hr == S_OK)
{
pdwOptionData[0] =
htonl(IPStringToDword(pAdapter->m_BackupInfo.m_strSubnetMask.c_str()));
// the adapter's subnet mask can't be an empty string, hence a 0.0.0.0 address
hr = HrSaveBackupDwordOption (
OPTION_SUBNET_MASK,
pdwOptionData,
1,
&pRegRaw,
&cb,
&cbMax);
}
// fill in option 3 if any Fallback gateway is specified
if (hr == S_OK)
{
dwIdxData = 0;
pdwOptionData[dwIdxData] =
htonl(IPStringToDword(pAdapter->m_BackupInfo.m_strDefGw.c_str()));
dwIdxData += (pdwOptionData[dwIdxData] != 0);
hr = HrSaveBackupDwordOption (
OPTION_ROUTER_ADDRESS,
pdwOptionData,
dwIdxData,
&pRegRaw,
&cb,
&cbMax);
}
// fill in option 6 if any Fallback DNS servers (maximum 2 supported for now) is specified
if (hr == S_OK)
{
dwIdxData = 0;
pdwOptionData[dwIdxData] =
htonl(IPStringToDword(pAdapter->m_BackupInfo.m_strPreferredDns.c_str()));
dwIdxData += (pdwOptionData[dwIdxData] != 0);
pdwOptionData[dwIdxData] =
htonl(IPStringToDword(pAdapter->m_BackupInfo.m_strAlternateDns.c_str()));
dwIdxData += (pdwOptionData[dwIdxData] != 0);
hr = HrSaveBackupDwordOption (
OPTION_DOMAIN_NAME_SERVERS,
pdwOptionData,
dwIdxData,
&pRegRaw,
&cb,
&cbMax);
}
// fill in option 44 if any Fallback WINS servers (maximum 2 supported for now) is specified
if (hr == S_OK)
{
dwIdxData = 0;
pdwOptionData[dwIdxData] =
htonl(IPStringToDword(pAdapter->m_BackupInfo.m_strPreferredWins.c_str()));
dwIdxData += (pdwOptionData[dwIdxData] != 0);
pdwOptionData[dwIdxData] =
htonl(IPStringToDword(pAdapter->m_BackupInfo.m_strAlternateWins.c_str()));
dwIdxData += (pdwOptionData[dwIdxData] != 0);
hr = HrSaveBackupDwordOption (
OPTION_NETBIOS_NAME_SERVER,
pdwOptionData,
dwIdxData,
&pRegRaw,
&cb,
&cbMax);
}
// write the blob to the registry
if (hr == S_OK)
{
hr = HrRegSetBinary(hkeyDhcpCfg,
c_szConfigOptions,
pRegRaw,
cb);
}
// free whatever mem was allocated
if (pRegRaw != NULL)
CoTaskMemFree(pRegRaw);
RegSafeCloseKey(hkeyDhcpCfg);
}
RegSafeCloseKey(hkeyDhcpConfigs);
LERROR:
return hr;
}
///////////////////////////////////////////////////////////////////
// Fills in a DHCP DWORD option into a blob. Adjusts the size of
// the buffer holding the blob if needed and returns through the
// out params the new buffer, its size and the size of the blob
// it contains.
HRESULT CTcpipcfg::HrSaveBackupDwordOption (
/*IN*/ DWORD Option,
/*IN*/ DWORD OptionData[],
/*IN*/ DWORD OptionDataSz,
/*IN OUT*/ LPBYTE *ppBuffer,
/*IN OUT*/ LPDWORD pdwBlobSz,
/*IN OUT*/ LPDWORD pdwBufferSz)
{
DWORD dwBlobSz;
REG_BACKUP_INFO *pRegBackupInfo;
DWORD dwOptIdx;
// if no data is available at all, then don't save anything
if (OptionDataSz == 0)
return S_OK;
// calculate the memory size needed for the new updated blob.
// don't forget, REG_BACKUP_INFO already contains one DWORD from the Option's data
dwBlobSz = (*pdwBlobSz) + sizeof(REG_BACKUP_INFO) + (OptionDataSz-1)*sizeof(DWORD);
// check whether the buffer is large enough to hold the new blob
if ((*pdwBufferSz) < dwBlobSz)
{
HRESULT hr;
LPBYTE pNewBuffer;
DWORD dwBuffSz;
// get the expected size of the new buffer
dwBuffSz = (DWORD)(max((*pdwBufferSz) + BUFFER_ENLARGEMENT_CHUNK, dwBlobSz));
// if the pointer provided is NULL...
if (*ppBuffer == NULL)
{
// ...this means we have to do the initial allocation
pNewBuffer = (LPBYTE)CoTaskMemAlloc(dwBuffSz);
}
else
{
// ...otherwise is just a buffer enlargement so do a
// realloc in order to keep the original payload
pNewBuffer = (LPBYTE)CoTaskMemRealloc((*ppBuffer), dwBuffSz);
}
if (pNewBuffer == NULL)
return E_OUTOFMEMORY;
// starting from this point we don't expect any other errors
// so start update the output parameters
(*ppBuffer) = pNewBuffer;
(*pdwBufferSz) += dwBuffSz;
}
// get the mem storage seen as a REG_BACKUP_INFO struct
pRegBackupInfo = (REG_BACKUP_INFO *)((*ppBuffer) + (*pdwBlobSz));
(*pdwBlobSz) = dwBlobSz;
// update the blob by adding the new option
pRegBackupInfo->dwOptionId = Option;
pRegBackupInfo->dwClassLen = 0; // fallback options don't have a class
pRegBackupInfo->dwDataLen = OptionDataSz * sizeof(DWORD);
pRegBackupInfo->dwIsVendor = 0; // fallback options are not vendor options
pRegBackupInfo->dwExpiryTime = 0x7fffffff; // fallback options don't expire
// add all the Option's data
for (dwOptIdx = 0; dwOptIdx < OptionDataSz; dwOptIdx++)
{
pRegBackupInfo->dwData[dwOptIdx] = OptionData[dwOptIdx];
}
return S_OK;
}
HRESULT CTcpipcfg::HrLoadBackupTcpSettings(HKEY hkeyInterfaceParam, ADAPTER_INFO * pAdapter)
{
HRESULT hr = S_OK;
//construct the string "Alternate_{Interface GUID}"
tstring strConfigurationName = c_szAlternate;
strConfigurationName += pAdapter->m_strBindName;
// if ActiveConfigurations contain a string "Alternate_{Interface GUID}"
// then there is customized fall-back settings, otherwise Autonet
VSTR vstrTmp;
pAdapter->m_BackupInfo.m_fAutoNet = TRUE;
hr = HrRegQueryColString( hkeyInterfaceParam,
c_szActiveConfigurations,
&vstrTmp);
if (SUCCEEDED(hr))
{
BOOL fFound = FALSE;
for (int i = 0; i < (int)vstrTmp.size(); i++)
{
if (strConfigurationName == *vstrTmp[i])
{
pAdapter->m_BackupInfo.m_fAutoNet = FALSE;
break;
}
}
DeleteColString(&vstrTmp);
}
tstring strReg = c_szDhcpConfigurations;
strReg += _T("\\");
strReg += strConfigurationName;
HKEY hkeyDhcpConfig = NULL;
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, strReg.c_str(),
KEY_READ, &hkeyDhcpConfig);
if (SUCCEEDED(hr))
{
LPBYTE pBackupInfoForReg = NULL;
DWORD cb = 0;
hr = HrRegQueryBinaryWithAlloc(hkeyDhcpConfig,
c_szConfigOptions,
&pBackupInfoForReg,
&cb);
if (SUCCEEDED(hr))
{
LPBYTE pRaw;
pRaw = pBackupInfoForReg;
while (cb >= sizeof(REG_BACKUP_INFO))
{
REG_BACKUP_INFO *pOption;
pOption = (REG_BACKUP_INFO *)pRaw;
// don't forget REG_BACKUP_INFO already contains one DWORD from
// the data section. Although the statememnts below are somehow identical
// the compiler is expected to optimize the code: one constant generated
// at compile time for sizeof(REG_BACKUP_INFO) - sizeof(DWORD), and one
// register only used in both lines below.
cb -= sizeof(REG_BACKUP_INFO) - sizeof(DWORD);
pRaw += sizeof(REG_BACKUP_INFO) - sizeof(DWORD);
// since cb is DWORD take special care to avoid roll over
if (cb < pOption->dwDataLen)
break;
cb -= pOption->dwDataLen;
pRaw += pOption->dwDataLen;
HrLoadBackupOption(pOption, &pAdapter->m_BackupInfo);
}
MemFree(pBackupInfoForReg);
}
RegSafeCloseKey(hkeyDhcpConfig);
}
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
{
//it's ok if the reg values are missing
hr = S_OK;
}
return hr;
}
///////////////////////////////////////////////////////////////////
// transfers data from the registry raw representation of the option
// to the corresponding fields from the BACKUP_CFG_INFO structure
//
HRESULT CTcpipcfg::HrLoadBackupOption(
/*IN*/ REG_BACKUP_INFO *pOption,
/*OUT*/ BACKUP_CFG_INFO *pBackupInfo)
{
tstring *pIp1 = NULL;
tstring *pIp2 = NULL;
HRESULT hr = S_OK;
// depending on what the option is, have pIp1 & pIp2 point to the
// fields to be filled in from BACKUP_CFG_INFO
switch(pOption->dwOptionId)
{
case OPTION_REQUESTED_ADDRESS:
pIp1 = &pBackupInfo->m_strIpAddr;
break;
case OPTION_SUBNET_MASK:
pIp1 = &pBackupInfo->m_strSubnetMask;
break;
case OPTION_ROUTER_ADDRESS:
pIp1 = &pBackupInfo->m_strDefGw;
break;
case OPTION_DOMAIN_NAME_SERVERS:
pIp1 = &pBackupInfo->m_strPreferredDns;
pIp2 = &pBackupInfo->m_strAlternateDns;
break;
case OPTION_NETBIOS_NAME_SERVER:
pIp1 = &pBackupInfo->m_strPreferredWins;
pIp2 = &pBackupInfo->m_strAlternateWins;
break;
default:
return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
}
// each option has at least one IpAddress value
DwordToIPString(ntohl(pOption->dwData[0]), *pIp1);
// if the option has more than one IpAddress (meaning two :-)
// and if it is supposed to allow 2 addresses to be specified
// then fill up the second field as well.
if (pOption->dwDataLen > sizeof(DWORD) && pIp2 != NULL)
DwordToIPString(ntohl(pOption->dwData[1]), *pIp2);
return hr;
}
//Cleanup the backup settings registry under System\Services\dhcp
// wszAdapterName GUID of the adapter of which we want to delete the registry
HRESULT CTcpipcfg::HrDeleteBackupSettingsInDhcp(LPCWSTR wszAdapterName)
{
HRESULT hr = S_OK;
HKEY hkeyDhcpConfigs = NULL;
HKEY hkeyDhcpCfg = NULL;
DWORD dwDisposition = 0;
tstring strConfigurationName = c_szAlternate;
strConfigurationName += wszAdapterName;;
hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szDhcpConfigurations,
REG_OPTION_NON_VOLATILE, KEY_READ_WRITE_DELETE, NULL,
&hkeyDhcpConfigs, &dwDisposition);
if (FAILED(hr))
{
TraceTag(ttidTcpip, "HrDeleteBackupSettingsInDhcp: Failed to open the Services reg key, hr: %x", hr);
goto LERROR;
}
hr = HrRegDeleteKeyTree(hkeyDhcpConfigs, strConfigurationName.c_str());
RegSafeCloseKey(hkeyDhcpConfigs);
LERROR:
return hr;
}
HRESULT CTcpipcfg::HrSetSecurityForNetConfigOpsOnSubkeys(HKEY hkeyRoot, LPCWSTR strKeyName)
{
PSID psidGroup = NULL;
SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY;
HRESULT hr = S_OK;
if (AllocateAndInitializeSid(&sidAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS, 0, 0, 0, 0, 0, 0, &psidGroup))
{
CRegKeySecurity rkSecurity;
hr = rkSecurity.RegOpenKey(hkeyRoot, strKeyName);
if (SUCCEEDED(hr))
{
hr = rkSecurity.GetKeySecurity();
if (SUCCEEDED(hr))
{
hr = rkSecurity.GrantRightsOnRegKey(psidGroup, KEY_READ_WRITE_DELETE, KEY_ALL);
}
rkSecurity.RegCloseKey();
}
FreeSid(psidGroup);
}
return hr;
}
HRESULT CTcpipcfg::HrSetSecurityForNetSvcOnSubkeys(HKEY hkeyRoot, LPCWSTR strKeyName)
{
PSID psidNetSvc = NULL;
SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY;
HRESULT hr = S_OK;
if (AllocateAndInitializeSid(&sidAuth, 1, SECURITY_NETWORK_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0, &psidNetSvc))
{
CRegKeySecurity rkSecurity;
hr = rkSecurity.RegOpenKey(hkeyRoot, strKeyName);
if (SUCCEEDED(hr))
{
hr = rkSecurity.GetKeySecurity();
if (SUCCEEDED(hr))
{
hr = rkSecurity.GrantRightsOnRegKey(psidNetSvc, KEY_READ_WRITE_DELETE, KEY_ALL);
}
rkSecurity.RegCloseKey();
}
FreeSid(psidNetSvc);
}
return hr;
}
//Update the NT4 registry permission to grant Netcfg Op and Network Service access
//This is called during upgrade
HRESULT CTcpipcfg::HrUpdateNt4RegistryPermission()
{
HRESULT hr = S_OK;
HKEY hkeyServices = NULL;
tstring strNt4SubKey;
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE,
c_szRegServices,
KEY_READ,
&hkeyServices);
if (FAILED(hr))
{
TraceTag(ttidTcpip, "HrUpdateNt4RegistryPermission: Failed to open the Services reg key, hr: %x", hr);
return hr;
}
for(VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin();
iterAdapter != m_vcardAdapterInfo.end();
iterAdapter ++)
{
ADAPTER_INFO * pAdapter = *iterAdapter;
if (pAdapter->m_fIsRasFakeAdapter || pAdapter->m_fIsWanAdapter)
{
continue;
}
strNt4SubKey = pAdapter->m_strBindName;
strNt4SubKey += c_szRegParamsTcpip;
//Grant Network service and Netcfg OP the access to the NT4 key
//if the keys already have the ACEs, then the APIs wont add duplicate ones
//
//We ignore the return value since nothing can be done if it failed
//Also this is not critical for the system to run
HrSetSecurityForNetConfigOpsOnSubkeys(hkeyServices, strNt4SubKey.c_str());
HrSetSecurityForNetSvcOnSubkeys(hkeyServices, strNt4SubKey.c_str());
}
RegSafeCloseKey(hkeyServices);
return hr;
}