vbscript: Added partial implementation of IDispatch methods in IRegExp2.
[wine] / dlls / vbscript / vbregexp.c
1 /*
2  * Copyright 2013 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 #include "vbsregexp55.h"
21
22 #include "wine/debug.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
25
26 #define REGEXP_TID_LIST \
27     XDIID(RegExp2) \
28     XDIID(Match2) \
29     XDIID(MatchCollection2) \
30     XDIID(SubMatches)
31
32 typedef enum {
33 #define XDIID(iface) iface ## _tid,
34 REGEXP_TID_LIST
35 #undef XDIID
36     REGEXP_LAST_tid
37 } regexp_tid_t;
38
39 static REFIID tid_ids[] = {
40 #define XDIID(iface) &IID_I ## iface,
41 REGEXP_TID_LIST
42 #undef XDIID
43 };
44
45 static ITypeLib *typelib;
46 static ITypeInfo *typeinfos[REGEXP_LAST_tid];
47
48 static HRESULT init_regexp_typeinfo(regexp_tid_t tid)
49 {
50     HRESULT hres;
51
52     if(!typelib) {
53         static const WCHAR vbscript_dll3W[] = {'v','b','s','c','r','i','p','t','.','d','l','l','\\','3',0};
54         ITypeLib *tl;
55
56         hres = LoadTypeLib(vbscript_dll3W, &tl);
57         if(FAILED(hres)) {
58             ERR("LoadRegTypeLib failed: %08x\n", hres);
59             return hres;
60         }
61
62         if(InterlockedCompareExchangePointer((void**)&typelib, tl, NULL))
63             ITypeLib_Release(tl);
64     }
65
66     if(!typeinfos[tid]) {
67         ITypeInfo *ti;
68
69         hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
70         if(FAILED(hres)) {
71             ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hres);
72             return hres;
73         }
74
75         if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
76             ITypeInfo_Release(ti);
77     }
78
79     return S_OK;
80 }
81
82 typedef struct {
83     IRegExp2 IRegExp2_iface;
84     IRegExp IRegExp_iface;
85
86     LONG ref;
87 } RegExp2;
88
89 static inline RegExp2 *impl_from_IRegExp2(IRegExp2 *iface)
90 {
91     return CONTAINING_RECORD(iface, RegExp2, IRegExp2_iface);
92 }
93
94 static HRESULT WINAPI RegExp2_QueryInterface(IRegExp2 *iface, REFIID riid, void **ppv)
95 {
96     RegExp2 *This = impl_from_IRegExp2(iface);
97
98     if(IsEqualGUID(riid, &IID_IUnknown)) {
99         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
100         *ppv = &This->IRegExp2_iface;
101     }else if(IsEqualGUID(riid, &IID_IDispatch)) {
102         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
103         *ppv = &This->IRegExp2_iface;
104     }else if(IsEqualGUID(riid, &IID_IRegExp2)) {
105         TRACE("(%p)->(IID_IRegExp2 %p)\n", This, ppv);
106         *ppv = &This->IRegExp2_iface;
107     }else if(IsEqualGUID(riid, &IID_IRegExp)) {
108         TRACE("(%p)->(IID_IRegExp %p)\n", This, ppv);
109         *ppv = &This->IRegExp_iface;
110     }else {
111         FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
112         *ppv = NULL;
113         return E_NOINTERFACE;
114     }
115
116     IUnknown_AddRef((IUnknown*)*ppv);
117     return S_OK;
118 }
119
120 static ULONG WINAPI RegExp2_AddRef(IRegExp2 *iface)
121 {
122     RegExp2 *This = impl_from_IRegExp2(iface);
123     LONG ref = InterlockedIncrement(&This->ref);
124
125     TRACE("(%p) ref=%d\n", This, ref);
126
127     return ref;
128 }
129
130 static ULONG WINAPI RegExp2_Release(IRegExp2 *iface)
131 {
132     RegExp2 *This = impl_from_IRegExp2(iface);
133     LONG ref = InterlockedDecrement(&This->ref);
134
135     TRACE("(%p) ref=%d\n", This, ref);
136
137     if(!ref) {
138         heap_free(This);
139     }
140
141     return ref;
142 }
143
144 static HRESULT WINAPI RegExp2_GetTypeInfoCount(IRegExp2 *iface, UINT *pctinfo)
145 {
146     RegExp2 *This = impl_from_IRegExp2(iface);
147
148     TRACE("(%p)->(%p)\n", This, pctinfo);
149
150     *pctinfo = 1;
151     return S_OK;
152 }
153
154 static HRESULT WINAPI RegExp2_GetTypeInfo(IRegExp2 *iface,
155         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
156 {
157     RegExp2 *This = impl_from_IRegExp2(iface);
158     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
159     return E_NOTIMPL;
160 }
161
162 static HRESULT WINAPI RegExp2_GetIDsOfNames(IRegExp2 *iface, REFIID riid,
163         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
164 {
165     RegExp2 *This = impl_from_IRegExp2(iface);
166
167     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
168             rgszNames, cNames, lcid, rgDispId);
169
170     return ITypeInfo_GetIDsOfNames(typeinfos[RegExp2_tid], rgszNames, cNames, rgDispId);
171 }
172
173 static HRESULT WINAPI RegExp2_Invoke(IRegExp2 *iface, DISPID dispIdMember,
174         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
175         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
176 {
177     RegExp2 *This = impl_from_IRegExp2(iface);
178
179     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
180             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
181
182     return ITypeInfo_Invoke(typeinfos[RegExp2_tid], iface, dispIdMember, wFlags,
183             pDispParams, pVarResult, pExcepInfo, puArgErr);
184 }
185
186 static HRESULT WINAPI RegExp2_get_Pattern(IRegExp2 *iface, BSTR *pPattern)
187 {
188     RegExp2 *This = impl_from_IRegExp2(iface);
189     FIXME("(%p)->(%p)\n", This, pPattern);
190     return E_NOTIMPL;
191 }
192
193 static HRESULT WINAPI RegExp2_put_Pattern(IRegExp2 *iface, BSTR pattern)
194 {
195     RegExp2 *This = impl_from_IRegExp2(iface);
196     FIXME("(%p)->(%s)\n", This, wine_dbgstr_w(pattern));
197     return E_NOTIMPL;
198 }
199
200 static HRESULT WINAPI RegExp2_get_IgnoreCase(IRegExp2 *iface, VARIANT_BOOL *pIgnoreCase)
201 {
202     RegExp2 *This = impl_from_IRegExp2(iface);
203     FIXME("(%p)->(%p)\n", This, pIgnoreCase);
204     return E_NOTIMPL;
205 }
206
207 static HRESULT WINAPI RegExp2_put_IgnoreCase(IRegExp2 *iface, VARIANT_BOOL ignoreCase)
208 {
209     RegExp2 *This = impl_from_IRegExp2(iface);
210     FIXME("(%p)->(%s)\n", This, ignoreCase ? "true" : "false");
211     return E_NOTIMPL;
212 }
213
214 static HRESULT WINAPI RegExp2_get_Global(IRegExp2 *iface, VARIANT_BOOL *pGlobal)
215 {
216     RegExp2 *This = impl_from_IRegExp2(iface);
217     FIXME("(%p)->(%p)\n", This, pGlobal);
218     return E_NOTIMPL;
219 }
220
221 static HRESULT WINAPI RegExp2_put_Global(IRegExp2 *iface, VARIANT_BOOL global)
222 {
223     RegExp2 *This = impl_from_IRegExp2(iface);
224     FIXME("(%p)->(%s)\n", This, global ? "true" : "false");
225     return E_NOTIMPL;
226 }
227
228 static HRESULT WINAPI RegExp2_get_Multiline(IRegExp2 *iface, VARIANT_BOOL *pMultiline)
229 {
230     RegExp2 *This = impl_from_IRegExp2(iface);
231     FIXME("(%p)->(%p)\n", This, pMultiline);
232     return E_NOTIMPL;
233 }
234
235 static HRESULT WINAPI RegExp2_put_Multiline(IRegExp2 *iface, VARIANT_BOOL multiline)
236 {
237     RegExp2 *This = impl_from_IRegExp2(iface);
238     FIXME("(%p)->(%s)\n", This, multiline ? "true" : "false");
239     return E_NOTIMPL;
240 }
241
242 static HRESULT WINAPI RegExp2_Execute(IRegExp2 *iface,
243         BSTR sourceString, IDispatch **ppMatches)
244 {
245     RegExp2 *This = impl_from_IRegExp2(iface);
246     FIXME("(%p)->(%s %p)\n", This, debugstr_w(sourceString), ppMatches);
247     return E_NOTIMPL;
248 }
249
250 static HRESULT WINAPI RegExp2_Test(IRegExp2 *iface, BSTR sourceString, VARIANT_BOOL *pMatch)
251 {
252     RegExp2 *This = impl_from_IRegExp2(iface);
253     FIXME("(%p)->(%s %p)\n", This, debugstr_w(sourceString), pMatch);
254     return E_NOTIMPL;
255 }
256
257 static HRESULT WINAPI RegExp2_Replace(IRegExp2 *iface, BSTR sourceString,
258         VARIANT replaceVar, BSTR *pDestString)
259 {
260     RegExp2 *This = impl_from_IRegExp2(iface);
261     FIXME("(%p)->(%s %s %p)\n", This, debugstr_w(sourceString),
262             debugstr_variant(&replaceVar), pDestString);
263     return E_NOTIMPL;
264 }
265
266 static const IRegExp2Vtbl RegExp2Vtbl = {
267     RegExp2_QueryInterface,
268     RegExp2_AddRef,
269     RegExp2_Release,
270     RegExp2_GetTypeInfoCount,
271     RegExp2_GetTypeInfo,
272     RegExp2_GetIDsOfNames,
273     RegExp2_Invoke,
274     RegExp2_get_Pattern,
275     RegExp2_put_Pattern,
276     RegExp2_get_IgnoreCase,
277     RegExp2_put_IgnoreCase,
278     RegExp2_get_Global,
279     RegExp2_put_Global,
280     RegExp2_get_Multiline,
281     RegExp2_put_Multiline,
282     RegExp2_Execute,
283     RegExp2_Test,
284     RegExp2_Replace
285 };
286
287 static inline RegExp2 *impl_from_IRegExp(IRegExp *iface)
288 {
289     return CONTAINING_RECORD(iface, RegExp2, IRegExp_iface);
290 }
291
292 static HRESULT WINAPI RegExp_QueryInterface(IRegExp *iface, REFIID riid, void **ppv)
293 {
294     RegExp2 *This = impl_from_IRegExp(iface);
295     return IRegExp2_QueryInterface(&This->IRegExp2_iface, riid, ppv);
296 }
297
298 static ULONG WINAPI RegExp_AddRef(IRegExp *iface)
299 {
300     RegExp2 *This = impl_from_IRegExp(iface);
301     return IRegExp2_AddRef(&This->IRegExp2_iface);
302 }
303
304 static ULONG WINAPI RegExp_Release(IRegExp *iface)
305 {
306     RegExp2 *This = impl_from_IRegExp(iface);
307     return IRegExp2_Release(&This->IRegExp2_iface);
308 }
309
310 static HRESULT WINAPI RegExp_GetTypeInfoCount(IRegExp *iface, UINT *pctinfo)
311 {
312     RegExp2 *This = impl_from_IRegExp(iface);
313     return IRegExp2_GetTypeInfoCount(&This->IRegExp2_iface, pctinfo);
314 }
315
316 static HRESULT WINAPI RegExp_GetTypeInfo(IRegExp *iface,
317         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
318 {
319     RegExp2 *This = impl_from_IRegExp(iface);
320     return IRegExp2_GetTypeInfo(&This->IRegExp2_iface, iTInfo, lcid, ppTInfo);
321 }
322
323 static HRESULT WINAPI RegExp_GetIDsOfNames(IRegExp *iface, REFIID riid,
324         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
325 {
326     RegExp2 *This = impl_from_IRegExp(iface);
327     return IRegExp2_GetIDsOfNames(&This->IRegExp2_iface, riid, rgszNames, cNames, lcid, rgDispId);
328 }
329
330 static HRESULT WINAPI RegExp_Invoke(IRegExp *iface, DISPID dispIdMember,
331         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
332                 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
333 {
334     RegExp2 *This = impl_from_IRegExp(iface);
335     return IRegExp2_Invoke(&This->IRegExp2_iface, dispIdMember, riid, lcid,
336             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
337 }
338
339 static HRESULT WINAPI RegExp_get_Pattern(IRegExp *iface, BSTR *pPattern)
340 {
341     RegExp2 *This = impl_from_IRegExp(iface);
342     return IRegExp2_get_Pattern(&This->IRegExp2_iface, pPattern);
343 }
344
345 static HRESULT WINAPI RegExp_put_Pattern(IRegExp *iface, BSTR pPattern)
346 {
347     RegExp2 *This = impl_from_IRegExp(iface);
348     return IRegExp2_put_Pattern(&This->IRegExp2_iface, pPattern);
349 }
350
351 static HRESULT WINAPI RegExp_get_IgnoreCase(IRegExp *iface, VARIANT_BOOL *pIgnoreCase)
352 {
353     RegExp2 *This = impl_from_IRegExp(iface);
354     return IRegExp2_get_IgnoreCase(&This->IRegExp2_iface, pIgnoreCase);
355 }
356
357 static HRESULT WINAPI RegExp_put_IgnoreCase(IRegExp *iface, VARIANT_BOOL pIgnoreCase)
358 {
359     RegExp2 *This = impl_from_IRegExp(iface);
360     return IRegExp2_put_IgnoreCase(&This->IRegExp2_iface, pIgnoreCase);
361 }
362
363 static HRESULT WINAPI RegExp_get_Global(IRegExp *iface, VARIANT_BOOL *pGlobal)
364 {
365     RegExp2 *This = impl_from_IRegExp(iface);
366     return IRegExp2_get_Global(&This->IRegExp2_iface, pGlobal);
367 }
368
369 static HRESULT WINAPI RegExp_put_Global(IRegExp *iface, VARIANT_BOOL pGlobal)
370 {
371     RegExp2 *This = impl_from_IRegExp(iface);
372     return IRegExp2_put_Global(&This->IRegExp2_iface, pGlobal);
373 }
374
375 static HRESULT WINAPI RegExp_Execute(IRegExp *iface,
376         BSTR sourceString, IDispatch **ppMatches)
377 {
378     RegExp2 *This = impl_from_IRegExp(iface);
379     return IRegExp2_Execute(&This->IRegExp2_iface, sourceString, ppMatches);
380 }
381
382 static HRESULT WINAPI RegExp_Test(IRegExp *iface, BSTR sourceString, VARIANT_BOOL *pMatch)
383 {
384     RegExp2 *This = impl_from_IRegExp(iface);
385     return IRegExp2_Test(&This->IRegExp2_iface, sourceString, pMatch);
386 }
387
388 static HRESULT WINAPI RegExp_Replace(IRegExp *iface, BSTR sourceString,
389         BSTR replaceString, BSTR *pDestString)
390 {
391     RegExp2 *This = impl_from_IRegExp(iface);
392     VARIANT replace;
393
394     V_VT(&replace) = VT_BSTR;
395     V_BSTR(&replace) = replaceString;
396     return IRegExp2_Replace(&This->IRegExp2_iface, sourceString, replace, pDestString);
397 }
398
399 static IRegExpVtbl RegExpVtbl = {
400     RegExp_QueryInterface,
401     RegExp_AddRef,
402     RegExp_Release,
403     RegExp_GetTypeInfoCount,
404     RegExp_GetTypeInfo,
405     RegExp_GetIDsOfNames,
406     RegExp_Invoke,
407     RegExp_get_Pattern,
408     RegExp_put_Pattern,
409     RegExp_get_IgnoreCase,
410     RegExp_put_IgnoreCase,
411     RegExp_get_Global,
412     RegExp_put_Global,
413     RegExp_Execute,
414     RegExp_Test,
415     RegExp_Replace
416 };
417
418 HRESULT WINAPI VBScriptRegExpFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, REFIID riid, void **ppv)
419 {
420     RegExp2 *ret;
421     HRESULT hres;
422
423     TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv);
424
425     hres = init_regexp_typeinfo(RegExp2_tid);
426     if(FAILED(hres))
427         return hres;
428
429     ret = heap_alloc_zero(sizeof(*ret));
430     if(!ret)
431         return E_OUTOFMEMORY;
432
433     ret->IRegExp2_iface.lpVtbl = &RegExp2Vtbl;
434     ret->IRegExp_iface.lpVtbl = &RegExpVtbl;
435
436     ret->ref = 1;
437
438     hres = IRegExp2_QueryInterface(&ret->IRegExp2_iface, riid, ppv);
439     IRegExp2_Release(&ret->IRegExp2_iface);
440     return hres;
441 }
442
443 void release_regexp_typelib(void)
444 {
445     DWORD i;
446
447     for(i=0; i<REGEXP_LAST_tid; i++) {
448         if(typeinfos[i])
449             ITypeInfo_Release(typeinfos[i]);
450     }
451     if(typelib)
452         ITypeLib_Release(typelib);
453 }