windows-nt/Source/XPSP1/NT/net/homenet/config/natupnp/upnpnat.cpp
2020-09-26 16:20:57 +08:00

271 lines
8.3 KiB
C++

// UPnPNAT.cpp : Implementation of CUPnPNAT
#include "stdafx.h"
#pragma hdrstop
#include "UPnPNAT.h"
#include "NATEM.h"
#include "dprtmapc.h"
#include "sprtmapc.h"
DEFINE_GUID(CLSID_CInternetGatewayFinder,
0x4d3f9715, 0x73da, 0x4506, 0x89, 0x33, 0x1e, 0xe, 0x17, 0x18, 0xba, 0x3b);
void __cdecl nat_trans_func (unsigned int uSECode, EXCEPTION_POINTERS* pExp)
{
throw NAT_SEH_Exception (uSECode);
}
void EnableNATExceptionHandling()
{
_set_se_translator (nat_trans_func);
}
void DisableNATExceptionHandling()
{
_set_se_translator (NULL);
}
HRESULT GetServiceFromINetConnection (IUnknown * pUnk, IUPnPService ** ppUPS)
{
CComPtr<INetConnection> spNC = NULL;
HRESULT hr = pUnk->QueryInterface (__uuidof(INetConnection), (void**)&spNC);
if (!spNC)
return E_INVALIDARG;
SAHOST_SERVICES sas;
// make sure we have either
// NCM_SHAREDACCESSHOST_LAN or NCM_SHAREDACCESSHOST_RAS
switch (GetMediaType (spNC)) {
case NCM_SHAREDACCESSHOST_LAN:
sas = SAHOST_SERVICE_WANIPCONNECTION;
break;
case NCM_SHAREDACCESSHOST_RAS:
sas = SAHOST_SERVICE_WANPPPCONNECTION;
break;
default:
return E_INVALIDARG;
}
CComPtr<INetSharedAccessConnection> spNSAC = NULL;
hr = pUnk->QueryInterface (__uuidof(INetSharedAccessConnection), (void**)&spNSAC);
if (spNSAC)
hr = spNSAC->GetService (sas, ppUPS);
return hr;
}
HRESULT GetServiceFromFinder (IInternetGatewayFinder * pIGF, IUPnPService ** ppUPS)
{
CComPtr<IInternetGateway> spIG = NULL;
HRESULT hr = pIGF->GetInternetGateway (NULL, &spIG); // NULL gets default.
if (spIG) {
NETCON_MEDIATYPE MediaType = NCM_NONE;
hr = spIG->GetMediaType (&MediaType);
if (SUCCEEDED(hr)) {
switch (MediaType) {
case NCM_SHAREDACCESSHOST_LAN:
hr = spIG->GetService (SAHOST_SERVICE_WANIPCONNECTION, ppUPS);
break;
case NCM_SHAREDACCESSHOST_RAS:
hr = spIG->GetService (SAHOST_SERVICE_WANPPPCONNECTION, ppUPS);
break;
default:
return E_UNEXPECTED;
}
}
}
return hr;
}
HRESULT GetService (IUPnPService ** ppUPS)
{
if (!ppUPS)
return E_POINTER;
*ppUPS = NULL;
// either enum all netconnections, or
// for downlevel, use Ken's object
CComPtr<INetConnectionManager> spNCM = NULL;
HRESULT hr = ::CoCreateInstance (CLSID_ConnectionManager,
NULL,
CLSCTX_ALL,
__uuidof(INetConnectionManager),
(void**)&spNCM);
if (spNCM) {
CComPtr<IUnknown> spUnk = NULL;
CComPtr<IEnumNetConnection> spENC = NULL;
hr = spNCM->EnumConnections (NCME_DEFAULT, &spENC);
if (spENC) {
ULONG ul = 0;
CComPtr<INetConnection> spNC = NULL;
while (S_OK == spENC->Next (1, &spNC, &ul)) {
NETCON_PROPERTIES * pProps = NULL;
spNC->GetProperties (&pProps);
if (pProps) {
NETCON_MEDIATYPE MediaType = pProps->MediaType;
NcFreeNetconProperties (pProps);
if ((MediaType == NCM_SHAREDACCESSHOST_LAN) ||
(MediaType == NCM_SHAREDACCESSHOST_RAS) ){
// found it
spNC->QueryInterface (__uuidof(IUnknown),
(void**)&spUnk);
break;
}
}
spNC = NULL;
}
}
if (spUnk)
hr = GetServiceFromINetConnection (spUnk, ppUPS);
} else {
// downlevel
CComPtr<IInternetGatewayFinder> spIGF = NULL;
hr = ::CoCreateInstance (CLSID_CInternetGatewayFinder,
NULL,
CLSCTX_ALL,
__uuidof(IInternetGatewayFinder),
(void**)&spIGF);
if (spIGF)
hr = GetServiceFromFinder (spIGF, ppUPS);
}
return hr;
}
template<class C, class I> class UN {
public:
HRESULT Create (I ** ppI)
{
if (ppI)
*ppI = NULL;
if (!ppI)
return E_POINTER;
CComPtr<IUPnPService> spUPS = NULL;
HRESULT hr = GetService (&spUPS);
if (spUPS) {
// create class so that I can initialize it
CComObject<C> * pC = NULL;
hr = CComObject<C>::CreateInstance (&pC);
if (pC) {
pC->AddRef();
// init
hr = pC->Initialize (spUPS);
if (SUCCEEDED(hr))
hr = pC->QueryInterface (__uuidof(I), (void**)ppI);
pC->Release();
}
}
return hr;
}
};
/////////////////////////////////////////////////////////////////////////////
// CUPnPNAT
STDMETHODIMP CUPnPNAT::get_NATEventManager(INATEventManager ** ppNEM)
{
NAT_API_ENTER
UN<CNATEventManager, INATEventManager> un;
return un.Create (ppNEM);
NAT_API_LEAVE
}
STDMETHODIMP CUPnPNAT::get_DynamicPortMappingCollection (IDynamicPortMappingCollection ** ppDPMC)
{
NAT_API_ENTER
// remove the section below when turning dynamic port mappings back on
if (!ppDPMC)
return E_POINTER;
*ppDPMC = NULL;
return E_NOTIMPL;
// remove the section above when turning dynamic port mappings back on
UN<CDynamicPortMappingCollection, IDynamicPortMappingCollection> un;
return un.Create (ppDPMC);
NAT_API_LEAVE
}
STDMETHODIMP CUPnPNAT::get_StaticPortMappingCollection (IStaticPortMappingCollection ** ppSPMC)
{
NAT_API_ENTER
UN<CStaticPortMappingCollection, IStaticPortMappingCollection> un;
return un.Create (ppSPMC);
NAT_API_LEAVE
}
// private method(s)
HRESULT GetOSInfoService (IUPnPService ** ppUPS)
{
if (!ppUPS)
return E_POINTER;
*ppUPS = NULL;
// either enum all netconnections, or
// for downlevel, use Ken's object
CComPtr<INetConnectionManager> spNCM = NULL;
HRESULT hr = ::CoCreateInstance (CLSID_ConnectionManager,
NULL,
CLSCTX_ALL,
__uuidof(INetConnectionManager),
(void**)&spNCM);
if (spNCM) {
CComPtr<IEnumNetConnection> spENC = NULL;
hr = spNCM->EnumConnections (NCME_DEFAULT, &spENC);
if (spENC) {
ULONG ul = 0;
CComPtr<INetConnection> spNC = NULL;
while (S_OK == spENC->Next (1, &spNC, &ul)) {
NETCON_PROPERTIES * pProps = NULL;
spNC->GetProperties (&pProps);
if (pProps) {
NETCON_MEDIATYPE MediaType = pProps->MediaType;
NcFreeNetconProperties (pProps);
if ((MediaType == NCM_SHAREDACCESSHOST_LAN) ||
(MediaType == NCM_SHAREDACCESSHOST_RAS) ){
// found it
break;
}
}
spNC = NULL;
}
if (spNC) {
CComPtr<INetSharedAccessConnection> spNSAC = NULL;
hr = spNC->QueryInterface (__uuidof(INetSharedAccessConnection), (void**)&spNSAC);
if (spNSAC)
hr = spNSAC->GetService (SAHOST_SERVICE_OSINFO, ppUPS);
} else
hr = HRESULT_FROM_WIN32 (ERROR_FILE_NOT_FOUND);
}
} else {
// downlevel
CComPtr<IInternetGatewayFinder> spIGF = NULL;
hr = ::CoCreateInstance (CLSID_CInternetGatewayFinder,
NULL,
CLSCTX_ALL,
__uuidof(IInternetGatewayFinder),
(void**)&spIGF);
if (spIGF) {
CComPtr<IInternetGateway> spIG = NULL;
hr = spIGF->GetInternetGateway (NULL, &spIG); // NULL gets default.
if (spIG)
hr = spIG->GetService (SAHOST_SERVICE_OSINFO, ppUPS);
}
}
return hr;
}
BOOL IsICSHost ()
{
CComPtr<IUPnPService> spOSI = NULL;
GetOSInfoService (&spOSI);
if (spOSI)
return TRUE;
return FALSE;
}