home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / oleaut / spoly / cenumpt.cpp next >
C/C++ Source or Header  |  1997-08-01  |  6KB  |  291 lines

  1. /*** 
  2. *cenumpt.cpp
  3. *
  4. *  This is a part of the Microsoft Source Code Samples.
  5. *
  6. *  Copyright (C) 1992-1997 Microsoft Corporation. All rights reserved.
  7. *
  8. *  This source code is only intended as a supplement to Microsoft Development
  9. *  Tools and/or WinHelp documentation.  See these sources for detailed
  10. *  information regarding the Microsoft samples programs.
  11. *
  12. *Purpose:
  13. *  This module implements the CEnumPoint class.
  14. *
  15. *
  16. *Implementation Notes:
  17. *
  18. *****************************************************************************/
  19.  
  20. #include "hostenv.h"
  21. #include "cenumpt.h"
  22.  
  23.  
  24. CEnumPoint::CEnumPoint()
  25. {
  26.     m_refs = 0;
  27.  
  28.     m_psa = NULL;
  29.     m_celts = 0;
  30.     m_iCurrent = 0;
  31. }
  32.  
  33.  
  34. /***
  35. *HRESULT CEnumPoint::Create(SAFEARRAY*, CEnumPoint**)
  36. *Purpose:
  37. *  This routine creates a CPoint enumerator from the given
  38. *  (1 X N) SafeArray of CPoint IDispatch pointers.
  39. *
  40. *Entry:
  41. *  psa = pointer to a SafeArray of VARIANTs
  42. *
  43. *Exit:
  44. *  return value = HRESULT
  45. *
  46. *  *ppenum = pointer to a CPoint enumerator
  47. *
  48. ***********************************************************************/
  49. HRESULT
  50. CEnumPoint::Create(SAFEARRAY FAR* psa, CEnumPoint FAR* FAR* ppenum)
  51. {
  52.     long lBound;
  53.     HRESULT hresult;
  54.     CEnumPoint FAR* penum;
  55.  
  56.  
  57.     // Verify that the SafeArray is the proper shape.
  58.     //
  59.     if(SafeArrayGetDim(psa) != 1)
  60.       return E_INVALIDARG;
  61.  
  62.     hresult = SafeArrayGetLBound(psa, 1, &lBound);
  63.     if(FAILED(hresult))
  64.       return hresult;
  65.  
  66.     if(lBound != 0)
  67.       return E_INVALIDARG;
  68.  
  69.     penum = new FAR CEnumPoint();
  70.     if(penum == NULL)
  71.       return E_OUTOFMEMORY;
  72.     penum->AddRef();
  73.  
  74.     hresult = SafeArrayGetUBound(psa, 1, &lBound);
  75.     if(FAILED(hresult))
  76.       goto LError0;
  77.  
  78.     penum->m_psa = psa;
  79.     penum->m_celts = lBound + 1;
  80.  
  81.     *ppenum = penum;
  82.  
  83.     return NOERROR;
  84.  
  85. LError0:;
  86.     penum->Release();
  87.  
  88.     return hresult;
  89. }
  90.  
  91.  
  92. //---------------------------------------------------------------------
  93. //                        IUnknown methods
  94. //---------------------------------------------------------------------
  95.  
  96.  
  97. STDMETHODIMP
  98. CEnumPoint::QueryInterface(REFIID riid, void FAR* FAR* ppv)
  99. {
  100.  
  101.     if(!IsEqualIID(riid, IID_IUnknown))
  102.       if(!IsEqualIID(riid, IID_IEnumVARIANT)) {
  103.         *ppv = NULL;              
  104.         return E_NOINTERFACE;
  105.     }
  106.     
  107.     *ppv = this;
  108.     AddRef();
  109.     return NOERROR;
  110. }
  111.  
  112.  
  113. STDMETHODIMP_(unsigned long)
  114. CEnumPoint::AddRef()
  115. {
  116.     return ++m_refs;
  117. }
  118.  
  119.  
  120. STDMETHODIMP_(unsigned long)
  121. CEnumPoint::Release()
  122. {
  123.     if(--m_refs == 0){
  124.       if(m_psa != NULL)
  125.     SafeArrayDestroy(m_psa);
  126.       delete this;
  127.       return 0;
  128.     }
  129.     return m_refs;
  130. }
  131.  
  132.  
  133. //---------------------------------------------------------------------
  134. //                        IEnumVARIANT methods
  135. //---------------------------------------------------------------------
  136.  
  137.  
  138. /***
  139. *HRESULT CEnumPoint::Next(unsigned long, VARIANT*, unsigned long*)
  140. *Purpose:
  141. *  Attempt to get the next 'celt' items in the enumeration sequence.
  142. *
  143. *Entry:
  144. *  celt = the number of elements to get
  145. *
  146. *Exit:
  147. *  return value = HRESULT
  148. *    S_OK
  149. *    S_FALSE - the end of the sequence was reached
  150. *
  151. *  rgvar = array of the next 'celt' items
  152. *  *pceltFetched = count of the elements actually fetched.
  153. *
  154. ***********************************************************************/
  155. STDMETHODIMP
  156. CEnumPoint::Next(
  157.     unsigned long celt,
  158.     VARIANT FAR* rgvar,
  159.     unsigned long FAR* pceltFetched)
  160. {
  161.     long ix;
  162.     unsigned int i;
  163.     HRESULT hresult;
  164.  
  165.  
  166.     for(i = 0; i < celt; ++i)
  167.       VariantInit(&rgvar[i]);
  168.  
  169.     for(i = 0; i < celt; ++i){
  170.       if(m_iCurrent == m_celts){
  171.         hresult = S_FALSE;
  172.     goto LDone;
  173.       }
  174.  
  175.       ix = m_iCurrent++;
  176.       hresult = SafeArrayGetElement(m_psa, &ix, &rgvar[i]);
  177.       if(FAILED(hresult))
  178.     goto LError0;
  179.     }
  180.  
  181.     hresult = NOERROR;
  182.  
  183. LDone:;
  184.     if (pceltFetched != NULL)
  185.       *pceltFetched = i;
  186.  
  187.     return hresult;
  188.  
  189. LError0:;
  190.  
  191.     for(i = 0; i < celt; ++i)
  192.       VariantClear(&rgvar[i]);
  193.  
  194.     return hresult;
  195. }
  196.  
  197.  
  198. /***
  199. *HRESULT CEnumPoint::Skip(unsigned long)
  200. *Purpose:
  201. *  Attempt to skip over the next 'celt' elements in the enumeration
  202. *  sequence.
  203. *
  204. *Entry:
  205. *  celt = the count of elements to skip
  206. *
  207. *Exit:
  208. *  return value = HRESULT
  209. *    S_OK
  210. *    S_FALSE -  the end of the sequence was reached
  211. *
  212. ***********************************************************************/
  213. STDMETHODIMP
  214. CEnumPoint::Skip(unsigned long celt)
  215. {
  216.     m_iCurrent += celt;
  217.  
  218.     if(m_iCurrent > m_celts)
  219.      m_iCurrent = m_celts;
  220.  
  221.     return (m_iCurrent == m_celts)
  222.       ? S_FALSE : NOERROR;
  223. }
  224.  
  225.  
  226. /***
  227. *HRESULT CEnumPoint::Reset(void)
  228. *Purpose:
  229. *  Reset the enumeration sequence back to the beginning.
  230. *
  231. *Entry:
  232. *  None
  233. *
  234. *Exit:
  235. *  return value = SHRESULT CODE
  236. *    S_OK
  237. *
  238. ***********************************************************************/
  239. STDMETHODIMP
  240. CEnumPoint::Reset()
  241. {
  242.     m_iCurrent = 0;
  243.  
  244.     return NOERROR; 
  245. }
  246.  
  247.  
  248. /***
  249. *HRESULT CEnumPoint::Clone(IEnumVARIANT**)
  250. *Purpose:
  251. *  Retrun a CPoint enumerator with exactly the same state as the
  252. *  current one.
  253. *
  254. *Entry:
  255. *  None
  256. *
  257. *Exit:
  258. *  return value = HRESULT
  259. *    S_OK
  260. *    E_OUTOFMEMORY
  261. *
  262. ***********************************************************************/
  263. STDMETHODIMP
  264. CEnumPoint::Clone(IEnumVARIANT FAR* FAR* ppenum)
  265. {
  266.     HRESULT hresult;
  267.     SAFEARRAY FAR* psa;
  268.     CEnumPoint FAR* penum;
  269.  
  270.     hresult = SafeArrayCopy(m_psa, &psa);
  271.     if(FAILED(hresult))
  272.       return hresult;
  273.  
  274.     hresult = CEnumPoint::Create(psa, &penum);
  275.     if(FAILED(hresult))
  276.       goto LError0;
  277.  
  278.     // Assert(penum->m_celts == m_celts);
  279.  
  280.     penum->m_iCurrent = m_iCurrent;
  281.  
  282.     *ppenum = penum;
  283.  
  284.     return NOERROR;
  285.  
  286. LError0:
  287.     SafeArrayDestroy(psa);
  288.  
  289.     return hresult;
  290. }
  291.