Reactos
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}