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
);