[VBSCRIPT]
[reactos.git] / reactos / dll / win32 / vbscript / vbregexp.c
1 /*
2 * Copyright 2013 Piotr Caban for CodeWeavers
3 *
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.
8 *
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.
13 *
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
17 */
18
19 #include "vbscript.h"
20
21 #include <initguid.h>
22 #include <vbsregexp55.h>
23
24 #define REGEXP_TID_LIST \
25 XDIID(RegExp2), \
26 XDIID(Match2), \
27 XDIID(MatchCollection2), \
28 XDIID(SubMatches)
29
30 typedef enum {
31 #define XDIID(iface) iface ## _tid
32 REGEXP_TID_LIST,
33 #undef XDIID
34 REGEXP_LAST_tid
35 } regexp_tid_t;
36
37 static REFIID tid_ids[] = {
38 #define XDIID(iface) &IID_I ## iface
39 REGEXP_TID_LIST
40 #undef XDIID
41 };
42
43 static ITypeLib *typelib;
44 static ITypeInfo *typeinfos[REGEXP_LAST_tid];
45
46 static HRESULT init_regexp_typeinfo(regexp_tid_t tid)
47 {
48 HRESULT hres;
49
50 if(!typelib) {
51 static const WCHAR vbscript_dll3W[] = {'v','b','s','c','r','i','p','t','.','d','l','l','\\','3',0};
52 ITypeLib *tl;
53
54 hres = LoadTypeLib(vbscript_dll3W, &tl);
55 if(FAILED(hres)) {
56 ERR("LoadRegTypeLib failed: %08x\n", hres);
57 return hres;
58 }
59
60 if(InterlockedCompareExchangePointer((void**)&typelib, tl, NULL))
61 ITypeLib_Release(tl);
62 }
63
64 if(!typeinfos[tid]) {
65 ITypeInfo *ti;
66
67 hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
68 if(FAILED(hres)) {
69 ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hres);
70 return hres;
71 }
72
73 if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
74 ITypeInfo_Release(ti);
75 }
76
77 return S_OK;
78 }
79
80 struct SubMatches {
81 ISubMatches ISubMatches_iface;
82
83 LONG ref;
84
85 WCHAR *match;
86 match_state_t *result;
87 };
88
89 typedef struct Match2 {
90 IMatch2 IMatch2_iface;
91 IMatch IMatch_iface;
92
93 LONG ref;
94
95 DWORD index;
96 SubMatches *sub_matches;
97 } Match2;
98
99 typedef struct MatchCollectionEnum {
100 IEnumVARIANT IEnumVARIANT_iface;
101
102 LONG ref;
103
104 IMatchCollection2 *mc;
105 LONG pos;
106 LONG count;
107 } MatchCollectionEnum;
108
109 typedef struct MatchCollection2 {
110 IMatchCollection2 IMatchCollection2_iface;
111 IMatchCollection IMatchCollection_iface;
112
113 LONG ref;
114
115 IMatch2 **matches;
116 DWORD count;
117 DWORD size;
118 } MatchCollection2;
119
120 typedef struct RegExp2 {
121 IRegExp2 IRegExp2_iface;
122 IRegExp IRegExp_iface;
123
124 LONG ref;
125
126 WCHAR *pattern;
127 regexp_t *regexp;
128 heap_pool_t pool;
129 WORD flags;
130 } RegExp2;
131
132 static inline SubMatches* impl_from_ISubMatches(ISubMatches *iface)
133 {
134 return CONTAINING_RECORD(iface, SubMatches, ISubMatches_iface);
135 }
136
137 static HRESULT WINAPI SubMatches_QueryInterface(
138 ISubMatches *iface, REFIID riid, void **ppv)
139 {
140 SubMatches *This = impl_from_ISubMatches(iface);
141
142 if(IsEqualGUID(riid, &IID_IUnknown)) {
143 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
144 *ppv = &This->ISubMatches_iface;
145 }else if(IsEqualGUID(riid, &IID_IDispatch)) {
146 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
147 *ppv = &This->ISubMatches_iface;
148 }else if(IsEqualGUID(riid, &IID_ISubMatches)) {
149 TRACE("(%p)->(IID_ISubMatches %p)\n", This, ppv);
150 *ppv = &This->ISubMatches_iface;
151 }else if(IsEqualGUID(riid, &IID_IDispatchEx)) {
152 TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
153 *ppv = NULL;
154 return E_NOINTERFACE;
155 }else {
156 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
157 *ppv = NULL;
158 return E_NOINTERFACE;
159 }
160
161 IUnknown_AddRef((IUnknown*)*ppv);
162 return S_OK;
163 }
164
165 static ULONG WINAPI SubMatches_AddRef(ISubMatches *iface)
166 {
167 SubMatches *This = impl_from_ISubMatches(iface);
168 LONG ref = InterlockedIncrement(&This->ref);
169
170 TRACE("(%p) ref=%d\n", This, ref);
171
172 return ref;
173 }
174
175 static ULONG WINAPI SubMatches_Release(ISubMatches *iface)
176 {
177 SubMatches *This = impl_from_ISubMatches(iface);
178 LONG ref = InterlockedDecrement(&This->ref);
179
180 TRACE("(%p) ref=%d\n", This, ref);
181
182 if(!ref) {
183 heap_free(This->match);
184 heap_free(This->result);
185 heap_free(This);
186 }
187
188 return ref;
189 }
190
191 static HRESULT WINAPI SubMatches_GetTypeInfoCount(ISubMatches *iface, UINT *pctinfo)
192 {
193 SubMatches *This = impl_from_ISubMatches(iface);
194
195 TRACE("(%p)->(%p)\n", This, pctinfo);
196
197 *pctinfo = 1;
198 return S_OK;
199 }
200
201 static HRESULT WINAPI SubMatches_GetTypeInfo(ISubMatches *iface,
202 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
203 {
204 SubMatches *This = impl_from_ISubMatches(iface);
205 FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
206 return E_NOTIMPL;
207 }
208
209 static HRESULT WINAPI SubMatches_GetIDsOfNames(ISubMatches *iface,
210 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
211 {
212 SubMatches *This = impl_from_ISubMatches(iface);
213
214 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
215 rgszNames, cNames, lcid, rgDispId);
216
217 return ITypeInfo_GetIDsOfNames(typeinfos[SubMatches_tid], rgszNames, cNames, rgDispId);
218 }
219
220 static HRESULT WINAPI SubMatches_Invoke(ISubMatches *iface, DISPID dispIdMember,
221 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
222 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
223 {
224 SubMatches *This = impl_from_ISubMatches(iface);
225
226 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
227 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
228
229 return ITypeInfo_Invoke(typeinfos[SubMatches_tid], iface, dispIdMember, wFlags,
230 pDispParams, pVarResult, pExcepInfo, puArgErr);
231 }
232
233 static HRESULT WINAPI SubMatches_get_Item(ISubMatches *iface,
234 LONG index, VARIANT *pSubMatch)
235 {
236 SubMatches *This = impl_from_ISubMatches(iface);
237
238 TRACE("(%p)->(%d %p)\n", This, index, pSubMatch);
239
240 if(!pSubMatch)
241 return E_POINTER;
242
243 if(!This->result || index<0 || index>=This->result->paren_count)
244 return E_INVALIDARG;
245
246 if(This->result->parens[index].index == -1) {
247 V_VT(pSubMatch) = VT_EMPTY;
248 }else {
249 V_VT(pSubMatch) = VT_BSTR;
250 V_BSTR(pSubMatch) = SysAllocStringLen(
251 This->match+This->result->parens[index].index,
252 This->result->parens[index].length);
253
254 if(!V_BSTR(pSubMatch))
255 return E_OUTOFMEMORY;
256 }
257
258 return S_OK;
259 }
260
261 static HRESULT WINAPI SubMatches_get_Count(ISubMatches *iface, LONG *pCount)
262 {
263 SubMatches *This = impl_from_ISubMatches(iface);
264
265 TRACE("(%p)->(%p)\n", This, pCount);
266
267 if(!pCount)
268 return E_POINTER;
269
270 if(!This->result)
271 *pCount = 0;
272 else
273 *pCount = This->result->paren_count;
274 return S_OK;
275 }
276
277 static HRESULT WINAPI SubMatches_get__NewEnum(ISubMatches *iface, IUnknown **ppEnum)
278 {
279 SubMatches *This = impl_from_ISubMatches(iface);
280 FIXME("(%p)->(%p)\n", This, ppEnum);
281 return E_NOTIMPL;
282 }
283
284 static const ISubMatchesVtbl SubMatchesVtbl = {
285 SubMatches_QueryInterface,
286 SubMatches_AddRef,
287 SubMatches_Release,
288 SubMatches_GetTypeInfoCount,
289 SubMatches_GetTypeInfo,
290 SubMatches_GetIDsOfNames,
291 SubMatches_Invoke,
292 SubMatches_get_Item,
293 SubMatches_get_Count,
294 SubMatches_get__NewEnum
295 };
296
297 static HRESULT create_sub_matches(DWORD pos, match_state_t *result, SubMatches **sub_matches)
298 {
299 SubMatches *ret;
300 DWORD i;
301 HRESULT hres;
302
303 hres = init_regexp_typeinfo(SubMatches_tid);
304 if(FAILED(hres))
305 return hres;
306
307 ret = heap_alloc_zero(sizeof(*ret));
308 if(!ret)
309 return E_OUTOFMEMORY;
310
311 ret->ISubMatches_iface.lpVtbl = &SubMatchesVtbl;
312
313 ret->result = result;
314 if(result) {
315 ret->match = heap_alloc((result->match_len+1) * sizeof(WCHAR));
316 if(!ret->match) {
317 heap_free(ret);
318 return E_OUTOFMEMORY;
319 }
320 memcpy(ret->match, result->cp-result->match_len, result->match_len*sizeof(WCHAR));
321 ret->match[result->match_len] = 0;
322
323 result->cp = NULL;
324 for(i=0; i<result->paren_count; i++)
325 if(result->parens[i].index != -1)
326 result->parens[i].index -= pos;
327 }else {
328 ret->match = NULL;
329 }
330
331 ret->ref = 1;
332 *sub_matches = ret;
333 return hres;
334 }
335
336 static inline Match2* impl_from_IMatch2(IMatch2 *iface)
337 {
338 return CONTAINING_RECORD(iface, Match2, IMatch2_iface);
339 }
340
341 static HRESULT WINAPI Match2_QueryInterface(
342 IMatch2 *iface, REFIID riid, void **ppv)
343 {
344 Match2 *This = impl_from_IMatch2(iface);
345
346 if(IsEqualGUID(riid, &IID_IUnknown)) {
347 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
348 *ppv = &This->IMatch2_iface;
349 }else if(IsEqualGUID(riid, &IID_IDispatch)) {
350 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
351 *ppv = &This->IMatch2_iface;
352 }else if(IsEqualGUID(riid, &IID_IMatch2)) {
353 TRACE("(%p)->(IID_IMatch2 %p)\n", This, ppv);
354 *ppv = &This->IMatch2_iface;
355 }else if(IsEqualGUID(riid, &IID_IMatch)) {
356 TRACE("(%p)->(IID_IMatch %p)\n", This, ppv);
357 *ppv = &This->IMatch_iface;
358 }else if(IsEqualGUID(riid, &IID_IDispatchEx)) {
359 TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
360 *ppv = NULL;
361 return E_NOINTERFACE;
362 }else {
363 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
364 *ppv = NULL;
365 return E_NOINTERFACE;
366 }
367
368 IUnknown_AddRef((IUnknown*)*ppv);
369 return S_OK;
370 }
371
372 static ULONG WINAPI Match2_AddRef(IMatch2 *iface)
373 {
374 Match2 *This = impl_from_IMatch2(iface);
375 LONG ref = InterlockedIncrement(&This->ref);
376
377 TRACE("(%p) ref=%d\n", This, ref);
378
379 return ref;
380 }
381
382 static ULONG WINAPI Match2_Release(IMatch2 *iface)
383 {
384 Match2 *This = impl_from_IMatch2(iface);
385 LONG ref = InterlockedDecrement(&This->ref);
386
387 TRACE("(%p) ref=%d\n", This, ref);
388
389 if(!ref) {
390 ISubMatches_Release(&This->sub_matches->ISubMatches_iface);
391 heap_free(This);
392 }
393
394 return ref;
395 }
396
397 static HRESULT WINAPI Match2_GetTypeInfoCount(IMatch2 *iface, UINT *pctinfo)
398 {
399 Match2 *This = impl_from_IMatch2(iface);
400
401 TRACE("(%p)->(%p)\n", This, pctinfo);
402
403 *pctinfo = 1;
404 return S_OK;
405 }
406
407 static HRESULT WINAPI Match2_GetTypeInfo(IMatch2 *iface,
408 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
409 {
410 Match2 *This = impl_from_IMatch2(iface);
411 FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
412 return E_NOTIMPL;
413 }
414
415 static HRESULT WINAPI Match2_GetIDsOfNames(IMatch2 *iface,
416 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
417 {
418 Match2 *This = impl_from_IMatch2(iface);
419
420 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
421 rgszNames, cNames, lcid, rgDispId);
422
423 return ITypeInfo_GetIDsOfNames(typeinfos[Match2_tid], rgszNames, cNames, rgDispId);
424 }
425
426 static HRESULT WINAPI Match2_Invoke(IMatch2 *iface, DISPID dispIdMember,
427 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
428 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
429 {
430 Match2 *This = impl_from_IMatch2(iface);
431
432 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
433 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
434
435 return ITypeInfo_Invoke(typeinfos[Match2_tid], iface, dispIdMember, wFlags,
436 pDispParams, pVarResult, pExcepInfo, puArgErr);
437 }
438
439 static HRESULT WINAPI Match2_get_Value(IMatch2 *iface, BSTR *pValue)
440 {
441 Match2 *This = impl_from_IMatch2(iface);
442
443 TRACE("(%p)->(%p)\n", This, pValue);
444
445 if(!pValue)
446 return E_POINTER;
447
448 if(!This->sub_matches->match) {
449 *pValue = NULL;
450 return S_OK;
451 }
452
453 *pValue = SysAllocString(This->sub_matches->match);
454 return *pValue ? S_OK : E_OUTOFMEMORY;
455 }
456
457 static HRESULT WINAPI Match2_get_FirstIndex(IMatch2 *iface, LONG *pFirstIndex)
458 {
459 Match2 *This = impl_from_IMatch2(iface);
460
461 TRACE("(%p)->(%p)\n", This, pFirstIndex);
462
463 if(!pFirstIndex)
464 return E_POINTER;
465
466 *pFirstIndex = This->index;
467 return S_OK;
468 }
469
470 static HRESULT WINAPI Match2_get_Length(IMatch2 *iface, LONG *pLength)
471 {
472 Match2 *This = impl_from_IMatch2(iface);
473
474 TRACE("(%p)->(%p)\n", This, pLength);
475
476 if(!pLength)
477 return E_POINTER;
478
479 if(This->sub_matches->result)
480 *pLength = This->sub_matches->result->match_len;
481 else
482 *pLength = 0;
483 return S_OK;
484 }
485
486 static HRESULT WINAPI Match2_get_SubMatches(IMatch2 *iface, IDispatch **ppSubMatches)
487 {
488 Match2 *This = impl_from_IMatch2(iface);
489
490 TRACE("(%p)->(%p)\n", This, ppSubMatches);
491
492 if(!ppSubMatches)
493 return E_POINTER;
494
495 *ppSubMatches = (IDispatch*)&This->sub_matches->ISubMatches_iface;
496 ISubMatches_AddRef(&This->sub_matches->ISubMatches_iface);
497 return S_OK;
498 }
499
500 static const IMatch2Vtbl Match2Vtbl = {
501 Match2_QueryInterface,
502 Match2_AddRef,
503 Match2_Release,
504 Match2_GetTypeInfoCount,
505 Match2_GetTypeInfo,
506 Match2_GetIDsOfNames,
507 Match2_Invoke,
508 Match2_get_Value,
509 Match2_get_FirstIndex,
510 Match2_get_Length,
511 Match2_get_SubMatches
512 };
513
514 static inline Match2 *impl_from_IMatch(IMatch *iface)
515 {
516 return CONTAINING_RECORD(iface, Match2, IMatch_iface);
517 }
518
519 static HRESULT WINAPI Match_QueryInterface(IMatch *iface, REFIID riid, void **ppv)
520 {
521 Match2 *This = impl_from_IMatch(iface);
522 return IMatch2_QueryInterface(&This->IMatch2_iface, riid, ppv);
523 }
524
525 static ULONG WINAPI Match_AddRef(IMatch *iface)
526 {
527 Match2 *This = impl_from_IMatch(iface);
528 return IMatch2_AddRef(&This->IMatch2_iface);
529 }
530
531 static ULONG WINAPI Match_Release(IMatch *iface)
532 {
533 Match2 *This = impl_from_IMatch(iface);
534 return IMatch2_Release(&This->IMatch2_iface);
535 }
536
537 static HRESULT WINAPI Match_GetTypeInfoCount(IMatch *iface, UINT *pctinfo)
538 {
539 Match2 *This = impl_from_IMatch(iface);
540 return IMatch2_GetTypeInfoCount(&This->IMatch2_iface, pctinfo);
541 }
542
543 static HRESULT WINAPI Match_GetTypeInfo(IMatch *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
544 {
545 Match2 *This = impl_from_IMatch(iface);
546 return IMatch2_GetTypeInfo(&This->IMatch2_iface, iTInfo, lcid, ppTInfo);
547 }
548
549 static HRESULT WINAPI Match_GetIDsOfNames(IMatch *iface, REFIID riid,
550 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
551 {
552 Match2 *This = impl_from_IMatch(iface);
553 return IMatch2_GetIDsOfNames(&This->IMatch2_iface, riid, rgszNames, cNames, lcid, rgDispId);
554 }
555
556 static HRESULT WINAPI Match_Invoke(IMatch *iface, DISPID dispIdMember,
557 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
558 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
559 {
560 Match2 *This = impl_from_IMatch(iface);
561 return IMatch2_Invoke(&This->IMatch2_iface, dispIdMember, riid, lcid,
562 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
563 }
564
565 static HRESULT WINAPI Match_get_Value(IMatch *iface, BSTR *pValue)
566 {
567 Match2 *This = impl_from_IMatch(iface);
568 return IMatch2_get_Value(&This->IMatch2_iface, pValue);
569 }
570
571 static HRESULT WINAPI Match_get_FirstIndex(IMatch *iface, LONG *pFirstIndex)
572 {
573 Match2 *This = impl_from_IMatch(iface);
574 return IMatch2_get_FirstIndex(&This->IMatch2_iface, pFirstIndex);
575 }
576
577 static HRESULT WINAPI Match_get_Length(IMatch *iface, LONG *pLength)
578 {
579 Match2 *This = impl_from_IMatch(iface);
580 return IMatch2_get_Length(&This->IMatch2_iface, pLength);
581 }
582
583 static IMatchVtbl MatchVtbl = {
584 Match_QueryInterface,
585 Match_AddRef,
586 Match_Release,
587 Match_GetTypeInfoCount,
588 Match_GetTypeInfo,
589 Match_GetIDsOfNames,
590 Match_Invoke,
591 Match_get_Value,
592 Match_get_FirstIndex,
593 Match_get_Length
594 };
595
596 static HRESULT create_match2(DWORD pos, match_state_t **result, IMatch2 **match)
597 {
598 Match2 *ret;
599 HRESULT hres;
600
601 hres = init_regexp_typeinfo(Match2_tid);
602 if(FAILED(hres))
603 return hres;
604
605 ret = heap_alloc_zero(sizeof(*ret));
606 if(!ret)
607 return E_OUTOFMEMORY;
608
609 ret->index = pos;
610 hres = create_sub_matches(pos, result ? *result : NULL, &ret->sub_matches);
611 if(FAILED(hres)) {
612 heap_free(ret);
613 return hres;
614 }
615 if(result)
616 *result = NULL;
617
618 ret->IMatch2_iface.lpVtbl = &Match2Vtbl;
619 ret->IMatch_iface.lpVtbl = &MatchVtbl;
620
621 ret->ref = 1;
622 *match = &ret->IMatch2_iface;
623 return hres;
624 }
625
626 static inline MatchCollectionEnum* impl_from_IMatchCollectionEnum(IEnumVARIANT *iface)
627 {
628 return CONTAINING_RECORD(iface, MatchCollectionEnum, IEnumVARIANT_iface);
629 }
630
631 static HRESULT WINAPI MatchCollectionEnum_QueryInterface(
632 IEnumVARIANT *iface, REFIID riid, void **ppv)
633 {
634 MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
635
636 if(IsEqualGUID(riid, &IID_IUnknown)) {
637 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
638 *ppv = &This->IEnumVARIANT_iface;
639 }else if(IsEqualGUID(riid, &IID_IEnumVARIANT)) {
640 TRACE("(%p)->(IID_IEnumVARIANT %p)\n", This, ppv);
641 *ppv = &This->IEnumVARIANT_iface;
642 }else {
643 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
644 *ppv = NULL;
645 return E_NOINTERFACE;
646 }
647
648 IUnknown_AddRef((IUnknown*)*ppv);
649 return S_OK;
650 }
651
652 static ULONG WINAPI MatchCollectionEnum_AddRef(IEnumVARIANT *iface)
653 {
654 MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
655 LONG ref = InterlockedIncrement(&This->ref);
656
657 TRACE("(%p) ref=%d\n", This, ref);
658
659 return ref;
660 }
661
662 static ULONG WINAPI MatchCollectionEnum_Release(IEnumVARIANT *iface)
663 {
664 MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
665 LONG ref = InterlockedDecrement(&This->ref);
666
667 TRACE("(%p) ref=%d\n", This, ref);
668
669 if(!ref) {
670 IMatchCollection2_Release(This->mc);
671 heap_free(This);
672 }
673
674 return ref;
675 }
676
677 static HRESULT WINAPI MatchCollectionEnum_Next(IEnumVARIANT *iface,
678 ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
679 {
680 MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
681 DWORD i;
682 HRESULT hres = S_OK;
683
684 TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched);
685
686 if(This->pos>=This->count) {
687 if(pCeltFetched)
688 *pCeltFetched = 0;
689 return S_FALSE;
690 }
691
692 for(i=0; i<celt && This->pos+i<This->count; i++) {
693 V_VT(rgVar+i) = VT_DISPATCH;
694 hres = IMatchCollection2_get_Item(This->mc, This->pos+i, &V_DISPATCH(rgVar+i));
695 if(FAILED(hres))
696 break;
697 }
698 if(FAILED(hres)) {
699 while(i--)
700 VariantClear(rgVar+i);
701 return hres;
702 }
703
704 if(pCeltFetched)
705 *pCeltFetched = i;
706 This->pos += i;
707 return S_OK;
708 }
709
710 static HRESULT WINAPI MatchCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt)
711 {
712 MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
713
714 TRACE("(%p)->(%u)\n", This, celt);
715
716 if(This->pos+celt <= This->count)
717 This->pos += celt;
718 else
719 This->pos = This->count;
720 return S_OK;
721 }
722
723 static HRESULT WINAPI MatchCollectionEnum_Reset(IEnumVARIANT *iface)
724 {
725 MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
726
727 TRACE("(%p)\n", This);
728
729 This->pos = 0;
730 return S_OK;
731 }
732
733 static HRESULT WINAPI MatchCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
734 {
735 MatchCollectionEnum *This = impl_from_IMatchCollectionEnum(iface);
736 FIXME("(%p)->(%p)\n", This, ppEnum);
737 return E_NOTIMPL;
738 }
739
740 static const IEnumVARIANTVtbl MatchCollectionEnum_Vtbl = {
741 MatchCollectionEnum_QueryInterface,
742 MatchCollectionEnum_AddRef,
743 MatchCollectionEnum_Release,
744 MatchCollectionEnum_Next,
745 MatchCollectionEnum_Skip,
746 MatchCollectionEnum_Reset,
747 MatchCollectionEnum_Clone
748 };
749
750 static HRESULT create_enum_variant_mc2(IMatchCollection2 *mc, ULONG pos, IEnumVARIANT **enum_variant)
751 {
752 MatchCollectionEnum *ret;
753
754 ret = heap_alloc_zero(sizeof(*ret));
755 if(!ret)
756 return E_OUTOFMEMORY;
757
758 ret->IEnumVARIANT_iface.lpVtbl = &MatchCollectionEnum_Vtbl;
759 ret->ref = 1;
760 ret->pos = pos;
761 IMatchCollection2_get_Count(mc, &ret->count);
762 ret->mc = mc;
763 IMatchCollection2_AddRef(mc);
764
765 *enum_variant = &ret->IEnumVARIANT_iface;
766 return S_OK;
767 }
768
769 static inline MatchCollection2* impl_from_IMatchCollection2(IMatchCollection2 *iface)
770 {
771 return CONTAINING_RECORD(iface, MatchCollection2, IMatchCollection2_iface);
772 }
773
774 static HRESULT WINAPI MatchCollection2_QueryInterface(
775 IMatchCollection2 *iface, REFIID riid, void **ppv)
776 {
777 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
778
779 if(IsEqualGUID(riid, &IID_IUnknown)) {
780 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
781 *ppv = &This->IMatchCollection2_iface;
782 }else if(IsEqualGUID(riid, &IID_IDispatch)) {
783 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
784 *ppv = &This->IMatchCollection2_iface;
785 }else if(IsEqualGUID(riid, &IID_IMatchCollection2)) {
786 TRACE("(%p)->(IID_IMatchCollection2 %p)\n", This, ppv);
787 *ppv = &This->IMatchCollection2_iface;
788 }else if(IsEqualGUID(riid, &IID_IMatchCollection)) {
789 TRACE("(%p)->(IID_IMatchCollection %p)\n", This, ppv);
790 *ppv = &This->IMatchCollection_iface;
791 }else if(IsEqualGUID(riid, &IID_IDispatchEx)) {
792 TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
793 *ppv = NULL;
794 return E_NOINTERFACE;
795 }else {
796 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
797 *ppv = NULL;
798 return E_NOINTERFACE;
799 }
800
801 IUnknown_AddRef((IUnknown*)*ppv);
802 return S_OK;
803 }
804
805 static ULONG WINAPI MatchCollection2_AddRef(IMatchCollection2 *iface)
806 {
807 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
808 LONG ref = InterlockedIncrement(&This->ref);
809
810 TRACE("(%p) ref=%d\n", This, ref);
811
812 return ref;
813 }
814
815 static ULONG WINAPI MatchCollection2_Release(IMatchCollection2 *iface)
816 {
817 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
818 LONG ref = InterlockedDecrement(&This->ref);
819
820 TRACE("(%p) ref=%d\n", This, ref);
821
822 if(!ref) {
823 DWORD i;
824
825 for(i=0; i<This->count; i++)
826 IMatch2_Release(This->matches[i]);
827 heap_free(This->matches);
828
829 heap_free(This);
830 }
831
832 return ref;
833 }
834
835 static HRESULT WINAPI MatchCollection2_GetTypeInfoCount(IMatchCollection2 *iface, UINT *pctinfo)
836 {
837 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
838
839 TRACE("(%p)->(%p)\n", This, pctinfo);
840
841 *pctinfo = 1;
842 return S_OK;
843 }
844
845 static HRESULT WINAPI MatchCollection2_GetTypeInfo(IMatchCollection2 *iface,
846 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
847 {
848 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
849 FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
850 return E_NOTIMPL;
851 }
852
853 static HRESULT WINAPI MatchCollection2_GetIDsOfNames(IMatchCollection2 *iface,
854 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
855 {
856 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
857
858 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
859 rgszNames, cNames, lcid, rgDispId);
860
861 return ITypeInfo_GetIDsOfNames(typeinfos[MatchCollection2_tid], rgszNames, cNames, rgDispId);
862 }
863
864 static HRESULT WINAPI MatchCollection2_Invoke(IMatchCollection2 *iface, DISPID dispIdMember,
865 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
866 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
867 {
868 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
869
870 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
871 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
872
873 return ITypeInfo_Invoke(typeinfos[MatchCollection2_tid], iface, dispIdMember, wFlags,
874 pDispParams, pVarResult, pExcepInfo, puArgErr);
875 }
876
877 static HRESULT WINAPI MatchCollection2_get_Item(IMatchCollection2 *iface,
878 LONG index, IDispatch **ppMatch)
879 {
880 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
881
882 TRACE("(%p)->()\n", This);
883
884 if(!ppMatch)
885 return E_POINTER;
886
887 if(index<0 || index>=This->count)
888 return E_INVALIDARG;
889
890 *ppMatch = (IDispatch*)This->matches[index];
891 IMatch2_AddRef(This->matches[index]);
892 return S_OK;
893 }
894
895 static HRESULT WINAPI MatchCollection2_get_Count(IMatchCollection2 *iface, LONG *pCount)
896 {
897 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
898
899 TRACE("(%p)->()\n", This);
900
901 if(!pCount)
902 return E_POINTER;
903
904 *pCount = This->count;
905 return S_OK;
906 }
907
908 static HRESULT WINAPI MatchCollection2_get__NewEnum(IMatchCollection2 *iface, IUnknown **ppEnum)
909 {
910 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
911
912 TRACE("(%p)->(%p)\n", This, ppEnum);
913
914 if(!ppEnum)
915 return E_POINTER;
916
917 return create_enum_variant_mc2(&This->IMatchCollection2_iface, 0, (IEnumVARIANT**)ppEnum);
918 }
919
920 static const IMatchCollection2Vtbl MatchCollection2Vtbl = {
921 MatchCollection2_QueryInterface,
922 MatchCollection2_AddRef,
923 MatchCollection2_Release,
924 MatchCollection2_GetTypeInfoCount,
925 MatchCollection2_GetTypeInfo,
926 MatchCollection2_GetIDsOfNames,
927 MatchCollection2_Invoke,
928 MatchCollection2_get_Item,
929 MatchCollection2_get_Count,
930 MatchCollection2_get__NewEnum
931 };
932
933 static inline MatchCollection2 *impl_from_IMatchCollection(IMatchCollection *iface)
934 {
935 return CONTAINING_RECORD(iface, MatchCollection2, IMatchCollection_iface);
936 }
937
938 static HRESULT WINAPI MatchCollection_QueryInterface(IMatchCollection *iface, REFIID riid, void **ppv)
939 {
940 MatchCollection2 *This = impl_from_IMatchCollection(iface);
941 return IMatchCollection2_QueryInterface(&This->IMatchCollection2_iface, riid, ppv);
942 }
943
944 static ULONG WINAPI MatchCollection_AddRef(IMatchCollection *iface)
945 {
946 MatchCollection2 *This = impl_from_IMatchCollection(iface);
947 return IMatchCollection2_AddRef(&This->IMatchCollection2_iface);
948 }
949
950 static ULONG WINAPI MatchCollection_Release(IMatchCollection *iface)
951 {
952 MatchCollection2 *This = impl_from_IMatchCollection(iface);
953 return IMatchCollection2_Release(&This->IMatchCollection2_iface);
954 }
955
956 static HRESULT WINAPI MatchCollection_GetTypeInfoCount(IMatchCollection *iface, UINT *pctinfo)
957 {
958 MatchCollection2 *This = impl_from_IMatchCollection(iface);
959 return IMatchCollection2_GetTypeInfoCount(&This->IMatchCollection2_iface, pctinfo);
960 }
961
962 static HRESULT WINAPI MatchCollection_GetTypeInfo(IMatchCollection *iface,
963 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
964 {
965 MatchCollection2 *This = impl_from_IMatchCollection(iface);
966 return IMatchCollection2_GetTypeInfo(&This->IMatchCollection2_iface, iTInfo, lcid, ppTInfo);
967 }
968
969 static HRESULT WINAPI MatchCollection_GetIDsOfNames(IMatchCollection *iface, REFIID riid,
970 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
971 {
972 MatchCollection2 *This = impl_from_IMatchCollection(iface);
973 return IMatchCollection2_GetIDsOfNames(&This->IMatchCollection2_iface,
974 riid, rgszNames, cNames, lcid, rgDispId);
975 }
976
977 static HRESULT WINAPI MatchCollection_Invoke(IMatchCollection *iface, DISPID dispIdMember,
978 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
979 EXCEPINFO *pExcepInfo, UINT *puArgErr)
980 {
981 MatchCollection2 *This = impl_from_IMatchCollection(iface);
982 return IMatchCollection2_Invoke(&This->IMatchCollection2_iface, dispIdMember,
983 riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
984 }
985
986 static HRESULT WINAPI MatchCollection_get_Item(IMatchCollection *iface, LONG index, IDispatch **ppMatch)
987 {
988 MatchCollection2 *This = impl_from_IMatchCollection(iface);
989 return IMatchCollection2_get_Item(&This->IMatchCollection2_iface, index, ppMatch);
990 }
991
992 static HRESULT WINAPI MatchCollection_get_Count(IMatchCollection *iface, LONG *pCount)
993 {
994 MatchCollection2 *This = impl_from_IMatchCollection(iface);
995 return IMatchCollection2_get_Count(&This->IMatchCollection2_iface, pCount);
996 }
997
998 static HRESULT WINAPI MatchCollection_get__NewEnum(IMatchCollection *iface, IUnknown **ppEnum)
999 {
1000 MatchCollection2 *This = impl_from_IMatchCollection(iface);
1001 return IMatchCollection2_get__NewEnum(&This->IMatchCollection2_iface, ppEnum);
1002 }
1003
1004 static const IMatchCollectionVtbl MatchCollectionVtbl = {
1005 MatchCollection_QueryInterface,
1006 MatchCollection_AddRef,
1007 MatchCollection_Release,
1008 MatchCollection_GetTypeInfoCount,
1009 MatchCollection_GetTypeInfo,
1010 MatchCollection_GetIDsOfNames,
1011 MatchCollection_Invoke,
1012 MatchCollection_get_Item,
1013 MatchCollection_get_Count,
1014 MatchCollection_get__NewEnum
1015 };
1016
1017 static HRESULT add_match(IMatchCollection2 *iface, IMatch2 *add)
1018 {
1019 MatchCollection2 *This = impl_from_IMatchCollection2(iface);
1020
1021 TRACE("(%p)->(%p)\n", This, add);
1022
1023 if(!This->size) {
1024 This->matches = heap_alloc(8*sizeof(IMatch*));
1025 if(!This->matches)
1026 return E_OUTOFMEMORY;
1027 This->size = 8;
1028 }else if(This->size == This->count) {
1029 IMatch2 **new_matches = heap_realloc(This->matches, 2*This->size*sizeof(IMatch*));
1030 if(!new_matches)
1031 return E_OUTOFMEMORY;
1032
1033 This->matches = new_matches;
1034 This->size <<= 1;
1035 }
1036
1037 This->matches[This->count++] = add;
1038 IMatch2_AddRef(add);
1039 return S_OK;
1040 }
1041
1042 static HRESULT create_match_collection2(IMatchCollection2 **match_collection)
1043 {
1044 MatchCollection2 *ret;
1045 HRESULT hres;
1046
1047 hres = init_regexp_typeinfo(MatchCollection2_tid);
1048 if(FAILED(hres))
1049 return hres;
1050
1051 ret = heap_alloc_zero(sizeof(*ret));
1052 if(!ret)
1053 return E_OUTOFMEMORY;
1054
1055 ret->IMatchCollection2_iface.lpVtbl = &MatchCollection2Vtbl;
1056 ret->IMatchCollection_iface.lpVtbl = &MatchCollectionVtbl;
1057
1058 ret->ref = 1;
1059 *match_collection = &ret->IMatchCollection2_iface;
1060 return S_OK;
1061 }
1062
1063 static inline RegExp2 *impl_from_IRegExp2(IRegExp2 *iface)
1064 {
1065 return CONTAINING_RECORD(iface, RegExp2, IRegExp2_iface);
1066 }
1067
1068 static HRESULT WINAPI RegExp2_QueryInterface(IRegExp2 *iface, REFIID riid, void **ppv)
1069 {
1070 RegExp2 *This = impl_from_IRegExp2(iface);
1071
1072 if(IsEqualGUID(riid, &IID_IUnknown)) {
1073 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1074 *ppv = &This->IRegExp2_iface;
1075 }else if(IsEqualGUID(riid, &IID_IDispatch)) {
1076 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
1077 *ppv = &This->IRegExp2_iface;
1078 }else if(IsEqualGUID(riid, &IID_IRegExp2)) {
1079 TRACE("(%p)->(IID_IRegExp2 %p)\n", This, ppv);
1080 *ppv = &This->IRegExp2_iface;
1081 }else if(IsEqualGUID(riid, &IID_IRegExp)) {
1082 TRACE("(%p)->(IID_IRegExp %p)\n", This, ppv);
1083 *ppv = &This->IRegExp_iface;
1084 }else if(IsEqualGUID(riid, &IID_IDispatchEx)) {
1085 TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
1086 *ppv = NULL;
1087 return E_NOINTERFACE;
1088 }else {
1089 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1090 *ppv = NULL;
1091 return E_NOINTERFACE;
1092 }
1093
1094 IUnknown_AddRef((IUnknown*)*ppv);
1095 return S_OK;
1096 }
1097
1098 static ULONG WINAPI RegExp2_AddRef(IRegExp2 *iface)
1099 {
1100 RegExp2 *This = impl_from_IRegExp2(iface);
1101 LONG ref = InterlockedIncrement(&This->ref);
1102
1103 TRACE("(%p) ref=%d\n", This, ref);
1104
1105 return ref;
1106 }
1107
1108 static ULONG WINAPI RegExp2_Release(IRegExp2 *iface)
1109 {
1110 RegExp2 *This = impl_from_IRegExp2(iface);
1111 LONG ref = InterlockedDecrement(&This->ref);
1112
1113 TRACE("(%p) ref=%d\n", This, ref);
1114
1115 if(!ref) {
1116 heap_free(This->pattern);
1117 if(This->regexp)
1118 regexp_destroy(This->regexp);
1119 heap_pool_free(&This->pool);
1120 heap_free(This);
1121 }
1122
1123 return ref;
1124 }
1125
1126 static HRESULT WINAPI RegExp2_GetTypeInfoCount(IRegExp2 *iface, UINT *pctinfo)
1127 {
1128 RegExp2 *This = impl_from_IRegExp2(iface);
1129
1130 TRACE("(%p)->(%p)\n", This, pctinfo);
1131
1132 *pctinfo = 1;
1133 return S_OK;
1134 }
1135
1136 static HRESULT WINAPI RegExp2_GetTypeInfo(IRegExp2 *iface,
1137 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1138 {
1139 RegExp2 *This = impl_from_IRegExp2(iface);
1140 FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1141 return E_NOTIMPL;
1142 }
1143
1144 static HRESULT WINAPI RegExp2_GetIDsOfNames(IRegExp2 *iface, REFIID riid,
1145 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1146 {
1147 RegExp2 *This = impl_from_IRegExp2(iface);
1148
1149 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid),
1150 rgszNames, cNames, lcid, rgDispId);
1151
1152 return ITypeInfo_GetIDsOfNames(typeinfos[RegExp2_tid], rgszNames, cNames, rgDispId);
1153 }
1154
1155 static HRESULT WINAPI RegExp2_Invoke(IRegExp2 *iface, DISPID dispIdMember,
1156 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1157 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1158 {
1159 RegExp2 *This = impl_from_IRegExp2(iface);
1160
1161 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1162 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1163
1164 return ITypeInfo_Invoke(typeinfos[RegExp2_tid], iface, dispIdMember, wFlags,
1165 pDispParams, pVarResult, pExcepInfo, puArgErr);
1166 }
1167
1168 static HRESULT WINAPI RegExp2_get_Pattern(IRegExp2 *iface, BSTR *pPattern)
1169 {
1170 RegExp2 *This = impl_from_IRegExp2(iface);
1171
1172 TRACE("(%p)->(%p)\n", This, pPattern);
1173
1174 if(!pPattern)
1175 return E_POINTER;
1176
1177 if(!This->pattern) {
1178 *pPattern = NULL;
1179 return S_OK;
1180 }
1181
1182 *pPattern = SysAllocString(This->pattern);
1183 return *pPattern ? S_OK : E_OUTOFMEMORY;
1184 }
1185
1186 static HRESULT WINAPI RegExp2_put_Pattern(IRegExp2 *iface, BSTR pattern)
1187 {
1188 RegExp2 *This = impl_from_IRegExp2(iface);
1189 WCHAR *p;
1190 DWORD size;
1191
1192 TRACE("(%p)->(%s)\n", This, wine_dbgstr_w(pattern));
1193
1194 if(!pattern) {
1195 heap_free(This->pattern);
1196 if(This->regexp) {
1197 regexp_destroy(This->regexp);
1198 This->regexp = NULL;
1199 }
1200 This->pattern = NULL;
1201 return S_OK;
1202 }
1203
1204 size = (SysStringLen(pattern)+1) * sizeof(WCHAR);
1205 p = heap_alloc(size);
1206 if(!p)
1207 return E_OUTOFMEMORY;
1208
1209 heap_free(This->pattern);
1210 This->pattern = p;
1211 memcpy(p, pattern, size);
1212 if(This->regexp) {
1213 regexp_destroy(This->regexp);
1214 This->regexp = NULL;
1215 }
1216 return S_OK;
1217 }
1218
1219 static HRESULT WINAPI RegExp2_get_IgnoreCase(IRegExp2 *iface, VARIANT_BOOL *pIgnoreCase)
1220 {
1221 RegExp2 *This = impl_from_IRegExp2(iface);
1222
1223 TRACE("(%p)->(%p)\n", This, pIgnoreCase);
1224
1225 if(!pIgnoreCase)
1226 return E_POINTER;
1227
1228 *pIgnoreCase = This->flags & REG_FOLD ? VARIANT_TRUE : VARIANT_FALSE;
1229 return S_OK;
1230 }
1231
1232 static HRESULT WINAPI RegExp2_put_IgnoreCase(IRegExp2 *iface, VARIANT_BOOL ignoreCase)
1233 {
1234 RegExp2 *This = impl_from_IRegExp2(iface);
1235
1236 TRACE("(%p)->(%s)\n", This, ignoreCase ? "true" : "false");
1237
1238 if(ignoreCase)
1239 This->flags |= REG_FOLD;
1240 else
1241 This->flags &= ~REG_FOLD;
1242 return S_OK;
1243 }
1244
1245 static HRESULT WINAPI RegExp2_get_Global(IRegExp2 *iface, VARIANT_BOOL *pGlobal)
1246 {
1247 RegExp2 *This = impl_from_IRegExp2(iface);
1248
1249 TRACE("(%p)->(%p)\n", This, pGlobal);
1250
1251 if(!pGlobal)
1252 return E_POINTER;
1253
1254 *pGlobal = This->flags & REG_GLOB ? VARIANT_TRUE : VARIANT_FALSE;
1255 return S_OK;
1256 }
1257
1258 static HRESULT WINAPI RegExp2_put_Global(IRegExp2 *iface, VARIANT_BOOL global)
1259 {
1260 RegExp2 *This = impl_from_IRegExp2(iface);
1261
1262 TRACE("(%p)->(%s)\n", This, global ? "true" : "false");
1263
1264 if(global)
1265 This->flags |= REG_GLOB;
1266 else
1267 This->flags &= ~REG_GLOB;
1268 return S_OK;
1269 }
1270
1271 static HRESULT WINAPI RegExp2_get_Multiline(IRegExp2 *iface, VARIANT_BOOL *pMultiline)
1272 {
1273 RegExp2 *This = impl_from_IRegExp2(iface);
1274
1275 TRACE("(%p)->(%p)\n", This, pMultiline);
1276
1277 if(!pMultiline)
1278 return E_POINTER;
1279
1280 *pMultiline = This->flags & REG_MULTILINE ? VARIANT_TRUE : VARIANT_FALSE;
1281 return S_OK;
1282 }
1283
1284 static HRESULT WINAPI RegExp2_put_Multiline(IRegExp2 *iface, VARIANT_BOOL multiline)
1285 {
1286 RegExp2 *This = impl_from_IRegExp2(iface);
1287
1288 TRACE("(%p)->(%s)\n", This, multiline ? "true" : "false");
1289
1290 if(multiline)
1291 This->flags |= REG_MULTILINE;
1292 else
1293 This->flags &= ~REG_MULTILINE;
1294 return S_OK;
1295 }
1296
1297 static HRESULT WINAPI RegExp2_Execute(IRegExp2 *iface,
1298 BSTR sourceString, IDispatch **ppMatches)
1299 {
1300 RegExp2 *This = impl_from_IRegExp2(iface);
1301 match_state_t *result;
1302 const WCHAR *pos;
1303 IMatchCollection2 *match_collection;
1304 IMatch2 *add = NULL;
1305 HRESULT hres;
1306
1307 TRACE("(%p)->(%s %p)\n", This, debugstr_w(sourceString), ppMatches);
1308
1309 if(!This->pattern) {
1310 DWORD i, len = SysStringLen(sourceString);
1311
1312 hres = create_match_collection2(&match_collection);
1313 if(FAILED(hres))
1314 return hres;
1315
1316 for(i=0; i<=len; i++) {
1317 hres = create_match2(i, NULL, &add);
1318 if(FAILED(hres))
1319 break;
1320
1321 hres = add_match(match_collection, add);
1322 if(FAILED(hres))
1323 break;
1324 IMatch2_Release(add);
1325
1326 if(!(This->flags & REG_GLOB))
1327 break;
1328 }
1329
1330 if(FAILED(hres)) {
1331 IMatchCollection2_Release(match_collection);
1332 return hres;
1333 }
1334
1335 *ppMatches = (IDispatch*)match_collection;
1336 return S_OK;
1337 }
1338
1339 if(!This->regexp) {
1340 This->regexp = regexp_new(NULL, &This->pool, This->pattern,
1341 strlenW(This->pattern), This->flags, FALSE);
1342 if(!This->regexp)
1343 return E_FAIL;
1344 }else {
1345 hres = regexp_set_flags(&This->regexp, NULL, &This->pool, This->flags);
1346 if(FAILED(hres))
1347 return hres;
1348 }
1349
1350 hres = create_match_collection2(&match_collection);
1351 if(FAILED(hres))
1352 return hres;
1353
1354 pos = sourceString;
1355 while(1) {
1356 result = alloc_match_state(This->regexp, NULL, pos);
1357 if(!result) {
1358 hres = E_OUTOFMEMORY;
1359 break;
1360 }
1361
1362 hres = regexp_execute(This->regexp, NULL, &This->pool,
1363 sourceString, SysStringLen(sourceString), result);
1364 if(hres != S_OK) {
1365 heap_free(result);
1366 break;
1367 }
1368 pos = result->cp;
1369
1370 hres = create_match2(result->cp-result->match_len-sourceString, &result, &add);
1371 heap_free(result);
1372 if(FAILED(hres))
1373 break;
1374 hres = add_match(match_collection, add);
1375 IMatch2_Release(add);
1376 if(FAILED(hres))
1377 break;
1378
1379 if(!(This->flags & REG_GLOB))
1380 break;
1381 }
1382
1383 if(FAILED(hres)) {
1384 IMatchCollection2_Release(match_collection);
1385 return hres;
1386 }
1387
1388 *ppMatches = (IDispatch*)match_collection;
1389 return S_OK;
1390 }
1391
1392 static HRESULT WINAPI RegExp2_Test(IRegExp2 *iface, BSTR sourceString, VARIANT_BOOL *pMatch)
1393 {
1394 RegExp2 *This = impl_from_IRegExp2(iface);
1395 match_state_t *result;
1396 heap_pool_t *mark;
1397 HRESULT hres;
1398
1399 TRACE("(%p)->(%s %p)\n", This, debugstr_w(sourceString), pMatch);
1400
1401 if(!This->pattern) {
1402 *pMatch = VARIANT_TRUE;
1403 return S_OK;
1404 }
1405
1406 if(!This->regexp) {
1407 This->regexp = regexp_new(NULL, &This->pool, This->pattern,
1408 strlenW(This->pattern), This->flags, FALSE);
1409 if(!This->regexp)
1410 return E_FAIL;
1411 }else {
1412 hres = regexp_set_flags(&This->regexp, NULL, &This->pool, This->flags);
1413 if(FAILED(hres))
1414 return hres;
1415 }
1416
1417 mark = heap_pool_mark(&This->pool);
1418 result = alloc_match_state(This->regexp, &This->pool, sourceString);
1419 if(!result) {
1420 heap_pool_clear(mark);
1421 return E_OUTOFMEMORY;
1422 }
1423
1424 hres = regexp_execute(This->regexp, NULL, &This->pool,
1425 sourceString, SysStringLen(sourceString), result);
1426
1427 heap_pool_clear(mark);
1428
1429 if(hres == S_OK) {
1430 *pMatch = VARIANT_TRUE;
1431 }else if(hres == S_FALSE) {
1432 *pMatch = VARIANT_FALSE;
1433 hres = S_OK;
1434 }
1435 return hres;
1436 }
1437
1438 static HRESULT WINAPI RegExp2_Replace(IRegExp2 *iface, BSTR sourceString,
1439 VARIANT replaceVar, BSTR *pDestString)
1440 {
1441 RegExp2 *This = impl_from_IRegExp2(iface);
1442 FIXME("(%p)->(%s %s %p)\n", This, debugstr_w(sourceString),
1443 debugstr_variant(&replaceVar), pDestString);
1444 return E_NOTIMPL;
1445 }
1446
1447 static const IRegExp2Vtbl RegExp2Vtbl = {
1448 RegExp2_QueryInterface,
1449 RegExp2_AddRef,
1450 RegExp2_Release,
1451 RegExp2_GetTypeInfoCount,
1452 RegExp2_GetTypeInfo,
1453 RegExp2_GetIDsOfNames,
1454 RegExp2_Invoke,
1455 RegExp2_get_Pattern,
1456 RegExp2_put_Pattern,
1457 RegExp2_get_IgnoreCase,
1458 RegExp2_put_IgnoreCase,
1459 RegExp2_get_Global,
1460 RegExp2_put_Global,
1461 RegExp2_get_Multiline,
1462 RegExp2_put_Multiline,
1463 RegExp2_Execute,
1464 RegExp2_Test,
1465 RegExp2_Replace
1466 };
1467
1468 static inline RegExp2 *impl_from_IRegExp(IRegExp *iface)
1469 {
1470 return CONTAINING_RECORD(iface, RegExp2, IRegExp_iface);
1471 }
1472
1473 static HRESULT WINAPI RegExp_QueryInterface(IRegExp *iface, REFIID riid, void **ppv)
1474 {
1475 RegExp2 *This = impl_from_IRegExp(iface);
1476 return IRegExp2_QueryInterface(&This->IRegExp2_iface, riid, ppv);
1477 }
1478
1479 static ULONG WINAPI RegExp_AddRef(IRegExp *iface)
1480 {
1481 RegExp2 *This = impl_from_IRegExp(iface);
1482 return IRegExp2_AddRef(&This->IRegExp2_iface);
1483 }
1484
1485 static ULONG WINAPI RegExp_Release(IRegExp *iface)
1486 {
1487 RegExp2 *This = impl_from_IRegExp(iface);
1488 return IRegExp2_Release(&This->IRegExp2_iface);
1489 }
1490
1491 static HRESULT WINAPI RegExp_GetTypeInfoCount(IRegExp *iface, UINT *pctinfo)
1492 {
1493 RegExp2 *This = impl_from_IRegExp(iface);
1494 return IRegExp2_GetTypeInfoCount(&This->IRegExp2_iface, pctinfo);
1495 }
1496
1497 static HRESULT WINAPI RegExp_GetTypeInfo(IRegExp *iface,
1498 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1499 {
1500 RegExp2 *This = impl_from_IRegExp(iface);
1501 return IRegExp2_GetTypeInfo(&This->IRegExp2_iface, iTInfo, lcid, ppTInfo);
1502 }
1503
1504 static HRESULT WINAPI RegExp_GetIDsOfNames(IRegExp *iface, REFIID riid,
1505 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1506 {
1507 RegExp2 *This = impl_from_IRegExp(iface);
1508 return IRegExp2_GetIDsOfNames(&This->IRegExp2_iface, riid, rgszNames, cNames, lcid, rgDispId);
1509 }
1510
1511 static HRESULT WINAPI RegExp_Invoke(IRegExp *iface, DISPID dispIdMember,
1512 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1513 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1514 {
1515 RegExp2 *This = impl_from_IRegExp(iface);
1516 return IRegExp2_Invoke(&This->IRegExp2_iface, dispIdMember, riid, lcid,
1517 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1518 }
1519
1520 static HRESULT WINAPI RegExp_get_Pattern(IRegExp *iface, BSTR *pPattern)
1521 {
1522 RegExp2 *This = impl_from_IRegExp(iface);
1523 return IRegExp2_get_Pattern(&This->IRegExp2_iface, pPattern);
1524 }
1525
1526 static HRESULT WINAPI RegExp_put_Pattern(IRegExp *iface, BSTR pPattern)
1527 {
1528 RegExp2 *This = impl_from_IRegExp(iface);
1529 return IRegExp2_put_Pattern(&This->IRegExp2_iface, pPattern);
1530 }
1531
1532 static HRESULT WINAPI RegExp_get_IgnoreCase(IRegExp *iface, VARIANT_BOOL *pIgnoreCase)
1533 {
1534 RegExp2 *This = impl_from_IRegExp(iface);
1535 return IRegExp2_get_IgnoreCase(&This->IRegExp2_iface, pIgnoreCase);
1536 }
1537
1538 static HRESULT WINAPI RegExp_put_IgnoreCase(IRegExp *iface, VARIANT_BOOL pIgnoreCase)
1539 {
1540 RegExp2 *This = impl_from_IRegExp(iface);
1541 return IRegExp2_put_IgnoreCase(&This->IRegExp2_iface, pIgnoreCase);
1542 }
1543
1544 static HRESULT WINAPI RegExp_get_Global(IRegExp *iface, VARIANT_BOOL *pGlobal)
1545 {
1546 RegExp2 *This = impl_from_IRegExp(iface);
1547 return IRegExp2_get_Global(&This->IRegExp2_iface, pGlobal);
1548 }
1549
1550 static HRESULT WINAPI RegExp_put_Global(IRegExp *iface, VARIANT_BOOL pGlobal)
1551 {
1552 RegExp2 *This = impl_from_IRegExp(iface);
1553 return IRegExp2_put_Global(&This->IRegExp2_iface, pGlobal);
1554 }
1555
1556 static HRESULT WINAPI RegExp_Execute(IRegExp *iface,
1557 BSTR sourceString, IDispatch **ppMatches)
1558 {
1559 RegExp2 *This = impl_from_IRegExp(iface);
1560 return IRegExp2_Execute(&This->IRegExp2_iface, sourceString, ppMatches);
1561 }
1562
1563 static HRESULT WINAPI RegExp_Test(IRegExp *iface, BSTR sourceString, VARIANT_BOOL *pMatch)
1564 {
1565 RegExp2 *This = impl_from_IRegExp(iface);
1566 return IRegExp2_Test(&This->IRegExp2_iface, sourceString, pMatch);
1567 }
1568
1569 static HRESULT WINAPI RegExp_Replace(IRegExp *iface, BSTR sourceString,
1570 BSTR replaceString, BSTR *pDestString)
1571 {
1572 RegExp2 *This = impl_from_IRegExp(iface);
1573 VARIANT replace;
1574
1575 V_VT(&replace) = VT_BSTR;
1576 V_BSTR(&replace) = replaceString;
1577 return IRegExp2_Replace(&This->IRegExp2_iface, sourceString, replace, pDestString);
1578 }
1579
1580 static IRegExpVtbl RegExpVtbl = {
1581 RegExp_QueryInterface,
1582 RegExp_AddRef,
1583 RegExp_Release,
1584 RegExp_GetTypeInfoCount,
1585 RegExp_GetTypeInfo,
1586 RegExp_GetIDsOfNames,
1587 RegExp_Invoke,
1588 RegExp_get_Pattern,
1589 RegExp_put_Pattern,
1590 RegExp_get_IgnoreCase,
1591 RegExp_put_IgnoreCase,
1592 RegExp_get_Global,
1593 RegExp_put_Global,
1594 RegExp_Execute,
1595 RegExp_Test,
1596 RegExp_Replace
1597 };
1598
1599 HRESULT WINAPI VBScriptRegExpFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, REFIID riid, void **ppv)
1600 {
1601 RegExp2 *ret;
1602 HRESULT hres;
1603
1604 TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv);
1605
1606 hres = init_regexp_typeinfo(RegExp2_tid);
1607 if(FAILED(hres))
1608 return hres;
1609
1610 ret = heap_alloc_zero(sizeof(*ret));
1611 if(!ret)
1612 return E_OUTOFMEMORY;
1613
1614 ret->IRegExp2_iface.lpVtbl = &RegExp2Vtbl;
1615 ret->IRegExp_iface.lpVtbl = &RegExpVtbl;
1616
1617 ret->ref = 1;
1618 heap_pool_init(&ret->pool);
1619
1620 hres = IRegExp2_QueryInterface(&ret->IRegExp2_iface, riid, ppv);
1621 IRegExp2_Release(&ret->IRegExp2_iface);
1622 return hres;
1623 }
1624
1625 void release_regexp_typelib(void)
1626 {
1627 DWORD i;
1628
1629 for(i=0; i<REGEXP_LAST_tid; i++) {
1630 if(typeinfos[i])
1631 ITypeInfo_Release(typeinfos[i]);
1632 }
1633 if(typelib)
1634 ITypeLib_Release(typelib);
1635 }