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
)
55 static const WCHAR vbscript_dll3W
[] = {'v','b','s','c','r','i','p','t','.','d','l','l','\\','3',0};
58 hres
= LoadTypeLib(vbscript_dll3W
, &tl
);
60 ERR("LoadRegTypeLib failed: %08x\n", hres
);
64 if(InterlockedCompareExchangePointer((void**)&typelib
, tl
, NULL
))
71 hres
= ITypeLib_GetTypeInfoOfGuid(typelib
, tid_ids
[tid
], &ti
);
73 ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids
[tid
]), hres
);
77 if(InterlockedCompareExchangePointer((void**)(typeinfos
+tid
), ti
, NULL
))
78 ITypeInfo_Release(ti
);
85 ISubMatches ISubMatches_iface
;
90 match_state_t
*result
;
93 typedef struct Match2
{
94 IMatch2 IMatch2_iface
;
100 SubMatches
*sub_matches
;
103 typedef struct MatchCollectionEnum
{
104 IEnumVARIANT IEnumVARIANT_iface
;
108 IMatchCollection2
*mc
;
111 } MatchCollectionEnum
;
113 typedef struct MatchCollection2
{
114 IMatchCollection2 IMatchCollection2_iface
;
115 IMatchCollection IMatchCollection_iface
;
124 typedef struct RegExp2
{
125 IRegExp2 IRegExp2_iface
;
126 IRegExp IRegExp_iface
;
136 static inline SubMatches
* impl_from_ISubMatches(ISubMatches
*iface
)
138 return CONTAINING_RECORD(iface
, SubMatches
, ISubMatches_iface
);
141 static HRESULT WINAPI
SubMatches_QueryInterface(
142 ISubMatches
*iface
, REFIID riid
, void **ppv
)
144 SubMatches
*This
= impl_from_ISubMatches(iface
);
146 if(IsEqualGUID(riid
, &IID_IUnknown
)) {
147 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
148 *ppv
= &This
->ISubMatches_iface
;
149 }else if(IsEqualGUID(riid
, &IID_IDispatch
)) {
150 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
151 *ppv
= &This
->ISubMatches_iface
;
152 }else if(IsEqualGUID(riid
, &IID_ISubMatches
)) {
153 TRACE("(%p)->(IID_ISubMatches %p)\n", This
, ppv
);
154 *ppv
= &This
->ISubMatches_iface
;
155 }else if(IsEqualGUID(riid
, &IID_IDispatchEx
)) {
156 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
158 return E_NOINTERFACE
;
160 FIXME("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
162 return E_NOINTERFACE
;
165 IUnknown_AddRef((IUnknown
*)*ppv
);
169 static ULONG WINAPI
SubMatches_AddRef(ISubMatches
*iface
)
171 SubMatches
*This
= impl_from_ISubMatches(iface
);
172 LONG ref
= InterlockedIncrement(&This
->ref
);
174 TRACE("(%p) ref=%d\n", This
, ref
);
179 static ULONG WINAPI
SubMatches_Release(ISubMatches
*iface
)
181 SubMatches
*This
= impl_from_ISubMatches(iface
);
182 LONG ref
= InterlockedDecrement(&This
->ref
);
184 TRACE("(%p) ref=%d\n", This
, ref
);
187 heap_free(This
->match
);
188 heap_free(This
->result
);
195 static HRESULT WINAPI
SubMatches_GetTypeInfoCount(ISubMatches
*iface
, UINT
*pctinfo
)
197 SubMatches
*This
= impl_from_ISubMatches(iface
);
199 TRACE("(%p)->(%p)\n", This
, pctinfo
);
205 static HRESULT WINAPI
SubMatches_GetTypeInfo(ISubMatches
*iface
,
206 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
208 SubMatches
*This
= impl_from_ISubMatches(iface
);
209 FIXME("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
213 static HRESULT WINAPI
SubMatches_GetIDsOfNames(ISubMatches
*iface
,
214 REFIID riid
, LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
216 SubMatches
*This
= impl_from_ISubMatches(iface
);
218 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
219 rgszNames
, cNames
, lcid
, rgDispId
);
221 return ITypeInfo_GetIDsOfNames(typeinfos
[SubMatches_tid
], rgszNames
, cNames
, rgDispId
);
224 static HRESULT WINAPI
SubMatches_Invoke(ISubMatches
*iface
, DISPID dispIdMember
,
225 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
226 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
228 SubMatches
*This
= impl_from_ISubMatches(iface
);
230 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
231 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
233 return ITypeInfo_Invoke(typeinfos
[SubMatches_tid
], iface
, dispIdMember
, wFlags
,
234 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
237 static HRESULT WINAPI
SubMatches_get_Item(ISubMatches
*iface
,
238 LONG index
, VARIANT
*pSubMatch
)
240 SubMatches
*This
= impl_from_ISubMatches(iface
);
242 TRACE("(%p)->(%d %p)\n", This
, index
, pSubMatch
);
247 if(!This
->result
|| index
<0 || index
>=This
->result
->paren_count
)
250 if(This
->result
->parens
[index
].index
== -1) {
251 V_VT(pSubMatch
) = VT_EMPTY
;
253 V_VT(pSubMatch
) = VT_BSTR
;
254 V_BSTR(pSubMatch
) = SysAllocStringLen(
255 This
->match
+This
->result
->parens
[index
].index
,
256 This
->result
->parens
[index
].length
);
258 if(!V_BSTR(pSubMatch
))
259 return E_OUTOFMEMORY
;
265 static HRESULT WINAPI
SubMatches_get_Count(ISubMatches
*iface
, LONG
*pCount
)
267 SubMatches
*This
= impl_from_ISubMatches(iface
);
269 TRACE("(%p)->(%p)\n", This
, pCount
);
277 *pCount
= This
->result
->paren_count
;
281 static HRESULT WINAPI
SubMatches_get__NewEnum(ISubMatches
*iface
, IUnknown
**ppEnum
)
283 SubMatches
*This
= impl_from_ISubMatches(iface
);
284 FIXME("(%p)->(%p)\n", This
, ppEnum
);
288 static const ISubMatchesVtbl SubMatchesVtbl
= {
289 SubMatches_QueryInterface
,
292 SubMatches_GetTypeInfoCount
,
293 SubMatches_GetTypeInfo
,
294 SubMatches_GetIDsOfNames
,
297 SubMatches_get_Count
,
298 SubMatches_get__NewEnum
301 static HRESULT
create_sub_matches(DWORD pos
, match_state_t
*result
, SubMatches
**sub_matches
)
307 hres
= init_regexp_typeinfo(SubMatches_tid
);
311 ret
= heap_alloc_zero(sizeof(*ret
));
313 return E_OUTOFMEMORY
;
315 ret
->ISubMatches_iface
.lpVtbl
= &SubMatchesVtbl
;
317 ret
->result
= result
;
319 ret
->match
= heap_alloc((result
->match_len
+1) * sizeof(WCHAR
));
322 return E_OUTOFMEMORY
;
324 memcpy(ret
->match
, result
->cp
-result
->match_len
, result
->match_len
*sizeof(WCHAR
));
325 ret
->match
[result
->match_len
] = 0;
328 for(i
=0; i
<result
->paren_count
; i
++)
329 if(result
->parens
[i
].index
!= -1)
330 result
->parens
[i
].index
-= pos
;
340 static inline Match2
* impl_from_IMatch2(IMatch2
*iface
)
342 return CONTAINING_RECORD(iface
, Match2
, IMatch2_iface
);
345 static HRESULT WINAPI
Match2_QueryInterface(
346 IMatch2
*iface
, REFIID riid
, void **ppv
)
348 Match2
*This
= impl_from_IMatch2(iface
);
350 if(IsEqualGUID(riid
, &IID_IUnknown
)) {
351 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
352 *ppv
= &This
->IMatch2_iface
;
353 }else if(IsEqualGUID(riid
, &IID_IDispatch
)) {
354 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
355 *ppv
= &This
->IMatch2_iface
;
356 }else if(IsEqualGUID(riid
, &IID_IMatch2
)) {
357 TRACE("(%p)->(IID_IMatch2 %p)\n", This
, ppv
);
358 *ppv
= &This
->IMatch2_iface
;
359 }else if(IsEqualGUID(riid
, &IID_IMatch
)) {
360 TRACE("(%p)->(IID_IMatch %p)\n", This
, ppv
);
361 *ppv
= &This
->IMatch_iface
;
362 }else if(IsEqualGUID(riid
, &IID_IDispatchEx
)) {
363 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
365 return E_NOINTERFACE
;
367 FIXME("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
369 return E_NOINTERFACE
;
372 IUnknown_AddRef((IUnknown
*)*ppv
);
376 static ULONG WINAPI
Match2_AddRef(IMatch2
*iface
)
378 Match2
*This
= impl_from_IMatch2(iface
);
379 LONG ref
= InterlockedIncrement(&This
->ref
);
381 TRACE("(%p) ref=%d\n", This
, ref
);
386 static ULONG WINAPI
Match2_Release(IMatch2
*iface
)
388 Match2
*This
= impl_from_IMatch2(iface
);
389 LONG ref
= InterlockedDecrement(&This
->ref
);
391 TRACE("(%p) ref=%d\n", This
, ref
);
394 ISubMatches_Release(&This
->sub_matches
->ISubMatches_iface
);
401 static HRESULT WINAPI
Match2_GetTypeInfoCount(IMatch2
*iface
, UINT
*pctinfo
)
403 Match2
*This
= impl_from_IMatch2(iface
);
405 TRACE("(%p)->(%p)\n", This
, pctinfo
);
411 static HRESULT WINAPI
Match2_GetTypeInfo(IMatch2
*iface
,
412 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
414 Match2
*This
= impl_from_IMatch2(iface
);
415 FIXME("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
419 static HRESULT WINAPI
Match2_GetIDsOfNames(IMatch2
*iface
,
420 REFIID riid
, LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
422 Match2
*This
= impl_from_IMatch2(iface
);
424 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
425 rgszNames
, cNames
, lcid
, rgDispId
);
427 return ITypeInfo_GetIDsOfNames(typeinfos
[Match2_tid
], rgszNames
, cNames
, rgDispId
);
430 static HRESULT WINAPI
Match2_Invoke(IMatch2
*iface
, DISPID dispIdMember
,
431 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
432 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
434 Match2
*This
= impl_from_IMatch2(iface
);
436 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
437 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
439 return ITypeInfo_Invoke(typeinfos
[Match2_tid
], iface
, dispIdMember
, wFlags
,
440 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
443 static HRESULT WINAPI
Match2_get_Value(IMatch2
*iface
, BSTR
*pValue
)
445 Match2
*This
= impl_from_IMatch2(iface
);
447 TRACE("(%p)->(%p)\n", This
, pValue
);
452 if(!This
->sub_matches
->match
) {
457 *pValue
= SysAllocString(This
->sub_matches
->match
);
458 return *pValue
? S_OK
: E_OUTOFMEMORY
;
461 static HRESULT WINAPI
Match2_get_FirstIndex(IMatch2
*iface
, LONG
*pFirstIndex
)
463 Match2
*This
= impl_from_IMatch2(iface
);
465 TRACE("(%p)->(%p)\n", This
, pFirstIndex
);
470 *pFirstIndex
= This
->index
;
474 static HRESULT WINAPI
Match2_get_Length(IMatch2
*iface
, LONG
*pLength
)
476 Match2
*This
= impl_from_IMatch2(iface
);
478 TRACE("(%p)->(%p)\n", This
, pLength
);
483 if(This
->sub_matches
->result
)
484 *pLength
= This
->sub_matches
->result
->match_len
;
490 static HRESULT WINAPI
Match2_get_SubMatches(IMatch2
*iface
, IDispatch
**ppSubMatches
)
492 Match2
*This
= impl_from_IMatch2(iface
);
494 TRACE("(%p)->(%p)\n", This
, ppSubMatches
);
499 *ppSubMatches
= (IDispatch
*)&This
->sub_matches
->ISubMatches_iface
;
500 ISubMatches_AddRef(&This
->sub_matches
->ISubMatches_iface
);
504 static const IMatch2Vtbl Match2Vtbl
= {
505 Match2_QueryInterface
,
508 Match2_GetTypeInfoCount
,
510 Match2_GetIDsOfNames
,
513 Match2_get_FirstIndex
,
515 Match2_get_SubMatches
518 static inline Match2
*impl_from_IMatch(IMatch
*iface
)
520 return CONTAINING_RECORD(iface
, Match2
, IMatch_iface
);
523 static HRESULT WINAPI
Match_QueryInterface(IMatch
*iface
, REFIID riid
, void **ppv
)
525 Match2
*This
= impl_from_IMatch(iface
);
526 return IMatch2_QueryInterface(&This
->IMatch2_iface
, riid
, ppv
);
529 static ULONG WINAPI
Match_AddRef(IMatch
*iface
)
531 Match2
*This
= impl_from_IMatch(iface
);
532 return IMatch2_AddRef(&This
->IMatch2_iface
);
535 static ULONG WINAPI
Match_Release(IMatch
*iface
)
537 Match2
*This
= impl_from_IMatch(iface
);
538 return IMatch2_Release(&This
->IMatch2_iface
);
541 static HRESULT WINAPI
Match_GetTypeInfoCount(IMatch
*iface
, UINT
*pctinfo
)
543 Match2
*This
= impl_from_IMatch(iface
);
544 return IMatch2_GetTypeInfoCount(&This
->IMatch2_iface
, pctinfo
);
547 static HRESULT WINAPI
Match_GetTypeInfo(IMatch
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
549 Match2
*This
= impl_from_IMatch(iface
);
550 return IMatch2_GetTypeInfo(&This
->IMatch2_iface
, iTInfo
, lcid
, ppTInfo
);
553 static HRESULT WINAPI
Match_GetIDsOfNames(IMatch
*iface
, REFIID riid
,
554 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
556 Match2
*This
= impl_from_IMatch(iface
);
557 return IMatch2_GetIDsOfNames(&This
->IMatch2_iface
, riid
, rgszNames
, cNames
, lcid
, rgDispId
);
560 static HRESULT WINAPI
Match_Invoke(IMatch
*iface
, DISPID dispIdMember
,
561 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
562 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
564 Match2
*This
= impl_from_IMatch(iface
);
565 return IMatch2_Invoke(&This
->IMatch2_iface
, dispIdMember
, riid
, lcid
,
566 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
569 static HRESULT WINAPI
Match_get_Value(IMatch
*iface
, BSTR
*pValue
)
571 Match2
*This
= impl_from_IMatch(iface
);
572 return IMatch2_get_Value(&This
->IMatch2_iface
, pValue
);
575 static HRESULT WINAPI
Match_get_FirstIndex(IMatch
*iface
, LONG
*pFirstIndex
)
577 Match2
*This
= impl_from_IMatch(iface
);
578 return IMatch2_get_FirstIndex(&This
->IMatch2_iface
, pFirstIndex
);
581 static HRESULT WINAPI
Match_get_Length(IMatch
*iface
, LONG
*pLength
)
583 Match2
*This
= impl_from_IMatch(iface
);
584 return IMatch2_get_Length(&This
->IMatch2_iface
, pLength
);
587 static IMatchVtbl MatchVtbl
= {
588 Match_QueryInterface
,
591 Match_GetTypeInfoCount
,
596 Match_get_FirstIndex
,
600 static HRESULT
create_match2(DWORD pos
, match_state_t
**result
, IMatch2
**match
)
605 hres
= init_regexp_typeinfo(Match2_tid
);
609 ret
= heap_alloc_zero(sizeof(*ret
));
611 return E_OUTOFMEMORY
;
614 hres
= create_sub_matches(pos
, result
? *result
: NULL
, &ret
->sub_matches
);
622 ret
->IMatch2_iface
.lpVtbl
= &Match2Vtbl
;
623 ret
->IMatch_iface
.lpVtbl
= &MatchVtbl
;
626 *match
= &ret
->IMatch2_iface
;
630 static inline MatchCollectionEnum
* impl_from_IMatchCollectionEnum(IEnumVARIANT
*iface
)
632 return CONTAINING_RECORD(iface
, MatchCollectionEnum
, IEnumVARIANT_iface
);
635 static HRESULT WINAPI
MatchCollectionEnum_QueryInterface(
636 IEnumVARIANT
*iface
, REFIID riid
, void **ppv
)
638 MatchCollectionEnum
*This
= impl_from_IMatchCollectionEnum(iface
);
640 if(IsEqualGUID(riid
, &IID_IUnknown
)) {
641 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
642 *ppv
= &This
->IEnumVARIANT_iface
;
643 }else if(IsEqualGUID(riid
, &IID_IEnumVARIANT
)) {
644 TRACE("(%p)->(IID_IEnumVARIANT %p)\n", This
, ppv
);
645 *ppv
= &This
->IEnumVARIANT_iface
;
647 FIXME("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
649 return E_NOINTERFACE
;
652 IUnknown_AddRef((IUnknown
*)*ppv
);
656 static ULONG WINAPI
MatchCollectionEnum_AddRef(IEnumVARIANT
*iface
)
658 MatchCollectionEnum
*This
= impl_from_IMatchCollectionEnum(iface
);
659 LONG ref
= InterlockedIncrement(&This
->ref
);
661 TRACE("(%p) ref=%d\n", This
, ref
);
666 static ULONG WINAPI
MatchCollectionEnum_Release(IEnumVARIANT
*iface
)
668 MatchCollectionEnum
*This
= impl_from_IMatchCollectionEnum(iface
);
669 LONG ref
= InterlockedDecrement(&This
->ref
);
671 TRACE("(%p) ref=%d\n", This
, ref
);
674 IMatchCollection2_Release(This
->mc
);
681 static HRESULT WINAPI
MatchCollectionEnum_Next(IEnumVARIANT
*iface
,
682 ULONG celt
, VARIANT
*rgVar
, ULONG
*pCeltFetched
)
684 MatchCollectionEnum
*This
= impl_from_IMatchCollectionEnum(iface
);
688 TRACE("(%p)->(%u %p %p)\n", This
, celt
, rgVar
, pCeltFetched
);
690 if(This
->pos
>=This
->count
) {
696 for(i
=0; i
<celt
&& This
->pos
+i
<This
->count
; i
++) {
697 V_VT(rgVar
+i
) = VT_DISPATCH
;
698 hres
= IMatchCollection2_get_Item(This
->mc
, This
->pos
+i
, &V_DISPATCH(rgVar
+i
));
704 VariantClear(rgVar
+i
);
714 static HRESULT WINAPI
MatchCollectionEnum_Skip(IEnumVARIANT
*iface
, ULONG celt
)
716 MatchCollectionEnum
*This
= impl_from_IMatchCollectionEnum(iface
);
718 TRACE("(%p)->(%u)\n", This
, celt
);
720 if(This
->pos
+celt
<= This
->count
)
723 This
->pos
= This
->count
;
727 static HRESULT WINAPI
MatchCollectionEnum_Reset(IEnumVARIANT
*iface
)
729 MatchCollectionEnum
*This
= impl_from_IMatchCollectionEnum(iface
);
731 TRACE("(%p)\n", This
);
737 static HRESULT WINAPI
MatchCollectionEnum_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**ppEnum
)
739 MatchCollectionEnum
*This
= impl_from_IMatchCollectionEnum(iface
);
740 FIXME("(%p)->(%p)\n", This
, ppEnum
);
744 static const IEnumVARIANTVtbl MatchCollectionEnum_Vtbl
= {
745 MatchCollectionEnum_QueryInterface
,
746 MatchCollectionEnum_AddRef
,
747 MatchCollectionEnum_Release
,
748 MatchCollectionEnum_Next
,
749 MatchCollectionEnum_Skip
,
750 MatchCollectionEnum_Reset
,
751 MatchCollectionEnum_Clone
754 static HRESULT
create_enum_variant_mc2(IMatchCollection2
*mc
, ULONG pos
, IEnumVARIANT
**enum_variant
)
756 MatchCollectionEnum
*ret
;
758 ret
= heap_alloc_zero(sizeof(*ret
));
760 return E_OUTOFMEMORY
;
762 ret
->IEnumVARIANT_iface
.lpVtbl
= &MatchCollectionEnum_Vtbl
;
765 IMatchCollection2_get_Count(mc
, &ret
->count
);
767 IMatchCollection2_AddRef(mc
);
769 *enum_variant
= &ret
->IEnumVARIANT_iface
;
773 static inline MatchCollection2
* impl_from_IMatchCollection2(IMatchCollection2
*iface
)
775 return CONTAINING_RECORD(iface
, MatchCollection2
, IMatchCollection2_iface
);
778 static HRESULT WINAPI
MatchCollection2_QueryInterface(
779 IMatchCollection2
*iface
, REFIID riid
, void **ppv
)
781 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
783 if(IsEqualGUID(riid
, &IID_IUnknown
)) {
784 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
785 *ppv
= &This
->IMatchCollection2_iface
;
786 }else if(IsEqualGUID(riid
, &IID_IDispatch
)) {
787 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
788 *ppv
= &This
->IMatchCollection2_iface
;
789 }else if(IsEqualGUID(riid
, &IID_IMatchCollection2
)) {
790 TRACE("(%p)->(IID_IMatchCollection2 %p)\n", This
, ppv
);
791 *ppv
= &This
->IMatchCollection2_iface
;
792 }else if(IsEqualGUID(riid
, &IID_IMatchCollection
)) {
793 TRACE("(%p)->(IID_IMatchCollection %p)\n", This
, ppv
);
794 *ppv
= &This
->IMatchCollection_iface
;
795 }else if(IsEqualGUID(riid
, &IID_IDispatchEx
)) {
796 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
798 return E_NOINTERFACE
;
800 FIXME("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
802 return E_NOINTERFACE
;
805 IUnknown_AddRef((IUnknown
*)*ppv
);
809 static ULONG WINAPI
MatchCollection2_AddRef(IMatchCollection2
*iface
)
811 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
812 LONG ref
= InterlockedIncrement(&This
->ref
);
814 TRACE("(%p) ref=%d\n", This
, ref
);
819 static ULONG WINAPI
MatchCollection2_Release(IMatchCollection2
*iface
)
821 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
822 LONG ref
= InterlockedDecrement(&This
->ref
);
824 TRACE("(%p) ref=%d\n", This
, ref
);
829 for(i
=0; i
<This
->count
; i
++)
830 IMatch2_Release(This
->matches
[i
]);
831 heap_free(This
->matches
);
839 static HRESULT WINAPI
MatchCollection2_GetTypeInfoCount(IMatchCollection2
*iface
, UINT
*pctinfo
)
841 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
843 TRACE("(%p)->(%p)\n", This
, pctinfo
);
849 static HRESULT WINAPI
MatchCollection2_GetTypeInfo(IMatchCollection2
*iface
,
850 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
852 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
853 FIXME("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
857 static HRESULT WINAPI
MatchCollection2_GetIDsOfNames(IMatchCollection2
*iface
,
858 REFIID riid
, LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
860 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
862 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
863 rgszNames
, cNames
, lcid
, rgDispId
);
865 return ITypeInfo_GetIDsOfNames(typeinfos
[MatchCollection2_tid
], rgszNames
, cNames
, rgDispId
);
868 static HRESULT WINAPI
MatchCollection2_Invoke(IMatchCollection2
*iface
, DISPID dispIdMember
,
869 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
870 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
872 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
874 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
875 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
877 return ITypeInfo_Invoke(typeinfos
[MatchCollection2_tid
], iface
, dispIdMember
, wFlags
,
878 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
881 static HRESULT WINAPI
MatchCollection2_get_Item(IMatchCollection2
*iface
,
882 LONG index
, IDispatch
**ppMatch
)
884 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
886 TRACE("(%p)->()\n", This
);
891 if(index
<0 || index
>=This
->count
)
894 *ppMatch
= (IDispatch
*)This
->matches
[index
];
895 IMatch2_AddRef(This
->matches
[index
]);
899 static HRESULT WINAPI
MatchCollection2_get_Count(IMatchCollection2
*iface
, LONG
*pCount
)
901 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
903 TRACE("(%p)->()\n", This
);
908 *pCount
= This
->count
;
912 static HRESULT WINAPI
MatchCollection2_get__NewEnum(IMatchCollection2
*iface
, IUnknown
**ppEnum
)
914 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
916 TRACE("(%p)->(%p)\n", This
, ppEnum
);
921 return create_enum_variant_mc2(&This
->IMatchCollection2_iface
, 0, (IEnumVARIANT
**)ppEnum
);
924 static const IMatchCollection2Vtbl MatchCollection2Vtbl
= {
925 MatchCollection2_QueryInterface
,
926 MatchCollection2_AddRef
,
927 MatchCollection2_Release
,
928 MatchCollection2_GetTypeInfoCount
,
929 MatchCollection2_GetTypeInfo
,
930 MatchCollection2_GetIDsOfNames
,
931 MatchCollection2_Invoke
,
932 MatchCollection2_get_Item
,
933 MatchCollection2_get_Count
,
934 MatchCollection2_get__NewEnum
937 static inline MatchCollection2
*impl_from_IMatchCollection(IMatchCollection
*iface
)
939 return CONTAINING_RECORD(iface
, MatchCollection2
, IMatchCollection_iface
);
942 static HRESULT WINAPI
MatchCollection_QueryInterface(IMatchCollection
*iface
, REFIID riid
, void **ppv
)
944 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
945 return IMatchCollection2_QueryInterface(&This
->IMatchCollection2_iface
, riid
, ppv
);
948 static ULONG WINAPI
MatchCollection_AddRef(IMatchCollection
*iface
)
950 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
951 return IMatchCollection2_AddRef(&This
->IMatchCollection2_iface
);
954 static ULONG WINAPI
MatchCollection_Release(IMatchCollection
*iface
)
956 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
957 return IMatchCollection2_Release(&This
->IMatchCollection2_iface
);
960 static HRESULT WINAPI
MatchCollection_GetTypeInfoCount(IMatchCollection
*iface
, UINT
*pctinfo
)
962 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
963 return IMatchCollection2_GetTypeInfoCount(&This
->IMatchCollection2_iface
, pctinfo
);
966 static HRESULT WINAPI
MatchCollection_GetTypeInfo(IMatchCollection
*iface
,
967 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
969 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
970 return IMatchCollection2_GetTypeInfo(&This
->IMatchCollection2_iface
, iTInfo
, lcid
, ppTInfo
);
973 static HRESULT WINAPI
MatchCollection_GetIDsOfNames(IMatchCollection
*iface
, REFIID riid
,
974 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
976 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
977 return IMatchCollection2_GetIDsOfNames(&This
->IMatchCollection2_iface
,
978 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
981 static HRESULT WINAPI
MatchCollection_Invoke(IMatchCollection
*iface
, DISPID dispIdMember
,
982 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
983 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
985 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
986 return IMatchCollection2_Invoke(&This
->IMatchCollection2_iface
, dispIdMember
,
987 riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
990 static HRESULT WINAPI
MatchCollection_get_Item(IMatchCollection
*iface
, LONG index
, IDispatch
**ppMatch
)
992 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
993 return IMatchCollection2_get_Item(&This
->IMatchCollection2_iface
, index
, ppMatch
);
996 static HRESULT WINAPI
MatchCollection_get_Count(IMatchCollection
*iface
, LONG
*pCount
)
998 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
999 return IMatchCollection2_get_Count(&This
->IMatchCollection2_iface
, pCount
);
1002 static HRESULT WINAPI
MatchCollection_get__NewEnum(IMatchCollection
*iface
, IUnknown
**ppEnum
)
1004 MatchCollection2
*This
= impl_from_IMatchCollection(iface
);
1005 return IMatchCollection2_get__NewEnum(&This
->IMatchCollection2_iface
, ppEnum
);
1008 static const IMatchCollectionVtbl MatchCollectionVtbl
= {
1009 MatchCollection_QueryInterface
,
1010 MatchCollection_AddRef
,
1011 MatchCollection_Release
,
1012 MatchCollection_GetTypeInfoCount
,
1013 MatchCollection_GetTypeInfo
,
1014 MatchCollection_GetIDsOfNames
,
1015 MatchCollection_Invoke
,
1016 MatchCollection_get_Item
,
1017 MatchCollection_get_Count
,
1018 MatchCollection_get__NewEnum
1021 static HRESULT
add_match(IMatchCollection2
*iface
, IMatch2
*add
)
1023 MatchCollection2
*This
= impl_from_IMatchCollection2(iface
);
1025 TRACE("(%p)->(%p)\n", This
, add
);
1028 This
->matches
= heap_alloc(8*sizeof(IMatch
*));
1030 return E_OUTOFMEMORY
;
1032 }else if(This
->size
== This
->count
) {
1033 IMatch2
**new_matches
= heap_realloc(This
->matches
, 2*This
->size
*sizeof(IMatch
*));
1035 return E_OUTOFMEMORY
;
1037 This
->matches
= new_matches
;
1041 This
->matches
[This
->count
++] = add
;
1042 IMatch2_AddRef(add
);
1046 static HRESULT
create_match_collection2(IMatchCollection2
**match_collection
)
1048 MatchCollection2
*ret
;
1051 hres
= init_regexp_typeinfo(MatchCollection2_tid
);
1055 ret
= heap_alloc_zero(sizeof(*ret
));
1057 return E_OUTOFMEMORY
;
1059 ret
->IMatchCollection2_iface
.lpVtbl
= &MatchCollection2Vtbl
;
1060 ret
->IMatchCollection_iface
.lpVtbl
= &MatchCollectionVtbl
;
1063 *match_collection
= &ret
->IMatchCollection2_iface
;
1067 static inline RegExp2
*impl_from_IRegExp2(IRegExp2
*iface
)
1069 return CONTAINING_RECORD(iface
, RegExp2
, IRegExp2_iface
);
1072 static HRESULT WINAPI
RegExp2_QueryInterface(IRegExp2
*iface
, REFIID riid
, void **ppv
)
1074 RegExp2
*This
= impl_from_IRegExp2(iface
);
1076 if(IsEqualGUID(riid
, &IID_IUnknown
)) {
1077 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
1078 *ppv
= &This
->IRegExp2_iface
;
1079 }else if(IsEqualGUID(riid
, &IID_IDispatch
)) {
1080 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
1081 *ppv
= &This
->IRegExp2_iface
;
1082 }else if(IsEqualGUID(riid
, &IID_IRegExp2
)) {
1083 TRACE("(%p)->(IID_IRegExp2 %p)\n", This
, ppv
);
1084 *ppv
= &This
->IRegExp2_iface
;
1085 }else if(IsEqualGUID(riid
, &IID_IRegExp
)) {
1086 TRACE("(%p)->(IID_IRegExp %p)\n", This
, ppv
);
1087 *ppv
= &This
->IRegExp_iface
;
1088 }else if(IsEqualGUID(riid
, &IID_IDispatchEx
)) {
1089 TRACE("(%p)->(IID_IDispatchEx %p)\n", This
, ppv
);
1091 return E_NOINTERFACE
;
1093 FIXME("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
1095 return E_NOINTERFACE
;
1098 IUnknown_AddRef((IUnknown
*)*ppv
);
1102 static ULONG WINAPI
RegExp2_AddRef(IRegExp2
*iface
)
1104 RegExp2
*This
= impl_from_IRegExp2(iface
);
1105 LONG ref
= InterlockedIncrement(&This
->ref
);
1107 TRACE("(%p) ref=%d\n", This
, ref
);
1112 static ULONG WINAPI
RegExp2_Release(IRegExp2
*iface
)
1114 RegExp2
*This
= impl_from_IRegExp2(iface
);
1115 LONG ref
= InterlockedDecrement(&This
->ref
);
1117 TRACE("(%p) ref=%d\n", This
, ref
);
1120 heap_free(This
->pattern
);
1122 regexp_destroy(This
->regexp
);
1123 heap_pool_free(&This
->pool
);
1130 static HRESULT WINAPI
RegExp2_GetTypeInfoCount(IRegExp2
*iface
, UINT
*pctinfo
)
1132 RegExp2
*This
= impl_from_IRegExp2(iface
);
1134 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1140 static HRESULT WINAPI
RegExp2_GetTypeInfo(IRegExp2
*iface
,
1141 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
1143 RegExp2
*This
= impl_from_IRegExp2(iface
);
1144 FIXME("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1148 static HRESULT WINAPI
RegExp2_GetIDsOfNames(IRegExp2
*iface
, REFIID riid
,
1149 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1151 RegExp2
*This
= impl_from_IRegExp2(iface
);
1153 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
),
1154 rgszNames
, cNames
, lcid
, rgDispId
);
1156 return ITypeInfo_GetIDsOfNames(typeinfos
[RegExp2_tid
], rgszNames
, cNames
, rgDispId
);
1159 static HRESULT WINAPI
RegExp2_Invoke(IRegExp2
*iface
, DISPID dispIdMember
,
1160 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
1161 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1163 RegExp2
*This
= impl_from_IRegExp2(iface
);
1165 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1166 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1168 return ITypeInfo_Invoke(typeinfos
[RegExp2_tid
], iface
, dispIdMember
, wFlags
,
1169 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1172 static HRESULT WINAPI
RegExp2_get_Pattern(IRegExp2
*iface
, BSTR
*pPattern
)
1174 RegExp2
*This
= impl_from_IRegExp2(iface
);
1176 TRACE("(%p)->(%p)\n", This
, pPattern
);
1181 if(!This
->pattern
) {
1186 *pPattern
= SysAllocString(This
->pattern
);
1187 return *pPattern
? S_OK
: E_OUTOFMEMORY
;
1190 static HRESULT WINAPI
RegExp2_put_Pattern(IRegExp2
*iface
, BSTR pattern
)
1192 RegExp2
*This
= impl_from_IRegExp2(iface
);
1195 TRACE("(%p)->(%s)\n", This
, wine_dbgstr_w(pattern
));
1197 if(pattern
&& *pattern
) {
1198 SIZE_T size
= (SysStringLen(pattern
)+1) * sizeof(WCHAR
);
1199 new_pattern
= heap_alloc(size
);
1201 return E_OUTOFMEMORY
;
1202 memcpy(new_pattern
, pattern
, size
);
1207 heap_free(This
->pattern
);
1208 This
->pattern
= new_pattern
;
1211 regexp_destroy(This
->regexp
);
1212 This
->regexp
= NULL
;
1217 static HRESULT WINAPI
RegExp2_get_IgnoreCase(IRegExp2
*iface
, VARIANT_BOOL
*pIgnoreCase
)
1219 RegExp2
*This
= impl_from_IRegExp2(iface
);
1221 TRACE("(%p)->(%p)\n", This
, pIgnoreCase
);
1226 *pIgnoreCase
= This
->flags
& REG_FOLD
? VARIANT_TRUE
: VARIANT_FALSE
;
1230 static HRESULT WINAPI
RegExp2_put_IgnoreCase(IRegExp2
*iface
, VARIANT_BOOL ignoreCase
)
1232 RegExp2
*This
= impl_from_IRegExp2(iface
);
1234 TRACE("(%p)->(%s)\n", This
, ignoreCase
? "true" : "false");
1237 This
->flags
|= REG_FOLD
;
1239 This
->flags
&= ~REG_FOLD
;
1243 static HRESULT WINAPI
RegExp2_get_Global(IRegExp2
*iface
, VARIANT_BOOL
*pGlobal
)
1245 RegExp2
*This
= impl_from_IRegExp2(iface
);
1247 TRACE("(%p)->(%p)\n", This
, pGlobal
);
1252 *pGlobal
= This
->flags
& REG_GLOB
? VARIANT_TRUE
: VARIANT_FALSE
;
1256 static HRESULT WINAPI
RegExp2_put_Global(IRegExp2
*iface
, VARIANT_BOOL global
)
1258 RegExp2
*This
= impl_from_IRegExp2(iface
);
1260 TRACE("(%p)->(%s)\n", This
, global
? "true" : "false");
1263 This
->flags
|= REG_GLOB
;
1265 This
->flags
&= ~REG_GLOB
;
1269 static HRESULT WINAPI
RegExp2_get_Multiline(IRegExp2
*iface
, VARIANT_BOOL
*pMultiline
)
1271 RegExp2
*This
= impl_from_IRegExp2(iface
);
1273 TRACE("(%p)->(%p)\n", This
, pMultiline
);
1278 *pMultiline
= This
->flags
& REG_MULTILINE
? VARIANT_TRUE
: VARIANT_FALSE
;
1282 static HRESULT WINAPI
RegExp2_put_Multiline(IRegExp2
*iface
, VARIANT_BOOL multiline
)
1284 RegExp2
*This
= impl_from_IRegExp2(iface
);
1286 TRACE("(%p)->(%s)\n", This
, multiline
? "true" : "false");
1289 This
->flags
|= REG_MULTILINE
;
1291 This
->flags
&= ~REG_MULTILINE
;
1295 static HRESULT WINAPI
RegExp2_Execute(IRegExp2
*iface
,
1296 BSTR sourceString
, IDispatch
**ppMatches
)
1298 RegExp2
*This
= impl_from_IRegExp2(iface
);
1299 match_state_t
*result
;
1301 IMatchCollection2
*match_collection
;
1302 IMatch2
*add
= NULL
;
1305 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(sourceString
), ppMatches
);
1307 if(!This
->pattern
) {
1308 DWORD i
, len
= SysStringLen(sourceString
);
1310 hres
= create_match_collection2(&match_collection
);
1314 for(i
=0; i
<=len
; i
++) {
1315 hres
= create_match2(i
, NULL
, &add
);
1319 hres
= add_match(match_collection
, add
);
1322 IMatch2_Release(add
);
1324 if(!(This
->flags
& REG_GLOB
))
1329 IMatchCollection2_Release(match_collection
);
1333 *ppMatches
= (IDispatch
*)match_collection
;
1338 This
->regexp
= regexp_new(NULL
, &This
->pool
, This
->pattern
,
1339 lstrlenW(This
->pattern
), This
->flags
, FALSE
);
1343 hres
= regexp_set_flags(&This
->regexp
, NULL
, &This
->pool
, This
->flags
);
1348 hres
= create_match_collection2(&match_collection
);
1354 result
= alloc_match_state(This
->regexp
, NULL
, pos
);
1356 hres
= E_OUTOFMEMORY
;
1360 hres
= regexp_execute(This
->regexp
, NULL
, &This
->pool
,
1361 sourceString
, SysStringLen(sourceString
), result
);
1368 hres
= create_match2(result
->cp
-result
->match_len
-sourceString
, &result
, &add
);
1372 hres
= add_match(match_collection
, add
);
1373 IMatch2_Release(add
);
1377 if(!(This
->flags
& REG_GLOB
))
1382 IMatchCollection2_Release(match_collection
);
1386 *ppMatches
= (IDispatch
*)match_collection
;
1390 static HRESULT WINAPI
RegExp2_Test(IRegExp2
*iface
, BSTR sourceString
, VARIANT_BOOL
*pMatch
)
1392 RegExp2
*This
= impl_from_IRegExp2(iface
);
1393 match_state_t
*result
;
1397 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(sourceString
), pMatch
);
1399 if(!This
->pattern
) {
1400 *pMatch
= VARIANT_TRUE
;
1405 This
->regexp
= regexp_new(NULL
, &This
->pool
, This
->pattern
,
1406 lstrlenW(This
->pattern
), This
->flags
, FALSE
);
1410 hres
= regexp_set_flags(&This
->regexp
, NULL
, &This
->pool
, This
->flags
);
1415 mark
= heap_pool_mark(&This
->pool
);
1416 result
= alloc_match_state(This
->regexp
, &This
->pool
, sourceString
);
1418 heap_pool_clear(mark
);
1419 return E_OUTOFMEMORY
;
1422 hres
= regexp_execute(This
->regexp
, NULL
, &This
->pool
,
1423 sourceString
, SysStringLen(sourceString
), result
);
1425 heap_pool_clear(mark
);
1428 *pMatch
= VARIANT_TRUE
;
1429 }else if(hres
== S_FALSE
) {
1430 *pMatch
= VARIANT_FALSE
;
1442 static BOOL
strbuf_ensure_size(strbuf_t
*buf
, unsigned len
)
1447 if(len
<= buf
->size
)
1450 new_size
= buf
->size
? buf
->size
<<1 : 16;
1454 new_buf
= heap_realloc(buf
->buf
, new_size
*sizeof(WCHAR
));
1456 new_buf
= heap_alloc(new_size
*sizeof(WCHAR
));
1461 buf
->size
= new_size
;
1465 static HRESULT
strbuf_append(strbuf_t
*buf
, const WCHAR
*str
, DWORD len
)
1470 if(!strbuf_ensure_size(buf
, buf
->len
+len
))
1471 return E_OUTOFMEMORY
;
1473 memcpy(buf
->buf
+buf
->len
, str
, len
*sizeof(WCHAR
));
1478 static HRESULT WINAPI
RegExp2_Replace(IRegExp2
*iface
, BSTR source
, VARIANT replaceVar
, BSTR
*ret
)
1480 RegExp2
*This
= impl_from_IRegExp2(iface
);
1481 const WCHAR
*cp
, *prev_cp
= NULL
, *ptr
, *prev_ptr
;
1482 size_t match_len
= 0, source_len
, replace_len
;
1483 strbuf_t buf
= { NULL
, 0, 0 };
1484 match_state_t
*state
= NULL
;
1490 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_w(source
), debugstr_variant(&replaceVar
), ret
);
1494 This
->regexp
= regexp_new(NULL
, &This
->pool
, This
->pattern
,
1495 lstrlenW(This
->pattern
), This
->flags
, FALSE
);
1497 return E_OUTOFMEMORY
;
1499 hres
= regexp_set_flags(&This
->regexp
, NULL
, &This
->pool
, This
->flags
);
1505 V_VT(&strv
) = VT_EMPTY
;
1506 hres
= VariantChangeType(&strv
, &replaceVar
, 0, VT_BSTR
);
1509 replace
= V_BSTR(&strv
);
1510 replace_len
= SysStringLen(replace
);
1511 source_len
= SysStringLen(source
);
1513 mark
= heap_pool_mark(&This
->pool
);
1515 if(This
->regexp
&& !(state
= alloc_match_state(This
->regexp
, &This
->pool
, cp
)))
1516 hres
= E_OUTOFMEMORY
;
1518 while(SUCCEEDED(hres
)) {
1521 hres
= regexp_execute(This
->regexp
, NULL
, &This
->pool
, source
, source_len
, state
);
1522 if(hres
!= S_OK
) break;
1524 match_len
= state
->match_len
;
1526 if(cp
== source
+ source_len
)
1533 hres
= strbuf_append(&buf
, prev_cp
, cp
- prev_cp
- match_len
);
1538 while((ptr
= wmemchr(prev_ptr
, '$', replace
+ replace_len
- prev_ptr
))) {
1539 hres
= strbuf_append(&buf
, prev_ptr
, ptr
- prev_ptr
);
1545 hres
= strbuf_append(&buf
, ptr
, 1);
1549 hres
= strbuf_append(&buf
, cp
- match_len
, match_len
);
1553 hres
= strbuf_append(&buf
, source
, cp
- source
- match_len
);
1557 hres
= strbuf_append(&buf
, cp
, source
+ source_len
- cp
);
1563 if(!is_digit(ptr
[1])) {
1564 hres
= strbuf_append(&buf
, ptr
, 1);
1570 if(is_digit(ptr
[2]) && idx
* 10 + (ptr
[2] - '0') <= state
->paren_count
) {
1571 idx
= idx
* 10 + (ptr
[2] - '0');
1573 }else if(idx
&& idx
<= state
->paren_count
) {
1576 hres
= strbuf_append(&buf
, ptr
, 1);
1581 if(state
->parens
[idx
- 1].index
!= -1)
1582 hres
= strbuf_append(&buf
, source
+ state
->parens
[idx
- 1].index
,
1583 state
->parens
[idx
- 1].length
);
1591 hres
= strbuf_append(&buf
, prev_ptr
, replace
+ replace_len
- prev_ptr
);
1595 if(!(This
->flags
& REG_GLOB
))
1599 if(SUCCEEDED(hres
)) {
1600 hres
= strbuf_append(&buf
, cp
, source
+ source_len
- cp
);
1601 if(SUCCEEDED(hres
) && !(*ret
= SysAllocStringLen(buf
.buf
, buf
.len
)))
1602 hres
= E_OUTOFMEMORY
;
1605 heap_pool_clear(mark
);
1607 SysFreeString(replace
);
1611 static const IRegExp2Vtbl RegExp2Vtbl
= {
1612 RegExp2_QueryInterface
,
1615 RegExp2_GetTypeInfoCount
,
1616 RegExp2_GetTypeInfo
,
1617 RegExp2_GetIDsOfNames
,
1619 RegExp2_get_Pattern
,
1620 RegExp2_put_Pattern
,
1621 RegExp2_get_IgnoreCase
,
1622 RegExp2_put_IgnoreCase
,
1625 RegExp2_get_Multiline
,
1626 RegExp2_put_Multiline
,
1632 BSTR
string_replace(BSTR string
, BSTR find
, BSTR replace
, int from
, int cnt
, int mode
)
1634 const WCHAR
*ptr
, *string_end
;
1635 strbuf_t buf
= { NULL
, 0, 0 };
1636 size_t replace_len
, find_len
;
1638 HRESULT hres
= S_OK
;
1641 string_end
= string
+ SysStringLen(string
);
1642 ptr
= from
> SysStringLen(string
) ? string_end
: string
+ from
;
1644 find_len
= SysStringLen(find
);
1645 replace_len
= SysStringLen(replace
);
1647 while(string_end
- ptr
>= find_len
&& cnt
&& find_len
) {
1648 pos
= FindStringOrdinal(FIND_FROMSTART
, ptr
, string_end
- ptr
,
1649 find
, find_len
, mode
);
1654 hres
= strbuf_append(&buf
, ptr
, pos
);
1657 hres
= strbuf_append(&buf
, replace
, replace_len
);
1661 ptr
= ptr
+ pos
+ find_len
;
1667 if(SUCCEEDED(hres
)) {
1668 hres
= strbuf_append(&buf
, ptr
, string_end
- ptr
);
1670 ret
= SysAllocStringLen(buf
.buf
, buf
.len
);
1677 static inline RegExp2
*impl_from_IRegExp(IRegExp
*iface
)
1679 return CONTAINING_RECORD(iface
, RegExp2
, IRegExp_iface
);
1682 static HRESULT WINAPI
RegExp_QueryInterface(IRegExp
*iface
, REFIID riid
, void **ppv
)
1684 RegExp2
*This
= impl_from_IRegExp(iface
);
1685 return IRegExp2_QueryInterface(&This
->IRegExp2_iface
, riid
, ppv
);
1688 static ULONG WINAPI
RegExp_AddRef(IRegExp
*iface
)
1690 RegExp2
*This
= impl_from_IRegExp(iface
);
1691 return IRegExp2_AddRef(&This
->IRegExp2_iface
);
1694 static ULONG WINAPI
RegExp_Release(IRegExp
*iface
)
1696 RegExp2
*This
= impl_from_IRegExp(iface
);
1697 return IRegExp2_Release(&This
->IRegExp2_iface
);
1700 static HRESULT WINAPI
RegExp_GetTypeInfoCount(IRegExp
*iface
, UINT
*pctinfo
)
1702 RegExp2
*This
= impl_from_IRegExp(iface
);
1703 return IRegExp2_GetTypeInfoCount(&This
->IRegExp2_iface
, pctinfo
);
1706 static HRESULT WINAPI
RegExp_GetTypeInfo(IRegExp
*iface
,
1707 UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
1709 RegExp2
*This
= impl_from_IRegExp(iface
);
1710 return IRegExp2_GetTypeInfo(&This
->IRegExp2_iface
, iTInfo
, lcid
, ppTInfo
);
1713 static HRESULT WINAPI
RegExp_GetIDsOfNames(IRegExp
*iface
, REFIID riid
,
1714 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1716 RegExp2
*This
= impl_from_IRegExp(iface
);
1717 return IRegExp2_GetIDsOfNames(&This
->IRegExp2_iface
, riid
, rgszNames
, cNames
, lcid
, rgDispId
);
1720 static HRESULT WINAPI
RegExp_Invoke(IRegExp
*iface
, DISPID dispIdMember
,
1721 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
1722 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1724 RegExp2
*This
= impl_from_IRegExp(iface
);
1725 return IRegExp2_Invoke(&This
->IRegExp2_iface
, dispIdMember
, riid
, lcid
,
1726 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1729 static HRESULT WINAPI
RegExp_get_Pattern(IRegExp
*iface
, BSTR
*pPattern
)
1731 RegExp2
*This
= impl_from_IRegExp(iface
);
1732 return IRegExp2_get_Pattern(&This
->IRegExp2_iface
, pPattern
);
1735 static HRESULT WINAPI
RegExp_put_Pattern(IRegExp
*iface
, BSTR pPattern
)
1737 RegExp2
*This
= impl_from_IRegExp(iface
);
1738 return IRegExp2_put_Pattern(&This
->IRegExp2_iface
, pPattern
);
1741 static HRESULT WINAPI
RegExp_get_IgnoreCase(IRegExp
*iface
, VARIANT_BOOL
*pIgnoreCase
)
1743 RegExp2
*This
= impl_from_IRegExp(iface
);
1744 return IRegExp2_get_IgnoreCase(&This
->IRegExp2_iface
, pIgnoreCase
);
1747 static HRESULT WINAPI
RegExp_put_IgnoreCase(IRegExp
*iface
, VARIANT_BOOL pIgnoreCase
)
1749 RegExp2
*This
= impl_from_IRegExp(iface
);
1750 return IRegExp2_put_IgnoreCase(&This
->IRegExp2_iface
, pIgnoreCase
);
1753 static HRESULT WINAPI
RegExp_get_Global(IRegExp
*iface
, VARIANT_BOOL
*pGlobal
)
1755 RegExp2
*This
= impl_from_IRegExp(iface
);
1756 return IRegExp2_get_Global(&This
->IRegExp2_iface
, pGlobal
);
1759 static HRESULT WINAPI
RegExp_put_Global(IRegExp
*iface
, VARIANT_BOOL pGlobal
)
1761 RegExp2
*This
= impl_from_IRegExp(iface
);
1762 return IRegExp2_put_Global(&This
->IRegExp2_iface
, pGlobal
);
1765 static HRESULT WINAPI
RegExp_Execute(IRegExp
*iface
,
1766 BSTR sourceString
, IDispatch
**ppMatches
)
1768 RegExp2
*This
= impl_from_IRegExp(iface
);
1769 return IRegExp2_Execute(&This
->IRegExp2_iface
, sourceString
, ppMatches
);
1772 static HRESULT WINAPI
RegExp_Test(IRegExp
*iface
, BSTR sourceString
, VARIANT_BOOL
*pMatch
)
1774 RegExp2
*This
= impl_from_IRegExp(iface
);
1775 return IRegExp2_Test(&This
->IRegExp2_iface
, sourceString
, pMatch
);
1778 static HRESULT WINAPI
RegExp_Replace(IRegExp
*iface
, BSTR sourceString
,
1779 BSTR replaceString
, BSTR
*pDestString
)
1781 RegExp2
*This
= impl_from_IRegExp(iface
);
1784 V_VT(&replace
) = VT_BSTR
;
1785 V_BSTR(&replace
) = replaceString
;
1786 return IRegExp2_Replace(&This
->IRegExp2_iface
, sourceString
, replace
, pDestString
);
1789 static IRegExpVtbl RegExpVtbl
= {
1790 RegExp_QueryInterface
,
1793 RegExp_GetTypeInfoCount
,
1795 RegExp_GetIDsOfNames
,
1799 RegExp_get_IgnoreCase
,
1800 RegExp_put_IgnoreCase
,
1808 HRESULT
create_regexp(IDispatch
**ret
)
1813 hres
= init_regexp_typeinfo(RegExp2_tid
);
1817 regexp
= heap_alloc_zero(sizeof(*regexp
));
1819 return E_OUTOFMEMORY
;
1821 regexp
->IRegExp2_iface
.lpVtbl
= &RegExp2Vtbl
;
1822 regexp
->IRegExp_iface
.lpVtbl
= &RegExpVtbl
;
1824 heap_pool_init(®exp
->pool
);
1826 *ret
= (IDispatch
*)®exp
->IRegExp2_iface
;
1830 HRESULT WINAPI
VBScriptRegExpFactory_CreateInstance(IClassFactory
*iface
, IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
1835 TRACE("(%p %s %p)\n", pUnkOuter
, debugstr_guid(riid
), ppv
);
1837 hres
= create_regexp(®exp
);
1841 hres
= IDispatch_QueryInterface(regexp
, riid
, ppv
);
1842 IDispatch_Release(regexp
);
1846 void release_regexp_typelib(void)
1850 for(i
=0; i
<REGEXP_LAST_tid
; i
++) {
1852 ITypeInfo_Release(typeinfos
[i
]);
1855 ITypeLib_Release(typelib
);