|
|
#include "pch.h"
#pragma hdrstop
#include "CWANConnectionBase.h"
#include "beacon.h"
#include <ipnat.h>
#include <iphlpapi.h>
#include <ntddip.h>
#include <winsock.h>
#include "debug.h"
#include "util.h"
extern "C" ULONG NhpAllocateAndGetInterfaceInfoFromStack( IP_INTERFACE_NAME_INFO** Table, PULONG Count, BOOL SortOutput, HANDLE AllocationHeap, ULONG AllocationFlags );
CWANConnectionBase::CWANConnectionBase() { m_pConnectionPoint = NULL; m_pHomenetConnection = NULL; m_pEventSink = NULL;
m_pStatisticsProvider = NULL;
m_IcsSettingsp = NULL; m_hAdviseNATEventsResult = E_FAIL; }
HRESULT CWANConnectionBase::FinalConstruct() { HRESULT hr = S_OK; hr = StartNetmanEvents(this); if(SUCCEEDED(hr)) { hr = AdviseNATEvents(this); m_hAdviseNATEventsResult = hr; } return hr; }
HRESULT CWANConnectionBase::FinalRelease() {
if ( NULL != m_pHomenetConnection) { m_pHomenetConnection->Release(); }
if ( NULL != m_IcsSettingsp) { m_IcsSettingsp->Release(); }
if(NULL != m_pStatisticsProvider) { m_pStatisticsProvider->Release(); } DestroyDebugger();
return S_OK; }
HRESULT CWANConnectionBase::StopListening()
{ HRESULT hr = S_OK;
if(NULL != m_pConnectionPoint) { hr = m_pConnectionPoint->Unadvise(m_dwConnectionManagerConnectionPointCookie);
m_pConnectionPoint->Release(); m_pConnectionPoint = NULL; }
if(SUCCEEDED(m_hAdviseNATEventsResult)) { UnadviseNATEvents(this); } return hr; }
HRESULT CWANConnectionBase::StartNetmanEvents(INetConnectionNotifySink* pSink) { HRESULT hr = S_OK;
INetConnectionManager* pConnectionManager; hr = CoCreateInstance(CLSID_ConnectionManager, NULL, CLSCTX_SERVER, IID_INetConnectionManager, reinterpret_cast<void**>(&pConnectionManager)); if SUCCEEDED(hr) { IConnectionPointContainer* pConnectionPointContainer; hr = pConnectionManager->QueryInterface(IID_IConnectionPointContainer, reinterpret_cast<void**>(&pConnectionPointContainer)); if(SUCCEEDED(hr)) { hr = pConnectionPointContainer->FindConnectionPoint(IID_INetConnectionNotifySink, &m_pConnectionPoint); if(SUCCEEDED(hr)) { hr = m_pConnectionPoint->Advise(pSink, &m_dwConnectionManagerConnectionPointCookie); if(FAILED(hr)) { m_pConnectionPoint->Release(); m_pConnectionPoint = NULL; } // release in stop listening on success
} pConnectionPointContainer->Release(); } pConnectionManager->Release(); }
return hr; }
HRESULT CWANConnectionBase::Initialize( GUID* pGuid, IHNetConnection* pHomenetConnection, IStatisticsProvider* pStatisticsProvider ) { HRESULT hr = S_OK; InitDebugger();
DBG_SPEW(TM_STATIC, TL_INFO, L" > Initialize ");
m_pStatisticsProvider = pStatisticsProvider; m_pStatisticsProvider->AddRef(); m_pHomenetConnection = pHomenetConnection; m_pHomenetConnection->AddRef();
CopyMemory(&m_SharedGuid, pGuid, sizeof(GUID));
hr = CoCreateInstance(CLSID_HNetCfgMgr, NULL, CLSCTX_SERVER, IID_IHNetIcsSettings, reinterpret_cast<void**>(&m_IcsSettingsp));
return hr; }
HRESULT CWANConnectionBase::FireEvent(DISPID DispatchId) { HRESULT hr = S_OK;
IUPnPEventSink* pEventSink = NULL;
Lock();
if(NULL != m_pEventSink) { pEventSink = m_pEventSink; pEventSink->AddRef(); }
Unlock();
if(NULL != pEventSink) { hr = pEventSink->OnStateChanged(1, &DispatchId); pEventSink->Release(); }
return hr; }
// IUPnPEventSource methods
HRESULT CWANConnectionBase::Advise(IUPnPEventSink* pesSubscriber) { HRESULT hr = S_OK;
Lock();
m_pEventSink = pesSubscriber; m_pEventSink->AddRef();
Unlock();
return hr; }
HRESULT CWANConnectionBase::Unadvise(IUPnPEventSink *pesSubscriber) { HRESULT hr = S_OK;
Lock(); m_pEventSink->Release(); m_pEventSink = NULL;
Unlock();
return hr; }
// INATEventsNotifySink
HRESULT CWANConnectionBase::PublicIPAddressChanged(void) { return FireEvent(IWANIPCONNECTION_DISPID_EXTERNALIPADDRESS); }
HRESULT CWANConnectionBase::PortMappingsChanged(void) { return FireEvent(IWANIPCONNECTION_DISPID_PORTMAPPINGNUMBEROFENTRIES); }
// INetConnectionNotifySink methods
HRESULT CWANConnectionBase::ConnectionAdded(const NETCON_PROPERTIES_EX* pProps) { HRESULT hr = S_OK;
return hr; }
HRESULT CWANConnectionBase::ConnectionBandWidthChange(const GUID* pguidId) { HRESULT hr = S_OK;
return hr; }
HRESULT CWANConnectionBase::ConnectionDeleted(const GUID* pguidId) { HRESULT hr = S_OK;
return hr; }
HRESULT CWANConnectionBase::ConnectionModified(const NETCON_PROPERTIES_EX* pProps) { HRESULT hr = S_OK; return hr; }
HRESULT CWANConnectionBase::ConnectionRenamed(const GUID* pguidId, LPCWSTR pszwNewName) { HRESULT hr = S_OK; if(IsEqualGUID(*pguidId, m_SharedGuid)) { hr = FireEvent(IWANIPCONNECTION_DISPID_NAME); }
return hr; }
HRESULT CWANConnectionBase::ConnectionStatusChange(const GUID* pguidId, NETCON_STATUS Status) { HRESULT hr = S_OK; if(IsEqualGUID(*pguidId, m_SharedGuid)) { hr = FireEvent(IWANIPCONNECTION_DISPID_CONNECTIONSTATUS); } return hr; }
HRESULT CWANConnectionBase::ConnectionAddressChange(const GUID* pguidId) { HRESULT hr = S_OK;
if ( IsEqualGUID(*pguidId, m_SharedGuid) ) { hr = FireEvent( IWANIPCONNECTION_DISPID_EXTERNALIPADDRESS ); }
return hr; }
HRESULT CWANConnectionBase::ShowBalloon(const GUID* pguidId, const BSTR szCookie, const BSTR szBalloonText) { HRESULT hr = E_NOTIMPL; return hr; }
HRESULT CWANConnectionBase::RefreshAll() { HRESULT hr = S_OK;
return hr; }
HRESULT CWANConnectionBase::DisableEvents(const BOOL fDisable, const ULONG ulDisableTimeout) { HRESULT hr = S_OK;
return hr; }
// IWANIPConnection and IWANPPPConnection methods
HRESULT CWANConnectionBase::get_ConnectionType(BSTR *pConnectionType) { HRESULT hr = S_OK; *pConnectionType = SysAllocString(L"IP_Routed"); if(NULL == *pConnectionType) { hr = E_OUTOFMEMORY; } return hr; }
HRESULT CWANConnectionBase::get_PossibleConnectionTypes(BSTR *pPossibleConnectionTypes) { HRESULT hr = S_OK; *pPossibleConnectionTypes = SysAllocString(L"IP_Routed"); if(NULL == *pPossibleConnectionTypes) { hr = E_OUTOFMEMORY; } return hr; }
HRESULT CWANConnectionBase::get_ConnectionStatus(BSTR *pConnectionStatus) { HRESULT hr = S_OK;
*pConnectionStatus = NULL;
INetConnection* pNetConnection; hr = m_pHomenetConnection->GetINetConnection(&pNetConnection); if(SUCCEEDED(hr)) { NETCON_PROPERTIES* pProperties; hr = pNetConnection->GetProperties(&pProperties); if(SUCCEEDED(hr)) { LPWSTR pszStatus; switch(pProperties->Status) { case NCS_AUTHENTICATION_SUCCEEDED: case NCS_CONNECTED: pszStatus = L"Connected"; break; case NCS_DISCONNECTED: pszStatus = L"Disconnected"; break; case NCS_AUTHENTICATING: case NCS_CONNECTING: pszStatus = L"Connecting"; break; case NCS_DISCONNECTING: pszStatus = L"Disconnecting"; break; case NCS_INVALID_ADDRESS: case NCS_CREDENTIALS_REQUIRED: case NCS_AUTHENTICATION_FAILED: case NCS_HARDWARE_DISABLED: case NCS_HARDWARE_MALFUNCTION: case NCS_HARDWARE_NOT_PRESENT: default: pszStatus = L"Unconfigured"; break; } *pConnectionStatus = SysAllocString(pszStatus); if(NULL == *pConnectionStatus) { hr = E_OUTOFMEMORY; } NcFreeNetconProperties(pProperties); } pNetConnection->Release(); } return hr;
}
HRESULT CWANConnectionBase::get_Uptime(ULONG *pUptime) { HRESULT hr = S_OK;
hr = m_pStatisticsProvider->GetStatistics(NULL, NULL, NULL, NULL, NULL, pUptime); return hr; }
HRESULT CWANConnectionBase::get_UpstreamMaxBitRate(ULONG *pUpstreamMaxBitRate) { HRESULT hr = S_OK;
hr = m_pStatisticsProvider->GetStatistics(NULL, NULL, NULL, NULL, pUpstreamMaxBitRate, NULL); return hr; }
HRESULT CWANConnectionBase::get_DownstreamMaxBitRate(ULONG *pDownstreamMaxBitRate) { HRESULT hr = S_OK; hr = m_pStatisticsProvider->GetStatistics(NULL, NULL, NULL, NULL, pDownstreamMaxBitRate, NULL);
return hr; }
HRESULT CWANConnectionBase::get_RSIPAvailable(VARIANT_BOOL *pRSIPAvailable) { HRESULT hr = S_OK; *pRSIPAvailable = VARIANT_FALSE; return hr; }
HRESULT CWANConnectionBase::get_NATEnabled(VARIANT_BOOL *pNATEnabled) { HRESULT hr = S_OK; *pNATEnabled = VARIANT_TRUE; return hr; }
HRESULT CWANConnectionBase::get_X_Name(BSTR* pName) {
HRESULT hr = S_OK;
*pName = NULL; INetConnection* pNetConnection; hr = m_pHomenetConnection->GetINetConnection(&pNetConnection); if(SUCCEEDED(hr)) { NETCON_PROPERTIES* pProperties; hr = pNetConnection->GetProperties(&pProperties); if(SUCCEEDED(hr)) { *pName = SysAllocString(pProperties->pszwName); if(NULL == *pName) { hr = E_OUTOFMEMORY; } NcFreeNetconProperties(pProperties); } pNetConnection->Release(); } return hr; }
HRESULT get_HrLocalAdaptersInfo(PIP_ADAPTER_INFO* ppAdapter) { HRESULT hr = S_OK, dwErr = NO_ERROR; PIP_ADAPTER_INFO paAdapterInfo = NULL; ULONG uBufLen = (2 * BUF_SIZE);
_ASSERT( ppAdapter != NULL );
*ppAdapter = NULL;
paAdapterInfo = (PIP_ADAPTER_INFO) CoTaskMemAlloc( uBufLen );
if ( NULL == paAdapterInfo ) { return E_OUTOFMEMORY; }
//
// Discover How much Memory we need. If we need at all.
// Note that paAdapterInfo may be non-NULL and that is desired.
dwErr = GetAdaptersInfo( paAdapterInfo, &uBufLen );
if ( ERROR_BUFFER_OVERFLOW == dwErr ) { CoTaskMemFree( paAdapterInfo );
paAdapterInfo = (PIP_ADAPTER_INFO) CoTaskMemAlloc( uBufLen );
if ( paAdapterInfo != NULL) { dwErr = GetAdaptersInfo ( paAdapterInfo, &uBufLen ); } }
if ( paAdapterInfo == NULL) { return E_OUTOFMEMORY; }
if ( ERROR_SUCCESS != dwErr ) { DBG_SPEW( TM_INFO, TL_ERROR, L" GetAdapterInfo has failed with E(%u) BufSize(%u) ", dwErr, uBufLen );
CoTaskMemFree(paAdapterInfo);
return HRESULT_FROM_WIN32( dwErr ); }
if ( ppAdapter && paAdapterInfo ) { *ppAdapter = paAdapterInfo; }
return hr; }
// {c200e360-38c5-11ce-ae62-08002b2b79ef} - 38 chars
#define GUID_STRING_LENGTH 38
PIP_ADAPTER_INFO GetExternalAdapterInfo( GUID* pGUID ) { HRESULT hr = S_OK; WCHAR szwGUID[ GUID_STRING_LENGTH + 1 ] = { 0 }; char ascGUID[ GUID_STRING_LENGTH + 1 ] = { 0 }; PIP_ADAPTER_INFO pRetAdapter = NULL; PIP_ADAPTER_INFO pAdapterList = NULL, pTempAdapter = NULL;
_ASSERT( pGUID != NULL );
//
// Change the given GUID to a String
if ( StringFromGUID2( *pGUID, szwGUID, GUID_STRING_LENGTH + 1 ) == 0 ) { return NULL; }
if ( WideCharToMultiByte( CP_ACP, 0, szwGUID, -1, ascGUID, sizeof(ascGUID), NULL, NULL) == 0 ) { return NULL; }
hr = get_HrLocalAdaptersInfo( &pAdapterList );
if ( FAILED(hr) || (pAdapterList == NULL) ) { return NULL; }
pTempAdapter = pAdapterList;
while ( pAdapterList != NULL ) { if ( 0 == strcmp(ascGUID, pAdapterList->AdapterName) ) { pRetAdapter = (PIP_ADAPTER_INFO) CoTaskMemAlloc( sizeof(IP_ADAPTER_INFO) );
if ( NULL != pRetAdapter ) { memcpy( pRetAdapter, pAdapterList, sizeof(IP_ADAPTER_INFO) ); pRetAdapter->Next = NULL; break; } }
pAdapterList = pAdapterList->Next; } CoTaskMemFree( pTempAdapter ); return pRetAdapter; }
HRESULT CWANConnectionBase::get_ExternalIPAddress(BSTR *pExternalIPAddress) { HRESULT hr = S_OK; ULONG AddressCount = 0; LPOLESTR swAddr = NULL; PIP_ADAPTER_INFO pExternalAdapterInfo = NULL; ULONG numOfChar = 0, uTemp = 0, Error = NO_ERROR;
WCHAR szwGUID[ GUID_STRING_LENGTH + 1 ] = { 0 }; IP_INTERFACE_NAME_INFO* Table = NULL; ULONG Count = 0;
_ASSERT( pExternalIPAddress != NULL ); if ( pExternalIPAddress != NULL ) { *pExternalIPAddress = NULL; } else { return E_POINTER; }
_ASSERT( pExternalIPAddress != NULL );
StringFromGUID2( m_SharedGuid, szwGUID, GUID_STRING_LENGTH + 1 );
DBG_SPEW(TM_INFO, TL_TRACE, L"> get_ExternalIpAddress Looking for GUID %s", szwGUID);
Error = NhpAllocateAndGetInterfaceInfoFromStack(&Table, &Count, FALSE, GetProcessHeap(), 0); if ( (NO_ERROR == Error) && (Table != NULL) ) { for (ULONG i = 0; i < Count ; i++) { #if DBG
StringFromGUID2( Table[i].DeviceGuid, szwGUID, GUID_STRING_LENGTH + 1 ); DBG_SPEW(TM_INFO, TL_DUMP, L" DeviceGUID[%u] = %s", i, szwGUID); StringFromGUID2( Table[i].InterfaceGuid, szwGUID, GUID_STRING_LENGTH + 1 ); DBG_SPEW(TM_INFO, TL_DUMP, L" DeviceGUID[%u] = %s", i, szwGUID); #endif
if ( IsEqualGUID((Table[i].InterfaceGuid), m_SharedGuid) ) { pExternalAdapterInfo = GetExternalAdapterInfo( &Table[i].DeviceGuid );
break; } }
HeapFree(GetProcessHeap(), 0, Table); }
if ( pExternalAdapterInfo == NULL ) { pExternalAdapterInfo = GetExternalAdapterInfo( &m_SharedGuid ); }
if ( pExternalAdapterInfo != NULL ) { if ( strcmp("0.0.0.0", pExternalAdapterInfo->IpAddressList.IpAddress.String) ) { numOfChar = strlen( pExternalAdapterInfo->IpAddressList.IpAddress.String ); swAddr = (LPOLESTR) CoTaskMemAlloc( (numOfChar + 1) * sizeof(WCHAR) ); if ( swAddr != NULL ) { memset( swAddr, 0, (numOfChar + 1) * sizeof(WCHAR)); uTemp = _snwprintf( swAddr, numOfChar, L"%S", pExternalAdapterInfo->IpAddressList.IpAddress.String ); _ASSERT( numOfChar == uTemp );
swAddr[ numOfChar] = L'\0'; *pExternalIPAddress = SysAllocString( swAddr ); CoTaskMemFree( swAddr ); } } else { *pExternalIPAddress = SysAllocString( L"" ); }
CoTaskMemFree( pExternalAdapterInfo ); } else { *pExternalIPAddress = SysAllocString( L"" ); }
if ( *pExternalIPAddress == NULL ) { hr = E_OUTOFMEMORY; } else { DBG_SPEW(TM_INFO, TL_INFO, L"Returning IP String (%s)", *pExternalIPAddress); }
return hr; }
HRESULT CWANConnectionBase::get_RemoteHost(BSTR *pRemoteHost) { HRESULT hr = E_NOTIMPL;
return hr; }
HRESULT CWANConnectionBase::get_ExternalPort(USHORT *pExternalPort) { HRESULT hr = E_NOTIMPL;
return hr; }
HRESULT CWANConnectionBase::get_InternalPort(USHORT *pInternalPort) { HRESULT hr = E_NOTIMPL;
return hr; }
HRESULT CWANConnectionBase::get_PortMappingProtocol(BSTR *pProtocol) { HRESULT hr = E_NOTIMPL;
return hr; }
HRESULT CWANConnectionBase::get_InternalClient(BSTR *pInternalClient) { HRESULT hr = E_NOTIMPL;
return hr; }
HRESULT CWANConnectionBase::get_PortMappingDescription(BSTR *pDescription) { HRESULT hr = E_NOTIMPL;
return hr; }
HRESULT CWANConnectionBase::get_PortMappingEnabled(VARIANT_BOOL *pEnabled) { HRESULT hr = E_NOTIMPL;
return hr; }
HRESULT CWANConnectionBase::get_PortMappingLeaseDuration(ULONG *LeaseDuration) { HRESULT hr = E_NOTIMPL;
return hr; }
HRESULT CWANConnectionBase::get_PortMappingNumberOfEntries(USHORT *pNumberOfEntries) { HRESULT hr = S_OK; IHNetPortMappingProtocol* MappingProtocolp = NULL;
IHNetProtocolSettings* ProtocolSettingsp = NULL;
IEnumHNetPortMappingProtocols* EnumProtocolsp = NULL;
_ASSERT( pNumberOfEntries != NULL );
*pNumberOfEntries = 0;
do { hr = m_IcsSettingsp->QueryInterface(IID_IHNetProtocolSettings, reinterpret_cast<void**>(&ProtocolSettingsp)); if( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Query Interface failed for ProtocolSettingsp E:(%X)", hr);
break; }
hr = ProtocolSettingsp->EnumPortMappingProtocols(&EnumProtocolsp);
if ( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Enum Interface can't be retrieved E(%X)", hr);
break; }
while( S_OK == EnumProtocolsp->Next(1, &MappingProtocolp, NULL) ) { (*pNumberOfEntries)++;
_ASSERT( MappingProtocolp != NULL );
MappingProtocolp->Release(); } } while ( FALSE );
if ( ProtocolSettingsp != NULL ) { ProtocolSettingsp->Release(); }
if ( EnumProtocolsp != NULL) { EnumProtocolsp->Release(); }
return hr; }
HRESULT CWANConnectionBase::SetConnectionType(BSTR NewConnectionType) { HRESULT hr = S_OK; if(0 != lstrcmp(NewConnectionType, L"IP_Routed")) { hr = E_FAIL; // we only support IP_Routed
}
return hr; }
HRESULT CWANConnectionBase::GetConnectionTypeInfo(BSTR* pNewConnectionType, BSTR* pNewPossibleConnectionTypes) { HRESULT hr = S_OK;
SysFreeString(*pNewConnectionType); SysFreeString(*pNewPossibleConnectionTypes); *pNewConnectionType = NULL; *pNewPossibleConnectionTypes = NULL;
hr = get_ConnectionType(pNewConnectionType); if(SUCCEEDED(hr)) { hr = get_PossibleConnectionTypes(pNewPossibleConnectionTypes); }
if(FAILED(hr)) { if(NULL != *pNewConnectionType) { SysFreeString(*pNewConnectionType); *pNewConnectionType = NULL; } } return hr; }
HRESULT CWANConnectionBase::GetStatusInfo(BSTR* pNewConnectionStatus, BSTR* pNewLastConnectionError, ULONG* pNewUptime) { HRESULT hr = S_OK;
SysFreeString(*pNewConnectionStatus); SysFreeString(*pNewLastConnectionError); *pNewConnectionStatus = NULL; *pNewLastConnectionError = NULL; hr = get_ConnectionStatus(pNewConnectionStatus); if(SUCCEEDED(hr)) { hr = get_LastConnectionError(pNewLastConnectionError); }
if(SUCCEEDED(hr) && 0 == lstrcmp(L"Connected", *pNewConnectionStatus)) { hr = get_Uptime(pNewUptime); } else { *pNewUptime = 0; }
if(FAILED(hr)) { if(NULL != *pNewConnectionStatus) { SysFreeString(*pNewConnectionStatus); *pNewConnectionStatus = NULL; } if(NULL != *pNewLastConnectionError) { SysFreeString(*pNewLastConnectionError); *pNewLastConnectionError = NULL; }
}
return hr; }
HRESULT CWANConnectionBase::GetNATRSIPStatus(VARIANT_BOOL* pNewRSIPAvailable, VARIANT_BOOL* pNewNATEnabled) { HRESULT hr = S_OK;
hr = get_RSIPAvailable(pNewRSIPAvailable); if(SUCCEEDED(hr)) { hr = get_NATEnabled(pNewNATEnabled); }
return hr; }
HRESULT CWANConnectionBase::GetLinkLayerMaxBitRates(ULONG* pNewUpstreamMaxBitRate, ULONG* pNewDownstreamMaxBitRate) { HRESULT hr = S_OK;
hr = get_UpstreamMaxBitRate(pNewUpstreamMaxBitRate); if(SUCCEEDED(hr)) { hr = get_DownstreamMaxBitRate(pNewDownstreamMaxBitRate); }
return hr; }
HRESULT CWANConnectionBase::GetGenericPortMappingEntry( USHORT ulIndex, BSTR* RemoteHostp, USHORT* uExternalPortp, BSTR* Protocolp, USHORT* uInternalPortp, BSTR* InternalClientp, VARIANT_BOOL* bEnabledp, BSTR* Descriptionp, ULONG* ulLeaseDurationp ) { HRESULT hr = S_OK; IHNetPortMappingProtocol* MappingProtocolp = NULL; IHNetPortMappingBinding* Bindingp = NULL; USHORT BoundaryPort = 0, InternalPort = 0;
_ASSERT ( RemoteHostp != NULL ); _ASSERT ( uExternalPortp != NULL ); _ASSERT ( Protocolp != NULL ); _ASSERT ( uInternalPortp != NULL ); _ASSERT ( InternalClientp != NULL ); _ASSERT ( bEnabledp != NULL ); _ASSERT ( Descriptionp != NULL ); _ASSERT ( ulLeaseDurationp != NULL );
//
// In/Out Parameters to COM Interfaces needs cleanup
//
SysFreeString(*RemoteHostp); SysFreeString(*Protocolp); SysFreeString(*InternalClientp); SysFreeString(*Descriptionp);
*RemoteHostp = NULL; *Protocolp = NULL; *InternalClientp = NULL; *Descriptionp = NULL; *ulLeaseDurationp = 0;
DBG_SPEW(TM_INFO, TL_TRACE, L"> GetGenericPortMapping");
//
// check for access
hr = this->ControlEnabled();
if ( FAILED(hr) ) { DBG_SPEW(TM_INFO, TL_ERROR, L"Control Disabled returning E(%X)", hr); return hr; } do { //
// SECURITY - SECURITY - SECURITY
// Here we're allowing the out-of-proc COM call
// into our service to have SYSTEM access rights.
//
// REASON: UPnP works in LOCAL_SERVICE and COM
// Calls into our service which modify
// the WMI repository will FAIL. This
// Call alleviates that problem by changing
// The Security to that of the SYSTEM
// and is reverted back when the class
// is out of scope by the destructor of.
// CSwitchSecurityContext
//
CSwitchSecurityContext SwSecCxt; hr = SearchPortMapping(m_IcsSettingsp, ulIndex, 0, 0, &MappingProtocolp);
if ( FAILED(hr) ) { DBG_SPEW(TM_INFO, TL_ERROR, L"Enum - Seeking the port has failed E(%X)", hr); SetUPnPError(L"713"); break; }
//
// Getting the binding - is this how it should be?
//
hr = m_pHomenetConnection->GetBindingForPortMappingProtocol(MappingProtocolp, &Bindingp);
if ( FAILED(hr) ) { DBG_SPEW(TM_INFO, TL_ERROR, L"Enum - Error In Getting Binding for Protocol E(%X)", hr);
break; }
hr = FillStaticMappingInformation(MappingProtocolp, Bindingp, &BoundaryPort, Protocolp, &InternalPort, InternalClientp, bEnabledp, Descriptionp);
_ASSERT( SUCCEEDED(hr) );
if ( SUCCEEDED(hr) ) // correct the port Byte Ordering
{ *uExternalPortp = ntohs( BoundaryPort ); *uInternalPortp = ntohs( InternalPort ); } else { DBG_SPEW(TM_INFO, TL_ERROR, L"Enum - Error In Getting Binding for Protocol E(%X)" , hr); } } while ( FALSE );
if ( MappingProtocolp != NULL) MappingProtocolp->Release();
if ( Bindingp != NULL ) Bindingp->Release();
if ( FAILED(hr) ) { DBG_SPEW(TM_INFO, TL_ERROR, L"Enum - GetGenericEntry has failed with E(%X)", hr); } return hr; } // GetArrayEntry
HRESULT CWANConnectionBase::GetSpecificPortMappingEntry( IN BSTR RemoteHost, IN USHORT uwExternalPort, IN BSTR Protocol, OUT USHORT* puwInternalPort, OUT BSTR* InternalClientp, OUT VARIANT_BOOL* pbEnabled, OUT BSTR* Descriptionp, OUT ULONG* pulLeaseDuration ) //
// Note that every port is expected to arrive in HOST order
// and will be returned in HOST order
//
{ HRESULT hr = S_OK; IHNetPortMappingProtocol* MappingProtocolp = NULL; IHNetPortMappingBinding* Bindingp = NULL; USHORT tempExtPort = 0, tempIntPort = 0; UCHAR searchProtocol = NULL;
_ASSERT( RemoteHost != NULL ); _ASSERT( uwExternalPort != 0 ); _ASSERT( Protocol != NULL );
SysFreeString( *InternalClientp ); SysFreeString( *Descriptionp );
*InternalClientp = NULL; *Descriptionp = NULL;
tempExtPort = htons( uwExternalPort ); // flip to Network order
DBG_SPEW(TM_INFO, TL_TRACE, L"> GetSpecificPortMapping");
//
// check for access
hr = this->ControlEnabled();
if ( FAILED(hr) ) { DBG_SPEW(TM_INFO, TL_ERROR, L"Control is Disabled E(%X)", hr); return hr; } if ( 0 == uwExternalPort) { DBG_SPEW(TM_INFO, TL_ERROR, L"Parameters Incorrect Port(%hu)", uwExternalPort ); SetUPnPError(L"402"); return E_INVALIDARG; }
do { //
// SECURITY - SECURITY - SECURITY
// Here we're allowing the out-of-proc COM call
// into our service to have SYSTEM access rights.
//
// REASON: UPnP works in LOCAL_SERVICE and COM
// Calls into our service which modify
// the WMI repository will FAIL. This
// Call alleviates that problem by changing
// The Security to that of the SYSTEM
// and is reverted back when the class
// is out of scope by the destructor of.
// CSwitchSecurityContext
//
CSwitchSecurityContext SwSecCxt;
//
// Resolve the Protocol to the appropriate enum.
//
RESOLVE_PROTOCOL_TYPE(searchProtocol, Protocol);
DBG_SPEW(TM_INFO, TL_INFO, L"Search Specific - ExtPort (%hu) Protocol (%s)", htons( tempExtPort ), (NAT_PROTOCOL_TCP == searchProtocol)?L"TCP":L"UDP");
hr = SearchPortMapping(m_IcsSettingsp, 0, tempExtPort, searchProtocol, &MappingProtocolp);
if ( FAILED(hr)) { DBG_SPEW(TM_INFO, TL_ERROR, L"Error or can't get Search E(%X)", hr); SetUPnPError(L"714"); break; } //
// Getting the binding
//
hr = m_pHomenetConnection->GetBindingForPortMappingProtocol(MappingProtocolp, &Bindingp);
if ( FAILED(hr) ) { DBG_SPEW(TM_INFO, TL_ERROR, L"Error In Getting Binding for Protocol E(%X)", hr);
break; }
hr = FillStaticMappingInformation(MappingProtocolp, Bindingp, &tempExtPort, &Protocol, &tempIntPort, InternalClientp, pbEnabled, Descriptionp); _ASSERT( SUCCEEDED(hr) );
*puwInternalPort = ntohs( tempIntPort ); DBG_SPEW(TM_INFO, TL_TRACE, L"Returning IntClient (%s) IntPort (%hu) IntProtocol (%s), Enabled (%s), Desc (%s)", *InternalClientp, *puwInternalPort, Protocol, (*pbEnabled == VARIANT_TRUE)?L"TRUE":L"FALSE", *Descriptionp);
} while ( FALSE );
if ( MappingProtocolp != NULL) MappingProtocolp->Release();
if ( Bindingp != NULL ) Bindingp->Release();
if ( FAILED(hr) ) { DBG_SPEW(TM_INFO, TL_ERROR, L"Error or can't get Search Done E(%X)", hr); }
return hr; }
HRESULT CWANConnectionBase::AddPortMapping( BSTR RemoteHost, USHORT uwExternalPort, BSTR Protocol, USHORT uwInternalPort, BSTR InternalClient, VARIANT_BOOL bEnabled, BSTR Description, ULONG ulLeaseDuration ) { HRESULT hr = S_OK; MAPPING_TYPE MappingType = ePortMappingInvalid;
DBG_SPEW(TM_STATIC, TL_TRACE, L"> AddPortMapping");
//
// Check for Access status
hr = this->ControlEnabled();
if ( SUCCEEDED(hr) ) { hr = ValidatePortMappingParameters(RemoteHost, uwExternalPort, Protocol, uwInternalPort, InternalClient, bEnabled, Description, ulLeaseDuration, &MappingType);
if ( SUCCEEDED(hr) ) { DBG_SPEW(TM_STATIC, TL_TRACE, L"Add PortMapping - ExtPort (%hu) Protocol (%s)", uwExternalPort, Protocol);
DBG_SPEW(TM_STATIC, TL_TRACE, L"IntClient (%s) IntPort (%hu) Enabled (%s), Desc (%s)", InternalClient, uwInternalPort, (bEnabled == VARIANT_TRUE)?L"TRUE":L"FALSE", Description);
if ( ePortMappingStatic == MappingType ) { //
// SECURITY - SECURITY - SECURITY
// Here we're allowing the out-of-proc COM call
// into our service to have SYSTEM access rights.
//
// REASON: UPnP works in LOCAL_SERVICE and COM
// Calls into our service which modify
// the WMI repository will FAIL. This
// Call alleviates that problem by changing
// The Security to that of the SYSTEM
// and is reverted back when the class
// is out of scope by the destructor of.
// CSwitchSecurityContext
//
CSwitchSecurityContext SwSecCxt;
hr = AddStaticPortMapping(RemoteHost, uwExternalPort, Protocol, uwInternalPort, InternalClient, bEnabled, Description, ulLeaseDuration); } else { hr = AddDynamicPortMapping(RemoteHost, uwExternalPort, Protocol, uwInternalPort, InternalClient, bEnabled, Description, ulLeaseDuration); } } } else { DBG_SPEW(TM_STATIC, TL_ERROR, L"Control Disabled E(%X)", hr); }
return hr; }
HRESULT CWANConnectionBase::AddDynamicPortMapping( BSTR RemoteHost, USHORT uwExternalPort, BSTR Protocol, USHORT uwInternalPort, BSTR InternalClient, VARIANT_BOOL bEnabled, BSTR Description, ULONG ulLeaseDuration ) { //
// We currently don't handle any Dynamic Port Redirections.
//
DBG_SPEW(TM_DYNAMIC, TL_ERROR, L"Only Static Mappings are allowed [Lease]");
SetUPnPError(L"725");
return E_INVALIDARG; }
HRESULT CWANConnectionBase::AddStaticPortMapping( BSTR RemoteHost, USHORT uwExternalPort, BSTR Protocol, USHORT uwInternalPort, BSTR InternalClient, VARIANT_BOOL bEnabled, BSTR Description, ULONG ulLeaseDuration ) { HRESULT hr = S_OK; UCHAR ProtocolType = 0; IHNetProtocolSettings* ProtocolSettingsp = NULL; IHNetPortMappingProtocol* PortMappingProtocolp = NULL; IHNetPortMappingBinding* PortMappingBindingp = NULL; ULONG ClientAddr = 0; BOOLEAN bLetsEnable = FALSE; BOOLEAN bCreatedProtocol = FALSE; ULONG tempStrLen = 0; WCHAR tempPortStr[] = L"00000"; LPOLESTR tempStr = NULL; USHORT tempExtPort = 0, tempIntPort = 0; BSTR ProtocolFromBinding = NULL; BSTR ClientFromBinding = NULL; BSTR DescriptionFromBinding = NULL; VARIANT_BOOL boolEnabled;
_ASSERT( uwExternalPort ); _ASSERT( uwInternalPort );
//
// Convert both ends to Network Order
//
tempExtPort = htons( uwExternalPort ); tempIntPort = htons( uwInternalPort );
//
// Convert VARIANT_BOOL to boolean
//
bLetsEnable = ( bEnabled == VARIANT_TRUE );
//
// Process the Operation
//
do { RESOLVE_PROTOCOL_TYPE(ProtocolType, Protocol);
//
// IF there is no description crate one
// using PORT and PROTOCOL
//
if ( wcscmp(Description, L"\0") == 0 ) { // Get Internal ClientName + the seperator
tempStrLen = ( SysStringLen( InternalClient ) + 1 ); // Get port len + plus the seperator
_itow ( uwExternalPort, tempPortStr, 10); tempStrLen += (wcslen (tempPortStr) + 1);
// Get Protocol Name
tempStrLen += SysStringLen( Protocol );
// Create out from these two
tempStr = (LPOLESTR)CoTaskMemAlloc( (tempStrLen + 1) * sizeof(WCHAR) ); if ( tempStr != NULL ) {
_snwprintf(tempStr, tempStrLen, L"%s-%s-%s", InternalClient, tempPortStr, Protocol);
tempStr[ tempStrLen ] = L'\0';
Description = SysAllocString ( tempStr ); } if ( (tempStr == NULL) || (Description == NULL) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Can't Initialize Strings - out of mem");
hr = E_OUTOFMEMORY;
break; } }
//
// Find Existing Mapping
//
hr = SearchPortMapping(m_IcsSettingsp, 0, tempExtPort, ProtocolType, &PortMappingProtocolp); //
// if found it is in Edit Mode.
//
if ( SUCCEEDED(hr) ) {
hr = m_pHomenetConnection->GetBindingForPortMappingProtocol(PortMappingProtocolp, &PortMappingBindingp);
_ASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Can't get Binding for Port Mapping E(X)", hr); _ASSERT( FALSE ); break; }
//
// Fill the information
//
hr = FillStaticMappingInformation(PortMappingProtocolp, PortMappingBindingp, &tempExtPort, &ProtocolFromBinding, &tempIntPort, &ClientFromBinding, &boolEnabled, &DescriptionFromBinding);
if ( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Filling has failed for Mapping Information E(%X)", hr); break; } //
// If the existin Mapping was disabled we should be able to change
// the Internal Client
//
if ( boolEnabled == VARIANT_TRUE ) { if ( _wcsicmp( InternalClient, ClientFromBinding) != 0 ) // if diff then error
{ hr = E_INVALIDARG; DBG_SPEW(TM_STATIC, TL_ERROR, L"Will not change the internal client for an enabled PortMapping"); SetUPnPError(L"718"); break; } }
//
// if the Internal Port has changed reflect the change
//
if ( tempIntPort != htons( uwInternalPort ) ) { tempIntPort = htons( uwInternalPort );
hr = PortMappingBindingp->SetTargetPort( tempIntPort );
_ASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Changin Internal Port has Failed E(%X)", hr); break; } }
//
// Set the description if changed
//
if ( _wcsicmp(DescriptionFromBinding, Description) != 0) { hr = PortMappingProtocolp->SetName(Description); if ( FAILED(hr) ) { hr = E_INVALIDARG; DBG_SPEW(TM_STATIC, TL_ERROR, L"Set Name has failed E(%X)", hr); break; } } } else { //
// Start Getting the Interface
//
hr = m_IcsSettingsp->QueryInterface(IID_IHNetProtocolSettings, reinterpret_cast<void**>(&ProtocolSettingsp));
if ( SUCCEEDED(hr) ) { hr = ProtocolSettingsp->CreatePortMappingProtocol(Description, ProtocolType, tempExtPort, &PortMappingProtocolp);
if ( SUCCEEDED(hr) ) { hr = m_pHomenetConnection->GetBindingForPortMappingProtocol(PortMappingProtocolp, &PortMappingBindingp); if ( SUCCEEDED(hr) ) { hr = PortMappingBindingp->SetTargetPort( tempIntPort );
_ASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Set Target Port has Failed E(%X)", hr); } bCreatedProtocol = TRUE;
} else { DBG_SPEW(TM_STATIC, TL_ERROR, L"Getting Binding has Failed E(X)", hr); PortMappingProtocolp->Delete(); break; } } else { DBG_SPEW(TM_STATIC, TL_ERROR, L"Creating the PortMapping has Failed E(%X)", hr); break; }
} else { DBG_SPEW(TM_STATIC, TL_ERROR, L"Getting the Protocol Settings has failed E(X)", hr); break; } }
//
// Setting the Client name / address
// For Edit mode we already checked wether this code will be run or not.
//
if ( ( wcscmp(L"0.0.0.0", InternalClient) != 0 ) && ( InternalClient[0] != L'\0' ) ) { ClientAddr = INET_ADDR((LPOLESTR) InternalClient );
//
// if the address is not valid (INADDR_NONE)
// and if the address is different than Broadcast address (which also is INADDR_NONE)
//
if ( (ClientAddr == INADDR_NONE) && wcscmp(L"255.255.255.255", InternalClient) ) { hr = PortMappingBindingp->SetTargetComputerName( InternalClient ); } else { hr = PortMappingBindingp->SetTargetComputerAddress( ClientAddr ); }
_ASSERT( SUCCEEDED(hr) );
if ( SUCCEEDED(hr) ) { hr = PortMappingBindingp->SetEnabled( bLetsEnable ); }
if ( FAILED(hr) ) DBG_SPEW(TM_STATIC, TL_ERROR, L"Client Add/Edit IntClient failed - E(%X)", hr); }
if ( FAILED(hr) && (TRUE == bCreatedProtocol) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Client Add / Edit failed - E(%X)", hr); hr = PortMappingProtocolp->Delete(); }
} while ( FALSE );
if ( tempStr != NULL) { CoTaskMemFree ( tempStr ); SysFreeString ( Description ); // you can free a NULL string.
}
if ( ProtocolFromBinding ) SysFreeString(ProtocolFromBinding);
if ( ClientFromBinding ) SysFreeString(ClientFromBinding);
if ( DescriptionFromBinding ) SysFreeString(DescriptionFromBinding); if ( PortMappingBindingp != NULL ) PortMappingBindingp->Release();
if ( PortMappingProtocolp != NULL ) PortMappingProtocolp->Release();
if ( ProtocolSettingsp != NULL ) ProtocolSettingsp->Release();
if ( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Error Returning hr (%X)", hr); }
return hr; } // CWANConnectionBase :: AddStaticPortMapping
HRESULT CWANConnectionBase::DeletePortMapping( BSTR RemoteHost, USHORT uwExternalPort, BSTR Protocol ) { HRESULT hr = S_OK;
UCHAR ProtocolType = 0;
IHNetPortMappingProtocol* PortMappingProtocolp = NULL;
USHORT tempExtPort = 0;
//
// SECURITY - SECURITY - SECURITY
// Here we're allowing the out-of-proc COM call
// into our service to have SYSTEM access rights.
//
// REASON: UPnP works in LOCAL_SERVICE and COM
// Calls into our service which modify
// the WMI repository will FAIL. This
// Call alleviates that problem by changing
// The Security to that of the SYSTEM
// and is reverted back when the class
// is out of scope by the destructor of.
// CSwitchSecurityContext
//
CSwitchSecurityContext SwSecCxt;
_ASSERT( RemoteHost != NULL ); _ASSERT( uwExternalPort != 0 ); _ASSERT( Protocol != NULL );
DBG_SPEW(TM_STATIC, TL_TRACE, L"> DeletePortMapping");
//
// check for access
hr = this->ControlEnabled();
if ( FAILED(hr) ) { return hr; } //
// Convert to Network order
//
tempExtPort = htons(uwExternalPort );
DBG_SPEW(TM_STATIC, TL_INFO, L"Search Specific - ExtPort (%hu) Protocol (%s)", uwExternalPort, Protocol);
do { RESOLVE_PROTOCOL_TYPE( ProtocolType, Protocol );
hr = SearchPortMapping(m_IcsSettingsp, 0, tempExtPort, ProtocolType, &PortMappingProtocolp); if ( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Error in Searching E(%X)", hr ); SetUPnPError(L"714"); break; }
hr = PortMappingProtocolp->Delete();
if ( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"ProtocolMapping deletion failure, Might be Built in E(%X)", hr ); } PortMappingProtocolp->Release();
} while ( FALSE );
if ( FAILED(hr) ) DBG_SPEW(TM_STATIC, TL_ERROR, L"Delete failed with hr - %X", hr);
return hr; }
HRESULT CWANConnectionBase::GetExternalIPAddress(BSTR* pExternalIPAddress) { HRESULT hr = S_OK;
SysFreeString(*pExternalIPAddress); *pExternalIPAddress = NULL;
hr = get_ExternalIPAddress(pExternalIPAddress);
return hr; }
HRESULT CWANConnectionBase::ControlEnabled() { HRESULT hr = S_OK;
// check the reg key. Only disable if key exists and is 0.
HKEY hKey; DWORD dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_SHAREDACCESSCLIENTKEYPATH, 0, KEY_QUERY_VALUE, &hKey); if(ERROR_SUCCESS == dwError) // if this fails we assume it is on, set the box, and commit on apply
{ DWORD dwType; DWORD dwData = 0; DWORD dwSize = sizeof(dwData); dwError = RegQueryValueEx(hKey, REGVAL_SHAREDACCESSCLIENTENABLECONTROL, 0, &dwType, reinterpret_cast<LPBYTE>(&dwData), &dwSize); if(ERROR_SUCCESS == dwError && REG_DWORD == dwType && 0 == dwData) { hr = E_ACCESSDENIED; } RegCloseKey(hKey); }
return hr; }
HRESULT SearchPortMapping( IN IHNetIcsSettings* IcsSettingsp, IN OPTIONAL ULONG searchIndex, IN OPTIONAL USHORT searchPort, IN OPTIONAL UCHAR searchProtocol, OUT IHNetPortMappingProtocol **Protocolpp ) //
// Two ways of Seeking an entry..
// 1) By Index.. Enumerate until you hit the giventh Index.
// 2) Seeks and retrieves Port and ProtocolType
//
{ HRESULT hr = S_OK;
IHNetProtocolSettings* ProtocolSettingsp = NULL;
IEnumHNetPortMappingProtocols* EnumProtocolsp = NULL;
IHNetPortMappingProtocol* tempProtocolp = NULL;
USHORT ProtocolPort = 0;
UCHAR ProtocolType = 0;
BOOLEAN bFound = FALSE;
ULONG iIndex = 0;
DBG_SPEW(TM_STATIC, TL_ERROR, L" > SearchPortMapping ");
//
// Index = 0 is a valid search
// searchPort and searcProtocol should exist both or not.
//
_ASSERT( !((searchPort == NULL) ^ (searchProtocol == 0)) );
_ASSERT( IcsSettingsp != NULL ); _ASSERT( Protocolpp != NULL );
do { hr = IcsSettingsp->QueryInterface(IID_IHNetProtocolSettings, reinterpret_cast<void**>(&ProtocolSettingsp)); if( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Query Interface failed for ProtocolSettingsp E(%X)", hr); break; }
hr = ProtocolSettingsp->EnumPortMappingProtocols(&EnumProtocolsp);
if ( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Enum Interface can't be retrieved E(%X)", hr); break; }
while( (FALSE == bFound) && (S_OK == EnumProtocolsp->Next(1, &tempProtocolp, NULL)) ) { if ( searchPort != 0 ) { hr = tempProtocolp->GetPort( &ProtocolPort );
if ( SUCCEEDED(hr) ) { hr = tempProtocolp->GetIPProtocol(&ProtocolType); } if( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Search info Failure E(%X)", hr); } else if((searchPort == ProtocolPort) && (ProtocolType == searchProtocol)) { bFound = TRUE; } } else // if the search key == the Index
{ if ( iIndex == searchIndex ) { bFound = TRUE; } } //
// if Nothing is found
if (FALSE == bFound) { tempProtocolp->Release(); } iIndex++; }
EnumProtocolsp->Release();
} while ( FALSE );
if(ProtocolSettingsp != NULL) { ProtocolSettingsp->Release(); }
if( (bFound == TRUE) && (tempProtocolp != NULL)) { *Protocolpp = tempProtocolp; } else { return E_INVALIDARG; }
return hr; }
HRESULT FillStaticMappingInformation( IN IHNetPortMappingProtocol* MappingProtocolp, IN OPTIONAL IHNetPortMappingBinding* Bindingp, OUT PUSHORT uExternalPortp, OUT BSTR* Protocolp, OUT PUSHORT uInternalPortp, OUT BSTR* InternalClientp, OUT VARIANT_BOOL* bEnabledp, OUT BSTR* Descriptionp ) //
// Note that Will return the port in Network Byte Order
//
{ HRESULT hr = S_OK; UCHAR ProtocolType = NULL; LPOLESTR szInternalHostAddr = NULL; LPOLESTR szDescription = NULL; BOOLEAN bEnabled = FALSE; BOOLEAN bUseName = FALSE; ULONG InternalHostAddr = 0;
_ASSERT ( uExternalPortp != NULL ); _ASSERT ( Protocolp != NULL ); _ASSERT ( InternalClientp != NULL ); _ASSERT ( bEnabledp != NULL ); _ASSERT ( Descriptionp != NULL ); _ASSERT ( MappingProtocolp != NULL ); _ASSERT ( Bindingp != NULL );
*uExternalPortp = 0; *Protocolp = NULL; *InternalClientp = NULL; *bEnabledp = VARIANT_FALSE; *Descriptionp = NULL;
DBG_SPEW(TM_STATIC, TL_TRACE, L"> FillStaticMappingInformation");
do { //
// Description
//
hr = MappingProtocolp->GetName(&szDescription);
if ( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Getting the Name has failed E(%X)", hr); break; }
BOOLEAN fBuiltin = FALSE;
hr = MappingProtocolp->GetBuiltIn( &fBuiltin );
_ASSERT( SUCCEEDED(hr) );
if ( fBuiltin ) { #define BUILTIN_KEY L" [MICROSOFT]"
UINT uiLength = wcslen(szDescription ); uiLength += wcslen(BUILTIN_KEY); *Descriptionp = SysAllocStringLen(NULL, uiLength);
if ( *Descriptionp ) { wcscpy (*Descriptionp, szDescription); wcscat (*Descriptionp, BUILTIN_KEY); } } else { *Descriptionp = SysAllocString(szDescription); }
if(*Descriptionp == NULL) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Memory Allocation for Description has Failed"); hr = E_OUTOFMEMORY; break; }
//
// Protocol
//
hr = MappingProtocolp->GetIPProtocol(&ProtocolType);
_ASSERT( SUCCEEDED(hr) );
if ( ProtocolType == NAT_PROTOCOL_TCP ) { *Protocolp = SysAllocString(L"TCP"); } else if ( ProtocolType == NAT_PROTOCOL_UDP ) { *Protocolp = SysAllocString(L"UDP"); } else { _ASSERT( FALSE ); }
if (*Protocolp == NULL) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Memory Allocation for Description has Failed"); hr = E_OUTOFMEMORY; break; }
//
// External Port
//
hr = MappingProtocolp->GetPort( uExternalPortp );
_ASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"GetPort for Protocol has failed E(%X)", hr); break; }
// Getting the Binding Information
if ( Bindingp != NULL ) { //
// Enabled
hr = Bindingp->GetEnabled(&bEnabled);
_ASSERT( SUCCEEDED(hr) );
if ( bEnabled == TRUE) { *bEnabledp = VARIANT_TRUE; } else { *bEnabledp = VARIANT_FALSE; }
hr = Bindingp->GetTargetPort( uInternalPortp );
_ASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"GetPort for Binding has failed E(%X)", hr);
break; }
//
// InternalClient
hr = Bindingp->GetCurrentMethod(&bUseName);
if( SUCCEEDED(hr) ) { if ( bUseName == TRUE) { hr = Bindingp->GetTargetComputerName(&szInternalHostAddr); if ( FAILED(hr) ) { break; } _ASSERT( SUCCEEDED(hr) ); } else { hr = Bindingp->GetTargetComputerAddress(&InternalHostAddr); _ASSERT( SUCCEEDED(hr) ); if ( FAILED(hr) ) { break; } //
// IF the address is Loopback change it to a name which would make more
// sense to any client who sees it.
//
if ( INADDR_LOOPBACK == htonl(InternalHostAddr) ) { ULONG uCount = 0; if ( 0 == GetComputerNameEx( ComputerNameDnsHostname, NULL, &uCount) ) { if ( (ERROR_MORE_DATA == GetLastError()) ) { szInternalHostAddr = (LPOLESTR) CoTaskMemAlloc( uCount * sizeof(WCHAR) ); if ( NULL != szInternalHostAddr ) { if (!GetComputerNameEx(ComputerNameDnsHostname, szInternalHostAddr, &uCount)) { hr = HRESULT_FROM_WIN32( GetLastError() ); break; } } else { hr = E_OUTOFMEMORY; break; } } else { hr = E_FAIL; break; } } } else if ( 0 != InternalHostAddr ) { szInternalHostAddr = INET_NTOW_TS( InternalHostAddr ); } else { szInternalHostAddr = (LPOLESTR) CoTaskMemAlloc( sizeof(WCHAR) ); if ( NULL != szInternalHostAddr) szInternalHostAddr[0] = 0; } if ( szInternalHostAddr == NULL ) { hr = E_OUTOFMEMORY; break; } } // if Name method
}
*InternalClientp = SysAllocString( szInternalHostAddr );
if ( *InternalClientp == NULL) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Mem Allocation for Internal Client Name");
hr = E_OUTOFMEMORY;
break; } } // if bindingp
} while ( FALSE );
if ( szDescription ) CoTaskMemFree( szDescription ); if ( szInternalHostAddr ) CoTaskMemFree( szInternalHostAddr );
if ( FAILED(hr) ) { if(*Protocolp) { SysFreeString(*Protocolp); *Protocolp = NULL; }
if(*InternalClientp) { SysFreeString(*InternalClientp); *InternalClientp = NULL;}
if(*Descriptionp) { SysFreeString(*Descriptionp); *Descriptionp = NULL;} } return hr; }
inline HRESULT ValidatePortMappingParameters ( IN BSTR RemoteHost, IN USHORT uwExternalPort, IN BSTR Protocol, IN USHORT uwInternalPort, IN BSTR InternalClient, IN VARIANT_BOOL bEnabled, IN BSTR Description, IN ULONG ulLeaseDuration, OUT MAPPING_TYPE* pMappingType ) //
// Decide wether a Mapping is to be dynamic or static
// Validate the parameters pre-emptively
//
{ MAPPING_TYPE MappingType = ePortMappingInvalid;
_ASSERT( RemoteHost != NULL ); _ASSERT( Protocol != NULL ); _ASSERT( Protocol[0] != 0 ); _ASSERT( Description != NULL ); _ASSERT( uwInternalPort != 0 ); _ASSERT( pMappingType != NULL ); _ASSERT( InternalClient != NULL ); _ASSERT( RemoteHost[0] == 0 );
//
// An Internal Port as well as an external Port should exist all time
//
if ( (0 == uwInternalPort) || (0 == uwExternalPort) ) { SetUPnPError(L"716");
return E_INVALIDARG; }
//
// is this a dynamic request?
//
if ( 0 != ulLeaseDuration ) { MappingType = ePortMappingDynamic; } else { MappingType = ePortMappingStatic; }
//
// A Dynamic Port Mapping needs to be with
// an Internal Client
//
if ( ( ePortMappingDynamic == MappingType ) && ( InternalClient[0] == L'\0' ) ) { SetUPnPError(L"402");
return E_INVALIDARG; }
//
// A remote Host is defined.. we can't process this
//
if ( RemoteHost[0] != L'\0' ) { SetUPnPError(L"726");
return E_INVALIDARG; }
//
// Check the bEnabled bool value
//
if ( (bEnabled != VARIANT_TRUE) && (bEnabled != VARIANT_FALSE) ) { SetUPnPError(L"402");
return E_INVALIDARG; } *pMappingType = MappingType;
return S_OK; }
|