Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

269 lines
7.0 KiB

  1. // SPrtMapC.h : Declaration of the CStaticPortMappingCollection
  2. #ifndef __STATICPORTMAPPINGCOLLECTION_H_
  3. #define __STATICPORTMAPPINGCOLLECTION_H_
  4. #include "dprtmapc.h" // everything goes through CEnumDynamicPortMappingCollection
  5. #include "sportmap.h"
  6. /////////////////////////////////////////////////////////////////////////////
  7. // CStaticPortMappingCollection
  8. class ATL_NO_VTABLE CStaticPortMappingCollection :
  9. public CComObjectRootEx<CComSingleThreadModel>,
  10. // public CComCoClass<CStaticPortMappingCollection, &CLSID_StaticPortMappingCollection>,
  11. public IDispatchImpl<IStaticPortMappingCollection, &IID_IStaticPortMappingCollection, &LIBID_NATUPNPLib>
  12. {
  13. private:
  14. CComPtr<IUPnPService> m_spUPS;
  15. public:
  16. CStaticPortMappingCollection()
  17. {
  18. }
  19. //DECLARE_REGISTRY_RESOURCEID(IDR_STATICPORTMAPPINGCOLLECTION)
  20. DECLARE_PROTECT_FINAL_CONSTRUCT()
  21. BEGIN_COM_MAP(CStaticPortMappingCollection)
  22. COM_INTERFACE_ENTRY(IStaticPortMappingCollection)
  23. COM_INTERFACE_ENTRY(IDispatch)
  24. END_COM_MAP()
  25. // IStaticPortMappingCollection
  26. public:
  27. STDMETHOD(get__NewEnum)(/*[out, retval]*/ IUnknown* *pVal);
  28. STDMETHOD(get_Item)(/*[in]*/ long lExternalPort, /*[in]*/ BSTR bstrProtocol, /*[out, retval]*/ IStaticPortMapping ** ppSPM);
  29. STDMETHOD(get_Count)(/*[out, retval]*/ long *pVal);
  30. STDMETHOD(Remove)(/*[in]*/ long lExternalPort, /*[in]*/ BSTR bstrProtocol);
  31. STDMETHOD(Add)(/*[in]*/ long lExternalPort, /*[in]*/ BSTR bstrProtocol, /*[in]*/ long lInternalPort, /*[in]*/ BSTR bstrInternalClient, /*[in]*/ VARIANT_BOOL bEnabled, /*[in]*/ BSTR bstrDescription, /*[out, retval]*/ IStaticPortMapping ** ppSPM);
  32. // CStaticPortMappingCollection
  33. public:
  34. HRESULT Initialize (IUPnPService * pUPS);
  35. };
  36. // quickie enumerator
  37. class CEnumStaticPortMappingCollection : public IEnumVARIANT
  38. {
  39. private:
  40. CComPtr<IEnumVARIANT> m_spEV;
  41. CComPtr<IUPnPService> m_spUPS;
  42. long m_index, m_refs;
  43. CEnumStaticPortMappingCollection ()
  44. {
  45. m_refs = 0;
  46. m_index = 0;
  47. }
  48. HRESULT Init (IUPnPService * pUPS)
  49. {
  50. m_spUPS = pUPS; // we need to hang onto this for the Clone method
  51. CComPtr<IEnumVARIANT> spEV =
  52. CEnumDynamicPortMappingCollection::CreateInstance (pUPS);
  53. if (!spEV)
  54. return E_OUTOFMEMORY;
  55. m_spEV = spEV;
  56. return S_OK;
  57. }
  58. public:
  59. static IEnumVARIANT * CreateInstance (IUPnPService * pUPS)
  60. {
  61. CEnumStaticPortMappingCollection * pCEV = new CEnumStaticPortMappingCollection ();
  62. if (!pCEV)
  63. return NULL;
  64. HRESULT hr = pCEV->Init (pUPS);
  65. if (FAILED(hr)) {
  66. delete pCEV;
  67. return NULL;
  68. }
  69. IEnumVARIANT * pIEV = NULL;
  70. pCEV->AddRef();
  71. pCEV->QueryInterface (IID_IEnumVARIANT, (void**)&pIEV);
  72. pCEV->Release();
  73. return pIEV;
  74. }
  75. // IUnknown
  76. virtual HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void ** ppvObject)
  77. {
  78. NAT_API_ENTER
  79. if (ppvObject)
  80. *ppvObject = NULL;
  81. else
  82. return E_POINTER;
  83. HRESULT hr = S_OK;
  84. if ((riid == IID_IUnknown) ||
  85. (riid == IID_IEnumVARIANT) ){
  86. AddRef();
  87. *ppvObject = (void *)this;
  88. } else
  89. hr = E_NOINTERFACE;
  90. return hr;
  91. NAT_API_LEAVE
  92. }
  93. virtual ULONG STDMETHODCALLTYPE AddRef ()
  94. {
  95. return InterlockedIncrement ((PLONG)&m_refs);
  96. }
  97. virtual ULONG STDMETHODCALLTYPE Release ()
  98. {
  99. ULONG l = InterlockedDecrement ((PLONG)&m_refs);
  100. if (l == 0)
  101. delete this;
  102. return l;
  103. }
  104. // IEnumVARIANT
  105. virtual HRESULT STDMETHODCALLTYPE Next (/*[in]*/ ULONG celt, /*[out, size_is(celt), length_is(*pCeltFetched)]*/ VARIANT * rgVar, /*[out]*/ ULONG * pCeltFetched)
  106. {
  107. NAT_API_ENTER
  108. // pass everything to contained dynamic portmapping enumerator
  109. // clear stuff being passed in (just in case)
  110. if (pCeltFetched) *pCeltFetched = 0;
  111. for (ULONG i=0; i<celt; i++)
  112. VariantInit (&rgVar[i]);
  113. HRESULT hr = S_OK;
  114. // get the next celt elements
  115. for (i=0; i<celt; i++) {
  116. CComVariant cv;
  117. hr = m_spEV->Next (1, &cv, NULL);
  118. if (hr != S_OK)
  119. break;
  120. // all static port mappings are in the beginning of NAT's array:
  121. // we can stop as soon as we hit a dynamic one.
  122. CComPtr<IDynamicPortMapping> spDPM = NULL;
  123. V_DISPATCH (&cv)->QueryInterface (__uuidof(IDynamicPortMapping),
  124. (void**)&spDPM);
  125. _ASSERT (spDPM != NULL); // can't fail
  126. if (!IsStaticPortMapping (spDPM))
  127. i--; // try next one.
  128. else {
  129. // create a static port map object out of a dynamic object.
  130. CComPtr<IStaticPortMapping> spSPM =
  131. CStaticPortMapping::CreateInstance (spDPM);
  132. if (!spSPM) {
  133. hr = E_OUTOFMEMORY;
  134. break;
  135. }
  136. V_VT (&rgVar[i]) = VT_DISPATCH;
  137. spSPM->QueryInterface (__uuidof(IDispatch),
  138. (void**)&V_DISPATCH (&rgVar[i]));
  139. }
  140. }
  141. if (hr == HRESULT_FROM_WIN32 (ERROR_FILE_NOT_FOUND))
  142. hr = S_OK; // no more; will return S_FALSE below
  143. if (FAILED(hr)) {
  144. // on error clear variant array....
  145. for (ULONG j=0; j<i; j++)
  146. VariantClear (&rgVar[j]);
  147. return hr;
  148. }
  149. // now update index
  150. m_index += i;
  151. // fill out how many we're returning
  152. if (pCeltFetched)
  153. *pCeltFetched = i;
  154. return i < celt ? S_FALSE : S_OK;
  155. NAT_API_LEAVE
  156. }
  157. virtual HRESULT STDMETHODCALLTYPE Skip (/*[in]*/ ULONG celt)
  158. {
  159. NAT_API_ENTER
  160. HRESULT hr = S_OK;
  161. for (ULONG i=0; i<celt; i++) {
  162. CComVariant cv;
  163. hr = Next (1, &cv, NULL);
  164. if (hr != S_OK)
  165. break;
  166. }
  167. m_index += i;
  168. if (FAILED(hr))
  169. return hr;
  170. if (i != celt)
  171. return S_FALSE;
  172. return S_OK;
  173. NAT_API_LEAVE
  174. }
  175. virtual HRESULT STDMETHODCALLTYPE Reset ()
  176. {
  177. NAT_API_ENTER
  178. m_index = 0;
  179. return m_spEV->Reset ();
  180. NAT_API_LEAVE
  181. }
  182. virtual HRESULT STDMETHODCALLTYPE Clone (/*[out]*/ IEnumVARIANT ** ppEnum)
  183. {
  184. NAT_API_ENTER
  185. if (!ppEnum)
  186. return E_POINTER;
  187. if (!(*ppEnum = CreateInstance (m_spUPS)))
  188. return E_OUTOFMEMORY;
  189. return (*ppEnum)->Skip (m_index);
  190. NAT_API_LEAVE
  191. }
  192. private:
  193. static BOOL IsStaticPortMapping (IDynamicPortMapping * pDPM)
  194. {
  195. /* is it dynamic?
  196. lease must be infinite (i.e. 0)
  197. remote host must be wildcard (i.e. "")
  198. ports must match
  199. */
  200. long lLease = -1;
  201. HRESULT hr = pDPM->get_LeaseDuration (&lLease);
  202. if (FAILED(hr))
  203. return FALSE;
  204. if (lLease != 0)
  205. return FALSE;
  206. CComBSTR cbRemoteHost;
  207. hr = pDPM->get_RemoteHost (&cbRemoteHost);
  208. if (FAILED(hr))
  209. return FALSE;
  210. if (wcscmp(cbRemoteHost, L""))
  211. return FALSE;
  212. // still here? must be static!
  213. return TRUE;
  214. }
  215. };
  216. #endif //__STATICPORTMAPPINGCOLLECTION_H_