//+--------------------------------------------------------------------------- // // 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 #define STRSAFE_NO_DEPRECATE #include // // 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_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_DISABLE_AAA, 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 *pHNConn; // // Create the wrapper object // hr = CComObject::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 *pHNConn; // // Create the wrapper object // hr = CComObject::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 *pEnum; IHNetBridge *phnbridge; if( NULL != ppEnum ) { *ppEnum = NULL; hr = GetBridgeConnection( m_piwsHomenet, &phnbridge ); if( S_OK == hr ) { hr = CComObject::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::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 *pBridge; // // Create wrapper object to return // hr = CComObject::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 *pEnum; hr = CComObject::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( 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 *pEnum; hr = CComObject::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 *pEnum; hr = CComObject::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( 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_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_DISABLE_AAA, 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(rgConnections); rgConnections = reinterpret_cast( 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(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(rgConnections)); } } else { // // Cleanup output array // if (NULL != rgConnections) { for (i = 0; i < cConn; i++) { if (NULL != rgConnections[i]) { rgConnections[i]->Release(); } } CoTaskMemFree(reinterpret_cast(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 *pEnum; hr = CComObject::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 CHNetCfgMgr::RefreshTargetComputerAddress( OLECHAR *pszwName, ULONG ulAddress ) { HRESULT hr = S_OK; BSTR bstrQuery; LPWSTR wszNameClause; LPWSTR wszWhereClause; IEnumWbemClassObject *pwcoEnum = NULL; IWbemClassObject *pwcoInstance; VARIANT vt; if (NULL == pszwName || 0 == ulAddress) { hr = E_INVALIDARG; } // // Query for all bindings which match the target computer name. // // SELECT * FROM HNet_ConnectionPortMapping2 where // TargetName = (computer name) AND NameActive != FALSE // if (S_OK == hr) { hr = BuildQuotedEqualsString( &wszNameClause, c_wszTargetName, pszwName ); } if (S_OK == hr) { hr = BuildAndString( &wszWhereClause, wszNameClause, L"NameActive != FALSE" ); delete [] wszNameClause; } if (S_OK == hr) { hr = BuildSelectQueryBstr( &bstrQuery, c_wszStar, c_wszHnetConnectionPortMapping, wszWhereClause ); delete [] wszWhereClause; } if (S_OK == hr) { hr = m_piwsHomenet->ExecQuery( m_bstrWQL, bstrQuery, WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, NULL, &pwcoEnum ); SysFreeString(bstrQuery); } while (WBEM_S_NO_ERROR == hr) { ULONG ulCount; pwcoInstance = NULL; hr = pwcoEnum->Next(WBEM_INFINITE, 1, &pwcoInstance, &ulCount); if (SUCCEEDED(hr) && ulCount == 1) { V_VT(&vt) = VT_I4; V_I4(&vt) = ulAddress; hr = pwcoInstance->Put( c_wszTargetIPAddress, 0, &vt, NULL ); if (WBEM_S_NO_ERROR == hr) { // // Write the modified instance to the store // hr = m_piwsHomenet->PutInstance( pwcoInstance, WBEM_FLAG_UPDATE_ONLY, NULL, NULL ); } pwcoInstance->Release(); } } if (S_FALSE == hr) { hr = S_OK; } if (pwcoEnum) { 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 *pEnum; hr = CComObject::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) { // bug 555896: should limit the length of untrusted input string // to some reasonable size. Am using INTERNET_MAX_HOST_NAME_LENGTH // (somewhat arbitrarily), which is 256. WCHAR szwName[INTERNET_MAX_HOST_NAME_LENGTH]; StringCchCopyW (szwName, INTERNET_MAX_HOST_NAME_LENGTH, pszwName); // // Write the name // V_VT(&vt) = VT_BSTR; V_BSTR(&vt) = SysAllocString(szwName); 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 *pProt; hr = CComObject::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 *pEnum; hr = CComObject::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) { // bug 555896: should limit the length of untrusted input string // to some reasonable size. Am using INTERNET_MAX_HOST_NAME_LENGTH // (somewhat arbitrarily), which is 256. WCHAR szwName[INTERNET_MAX_HOST_NAME_LENGTH]; StringCchCopyW (szwName, INTERNET_MAX_HOST_NAME_LENGTH, pszwName); V_VT(&vt) = VT_BSTR; V_BSTR(&vt) = SysAllocString(szwName); 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 *pProt; hr = CComObject::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 *pProtocol; hr = CComObject::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); bstr = NULL; 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); bstr = NULL; } } } 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 (bstr) { SysFreeString (bstr); bstr = 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_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 CHNetCfgMgr::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; }