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
21 #include "vbsregexp55.h"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
27 #define REGEXP_TID_LIST \
30 XDIID(MatchCollection2), \
34 #define XDIID(iface) iface ## _tid
40 static REFIID tid_ids[] = {
41 #define XDIID(iface) &IID_I ## iface
46 static ITypeLib *typelib;
47 static ITypeInfo *typeinfos[REGEXP_LAST_tid];
49 static HRESULT init_regexp_typeinfo(regexp_tid_t tid)
54 static const WCHAR vbscript_dll3W[] = {'v','b','s','c','r','i','p','t','.','d','l','l','\\','3',0};
57 hres = LoadTypeLib(vbscript_dll3W, &tl);
59 ERR("LoadRegTypeLib failed: %08x\n", hres);
63 if(InterlockedCompareExchangePointer((void**)&typelib, tl, NULL))
70 hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
72 ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hres);
76 if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
77 ITypeInfo_Release(ti);
84 ISubMatches ISubMatches_iface;
89 match_state_t *result;
92 typedef struct Match2 {
93 IMatch2 IMatch2_iface;
98 SubMatches *sub_matches;
101 typedef struct MatchCollectionEnum {
102 IEnumVARIANT IEnumVARIANT_iface;
106 IMatchCollection2 *mc;
109 } MatchCollectionEnum;
111 typedef struct MatchCollection2 {
112 IMatchCollection2 IMatchCollection2_iface;
121 typedef struct RegExp2 {
122 IRegExp2 IRegExp2_iface;
123 IRegExp IRegExp_iface;
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);
155 return E_NOINTERFACE;
157 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
159 return E_NOINTERFACE;
162 IUnknown_AddRef((IUnknown*)*ppv);
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);
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);
184 heap_free(This->match);
185 heap_free(This->result);
192 static HRESULT WINAPI SubMatches_GetTypeInfoCount(ISubMatches *iface, UINT *pctinfo)
194 SubMatches *This = impl_from_ISubMatches(iface);
196 TRACE("(%p)->(%p)\n", This, pctinfo);
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);
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);
244 if(!This->result || index<0 || index>=This->result->paren_count)
247 if(This->result->parens[index].index == -1) {
248 V_VT(pSubMatch) = VT_EMPTY;
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;
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);
274 *pCount = This->result->paren_count;
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);
285 static const ISubMatchesVtbl SubMatchesVtbl = {
286 SubMatches_QueryInterface,
289 SubMatches_GetTypeInfoCount,
290 SubMatches_GetTypeInfo,
291 SubMatches_GetIDsOfNames,
294 SubMatches_get_Count,
295 SubMatches_get__NewEnum
298 static HRESULT create_sub_matches(DWORD pos, match_state_t *result, SubMatches **sub_matches)
304 hres = init_regexp_typeinfo(SubMatches_tid);
308 ret = heap_alloc_zero(sizeof(*ret));
310 return E_OUTOFMEMORY;
312 ret->ISubMatches_iface.lpVtbl = &SubMatchesVtbl;
314 ret->result = result;
316 ret->match = heap_alloc((result->match_len+1) * sizeof(WCHAR));
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;
325 for(i=0; i<result->paren_count; i++)
326 if(result->parens[i].index != -1)
327 result->parens[i].index -= pos;
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);
359 return E_NOINTERFACE;
361 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
363 return E_NOINTERFACE;
366 IUnknown_AddRef((IUnknown*)*ppv);
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);
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);
388 ISubMatches_Release(&This->sub_matches->ISubMatches_iface);
395 static HRESULT WINAPI Match2_GetTypeInfoCount(IMatch2 *iface, UINT *pctinfo)
397 Match2 *This = impl_from_IMatch2(iface);
399 TRACE("(%p)->(%p)\n", This, pctinfo);
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);
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);
446 if(!This->sub_matches->match) {
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);
464 *pFirstIndex = This->index;
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);
477 if(This->sub_matches->result)
478 *pLength = This->sub_matches->result->match_len;
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);
493 *ppSubMatches = (IDispatch*)&This->sub_matches->ISubMatches_iface;
494 ISubMatches_AddRef(&This->sub_matches->ISubMatches_iface);
498 static const IMatch2Vtbl Match2Vtbl = {
499 Match2_QueryInterface,
502 Match2_GetTypeInfoCount,
504 Match2_GetIDsOfNames,
507 Match2_get_FirstIndex,
509 Match2_get_SubMatches
512 static HRESULT create_match2(DWORD pos, match_state_t **result, IMatch2 **match)
517 hres = init_regexp_typeinfo(Match2_tid);
521 ret = heap_alloc_zero(sizeof(*ret));
523 return E_OUTOFMEMORY;
526 hres = create_sub_matches(pos, result ? *result : NULL, &ret->sub_matches);
534 ret->IMatch2_iface.lpVtbl = &Match2Vtbl;
537 *match = &ret->IMatch2_iface;
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;
558 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
560 return E_NOINTERFACE;
563 IUnknown_AddRef((IUnknown*)*ppv);
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);
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);
585 IMatchCollection2_Release(This->mc);
592 static HRESULT WINAPI MatchCollectionEnum_Next(IEnumVARIANT *iface,
593 ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
595 MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
599 TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched);
601 if(This->pos>=This->count) {
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));
615 VariantClear(rgVar+i);
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)
634 This->pos = This->count;
638 static HRESULT WINAPI MatchCollectionEnum_Reset(IEnumVARIANT *iface)
640 MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
642 TRACE("(%p)\n", This);
648 static HRESULT WINAPI MatchCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
650 MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
651 FIXME("(%p)->(%p)\n", This, ppEnum);
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));
671 return E_OUTOFMEMORY;
673 ret->IEnumVARIANT_iface.lpVtbl = &MatchCollectionEnum_Vtbl;
676 IMatchCollection2_get_Count(mc, &ret->count);
678 IMatchCollection2_AddRef(mc);
680 *enum_variant = &ret->IEnumVARIANT_iface;
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);
706 return E_NOINTERFACE;
708 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
710 return E_NOINTERFACE;
713 IUnknown_AddRef((IUnknown*)*ppv);
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);
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);
737 for(i=0; i<This->count; i++)
738 IMatch2_Release(This->matches[i]);
739 heap_free(This->matches);
747 static HRESULT WINAPI MatchCollection2_GetTypeInfoCount(IMatchCollection2 *iface, UINT *pctinfo)
749 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
751 TRACE("(%p)->(%p)\n", This, pctinfo);
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);
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);
799 if(index<0 || index>=This->count)
802 *ppMatch = (IDispatch*)This->matches[index];
803 IMatch2_AddRef(This->matches[index]);
807 static HRESULT WINAPI MatchCollection2_get_Count(IMatchCollection2 *iface, LONG *pCount)
809 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
811 TRACE("(%p)->()\n", This);
816 *pCount = This->count;
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);
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);
852 This->matches = heap_alloc(8*sizeof(IMatch*));
854 return E_OUTOFMEMORY;
856 }else if(This->size == This->count) {
857 IMatch2 **new_matches = heap_realloc(This->matches, 2*This->size*sizeof(IMatch*));
859 return E_OUTOFMEMORY;
861 This->matches = new_matches;
865 This->matches[This->count++] = add;
870 static HRESULT create_match_collection2(IMatchCollection2 **match_collection)
872 MatchCollection2 *ret;
875 hres = init_regexp_typeinfo(MatchCollection2_tid);
879 ret = heap_alloc_zero(sizeof(*ret));
881 return E_OUTOFMEMORY;
883 ret->IMatchCollection2_iface.lpVtbl = &MatchCollection2Vtbl;
886 *match_collection = &ret->IMatchCollection2_iface;
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);
914 return E_NOINTERFACE;
916 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
918 return E_NOINTERFACE;
921 IUnknown_AddRef((IUnknown*)*ppv);
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);
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);
943 heap_free(This->pattern);
945 regexp_destroy(This->regexp);
946 heap_pool_free(&This->pool);
953 static HRESULT WINAPI RegExp2_GetTypeInfoCount(IRegExp2 *iface, UINT *pctinfo)
955 RegExp2 *This = impl_from_IRegExp2(iface);
957 TRACE("(%p)->(%p)\n", This, pctinfo);
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);
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);
1004 if(!This->pattern) {
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);
1019 TRACE("(%p)->(%s)\n", This, wine_dbgstr_w(pattern));
1022 heap_free(This->pattern);
1024 regexp_destroy(This->regexp);
1025 This->regexp = NULL;
1027 This->pattern = NULL;
1031 size = (SysStringLen(pattern)+1) * sizeof(WCHAR);
1032 p = heap_alloc(size);
1034 return E_OUTOFMEMORY;
1036 heap_free(This->pattern);
1038 memcpy(p, pattern, size);
1040 regexp_destroy(This->regexp);
1041 This->regexp = NULL;
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);
1055 *pIgnoreCase = This->flags & REG_FOLD ? VARIANT_TRUE : VARIANT_FALSE;
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");
1066 This->flags |= REG_FOLD;
1068 This->flags &= ~REG_FOLD;
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);
1081 *pGlobal = This->flags & REG_GLOB ? VARIANT_TRUE : VARIANT_FALSE;
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");
1092 This->flags |= REG_GLOB;
1094 This->flags &= ~REG_GLOB;
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);
1107 *pMultiline = This->flags & REG_MULTILINE ? VARIANT_TRUE : VARIANT_FALSE;
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");
1118 This->flags |= REG_MULTILINE;
1120 This->flags &= ~REG_MULTILINE;
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;
1130 IMatchCollection2 *match_collection;
1131 IMatch2 *add = NULL;
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);
1143 for(i=0; i<=len; i++) {
1144 hres = create_match2(i, NULL, &add);
1148 hres = add_match(match_collection, add);
1151 IMatch2_Release(add);
1153 if(!(This->flags & REG_GLOB))
1158 IMatchCollection2_Release(match_collection);
1162 *ppMatches = (IDispatch*)match_collection;
1167 This->regexp = regexp_new(NULL, &This->pool, This->pattern,
1168 strlenW(This->pattern), This->flags, FALSE);
1172 hres = regexp_set_flags(&This->regexp, NULL, &This->pool, This->flags);
1177 hres = create_match_collection2(&match_collection);
1183 result = alloc_match_state(This->regexp, NULL, pos);
1185 hres = E_OUTOFMEMORY;
1189 hres = regexp_execute(This->regexp, NULL, &This->pool,
1190 sourceString, SysStringLen(sourceString), result);
1197 hres = create_match2(result->cp-result->match_len-sourceString, &result, &add);
1201 hres = add_match(match_collection, add);
1202 IMatch2_Release(add);
1206 if(!(This->flags & REG_GLOB))
1211 IMatchCollection2_Release(match_collection);
1215 *ppMatches = (IDispatch*)match_collection;
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;
1226 TRACE("(%p)->(%s %p)\n", This, debugstr_w(sourceString), pMatch);
1228 if(!This->pattern) {
1229 *pMatch = VARIANT_TRUE;
1234 This->regexp = regexp_new(NULL, &This->pool, This->pattern,
1235 strlenW(This->pattern), This->flags, FALSE);
1239 hres = regexp_set_flags(&This->regexp, NULL, &This->pool, This->flags);
1244 mark = heap_pool_mark(&This->pool);
1245 result = alloc_match_state(This->regexp, &This->pool, sourceString);
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);
1257 *pMatch = VARIANT_TRUE;
1258 }else if(hres == S_FALSE) {
1259 *pMatch = VARIANT_FALSE;
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);
1274 static const IRegExp2Vtbl RegExp2Vtbl = {
1275 RegExp2_QueryInterface,
1278 RegExp2_GetTypeInfoCount,
1279 RegExp2_GetTypeInfo,
1280 RegExp2_GetIDsOfNames,
1282 RegExp2_get_Pattern,
1283 RegExp2_put_Pattern,
1284 RegExp2_get_IgnoreCase,
1285 RegExp2_put_IgnoreCase,
1288 RegExp2_get_Multiline,
1289 RegExp2_put_Multiline,
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);
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,
1411 RegExp_GetTypeInfoCount,
1413 RegExp_GetIDsOfNames,
1417 RegExp_get_IgnoreCase,
1418 RegExp_put_IgnoreCase,
1426 HRESULT WINAPI VBScriptRegExpFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, REFIID riid, void **ppv)
1431 TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv);
1433 hres = init_regexp_typeinfo(RegExp2_tid);
1437 ret = heap_alloc_zero(sizeof(*ret));
1439 return E_OUTOFMEMORY;
1441 ret->IRegExp2_iface.lpVtbl = &RegExp2Vtbl;
1442 ret->IRegExp_iface.lpVtbl = &RegExpVtbl;
1445 heap_pool_init(&ret->pool);
1447 hres = IRegExp2_QueryInterface(&ret->IRegExp2_iface, riid, ppv);
1448 IRegExp2_Release(&ret->IRegExp2_iface);
1452 void release_regexp_typelib(void)
1456 for(i=0; i<REGEXP_LAST_tid; i++) {
1458 ITypeInfo_Release(typeinfos[i]);
1461 ITypeLib_Release(typelib);