// 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 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 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 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 spNCM = NULL; HRESULT hr = ::CoCreateInstance (CLSID_ConnectionManager, NULL, CLSCTX_ALL, __uuidof(INetConnectionManager), (void**)&spNCM); if (spNCM) { CComPtr spUnk = NULL; CComPtr spENC = NULL; hr = spNCM->EnumConnections (NCME_DEFAULT, &spENC); if (spENC) { ULONG ul = 0; CComPtr 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 spIGF = NULL; hr = ::CoCreateInstance (CLSID_CInternetGatewayFinder, NULL, CLSCTX_ALL, __uuidof(IInternetGatewayFinder), (void**)&spIGF); if (spIGF) hr = GetServiceFromFinder (spIGF, ppUPS); } return hr; } template class UN { public: HRESULT Create (I ** ppI) { if (ppI) *ppI = NULL; if (!ppI) return E_POINTER; CComPtr spUPS = NULL; HRESULT hr = GetService (&spUPS); if (spUPS) { // create class so that I can initialize it CComObject * pC = NULL; hr = CComObject::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 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 un; return un.Create (ppDPMC); NAT_API_LEAVE } STDMETHODIMP CUPnPNAT::get_StaticPortMappingCollection (IStaticPortMappingCollection ** ppSPMC) { NAT_API_ENTER UN 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 spNCM = NULL; HRESULT hr = ::CoCreateInstance (CLSID_ConnectionManager, NULL, CLSCTX_ALL, __uuidof(INetConnectionManager), (void**)&spNCM); if (spNCM) { CComPtr spENC = NULL; hr = spNCM->EnumConnections (NCME_DEFAULT, &spENC); if (spENC) { ULONG ul = 0; CComPtr 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 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 spIGF = NULL; hr = ::CoCreateInstance (CLSID_CInternetGatewayFinder, NULL, CLSCTX_ALL, __uuidof(IInternetGatewayFinder), (void**)&spIGF); if (spIGF) { CComPtr spIG = NULL; hr = spIGF->GetInternetGateway (NULL, &spIG); // NULL gets default. if (spIG) hr = spIG->GetService (SAHOST_SERVICE_OSINFO, ppUPS); } } return hr; } BOOL IsICSHost () { CComPtr spOSI = NULL; GetOSInfoService (&spOSI); if (spOSI) return TRUE; return FALSE; }