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 23 WINE_DEFAULT_DEBUG_CHANNEL(vbscript); 24 25 typedef struct { 26 IEnumVARIANT IEnumVARIANT_iface; 27 28 LONG ref; 29 30 SAFEARRAY *sa; 31 ULONG i, size; 32 } safearray_iter; 33 34 static inline safearray_iter *impl_from_IEnumVARIANT(IEnumVARIANT *iface) 35 { 36 return CONTAINING_RECORD(iface, safearray_iter, IEnumVARIANT_iface); 37 } 38 39 static 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 60 static 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 70 static 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 86 static 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 121 static HRESULT WINAPI safearray_iter_IEnumVARIANT_Skip(IEnumVARIANT *iface, ULONG celt) 122 { 123 FIXME("\n"); 124 return E_NOTIMPL; 125 } 126 127 static HRESULT WINAPI safearray_iter_IEnumVARIANT_Reset(IEnumVARIANT *iface) 128 { 129 FIXME("\n"); 130 return E_NOTIMPL; 131 } 132 133 static HRESULT WINAPI safearray_iter_IEnumVARIANT_Clone( 134 IEnumVARIANT *iface, IEnumVARIANT **ppEnum) 135 { 136 FIXME("\n"); 137 return E_NOTIMPL; 138 } 139 140 static 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 150 static 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 163 HRESULT 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 } 194