743 lines
31 KiB
C++
743 lines
31 KiB
C++
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1997.
|
||
|
//
|
||
|
// File: T C P D H C P . C P P
|
||
|
//
|
||
|
// Contents: Functions related to Calling Dhcpcsvc.dll entry point
|
||
|
// called from HrSetMisc
|
||
|
//
|
||
|
// HrNotifyDhcp, HrCallDhcpConfig
|
||
|
//
|
||
|
// Notes: These functions are based on what was in ncpa1.1
|
||
|
//
|
||
|
// HrNotifyDHCP is from CTcpGenPage::NotifyDHCP
|
||
|
// HrCallDhcpConfig is from CallDHCPConfig
|
||
|
//
|
||
|
// Author: tongl 11 May 1997
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#include "pch.h"
|
||
|
#pragma hdrstop
|
||
|
#include "tcpipobj.h"
|
||
|
#include "ncatlui.h"
|
||
|
#include "ncreg.h"
|
||
|
#include "ncsvc.h"
|
||
|
#include "tcpconst.h"
|
||
|
#include "tcputil.h"
|
||
|
#include "atmcommon.h"
|
||
|
|
||
|
#define ConvertIpDword(dwIpOrSubnet) ((dwIpOrSubnet[3]<<24) | (dwIpOrSubnet[2]<<16) | (dwIpOrSubnet[1]<<8) | (dwIpOrSubnet[0]))
|
||
|
|
||
|
//
|
||
|
// CTcpipcfg::HrNotifyDhcp
|
||
|
//
|
||
|
// Makes on the fly IP Address changes for all cards in the system
|
||
|
//
|
||
|
// hkeyTcpipParam Handle to \CCS\Services\Tcpip\Parameters reg key
|
||
|
|
||
|
HRESULT CTcpipcfg::HrNotifyDhcp()
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
HRESULT hrTmp = S_OK;
|
||
|
|
||
|
ADAPTER_INFO* pAdapter;
|
||
|
|
||
|
for (VCARD::iterator iterAdapter = m_vcardAdapterInfo.begin();
|
||
|
iterAdapter != m_vcardAdapterInfo.end();
|
||
|
iterAdapter ++)
|
||
|
{
|
||
|
pAdapter = *iterAdapter;
|
||
|
|
||
|
if((pAdapter->m_BindingState == BINDING_ENABLE) &&
|
||
|
(pAdapter->m_InitialBindingState != BINDING_DISABLE) &&
|
||
|
(!pAdapter->m_fIsWanAdapter))
|
||
|
{
|
||
|
// 1) Static IP-> Dhcp
|
||
|
// The new value is enable DHCP,
|
||
|
// but the old value was disable DHCP
|
||
|
if(pAdapter->m_fEnableDhcp &&
|
||
|
!pAdapter->m_fOldEnableDhcp)
|
||
|
{
|
||
|
TraceTag(ttidTcpip,"[HrNotifyDhcp] adapter:%S: Static IP->DHCP",
|
||
|
pAdapter->m_strBindName.c_str());
|
||
|
|
||
|
HKEY hkeyTcpipParam = NULL;
|
||
|
hrTmp = m_pnccTcpip->OpenParamKey(&hkeyTcpipParam);
|
||
|
|
||
|
if SUCCEEDED(hrTmp)
|
||
|
{
|
||
|
// Enable Dhcp
|
||
|
HKEY hkeyInterfaces = NULL;
|
||
|
DWORD dwGarbage;
|
||
|
|
||
|
// Open the interfaces key
|
||
|
hrTmp = HrRegCreateKeyEx(hkeyTcpipParam,
|
||
|
c_szInterfacesRegKey,
|
||
|
REG_OPTION_NON_VOLATILE,
|
||
|
KEY_READ,
|
||
|
NULL,
|
||
|
&hkeyInterfaces,
|
||
|
&dwGarbage);
|
||
|
|
||
|
if(SUCCEEDED(hrTmp))
|
||
|
{
|
||
|
Assert(hkeyInterfaces);
|
||
|
HKEY hkeyInterfaceParam = NULL;
|
||
|
|
||
|
// Open the interface key for the specified interface
|
||
|
hrTmp = HrRegCreateKeyEx(
|
||
|
hkeyInterfaces,
|
||
|
pAdapter->m_strTcpipBindPath.c_str(),
|
||
|
REG_OPTION_NON_VOLATILE,
|
||
|
KEY_READ_WRITE,
|
||
|
NULL,
|
||
|
&hkeyInterfaceParam,
|
||
|
&dwGarbage);
|
||
|
|
||
|
if (SUCCEEDED(hrTmp))
|
||
|
{
|
||
|
// Clear up the IP address and subnet registry entries
|
||
|
Assert(hkeyInterfaceParam);
|
||
|
|
||
|
hrTmp = HrRegSetString(hkeyInterfaceParam,
|
||
|
RGAS_DHCP_IPADDRESS,
|
||
|
tstring(ZERO_ADDRESS));
|
||
|
|
||
|
if(SUCCEEDED(hrTmp))
|
||
|
{
|
||
|
hrTmp = HrRegSetString(hkeyInterfaceParam,
|
||
|
RGAS_DHCP_SUBNETMASK,
|
||
|
tstring(FF_ADDRESS));
|
||
|
|
||
|
if(SUCCEEDED(hrTmp))
|
||
|
{
|
||
|
// Enable Dhcp & remove first static IP address
|
||
|
hrTmp = HrCallDhcpConfig(
|
||
|
NULL,
|
||
|
(PWSTR)pAdapter->m_strTcpipBindPath.c_str(),
|
||
|
pAdapter->m_guidInstanceId,
|
||
|
FALSE, // static->dhcp
|
||
|
0, // index
|
||
|
0, // IP address
|
||
|
0, // Subnet mask
|
||
|
DhcpEnable); //Flag: enable Dhcp
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
RegSafeCloseKey(hkeyInterfaceParam);
|
||
|
}
|
||
|
RegSafeCloseKey(hkeyInterfaces);
|
||
|
}
|
||
|
RegSafeCloseKey(hkeyTcpipParam);
|
||
|
}
|
||
|
|
||
|
// 2) Static IP change
|
||
|
// DHCP is disabled now, and also used to be disabled before
|
||
|
if(!pAdapter->m_fEnableDhcp &&
|
||
|
!pAdapter->m_fOldEnableDhcp)
|
||
|
{
|
||
|
TraceTag(ttidTcpip,"[HrNotifyDhcp] adapter:%S: Static IP change.",
|
||
|
pAdapter->m_strBindName.c_str());
|
||
|
|
||
|
HRESULT hrTmp2 = S_OK;
|
||
|
BOOL fStaticIpChanged = FALSE;
|
||
|
|
||
|
// We should have equal number of IP addresses & subnet masks
|
||
|
Assert(pAdapter->m_vstrIpAddresses.size() ==
|
||
|
pAdapter->m_vstrSubnetMask.size());
|
||
|
|
||
|
Assert(pAdapter->m_vstrOldIpAddresses.size() ==
|
||
|
pAdapter->m_vstrOldSubnetMask.size());
|
||
|
|
||
|
// We need to check if individual IP addresses are different
|
||
|
// and call HrCallDhcpConfig once for each difference
|
||
|
|
||
|
int iCountNew = pAdapter->m_vstrIpAddresses.size();
|
||
|
int iCountOld = pAdapter->m_vstrOldIpAddresses.size();
|
||
|
|
||
|
int iCount = iCountNew>iCountOld ? iCountOld :iCountNew;
|
||
|
Assert(iCount>0);
|
||
|
|
||
|
int iIp;
|
||
|
|
||
|
// For each static IP address index in both old and new
|
||
|
// Update IP
|
||
|
for (iIp=0; iIp<iCount; iIp++)
|
||
|
{
|
||
|
// Change address if mismatch
|
||
|
if((*pAdapter->m_vstrIpAddresses[iIp] !=
|
||
|
*pAdapter->m_vstrOldIpAddresses[iIp]) ||
|
||
|
(*pAdapter->m_vstrSubnetMask[iIp] !=
|
||
|
*pAdapter->m_vstrOldSubnetMask[iIp]))
|
||
|
{
|
||
|
// if a mismatch found, change it
|
||
|
fStaticIpChanged = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fStaticIpChanged)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
// blow away the rest of the old addresses in reverse order
|
||
|
for (i= iCountOld-1; i>=iIp; i--)
|
||
|
{
|
||
|
// Remove IP address on the fly
|
||
|
hrTmp2= HrCallDhcpConfig(
|
||
|
NULL,
|
||
|
(PWSTR)pAdapter->m_strTcpipBindPath.c_str(),
|
||
|
pAdapter->m_guidInstanceId,
|
||
|
TRUE, // IsNewIpAddress: TRUE in static->static
|
||
|
i, // Index of old IP address
|
||
|
0, // Ip Address: remove
|
||
|
0, // Subnetmask: remove
|
||
|
IgnoreFlag); // Flag: static->static
|
||
|
|
||
|
TraceError("Ctcpipcfg::HrNotifyDhcp - remove static IP address", hrTmp2);
|
||
|
|
||
|
if SUCCEEDED(hrTmp)
|
||
|
hrTmp = hrTmp2;
|
||
|
}
|
||
|
|
||
|
// add the rest of the new addresses in order
|
||
|
for (i= iIp; i< iCountNew; i++)
|
||
|
{
|
||
|
// Ip Address
|
||
|
DWORD dwIp[4];
|
||
|
GetNodeNum(pAdapter->m_vstrIpAddresses[i]->c_str(),dwIp);
|
||
|
DWORD dwNewIp = ConvertIpDword(dwIp);
|
||
|
|
||
|
// Subnet mask
|
||
|
DWORD dwSubnet[4];
|
||
|
GetNodeNum(pAdapter->m_vstrSubnetMask[i]->c_str(),dwSubnet);
|
||
|
DWORD dwNewSubnet = ConvertIpDword(dwSubnet);
|
||
|
|
||
|
if (0 == i)
|
||
|
{
|
||
|
// $REVIEW(tongl 6/3/98): the first address has to be added differently,
|
||
|
// yet another requirement by the api to change static ip list (bug #180015).
|
||
|
// Bug #180617 had my request to change the API to allow reconfigure whole
|
||
|
// static ip list instead of requiring caller to figure out everything needed
|
||
|
// for the internal data structure change for ip.
|
||
|
|
||
|
// must call "replace" instead of "add"
|
||
|
hrTmp2= HrCallDhcpConfig(
|
||
|
NULL,
|
||
|
(PWSTR)pAdapter->m_strTcpipBindPath.c_str(),
|
||
|
pAdapter->m_guidInstanceId,
|
||
|
TRUE, // IsNewIpAddress: TRUE in static->static
|
||
|
0, // Replace first address
|
||
|
dwNewIp,
|
||
|
dwNewSubnet,
|
||
|
IgnoreFlag); // Flag: static->static
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Add IP address on the fly
|
||
|
hrTmp2= HrCallDhcpConfig(
|
||
|
NULL,
|
||
|
(PWSTR)pAdapter->m_strTcpipBindPath.c_str(),
|
||
|
pAdapter->m_guidInstanceId,
|
||
|
TRUE, // IsNewIpAddress: TRUE in static->static
|
||
|
0xFFFF, // New IP address
|
||
|
dwNewIp,
|
||
|
dwNewSubnet,
|
||
|
IgnoreFlag); // Flag: static->static
|
||
|
}
|
||
|
|
||
|
TraceError("Ctcpipcfg::HrNotifyDhcp - add static IP address", hrTmp2);
|
||
|
|
||
|
if SUCCEEDED(hrTmp)
|
||
|
hrTmp = hrTmp2;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// existing addresses all match
|
||
|
if (iIp<iCountNew) // We ust get more new addresses to add
|
||
|
{
|
||
|
fStaticIpChanged = TRUE;
|
||
|
|
||
|
while (iIp<iCountNew)
|
||
|
{
|
||
|
DWORD dwIp[4];
|
||
|
Assert(!pAdapter->m_vstrIpAddresses.empty());
|
||
|
|
||
|
GetNodeNum(pAdapter->m_vstrIpAddresses[iIp]->c_str(),
|
||
|
dwIp);
|
||
|
DWORD dwNewIp = ConvertIpDword(dwIp);
|
||
|
|
||
|
// Subnet mask
|
||
|
DWORD dwSubnet[4];
|
||
|
Assert(!pAdapter->m_vstrSubnetMask.empty());
|
||
|
GetNodeNum(pAdapter->m_vstrSubnetMask[iIp]->c_str(),
|
||
|
dwSubnet);
|
||
|
DWORD dwNewSubnet = ConvertIpDword(dwSubnet);
|
||
|
|
||
|
// Add IP address on the fly
|
||
|
hrTmp2= HrCallDhcpConfig(
|
||
|
NULL,
|
||
|
(PWSTR)pAdapter->m_strTcpipBindPath.c_str(),
|
||
|
pAdapter->m_guidInstanceId,
|
||
|
TRUE, // IsNewIpAddress: TRUE in static->static
|
||
|
0xFFFF, // New IP address
|
||
|
dwNewIp,
|
||
|
dwNewSubnet,
|
||
|
IgnoreFlag); // Flag: static->static
|
||
|
|
||
|
TraceError("Ctcpipcfg::HrNotifyDhcp - add static IP address", hrTmp2);
|
||
|
|
||
|
if SUCCEEDED(hrTmp)
|
||
|
hrTmp = hrTmp2;
|
||
|
|
||
|
iIp++;
|
||
|
}
|
||
|
}
|
||
|
else if (iIp<iCountOld) // We just get more old addresses to remove
|
||
|
{
|
||
|
fStaticIpChanged = TRUE;
|
||
|
|
||
|
int iIp2 = iCountOld-1;
|
||
|
|
||
|
while (iIp2 >= iIp)
|
||
|
{
|
||
|
// Remove IP address on the fly
|
||
|
hrTmp2= HrCallDhcpConfig(
|
||
|
NULL,
|
||
|
(PWSTR)pAdapter->m_strTcpipBindPath.c_str(),
|
||
|
pAdapter->m_guidInstanceId,
|
||
|
TRUE, // IsNewIpAddress: TRUE in static->static
|
||
|
iIp2, // Index of old IP address
|
||
|
0, // Ip Address: remove
|
||
|
0, // Subnetmask: remove
|
||
|
IgnoreFlag); // Flag: static->static
|
||
|
|
||
|
TraceError("Ctcpipcfg::HrNotifyDhcp - remove static IP address", hrTmp2);
|
||
|
|
||
|
if SUCCEEDED(hrTmp)
|
||
|
hrTmp = hrTmp2;
|
||
|
|
||
|
iIp2--;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 3) Dhcp->Static
|
||
|
// DHCP is disabled now, but used to be enabled
|
||
|
if(!pAdapter->m_fEnableDhcp &&
|
||
|
pAdapter->m_fOldEnableDhcp)
|
||
|
{
|
||
|
TraceTag(ttidTcpip,"[HrNotifyDhcp] adapter:%S: DHCP->Static IP",
|
||
|
pAdapter->m_strBindName.c_str());
|
||
|
|
||
|
// Disable Dhcp & add first static Ip address
|
||
|
Assert(!pAdapter->m_vstrIpAddresses.empty());
|
||
|
|
||
|
// Ip Address
|
||
|
DWORD dwIp[4];
|
||
|
GetNodeNum(pAdapter->m_vstrIpAddresses[0]->c_str(),
|
||
|
dwIp);
|
||
|
DWORD dwNewIp = ConvertIpDword(dwIp);
|
||
|
|
||
|
// Subnet Mask
|
||
|
DWORD dwSubnet[4];
|
||
|
Assert(!pAdapter->m_vstrSubnetMask.empty());
|
||
|
GetNodeNum(pAdapter->m_vstrSubnetMask[0]->c_str(),
|
||
|
dwSubnet);
|
||
|
DWORD dwNewSubnet = ConvertIpDword(dwSubnet);
|
||
|
|
||
|
// change IP address on the fly
|
||
|
hrTmp = HrCallDhcpConfig(
|
||
|
NULL,
|
||
|
(PWSTR)pAdapter->m_strTcpipBindPath.c_str(),
|
||
|
pAdapter->m_guidInstanceId,
|
||
|
TRUE,
|
||
|
0, // index: update dhcp address to first static address
|
||
|
dwNewIp,
|
||
|
dwNewSubnet,
|
||
|
DhcpDisable); // Flag: disable Dhcp
|
||
|
|
||
|
if SUCCEEDED(hrTmp)
|
||
|
{
|
||
|
HRESULT hrTmp2 = S_OK;
|
||
|
|
||
|
// Add the rest of new static IP addresses
|
||
|
for (size_t iIp = 1;
|
||
|
iIp < pAdapter->m_vstrIpAddresses.size();
|
||
|
iIp++)
|
||
|
{
|
||
|
// Ip Address
|
||
|
DWORD dwIp[4];
|
||
|
Assert(!pAdapter->m_vstrIpAddresses.empty());
|
||
|
GetNodeNum(pAdapter->m_vstrIpAddresses[iIp]->c_str(),
|
||
|
dwIp);
|
||
|
DWORD dwNewIp = ConvertIpDword(dwIp);
|
||
|
|
||
|
// Subnet Mask
|
||
|
DWORD dwSubnet[4];
|
||
|
Assert(!pAdapter->m_vstrSubnetMask.empty());
|
||
|
GetNodeNum(pAdapter->m_vstrSubnetMask[iIp]->c_str(),
|
||
|
dwSubnet);
|
||
|
DWORD dwNewSubnet = ConvertIpDword(dwSubnet);
|
||
|
|
||
|
// change IP address on the fly
|
||
|
hrTmp2= HrCallDhcpConfig(
|
||
|
NULL,
|
||
|
(PWSTR)pAdapter->m_strTcpipBindPath.c_str(),
|
||
|
pAdapter->m_guidInstanceId,
|
||
|
TRUE,
|
||
|
0xFFFF, // index: new address
|
||
|
dwNewIp,
|
||
|
dwNewSubnet,
|
||
|
IgnoreFlag ); // Flag: static->static
|
||
|
|
||
|
TraceError("CTcpipcfg::HrNotifyDhcp - add static IP address", hrTmp2);
|
||
|
|
||
|
if SUCCEEDED(hrTmp)
|
||
|
hrTmp = hrTmp2;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
hr = hrTmp;
|
||
|
|
||
|
// 4) Dhcp Class ID, DNS server list and domain change
|
||
|
// $REVIEW(tongl 6/12): Notify DNS server list and domain changes
|
||
|
// here (Raid #175766)
|
||
|
|
||
|
DHCP_PNP_CHANGE DhcpPnpChange;
|
||
|
ZeroMemory(&DhcpPnpChange, sizeof(DHCP_PNP_CHANGE));
|
||
|
|
||
|
DhcpPnpChange.Version = DHCP_PNP_CHANGE_VERSION_0;
|
||
|
DhcpPnpChange.HostNameChanged = FALSE;
|
||
|
DhcpPnpChange.MaskChanged = FALSE;
|
||
|
|
||
|
//Bug 257868 If there is user specified default gateway, notify dhcp client
|
||
|
DhcpPnpChange.GateWayChanged = !fIsSameVstr(pAdapter->m_vstrDefaultGateway,
|
||
|
pAdapter->m_vstrOldDefaultGateway) ||
|
||
|
!fIsSameVstr(pAdapter->m_vstrDefaultGatewayMetric,
|
||
|
pAdapter->m_vstrOldDefaultGatewayMetric);
|
||
|
DhcpPnpChange.RouteChanged = FALSE;
|
||
|
DhcpPnpChange.OptsChanged = FALSE;
|
||
|
DhcpPnpChange.OptDefsChanged = FALSE;
|
||
|
|
||
|
DhcpPnpChange.DnsListChanged = !fIsSameVstr(pAdapter->m_vstrDnsServerList,
|
||
|
pAdapter->m_vstrOldDnsServerList);
|
||
|
DhcpPnpChange.DomainChanged = pAdapter->m_strDnsDomain != pAdapter->m_strOldDnsDomain;
|
||
|
DhcpPnpChange.ClassIdChanged = FALSE;
|
||
|
DhcpPnpChange.DnsOptionsChanged =
|
||
|
((!!pAdapter->m_fDisableDynamicUpdate) !=
|
||
|
(!!pAdapter->m_fOldDisableDynamicUpdate))
|
||
|
||
|
||
|
((!!pAdapter->m_fEnableNameRegistration) !=
|
||
|
(!!pAdapter->m_fOldEnableNameRegistration));
|
||
|
|
||
|
|
||
|
if(DhcpPnpChange.DnsListChanged ||
|
||
|
DhcpPnpChange.DnsOptionsChanged ||
|
||
|
DhcpPnpChange.DomainChanged ||
|
||
|
(DhcpPnpChange.GateWayChanged && pAdapter->m_fEnableDhcp))
|
||
|
{
|
||
|
hrTmp = HrCallDhcpHandlePnPEvent(pAdapter, &DhcpPnpChange);
|
||
|
if (FAILED(hrTmp))
|
||
|
{
|
||
|
TraceError("HrCallDhcpHandlePnPEvent returns failure, requesting reboot...", hrTmp);
|
||
|
hr = NETCFG_S_REBOOT;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pAdapter->m_fBackUpSettingChanged)
|
||
|
{
|
||
|
hrTmp = HrDhcpRefreshFallbackParams(pAdapter);
|
||
|
if (FAILED(hrTmp))
|
||
|
{
|
||
|
TraceError("HrDhcpRefreshFallbackParams returns failure, requesting reboot...", hrTmp);
|
||
|
hr = NETCFG_S_REBOOT;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NETCFG_S_REBOOT != hr)
|
||
|
hr = hrTmp;
|
||
|
|
||
|
TraceError("CTcpipcfg::HrNotifyDhcp", hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// Define the export function prototype from dhcpcsvc.dll
|
||
|
|
||
|
typedef DWORD (APIENTRY *T_DhcpNotifyConfigChange)(PWSTR ServerName,
|
||
|
PWSTR AdapterName,
|
||
|
BOOL IsNewIpAddress,
|
||
|
DWORD IpIndex,
|
||
|
DWORD IpAddress,
|
||
|
DWORD SubnetMask,
|
||
|
SERVICE_ENABLE DhcpServiceEnabled);
|
||
|
|
||
|
//
|
||
|
// CTcpipcfg::HrCallDhcpConfig
|
||
|
//
|
||
|
// Sets the IP address on the fly (without re-booting)
|
||
|
//
|
||
|
// ServerName always set to NULL
|
||
|
// AdapterName the adapter BindPathName to tcpip
|
||
|
// IsNewIpAddress set to TRUE if Dhcp->Static or Statis->Static changes
|
||
|
// set to FALSE if Static->Dhcp changes
|
||
|
//
|
||
|
//
|
||
|
// IpIndex the index of the IP Address for the card
|
||
|
// adapters can have more than 1 IP Address
|
||
|
// (as seen in the Advanced dialog)
|
||
|
// (this is causing problem for Munil
|
||
|
// because the use of this index is buggy in his code
|
||
|
// index is always set to 0 if there is only one IP Address
|
||
|
// for the card
|
||
|
//
|
||
|
// IpAddress the new IP Address
|
||
|
// SubnetMask the new SubnetMask
|
||
|
//
|
||
|
// DhcpServiceEnabled enum type, can be set to :
|
||
|
// DhcpEnable -> if DHCP was disabled,
|
||
|
// but now being changed to enabled
|
||
|
// IgnoreFlag -> DHCP was disabled and is still disabled
|
||
|
// DhcpDisable -> DHCP was enabled, but now being changed
|
||
|
// to disabled
|
||
|
//
|
||
|
// For extra reference talk to Munil -> these parameters correspond to the
|
||
|
// DhcpNotifyConfigChange API of the dhcpcsvc.dll file
|
||
|
//
|
||
|
|
||
|
HRESULT CTcpipcfg::HrCallDhcpConfig(PWSTR ServerName,
|
||
|
PWSTR AdapterName,
|
||
|
GUID & guidAdaputer,
|
||
|
BOOL IsNewIpAddress,
|
||
|
DWORD IpIndex,
|
||
|
DWORD IpAddress,
|
||
|
DWORD SubnetMask,
|
||
|
SERVICE_ENABLE DhcpServiceEnabled)
|
||
|
{
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
// Make sure TCP/IP is running.
|
||
|
// Scoping brackets cause service and service controller to be
|
||
|
// closed when we don't need them anymore.
|
||
|
{
|
||
|
CServiceManager smng;
|
||
|
CService serv;
|
||
|
|
||
|
hr = smng.HrOpenService(&serv, c_szTcpip, NO_LOCK,
|
||
|
SC_MANAGER_CONNECT, SERVICE_QUERY_STATUS);
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
DWORD dwState;
|
||
|
|
||
|
hr = serv.HrQueryState(&dwState);
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
if(dwState != SERVICE_RUNNING)
|
||
|
{
|
||
|
//TCPIP must always be running if installed!!!
|
||
|
AssertSz(FALSE, "Tcpip service must always be running if installed!");
|
||
|
hr = E_FAIL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
HMODULE hDll;
|
||
|
FARPROC pDhcpConfig;
|
||
|
hr = HrLoadLibAndGetProc (L"dhcpcsvc.dll",
|
||
|
"DhcpNotifyConfigChange",
|
||
|
&hDll, &pDhcpConfig);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
TraceTag(ttidTcpip,"Begin calling DhcpNotifyConfigChange...");
|
||
|
|
||
|
// Parameter dump for debugging
|
||
|
TraceTag(ttidTcpip, "[DhcpNotifyConfigChange] ServerName:%S", ServerName);
|
||
|
TraceTag(ttidTcpip, "[DhcpNotifyConfigChange] AdapterName:%S", AdapterName);
|
||
|
TraceTag(ttidTcpip, "[DhcpNotifyConfigChange] IsNewIpAddress:%d", IsNewIpAddress);
|
||
|
TraceTag(ttidTcpip, "[DhcpNotifyConfigChange] IpIndex:%d", IpIndex);
|
||
|
TraceTag(ttidTcpip, "[DhcpNotifyConfigChange] IpAddress:%d", IpAddress);
|
||
|
TraceTag(ttidTcpip, "[DhcpNotifyConfigChange] SubnetMask:%d", SubnetMask);
|
||
|
TraceTag(ttidTcpip, "[DhcpNotifyConfigChange] DhcpServiceEnabled:%d", DhcpServiceEnabled);
|
||
|
|
||
|
DWORD dwError;
|
||
|
|
||
|
dwError = (*(T_DhcpNotifyConfigChange)pDhcpConfig)(
|
||
|
ServerName,
|
||
|
AdapterName,
|
||
|
IsNewIpAddress,
|
||
|
IpIndex,
|
||
|
IpAddress,
|
||
|
SubnetMask,
|
||
|
DhcpServiceEnabled);
|
||
|
|
||
|
TraceTag(ttidTcpip,"Finished calling DhcpNotifyConfigChange...");
|
||
|
hr = HRESULT_FROM_WIN32(dwError);
|
||
|
|
||
|
if FAILED(hr)
|
||
|
{
|
||
|
// Added as part of fix for #107373
|
||
|
if (ERROR_DUP_NAME == dwError)
|
||
|
{
|
||
|
// Warn the user about duplicate IP address
|
||
|
NcMsgBox(::GetActiveWindow(), IDS_MSFT_TCP_TEXT,
|
||
|
IDS_DUP_NETIP, MB_APPLMODAL | MB_ICONEXCLAMATION | MB_OK);
|
||
|
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else if (ERROR_FILE_NOT_FOUND == dwError)
|
||
|
{
|
||
|
// The adapter we want to reconfig is not connected
|
||
|
TraceTag(ttidTcpip, "The adater is disconnected or not bound to TCP/IP.");
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else if (STATUS_DUPLICATE_OBJECTID == dwError)
|
||
|
{
|
||
|
// fix for 320797
|
||
|
TraceTag(ttidTcpip, "The address is already configured for the adapter");
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else if (ERROR_INVALID_DRIVE == dwError)
|
||
|
{
|
||
|
// fix for 320797
|
||
|
TraceTag(ttidTcpip, "The address has already been deleted from the stack");
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TraceError("Error on DhcpNotifyConfigChange from dhcpcsvc.dll", hr);
|
||
|
|
||
|
FARPROC pfnHrGetPnpDeviceStatus = NULL;
|
||
|
HRESULT hrTmp = S_OK;
|
||
|
HMODULE hNetman = NULL;
|
||
|
NETCON_STATUS ncStatus = NCS_CONNECTED;
|
||
|
hrTmp = HrLoadLibAndGetProc(L"netman.dll", "HrGetPnpDeviceStatus",
|
||
|
&hNetman, &pfnHrGetPnpDeviceStatus);
|
||
|
|
||
|
if (SUCCEEDED(hrTmp))
|
||
|
{
|
||
|
Assert(pfnHrGetPnpDeviceStatus);
|
||
|
hrTmp = (*(PHRGETPNPDEVICESTATUS)pfnHrGetPnpDeviceStatus)(
|
||
|
&guidAdaputer,
|
||
|
&ncStatus);
|
||
|
FreeLibrary(hNetman);
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hrTmp) && NCS_MEDIA_DISCONNECTED == ncStatus)
|
||
|
{
|
||
|
TraceTag(ttidTcpip, "The connection is media disconnected. Do not need to reboot");
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Mask the specific error so NCPA does not fail.
|
||
|
hr = NETCFG_S_REBOOT;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FreeLibrary (hDll);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
TraceError("CTcpipcfg::HrCallDhcpConfig", hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
typedef DWORD (WINAPI * PFNDhcpHandlePnPEvent) (
|
||
|
IN DWORD Flags,
|
||
|
IN DWORD Caller,
|
||
|
IN PWSTR AdapterName,
|
||
|
IN LPDHCP_PNP_CHANGE Changes,
|
||
|
IN LPVOID Reserved
|
||
|
);
|
||
|
|
||
|
HRESULT CTcpipcfg::HrCallDhcpHandlePnPEvent(ADAPTER_INFO * pAdapterInfo,
|
||
|
LPDHCP_PNP_CHANGE pDhcpPnpChange)
|
||
|
{
|
||
|
// load the dll and get function pointer
|
||
|
HMODULE hDll;
|
||
|
FARPROC pDhcpHandlePnPEvent;
|
||
|
HRESULT hr = HrLoadLibAndGetProc (L"dhcpcsvc.dll",
|
||
|
"DhcpHandlePnPEvent",
|
||
|
&hDll, &pDhcpHandlePnPEvent);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
TraceTag(ttidTcpip, "[DhcpHandlePnPEvent] Flags: 0");
|
||
|
TraceTag(ttidTcpip, "[DhcpHandlePnPEvent] Caller: DHCP_CALLER_TCPUI");
|
||
|
TraceTag(ttidTcpip, "[DhcpHandlePnPEvent] AdapterName: %S", pAdapterInfo->m_strBindName.c_str());
|
||
|
TraceTag(ttidTcpip, "[DhcpHandlePnPEvent] Changes.DnsListChanged: %d", pDhcpPnpChange->DnsListChanged);
|
||
|
TraceTag(ttidTcpip, "[DhcpHandlePnPEvent] Changes.DomainChanged: %d", pDhcpPnpChange->DomainChanged);
|
||
|
TraceTag(ttidTcpip, "[DhcpHandlePnPEvent] Changes.ClassIdChanged: %d", pDhcpPnpChange->ClassIdChanged);
|
||
|
|
||
|
DWORD dwRet = (*(PFNDhcpHandlePnPEvent)pDhcpHandlePnPEvent)(
|
||
|
0,
|
||
|
DHCP_CALLER_TCPUI,
|
||
|
(PWSTR)pAdapterInfo->m_strBindName.c_str(),
|
||
|
pDhcpPnpChange,
|
||
|
NULL);
|
||
|
|
||
|
hr = HRESULT_FROM_WIN32(dwRet);
|
||
|
|
||
|
if (ERROR_FILE_NOT_FOUND == dwRet)
|
||
|
{
|
||
|
// The adapter we want to reconfig is not connected
|
||
|
TraceTag(ttidTcpip, "DhcpHandlePnPEvent returns ERROR_FILE_NOT_FOUND. The adater is disconnected or not bound to TCP/IP.");
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
FreeLibrary (hDll);
|
||
|
}
|
||
|
|
||
|
TraceError("CTcpipcfg::HrCallDhcpHandlePnPEvent", hr);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
typedef DWORD (WINAPI * PFDhcpFallbackRefreshParams) (
|
||
|
IN LPWSTR AdapterName
|
||
|
);
|
||
|
|
||
|
HRESULT CTcpipcfg::HrDhcpRefreshFallbackParams(ADAPTER_INFO * pAdapterInfo)
|
||
|
{
|
||
|
// load the dll and get function pointer
|
||
|
HMODULE hDll;
|
||
|
FARPROC pDhcpFallbackRefreshParams;
|
||
|
HRESULT hr = HrLoadLibAndGetProc (L"dhcpcsvc.dll",
|
||
|
"DhcpFallbackRefreshParams",
|
||
|
&hDll, &pDhcpFallbackRefreshParams);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
TraceTag(ttidTcpip, "[DhcpFallbackRefreshParams] AdapterName: %S", pAdapterInfo->m_strBindName.c_str());
|
||
|
DWORD dwRet = (*(PFDhcpFallbackRefreshParams)pDhcpFallbackRefreshParams)(
|
||
|
(LPWSTR)pAdapterInfo->m_strBindName.c_str()
|
||
|
);
|
||
|
|
||
|
hr = HRESULT_FROM_WIN32(dwRet);
|
||
|
|
||
|
if (ERROR_FILE_NOT_FOUND == dwRet)
|
||
|
{
|
||
|
// The adapter we want to reconfig is not connected
|
||
|
TraceTag(ttidTcpip, "DhcpFallbackRefreshParams returns ERROR_FILE_NOT_FOUND. The adater is disconnected or not bound to TCP/IP.");
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
FreeLibrary (hDll);
|
||
|
}
|
||
|
|
||
|
TraceError("CTcpipcfg::HrDhcpRefreshFallbackParams", hr);
|
||
|
return hr;
|
||
|
}
|