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 lstrlenW(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 lstrlenW(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(®exp->pool); 1613 1614 *ret = (IDispatch*)®exp->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(®exp); 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 } 1645