Reactos
at master 193 lines 4.9 kB view raw
1/* 2 * Copyright 2017 Piotr Caban for CodeWeavers 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19#include "vbscript.h" 20 21#include "wine/debug.h" 22 23WINE_DEFAULT_DEBUG_CHANNEL(vbscript); 24 25typedef struct { 26 IEnumVARIANT IEnumVARIANT_iface; 27 28 LONG ref; 29 30 SAFEARRAY *sa; 31 ULONG i, size; 32} safearray_iter; 33 34static inline safearray_iter *impl_from_IEnumVARIANT(IEnumVARIANT *iface) 35{ 36 return CONTAINING_RECORD(iface, safearray_iter, IEnumVARIANT_iface); 37} 38 39static HRESULT WINAPI safearray_iter_IEnumVARIANT_QueryInterface( 40 IEnumVARIANT *iface, REFIID riid, void **ppv) 41{ 42 safearray_iter *This = impl_from_IEnumVARIANT(iface); 43 44 if(IsEqualGUID(riid, &IID_IUnknown)) { 45 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 46 *ppv = &This->IEnumVARIANT_iface; 47 }else if(IsEqualGUID(riid, &IID_IEnumVARIANT)) { 48 TRACE("(%p)->(IID_IEnumVARIANT %p)\n", This, ppv); 49 *ppv = &This->IEnumVARIANT_iface; 50 }else { 51 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); 52 *ppv = NULL; 53 return E_NOINTERFACE; 54 } 55 56 IUnknown_AddRef((IUnknown*)*ppv); 57 return S_OK; 58} 59 60static ULONG WINAPI safearray_iter_IEnumVARIANT_AddRef(IEnumVARIANT *iface) 61{ 62 safearray_iter *This = impl_from_IEnumVARIANT(iface); 63 LONG ref = InterlockedIncrement(&This->ref); 64 65 TRACE("(%p) ref=%d\n", This, ref); 66 67 return ref; 68} 69 70static ULONG WINAPI safearray_iter_IEnumVARIANT_Release(IEnumVARIANT *iface) 71{ 72 safearray_iter *This = impl_from_IEnumVARIANT(iface); 73 LONG ref = InterlockedDecrement(&This->ref); 74 75 TRACE("(%p) ref=%d\n", iface, ref); 76 77 if(!ref) { 78 if(This->sa) 79 SafeArrayUnlock(This->sa); 80 heap_free(This); 81 } 82 83 return ref; 84} 85 86static HRESULT WINAPI safearray_iter_IEnumVARIANT_Next(IEnumVARIANT *iface, 87 ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched) 88{ 89 safearray_iter *This = impl_from_IEnumVARIANT(iface); 90 HRESULT hres; 91 VARIANT *v; 92 93 TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched); 94 95 if(celt != 1) { 96 FIXME("celt != 1\n"); 97 return E_NOTIMPL; 98 } 99 100 if(This->i >= This->size) { 101 if(pCeltFetched) 102 *pCeltFetched = 0; 103 return S_FALSE; 104 } 105 106 if(!This->sa->cLocks) 107 ERR("SAFEARRAY not locked\n"); 108 109 v = (VARIANT*)(((BYTE*)This->sa->pvData) + This->i * This->sa->cbElements); 110 V_VT(rgVar) = VT_EMPTY; 111 hres = VariantCopy(rgVar, v); 112 if(FAILED(hres)) 113 return hres; 114 115 This->i++; 116 if(pCeltFetched) 117 *pCeltFetched = 1; 118 return S_OK; 119} 120 121static HRESULT WINAPI safearray_iter_IEnumVARIANT_Skip(IEnumVARIANT *iface, ULONG celt) 122{ 123 FIXME("\n"); 124 return E_NOTIMPL; 125} 126 127static HRESULT WINAPI safearray_iter_IEnumVARIANT_Reset(IEnumVARIANT *iface) 128{ 129 FIXME("\n"); 130 return E_NOTIMPL; 131} 132 133static HRESULT WINAPI safearray_iter_IEnumVARIANT_Clone( 134 IEnumVARIANT *iface, IEnumVARIANT **ppEnum) 135{ 136 FIXME("\n"); 137 return E_NOTIMPL; 138} 139 140static const IEnumVARIANTVtbl safearray_iter_EnumVARIANTVtbl = { 141 safearray_iter_IEnumVARIANT_QueryInterface, 142 safearray_iter_IEnumVARIANT_AddRef, 143 safearray_iter_IEnumVARIANT_Release, 144 safearray_iter_IEnumVARIANT_Next, 145 safearray_iter_IEnumVARIANT_Skip, 146 safearray_iter_IEnumVARIANT_Reset, 147 safearray_iter_IEnumVARIANT_Clone 148}; 149 150static ULONG get_safearray_size(SAFEARRAY *sa) 151{ 152 ULONG ret = 1; 153 USHORT i; 154 155 if(!sa) 156 return 0; 157 158 for(i=0; i<sa->cDims && ret; i++) 159 ret *= sa->rgsabound[i].cElements; 160 return ret; 161} 162 163HRESULT create_safearray_iter(SAFEARRAY *sa, IEnumVARIANT **ev) 164{ 165 safearray_iter *iter; 166 HRESULT hres; 167 168 if(sa && !(sa->fFeatures & FADF_VARIANT)) { 169 FIXME("enumeration not supported: %x\n", sa->fFeatures); 170 return E_NOTIMPL; 171 } 172 173 iter = heap_alloc(sizeof(*iter)); 174 if(!iter) 175 return E_OUTOFMEMORY; 176 177 if(sa) { 178 hres = SafeArrayLock(sa); 179 if(FAILED(hres)) { 180 heap_free(iter); 181 return hres; 182 } 183 } 184 185 iter->IEnumVARIANT_iface.lpVtbl = &safearray_iter_EnumVARIANTVtbl; 186 iter->ref = 1; 187 iter->sa = sa; 188 iter->i = 0; 189 iter->size = get_safearray_size(sa); 190 191 *ev = &iter->IEnumVARIANT_iface; 192 return S_OK; 193}