oleenum.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #ifdef AFX_OLE3_SEG
  12. #pragma code_seg(AFX_OLE3_SEG)
  13. #endif
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. #define new DEBUG_NEW
  19. /////////////////////////////////////////////////////////////////////////////
  20. // CEnumArray (provides OLE enumerator for arbitrary items in an array)
  21. CEnumArray::CEnumArray(size_t nSizeElem, const void* pvEnum, UINT nSize,
  22. BOOL bNeedFree)
  23. {
  24. m_nSizeElem = nSizeElem;
  25. m_pClonedFrom = NULL;
  26. m_nCurPos = 0;
  27. m_nSize = nSize;
  28. m_pvEnum = (BYTE*)pvEnum;
  29. m_bNeedFree = bNeedFree;
  30. ASSERT_VALID(this);
  31. }
  32. CEnumArray::~CEnumArray()
  33. {
  34. ASSERT_VALID(this);
  35. // release the clone pointer (only for clones)
  36. if (m_pClonedFrom != NULL)
  37. {
  38. m_pClonedFrom->InternalRelease();
  39. ASSERT(!m_bNeedFree);
  40. }
  41. // release the pointer (should only happen on non-clones)
  42. if (m_bNeedFree)
  43. {
  44. ASSERT(m_pClonedFrom == NULL);
  45. delete m_pvEnum;
  46. }
  47. }
  48. BOOL CEnumArray::OnNext(void* pv)
  49. {
  50. ASSERT_VALID(this);
  51. if (m_nCurPos >= m_nSize)
  52. return FALSE;
  53. memcpy(pv, &m_pvEnum[m_nCurPos*m_nSizeElem], m_nSizeElem);
  54. ++m_nCurPos;
  55. return TRUE;
  56. }
  57. BOOL CEnumArray::OnSkip()
  58. {
  59. ASSERT_VALID(this);
  60. if (m_nCurPos >= m_nSize)
  61. return FALSE;
  62. return ++m_nCurPos < m_nSize;
  63. }
  64. void CEnumArray::OnReset()
  65. {
  66. ASSERT_VALID(this);
  67. m_nCurPos = 0;
  68. }
  69. CEnumArray* CEnumArray::OnClone()
  70. {
  71. ASSERT_VALID(this);
  72. // set up an exact copy of this object
  73. // (derivatives may have to replace this code)
  74. CEnumArray* pClone;
  75. pClone = new CEnumArray(m_nSizeElem, m_pvEnum, m_nSize);
  76. ASSERT(pClone != NULL);
  77. ASSERT(!pClone->m_bNeedFree); // clones should never free themselves
  78. pClone->m_nCurPos = m_nCurPos;
  79. // finally, return the clone to OLE
  80. ASSERT_VALID(pClone);
  81. return pClone;
  82. }
  83. /////////////////////////////////////////////////////////////////////////////
  84. // CEnumArray::XEnumVOID implementation
  85. STDMETHODIMP_(ULONG) CEnumArray::XEnumVOID::AddRef()
  86. {
  87. METHOD_PROLOGUE_EX_(CEnumArray, EnumVOID)
  88. return pThis->ExternalAddRef();
  89. }
  90. STDMETHODIMP_(ULONG) CEnumArray::XEnumVOID::Release()
  91. {
  92. METHOD_PROLOGUE_EX_(CEnumArray, EnumVOID)
  93. return pThis->ExternalRelease();
  94. }
  95. STDMETHODIMP CEnumArray::XEnumVOID::QueryInterface(
  96. REFIID iid, LPVOID* ppvObj)
  97. {
  98. METHOD_PROLOGUE_EX_(CEnumArray, EnumVOID)
  99. return pThis->ExternalQueryInterface(&iid, ppvObj);
  100. }
  101. STDMETHODIMP CEnumArray::XEnumVOID::Next(
  102. ULONG celt, void* reelt, ULONG* pceltFetched)
  103. {
  104. METHOD_PROLOGUE_EX(CEnumArray, EnumVOID);
  105. ASSERT_VALID(pThis);
  106. if (pceltFetched != NULL)
  107. *pceltFetched = 0;
  108. ASSERT(celt > 0);
  109. ASSERT(celt == 1 || pceltFetched != NULL);
  110. BYTE* pchCur = (BYTE*)reelt;
  111. ULONG celtT = celt;
  112. SCODE sc = E_UNEXPECTED;
  113. TRY
  114. {
  115. while (celtT != 0 && pThis->OnNext((void*)pchCur))
  116. {
  117. pchCur += pThis->m_nSizeElem;
  118. --celtT;
  119. }
  120. if (pceltFetched != NULL)
  121. *pceltFetched = celt - celtT;
  122. sc = celtT == 0 ? S_OK : S_FALSE;
  123. }
  124. END_TRY
  125. return sc;
  126. }
  127. STDMETHODIMP CEnumArray::XEnumVOID::Skip(ULONG celt)
  128. {
  129. METHOD_PROLOGUE_EX(CEnumArray, EnumVOID);
  130. ASSERT_VALID(pThis);
  131. ULONG celtT = celt;
  132. SCODE sc = E_UNEXPECTED;
  133. TRY
  134. {
  135. while (celtT != 0 && pThis->OnSkip())
  136. --celtT;
  137. sc = celtT == 0 ? S_OK : S_FALSE;
  138. }
  139. END_TRY
  140. return celtT != 0 ? S_FALSE : S_OK;
  141. }
  142. STDMETHODIMP CEnumArray::XEnumVOID::Reset()
  143. {
  144. METHOD_PROLOGUE_EX(CEnumArray, EnumVOID);
  145. ASSERT_VALID(pThis);
  146. pThis->OnReset();
  147. return S_OK;
  148. }
  149. STDMETHODIMP CEnumArray::XEnumVOID::Clone(IEnumVOID** ppenm)
  150. {
  151. METHOD_PROLOGUE_EX(CEnumArray, EnumVOID);
  152. ASSERT_VALID(pThis);
  153. *ppenm = NULL;
  154. SCODE sc = E_UNEXPECTED;
  155. TRY
  156. {
  157. CEnumArray* pEnumHelper = pThis->OnClone();
  158. ASSERT_VALID(pEnumHelper);
  159. // we use an extra reference to keep the original object alive
  160. // (the extra reference is removed in the clone's destructor)
  161. if (pThis->m_pClonedFrom != NULL)
  162. pEnumHelper->m_pClonedFrom = pThis->m_pClonedFrom;
  163. else
  164. pEnumHelper->m_pClonedFrom = pThis;
  165. pEnumHelper->m_pClonedFrom->InternalAddRef();
  166. *ppenm = &pEnumHelper->m_xEnumVOID;
  167. sc = S_OK;
  168. }
  169. END_TRY
  170. return sc;
  171. }
  172. /////////////////////////////////////////////////////////////////////////////