|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 2001
//
// File : CNATStaticPortMappingService.cpp
//
// Contents : CNATStaticPortMappingService implementation
//
// Notes :
//
// Author : savasg 28 February 2001
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "CNATStaticPortMappingService.h"
#include "ipnat.h"
#include "winsock2.h"
#include "debug.h"
//
// GLOBALS
//
IHNetIcsSettings* g_IcsSettingsp = NULL;
HRESULT SeekPortMapping( IN OPTIONAL LPOLESTR searchNamep, IN OPTIONAL USHORT searchPort, OUT IHNetPortMappingProtocol **Protocolpp ) //
// Seeks and retrieves a MappingProtocol by Name or Port
//
{ HRESULT hr = S_OK;
IHNetProtocolSettings* ProtocolSettingsp = NULL;
IEnumHNetPortMappingProtocols* EnumProtocolsp = NULL;
IHNetPortMappingProtocol* Protocolp = NULL;
LPOLESTR ProtocolNamep = NULL;
USHORT ProtocolPort = 0;
BOOLEAN bFound = FALSE;
DBG_SPEW(TM_STATIC, TL_ERROR, L" > SeekPortMapping \n");
do { hr = g_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 \n");
break; }
while( (FALSE == bFound) && (S_OK == EnumProtocolsp->Next(1, &Protocolp, NULL)) ) { hr = Protocolp->GetName(&ProtocolNamep);
if( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"problemo name\n"); }
hr = Protocolp->GetPort(&ProtocolPort);
if( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L" problemo ");
break; }
if(searchNamep && !( wcscmp(ProtocolNamep, searchNamep) ) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"The Name is hit %S\n", searchNamep);
bFound = TRUE; }
if(searchPort && (searchPort == ProtocolPort)) { bFound = TRUE; }
CoTaskMemFree(ProtocolNamep);
ProtocolNamep = NULL; if (FALSE == bFound) Protocolp->Release(); }
EnumProtocolsp->Release();
} while ( FALSE );
if(ProtocolSettingsp != NULL) { ProtocolSettingsp->Release(); }
if(Protocolpp && (bFound == TRUE) ) { *Protocolpp = Protocolp; }
return hr; }
HRESULT DeleteMappingByName(LPOLESTR ProtocolNamep) { HRESULT hr = S_OK;
IHNetPortMappingProtocol* Protocolp = NULL;
DBG_SPEW(TM_STATIC, TL_ERROR, L" > DeleteMappingByName \n");
do { if(ProtocolNamep == NULL) { break; } hr = SeekPortMapping(ProtocolNamep, 0, &Protocolp); if( FAILED(hr) || (Protocolp == NULL)) { DBG_SPEW(TM_STATIC, TL_ERROR, L"No Such Protocol %S: %X", ProtocolNamep, hr);
break; }
DBG_SPEW(TM_STATIC, TL_ERROR, L"DELETING\n");
hr = Protocolp->Delete();
Protocolp->Release();
} while ( FALSE );
return hr; }
CNATStaticPortMappingService::CNATStaticPortMappingService() { m_pEventSink = NULL;
m_pHNetConnection = NULL; }
HRESULT CNATStaticPortMappingService::FinalConstruct() { HRESULT hr = S_OK;
return hr; }
HRESULT CNATStaticPortMappingService::FinalRelease() { HRESULT hr = S_OK;
if(NULL != m_pHNetConnection) { m_pHNetConnection->Release(); } return hr; }
HRESULT CNATStaticPortMappingService::Initialize(IHNetConnection* pHNetConnection) /*++
Routine Description:
Arguments:
none
Return Value:
none
--*/ { HRESULT hr = S_OK;
IHNetConnection* HomenetConnectionp = NULL;
IEnumHNetIcsPublicConnections* EnumIcsPublicConnectionsp = NULL;
IHNetIcsPublicConnection* PublicConnectionp = NULL;
DBG_SPEW(TM_STATIC, TL_ERROR, L" > Initialize \n");
do { hr = CoCreateInstance(CLSID_HNetCfgMgr, NULL, CLSCTX_SERVER, IID_IHNetIcsSettings, reinterpret_cast<void**>(&g_IcsSettingsp));
if( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L" CoCreateInstance for IID_IHNetIcsSettings failed \n");
break; } //
// Get the Enumeration Interface
//
hr = g_IcsSettingsp->EnumIcsPublicConnections(&EnumIcsPublicConnectionsp); if( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Getting Interface for Enumeration of Public Connections has failed \n");
break; } //
// Find the Interface .. for now there is only one Public Interface
// This is not the RRAS case
//
hr = EnumIcsPublicConnectionsp->Next(1, &PublicConnectionp, NULL); if( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"There is no Public Connection.. how come?\n");
break; }
hr = PublicConnectionp->QueryInterface(IID_IHNetConnection, reinterpret_cast<void**>(&HomenetConnectionp));
_ASSERT( SUCCEEDED(hr) );
if( FAILED(hr) ) { EnumIcsPublicConnectionsp->Release();
PublicConnectionp->Release();
DBG_SPEW(TM_STATIC, TL_ERROR, L"Can't Get the IID_IHNetConnection Interface from the Public Connection\n");
break; } } while( FALSE ); //
// Release the Ref counts
//
if(PublicConnectionp != NULL) { PublicConnectionp->Release(); }
if(EnumIcsPublicConnectionsp != NULL) { EnumIcsPublicConnectionsp->Release(); } m_pHNetConnection = HomenetConnectionp;
/* Instead of Using the existing
m_pHNetConnection = pHNetConnection; m_pHNetConnection->AddRef(); */ return hr; }
HRESULT CNATStaticPortMappingService::Advise(IUPnPEventSink* pesSubscriber) { HRESULT hr = S_OK;
m_pEventSink = pesSubscriber;
m_pEventSink->AddRef();
return hr; }
HRESULT CNATStaticPortMappingService::Unadvise(IUPnPEventSink* pesSubscriber) { HRESULT hr = S_OK;
m_pEventSink->Release();
m_pEventSink = NULL;
return hr; }
HRESULT CNATStaticPortMappingService::get_StaticPortDescriptionList(BSTR* pStaticPortDescriptionList) { HRESULT hr = S_OK; *pStaticPortDescriptionList = NULL; typedef struct tagNameEnablePair { LIST_ENTRY LinkField; LPOLESTR pName; ULONG ulNameSize; BOOLEAN bEnabled; } NameEnablePair; LIST_ENTRY PairList; InitializeListHead(&PairList); // First construct a linklist of NameEnablePairs with the info needed
IEnumHNetPortMappingBindings *pBindingEnum = NULL; hr = m_pHNetConnection->EnumPortMappings(FALSE, &pBindingEnum); if(SUCCEEDED(hr)) { IHNetPortMappingBinding* pBinding; while(S_OK == pBindingEnum->Next(1, &pBinding, NULL)) { BOOLEAN bEnabled; hr = pBinding->GetEnabled(&bEnabled); if(SUCCEEDED(hr)) { IHNetPortMappingProtocol* pProtocol; hr = pBinding->GetProtocol(&pProtocol); if(SUCCEEDED(hr)) { LPOLESTR pName; hr = pProtocol->GetName(&pName); if(SUCCEEDED(hr)) { NameEnablePair* pPair = new NameEnablePair; if(NULL != pPair) { pPair->pName = pName; pPair->bEnabled = bEnabled; InsertTailList(&PairList, &pPair->LinkField); } //CoTaskMemFree(pName);
} pProtocol->Release(); } } pBinding->Release(); } pBindingEnum->Release(); }
LIST_ENTRY* pCount; NameEnablePair* pContainingPair;
if(SUCCEEDED(hr)) { // Count the space needed in the return string
unsigned int uSizeNeeded = 0; pCount = PairList.Flink; while(&PairList != pCount) { pContainingPair = CONTAINING_RECORD(pCount, NameEnablePair, LinkField); pContainingPair->ulNameSize = lstrlen(pContainingPair->pName); uSizeNeeded += 3 + pContainingPair->ulNameSize; //Name:1,
pCount = pCount->Flink; }
BSTR pReturnString; if(0 != uSizeNeeded) { pReturnString = SysAllocStringLen(NULL, uSizeNeeded); } else { pReturnString = SysAllocString(L""); } if(NULL != pReturnString) { *pStaticPortDescriptionList = pReturnString; // Fill in the string
pCount = PairList.Flink; while(&PairList != pCount) { pContainingPair = CONTAINING_RECORD(pCount, NameEnablePair, LinkField); lstrcpy(pReturnString, pContainingPair->pName); pReturnString += pContainingPair->ulNameSize; *pReturnString = L':'; pReturnString++; *pReturnString = pContainingPair->bEnabled ? L'1' : L'0'; pReturnString++; *pReturnString = (&PairList == pCount->Flink) ? L'\0' : L','; pReturnString++; pCount = pCount->Flink; } } else { hr = E_OUTOFMEMORY; } }
// Clean up the linked list
pCount = PairList.Flink; while(&PairList != pCount) { NameEnablePair* pDelete = CONTAINING_RECORD(pCount, NameEnablePair, LinkField); pCount = pCount->Flink; CoTaskMemFree(pDelete->pName); delete pDelete; }
return hr; }
HRESULT CNATStaticPortMappingService::get_StaticPort(ULONG* pulStaticPort) { return E_UNEXPECTED; }
HRESULT CNATStaticPortMappingService::get_StaticPortProtocol(BSTR* pStaticPortProtocol) { *pStaticPortProtocol = NULL; return E_UNEXPECTED; }
HRESULT CNATStaticPortMappingService::get_StaticPortClient(BSTR* pStaticPortClient) { *pStaticPortClient = NULL; return E_UNEXPECTED; }
HRESULT CNATStaticPortMappingService::get_StaticPortEnable(VARIANT_BOOL* pbStaticPortEnable) { return E_UNEXPECTED; }
HRESULT CNATStaticPortMappingService::get_StaticPortDescription(BSTR* pStaticPortDescription) { *pStaticPortDescription = NULL; return E_UNEXPECTED; }
HRESULT CNATStaticPortMappingService::GetStaticPortMappingList(BSTR* pStaticPortMappingList) { HRESULT hr = S_OK; SysFreeString(*pStaticPortMappingList);
*pStaticPortMappingList = NULL;
hr = get_StaticPortDescriptionList(pStaticPortMappingList); return hr; }
HRESULT CNATStaticPortMappingService::GetStaticPortMapping( BSTR StaticPortMappingDescription, ULONG* pulStaticPort, BSTR* pStaticPortClient, BSTR* pStaticPortProtocol ) /*++
Routine Description:
Retrieves the Port, Client Name/Address and the Protocol for a given Mapping (redirect in NAT context)... Note that a Binding may not exist for a Mapping.. Thus There might not be a Client Name/Address.
Arguments:
none
Return Value:
none
--*/ { HRESULT hr = S_OK;
IHNetPortMappingProtocol* Protocolp = NULL;
IHNetPortMappingBinding* Bindingp = NULL;
LPOLESTR ClientNamep = NULL;
ULONG ClientAddress = 0;
USHORT ProtocolPort = 0;
UCHAR ProtocolType = 0;
DBG_SPEW(TM_STATIC, TL_ERROR, L" > GetStaticPortMapping");
_ASSERT( StaticPortMappingDescription != NULL ); _ASSERT( pulStaticPort != NULL ); _ASSERT( pStaticPortClient != NULL ); _ASSERT( pStaticPortProtocol != NULL ); SysFreeString(*pStaticPortClient);
SysFreeString(*pStaticPortProtocol);
*pStaticPortClient = NULL;
*pStaticPortProtocol = NULL;
do { hr = SeekPortMapping((LPOLESTR)StaticPortMappingDescription, 0, &Protocolp);
if( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"There is no such Port Mapping");
break; }
hr = Protocolp->GetPort(&ProtocolPort); //USHORT
_ASSERT( SUCCEEDED(hr) );
*pulStaticPort = ProtocolPort; //
// Get the Type of the Protocol Mapping and put the appropriate
// String
//
hr = Protocolp->GetIPProtocol(&ProtocolType); //UCHAR
_ASSERT( SUCCEEDED(hr) );
if ( ProtocolType == NAT_PROTOCOL_TCP ) { *pStaticPortProtocol = SysAllocString(L"TCP"); } else if ( ProtocolType == NAT_PROTOCOL_UDP ) { *pStaticPortProtocol = SysAllocString(L"UDP"); } else { _ASSERT( FALSE ); }
//
// A Binding may not exist.. That's Ok..
//
hr = m_pHNetConnection->GetBindingForPortMappingProtocol(Protocolp, &Bindingp);
if ( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L" No Such Binding for that protocol.");
hr = S_OK;
break; }
//
// If the Address exist just process that.
// Convert the Name to a OLESTR
//
hr = Bindingp->GetTargetComputerAddress(&ClientAddress);
if ( SUCCEEDED(hr) ) { ClientNamep = (LPOLESTR) CoTaskMemAlloc( (wcslen(INET_NTOW(ClientAddress)) + 1) * sizeof(WCHAR) );
_ASSERT(ClientNamep != NULL);
wcscpy( ClientNamep, INET_NTOW(ClientAddress) ); } else { hr = Bindingp->GetTargetComputerName(&ClientNamep); }
if( FAILED( hr ) || (ClientNamep == NULL)) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Can't Retrieve Name or Address of Client from Binding ");
break; }
*pStaticPortClient = SysAllocString( ClientNamep );
if (*pStaticPortClient == NULL) { hr = E_OUTOFMEMORY; }
} while ( FALSE );
if ( ClientNamep != NULL) { CoTaskMemFree( ClientNamep ); }
if ( Bindingp != NULL) { Bindingp->Release(); }
if ( Protocolp != NULL ) { Protocolp->Release(); }
//
// If there was a failure then clear up the allocated Strings
//
if ( FAILED(hr) && ( *pStaticPortProtocol != NULL ) ) { SysFreeString( *pStaticPortProtocol );
*pStaticPortProtocol = NULL; }
return hr; }
HRESULT CNATStaticPortMappingService::SetStaticPortMappingEnabled( BSTR StaticPortMappingDescription, VARIANT_BOOL bStaticPortEnable ) /*++
Routine Description:
Arguments:
none
Return Value:
none
--*/ { HRESULT hr = S_OK;
IHNetPortMappingProtocol* Protocolp = NULL;
IHNetPortMappingBinding* Bindingp = NULL;
DBG_SPEW(TM_STATIC, TL_ERROR, L" > SetStaticPortMappingEnabled");
do { hr = SeekPortMapping((LPOLESTR)StaticPortMappingDescription, NULL, &Protocolp);
if( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"There is no such Port Mapping");
break; } hr = m_pHNetConnection->GetBindingForPortMappingProtocol(Protocolp, &Bindingp);
if ( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L" No Such Binding for that protocol.");
break; }
if ( VARIANT_TRUE == bStaticPortEnable ) { hr = Bindingp->SetEnabled(TRUE); } else if ( VARIANT_FALSE == bStaticPortEnable ) { hr = Bindingp->SetEnabled(FALSE); }
_ASSERT( SUCCEEDED(hr) );
} while ( FALSE );
if (Protocolp != NULL) { Protocolp->Release(); } if (Bindingp != NULL) { Bindingp->Release(); }
return hr; }
HRESULT CNATStaticPortMappingService::CreateStaticPortMapping( BSTR StaticPortMappingDescription, ULONG ulStaticPort, BSTR StaticPortClient, BSTR StaticPortProtocol ) /*++
Routine Description:
Arguments:
none
Return Value:
none
--*/
{ HRESULT hr = S_OK;
UCHAR ProtocolType = 0;
IHNetProtocolSettings* ProtocolSettingsp = NULL;
IHNetPortMappingProtocol* PortMappingProtocolp = NULL;
IHNetPortMappingBinding* PortMappingBindingp = NULL;
ULONG ClientAddr = 0;
ASSERT( StaticPortMappingDescription != NULL ); ASSERT( ulStaticPort == 0 ); // ASSERT( StaticPortClient != NULL );
ASSERT( StaticPortProtocol );
DBG_SPEW(TM_STATIC, TL_ERROR, L" > CreateStaticPortMapping");
//
// Check and transform the Protocol Value to its correct type.
//
if( wcscmp(StaticPortProtocol, L"TCP") == 0) { ProtocolType = NAT_PROTOCOL_TCP; } else if ( wcscmp(StaticPortProtocol, L"UDP") == 0) { ProtocolType = NAT_PROTOCOL_UDP; } else { DBG_SPEW(TM_STATIC, TL_ERROR, L"Unknown Protocol Type\n");
_ASSERT(FALSE);
return E_INVALIDARG; }
do { hr = g_IcsSettingsp->QueryInterface(IID_IHNetProtocolSettings, reinterpret_cast<void**>(&ProtocolSettingsp));
_ASSERT( SUCCEEDED(hr) ); if( FAILED(hr) ) { break; }
hr = ProtocolSettingsp->CreatePortMappingProtocol((LPOLESTR)StaticPortMappingDescription, ProtocolType, (USHORT)ulStaticPort, &PortMappingProtocolp);
if( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Creating the PortMapping has failed");
break; }
//
// If there is no
//
if ( StaticPortClient != NULL ) { hr = m_pHNetConnection->GetBindingForPortMappingProtocol(PortMappingProtocolp, &PortMappingBindingp);
if( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L" GetBinding for PORT Mapping has failed ");
break; }
//
// Decide wether the given address is a Name or an valid IP address
// ient_addrw will return an INADDR_NONE if the address is not
// decimal doted IP address
//
ClientAddr = INET_ADDR((LPOLESTR)StaticPortClient);
if( ClientAddr == INADDR_NONE) { hr = PortMappingBindingp->SetTargetComputerName(StaticPortClient);
_ASSERT( SUCCEEDED(hr) ); } else { hr = PortMappingBindingp->SetTargetComputerAddress(ClientAddr);
_ASSERT( SUCCEEDED(hr) ); }
//
// It creates it enabled
//
hr = PortMappingBindingp->SetEnabled(TRUE); } } while (FALSE);
if( PortMappingProtocolp != NULL) { PortMappingProtocolp->Release(); }
if( ProtocolSettingsp != NULL) { ProtocolSettingsp->Release(); }
return hr; }
HRESULT CNATStaticPortMappingService::DeleteStaticPortMapping(BSTR StaticPortMappingDescription) /*++
Routine Description:
Arguments:
none
Return Value:
none
--*/ { HRESULT hr = S_OK;
DBG_SPEW(TM_STATIC, TL_ERROR, L"> DeleteStaticPortMapping");
_ASSERT( StaticPortMappingDescription != NULL );
hr = DeleteMappingByName( (LPOLESTR) StaticPortMappingDescription );
return hr; }
HRESULT CNATStaticPortMappingService::SetStaticPortMapping( BSTR StaticPortMappingDescription, ULONG ulStaticPort, BSTR StaticPortClient, BSTR StaticPortProtocol ) /*++
Routine Description:
Arguments:
none
Return Value:
none
--*/ { HRESULT hr = S_OK;
hr = DeleteMappingByName((LPOLESTR) StaticPortMappingDescription);
if ( SUCCEEDED(hr) ) { hr = this->CreateStaticPortMapping(StaticPortMappingDescription, ulStaticPort, StaticPortClient, StaticPortProtocol);
_ASSERT( SUCCEEDED(hr) ); }
return hr; }
|