xref: /reactos/dll/win32/vbscript/utils.c (revision 234f89c0)
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