xref: /reactos/dll/win32/vbscript/vbregexp.c (revision 9a0ddc13)
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 "regexp.h"
21 #include "vbsregexp55.h"
22 
23 #include "wine/debug.h"
24 
25 WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
26 
27 #define REGEXP_TID_LIST \
28     XDIID(RegExp2), \
29     XDIID(Match2), \
30     XDIID(MatchCollection2), \
31     XDIID(SubMatches)
32 
33 typedef enum {
34 #define XDIID(iface) iface ## _tid
35     REGEXP_TID_LIST,
36 #undef XDIID
37     REGEXP_LAST_tid
38 } regexp_tid_t;
39 
40 static REFIID tid_ids[] = {
41 #define XDIID(iface) &IID_I ## iface
42     REGEXP_TID_LIST
43 #undef XDIID
44 };
45 
46 static ITypeLib *typelib;
47 static ITypeInfo *typeinfos[REGEXP_LAST_tid];
48 
init_regexp_typeinfo(regexp_tid_t tid)49 static HRESULT init_regexp_typeinfo(regexp_tid_t tid)
50 {
51     HRESULT hres;
52 
53     if(!typelib) {
54         static const WCHAR vbscript_dll3W[] = {'v','b','s','c','r','i','p','t','.','d','l','l','\\','3',0};
55         ITypeLib *tl;
56 
57         hres = LoadTypeLib(vbscript_dll3W, &tl);
58         if(FAILED(hres)) {
59             ERR("LoadRegTypeLib failed: %08x\n", hres);
60             return hres;
61         }
62 
63         if(InterlockedCompareExchangePointer((void**)&typelib, tl, NULL))
64             ITypeLib_Release(tl);
65     }
66 
67     if(!typeinfos[tid]) {
68         ITypeInfo *ti;
69 
70         hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
71         if(FAILED(hres)) {
72             ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hres);
73             return hres;
74         }
75 
76         if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
77             ITypeInfo_Release(ti);
78     }
79 
80     return S_OK;
81 }
82 
83 struct SubMatches {
84     ISubMatches ISubMatches_iface;
85 
86     LONG ref;
87 
88     WCHAR *match;
89     match_state_t *result;
90 };
91 
92 typedef struct Match2 {
93     IMatch2 IMatch2_iface;
94     IMatch IMatch_iface;
95 
96     LONG ref;
97 
98     DWORD index;
99     SubMatches *sub_matches;
100 } Match2;
101 
102 typedef struct MatchCollectionEnum {
103     IEnumVARIANT IEnumVARIANT_iface;
104 
105     LONG ref;
106 
107     IMatchCollection2 *mc;
108     LONG pos;
109     LONG count;
110 } MatchCollectionEnum;
111 
112 typedef struct MatchCollection2 {
113     IMatchCollection2 IMatchCollection2_iface;
114     IMatchCollection IMatchCollection_iface;
115 
116     LONG ref;
117 
118     IMatch2 **matches;
119     DWORD count;
120     DWORD size;
121 } MatchCollection2;
122 
123 typedef struct RegExp2 {
124     IRegExp2 IRegExp2_iface;
125     IRegExp IRegExp_iface;
126 
127     LONG ref;
128 
129     WCHAR *pattern;
130     regexp_t *regexp;
131     heap_pool_t pool;
132     WORD flags;
133 } RegExp2;
134 
impl_from_ISubMatches(ISubMatches * iface)135 static inline SubMatches* impl_from_ISubMatches(ISubMatches *iface)
136 {
137     return CONTAINING_RECORD(iface, SubMatches, ISubMatches_iface);
138 }
139 
SubMatches_QueryInterface(ISubMatches * iface,REFIID riid,void ** ppv)140 static HRESULT WINAPI SubMatches_QueryInterface(
141         ISubMatches *iface, REFIID riid, void **ppv)
142 {
143     SubMatches *This = impl_from_ISubMatches(iface);
144 
145     if(IsEqualGUID(riid, &IID_IUnknown)) {
146         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
147         *ppv = &This->ISubMatches_iface;
148     }else if(IsEqualGUID(riid, &IID_IDispatch)) {
149         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
150         *ppv = &This->ISubMatches_iface;
151     }else if(IsEqualGUID(riid, &IID_ISubMatches)) {
152         TRACE("(%p)->(IID_ISubMatches %p)\n", This, ppv);
153         *ppv = &This->ISubMatches_iface;
154     }else if(IsEqualGUID(riid, &IID_IDispatchEx)) {
155         TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
156         *ppv = NULL;
157         return E_NOINTERFACE;
158     }else {
159         FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
160         *ppv = NULL;
161         return E_NOINTERFACE;
162     }
163 
164     IUnknown_AddRef((IUnknown*)*ppv);
165     return S_OK;
166 }
167 
SubMatches_AddRef(ISubMatches * iface)168 static ULONG WINAPI SubMatches_AddRef(ISubMatches *iface)
169 {
170     SubMatches *This = impl_from_ISubMatches(iface);
171     LONG ref = InterlockedIncrement(&This->ref);
172 
173     TRACE("(%p) ref=%d\n", This, ref);
174 
175     return ref;
176 }
177 
SubMatches_Release(ISubMatches * iface)178 static ULONG WINAPI SubMatches_Release(ISubMatches *iface)
179 {
180     SubMatches *This = impl_from_ISubMatches(iface);
181     LONG ref = InterlockedDecrement(&This->ref);
182 
183     TRACE("(%p) ref=%d\n", This, ref);
184 
185     if(!ref) {
186         heap_free(This->match);
187         heap_free(This->result);
188         heap_free(This);
189     }
190 
191     return ref;
192 }
193 
SubMatches_GetTypeInfoCount(ISubMatches * iface,UINT * pctinfo)194 static HRESULT WINAPI SubMatches_GetTypeInfoCount(ISubMatches *iface, UINT *pctinfo)
195 {
196     SubMatches *This = impl_from_ISubMatches(iface);
197 
198     TRACE("(%p)->(%p)\n", This, pctinfo);
199 
200     *pctinfo = 1;
201     return S_OK;
202 }
203 
SubMatches_GetTypeInfo(ISubMatches * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)204 static HRESULT WINAPI SubMatches_GetTypeInfo(ISubMatches *iface,
205         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
206 {
207     SubMatches *This = impl_from_ISubMatches(iface);
208     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
209     return E_NOTIMPL;
210 }
211 
SubMatches_GetIDsOfNames(ISubMatches * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)212 static HRESULT WINAPI SubMatches_GetIDsOfNames(ISubMatches *iface,
213         REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
214 {
215     SubMatches *This = impl_from_ISubMatches(iface);
216 
217     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
218             rgszNames, cNames, lcid, rgDispId);
219 
220     return ITypeInfo_GetIDsOfNames(typeinfos[SubMatches_tid], rgszNames, cNames, rgDispId);
221 }
222 
SubMatches_Invoke(ISubMatches * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)223 static HRESULT WINAPI SubMatches_Invoke(ISubMatches *iface, DISPID dispIdMember,
224         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
225                         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
226 {
227     SubMatches *This = impl_from_ISubMatches(iface);
228 
229     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
230             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
231 
232     return ITypeInfo_Invoke(typeinfos[SubMatches_tid], iface, dispIdMember, wFlags,
233             pDispParams, pVarResult, pExcepInfo, puArgErr);
234 }
235 
SubMatches_get_Item(ISubMatches * iface,LONG index,VARIANT * pSubMatch)236 static HRESULT WINAPI SubMatches_get_Item(ISubMatches *iface,
237         LONG index, VARIANT *pSubMatch)
238 {
239     SubMatches *This = impl_from_ISubMatches(iface);
240 
241     TRACE("(%p)->(%d %p)\n", This, index, pSubMatch);
242 
243     if(!pSubMatch)
244         return E_POINTER;
245 
246     if(!This->result || index<0 || index>=This->result->paren_count)
247         return E_INVALIDARG;
248 
249     if(This->result->parens[index].index == -1) {
250         V_VT(pSubMatch) = VT_EMPTY;
251     }else {
252         V_VT(pSubMatch) = VT_BSTR;
253         V_BSTR(pSubMatch) = SysAllocStringLen(
254                 This->match+This->result->parens[index].index,
255                 This->result->parens[index].length);
256 
257         if(!V_BSTR(pSubMatch))
258             return E_OUTOFMEMORY;
259     }
260 
261     return S_OK;
262 }
263 
SubMatches_get_Count(ISubMatches * iface,LONG * pCount)264 static HRESULT WINAPI SubMatches_get_Count(ISubMatches *iface, LONG *pCount)
265 {
266     SubMatches *This = impl_from_ISubMatches(iface);
267 
268     TRACE("(%p)->(%p)\n", This, pCount);
269 
270     if(!pCount)
271         return E_POINTER;
272 
273     if(!This->result)
274         *pCount = 0;
275     else
276         *pCount = This->result->paren_count;
277     return S_OK;
278 }
279 
SubMatches_get__NewEnum(ISubMatches * iface,IUnknown ** ppEnum)280 static HRESULT WINAPI SubMatches_get__NewEnum(ISubMatches *iface, IUnknown **ppEnum)
281 {
282     SubMatches *This = impl_from_ISubMatches(iface);
283     FIXME("(%p)->(%p)\n", This, ppEnum);
284     return E_NOTIMPL;
285 }
286 
287 static const ISubMatchesVtbl SubMatchesVtbl = {
288     SubMatches_QueryInterface,
289     SubMatches_AddRef,
290     SubMatches_Release,
291     SubMatches_GetTypeInfoCount,
292     SubMatches_GetTypeInfo,
293     SubMatches_GetIDsOfNames,
294     SubMatches_Invoke,
295     SubMatches_get_Item,
296     SubMatches_get_Count,
297     SubMatches_get__NewEnum
298 };
299 
create_sub_matches(DWORD pos,match_state_t * result,SubMatches ** sub_matches)300 static HRESULT create_sub_matches(DWORD pos, match_state_t *result, SubMatches **sub_matches)
301 {
302     SubMatches *ret;
303     DWORD i;
304     HRESULT hres;
305 
306     hres = init_regexp_typeinfo(SubMatches_tid);
307     if(FAILED(hres))
308         return hres;
309 
310     ret = heap_alloc_zero(sizeof(*ret));
311     if(!ret)
312         return E_OUTOFMEMORY;
313 
314     ret->ISubMatches_iface.lpVtbl = &SubMatchesVtbl;
315 
316     ret->result = result;
317     if(result) {
318         ret->match = heap_alloc((result->match_len+1) * sizeof(WCHAR));
319         if(!ret->match) {
320             heap_free(ret);
321             return E_OUTOFMEMORY;
322         }
323         memcpy(ret->match, result->cp-result->match_len, result->match_len*sizeof(WCHAR));
324         ret->match[result->match_len] = 0;
325 
326         result->cp = NULL;
327         for(i=0; i<result->paren_count; i++)
328             if(result->parens[i].index != -1)
329                 result->parens[i].index -= pos;
330     }else {
331         ret->match = NULL;
332     }
333 
334     ret->ref = 1;
335     *sub_matches = ret;
336     return hres;
337 }
338 
impl_from_IMatch2(IMatch2 * iface)339 static inline Match2* impl_from_IMatch2(IMatch2 *iface)
340 {
341     return CONTAINING_RECORD(iface, Match2, IMatch2_iface);
342 }
343 
Match2_QueryInterface(IMatch2 * iface,REFIID riid,void ** ppv)344 static HRESULT WINAPI Match2_QueryInterface(
345         IMatch2 *iface, REFIID riid, void **ppv)
346 {
347     Match2 *This = impl_from_IMatch2(iface);
348 
349     if(IsEqualGUID(riid, &IID_IUnknown)) {
350         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
351         *ppv = &This->IMatch2_iface;
352     }else if(IsEqualGUID(riid, &IID_IDispatch)) {
353         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
354         *ppv = &This->IMatch2_iface;
355     }else if(IsEqualGUID(riid, &IID_IMatch2)) {
356         TRACE("(%p)->(IID_IMatch2 %p)\n", This, ppv);
357         *ppv = &This->IMatch2_iface;
358     }else if(IsEqualGUID(riid, &IID_IMatch)) {
359         TRACE("(%p)->(IID_IMatch %p)\n", This, ppv);
360         *ppv = &This->IMatch_iface;
361     }else if(IsEqualGUID(riid, &IID_IDispatchEx)) {
362         TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
363         *ppv = NULL;
364         return E_NOINTERFACE;
365     }else {
366         FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
367         *ppv = NULL;
368         return E_NOINTERFACE;
369     }
370 
371     IUnknown_AddRef((IUnknown*)*ppv);
372     return S_OK;
373 }
374 
Match2_AddRef(IMatch2 * iface)375 static ULONG WINAPI Match2_AddRef(IMatch2 *iface)
376 {
377     Match2 *This = impl_from_IMatch2(iface);
378     LONG ref = InterlockedIncrement(&This->ref);
379 
380     TRACE("(%p) ref=%d\n", This, ref);
381 
382     return ref;
383 }
384 
Match2_Release(IMatch2 * iface)385 static ULONG WINAPI Match2_Release(IMatch2 *iface)
386 {
387     Match2 *This = impl_from_IMatch2(iface);
388     LONG ref = InterlockedDecrement(&This->ref);
389 
390     TRACE("(%p) ref=%d\n", This, ref);
391 
392     if(!ref) {
393         ISubMatches_Release(&This->sub_matches->ISubMatches_iface);
394         heap_free(This);
395     }
396 
397     return ref;
398 }
399 
Match2_GetTypeInfoCount(IMatch2 * iface,UINT * pctinfo)400 static HRESULT WINAPI Match2_GetTypeInfoCount(IMatch2 *iface, UINT *pctinfo)
401 {
402     Match2 *This = impl_from_IMatch2(iface);
403 
404     TRACE("(%p)->(%p)\n", This, pctinfo);
405 
406     *pctinfo = 1;
407     return S_OK;
408 }
409 
Match2_GetTypeInfo(IMatch2 * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)410 static HRESULT WINAPI Match2_GetTypeInfo(IMatch2 *iface,
411         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
412 {
413     Match2 *This = impl_from_IMatch2(iface);
414     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
415     return E_NOTIMPL;
416 }
417 
Match2_GetIDsOfNames(IMatch2 * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)418 static HRESULT WINAPI Match2_GetIDsOfNames(IMatch2 *iface,
419         REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
420 {
421     Match2 *This = impl_from_IMatch2(iface);
422 
423     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
424             rgszNames, cNames, lcid, rgDispId);
425 
426     return ITypeInfo_GetIDsOfNames(typeinfos[Match2_tid], rgszNames, cNames, rgDispId);
427 }
428 
Match2_Invoke(IMatch2 * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)429 static HRESULT WINAPI Match2_Invoke(IMatch2 *iface, DISPID dispIdMember,
430         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
431                 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
432 {
433     Match2 *This = impl_from_IMatch2(iface);
434 
435     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
436             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
437 
438     return ITypeInfo_Invoke(typeinfos[Match2_tid], iface, dispIdMember, wFlags,
439             pDispParams, pVarResult, pExcepInfo, puArgErr);
440 }
441 
Match2_get_Value(IMatch2 * iface,BSTR * pValue)442 static HRESULT WINAPI Match2_get_Value(IMatch2 *iface, BSTR *pValue)
443 {
444     Match2 *This = impl_from_IMatch2(iface);
445 
446     TRACE("(%p)->(%p)\n", This, pValue);
447 
448     if(!pValue)
449         return E_POINTER;
450 
451     if(!This->sub_matches->match) {
452         *pValue = NULL;
453         return S_OK;
454     }
455 
456     *pValue = SysAllocString(This->sub_matches->match);
457     return *pValue ? S_OK : E_OUTOFMEMORY;
458 }
459 
Match2_get_FirstIndex(IMatch2 * iface,LONG * pFirstIndex)460 static HRESULT WINAPI Match2_get_FirstIndex(IMatch2 *iface, LONG *pFirstIndex)
461 {
462     Match2 *This = impl_from_IMatch2(iface);
463 
464     TRACE("(%p)->(%p)\n", This, pFirstIndex);
465 
466     if(!pFirstIndex)
467         return E_POINTER;
468 
469     *pFirstIndex = This->index;
470     return S_OK;
471 }
472 
Match2_get_Length(IMatch2 * iface,LONG * pLength)473 static HRESULT WINAPI Match2_get_Length(IMatch2 *iface, LONG *pLength)
474 {
475     Match2 *This = impl_from_IMatch2(iface);
476 
477     TRACE("(%p)->(%p)\n", This, pLength);
478 
479     if(!pLength)
480         return E_POINTER;
481 
482     if(This->sub_matches->result)
483         *pLength = This->sub_matches->result->match_len;
484     else
485         *pLength = 0;
486     return S_OK;
487 }
488 
Match2_get_SubMatches(IMatch2 * iface,IDispatch ** ppSubMatches)489 static HRESULT WINAPI Match2_get_SubMatches(IMatch2 *iface, IDispatch **ppSubMatches)
490 {
491     Match2 *This = impl_from_IMatch2(iface);
492 
493     TRACE("(%p)->(%p)\n", This, ppSubMatches);
494 
495     if(!ppSubMatches)
496         return E_POINTER;
497 
498     *ppSubMatches = (IDispatch*)&This->sub_matches->ISubMatches_iface;
499     ISubMatches_AddRef(&This->sub_matches->ISubMatches_iface);
500     return S_OK;
501 }
502 
503 static const IMatch2Vtbl Match2Vtbl = {
504     Match2_QueryInterface,
505     Match2_AddRef,
506     Match2_Release,
507     Match2_GetTypeInfoCount,
508     Match2_GetTypeInfo,
509     Match2_GetIDsOfNames,
510     Match2_Invoke,
511     Match2_get_Value,
512     Match2_get_FirstIndex,
513     Match2_get_Length,
514     Match2_get_SubMatches
515 };
516 
impl_from_IMatch(IMatch * iface)517 static inline Match2 *impl_from_IMatch(IMatch *iface)
518 {
519     return CONTAINING_RECORD(iface, Match2, IMatch_iface);
520 }
521 
Match_QueryInterface(IMatch * iface,REFIID riid,void ** ppv)522 static HRESULT WINAPI Match_QueryInterface(IMatch *iface, REFIID riid, void **ppv)
523 {
524     Match2 *This = impl_from_IMatch(iface);
525     return IMatch2_QueryInterface(&This->IMatch2_iface, riid, ppv);
526 }
527 
Match_AddRef(IMatch * iface)528 static ULONG WINAPI Match_AddRef(IMatch *iface)
529 {
530     Match2 *This = impl_from_IMatch(iface);
531     return IMatch2_AddRef(&This->IMatch2_iface);
532 }
533 
Match_Release(IMatch * iface)534 static ULONG WINAPI Match_Release(IMatch *iface)
535 {
536     Match2 *This = impl_from_IMatch(iface);
537     return IMatch2_Release(&This->IMatch2_iface);
538 }
539 
Match_GetTypeInfoCount(IMatch * iface,UINT * pctinfo)540 static HRESULT WINAPI Match_GetTypeInfoCount(IMatch *iface, UINT *pctinfo)
541 {
542     Match2 *This = impl_from_IMatch(iface);
543     return IMatch2_GetTypeInfoCount(&This->IMatch2_iface, pctinfo);
544 }
545 
Match_GetTypeInfo(IMatch * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)546 static HRESULT WINAPI Match_GetTypeInfo(IMatch *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
547 {
548     Match2 *This = impl_from_IMatch(iface);
549     return IMatch2_GetTypeInfo(&This->IMatch2_iface, iTInfo, lcid, ppTInfo);
550 }
551 
Match_GetIDsOfNames(IMatch * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)552 static HRESULT WINAPI Match_GetIDsOfNames(IMatch *iface, REFIID riid,
553         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
554 {
555     Match2 *This = impl_from_IMatch(iface);
556     return IMatch2_GetIDsOfNames(&This->IMatch2_iface, riid, rgszNames, cNames, lcid, rgDispId);
557 }
558 
Match_Invoke(IMatch * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)559 static HRESULT WINAPI Match_Invoke(IMatch *iface, DISPID dispIdMember,
560         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
561         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
562 {
563     Match2 *This = impl_from_IMatch(iface);
564     return IMatch2_Invoke(&This->IMatch2_iface, dispIdMember, riid, lcid,
565             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
566 }
567 
Match_get_Value(IMatch * iface,BSTR * pValue)568 static HRESULT WINAPI Match_get_Value(IMatch *iface, BSTR *pValue)
569 {
570     Match2 *This = impl_from_IMatch(iface);
571     return IMatch2_get_Value(&This->IMatch2_iface, pValue);
572 }
573 
Match_get_FirstIndex(IMatch * iface,LONG * pFirstIndex)574 static HRESULT WINAPI Match_get_FirstIndex(IMatch *iface, LONG *pFirstIndex)
575 {
576     Match2 *This = impl_from_IMatch(iface);
577     return IMatch2_get_FirstIndex(&This->IMatch2_iface, pFirstIndex);
578 }
579 
Match_get_Length(IMatch * iface,LONG * pLength)580 static HRESULT WINAPI Match_get_Length(IMatch *iface, LONG *pLength)
581 {
582     Match2 *This = impl_from_IMatch(iface);
583     return IMatch2_get_Length(&This->IMatch2_iface, pLength);
584 }
585 
586 static IMatchVtbl MatchVtbl = {
587     Match_QueryInterface,
588     Match_AddRef,
589     Match_Release,
590     Match_GetTypeInfoCount,
591     Match_GetTypeInfo,
592     Match_GetIDsOfNames,
593     Match_Invoke,
594     Match_get_Value,
595     Match_get_FirstIndex,
596     Match_get_Length
597 };
598 
create_match2(DWORD pos,match_state_t ** result,IMatch2 ** match)599 static HRESULT create_match2(DWORD pos, match_state_t **result, IMatch2 **match)
600 {
601     Match2 *ret;
602     HRESULT hres;
603 
604     hres = init_regexp_typeinfo(Match2_tid);
605     if(FAILED(hres))
606         return hres;
607 
608     ret = heap_alloc_zero(sizeof(*ret));
609     if(!ret)
610         return E_OUTOFMEMORY;
611 
612     ret->index = pos;
613     hres = create_sub_matches(pos, result ? *result : NULL, &ret->sub_matches);
614     if(FAILED(hres)) {
615         heap_free(ret);
616         return hres;
617     }
618     if(result)
619         *result = NULL;
620 
621     ret->IMatch2_iface.lpVtbl = &Match2Vtbl;
622     ret->IMatch_iface.lpVtbl = &MatchVtbl;
623 
624     ret->ref = 1;
625     *match = &ret->IMatch2_iface;
626     return hres;
627 }
628 
impl_from_IMatchCollectionEnum(IEnumVARIANT * iface)629 static inline MatchCollectionEnum* impl_from_IMatchCollectionEnum(IEnumVARIANT *iface)
630 {
631     return CONTAINING_RECORD(iface, MatchCollectionEnum, IEnumVARIANT_iface);
632 }
633 
MatchCollectionEnum_QueryInterface(IEnumVARIANT * iface,REFIID riid,void ** ppv)634 static HRESULT WINAPI MatchCollectionEnum_QueryInterface(
635         IEnumVARIANT *iface, REFIID riid, void **ppv)
636 {
637     MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
638 
639     if(IsEqualGUID(riid, &IID_IUnknown)) {
640         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
641         *ppv = &This->IEnumVARIANT_iface;
642     }else if(IsEqualGUID(riid, &IID_IEnumVARIANT)) {
643         TRACE("(%p)->(IID_IEnumVARIANT %p)\n", This, ppv);
644         *ppv = &This->IEnumVARIANT_iface;
645     }else {
646         FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
647         *ppv = NULL;
648         return E_NOINTERFACE;
649     }
650 
651     IUnknown_AddRef((IUnknown*)*ppv);
652     return S_OK;
653 }
654 
MatchCollectionEnum_AddRef(IEnumVARIANT * iface)655 static ULONG WINAPI MatchCollectionEnum_AddRef(IEnumVARIANT *iface)
656 {
657     MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
658     LONG ref = InterlockedIncrement(&This->ref);
659 
660     TRACE("(%p) ref=%d\n", This, ref);
661 
662     return ref;
663 }
664 
MatchCollectionEnum_Release(IEnumVARIANT * iface)665 static ULONG WINAPI MatchCollectionEnum_Release(IEnumVARIANT *iface)
666 {
667     MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
668     LONG ref = InterlockedDecrement(&This->ref);
669 
670     TRACE("(%p) ref=%d\n", This, ref);
671 
672     if(!ref) {
673         IMatchCollection2_Release(This->mc);
674         heap_free(This);
675     }
676 
677     return ref;
678 }
679 
MatchCollectionEnum_Next(IEnumVARIANT * iface,ULONG celt,VARIANT * rgVar,ULONG * pCeltFetched)680 static HRESULT WINAPI MatchCollectionEnum_Next(IEnumVARIANT *iface,
681         ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
682 {
683     MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
684     DWORD i;
685     HRESULT hres = S_OK;
686 
687     TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched);
688 
689     if(This->pos>=This->count) {
690         if(pCeltFetched)
691             *pCeltFetched = 0;
692         return S_FALSE;
693     }
694 
695     for(i=0; i<celt && This->pos+i<This->count; i++) {
696         V_VT(rgVar+i) = VT_DISPATCH;
697         hres = IMatchCollection2_get_Item(This->mc, This->pos+i, &V_DISPATCH(rgVar+i));
698         if(FAILED(hres))
699             break;
700     }
701     if(FAILED(hres)) {
702         while(i--)
703             VariantClear(rgVar+i);
704         return hres;
705     }
706 
707     if(pCeltFetched)
708         *pCeltFetched = i;
709     This->pos += i;
710     return S_OK;
711 }
712 
MatchCollectionEnum_Skip(IEnumVARIANT * iface,ULONG celt)713 static HRESULT WINAPI MatchCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt)
714 {
715     MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
716 
717     TRACE("(%p)->(%u)\n", This, celt);
718 
719     if(This->pos+celt <= This->count)
720         This->pos += celt;
721     else
722         This->pos = This->count;
723     return S_OK;
724 }
725 
MatchCollectionEnum_Reset(IEnumVARIANT * iface)726 static HRESULT WINAPI MatchCollectionEnum_Reset(IEnumVARIANT *iface)
727 {
728     MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
729 
730     TRACE("(%p)\n", This);
731 
732     This->pos = 0;
733     return S_OK;
734 }
735 
MatchCollectionEnum_Clone(IEnumVARIANT * iface,IEnumVARIANT ** ppEnum)736 static HRESULT WINAPI MatchCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
737 {
738     MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
739     FIXME("(%p)->(%p)\n", This, ppEnum);
740     return E_NOTIMPL;
741 }
742 
743 static const IEnumVARIANTVtbl MatchCollectionEnum_Vtbl = {
744     MatchCollectionEnum_QueryInterface,
745     MatchCollectionEnum_AddRef,
746     MatchCollectionEnum_Release,
747     MatchCollectionEnum_Next,
748     MatchCollectionEnum_Skip,
749     MatchCollectionEnum_Reset,
750     MatchCollectionEnum_Clone
751 };
752 
create_enum_variant_mc2(IMatchCollection2 * mc,ULONG pos,IEnumVARIANT ** enum_variant)753 static HRESULT create_enum_variant_mc2(IMatchCollection2 *mc, ULONG pos, IEnumVARIANT **enum_variant)
754 {
755     MatchCollectionEnum *ret;
756 
757     ret = heap_alloc_zero(sizeof(*ret));
758     if(!ret)
759         return E_OUTOFMEMORY;
760 
761     ret->IEnumVARIANT_iface.lpVtbl = &MatchCollectionEnum_Vtbl;
762     ret->ref = 1;
763     ret->pos = pos;
764     IMatchCollection2_get_Count(mc, &ret->count);
765     ret->mc = mc;
766     IMatchCollection2_AddRef(mc);
767 
768     *enum_variant = &ret->IEnumVARIANT_iface;
769     return S_OK;
770 }
771 
impl_from_IMatchCollection2(IMatchCollection2 * iface)772 static inline MatchCollection2* impl_from_IMatchCollection2(IMatchCollection2 *iface)
773 {
774     return CONTAINING_RECORD(iface, MatchCollection2, IMatchCollection2_iface);
775 }
776 
MatchCollection2_QueryInterface(IMatchCollection2 * iface,REFIID riid,void ** ppv)777 static HRESULT WINAPI MatchCollection2_QueryInterface(
778         IMatchCollection2 *iface, REFIID riid, void **ppv)
779 {
780     MatchCollection2 *This = impl_from_IMatchCollection2(iface);
781 
782     if(IsEqualGUID(riid, &IID_IUnknown)) {
783         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
784         *ppv = &This->IMatchCollection2_iface;
785     }else if(IsEqualGUID(riid, &IID_IDispatch)) {
786         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
787         *ppv = &This->IMatchCollection2_iface;
788     }else if(IsEqualGUID(riid, &IID_IMatchCollection2)) {
789         TRACE("(%p)->(IID_IMatchCollection2 %p)\n", This, ppv);
790         *ppv = &This->IMatchCollection2_iface;
791     }else if(IsEqualGUID(riid, &IID_IMatchCollection)) {
792         TRACE("(%p)->(IID_IMatchCollection %p)\n", This, ppv);
793         *ppv = &This->IMatchCollection_iface;
794     }else if(IsEqualGUID(riid, &IID_IDispatchEx)) {
795         TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
796         *ppv = NULL;
797         return E_NOINTERFACE;
798     }else {
799         FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
800         *ppv = NULL;
801         return E_NOINTERFACE;
802     }
803 
804     IUnknown_AddRef((IUnknown*)*ppv);
805     return S_OK;
806 }
807 
MatchCollection2_AddRef(IMatchCollection2 * iface)808 static ULONG WINAPI MatchCollection2_AddRef(IMatchCollection2 *iface)
809 {
810     MatchCollection2 *This = impl_from_IMatchCollection2(iface);
811     LONG ref = InterlockedIncrement(&This->ref);
812 
813     TRACE("(%p) ref=%d\n", This, ref);
814 
815     return ref;
816 }
817 
MatchCollection2_Release(IMatchCollection2 * iface)818 static ULONG WINAPI MatchCollection2_Release(IMatchCollection2 *iface)
819 {
820     MatchCollection2 *This = impl_from_IMatchCollection2(iface);
821     LONG ref = InterlockedDecrement(&This->ref);
822 
823     TRACE("(%p) ref=%d\n", This, ref);
824 
825     if(!ref) {
826         DWORD i;
827 
828         for(i=0; i<This->count; i++)
829             IMatch2_Release(This->matches[i]);
830         heap_free(This->matches);
831 
832         heap_free(This);
833     }
834 
835     return ref;
836 }
837 
MatchCollection2_GetTypeInfoCount(IMatchCollection2 * iface,UINT * pctinfo)838 static HRESULT WINAPI MatchCollection2_GetTypeInfoCount(IMatchCollection2 *iface, UINT *pctinfo)
839 {
840     MatchCollection2 *This = impl_from_IMatchCollection2(iface);
841 
842     TRACE("(%p)->(%p)\n", This, pctinfo);
843 
844     *pctinfo = 1;
845     return S_OK;
846 }
847 
MatchCollection2_GetTypeInfo(IMatchCollection2 * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)848 static HRESULT WINAPI MatchCollection2_GetTypeInfo(IMatchCollection2 *iface,
849         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
850 {
851     MatchCollection2 *This = impl_from_IMatchCollection2(iface);
852     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
853     return E_NOTIMPL;
854 }
855 
MatchCollection2_GetIDsOfNames(IMatchCollection2 * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)856 static HRESULT WINAPI MatchCollection2_GetIDsOfNames(IMatchCollection2 *iface,
857         REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
858 {
859     MatchCollection2 *This = impl_from_IMatchCollection2(iface);
860 
861     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
862             rgszNames, cNames, lcid, rgDispId);
863 
864     return ITypeInfo_GetIDsOfNames(typeinfos[MatchCollection2_tid], rgszNames, cNames, rgDispId);
865 }
866 
MatchCollection2_Invoke(IMatchCollection2 * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)867 static HRESULT WINAPI MatchCollection2_Invoke(IMatchCollection2 *iface, DISPID dispIdMember,
868         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
869         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
870 {
871     MatchCollection2 *This = impl_from_IMatchCollection2(iface);
872 
873     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
874             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
875 
876     return ITypeInfo_Invoke(typeinfos[MatchCollection2_tid], iface, dispIdMember, wFlags,
877             pDispParams, pVarResult, pExcepInfo, puArgErr);
878 }
879 
MatchCollection2_get_Item(IMatchCollection2 * iface,LONG index,IDispatch ** ppMatch)880 static HRESULT WINAPI MatchCollection2_get_Item(IMatchCollection2 *iface,
881         LONG index, IDispatch **ppMatch)
882 {
883     MatchCollection2 *This = impl_from_IMatchCollection2(iface);
884 
885     TRACE("(%p)->()\n", This);
886 
887     if(!ppMatch)
888         return E_POINTER;
889 
890     if(index<0 || index>=This->count)
891         return E_INVALIDARG;
892 
893     *ppMatch = (IDispatch*)This->matches[index];
894     IMatch2_AddRef(This->matches[index]);
895     return S_OK;
896 }
897 
MatchCollection2_get_Count(IMatchCollection2 * iface,LONG * pCount)898 static HRESULT WINAPI MatchCollection2_get_Count(IMatchCollection2 *iface, LONG *pCount)
899 {
900     MatchCollection2 *This = impl_from_IMatchCollection2(iface);
901 
902     TRACE("(%p)->()\n", This);
903 
904     if(!pCount)
905         return E_POINTER;
906 
907     *pCount = This->count;
908     return S_OK;
909 }
910 
MatchCollection2_get__NewEnum(IMatchCollection2 * iface,IUnknown ** ppEnum)911 static HRESULT WINAPI MatchCollection2_get__NewEnum(IMatchCollection2 *iface, IUnknown **ppEnum)
912 {
913     MatchCollection2 *This = impl_from_IMatchCollection2(iface);
914 
915     TRACE("(%p)->(%p)\n", This, ppEnum);
916 
917     if(!ppEnum)
918         return E_POINTER;
919 
920     return create_enum_variant_mc2(&This->IMatchCollection2_iface, 0, (IEnumVARIANT**)ppEnum);
921 }
922 
923 static const IMatchCollection2Vtbl MatchCollection2Vtbl = {
924     MatchCollection2_QueryInterface,
925     MatchCollection2_AddRef,
926     MatchCollection2_Release,
927     MatchCollection2_GetTypeInfoCount,
928     MatchCollection2_GetTypeInfo,
929     MatchCollection2_GetIDsOfNames,
930     MatchCollection2_Invoke,
931     MatchCollection2_get_Item,
932     MatchCollection2_get_Count,
933     MatchCollection2_get__NewEnum
934 };
935 
impl_from_IMatchCollection(IMatchCollection * iface)936 static inline MatchCollection2 *impl_from_IMatchCollection(IMatchCollection *iface)
937 {
938     return CONTAINING_RECORD(iface, MatchCollection2, IMatchCollection_iface);
939 }
940 
MatchCollection_QueryInterface(IMatchCollection * iface,REFIID riid,void ** ppv)941 static HRESULT WINAPI MatchCollection_QueryInterface(IMatchCollection *iface, REFIID riid, void **ppv)
942 {
943     MatchCollection2 *This = impl_from_IMatchCollection(iface);
944     return IMatchCollection2_QueryInterface(&This->IMatchCollection2_iface, riid, ppv);
945 }
946 
MatchCollection_AddRef(IMatchCollection * iface)947 static ULONG WINAPI MatchCollection_AddRef(IMatchCollection *iface)
948 {
949     MatchCollection2 *This = impl_from_IMatchCollection(iface);
950     return IMatchCollection2_AddRef(&This->IMatchCollection2_iface);
951 }
952 
MatchCollection_Release(IMatchCollection * iface)953 static ULONG WINAPI MatchCollection_Release(IMatchCollection *iface)
954 {
955     MatchCollection2 *This = impl_from_IMatchCollection(iface);
956     return IMatchCollection2_Release(&This->IMatchCollection2_iface);
957 }
958 
MatchCollection_GetTypeInfoCount(IMatchCollection * iface,UINT * pctinfo)959 static HRESULT WINAPI MatchCollection_GetTypeInfoCount(IMatchCollection *iface, UINT *pctinfo)
960 {
961     MatchCollection2 *This = impl_from_IMatchCollection(iface);
962     return IMatchCollection2_GetTypeInfoCount(&This->IMatchCollection2_iface, pctinfo);
963 }
964 
MatchCollection_GetTypeInfo(IMatchCollection * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)965 static HRESULT WINAPI MatchCollection_GetTypeInfo(IMatchCollection *iface,
966         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
967 {
968     MatchCollection2 *This = impl_from_IMatchCollection(iface);
969     return IMatchCollection2_GetTypeInfo(&This->IMatchCollection2_iface, iTInfo, lcid, ppTInfo);
970 }
971 
MatchCollection_GetIDsOfNames(IMatchCollection * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)972 static HRESULT WINAPI MatchCollection_GetIDsOfNames(IMatchCollection *iface, REFIID riid,
973         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
974 {
975     MatchCollection2 *This = impl_from_IMatchCollection(iface);
976     return IMatchCollection2_GetIDsOfNames(&This->IMatchCollection2_iface,
977             riid, rgszNames, cNames, lcid, rgDispId);
978 }
979 
MatchCollection_Invoke(IMatchCollection * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)980 static HRESULT WINAPI MatchCollection_Invoke(IMatchCollection *iface, DISPID dispIdMember,
981         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
982         EXCEPINFO *pExcepInfo, UINT *puArgErr)
983 {
984     MatchCollection2 *This = impl_from_IMatchCollection(iface);
985     return IMatchCollection2_Invoke(&This->IMatchCollection2_iface, dispIdMember,
986             riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
987 }
988 
MatchCollection_get_Item(IMatchCollection * iface,LONG index,IDispatch ** ppMatch)989 static HRESULT WINAPI MatchCollection_get_Item(IMatchCollection *iface, LONG index, IDispatch **ppMatch)
990 {
991     MatchCollection2 *This = impl_from_IMatchCollection(iface);
992     return IMatchCollection2_get_Item(&This->IMatchCollection2_iface, index, ppMatch);
993 }
994 
MatchCollection_get_Count(IMatchCollection * iface,LONG * pCount)995 static HRESULT WINAPI MatchCollection_get_Count(IMatchCollection *iface, LONG *pCount)
996 {
997     MatchCollection2 *This = impl_from_IMatchCollection(iface);
998     return IMatchCollection2_get_Count(&This->IMatchCollection2_iface, pCount);
999 }
1000 
MatchCollection_get__NewEnum(IMatchCollection * iface,IUnknown ** ppEnum)1001 static HRESULT WINAPI MatchCollection_get__NewEnum(IMatchCollection *iface, IUnknown **ppEnum)
1002 {
1003     MatchCollection2 *This = impl_from_IMatchCollection(iface);
1004     return IMatchCollection2_get__NewEnum(&This->IMatchCollection2_iface, ppEnum);
1005 }
1006 
1007 static const IMatchCollectionVtbl MatchCollectionVtbl = {
1008     MatchCollection_QueryInterface,
1009     MatchCollection_AddRef,
1010     MatchCollection_Release,
1011     MatchCollection_GetTypeInfoCount,
1012     MatchCollection_GetTypeInfo,
1013     MatchCollection_GetIDsOfNames,
1014     MatchCollection_Invoke,
1015     MatchCollection_get_Item,
1016     MatchCollection_get_Count,
1017     MatchCollection_get__NewEnum
1018 };
1019 
add_match(IMatchCollection2 * iface,IMatch2 * add)1020 static HRESULT add_match(IMatchCollection2 *iface, IMatch2 *add)
1021 {
1022     MatchCollection2 *This = impl_from_IMatchCollection2(iface);
1023 
1024     TRACE("(%p)->(%p)\n", This, add);
1025 
1026     if(!This->size) {
1027         This->matches = heap_alloc(8*sizeof(IMatch*));
1028         if(!This->matches)
1029             return E_OUTOFMEMORY;
1030         This->size = 8;
1031     }else if(This->size == This->count) {
1032         IMatch2 **new_matches = heap_realloc(This->matches, 2*This->size*sizeof(IMatch*));
1033         if(!new_matches)
1034             return E_OUTOFMEMORY;
1035 
1036         This->matches = new_matches;
1037         This->size <<= 1;
1038     }
1039 
1040     This->matches[This->count++] = add;
1041     IMatch2_AddRef(add);
1042     return S_OK;
1043 }
1044 
create_match_collection2(IMatchCollection2 ** match_collection)1045 static HRESULT create_match_collection2(IMatchCollection2 **match_collection)
1046 {
1047     MatchCollection2 *ret;
1048     HRESULT hres;
1049 
1050     hres = init_regexp_typeinfo(MatchCollection2_tid);
1051     if(FAILED(hres))
1052         return hres;
1053 
1054     ret = heap_alloc_zero(sizeof(*ret));
1055     if(!ret)
1056         return E_OUTOFMEMORY;
1057 
1058     ret->IMatchCollection2_iface.lpVtbl = &MatchCollection2Vtbl;
1059     ret->IMatchCollection_iface.lpVtbl = &MatchCollectionVtbl;
1060 
1061     ret->ref = 1;
1062     *match_collection = &ret->IMatchCollection2_iface;
1063     return S_OK;
1064 }
1065 
impl_from_IRegExp2(IRegExp2 * iface)1066 static inline RegExp2 *impl_from_IRegExp2(IRegExp2 *iface)
1067 {
1068     return CONTAINING_RECORD(iface, RegExp2, IRegExp2_iface);
1069 }
1070 
RegExp2_QueryInterface(IRegExp2 * iface,REFIID riid,void ** ppv)1071 static HRESULT WINAPI RegExp2_QueryInterface(IRegExp2 *iface, REFIID riid, void **ppv)
1072 {
1073     RegExp2 *This = impl_from_IRegExp2(iface);
1074 
1075     if(IsEqualGUID(riid, &IID_IUnknown)) {
1076         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1077         *ppv = &This->IRegExp2_iface;
1078     }else if(IsEqualGUID(riid, &IID_IDispatch)) {
1079         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
1080         *ppv = &This->IRegExp2_iface;
1081     }else if(IsEqualGUID(riid, &IID_IRegExp2)) {
1082         TRACE("(%p)->(IID_IRegExp2 %p)\n", This, ppv);
1083         *ppv = &This->IRegExp2_iface;
1084     }else if(IsEqualGUID(riid, &IID_IRegExp)) {
1085         TRACE("(%p)->(IID_IRegExp %p)\n", This, ppv);
1086         *ppv = &This->IRegExp_iface;
1087     }else if(IsEqualGUID(riid, &IID_IDispatchEx)) {
1088         TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
1089         *ppv = NULL;
1090         return E_NOINTERFACE;
1091     }else {
1092         FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1093         *ppv = NULL;
1094         return E_NOINTERFACE;
1095     }
1096 
1097     IUnknown_AddRef((IUnknown*)*ppv);
1098     return S_OK;
1099 }
1100 
RegExp2_AddRef(IRegExp2 * iface)1101 static ULONG WINAPI RegExp2_AddRef(IRegExp2 *iface)
1102 {
1103     RegExp2 *This = impl_from_IRegExp2(iface);
1104     LONG ref = InterlockedIncrement(&This->ref);
1105 
1106     TRACE("(%p) ref=%d\n", This, ref);
1107 
1108     return ref;
1109 }
1110 
RegExp2_Release(IRegExp2 * iface)1111 static ULONG WINAPI RegExp2_Release(IRegExp2 *iface)
1112 {
1113     RegExp2 *This = impl_from_IRegExp2(iface);
1114     LONG ref = InterlockedDecrement(&This->ref);
1115 
1116     TRACE("(%p) ref=%d\n", This, ref);
1117 
1118     if(!ref) {
1119         heap_free(This->pattern);
1120         if(This->regexp)
1121             regexp_destroy(This->regexp);
1122         heap_pool_free(&This->pool);
1123         heap_free(This);
1124     }
1125 
1126     return ref;
1127 }
1128 
RegExp2_GetTypeInfoCount(IRegExp2 * iface,UINT * pctinfo)1129 static HRESULT WINAPI RegExp2_GetTypeInfoCount(IRegExp2 *iface, UINT *pctinfo)
1130 {
1131     RegExp2 *This = impl_from_IRegExp2(iface);
1132 
1133     TRACE("(%p)->(%p)\n", This, pctinfo);
1134 
1135     *pctinfo = 1;
1136     return S_OK;
1137 }
1138 
RegExp2_GetTypeInfo(IRegExp2 * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)1139 static HRESULT WINAPI RegExp2_GetTypeInfo(IRegExp2 *iface,
1140         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1141 {
1142     RegExp2 *This = impl_from_IRegExp2(iface);
1143     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1144     return E_NOTIMPL;
1145 }
1146 
RegExp2_GetIDsOfNames(IRegExp2 * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)1147 static HRESULT WINAPI RegExp2_GetIDsOfNames(IRegExp2 *iface, REFIID riid,
1148         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1149 {
1150     RegExp2 *This = impl_from_IRegExp2(iface);
1151 
1152     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
1153             rgszNames, cNames, lcid, rgDispId);
1154 
1155     return ITypeInfo_GetIDsOfNames(typeinfos[RegExp2_tid], rgszNames, cNames, rgDispId);
1156 }
1157 
RegExp2_Invoke(IRegExp2 * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1158 static HRESULT WINAPI RegExp2_Invoke(IRegExp2 *iface, DISPID dispIdMember,
1159         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1160         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1161 {
1162     RegExp2 *This = impl_from_IRegExp2(iface);
1163 
1164     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1165             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1166 
1167     return ITypeInfo_Invoke(typeinfos[RegExp2_tid], iface, dispIdMember, wFlags,
1168             pDispParams, pVarResult, pExcepInfo, puArgErr);
1169 }
1170 
RegExp2_get_Pattern(IRegExp2 * iface,BSTR * pPattern)1171 static HRESULT WINAPI RegExp2_get_Pattern(IRegExp2 *iface, BSTR *pPattern)
1172 {
1173     RegExp2 *This = impl_from_IRegExp2(iface);
1174 
1175     TRACE("(%p)->(%p)\n", This, pPattern);
1176 
1177     if(!pPattern)
1178         return E_POINTER;
1179 
1180     if(!This->pattern) {
1181         *pPattern = NULL;
1182         return S_OK;
1183     }
1184 
1185     *pPattern = SysAllocString(This->pattern);
1186     return *pPattern ? S_OK : E_OUTOFMEMORY;
1187 }
1188 
RegExp2_put_Pattern(IRegExp2 * iface,BSTR pattern)1189 static HRESULT WINAPI RegExp2_put_Pattern(IRegExp2 *iface, BSTR pattern)
1190 {
1191     RegExp2 *This = impl_from_IRegExp2(iface);
1192     WCHAR *new_pattern;
1193 
1194     TRACE("(%p)->(%s)\n", This, wine_dbgstr_w(pattern));
1195 
1196     if(pattern && *pattern) {
1197         SIZE_T size = (SysStringLen(pattern)+1) * sizeof(WCHAR);
1198         new_pattern = heap_alloc(size);
1199         if(!new_pattern)
1200             return E_OUTOFMEMORY;
1201         memcpy(new_pattern, pattern, size);
1202     }else {
1203         new_pattern = NULL;
1204     }
1205 
1206     heap_free(This->pattern);
1207     This->pattern = new_pattern;
1208 
1209     if(This->regexp) {
1210         regexp_destroy(This->regexp);
1211         This->regexp = NULL;
1212     }
1213     return S_OK;
1214 }
1215 
RegExp2_get_IgnoreCase(IRegExp2 * iface,VARIANT_BOOL * pIgnoreCase)1216 static HRESULT WINAPI RegExp2_get_IgnoreCase(IRegExp2 *iface, VARIANT_BOOL *pIgnoreCase)
1217 {
1218     RegExp2 *This = impl_from_IRegExp2(iface);
1219 
1220     TRACE("(%p)->(%p)\n", This, pIgnoreCase);
1221 
1222     if(!pIgnoreCase)
1223         return E_POINTER;
1224 
1225     *pIgnoreCase = This->flags & REG_FOLD ? VARIANT_TRUE : VARIANT_FALSE;
1226     return S_OK;
1227 }
1228 
RegExp2_put_IgnoreCase(IRegExp2 * iface,VARIANT_BOOL ignoreCase)1229 static HRESULT WINAPI RegExp2_put_IgnoreCase(IRegExp2 *iface, VARIANT_BOOL ignoreCase)
1230 {
1231     RegExp2 *This = impl_from_IRegExp2(iface);
1232 
1233     TRACE("(%p)->(%s)\n", This, ignoreCase ? "true" : "false");
1234 
1235     if(ignoreCase)
1236         This->flags |= REG_FOLD;
1237     else
1238         This->flags &= ~REG_FOLD;
1239     return S_OK;
1240 }
1241 
RegExp2_get_Global(IRegExp2 * iface,VARIANT_BOOL * pGlobal)1242 static HRESULT WINAPI RegExp2_get_Global(IRegExp2 *iface, VARIANT_BOOL *pGlobal)
1243 {
1244     RegExp2 *This = impl_from_IRegExp2(iface);
1245 
1246     TRACE("(%p)->(%p)\n", This, pGlobal);
1247 
1248     if(!pGlobal)
1249         return E_POINTER;
1250 
1251     *pGlobal = This->flags & REG_GLOB ? VARIANT_TRUE : VARIANT_FALSE;
1252     return S_OK;
1253 }
1254 
RegExp2_put_Global(IRegExp2 * iface,VARIANT_BOOL global)1255 static HRESULT WINAPI RegExp2_put_Global(IRegExp2 *iface, VARIANT_BOOL global)
1256 {
1257     RegExp2 *This = impl_from_IRegExp2(iface);
1258 
1259     TRACE("(%p)->(%s)\n", This, global ? "true" : "false");
1260 
1261     if(global)
1262         This->flags |= REG_GLOB;
1263     else
1264         This->flags &= ~REG_GLOB;
1265     return S_OK;
1266 }
1267 
RegExp2_get_Multiline(IRegExp2 * iface,VARIANT_BOOL * pMultiline)1268 static HRESULT WINAPI RegExp2_get_Multiline(IRegExp2 *iface, VARIANT_BOOL *pMultiline)
1269 {
1270     RegExp2 *This = impl_from_IRegExp2(iface);
1271 
1272     TRACE("(%p)->(%p)\n", This, pMultiline);
1273 
1274     if(!pMultiline)
1275         return E_POINTER;
1276 
1277     *pMultiline = This->flags & REG_MULTILINE ? VARIANT_TRUE : VARIANT_FALSE;
1278     return S_OK;
1279 }
1280 
RegExp2_put_Multiline(IRegExp2 * iface,VARIANT_BOOL multiline)1281 static HRESULT WINAPI RegExp2_put_Multiline(IRegExp2 *iface, VARIANT_BOOL multiline)
1282 {
1283     RegExp2 *This = impl_from_IRegExp2(iface);
1284 
1285     TRACE("(%p)->(%s)\n", This, multiline ? "true" : "false");
1286 
1287     if(multiline)
1288         This->flags |= REG_MULTILINE;
1289     else
1290         This->flags &= ~REG_MULTILINE;
1291     return S_OK;
1292 }
1293 
RegExp2_Execute(IRegExp2 * iface,BSTR sourceString,IDispatch ** ppMatches)1294 static HRESULT WINAPI RegExp2_Execute(IRegExp2 *iface,
1295         BSTR sourceString, IDispatch **ppMatches)
1296 {
1297     RegExp2 *This = impl_from_IRegExp2(iface);
1298     match_state_t *result;
1299     const WCHAR *pos;
1300     IMatchCollection2 *match_collection;
1301     IMatch2 *add = NULL;
1302     HRESULT hres;
1303 
1304     TRACE("(%p)->(%s %p)\n", This, debugstr_w(sourceString), ppMatches);
1305 
1306     if(!This->pattern) {
1307         DWORD i, len = SysStringLen(sourceString);
1308 
1309         hres = create_match_collection2(&match_collection);
1310         if(FAILED(hres))
1311             return hres;
1312 
1313         for(i=0; i<=len; i++) {
1314             hres = create_match2(i, NULL, &add);
1315             if(FAILED(hres))
1316                 break;
1317 
1318             hres = add_match(match_collection, add);
1319             if(FAILED(hres))
1320                 break;
1321             IMatch2_Release(add);
1322 
1323             if(!(This->flags & REG_GLOB))
1324                 break;
1325         }
1326 
1327         if(FAILED(hres)) {
1328             IMatchCollection2_Release(match_collection);
1329             return hres;
1330         }
1331 
1332         *ppMatches = (IDispatch*)match_collection;
1333         return S_OK;
1334     }
1335 
1336     if(!This->regexp) {
1337         This->regexp = regexp_new(NULL, &This->pool, This->pattern,
1338                 lstrlenW(This->pattern), This->flags, FALSE);
1339         if(!This->regexp)
1340             return E_FAIL;
1341     }else {
1342         hres = regexp_set_flags(&This->regexp, NULL, &This->pool, This->flags);
1343         if(FAILED(hres))
1344             return hres;
1345     }
1346 
1347     hres = create_match_collection2(&match_collection);
1348     if(FAILED(hres))
1349         return hres;
1350 
1351     pos = sourceString;
1352     while(1) {
1353         result = alloc_match_state(This->regexp, NULL, pos);
1354         if(!result) {
1355             hres = E_OUTOFMEMORY;
1356             break;
1357         }
1358 
1359         hres = regexp_execute(This->regexp, NULL, &This->pool,
1360                 sourceString, SysStringLen(sourceString), result);
1361         if(hres != S_OK) {
1362             heap_free(result);
1363             break;
1364         }
1365         pos = result->cp;
1366 
1367         hres = create_match2(result->cp-result->match_len-sourceString, &result, &add);
1368         heap_free(result);
1369         if(FAILED(hres))
1370             break;
1371         hres = add_match(match_collection, add);
1372         IMatch2_Release(add);
1373         if(FAILED(hres))
1374             break;
1375 
1376         if(!(This->flags & REG_GLOB))
1377             break;
1378     }
1379 
1380     if(FAILED(hres)) {
1381         IMatchCollection2_Release(match_collection);
1382         return hres;
1383     }
1384 
1385     *ppMatches = (IDispatch*)match_collection;
1386     return S_OK;
1387 }
1388 
RegExp2_Test(IRegExp2 * iface,BSTR sourceString,VARIANT_BOOL * pMatch)1389 static HRESULT WINAPI RegExp2_Test(IRegExp2 *iface, BSTR sourceString, VARIANT_BOOL *pMatch)
1390 {
1391     RegExp2 *This = impl_from_IRegExp2(iface);
1392     match_state_t *result;
1393     heap_pool_t *mark;
1394     HRESULT hres;
1395 
1396     TRACE("(%p)->(%s %p)\n", This, debugstr_w(sourceString), pMatch);
1397 
1398     if(!This->pattern) {
1399         *pMatch = VARIANT_TRUE;
1400         return S_OK;
1401     }
1402 
1403     if(!This->regexp) {
1404         This->regexp = regexp_new(NULL, &This->pool, This->pattern,
1405                 lstrlenW(This->pattern), This->flags, FALSE);
1406         if(!This->regexp)
1407             return E_FAIL;
1408     }else {
1409         hres = regexp_set_flags(&This->regexp, NULL, &This->pool, This->flags);
1410         if(FAILED(hres))
1411             return hres;
1412     }
1413 
1414     mark = heap_pool_mark(&This->pool);
1415     result = alloc_match_state(This->regexp, &This->pool, sourceString);
1416     if(!result) {
1417         heap_pool_clear(mark);
1418         return E_OUTOFMEMORY;
1419     }
1420 
1421     hres = regexp_execute(This->regexp, NULL, &This->pool,
1422             sourceString, SysStringLen(sourceString), result);
1423 
1424     heap_pool_clear(mark);
1425 
1426     if(hres == S_OK) {
1427         *pMatch = VARIANT_TRUE;
1428     }else if(hres == S_FALSE) {
1429         *pMatch = VARIANT_FALSE;
1430         hres = S_OK;
1431     }
1432     return hres;
1433 }
1434 
RegExp2_Replace(IRegExp2 * iface,BSTR sourceString,VARIANT replaceVar,BSTR * pDestString)1435 static HRESULT WINAPI RegExp2_Replace(IRegExp2 *iface, BSTR sourceString,
1436         VARIANT replaceVar, BSTR *pDestString)
1437 {
1438     RegExp2 *This = impl_from_IRegExp2(iface);
1439     FIXME("(%p)->(%s %s %p)\n", This, debugstr_w(sourceString),
1440             debugstr_variant(&replaceVar), pDestString);
1441     return E_NOTIMPL;
1442 }
1443 
1444 static const IRegExp2Vtbl RegExp2Vtbl = {
1445     RegExp2_QueryInterface,
1446     RegExp2_AddRef,
1447     RegExp2_Release,
1448     RegExp2_GetTypeInfoCount,
1449     RegExp2_GetTypeInfo,
1450     RegExp2_GetIDsOfNames,
1451     RegExp2_Invoke,
1452     RegExp2_get_Pattern,
1453     RegExp2_put_Pattern,
1454     RegExp2_get_IgnoreCase,
1455     RegExp2_put_IgnoreCase,
1456     RegExp2_get_Global,
1457     RegExp2_put_Global,
1458     RegExp2_get_Multiline,
1459     RegExp2_put_Multiline,
1460     RegExp2_Execute,
1461     RegExp2_Test,
1462     RegExp2_Replace
1463 };
1464 
impl_from_IRegExp(IRegExp * iface)1465 static inline RegExp2 *impl_from_IRegExp(IRegExp *iface)
1466 {
1467     return CONTAINING_RECORD(iface, RegExp2, IRegExp_iface);
1468 }
1469 
RegExp_QueryInterface(IRegExp * iface,REFIID riid,void ** ppv)1470 static HRESULT WINAPI RegExp_QueryInterface(IRegExp *iface, REFIID riid, void **ppv)
1471 {
1472     RegExp2 *This = impl_from_IRegExp(iface);
1473     return IRegExp2_QueryInterface(&This->IRegExp2_iface, riid, ppv);
1474 }
1475 
RegExp_AddRef(IRegExp * iface)1476 static ULONG WINAPI RegExp_AddRef(IRegExp *iface)
1477 {
1478     RegExp2 *This = impl_from_IRegExp(iface);
1479     return IRegExp2_AddRef(&This->IRegExp2_iface);
1480 }
1481 
RegExp_Release(IRegExp * iface)1482 static ULONG WINAPI RegExp_Release(IRegExp *iface)
1483 {
1484     RegExp2 *This = impl_from_IRegExp(iface);
1485     return IRegExp2_Release(&This->IRegExp2_iface);
1486 }
1487 
RegExp_GetTypeInfoCount(IRegExp * iface,UINT * pctinfo)1488 static HRESULT WINAPI RegExp_GetTypeInfoCount(IRegExp *iface, UINT *pctinfo)
1489 {
1490     RegExp2 *This = impl_from_IRegExp(iface);
1491     return IRegExp2_GetTypeInfoCount(&This->IRegExp2_iface, pctinfo);
1492 }
1493 
RegExp_GetTypeInfo(IRegExp * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)1494 static HRESULT WINAPI RegExp_GetTypeInfo(IRegExp *iface,
1495         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1496 {
1497     RegExp2 *This = impl_from_IRegExp(iface);
1498     return IRegExp2_GetTypeInfo(&This->IRegExp2_iface, iTInfo, lcid, ppTInfo);
1499 }
1500 
RegExp_GetIDsOfNames(IRegExp * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)1501 static HRESULT WINAPI RegExp_GetIDsOfNames(IRegExp *iface, REFIID riid,
1502         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1503 {
1504     RegExp2 *This = impl_from_IRegExp(iface);
1505     return IRegExp2_GetIDsOfNames(&This->IRegExp2_iface, riid, rgszNames, cNames, lcid, rgDispId);
1506 }
1507 
RegExp_Invoke(IRegExp * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1508 static HRESULT WINAPI RegExp_Invoke(IRegExp *iface, DISPID dispIdMember,
1509         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1510                 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1511 {
1512     RegExp2 *This = impl_from_IRegExp(iface);
1513     return IRegExp2_Invoke(&This->IRegExp2_iface, dispIdMember, riid, lcid,
1514             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1515 }
1516 
RegExp_get_Pattern(IRegExp * iface,BSTR * pPattern)1517 static HRESULT WINAPI RegExp_get_Pattern(IRegExp *iface, BSTR *pPattern)
1518 {
1519     RegExp2 *This = impl_from_IRegExp(iface);
1520     return IRegExp2_get_Pattern(&This->IRegExp2_iface, pPattern);
1521 }
1522 
RegExp_put_Pattern(IRegExp * iface,BSTR pPattern)1523 static HRESULT WINAPI RegExp_put_Pattern(IRegExp *iface, BSTR pPattern)
1524 {
1525     RegExp2 *This = impl_from_IRegExp(iface);
1526     return IRegExp2_put_Pattern(&This->IRegExp2_iface, pPattern);
1527 }
1528 
RegExp_get_IgnoreCase(IRegExp * iface,VARIANT_BOOL * pIgnoreCase)1529 static HRESULT WINAPI RegExp_get_IgnoreCase(IRegExp *iface, VARIANT_BOOL *pIgnoreCase)
1530 {
1531     RegExp2 *This = impl_from_IRegExp(iface);
1532     return IRegExp2_get_IgnoreCase(&This->IRegExp2_iface, pIgnoreCase);
1533 }
1534 
RegExp_put_IgnoreCase(IRegExp * iface,VARIANT_BOOL pIgnoreCase)1535 static HRESULT WINAPI RegExp_put_IgnoreCase(IRegExp *iface, VARIANT_BOOL pIgnoreCase)
1536 {
1537     RegExp2 *This = impl_from_IRegExp(iface);
1538     return IRegExp2_put_IgnoreCase(&This->IRegExp2_iface, pIgnoreCase);
1539 }
1540 
RegExp_get_Global(IRegExp * iface,VARIANT_BOOL * pGlobal)1541 static HRESULT WINAPI RegExp_get_Global(IRegExp *iface, VARIANT_BOOL *pGlobal)
1542 {
1543     RegExp2 *This = impl_from_IRegExp(iface);
1544     return IRegExp2_get_Global(&This->IRegExp2_iface, pGlobal);
1545 }
1546 
RegExp_put_Global(IRegExp * iface,VARIANT_BOOL pGlobal)1547 static HRESULT WINAPI RegExp_put_Global(IRegExp *iface, VARIANT_BOOL pGlobal)
1548 {
1549     RegExp2 *This = impl_from_IRegExp(iface);
1550     return IRegExp2_put_Global(&This->IRegExp2_iface, pGlobal);
1551 }
1552 
RegExp_Execute(IRegExp * iface,BSTR sourceString,IDispatch ** ppMatches)1553 static HRESULT WINAPI RegExp_Execute(IRegExp *iface,
1554         BSTR sourceString, IDispatch **ppMatches)
1555 {
1556     RegExp2 *This = impl_from_IRegExp(iface);
1557     return IRegExp2_Execute(&This->IRegExp2_iface, sourceString, ppMatches);
1558 }
1559 
RegExp_Test(IRegExp * iface,BSTR sourceString,VARIANT_BOOL * pMatch)1560 static HRESULT WINAPI RegExp_Test(IRegExp *iface, BSTR sourceString, VARIANT_BOOL *pMatch)
1561 {
1562     RegExp2 *This = impl_from_IRegExp(iface);
1563     return IRegExp2_Test(&This->IRegExp2_iface, sourceString, pMatch);
1564 }
1565 
RegExp_Replace(IRegExp * iface,BSTR sourceString,BSTR replaceString,BSTR * pDestString)1566 static HRESULT WINAPI RegExp_Replace(IRegExp *iface, BSTR sourceString,
1567         BSTR replaceString, BSTR *pDestString)
1568 {
1569     RegExp2 *This = impl_from_IRegExp(iface);
1570     VARIANT replace;
1571 
1572     V_VT(&replace) = VT_BSTR;
1573     V_BSTR(&replace) = replaceString;
1574     return IRegExp2_Replace(&This->IRegExp2_iface, sourceString, replace, pDestString);
1575 }
1576 
1577 static IRegExpVtbl RegExpVtbl = {
1578     RegExp_QueryInterface,
1579     RegExp_AddRef,
1580     RegExp_Release,
1581     RegExp_GetTypeInfoCount,
1582     RegExp_GetTypeInfo,
1583     RegExp_GetIDsOfNames,
1584     RegExp_Invoke,
1585     RegExp_get_Pattern,
1586     RegExp_put_Pattern,
1587     RegExp_get_IgnoreCase,
1588     RegExp_put_IgnoreCase,
1589     RegExp_get_Global,
1590     RegExp_put_Global,
1591     RegExp_Execute,
1592     RegExp_Test,
1593     RegExp_Replace
1594 };
1595 
create_regexp(IDispatch ** ret)1596 HRESULT create_regexp(IDispatch **ret)
1597 {
1598     RegExp2 *regexp;
1599     HRESULT hres;
1600 
1601     hres = init_regexp_typeinfo(RegExp2_tid);
1602     if(FAILED(hres))
1603         return hres;
1604 
1605     regexp = heap_alloc_zero(sizeof(*regexp));
1606     if(!regexp)
1607         return E_OUTOFMEMORY;
1608 
1609     regexp->IRegExp2_iface.lpVtbl = &RegExp2Vtbl;
1610     regexp->IRegExp_iface.lpVtbl = &RegExpVtbl;
1611     regexp->ref = 1;
1612     heap_pool_init(&regexp->pool);
1613 
1614     *ret = (IDispatch*)&regexp->IRegExp2_iface;
1615     return S_OK;
1616 }
1617 
VBScriptRegExpFactory_CreateInstance(IClassFactory * iface,IUnknown * pUnkOuter,REFIID riid,void ** ppv)1618 HRESULT WINAPI VBScriptRegExpFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, REFIID riid, void **ppv)
1619 {
1620     IDispatch *regexp;
1621     HRESULT hres;
1622 
1623     TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv);
1624 
1625     hres = create_regexp(&regexp);
1626     if(FAILED(hres))
1627         return hres;
1628 
1629     hres = IDispatch_QueryInterface(regexp, riid, ppv);
1630     IDispatch_Release(regexp);
1631     return hres;
1632 }
1633 
release_regexp_typelib(void)1634 void release_regexp_typelib(void)
1635 {
1636     DWORD i;
1637 
1638     for(i=0; i<REGEXP_LAST_tid; i++) {
1639         if(typeinfos[i])
1640             ITypeInfo_Release(typeinfos[i]);
1641     }
1642     if(typelib)
1643         ITypeLib_Release(typelib);
1644 }
1645