|
|
// 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_
|