Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

4544 lines
109 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997 - 2000
//
// File: H N E T C O N N . C P P
//
// Contents: CHNetConn implementation
//
// Notes:
//
// Author: jonburs 23 May 2000
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
//
// Prototype for iphlpapi routine. For some reason, this isn't defined
// in any header.
//
extern "C"
DWORD
APIENTRY
SetAdapterIpAddress(LPSTR AdapterName,
BOOL EnableDHCP,
ULONG IPAddress,
ULONG SubnetMask,
ULONG DefaultGateway
);
//
// CLSIDs for connection objects. We don't want to pull in all of the
// other guids that are defined in nmclsid.h, so we copy these
// into here
//
#define INITGUID
#include <guiddef.h>
DEFINE_GUID(CLSID_DialupConnection,
0xBA126AD7,0x2166,0x11D1,0xB1,0xD0,0x00,0x80,0x5F,0xC1,0x27,0x0E);
DEFINE_GUID(CLSID_LanConnection,
0xBA126ADB,0x2166,0x11D1,0xB1,0xD0,0x00,0x80,0x5F,0xC1,0x27,0x0E);
#undef INITGUID
//
// ATL Methods
//
HRESULT
CHNetConn::FinalConstruct()
{
HRESULT hr = S_OK;
m_bstrWQL = SysAllocString(c_wszWQL);
if (NULL == m_bstrWQL)
{
hr = E_OUTOFMEMORY;
}
return hr;
}
HRESULT
CHNetConn::FinalRelease()
{
if (m_piwsHomenet) m_piwsHomenet->Release();
if (m_bstrConnection) SysFreeString(m_bstrConnection);
if (m_bstrProperties) SysFreeString(m_bstrProperties);
if (m_pNetConn) m_pNetConn->Release();
if (m_bstrWQL) SysFreeString(m_bstrWQL);
if (m_wszName) CoTaskMemFree(m_wszName);
if (m_pGuid) CoTaskMemFree(m_pGuid);
if (m_pNetConnUiUtil) m_pNetConnUiUtil->Release();
if (m_pNetConnHNetUtil) m_pNetConnHNetUtil->Release();
if (m_pNetConnRefresh) m_pNetConnRefresh->Release();
return S_OK;
}
//
// Ojbect initialization
//
HRESULT
CHNetConn::Initialize(
IWbemServices *piwsNamespace,
IWbemClassObject *pwcoProperties
)
{
HRESULT hr = S_OK;
IWbemClassObject *pwcoConnection;
VARIANT vt;
_ASSERT(NULL == m_piwsHomenet);
_ASSERT(NULL == m_bstrProperties);
_ASSERT(NULL == m_bstrConnection);
_ASSERT(NULL != piwsNamespace);
_ASSERT(NULL != pwcoProperties);
//
// Store pointer to our namespace.
//
m_piwsHomenet = piwsNamespace;
m_piwsHomenet->AddRef();
//
// Get the path to the properties
//
hr = GetWmiPathFromObject(pwcoProperties, &m_bstrProperties);
if (WBEM_S_NO_ERROR == hr)
{
//
// Get the path to the HNet_Connection from our properties
//
hr = pwcoProperties->Get(
c_wszConnection,
0,
&vt,
NULL,
NULL
);
}
if (WBEM_S_NO_ERROR == hr)
{
_ASSERT(VT_BSTR == V_VT(&vt));
m_bstrConnection = V_BSTR(&vt);
//
// BSTR ownership transfered to object
//
VariantInit(&vt);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Get the underying connection object
//
hr = GetConnectionObject(&pwcoConnection);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// See if this is a lan connection
//
hr = GetBooleanValue(
pwcoConnection,
c_wszIsLanConnection,
&m_fLanConnection
);
pwcoConnection->Release();
}
return hr;
}
HRESULT
CHNetConn::InitializeFromConnection(
IWbemServices *piwsNamespace,
IWbemClassObject *pwcoConnection
)
{
HRESULT hr = S_OK;
BSTR bstr;
IEnumWbemClassObject *pwcoEnum;
IWbemClassObject *pwcoProperties;
_ASSERT(NULL == m_piwsHomenet);
_ASSERT(NULL == m_bstrConnection);
_ASSERT(NULL == m_bstrProperties);
_ASSERT(NULL != piwsNamespace);
_ASSERT(NULL != pwcoConnection);
//
// Store pointer to our namespace.
//
m_piwsHomenet = piwsNamespace;
m_piwsHomenet->AddRef();
//
// Get the path to our connection
//
hr = GetWmiPathFromObject(pwcoConnection, &m_bstrConnection);
if (WBEM_S_NO_ERROR == hr)
{
//
// Get the HNet_ConnectionProperties for our connection and
// store its path
//
hr = GetPropInstanceFromConnInstance(
piwsNamespace,
pwcoConnection,
&pwcoProperties
);
if (WBEM_S_NO_ERROR == hr)
{
hr = GetWmiPathFromObject(pwcoProperties, &m_bstrProperties);
pwcoProperties->Release();
}
}
if (WBEM_S_NO_ERROR == hr)
{
//
// See if this is a lan connection
//
hr = GetBooleanValue(
pwcoConnection,
c_wszIsLanConnection,
&m_fLanConnection
);
}
return hr;
}
HRESULT
CHNetConn::InitializeFromInstances(
IWbemServices *piwsNamespace,
IWbemClassObject *pwcoConnection,
IWbemClassObject *pwcoProperties
)
{
HRESULT hr;
_ASSERT(NULL == m_piwsHomenet);
_ASSERT(NULL == m_bstrConnection);
_ASSERT(NULL == m_bstrProperties);
_ASSERT(NULL != piwsNamespace);
_ASSERT(NULL != pwcoConnection);
_ASSERT(NULL != pwcoProperties);
m_piwsHomenet = piwsNamespace;
m_piwsHomenet->AddRef();
hr = GetWmiPathFromObject(pwcoConnection, &m_bstrConnection);
if (WBEM_S_NO_ERROR == hr)
{
hr = GetWmiPathFromObject(pwcoProperties, &m_bstrProperties);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = GetBooleanValue(
pwcoConnection,
c_wszIsLanConnection,
&m_fLanConnection
);
}
return hr;
}
HRESULT
CHNetConn::InitializeFull(
IWbemServices *piwsNamespace,
BSTR bstrConnection,
BSTR bstrProperties,
BOOLEAN fLanConnection
)
{
HRESULT hr = S_OK;
_ASSERT(NULL == m_piwsHomenet);
_ASSERT(NULL == m_bstrConnection);
_ASSERT(NULL == m_bstrProperties);
_ASSERT(NULL != piwsNamespace);
_ASSERT(NULL != bstrConnection);
_ASSERT(NULL != bstrProperties);
m_piwsHomenet = piwsNamespace;
m_piwsHomenet->AddRef();
m_fLanConnection = fLanConnection;
m_bstrConnection = SysAllocString(bstrConnection);
if (NULL != m_bstrConnection)
{
m_bstrProperties = SysAllocString(bstrProperties);
if (NULL == m_bstrProperties)
{
hr = E_OUTOFMEMORY;
}
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}
HRESULT
CHNetConn::SetINetConnection(
INetConnection *pConn
)
{
Lock();
_ASSERT(NULL == m_pNetConn);
_ASSERT(NULL != pConn);
m_pNetConn = pConn;
m_pNetConn->AddRef();
Unlock();
return S_OK;
}
//
// IHNetConnection methods
//
STDMETHODIMP
CHNetConn::GetINetConnection(
INetConnection **ppNetConnection
)
{
HRESULT hr = S_OK;
GUID *pGuid;
if (NULL != ppNetConnection)
{
*ppNetConnection = NULL;
}
else
{
hr = E_POINTER;
}
if (S_OK == hr)
{
Lock();
if (NULL != m_pNetConn)
{
//
// We've already cached away a pointer.
//
*ppNetConnection = m_pNetConn;
(*ppNetConnection)->AddRef();
}
else
{
//
// We don't have a cached pointer. Create the correct
// connection object type and initialize appropriately.
//
hr = GetGuidInternal(&pGuid);
if (S_OK == hr)
{
if (m_fLanConnection)
{
INetLanConnection *pLanConnection;
hr = CoCreateInstance(
CLSID_LanConnection,
NULL,
CLSCTX_SERVER,
IID_PPV_ARG(INetLanConnection, &pLanConnection)
);
if (SUCCEEDED(hr))
{
LANCON_INFO lanInfo;
//
// We must set the proxy blanket on the object we just
// created.
//
SetProxyBlanket(pLanConnection);
//
// We don't need to include the name to initialize
// a LAN connection -- the guid is sufficient.
//
lanInfo.szwConnName = NULL;
lanInfo.fShowIcon = TRUE;
lanInfo.guid = *pGuid;
hr = pLanConnection->SetInfo(
LCIF_COMP,
&lanInfo
);
if (SUCCEEDED(hr))
{
hr = pLanConnection->QueryInterface(
IID_PPV_ARG(
INetConnection,
ppNetConnection
)
);
if (SUCCEEDED(hr))
{
SetProxyBlanket(*ppNetConnection);
}
}
pLanConnection->Release();
}
}
else
{
INetRasConnection *pRasConnection;
hr = CoCreateInstance(
CLSID_DialupConnection,
NULL,
CLSCTX_SERVER,
IID_PPV_ARG(INetRasConnection, &pRasConnection)
);
if (SUCCEEDED(hr))
{
OLECHAR *pszwName;
OLECHAR *pszwPath;
//
// We must set the proxy blanket on the object we just
// created.
//
SetProxyBlanket(pRasConnection);
//
// We need to obtain the name and path of a RAS
// connection in order to initialize it.
//
hr = GetRasConnectionName(&pszwName);
if (S_OK == hr)
{
hr = GetRasPhonebookPath(&pszwPath);
if (S_OK == hr)
{
RASCON_INFO rasInfo;
rasInfo.pszwPbkFile = pszwPath;
rasInfo.pszwEntryName = pszwName;
rasInfo.guidId = *pGuid;
hr = pRasConnection->SetRasConnectionInfo(
&rasInfo
);
if (SUCCEEDED(hr))
{
hr = pRasConnection->QueryInterface(
IID_PPV_ARG(
INetConnection,
ppNetConnection
)
);
if (SUCCEEDED(hr))
{
SetProxyBlanket(*ppNetConnection);
}
}
CoTaskMemFree(pszwPath);
}
CoTaskMemFree(pszwName);
}
pRasConnection->Release();
}
}
if (SUCCEEDED(hr))
{
//
// Cache the connection
//
m_pNetConn = *ppNetConnection;
m_pNetConn->AddRef();
hr = S_OK;
}
}
}
Unlock();
}
return hr;
}
STDMETHODIMP
CHNetConn::GetGuid(
GUID **ppGuid
)
{
HRESULT hr = S_OK;
if (NULL == ppGuid)
{
hr = E_POINTER;
}
if (S_OK == hr)
{
//
// Allocate memory for the guid
//
*ppGuid = reinterpret_cast<GUID*>(
CoTaskMemAlloc(sizeof(GUID))
);
if (NULL == *ppGuid)
{
hr = E_OUTOFMEMORY;
}
}
if (S_OK == hr)
{
GUID *pGuid;
//
// Get our guid
//
hr = GetGuidInternal(&pGuid);
if (SUCCEEDED(hr))
{
CopyMemory(
reinterpret_cast<PVOID>(*ppGuid),
reinterpret_cast<PVOID>(pGuid),
sizeof(GUID)
);
}
else
{
CoTaskMemFree(*ppGuid);
*ppGuid = NULL;
}
}
return hr;
}
STDMETHODIMP
CHNetConn::GetName(
OLECHAR **ppszwName
)
{
HRESULT hr = S_OK;
INetConnection *pConn;
NETCON_PROPERTIES *pProps;
OLECHAR *pszwOldName = NULL;
if (NULL != ppszwName)
{
*ppszwName = NULL;
}
else
{
hr = E_POINTER;
}
if (S_OK == hr)
{
Lock();
hr = GetINetConnection(&pConn);
if (S_OK == hr)
{
hr = pConn->GetProperties(&pProps);
if (SUCCEEDED(hr))
{
pszwOldName = m_wszName;
m_wszName = pProps->pszwName;
//
// We can't call NcFreeNetconProperties, as that
// would free the string pointer we just tucked away.
//
CoTaskMemFree(pProps->pszwDeviceName);
CoTaskMemFree(pProps);
hr = S_OK;
}
pConn->Release();
}
//
// If the new name is not the same as the old name
// store the new name
//
if (S_OK == hr
&& (NULL == pszwOldName
|| 0 != wcscmp(pszwOldName, m_wszName)))
{
IWbemClassObject *pwcoConnection;
HRESULT hr2;
VARIANT vt;
hr2 = GetConnectionObject(&pwcoConnection);
if (WBEM_S_NO_ERROR == hr2)
{
//
// Write the retrieved name to the store. (While the stored
// name is used only for debugging purposes, it's worth the
// hit to keep it up to date.)
//
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = SysAllocString(m_wszName);
if (NULL != V_BSTR(&vt))
{
hr2 = pwcoConnection->Put(
c_wszName,
0,
&vt,
NULL
);
VariantClear(&vt);
if (WBEM_S_NO_ERROR == hr2)
{
m_piwsHomenet->PutInstance(
pwcoConnection,
WBEM_FLAG_UPDATE_ONLY,
NULL,
NULL
);
}
}
pwcoConnection->Release();
}
}
if (S_OK == hr)
{
ULONG ulSize = (wcslen(m_wszName) + 1) * sizeof(OLECHAR);
*ppszwName = reinterpret_cast<OLECHAR*>(
CoTaskMemAlloc(ulSize)
);
if (NULL != *ppszwName)
{
CopyMemory(
reinterpret_cast<PVOID>(*ppszwName),
reinterpret_cast<PVOID>(m_wszName),
ulSize
);
}
else
{
hr = E_OUTOFMEMORY;
}
}
Unlock();
}
if (NULL != pszwOldName)
{
CoTaskMemFree(pszwOldName);
}
return hr;
}
STDMETHODIMP
CHNetConn::GetRasPhonebookPath(
OLECHAR **ppszwPath
)
{
HRESULT hr = S_OK;
VARIANT vt;
IWbemClassObject *pwcoConnection;
if (NULL != ppszwPath)
{
*ppszwPath = NULL;
}
else
{
hr = E_POINTER;
}
if (TRUE == m_fLanConnection)
{
hr = E_UNEXPECTED;
}
if (S_OK == hr)
{
hr = GetConnectionObject(&pwcoConnection);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = pwcoConnection->Get(
c_wszPhonebookPath,
0,
&vt,
NULL,
NULL
);
pwcoConnection->Release();
}
if (WBEM_S_NO_ERROR == hr)
{
_ASSERT(VT_BSTR == V_VT(&vt));
*ppszwPath = reinterpret_cast<OLECHAR*>(
CoTaskMemAlloc((SysStringLen(V_BSTR(&vt)) + 1)
* sizeof(OLECHAR))
);
if (NULL != *ppszwPath)
{
wcscpy(*ppszwPath, V_BSTR(&vt));
}
else
{
hr = E_OUTOFMEMORY;
}
VariantClear(&vt);
}
return hr;
}
STDMETHODIMP
CHNetConn::GetProperties(
HNET_CONN_PROPERTIES **ppProperties
)
{
HRESULT hr = S_OK;
IWbemClassObject *pwcoProperties;
if (NULL == ppProperties)
{
hr = E_POINTER;
}
else
{
*ppProperties = reinterpret_cast<HNET_CONN_PROPERTIES*>(
CoTaskMemAlloc(sizeof(HNET_CONN_PROPERTIES))
);
if (NULL == *ppProperties)
{
hr = E_OUTOFMEMORY;
}
}
if (S_OK == hr)
{
hr = GetConnectionPropertiesObject(&pwcoProperties);
if (WBEM_S_NO_ERROR == hr)
{
hr = InternalGetProperties(pwcoProperties, *ppProperties);
pwcoProperties->Release();
}
if (FAILED(hr))
{
CoTaskMemFree(*ppProperties);
*ppProperties = NULL;
}
}
return hr;
}
STDMETHODIMP
CHNetConn::GetControlInterface(
REFIID iid,
void **ppv
)
{
HRESULT hr = S_OK;
HNET_CONN_PROPERTIES Props;
if (NULL != ppv)
{
*ppv = NULL;
}
else
{
hr = E_POINTER;
}
if (S_OK == hr)
{
//
// See if a simple QI will produce the desired interface
//
hr = QueryInterface(iid, ppv);
if (FAILED(hr))
{
//
// Nope. Get our properties and see if it's appropriate to
// provide the requested control interface.
//
IWbemClassObject *pwcoProperties;
hr = GetConnectionPropertiesObject(&pwcoProperties);
if (WBEM_S_NO_ERROR == hr)
{
hr = InternalGetProperties(pwcoProperties, &Props);
pwcoProperties->Release();
}
if (S_OK == hr)
{
if (IsEqualGUID(
__uuidof(IHNetFirewalledConnection),
iid
))
{
if (TRUE == Props.fFirewalled)
{
CComObject<CHNFWConn> *pfwConn;
hr = CComObject<CHNFWConn>::CreateInstance(&pfwConn);
if (SUCCEEDED(hr))
{
pfwConn->AddRef();
hr = pfwConn->InitializeFull(
m_piwsHomenet,
m_bstrConnection,
m_bstrProperties,
m_fLanConnection
);
if (SUCCEEDED(hr))
{
hr = pfwConn->QueryInterface(iid, ppv);
}
pfwConn->Release();
}
}
else
{
hr = E_NOINTERFACE;
}
}
else if (IsEqualGUID(
__uuidof(IHNetIcsPublicConnection),
iid
))
{
if (TRUE == Props.fIcsPublic)
{
CComObject<CHNIcsPublicConn> *pIcsPubConn;
hr = CComObject<CHNIcsPublicConn>::CreateInstance(&pIcsPubConn);
if (SUCCEEDED(hr))
{
pIcsPubConn->AddRef();
hr = pIcsPubConn->InitializeFull(
m_piwsHomenet,
m_bstrConnection,
m_bstrProperties,
m_fLanConnection
);
if (SUCCEEDED(hr))
{
hr = pIcsPubConn->QueryInterface(iid, ppv);
}
pIcsPubConn->Release();
}
}
else
{
hr = E_NOINTERFACE;
}
}
else if (IsEqualGUID(
__uuidof(IHNetIcsPrivateConnection),
iid
))
{
if (TRUE == Props.fIcsPrivate)
{
CComObject<CHNIcsPrivateConn> *pIcsPrvConn;
hr = CComObject<CHNIcsPrivateConn>::CreateInstance(&pIcsPrvConn);
if (SUCCEEDED(hr))
{
pIcsPrvConn->AddRef();
hr = pIcsPrvConn->InitializeFull(
m_piwsHomenet,
m_bstrConnection,
m_bstrProperties,
m_fLanConnection
);
if (SUCCEEDED(hr))
{
hr = pIcsPrvConn->QueryInterface(iid, ppv);
}
pIcsPrvConn->Release();
}
}
else
{
hr = E_NOINTERFACE;
}
}
else if (IsEqualGUID(
__uuidof(IHNetBridge),
iid
))
{
if (TRUE == Props.fBridge)
{
CComObject<CHNBridge> *pBridge;
hr = CComObject<CHNBridge>::CreateInstance(&pBridge);
if (SUCCEEDED(hr))
{
pBridge->AddRef();
hr = pBridge->InitializeFull(
m_piwsHomenet,
m_bstrConnection,
m_bstrProperties,
m_fLanConnection
);
if (SUCCEEDED(hr))
{
hr = pBridge->QueryInterface(iid, ppv);
}
pBridge->Release();
}
}
else
{
hr = E_NOINTERFACE;
}
}
else if (IsEqualGUID(
__uuidof(IHNetBridgedConnection),
iid
))
{
if (TRUE == Props.fPartOfBridge)
{
CComObject<CHNBridgedConn> *pBridgeConn;
hr = CComObject<CHNBridgedConn>::CreateInstance(&pBridgeConn);
if (SUCCEEDED(hr))
{
pBridgeConn->AddRef();
hr = pBridgeConn->InitializeFull(
m_piwsHomenet,
m_bstrConnection,
m_bstrProperties,
m_fLanConnection
);
if (SUCCEEDED(hr))
{
hr = pBridgeConn->QueryInterface(iid, ppv);
}
pBridgeConn->Release();
}
}
else
{
hr = E_NOINTERFACE;
}
}
else
{
//
// Unknown control interface
//
hr = E_NOINTERFACE;
}
}
}
}
return hr;
}
STDMETHODIMP
CHNetConn::Firewall(
IHNetFirewalledConnection **ppFirewalledConn
)
{
HRESULT hr = S_OK;
HNET_CONN_PROPERTIES hnProps;
IWbemClassObject *pwcoProperties;
if (NULL == ppFirewalledConn)
{
hr = E_POINTER;
}
else
{
*ppFirewalledConn = NULL;
//
// We fail immediately if firewalling is prohibited by policy,
// or if the NAT routing protocol is installed.
//
if (ProhibitedByPolicy(NCPERM_PersonalFirewallConfig))
{
hr = HN_E_POLICY;
}
if (IsRoutingProtocolInstalled(MS_IP_NAT))
{
hr = HRESULT_FROM_WIN32(ERROR_SHARING_RRAS_CONFLICT);
}
}
if (S_OK == hr)
{
hr = GetConnectionPropertiesObject(&pwcoProperties);
}
if (S_OK == hr)
{
hr = InternalGetProperties(pwcoProperties, &hnProps);
if (S_OK == hr)
{
if (FALSE == hnProps.fCanBeFirewalled || TRUE == hnProps.fFirewalled)
{
hr = E_UNEXPECTED;
}
else
{
//
// Set the firewalled property to true
//
hr = SetBooleanValue(
pwcoProperties,
c_wszIsFirewalled,
TRUE
);
}
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Write the modified instance to the store
//
hr = m_piwsHomenet->PutInstance(
pwcoProperties,
WBEM_FLAG_UPDATE_ONLY,
NULL,
NULL
);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Inform netman that something changed. Error doesn't matter.
//
UpdateNetman();
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Create the new object
//
CComObject<CHNFWConn> *pfwConn;
hr = CComObject<CHNFWConn>::CreateInstance(&pfwConn);
if (SUCCEEDED(hr))
{
pfwConn->AddRef();
hr = pfwConn->InitializeFull(
m_piwsHomenet,
m_bstrConnection,
m_bstrProperties,
m_fLanConnection
);
if (SUCCEEDED(hr))
{
hr = pfwConn->QueryInterface(
IID_PPV_ARG(IHNetFirewalledConnection, ppFirewalledConn)
);
}
pfwConn->Release();
}
}
pwcoProperties->Release();
}
if (S_OK == hr)
{
//
// Make sure the service is started
//
DWORD dwError = StartOrUpdateService();
if (NO_ERROR != dwError)
{
(*ppFirewalledConn)->Unfirewall();
(*ppFirewalledConn)->Release();
*ppFirewalledConn = NULL;
hr = HRESULT_FROM_WIN32(dwError);
}
RefreshNetConnectionsUI();
}
return hr;
}
STDMETHODIMP
CHNetConn::SharePublic(
IHNetIcsPublicConnection **ppIcsPublicConn
)
{
HRESULT hr = S_OK;
HNET_CONN_PROPERTIES hnProps;
IWbemClassObject *pwcoProperties;
if (NULL == ppIcsPublicConn)
{
hr = E_POINTER;
}
else
{
*ppIcsPublicConn = NULL;
//
// We fail immediately if sharing is prohibited by policy,
// or if the NAT routing protocol is installed.
//
if (ProhibitedByPolicy(NCPERM_ShowSharedAccessUi))
{
hr = HN_E_POLICY;
}
if (IsRoutingProtocolInstalled(MS_IP_NAT))
{
hr = HRESULT_FROM_WIN32(ERROR_SHARING_RRAS_CONFLICT);
}
}
if (S_OK == hr)
{
hr = GetConnectionPropertiesObject(&pwcoProperties);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = InternalGetProperties(pwcoProperties, &hnProps);
if (S_OK == hr)
{
if (FALSE == hnProps.fCanBeIcsPublic || TRUE == hnProps.fIcsPublic)
{
hr = E_UNEXPECTED;
}
else
{
//
// Set the ICS Public property to true
//
hr = SetBooleanValue(
pwcoProperties,
c_wszIsIcsPublic,
TRUE
);
}
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Write the modified instance to the store
//
hr = m_piwsHomenet->PutInstance(
pwcoProperties,
WBEM_FLAG_UPDATE_ONLY,
NULL,
NULL
);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Inform netman that something changed. Error doesn't matter.
//
UpdateNetman();
}
pwcoProperties->Release();
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Create the new object
//
CComObject<CHNIcsPublicConn> *pIcsConn;
hr = CComObject<CHNIcsPublicConn>::CreateInstance(&pIcsConn);
if (SUCCEEDED(hr))
{
pIcsConn->AddRef();
hr = pIcsConn->InitializeFull(
m_piwsHomenet,
m_bstrConnection,
m_bstrProperties,
m_fLanConnection
);
if (SUCCEEDED(hr))
{
hr = pIcsConn->QueryInterface(
IID_PPV_ARG(IHNetIcsPublicConnection, ppIcsPublicConn)
);
}
pIcsConn->Release();
}
}
if (S_OK == hr)
{
//
// Make sure the service is started
//
DWORD dwError = StartOrUpdateService();
if (NO_ERROR != dwError)
{
(*ppIcsPublicConn)->Unshare();
(*ppIcsPublicConn)->Release();
*ppIcsPublicConn = NULL;
hr = HRESULT_FROM_WIN32(dwError);
}
RefreshNetConnectionsUI();
}
if (S_OK == hr && m_fLanConnection)
{
DWORD dwMode;
DWORD dwLength = sizeof(dwMode);
BOOL fResult;
//
// If this is a LAN connection, make sure that WinInet is
// not set to dial always (#143885)
//
fResult =
InternetQueryOption(
NULL,
INTERNET_OPTION_AUTODIAL_MODE,
&dwMode,
&dwLength
);
_ASSERT(TRUE == fResult);
if (fResult && AUTODIAL_MODE_ALWAYS == dwMode)
{
//
// Set the mode to contingent dialing.
//
dwMode = AUTODIAL_MODE_NO_NETWORK_PRESENT;
fResult =
InternetSetOption(
NULL,
INTERNET_OPTION_AUTODIAL_MODE,
&dwMode,
sizeof(dwMode)
);
_ASSERT(TRUE == fResult);
}
}
else if (S_OK == hr)
{
RASAUTODIALENTRYW adEntry;
OLECHAR *pszwName;
HRESULT hr2;
//
// Set this to be the RAS default connection. Errors
// are not propagated to caller.
//
hr2 = GetName(&pszwName);
if (S_OK == hr2)
{
ZeroMemory(&adEntry, sizeof(adEntry));
adEntry.dwSize = sizeof(adEntry);
wcsncpy(
adEntry.szEntry,
pszwName,
sizeof(adEntry.szEntry)/sizeof(WCHAR)
);
RasSetAutodialAddress(
NULL,
0,
&adEntry,
sizeof(adEntry),
1
);
CoTaskMemFree(pszwName);
}
}
return hr;
}
STDMETHODIMP
CHNetConn::SharePrivate(
IHNetIcsPrivateConnection **ppIcsPrivateConn
)
{
HRESULT hr = S_OK;
HNET_CONN_PROPERTIES hnProps;
IWbemClassObject *pwcoProperties;
if (NULL == ppIcsPrivateConn)
{
hr = E_POINTER;
}
else
{
*ppIcsPrivateConn = NULL;
//
// We fail immediately if sharing is prohibited by policy,
// or if the NAT routing protocol is installed.
//
if (ProhibitedByPolicy(NCPERM_ShowSharedAccessUi))
{
hr = HN_E_POLICY;
}
if (IsRoutingProtocolInstalled(MS_IP_NAT))
{
hr = HRESULT_FROM_WIN32(ERROR_SHARING_RRAS_CONFLICT);
}
}
if (S_OK == hr)
{
hr = GetConnectionPropertiesObject(&pwcoProperties);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = InternalGetProperties(pwcoProperties, &hnProps);
if (S_OK == hr)
{
if (FALSE == hnProps.fCanBeIcsPrivate || TRUE == hnProps.fIcsPrivate)
{
hr = E_UNEXPECTED;
}
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Backup current address information
//
hr = BackupIpConfiguration();
}
if (WBEM_S_NO_ERROR == hr)
{
//
// if we are in ICS Upgrade, we don't need
// to setup the private address because dhcp client won't be running in GUI Mode Setup
// and the private tcpip addresses should be upgraded as is.
//
HANDLE hIcsUpgradeEvent = OpenEvent( EVENT_MODIFY_STATE, FALSE, c_wszIcsUpgradeEventName );
if ( NULL != hIcsUpgradeEvent )
{
CloseHandle( hIcsUpgradeEvent );
}
else
{
//
// Setup addressing for private usage
//
hr = SetupConnectionAsPrivateLan();
}
}
if (S_OK == hr)
{
//
// Set the ICS Public property to true
//
hr = SetBooleanValue(
pwcoProperties,
c_wszIsIcsPrivate,
TRUE
);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Write the modified instance to the store
//
hr = m_piwsHomenet->PutInstance(
pwcoProperties,
WBEM_FLAG_UPDATE_ONLY,
NULL,
NULL
);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Inform netman that something changed. Error doesn't matter.
//
UpdateNetman();
}
pwcoProperties->Release();
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Create the new object
//
CComObject<CHNIcsPrivateConn> *pIcsConn;
hr = CComObject<CHNIcsPrivateConn>::CreateInstance(&pIcsConn);
if (SUCCEEDED(hr))
{
pIcsConn->AddRef();
hr = pIcsConn->InitializeFull(
m_piwsHomenet,
m_bstrConnection,
m_bstrProperties,
m_fLanConnection
);
if (SUCCEEDED(hr))
{
hr = pIcsConn->QueryInterface(
IID_PPV_ARG(IHNetIcsPrivateConnection, ppIcsPrivateConn)
);
}
pIcsConn->Release();
}
}
else
{
//
// Restore backup address information
//
RestoreIpConfiguration();
}
if (S_OK == hr)
{
//
// Make sure the service is started
//
DWORD dwError = StartOrUpdateService();
if (NO_ERROR != dwError)
{
(*ppIcsPrivateConn)->RemoveFromIcs();
(*ppIcsPrivateConn)->Release();
*ppIcsPrivateConn = NULL;
hr = HRESULT_FROM_WIN32(dwError);
}
RefreshNetConnectionsUI();
}
return hr;
}
STDMETHODIMP
CHNetConn::EnumPortMappings(
BOOLEAN fEnabledOnly,
IEnumHNetPortMappingBindings **ppEnum
)
{
HRESULT hr = S_OK;
BSTR bstrQuery;
LPWSTR wszWhere;
IEnumWbemClassObject *pwcoEnum;
if (NULL != ppEnum)
{
*ppEnum = NULL;
}
else
{
hr = E_POINTER;
}
if (S_OK == hr && FALSE == fEnabledOnly)
{
//
// Make sure that we have port mapping binding instances for
// all of the port mapping protocols. If we're only enumerating
// enabled protocols, then there's no need for us to create
// anything.
//
hr = CreatePortMappingBindings();
}
if (S_OK == hr)
{
hr = BuildEscapedQuotedEqualsString(
&wszWhere,
c_wszConnection,
m_bstrConnection
);
if (S_OK == hr && fEnabledOnly)
{
LPWSTR wsz;
//
// Add "AND Enabled != FALSE"
//
hr = BuildAndString(
&wsz,
wszWhere,
L"Enabled != FALSE"
);
delete [] wszWhere;
if (S_OK == hr)
{
wszWhere = wsz;
}
}
}
if (S_OK == hr)
{
hr = BuildSelectQueryBstr(
&bstrQuery,
c_wszStar,
c_wszHnetConnectionPortMapping,
wszWhere
);
delete [] wszWhere;
}
if (S_OK == hr)
{
//
// Execute the query and build the enum wrapper
//
pwcoEnum = NULL;
hr = m_piwsHomenet->ExecQuery(
m_bstrWQL,
bstrQuery,
WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pwcoEnum
);
SysFreeString(bstrQuery);
}
if (WBEM_S_NO_ERROR == hr)
{
CComObject<CEnumHNetPortMappingBindings> *pEnum;
hr = CComObject<CEnumHNetPortMappingBindings>::CreateInstance(&pEnum);
if (S_OK == hr)
{
pEnum->AddRef();
hr = pEnum->Initialize(m_piwsHomenet, pwcoEnum);
if (S_OK == hr)
{
hr = pEnum->QueryInterface(
IID_PPV_ARG(IEnumHNetPortMappingBindings, ppEnum)
);
}
pEnum->Release();
}
pwcoEnum->Release();
}
return hr;
}
STDMETHODIMP
CHNetConn::GetBindingForPortMappingProtocol(
IHNetPortMappingProtocol *pProtocol,
IHNetPortMappingBinding **ppBinding
)
{
HRESULT hr = S_OK;
BSTR bstrConPath;
BSTR bstrProtPath;
IWbemClassObject *pwcoInstance;
USHORT usPublicPort;
if (NULL == pProtocol)
{
hr = E_INVALIDARG;
}
else if (NULL == ppBinding)
{
hr = E_POINTER;
}
else
{
*ppBinding = NULL;
}
if (S_OK == hr)
{
hr = pProtocol->GetPort(&usPublicPort);
}
if (S_OK == hr)
{
IHNetPrivate *pHNetPrivate;
//
// Use our private interface to get the path to the
// protocol object
//
hr = pProtocol->QueryInterface(
IID_PPV_ARG(IHNetPrivate, &pHNetPrivate)
);
if (S_OK == hr)
{
hr = pHNetPrivate->GetObjectPath(&bstrProtPath);
pHNetPrivate->Release();
}
}
//
// Retrieve the binding instance for the protocol. If
// it doesn't yet exist, this routine will create it.
//
if (S_OK == hr)
{
hr = GetPortMappingBindingInstance(
m_piwsHomenet,
m_bstrWQL,
m_bstrConnection,
bstrProtPath,
usPublicPort,
&pwcoInstance
);
SysFreeString(bstrProtPath);
}
if (S_OK == hr)
{
CComObject<CHNetPortMappingBinding> *pBinding;
hr = CComObject<CHNetPortMappingBinding>::CreateInstance(&pBinding);
if (S_OK == hr)
{
pBinding->AddRef();
hr = pBinding->Initialize(m_piwsHomenet, pwcoInstance);
if (S_OK == hr)
{
hr = pBinding->QueryInterface(
IID_PPV_ARG(IHNetPortMappingBinding, ppBinding)
);
}
pBinding->Release();
}
pwcoInstance->Release();
}
return hr;
}
STDMETHODIMP
CHNetConn::GetIcmpSettings(
HNET_FW_ICMP_SETTINGS **ppSettings
)
{
HRESULT hr = S_OK;
IWbemClassObject *pwcoSettings;
if (NULL != ppSettings)
{
//
// Allocate output structure
//
*ppSettings = reinterpret_cast<HNET_FW_ICMP_SETTINGS*>(
CoTaskMemAlloc(sizeof(HNET_FW_ICMP_SETTINGS))
);
if (NULL == *ppSettings)
{
hr = E_OUTOFMEMORY;
}
}
else
{
hr = E_POINTER;
}
//
// Retrieve the ICMP setting block for this connection
//
if (S_OK == hr)
{
hr = GetIcmpSettingsInstance(&pwcoSettings);
}
if (S_OK == hr)
{
//
// Copy settings instance to struct
//
hr = CopyIcmpSettingsInstanceToStruct(
pwcoSettings,
*ppSettings
);
pwcoSettings->Release();
}
if (FAILED(hr) && NULL != *ppSettings)
{
CoTaskMemFree(*ppSettings);
*ppSettings = NULL;
}
return hr;
}
STDMETHODIMP
CHNetConn::SetIcmpSettings(
HNET_FW_ICMP_SETTINGS *pSettings
)
{
HRESULT hr = S_OK;
BOOLEAN fNewInstance = FALSE;
VARIANT vt;
IEnumWbemClassObject *pwcoEnum;
IWbemClassObject *pwcoSettings = NULL;
BSTR bstr;
if (NULL == pSettings)
{
hr = E_INVALIDARG;
}
//
// Retrieve the ICMP setting block for this connection
//
if (S_OK == hr)
{
hr = GetIcmpSettingsInstance(&pwcoSettings);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Check to see if we need a new settings instace (i.e.,
// the name of this instance is "Default"
//
hr = pwcoSettings->Get(
c_wszName,
0,
&vt,
NULL,
NULL
);
if (WBEM_S_NO_ERROR == hr)
{
_ASSERT(VT_BSTR == V_VT(&vt));
if (0 == wcscmp(V_BSTR(&vt), c_wszDefault))
{
//
// Need to create new settings block
//
fNewInstance = TRUE;
pwcoSettings->Release();
pwcoSettings = NULL;
}
VariantClear(&vt);
}
else
{
pwcoSettings->Release();
pwcoSettings = NULL;
}
}
if (WBEM_S_NO_ERROR == hr && TRUE == fNewInstance)
{
hr = SpawnNewInstance(
m_piwsHomenet,
c_wszHnetFwIcmpSettings,
&pwcoSettings
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = CopyStructToIcmpSettingsInstance(pSettings, pwcoSettings);
}
if (WBEM_S_NO_ERROR == hr)
{
IWbemCallResult *pResult;
//
// Write the instance to the store
//
pResult = NULL;
hr = m_piwsHomenet->PutInstance(
pwcoSettings,
WBEM_FLAG_CREATE_OR_UPDATE | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pResult
);
if (WBEM_S_NO_ERROR == hr)
{
//
// We need to call GetResultString no matter what so that we
// can get the proper error code if the put failed. However,
// we only need to keep the path if this is a new instance,
// as in that situation we need the path below to create the
// new association object.
//
hr = pResult->GetResultString(WBEM_INFINITE, &bstr);
pResult->Release();
if (FALSE == fNewInstance)
{
SysFreeString(bstr);
bstr = NULL;
}
}
}
if (WBEM_S_NO_ERROR == hr && TRUE == fNewInstance)
{
BSTR bstrQuery;
LPWSTR wsz;
//
// Delete the old association object, if any
//
hr = BuildEscapedQuotedEqualsString(
&wsz,
c_wszConnection,
m_bstrConnection
);
if (S_OK == hr)
{
//
// Query for the object associating the connection to
// the ICMP settings block
//
hr = BuildSelectQueryBstr(
&bstrQuery,
c_wszStar,
c_wszHnetConnectionIcmpSetting,
wsz
);
delete [] wsz;
if (S_OK == hr)
{
pwcoEnum = NULL;
hr = m_piwsHomenet->ExecQuery(
m_bstrWQL,
bstrQuery,
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pwcoEnum
);
SysFreeString(bstrQuery);
}
}
if (WBEM_S_NO_ERROR == hr)
{
ULONG ulCount;
IWbemClassObject *pwcoAssoc;
pwcoAssoc = NULL;
hr = pwcoEnum->Next(
WBEM_INFINITE,
1,
&pwcoAssoc,
&ulCount
);
//
// Enum should be empty at this point
//
ValidateFinishedWCOEnum(m_piwsHomenet, pwcoEnum);
pwcoEnum->Release();
if (SUCCEEDED(hr) && 1 == ulCount)
{
//
// Delete old association object
//
DeleteWmiInstance(m_piwsHomenet, pwcoAssoc);
pwcoAssoc->Release();
}
}
//
// Create new association
//
hr = CreateIcmpSettingsAssociation(bstr);
SysFreeString(bstr);
}
if (SUCCEEDED(hr))
{
//
// Notify service of configuration change
//
UpdateService(IPNATHLP_CONTROL_UPDATE_CONNECTION);
}
if (NULL != pwcoSettings)
{
pwcoSettings->Release();
}
return hr;
}
STDMETHODIMP
CHNetConn::ShowAutoconfigBalloon(
BOOLEAN *pfShowBalloon
)
{
HRESULT hr = S_OK;
BOOLEAN fShowBalloon = FALSE;
BSTR bstrQuery;
LPWSTR wszWhere;
IEnumWbemClassObject *pwcoEnum;
if (NULL != pfShowBalloon)
{
*pfShowBalloon = FALSE;
}
else
{
hr = E_POINTER;
}
//
// Autoconfig balloon is never shown for a RAS connection
//
if (!m_fLanConnection)
{
hr = E_UNEXPECTED;
}
//
// Attempt to locate the HNet_ConnectionAutoconfig block
// for this connection
//
if (S_OK == hr)
{
//
// Build query string:
//
// SELECT * FROM HNet_ConnectionAutoconfig WHERE Connection = [this]
//
hr = BuildEscapedQuotedEqualsString(
&wszWhere,
c_wszConnection,
m_bstrConnection
);
if (S_OK == hr)
{
hr = BuildSelectQueryBstr(
&bstrQuery,
c_wszStar,
c_wszHnetConnectionAutoconfig,
wszWhere
);
delete [] wszWhere;
}
}
if (S_OK == hr)
{
//
// Execute the query
//
pwcoEnum = NULL;
hr = m_piwsHomenet->ExecQuery(
m_bstrWQL,
bstrQuery,
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pwcoEnum
);
SysFreeString(bstrQuery);
}
if (WBEM_S_NO_ERROR == hr)
{
ULONG ulCount;
IWbemClassObject *pwcoInstance;
pwcoInstance = NULL;
hr = pwcoEnum->Next(
WBEM_INFINITE,
1,
&pwcoInstance,
&ulCount
);
//
// Enum should be empty at this point
//
ValidateFinishedWCOEnum(m_piwsHomenet, pwcoEnum);
pwcoEnum->Release();
if (WBEM_S_NO_ERROR == hr && 1 == ulCount)
{
//
// Autoconfig block already exists
//
fShowBalloon = FALSE;
pwcoInstance->Release();
}
else
{
//
// Block doesn't exist -- create it now.
//
fShowBalloon = TRUE;
hr = SpawnNewInstance(
m_piwsHomenet,
c_wszHnetConnectionAutoconfig,
&pwcoInstance
);
if (WBEM_S_NO_ERROR == hr)
{
VARIANT vt;
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = m_bstrConnection;
hr = pwcoInstance->Put(
c_wszConnection,
0,
&vt,
NULL
);
//
// We don't clear the variant as we did not
// copy m_bstrConnection.
//
if (WBEM_S_NO_ERROR == hr)
{
hr = m_piwsHomenet->PutInstance(
pwcoInstance,
WBEM_FLAG_CREATE_ONLY,
NULL,
NULL
);
}
pwcoInstance->Release();
}
}
}
//
// If we think that we should show the balloon, make sure
// that the connection isn't:
// 1. ICS Public
// 2. ICS Private
// 3. Firewalled
// 4. A bridge
// 5. Part of a bridge
//
// If any of the above are true, we must have seen the connection
// before, but just not in a way that would have caused us to
// note it in it's autoconfig settings.
//
if (fShowBalloon)
{
IWbemClassObject *pwcoProperties;
HNET_CONN_PROPERTIES hnProps;
hr = GetConnectionPropertiesObject(&pwcoProperties);
if (S_OK == hr)
{
hr = InternalGetProperties(pwcoProperties, &hnProps);
pwcoProperties->Release();
}
if (S_OK == hr)
{
if (hnProps.fFirewalled
|| hnProps.fIcsPublic
|| hnProps.fIcsPrivate
|| hnProps.fBridge
|| hnProps.fPartOfBridge)
{
fShowBalloon = FALSE;
}
}
}
if (S_OK == hr)
{
*pfShowBalloon = fShowBalloon;
}
return hr;
}
STDMETHODIMP
CHNetConn::DeleteRasConnectionEntry()
{
HRESULT hr = S_OK;
HNET_CONN_PROPERTIES hnProps;
IHNetFirewalledConnection *pHNetFwConnection;
IEnumWbemClassObject *pwcoEnum;
IWbemClassObject *pwcoInstance;
IWbemClassObject *pwcoProperties;
ULONG ulPublic;
ULONG ulPrivate;
BSTR bstr;
if (m_fLanConnection)
{
hr = E_UNEXPECTED;
}
if (SUCCEEDED(hr))
{
hr = GetConnectionPropertiesObject(&pwcoProperties);
}
if (SUCCEEDED(hr))
{
hr = InternalGetProperties(pwcoProperties, &hnProps);
if (SUCCEEDED(hr))
{
if (hnProps.fIcsPublic)
{
CComObject<CHNetCfgMgrChild> *pCfgMgr;
hr = CComObject<CHNetCfgMgrChild>::CreateInstance(&pCfgMgr);
if (SUCCEEDED(hr))
{
pCfgMgr->AddRef();
hr = pCfgMgr->Initialize(m_piwsHomenet);
if (SUCCEEDED(hr))
{
hr = pCfgMgr->DisableIcs(&ulPublic, &ulPrivate);
}
pCfgMgr->Release();
}
}
//
// If an error occured disabling sharing we'll still
// try to disable firewalling.
//
if (hnProps.fFirewalled)
{
hr = GetControlInterface(
IID_PPV_ARG(
IHNetFirewalledConnection,
&pHNetFwConnection
)
);
if (SUCCEEDED(hr))
{
hr = pHNetFwConnection->Unfirewall();
pHNetFwConnection->Release();
}
}
}
pwcoProperties->Release();
//
// Delete the entries relating to this connection. We'll try
// to do this even if any of the above failed. We ignore any
// errors that occur during the deletion prcoess (i.e., from
// Delete[Wmi]Instance).
//
hr = GetIcmpSettingsInstance(&pwcoInstance);
if (SUCCEEDED(hr))
{
//
// We only want to delete this block if it's
// not the default.
//
hr = GetWmiPathFromObject(pwcoInstance, &bstr);
if (SUCCEEDED(hr))
{
if (0 != _wcsicmp(bstr, c_wszDefaultIcmpSettingsPath))
{
m_piwsHomenet->DeleteInstance(
bstr,
0,
NULL,
NULL
);
}
SysFreeString(bstr);
}
pwcoInstance->Release();
}
//
// Now find all object that refer to our conection object.
//
hr = BuildReferencesQueryBstr(
&bstr,
m_bstrConnection,
NULL
);
if (SUCCEEDED(hr))
{
pwcoEnum = NULL;
hr = m_piwsHomenet->ExecQuery(
m_bstrWQL,
bstr,
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pwcoEnum
);
SysFreeString(bstr);
if (SUCCEEDED(hr))
{
ULONG ulCount;
do
{
pwcoInstance = NULL;
hr = pwcoEnum->Next(
WBEM_INFINITE,
1,
&pwcoInstance,
&ulCount
);
if (S_OK == hr && 1 == ulCount)
{
DeleteWmiInstance(
m_piwsHomenet,
pwcoInstance
);
pwcoInstance->Release();
}
}
while (S_OK == hr && 1 == ulCount);
pwcoEnum->Release();
hr = S_OK;
}
}
//
// Finally, delete the connection object. (The connection
// properties object will have been deleted during the
// references set.)
//
hr = m_piwsHomenet->DeleteInstance(
m_bstrConnection,
0,
NULL,
NULL
);
}
return hr;
}
//
// Protected methods
//
HRESULT
CHNetConn::GetIcmpSettingsInstance(
IWbemClassObject **ppwcoSettings
)
{
HRESULT hr = S_OK;
BSTR bstrQuery;
IEnumWbemClassObject *pwcoEnum;
ULONG ulCount;
_ASSERT(NULL != ppwcoSettings);
hr = BuildAssociatorsQueryBstr(
&bstrQuery,
m_bstrConnection,
c_wszHnetConnectionIcmpSetting
);
if (S_OK == hr)
{
pwcoEnum = NULL;
hr = m_piwsHomenet->ExecQuery(
m_bstrWQL,
bstrQuery,
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pwcoEnum
);
SysFreeString(bstrQuery);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Get the settings instance from the enum
//
*ppwcoSettings = NULL;
hr = pwcoEnum->Next(
WBEM_INFINITE,
1,
ppwcoSettings,
&ulCount
);
if (SUCCEEDED(hr) && 1 == ulCount)
{
//
// Normalize return value
//
hr = S_OK;
}
else
{
//
// Settings block not found -- use default settings
//
bstrQuery = SysAllocString(c_wszDefaultIcmpSettingsPath);
if (NULL != bstrQuery)
{
hr = GetWmiObjectFromPath(
m_piwsHomenet,
bstrQuery,
ppwcoSettings
);
SysFreeString(bstrQuery);
}
else
{
hr = E_OUTOFMEMORY;
}
}
//
// Enum should be empty at this point
//
ValidateFinishedWCOEnum(m_piwsHomenet, pwcoEnum);
pwcoEnum->Release();
}
return hr;
}
HRESULT
CHNetConn::CopyIcmpSettingsInstanceToStruct(
IWbemClassObject *pwcoSettings,
HNET_FW_ICMP_SETTINGS *pSettings
)
{
HRESULT hr = S_OK;
_ASSERT(NULL != pwcoSettings);
_ASSERT(NULL != pSettings);
hr = GetBooleanValue(
pwcoSettings,
c_wszAllowOutboundDestinationUnreachable,
&pSettings->fAllowOutboundDestinationUnreachable
);
if (WBEM_S_NO_ERROR == hr)
{
hr = GetBooleanValue(
pwcoSettings,
c_wszAllowOutboundSourceQuench,
&pSettings->fAllowOutboundSourceQuench
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = GetBooleanValue(
pwcoSettings,
c_wszAllowRedirect,
&pSettings->fAllowRedirect
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = GetBooleanValue(
pwcoSettings,
c_wszAllowInboundEchoRequest,
&pSettings->fAllowInboundEchoRequest
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = GetBooleanValue(
pwcoSettings,
c_wszAllowInboundRouterRequest,
&pSettings->fAllowInboundRouterRequest
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = GetBooleanValue(
pwcoSettings,
c_wszAllowOutboundTimeExceeded,
&pSettings->fAllowOutboundTimeExceeded
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = GetBooleanValue(
pwcoSettings,
c_wszAllowOutboundParameterProblem,
&pSettings->fAllowOutboundParameterProblem
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = GetBooleanValue(
pwcoSettings,
c_wszAllowInboundTimestampRequest,
&pSettings->fAllowInboundTimestampRequest
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = GetBooleanValue(
pwcoSettings,
c_wszAllowInboundMaskRequest,
&pSettings->fAllowInboundMaskRequest
);
}
return hr;
}
HRESULT
CHNetConn::CopyStructToIcmpSettingsInstance(
HNET_FW_ICMP_SETTINGS *pSettings,
IWbemClassObject *pwcoSettings
)
{
HRESULT hr = S_OK;
_ASSERT(NULL != pSettings);
_ASSERT(NULL != pwcoSettings);
hr = SetBooleanValue(
pwcoSettings,
c_wszAllowOutboundDestinationUnreachable,
pSettings->fAllowOutboundDestinationUnreachable
);
if (WBEM_S_NO_ERROR == hr)
{
hr = SetBooleanValue(
pwcoSettings,
c_wszAllowOutboundSourceQuench,
pSettings->fAllowOutboundSourceQuench
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = SetBooleanValue(
pwcoSettings,
c_wszAllowRedirect,
pSettings->fAllowRedirect
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = SetBooleanValue(
pwcoSettings,
c_wszAllowInboundEchoRequest,
pSettings->fAllowInboundEchoRequest
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = SetBooleanValue(
pwcoSettings,
c_wszAllowInboundRouterRequest,
pSettings->fAllowInboundRouterRequest
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = SetBooleanValue(
pwcoSettings,
c_wszAllowOutboundTimeExceeded,
pSettings->fAllowOutboundTimeExceeded
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = SetBooleanValue(
pwcoSettings,
c_wszAllowOutboundParameterProblem,
pSettings->fAllowOutboundParameterProblem
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = SetBooleanValue(
pwcoSettings,
c_wszAllowInboundTimestampRequest,
pSettings->fAllowInboundTimestampRequest
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = SetBooleanValue(
pwcoSettings,
c_wszAllowInboundMaskRequest,
pSettings->fAllowInboundMaskRequest
);
}
return hr;
}
HRESULT
CHNetConn::CreatePortMappingBindings()
{
HRESULT hr = S_OK;
BSTR bstr;
IEnumWbemClassObject *pwcoEnumProtocols;
IWbemClassObject *pwcoInstance;
VARIANT vt;
//
// Get the enumeration of all protocol instances
//
bstr = SysAllocString(c_wszHnetPortMappingProtocol);
if (NULL != bstr)
{
pwcoEnumProtocols = NULL;
hr = m_piwsHomenet->CreateInstanceEnum(
bstr,
WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
NULL,
&pwcoEnumProtocols
);
SysFreeString(bstr);
}
else
{
hr = E_OUTOFMEMORY;
}
if (WBEM_S_NO_ERROR == hr)
{
ULONG ulCount;
//
// Loop through the enumeration, checking to see if the desired binding
// exists
//
do
{
pwcoInstance = NULL;
hr = pwcoEnumProtocols->Next(
WBEM_INFINITE,
1,
&pwcoInstance,
&ulCount
);
if (SUCCEEDED(hr) && 1 == ulCount)
{
hr = pwcoInstance->Get(
c_wszPort,
0,
&vt,
NULL,
NULL
);
if (WBEM_S_NO_ERROR == hr)
{
ASSERT(VT_I4 == V_VT(&vt));
hr = GetWmiPathFromObject(pwcoInstance, &bstr);
}
if (WBEM_S_NO_ERROR == hr)
{
IWbemClassObject *pwcoBinding;
hr = GetPortMappingBindingInstance(
m_piwsHomenet,
m_bstrWQL,
m_bstrConnection,
bstr,
static_cast<USHORT>(V_I4(&vt)),
&pwcoBinding
);
SysFreeString(bstr);
if (S_OK == hr)
{
pwcoBinding->Release();
}
else if (WBEM_E_NOT_FOUND == hr)
{
//
// This can occur if the protocol instance is
// deleted after we retrieved it from the enumeration
// but before we created the binding instance. It's
// OK to continue in this situation.
//
hr = S_OK;
}
}
pwcoInstance->Release();
}
} while (SUCCEEDED(hr) && 1 == ulCount);
pwcoEnumProtocols->Release();
}
return SUCCEEDED(hr) ? S_OK : hr;
}
HRESULT
CHNetConn::InternalGetProperties(
IWbemClassObject *pwcoProperties,
HNET_CONN_PROPERTIES *pProperties
)
{
HRESULT hr = S_OK;
_ASSERT(NULL != pwcoProperties);
_ASSERT(NULL != pProperties);
pProperties->fLanConnection = m_fLanConnection;
if (IsServiceRunning(c_wszSharedAccess))
{
hr = GetBooleanValue(
pwcoProperties,
c_wszIsFirewalled,
&pProperties->fFirewalled
);
}
else
{
//
// If the SharedAccess service is not running (or in the process
// of starting up) we don't want to report this connection as
// being firewalled. This is to prevent the confusion that could
// result if the UI indicates the firewall is active, when in
// reality it's not there providing protection.
//
pProperties->fFirewalled = FALSE;
}
if (WBEM_S_NO_ERROR == hr)
{
hr = GetBooleanValue(
pwcoProperties,
c_wszIsIcsPublic,
&pProperties->fIcsPublic
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = GetBooleanValue(
pwcoProperties,
c_wszIsIcsPrivate,
&pProperties->fIcsPrivate
);
}
if (WBEM_S_NO_ERROR == hr)
{
if( m_fLanConnection )
{
//
// Figure out NetCfg-based properties
//
INetCfg *pnetcfg;
hr = CoCreateInstance(
CLSID_CNetCfg,
NULL,
CLSCTX_SERVER,
IID_PPV_ARG(INetCfg, &pnetcfg)
);
if (S_OK == hr)
{
hr = pnetcfg->Initialize( NULL );
if( S_OK == hr )
{
GUID *pguid;
INetCfgComponent *pncfgcomp;
hr = GetGuidInternal(&pguid);
if(S_OK == hr)
{
// Get the NetCfg component that corresponds to us
hr = FindAdapterByGUID( pnetcfg, pguid, &pncfgcomp );
if(S_OK == hr)
{
LPWSTR pszwId;
pncfgcomp->GetId( &pszwId );
if(S_OK == hr)
{
pProperties->fBridge = (BOOLEAN)(_wcsicmp(pszwId, c_wszSBridgeMPID) == 0);
CoTaskMemFree(pszwId);
if( pProperties->fBridge )
{
// This adapter is the bridge. It can't possibly also be a bridge
// member.
pProperties->fPartOfBridge = FALSE;
}
else
{
//
// This adapter is not the bridge. Check if it's part of a bridge.
//
INetCfgComponent *pnetcfgcompBridgeProtocol;
// Find the bridge protocol component
hr = pnetcfg->FindComponent( c_wszSBridgeSID, &pnetcfgcompBridgeProtocol );
if(S_OK == hr)
{
INetCfgComponentBindings *pnetcfgProtocolBindings;
// Get the ComponentBindings interface for the protocol component
hr = pnetcfgcompBridgeProtocol->QueryInterface(
IID_PPV_ARG(INetCfgComponentBindings, &pnetcfgProtocolBindings)
);
if(S_OK == hr)
{
hr = pnetcfgProtocolBindings->IsBoundTo(pncfgcomp);
if(S_OK == hr)
{
// The bridge protocol is bound to this adapter
pProperties->fPartOfBridge = TRUE;
}
else if(S_FALSE == hr)
{
// The bridge protocol is not bound to this adapter
pProperties->fPartOfBridge = FALSE;
// Reset to success
hr = S_OK;
}
// else an error occured
pnetcfgProtocolBindings->Release();
}
pnetcfgcompBridgeProtocol->Release();
}
else
{
// This adapter can't be bridged if there's no bridge protocol
// in the system
pProperties->fPartOfBridge = FALSE;
// Reset to success
hr = S_OK;
}
}
}
pncfgcomp->Release();
}
}
pnetcfg->Uninitialize();
}
pnetcfg->Release();
}
} // if m_fLanConnection
else
{
// We're not a LAN connection. We can never be a bridge or a bridge member.
pProperties->fBridge = FALSE;
pProperties->fPartOfBridge = FALSE;
}
}
if(S_OK == hr)
{
//
// Calculated properties
//
pProperties->fCanBeFirewalled =
!pProperties->fPartOfBridge
&& !pProperties->fBridge
&& !pProperties->fIcsPrivate;
pProperties->fCanBeIcsPublic =
!pProperties->fBridge
&& !pProperties->fPartOfBridge
&& !pProperties->fIcsPrivate;
pProperties->fCanBeIcsPrivate =
m_fLanConnection
&& !pProperties->fIcsPublic
&& !pProperties->fFirewalled
&& !pProperties->fPartOfBridge;
pProperties->fCanBeBridged =
m_fLanConnection
&& !pProperties->fIcsPublic
&& !pProperties->fIcsPrivate
&& !pProperties->fFirewalled
&& !pProperties->fBridge;
}
return hr;
}
HRESULT
CHNetConn::SetupConnectionAsPrivateLan()
{
HRESULT hr;
GUID *pGuid;
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
ULONG Error;
DWORD dwAddress;
DWORD dwMask;
ULONG i;
PMIB_IPADDRTABLE Table;
ZeroMemory(&UnicodeString, sizeof(UnicodeString));
ZeroMemory(&AnsiString, sizeof(AnsiString));
hr = GetGuidInternal(&pGuid);
if (SUCCEEDED(hr))
{
hr = RtlStringFromGUID(*pGuid, &UnicodeString);
if (SUCCEEDED(hr))
{
hr = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, TRUE);
}
}
if (SUCCEEDED(hr))
{
//
// Obtain the address and mask for the private network
//
hr = ReadDhcpScopeSettings(&dwAddress, &dwMask);
}
if (SUCCEEDED(hr))
{
//
// Determine whether some LAN adapter other than the private LAN
// is already using an address in the private network scope.
// In the process, make sure that the private LAN has only one
// IP address (otherwise, 'SetAdapterIpAddress' fails.)
//
Error =
AllocateAndGetIpAddrTableFromStack(
&Table,
FALSE,
GetProcessHeap(),
0
);
if (ERROR_SUCCESS == Error)
{
ULONG Index = 0;
ULONG Count;
hr = MapGuidStringToAdapterIndex(UnicodeString.Buffer, &Index);
if (SUCCEEDED(hr))
{
for (i = 0, Count = 0; i < Table->dwNumEntries; i++)
{
if (Index == Table->table[i].dwIndex)
{
++Count;
}
else if ((Table->table[i].dwAddr & dwMask)
== (dwAddress & dwMask))
{
//
// It appears that some other LAN adapter has an
// address in the proposed scope.
//
// This may happen when multiple netcards go into
// autonet mode or when the RAS server is handing
// out autonet addresses.
//
// Therefore, if we're using the autonet scope,
// allow this behavior; otherwise prohibit it.
//
if ((dwAddress & dwMask) != 0x0000fea9)
{
break;
}
}
}
if (i < Table->dwNumEntries)
{
hr = HRESULT_FROM_WIN32(ERROR_SHARING_ADDRESS_EXISTS);
}
else if (Count > 1)
{
hr = HRESULT_FROM_WIN32(ERROR_SHARING_MULTIPLE_ADDRESSES);
}
}
HeapFree(GetProcessHeap(), 0, Table);
}
else
{
hr = HRESULT_FROM_WIN32(Error);
}
}
//
// Set the predefined static IP address for the private LAN.
//
if (SUCCEEDED(hr))
{
Error =
SetAdapterIpAddress(
AnsiString.Buffer,
FALSE,
dwAddress,
dwMask,
0
);
if (ERROR_SUCCESS != Error)
{
if (Error == ERROR_TOO_MANY_NAMES)
{
Error = ERROR_SHARING_MULTIPLE_ADDRESSES;
}
else if (Error == ERROR_DUP_NAME)
{
Error = ERROR_SHARING_HOST_ADDRESS_CONFLICT;
}
else
{
//
// Query the state of the connection.
// If it is disconnected, convert the error code
// to something more informative.
//
UNICODE_STRING DeviceString;
NIC_STATISTICS NdisStatistics;
LPWSTR pwsz;
//
// Build a buffer large enough for the device string
//
pwsz = new WCHAR[wcslen(c_wszDevice) + wcslen(UnicodeString.Buffer) + 1];
if (NULL != pwsz)
{
swprintf(pwsz, L"%s%s", c_wszDevice, UnicodeString.Buffer);
RtlInitUnicodeString(&DeviceString, pwsz);
NdisStatistics.Size = sizeof(NdisStatistics);
NdisQueryStatistics(&DeviceString, &NdisStatistics);
delete [] pwsz;
if (NdisStatistics.DeviceState != DEVICE_STATE_CONNECTED)
{
Error = ERROR_SHARING_NO_PRIVATE_LAN;
}
else if (NdisStatistics.MediaState == MEDIA_STATE_UNKNOWN)
{
Error = ERROR_SHARING_HOST_ADDRESS_CONFLICT;
}
else if (NdisStatistics.MediaState == MEDIA_STATE_DISCONNECTED)
{
//
// The adapter is connected but is in a media disconnect
// state. When this happens the correct IP address will
// be there when the adapter is reconnected, so ignore
// the error.
//
Error = ERROR_SUCCESS;
}
}
}
hr = HRESULT_FROM_WIN32(Error);
}
}
//
// As we zeroed out the string structure above, it's safe to call
// the free routines, even if we never actually allocated anything.
//
RtlFreeUnicodeString(&UnicodeString);
RtlFreeAnsiString(&AnsiString);
return hr;
}
HRESULT
CHNetConn::BackupIpConfiguration()
{
HRESULT hr = S_OK;
HANDLE Key;
IWbemClassObject *pwcoInstance = NULL;
VARIANT vt;
PKEY_VALUE_PARTIAL_INFORMATION pInformation;
//
// Spawn a new HNet_BackupIpConfiguration instance
//
hr = SpawnNewInstance(
m_piwsHomenet,
c_wszBackupIpConfiguration,
&pwcoInstance
);
if (SUCCEEDED(hr))
{
//
// Write connection property into instance
//
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = m_bstrConnection;
hr = pwcoInstance->Put(
c_wszConnection,
0,
&vt,
NULL
);
VariantInit(&vt);
}
//
// Open the registry key that stores the IP configuration
// for this connection
//
if (SUCCEEDED(hr))
{
hr = OpenIpConfigurationRegKey(KEY_READ, &Key);
}
//
// Read each part of the configuration, and write it to
// the settings instance
//
if (SUCCEEDED(hr))
{
hr = QueryRegValueKey(Key, c_wszIPAddress, &pInformation);
if (SUCCEEDED(hr))
{
_ASSERT(REG_MULTI_SZ == pInformation->Type);
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = SysAllocStringLen(
reinterpret_cast<OLECHAR*>(pInformation->Data),
pInformation->DataLength / sizeof(OLECHAR)
);
if (NULL != V_BSTR(&vt))
{
hr = pwcoInstance->Put(
c_wszIPAddress,
0,
&vt,
NULL
);
VariantClear(&vt);
}
else
{
hr = E_OUTOFMEMORY;
}
HeapFree(GetProcessHeap(), 0, pInformation);
}
if (SUCCEEDED(hr))
{
hr = QueryRegValueKey(Key, c_wszSubnetMask, &pInformation);
}
if (SUCCEEDED(hr))
{
_ASSERT(REG_MULTI_SZ == pInformation->Type);
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = SysAllocStringLen(
reinterpret_cast<OLECHAR*>(pInformation->Data),
pInformation->DataLength / sizeof(OLECHAR)
);
if (NULL != V_BSTR(&vt))
{
hr = pwcoInstance->Put(
c_wszSubnetMask,
0,
&vt,
NULL
);
VariantClear(&vt);
}
else
{
hr = E_OUTOFMEMORY;
}
HeapFree(GetProcessHeap(), 0, pInformation);
}
if (SUCCEEDED(hr))
{
hr = QueryRegValueKey(Key, c_wszDefaultGateway, &pInformation);
}
if (SUCCEEDED(hr))
{
_ASSERT(REG_MULTI_SZ == pInformation->Type);
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = SysAllocStringLen(
reinterpret_cast<OLECHAR*>(pInformation->Data),
pInformation->DataLength / sizeof(OLECHAR)
);
if (NULL != V_BSTR(&vt))
{
hr = pwcoInstance->Put(
c_wszDefaultGateway,
0,
&vt,
NULL
);
VariantClear(&vt);
}
else
{
hr = E_OUTOFMEMORY;
}
HeapFree(GetProcessHeap(), 0, pInformation);
}
if (SUCCEEDED(hr))
{
hr = QueryRegValueKey(Key, c_wszEnableDHCP, &pInformation);
}
if (SUCCEEDED(hr))
{
_ASSERT(REG_DWORD == pInformation->Type);
_ASSERT(sizeof(DWORD) == pInformation->DataLength);
V_VT(&vt) = VT_I4;
V_I4(&vt) = *(reinterpret_cast<DWORD*>(pInformation->Data));
hr = pwcoInstance->Put(
c_wszEnableDHCP,
0,
&vt,
NULL
);
HeapFree(GetProcessHeap(), 0, pInformation);
}
NtClose(Key);
};
//
// Write the settings to the store
//
if (SUCCEEDED(hr))
{
hr = m_piwsHomenet->PutInstance(
pwcoInstance,
WBEM_FLAG_CREATE_OR_UPDATE,
NULL,
NULL
);
}
if (NULL != pwcoInstance)
{
pwcoInstance->Release();
}
return hr;
}
HRESULT
CHNetConn::RestoreIpConfiguration()
{
HRESULT hr;
IEnumWbemClassObject *pwcoEnum;
IWbemClassObject *pwcoSettings;
BSTR bstr;
LPWSTR wszAddress;
VARIANT vt;
LPWSTR wsz;
UNICODE_STRING UnicodeString;
HANDLE hKey = NULL;
BOOLEAN fDhcpEnabled;
ULONG ulLength;
ULONG ulAddress;
ULONG ulMask;
//
// Open the registry key
//
hr = OpenIpConfigurationRegKey(KEY_ALL_ACCESS, &hKey);
//
// Get the backup configuration block for this connection
//
if (S_OK == hr)
{
hr = BuildEscapedQuotedEqualsString(
&wsz,
c_wszConnection,
m_bstrConnection
);
}
if (S_OK == hr)
{
hr = BuildSelectQueryBstr(
&bstr,
c_wszStar,
c_wszBackupIpConfiguration,
wsz
);
delete [] wsz;
}
if (S_OK == hr)
{
pwcoEnum = NULL;
hr = m_piwsHomenet->ExecQuery(
m_bstrWQL,
bstr,
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pwcoEnum
);
SysFreeString(bstr);
}
if (S_OK == hr)
{
ULONG ulCount;
pwcoSettings = NULL;
hr = pwcoEnum->Next(WBEM_INFINITE, 1, &pwcoSettings, &ulCount);
//
// Even if we're not able to obtain backup settings we continue
// to operate. By setting pwcoSettings to NULL we indidcate that
// the default DHCP configuration should be used. (A failure for
// ExecQuery indicates a much more serious problem, so we don't
// try to continue if that occurs.)
//
if (FAILED(hr) || 1 != ulCount)
{
pwcoSettings = NULL;
}
hr = S_OK;
ValidateFinishedWCOEnum(m_piwsHomenet, pwcoEnum);
pwcoEnum->Release();
}
//
// Write backup values to registry -- start by getting the
// old IP address
//
if (S_OK == hr)
{
if (NULL != pwcoSettings)
{
hr = pwcoSettings->Get(
c_wszIPAddress,
0,
&vt,
NULL,
NULL
);
if (WBEM_S_NO_ERROR == hr)
{
ULONG ulDhcpAddress;
ULONG ulDhcpMask;
_ASSERT(VT_BSTR == V_VT(&vt));
//
// Check to see if the stored backup address is the
// same as our default DHCP scope -- if so, use
// the default DHCP configuration.
//
hr = ReadDhcpScopeSettings(&ulDhcpAddress, &ulDhcpMask);
if (S_OK == hr)
{
ulAddress =
RtlUlongByteSwap(
IpPszToHostAddr(V_BSTR(&vt))
);
if (ulAddress == ulDhcpAddress
|| static_cast<DWORD>(-1) == ulAddress)
{
//
// Use the default configuration.
//
DeleteWmiInstance(m_piwsHomenet, pwcoSettings);
pwcoSettings->Release();
pwcoSettings = NULL;
VariantClear(&vt);
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = SysAllocString(c_wszZeroIpAddress);
if (NULL == V_BSTR(&vt))
{
hr = E_OUTOFMEMORY;
}
}
}
}
}
else
{
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = SysAllocString(c_wszZeroIpAddress);
if (NULL == V_BSTR(&vt))
{
hr = E_OUTOFMEMORY;
}
}
if (WBEM_S_NO_ERROR == hr)
{
//
// REG_MULTI_SZ is double-null terminated; need to copy
// the returned string into a larger buffer to add the
// nulls.
//
// The length computation here is correct; SysStringByteLen
// gives the number of bytes, not WCHARs. The 2 * sizeof(WCHAR)
// is for the double NULL at the end. (SysStringByteLen also
// doesn't include the terminating NULL.)
//
ulLength = SysStringByteLen(V_BSTR(&vt)) + 2 * sizeof(WCHAR);
wszAddress =
reinterpret_cast<LPWSTR>(
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulLength)
);
if (NULL != wszAddress)
{
RtlCopyMemory(wszAddress, V_BSTR(&vt), ulLength - 2 * sizeof(WCHAR));
RtlInitUnicodeString(&UnicodeString, c_wszIPAddress);
hr = NtSetValueKey(
hKey,
&UnicodeString,
0,
REG_MULTI_SZ,
reinterpret_cast<PVOID>(wszAddress),
ulLength
);
HeapFree(GetProcessHeap(), 0, wszAddress);
}
else
{
hr = E_OUTOFMEMORY;
}
VariantClear(&vt);
}
//
// DHCP settings
//
if (SUCCEEDED(hr))
{
if (NULL != pwcoSettings)
{
hr = pwcoSettings->Get(
c_wszEnableDHCP,
0,
&vt,
NULL,
NULL
);
}
else
{
V_VT(&vt) = VT_I4;
V_I4(&vt) = 1;
hr = WBEM_S_NO_ERROR;
}
}
//
// Subnet mask
//
if (WBEM_S_NO_ERROR == hr)
{
_ASSERT(VT_I4 == V_VT(&vt));
RtlInitUnicodeString(&UnicodeString, c_wszEnableDHCP);
hr = NtSetValueKey(
hKey,
&UnicodeString,
0,
REG_DWORD,
reinterpret_cast<PVOID>(&(V_I4(&vt))),
sizeof(V_I4(&vt))
);
fDhcpEnabled = 1 == V_I4(&vt);
VariantClear(&vt);
}
if (SUCCEEDED(hr))
{
if (NULL != pwcoSettings)
{
hr = pwcoSettings->Get(
c_wszSubnetMask,
0,
&vt,
NULL,
NULL
);
}
else
{
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = SysAllocString(c_wszZeroIpAddress);
if (NULL != V_BSTR(&vt))
{
hr = WBEM_S_NO_ERROR;
}
else
{
hr = E_OUTOFMEMORY;
}
}
}
if (WBEM_S_NO_ERROR == hr)
{
LPWSTR wszMask;
_ASSERT(VT_BSTR == V_VT(&vt));
//
// REG_MULTI_SZ is double-null terminated; need to copy
// the returned string into a larger buffer to add the
// nulls.
//
// The length computation here is correct; SysStringByteLen
// gives the number of bytes, not WCHARs. The 2 * sizeof(WCHAR)
// is for the double NULL at the end. (SysStringByteLen also
// doesn't include the terminating NULL.)
//
ulLength = SysStringByteLen(V_BSTR(&vt)) + 2 * sizeof(WCHAR);
wszMask =
reinterpret_cast<LPWSTR>(
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulLength)
);
if (NULL != wszMask)
{
RtlCopyMemory(wszMask, V_BSTR(&vt), ulLength - 2 * sizeof(WCHAR));
RtlInitUnicodeString(&UnicodeString, c_wszSubnetMask);
hr = NtSetValueKey(
hKey,
&UnicodeString,
0,
REG_MULTI_SZ,
reinterpret_cast<PVOID>(wszMask),
ulLength
);
if (!fDhcpEnabled)
{
ulMask =
RtlUlongByteSwap(
IpPszToHostAddr(wszMask)
);
}
HeapFree(GetProcessHeap(), 0, wszMask);
}
else
{
hr = E_OUTOFMEMORY;
}
VariantClear(&vt);
}
//
// Default gateway
//
if (SUCCEEDED(hr))
{
if (NULL != pwcoSettings)
{
hr = pwcoSettings->Get(
c_wszDefaultGateway,
0,
&vt,
NULL,
NULL
);
}
else
{
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = SysAllocString(L"");
if (NULL != V_BSTR(&vt))
{
hr = WBEM_S_NO_ERROR;
}
else
{
hr = E_OUTOFMEMORY;
}
}
}
if (WBEM_S_NO_ERROR == hr)
{
_ASSERT(VT_BSTR == V_VT(&vt));
//
// REG_MULTI_SZ is double-null terminated; need to copy
// the returned string into a larger buffer to add the
// nulls.
//
// The length computation here is correct; SysStringByteLen
// gives the number of bytes, not WCHARs. The 2 * sizeof(WCHAR)
// is for the double NULL at the end. (SysStringByteLen also
// doesn't include the terminating NULL.)
//
ulLength = SysStringByteLen(V_BSTR(&vt)) + 2 * sizeof(WCHAR);
wsz =
reinterpret_cast<LPWSTR>(
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulLength)
);
if (NULL != wsz)
{
RtlCopyMemory(wsz, V_BSTR(&vt), ulLength - 2 * sizeof(WCHAR));
RtlInitUnicodeString(&UnicodeString, c_wszDefaultGateway);
hr = NtSetValueKey(
hKey,
&UnicodeString,
0,
REG_MULTI_SZ,
reinterpret_cast<PVOID>(wsz),
ulLength
);
HeapFree(GetProcessHeap(), 0, wsz);
}
else
{
hr = E_OUTOFMEMORY;
}
VariantClear(&vt);
}
//
// Delete the backup instance
//
if (NULL != pwcoSettings)
{
DeleteWmiInstance(m_piwsHomenet, pwcoSettings);
pwcoSettings->Release();
}
}
if (SUCCEEDED(hr))
{
GUID *pGuid;
LPWSTR wszGuid;
ULONG ulError;
//
// Notify the stack that the IP settings have changed
//
hr = GetGuidInternal(&pGuid);
if (S_OK == hr)
{
hr = StringFromCLSID(*pGuid, &wszGuid);
}
if (S_OK == hr)
{
if (fDhcpEnabled)
{
ulError = DhcpNotifyConfigChange(
NULL,
wszGuid,
FALSE,
0,
0,
0,
DhcpEnable
);
if (NO_ERROR != ulError)
{
hr = HRESULT_FROM_WIN32(ulError);
}
}
else
{
UNICODE_STRING BindList;
UNICODE_STRING LowerComponent;
IP_PNP_RECONFIG_REQUEST Request;
UNICODE_STRING UpperComponent;
if ((ULONG)-1 != ulMask)
{
//
// First delete the old (static) IP address
//
DhcpNotifyConfigChange(
NULL,
wszGuid,
TRUE,
0,
0,
0,
IgnoreFlag
);
//
// Now set the new address
//
ulError =
DhcpNotifyConfigChange(
NULL,
wszGuid,
TRUE,
0,
ulAddress,
ulMask,
DhcpDisable
);
if (NO_ERROR != ulError)
{
hr = HRESULT_FROM_WIN32(ulError);
}
}
else
{
hr = E_FAIL;
}
if (SUCCEEDED(hr))
{
//
// Instruct the stack to pickup the
// new default gateway
//
RtlInitUnicodeString(&BindList, L"");
RtlInitUnicodeString(&LowerComponent, L"");
RtlInitUnicodeString(&UpperComponent, L"Tcpip");
ZeroMemory(&Request, sizeof(Request));
Request.version = IP_PNP_RECONFIG_VERSION;
Request.gatewayListUpdate = TRUE;
Request.Flags = IP_PNP_FLAG_GATEWAY_LIST_UPDATE;
NdisHandlePnPEvent(
NDIS,
RECONFIGURE,
&LowerComponent,
&UpperComponent,
&BindList,
&Request,
sizeof(Request)
);
}
}
CoTaskMemFree(wszGuid);
}
}
if (NULL != hKey)
{
NtClose(hKey);
}
return hr;
}
HRESULT
CHNetConn::OpenIpConfigurationRegKey(
ACCESS_MASK DesiredAccess,
HANDLE *phKey
)
{
HRESULT hr;
LPWSTR KeyName;
ULONG KeyNameLength;
GUID *pGuid;
LPWSTR wszGuid;
hr = GetGuidInternal(&pGuid);
if (SUCCEEDED(hr))
{
hr = StringFromCLSID(*pGuid, &wszGuid);
}
if (SUCCEEDED(hr))
{
KeyNameLength =
wcslen(c_wszTcpipParametersKey) + 1 +
wcslen(c_wszInterfaces) + 1 +
wcslen(wszGuid) + 2;
KeyName = new OLECHAR[KeyNameLength];
if (NULL != KeyName)
{
swprintf(
KeyName,
L"%ls\\%ls\\%ls",
c_wszTcpipParametersKey,
c_wszInterfaces,
wszGuid
);
}
else
{
hr = E_OUTOFMEMORY;
}
CoTaskMemFree(wszGuid);
}
if (SUCCEEDED(hr))
{
hr = OpenRegKey(phKey, DesiredAccess, KeyName);
delete [] KeyName;
}
return hr;
}
HRESULT
CHNetConn::GetGuidInternal(
GUID **ppGuid
)
{
HRESULT hr = S_OK;
VARIANT vt;
_ASSERT(NULL != ppGuid);
Lock();
if (NULL == m_pGuid)
{
//
// Our guid hasn't been retrieved yet -- do it now.
//
m_pGuid = reinterpret_cast<GUID*>(
CoTaskMemAlloc(sizeof(GUID))
);
if (NULL == m_pGuid)
{
hr = E_OUTOFMEMORY;
}
else
{
IWbemClassObject *pwcoConnection;
hr = GetConnectionObject(&pwcoConnection);
if (WBEM_S_NO_ERROR == hr)
{
//
// Get our guid property
//
hr = pwcoConnection->Get(
c_wszGuid,
0,
&vt,
NULL,
NULL
);
pwcoConnection->Release();
}
}
if (WBEM_S_NO_ERROR == hr)
{
_ASSERT(VT_BSTR == V_VT(&vt));
//
// Convert the string to a guid.
//
hr = CLSIDFromString(V_BSTR(&vt), m_pGuid);
VariantClear(&vt);
}
if (FAILED(hr) && NULL != m_pGuid)
{
CoTaskMemFree(m_pGuid);
m_pGuid = NULL;
}
}
if (S_OK == hr)
{
*ppGuid = m_pGuid;
}
Unlock();
return hr;
}
HRESULT
CHNetConn::GetConnectionObject(
IWbemClassObject **ppwcoConnection
)
{
_ASSERT(NULL != ppwcoConnection);
return GetWmiObjectFromPath(
m_piwsHomenet,
m_bstrConnection,
ppwcoConnection
);
}
HRESULT
CHNetConn::GetConnectionPropertiesObject(
IWbemClassObject **ppwcoProperties
)
{
_ASSERT(NULL != ppwcoProperties);
return GetWmiObjectFromPath(
m_piwsHomenet,
m_bstrProperties,
ppwcoProperties
);
}
BOOLEAN
CHNetConn::ProhibitedByPolicy(
DWORD dwPerm
)
{
HRESULT hr = S_OK;
BOOLEAN fProhibited = FALSE;
if (NULL == m_pNetConnUiUtil)
{
Lock();
if (NULL == m_pNetConnUiUtil)
{
hr = CoCreateInstance(
CLSID_NetConnectionUiUtilities,
NULL,
CLSCTX_ALL,
IID_PPV_ARG(INetConnectionUiUtilities, &m_pNetConnUiUtil)
);
}
Unlock();
}
if (SUCCEEDED(hr))
{
fProhibited = !m_pNetConnUiUtil->UserHasPermission(dwPerm);
}
return fProhibited;
}
HRESULT
CHNetConn::UpdateNetman()
{
HRESULT hr = S_OK;
if (NULL == m_pNetConnHNetUtil)
{
Lock();
if (NULL == m_pNetConnHNetUtil)
{
hr = CoCreateInstance(
CLSID_NetConnectionHNetUtil,
NULL,
CLSCTX_ALL,
IID_PPV_ARG(INetConnectionHNetUtil, &m_pNetConnHNetUtil)
);
}
Unlock();
}
if (SUCCEEDED(hr))
{
hr = m_pNetConnHNetUtil->NotifyUpdate();
}
return hr;
}
HRESULT
CHNetConn::CreateIcmpSettingsAssociation(
BSTR bstrIcmpSettingsPath
)
{
HRESULT hr;
VARIANT vt;
IWbemClassObject *pwcoInstance;
_ASSERT(NULL != bstrIcmpSettingsPath);
//
// Spawn a new instance of the association class
//
pwcoInstance = NULL;
hr = SpawnNewInstance(
m_piwsHomenet,
c_wszHnetConnectionIcmpSetting,
&pwcoInstance
);
if (WBEM_S_NO_ERROR == hr)
{
//
// Set connection property
//
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = m_bstrConnection;
hr = pwcoInstance->Put(
c_wszConnection,
0,
&vt,
NULL
);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Point the association to the settings block
//
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = bstrIcmpSettingsPath;
hr = pwcoInstance->Put(
c_wszIcmpSettings,
0,
&vt,
NULL
);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Save the object to the store
//
hr = m_piwsHomenet->PutInstance(
pwcoInstance,
WBEM_FLAG_CREATE_OR_UPDATE,
NULL,
NULL
);
}
return hr;
}
HRESULT
CHNetConn::GetRasConnectionName(
OLECHAR **ppszwConnectionName
)
{
HRESULT hr;
GUID *pGuid;
OLECHAR *pszwPath;
RASENUMENTRYDETAILS *rgEntryDetails;
DWORD cBytes;
DWORD cEntries;
DWORD dwError;
_ASSERT(NULL != ppszwConnectionName);
_ASSERT(FALSE == m_fLanConnection);
hr = GetGuidInternal(&pGuid);
if (S_OK == hr)
{
hr = GetRasPhonebookPath(&pszwPath);
}
if (S_OK == hr)
{
//
// Start with a buffer large enough to hold 5 entries.
//
cBytes = 5 * sizeof(RASENUMENTRYDETAILS);
rgEntryDetails =
reinterpret_cast<RASENUMENTRYDETAILS *>(
CoTaskMemAlloc(cBytes)
);
if (NULL != rgEntryDetails)
{
//
// Try to obtain the entry details
//
rgEntryDetails[0].dwSize = sizeof(RASENUMENTRYDETAILS);
dwError =
DwEnumEntryDetails(
pszwPath,
rgEntryDetails,
&cBytes,
&cEntries
);
if (ERROR_BUFFER_TOO_SMALL == dwError)
{
//
// Try again with a larger buffer
//
CoTaskMemFree(rgEntryDetails);
rgEntryDetails =
reinterpret_cast<RASENUMENTRYDETAILS *>(
CoTaskMemAlloc(cBytes)
);
if (NULL != rgEntryDetails)
{
rgEntryDetails[0].dwSize = sizeof(RASENUMENTRYDETAILS);
dwError =
DwEnumEntryDetails(
pszwPath,
rgEntryDetails,
&cBytes,
&cEntries
);
if (ERROR_SUCCESS != dwError)
{
CoTaskMemFree(rgEntryDetails);
hr = HRESULT_FROM_WIN32(dwError);
}
}
else
{
hr = E_OUTOFMEMORY;
}
}
else if (ERROR_SUCCESS != dwError)
{
CoTaskMemFree(rgEntryDetails);
hr = HRESULT_FROM_WIN32(dwError);
}
}
else
{
hr = E_OUTOFMEMORY;
}
CoTaskMemFree(pszwPath);
}
if (S_OK == hr)
{
DWORD i;
//
// Locate the correct entry in the returned array
//
for (i = 0; i < cEntries; i++)
{
if (IsEqualGUID(rgEntryDetails[i].guidId, *pGuid))
{
//
// We've located the correct entry. Allocate the
// output buffer and copy over the name.
//
*ppszwConnectionName =
reinterpret_cast<OLECHAR *>(
CoTaskMemAlloc(
sizeof(OLECHAR)
* (wcslen(rgEntryDetails[i].szEntryName) + 1)
)
);
if (NULL != *ppszwConnectionName)
{
wcscpy(
*ppszwConnectionName,
rgEntryDetails[i].szEntryName
);
}
else
{
hr = E_OUTOFMEMORY;
}
break;
}
}
if (i == cEntries)
{
//
// Connection not found
//
hr = E_FAIL;
}
CoTaskMemFree(rgEntryDetails);
}
return hr;
}
HRESULT
CHNetConn::RefreshNetConnectionsUI(
VOID
)
{
HRESULT hr = S_OK;
INetConnection *pNetConnection;
//
// Make sure the UI refresh object exists
//
if (NULL == m_pNetConnRefresh)
{
Lock();
if (NULL == m_pNetConnRefresh)
{
hr = CoCreateInstance(
CLSID_ConnectionManager,
NULL,
CLSCTX_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
IID_PPV_ARG(INetConnectionRefresh, &m_pNetConnRefresh)
);
if (SUCCEEDED(hr))
{
SetProxyBlanket(m_pNetConnRefresh);
}
}
Unlock();
}
if (SUCCEEDED(hr))
{
hr = GetINetConnection(&pNetConnection);
if (SUCCEEDED(hr))
{
hr = m_pNetConnRefresh->ConnectionModified(pNetConnection);
pNetConnection->Release();
}
}
return hr;
}