Home | History | Annotate | Download | only in win
      1 /*
      2  * Copyright (C) 2007 Apple Inc. All Rights Reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef COMEnumVariant_h
     27 #define COMEnumVariant_h
     28 
     29 #define NOMINMAX
     30 #include <unknwn.h>
     31 
     32 
     33 #include "COMVariantSetter.h"
     34 
     35 template<typename ContainerType>
     36 class COMEnumVariant : public IEnumVARIANT {
     37     WTF_MAKE_NONCOPYABLE(COMEnumVariant);
     38 public:
     39     static COMEnumVariant* adopt(ContainerType&);
     40     static COMEnumVariant* createInstance(const ContainerType&);
     41 
     42     // IUnknown
     43     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
     44     virtual ULONG STDMETHODCALLTYPE AddRef();
     45     virtual ULONG STDMETHODCALLTYPE Release();
     46 
     47     // IEnumVARIANT
     48     virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt, VARIANT* rgVar, ULONG* pCeltFetched);
     49     virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt);
     50     virtual HRESULT STDMETHODCALLTYPE Reset();
     51     virtual HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT** ppEnum);
     52 
     53 private:
     54     COMEnumVariant()
     55         : m_refCount(0)
     56     {
     57     }
     58 
     59     COMEnumVariant(const ContainerType& container)
     60         : m_refCount(0)
     61         , m_container(container)
     62         , m_currentPos(m_container.begin())
     63     {
     64     }
     65 
     66     ~COMEnumVariant() {}
     67 
     68     ULONG m_refCount;
     69 
     70     ContainerType m_container;
     71     typename ContainerType::const_iterator m_currentPos;
     72 };
     73 
     74 // COMEnumVariant ------------------------------------------------------------------
     75 template<typename ContainerType>
     76 COMEnumVariant<typename ContainerType>* COMEnumVariant<ContainerType>::adopt(ContainerType& container)
     77 {
     78     COMEnumVariant* instance = new COMEnumVariant;
     79     instance->m_container.swap(container);
     80     instance->m_currentPos = instance->m_container.begin();
     81     instance->AddRef();
     82     return instance;
     83 }
     84 
     85 template<typename ContainerType>
     86 COMEnumVariant<typename ContainerType>* COMEnumVariant<ContainerType>::createInstance(const ContainerType& container)
     87 {
     88     COMEnumVariant* instance = new COMEnumVariant(container);
     89     instance->AddRef();
     90     return instance;
     91 }
     92 
     93 // IUnknown ------------------------------------------------------------------------
     94 template<typename ContainerType>
     95 HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::QueryInterface(REFIID riid, void** ppvObject)
     96 {
     97     *ppvObject = 0;
     98     if (IsEqualGUID(riid, IID_IUnknown))
     99         *ppvObject = static_cast<COMEnumVariant*>(this);
    100     else if (IsEqualGUID(riid, IID_IEnumVARIANT))
    101         *ppvObject = static_cast<COMEnumVariant*>(this);
    102     else
    103         return E_NOINTERFACE;
    104 
    105     AddRef();
    106     return S_OK;
    107 }
    108 
    109 template<typename ContainerType>
    110 ULONG STDMETHODCALLTYPE COMEnumVariant<ContainerType>::AddRef()
    111 {
    112     return ++m_refCount;
    113 }
    114 
    115 template<typename ContainerType>
    116 ULONG STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Release()
    117 {
    118     ULONG newRef = --m_refCount;
    119     if (!newRef)
    120         delete this;
    121 
    122     return newRef;
    123 }
    124 
    125 // IEnumVARIANT --------------------------------------------------------------------
    126 template<typename ContainerType>
    127 HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Next(ULONG celt, VARIANT* rgVar, ULONG* pCeltFetched)
    128 {
    129     if (pCeltFetched)
    130         *pCeltFetched = 0;
    131     if (!rgVar)
    132         return E_POINTER;
    133     for (unsigned i = 0 ; i < celt; i++)
    134         VariantInit(&rgVar[i]);
    135 
    136     for (unsigned i = 0; i < celt; i++) {
    137         if (m_currentPos == m_container.end())
    138             return S_FALSE;
    139 
    140         COMVariantSetter<ContainerType::ValueType>::setVariant(&rgVar[i], *m_currentPos);
    141         ++m_currentPos;
    142         if (pCeltFetched)
    143             (*pCeltFetched)++;
    144     }
    145 
    146     return S_OK;
    147 }
    148 
    149 template<typename ContainerType>
    150 HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Skip(ULONG celt)
    151 {
    152     for (unsigned i = 0; i < celt; i++) {
    153         if (m_currentPos == m_container.end())
    154             return S_FALSE;
    155 
    156         ++m_currentPos;
    157     }
    158     return S_OK;
    159 }
    160 
    161 template<typename ContainerType>
    162 HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Reset()
    163 {
    164     m_currentPos = m_container.begin();
    165     return S_OK;
    166 }
    167 
    168 template<typename ContainerType>
    169 HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Clone(IEnumVARIANT** ppEnum)
    170 {
    171     if (!ppEnum)
    172         return E_POINTER;
    173 
    174     *ppEnum = 0;
    175     return E_NOTIMPL;
    176 }
    177 
    178 #endif
    179