// DPrtMapC.h : Declaration of the CDynamicPortMappingCollection #ifndef __DYNAMICPORTMAPPINGCOLLECTION_H_ #define __DYNAMICPORTMAPPINGCOLLECTION_H_ #include "dportmap.h" ///////////////////////////////////////////////////////////////////////////// // CDynamicPortMappingCollection class ATL_NO_VTABLE CDynamicPortMappingCollection : public CComObjectRootEx<CComSingleThreadModel>, // public CComCoClass<CDynamicPortMappingCollection, &CLSID_DynamicPortMappingCollection>, public IDispatchImpl<IDynamicPortMappingCollection, &IID_IDynamicPortMappingCollection, &LIBID_NATUPNPLib> { private: CComPtr<IUPnPService> m_spUPS; public: CDynamicPortMappingCollection() { } //DECLARE_REGISTRY_RESOURCEID(IDR_DYNAMICPORTMAPPINGCOLLECTION) DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(CDynamicPortMappingCollection) COM_INTERFACE_ENTRY(IDynamicPortMappingCollection) COM_INTERFACE_ENTRY(IDispatch) END_COM_MAP() // IDynamicPortMappingCollection public: STDMETHOD(Add)(/*[in]*/ BSTR bstrRemoteHost, /*[in]*/ long lExternalPort, /*[in]*/ BSTR bstrProtocol, /*[in]*/ long lInternalPort, /*[in]*/ BSTR bstrInternalClient, /*[in]*/ VARIANT_BOOL bEnabled, /*[in]*/ BSTR bstrDescription, /*[in]*/ long lLeaseDuration, /*[retval][out]*/ IDynamicPortMapping **ppDPM); STDMETHOD(Remove)(/*[in]*/ BSTR bstrRemoteHost, /*[in]*/ long lExternalPort, /*[in]*/ BSTR bstrProtocol); STDMETHOD(get_Count)(/*[out, retval]*/ long *pVal); STDMETHOD(get__NewEnum)(/*[out, retval]*/ IUnknown* *pVal); STDMETHOD(get_Item)(/*[in]*/ BSTR bstrRemoteHost, /*[in]*/ long lExternalPort, /*[in]*/ BSTR bstrProtocol, /*[out, retval]*/ IDynamicPortMapping ** ppDPM); // CDynamicPortMappingCollection public: HRESULT Initialize (IUPnPService * pUPS); }; // quickie enumerator class CEnumDynamicPortMappingCollection : public IEnumVARIANT { private: CComPtr<IUPnPService> m_spUPS; long m_index, m_refs; CEnumDynamicPortMappingCollection () { m_refs = 0; m_index = 0; } HRESULT Init (IUPnPService * pUPS, long lIndex) { m_index = lIndex; m_spUPS = pUPS; return S_OK; } public: static IEnumVARIANT * CreateInstance (IUPnPService * pUPS, long lIndex = 0) { CEnumDynamicPortMappingCollection * pCEV = new CEnumDynamicPortMappingCollection (); if (!pCEV) return NULL; HRESULT hr = pCEV->Init (pUPS, lIndex); if (FAILED(hr)) { delete pCEV; return NULL; } IEnumVARIANT * pIEV = NULL; pCEV->AddRef(); pCEV->QueryInterface (IID_IEnumVARIANT, (void**)&pIEV); pCEV->Release(); return pIEV; } // IUnknown virtual HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void ** ppvObject) { NAT_API_ENTER if (ppvObject) *ppvObject = NULL; else return E_POINTER; HRESULT hr = S_OK; if ((riid == IID_IUnknown) || (riid == IID_IEnumVARIANT) ){ AddRef(); *ppvObject = (void *)this; } else hr = E_NOINTERFACE; return hr; NAT_API_LEAVE } virtual ULONG STDMETHODCALLTYPE AddRef () { return InterlockedIncrement ((PLONG)&m_refs); } virtual ULONG STDMETHODCALLTYPE Release () { ULONG l = InterlockedDecrement ((PLONG)&m_refs); if (l == 0) delete this; return l; } // IEnumVARIANT virtual HRESULT STDMETHODCALLTYPE Next (/*[in]*/ ULONG celt, /*[out, size_is(celt), length_is(*pCeltFetched)]*/ VARIANT * rgVar, /*[out]*/ ULONG * pCeltFetched) { NAT_API_ENTER // clear stuff being passed in (just in case) if (pCeltFetched) *pCeltFetched = 0; for (ULONG i=0; i<celt; i++) VariantInit (&rgVar[i]); HRESULT hr = S_OK; // get the next celt elements for (i=0; i<celt; i++) { // ask service for more.... CComPtr<IDynamicPortMapping> spDPM = NULL; hr = CDynamicPortMapping::CreateInstance (m_spUPS, (long)m_index+i, &spDPM); if (!spDPM) break; // can't fail V_VT (&rgVar[i]) = VT_DISPATCH; spDPM->QueryInterface (__uuidof(IDispatch), (void**)&V_DISPATCH (&rgVar[i])); } if (hr == HRESULT_FROM_WIN32 (ERROR_FILE_NOT_FOUND)) hr = S_OK; // no more; will return S_FALSE below if (FAILED(hr)) { // on error clear variant array.... for (ULONG j=0; j<i; j++) VariantClear (&rgVar[j]); return hr; } // now update index m_index += i; // fill out how many we're returning if (pCeltFetched) *pCeltFetched = i; return i < celt ? S_FALSE : S_OK; NAT_API_LEAVE } virtual HRESULT STDMETHODCALLTYPE Skip (/*[in]*/ ULONG celt) { NAT_API_ENTER if (celt + m_index > GetTotal()) return S_FALSE; m_index += celt; return S_OK; NAT_API_LEAVE } virtual HRESULT STDMETHODCALLTYPE Reset () { NAT_API_ENTER m_index = 0; return S_OK; NAT_API_LEAVE } virtual HRESULT STDMETHODCALLTYPE Clone (/*[out]*/ IEnumVARIANT ** ppEnum) { NAT_API_ENTER if (!(*ppEnum = CreateInstance (m_spUPS, m_index))) return E_OUTOFMEMORY; return S_OK; NAT_API_LEAVE } private: ULONG GetTotal() { ULONG ul = 0; GetNumberOfEntries (m_spUPS, &ul); return ul; } }; #endif //__DYNAMICPORTMAPPINGCOLLECTION_H_