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.
4553 lines
114 KiB
4553 lines
114 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_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_DISABLE_AAA,
|
|
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_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_DISABLE_AAA,
|
|
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 RRAS is configured.
|
|
//
|
|
|
|
if (ProhibitedByPolicy(NCPERM_PersonalFirewallConfig))
|
|
{
|
|
hr = HN_E_POLICY;
|
|
}
|
|
|
|
if (IsRrasConfigured())
|
|
{
|
|
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 RRAS is configured.
|
|
//
|
|
|
|
if (ProhibitedByPolicy(NCPERM_ShowSharedAccessUi))
|
|
{
|
|
hr = HN_E_POLICY;
|
|
}
|
|
|
|
if (IsRrasConfigured())
|
|
{
|
|
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 RRAS is configured.
|
|
//
|
|
|
|
if (ProhibitedByPolicy(NCPERM_ShowSharedAccessUi))
|
|
{
|
|
hr = HN_E_POLICY;
|
|
}
|
|
|
|
if (IsRrasConfigured())
|
|
{
|
|
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
|
|
)
|
|
|
|
{
|
|
BOOLEAN fCanBeBoundToBridge = FALSE;
|
|
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_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_DISABLE_AAA,
|
|
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;
|
|
|
|
//
|
|
// Also need to check if it's even possible to bind
|
|
// the bridge protocol to this adapter.
|
|
//
|
|
|
|
hr = pnetcfgProtocolBindings->IsBindableTo(pncfgcomp);
|
|
fCanBeBoundToBridge = (S_OK == hr);
|
|
|
|
// 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
|
|
&& fCanBeBoundToBridge
|
|
&& !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_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_DISABLE_AAA,
|
|
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_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_DISABLE_AAA,
|
|
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_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_DISABLE_AAA | 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;
|
|
}
|
|
|