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.
 
 
 
 
 
 

3427 lines
74 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997 - 2000
//
// File: H N C F G M G R . C P P
//
// Contents: CHNetCfgMgr implementation
//
// Notes:
//
// Author: jonburs 23 May 2000
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
//
// Atl methods
//
HRESULT
CHNetCfgMgr::FinalConstruct()
{
HRESULT hr = S_OK;
IWbemLocator *pLocator = NULL;
BSTR bstrNamespace = NULL;
//
// Allocate the commonly used BSTRs
//
m_bstrWQL = SysAllocString(c_wszWQL);
if (NULL == m_bstrWQL)
{
hr = E_OUTOFMEMORY;
}
if (S_OK == hr)
{
//
// Allocate the BSTR for our namespace
//
bstrNamespace = SysAllocString(c_wszNamespace);
if (NULL == bstrNamespace)
{
hr = E_OUTOFMEMORY;
}
}
if (S_OK == hr)
{
//
// Create the IWbemLocator object. This interface allows us to
// connect to the desired namespace.
//
hr = CoCreateInstance(
CLSID_WbemLocator,
NULL,
CLSCTX_ALL,
IID_PPV_ARG(IWbemLocator, &pLocator)
);
}
if (S_OK == hr)
{
//
// Connect to our namespace
//
hr = pLocator->ConnectServer(
bstrNamespace,
NULL, // user
NULL, // password
NULL, // locale
0, // security flags
NULL, // authority
NULL, // context
&m_piwsHomenet
);
}
//
// Cleanup locals.
//
if (pLocator) pLocator->Release();
if (bstrNamespace) SysFreeString(bstrNamespace);
if (S_OK != hr)
{
//
// Cleanup object members
//
SysFreeString(m_bstrWQL);
m_bstrWQL = NULL;
if (NULL != m_piwsHomenet)
{
m_piwsHomenet->Release();
m_piwsHomenet = NULL;
}
}
return hr;
}
HRESULT
CHNetCfgMgr::FinalRelease()
{
if (m_piwsHomenet) m_piwsHomenet->Release();
if (m_pNetConnUiUtil) m_pNetConnUiUtil->Release();
if (m_pNetConnHNetUtil) m_pNetConnHNetUtil->Release();
if (m_bstrWQL) SysFreeString(m_bstrWQL);
return S_OK;
}
//
// IHNetCfgMgr methods
//
STDMETHODIMP
CHNetCfgMgr::GetIHNetConnectionForINetConnection(
INetConnection *pNetConnection,
IHNetConnection **ppHNetConnection
)
{
HRESULT hr = S_OK;
NETCON_PROPERTIES* pProps;
IWbemClassObject *pwcoConnection = NULL;
IWbemClassObject *pwcoProperties = NULL;
BOOLEAN fLanConnection;
if (NULL == ppHNetConnection)
{
hr = E_POINTER;
}
if (S_OK == hr)
{
*ppHNetConnection = NULL;
if (NULL == pNetConnection)
{
hr = E_INVALIDARG;
}
}
if (S_OK == hr)
{
//
// Get the properties for the connection
//
hr = pNetConnection->GetProperties(&pProps);
}
if (SUCCEEDED(hr))
{
//
// Attempt to find the connection and properties
// instances in the store
//
hr = GetConnAndPropInstancesByGuid(
m_piwsHomenet,
&pProps->guidId,
&pwcoConnection,
&pwcoProperties
);
if (FAILED(hr))
{
//
// We have no record of this connection. Determine
// if it is a lan connection. (Will need to update
// this for bridge)
//
fLanConnection = (NCM_LAN == pProps->MediaType ||
NCM_BRIDGE == pProps->MediaType);
//
// Create the store instances
//
hr = CreateConnectionAndPropertyInstances(
&pProps->guidId,
fLanConnection,
pProps->pszwName,
&pwcoConnection,
&pwcoProperties
);
//
// If this is a ras connection, determine the
// phonebook path
//
if (S_OK == hr && FALSE == fLanConnection)
{
LPWSTR wsz;
VARIANT vt;
hr = GetPhonebookPathFromRasNetcon(pNetConnection, &wsz);
if (SUCCEEDED(hr))
{
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = SysAllocString(wsz);
CoTaskMemFree(wsz);
if (NULL != V_BSTR(&vt))
{
hr = pwcoConnection->Put(
c_wszPhonebookPath,
0,
&vt,
NULL
);
VariantClear(&vt);
}
else
{
hr = E_OUTOFMEMORY;
}
}
if (SUCCEEDED(hr))
{
//
// Save modified connection instance
//
hr = m_piwsHomenet->PutInstance(
pwcoConnection,
WBEM_FLAG_CREATE_OR_UPDATE,
NULL,
NULL
);
}
else
{
//
// Delete the newly created instances
//
DeleteWmiInstance(m_piwsHomenet, pwcoConnection);
DeleteWmiInstance(m_piwsHomenet, pwcoProperties);
pwcoConnection->Release();
pwcoProperties->Release();
}
}
}
NcFreeNetconProperties(pProps);
}
if (S_OK == hr)
{
CComObject<CHNetConn> *pHNConn;
//
// Create the wrapper object
//
hr = CComObject<CHNetConn>::CreateInstance(&pHNConn);
if (SUCCEEDED(hr))
{
pHNConn->AddRef();
hr = pHNConn->SetINetConnection(pNetConnection);
if (S_OK == hr)
{
hr = pHNConn->InitializeFromInstances(
m_piwsHomenet,
pwcoConnection,
pwcoProperties
);
}
if (S_OK == hr)
{
hr = pHNConn->QueryInterface(
IID_PPV_ARG(IHNetConnection, ppHNetConnection)
);
}
pHNConn->Release();
}
pwcoConnection->Release();
pwcoProperties->Release();
}
return hr;
}
STDMETHODIMP
CHNetCfgMgr::GetIHNetConnectionForGuid(
GUID *pGuid,
BOOLEAN fLanConnection,
BOOLEAN fCreateEntries,
IHNetConnection **ppHNetConnection
)
{
HRESULT hr = S_OK;
IWbemClassObject *pwcoConnection = NULL;
IWbemClassObject *pwcoProperties = NULL;
if (NULL == ppHNetConnection)
{
hr = E_POINTER;
}
if (S_OK == hr)
{
*ppHNetConnection = NULL;
if (NULL == pGuid)
{
hr = E_INVALIDARG;
}
}
if (S_OK == hr)
{
//
// Attempt to find the connection and properties
// instances in the store
//
hr = GetConnAndPropInstancesByGuid(
m_piwsHomenet,
pGuid,
&pwcoConnection,
&pwcoProperties
);
if (FAILED(hr) && fCreateEntries)
{
INetConnection *pNetConn;
//
// We don't have a record of this guid. Get the INetConnection
// that it corresponds to.
//
hr = FindINetConnectionByGuid(pGuid, &pNetConn);
if (SUCCEEDED(hr))
{
hr = GetIHNetConnectionForINetConnection(
pNetConn,
ppHNetConnection
);
pNetConn->Release();
return hr;
}
}
}
if (S_OK == hr)
{
CComObject<CHNetConn> *pHNConn;
//
// Create the wrapper object
//
hr = CComObject<CHNetConn>::CreateInstance(&pHNConn);
if (SUCCEEDED(hr))
{
pHNConn->AddRef();
hr = pHNConn->InitializeFromInstances(
m_piwsHomenet,
pwcoConnection,
pwcoProperties
);
if (S_OK == hr)
{
hr = pHNConn->QueryInterface(
IID_PPV_ARG(IHNetConnection, ppHNetConnection)
);
}
pHNConn->Release();
}
pwcoConnection->Release();
pwcoProperties->Release();
}
return hr;
}
//
// IHNetBridgeSettings methods
//
STDMETHODIMP
CHNetCfgMgr::EnumBridges(
IEnumHNetBridges **ppEnum
)
{
HRESULT hr;
CComObject<CEnumHNetBridges> *pEnum;
IHNetBridge *phnbridge;
if( NULL != ppEnum )
{
*ppEnum = NULL;
hr = GetBridgeConnection( m_piwsHomenet, &phnbridge );
if( S_OK == hr )
{
hr = CComObject<CEnumHNetBridges>::CreateInstance(&pEnum);
if( SUCCEEDED(hr) )
{
pEnum->AddRef();
hr = pEnum->Initialize(&phnbridge, 1L);
if( SUCCEEDED(hr) )
{
hr = pEnum-> QueryInterface(
IID_PPV_ARG(IEnumHNetBridges, ppEnum)
);
}
pEnum->Release();
}
phnbridge->Release();
}
else
{
// Make an empty enumerator
hr = CComObject<CEnumHNetBridges>::CreateInstance(&pEnum);
if( SUCCEEDED(hr) )
{
pEnum->AddRef();
hr = pEnum->Initialize(NULL, 0L);
if( SUCCEEDED(hr) )
{
hr = pEnum-> QueryInterface(
IID_PPV_ARG(IEnumHNetBridges, ppEnum)
);
}
pEnum->Release();
}
}
}
else
{
hr = E_POINTER;
}
return hr;
}
STDMETHODIMP
CHNetCfgMgr::CreateBridge(
IHNetBridge **ppHNetBridge,
INetCfg *pnetcfgExisting
)
{
HRESULT hr = S_OK;
GUID guid;
IWbemClassObject *pwcoConnection = NULL;
IWbemClassObject *pwcoProperties = NULL;
if (NULL != ppHNetBridge)
{
*ppHNetBridge = NULL;
}
else
{
hr = E_POINTER;
}
if (ProhibitedByPolicy(NCPERM_AllowNetBridge_NLA))
{
hr = HN_E_POLICY;
}
if (S_OK == hr)
{
//
// Install the bridge driver, and create the bridge miniport.
//
hr = InstallBridge( &guid, pnetcfgExisting );
}
if (S_OK == hr)
{
//
// See if we already have property instances for this connection.
// (They may have been created when the bridge connection object
// was instantiated.)
//
hr = GetConnAndPropInstancesByGuid(
m_piwsHomenet,
&guid,
&pwcoConnection,
&pwcoProperties
);
if (S_OK != hr)
{
//
// Create the store instances
//
hr = CreateConnectionAndPropertyInstances(
&guid,
TRUE,
c_wszBridge,
&pwcoConnection,
&pwcoProperties
);
}
}
if (S_OK == hr)
{
//
// Inform netman that something changed. Error doesn't matter.
//
UpdateNetman();
}
if (S_OK == hr)
{
CComObject<CHNBridge> *pBridge;
//
// Create wrapper object to return
//
hr = CComObject<CHNBridge>::CreateInstance(&pBridge);
if (SUCCEEDED(hr))
{
pBridge->AddRef();
hr = pBridge->InitializeFromInstances(
m_piwsHomenet,
pwcoConnection,
pwcoProperties
);
if (S_OK == hr)
{
hr = pBridge->QueryInterface(
IID_PPV_ARG(IHNetBridge, ppHNetBridge)
);
}
pBridge->Release();
}
}
if (NULL != pwcoConnection) pwcoConnection->Release();
if (NULL != pwcoProperties) pwcoProperties->Release();
return hr;
}
STDMETHODIMP
CHNetCfgMgr::DestroyAllBridges(
ULONG *pcBridges,
INetCfg *pnetcfgExisting
)
{
HRESULT hr = S_OK;
IEnumHNetBridges *pehnbEnum;
IHNetBridge *phnBridge;
if (!pcBridges)
{
hr = E_POINTER;
}
if (ProhibitedByPolicy(NCPERM_AllowNetBridge_NLA))
{
hr = HN_E_POLICY;
}
if (S_OK == hr)
{
*pcBridges = 0;
//
// Get the enumeration of the bridges.
//
hr = EnumBridges(&pehnbEnum);
}
if (S_OK == hr)
{
//
// Walk through the enumeration, destroying
// each bridge
//
do
{
hr = pehnbEnum->Next(1, &phnBridge, NULL);
if (S_OK == hr)
{
phnBridge->Destroy( pnetcfgExisting );
phnBridge->Release();
*pcBridges += 1;
}
}
while (S_OK == hr);
hr = S_OK;
pehnbEnum->Release();
}
return hr;
}
//
// IHNetFirewallSettings methods
//
STDMETHODIMP
CHNetCfgMgr::EnumFirewalledConnections(
IEnumHNetFirewalledConnections **ppEnum
)
{
HRESULT hr = S_OK;
IEnumWbemClassObject *pwcoEnum;
BSTR bstrQuery;
if (!ppEnum)
{
hr = E_POINTER;
}
if (S_OK == hr)
{
*ppEnum = NULL;
//
// Query the WMI store for HNet_ConnectionProperties instances
// where IsFirewall is true.
//
hr = BuildSelectQueryBstr(
&bstrQuery,
c_wszStar,
c_wszHnetProperties,
L"IsFirewalled != FALSE"
);
}
if (S_OK == hr)
{
pwcoEnum = NULL;
hr = m_piwsHomenet->ExecQuery(
m_bstrWQL,
bstrQuery,
WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pwcoEnum
);
SysFreeString(bstrQuery);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Create and initialize the wrapper for the enum
//
CComObject<CEnumHNetFirewalledConnections> *pEnum;
hr = CComObject<CEnumHNetFirewalledConnections>::CreateInstance(&pEnum);
if (SUCCEEDED(hr))
{
pEnum->AddRef();
hr = pEnum->Initialize(m_piwsHomenet, pwcoEnum);
if (SUCCEEDED(hr))
{
hr = pEnum->QueryInterface(
IID_PPV_ARG(IEnumHNetFirewalledConnections, ppEnum)
);
}
pEnum->Release();
}
pwcoEnum->Release();
}
return hr;
}
STDMETHODIMP
CHNetCfgMgr::GetFirewallLoggingSettings(
HNET_FW_LOGGING_SETTINGS **ppSettings
)
{
HRESULT hr = S_OK;
IWbemClassObject *pwcoSettings = NULL;
if (!ppSettings)
{
hr = E_POINTER;
}
//
// Allocate the necessary memory for the settings structure.
//
if (S_OK == hr)
{
*ppSettings = reinterpret_cast<HNET_FW_LOGGING_SETTINGS *>(
CoTaskMemAlloc(sizeof(HNET_FW_LOGGING_SETTINGS))
);
if (NULL == *ppSettings)
{
hr = E_OUTOFMEMORY;
}
}
if (S_OK == hr)
{
hr = RetrieveSingleInstance(
m_piwsHomenet,
c_wszHnetFWLoggingSettings,
FALSE,
&pwcoSettings
);
}
if (S_OK == hr)
{
//
// Copy the instance info into the settings block
//
hr = CopyLoggingInstanceToStruct(pwcoSettings, *ppSettings);
pwcoSettings->Release();
}
if (FAILED(hr))
{
//
// Clean up output structure
//
if (ppSettings && *ppSettings)
{
CoTaskMemFree(*ppSettings);
*ppSettings = NULL;
}
}
return hr;
}
STDMETHODIMP
CHNetCfgMgr::SetFirewallLoggingSettings(
HNET_FW_LOGGING_SETTINGS *pSettings
)
{
HRESULT hr = S_OK;
IWbemClassObject *pwcoSettings;
if (NULL == pSettings)
{
hr = E_INVALIDARG;
}
if (ProhibitedByPolicy(NCPERM_PersonalFirewallConfig))
{
hr = HN_E_POLICY;
}
if (S_OK == hr)
{
//
// Attempt to retrieve the HNet_FirewallLoggingSettings instance from
// the store
//
hr = RetrieveSingleInstance(
m_piwsHomenet,
c_wszHnetFWLoggingSettings,
TRUE,
&pwcoSettings
);
}
if (S_OK == hr)
{
//
// Copy settings struct into object instance
//
hr = CopyStructToLoggingInstance(pSettings, pwcoSettings);
if (S_OK == hr)
{
//
// Write settings instance back to the store
//
hr = m_piwsHomenet->PutInstance(
pwcoSettings,
WBEM_FLAG_CREATE_OR_UPDATE,
NULL,
NULL
);
}
pwcoSettings->Release();
}
if (SUCCEEDED(hr))
{
//
// Notify service of configuration change
//
UpdateService(IPNATHLP_CONTROL_UPDATE_FWLOGGER);
}
return hr;
}
STDMETHODIMP
CHNetCfgMgr::DisableAllFirewalling(
ULONG *pcFirewalledConnections
)
{
HRESULT hr = S_OK;
IEnumHNetFirewalledConnections *pehfcEnum;
IHNetFirewalledConnection *phfcConnection;
if (!pcFirewalledConnections)
{
hr = E_POINTER;
}
if (ProhibitedByPolicy(NCPERM_PersonalFirewallConfig))
{
hr = HN_E_POLICY;
}
if (S_OK == hr)
{
*pcFirewalledConnections = 0;
//
// Get the enumeration of firewalled connections
//
hr = EnumFirewalledConnections(&pehfcEnum);
}
if (S_OK == hr)
{
//
// Walk through the enumeration, turning off
// firewalling for each connection
//
do
{
hr = pehfcEnum->Next(1, &phfcConnection, NULL);
if (S_OK == hr)
{
phfcConnection->Unfirewall();
phfcConnection->Release();
*pcFirewalledConnections += 1;
}
}
while (S_OK == hr);
hr = S_OK;
pehfcEnum->Release();
}
return hr;
}
//
// IHNetIcsSettings methods
//
STDMETHODIMP
CHNetCfgMgr::EnumIcsPublicConnections(
IEnumHNetIcsPublicConnections **ppEnum
)
{
HRESULT hr = S_OK;
IEnumWbemClassObject *pwcoEnum;
BSTR bstrQuery;
if (!ppEnum)
{
hr = E_POINTER;
}
if (S_OK == hr)
{
*ppEnum = NULL;
//
// Query the WMI store for HNet_ConnectionProperties instances
// where IsIcsPublic is true.
//
hr = BuildSelectQueryBstr(
&bstrQuery,
c_wszStar,
c_wszHnetProperties,
L"IsIcsPublic != FALSE"
);
}
if (S_OK == hr)
{
pwcoEnum = NULL;
hr = m_piwsHomenet->ExecQuery(
m_bstrWQL,
bstrQuery,
WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pwcoEnum
);
SysFreeString(bstrQuery);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Create and initialize the wrapper for the enum
//
CComObject<CEnumHNetIcsPublicConnections> *pEnum;
hr = CComObject<CEnumHNetIcsPublicConnections>::CreateInstance(&pEnum);
if (SUCCEEDED(hr))
{
pEnum->AddRef();
hr = pEnum->Initialize(m_piwsHomenet, pwcoEnum);
if (SUCCEEDED(hr))
{
hr = pEnum->QueryInterface(
IID_PPV_ARG(IEnumHNetIcsPublicConnections, ppEnum)
);
}
pEnum->Release();
}
pwcoEnum->Release();
}
return hr;
}
STDMETHODIMP
CHNetCfgMgr::EnumIcsPrivateConnections(
IEnumHNetIcsPrivateConnections **ppEnum
)
{
HRESULT hr = S_OK;
IEnumWbemClassObject *pwcoEnum;
BSTR bstrQuery;
if (!ppEnum)
{
hr = E_POINTER;
}
if (S_OK == hr)
{
*ppEnum = NULL;
//
// Query the WMI store for HNet_ConnectionProperties instances
// where IsIcsPrivate is true.
//
hr = BuildSelectQueryBstr(
&bstrQuery,
c_wszStar,
c_wszHnetProperties,
L"IsIcsPrivate != FALSE"
);
}
if (S_OK == hr)
{
pwcoEnum = NULL;
hr = m_piwsHomenet->ExecQuery(
m_bstrWQL,
bstrQuery,
WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pwcoEnum
);
SysFreeString(bstrQuery);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Create and initialize the wrapper for the enum
//
CComObject<CEnumHNetIcsPrivateConnections> *pEnum;
hr = CComObject<CEnumHNetIcsPrivateConnections>::CreateInstance(&pEnum);
if (SUCCEEDED(hr))
{
pEnum->AddRef();
hr = pEnum->Initialize(m_piwsHomenet, pwcoEnum);
if (SUCCEEDED(hr))
{
hr = pEnum->QueryInterface(
IID_PPV_ARG(IEnumHNetIcsPrivateConnections, ppEnum)
);
}
pEnum->Release();
}
pwcoEnum->Release();
}
return hr;
}
STDMETHODIMP
CHNetCfgMgr::DisableIcs(
ULONG *pcIcsPublicConnections,
ULONG *pcIcsPrivateConnections
)
{
HRESULT hr = S_OK;
IEnumHNetIcsPrivateConnections *pehiPrivate;
IEnumHNetIcsPublicConnections *pehiPublic;
IHNetIcsPrivateConnection *phicPrivate;
IHNetIcsPublicConnection *phicPublic;
if (!pcIcsPublicConnections
|| !pcIcsPrivateConnections)
{
hr = E_POINTER;
}
if (ProhibitedByPolicy(NCPERM_ShowSharedAccessUi))
{
hr = HN_E_POLICY;
}
if (S_OK == hr)
{
*pcIcsPublicConnections = 0;
*pcIcsPrivateConnections = 0;
//
// Get enumeration of private connections
//
hr = EnumIcsPrivateConnections(&pehiPrivate);
}
if (S_OK == hr)
{
//
// Loop through enumeration, unsharing the connection
//
do
{
hr = pehiPrivate->Next(1, &phicPrivate, NULL);
if (S_OK == hr)
{
phicPrivate->RemoveFromIcs();
phicPrivate->Release();
*pcIcsPrivateConnections += 1;
}
} while (S_OK == hr);
hr = S_OK;
pehiPrivate->Release();
}
if (S_OK == hr)
{
//
// Get enumeration of public connections
//
hr = EnumIcsPublicConnections(&pehiPublic);
}
if (S_OK == hr)
{
//
// Loop through enumeration, unsharing the connection
//
do
{
hr = pehiPublic->Next(1, &phicPublic, NULL);
if (S_OK == hr)
{
phicPublic->Unshare();
phicPublic->Release();
*pcIcsPublicConnections += 1;
}
} while (S_OK == hr);
hr = S_OK;
pehiPublic->Release();
}
if (S_OK == hr)
{
//
// Currently, maximum of 1 public and private connection
//
_ASSERT(*pcIcsPrivateConnections <= 1);
_ASSERT(*pcIcsPublicConnections <= 1);
}
return hr;
}
STDMETHODIMP
CHNetCfgMgr::GetPossiblePrivateConnections(
IHNetConnection *pConn,
ULONG *pcPrivateConnections,
IHNetConnection **pprgPrivateConnections[],
LONG *pxCurrentPrivate
)
/*++
Routine Description:
Given an IHNetConnection, determines the what connections may
serve as a private connection. Only connections that meet the
following criteria may serve as a private connection:
* it's a LAN connection
* it's not part of a bridge
* it's not firewalled
* it's not the connection passed in
* it's bound to TCP/IP
Note that these are not the same rules that are used to set the
fCanBeIcsPrivate member in HNET_CONN_PROPERTIES. In particular,
these rules don't take into account whether or not a connection
is currently marked as IcsPublic.
Arguments:
pConn - the connection that would be the public connection
pcPrivateConnections - receives the count of connections returned
pprgPrivateConnections - receives that possible private connections.
The caller is responsible for:
1) Releasing all of the interface pointers w/in the array
2) Calling CoTaskMemFree on the pointer to the array
pxCurrentPrivate - receives the index into pprgPrivateConnections of
the connection that is currently marked IcsPrivate. If no connection
is so marked, receives -1.
Return Value:
Standard HRESULT
--*/
{
HRESULT hr = S_OK;
INetConnectionManager *pNetConnMgr;
IEnumNetConnection *pEnum;
INetConnection *rgNetConn[16];
GUID *pGuid = NULL;
HNET_CONN_PROPERTIES *pProps;
IHNetConnection **rgConnections = NULL;
ULONG cConn = 0;
ULONG i;
PIP_INTERFACE_INFO pIpIfTable = NULL;
if (NULL != pprgPrivateConnections)
{
*pprgPrivateConnections = NULL;
if (NULL == pConn)
{
hr = E_INVALIDARG;
}
else if (NULL == pcPrivateConnections
|| NULL == pxCurrentPrivate)
{
hr = E_POINTER;
}
else
{
*pcPrivateConnections = 0;
*pxCurrentPrivate = -1;
}
}
else
{
hr = E_POINTER;
}
//
// Obtain the IP interface table. We use this table to see if an
// adapter is bound to TCP/IP.
//
if (S_OK == hr)
{
DWORD dwError;
ULONG ulSize = 0;
dwError = GetInterfaceInfo(NULL, &ulSize);
if (ERROR_INSUFFICIENT_BUFFER == dwError)
{
pIpIfTable =
reinterpret_cast<PIP_INTERFACE_INFO>(
HeapAlloc(GetProcessHeap(), 0, ulSize)
);
if (NULL != pIpIfTable)
{
dwError = GetInterfaceInfo(pIpIfTable, &ulSize);
if (ERROR_SUCCESS != dwError)
{
hr = HRESULT_FROM_WIN32(dwError);
HeapFree(GetProcessHeap(), 0, pIpIfTable);
pIpIfTable = NULL;
}
}
else
{
hr = E_OUTOFMEMORY;
}
}
else
{
hr = HRESULT_FROM_WIN32(dwError);
}
}
//
// If the connection we we're given is a LAN connection, get its
// guid so that we can exclude it from the possible private
// connections.
//
if (S_OK == hr)
{
hr = pConn->GetProperties(&pProps);
if (SUCCEEDED(hr))
{
if (pProps->fLanConnection)
{
hr = pConn->GetGuid(&pGuid);
}
CoTaskMemFree(pProps);
}
}
//
// Create the net connections manager, and enumerate through the
// connections. We don't enumerate through just what our store has,
// as it might have stale entries (i.e., information for adapters
// that have been removed from the system).
//
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(
CLSID_ConnectionManager,
NULL,
CLSCTX_ALL,
IID_PPV_ARG(INetConnectionManager, &pNetConnMgr)
);
}
if (SUCCEEDED(hr))
{
SetProxyBlanket(pNetConnMgr);
hr = pNetConnMgr->EnumConnections(NCME_DEFAULT, &pEnum);
pNetConnMgr->Release();
}
if (SUCCEEDED(hr))
{
ULONG ulCount;
SetProxyBlanket(pEnum);
do
{
//
// Grab a bunch of connections out of the enumeration
//
hr = pEnum->Next(ARRAYSIZE(rgNetConn), rgNetConn, &ulCount);
if (SUCCEEDED(hr) && ulCount > 0)
{
//
// Allocate memory for the output array
//
LPVOID pTemp = reinterpret_cast<LPVOID>(rgConnections);
rgConnections = reinterpret_cast<IHNetConnection**>(
CoTaskMemRealloc(
pTemp,
(cConn + ulCount) * sizeof(IHNetConnection*))
);
if (NULL != rgConnections)
{
for (i = 0; i < ulCount; i++)
{
SetProxyBlanket(rgNetConn[i]);
hr = GetIHNetConnectionForINetConnection(
rgNetConn[i],
&rgConnections[cConn]
);
if (SUCCEEDED(hr))
{
hr = rgConnections[cConn]->GetProperties(&pProps);
if (SUCCEEDED(hr))
{
if (!pProps->fLanConnection
|| pProps->fPartOfBridge
|| pProps->fFirewalled)
{
//
// Connection can't be private
//
rgConnections[cConn]->Release();
rgConnections[cConn] = NULL;
}
else
{
GUID *pg;
//
// This connection can be private if:
// 1) it's not the same as the public connection
// (if the public is LAN), and,
// 2) it's bound to TCP/IP
//
hr = rgConnections[cConn]->GetGuid(&pg);
if (SUCCEEDED(hr))
{
if ((NULL == pGuid
|| !IsEqualGUID(*pGuid, *pg))
&& ConnectionIsBoundToTcp(pIpIfTable, pg))
{
//
// Connection can be private
//
if (pProps->fIcsPrivate)
{
_ASSERT(-1 == *pxCurrentPrivate);
*pxCurrentPrivate = cConn;
}
cConn += 1;
}
else
{
rgConnections[cConn]->Release();
rgConnections[cConn] = NULL;
}
CoTaskMemFree(pg);
}
else
{
rgConnections[cConn]->Release();
rgConnections[cConn] = NULL;
}
}
CoTaskMemFree(pProps);
}
}
else
{
//
// The connection couldn't be converted to an
// IHNetConnection -- this is expected for
// certain connection types (e.g., inbound)
//
hr = S_OK;
rgConnections[cConn] = NULL;
}
}
}
else
{
hr = E_OUTOFMEMORY;
if (NULL != pTemp)
{
rgConnections = reinterpret_cast<IHNetConnection**>(pTemp);
for (i = 0; i < cConn; i++)
{
rgConnections[i]->Release();
}
CoTaskMemFree(pTemp);
}
}
//
// Free the retrieved INetConnections
//
for (i = 0; i < ulCount; i++)
{
rgNetConn[i]->Release();
}
}
} while (SUCCEEDED(hr) && ulCount > 0);
pEnum->Release();
}
if (SUCCEEDED(hr))
{
hr = S_OK;
if (cConn > 0)
{
*pcPrivateConnections = cConn;
*pprgPrivateConnections = rgConnections;
}
else if (NULL != rgConnections)
{
CoTaskMemFree(reinterpret_cast<LPVOID>(rgConnections));
}
}
else
{
//
// Cleanup output array
//
if (NULL != rgConnections)
{
for (i = 0; i < cConn; i++)
{
if (NULL != rgConnections[i])
{
rgConnections[i]->Release();
}
}
CoTaskMemFree(reinterpret_cast<LPVOID>(rgConnections));
}
if (NULL != pxCurrentPrivate)
{
*pxCurrentPrivate = -1;
}
//
// Even though a failure occurred, return success (with 0 possible
// private connnections). Doing this allows our UI to continue to
// show other homenet features, instead of throwing up an error
// dialog and blocking everything.
//
hr = S_OK;
}
if (NULL != pGuid)
{
CoTaskMemFree(pGuid);
}
if (NULL != pIpIfTable)
{
HeapFree(GetProcessHeap(), 0, pIpIfTable);
}
return hr;
}
STDMETHODIMP
CHNetCfgMgr::GetAutodialSettings(
BOOLEAN *pfAutodialEnabled
)
{
HRESULT hr = S_OK;
BOOL fEnabled;
DWORD dwError;
if (!pfAutodialEnabled)
{
hr = E_POINTER;
}
if (S_OK == hr)
{
//
// Autodial information is stored in the registry and managed through
// routines exported from rasapi32.dll. We're not changing any of the
// autodial code, as to do so would require modifications to numerous
// files and binaries, and thus would result in a very large test hit.
//
dwError = RasQuerySharedAutoDial(&fEnabled);
if (ERROR_SUCCESS == dwError)
{
*pfAutodialEnabled = !!fEnabled;
}
else
{
//
// Autodial defaults to true on failure.
//
*pfAutodialEnabled = TRUE;
hr = HRESULT_FROM_WIN32(dwError);
}
}
return hr;
}
STDMETHODIMP
CHNetCfgMgr::SetAutodialSettings(
BOOLEAN fEnableAutodial
)
{
DWORD dwError;
//
// Autodial information is stored in the registry and managed through
// routines exported from rasapi32.dll. We're not changing any of the
// autodial code, as to do so would require modifications to numerous
// files and binaries, and thus would result in a very large test hit.
//
dwError = RasSetSharedAutoDial(!!fEnableAutodial);
return HRESULT_FROM_WIN32(dwError);
}
STDMETHODIMP
CHNetCfgMgr::GetDhcpEnabled(
BOOLEAN *pfDhcpEnabled
)
{
//
// Not supported in whistler, per 173399.
//
return E_NOTIMPL;
/**
HRESULT hr = S_OK;
IWbemClassObject *pwcoInstance;
if (NULL == pfDhcpEnabled)
{
hr = E_POINTER;
}
if (S_OK == hr)
{
//
// Default to true on failure
//
*pfDhcpEnabled = TRUE;
//
// Get the HNet_IcsSettings instance from the store
//
hr = RetrieveSingleInstance(
m_piwsHomenet,
c_wszHnetIcsSettings,
FALSE,
&pwcoInstance
);
}
if (S_OK == hr)
{
//
// Retrieve the DHCP enabled property
//
hr = GetBooleanValue(
pwcoInstance,
c_wszDhcpEnabled,
pfDhcpEnabled
);
pwcoInstance->Release();
}
return hr;
**/
}
STDMETHODIMP
CHNetCfgMgr::SetDhcpEnabled(
BOOLEAN fEnableDhcp
)
{
//
// Not supported in whistler, per 173399.
//
return E_NOTIMPL;
/**
HRESULT hr = S_OK;
IWbemClassObject *pwcoInstance = NULL;
//
// Get the HNet_IcsSettings instance from the store
//
hr = RetrieveSingleInstance(
m_piwsHomenet,
c_wszHnetIcsSettings,
TRUE,
&pwcoInstance
);
if (S_OK == hr)
{
//
// Write the property
//
hr = SetBooleanValue(
pwcoInstance,
c_wszDhcpEnabled,
fEnableDhcp
);
if (WBEM_S_NO_ERROR == hr)
{
//
// Write the modified instance to the store
//
hr = m_piwsHomenet->PutInstance(
pwcoInstance,
WBEM_FLAG_CREATE_OR_UPDATE,
NULL,
NULL
);
}
pwcoInstance->Release();
}
return hr;
**/
}
STDMETHODIMP
CHNetCfgMgr::GetDhcpScopeSettings(
DWORD *pdwScopeAddress,
DWORD *pdwScopeMask
)
{
HRESULT hr = S_OK;
if (NULL == pdwScopeAddress || NULL == pdwScopeMask)
{
hr = E_POINTER;
}
else
{
hr = ReadDhcpScopeSettings(pdwScopeAddress, pdwScopeMask);
}
return hr;
}
STDMETHODIMP
CHNetCfgMgr::SetDhcpScopeSettings(
DWORD dwScopeAddress,
DWORD dwScopeMask
)
{
//
// This functionality isn't exposed in any way at the moment.
//
// People needing to override the default settings can do so
// through the registry...
//
return E_NOTIMPL;
}
STDMETHODIMP
CHNetCfgMgr::GetDnsEnabled(
BOOLEAN *pfDnsEnabled
)
{
//
// Not supported in whistler, per 173399.
//
return E_NOTIMPL;
/**
HRESULT hr = S_OK;
IWbemClassObject *pwcoInstance = NULL;
if (NULL == pfDnsEnabled)
{
hr = E_POINTER;
}
if (S_OK == hr)
{
//
// Default to true on failure
//
*pfDnsEnabled = TRUE;
//
// Get the HNet_IcsSettings instance from the store
//
hr = RetrieveSingleInstance(
m_piwsHomenet,
c_wszHnetIcsSettings,
FALSE,
&pwcoInstance
);
}
if (S_OK == hr)
{
//
// Retrieve the DHCP enabled property
//
hr = GetBooleanValue(
pwcoInstance,
c_wszDnsEnabled,
pfDnsEnabled
);
pwcoInstance->Release();
}
return hr;
**/
}
STDMETHODIMP
CHNetCfgMgr::SetDnsEnabled(
BOOLEAN fEnableDns
)
{
//
// Not supported in whistler, per 173399.
//
return E_NOTIMPL;
/**
HRESULT hr = S_OK;
IWbemClassObject *pwcoInstance = NULL;
//
// Get the HNet_IcsSettings instance from the store
//
hr = RetrieveSingleInstance(
m_piwsHomenet,
c_wszHnetIcsSettings,
TRUE,
&pwcoInstance
);
if (S_OK == hr)
{
//
// Write the property
//
hr = SetBooleanValue(
pwcoInstance,
c_wszDnsEnabled,
fEnableDns
);
if (WBEM_S_NO_ERROR == hr)
{
//
// Write the modified instance to the store
//
hr = m_piwsHomenet->PutInstance(
pwcoInstance,
WBEM_FLAG_CREATE_OR_UPDATE,
NULL,
NULL
);
}
pwcoInstance->Release();
}
return hr;
**/
}
STDMETHODIMP
CHNetCfgMgr::EnumDhcpReservedAddresses(
IEnumHNetPortMappingBindings **ppEnum
)
{
HRESULT hr = S_OK;
BSTR bstrQuery;
IEnumWbemClassObject *pwcoEnum;
if (NULL != ppEnum)
{
*ppEnum = NULL;
}
else
{
hr = E_POINTER;
}
//
// Query for all enabled bindings where the name is active.
//
if (S_OK == hr)
{
hr = BuildSelectQueryBstr(
&bstrQuery,
c_wszStar,
c_wszHnetConnectionPortMapping,
L"Enabled != FALSE AND NameActive != FALSE"
);
}
if (S_OK == hr)
{
pwcoEnum = NULL;
hr = m_piwsHomenet->ExecQuery(
m_bstrWQL,
bstrQuery,
WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pwcoEnum
);
SysFreeString(bstrQuery);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Build wrapper object
//
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;
}
//
// IHNetProtocolSettings methods
//
STDMETHODIMP
CHNetCfgMgr::EnumApplicationProtocols(
BOOLEAN fEnabledOnly,
IEnumHNetApplicationProtocols **ppEnum
)
{
HRESULT hr = S_OK;
IEnumWbemClassObject *pwcoEnum;
BSTR bstrQuery;
if (!ppEnum)
{
hr = E_POINTER;
}
if (S_OK == hr)
{
*ppEnum = NULL;
//
// Query the WMI store for HNet_ApplicationProtocol instances;
// if fEnabledOnly is true, then only retrieve instances for
// which the Enabled property is true
//
hr = BuildSelectQueryBstr(
&bstrQuery,
c_wszStar,
c_wszHnetApplicationProtocol,
fEnabledOnly ? L"Enabled != FALSE" : NULL
);
}
if (S_OK == hr)
{
pwcoEnum = NULL;
hr = m_piwsHomenet->ExecQuery(
m_bstrWQL,
bstrQuery,
WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pwcoEnum
);
SysFreeString(bstrQuery);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Create and initialize the wrapper for the enum
//
CComObject<CEnumHNetApplicationProtocols> *pEnum;
hr = CComObject<CEnumHNetApplicationProtocols>::CreateInstance(&pEnum);
if (SUCCEEDED(hr))
{
pEnum->AddRef();
hr = pEnum->Initialize(m_piwsHomenet, pwcoEnum);
if (SUCCEEDED(hr))
{
hr = pEnum->QueryInterface(
IID_PPV_ARG(IEnumHNetApplicationProtocols, ppEnum)
);
}
pEnum->Release();
}
pwcoEnum->Release();
}
return hr;
}
STDMETHODIMP
CHNetCfgMgr::CreateApplicationProtocol(
OLECHAR *pszwName,
UCHAR ucOutgoingIPProtocol,
USHORT usOutgoingPort,
USHORT uscResponses,
HNET_RESPONSE_RANGE rgResponses[],
IHNetApplicationProtocol **ppProtocol
)
{
HRESULT hr = S_OK;
BSTR bstr;
VARIANT vt;
SAFEARRAY *psa;
IWbemClassObject *pwcoInstance;
if (NULL == ppProtocol)
{
hr = E_POINTER;
}
else
{
*ppProtocol = NULL;
if (NULL == pszwName
|| 0 == ucOutgoingIPProtocol
|| 0 == usOutgoingPort
|| 0 == uscResponses
|| NULL == rgResponses)
{
hr = E_INVALIDARG;
}
}
if (S_OK == hr)
{
//
// Check to see if there already exists a protocol with the same
// outgoing protocol and port
//
if (ApplicationProtocolExists(
m_piwsHomenet,
m_bstrWQL,
usOutgoingPort,
ucOutgoingIPProtocol
))
{
hr = HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS);
}
}
if (S_OK == hr)
{
//
// Convert the array of response range structure to a
// SAFEARRAY of IUnknowns representing instances.
//
hr = ConvertResponseRangeArrayToInstanceSafearray(
m_piwsHomenet,
uscResponses,
rgResponses,
&psa
);
}
if (S_OK == hr)
{
//
// Spawn a new HNet_ApplicationProtocol
//
hr = SpawnNewInstance(
m_piwsHomenet,
c_wszHnetApplicationProtocol,
&pwcoInstance
);
if (WBEM_S_NO_ERROR == hr)
{
//
// Write the array property
//
V_VT(&vt) = VT_ARRAY | VT_UNKNOWN;
V_ARRAY(&vt) = psa;
hr = pwcoInstance->Put(
c_wszResponseArray,
0,
&vt,
NULL
);
if (WBEM_S_NO_ERROR == hr)
{
//
// Write the name
//
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = SysAllocString(pszwName);
if (NULL != V_BSTR(&vt))
{
hr = pwcoInstance->Put(
c_wszName,
0,
&vt,
NULL
);
VariantClear(&vt);
}
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Write the response count. WMI uses VT_I4
// for its uint16 type
//
V_VT(&vt) = VT_I4;
V_I4(&vt) = uscResponses;
hr = pwcoInstance->Put(
c_wszResponseCount,
0,
&vt,
NULL
);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Write the outgoing port
//
V_VT(&vt) = VT_I4;
V_I4(&vt) = usOutgoingPort;
hr = pwcoInstance->Put(
c_wszOutgoingPort,
0,
&vt,
NULL
);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Write the outgoing IP protocol
//
V_VT(&vt) = VT_UI1;
V_UI1(&vt) = ucOutgoingIPProtocol;
hr = pwcoInstance->Put(
c_wszOutgoingIPProtocol,
0,
&vt,
NULL
);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Set the builtin value to false
//
hr = SetBooleanValue(
pwcoInstance,
c_wszBuiltIn,
FALSE
);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// New protocols are disabled by default
//
hr = SetBooleanValue(
pwcoInstance,
c_wszEnabled,
FALSE
);
}
if (WBEM_S_NO_ERROR == hr)
{
IWbemCallResult *pResult;
//
// Write the instance to the store
//
pResult = NULL;
hr = m_piwsHomenet->PutInstance(
pwcoInstance,
WBEM_FLAG_CREATE_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pResult
);
if (WBEM_S_NO_ERROR == hr)
{
pwcoInstance->Release();
pwcoInstance = NULL;
hr = pResult->GetResultString(WBEM_INFINITE, &bstr);
if (WBEM_S_NO_ERROR == hr)
{
hr = GetWmiObjectFromPath(
m_piwsHomenet,
bstr,
&pwcoInstance
);
SysFreeString(bstr);
}
pResult->Release();
}
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Create the object to return
//
CComObject<CHNetAppProtocol> *pProt;
hr = CComObject<CHNetAppProtocol>::CreateInstance(&pProt);
if (S_OK == hr)
{
pProt->AddRef();
hr = pProt->Initialize(m_piwsHomenet, pwcoInstance);
if (S_OK == hr)
{
hr = pProt->QueryInterface(
IID_PPV_ARG(IHNetApplicationProtocol, ppProtocol)
);
}
pProt->Release();
}
}
if (NULL != pwcoInstance)
{
pwcoInstance->Release();
}
}
SafeArrayDestroy(psa);
}
return hr;
}
STDMETHODIMP
CHNetCfgMgr::EnumPortMappingProtocols(
IEnumHNetPortMappingProtocols **ppEnum
)
{
HRESULT hr = S_OK;
IEnumWbemClassObject *pwcoEnum;
BSTR bstrClass;
if (!ppEnum)
{
hr = E_POINTER;
}
else
{
*ppEnum = NULL;
}
if (S_OK == hr)
{
bstrClass = SysAllocString(c_wszHnetPortMappingProtocol);
if (NULL == bstrClass)
{
hr = E_OUTOFMEMORY;
}
}
if (S_OK == hr)
{
//
// Query the WMI store for HNet_PortMappingProtocol instances.
//
pwcoEnum = NULL;
hr = m_piwsHomenet->CreateInstanceEnum(
bstrClass,
WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pwcoEnum
);
SysFreeString(bstrClass);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Create and initialize the wrapper for the enum
//
CComObject<CEnumHNetPortMappingProtocols> *pEnum;
hr = CComObject<CEnumHNetPortMappingProtocols>::CreateInstance(&pEnum);
if (SUCCEEDED(hr))
{
pEnum->AddRef();
hr = pEnum->Initialize(m_piwsHomenet, pwcoEnum);
if (SUCCEEDED(hr))
{
hr = pEnum->QueryInterface(
IID_PPV_ARG(IEnumHNetPortMappingProtocols, ppEnum)
);
}
pEnum->Release();
}
pwcoEnum->Release();
}
return hr;
}
STDMETHODIMP
CHNetCfgMgr::CreatePortMappingProtocol(
OLECHAR *pszwName,
UCHAR ucIPProtocol,
USHORT usPort,
IHNetPortMappingProtocol **ppProtocol
)
{
HRESULT hr = S_OK;
BSTR bstr;
VARIANT vt;
IWbemClassObject *pwcoInstance;
if (NULL == ppProtocol)
{
hr = E_POINTER;
}
else
{
*ppProtocol = NULL;
if (NULL == pszwName
|| 0 == ucIPProtocol
|| 0 == usPort)
{
hr = E_INVALIDARG;
}
}
if (S_OK == hr)
{
//
// Check to see if there already exists a protocol with
// the same port/protocol combination
//
if (PortMappingProtocolExists(
m_piwsHomenet,
m_bstrWQL,
usPort,
ucIPProtocol
))
{
hr = HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS);
}
}
if (S_OK == hr)
{
hr = SpawnNewInstance(
m_piwsHomenet,
c_wszHnetPortMappingProtocol,
&pwcoInstance
);
}
if (WBEM_S_NO_ERROR == hr)
{
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = SysAllocString(pszwName);
if (NULL != V_BSTR(&vt))
{
//
// Write the name
//
hr = pwcoInstance->Put(
c_wszName,
0,
&vt,
NULL
);
VariantClear(&vt);
}
else
{
hr = E_OUTOFMEMORY;
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Write the port
//
V_VT(&vt) = VT_I4;
V_I4(&vt) = usPort;
hr = pwcoInstance->Put(
c_wszPort,
0,
&vt,
NULL
);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Write the IP protocol
//
V_VT(&vt) = VT_UI1;
V_UI1(&vt) = ucIPProtocol;
hr = pwcoInstance->Put(
c_wszIPProtocol,
0,
&vt,
NULL
);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Set BuiltIn to false
//
hr = SetBooleanValue(
pwcoInstance,
c_wszBuiltIn,
FALSE
);
}
if (WBEM_S_NO_ERROR == hr)
{
IWbemCallResult *pResult;
//
// Write the instance to the store
//
pResult = NULL;
hr = m_piwsHomenet->PutInstance(
pwcoInstance,
WBEM_FLAG_CREATE_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pResult
);
if (WBEM_S_NO_ERROR == hr)
{
pwcoInstance->Release();
pwcoInstance = NULL;
hr = pResult->GetResultString(WBEM_INFINITE, &bstr);
if (WBEM_S_NO_ERROR == hr)
{
hr = GetWmiObjectFromPath(
m_piwsHomenet,
bstr,
&pwcoInstance
);
SysFreeString(bstr);
}
pResult->Release();
}
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Create the object to return
//
CComObject<CHNetPortMappingProtocol> *pProt;
hr = CComObject<CHNetPortMappingProtocol>::CreateInstance(&pProt);
if (S_OK == hr)
{
pProt->AddRef();
hr = pProt->Initialize(m_piwsHomenet, pwcoInstance);
if (S_OK == hr)
{
hr = pProt->QueryInterface(
IID_PPV_ARG(IHNetPortMappingProtocol, ppProtocol)
);
}
pProt->Release();
}
}
if (NULL != pwcoInstance)
{
pwcoInstance->Release();
}
}
if (WBEM_S_NO_ERROR == hr)
{
SendPortMappingListChangeNotification();
}
return hr;
}
STDMETHODIMP
CHNetCfgMgr::FindPortMappingProtocol(
GUID *pGuid,
IHNetPortMappingProtocol **ppProtocol
)
{
BSTR bstr;
HRESULT hr = S_OK;
OLECHAR *pwszGuid;
OLECHAR wszPath[MAX_PATH];
IWbemClassObject *pwcoInstance;
if (NULL != ppProtocol)
{
*ppProtocol = NULL;
if (NULL == pGuid)
{
hr = E_INVALIDARG;
}
}
else
{
hr = E_POINTER;
}
if (S_OK == hr)
{
//
// Convert the GUID to string form
//
hr = StringFromCLSID(*pGuid, &pwszGuid);
}
if (S_OK == hr)
{
//
// Construct the path to the desired protocol
//
int count =
_snwprintf(
wszPath,
MAX_PATH,
L"%s.%s=\"%s\"",
c_wszHnetPortMappingProtocol,
c_wszId,
pwszGuid
);
_ASSERT(count > 0);
CoTaskMemFree(pwszGuid);
bstr = SysAllocString(wszPath);
if (NULL != bstr)
{
hr = GetWmiObjectFromPath(m_piwsHomenet, bstr, &pwcoInstance);
SysFreeString(bstr);
}
else
{
hr = E_OUTOFMEMORY;
}
}
if (S_OK == hr)
{
CComObject<CHNetPortMappingProtocol> *pProtocol;
hr = CComObject<CHNetPortMappingProtocol>::CreateInstance(&pProtocol);
if (SUCCEEDED(hr))
{
pProtocol->AddRef();
hr = pProtocol->Initialize(m_piwsHomenet, pwcoInstance);
if (SUCCEEDED(hr))
{
hr = pProtocol->QueryInterface(
IID_PPV_ARG(IHNetPortMappingProtocol, ppProtocol)
);
}
pProtocol->Release();
}
pwcoInstance->Release();
}
return hr;
}
//
// Private methods
//
HRESULT
CHNetCfgMgr::CopyLoggingInstanceToStruct(
IWbemClassObject *pwcoInstance,
HNET_FW_LOGGING_SETTINGS *pfwSettings
)
{
HRESULT hr;
VARIANT vt;
BSTR bstrPath;
_ASSERT(pwcoInstance);
_ASSERT(pfwSettings);
//
// Zero-out settings structure
//
ZeroMemory(pfwSettings, sizeof(*pfwSettings));
//
// Get the Path property.
//
hr = pwcoInstance->Get(
c_wszPath,
0,
&vt,
NULL,
NULL
);
if (WBEM_S_NO_ERROR == hr)
{
_ASSERT(VT_BSTR == V_VT(&vt));
//
// Allocate space to hold the string
//
pfwSettings->pszwPath =
(LPWSTR) CoTaskMemAlloc((SysStringLen(V_BSTR(&vt)) + 1)
* sizeof(OLECHAR));
if (NULL != pfwSettings->pszwPath)
{
//
// Copy string over
//
wcscpy(pfwSettings->pszwPath, V_BSTR(&vt));
}
else
{
hr = E_OUTOFMEMORY;
}
//
// Free the returned BSTR
//
VariantClear(&vt);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Get max file size
//
hr = pwcoInstance->Get(
c_wszMaxFileSize,
0,
&vt,
NULL,
NULL
);
if (WBEM_S_NO_ERROR == hr)
{
_ASSERT(VT_I4 == V_VT(&vt));
pfwSettings->ulMaxFileSize = V_I4(&vt);
VariantClear(&vt);
}
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Get log dropped packets value
//
hr = GetBooleanValue(
pwcoInstance,
c_wszLogDroppedPackets,
&pfwSettings->fLogDroppedPackets
);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Get log connections value
//
hr = GetBooleanValue(
pwcoInstance,
c_wszLogConnections,
&pfwSettings->fLogConnections
);
}
if (FAILED(hr) && NULL != pfwSettings->pszwPath)
{
CoTaskMemFree(pfwSettings->pszwPath);
}
return hr;
}
HRESULT
CHNetCfgMgr::CopyStructToLoggingInstance(
HNET_FW_LOGGING_SETTINGS *pfwSettings,
IWbemClassObject *pwcoInstance
)
{
HRESULT hr = S_OK;
VARIANT vt;
_ASSERT(pwcoInstance);
_ASSERT(pfwSettings);
//
// Wrap the path in a BSTR in a varaint
//
VariantInit(&vt);
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = SysAllocString(pfwSettings->pszwPath);
if (NULL == V_BSTR(&vt))
{
hr = E_OUTOFMEMORY;
}
if (S_OK == hr)
{
//
// Set the Path property.
//
hr = pwcoInstance->Put(
c_wszPath,
0,
&vt,
NULL
);
//
// Clearing the variant will free the BSTR we allocated
// above.
//
VariantClear(&vt);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Set max file size
//
V_VT(&vt) = VT_I4;
V_I4(&vt) = pfwSettings->ulMaxFileSize;
hr = pwcoInstance->Put(
c_wszMaxFileSize,
0,
&vt,
NULL
);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Set log dropped packets value
//
hr = SetBooleanValue(
pwcoInstance,
c_wszLogDroppedPackets,
pfwSettings->fLogDroppedPackets
);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Set log connections value
//
hr = SetBooleanValue(
pwcoInstance,
c_wszLogConnections,
pfwSettings->fLogConnections
);
}
return hr;
}
HRESULT
CHNetCfgMgr::InstallBridge(
GUID *pguid,
INetCfg *pnetcfgExisting
)
{
HRESULT hr = S_OK;
INetCfg *pnetcfg = NULL;
INetCfgLock *pncfglock = NULL;
INetCfgComponent *pncfgcomp = NULL;
if( NULL == pnetcfgExisting )
{
hr = InitializeNetCfgForWrite( &pnetcfg, &pncfglock );
// Bail out if we can't acquire NetCfg.
if( FAILED(hr) )
{
return hr;
}
}
else
{
// Use the NetCfg context we were given
pnetcfg = pnetcfgExisting;
}
// We must have a NetCfg context at this point
_ASSERT( pnetcfg != NULL );
// ===================================================================
// (cut here)
//
// Check if the bridge component already exists
//
// **
// Remove this check when it becomes legal to have
// multiple bridges
// **
//
hr = pnetcfg->FindComponent(
c_wszSBridgeMPID,
&pncfgcomp
);
// S_OK indicates that the bridge component is present, which is BAD.
// We take any other success code to indicate that the search succeeded,
// but that the bridge component was not present (which is what we want).
// We take failure codes to mean the search blew up.
if ( S_OK == hr )
{
// Bridge was present
pncfgcomp->Release();
hr = E_UNEXPECTED;
}
// (cut here)
// ===================================================================
if ( SUCCEEDED(hr) )
{
const GUID guidClass = GUID_DEVCLASS_NET;
INetCfgClassSetup *pncfgsetup = NULL;
//
// Recover the NetCfgClassSetup interface
//
hr = pnetcfg->QueryNetCfgClass(
&guidClass,
IID_PPV_ARG(INetCfgClassSetup, &pncfgsetup)
);
if ( SUCCEEDED(hr) )
{
//
// Install the bridge miniport component
//
hr = pncfgsetup->Install(
c_wszSBridgeMPID,
NULL,
NSF_PRIMARYINSTALL,
0,
NULL,
NULL,
&pncfgcomp
);
if ( SUCCEEDED(hr) )
{
hr = pncfgcomp->GetInstanceGuid(pguid);
pncfgcomp->Release();
}
pncfgsetup->Release();
}
}
// If we created our own NetCfg context, shut it down now
if( NULL == pnetcfgExisting )
{
// Apply everything if we succeeded, back out otherwise
if ( SUCCEEDED(hr) )
{
hr = pnetcfg->Apply();
// Signal that the bridge should be drawn
SignalNewConnection( pguid );
}
else
{
// Don't want to lose the original error code
pnetcfg->Cancel();
}
UninitializeNetCfgForWrite( pnetcfg, pncfglock );
}
return hr;
}
HRESULT
CHNetCfgMgr::CreateConnectionAndPropertyInstances(
GUID *pGuid,
BOOLEAN fLanConnection,
LPCWSTR pszwName,
IWbemClassObject **ppwcoConnection,
IWbemClassObject **ppwcoProperties
)
{
HRESULT hr;
BSTR bstr = NULL;
IWbemClassObject *pwcoConnection = NULL;
IWbemClassObject *pwcoProperties;
IWbemCallResult *pResult;
VARIANT vt;
_ASSERT(NULL != pGuid);
_ASSERT(NULL != pszwName);
_ASSERT(NULL != ppwcoConnection);
_ASSERT(NULL != ppwcoProperties);
//
// Create the HNet_Connection instance
//
hr = SpawnNewInstance(
m_piwsHomenet,
c_wszHnetConnection,
&pwcoConnection
);
//
// Fill out the HNet_Connection instance
//
if (WBEM_S_NO_ERROR == hr)
{
LPOLESTR wszGuid;
//
// Set GUID property
//
hr = StringFromCLSID(*pGuid, &wszGuid);
if (S_OK == hr)
{
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = SysAllocString(wszGuid);
if (NULL != V_BSTR(&vt))
{
hr = pwcoConnection->Put(
c_wszGuid,
0,
&vt,
NULL
);
VariantClear(&vt);
}
else
{
hr = E_OUTOFMEMORY;
}
CoTaskMemFree(wszGuid);
}
//
// Set Name property
//
if (WBEM_S_NO_ERROR == hr)
{
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = SysAllocString(pszwName);
if (NULL != V_BSTR(&vt))
{
hr = pwcoConnection->Put(
c_wszName,
0,
&vt,
NULL
);
VariantClear(&vt);
}
else
{
hr = E_OUTOFMEMORY;
}
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Set the IsLan property
//
hr = SetBooleanValue(
pwcoConnection,
c_wszIsLanConnection,
fLanConnection
);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Commit the object and retrieve its path
//
pResult = NULL;
hr = m_piwsHomenet->PutInstance(
pwcoConnection,
WBEM_FLAG_CREATE_OR_UPDATE | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pResult
);
if (WBEM_S_NO_ERROR == hr)
{
pwcoConnection->Release();
pwcoConnection = NULL;
hr = pResult->GetResultString(WBEM_INFINITE, &bstr);
pResult->Release();
if (WBEM_S_NO_ERROR == hr)
{
hr = GetWmiObjectFromPath(
m_piwsHomenet,
bstr,
&pwcoConnection
);
if (FAILED(hr))
{
SysFreeString(bstr);
bstr = NULL;
}
//
// The bstr will be freed below on success
//
}
}
}
if (FAILED(hr) && NULL != pwcoConnection)
{
//
// Something went wrong -- get rid
// of the instance we created
//
pwcoConnection->Release();
pwcoConnection = NULL;
}
}
if (S_OK == hr)
{
//
// Create the HNet_ConnectionProperties instance
//
hr = SpawnNewInstance(
m_piwsHomenet,
c_wszHnetProperties,
&pwcoProperties
);
//
// Fill out the HNet_ConnectionProperties instance
//
if (WBEM_S_NO_ERROR == hr)
{
//
// Set the path to our connection
//
V_VT(&vt) = VT_BSTR;
V_BSTR(&vt) = bstr;
hr = pwcoProperties->Put(
c_wszConnection,
0,
&vt,
NULL
);
VariantClear(&vt);
if (WBEM_S_NO_ERROR == hr)
{
hr = SetBooleanValue(
pwcoProperties,
c_wszIsFirewalled,
FALSE
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = SetBooleanValue(
pwcoProperties,
c_wszIsIcsPublic,
FALSE
);
}
if (WBEM_S_NO_ERROR == hr)
{
hr = SetBooleanValue(
pwcoProperties,
c_wszIsIcsPrivate,
FALSE
);
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Commit properties instance to the store
//
pResult = NULL;
hr = m_piwsHomenet->PutInstance(
pwcoProperties,
WBEM_FLAG_CREATE_OR_UPDATE | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pResult
);
if (WBEM_S_NO_ERROR == hr)
{
pwcoProperties->Release();
pwcoProperties = NULL;
hr = pResult->GetResultString(WBEM_INFINITE, &bstr);
pResult->Release();
if (WBEM_S_NO_ERROR == hr)
{
hr = GetWmiObjectFromPath(
m_piwsHomenet,
bstr,
&pwcoProperties
);
SysFreeString(bstr);
}
}
}
if (FAILED(hr))
{
//
// Something went wrong -- get rid of the instances
// we created. We also need to delete the connection
// instance from the store.
//
DeleteWmiInstance(m_piwsHomenet, pwcoConnection);
pwcoConnection->Release();
pwcoConnection = NULL;
if (NULL != pwcoProperties)
{
pwcoProperties->Release();
pwcoProperties = NULL;
}
}
}
}
if (WBEM_S_NO_ERROR == hr)
{
//
// Transferring reference, so skip release on pwco[x] and
// addref on ppwco[x]
//
*ppwcoConnection = pwcoConnection;
*ppwcoProperties = pwcoProperties;
}
return hr;
}
BOOLEAN
CHNetCfgMgr::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
CHNetCfgMgr::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;
}