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"
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(vbscript
);
28 #define REGEXP_TID_LIST \
31 XDIID(MatchCollection2), \
35 #define XDIID(iface) iface ## _tid
41 static REFIID tid_ids
[] = {
42 #define XDIID(iface) &IID_I ## iface
47 static ITypeLib
*typelib
;
48 static ITypeInfo
*typeinfos
[REGEXP_LAST_tid
];
50 static HRESULT
init_regexp_typeinfo(regexp_tid_t tid
)
57 hres
= LoadTypeLib(L
"vbscript.dll\\3", &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
;
99 SubMatches
*sub_matches
;
102 typedef struct MatchCollectionEnum
{
103 IEnumVARIANT IEnumVARIANT_iface
;
107 IMatchCollection2
*mc
;
110 } MatchCollectionEnum
;
112 typedef struct MatchCollection2
{
113 IMatchCollection2 IMatchCollection2_iface
;
114 IMatchCollection IMatchCollection_iface
;
123 typedef struct RegExp2
{
124 IRegExp2 IRegExp2_iface
;
125 IRegExp IRegExp_iface
;
135 static inline SubMatches
* impl_from_ISubMatches(ISubMatches
*iface
)
137 return CONTAINING_RECORD(iface
, SubMatches
, ISubMatches_iface
);
140 static HRESULT WINAPI
SubMatches_QueryInterface(
141 ISubMatches
*iface
, REFIID riid
, void **ppv
)
143 SubMatches
*This
= impl_from_ISubMatches(iface
);
145 if(IsEqualGUID(riid
, &IID_IUnknown
)) {
146 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
147 *ppv
= &This
->ISubMatches_iface
;
148 }else if(IsEqualGUID(riid
, &IID_IDispatch
)) {
149 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
150 *ppv
= &This
->ISubMatches_iface
;
151 }else if(IsEqualGUID(riid
, &IID_ISubMatches
)) {
152 TRACE("(%p)->(IID_ISubMatches %p)\n", This
, ppv
);
153 *ppv
= &This
->ISubMatches_iface
;
154 }else if(IsEqualGUID(riid
, &IID_IDispatchEx
)) {
155 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
157 return E_NOINTERFACE
;
159 FIXME("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
161 return E_NOINTERFACE
;
164 IUnknown_AddRef((IUnknown
*)*ppv
);
168 static ULONG WINAPI
SubMatches_AddRef(ISubMatches
*iface
)
170 SubMatches
*This
= impl_from_ISubMatches(iface
);
171 LONG ref
= InterlockedIncrement(&This
->ref
);
173 TRACE("(%p) ref=%d\n", This
, ref
);
178 static ULONG WINAPI
SubMatches_Release(ISubMatches
*iface
)
180 SubMatches
*This
= impl_from_ISubMatches(iface
);
181 LONG ref
= InterlockedDecrement(&This
->ref
);
183 TRACE("(%p) ref=%d\n", This
, ref
);
186 heap_free(This
->match
);
187 heap_free(This
->result
);
194 static HRESULT WINAPI
SubMatches_GetTypeInfoCount(ISubMatches
*iface
, UINT
*pctinfo
)
196 SubMatches
*This
= impl_from_ISubMatches(iface
);
198 TRACE("(%p)->(%p)\n", This
, pctinfo
);
204 static HRESULT WINAPI
SubMatches_GetTypeInfo(ISubMatches
*iface
,
205 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
207 SubMatches
*This
= impl_from_ISubMatches(iface
);
208 FIXME("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
212 static HRESULT WINAPI
SubMatches_GetIDsOfNames(ISubMatches
*iface
,
213 REFIID riid
, LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
215 SubMatches
*This
= impl_from_ISubMatches(iface
);
217 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
218 rgszNames
, cNames
, lcid
, rgDispId
);
220 return ITypeInfo_GetIDsOfNames(typeinfos
[SubMatches_tid
], rgszNames
, cNames
, rgDispId
);
223 static HRESULT WINAPI
SubMatches_Invoke(ISubMatches
*iface
, DISPID dispIdMember
,
224 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
225 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
227 SubMatches
*This
= impl_from_ISubMatches(iface
);
229 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
230 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
232 return ITypeInfo_Invoke(typeinfos
[SubMatches_tid
], iface
, dispIdMember
, wFlags
,
233 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
236 static HRESULT WINAPI
SubMatches_get_Item(ISubMatches
*iface
,
237 LONG index
, VARIANT
*pSubMatch
)
239 SubMatches
*This
= impl_from_ISubMatches(iface
);
241 TRACE("(%p)->(%d %p)\n", This
, index
, pSubMatch
);
246 if(!This
->result
|| index
<0 || index
>=This
->result
->paren_count
)
249 if(This
->result
->parens
[index
].index
== -1) {
250 V_VT(pSubMatch
) = VT_EMPTY
;
252 V_VT(pSubMatch
) = VT_BSTR
;
253 V_BSTR(pSubMatch
) = SysAllocStringLen(
254 This
->match
+This
->result
->parens
[index
].index
,
255 This
->result
->parens
[index
].length
);
257 if(!V_BSTR(pSubMatch
))
258 return E_OUTOFMEMORY
;
264 static HRESULT WINAPI
SubMatches_get_Count(ISubMatches
*iface
, LONG
*pCount
)
266 SubMatches
*This
= impl_from_ISubMatches(iface
);
268 TRACE("(%p)->(%p)\n", This
, pCount
);
276 *pCount
= This
->result
->paren_count
;
280 static HRESULT WINAPI
SubMatches_get__NewEnum(ISubMatches
*iface
, IUnknown
**ppEnum
)
282 SubMatches
*This
= impl_from_ISubMatches(iface
);
283 FIXME("(%p)->(%p)\n", This
, ppEnum
);
287 static const ISubMatchesVtbl SubMatchesVtbl
= {
288 SubMatches_QueryInterface
,
291 SubMatches_GetTypeInfoCount
,
292 SubMatches_GetTypeInfo
,
293 SubMatches_GetIDsOfNames
,
296 SubMatches_get_Count
,
297 SubMatches_get__NewEnum
300 static HRESULT
create_sub_matches(DWORD pos
, match_state_t
*result
, SubMatches
**sub_matches
)
306 hres
= init_regexp_typeinfo(SubMatches_tid
);
310 ret
= heap_alloc_zero(sizeof(*ret
));
312 return E_OUTOFMEMORY
;
314 ret
->ISubMatches_iface
.lpVtbl
= &SubMatchesVtbl
;
316 ret
->result
= result
;
318 ret
->match
= heap_alloc((result
->match_len
+1) * sizeof(WCHAR
));
321 return E_OUTOFMEMORY
;
323 memcpy(ret
->match
, result
->cp
-result
->match_len
, result
->match_len
*sizeof(WCHAR
));
324 ret
->match
[result
->match_len
] = 0;
327 for(i
=0; i
<result
->paren_count
; i
++)
328 if(result
->parens
[i
].index
!= -1)
329 result
->parens
[i
].index
-= pos
;
339 static inline Match2
* impl_from_IMatch2(IMatch2
*iface
)
341 return CONTAINING_RECORD(iface
, Match2
, IMatch2_iface
);
344 static HRESULT WINAPI
Match2_QueryInterface(
345 IMatch2
*iface
, REFIID riid
, void **ppv
)
347 Match2
*This
= impl_from_IMatch2(iface
);
349 if(IsEqualGUID(riid
, &IID_IUnknown
)) {
350 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
351 *ppv
= &This
->IMatch2_iface
;
352 }else if(IsEqualGUID(riid
, &IID_IDispatch
)) {
353 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
354 *ppv
= &This
->IMatch2_iface
;
355 }else if(IsEqualGUID(riid
, &IID_IMatch2
)) {
356 TRACE("(%p)->(IID_IMatch2 %p)\n", This
, ppv
);
357 *ppv
= &This
->IMatch2_iface
;
358 }else if(IsEqualGUID(riid
, &IID_IMatch
)) {
359 TRACE("(%p)->(IID_IMatch %p)\n", This
, ppv
);
360 *ppv
= &This
->IMatch_iface
;
361 }else if(IsEqualGUID(riid
, &IID_IDispatchEx
)) {
362 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
364 return E_NOINTERFACE
;
366 FIXME("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
368 return E_NOINTERFACE
;
371 IUnknown_AddRef((IUnknown
*)*ppv
);
375 static ULONG WINAPI
Match2_AddRef(IMatch2
*iface
)
377 Match2
*This
= impl_from_IMatch2(iface
);
378 LONG ref
= InterlockedIncrement(&This
->ref
);
380 TRACE("(%p) ref=%d\n", This
, ref
);
385 static ULONG WINAPI
Match2_Release(IMatch2
*iface
)
387 Match2
*This
= impl_from_IMatch2(iface
);
388 LONG ref
= InterlockedDecrement(&This
->ref
);
390 TRACE("(%p) ref=%d\n", This
, ref
);
393 ISubMatches_Release(&This
->sub_matches
->ISubMatches_iface
);
400 static HRESULT WINAPI
Match2_GetTypeInfoCount(IMatch2
*iface
, UINT
*pctinfo
)
402 Match2
*This
= impl_from_IMatch2(iface
);
404 TRACE("(%p)->(%p)\n", This
, pctinfo
);
410 static HRESULT WINAPI
Match2_GetTypeInfo(IMatch2
*iface
,
411 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
413 Match2
*This
= impl_from_IMatch2(iface
);
414 FIXME("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
418 static HRESULT WINAPI
Match2_GetIDsOfNames(IMatch2
*iface
,
419 REFIID riid
, LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
421 Match2
*This
= impl_from_IMatch2(iface
);
423 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
424 rgszNames
, cNames
, lcid
, rgDispId
);
426 return ITypeInfo_GetIDsOfNames(typeinfos
[Match2_tid
], rgszNames
, cNames
, rgDispId
);
429 static HRESULT WINAPI
Match2_Invoke(IMatch2
*iface
, DISPID dispIdMember
,
430 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
431 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
433 Match2
*This
= impl_from_IMatch2(iface
);
435 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
436 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
438 return ITypeInfo_Invoke(typeinfos
[Match2_tid
], iface
, dispIdMember
, wFlags
,
439 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
442 static HRESULT WINAPI
Match2_get_Value(IMatch2
*iface
, BSTR
*pValue
)
444 Match2
*This
= impl_from_IMatch2(iface
);
446 TRACE("(%p)->(%p)\n", This
, pValue
);
451 if(!This
->sub_matches
->match
) {
456 *pValue
= SysAllocString(This
->sub_matches
->match
);
457 return *pValue
? S_OK
: E_OUTOFMEMORY
;
460 static HRESULT WINAPI
Match2_get_FirstIndex(IMatch2
*iface
, LONG
*pFirstIndex
)
462 Match2
*This
= impl_from_IMatch2(iface
);
464 TRACE("(%p)->(%p)\n", This
, pFirstIndex
);
469 *pFirstIndex
= This
->index
;
473 static HRESULT WINAPI
Match2_get_Length(IMatch2
*iface
, LONG
*pLength
)
475 Match2
*This
= impl_from_IMatch2(iface
);
477 TRACE("(%p)->(%p)\n", This
, pLength
);
482 if(This
->sub_matches
->result
)
483 *pLength
= This
->sub_matches
->result
->match_len
;
489 static HRESULT WINAPI
Match2_get_SubMatches(IMatch2
*iface
, IDispatch
**ppSubMatches
)
491 Match2
*This
= impl_from_IMatch2(iface
);
493 TRACE("(%p)->(%p)\n", This
, ppSubMatches
);
498 *ppSubMatches
= (IDispatch
*)&This
->sub_matches
->ISubMatches_iface
;
499 ISubMatches_AddRef(&This
->sub_matches
->ISubMatches_iface
);
503 static const IMatch2Vtbl Match2Vtbl
= {
504 Match2_QueryInterface
,
507 Match2_GetTypeInfoCount
,
509 Match2_GetIDsOfNames
,
512 Match2_get_FirstIndex
,
514 Match2_get_SubMatches
517 static inline Match2
*impl_from_IMatch(IMatch
*iface
)
519 return CONTAINING_RECORD(iface
, Match2
, IMatch_iface
);
522 static HRESULT WINAPI
Match_QueryInterface(IMatch
*iface
, REFIID riid
, void **ppv
)
524 Match2
*This
= impl_from_IMatch(iface
);
525 return IMatch2_QueryInterface(&This
->IMatch2_iface
, riid
, ppv
);
528 static ULONG WINAPI
Match_AddRef(IMatch
*iface
)
530 Match2
*This
= impl_from_IMatch(iface
);
531 return IMatch2_AddRef(&This
->IMatch2_iface
);
534 static ULONG WINAPI
Match_Release(IMatch
*iface
)
536 Match2
*This
= impl_from_IMatch(iface
);
537 return IMatch2_Release(&This
->IMatch2_iface
);
540 static HRESULT WINAPI
Match_GetTypeInfoCount(IMatch
*iface
, UINT
*pctinfo
)
542 Match2
*This
= impl_from_IMatch(iface
);
543 return IMatch2_GetTypeInfoCount(&This
->IMatch2_iface
, pctinfo
);
546 static HRESULT WINAPI
Match_GetTypeInfo(IMatch
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
548 Match2
*This
= impl_from_IMatch(iface
);
549 return IMatch2_GetTypeInfo(&This
->IMatch2_iface
, iTInfo
, lcid
, ppTInfo
);
552 static HRESULT WINAPI
Match_GetIDsOfNames(IMatch
*iface
, REFIID riid
,
553 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
555 Match2
*This
= impl_from_IMatch(iface
);
556 return IMatch2_GetIDsOfNames(&This
->IMatch2_iface
, riid
, rgszNames
, cNames
, lcid
, rgDispId
);
559 static HRESULT WINAPI
Match_Invoke(IMatch
*iface
, DISPID dispIdMember
,
560 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
561 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
563 Match2
*This
= impl_from_IMatch(iface
);
564 return IMatch2_Invoke(&This
->IMatch2_iface
, dispIdMember
, riid
, lcid
,
565 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
568 static HRESULT WINAPI
Match_get_Value(IMatch
*iface
, BSTR
*pValue
)
570 Match2
*This
= impl_from_IMatch(iface
);
571 return IMatch2_get_Value(&This
->IMatch2_iface
, pValue
);
574 static HRESULT WINAPI
Match_get_FirstIndex(IMatch
*iface
, LONG
*pFirstIndex
)
576 Match2
*This
= impl_from_IMatch(iface
);
577 return IMatch2_get_FirstIndex(&This
->IMatch2_iface
, pFirstIndex
);
580 static HRESULT WINAPI
Match_get_Length(IMatch
*iface
, LONG
*pLength
)
582 Match2
*This
= impl_from_IMatch(iface
);
583 return IMatch2_get_Length(&This
->IMatch2_iface
, pLength
);
586 static IMatchVtbl MatchVtbl
= {
587 Match_QueryInterface
,
590 Match_GetTypeInfoCount
,
595 Match_get_FirstIndex
,
599 static HRESULT
create_match2(DWORD pos
, match_state_t
**result
, IMatch2
**match
)
604 hres
= init_regexp_typeinfo(Match2_tid
);
608 ret
= heap_alloc_zero(sizeof(*ret
));
610 return E_OUTOFMEMORY
;
613 hres
= create_sub_matches(pos
, result
? *result
: NULL
, &ret
->sub_matches
);
621 ret
->IMatch2_iface
.lpVtbl
= &Match2Vtbl
;
622 ret
->IMatch_iface
.lpVtbl
= &MatchVtbl
;
625 *match
= &ret
->IMatch2_iface
;
629 static inline MatchCollectionEnum
* impl_from_IMatchCollectionEnum(IEnumVARIANT
*iface
)
631 return CONTAINING_RECORD(iface
, MatchCollectionEnum
, IEnumVARIANT_iface
);
634 static HRESULT WINAPI
MatchCollectionEnum_QueryInterface(
635 IEnumVARIANT
*iface
, REFIID riid
, void **ppv
)
637 MatchCollectionEnum
*This
= impl_from_IMatchCollectionEnum(iface
);
639 if(IsEqualGUID(riid
, &IID_IUnknown
)) {
640 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
641 *ppv
= &This
->IEnumVARIANT_iface
;
642 }else if(IsEqualGUID(riid
, &IID_IEnumVARIANT
)) {
643 TRACE("(%p)->(IID_IEnumVARIANT %p)\n", This
, ppv
);
644 *ppv
= &This
->IEnumVARIANT_iface
;
646 FIXME("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
648 return E_NOINTERFACE
;
651 IUnknown_AddRef((IUnknown
*)*ppv
);
655 static ULONG WINAPI
MatchCollectionEnum_AddRef(IEnumVARIANT
*iface
)
657 MatchCollectionEnum
*This
= impl_from_IMatchCollectionEnum(iface
);
658 LONG ref
= InterlockedIncrement(&This
->ref
);
660 TRACE("(%p) ref=%d\n", This
, ref
);
665 static ULONG WINAPI
MatchCollectionEnum_Release(IEnumVARIANT
*iface
)
667 MatchCollectionEnum
*This
= impl_from_IMatchCollectionEnum(iface
);
668 LONG ref
= InterlockedDecrement(&This
->ref
);
670 TRACE("(%p) ref=%d\n", This
, ref
);
673 IMatchCollection2_Release(This
->mc
);
680 static HRESULT WINAPI
MatchCollectionEnum_Next(IEnumVARIANT
*iface
,
681 ULONG celt
, VARIANT
*rgVar
, ULONG
*pCeltFetched
)
683 MatchCollectionEnum
*This
= impl_from_IMatchCollectionEnum(iface
);
687 TRACE("(%p)->(%u %p %p)\n", This
, celt
, rgVar
, pCeltFetched
);
689 if(This
->pos
>=This
->count
) {
695 for(i
=0; i
<celt
&& This
->pos
+i
<This
->count
; i
++) {
696 V_VT(rgVar
+i
) = VT_DISPATCH
;
697 hres
= IMatchCollection2_get_Item(This
->mc
, This
->pos
+i
, &V_DISPATCH(rgVar
+i
));
703 VariantClear(rgVar
+i
);
713 static HRESULT WINAPI
MatchCollectionEnum_Skip(IEnumVARIANT
*iface
, ULONG celt
)
715 MatchCollectionEnum
*This
= impl_from_IMatchCollectionEnum(iface
);
717 TRACE("(%p)->(%u)\n", This
, celt
);
719 if(This
->pos
+celt
<= This
->count
)
722 This
->pos
= This
->count
;
726 static HRESULT WINAPI
MatchCollectionEnum_Reset(IEnumVARIANT
*iface
)
728 MatchCollectionEnum
*This
= impl_from_IMatchCollectionEnum(iface
);
730 TRACE("(%p)\n", This
);
736 static HRESULT WINAPI
MatchCollectionEnum_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**ppEnum
)
738 MatchCollectionEnum
*This
= impl_from_IMatchCollectionEnum(iface
);
739 FIXME("(%p)->(%p)\n", This
, ppEnum
);
743 static const IEnumVARIANTVtbl MatchCollectionEnum_Vtbl
= {
744 MatchCollectionEnum_QueryInterface
,
745 MatchCollectionEnum_AddRef
,
746 MatchCollectionEnum_Release
,
747 MatchCollectionEnum_Next
,
748 MatchCollectionEnum_Skip
,
749 MatchCollectionEnum_Reset
,
750 MatchCollectionEnum_Clone
753 static HRESULT
create_enum_variant_mc2(IMatchCollection2
*mc
, ULONG pos
, IEnumVARIANT
**enum_variant
)
755 MatchCollectionEnum
*ret
;
757 ret
= heap_alloc_zero(sizeof(*ret
));
759 return E_OUTOFMEMORY
;
761 ret
->IEnumVARIANT_iface
.lpVtbl
= &MatchCollectionEnum_Vtbl
;
764 IMatchCollection2_get_Count(mc
, &ret
->count
);
766 IMatchCollection2_AddRef(mc
);
768 *enum_variant
= &ret
->IEnumVARIANT_iface
;
772 static inline MatchCollection2
* impl_from_IMatchCollection2(IMatchCollection2
*iface
)
774 return CONTAINING_RECORD(iface
, MatchCollection2
, IMatchCollection2_iface
);
777 static HRESULT WINAPI
MatchCollection2_QueryInterface(
778 IMatchCollection2
*iface
, REFIID riid
, void **ppv
)
780 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
782 if(IsEqualGUID(riid
, &IID_IUnknown
)) {
783 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
784 *ppv
= &This
->IMatchCollection2_iface
;
785 }else if(IsEqualGUID(riid
, &IID_IDispatch
)) {
786 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
787 *ppv
= &This
->IMatchCollection2_iface
;
788 }else if(IsEqualGUID(riid
, &IID_IMatchCollection2
)) {
789 TRACE("(%p)->(IID_IMatchCollection2 %p)\n", This
, ppv
);
790 *ppv
= &This
->IMatchCollection2_iface
;
791 }else if(IsEqualGUID(riid
, &IID_IMatchCollection
)) {
792 TRACE("(%p)->(IID_IMatchCollection %p)\n", This
, ppv
);
793 *ppv
= &This
->IMatchCollection_iface
;
794 }else if(IsEqualGUID(riid
, &IID_IDispatchEx
)) {
795 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
797 return E_NOINTERFACE
;
799 FIXME("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
801 return E_NOINTERFACE
;
804 IUnknown_AddRef((IUnknown
*)*ppv
);
808 static ULONG WINAPI
MatchCollection2_AddRef(IMatchCollection2
*iface
)
810 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
811 LONG ref
= InterlockedIncrement(&This
->ref
);
813 TRACE("(%p) ref=%d\n", This
, ref
);
818 static ULONG WINAPI
MatchCollection2_Release(IMatchCollection2
*iface
)
820 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
821 LONG ref
= InterlockedDecrement(&This
->ref
);
823 TRACE("(%p) ref=%d\n", This
, ref
);
828 for(i
=0; i
<This
->count
; i
++)
829 IMatch2_Release(This
->matches
[i
]);
830 heap_free(This
->matches
);
838 static HRESULT WINAPI
MatchCollection2_GetTypeInfoCount(IMatchCollection2
*iface
, UINT
*pctinfo
)
840 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
842 TRACE("(%p)->(%p)\n", This
, pctinfo
);
848 static HRESULT WINAPI
MatchCollection2_GetTypeInfo(IMatchCollection2
*iface
,
849 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
851 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
852 FIXME("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
856 static HRESULT WINAPI
MatchCollection2_GetIDsOfNames(IMatchCollection2
*iface
,
857 REFIID riid
, LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
859 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
861 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
862 rgszNames
, cNames
, lcid
, rgDispId
);
864 return ITypeInfo_GetIDsOfNames(typeinfos
[MatchCollection2_tid
], rgszNames
, cNames
, rgDispId
);
867 static HRESULT WINAPI
MatchCollection2_Invoke(IMatchCollection2
*iface
, DISPID dispIdMember
,
868 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
869 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
871 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
873 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
874 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
876 return ITypeInfo_Invoke(typeinfos
[MatchCollection2_tid
], iface
, dispIdMember
, wFlags
,
877 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
880 static HRESULT WINAPI
MatchCollection2_get_Item(IMatchCollection2
*iface
,
881 LONG index
, IDispatch
**ppMatch
)
883 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
885 TRACE("(%p)->()\n", This
);
890 if(index
<0 || index
>=This
->count
)
893 *ppMatch
= (IDispatch
*)This
->matches
[index
];
894 IMatch2_AddRef(This
->matches
[index
]);
898 static HRESULT WINAPI
MatchCollection2_get_Count(IMatchCollection2
*iface
, LONG
*pCount
)
900 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
902 TRACE("(%p)->()\n", This
);
907 *pCount
= This
->count
;
911 static HRESULT WINAPI
MatchCollection2_get__NewEnum(IMatchCollection2
*iface
, IUnknown
**ppEnum
)
913 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
915 TRACE("(%p)->(%p)\n", This
, ppEnum
);
920 return create_enum_variant_mc2(&This
->IMatchCollection2_iface
, 0, (IEnumVARIANT
**)ppEnum
);
923 static const IMatchCollection2Vtbl MatchCollection2Vtbl
= {
924 MatchCollection2_QueryInterface
,
925 MatchCollection2_AddRef
,
926 MatchCollection2_Release
,
927 MatchCollection2_GetTypeInfoCount
,
928 MatchCollection2_GetTypeInfo
,
929 MatchCollection2_GetIDsOfNames
,
930 MatchCollection2_Invoke
,
931 MatchCollection2_get_Item
,
932 MatchCollection2_get_Count
,
933 MatchCollection2_get__NewEnum
936 static inline MatchCollection2
*impl_from_IMatchCollection(IMatchCollection
*iface
)
938 return CONTAINING_RECORD(iface
, MatchCollection2
, IMatchCollection_iface
);
941 static HRESULT WINAPI
MatchCollection_QueryInterface(IMatchCollection
*iface
, REFIID riid
, void **ppv
)
943 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
944 return IMatchCollection2_QueryInterface(&This
->IMatchCollection2_iface
, riid
, ppv
);
947 static ULONG WINAPI
MatchCollection_AddRef(IMatchCollection
*iface
)
949 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
950 return IMatchCollection2_AddRef(&This
->IMatchCollection2_iface
);
953 static ULONG WINAPI
MatchCollection_Release(IMatchCollection
*iface
)
955 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
956 return IMatchCollection2_Release(&This
->IMatchCollection2_iface
);
959 static HRESULT WINAPI
MatchCollection_GetTypeInfoCount(IMatchCollection
*iface
, UINT
*pctinfo
)
961 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
962 return IMatchCollection2_GetTypeInfoCount(&This
->IMatchCollection2_iface
, pctinfo
);
965 static HRESULT WINAPI
MatchCollection_GetTypeInfo(IMatchCollection
*iface
,
966 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
968 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
969 return IMatchCollection2_GetTypeInfo(&This
->IMatchCollection2_iface
, iTInfo
, lcid
, ppTInfo
);
972 static HRESULT WINAPI
MatchCollection_GetIDsOfNames(IMatchCollection
*iface
, REFIID riid
,
973 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
975 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
976 return IMatchCollection2_GetIDsOfNames(&This
->IMatchCollection2_iface
,
977 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
980 static HRESULT WINAPI
MatchCollection_Invoke(IMatchCollection
*iface
, DISPID dispIdMember
,
981 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
982 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
984 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
985 return IMatchCollection2_Invoke(&This
->IMatchCollection2_iface
, dispIdMember
,
986 riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
989 static HRESULT WINAPI
MatchCollection_get_Item(IMatchCollection
*iface
, LONG index
, IDispatch
**ppMatch
)
991 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
992 return IMatchCollection2_get_Item(&This
->IMatchCollection2_iface
, index
, ppMatch
);
995 static HRESULT WINAPI
MatchCollection_get_Count(IMatchCollection
*iface
, LONG
*pCount
)
997 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
998 return IMatchCollection2_get_Count(&This
->IMatchCollection2_iface
, pCount
);
1001 static HRESULT WINAPI
MatchCollection_get__NewEnum(IMatchCollection
*iface
, IUnknown
**ppEnum
)
1003 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
1004 return IMatchCollection2_get__NewEnum(&This
->IMatchCollection2_iface
, ppEnum
);
1007 static const IMatchCollectionVtbl MatchCollectionVtbl
= {
1008 MatchCollection_QueryInterface
,
1009 MatchCollection_AddRef
,
1010 MatchCollection_Release
,
1011 MatchCollection_GetTypeInfoCount
,
1012 MatchCollection_GetTypeInfo
,
1013 MatchCollection_GetIDsOfNames
,
1014 MatchCollection_Invoke
,
1015 MatchCollection_get_Item
,
1016 MatchCollection_get_Count
,
1017 MatchCollection_get__NewEnum
1020 static HRESULT
add_match(IMatchCollection2
*iface
, IMatch2
*add
)
1022 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
1024 TRACE("(%p)->(%p)\n", This
, add
);
1027 This
->matches
= heap_alloc(8*sizeof(IMatch
*));
1029 return E_OUTOFMEMORY
;
1031 }else if(This
->size
== This
->count
) {
1032 IMatch2
**new_matches
= heap_realloc(This
->matches
, 2*This
->size
*sizeof(IMatch
*));
1034 return E_OUTOFMEMORY
;
1036 This
->matches
= new_matches
;
1040 This
->matches
[This
->count
++] = add
;
1041 IMatch2_AddRef(add
);
1045 static HRESULT
create_match_collection2(IMatchCollection2
**match_collection
)
1047 MatchCollection2
*ret
;
1050 hres
= init_regexp_typeinfo(MatchCollection2_tid
);
1054 ret
= heap_alloc_zero(sizeof(*ret
));
1056 return E_OUTOFMEMORY
;
1058 ret
->IMatchCollection2_iface
.lpVtbl
= &MatchCollection2Vtbl
;
1059 ret
->IMatchCollection_iface
.lpVtbl
= &MatchCollectionVtbl
;
1062 *match_collection
= &ret
->IMatchCollection2_iface
;
1066 static inline RegExp2
*impl_from_IRegExp2(IRegExp2
*iface
)
1068 return CONTAINING_RECORD(iface
, RegExp2
, IRegExp2_iface
);
1071 static HRESULT WINAPI
RegExp2_QueryInterface(IRegExp2
*iface
, REFIID riid
, void **ppv
)
1073 RegExp2
*This
= impl_from_IRegExp2(iface
);
1075 if(IsEqualGUID(riid
, &IID_IUnknown
)) {
1076 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
1077 *ppv
= &This
->IRegExp2_iface
;
1078 }else if(IsEqualGUID(riid
, &IID_IDispatch
)) {
1079 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
1080 *ppv
= &This
->IRegExp2_iface
;
1081 }else if(IsEqualGUID(riid
, &IID_IRegExp2
)) {
1082 TRACE("(%p)->(IID_IRegExp2 %p)\n", This
, ppv
);
1083 *ppv
= &This
->IRegExp2_iface
;
1084 }else if(IsEqualGUID(riid
, &IID_IRegExp
)) {
1085 TRACE("(%p)->(IID_IRegExp %p)\n", This
, ppv
);
1086 *ppv
= &This
->IRegExp_iface
;
1087 }else if(IsEqualGUID(riid
, &IID_IDispatchEx
)) {
1088 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
1090 return E_NOINTERFACE
;
1092 FIXME("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
1094 return E_NOINTERFACE
;
1097 IUnknown_AddRef((IUnknown
*)*ppv
);
1101 static ULONG WINAPI
RegExp2_AddRef(IRegExp2
*iface
)
1103 RegExp2
*This
= impl_from_IRegExp2(iface
);
1104 LONG ref
= InterlockedIncrement(&This
->ref
);
1106 TRACE("(%p) ref=%d\n", This
, ref
);
1111 static ULONG WINAPI
RegExp2_Release(IRegExp2
*iface
)
1113 RegExp2
*This
= impl_from_IRegExp2(iface
);
1114 LONG ref
= InterlockedDecrement(&This
->ref
);
1116 TRACE("(%p) ref=%d\n", This
, ref
);
1119 heap_free(This
->pattern
);
1121 regexp_destroy(This
->regexp
);
1122 heap_pool_free(&This
->pool
);
1129 static HRESULT WINAPI
RegExp2_GetTypeInfoCount(IRegExp2
*iface
, UINT
*pctinfo
)
1131 RegExp2
*This
= impl_from_IRegExp2(iface
);
1133 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1139 static HRESULT WINAPI
RegExp2_GetTypeInfo(IRegExp2
*iface
,
1140 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
1142 RegExp2
*This
= impl_from_IRegExp2(iface
);
1143 FIXME("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1147 static HRESULT WINAPI
RegExp2_GetIDsOfNames(IRegExp2
*iface
, REFIID riid
,
1148 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1150 RegExp2
*This
= impl_from_IRegExp2(iface
);
1152 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
1153 rgszNames
, cNames
, lcid
, rgDispId
);
1155 return ITypeInfo_GetIDsOfNames(typeinfos
[RegExp2_tid
], rgszNames
, cNames
, rgDispId
);
1158 static HRESULT WINAPI
RegExp2_Invoke(IRegExp2
*iface
, DISPID dispIdMember
,
1159 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
1160 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1162 RegExp2
*This
= impl_from_IRegExp2(iface
);
1164 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1165 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1167 return ITypeInfo_Invoke(typeinfos
[RegExp2_tid
], iface
, dispIdMember
, wFlags
,
1168 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1171 static HRESULT WINAPI
RegExp2_get_Pattern(IRegExp2
*iface
, BSTR
*pPattern
)
1173 RegExp2
*This
= impl_from_IRegExp2(iface
);
1175 TRACE("(%p)->(%p)\n", This
, pPattern
);
1180 if(!This
->pattern
) {
1185 *pPattern
= SysAllocString(This
->pattern
);
1186 return *pPattern
? S_OK
: E_OUTOFMEMORY
;
1189 static HRESULT WINAPI
RegExp2_put_Pattern(IRegExp2
*iface
, BSTR pattern
)
1191 RegExp2
*This
= impl_from_IRegExp2(iface
);
1194 TRACE("(%p)->(%s)\n", This
, wine_dbgstr_w(pattern
));
1196 if(pattern
&& *pattern
) {
1197 SIZE_T size
= (SysStringLen(pattern
)+1) * sizeof(WCHAR
);
1198 new_pattern
= heap_alloc(size
);
1200 return E_OUTOFMEMORY
;
1201 memcpy(new_pattern
, pattern
, size
);
1206 heap_free(This
->pattern
);
1207 This
->pattern
= new_pattern
;
1210 regexp_destroy(This
->regexp
);
1211 This
->regexp
= NULL
;
1216 static HRESULT WINAPI
RegExp2_get_IgnoreCase(IRegExp2
*iface
, VARIANT_BOOL
*pIgnoreCase
)
1218 RegExp2
*This
= impl_from_IRegExp2(iface
);
1220 TRACE("(%p)->(%p)\n", This
, pIgnoreCase
);
1225 *pIgnoreCase
= This
->flags
& REG_FOLD
? VARIANT_TRUE
: VARIANT_FALSE
;
1229 static HRESULT WINAPI
RegExp2_put_IgnoreCase(IRegExp2
*iface
, VARIANT_BOOL ignoreCase
)
1231 RegExp2
*This
= impl_from_IRegExp2(iface
);
1233 TRACE("(%p)->(%s)\n", This
, ignoreCase
? "true" : "false");
1236 This
->flags
|= REG_FOLD
;
1238 This
->flags
&= ~REG_FOLD
;
1242 static HRESULT WINAPI
RegExp2_get_Global(IRegExp2
*iface
, VARIANT_BOOL
*pGlobal
)
1244 RegExp2
*This
= impl_from_IRegExp2(iface
);
1246 TRACE("(%p)->(%p)\n", This
, pGlobal
);
1251 *pGlobal
= This
->flags
& REG_GLOB
? VARIANT_TRUE
: VARIANT_FALSE
;
1255 static HRESULT WINAPI
RegExp2_put_Global(IRegExp2
*iface
, VARIANT_BOOL global
)
1257 RegExp2
*This
= impl_from_IRegExp2(iface
);
1259 TRACE("(%p)->(%s)\n", This
, global
? "true" : "false");
1262 This
->flags
|= REG_GLOB
;
1264 This
->flags
&= ~REG_GLOB
;
1268 static HRESULT WINAPI
RegExp2_get_Multiline(IRegExp2
*iface
, VARIANT_BOOL
*pMultiline
)
1270 RegExp2
*This
= impl_from_IRegExp2(iface
);
1272 TRACE("(%p)->(%p)\n", This
, pMultiline
);
1277 *pMultiline
= This
->flags
& REG_MULTILINE
? VARIANT_TRUE
: VARIANT_FALSE
;
1281 static HRESULT WINAPI
RegExp2_put_Multiline(IRegExp2
*iface
, VARIANT_BOOL multiline
)
1283 RegExp2
*This
= impl_from_IRegExp2(iface
);
1285 TRACE("(%p)->(%s)\n", This
, multiline
? "true" : "false");
1288 This
->flags
|= REG_MULTILINE
;
1290 This
->flags
&= ~REG_MULTILINE
;
1294 static HRESULT WINAPI
RegExp2_Execute(IRegExp2
*iface
,
1295 BSTR sourceString
, IDispatch
**ppMatches
)
1297 RegExp2
*This
= impl_from_IRegExp2(iface
);
1298 match_state_t
*result
;
1300 IMatchCollection2
*match_collection
;
1301 IMatch2
*add
= NULL
;
1304 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(sourceString
), ppMatches
);
1306 if(!This
->pattern
) {
1307 DWORD i
, len
= SysStringLen(sourceString
);
1309 hres
= create_match_collection2(&match_collection
);
1313 for(i
=0; i
<=len
; i
++) {
1314 hres
= create_match2(i
, NULL
, &add
);
1318 hres
= add_match(match_collection
, add
);
1321 IMatch2_Release(add
);
1323 if(!(This
->flags
& REG_GLOB
))
1328 IMatchCollection2_Release(match_collection
);
1332 *ppMatches
= (IDispatch
*)match_collection
;
1337 This
->regexp
= regexp_new(NULL
, &This
->pool
, This
->pattern
,
1338 lstrlenW(This
->pattern
), This
->flags
, FALSE
);
1342 hres
= regexp_set_flags(&This
->regexp
, NULL
, &This
->pool
, This
->flags
);
1347 hres
= create_match_collection2(&match_collection
);
1353 result
= alloc_match_state(This
->regexp
, NULL
, pos
);
1355 hres
= E_OUTOFMEMORY
;
1359 hres
= regexp_execute(This
->regexp
, NULL
, &This
->pool
,
1360 sourceString
, SysStringLen(sourceString
), result
);
1367 hres
= create_match2(result
->cp
-result
->match_len
-sourceString
, &result
, &add
);
1371 hres
= add_match(match_collection
, add
);
1372 IMatch2_Release(add
);
1376 if(!(This
->flags
& REG_GLOB
))
1381 IMatchCollection2_Release(match_collection
);
1385 *ppMatches
= (IDispatch
*)match_collection
;
1389 static HRESULT WINAPI
RegExp2_Test(IRegExp2
*iface
, BSTR sourceString
, VARIANT_BOOL
*pMatch
)
1391 RegExp2
*This
= impl_from_IRegExp2(iface
);
1392 match_state_t
*result
;
1396 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(sourceString
), pMatch
);
1398 if(!This
->pattern
) {
1399 *pMatch
= VARIANT_TRUE
;
1404 This
->regexp
= regexp_new(NULL
, &This
->pool
, This
->pattern
,
1405 lstrlenW(This
->pattern
), This
->flags
, FALSE
);
1409 hres
= regexp_set_flags(&This
->regexp
, NULL
, &This
->pool
, This
->flags
);
1414 mark
= heap_pool_mark(&This
->pool
);
1415 result
= alloc_match_state(This
->regexp
, &This
->pool
, sourceString
);
1417 heap_pool_clear(mark
);
1418 return E_OUTOFMEMORY
;
1421 hres
= regexp_execute(This
->regexp
, NULL
, &This
->pool
,
1422 sourceString
, SysStringLen(sourceString
), result
);
1424 heap_pool_clear(mark
);
1427 *pMatch
= VARIANT_TRUE
;
1428 }else if(hres
== S_FALSE
) {
1429 *pMatch
= VARIANT_FALSE
;
1441 static BOOL
strbuf_ensure_size(strbuf_t
*buf
, unsigned len
)
1446 if(len
<= buf
->size
)
1449 new_size
= buf
->size
? buf
->size
<<1 : 16;
1453 new_buf
= heap_realloc(buf
->buf
, new_size
*sizeof(WCHAR
));
1455 new_buf
= heap_alloc(new_size
*sizeof(WCHAR
));
1460 buf
->size
= new_size
;
1464 static HRESULT
strbuf_append(strbuf_t
*buf
, const WCHAR
*str
, DWORD len
)
1469 if(!strbuf_ensure_size(buf
, buf
->len
+len
))
1470 return E_OUTOFMEMORY
;
1472 memcpy(buf
->buf
+buf
->len
, str
, len
*sizeof(WCHAR
));
1477 static HRESULT WINAPI
RegExp2_Replace(IRegExp2
*iface
, BSTR source
, VARIANT replaceVar
, BSTR
*ret
)
1479 RegExp2
*This
= impl_from_IRegExp2(iface
);
1480 const WCHAR
*cp
, *prev_cp
= NULL
, *ptr
, *prev_ptr
;
1481 size_t match_len
= 0, source_len
, replace_len
;
1482 strbuf_t buf
= { NULL
, 0, 0 };
1483 match_state_t
*state
= NULL
;
1489 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(source
), debugstr_variant(&replaceVar
), ret
);
1493 This
->regexp
= regexp_new(NULL
, &This
->pool
, This
->pattern
,
1494 lstrlenW(This
->pattern
), This
->flags
, FALSE
);
1496 return E_OUTOFMEMORY
;
1498 hres
= regexp_set_flags(&This
->regexp
, NULL
, &This
->pool
, This
->flags
);
1504 V_VT(&strv
) = VT_EMPTY
;
1505 hres
= VariantChangeType(&strv
, &replaceVar
, 0, VT_BSTR
);
1508 replace
= V_BSTR(&strv
);
1509 replace_len
= SysStringLen(replace
);
1510 source_len
= SysStringLen(source
);
1512 mark
= heap_pool_mark(&This
->pool
);
1514 if(This
->regexp
&& !(state
= alloc_match_state(This
->regexp
, &This
->pool
, cp
)))
1515 hres
= E_OUTOFMEMORY
;
1517 while(SUCCEEDED(hres
)) {
1520 hres
= regexp_execute(This
->regexp
, NULL
, &This
->pool
, source
, source_len
, state
);
1521 if(hres
!= S_OK
) break;
1523 match_len
= state
->match_len
;
1525 if(cp
== source
+ source_len
)
1532 hres
= strbuf_append(&buf
, prev_cp
, cp
- prev_cp
- match_len
);
1537 while((ptr
= wmemchr(prev_ptr
, '$', replace
+ replace_len
- prev_ptr
))) {
1538 hres
= strbuf_append(&buf
, prev_ptr
, ptr
- prev_ptr
);
1544 hres
= strbuf_append(&buf
, ptr
, 1);
1548 hres
= strbuf_append(&buf
, cp
- match_len
, match_len
);
1552 hres
= strbuf_append(&buf
, source
, cp
- source
- match_len
);
1556 hres
= strbuf_append(&buf
, cp
, source
+ source_len
- cp
);
1562 if(!is_digit(ptr
[1])) {
1563 hres
= strbuf_append(&buf
, ptr
, 1);
1569 if(is_digit(ptr
[2]) && idx
* 10 + (ptr
[2] - '0') <= state
->paren_count
) {
1570 idx
= idx
* 10 + (ptr
[2] - '0');
1572 }else if(idx
&& idx
<= state
->paren_count
) {
1575 hres
= strbuf_append(&buf
, ptr
, 1);
1580 if(state
->parens
[idx
- 1].index
!= -1)
1581 hres
= strbuf_append(&buf
, source
+ state
->parens
[idx
- 1].index
,
1582 state
->parens
[idx
- 1].length
);
1590 hres
= strbuf_append(&buf
, prev_ptr
, replace
+ replace_len
- prev_ptr
);
1594 if(!(This
->flags
& REG_GLOB
))
1598 if(SUCCEEDED(hres
)) {
1599 hres
= strbuf_append(&buf
, cp
, source
+ source_len
- cp
);
1600 if(SUCCEEDED(hres
) && !(*ret
= SysAllocStringLen(buf
.buf
, buf
.len
)))
1601 hres
= E_OUTOFMEMORY
;
1604 heap_pool_clear(mark
);
1606 SysFreeString(replace
);
1610 static const IRegExp2Vtbl RegExp2Vtbl
= {
1611 RegExp2_QueryInterface
,
1614 RegExp2_GetTypeInfoCount
,
1615 RegExp2_GetTypeInfo
,
1616 RegExp2_GetIDsOfNames
,
1618 RegExp2_get_Pattern
,
1619 RegExp2_put_Pattern
,
1620 RegExp2_get_IgnoreCase
,
1621 RegExp2_put_IgnoreCase
,
1624 RegExp2_get_Multiline
,
1625 RegExp2_put_Multiline
,
1631 BSTR
string_replace(BSTR string
, BSTR find
, BSTR replace
, int from
, int cnt
, int mode
)
1633 const WCHAR
*ptr
, *string_end
;
1634 strbuf_t buf
= { NULL
, 0, 0 };
1635 size_t replace_len
, find_len
;
1637 HRESULT hres
= S_OK
;
1640 string_end
= string
+ SysStringLen(string
);
1641 ptr
= from
> SysStringLen(string
) ? string_end
: string
+ from
;
1643 find_len
= SysStringLen(find
);
1644 replace_len
= SysStringLen(replace
);
1646 while(string_end
- ptr
>= find_len
&& cnt
&& find_len
) {
1647 pos
= FindStringOrdinal(FIND_FROMSTART
, ptr
, string_end
- ptr
,
1648 find
, find_len
, mode
);
1653 hres
= strbuf_append(&buf
, ptr
, pos
);
1656 hres
= strbuf_append(&buf
, replace
, replace_len
);
1660 ptr
= ptr
+ pos
+ find_len
;
1666 if(SUCCEEDED(hres
)) {
1667 hres
= strbuf_append(&buf
, ptr
, string_end
- ptr
);
1669 ret
= SysAllocStringLen(buf
.buf
, buf
.len
);
1676 static inline RegExp2
*impl_from_IRegExp(IRegExp
*iface
)
1678 return CONTAINING_RECORD(iface
, RegExp2
, IRegExp_iface
);
1681 static HRESULT WINAPI
RegExp_QueryInterface(IRegExp
*iface
, REFIID riid
, void **ppv
)
1683 RegExp2
*This
= impl_from_IRegExp(iface
);
1684 return IRegExp2_QueryInterface(&This
->IRegExp2_iface
, riid
, ppv
);
1687 static ULONG WINAPI
RegExp_AddRef(IRegExp
*iface
)
1689 RegExp2
*This
= impl_from_IRegExp(iface
);
1690 return IRegExp2_AddRef(&This
->IRegExp2_iface
);
1693 static ULONG WINAPI
RegExp_Release(IRegExp
*iface
)
1695 RegExp2
*This
= impl_from_IRegExp(iface
);
1696 return IRegExp2_Release(&This
->IRegExp2_iface
);
1699 static HRESULT WINAPI
RegExp_GetTypeInfoCount(IRegExp
*iface
, UINT
*pctinfo
)
1701 RegExp2
*This
= impl_from_IRegExp(iface
);
1702 return IRegExp2_GetTypeInfoCount(&This
->IRegExp2_iface
, pctinfo
);
1705 static HRESULT WINAPI
RegExp_GetTypeInfo(IRegExp
*iface
,
1706 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
1708 RegExp2
*This
= impl_from_IRegExp(iface
);
1709 return IRegExp2_GetTypeInfo(&This
->IRegExp2_iface
, iTInfo
, lcid
, ppTInfo
);
1712 static HRESULT WINAPI
RegExp_GetIDsOfNames(IRegExp
*iface
, REFIID riid
,
1713 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1715 RegExp2
*This
= impl_from_IRegExp(iface
);
1716 return IRegExp2_GetIDsOfNames(&This
->IRegExp2_iface
, riid
, rgszNames
, cNames
, lcid
, rgDispId
);
1719 static HRESULT WINAPI
RegExp_Invoke(IRegExp
*iface
, DISPID dispIdMember
,
1720 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
1721 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1723 RegExp2
*This
= impl_from_IRegExp(iface
);
1724 return IRegExp2_Invoke(&This
->IRegExp2_iface
, dispIdMember
, riid
, lcid
,
1725 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1728 static HRESULT WINAPI
RegExp_get_Pattern(IRegExp
*iface
, BSTR
*pPattern
)
1730 RegExp2
*This
= impl_from_IRegExp(iface
);
1731 return IRegExp2_get_Pattern(&This
->IRegExp2_iface
, pPattern
);
1734 static HRESULT WINAPI
RegExp_put_Pattern(IRegExp
*iface
, BSTR pPattern
)
1736 RegExp2
*This
= impl_from_IRegExp(iface
);
1737 return IRegExp2_put_Pattern(&This
->IRegExp2_iface
, pPattern
);
1740 static HRESULT WINAPI
RegExp_get_IgnoreCase(IRegExp
*iface
, VARIANT_BOOL
*pIgnoreCase
)
1742 RegExp2
*This
= impl_from_IRegExp(iface
);
1743 return IRegExp2_get_IgnoreCase(&This
->IRegExp2_iface
, pIgnoreCase
);
1746 static HRESULT WINAPI
RegExp_put_IgnoreCase(IRegExp
*iface
, VARIANT_BOOL pIgnoreCase
)
1748 RegExp2
*This
= impl_from_IRegExp(iface
);
1749 return IRegExp2_put_IgnoreCase(&This
->IRegExp2_iface
, pIgnoreCase
);
1752 static HRESULT WINAPI
RegExp_get_Global(IRegExp
*iface
, VARIANT_BOOL
*pGlobal
)
1754 RegExp2
*This
= impl_from_IRegExp(iface
);
1755 return IRegExp2_get_Global(&This
->IRegExp2_iface
, pGlobal
);
1758 static HRESULT WINAPI
RegExp_put_Global(IRegExp
*iface
, VARIANT_BOOL pGlobal
)
1760 RegExp2
*This
= impl_from_IRegExp(iface
);
1761 return IRegExp2_put_Global(&This
->IRegExp2_iface
, pGlobal
);
1764 static HRESULT WINAPI
RegExp_Execute(IRegExp
*iface
,
1765 BSTR sourceString
, IDispatch
**ppMatches
)
1767 RegExp2
*This
= impl_from_IRegExp(iface
);
1768 return IRegExp2_Execute(&This
->IRegExp2_iface
, sourceString
, ppMatches
);
1771 static HRESULT WINAPI
RegExp_Test(IRegExp
*iface
, BSTR sourceString
, VARIANT_BOOL
*pMatch
)
1773 RegExp2
*This
= impl_from_IRegExp(iface
);
1774 return IRegExp2_Test(&This
->IRegExp2_iface
, sourceString
, pMatch
);
1777 static HRESULT WINAPI
RegExp_Replace(IRegExp
*iface
, BSTR sourceString
,
1778 BSTR replaceString
, BSTR
*pDestString
)
1780 RegExp2
*This
= impl_from_IRegExp(iface
);
1783 V_VT(&replace
) = VT_BSTR
;
1784 V_BSTR(&replace
) = replaceString
;
1785 return IRegExp2_Replace(&This
->IRegExp2_iface
, sourceString
, replace
, pDestString
);
1788 static IRegExpVtbl RegExpVtbl
= {
1789 RegExp_QueryInterface
,
1792 RegExp_GetTypeInfoCount
,
1794 RegExp_GetIDsOfNames
,
1798 RegExp_get_IgnoreCase
,
1799 RegExp_put_IgnoreCase
,
1807 HRESULT
create_regexp(IDispatch
**ret
)
1812 hres
= init_regexp_typeinfo(RegExp2_tid
);
1816 regexp
= heap_alloc_zero(sizeof(*regexp
));
1818 return E_OUTOFMEMORY
;
1820 regexp
->IRegExp2_iface
.lpVtbl
= &RegExp2Vtbl
;
1821 regexp
->IRegExp_iface
.lpVtbl
= &RegExpVtbl
;
1823 heap_pool_init(®exp
->pool
);
1825 *ret
= (IDispatch
*)®exp
->IRegExp2_iface
;
1829 HRESULT WINAPI
VBScriptRegExpFactory_CreateInstance(IClassFactory
*iface
, IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
1834 TRACE("(%p %s %p)\n", pUnkOuter
, debugstr_guid(riid
), ppv
);
1836 hres
= create_regexp(®exp
);
1840 hres
= IDispatch_QueryInterface(regexp
, riid
, ppv
);
1841 IDispatch_Release(regexp
);
1845 void release_regexp_typelib(void)
1849 for(i
=0; i
<REGEXP_LAST_tid
; i
++) {
1851 ITypeInfo_Release(typeinfos
[i
]);
1854 ITypeLib_Release(typelib
);