1 /* 2 * CompositeMonikers implementation 3 * 4 * Copyright 1999 Noomen Hamza 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <assert.h> 22 #include <stdarg.h> 23 #include <string.h> 24 25 #define COBJMACROS 26 27 #include "windef.h" 28 #include "winbase.h" 29 #include "winuser.h" 30 #include "winerror.h" 31 #include "wine/debug.h" 32 #include "wine/unicode.h" 33 #include "ole2.h" 34 #include "moniker.h" 35 36 WINE_DEFAULT_DEBUG_CHANNEL(ole); 37 38 #define BLOCK_TAB_SIZE 5 /* represent the first size table and its increment block size */ 39 40 /* CompositeMoniker data structure */ 41 typedef struct CompositeMonikerImpl{ 42 IMoniker IMoniker_iface; 43 IROTData IROTData_iface; 44 IMarshal IMarshal_iface; 45 LONG ref; 46 IMoniker** tabMoniker; /* dynamic table containing all components (monikers) of this composite moniker */ 47 ULONG tabSize; /* size of tabMoniker */ 48 ULONG tabLastIndex; /* first free index in tabMoniker */ 49 } CompositeMonikerImpl; 50 51 static inline CompositeMonikerImpl *impl_from_IMoniker(IMoniker *iface) 52 { 53 return CONTAINING_RECORD(iface, CompositeMonikerImpl, IMoniker_iface); 54 } 55 56 static inline CompositeMonikerImpl *impl_from_IROTData(IROTData *iface) 57 { 58 return CONTAINING_RECORD(iface, CompositeMonikerImpl, IROTData_iface); 59 } 60 61 static inline CompositeMonikerImpl *impl_from_IMarshal(IMarshal *iface) 62 { 63 return CONTAINING_RECORD(iface, CompositeMonikerImpl, IMarshal_iface); 64 } 65 66 /* EnumMoniker data structure */ 67 typedef struct EnumMonikerImpl{ 68 IEnumMoniker IEnumMoniker_iface; 69 LONG ref; 70 IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */ 71 ULONG tabSize; /* size of tabMoniker */ 72 ULONG currentPos; /* index pointer on the current moniker */ 73 } EnumMonikerImpl; 74 75 static inline EnumMonikerImpl *impl_from_IEnumMoniker(IEnumMoniker *iface) 76 { 77 return CONTAINING_RECORD(iface, EnumMonikerImpl, IEnumMoniker_iface); 78 } 79 80 static HRESULT EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRight,IEnumMoniker ** ppmk); 81 82 /******************************************************************************* 83 * CompositeMoniker_QueryInterface 84 *******************************************************************************/ 85 static HRESULT WINAPI 86 CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) 87 { 88 CompositeMonikerImpl *This = impl_from_IMoniker(iface); 89 90 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject); 91 92 /* Perform a sanity check on the parameters.*/ 93 if ( ppvObject==0 ) 94 return E_INVALIDARG; 95 96 /* Initialize the return parameter */ 97 *ppvObject = 0; 98 99 /* Compare the riid with the interface IDs implemented by this object.*/ 100 if (IsEqualIID(&IID_IUnknown, riid) || 101 IsEqualIID(&IID_IPersist, riid) || 102 IsEqualIID(&IID_IPersistStream, riid) || 103 IsEqualIID(&IID_IMoniker, riid) 104 ) 105 *ppvObject = iface; 106 else if (IsEqualIID(&IID_IROTData, riid)) 107 *ppvObject = &This->IROTData_iface; 108 else if (IsEqualIID(&IID_IMarshal, riid)) 109 *ppvObject = &This->IMarshal_iface; 110 111 /* Check that we obtained an interface.*/ 112 if ((*ppvObject)==0) 113 return E_NOINTERFACE; 114 115 /* Query Interface always increases the reference count by one when it is successful */ 116 IMoniker_AddRef(iface); 117 118 return S_OK; 119 } 120 121 /****************************************************************************** 122 * CompositeMoniker_AddRef 123 ******************************************************************************/ 124 static ULONG WINAPI 125 CompositeMonikerImpl_AddRef(IMoniker* iface) 126 { 127 CompositeMonikerImpl *This = impl_from_IMoniker(iface); 128 129 TRACE("(%p)\n",This); 130 131 return InterlockedIncrement(&This->ref); 132 } 133 134 static void CompositeMonikerImpl_ReleaseMonikersInTable(CompositeMonikerImpl *This) 135 { 136 ULONG i; 137 138 for (i = 0; i < This->tabLastIndex; i++) 139 IMoniker_Release(This->tabMoniker[i]); 140 141 This->tabLastIndex = 0; 142 } 143 144 /****************************************************************************** 145 * CompositeMoniker_Release 146 ******************************************************************************/ 147 static ULONG WINAPI 148 CompositeMonikerImpl_Release(IMoniker* iface) 149 { 150 CompositeMonikerImpl *This = impl_from_IMoniker(iface); 151 ULONG ref; 152 153 TRACE("(%p)\n",This); 154 155 ref = InterlockedDecrement(&This->ref); 156 157 /* destroy the object if there are no more references to it */ 158 if (ref == 0){ 159 160 /* release all the components before destroying this object */ 161 CompositeMonikerImpl_ReleaseMonikersInTable(This); 162 163 HeapFree(GetProcessHeap(),0,This->tabMoniker); 164 HeapFree(GetProcessHeap(),0,This); 165 } 166 return ref; 167 } 168 169 /****************************************************************************** 170 * CompositeMoniker_GetClassID 171 ******************************************************************************/ 172 static HRESULT WINAPI 173 CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID) 174 { 175 TRACE("(%p,%p)\n",iface,pClassID); 176 177 if (pClassID==NULL) 178 return E_POINTER; 179 180 *pClassID = CLSID_CompositeMoniker; 181 182 return S_OK; 183 } 184 185 /****************************************************************************** 186 * CompositeMoniker_IsDirty 187 ******************************************************************************/ 188 static HRESULT WINAPI 189 CompositeMonikerImpl_IsDirty(IMoniker* iface) 190 { 191 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty 192 method in the OLE-provided moniker interfaces always return S_FALSE because 193 their internal state never changes. */ 194 195 TRACE("(%p)\n",iface); 196 197 return S_FALSE; 198 } 199 200 /****************************************************************************** 201 * CompositeMoniker_Load 202 ******************************************************************************/ 203 static HRESULT WINAPI 204 CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm) 205 { 206 CompositeMonikerImpl *This = impl_from_IMoniker(iface); 207 HRESULT res; 208 DWORD moniker_count; 209 DWORD i; 210 211 TRACE("(%p,%p)\n",iface,pStm); 212 213 /* this function call OleLoadFromStream function for each moniker within this object */ 214 215 res=IStream_Read(pStm,&moniker_count,sizeof(DWORD),NULL); 216 if (res != S_OK) 217 { 218 ERR("couldn't reading moniker count from stream\n"); 219 return E_FAIL; 220 } 221 222 CompositeMonikerImpl_ReleaseMonikersInTable(This); 223 224 for (i = 0; i < moniker_count; i++) 225 { 226 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]); 227 if (FAILED(res)) 228 { 229 ERR("couldn't load moniker from stream, res = 0x%08x\n", res); 230 break; 231 } 232 233 /* resize the table if needed */ 234 if (++This->tabLastIndex==This->tabSize){ 235 236 This->tabSize+=BLOCK_TAB_SIZE; 237 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(This->tabMoniker[0])); 238 239 if (This->tabMoniker==NULL) 240 return E_OUTOFMEMORY; 241 } 242 } 243 244 return res; 245 } 246 247 /****************************************************************************** 248 * CompositeMoniker_Save 249 ******************************************************************************/ 250 static HRESULT WINAPI 251 CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty) 252 { 253 CompositeMonikerImpl *This = impl_from_IMoniker(iface); 254 HRESULT res; 255 IEnumMoniker *enumMk; 256 IMoniker *pmk; 257 DWORD moniker_count = This->tabLastIndex; 258 259 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty); 260 261 /* This function calls OleSaveToStream function for each moniker within 262 * this object. 263 * When I tested this function in windows, I usually found this constant 264 * at the beginning of the stream. I don't known why (there's no 265 * indication in the specification) ! 266 */ 267 res=IStream_Write(pStm,&moniker_count,sizeof(moniker_count),NULL); 268 if (FAILED(res)) return res; 269 270 IMoniker_Enum(iface,TRUE,&enumMk); 271 272 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){ 273 274 res=OleSaveToStream((IPersistStream*)pmk,pStm); 275 276 IMoniker_Release(pmk); 277 278 if (FAILED(res)){ 279 280 IEnumMoniker_Release(enumMk); 281 return res; 282 } 283 } 284 285 IEnumMoniker_Release(enumMk); 286 287 return S_OK; 288 } 289 290 /****************************************************************************** 291 * CompositeMoniker_GetSizeMax 292 ******************************************************************************/ 293 static HRESULT WINAPI 294 CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize) 295 { 296 IEnumMoniker *enumMk; 297 IMoniker *pmk; 298 ULARGE_INTEGER ptmpSize; 299 300 /* The sizeMax of this object is calculated by calling GetSizeMax on 301 * each moniker within this object then summing all returned values 302 */ 303 304 TRACE("(%p,%p)\n",iface,pcbSize); 305 306 if (!pcbSize) 307 return E_POINTER; 308 309 pcbSize->QuadPart = sizeof(DWORD); 310 311 IMoniker_Enum(iface,TRUE,&enumMk); 312 313 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){ 314 315 IMoniker_GetSizeMax(pmk,&ptmpSize); 316 317 IMoniker_Release(pmk); 318 319 pcbSize->QuadPart = ptmpSize.QuadPart + sizeof(CLSID); 320 } 321 322 IEnumMoniker_Release(enumMk); 323 324 return S_OK; 325 } 326 327 /****************************************************************************** 328 * CompositeMoniker_BindToObject 329 ******************************************************************************/ 330 static HRESULT WINAPI 331 CompositeMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, 332 IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult) 333 { 334 HRESULT res; 335 IRunningObjectTable *prot; 336 IMoniker *tempMk,*antiMk,*rightMostMk; 337 IEnumMoniker *enumMoniker; 338 339 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult); 340 341 if (ppvResult==NULL) 342 return E_POINTER; 343 344 *ppvResult=0; 345 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */ 346 /* object for the requested interface pointer. */ 347 if(pmkToLeft==NULL){ 348 349 res=IBindCtx_GetRunningObjectTable(pbc,&prot); 350 351 if (SUCCEEDED(res)){ 352 353 /* if the requested class was loaded before ! we don't need to reload it */ 354 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult); 355 356 if (res==S_OK) 357 return res; 358 } 359 } 360 else{ 361 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */ 362 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */ 363 364 IMoniker_Enum(iface,FALSE,&enumMoniker); 365 IEnumMoniker_Next(enumMoniker,1,&rightMostMk,NULL); 366 IEnumMoniker_Release(enumMoniker); 367 368 res=CreateAntiMoniker(&antiMk); 369 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk); 370 IMoniker_Release(antiMk); 371 372 res=IMoniker_BindToObject(rightMostMk,pbc,tempMk,riid,ppvResult); 373 374 IMoniker_Release(tempMk); 375 IMoniker_Release(rightMostMk); 376 } 377 378 return res; 379 } 380 381 /****************************************************************************** 382 * CompositeMoniker_BindToStorage 383 ******************************************************************************/ 384 static HRESULT WINAPI 385 CompositeMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, 386 IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult) 387 { 388 HRESULT res; 389 IMoniker *tempMk,*antiMk,*rightMostMk,*leftMk; 390 IEnumMoniker *enumMoniker; 391 392 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult); 393 394 *ppvResult=0; 395 396 /* This method recursively calls BindToStorage on the rightmost component of the composite, */ 397 /* passing the rest of the composite as the pmkToLeft parameter for that call. */ 398 399 if (pmkToLeft) 400 { 401 res = IMoniker_ComposeWith(pmkToLeft, iface, FALSE, &leftMk); 402 if (FAILED(res)) return res; 403 } 404 else 405 leftMk = iface; 406 407 IMoniker_Enum(iface, FALSE, &enumMoniker); 408 IEnumMoniker_Next(enumMoniker, 1, &rightMostMk, NULL); 409 IEnumMoniker_Release(enumMoniker); 410 411 res = CreateAntiMoniker(&antiMk); 412 if (FAILED(res)) return res; 413 res = IMoniker_ComposeWith(leftMk, antiMk, 0, &tempMk); 414 if (FAILED(res)) return res; 415 IMoniker_Release(antiMk); 416 417 res = IMoniker_BindToStorage(rightMostMk, pbc, tempMk, riid, ppvResult); 418 419 IMoniker_Release(tempMk); 420 421 IMoniker_Release(rightMostMk); 422 423 if (pmkToLeft) 424 IMoniker_Release(leftMk); 425 426 return res; 427 } 428 429 /****************************************************************************** 430 * CompositeMoniker_Reduce 431 ******************************************************************************/ 432 static HRESULT WINAPI 433 CompositeMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar, 434 IMoniker** ppmkToLeft, IMoniker** ppmkReduced) 435 { 436 IMoniker *tempMk,*antiMk,*rightMostMk,*leftReducedComposedMk,*rightMostReducedMk; 437 IEnumMoniker *enumMoniker; 438 439 TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced); 440 441 if (ppmkReduced==NULL) 442 return E_POINTER; 443 444 /* This method recursively calls Reduce for each of its component monikers. */ 445 446 if (ppmkToLeft==NULL){ 447 448 IMoniker_Enum(iface,FALSE,&enumMoniker); 449 IEnumMoniker_Next(enumMoniker,1,&rightMostMk,NULL); 450 IEnumMoniker_Release(enumMoniker); 451 452 CreateAntiMoniker(&antiMk); 453 IMoniker_ComposeWith(iface,antiMk,0,&tempMk); 454 IMoniker_Release(antiMk); 455 456 return IMoniker_Reduce(rightMostMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced); 457 } 458 else if (*ppmkToLeft==NULL) 459 460 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced); 461 462 else{ 463 464 /* separate the composite moniker in to left and right moniker */ 465 IMoniker_Enum(iface,FALSE,&enumMoniker); 466 IEnumMoniker_Next(enumMoniker,1,&rightMostMk,NULL); 467 IEnumMoniker_Release(enumMoniker); 468 469 CreateAntiMoniker(&antiMk); 470 IMoniker_ComposeWith(iface,antiMk,0,&tempMk); 471 IMoniker_Release(antiMk); 472 473 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */ 474 /* of the reduced components */ 475 if (IMoniker_Reduce(rightMostMk,pbc,dwReduceHowFar,NULL,&rightMostReducedMk) && 476 IMoniker_Reduce(rightMostMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk) 477 ) 478 479 return CreateGenericComposite(leftReducedComposedMk,rightMostReducedMk,ppmkReduced); 480 481 else{ 482 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/ 483 484 IMoniker_AddRef(iface); 485 486 *ppmkReduced=iface; 487 488 return MK_S_REDUCED_TO_SELF; 489 } 490 } 491 } 492 493 /****************************************************************************** 494 * CompositeMoniker_ComposeWith 495 ******************************************************************************/ 496 static HRESULT WINAPI 497 CompositeMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight, 498 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite) 499 { 500 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite); 501 502 if ((ppmkComposite==NULL)||(pmkRight==NULL)) 503 return E_POINTER; 504 505 *ppmkComposite=0; 506 507 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */ 508 /* otherwise, the method returns the result of combining the two monikers by calling the */ 509 /* CreateGenericComposite function */ 510 511 if (fOnlyIfNotGeneric) 512 return MK_E_NEEDGENERIC; 513 514 return CreateGenericComposite(iface,pmkRight,ppmkComposite); 515 } 516 517 /****************************************************************************** 518 * CompositeMoniker_Enum 519 ******************************************************************************/ 520 static HRESULT WINAPI 521 CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker) 522 { 523 CompositeMonikerImpl *This = impl_from_IMoniker(iface); 524 525 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker); 526 527 if (ppenumMoniker == NULL) 528 return E_POINTER; 529 530 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker); 531 } 532 533 /****************************************************************************** 534 * CompositeMoniker_IsEqual 535 ******************************************************************************/ 536 static HRESULT WINAPI 537 CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) 538 { 539 IEnumMoniker *enumMoniker1,*enumMoniker2; 540 IMoniker *tempMk1,*tempMk2; 541 HRESULT res1,res2,res; 542 BOOL done; 543 544 TRACE("(%p,%p)\n",iface,pmkOtherMoniker); 545 546 if (pmkOtherMoniker==NULL) 547 return S_FALSE; 548 549 /* This method returns S_OK if the components of both monikers are equal when compared in the */ 550 /* left-to-right order.*/ 551 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1); 552 553 if (enumMoniker1==NULL) 554 return S_FALSE; 555 556 IMoniker_Enum(iface,TRUE,&enumMoniker2); 557 558 do { 559 560 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL); 561 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL); 562 563 if((res1==S_OK)&&(res2==S_OK)){ 564 done = (res = IMoniker_IsEqual(tempMk1,tempMk2)) == S_FALSE; 565 } 566 else 567 { 568 res = (res1==S_FALSE) && (res2==S_FALSE); 569 done = TRUE; 570 } 571 572 if (res1==S_OK) 573 IMoniker_Release(tempMk1); 574 575 if (res2==S_OK) 576 IMoniker_Release(tempMk2); 577 } while (!done); 578 579 IEnumMoniker_Release(enumMoniker1); 580 IEnumMoniker_Release(enumMoniker2); 581 582 return res; 583 } 584 /****************************************************************************** 585 * CompositeMoniker_Hash 586 ******************************************************************************/ 587 static HRESULT WINAPI 588 CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash) 589 { 590 IEnumMoniker *enumMoniker; 591 IMoniker *tempMk; 592 HRESULT res; 593 DWORD tempHash; 594 595 TRACE("(%p,%p)\n",iface,pdwHash); 596 597 if (pdwHash==NULL) 598 return E_POINTER; 599 600 res = IMoniker_Enum(iface,TRUE,&enumMoniker); 601 if(FAILED(res)) 602 return res; 603 604 *pdwHash = 0; 605 606 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){ 607 res = IMoniker_Hash(tempMk, &tempHash); 608 if(FAILED(res)) 609 break; 610 *pdwHash = *pdwHash ^ tempHash; 611 612 IMoniker_Release(tempMk); 613 } 614 615 IEnumMoniker_Release(enumMoniker); 616 617 return res; 618 } 619 620 /****************************************************************************** 621 * CompositeMoniker_IsRunning 622 ******************************************************************************/ 623 static HRESULT WINAPI 624 CompositeMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, 625 IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning) 626 { 627 IRunningObjectTable* rot; 628 HRESULT res; 629 IMoniker *tempMk,*antiMk,*rightMostMk; 630 IEnumMoniker *enumMoniker; 631 632 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning); 633 634 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/ 635 if (pmkToLeft!=NULL){ 636 637 CreateGenericComposite(pmkToLeft,iface,&tempMk); 638 639 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning); 640 641 IMoniker_Release(tempMk); 642 643 return res; 644 } 645 else 646 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */ 647 /* to this moniker */ 648 649 if (pmkNewlyRunning!=NULL) 650 651 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK) 652 return S_OK; 653 654 else 655 return S_FALSE; 656 657 else{ 658 659 if (pbc==NULL) 660 return E_INVALIDARG; 661 662 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */ 663 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */ 664 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */ 665 /* the composite as the pmkToLeft parameter for that call. */ 666 667 res=IBindCtx_GetRunningObjectTable(pbc,&rot); 668 669 if (FAILED(res)) 670 return res; 671 672 res = IRunningObjectTable_IsRunning(rot,iface); 673 IRunningObjectTable_Release(rot); 674 675 if(res==S_OK) 676 return S_OK; 677 678 else{ 679 680 IMoniker_Enum(iface,FALSE,&enumMoniker); 681 IEnumMoniker_Next(enumMoniker,1,&rightMostMk,NULL); 682 IEnumMoniker_Release(enumMoniker); 683 684 res=CreateAntiMoniker(&antiMk); 685 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk); 686 IMoniker_Release(antiMk); 687 688 res=IMoniker_IsRunning(rightMostMk,pbc,tempMk,pmkNewlyRunning); 689 690 IMoniker_Release(tempMk); 691 IMoniker_Release(rightMostMk); 692 693 return res; 694 } 695 } 696 } 697 698 /****************************************************************************** 699 * CompositeMoniker_GetTimeOfLastChange 700 ******************************************************************************/ 701 static HRESULT WINAPI 702 CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, 703 IMoniker* pmkToLeft, FILETIME* pCompositeTime) 704 { 705 HRESULT res; 706 IMoniker *tempMk,*antiMk,*rightMostMk,*leftMk; 707 IEnumMoniker *enumMoniker; 708 709 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime); 710 711 if (pCompositeTime==NULL) 712 return E_INVALIDARG; 713 714 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */ 715 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */ 716 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */ 717 /* of the composite as the pmkToLeft parameter for that call. */ 718 if (pmkToLeft) 719 { 720 IRunningObjectTable* rot; 721 722 res = IMoniker_ComposeWith(pmkToLeft, iface, FALSE, &leftMk); 723 if (FAILED(res)) 724 return res; 725 726 res = IBindCtx_GetRunningObjectTable(pbc,&rot); 727 if (FAILED(res)) 728 { 729 IMoniker_Release(leftMk); 730 return res; 731 } 732 733 if (IRunningObjectTable_GetTimeOfLastChange(rot,leftMk,pCompositeTime)==S_OK) 734 { 735 IMoniker_Release(leftMk); 736 return res; 737 } 738 } 739 else 740 leftMk = iface; 741 742 IMoniker_Enum(iface, FALSE, &enumMoniker); 743 IEnumMoniker_Next(enumMoniker, 1, &rightMostMk, NULL); 744 IEnumMoniker_Release(enumMoniker); 745 746 res = CreateAntiMoniker(&antiMk); 747 res = IMoniker_ComposeWith(leftMk, antiMk, 0, &tempMk); 748 IMoniker_Release(antiMk); 749 750 res = IMoniker_GetTimeOfLastChange(rightMostMk, pbc, tempMk, pCompositeTime); 751 752 IMoniker_Release(tempMk); 753 IMoniker_Release(rightMostMk); 754 755 if (pmkToLeft) 756 IMoniker_Release(leftMk); 757 758 return res; 759 } 760 761 /****************************************************************************** 762 * CompositeMoniker_Inverse 763 ******************************************************************************/ 764 static HRESULT WINAPI 765 CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk) 766 { 767 HRESULT res; 768 IMoniker *tempMk,*antiMk,*rightMostMk,*tempInvMk,*rightMostInvMk; 769 IEnumMoniker *enumMoniker; 770 771 TRACE("(%p,%p)\n",iface,ppmk); 772 773 if (ppmk==NULL) 774 return E_POINTER; 775 776 /* This method returns a composite moniker that consists of the inverses of each of the components */ 777 /* of the original composite, stored in reverse order */ 778 779 *ppmk = NULL; 780 781 res=CreateAntiMoniker(&antiMk); 782 if (FAILED(res)) 783 return res; 784 785 res=IMoniker_ComposeWith(iface,antiMk,FALSE,&tempMk); 786 IMoniker_Release(antiMk); 787 if (FAILED(res)) 788 return res; 789 790 if (tempMk==NULL) 791 792 return IMoniker_Inverse(iface,ppmk); 793 794 else{ 795 796 IMoniker_Enum(iface,FALSE,&enumMoniker); 797 IEnumMoniker_Next(enumMoniker,1,&rightMostMk,NULL); 798 IEnumMoniker_Release(enumMoniker); 799 800 IMoniker_Inverse(rightMostMk,&rightMostInvMk); 801 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk); 802 803 res=CreateGenericComposite(rightMostInvMk,tempInvMk,ppmk); 804 805 IMoniker_Release(tempMk); 806 IMoniker_Release(rightMostMk); 807 IMoniker_Release(tempInvMk); 808 IMoniker_Release(rightMostInvMk); 809 810 return res; 811 } 812 } 813 814 /****************************************************************************** 815 * CompositeMoniker_CommonPrefixWith 816 ******************************************************************************/ 817 static HRESULT WINAPI 818 CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface, IMoniker* pmkOther, 819 IMoniker** ppmkPrefix) 820 { 821 DWORD mkSys; 822 HRESULT res1,res2; 823 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2; 824 IEnumMoniker *enumMoniker1,*enumMoniker2; 825 ULONG i,nbCommonMk=0; 826 827 /* If the other moniker is a composite, this method compares the components of each composite from left */ 828 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */ 829 /* of the leftmost components were common to both monikers. */ 830 831 if (ppmkPrefix==NULL) 832 return E_POINTER; 833 834 *ppmkPrefix=0; 835 836 if (pmkOther==NULL) 837 return MK_E_NOPREFIX; 838 839 IMoniker_IsSystemMoniker(pmkOther,&mkSys); 840 841 if(mkSys==MKSYS_GENERICCOMPOSITE){ 842 843 IMoniker_Enum(iface,TRUE,&enumMoniker1); 844 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2); 845 846 while(1){ 847 848 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL); 849 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL); 850 851 if ((res1==S_FALSE) && (res2==S_FALSE)){ 852 853 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/ 854 *ppmkPrefix=iface; 855 IMoniker_AddRef(iface); 856 return MK_S_US; 857 } 858 else if ((res1==S_OK) && (res2==S_OK)){ 859 860 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK) 861 862 nbCommonMk++; 863 864 else 865 break; 866 867 } 868 else if (res1==S_OK){ 869 870 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */ 871 /* ppmkPrefix to the other moniker. */ 872 *ppmkPrefix=pmkOther; 873 return MK_S_HIM; 874 } 875 else{ 876 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */ 877 /* to this moniker. */ 878 *ppmkPrefix=iface; 879 return MK_S_ME; 880 } 881 } 882 883 IEnumMoniker_Release(enumMoniker1); 884 IEnumMoniker_Release(enumMoniker2); 885 886 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */ 887 if (nbCommonMk==0) 888 return MK_E_NOPREFIX; 889 890 IEnumMoniker_Reset(enumMoniker1); 891 892 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL); 893 894 /* if we have more than one common moniker the result will be a composite moniker */ 895 if (nbCommonMk>1){ 896 897 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/ 898 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL); 899 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix); 900 IMoniker_Release(tempMk1); 901 IMoniker_Release(tempMk2); 902 903 /* compose all common monikers in a composite moniker */ 904 for(i=0;i<nbCommonMk;i++){ 905 906 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL); 907 908 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2); 909 910 IMoniker_Release(*ppmkPrefix); 911 912 IMoniker_Release(tempMk1); 913 914 *ppmkPrefix=tempMk2; 915 } 916 return S_OK; 917 } 918 else{ 919 /* if we have only one common moniker the result will be a simple moniker which is the most-left one*/ 920 *ppmkPrefix=tempMk1; 921 922 return S_OK; 923 } 924 } 925 else{ 926 /* If the other moniker is not a composite, the method simply compares it to the leftmost component 927 of this moniker.*/ 928 929 IMoniker_Enum(iface,TRUE,&enumMoniker1); 930 931 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL); 932 933 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){ 934 935 *ppmkPrefix=pmkOther; 936 937 return MK_S_HIM; 938 } 939 else 940 return MK_E_NOPREFIX; 941 } 942 } 943 944 /*************************************************************************************************** 945 * GetAfterCommonPrefix (local function) 946 * This function returns a moniker that consist of the remainder when the common prefix is removed 947 ***************************************************************************************************/ 948 static VOID GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk) 949 { 950 IMoniker *tempMk,*tempMk1,*tempMk2; 951 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3; 952 ULONG nbRestMk=0; 953 DWORD mkSys; 954 HRESULT res1,res2; 955 956 *restMk=0; 957 958 /* to create an enumerator for pGenMk with current position pointed on the first element after common */ 959 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */ 960 /* on the first difference. */ 961 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1); 962 963 IMoniker_IsSystemMoniker(commonMk,&mkSys); 964 965 if (mkSys==MKSYS_GENERICCOMPOSITE){ 966 967 IMoniker_Enum(commonMk,TRUE,&enumMoniker2); 968 while(1){ 969 970 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL); 971 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL); 972 973 if ((res1==S_FALSE)||(res2==S_FALSE)){ 974 975 if (res1==S_OK) 976 977 nbRestMk++; 978 979 IMoniker_Release(tempMk1); 980 IMoniker_Release(tempMk2); 981 982 break; 983 } 984 IMoniker_Release(tempMk1); 985 IMoniker_Release(tempMk2); 986 } 987 } 988 else{ 989 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL); 990 IMoniker_Release(tempMk1); 991 } 992 993 /* count the number of elements in the enumerator after the common prefix */ 994 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3); 995 996 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++) 997 998 IMoniker_Release(tempMk); 999 1000 if (nbRestMk==0) 1001 return; 1002 1003 /* create a generic composite moniker with monikers located after the common prefix */ 1004 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL); 1005 1006 if (nbRestMk==1){ 1007 1008 *restMk= tempMk1; 1009 return; 1010 } 1011 else { 1012 1013 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL); 1014 1015 CreateGenericComposite(tempMk1,tempMk2,restMk); 1016 1017 IMoniker_Release(tempMk1); 1018 1019 IMoniker_Release(tempMk2); 1020 1021 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){ 1022 1023 CreateGenericComposite(*restMk,tempMk1,&tempMk2); 1024 1025 IMoniker_Release(tempMk1); 1026 1027 IMoniker_Release(*restMk); 1028 1029 *restMk=tempMk2; 1030 } 1031 } 1032 } 1033 1034 /****************************************************************************** 1035 * CompositeMoniker_RelativePathTo 1036 ******************************************************************************/ 1037 static HRESULT WINAPI 1038 CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, 1039 IMoniker** ppmkRelPath) 1040 { 1041 HRESULT res; 1042 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0; 1043 1044 TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath); 1045 1046 if (ppmkRelPath==NULL) 1047 return E_POINTER; 1048 1049 *ppmkRelPath=0; 1050 1051 /* This method finds the common prefix of the two monikers and creates two monikers that consist */ 1052 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */ 1053 /* of this moniker and composes the remainder of the other moniker on the right of it. */ 1054 1055 /* finds the common prefix of the two monikers */ 1056 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk); 1057 1058 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */ 1059 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){ 1060 1061 *ppmkRelPath=pmkOther; 1062 IMoniker_AddRef(pmkOther); 1063 return MK_S_HIM; 1064 } 1065 1066 GetAfterCommonPrefix(iface,commonMk,&restThisMk); 1067 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk); 1068 1069 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */ 1070 /* moniker when the common prefix is removed */ 1071 if (res==MK_S_HIM){ 1072 1073 IMoniker_Inverse(restThisMk,ppmkRelPath); 1074 IMoniker_Release(restThisMk); 1075 } 1076 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */ 1077 /* when the common prefix is removed */ 1078 else if (res==MK_S_ME){ 1079 1080 *ppmkRelPath=restOtherMk; 1081 IMoniker_AddRef(restOtherMk); 1082 } 1083 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */ 1084 /* moniker on the right of it. */ 1085 else if (res==S_OK){ 1086 1087 IMoniker_Inverse(restThisMk,&invRestThisMk); 1088 IMoniker_Release(restThisMk); 1089 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath); 1090 IMoniker_Release(invRestThisMk); 1091 IMoniker_Release(restOtherMk); 1092 } 1093 return S_OK; 1094 } 1095 1096 /****************************************************************************** 1097 * CompositeMoniker_GetDisplayName 1098 ******************************************************************************/ 1099 static HRESULT WINAPI 1100 CompositeMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc, 1101 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName) 1102 { 1103 ULONG lengthStr=1; 1104 IEnumMoniker *enumMoniker; 1105 IMoniker* tempMk; 1106 LPOLESTR tempStr; 1107 1108 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName); 1109 1110 if (ppszDisplayName==NULL) 1111 return E_POINTER; 1112 1113 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)); 1114 1115 if (*ppszDisplayName==NULL) 1116 return E_OUTOFMEMORY; 1117 1118 /* This method returns the concatenation of the display names returned by each component moniker of */ 1119 /* the composite */ 1120 1121 **ppszDisplayName=0; 1122 1123 IMoniker_Enum(iface,TRUE,&enumMoniker); 1124 1125 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){ 1126 1127 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr); 1128 1129 lengthStr+=lstrlenW(tempStr); 1130 1131 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR)); 1132 1133 if (*ppszDisplayName==NULL) 1134 return E_OUTOFMEMORY; 1135 1136 strcatW(*ppszDisplayName,tempStr); 1137 1138 CoTaskMemFree(tempStr); 1139 IMoniker_Release(tempMk); 1140 } 1141 1142 IEnumMoniker_Release(enumMoniker); 1143 1144 return S_OK; 1145 } 1146 1147 /****************************************************************************** 1148 * CompositeMoniker_ParseDisplayName 1149 ******************************************************************************/ 1150 static HRESULT WINAPI 1151 CompositeMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, 1152 IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, 1153 IMoniker** ppmkOut) 1154 { 1155 IEnumMoniker *enumMoniker; 1156 IMoniker *tempMk,*rightMostMk,*antiMk; 1157 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/ 1158 /* passing everything else as the pmkToLeft parameter for that call. */ 1159 1160 /* get the most right moniker */ 1161 IMoniker_Enum(iface,FALSE,&enumMoniker); 1162 IEnumMoniker_Next(enumMoniker,1,&rightMostMk,NULL); 1163 IEnumMoniker_Release(enumMoniker); 1164 1165 /* get the left moniker */ 1166 CreateAntiMoniker(&antiMk); 1167 IMoniker_ComposeWith(iface,antiMk,0,&tempMk); 1168 IMoniker_Release(antiMk); 1169 1170 return IMoniker_ParseDisplayName(rightMostMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut); 1171 } 1172 1173 /****************************************************************************** 1174 * CompositeMoniker_IsSystemMoniker 1175 ******************************************************************************/ 1176 static HRESULT WINAPI 1177 CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) 1178 { 1179 TRACE("(%p,%p)\n",iface,pwdMksys); 1180 1181 if (!pwdMksys) 1182 return E_POINTER; 1183 1184 (*pwdMksys)=MKSYS_GENERICCOMPOSITE; 1185 1186 return S_OK; 1187 } 1188 1189 /******************************************************************************* 1190 * CompositeMonikerIROTData_QueryInterface 1191 *******************************************************************************/ 1192 static HRESULT WINAPI 1193 CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid, 1194 VOID** ppvObject) 1195 { 1196 CompositeMonikerImpl *This = impl_from_IROTData(iface); 1197 1198 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppvObject); 1199 1200 return CompositeMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject); 1201 } 1202 1203 /*********************************************************************** 1204 * CompositeMonikerIROTData_AddRef 1205 */ 1206 static ULONG WINAPI 1207 CompositeMonikerROTDataImpl_AddRef(IROTData *iface) 1208 { 1209 CompositeMonikerImpl *This = impl_from_IROTData(iface); 1210 1211 TRACE("(%p)\n",iface); 1212 1213 return IMoniker_AddRef(&This->IMoniker_iface); 1214 } 1215 1216 /*********************************************************************** 1217 * CompositeMonikerIROTData_Release 1218 */ 1219 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface) 1220 { 1221 CompositeMonikerImpl *This = impl_from_IROTData(iface); 1222 1223 TRACE("(%p)\n",iface); 1224 1225 return IMoniker_Release(&This->IMoniker_iface); 1226 } 1227 1228 /****************************************************************************** 1229 * CompositeMonikerIROTData_GetComparisonData 1230 ******************************************************************************/ 1231 static HRESULT WINAPI 1232 CompositeMonikerROTDataImpl_GetComparisonData(IROTData* iface, 1233 BYTE* pbData, ULONG cbMax, ULONG* pcbData) 1234 { 1235 CompositeMonikerImpl *This = impl_from_IROTData(iface); 1236 IEnumMoniker *pEnumMk; 1237 IMoniker *pmk; 1238 HRESULT hr; 1239 1240 TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData); 1241 1242 *pcbData = sizeof(CLSID); 1243 1244 hr = IMoniker_Enum(&This->IMoniker_iface, TRUE, &pEnumMk); 1245 if (FAILED(hr)) return hr; 1246 1247 while(IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK) 1248 { 1249 IROTData *pROTData; 1250 hr = IMoniker_QueryInterface(pmk, &IID_IROTData, (void **)&pROTData); 1251 if (FAILED(hr)) 1252 ERR("moniker doesn't support IROTData interface\n"); 1253 1254 if (SUCCEEDED(hr)) 1255 { 1256 ULONG cbData; 1257 hr = IROTData_GetComparisonData(pROTData, NULL, 0, &cbData); 1258 IROTData_Release(pROTData); 1259 if (SUCCEEDED(hr) || (hr == E_OUTOFMEMORY)) 1260 { 1261 *pcbData += cbData; 1262 hr = S_OK; 1263 } 1264 else 1265 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr); 1266 } 1267 1268 IMoniker_Release(pmk); 1269 1270 if (FAILED(hr)) 1271 { 1272 IEnumMoniker_Release(pEnumMk); 1273 return hr; 1274 } 1275 } 1276 if (cbMax < *pcbData) 1277 return E_OUTOFMEMORY; 1278 1279 IEnumMoniker_Reset(pEnumMk); 1280 1281 memcpy(pbData, &CLSID_CompositeMoniker, sizeof(CLSID)); 1282 pbData += sizeof(CLSID); 1283 cbMax -= sizeof(CLSID); 1284 1285 while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK) 1286 { 1287 IROTData *pROTData; 1288 hr = IMoniker_QueryInterface(pmk, &IID_IROTData, (void **)&pROTData); 1289 if (FAILED(hr)) 1290 ERR("moniker doesn't support IROTData interface\n"); 1291 1292 if (SUCCEEDED(hr)) 1293 { 1294 ULONG cbData; 1295 hr = IROTData_GetComparisonData(pROTData, pbData, cbMax, &cbData); 1296 IROTData_Release(pROTData); 1297 if (SUCCEEDED(hr)) 1298 { 1299 pbData += cbData; 1300 cbMax -= cbData; 1301 } 1302 else 1303 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr); 1304 } 1305 1306 IMoniker_Release(pmk); 1307 1308 if (FAILED(hr)) 1309 { 1310 IEnumMoniker_Release(pEnumMk); 1311 return hr; 1312 } 1313 } 1314 1315 IEnumMoniker_Release(pEnumMk); 1316 1317 return S_OK; 1318 } 1319 1320 static HRESULT WINAPI CompositeMonikerMarshalImpl_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv) 1321 { 1322 CompositeMonikerImpl *This = impl_from_IMarshal(iface); 1323 1324 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppv); 1325 1326 return CompositeMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppv); 1327 } 1328 1329 static ULONG WINAPI CompositeMonikerMarshalImpl_AddRef(IMarshal *iface) 1330 { 1331 CompositeMonikerImpl *This = impl_from_IMarshal(iface); 1332 1333 TRACE("(%p)\n",iface); 1334 1335 return CompositeMonikerImpl_AddRef(&This->IMoniker_iface); 1336 } 1337 1338 static ULONG WINAPI CompositeMonikerMarshalImpl_Release(IMarshal *iface) 1339 { 1340 CompositeMonikerImpl *This = impl_from_IMarshal(iface); 1341 1342 TRACE("(%p)\n",iface); 1343 1344 return CompositeMonikerImpl_Release(&This->IMoniker_iface); 1345 } 1346 1347 static HRESULT WINAPI CompositeMonikerMarshalImpl_GetUnmarshalClass( 1348 IMarshal *iface, REFIID riid, void *pv, DWORD dwDestContext, 1349 void* pvDestContext, DWORD mshlflags, CLSID* pCid) 1350 { 1351 CompositeMonikerImpl *This = impl_from_IMarshal(iface); 1352 1353 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv, 1354 dwDestContext, pvDestContext, mshlflags, pCid); 1355 1356 return IMoniker_GetClassID(&This->IMoniker_iface, pCid); 1357 } 1358 1359 static HRESULT WINAPI CompositeMonikerMarshalImpl_GetMarshalSizeMax( 1360 IMarshal *iface, REFIID riid, void *pv, DWORD dwDestContext, 1361 void* pvDestContext, DWORD mshlflags, DWORD* pSize) 1362 { 1363 CompositeMonikerImpl *This = impl_from_IMarshal(iface); 1364 IEnumMoniker *pEnumMk; 1365 IMoniker *pmk; 1366 HRESULT hr; 1367 ULARGE_INTEGER size; 1368 1369 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv, 1370 dwDestContext, pvDestContext, mshlflags, pSize); 1371 1372 *pSize = 0x10; /* to match native */ 1373 1374 hr = IMoniker_Enum(&This->IMoniker_iface, TRUE, &pEnumMk); 1375 if (FAILED(hr)) return hr; 1376 1377 hr = IMoniker_GetSizeMax(&This->IMoniker_iface, &size); 1378 1379 while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK) 1380 { 1381 ULONG size; 1382 1383 hr = CoGetMarshalSizeMax(&size, &IID_IMoniker, (IUnknown *)pmk, dwDestContext, pvDestContext, mshlflags); 1384 if (SUCCEEDED(hr)) 1385 *pSize += size; 1386 1387 IMoniker_Release(pmk); 1388 1389 if (FAILED(hr)) 1390 { 1391 IEnumMoniker_Release(pEnumMk); 1392 return hr; 1393 } 1394 } 1395 1396 IEnumMoniker_Release(pEnumMk); 1397 1398 return S_OK; 1399 } 1400 1401 static HRESULT WINAPI CompositeMonikerMarshalImpl_MarshalInterface(IMarshal *iface, IStream *pStm, 1402 REFIID riid, void* pv, DWORD dwDestContext, 1403 void* pvDestContext, DWORD mshlflags) 1404 { 1405 CompositeMonikerImpl *This = impl_from_IMarshal(iface); 1406 IEnumMoniker *pEnumMk; 1407 IMoniker *pmk; 1408 HRESULT hr; 1409 ULONG i = 0; 1410 1411 TRACE("(%p, %s, %p, %x, %p, %x)\n", pStm, debugstr_guid(riid), pv, 1412 dwDestContext, pvDestContext, mshlflags); 1413 1414 hr = IMoniker_Enum(&This->IMoniker_iface, TRUE, &pEnumMk); 1415 if (FAILED(hr)) return hr; 1416 1417 while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK) 1418 { 1419 hr = CoMarshalInterface(pStm, &IID_IMoniker, (IUnknown *)pmk, dwDestContext, pvDestContext, mshlflags); 1420 1421 IMoniker_Release(pmk); 1422 1423 if (FAILED(hr)) 1424 { 1425 IEnumMoniker_Release(pEnumMk); 1426 return hr; 1427 } 1428 i++; 1429 } 1430 1431 if (i != 2) 1432 FIXME("moniker count of %d not supported\n", i); 1433 1434 IEnumMoniker_Release(pEnumMk); 1435 1436 return S_OK; 1437 } 1438 1439 static HRESULT WINAPI CompositeMonikerMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, 1440 REFIID riid, void **ppv) 1441 { 1442 CompositeMonikerImpl *This = impl_from_IMarshal(iface); 1443 HRESULT hr; 1444 1445 TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv); 1446 1447 CompositeMonikerImpl_ReleaseMonikersInTable(This); 1448 1449 /* resize the table if needed */ 1450 if (This->tabLastIndex + 2 > This->tabSize) 1451 { 1452 This->tabSize += max(BLOCK_TAB_SIZE, 2); 1453 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(This->tabMoniker[0])); 1454 1455 if (This->tabMoniker==NULL) 1456 return E_OUTOFMEMORY; 1457 } 1458 1459 hr = CoUnmarshalInterface(pStm, &IID_IMoniker, (void**)&This->tabMoniker[This->tabLastIndex]); 1460 if (FAILED(hr)) 1461 { 1462 ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr); 1463 return hr; 1464 } 1465 This->tabLastIndex++; 1466 hr = CoUnmarshalInterface(pStm, &IID_IMoniker, (void**)&This->tabMoniker[This->tabLastIndex]); 1467 if (FAILED(hr)) 1468 { 1469 ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr); 1470 return hr; 1471 } 1472 This->tabLastIndex++; 1473 1474 return IMoniker_QueryInterface(&This->IMoniker_iface, riid, ppv); 1475 } 1476 1477 static HRESULT WINAPI CompositeMonikerMarshalImpl_ReleaseMarshalData(IMarshal *iface, IStream *pStm) 1478 { 1479 TRACE("(%p)\n", pStm); 1480 /* can't release a state-based marshal as nothing on server side to 1481 * release */ 1482 return S_OK; 1483 } 1484 1485 static HRESULT WINAPI CompositeMonikerMarshalImpl_DisconnectObject(IMarshal *iface, 1486 DWORD dwReserved) 1487 { 1488 TRACE("(0x%x)\n", dwReserved); 1489 /* can't disconnect a state-based marshal as nothing on server side to 1490 * disconnect from */ 1491 return S_OK; 1492 } 1493 1494 /****************************************************************************** 1495 * EnumMonikerImpl_QueryInterface 1496 ******************************************************************************/ 1497 static HRESULT WINAPI 1498 EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject) 1499 { 1500 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 1501 1502 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject); 1503 1504 /* Perform a sanity check on the parameters.*/ 1505 if ( ppvObject==0 ) 1506 return E_INVALIDARG; 1507 1508 /* Initialize the return parameter */ 1509 *ppvObject = 0; 1510 1511 /* Compare the riid with the interface IDs implemented by this object.*/ 1512 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid)) 1513 *ppvObject = iface; 1514 1515 /* Check that we obtained an interface.*/ 1516 if ((*ppvObject)==0) 1517 return E_NOINTERFACE; 1518 1519 /* Query Interface always increases the reference count by one when it is successful */ 1520 IEnumMoniker_AddRef(iface); 1521 1522 return S_OK; 1523 } 1524 1525 /****************************************************************************** 1526 * EnumMonikerImpl_AddRef 1527 ******************************************************************************/ 1528 static ULONG WINAPI 1529 EnumMonikerImpl_AddRef(IEnumMoniker* iface) 1530 { 1531 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 1532 1533 TRACE("(%p)\n",This); 1534 1535 return InterlockedIncrement(&This->ref); 1536 1537 } 1538 1539 /****************************************************************************** 1540 * EnumMonikerImpl_Release 1541 ******************************************************************************/ 1542 static ULONG WINAPI 1543 EnumMonikerImpl_Release(IEnumMoniker* iface) 1544 { 1545 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 1546 ULONG i; 1547 ULONG ref; 1548 TRACE("(%p)\n",This); 1549 1550 ref = InterlockedDecrement(&This->ref); 1551 1552 /* destroy the object if there are no more references to it */ 1553 if (ref == 0) { 1554 1555 for(i=0;i<This->tabSize;i++) 1556 IMoniker_Release(This->tabMoniker[i]); 1557 1558 HeapFree(GetProcessHeap(),0,This->tabMoniker); 1559 HeapFree(GetProcessHeap(),0,This); 1560 } 1561 return ref; 1562 } 1563 1564 /****************************************************************************** 1565 * EnumMonikerImpl_Next 1566 ******************************************************************************/ 1567 static HRESULT WINAPI 1568 EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, 1569 ULONG* pceltFethed) 1570 { 1571 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 1572 ULONG i; 1573 1574 /* retrieve the requested number of moniker from the current position */ 1575 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++) 1576 { 1577 rgelt[i]=This->tabMoniker[This->currentPos++]; 1578 IMoniker_AddRef(rgelt[i]); 1579 } 1580 1581 if (pceltFethed!=NULL) 1582 *pceltFethed= i; 1583 1584 if (i==celt) 1585 return S_OK; 1586 else 1587 return S_FALSE; 1588 } 1589 1590 /****************************************************************************** 1591 * EnumMonikerImpl_Skip 1592 ******************************************************************************/ 1593 static HRESULT WINAPI 1594 EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt) 1595 { 1596 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 1597 1598 if ((This->currentPos+celt) >= This->tabSize) 1599 return S_FALSE; 1600 1601 This->currentPos+=celt; 1602 1603 return S_OK; 1604 } 1605 1606 /****************************************************************************** 1607 * EnumMonikerImpl_Reset 1608 ******************************************************************************/ 1609 static HRESULT WINAPI 1610 EnumMonikerImpl_Reset(IEnumMoniker* iface) 1611 { 1612 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 1613 1614 This->currentPos=0; 1615 1616 return S_OK; 1617 } 1618 1619 /****************************************************************************** 1620 * EnumMonikerImpl_Clone 1621 ******************************************************************************/ 1622 static HRESULT WINAPI 1623 EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum) 1624 { 1625 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 1626 1627 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum); 1628 } 1629 1630 /********************************************************************************/ 1631 /* Virtual function table for the IROTData class */ 1632 static const IEnumMonikerVtbl VT_EnumMonikerImpl = 1633 { 1634 EnumMonikerImpl_QueryInterface, 1635 EnumMonikerImpl_AddRef, 1636 EnumMonikerImpl_Release, 1637 EnumMonikerImpl_Next, 1638 EnumMonikerImpl_Skip, 1639 EnumMonikerImpl_Reset, 1640 EnumMonikerImpl_Clone 1641 }; 1642 1643 /****************************************************************************** 1644 * EnumMonikerImpl_CreateEnumMoniker 1645 ******************************************************************************/ 1646 static HRESULT 1647 EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker, ULONG tabSize, 1648 ULONG currentPos, BOOL leftToRight, IEnumMoniker ** ppmk) 1649 { 1650 EnumMonikerImpl* newEnumMoniker; 1651 ULONG i; 1652 1653 if (currentPos > tabSize) 1654 return E_INVALIDARG; 1655 1656 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl)); 1657 1658 if (newEnumMoniker == 0) 1659 return STG_E_INSUFFICIENTMEMORY; 1660 1661 /* Initialize the virtual function table. */ 1662 newEnumMoniker->IEnumMoniker_iface.lpVtbl = &VT_EnumMonikerImpl; 1663 newEnumMoniker->ref = 1; 1664 1665 newEnumMoniker->tabSize=tabSize; 1666 newEnumMoniker->currentPos=currentPos; 1667 1668 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(newEnumMoniker->tabMoniker[0])); 1669 1670 if (newEnumMoniker->tabMoniker==NULL) { 1671 HeapFree(GetProcessHeap(), 0, newEnumMoniker); 1672 return E_OUTOFMEMORY; 1673 } 1674 1675 if (leftToRight) 1676 for (i=0;i<tabSize;i++){ 1677 1678 newEnumMoniker->tabMoniker[i]=tabMoniker[i]; 1679 IMoniker_AddRef(tabMoniker[i]); 1680 } 1681 else 1682 for (i = tabSize; i > 0; i--){ 1683 1684 newEnumMoniker->tabMoniker[tabSize-i]=tabMoniker[i - 1]; 1685 IMoniker_AddRef(tabMoniker[i - 1]); 1686 } 1687 1688 *ppmk=&newEnumMoniker->IEnumMoniker_iface; 1689 1690 return S_OK; 1691 } 1692 1693 /********************************************************************************/ 1694 /* Virtual function table for the CompositeMonikerImpl class which includes */ 1695 /* IPersist, IPersistStream and IMoniker functions. */ 1696 1697 static const IMonikerVtbl VT_CompositeMonikerImpl = 1698 { 1699 CompositeMonikerImpl_QueryInterface, 1700 CompositeMonikerImpl_AddRef, 1701 CompositeMonikerImpl_Release, 1702 CompositeMonikerImpl_GetClassID, 1703 CompositeMonikerImpl_IsDirty, 1704 CompositeMonikerImpl_Load, 1705 CompositeMonikerImpl_Save, 1706 CompositeMonikerImpl_GetSizeMax, 1707 CompositeMonikerImpl_BindToObject, 1708 CompositeMonikerImpl_BindToStorage, 1709 CompositeMonikerImpl_Reduce, 1710 CompositeMonikerImpl_ComposeWith, 1711 CompositeMonikerImpl_Enum, 1712 CompositeMonikerImpl_IsEqual, 1713 CompositeMonikerImpl_Hash, 1714 CompositeMonikerImpl_IsRunning, 1715 CompositeMonikerImpl_GetTimeOfLastChange, 1716 CompositeMonikerImpl_Inverse, 1717 CompositeMonikerImpl_CommonPrefixWith, 1718 CompositeMonikerImpl_RelativePathTo, 1719 CompositeMonikerImpl_GetDisplayName, 1720 CompositeMonikerImpl_ParseDisplayName, 1721 CompositeMonikerImpl_IsSystemMoniker 1722 }; 1723 1724 /********************************************************************************/ 1725 /* Virtual function table for the IROTData class. */ 1726 static const IROTDataVtbl VT_ROTDataImpl = 1727 { 1728 CompositeMonikerROTDataImpl_QueryInterface, 1729 CompositeMonikerROTDataImpl_AddRef, 1730 CompositeMonikerROTDataImpl_Release, 1731 CompositeMonikerROTDataImpl_GetComparisonData 1732 }; 1733 1734 static const IMarshalVtbl VT_MarshalImpl = 1735 { 1736 CompositeMonikerMarshalImpl_QueryInterface, 1737 CompositeMonikerMarshalImpl_AddRef, 1738 CompositeMonikerMarshalImpl_Release, 1739 CompositeMonikerMarshalImpl_GetUnmarshalClass, 1740 CompositeMonikerMarshalImpl_GetMarshalSizeMax, 1741 CompositeMonikerMarshalImpl_MarshalInterface, 1742 CompositeMonikerMarshalImpl_UnmarshalInterface, 1743 CompositeMonikerMarshalImpl_ReleaseMarshalData, 1744 CompositeMonikerMarshalImpl_DisconnectObject 1745 }; 1746 1747 /****************************************************************************** 1748 * Composite-Moniker_Construct (local function) 1749 *******************************************************************************/ 1750 static HRESULT 1751 CompositeMonikerImpl_Construct(IMoniker **ppMoniker, IMoniker *pmkFirst, IMoniker *pmkRest) 1752 { 1753 DWORD mkSys; 1754 IEnumMoniker *enumMoniker; 1755 IMoniker *tempMk; 1756 HRESULT res; 1757 CompositeMonikerImpl *This; 1758 int i; 1759 1760 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 1761 1762 if (!This) 1763 return E_OUTOFMEMORY; 1764 1765 TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest); 1766 1767 /* Initialize the virtual function table. */ 1768 This->IMoniker_iface.lpVtbl = &VT_CompositeMonikerImpl; 1769 This->IROTData_iface.lpVtbl = &VT_ROTDataImpl; 1770 This->IMarshal_iface.lpVtbl = &VT_MarshalImpl; 1771 This->ref = 1; 1772 1773 This->tabSize=BLOCK_TAB_SIZE; 1774 This->tabLastIndex=0; 1775 1776 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(This->tabMoniker[0])); 1777 if (This->tabMoniker==NULL) { 1778 HeapFree(GetProcessHeap(), 0, This); 1779 return E_OUTOFMEMORY; 1780 } 1781 1782 if (!pmkFirst && !pmkRest) 1783 { 1784 *ppMoniker = &This->IMoniker_iface; 1785 return S_OK; 1786 } 1787 1788 IMoniker_IsSystemMoniker(pmkFirst,&mkSys); 1789 1790 /* put the first moniker contents in the beginning of the table */ 1791 if (mkSys!=MKSYS_GENERICCOMPOSITE){ 1792 1793 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst; 1794 IMoniker_AddRef(pmkFirst); 1795 } 1796 else{ 1797 1798 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker); 1799 1800 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){ 1801 1802 1803 if (++This->tabLastIndex==This->tabSize){ 1804 IMoniker **tab_moniker = This->tabMoniker; 1805 1806 This->tabSize+=BLOCK_TAB_SIZE; 1807 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(This->tabMoniker[0])); 1808 1809 if (This->tabMoniker==NULL){ 1810 for (i = 0; i < This->tabLastIndex; i++) 1811 IMoniker_Release(tab_moniker[i]); 1812 HeapFree(GetProcessHeap(), 0, tab_moniker); 1813 HeapFree(GetProcessHeap(), 0, This); 1814 return E_OUTOFMEMORY; 1815 } 1816 } 1817 } 1818 1819 IEnumMoniker_Release(enumMoniker); 1820 } 1821 1822 /* put the rest moniker contents after the first one and make simplification if needed */ 1823 1824 IMoniker_IsSystemMoniker(pmkRest,&mkSys); 1825 1826 if (mkSys!=MKSYS_GENERICCOMPOSITE){ 1827 1828 /* add a simple moniker to the moniker table */ 1829 1830 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk); 1831 1832 if (res==MK_E_NEEDGENERIC){ 1833 1834 /* there's no simplification in this case */ 1835 This->tabMoniker[This->tabLastIndex]=pmkRest; 1836 1837 This->tabLastIndex++; 1838 1839 IMoniker_AddRef(pmkRest); 1840 } 1841 else if (tempMk==NULL){ 1842 1843 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */ 1844 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]); 1845 1846 This->tabLastIndex--; 1847 } 1848 else if (SUCCEEDED(res)){ 1849 1850 /* the non-generic composition was successful so we can make a simplification in this case */ 1851 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]); 1852 1853 This->tabMoniker[This->tabLastIndex-1]=tempMk; 1854 } else{ 1855 for (i = 0; i < This->tabLastIndex; i++) 1856 IMoniker_Release(This->tabMoniker[i]); 1857 HeapFree(GetProcessHeap(), 0, This->tabMoniker); 1858 HeapFree(GetProcessHeap(), 0, This); 1859 return res; 1860 } 1861 1862 /* resize tabMoniker if needed */ 1863 if (This->tabLastIndex==This->tabSize){ 1864 IMoniker **tab_moniker = This->tabMoniker; 1865 1866 This->tabSize+=BLOCK_TAB_SIZE; 1867 1868 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker)); 1869 1870 if (This->tabMoniker==NULL){ 1871 for (i = 0; i < This->tabLastIndex; i++) 1872 IMoniker_Release(tab_moniker[i]); 1873 HeapFree(GetProcessHeap(), 0, tab_moniker); 1874 HeapFree(GetProcessHeap(), 0, This); 1875 return E_OUTOFMEMORY; 1876 } 1877 } 1878 } 1879 else{ 1880 1881 /* add a composite moniker to the moniker table (do the same thing 1882 * for each moniker within the composite moniker as a simple moniker 1883 * (see above for how to add a simple moniker case) ) 1884 */ 1885 IMoniker_Enum(pmkRest,TRUE,&enumMoniker); 1886 1887 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){ 1888 1889 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk); 1890 1891 if (res==MK_E_NEEDGENERIC){ 1892 1893 This->tabLastIndex++; 1894 } 1895 else if (tempMk==NULL){ 1896 1897 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]); 1898 IMoniker_Release(This->tabMoniker[This->tabLastIndex]); 1899 This->tabLastIndex--; 1900 } 1901 else{ 1902 1903 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]); 1904 1905 This->tabMoniker[This->tabLastIndex-1]=tempMk; 1906 } 1907 1908 if (This->tabLastIndex==This->tabSize){ 1909 IMoniker **tab_moniker = This->tabMoniker; 1910 1911 This->tabSize+=BLOCK_TAB_SIZE; 1912 1913 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(This->tabMoniker[0])); 1914 1915 if (This->tabMoniker==NULL){ 1916 for (i = 0; i < This->tabLastIndex; i++) 1917 IMoniker_Release(tab_moniker[i]); 1918 HeapFree(GetProcessHeap(), 0, tab_moniker); 1919 HeapFree(GetProcessHeap(), 0, This); 1920 return E_OUTOFMEMORY; 1921 } 1922 } 1923 } 1924 1925 IEnumMoniker_Release(enumMoniker); 1926 } 1927 1928 /* only one moniker, then just return it */ 1929 if (This->tabLastIndex == 1) 1930 { 1931 *ppMoniker = This->tabMoniker[0]; 1932 IMoniker_AddRef(*ppMoniker); 1933 IMoniker_Release(&This->IMoniker_iface); 1934 } 1935 else 1936 *ppMoniker = &This->IMoniker_iface; 1937 1938 return S_OK; 1939 } 1940 1941 /****************************************************************************** 1942 * CreateGenericComposite [OLE32.@] 1943 ******************************************************************************/ 1944 HRESULT WINAPI 1945 CreateGenericComposite(IMoniker *pmkFirst, IMoniker *pmkRest, IMoniker **ppmkComposite) 1946 { 1947 IMoniker* moniker = 0; 1948 HRESULT hr = S_OK; 1949 1950 TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite); 1951 1952 if (ppmkComposite==NULL) 1953 return E_POINTER; 1954 1955 *ppmkComposite=0; 1956 1957 if (pmkFirst==NULL && pmkRest!=NULL){ 1958 1959 *ppmkComposite=pmkRest; 1960 IMoniker_AddRef(pmkRest); 1961 return S_OK; 1962 } 1963 else if (pmkFirst!=NULL && pmkRest==NULL){ 1964 *ppmkComposite=pmkFirst; 1965 IMoniker_AddRef(pmkFirst); 1966 return S_OK; 1967 } 1968 else if (pmkFirst==NULL && pmkRest==NULL) 1969 return S_OK; 1970 1971 hr = CompositeMonikerImpl_Construct(&moniker,pmkFirst,pmkRest); 1972 1973 if (FAILED(hr)) 1974 return hr; 1975 1976 hr = IMoniker_QueryInterface(moniker,&IID_IMoniker,(void**)ppmkComposite); 1977 IMoniker_Release(moniker); 1978 1979 return hr; 1980 } 1981 1982 /****************************************************************************** 1983 * MonikerCommonPrefixWith [OLE32.@] 1984 ******************************************************************************/ 1985 HRESULT WINAPI 1986 MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon) 1987 { 1988 FIXME("(),stub!\n"); 1989 return E_NOTIMPL; 1990 } 1991 1992 HRESULT WINAPI CompositeMoniker_CreateInstance(IClassFactory *iface, 1993 IUnknown *pUnk, REFIID riid, void **ppv) 1994 { 1995 IMoniker* pMoniker; 1996 HRESULT hr; 1997 1998 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv); 1999 2000 *ppv = NULL; 2001 2002 if (pUnk) 2003 return CLASS_E_NOAGGREGATION; 2004 2005 hr = CompositeMonikerImpl_Construct(&pMoniker, NULL, NULL); 2006 2007 if (SUCCEEDED(hr)) 2008 { 2009 hr = IMoniker_QueryInterface(pMoniker, riid, ppv); 2010 IMoniker_Release(pMoniker); 2011 } 2012 2013 return hr; 2014 } 2015