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.

371 lines
9.7 KiB

  1. /*****************************************************************************
  2. *
  3. * ftpefe.cpp - IEnumFORMATETC interface
  4. *
  5. *****************************************************************************/
  6. #include "priv.h"
  7. #include "ftpefe.h"
  8. #include "ftpobj.h"
  9. /*****************************************************************************
  10. * CFtpEfe::_NextOne
  11. *****************************************************************************/
  12. HRESULT CFtpEfe::_NextOne(FORMATETC * pfetc)
  13. {
  14. HRESULT hr = S_FALSE;
  15. while (ShouldSkipDropFormat(m_dwIndex))
  16. m_dwIndex++;
  17. ASSERT(m_hdsaFormatEtc);
  18. if (m_dwIndex < (DWORD) DSA_GetItemCount(m_hdsaFormatEtc))
  19. {
  20. DSA_GetItem(m_hdsaFormatEtc, m_dwIndex, (LPVOID) pfetc);
  21. m_dwIndex++; // We are off to the next one
  22. hr = S_OK;
  23. }
  24. if ((S_OK != hr) && m_pfo)
  25. {
  26. // We finished looking thru the types supported by the IDataObject.
  27. // Now look for other items inserted by IDataObject::SetData()
  28. if (m_dwExtraIndex < (DWORD) DSA_GetItemCount(m_pfo->m_hdsaSetData))
  29. {
  30. FORMATETC_STGMEDIUM fs;
  31. DSA_GetItem(m_pfo->m_hdsaSetData, m_dwExtraIndex, (LPVOID) &fs);
  32. *pfetc = fs.formatEtc;
  33. m_dwExtraIndex++; // We are off to the next one
  34. hr = S_OK;
  35. }
  36. }
  37. return hr;
  38. }
  39. //===========================
  40. // *** IEnumFORMATETC Interface ***
  41. //===========================
  42. /*****************************************************************************
  43. *
  44. * IEnumFORMATETC::Next
  45. *
  46. * Creates a brand new enumerator based on an existing one.
  47. *
  48. *
  49. * OLE random documentation of the day: IEnumXXX::Next.
  50. *
  51. * rgelt - Receives an array of size celt (or larger).
  52. *
  53. * "Receives an array"? No, it doesn't receive an array.
  54. * It *is* an array. The array receives *elements*.
  55. *
  56. * "Or larger"? Does this mean I can return more than the caller
  57. * asked for? No, of course not, because the caller didn't allocate
  58. * enough memory to hold that many return values.
  59. *
  60. * No semantics are assigned to the possibility of celt = 0.
  61. * Since I am a mathematician, I treat it as vacuous success.
  62. *
  63. * pcelt is documented as an INOUT parameter, but no semantics
  64. * are assigned to its input value.
  65. *
  66. * The dox don't say that you are allowed to return *pcelt < celt
  67. * for reasons other than "no more elements", but the shell does
  68. * it everywhere, so maybe it's legal...
  69. *
  70. *****************************************************************************/
  71. HRESULT CFtpEfe::Next(ULONG celt, FORMATETC * rgelt, ULONG *pceltFetched)
  72. {
  73. HRESULT hres = S_FALSE;
  74. DWORD dwIndex;
  75. // Do they want more and do we have more to give?
  76. for (dwIndex = 0; dwIndex < celt; dwIndex++)
  77. {
  78. if (S_FALSE == _NextOne(&rgelt[dwIndex])) // Yes, so give away...
  79. break;
  80. ASSERT(NULL == rgelt[dwIndex].ptd); // We don't do this correctly.
  81. #ifdef DEBUG
  82. char szName[MAX_PATH];
  83. GetCfBufA(rgelt[dwIndex].cfFormat, szName, ARRAYSIZE(szName));
  84. //TraceMsg(TF_FTP_IDENUM, "CFtpEfe::Next() - Returning %hs", szName);
  85. #endif // DEBUG
  86. }
  87. if (pceltFetched)
  88. *pceltFetched = dwIndex;
  89. // Were we able to give any?
  90. if ((0 != dwIndex) || (0 == celt))
  91. hres = S_OK;
  92. return hres;
  93. }
  94. /*****************************************************************************
  95. * IEnumFORMATETC::Skip
  96. *****************************************************************************/
  97. HRESULT CFtpEfe::Skip(ULONG celt)
  98. {
  99. m_dwIndex += celt;
  100. return S_OK;
  101. }
  102. /*****************************************************************************
  103. * IEnumFORMATETC::Reset
  104. *****************************************************************************/
  105. HRESULT CFtpEfe::Reset(void)
  106. {
  107. m_dwIndex = 0;
  108. return S_OK;
  109. }
  110. /*****************************************************************************
  111. *
  112. * IEnumFORMATETC::Clone
  113. *
  114. * Creates a brand new enumerator based on an existing one.
  115. *
  116. *****************************************************************************/
  117. HRESULT CFtpEfe::Clone(IEnumFORMATETC **ppenum)
  118. {
  119. return CFtpEfe_Create((DWORD) DSA_GetItemCount(m_hdsaFormatEtc), m_hdsaFormatEtc, m_dwIndex, m_pfo, ppenum);
  120. }
  121. /*****************************************************************************
  122. *
  123. * CFtpEfe_Create
  124. *
  125. * Creates a brand new enumerator based on a list of possibilities.
  126. *
  127. * Note that we are EVIL and know about CFSTR_FILECONTENTS here:
  128. * A FORMATETC of FileContents is always valid. This is important,
  129. * because CFtpObj doesn't actually have a STGMEDIUM for file contents.
  130. * (Due to lindex weirdness.)
  131. *
  132. *****************************************************************************/
  133. HRESULT CFtpEfe_Create(DWORD dwSize, FORMATETC rgfe[], STGMEDIUM rgstg[], CFtpObj * pfo, CFtpEfe ** ppfefe)
  134. {
  135. CFtpEfe * pfefe;
  136. HRESULT hres = E_OUTOFMEMORY;
  137. pfefe = *ppfefe = new CFtpEfe(dwSize, rgfe, rgstg, pfo);
  138. if (pfefe)
  139. {
  140. if (!pfefe->m_hdsaFormatEtc)
  141. pfefe->Release();
  142. else
  143. hres = S_OK;
  144. }
  145. if (FAILED(hres) && pfefe)
  146. IUnknown_Set(ppfefe, NULL);
  147. return hres;
  148. }
  149. /*****************************************************************************
  150. *
  151. * CFtpEfe_Create
  152. *
  153. * Creates a brand new enumerator based on a list of possibilities.
  154. *
  155. * Note that we are EVIL and know about CFSTR_FILECONTENTS here:
  156. * A FORMATETC of FileContents is always valid. This is important,
  157. * because CFtpObj doesn't actually have a STGMEDIUM for file contents.
  158. * (Due to lindex weirdness.)
  159. *
  160. *****************************************************************************/
  161. HRESULT CFtpEfe_Create(DWORD dwSize, FORMATETC rgfe[], STGMEDIUM rgstg[], CFtpObj * pfo, IEnumFORMATETC ** ppenum)
  162. {
  163. CFtpEfe * pfefe;
  164. HRESULT hres = CFtpEfe_Create(dwSize, rgfe, rgstg, pfo, &pfefe);
  165. if (pfefe)
  166. {
  167. hres = pfefe->QueryInterface(IID_IEnumFORMATETC, (LPVOID *) ppenum);
  168. pfefe->Release();
  169. }
  170. return hres;
  171. }
  172. /*****************************************************************************
  173. *
  174. * CFtpEfe_Create
  175. *****************************************************************************/
  176. HRESULT CFtpEfe_Create(DWORD dwSize, HDSA m_hdsaFormatEtc, DWORD dwIndex, CFtpObj * pfo, IEnumFORMATETC ** ppenum)
  177. {
  178. CFtpEfe * pfefe;
  179. HRESULT hres = E_OUTOFMEMORY;
  180. pfefe = new CFtpEfe(dwSize, m_hdsaFormatEtc, pfo, dwIndex);
  181. if (pfefe)
  182. {
  183. hres = pfefe->QueryInterface(IID_IEnumFORMATETC, (LPVOID *) ppenum);
  184. pfefe->Release();
  185. }
  186. return hres;
  187. }
  188. /****************************************************\
  189. Constructor
  190. \****************************************************/
  191. CFtpEfe::CFtpEfe(DWORD dwSize, FORMATETC rgfe[], STGMEDIUM rgstg[], CFtpObj * pfo) : m_cRef(1)
  192. {
  193. DllAddRef();
  194. // This needs to be allocated in Zero Inited Memory.
  195. // Assert that all Member Variables are inited to Zero.
  196. ASSERT(!m_dwIndex);
  197. ASSERT(!m_hdsaFormatEtc);
  198. ASSERT(!m_pfo);
  199. m_hdsaFormatEtc = DSA_Create(sizeof(rgfe[0]), 10);
  200. if (m_hdsaFormatEtc)
  201. {
  202. DWORD dwIndex;
  203. for (dwIndex = 0; dwIndex < dwSize; dwIndex++)
  204. {
  205. #ifdef DEBUG
  206. char szNameDebug[MAX_PATH];
  207. GetCfBufA(rgfe[dwIndex].cfFormat, szNameDebug, ARRAYSIZE(szNameDebug));
  208. #endif // DEBUG
  209. if (rgfe[dwIndex].tymed == TYMED_ISTREAM ||
  210. (rgstg && rgfe[dwIndex].tymed == rgstg[dwIndex].tymed))
  211. {
  212. #ifdef DEBUG
  213. //TraceMsg(TF_FTP_IDENUM, "CFtpEfe() Keeping %hs", szNameDebug);
  214. #endif // DEBUG
  215. DSA_SetItem(m_hdsaFormatEtc, dwIndex, &rgfe[dwIndex]);
  216. }
  217. else
  218. {
  219. #ifdef DEBUG
  220. //TraceMsg(TF_FTP_IDENUM, "CFtpEfe() Ignoring %hs", szNameDebug);
  221. #endif // DEBUG
  222. }
  223. }
  224. }
  225. if (pfo)
  226. {
  227. m_pfo = pfo;
  228. m_pfo->AddRef();
  229. }
  230. LEAK_ADDREF(LEAK_CFtpEfe);
  231. }
  232. /****************************************************\
  233. Constructor
  234. \****************************************************/
  235. CFtpEfe::CFtpEfe(DWORD dwSize, HDSA hdsaFormatEtc, CFtpObj * pfo, DWORD dwIndex) : m_cRef(1)
  236. {
  237. DllAddRef();
  238. // This needs to be allocated in Zero Inited Memory.
  239. // Assert that all Member Variables are inited to Zero.
  240. ASSERT(!m_dwIndex);
  241. ASSERT(!m_hdsaFormatEtc);
  242. ASSERT(!m_pfo);
  243. ASSERT(hdsaFormatEtc);
  244. m_hdsaFormatEtc = DSA_Create(sizeof(FORMATETC), 10);
  245. if (m_hdsaFormatEtc)
  246. {
  247. for (dwIndex = 0; dwIndex < (DWORD) DSA_GetItemCount(hdsaFormatEtc); dwIndex++)
  248. {
  249. DSA_SetItem(m_hdsaFormatEtc, dwIndex, DSA_GetItemPtr(hdsaFormatEtc, dwIndex));
  250. }
  251. }
  252. if (pfo)
  253. {
  254. m_pfo = pfo;
  255. m_pfo->AddRef();
  256. }
  257. LEAK_ADDREF(LEAK_CFtpEfe);
  258. }
  259. /****************************************************\
  260. Destructor
  261. \****************************************************/
  262. CFtpEfe::~CFtpEfe()
  263. {
  264. DSA_Destroy(m_hdsaFormatEtc);
  265. if (m_pfo)
  266. m_pfo->Release();
  267. DllRelease();
  268. LEAK_DELREF(LEAK_CFtpEfe);
  269. }
  270. //===========================
  271. // *** IUnknown Interface ***
  272. //===========================
  273. ULONG CFtpEfe::AddRef()
  274. {
  275. m_cRef++;
  276. return m_cRef;
  277. }
  278. ULONG CFtpEfe::Release()
  279. {
  280. ASSERT(m_cRef > 0);
  281. m_cRef--;
  282. if (m_cRef > 0)
  283. return m_cRef;
  284. delete this;
  285. return 0;
  286. }
  287. HRESULT CFtpEfe::QueryInterface(REFIID riid, void **ppvObj)
  288. {
  289. if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IEnumFORMATETC))
  290. {
  291. *ppvObj = SAFECAST(this, IEnumFORMATETC*);
  292. }
  293. else
  294. {
  295. TraceMsg(TF_FTPQI, "CFtpEfe::QueryInterface() failed.");
  296. *ppvObj = NULL;
  297. return E_NOINTERFACE;
  298. }
  299. AddRef();
  300. return S_OK;
  301. }