vbscript: Specify correct variable in memory allocation check (coverity).
[wine.git] / dlls / vbscript / vbregexp.c
blobf3fb8747a5bef28b81f47ec52bf7d0960d96d6fd
1 /*
2 * Copyright 2013 Piotr Caban for CodeWeavers
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.
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.
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
19 #include "vbscript.h"
20 #include "regexp.h"
21 #include "vbsregexp55.h"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
27 #define REGEXP_TID_LIST \
28 XDIID(RegExp2), \
29 XDIID(Match2), \
30 XDIID(MatchCollection2), \
31 XDIID(SubMatches)
33 typedef enum {
34 #define XDIID(iface) iface ## _tid
35 REGEXP_TID_LIST,
36 #undef XDIID
37 REGEXP_LAST_tid
38 } regexp_tid_t;
40 static REFIID tid_ids[] = {
41 #define XDIID(iface) &IID_I ## iface
42 REGEXP_TID_LIST
43 #undef XDIID
46 static ITypeLib *typelib;
47 static ITypeInfo *typeinfos[REGEXP_LAST_tid];
49 static HRESULT init_regexp_typeinfo(regexp_tid_t tid)
51 HRESULT hres;
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;
57 hres = LoadTypeLib(vbscript_dll3W, &tl);
58 if(FAILED(hres)) {
59 ERR("LoadRegTypeLib failed: %08x\n", hres);
60 return hres;
63 if(InterlockedCompareExchangePointer((void**)&typelib, tl, NULL))
64 ITypeLib_Release(tl);
67 if(!typeinfos[tid]) {
68 ITypeInfo *ti;
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;
76 if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
77 ITypeInfo_Release(ti);
80 return S_OK;
83 struct SubMatches {
84 ISubMatches ISubMatches_iface;
86 LONG ref;
88 WCHAR *match;
89 match_state_t *result;
92 typedef struct Match2 {
93 IMatch2 IMatch2_iface;
95 LONG ref;
97 DWORD index;
98 SubMatches *sub_matches;
99 } Match2;
101 typedef struct MatchCollectionEnum {
102 IEnumVARIANT IEnumVARIANT_iface;
104 LONG ref;
106 IMatchCollection2 *mc;
107 LONG pos;
108 LONG count;
109 } MatchCollectionEnum;
111 typedef struct MatchCollection2 {
112 IMatchCollection2 IMatchCollection2_iface;
114 LONG ref;
116 IMatch2 **matches;
117 DWORD count;
118 DWORD size;
119 } MatchCollection2;
121 typedef struct RegExp2 {
122 IRegExp2 IRegExp2_iface;
123 IRegExp IRegExp_iface;
125 LONG ref;
127 WCHAR *pattern;
128 regexp_t *regexp;
129 heap_pool_t pool;
130 WORD flags;
131 } RegExp2;
133 static inline SubMatches* impl_from_ISubMatches(ISubMatches *iface)
135 return CONTAINING_RECORD(iface, SubMatches, ISubMatches_iface);
138 static HRESULT WINAPI SubMatches_QueryInterface(
139 ISubMatches *iface, REFIID riid, void **ppv)
141 SubMatches *This = impl_from_ISubMatches(iface);
143 if(IsEqualGUID(riid, &IID_IUnknown)) {
144 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
145 *ppv = &This->ISubMatches_iface;
146 }else if(IsEqualGUID(riid, &IID_IDispatch)) {
147 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
148 *ppv = &This->ISubMatches_iface;
149 }else if(IsEqualGUID(riid, &IID_ISubMatches)) {
150 TRACE("(%p)->(IID_ISubMatches %p)\n", This, ppv);
151 *ppv = &This->ISubMatches_iface;
152 }else if(IsEqualGUID(riid, &IID_IDispatchEx)) {
153 TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
154 *ppv = NULL;
155 return E_NOINTERFACE;
156 }else {
157 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
158 *ppv = NULL;
159 return E_NOINTERFACE;
162 IUnknown_AddRef((IUnknown*)*ppv);
163 return S_OK;
166 static ULONG WINAPI SubMatches_AddRef(ISubMatches *iface)
168 SubMatches *This = impl_from_ISubMatches(iface);
169 LONG ref = InterlockedIncrement(&This->ref);
171 TRACE("(%p) ref=%d\n", This, ref);
173 return ref;
176 static ULONG WINAPI SubMatches_Release(ISubMatches *iface)
178 SubMatches *This = impl_from_ISubMatches(iface);
179 LONG ref = InterlockedDecrement(&This->ref);
181 TRACE("(%p) ref=%d\n", This, ref);
183 if(!ref) {
184 heap_free(This->match);
185 heap_free(This->result);
186 heap_free(This);
189 return ref;
192 static HRESULT WINAPI SubMatches_GetTypeInfoCount(ISubMatches *iface, UINT *pctinfo)
194 SubMatches *This = impl_from_ISubMatches(iface);
196 TRACE("(%p)->(%p)\n", This, pctinfo);
198 *pctinfo = 1;
199 return S_OK;
202 static HRESULT WINAPI SubMatches_GetTypeInfo(ISubMatches *iface,
203 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
205 SubMatches *This = impl_from_ISubMatches(iface);
206 FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
207 return E_NOTIMPL;
210 static HRESULT WINAPI SubMatches_GetIDsOfNames(ISubMatches *iface,
211 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
213 SubMatches *This = impl_from_ISubMatches(iface);
215 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
216 rgszNames, cNames, lcid, rgDispId);
218 return ITypeInfo_GetIDsOfNames(typeinfos[SubMatches_tid], rgszNames, cNames, rgDispId);
221 static HRESULT WINAPI SubMatches_Invoke(ISubMatches *iface, DISPID dispIdMember,
222 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
223 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
225 SubMatches *This = impl_from_ISubMatches(iface);
227 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
228 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
230 return ITypeInfo_Invoke(typeinfos[SubMatches_tid], iface, dispIdMember, wFlags,
231 pDispParams, pVarResult, pExcepInfo, puArgErr);
234 static HRESULT WINAPI SubMatches_get_Item(ISubMatches *iface,
235 LONG index, VARIANT *pSubMatch)
237 SubMatches *This = impl_from_ISubMatches(iface);
239 TRACE("(%p)->(%d %p)\n", This, index, pSubMatch);
241 if(!pSubMatch)
242 return E_POINTER;
244 if(!This->result || index<0 || index>=This->result->paren_count)
245 return E_INVALIDARG;
247 if(This->result->parens[index].index == -1) {
248 V_VT(pSubMatch) = VT_EMPTY;
249 }else {
250 V_VT(pSubMatch) = VT_BSTR;
251 V_BSTR(pSubMatch) = SysAllocStringLen(
252 This->match+This->result->parens[index].index,
253 This->result->parens[index].length);
255 if(!V_BSTR(pSubMatch))
256 return E_OUTOFMEMORY;
259 return S_OK;
262 static HRESULT WINAPI SubMatches_get_Count(ISubMatches *iface, LONG *pCount)
264 SubMatches *This = impl_from_ISubMatches(iface);
266 TRACE("(%p)->(%p)\n", This, pCount);
268 if(!pCount)
269 return E_POINTER;
271 if(!This->result)
272 *pCount = 0;
273 else
274 *pCount = This->result->paren_count;
275 return S_OK;
278 static HRESULT WINAPI SubMatches_get__NewEnum(ISubMatches *iface, IUnknown **ppEnum)
280 SubMatches *This = impl_from_ISubMatches(iface);
281 FIXME("(%p)->(%p)\n", This, ppEnum);
282 return E_NOTIMPL;
285 static const ISubMatchesVtbl SubMatchesVtbl = {
286 SubMatches_QueryInterface,
287 SubMatches_AddRef,
288 SubMatches_Release,
289 SubMatches_GetTypeInfoCount,
290 SubMatches_GetTypeInfo,
291 SubMatches_GetIDsOfNames,
292 SubMatches_Invoke,
293 SubMatches_get_Item,
294 SubMatches_get_Count,
295 SubMatches_get__NewEnum
298 static HRESULT create_sub_matches(DWORD pos, match_state_t *result, SubMatches **sub_matches)
300 SubMatches *ret;
301 DWORD i;
302 HRESULT hres;
304 hres = init_regexp_typeinfo(SubMatches_tid);
305 if(FAILED(hres))
306 return hres;
308 ret = heap_alloc_zero(sizeof(*ret));
309 if(!ret)
310 return E_OUTOFMEMORY;
312 ret->ISubMatches_iface.lpVtbl = &SubMatchesVtbl;
314 ret->result = result;
315 if(result) {
316 ret->match = heap_alloc((result->match_len+1) * sizeof(WCHAR));
317 if(!ret->match) {
318 heap_free(ret);
319 return E_OUTOFMEMORY;
321 memcpy(ret->match, result->cp-result->match_len, result->match_len*sizeof(WCHAR));
322 ret->match[result->match_len] = 0;
324 result->cp = NULL;
325 for(i=0; i<result->paren_count; i++)
326 if(result->parens[i].index != -1)
327 result->parens[i].index -= pos;
328 }else {
329 ret->match = NULL;
332 ret->ref = 1;
333 *sub_matches = ret;
334 return hres;
337 static inline Match2* impl_from_IMatch2(IMatch2 *iface)
339 return CONTAINING_RECORD(iface, Match2, IMatch2_iface);
342 static HRESULT WINAPI Match2_QueryInterface(
343 IMatch2 *iface, REFIID riid, void **ppv)
345 Match2 *This = impl_from_IMatch2(iface);
347 if(IsEqualGUID(riid, &IID_IUnknown)) {
348 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
349 *ppv = &This->IMatch2_iface;
350 }else if(IsEqualGUID(riid, &IID_IDispatch)) {
351 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
352 *ppv = &This->IMatch2_iface;
353 }else if(IsEqualGUID(riid, &IID_IMatch2)) {
354 TRACE("(%p)->(IID_IMatch2 %p)\n", This, ppv);
355 *ppv = &This->IMatch2_iface;
356 }else if(IsEqualGUID(riid, &IID_IDispatchEx)) {
357 TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
358 *ppv = NULL;
359 return E_NOINTERFACE;
360 }else {
361 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
362 *ppv = NULL;
363 return E_NOINTERFACE;
366 IUnknown_AddRef((IUnknown*)*ppv);
367 return S_OK;
370 static ULONG WINAPI Match2_AddRef(IMatch2 *iface)
372 Match2 *This = impl_from_IMatch2(iface);
373 LONG ref = InterlockedIncrement(&This->ref);
375 TRACE("(%p) ref=%d\n", This, ref);
377 return ref;
380 static ULONG WINAPI Match2_Release(IMatch2 *iface)
382 Match2 *This = impl_from_IMatch2(iface);
383 LONG ref = InterlockedDecrement(&This->ref);
385 TRACE("(%p) ref=%d\n", This, ref);
387 if(!ref) {
388 ISubMatches_Release(&This->sub_matches->ISubMatches_iface);
389 heap_free(This);
392 return ref;
395 static HRESULT WINAPI Match2_GetTypeInfoCount(IMatch2 *iface, UINT *pctinfo)
397 Match2 *This = impl_from_IMatch2(iface);
399 TRACE("(%p)->(%p)\n", This, pctinfo);
401 *pctinfo = 1;
402 return S_OK;
405 static HRESULT WINAPI Match2_GetTypeInfo(IMatch2 *iface,
406 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
408 Match2 *This = impl_from_IMatch2(iface);
409 FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
410 return E_NOTIMPL;
413 static HRESULT WINAPI Match2_GetIDsOfNames(IMatch2 *iface,
414 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
416 Match2 *This = impl_from_IMatch2(iface);
418 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
419 rgszNames, cNames, lcid, rgDispId);
421 return ITypeInfo_GetIDsOfNames(typeinfos[Match2_tid], rgszNames, cNames, rgDispId);
424 static HRESULT WINAPI Match2_Invoke(IMatch2 *iface, DISPID dispIdMember,
425 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
426 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
428 Match2 *This = impl_from_IMatch2(iface);
430 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
431 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
433 return ITypeInfo_Invoke(typeinfos[Match2_tid], iface, dispIdMember, wFlags,
434 pDispParams, pVarResult, pExcepInfo, puArgErr);
437 static HRESULT WINAPI Match2_get_Value(IMatch2 *iface, BSTR *pValue)
439 Match2 *This = impl_from_IMatch2(iface);
441 TRACE("(%p)->(%p)\n", This, pValue);
443 if(!pValue)
444 return E_POINTER;
446 if(!This->sub_matches->match) {
447 *pValue = NULL;
448 return S_OK;
451 *pValue = SysAllocString(This->sub_matches->match);
452 return *pValue ? S_OK : E_OUTOFMEMORY;
455 static HRESULT WINAPI Match2_get_FirstIndex(IMatch2 *iface, LONG *pFirstIndex)
457 Match2 *This = impl_from_IMatch2(iface);
459 TRACE("(%p)->(%p)\n", This, pFirstIndex);
461 if(!pFirstIndex)
462 return E_POINTER;
464 *pFirstIndex = This->index;
465 return S_OK;
468 static HRESULT WINAPI Match2_get_Length(IMatch2 *iface, LONG *pLength)
470 Match2 *This = impl_from_IMatch2(iface);
472 TRACE("(%p)->(%p)\n", This, pLength);
474 if(!pLength)
475 return E_POINTER;
477 if(This->sub_matches->result)
478 *pLength = This->sub_matches->result->match_len;
479 else
480 *pLength = 0;
481 return S_OK;
484 static HRESULT WINAPI Match2_get_SubMatches(IMatch2 *iface, IDispatch **ppSubMatches)
486 Match2 *This = impl_from_IMatch2(iface);
488 TRACE("(%p)->(%p)\n", This, ppSubMatches);
490 if(!ppSubMatches)
491 return E_POINTER;
493 *ppSubMatches = (IDispatch*)&This->sub_matches->ISubMatches_iface;
494 ISubMatches_AddRef(&This->sub_matches->ISubMatches_iface);
495 return S_OK;
498 static const IMatch2Vtbl Match2Vtbl = {
499 Match2_QueryInterface,
500 Match2_AddRef,
501 Match2_Release,
502 Match2_GetTypeInfoCount,
503 Match2_GetTypeInfo,
504 Match2_GetIDsOfNames,
505 Match2_Invoke,
506 Match2_get_Value,
507 Match2_get_FirstIndex,
508 Match2_get_Length,
509 Match2_get_SubMatches
512 static HRESULT create_match2(DWORD pos, match_state_t **result, IMatch2 **match)
514 Match2 *ret;
515 HRESULT hres;
517 hres = init_regexp_typeinfo(Match2_tid);
518 if(FAILED(hres))
519 return hres;
521 ret = heap_alloc_zero(sizeof(*ret));
522 if(!ret)
523 return E_OUTOFMEMORY;
525 ret->index = pos;
526 hres = create_sub_matches(pos, result ? *result : NULL, &ret->sub_matches);
527 if(FAILED(hres)) {
528 heap_free(ret);
529 return hres;
531 if(result)
532 *result = NULL;
534 ret->IMatch2_iface.lpVtbl = &Match2Vtbl;
536 ret->ref = 1;
537 *match = &ret->IMatch2_iface;
538 return hres;
541 static inline MatchCollectionEnum* impl_from_IMatchCollectionEnum(IEnumVARIANT *iface)
543 return CONTAINING_RECORD(iface, MatchCollectionEnum, IEnumVARIANT_iface);
546 static HRESULT WINAPI MatchCollectionEnum_QueryInterface(
547 IEnumVARIANT *iface, REFIID riid, void **ppv)
549 MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
551 if(IsEqualGUID(riid, &IID_IUnknown)) {
552 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
553 *ppv = &This->IEnumVARIANT_iface;
554 }else if(IsEqualGUID(riid, &IID_IEnumVARIANT)) {
555 TRACE("(%p)->(IID_IEnumVARIANT %p)\n", This, ppv);
556 *ppv = &This->IEnumVARIANT_iface;
557 }else {
558 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
559 *ppv = NULL;
560 return E_NOINTERFACE;
563 IUnknown_AddRef((IUnknown*)*ppv);
564 return S_OK;
567 static ULONG WINAPI MatchCollectionEnum_AddRef(IEnumVARIANT *iface)
569 MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
570 LONG ref = InterlockedIncrement(&This->ref);
572 TRACE("(%p) ref=%d\n", This, ref);
574 return ref;
577 static ULONG WINAPI MatchCollectionEnum_Release(IEnumVARIANT *iface)
579 MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
580 LONG ref = InterlockedDecrement(&This->ref);
582 TRACE("(%p) ref=%d\n", This, ref);
584 if(!ref) {
585 IMatchCollection2_Release(This->mc);
586 heap_free(This);
589 return ref;
592 static HRESULT WINAPI MatchCollectionEnum_Next(IEnumVARIANT *iface,
593 ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
595 MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
596 DWORD i;
597 HRESULT hres = S_OK;
599 TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched);
601 if(This->pos>=This->count) {
602 if(pCeltFetched)
603 *pCeltFetched = 0;
604 return S_FALSE;
607 for(i=0; i<celt && This->pos+i<This->count; i++) {
608 V_VT(rgVar+i) = VT_DISPATCH;
609 hres = IMatchCollection2_get_Item(This->mc, This->pos+i, &V_DISPATCH(rgVar+i));
610 if(FAILED(hres))
611 break;
613 if(FAILED(hres)) {
614 while(i--)
615 VariantClear(rgVar+i);
616 return hres;
619 if(pCeltFetched)
620 *pCeltFetched = i;
621 This->pos += i;
622 return S_OK;
625 static HRESULT WINAPI MatchCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt)
627 MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
629 TRACE("(%p)->(%u)\n", This, celt);
631 if(This->pos+celt <= This->count)
632 This->pos += celt;
633 else
634 This->pos = This->count;
635 return S_OK;
638 static HRESULT WINAPI MatchCollectionEnum_Reset(IEnumVARIANT *iface)
640 MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
642 TRACE("(%p)\n", This);
644 This->pos = 0;
645 return S_OK;
648 static HRESULT WINAPI MatchCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
650 MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
651 FIXME("(%p)->(%p)\n", This, ppEnum);
652 return E_NOTIMPL;
655 static const IEnumVARIANTVtbl MatchCollectionEnum_Vtbl = {
656 MatchCollectionEnum_QueryInterface,
657 MatchCollectionEnum_AddRef,
658 MatchCollectionEnum_Release,
659 MatchCollectionEnum_Next,
660 MatchCollectionEnum_Skip,
661 MatchCollectionEnum_Reset,
662 MatchCollectionEnum_Clone
665 static HRESULT create_enum_variant_mc2(IMatchCollection2 *mc, ULONG pos, IEnumVARIANT **enum_variant)
667 MatchCollectionEnum *ret;
669 ret = heap_alloc_zero(sizeof(*ret));
670 if(!ret)
671 return E_OUTOFMEMORY;
673 ret->IEnumVARIANT_iface.lpVtbl = &MatchCollectionEnum_Vtbl;
674 ret->ref = 1;
675 ret->pos = pos;
676 IMatchCollection2_get_Count(mc, &ret->count);
677 ret->mc = mc;
678 IMatchCollection2_AddRef(mc);
680 *enum_variant = &ret->IEnumVARIANT_iface;
681 return S_OK;
684 static inline MatchCollection2* impl_from_IMatchCollection2(IMatchCollection2 *iface)
686 return CONTAINING_RECORD(iface, MatchCollection2, IMatchCollection2_iface);
689 static HRESULT WINAPI MatchCollection2_QueryInterface(
690 IMatchCollection2 *iface, REFIID riid, void **ppv)
692 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
694 if(IsEqualGUID(riid, &IID_IUnknown)) {
695 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
696 *ppv = &This->IMatchCollection2_iface;
697 }else if(IsEqualGUID(riid, &IID_IDispatch)) {
698 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
699 *ppv = &This->IMatchCollection2_iface;
700 }else if(IsEqualGUID(riid, &IID_IMatchCollection2)) {
701 TRACE("(%p)->(IID_IMatchCollection2 %p)\n", This, ppv);
702 *ppv = &This->IMatchCollection2_iface;
703 }else if(IsEqualGUID(riid, &IID_IDispatchEx)) {
704 TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
705 *ppv = NULL;
706 return E_NOINTERFACE;
707 }else {
708 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
709 *ppv = NULL;
710 return E_NOINTERFACE;
713 IUnknown_AddRef((IUnknown*)*ppv);
714 return S_OK;
717 static ULONG WINAPI MatchCollection2_AddRef(IMatchCollection2 *iface)
719 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
720 LONG ref = InterlockedIncrement(&This->ref);
722 TRACE("(%p) ref=%d\n", This, ref);
724 return ref;
727 static ULONG WINAPI MatchCollection2_Release(IMatchCollection2 *iface)
729 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
730 LONG ref = InterlockedDecrement(&This->ref);
732 TRACE("(%p) ref=%d\n", This, ref);
734 if(!ref) {
735 DWORD i;
737 for(i=0; i<This->count; i++)
738 IMatch2_Release(This->matches[i]);
739 heap_free(This->matches);
741 heap_free(This);
744 return ref;
747 static HRESULT WINAPI MatchCollection2_GetTypeInfoCount(IMatchCollection2 *iface, UINT *pctinfo)
749 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
751 TRACE("(%p)->(%p)\n", This, pctinfo);
753 *pctinfo = 1;
754 return S_OK;
757 static HRESULT WINAPI MatchCollection2_GetTypeInfo(IMatchCollection2 *iface,
758 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
760 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
761 FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
762 return E_NOTIMPL;
765 static HRESULT WINAPI MatchCollection2_GetIDsOfNames(IMatchCollection2 *iface,
766 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
768 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
770 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
771 rgszNames, cNames, lcid, rgDispId);
773 return ITypeInfo_GetIDsOfNames(typeinfos[MatchCollection2_tid], rgszNames, cNames, rgDispId);
776 static HRESULT WINAPI MatchCollection2_Invoke(IMatchCollection2 *iface, DISPID dispIdMember,
777 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
778 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
780 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
782 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
783 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
785 return ITypeInfo_Invoke(typeinfos[MatchCollection2_tid], iface, dispIdMember, wFlags,
786 pDispParams, pVarResult, pExcepInfo, puArgErr);
789 static HRESULT WINAPI MatchCollection2_get_Item(IMatchCollection2 *iface,
790 LONG index, IDispatch **ppMatch)
792 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
794 TRACE("(%p)->()\n", This);
796 if(!ppMatch)
797 return E_POINTER;
799 if(index<0 || index>=This->count)
800 return E_INVALIDARG;
802 *ppMatch = (IDispatch*)This->matches[index];
803 IMatch2_AddRef(This->matches[index]);
804 return S_OK;
807 static HRESULT WINAPI MatchCollection2_get_Count(IMatchCollection2 *iface, LONG *pCount)
809 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
811 TRACE("(%p)->()\n", This);
813 if(!pCount)
814 return E_POINTER;
816 *pCount = This->count;
817 return S_OK;
820 static HRESULT WINAPI MatchCollection2_get__NewEnum(IMatchCollection2 *iface, IUnknown **ppEnum)
822 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
824 TRACE("(%p)->(%p)\n", This, ppEnum);
826 if(!ppEnum)
827 return E_POINTER;
829 return create_enum_variant_mc2(&This->IMatchCollection2_iface, 0, (IEnumVARIANT**)ppEnum);
832 static const IMatchCollection2Vtbl MatchCollection2Vtbl = {
833 MatchCollection2_QueryInterface,
834 MatchCollection2_AddRef,
835 MatchCollection2_Release,
836 MatchCollection2_GetTypeInfoCount,
837 MatchCollection2_GetTypeInfo,
838 MatchCollection2_GetIDsOfNames,
839 MatchCollection2_Invoke,
840 MatchCollection2_get_Item,
841 MatchCollection2_get_Count,
842 MatchCollection2_get__NewEnum
845 static HRESULT add_match(IMatchCollection2 *iface, IMatch2 *add)
847 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
849 TRACE("(%p)->(%p)\n", This, add);
851 if(!This->size) {
852 This->matches = heap_alloc(8*sizeof(IMatch*));
853 if(!This->matches)
854 return E_OUTOFMEMORY;
855 This->size = 8;
856 }else if(This->size == This->count) {
857 IMatch2 **new_matches = heap_realloc(This->matches, 2*This->size*sizeof(IMatch*));
858 if(!new_matches)
859 return E_OUTOFMEMORY;
861 This->matches = new_matches;
862 This->size <<= 1;
865 This->matches[This->count++] = add;
866 IMatch2_AddRef(add);
867 return S_OK;
870 static HRESULT create_match_collection2(IMatchCollection2 **match_collection)
872 MatchCollection2 *ret;
873 HRESULT hres;
875 hres = init_regexp_typeinfo(MatchCollection2_tid);
876 if(FAILED(hres))
877 return hres;
879 ret = heap_alloc_zero(sizeof(*ret));
880 if(!ret)
881 return E_OUTOFMEMORY;
883 ret->IMatchCollection2_iface.lpVtbl = &MatchCollection2Vtbl;
885 ret->ref = 1;
886 *match_collection = &ret->IMatchCollection2_iface;
887 return S_OK;
890 static inline RegExp2 *impl_from_IRegExp2(IRegExp2 *iface)
892 return CONTAINING_RECORD(iface, RegExp2, IRegExp2_iface);
895 static HRESULT WINAPI RegExp2_QueryInterface(IRegExp2 *iface, REFIID riid, void **ppv)
897 RegExp2 *This = impl_from_IRegExp2(iface);
899 if(IsEqualGUID(riid, &IID_IUnknown)) {
900 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
901 *ppv = &This->IRegExp2_iface;
902 }else if(IsEqualGUID(riid, &IID_IDispatch)) {
903 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
904 *ppv = &This->IRegExp2_iface;
905 }else if(IsEqualGUID(riid, &IID_IRegExp2)) {
906 TRACE("(%p)->(IID_IRegExp2 %p)\n", This, ppv);
907 *ppv = &This->IRegExp2_iface;
908 }else if(IsEqualGUID(riid, &IID_IRegExp)) {
909 TRACE("(%p)->(IID_IRegExp %p)\n", This, ppv);
910 *ppv = &This->IRegExp_iface;
911 }else if(IsEqualGUID(riid, &IID_IDispatchEx)) {
912 TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
913 *ppv = NULL;
914 return E_NOINTERFACE;
915 }else {
916 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
917 *ppv = NULL;
918 return E_NOINTERFACE;
921 IUnknown_AddRef((IUnknown*)*ppv);
922 return S_OK;
925 static ULONG WINAPI RegExp2_AddRef(IRegExp2 *iface)
927 RegExp2 *This = impl_from_IRegExp2(iface);
928 LONG ref = InterlockedIncrement(&This->ref);
930 TRACE("(%p) ref=%d\n", This, ref);
932 return ref;
935 static ULONG WINAPI RegExp2_Release(IRegExp2 *iface)
937 RegExp2 *This = impl_from_IRegExp2(iface);
938 LONG ref = InterlockedDecrement(&This->ref);
940 TRACE("(%p) ref=%d\n", This, ref);
942 if(!ref) {
943 heap_free(This->pattern);
944 if(This->regexp)
945 regexp_destroy(This->regexp);
946 heap_pool_free(&This->pool);
947 heap_free(This);
950 return ref;
953 static HRESULT WINAPI RegExp2_GetTypeInfoCount(IRegExp2 *iface, UINT *pctinfo)
955 RegExp2 *This = impl_from_IRegExp2(iface);
957 TRACE("(%p)->(%p)\n", This, pctinfo);
959 *pctinfo = 1;
960 return S_OK;
963 static HRESULT WINAPI RegExp2_GetTypeInfo(IRegExp2 *iface,
964 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
966 RegExp2 *This = impl_from_IRegExp2(iface);
967 FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
968 return E_NOTIMPL;
971 static HRESULT WINAPI RegExp2_GetIDsOfNames(IRegExp2 *iface, REFIID riid,
972 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
974 RegExp2 *This = impl_from_IRegExp2(iface);
976 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
977 rgszNames, cNames, lcid, rgDispId);
979 return ITypeInfo_GetIDsOfNames(typeinfos[RegExp2_tid], rgszNames, cNames, rgDispId);
982 static HRESULT WINAPI RegExp2_Invoke(IRegExp2 *iface, DISPID dispIdMember,
983 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
984 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
986 RegExp2 *This = impl_from_IRegExp2(iface);
988 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
989 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
991 return ITypeInfo_Invoke(typeinfos[RegExp2_tid], iface, dispIdMember, wFlags,
992 pDispParams, pVarResult, pExcepInfo, puArgErr);
995 static HRESULT WINAPI RegExp2_get_Pattern(IRegExp2 *iface, BSTR *pPattern)
997 RegExp2 *This = impl_from_IRegExp2(iface);
999 TRACE("(%p)->(%p)\n", This, pPattern);
1001 if(!pPattern)
1002 return E_POINTER;
1004 if(!This->pattern) {
1005 *pPattern = NULL;
1006 return S_OK;
1009 *pPattern = SysAllocString(This->pattern);
1010 return *pPattern ? S_OK : E_OUTOFMEMORY;
1013 static HRESULT WINAPI RegExp2_put_Pattern(IRegExp2 *iface, BSTR pattern)
1015 RegExp2 *This = impl_from_IRegExp2(iface);
1016 WCHAR *p;
1017 DWORD size;
1019 TRACE("(%p)->(%s)\n", This, wine_dbgstr_w(pattern));
1021 if(!pattern) {
1022 heap_free(This->pattern);
1023 if(This->regexp) {
1024 regexp_destroy(This->regexp);
1025 This->regexp = NULL;
1027 This->pattern = NULL;
1028 return S_OK;
1031 size = (SysStringLen(pattern)+1) * sizeof(WCHAR);
1032 p = heap_alloc(size);
1033 if(!p)
1034 return E_OUTOFMEMORY;
1036 heap_free(This->pattern);
1037 This->pattern = p;
1038 memcpy(p, pattern, size);
1039 if(This->regexp) {
1040 regexp_destroy(This->regexp);
1041 This->regexp = NULL;
1043 return S_OK;
1046 static HRESULT WINAPI RegExp2_get_IgnoreCase(IRegExp2 *iface, VARIANT_BOOL *pIgnoreCase)
1048 RegExp2 *This = impl_from_IRegExp2(iface);
1050 TRACE("(%p)->(%p)\n", This, pIgnoreCase);
1052 if(!pIgnoreCase)
1053 return E_POINTER;
1055 *pIgnoreCase = This->flags & REG_FOLD ? VARIANT_TRUE : VARIANT_FALSE;
1056 return S_OK;
1059 static HRESULT WINAPI RegExp2_put_IgnoreCase(IRegExp2 *iface, VARIANT_BOOL ignoreCase)
1061 RegExp2 *This = impl_from_IRegExp2(iface);
1063 TRACE("(%p)->(%s)\n", This, ignoreCase ? "true" : "false");
1065 if(ignoreCase)
1066 This->flags |= REG_FOLD;
1067 else
1068 This->flags &= ~REG_FOLD;
1069 return S_OK;
1072 static HRESULT WINAPI RegExp2_get_Global(IRegExp2 *iface, VARIANT_BOOL *pGlobal)
1074 RegExp2 *This = impl_from_IRegExp2(iface);
1076 TRACE("(%p)->(%p)\n", This, pGlobal);
1078 if(!pGlobal)
1079 return E_POINTER;
1081 *pGlobal = This->flags & REG_GLOB ? VARIANT_TRUE : VARIANT_FALSE;
1082 return S_OK;
1085 static HRESULT WINAPI RegExp2_put_Global(IRegExp2 *iface, VARIANT_BOOL global)
1087 RegExp2 *This = impl_from_IRegExp2(iface);
1089 TRACE("(%p)->(%s)\n", This, global ? "true" : "false");
1091 if(global)
1092 This->flags |= REG_GLOB;
1093 else
1094 This->flags &= ~REG_GLOB;
1095 return S_OK;
1098 static HRESULT WINAPI RegExp2_get_Multiline(IRegExp2 *iface, VARIANT_BOOL *pMultiline)
1100 RegExp2 *This = impl_from_IRegExp2(iface);
1102 TRACE("(%p)->(%p)\n", This, pMultiline);
1104 if(!pMultiline)
1105 return E_POINTER;
1107 *pMultiline = This->flags & REG_MULTILINE ? VARIANT_TRUE : VARIANT_FALSE;
1108 return S_OK;
1111 static HRESULT WINAPI RegExp2_put_Multiline(IRegExp2 *iface, VARIANT_BOOL multiline)
1113 RegExp2 *This = impl_from_IRegExp2(iface);
1115 TRACE("(%p)->(%s)\n", This, multiline ? "true" : "false");
1117 if(multiline)
1118 This->flags |= REG_MULTILINE;
1119 else
1120 This->flags &= ~REG_MULTILINE;
1121 return S_OK;
1124 static HRESULT WINAPI RegExp2_Execute(IRegExp2 *iface,
1125 BSTR sourceString, IDispatch **ppMatches)
1127 RegExp2 *This = impl_from_IRegExp2(iface);
1128 match_state_t *result;
1129 const WCHAR *pos;
1130 IMatchCollection2 *match_collection;
1131 IMatch2 *add = NULL;
1132 HRESULT hres;
1134 TRACE("(%p)->(%s %p)\n", This, debugstr_w(sourceString), ppMatches);
1136 if(!This->pattern) {
1137 DWORD i, len = SysStringLen(sourceString);
1139 hres = create_match_collection2(&match_collection);
1140 if(FAILED(hres))
1141 return hres;
1143 for(i=0; i<=len; i++) {
1144 hres = create_match2(i, NULL, &add);
1145 if(FAILED(hres))
1146 break;
1148 hres = add_match(match_collection, add);
1149 if(FAILED(hres))
1150 break;
1151 IMatch2_Release(add);
1153 if(!(This->flags & REG_GLOB))
1154 break;
1157 if(FAILED(hres)) {
1158 IMatchCollection2_Release(match_collection);
1159 return hres;
1162 *ppMatches = (IDispatch*)match_collection;
1163 return S_OK;
1166 if(!This->regexp) {
1167 This->regexp = regexp_new(NULL, &This->pool, This->pattern,
1168 strlenW(This->pattern), This->flags, FALSE);
1169 if(!This->regexp)
1170 return E_FAIL;
1171 }else {
1172 hres = regexp_set_flags(&This->regexp, NULL, &This->pool, This->flags);
1173 if(FAILED(hres))
1174 return hres;
1177 hres = create_match_collection2(&match_collection);
1178 if(FAILED(hres))
1179 return hres;
1181 pos = sourceString;
1182 while(1) {
1183 result = alloc_match_state(This->regexp, NULL, pos);
1184 if(!result) {
1185 hres = E_OUTOFMEMORY;
1186 break;
1189 hres = regexp_execute(This->regexp, NULL, &This->pool,
1190 sourceString, SysStringLen(sourceString), result);
1191 if(hres != S_OK) {
1192 heap_free(result);
1193 break;
1195 pos = result->cp;
1197 hres = create_match2(result->cp-result->match_len-sourceString, &result, &add);
1198 heap_free(result);
1199 if(FAILED(hres))
1200 break;
1201 hres = add_match(match_collection, add);
1202 IMatch2_Release(add);
1203 if(FAILED(hres))
1204 break;
1206 if(!(This->flags & REG_GLOB))
1207 break;
1210 if(FAILED(hres)) {
1211 IMatchCollection2_Release(match_collection);
1212 return hres;
1215 *ppMatches = (IDispatch*)match_collection;
1216 return S_OK;
1219 static HRESULT WINAPI RegExp2_Test(IRegExp2 *iface, BSTR sourceString, VARIANT_BOOL *pMatch)
1221 RegExp2 *This = impl_from_IRegExp2(iface);
1222 match_state_t *result;
1223 heap_pool_t *mark;
1224 HRESULT hres;
1226 TRACE("(%p)->(%s %p)\n", This, debugstr_w(sourceString), pMatch);
1228 if(!This->pattern) {
1229 *pMatch = VARIANT_TRUE;
1230 return S_OK;
1233 if(!This->regexp) {
1234 This->regexp = regexp_new(NULL, &This->pool, This->pattern,
1235 strlenW(This->pattern), This->flags, FALSE);
1236 if(!This->regexp)
1237 return E_FAIL;
1238 }else {
1239 hres = regexp_set_flags(&This->regexp, NULL, &This->pool, This->flags);
1240 if(FAILED(hres))
1241 return hres;
1244 mark = heap_pool_mark(&This->pool);
1245 result = alloc_match_state(This->regexp, &This->pool, sourceString);
1246 if(!result) {
1247 heap_pool_clear(mark);
1248 return E_OUTOFMEMORY;
1251 hres = regexp_execute(This->regexp, NULL, &This->pool,
1252 sourceString, SysStringLen(sourceString), result);
1254 heap_pool_clear(mark);
1256 if(hres == S_OK) {
1257 *pMatch = VARIANT_TRUE;
1258 }else if(hres == S_FALSE) {
1259 *pMatch = VARIANT_FALSE;
1260 hres = S_OK;
1262 return hres;
1265 static HRESULT WINAPI RegExp2_Replace(IRegExp2 *iface, BSTR sourceString,
1266 VARIANT replaceVar, BSTR *pDestString)
1268 RegExp2 *This = impl_from_IRegExp2(iface);
1269 FIXME("(%p)->(%s %s %p)\n", This, debugstr_w(sourceString),
1270 debugstr_variant(&replaceVar), pDestString);
1271 return E_NOTIMPL;
1274 static const IRegExp2Vtbl RegExp2Vtbl = {
1275 RegExp2_QueryInterface,
1276 RegExp2_AddRef,
1277 RegExp2_Release,
1278 RegExp2_GetTypeInfoCount,
1279 RegExp2_GetTypeInfo,
1280 RegExp2_GetIDsOfNames,
1281 RegExp2_Invoke,
1282 RegExp2_get_Pattern,
1283 RegExp2_put_Pattern,
1284 RegExp2_get_IgnoreCase,
1285 RegExp2_put_IgnoreCase,
1286 RegExp2_get_Global,
1287 RegExp2_put_Global,
1288 RegExp2_get_Multiline,
1289 RegExp2_put_Multiline,
1290 RegExp2_Execute,
1291 RegExp2_Test,
1292 RegExp2_Replace
1295 static inline RegExp2 *impl_from_IRegExp(IRegExp *iface)
1297 return CONTAINING_RECORD(iface, RegExp2, IRegExp_iface);
1300 static HRESULT WINAPI RegExp_QueryInterface(IRegExp *iface, REFIID riid, void **ppv)
1302 RegExp2 *This = impl_from_IRegExp(iface);
1303 return IRegExp2_QueryInterface(&This->IRegExp2_iface, riid, ppv);
1306 static ULONG WINAPI RegExp_AddRef(IRegExp *iface)
1308 RegExp2 *This = impl_from_IRegExp(iface);
1309 return IRegExp2_AddRef(&This->IRegExp2_iface);
1312 static ULONG WINAPI RegExp_Release(IRegExp *iface)
1314 RegExp2 *This = impl_from_IRegExp(iface);
1315 return IRegExp2_Release(&This->IRegExp2_iface);
1318 static HRESULT WINAPI RegExp_GetTypeInfoCount(IRegExp *iface, UINT *pctinfo)
1320 RegExp2 *This = impl_from_IRegExp(iface);
1321 return IRegExp2_GetTypeInfoCount(&This->IRegExp2_iface, pctinfo);
1324 static HRESULT WINAPI RegExp_GetTypeInfo(IRegExp *iface,
1325 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1327 RegExp2 *This = impl_from_IRegExp(iface);
1328 return IRegExp2_GetTypeInfo(&This->IRegExp2_iface, iTInfo, lcid, ppTInfo);
1331 static HRESULT WINAPI RegExp_GetIDsOfNames(IRegExp *iface, REFIID riid,
1332 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1334 RegExp2 *This = impl_from_IRegExp(iface);
1335 return IRegExp2_GetIDsOfNames(&This->IRegExp2_iface, riid, rgszNames, cNames, lcid, rgDispId);
1338 static HRESULT WINAPI RegExp_Invoke(IRegExp *iface, DISPID dispIdMember,
1339 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1340 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1342 RegExp2 *This = impl_from_IRegExp(iface);
1343 return IRegExp2_Invoke(&This->IRegExp2_iface, dispIdMember, riid, lcid,
1344 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1347 static HRESULT WINAPI RegExp_get_Pattern(IRegExp *iface, BSTR *pPattern)
1349 RegExp2 *This = impl_from_IRegExp(iface);
1350 return IRegExp2_get_Pattern(&This->IRegExp2_iface, pPattern);
1353 static HRESULT WINAPI RegExp_put_Pattern(IRegExp *iface, BSTR pPattern)
1355 RegExp2 *This = impl_from_IRegExp(iface);
1356 return IRegExp2_put_Pattern(&This->IRegExp2_iface, pPattern);
1359 static HRESULT WINAPI RegExp_get_IgnoreCase(IRegExp *iface, VARIANT_BOOL *pIgnoreCase)
1361 RegExp2 *This = impl_from_IRegExp(iface);
1362 return IRegExp2_get_IgnoreCase(&This->IRegExp2_iface, pIgnoreCase);
1365 static HRESULT WINAPI RegExp_put_IgnoreCase(IRegExp *iface, VARIANT_BOOL pIgnoreCase)
1367 RegExp2 *This = impl_from_IRegExp(iface);
1368 return IRegExp2_put_IgnoreCase(&This->IRegExp2_iface, pIgnoreCase);
1371 static HRESULT WINAPI RegExp_get_Global(IRegExp *iface, VARIANT_BOOL *pGlobal)
1373 RegExp2 *This = impl_from_IRegExp(iface);
1374 return IRegExp2_get_Global(&This->IRegExp2_iface, pGlobal);
1377 static HRESULT WINAPI RegExp_put_Global(IRegExp *iface, VARIANT_BOOL pGlobal)
1379 RegExp2 *This = impl_from_IRegExp(iface);
1380 return IRegExp2_put_Global(&This->IRegExp2_iface, pGlobal);
1383 static HRESULT WINAPI RegExp_Execute(IRegExp *iface,
1384 BSTR sourceString, IDispatch **ppMatches)
1386 RegExp2 *This = impl_from_IRegExp(iface);
1387 return IRegExp2_Execute(&This->IRegExp2_iface, sourceString, ppMatches);
1390 static HRESULT WINAPI RegExp_Test(IRegExp *iface, BSTR sourceString, VARIANT_BOOL *pMatch)
1392 RegExp2 *This = impl_from_IRegExp(iface);
1393 return IRegExp2_Test(&This->IRegExp2_iface, sourceString, pMatch);
1396 static HRESULT WINAPI RegExp_Replace(IRegExp *iface, BSTR sourceString,
1397 BSTR replaceString, BSTR *pDestString)
1399 RegExp2 *This = impl_from_IRegExp(iface);
1400 VARIANT replace;
1402 V_VT(&replace) = VT_BSTR;
1403 V_BSTR(&replace) = replaceString;
1404 return IRegExp2_Replace(&This->IRegExp2_iface, sourceString, replace, pDestString);
1407 static IRegExpVtbl RegExpVtbl = {
1408 RegExp_QueryInterface,
1409 RegExp_AddRef,
1410 RegExp_Release,
1411 RegExp_GetTypeInfoCount,
1412 RegExp_GetTypeInfo,
1413 RegExp_GetIDsOfNames,
1414 RegExp_Invoke,
1415 RegExp_get_Pattern,
1416 RegExp_put_Pattern,
1417 RegExp_get_IgnoreCase,
1418 RegExp_put_IgnoreCase,
1419 RegExp_get_Global,
1420 RegExp_put_Global,
1421 RegExp_Execute,
1422 RegExp_Test,
1423 RegExp_Replace
1426 HRESULT WINAPI VBScriptRegExpFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, REFIID riid, void **ppv)
1428 RegExp2 *ret;
1429 HRESULT hres;
1431 TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv);
1433 hres = init_regexp_typeinfo(RegExp2_tid);
1434 if(FAILED(hres))
1435 return hres;
1437 ret = heap_alloc_zero(sizeof(*ret));
1438 if(!ret)
1439 return E_OUTOFMEMORY;
1441 ret->IRegExp2_iface.lpVtbl = &RegExp2Vtbl;
1442 ret->IRegExp_iface.lpVtbl = &RegExpVtbl;
1444 ret->ref = 1;
1445 heap_pool_init(&ret->pool);
1447 hres = IRegExp2_QueryInterface(&ret->IRegExp2_iface, riid, ppv);
1448 IRegExp2_Release(&ret->IRegExp2_iface);
1449 return hres;
1452 void release_regexp_typelib(void)
1454 DWORD i;
1456 for(i=0; i<REGEXP_LAST_tid; i++) {
1457 if(typeinfos[i])
1458 ITypeInfo_Release(typeinfos[i]);
1460 if(typelib)
1461 ITypeLib_Release(typelib);