// DPrtMapC.h : Declaration of the CDynamicPortMappingCollection #ifndef __DYNAMICPORTMAPPINGCOLLECTION_H_ #define __DYNAMICPORTMAPPINGCOLLECTION_H_ #include "dportmap.h" ///////////////////////////////////////////////////////////////////////////// // CDynamicPortMappingCollection class ATL_NO_VTABLE CDynamicPortMappingCollection : public CComObjectRootEx, // public CComCoClass, public IDispatchImpl { private: CComPtr 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 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 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 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_