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: %08lx\n", hres
);
63 if(InterlockedCompareExchangePointer((void**)&typelib
, tl
, NULL
))
70 hres
= ITypeLib_GetTypeInfoOfGuid(typelib
, tid_ids
[tid
], &ti
);
72 ERR("GetTypeInfoOfGuid(%s) failed: %08lx\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=%ld\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=%ld\n", This
, ref
);
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 %lu %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 %lu %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)->(%ld %s %ld %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)->(%ld %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
= calloc(1, sizeof(*ret
));
312 return E_OUTOFMEMORY
;
314 ret
->ISubMatches_iface
.lpVtbl
= &SubMatchesVtbl
;
316 ret
->result
= result
;
318 ret
->match
= malloc((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=%ld\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=%ld\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 %lu %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 %lu %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)->(%ld %s %ld %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
= calloc(1, 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=%ld\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=%ld\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)->(%lu %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)->(%lu)\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
= calloc(1, 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=%ld\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=%ld\n", This
, ref
);
828 for(i
=0; i
<This
->count
; i
++)
829 IMatch2_Release(This
->matches
[i
]);
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 %lu %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 %lu %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)->(%ld %s %ld %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
= malloc(8 * sizeof(*This
->matches
));
1029 return E_OUTOFMEMORY
;
1031 }else if(This
->size
== This
->count
) {
1032 IMatch2
**new_matches
= realloc(This
->matches
, 2 * This
->size
* sizeof(*This
->matches
));
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
= calloc(1, 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=%ld\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=%ld\n", This
, ref
);
1119 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
);
1144 TRACE("(%p)->(%u %lu %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1146 *ppTInfo
= typeinfos
[RegExp2_tid
];
1147 ITypeInfo_AddRef(*ppTInfo
);
1151 static HRESULT WINAPI
RegExp2_GetIDsOfNames(IRegExp2
*iface
, REFIID riid
,
1152 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1154 RegExp2
*This
= impl_from_IRegExp2(iface
);
1156 TRACE("(%p)->(%s %p %u %lu %p)\n", This
, debugstr_guid(riid
),
1157 rgszNames
, cNames
, lcid
, rgDispId
);
1159 return ITypeInfo_GetIDsOfNames(typeinfos
[RegExp2_tid
], rgszNames
, cNames
, rgDispId
);
1162 static HRESULT WINAPI
RegExp2_Invoke(IRegExp2
*iface
, DISPID dispIdMember
,
1163 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
1164 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1166 RegExp2
*This
= impl_from_IRegExp2(iface
);
1168 TRACE("(%p)->(%ld %s %ld %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1169 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1171 return ITypeInfo_Invoke(typeinfos
[RegExp2_tid
], iface
, dispIdMember
, wFlags
,
1172 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1175 static HRESULT WINAPI
RegExp2_get_Pattern(IRegExp2
*iface
, BSTR
*pPattern
)
1177 RegExp2
*This
= impl_from_IRegExp2(iface
);
1179 TRACE("(%p)->(%p)\n", This
, pPattern
);
1184 if(!This
->pattern
) {
1189 *pPattern
= SysAllocString(This
->pattern
);
1190 return *pPattern
? S_OK
: E_OUTOFMEMORY
;
1193 static HRESULT WINAPI
RegExp2_put_Pattern(IRegExp2
*iface
, BSTR pattern
)
1195 RegExp2
*This
= impl_from_IRegExp2(iface
);
1198 TRACE("(%p)->(%s)\n", This
, wine_dbgstr_w(pattern
));
1200 if(pattern
&& *pattern
) {
1201 SIZE_T size
= (SysStringLen(pattern
)+1) * sizeof(WCHAR
);
1202 new_pattern
= malloc(size
);
1204 return E_OUTOFMEMORY
;
1205 memcpy(new_pattern
, pattern
, size
);
1210 free(This
->pattern
);
1211 This
->pattern
= new_pattern
;
1214 regexp_destroy(This
->regexp
);
1215 This
->regexp
= NULL
;
1220 static HRESULT WINAPI
RegExp2_get_IgnoreCase(IRegExp2
*iface
, VARIANT_BOOL
*pIgnoreCase
)
1222 RegExp2
*This
= impl_from_IRegExp2(iface
);
1224 TRACE("(%p)->(%p)\n", This
, pIgnoreCase
);
1229 *pIgnoreCase
= This
->flags
& REG_FOLD
? VARIANT_TRUE
: VARIANT_FALSE
;
1233 static HRESULT WINAPI
RegExp2_put_IgnoreCase(IRegExp2
*iface
, VARIANT_BOOL ignoreCase
)
1235 RegExp2
*This
= impl_from_IRegExp2(iface
);
1237 TRACE("(%p)->(%s)\n", This
, ignoreCase
? "true" : "false");
1240 This
->flags
|= REG_FOLD
;
1242 This
->flags
&= ~REG_FOLD
;
1246 static HRESULT WINAPI
RegExp2_get_Global(IRegExp2
*iface
, VARIANT_BOOL
*pGlobal
)
1248 RegExp2
*This
= impl_from_IRegExp2(iface
);
1250 TRACE("(%p)->(%p)\n", This
, pGlobal
);
1255 *pGlobal
= This
->flags
& REG_GLOB
? VARIANT_TRUE
: VARIANT_FALSE
;
1259 static HRESULT WINAPI
RegExp2_put_Global(IRegExp2
*iface
, VARIANT_BOOL global
)
1261 RegExp2
*This
= impl_from_IRegExp2(iface
);
1263 TRACE("(%p)->(%s)\n", This
, global
? "true" : "false");
1266 This
->flags
|= REG_GLOB
;
1268 This
->flags
&= ~REG_GLOB
;
1272 static HRESULT WINAPI
RegExp2_get_Multiline(IRegExp2
*iface
, VARIANT_BOOL
*pMultiline
)
1274 RegExp2
*This
= impl_from_IRegExp2(iface
);
1276 TRACE("(%p)->(%p)\n", This
, pMultiline
);
1281 *pMultiline
= This
->flags
& REG_MULTILINE
? VARIANT_TRUE
: VARIANT_FALSE
;
1285 static HRESULT WINAPI
RegExp2_put_Multiline(IRegExp2
*iface
, VARIANT_BOOL multiline
)
1287 RegExp2
*This
= impl_from_IRegExp2(iface
);
1289 TRACE("(%p)->(%s)\n", This
, multiline
? "true" : "false");
1292 This
->flags
|= REG_MULTILINE
;
1294 This
->flags
&= ~REG_MULTILINE
;
1298 static HRESULT WINAPI
RegExp2_Execute(IRegExp2
*iface
,
1299 BSTR sourceString
, IDispatch
**ppMatches
)
1301 RegExp2
*This
= impl_from_IRegExp2(iface
);
1302 match_state_t
*result
;
1304 IMatchCollection2
*match_collection
;
1305 IMatch2
*add
= NULL
;
1308 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(sourceString
), ppMatches
);
1310 if(!This
->pattern
) {
1311 DWORD i
, len
= SysStringLen(sourceString
);
1313 hres
= create_match_collection2(&match_collection
);
1317 for(i
=0; i
<=len
; i
++) {
1318 hres
= create_match2(i
, NULL
, &add
);
1322 hres
= add_match(match_collection
, add
);
1323 IMatch2_Release(add
);
1327 if(!(This
->flags
& REG_GLOB
))
1332 IMatchCollection2_Release(match_collection
);
1336 *ppMatches
= (IDispatch
*)match_collection
;
1341 This
->regexp
= regexp_new(NULL
, &This
->pool
, This
->pattern
,
1342 lstrlenW(This
->pattern
), This
->flags
, FALSE
);
1346 hres
= regexp_set_flags(&This
->regexp
, NULL
, &This
->pool
, This
->flags
);
1351 hres
= create_match_collection2(&match_collection
);
1357 result
= alloc_match_state(This
->regexp
, NULL
, pos
);
1359 hres
= E_OUTOFMEMORY
;
1363 hres
= regexp_execute(This
->regexp
, NULL
, &This
->pool
,
1364 sourceString
, SysStringLen(sourceString
), result
);
1371 hres
= create_match2(result
->cp
-result
->match_len
-sourceString
, &result
, &add
);
1375 hres
= add_match(match_collection
, add
);
1376 IMatch2_Release(add
);
1380 if(!(This
->flags
& REG_GLOB
))
1385 IMatchCollection2_Release(match_collection
);
1389 *ppMatches
= (IDispatch
*)match_collection
;
1393 static HRESULT WINAPI
RegExp2_Test(IRegExp2
*iface
, BSTR sourceString
, VARIANT_BOOL
*pMatch
)
1395 RegExp2
*This
= impl_from_IRegExp2(iface
);
1396 match_state_t
*result
;
1400 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(sourceString
), pMatch
);
1402 if(!This
->pattern
) {
1403 *pMatch
= VARIANT_TRUE
;
1408 This
->regexp
= regexp_new(NULL
, &This
->pool
, This
->pattern
,
1409 lstrlenW(This
->pattern
), This
->flags
, FALSE
);
1413 hres
= regexp_set_flags(&This
->regexp
, NULL
, &This
->pool
, This
->flags
);
1418 mark
= heap_pool_mark(&This
->pool
);
1419 result
= alloc_match_state(This
->regexp
, &This
->pool
, sourceString
);
1421 heap_pool_clear(mark
);
1422 return E_OUTOFMEMORY
;
1425 hres
= regexp_execute(This
->regexp
, NULL
, &This
->pool
,
1426 sourceString
, SysStringLen(sourceString
), result
);
1428 heap_pool_clear(mark
);
1431 *pMatch
= VARIANT_TRUE
;
1432 }else if(hres
== S_FALSE
) {
1433 *pMatch
= VARIANT_FALSE
;
1445 static BOOL
strbuf_ensure_size(strbuf_t
*buf
, unsigned len
)
1450 if(len
<= buf
->size
)
1453 new_size
= buf
->size
? buf
->size
<<1 : 16;
1457 new_buf
= realloc(buf
->buf
, new_size
*sizeof(WCHAR
));
1459 new_buf
= malloc(new_size
*sizeof(WCHAR
));
1464 buf
->size
= new_size
;
1468 static HRESULT
strbuf_append(strbuf_t
*buf
, const WCHAR
*str
, DWORD len
)
1473 if(!strbuf_ensure_size(buf
, buf
->len
+len
))
1474 return E_OUTOFMEMORY
;
1476 memcpy(buf
->buf
+buf
->len
, str
, len
*sizeof(WCHAR
));
1481 static HRESULT WINAPI
RegExp2_Replace(IRegExp2
*iface
, BSTR source
, VARIANT replaceVar
, BSTR
*ret
)
1483 RegExp2
*This
= impl_from_IRegExp2(iface
);
1484 const WCHAR
*cp
, *prev_cp
= NULL
, *ptr
, *prev_ptr
;
1485 size_t match_len
= 0, source_len
, replace_len
;
1486 strbuf_t buf
= { NULL
, 0, 0 };
1487 match_state_t
*state
= NULL
;
1493 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(source
), debugstr_variant(&replaceVar
), ret
);
1497 This
->regexp
= regexp_new(NULL
, &This
->pool
, This
->pattern
,
1498 lstrlenW(This
->pattern
), This
->flags
, FALSE
);
1500 return E_OUTOFMEMORY
;
1502 hres
= regexp_set_flags(&This
->regexp
, NULL
, &This
->pool
, This
->flags
);
1508 V_VT(&strv
) = VT_EMPTY
;
1509 hres
= VariantChangeType(&strv
, &replaceVar
, 0, VT_BSTR
);
1512 replace
= V_BSTR(&strv
);
1513 replace_len
= SysStringLen(replace
);
1514 source_len
= SysStringLen(source
);
1516 mark
= heap_pool_mark(&This
->pool
);
1518 if(This
->regexp
&& !(state
= alloc_match_state(This
->regexp
, &This
->pool
, cp
)))
1519 hres
= E_OUTOFMEMORY
;
1521 while(SUCCEEDED(hres
)) {
1524 hres
= regexp_execute(This
->regexp
, NULL
, &This
->pool
, source
, source_len
, state
);
1525 if(hres
!= S_OK
) break;
1527 match_len
= state
->match_len
;
1529 if(cp
== source
+ source_len
)
1536 hres
= strbuf_append(&buf
, prev_cp
, cp
- prev_cp
- match_len
);
1541 while((ptr
= wmemchr(prev_ptr
, '$', replace
+ replace_len
- prev_ptr
))) {
1542 hres
= strbuf_append(&buf
, prev_ptr
, ptr
- prev_ptr
);
1548 hres
= strbuf_append(&buf
, ptr
, 1);
1552 hres
= strbuf_append(&buf
, cp
- match_len
, match_len
);
1556 hres
= strbuf_append(&buf
, source
, cp
- source
- match_len
);
1560 hres
= strbuf_append(&buf
, cp
, source
+ source_len
- cp
);
1566 if(!is_digit(ptr
[1])) {
1567 hres
= strbuf_append(&buf
, ptr
, 1);
1573 if(is_digit(ptr
[2]) && idx
* 10 + (ptr
[2] - '0') <= state
->paren_count
) {
1574 idx
= idx
* 10 + (ptr
[2] - '0');
1576 }else if(idx
&& idx
<= state
->paren_count
) {
1579 hres
= strbuf_append(&buf
, ptr
, 1);
1584 if(state
->parens
[idx
- 1].index
!= -1)
1585 hres
= strbuf_append(&buf
, source
+ state
->parens
[idx
- 1].index
,
1586 state
->parens
[idx
- 1].length
);
1594 hres
= strbuf_append(&buf
, prev_ptr
, replace
+ replace_len
- prev_ptr
);
1598 if(!(This
->flags
& REG_GLOB
))
1602 if(SUCCEEDED(hres
)) {
1603 hres
= strbuf_append(&buf
, cp
, source
+ source_len
- cp
);
1604 if(SUCCEEDED(hres
) && !(*ret
= SysAllocStringLen(buf
.buf
, buf
.len
)))
1605 hres
= E_OUTOFMEMORY
;
1608 heap_pool_clear(mark
);
1610 SysFreeString(replace
);
1614 static const IRegExp2Vtbl RegExp2Vtbl
= {
1615 RegExp2_QueryInterface
,
1618 RegExp2_GetTypeInfoCount
,
1619 RegExp2_GetTypeInfo
,
1620 RegExp2_GetIDsOfNames
,
1622 RegExp2_get_Pattern
,
1623 RegExp2_put_Pattern
,
1624 RegExp2_get_IgnoreCase
,
1625 RegExp2_put_IgnoreCase
,
1628 RegExp2_get_Multiline
,
1629 RegExp2_put_Multiline
,
1635 BSTR
string_replace(BSTR string
, BSTR find
, BSTR replace
, int from
, int cnt
, int mode
)
1637 const WCHAR
*ptr
, *string_end
;
1638 strbuf_t buf
= { NULL
, 0, 0 };
1639 size_t replace_len
, find_len
;
1641 HRESULT hres
= S_OK
;
1644 string_end
= string
+ SysStringLen(string
);
1645 ptr
= from
> SysStringLen(string
) ? string_end
: string
+ from
;
1647 find_len
= SysStringLen(find
);
1648 replace_len
= SysStringLen(replace
);
1650 while(string_end
- ptr
>= find_len
&& cnt
&& find_len
) {
1651 pos
= FindStringOrdinal(FIND_FROMSTART
, ptr
, string_end
- ptr
,
1652 find
, find_len
, mode
);
1657 hres
= strbuf_append(&buf
, ptr
, pos
);
1660 hres
= strbuf_append(&buf
, replace
, replace_len
);
1664 ptr
= ptr
+ pos
+ find_len
;
1670 if(SUCCEEDED(hres
)) {
1671 hres
= strbuf_append(&buf
, ptr
, string_end
- ptr
);
1673 ret
= SysAllocStringLen(buf
.buf
, buf
.len
);
1680 static inline RegExp2
*impl_from_IRegExp(IRegExp
*iface
)
1682 return CONTAINING_RECORD(iface
, RegExp2
, IRegExp_iface
);
1685 static HRESULT WINAPI
RegExp_QueryInterface(IRegExp
*iface
, REFIID riid
, void **ppv
)
1687 RegExp2
*This
= impl_from_IRegExp(iface
);
1688 return IRegExp2_QueryInterface(&This
->IRegExp2_iface
, riid
, ppv
);
1691 static ULONG WINAPI
RegExp_AddRef(IRegExp
*iface
)
1693 RegExp2
*This
= impl_from_IRegExp(iface
);
1694 return IRegExp2_AddRef(&This
->IRegExp2_iface
);
1697 static ULONG WINAPI
RegExp_Release(IRegExp
*iface
)
1699 RegExp2
*This
= impl_from_IRegExp(iface
);
1700 return IRegExp2_Release(&This
->IRegExp2_iface
);
1703 static HRESULT WINAPI
RegExp_GetTypeInfoCount(IRegExp
*iface
, UINT
*pctinfo
)
1705 RegExp2
*This
= impl_from_IRegExp(iface
);
1706 return IRegExp2_GetTypeInfoCount(&This
->IRegExp2_iface
, pctinfo
);
1709 static HRESULT WINAPI
RegExp_GetTypeInfo(IRegExp
*iface
,
1710 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
1712 RegExp2
*This
= impl_from_IRegExp(iface
);
1713 return IRegExp2_GetTypeInfo(&This
->IRegExp2_iface
, iTInfo
, lcid
, ppTInfo
);
1716 static HRESULT WINAPI
RegExp_GetIDsOfNames(IRegExp
*iface
, REFIID riid
,
1717 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1719 RegExp2
*This
= impl_from_IRegExp(iface
);
1720 return IRegExp2_GetIDsOfNames(&This
->IRegExp2_iface
, riid
, rgszNames
, cNames
, lcid
, rgDispId
);
1723 static HRESULT WINAPI
RegExp_Invoke(IRegExp
*iface
, DISPID dispIdMember
,
1724 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
1725 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1727 RegExp2
*This
= impl_from_IRegExp(iface
);
1728 return IRegExp2_Invoke(&This
->IRegExp2_iface
, dispIdMember
, riid
, lcid
,
1729 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1732 static HRESULT WINAPI
RegExp_get_Pattern(IRegExp
*iface
, BSTR
*pPattern
)
1734 RegExp2
*This
= impl_from_IRegExp(iface
);
1735 return IRegExp2_get_Pattern(&This
->IRegExp2_iface
, pPattern
);
1738 static HRESULT WINAPI
RegExp_put_Pattern(IRegExp
*iface
, BSTR pPattern
)
1740 RegExp2
*This
= impl_from_IRegExp(iface
);
1741 return IRegExp2_put_Pattern(&This
->IRegExp2_iface
, pPattern
);
1744 static HRESULT WINAPI
RegExp_get_IgnoreCase(IRegExp
*iface
, VARIANT_BOOL
*pIgnoreCase
)
1746 RegExp2
*This
= impl_from_IRegExp(iface
);
1747 return IRegExp2_get_IgnoreCase(&This
->IRegExp2_iface
, pIgnoreCase
);
1750 static HRESULT WINAPI
RegExp_put_IgnoreCase(IRegExp
*iface
, VARIANT_BOOL pIgnoreCase
)
1752 RegExp2
*This
= impl_from_IRegExp(iface
);
1753 return IRegExp2_put_IgnoreCase(&This
->IRegExp2_iface
, pIgnoreCase
);
1756 static HRESULT WINAPI
RegExp_get_Global(IRegExp
*iface
, VARIANT_BOOL
*pGlobal
)
1758 RegExp2
*This
= impl_from_IRegExp(iface
);
1759 return IRegExp2_get_Global(&This
->IRegExp2_iface
, pGlobal
);
1762 static HRESULT WINAPI
RegExp_put_Global(IRegExp
*iface
, VARIANT_BOOL pGlobal
)
1764 RegExp2
*This
= impl_from_IRegExp(iface
);
1765 return IRegExp2_put_Global(&This
->IRegExp2_iface
, pGlobal
);
1768 static HRESULT WINAPI
RegExp_Execute(IRegExp
*iface
,
1769 BSTR sourceString
, IDispatch
**ppMatches
)
1771 RegExp2
*This
= impl_from_IRegExp(iface
);
1772 return IRegExp2_Execute(&This
->IRegExp2_iface
, sourceString
, ppMatches
);
1775 static HRESULT WINAPI
RegExp_Test(IRegExp
*iface
, BSTR sourceString
, VARIANT_BOOL
*pMatch
)
1777 RegExp2
*This
= impl_from_IRegExp(iface
);
1778 return IRegExp2_Test(&This
->IRegExp2_iface
, sourceString
, pMatch
);
1781 static HRESULT WINAPI
RegExp_Replace(IRegExp
*iface
, BSTR sourceString
,
1782 BSTR replaceString
, BSTR
*pDestString
)
1784 RegExp2
*This
= impl_from_IRegExp(iface
);
1787 V_VT(&replace
) = VT_BSTR
;
1788 V_BSTR(&replace
) = replaceString
;
1789 return IRegExp2_Replace(&This
->IRegExp2_iface
, sourceString
, replace
, pDestString
);
1792 static IRegExpVtbl RegExpVtbl
= {
1793 RegExp_QueryInterface
,
1796 RegExp_GetTypeInfoCount
,
1798 RegExp_GetIDsOfNames
,
1802 RegExp_get_IgnoreCase
,
1803 RegExp_put_IgnoreCase
,
1811 HRESULT
create_regexp(IDispatch
**ret
)
1816 hres
= init_regexp_typeinfo(RegExp2_tid
);
1820 regexp
= calloc(1, sizeof(*regexp
));
1822 return E_OUTOFMEMORY
;
1824 regexp
->IRegExp2_iface
.lpVtbl
= &RegExp2Vtbl
;
1825 regexp
->IRegExp_iface
.lpVtbl
= &RegExpVtbl
;
1827 heap_pool_init(®exp
->pool
);
1829 *ret
= (IDispatch
*)®exp
->IRegExp2_iface
;
1833 HRESULT WINAPI
VBScriptRegExpFactory_CreateInstance(IClassFactory
*iface
, IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
1838 TRACE("(%p %s %p)\n", pUnkOuter
, debugstr_guid(riid
), ppv
);
1840 hres
= create_regexp(®exp
);
1844 hres
= IDispatch_QueryInterface(regexp
, riid
, ppv
);
1845 IDispatch_Release(regexp
);
1849 void release_regexp_typelib(void)
1853 for(i
=0; i
<REGEXP_LAST_tid
; i
++) {
1855 ITypeInfo_Release(typeinfos
[i
]);
1858 ITypeLib_Release(typelib
);