2 * CompositeMonikers implementation
4 * Copyright 1999 Noomen Hamza
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
33 #include "wine/debug.h"
34 #include "wine/unicode.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ole);
40 const CLSID CLSID_CompositeMoniker = {
41 0x309, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
44 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
46 /* CompositeMoniker data structure */
47 typedef struct CompositeMonikerImpl{
49 IMonikerVtbl* lpvtbl1; /* VTable relative to the IMoniker interface.*/
51 /* The ROT (RunningObjectTable implementation) uses the IROTData
52 * interface to test whether two monikers are equal. That's why IROTData
53 * interface is implemented by monikers.
55 IROTDataVtbl* lpvtbl2; /* VTable relative to the IROTData interface.*/
57 ULONG ref; /* reference counter for this object */
59 IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */
61 ULONG tabSize; /* size of tabMoniker */
63 ULONG tabLastIndex; /* first free index in tabMoniker */
65 } CompositeMonikerImpl;
68 /* EnumMoniker data structure */
69 typedef struct EnumMonikerImpl{
71 IEnumMonikerVtbl *lpVtbl; /* VTable relative to the IEnumMoniker interface.*/
73 ULONG ref; /* reference counter for this object */
75 IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
77 ULONG tabSize; /* size of tabMoniker */
79 ULONG currentPos; /* index pointer on the current moniker */
84 static HRESULT EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
86 /*******************************************************************************
87 * CompositeMoniker_QueryInterface
88 *******************************************************************************/
90 CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
92 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
94 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
96 /* Perform a sanity check on the parameters.*/
97 if ( (This==0) || (ppvObject==0) )
100 /* Initialize the return parameter */
103 /* Compare the riid with the interface IDs implemented by this object.*/
104 if (IsEqualIID(&IID_IUnknown, riid) ||
105 IsEqualIID(&IID_IPersist, riid) ||
106 IsEqualIID(&IID_IPersistStream, riid) ||
107 IsEqualIID(&IID_IMoniker, riid)
110 else if (IsEqualIID(&IID_IROTData, riid))
111 *ppvObject = (IROTData*)&(This->lpvtbl2);
113 /* Check that we obtained an interface.*/
115 return E_NOINTERFACE;
117 /* Query Interface always increases the reference count by one when it is successful */
118 IMoniker_AddRef(iface);
123 /******************************************************************************
124 * CompositeMoniker_AddRef
125 ******************************************************************************/
127 CompositeMonikerImpl_AddRef(IMoniker* iface)
129 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
131 TRACE("(%p)\n",This);
133 return InterlockedIncrement(&This->ref);
136 /******************************************************************************
137 * CompositeMoniker_Release
138 ******************************************************************************/
140 CompositeMonikerImpl_Release(IMoniker* iface)
142 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
146 TRACE("(%p)\n",This);
148 ref = InterlockedDecrement(&This->ref);
150 /* destroy the object if there's no more reference on it */
153 /* release all the components before destroying this object */
154 for (i=0;i<This->tabLastIndex;i++)
155 IMoniker_Release(This->tabMoniker[i]);
157 HeapFree(GetProcessHeap(),0,This->tabMoniker);
158 HeapFree(GetProcessHeap(),0,This);
163 /******************************************************************************
164 * CompositeMoniker_GetClassID
165 ******************************************************************************/
166 static HRESULT WINAPI
167 CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
169 TRACE("(%p,%p),stub!\n",iface,pClassID);
174 *pClassID = CLSID_CompositeMoniker;
179 /******************************************************************************
180 * CompositeMoniker_IsDirty
181 ******************************************************************************/
182 static HRESULT WINAPI
183 CompositeMonikerImpl_IsDirty(IMoniker* iface)
185 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
186 method in the OLE-provided moniker interfaces always return S_FALSE because
187 their internal state never changes. */
189 TRACE("(%p)\n",iface);
194 /******************************************************************************
195 * CompositeMoniker_Load
196 ******************************************************************************/
197 static HRESULT WINAPI
198 CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
205 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
207 TRACE("(%p,%p)\n",iface,pStm);
209 /* this function call OleLoadFromStream function for each moniker within this object */
211 /* read the a constant written by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
212 res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
214 if (SUCCEEDED(res)&& constant!=3)
219 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
221 res=ReadClassStm(pStm,&clsid);
222 DPRINTF("res=%ld",res);
226 if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
227 res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
230 res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
234 else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
235 CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
238 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
242 else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
243 CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
246 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
250 else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
256 /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */
261 /* resize the table if needed */
262 if (++This->tabLastIndex==This->tabSize){
264 This->tabSize+=BLOCK_TAB_SIZE;
265 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
267 if (This->tabMoniker==NULL)
268 return E_OUTOFMEMORY;
275 /******************************************************************************
276 * CompositeMoniker_Save
277 ******************************************************************************/
278 static HRESULT WINAPI
279 CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
282 IEnumMoniker *enumMk;
286 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
288 /* This function calls OleSaveToStream function for each moniker within
290 * When I tested this function in windows, I usually found this constant
291 * at the beginning of the stream. I don't known why (there's no
292 * indication in the specification) !
294 res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
296 IMoniker_Enum(iface,TRUE,&enumMk);
298 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
300 res=OleSaveToStream((IPersistStream*)pmk,pStm);
302 IMoniker_Release(pmk);
306 IEnumMoniker_Release(pmk);
311 IEnumMoniker_Release(enumMk);
316 /******************************************************************************
317 * CompositeMoniker_GetSizeMax
318 ******************************************************************************/
319 static HRESULT WINAPI
320 CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
322 IEnumMoniker *enumMk;
324 ULARGE_INTEGER ptmpSize;
326 /* The sizeMax of this object is calculated by calling GetSizeMax on
327 * each moniker within this object then summing all returned values
330 TRACE("(%p,%p)\n",iface,pcbSize);
335 pcbSize->u.LowPart =0;
336 pcbSize->u.HighPart=0;
338 IMoniker_Enum(iface,TRUE,&enumMk);
340 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)){
342 IMoniker_GetSizeMax(pmk,&ptmpSize);
344 IMoniker_Release(pmk);
346 pcbSize->u.LowPart +=ptmpSize.u.LowPart;
347 pcbSize->u.HighPart+=ptmpSize.u.HighPart;
350 IEnumMoniker_Release(enumMk);
355 /******************************************************************************
356 * CompositeMoniker_BindToObject
357 ******************************************************************************/
358 static HRESULT WINAPI
359 CompositeMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc,
360 IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult)
363 IRunningObjectTable *prot;
364 IMoniker *tempMk,*antiMk,*mostRigthMk;
365 IEnumMoniker *enumMoniker;
367 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
373 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
374 /* object for the requested interface pointer. */
377 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
381 /* if the requested class was loaded before ! we don't need to reload it */
382 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
389 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
390 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
392 IMoniker_Enum(iface,FALSE,&enumMoniker);
393 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
394 IEnumMoniker_Release(enumMoniker);
396 res=CreateAntiMoniker(&antiMk);
397 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
398 IMoniker_Release(antiMk);
400 res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
402 IMoniker_Release(tempMk);
403 IMoniker_Release(mostRigthMk);
409 /******************************************************************************
410 * CompositeMoniker_BindToStorage
411 ******************************************************************************/
412 static HRESULT WINAPI
413 CompositeMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc,
414 IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult)
417 IMoniker *tempMk,*antiMk,*mostRigthMk;
418 IEnumMoniker *enumMoniker;
420 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
424 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
425 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
427 if (pmkToLeft!=NULL){
429 IMoniker_Enum(iface,FALSE,&enumMoniker);
430 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
431 IEnumMoniker_Release(enumMoniker);
433 res=CreateAntiMoniker(&antiMk);
434 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
435 IMoniker_Release(antiMk);
437 res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
439 IMoniker_Release(tempMk);
441 IMoniker_Release(mostRigthMk);
446 return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
449 /******************************************************************************
450 * CompositeMoniker_Reduce
451 ******************************************************************************/
452 static HRESULT WINAPI
453 CompositeMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
454 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
457 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
458 IEnumMoniker *enumMoniker;
460 TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
462 if (ppmkReduced==NULL)
465 /* This method recursively calls Reduce for each of its component monikers. */
467 if (ppmkToLeft==NULL){
469 IMoniker_Enum(iface,FALSE,&enumMoniker);
470 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
471 IEnumMoniker_Release(enumMoniker);
473 res=CreateAntiMoniker(&antiMk);
474 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
475 IMoniker_Release(antiMk);
477 return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
479 else if (*ppmkToLeft==NULL)
481 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
485 /* separate the composite moniker in to left and right moniker */
486 IMoniker_Enum(iface,FALSE,&enumMoniker);
487 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
488 IEnumMoniker_Release(enumMoniker);
490 res=CreateAntiMoniker(&antiMk);
491 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
492 IMoniker_Release(antiMk);
494 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
495 /* of the reduced components */
496 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
497 CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
500 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
503 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
505 IMoniker_AddRef(iface);
509 return MK_S_REDUCED_TO_SELF;
514 /******************************************************************************
515 * CompositeMoniker_ComposeWith
516 ******************************************************************************/
517 static HRESULT WINAPI
518 CompositeMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
519 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
521 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
523 if ((ppmkComposite==NULL)||(pmkRight==NULL))
528 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
529 /* otherwise, the method returns the result of combining the two monikers by calling the */
530 /* CreateGenericComposite function */
532 if (fOnlyIfNotGeneric)
533 return MK_E_NEEDGENERIC;
535 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
538 /******************************************************************************
539 * CompositeMoniker_Enum
540 ******************************************************************************/
541 static HRESULT WINAPI
542 CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
544 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
546 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
548 if (ppenumMoniker == NULL)
551 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
554 /******************************************************************************
555 * CompositeMoniker_IsEqual
556 ******************************************************************************/
557 static HRESULT WINAPI
558 CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
560 IEnumMoniker *enumMoniker1,*enumMoniker2;
561 IMoniker *tempMk1,*tempMk2;
562 HRESULT res1,res2,res;
564 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
566 if (pmkOtherMoniker==NULL)
569 /* This method returns S_OK if the components of both monikers are equal when compared in the */
570 /* left-to-right order.*/
571 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
573 if (enumMoniker1==NULL)
576 IMoniker_Enum(iface,TRUE,&enumMoniker2);
580 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
581 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
583 if((res1==S_OK)&&(res2==S_OK)){
585 if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
592 else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
602 IMoniker_Release(tempMk1);
605 IMoniker_Release(tempMk2);
608 IEnumMoniker_Release(enumMoniker1);
609 IEnumMoniker_Release(enumMoniker2);
613 /******************************************************************************
614 * CompositeMoniker_Hash
615 ******************************************************************************/
616 static HRESULT WINAPI
617 CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
624 /******************************************************************************
625 * CompositeMoniker_IsRunning
626 ******************************************************************************/
627 static HRESULT WINAPI
628 CompositeMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc,
629 IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning)
631 IRunningObjectTable* rot;
633 IMoniker *tempMk,*antiMk,*mostRigthMk;
634 IEnumMoniker *enumMoniker;
636 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
638 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
639 if (pmkToLeft!=NULL){
641 CreateGenericComposite(pmkToLeft,iface,&tempMk);
643 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
645 IMoniker_Release(tempMk);
650 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
651 /* to this moniker */
653 if (pmkNewlyRunning!=NULL)
655 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
666 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
667 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
668 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
669 /* the composite as the pmkToLeft parameter for that call. */
671 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
676 res = IRunningObjectTable_IsRunning(rot,iface);
677 IRunningObjectTable_Release(rot);
684 IMoniker_Enum(iface,FALSE,&enumMoniker);
685 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
686 IEnumMoniker_Release(enumMoniker);
688 res=CreateAntiMoniker(&antiMk);
689 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
690 IMoniker_Release(antiMk);
692 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
694 IMoniker_Release(tempMk);
695 IMoniker_Release(mostRigthMk);
702 /******************************************************************************
703 * CompositeMoniker_GetTimeOfLastChange
704 ******************************************************************************/
705 static HRESULT WINAPI
706 CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
707 IMoniker* pmkToLeft, FILETIME* pCompositeTime)
709 IRunningObjectTable* rot;
711 IMoniker *tempMk,*antiMk,*mostRigthMk;
712 IEnumMoniker *enumMoniker;
714 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
716 if (pCompositeTime==NULL)
719 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
720 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
721 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
722 /* of the composite as the pmkToLeft parameter for that call. */
723 if (pmkToLeft!=NULL){
725 res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
727 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
732 if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
736 IMoniker_Enum(iface,FALSE,&enumMoniker);
737 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
738 IEnumMoniker_Release(enumMoniker);
740 res=CreateAntiMoniker(&antiMk);
741 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
742 IMoniker_Release(antiMk);
744 res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
746 IMoniker_Release(tempMk);
747 IMoniker_Release(mostRigthMk);
752 return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
755 /******************************************************************************
756 * CompositeMoniker_Inverse
757 ******************************************************************************/
758 static HRESULT WINAPI
759 CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
762 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
763 IEnumMoniker *enumMoniker;
765 TRACE("(%p,%p)\n",iface,ppmk);
770 /* This method returns a composite moniker that consists of the inverses of each of the components */
771 /* of the original composite, stored in reverse order */
773 res=CreateAntiMoniker(&antiMk);
774 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
775 IMoniker_Release(antiMk);
779 return IMoniker_Inverse(iface,ppmk);
783 IMoniker_Enum(iface,FALSE,&enumMoniker);
784 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
785 IEnumMoniker_Release(enumMoniker);
787 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
788 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
790 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
792 IMoniker_Release(tempMk);
793 IMoniker_Release(mostRigthMk);
794 IMoniker_Release(tempInvMk);
795 IMoniker_Release(mostRigthInvMk);
801 /******************************************************************************
802 * CompositeMoniker_CommonPrefixWith
803 ******************************************************************************/
804 static HRESULT WINAPI
805 CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface, IMoniker* pmkOther,
806 IMoniker** ppmkPrefix)
810 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
811 IEnumMoniker *enumMoniker1,*enumMoniker2;
812 ULONG i,nbCommonMk=0;
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. */
818 if (ppmkPrefix==NULL)
824 return MK_E_NOPREFIX;
826 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
828 if((mkSys==MKSYS_GENERICCOMPOSITE)){
830 IMoniker_Enum(iface,TRUE,&enumMoniker1);
831 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
835 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
836 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
838 if ((res1==S_FALSE) && (res2==S_FALSE)){
840 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
842 IMoniker_AddRef(iface);
845 else if ((res1==S_OK) && (res2==S_OK)){
847 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
855 else if (res1==S_OK){
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;
863 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
864 /* to this moniker. */
870 IEnumMoniker_Release(enumMoniker1);
871 IEnumMoniker_Release(enumMoniker2);
873 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
875 return MK_E_NOPREFIX;
877 IEnumMoniker_Reset(enumMoniker1);
879 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
881 /* if we have more than one commun moniker the result will be a composite moniker */
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);
890 /* compose all common monikers in a composite moniker */
891 for(i=0;i<nbCommonMk;i++){
893 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
895 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
897 IMoniker_Release(*ppmkPrefix);
899 IMoniker_Release(tempMk1);
906 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
913 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
916 IMoniker_Enum(iface,TRUE,&enumMoniker1);
918 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
920 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
922 *ppmkPrefix=pmkOther;
927 return MK_E_NOPREFIX;
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)
937 IMoniker *tempMk,*tempMk1,*tempMk2;
938 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
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);
950 IMoniker_IsSystemMoniker(commonMk,&mkSys);
952 if (mkSys==MKSYS_GENERICCOMPOSITE){
954 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
957 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
958 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
960 if ((res1==S_FALSE)||(res2==S_FALSE)){
966 IMoniker_Release(tempMk1);
967 IMoniker_Release(tempMk1);
971 IMoniker_Release(tempMk1);
972 IMoniker_Release(tempMk1);
976 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
977 IMoniker_Release(tempMk1);
980 /* count the number of elements in the enumerator after the common prefix */
981 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
983 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
985 IMoniker_Release(tempMk);
990 /* create a generic composite moniker with monikers located after the common prefix */
991 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1000 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1002 CreateGenericComposite(tempMk1,tempMk2,restMk);
1004 IMoniker_Release(tempMk1);
1006 IMoniker_Release(tempMk2);
1008 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1010 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1012 IMoniker_Release(tempMk1);
1014 IMoniker_Release(*restMk);
1021 /******************************************************************************
1022 * CompositeMoniker_RelativePathTo
1023 ******************************************************************************/
1024 static HRESULT WINAPI
1025 CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther,
1026 IMoniker** ppmkRelPath)
1029 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1031 TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1033 if (ppmkRelPath==NULL)
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. */
1042 /* finds the common prefix of the two monikers */
1043 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
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)){
1048 *ppmkRelPath=pmkOther;
1049 IMoniker_AddRef(pmkOther);
1053 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1054 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
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 */
1060 IMoniker_Inverse(restThisMk,ppmkRelPath);
1061 IMoniker_Release(restThisMk);
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){
1067 *ppmkRelPath=restOtherMk;
1068 IMoniker_AddRef(restOtherMk);
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){
1074 IMoniker_Inverse(restThisMk,&invRestThisMk);
1075 IMoniker_Release(restThisMk);
1076 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1077 IMoniker_Release(invRestThisMk);
1078 IMoniker_Release(restOtherMk);
1083 /******************************************************************************
1084 * CompositeMoniker_GetDisplayName
1085 ******************************************************************************/
1086 static HRESULT WINAPI
1087 CompositeMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
1088 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
1091 IEnumMoniker *enumMoniker;
1095 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1097 if (ppszDisplayName==NULL)
1100 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1102 if (*ppszDisplayName==NULL)
1103 return E_OUTOFMEMORY;
1105 /* This method returns the concatenation of the display names returned by each component moniker of */
1108 **ppszDisplayName=0;
1110 IMoniker_Enum(iface,TRUE,&enumMoniker);
1112 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1114 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1116 lengthStr+=lstrlenW(tempStr);
1118 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1120 if (*ppszDisplayName==NULL)
1121 return E_OUTOFMEMORY;
1123 strcatW(*ppszDisplayName,tempStr);
1125 CoTaskMemFree(tempStr);
1126 IMoniker_Release(tempMk);
1129 IEnumMoniker_Release(enumMoniker);
1134 /******************************************************************************
1135 * CompositeMoniker_ParseDisplayName
1136 ******************************************************************************/
1137 static HRESULT WINAPI
1138 CompositeMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,
1139 IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten,
1142 IEnumMoniker *enumMoniker;
1143 IMoniker *tempMk,*mostRigthMk,*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. */
1147 /* get the most right moniker */
1148 IMoniker_Enum(iface,FALSE,&enumMoniker);
1149 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1150 IEnumMoniker_Release(enumMoniker);
1152 /* get the left moniker */
1153 CreateAntiMoniker(&antiMk);
1154 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1155 IMoniker_Release(antiMk);
1157 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1160 /******************************************************************************
1161 * CompositeMoniker_IsSystemMoniker
1162 ******************************************************************************/
1163 static HRESULT WINAPI
1164 CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1166 TRACE("(%p,%p)\n",iface,pwdMksys);
1171 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1176 /*******************************************************************************
1177 * CompositeMonikerIROTData_QueryInterface
1178 *******************************************************************************/
1179 static HRESULT WINAPI
1180 CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,
1184 ICOM_THIS_From_IROTData(IMoniker, iface);
1186 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
1188 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1191 /***********************************************************************
1192 * CompositeMonikerIROTData_AddRef
1195 CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1197 ICOM_THIS_From_IROTData(IMoniker, iface);
1199 TRACE("(%p)\n",iface);
1201 return IMoniker_AddRef(This);
1204 /***********************************************************************
1205 * CompositeMonikerIROTData_Release
1207 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1209 ICOM_THIS_From_IROTData(IMoniker, iface);
1211 TRACE("(%p)\n",iface);
1213 return IMoniker_Release(This);
1216 /******************************************************************************
1217 * CompositeMonikerIROTData_GetComparaisonData
1218 ******************************************************************************/
1219 static HRESULT WINAPI
1220 CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1221 BYTE* pbData, ULONG cbMax, ULONG* pcbData)
1223 FIXME("(),stub!\n");
1227 /******************************************************************************
1228 * EnumMonikerImpl_QueryInterface
1229 ******************************************************************************/
1230 static HRESULT WINAPI
1231 EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1233 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1235 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1237 /* Perform a sanity check on the parameters.*/
1238 if ( (This==0) || (ppvObject==0) )
1239 return E_INVALIDARG;
1241 /* Initialize the return parameter */
1244 /* Compare the riid with the interface IDs implemented by this object.*/
1245 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1248 /* Check that we obtained an interface.*/
1249 if ((*ppvObject)==0)
1250 return E_NOINTERFACE;
1252 /* Query Interface always increases the reference count by one when it is successful */
1253 IEnumMoniker_AddRef(iface);
1258 /******************************************************************************
1259 * EnumMonikerImpl_AddRef
1260 ******************************************************************************/
1262 EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1264 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1266 TRACE("(%p)\n",This);
1268 return InterlockedIncrement(&This->ref);
1272 /******************************************************************************
1273 * EnumMonikerImpl_Release
1274 ******************************************************************************/
1276 EnumMonikerImpl_Release(IEnumMoniker* iface)
1278 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1281 TRACE("(%p)\n",This);
1283 ref = InterlockedDecrement(&This->ref);
1285 /* destroy the object if there's no more reference on it */
1288 for(i=0;i<This->tabSize;i++)
1289 IMoniker_Release(This->tabMoniker[i]);
1291 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1292 HeapFree(GetProcessHeap(),0,This);
1297 /******************************************************************************
1298 * EnumMonikerImpl_Next
1299 ******************************************************************************/
1300 static HRESULT WINAPI
1301 EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt,
1304 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1307 /* retrieve the requested number of moniker from the current position */
1308 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1310 rgelt[i]=This->tabMoniker[This->currentPos++];
1312 if (pceltFethed!=NULL)
1321 /******************************************************************************
1322 * EnumMonikerImpl_Skip
1323 ******************************************************************************/
1324 static HRESULT WINAPI
1325 EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt)
1327 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1329 if ((This->currentPos+celt) >= This->tabSize)
1332 This->currentPos+=celt;
1337 /******************************************************************************
1338 * EnumMonikerImpl_Reset
1339 ******************************************************************************/
1340 static HRESULT WINAPI
1341 EnumMonikerImpl_Reset(IEnumMoniker* iface)
1344 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1351 /******************************************************************************
1352 * EnumMonikerImpl_Clone
1353 ******************************************************************************/
1354 static HRESULT WINAPI
1355 EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum)
1357 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1359 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1362 /********************************************************************************/
1363 /* Virtual function table for the IROTData class */
1364 static IEnumMonikerVtbl VT_EnumMonikerImpl =
1366 EnumMonikerImpl_QueryInterface,
1367 EnumMonikerImpl_AddRef,
1368 EnumMonikerImpl_Release,
1369 EnumMonikerImpl_Next,
1370 EnumMonikerImpl_Skip,
1371 EnumMonikerImpl_Reset,
1372 EnumMonikerImpl_Clone
1375 /******************************************************************************
1376 * EnumMonikerImpl_CreateEnumMoniker
1377 ******************************************************************************/
1379 EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker, ULONG tabSize,
1380 ULONG currentPos, BOOL leftToRigth, IEnumMoniker ** ppmk)
1382 EnumMonikerImpl* newEnumMoniker;
1385 if (currentPos > tabSize)
1386 return E_INVALIDARG;
1388 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1390 if (newEnumMoniker == 0)
1391 return STG_E_INSUFFICIENTMEMORY;
1393 /* Initialize the virtual function table. */
1394 newEnumMoniker->lpVtbl = &VT_EnumMonikerImpl;
1395 newEnumMoniker->ref = 0;
1397 newEnumMoniker->tabSize=tabSize;
1398 newEnumMoniker->currentPos=currentPos;
1400 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1402 if (newEnumMoniker->tabMoniker==NULL) {
1403 HeapFree(GetProcessHeap(), 0, newEnumMoniker);
1404 return E_OUTOFMEMORY;
1408 for (i=0;i<tabSize;i++){
1410 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1411 IMoniker_AddRef(tabMoniker[i]);
1414 for (i=tabSize-1;i>=0;i--){
1416 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1417 IMoniker_AddRef(tabMoniker[i]);
1420 *ppmk=(IEnumMoniker*)newEnumMoniker;
1425 /********************************************************************************/
1426 /* Virtual function table for the CompositeMonikerImpl class which includes */
1427 /* IPersist, IPersistStream and IMoniker functions. */
1429 static IMonikerVtbl VT_CompositeMonikerImpl =
1431 CompositeMonikerImpl_QueryInterface,
1432 CompositeMonikerImpl_AddRef,
1433 CompositeMonikerImpl_Release,
1434 CompositeMonikerImpl_GetClassID,
1435 CompositeMonikerImpl_IsDirty,
1436 CompositeMonikerImpl_Load,
1437 CompositeMonikerImpl_Save,
1438 CompositeMonikerImpl_GetSizeMax,
1439 CompositeMonikerImpl_BindToObject,
1440 CompositeMonikerImpl_BindToStorage,
1441 CompositeMonikerImpl_Reduce,
1442 CompositeMonikerImpl_ComposeWith,
1443 CompositeMonikerImpl_Enum,
1444 CompositeMonikerImpl_IsEqual,
1445 CompositeMonikerImpl_Hash,
1446 CompositeMonikerImpl_IsRunning,
1447 CompositeMonikerImpl_GetTimeOfLastChange,
1448 CompositeMonikerImpl_Inverse,
1449 CompositeMonikerImpl_CommonPrefixWith,
1450 CompositeMonikerImpl_RelativePathTo,
1451 CompositeMonikerImpl_GetDisplayName,
1452 CompositeMonikerImpl_ParseDisplayName,
1453 CompositeMonikerImpl_IsSystemMoniker
1456 /********************************************************************************/
1457 /* Virtual function table for the IROTData class. */
1458 static IROTDataVtbl VT_ROTDataImpl =
1460 CompositeMonikerROTDataImpl_QueryInterface,
1461 CompositeMonikerROTDataImpl_AddRef,
1462 CompositeMonikerROTDataImpl_Release,
1463 CompositeMonikerROTDataImpl_GetComparaisonData
1466 /******************************************************************************
1467 * Composite-Moniker_Construct (local function)
1468 *******************************************************************************/
1470 CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,
1471 LPMONIKER pmkFirst, LPMONIKER pmkRest)
1474 IEnumMoniker *enumMoniker;
1478 TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
1480 /* Initialize the virtual function table. */
1481 This->lpvtbl1 = &VT_CompositeMonikerImpl;
1482 This->lpvtbl2 = &VT_ROTDataImpl;
1485 This->tabSize=BLOCK_TAB_SIZE;
1486 This->tabLastIndex=0;
1488 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
1489 if (This->tabMoniker==NULL)
1490 return E_OUTOFMEMORY;
1492 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
1494 /* put the first moniker contents in the beginning of the table */
1495 if (mkSys!=MKSYS_GENERICCOMPOSITE){
1497 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
1498 IMoniker_AddRef(pmkFirst);
1502 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
1504 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
1507 if (++This->tabLastIndex==This->tabSize){
1509 This->tabSize+=BLOCK_TAB_SIZE;
1510 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1512 if (This->tabMoniker==NULL)
1513 return E_OUTOFMEMORY;
1517 IEnumMoniker_Release(enumMoniker);
1520 /* put the rest moniker contents after the first one and make simplification if needed */
1522 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
1524 if (mkSys!=MKSYS_GENERICCOMPOSITE){
1526 /* add a simple moniker to the moniker table */
1528 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
1530 if (res==MK_E_NEEDGENERIC){
1532 /* there's no simplification in this case */
1533 This->tabMoniker[This->tabLastIndex]=pmkRest;
1535 This->tabLastIndex++;
1537 IMoniker_AddRef(pmkRest);
1539 else if (tempMk==NULL){
1541 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
1542 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1544 This->tabLastIndex--;
1546 else if (SUCCEEDED(res)){
1548 /* the non-generic composition was successful so we can make a simplification in this case */
1549 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1551 This->tabMoniker[This->tabLastIndex-1]=tempMk;
1555 /* resize tabMoniker if needed */
1556 if (This->tabLastIndex==This->tabSize){
1558 This->tabSize+=BLOCK_TAB_SIZE;
1560 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1562 if (This->tabMoniker==NULL)
1563 return E_OUTOFMEMORY;
1568 /* add a composite moniker to the moniker table (do the same thing
1569 * for each moniker within the composite moniker as a simple moniker
1570 * (see above for how to add a simple moniker case) )
1572 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
1574 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
1576 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
1578 if (res==MK_E_NEEDGENERIC){
1580 This->tabLastIndex++;
1582 else if (tempMk==NULL){
1584 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1585 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
1586 This->tabLastIndex--;
1590 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1592 This->tabMoniker[This->tabLastIndex-1]=tempMk;
1595 if (This->tabLastIndex==This->tabSize){
1597 This->tabSize+=BLOCK_TAB_SIZE;
1599 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1601 if (This->tabMoniker==NULL)
1602 return E_OUTOFMEMORY;
1606 IEnumMoniker_Release(enumMoniker);
1612 /******************************************************************************
1613 * CreateGenericComposite [OLE32.@]
1614 ******************************************************************************/
1616 CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest,
1617 LPMONIKER* ppmkComposite)
1619 CompositeMonikerImpl* newCompositeMoniker = 0;
1622 TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1624 if (ppmkComposite==NULL)
1629 if (pmkFirst==NULL && pmkRest!=NULL){
1631 *ppmkComposite=pmkRest;
1634 else if (pmkFirst!=NULL && pmkRest==NULL){
1635 *ppmkComposite=pmkFirst;
1638 else if (pmkFirst==NULL && pmkRest==NULL)
1641 newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
1643 if (newCompositeMoniker == 0)
1644 return STG_E_INSUFFICIENTMEMORY;
1646 hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
1650 HeapFree(GetProcessHeap(),0,newCompositeMoniker);
1653 if (newCompositeMoniker->tabLastIndex==1)
1655 hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
1658 hr = IMoniker_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
1663 /******************************************************************************
1664 * MonikerCommonPrefixWith [OLE32.@]
1665 ******************************************************************************/
1667 MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1669 FIXME("(),stub!\n");