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