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