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