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 static 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 const 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 const IROTDataVtbl
* lpvtbl2
; /* VTable relative to the IROTData interface.*/
57 LONG 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 const IEnumMonikerVtbl
*lpVtbl
; /* VTable relative to the IEnumMoniker interface.*/
73 LONG 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 */
83 static inline IMoniker
*impl_from_IROTData( IROTData
*iface
)
85 return (IMoniker
*)((char*)iface
- FIELD_OFFSET(CompositeMonikerImpl
, lpvtbl2
));
88 static HRESULT
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,ULONG tabSize
,ULONG currentPos
,BOOL leftToRigth
,IEnumMoniker
** ppmk
);
90 /*******************************************************************************
91 * CompositeMoniker_QueryInterface
92 *******************************************************************************/
94 CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
96 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
98 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
100 /* Perform a sanity check on the parameters.*/
101 if ( (This
==0) || (ppvObject
==0) )
104 /* Initialize the return parameter */
107 /* Compare the riid with the interface IDs implemented by this object.*/
108 if (IsEqualIID(&IID_IUnknown
, riid
) ||
109 IsEqualIID(&IID_IPersist
, riid
) ||
110 IsEqualIID(&IID_IPersistStream
, riid
) ||
111 IsEqualIID(&IID_IMoniker
, riid
)
114 else if (IsEqualIID(&IID_IROTData
, riid
))
115 *ppvObject
= (IROTData
*)&(This
->lpvtbl2
);
117 /* Check that we obtained an interface.*/
119 return E_NOINTERFACE
;
121 /* Query Interface always increases the reference count by one when it is successful */
122 IMoniker_AddRef(iface
);
127 /******************************************************************************
128 * CompositeMoniker_AddRef
129 ******************************************************************************/
131 CompositeMonikerImpl_AddRef(IMoniker
* iface
)
133 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
135 TRACE("(%p)\n",This
);
137 return InterlockedIncrement(&This
->ref
);
140 /******************************************************************************
141 * CompositeMoniker_Release
142 ******************************************************************************/
144 CompositeMonikerImpl_Release(IMoniker
* iface
)
146 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
150 TRACE("(%p)\n",This
);
152 ref
= InterlockedDecrement(&This
->ref
);
154 /* destroy the object if there's no more reference on it */
157 /* release all the components before destroying this object */
158 for (i
=0;i
<This
->tabLastIndex
;i
++)
159 IMoniker_Release(This
->tabMoniker
[i
]);
161 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
162 HeapFree(GetProcessHeap(),0,This
);
167 /******************************************************************************
168 * CompositeMoniker_GetClassID
169 ******************************************************************************/
170 static HRESULT WINAPI
171 CompositeMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
173 TRACE("(%p,%p),stub!\n",iface
,pClassID
);
178 *pClassID
= CLSID_CompositeMoniker
;
183 /******************************************************************************
184 * CompositeMoniker_IsDirty
185 ******************************************************************************/
186 static HRESULT WINAPI
187 CompositeMonikerImpl_IsDirty(IMoniker
* iface
)
189 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
190 method in the OLE-provided moniker interfaces always return S_FALSE because
191 their internal state never changes. */
193 TRACE("(%p)\n",iface
);
198 /******************************************************************************
199 * CompositeMoniker_Load
200 ******************************************************************************/
201 static HRESULT WINAPI
202 CompositeMonikerImpl_Load(IMoniker
* iface
,IStream
* pStm
)
209 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
211 TRACE("(%p,%p)\n",iface
,pStm
);
213 /* this function call OleLoadFromStream function for each moniker within this object */
215 /* read the a constant written by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
216 res
=IStream_Read(pStm
,&constant
,sizeof(DWORD
),NULL
);
218 if (SUCCEEDED(res
)&& constant
!=3)
223 res
=OleLoadFromStream(pStm
,&IID_IMoniker
,(void**)&This
->tabMoniker
[This
->tabLastIndex
]);
225 res
=ReadClassStm(pStm
,&clsid
);
226 DPRINTF("res=%ld",res
);
230 if (IsEqualIID(&clsid
,&CLSID_FileMoniker
)){
231 res
=CreateFileMoniker(string
,&This
->tabMoniker
[This
->tabLastIndex
]);
234 res
=IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
238 else if (IsEqualIID(&clsid
,&CLSID_ItemMoniker
)){
239 CreateItemMoniker(string
,string
,&This
->tabMoniker
[This
->tabLastIndex
]);
242 IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
246 else if (IsEqualIID(&clsid
,&CLSID_AntiMoniker
)){
247 CreateAntiMoniker(&This
->tabMoniker
[This
->tabLastIndex
]);
250 IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
254 else if (IsEqualIID(&clsid
,&CLSID_CompositeMoniker
))
260 /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */
265 /* resize the table if needed */
266 if (++This
->tabLastIndex
==This
->tabSize
){
268 This
->tabSize
+=BLOCK_TAB_SIZE
;
269 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
271 if (This
->tabMoniker
==NULL
)
272 return E_OUTOFMEMORY
;
279 /******************************************************************************
280 * CompositeMoniker_Save
281 ******************************************************************************/
282 static HRESULT WINAPI
283 CompositeMonikerImpl_Save(IMoniker
* iface
,IStream
* pStm
,BOOL fClearDirty
)
286 IEnumMoniker
*enumMk
;
290 TRACE("(%p,%p,%d)\n",iface
,pStm
,fClearDirty
);
292 /* This function calls OleSaveToStream function for each moniker within
294 * When I tested this function in windows, I usually found this constant
295 * at the beginning of the stream. I don't known why (there's no
296 * indication in the specification) !
298 res
=IStream_Write(pStm
,&constant
,sizeof(constant
),NULL
);
300 IMoniker_Enum(iface
,TRUE
,&enumMk
);
302 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
304 res
=OleSaveToStream((IPersistStream
*)pmk
,pStm
);
306 IMoniker_Release(pmk
);
310 IEnumMoniker_Release(pmk
);
315 IEnumMoniker_Release(enumMk
);
320 /******************************************************************************
321 * CompositeMoniker_GetSizeMax
322 ******************************************************************************/
323 static HRESULT WINAPI
324 CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
,ULARGE_INTEGER
* pcbSize
)
326 IEnumMoniker
*enumMk
;
328 ULARGE_INTEGER ptmpSize
;
330 /* The sizeMax of this object is calculated by calling GetSizeMax on
331 * each moniker within this object then summing all returned values
334 TRACE("(%p,%p)\n",iface
,pcbSize
);
339 pcbSize
->u
.LowPart
=0;
340 pcbSize
->u
.HighPart
=0;
342 IMoniker_Enum(iface
,TRUE
,&enumMk
);
344 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)){
346 IMoniker_GetSizeMax(pmk
,&ptmpSize
);
348 IMoniker_Release(pmk
);
350 pcbSize
->u
.LowPart
+=ptmpSize
.u
.LowPart
;
351 pcbSize
->u
.HighPart
+=ptmpSize
.u
.HighPart
;
354 IEnumMoniker_Release(enumMk
);
359 /******************************************************************************
360 * CompositeMoniker_BindToObject
361 ******************************************************************************/
362 static HRESULT WINAPI
363 CompositeMonikerImpl_BindToObject(IMoniker
* iface
, IBindCtx
* pbc
,
364 IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
)
367 IRunningObjectTable
*prot
;
368 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
369 IEnumMoniker
*enumMoniker
;
371 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
377 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
378 /* object for the requested interface pointer. */
381 res
=IBindCtx_GetRunningObjectTable(pbc
,&prot
);
385 /* if the requested class was loaded before ! we don't need to reload it */
386 res
= IRunningObjectTable_GetObject(prot
,iface
,(IUnknown
**)ppvResult
);
393 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
394 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
396 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
397 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
398 IEnumMoniker_Release(enumMoniker
);
400 res
=CreateAntiMoniker(&antiMk
);
401 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
402 IMoniker_Release(antiMk
);
404 res
=CompositeMonikerImpl_BindToObject(mostRigthMk
,pbc
,tempMk
,riid
,ppvResult
);
406 IMoniker_Release(tempMk
);
407 IMoniker_Release(mostRigthMk
);
413 /******************************************************************************
414 * CompositeMoniker_BindToStorage
415 ******************************************************************************/
416 static HRESULT WINAPI
417 CompositeMonikerImpl_BindToStorage(IMoniker
* iface
, IBindCtx
* pbc
,
418 IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
)
421 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
422 IEnumMoniker
*enumMoniker
;
424 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
428 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
429 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
431 if (pmkToLeft
!=NULL
){
433 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
434 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
435 IEnumMoniker_Release(enumMoniker
);
437 res
=CreateAntiMoniker(&antiMk
);
438 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
439 IMoniker_Release(antiMk
);
441 res
=CompositeMonikerImpl_BindToStorage(mostRigthMk
,pbc
,tempMk
,riid
,ppvResult
);
443 IMoniker_Release(tempMk
);
445 IMoniker_Release(mostRigthMk
);
450 return IMoniker_BindToStorage(iface
,pbc
,NULL
,riid
,ppvResult
);
453 /******************************************************************************
454 * CompositeMoniker_Reduce
455 ******************************************************************************/
456 static HRESULT WINAPI
457 CompositeMonikerImpl_Reduce(IMoniker
* iface
, IBindCtx
* pbc
, DWORD dwReduceHowFar
,
458 IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
)
461 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*leftReducedComposedMk
,*mostRigthReducedMk
;
462 IEnumMoniker
*enumMoniker
;
464 TRACE("(%p,%p,%ld,%p,%p)\n",iface
,pbc
,dwReduceHowFar
,ppmkToLeft
,ppmkReduced
);
466 if (ppmkReduced
==NULL
)
469 /* This method recursively calls Reduce for each of its component monikers. */
471 if (ppmkToLeft
==NULL
){
473 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
474 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
475 IEnumMoniker_Release(enumMoniker
);
477 res
=CreateAntiMoniker(&antiMk
);
478 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
479 IMoniker_Release(antiMk
);
481 return CompositeMonikerImpl_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
, ppmkReduced
);
483 else if (*ppmkToLeft
==NULL
)
485 return IMoniker_Reduce(iface
,pbc
,dwReduceHowFar
,NULL
,ppmkReduced
);
489 /* separate the composite moniker in to left and right moniker */
490 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
491 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
492 IEnumMoniker_Release(enumMoniker
);
494 res
=CreateAntiMoniker(&antiMk
);
495 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
496 IMoniker_Release(antiMk
);
498 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
499 /* of the reduced components */
500 if (IMoniker_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,NULL
,&mostRigthReducedMk
) &&
501 CompositeMonikerImpl_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
,&leftReducedComposedMk
)
504 return CreateGenericComposite(leftReducedComposedMk
,mostRigthReducedMk
,ppmkReduced
);
507 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
509 IMoniker_AddRef(iface
);
513 return MK_S_REDUCED_TO_SELF
;
518 /******************************************************************************
519 * CompositeMoniker_ComposeWith
520 ******************************************************************************/
521 static HRESULT WINAPI
522 CompositeMonikerImpl_ComposeWith(IMoniker
* iface
, IMoniker
* pmkRight
,
523 BOOL fOnlyIfNotGeneric
, IMoniker
** ppmkComposite
)
525 TRACE("(%p,%p,%d,%p)\n",iface
,pmkRight
,fOnlyIfNotGeneric
,ppmkComposite
);
527 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
532 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
533 /* otherwise, the method returns the result of combining the two monikers by calling the */
534 /* CreateGenericComposite function */
536 if (fOnlyIfNotGeneric
)
537 return MK_E_NEEDGENERIC
;
539 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
542 /******************************************************************************
543 * CompositeMoniker_Enum
544 ******************************************************************************/
545 static HRESULT WINAPI
546 CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
548 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
550 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
552 if (ppenumMoniker
== NULL
)
555 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabLastIndex
,0,fForward
,ppenumMoniker
);
558 /******************************************************************************
559 * CompositeMoniker_IsEqual
560 ******************************************************************************/
561 static HRESULT WINAPI
562 CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
)
564 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
565 IMoniker
*tempMk1
,*tempMk2
;
566 HRESULT res1
,res2
,res
;
568 TRACE("(%p,%p)\n",iface
,pmkOtherMoniker
);
570 if (pmkOtherMoniker
==NULL
)
573 /* This method returns S_OK if the components of both monikers are equal when compared in the */
574 /* left-to-right order.*/
575 IMoniker_Enum(pmkOtherMoniker
,TRUE
,&enumMoniker1
);
577 if (enumMoniker1
==NULL
)
580 IMoniker_Enum(iface
,TRUE
,&enumMoniker2
);
584 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
585 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
587 if((res1
==S_OK
)&&(res2
==S_OK
)){
589 if(IMoniker_IsEqual(tempMk1
,tempMk2
)==S_FALSE
){
596 else if ( (res1
==S_FALSE
) && (res2
==S_FALSE
) ){
606 IMoniker_Release(tempMk1
);
609 IMoniker_Release(tempMk2
);
612 IEnumMoniker_Release(enumMoniker1
);
613 IEnumMoniker_Release(enumMoniker2
);
617 /******************************************************************************
618 * CompositeMoniker_Hash
619 ******************************************************************************/
620 static HRESULT WINAPI
621 CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
623 IEnumMoniker
*enumMoniker
;
628 TRACE("(%p,%p)\n",iface
,pdwHash
);
633 res
= IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
638 res
=IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
);
642 res
= IMoniker_Hash(tempMk
, &tempHash
);
645 *pdwHash
= (*pdwHash
* 37) + tempHash
;
647 IMoniker_Release(tempMk
);
650 IEnumMoniker_Release(enumMoniker
);
655 /******************************************************************************
656 * CompositeMoniker_IsRunning
657 ******************************************************************************/
658 static HRESULT WINAPI
659 CompositeMonikerImpl_IsRunning(IMoniker
* iface
, IBindCtx
* pbc
,
660 IMoniker
* pmkToLeft
, IMoniker
* pmkNewlyRunning
)
662 IRunningObjectTable
* rot
;
664 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
665 IEnumMoniker
*enumMoniker
;
667 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
669 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
670 if (pmkToLeft
!=NULL
){
672 CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
674 res
= IMoniker_IsRunning(tempMk
,pbc
,NULL
,pmkNewlyRunning
);
676 IMoniker_Release(tempMk
);
681 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
682 /* to this moniker */
684 if (pmkNewlyRunning
!=NULL
)
686 if (IMoniker_IsEqual(iface
,pmkNewlyRunning
)==S_OK
)
697 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
698 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
699 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
700 /* the composite as the pmkToLeft parameter for that call. */
702 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
707 res
= IRunningObjectTable_IsRunning(rot
,iface
);
708 IRunningObjectTable_Release(rot
);
715 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
716 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
717 IEnumMoniker_Release(enumMoniker
);
719 res
=CreateAntiMoniker(&antiMk
);
720 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
721 IMoniker_Release(antiMk
);
723 res
=IMoniker_IsRunning(mostRigthMk
,pbc
,tempMk
,pmkNewlyRunning
);
725 IMoniker_Release(tempMk
);
726 IMoniker_Release(mostRigthMk
);
733 /******************************************************************************
734 * CompositeMoniker_GetTimeOfLastChange
735 ******************************************************************************/
736 static HRESULT WINAPI
737 CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
, IBindCtx
* pbc
,
738 IMoniker
* pmkToLeft
, FILETIME
* pCompositeTime
)
740 IRunningObjectTable
* rot
;
742 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
743 IEnumMoniker
*enumMoniker
;
745 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pCompositeTime
);
747 if (pCompositeTime
==NULL
)
750 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
751 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
752 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
753 /* of the composite as the pmkToLeft parameter for that call. */
754 if (pmkToLeft
!=NULL
){
756 res
=CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
758 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
763 if (IRunningObjectTable_GetTimeOfLastChange(rot
,tempMk
,pCompositeTime
)==S_OK
)
767 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
768 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
769 IEnumMoniker_Release(enumMoniker
);
771 res
=CreateAntiMoniker(&antiMk
);
772 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
773 IMoniker_Release(antiMk
);
775 res
=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk
,pbc
,tempMk
,pCompositeTime
);
777 IMoniker_Release(tempMk
);
778 IMoniker_Release(mostRigthMk
);
783 return IMoniker_GetTimeOfLastChange(iface
,pbc
,NULL
,pCompositeTime
);
786 /******************************************************************************
787 * CompositeMoniker_Inverse
788 ******************************************************************************/
789 static HRESULT WINAPI
790 CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
793 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*tempInvMk
,*mostRigthInvMk
;
794 IEnumMoniker
*enumMoniker
;
796 TRACE("(%p,%p)\n",iface
,ppmk
);
801 /* This method returns a composite moniker that consists of the inverses of each of the components */
802 /* of the original composite, stored in reverse order */
804 res
=CreateAntiMoniker(&antiMk
);
805 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
806 IMoniker_Release(antiMk
);
810 return IMoniker_Inverse(iface
,ppmk
);
814 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
815 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
816 IEnumMoniker_Release(enumMoniker
);
818 IMoniker_Inverse(mostRigthMk
,&mostRigthInvMk
);
819 CompositeMonikerImpl_Inverse(tempMk
,&tempInvMk
);
821 res
=CreateGenericComposite(mostRigthInvMk
,tempInvMk
,ppmk
);
823 IMoniker_Release(tempMk
);
824 IMoniker_Release(mostRigthMk
);
825 IMoniker_Release(tempInvMk
);
826 IMoniker_Release(mostRigthInvMk
);
832 /******************************************************************************
833 * CompositeMoniker_CommonPrefixWith
834 ******************************************************************************/
835 static HRESULT WINAPI
836 CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
, IMoniker
* pmkOther
,
837 IMoniker
** ppmkPrefix
)
841 IMoniker
*tempMk1
,*tempMk2
,*mostLeftMk1
,*mostLeftMk2
;
842 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
843 ULONG i
,nbCommonMk
=0;
845 /* If the other moniker is a composite, this method compares the components of each composite from left */
846 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
847 /* of the leftmost components were common to both monikers. */
849 if (ppmkPrefix
==NULL
)
855 return MK_E_NOPREFIX
;
857 IMoniker_IsSystemMoniker(pmkOther
,&mkSys
);
859 if((mkSys
==MKSYS_GENERICCOMPOSITE
)){
861 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
862 IMoniker_Enum(pmkOther
,TRUE
,&enumMoniker2
);
866 res1
=IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
867 res2
=IEnumMoniker_Next(enumMoniker2
,1,&mostLeftMk2
,NULL
);
869 if ((res1
==S_FALSE
) && (res2
==S_FALSE
)){
871 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
873 IMoniker_AddRef(iface
);
876 else if ((res1
==S_OK
) && (res2
==S_OK
)){
878 if (IMoniker_IsEqual(mostLeftMk1
,mostLeftMk2
)==S_OK
)
886 else if (res1
==S_OK
){
888 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
889 /* ppmkPrefix to the other moniker. */
890 *ppmkPrefix
=pmkOther
;
894 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
895 /* to this moniker. */
901 IEnumMoniker_Release(enumMoniker1
);
902 IEnumMoniker_Release(enumMoniker2
);
904 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
906 return MK_E_NOPREFIX
;
908 IEnumMoniker_Reset(enumMoniker1
);
910 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
912 /* if we have more than one commun moniker the result will be a composite moniker */
915 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
916 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
917 CreateGenericComposite(tempMk1
,tempMk2
,ppmkPrefix
);
918 IMoniker_Release(tempMk1
);
919 IMoniker_Release(tempMk2
);
921 /* compose all common monikers in a composite moniker */
922 for(i
=0;i
<nbCommonMk
;i
++){
924 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
926 CreateGenericComposite(*ppmkPrefix
,tempMk1
,&tempMk2
);
928 IMoniker_Release(*ppmkPrefix
);
930 IMoniker_Release(tempMk1
);
937 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
944 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
947 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
949 IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
951 if (IMoniker_IsEqual(pmkOther
,mostLeftMk1
)==S_OK
){
953 *ppmkPrefix
=pmkOther
;
958 return MK_E_NOPREFIX
;
962 /***************************************************************************************************
963 * GetAfterCommonPrefix (local function)
964 * This function returns a moniker that consist of the remainder when the common prefix is removed
965 ***************************************************************************************************/
966 static VOID
GetAfterCommonPrefix(IMoniker
* pGenMk
,IMoniker
* commonMk
,IMoniker
** restMk
)
968 IMoniker
*tempMk
,*tempMk1
,*tempMk2
;
969 IEnumMoniker
*enumMoniker1
,*enumMoniker2
,*enumMoniker3
;
976 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
977 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
978 /* on the first difference. */
979 IMoniker_Enum(pGenMk
,TRUE
,&enumMoniker1
);
981 IMoniker_IsSystemMoniker(commonMk
,&mkSys
);
983 if (mkSys
==MKSYS_GENERICCOMPOSITE
){
985 IMoniker_Enum(commonMk
,TRUE
,&enumMoniker2
);
988 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
989 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
991 if ((res1
==S_FALSE
)||(res2
==S_FALSE
)){
997 IMoniker_Release(tempMk1
);
998 IMoniker_Release(tempMk1
);
1002 IMoniker_Release(tempMk1
);
1003 IMoniker_Release(tempMk1
);
1007 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1008 IMoniker_Release(tempMk1
);
1011 /* count the number of elements in the enumerator after the common prefix */
1012 IEnumMoniker_Clone(enumMoniker1
,&enumMoniker3
);
1014 for(;IEnumMoniker_Next(enumMoniker3
,1,&tempMk
,NULL
)==S_OK
;nbRestMk
++)
1016 IMoniker_Release(tempMk
);
1021 /* create a generic composite moniker with monikers located after the common prefix */
1022 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1031 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1033 CreateGenericComposite(tempMk1
,tempMk2
,restMk
);
1035 IMoniker_Release(tempMk1
);
1037 IMoniker_Release(tempMk2
);
1039 while(IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
)==S_OK
){
1041 CreateGenericComposite(*restMk
,tempMk1
,&tempMk2
);
1043 IMoniker_Release(tempMk1
);
1045 IMoniker_Release(*restMk
);
1052 /******************************************************************************
1053 * CompositeMoniker_RelativePathTo
1054 ******************************************************************************/
1055 static HRESULT WINAPI
1056 CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmkOther
,
1057 IMoniker
** ppmkRelPath
)
1060 IMoniker
*restOtherMk
=0,*restThisMk
=0,*invRestThisMk
=0,*commonMk
=0;
1062 TRACE("(%p,%p,%p)\n",iface
,pmkOther
,ppmkRelPath
);
1064 if (ppmkRelPath
==NULL
)
1069 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1070 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1071 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1073 /* finds the common prefix of the two monikers */
1074 res
=IMoniker_CommonPrefixWith(iface
,pmkOther
,&commonMk
);
1076 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1077 if ((res
== MK_E_NOPREFIX
)||(res
==MK_S_US
)){
1079 *ppmkRelPath
=pmkOther
;
1080 IMoniker_AddRef(pmkOther
);
1084 GetAfterCommonPrefix(iface
,commonMk
,&restThisMk
);
1085 GetAfterCommonPrefix(pmkOther
,commonMk
,&restOtherMk
);
1087 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1088 /* moniker when the common prefix is removed */
1091 IMoniker_Inverse(restThisMk
,ppmkRelPath
);
1092 IMoniker_Release(restThisMk
);
1094 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1095 /* when the common prefix is removed */
1096 else if (res
==MK_S_ME
){
1098 *ppmkRelPath
=restOtherMk
;
1099 IMoniker_AddRef(restOtherMk
);
1101 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1102 /* moniker on the right of it. */
1103 else if (res
==S_OK
){
1105 IMoniker_Inverse(restThisMk
,&invRestThisMk
);
1106 IMoniker_Release(restThisMk
);
1107 CreateGenericComposite(invRestThisMk
,restOtherMk
,ppmkRelPath
);
1108 IMoniker_Release(invRestThisMk
);
1109 IMoniker_Release(restOtherMk
);
1114 /******************************************************************************
1115 * CompositeMoniker_GetDisplayName
1116 ******************************************************************************/
1117 static HRESULT WINAPI
1118 CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
1119 IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
)
1122 IEnumMoniker
*enumMoniker
;
1126 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
1128 if (ppszDisplayName
==NULL
)
1131 *ppszDisplayName
=CoTaskMemAlloc(sizeof(WCHAR
));
1133 if (*ppszDisplayName
==NULL
)
1134 return E_OUTOFMEMORY
;
1136 /* This method returns the concatenation of the display names returned by each component moniker of */
1139 **ppszDisplayName
=0;
1141 IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
1143 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
1145 IMoniker_GetDisplayName(tempMk
,pbc
,NULL
,&tempStr
);
1147 lengthStr
+=lstrlenW(tempStr
);
1149 *ppszDisplayName
=CoTaskMemRealloc(*ppszDisplayName
,lengthStr
* sizeof(WCHAR
));
1151 if (*ppszDisplayName
==NULL
)
1152 return E_OUTOFMEMORY
;
1154 strcatW(*ppszDisplayName
,tempStr
);
1156 CoTaskMemFree(tempStr
);
1157 IMoniker_Release(tempMk
);
1160 IEnumMoniker_Release(enumMoniker
);
1165 /******************************************************************************
1166 * CompositeMoniker_ParseDisplayName
1167 ******************************************************************************/
1168 static HRESULT WINAPI
1169 CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
1170 IMoniker
* pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
* pchEaten
,
1173 IEnumMoniker
*enumMoniker
;
1174 IMoniker
*tempMk
,*mostRigthMk
,*antiMk
;
1175 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1176 /* passing everything else as the pmkToLeft parameter for that call. */
1178 /* get the most right moniker */
1179 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1180 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1181 IEnumMoniker_Release(enumMoniker
);
1183 /* get the left moniker */
1184 CreateAntiMoniker(&antiMk
);
1185 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1186 IMoniker_Release(antiMk
);
1188 return IMoniker_ParseDisplayName(mostRigthMk
,pbc
,tempMk
,pszDisplayName
,pchEaten
,ppmkOut
);
1191 /******************************************************************************
1192 * CompositeMoniker_IsSystemMoniker
1193 ******************************************************************************/
1194 static HRESULT WINAPI
1195 CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
1197 TRACE("(%p,%p)\n",iface
,pwdMksys
);
1202 (*pwdMksys
)=MKSYS_GENERICCOMPOSITE
;
1207 /*******************************************************************************
1208 * CompositeMonikerIROTData_QueryInterface
1209 *******************************************************************************/
1210 static HRESULT WINAPI
1211 CompositeMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,
1215 IMoniker
*This
= impl_from_IROTData(iface
);
1217 TRACE("(%p,%p,%p)\n",iface
,riid
,ppvObject
);
1219 return CompositeMonikerImpl_QueryInterface(This
, riid
, ppvObject
);
1222 /***********************************************************************
1223 * CompositeMonikerIROTData_AddRef
1226 CompositeMonikerROTDataImpl_AddRef(IROTData
*iface
)
1228 IMoniker
*This
= impl_from_IROTData(iface
);
1230 TRACE("(%p)\n",iface
);
1232 return IMoniker_AddRef(This
);
1235 /***********************************************************************
1236 * CompositeMonikerIROTData_Release
1238 static ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
)
1240 IMoniker
*This
= impl_from_IROTData(iface
);
1242 TRACE("(%p)\n",iface
);
1244 return IMoniker_Release(This
);
1247 /******************************************************************************
1248 * CompositeMonikerIROTData_GetComparaisonData
1249 ******************************************************************************/
1250 static HRESULT WINAPI
1251 CompositeMonikerROTDataImpl_GetComparaisonData(IROTData
* iface
,
1252 BYTE
* pbData
, ULONG cbMax
, ULONG
* pcbData
)
1254 FIXME("(),stub!\n");
1258 /******************************************************************************
1259 * EnumMonikerImpl_QueryInterface
1260 ******************************************************************************/
1261 static HRESULT WINAPI
1262 EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
)
1264 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1266 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
1268 /* Perform a sanity check on the parameters.*/
1269 if ( (This
==0) || (ppvObject
==0) )
1270 return E_INVALIDARG
;
1272 /* Initialize the return parameter */
1275 /* Compare the riid with the interface IDs implemented by this object.*/
1276 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IEnumMoniker
, riid
))
1279 /* Check that we obtained an interface.*/
1280 if ((*ppvObject
)==0)
1281 return E_NOINTERFACE
;
1283 /* Query Interface always increases the reference count by one when it is successful */
1284 IEnumMoniker_AddRef(iface
);
1289 /******************************************************************************
1290 * EnumMonikerImpl_AddRef
1291 ******************************************************************************/
1293 EnumMonikerImpl_AddRef(IEnumMoniker
* iface
)
1295 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1297 TRACE("(%p)\n",This
);
1299 return InterlockedIncrement(&This
->ref
);
1303 /******************************************************************************
1304 * EnumMonikerImpl_Release
1305 ******************************************************************************/
1307 EnumMonikerImpl_Release(IEnumMoniker
* iface
)
1309 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1312 TRACE("(%p)\n",This
);
1314 ref
= InterlockedDecrement(&This
->ref
);
1316 /* destroy the object if there's no more reference on it */
1319 for(i
=0;i
<This
->tabSize
;i
++)
1320 IMoniker_Release(This
->tabMoniker
[i
]);
1322 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
1323 HeapFree(GetProcessHeap(),0,This
);
1328 /******************************************************************************
1329 * EnumMonikerImpl_Next
1330 ******************************************************************************/
1331 static HRESULT WINAPI
1332 EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
, IMoniker
** rgelt
,
1335 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1338 /* retrieve the requested number of moniker from the current position */
1339 for(i
=0;((This
->currentPos
< This
->tabSize
) && (i
< celt
));i
++)
1341 rgelt
[i
]=This
->tabMoniker
[This
->currentPos
++];
1343 if (pceltFethed
!=NULL
)
1352 /******************************************************************************
1353 * EnumMonikerImpl_Skip
1354 ******************************************************************************/
1355 static HRESULT WINAPI
1356 EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
)
1358 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1360 if ((This
->currentPos
+celt
) >= This
->tabSize
)
1363 This
->currentPos
+=celt
;
1368 /******************************************************************************
1369 * EnumMonikerImpl_Reset
1370 ******************************************************************************/
1371 static HRESULT WINAPI
1372 EnumMonikerImpl_Reset(IEnumMoniker
* iface
)
1375 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1382 /******************************************************************************
1383 * EnumMonikerImpl_Clone
1384 ******************************************************************************/
1385 static HRESULT WINAPI
1386 EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
)
1388 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1390 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabSize
,This
->currentPos
,TRUE
,ppenum
);
1393 /********************************************************************************/
1394 /* Virtual function table for the IROTData class */
1395 static const IEnumMonikerVtbl VT_EnumMonikerImpl
=
1397 EnumMonikerImpl_QueryInterface
,
1398 EnumMonikerImpl_AddRef
,
1399 EnumMonikerImpl_Release
,
1400 EnumMonikerImpl_Next
,
1401 EnumMonikerImpl_Skip
,
1402 EnumMonikerImpl_Reset
,
1403 EnumMonikerImpl_Clone
1406 /******************************************************************************
1407 * EnumMonikerImpl_CreateEnumMoniker
1408 ******************************************************************************/
1410 EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
, ULONG tabSize
,
1411 ULONG currentPos
, BOOL leftToRigth
, IEnumMoniker
** ppmk
)
1413 EnumMonikerImpl
* newEnumMoniker
;
1416 if (currentPos
> tabSize
)
1417 return E_INVALIDARG
;
1419 newEnumMoniker
= HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl
));
1421 if (newEnumMoniker
== 0)
1422 return STG_E_INSUFFICIENTMEMORY
;
1424 /* Initialize the virtual function table. */
1425 newEnumMoniker
->lpVtbl
= &VT_EnumMonikerImpl
;
1426 newEnumMoniker
->ref
= 0;
1428 newEnumMoniker
->tabSize
=tabSize
;
1429 newEnumMoniker
->currentPos
=currentPos
;
1431 newEnumMoniker
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,tabSize
*sizeof(IMoniker
));
1433 if (newEnumMoniker
->tabMoniker
==NULL
) {
1434 HeapFree(GetProcessHeap(), 0, newEnumMoniker
);
1435 return E_OUTOFMEMORY
;
1439 for (i
=0;i
<tabSize
;i
++){
1441 newEnumMoniker
->tabMoniker
[i
]=tabMoniker
[i
];
1442 IMoniker_AddRef(tabMoniker
[i
]);
1445 for (i
=tabSize
-1;i
>=0;i
--){
1447 newEnumMoniker
->tabMoniker
[tabSize
-i
-1]=tabMoniker
[i
];
1448 IMoniker_AddRef(tabMoniker
[i
]);
1451 *ppmk
=(IEnumMoniker
*)newEnumMoniker
;
1456 /********************************************************************************/
1457 /* Virtual function table for the CompositeMonikerImpl class which includes */
1458 /* IPersist, IPersistStream and IMoniker functions. */
1460 static const IMonikerVtbl VT_CompositeMonikerImpl
=
1462 CompositeMonikerImpl_QueryInterface
,
1463 CompositeMonikerImpl_AddRef
,
1464 CompositeMonikerImpl_Release
,
1465 CompositeMonikerImpl_GetClassID
,
1466 CompositeMonikerImpl_IsDirty
,
1467 CompositeMonikerImpl_Load
,
1468 CompositeMonikerImpl_Save
,
1469 CompositeMonikerImpl_GetSizeMax
,
1470 CompositeMonikerImpl_BindToObject
,
1471 CompositeMonikerImpl_BindToStorage
,
1472 CompositeMonikerImpl_Reduce
,
1473 CompositeMonikerImpl_ComposeWith
,
1474 CompositeMonikerImpl_Enum
,
1475 CompositeMonikerImpl_IsEqual
,
1476 CompositeMonikerImpl_Hash
,
1477 CompositeMonikerImpl_IsRunning
,
1478 CompositeMonikerImpl_GetTimeOfLastChange
,
1479 CompositeMonikerImpl_Inverse
,
1480 CompositeMonikerImpl_CommonPrefixWith
,
1481 CompositeMonikerImpl_RelativePathTo
,
1482 CompositeMonikerImpl_GetDisplayName
,
1483 CompositeMonikerImpl_ParseDisplayName
,
1484 CompositeMonikerImpl_IsSystemMoniker
1487 /********************************************************************************/
1488 /* Virtual function table for the IROTData class. */
1489 static const IROTDataVtbl VT_ROTDataImpl
=
1491 CompositeMonikerROTDataImpl_QueryInterface
,
1492 CompositeMonikerROTDataImpl_AddRef
,
1493 CompositeMonikerROTDataImpl_Release
,
1494 CompositeMonikerROTDataImpl_GetComparaisonData
1497 /******************************************************************************
1498 * Composite-Moniker_Construct (local function)
1499 *******************************************************************************/
1501 CompositeMonikerImpl_Construct(CompositeMonikerImpl
* This
,
1502 LPMONIKER pmkFirst
, LPMONIKER pmkRest
)
1505 IEnumMoniker
*enumMoniker
;
1509 TRACE("(%p,%p,%p)\n",This
,pmkFirst
,pmkRest
);
1511 /* Initialize the virtual function table. */
1512 This
->lpvtbl1
= &VT_CompositeMonikerImpl
;
1513 This
->lpvtbl2
= &VT_ROTDataImpl
;
1516 This
->tabSize
=BLOCK_TAB_SIZE
;
1517 This
->tabLastIndex
=0;
1519 This
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,This
->tabSize
*sizeof(IMoniker
));
1520 if (This
->tabMoniker
==NULL
)
1521 return E_OUTOFMEMORY
;
1523 IMoniker_IsSystemMoniker(pmkFirst
,&mkSys
);
1525 /* put the first moniker contents in the beginning of the table */
1526 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
1528 This
->tabMoniker
[(This
->tabLastIndex
)++]=pmkFirst
;
1529 IMoniker_AddRef(pmkFirst
);
1533 IMoniker_Enum(pmkFirst
,TRUE
,&enumMoniker
);
1535 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
1538 if (++This
->tabLastIndex
==This
->tabSize
){
1540 This
->tabSize
+=BLOCK_TAB_SIZE
;
1541 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1543 if (This
->tabMoniker
==NULL
)
1544 return E_OUTOFMEMORY
;
1548 IEnumMoniker_Release(enumMoniker
);
1551 /* put the rest moniker contents after the first one and make simplification if needed */
1553 IMoniker_IsSystemMoniker(pmkRest
,&mkSys
);
1555 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
1557 /* add a simple moniker to the moniker table */
1559 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],pmkRest
,TRUE
,&tempMk
);
1561 if (res
==MK_E_NEEDGENERIC
){
1563 /* there's no simplification in this case */
1564 This
->tabMoniker
[This
->tabLastIndex
]=pmkRest
;
1566 This
->tabLastIndex
++;
1568 IMoniker_AddRef(pmkRest
);
1570 else if (tempMk
==NULL
){
1572 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
1573 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1575 This
->tabLastIndex
--;
1577 else if (SUCCEEDED(res
)){
1579 /* the non-generic composition was successful so we can make a simplification in this case */
1580 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1582 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
1586 /* resize tabMoniker if needed */
1587 if (This
->tabLastIndex
==This
->tabSize
){
1589 This
->tabSize
+=BLOCK_TAB_SIZE
;
1591 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1593 if (This
->tabMoniker
==NULL
)
1594 return E_OUTOFMEMORY
;
1599 /* add a composite moniker to the moniker table (do the same thing
1600 * for each moniker within the composite moniker as a simple moniker
1601 * (see above for how to add a simple moniker case) )
1603 IMoniker_Enum(pmkRest
,TRUE
,&enumMoniker
);
1605 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
1607 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],This
->tabMoniker
[This
->tabLastIndex
],TRUE
,&tempMk
);
1609 if (res
==MK_E_NEEDGENERIC
){
1611 This
->tabLastIndex
++;
1613 else if (tempMk
==NULL
){
1615 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1616 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
]);
1617 This
->tabLastIndex
--;
1621 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1623 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
1626 if (This
->tabLastIndex
==This
->tabSize
){
1628 This
->tabSize
+=BLOCK_TAB_SIZE
;
1630 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1632 if (This
->tabMoniker
==NULL
)
1633 return E_OUTOFMEMORY
;
1637 IEnumMoniker_Release(enumMoniker
);
1643 /******************************************************************************
1644 * CreateGenericComposite [OLE32.@]
1645 ******************************************************************************/
1647 CreateGenericComposite(LPMONIKER pmkFirst
, LPMONIKER pmkRest
,
1648 LPMONIKER
* ppmkComposite
)
1650 CompositeMonikerImpl
* newCompositeMoniker
= 0;
1653 TRACE("(%p,%p,%p)\n",pmkFirst
,pmkRest
,ppmkComposite
);
1655 if (ppmkComposite
==NULL
)
1660 if (pmkFirst
==NULL
&& pmkRest
!=NULL
){
1662 *ppmkComposite
=pmkRest
;
1665 else if (pmkFirst
!=NULL
&& pmkRest
==NULL
){
1666 *ppmkComposite
=pmkFirst
;
1669 else if (pmkFirst
==NULL
&& pmkRest
==NULL
)
1672 newCompositeMoniker
= HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl
));
1674 if (newCompositeMoniker
== 0)
1675 return STG_E_INSUFFICIENTMEMORY
;
1677 hr
= CompositeMonikerImpl_Construct(newCompositeMoniker
,pmkFirst
,pmkRest
);
1681 HeapFree(GetProcessHeap(),0,newCompositeMoniker
);
1684 if (newCompositeMoniker
->tabLastIndex
==1)
1686 hr
= IMoniker_QueryInterface(newCompositeMoniker
->tabMoniker
[0],&IID_IMoniker
,(void**)ppmkComposite
);
1689 hr
= IMoniker_QueryInterface((IMoniker
*)newCompositeMoniker
,&IID_IMoniker
,(void**)ppmkComposite
);
1694 /******************************************************************************
1695 * MonikerCommonPrefixWith [OLE32.@]
1696 ******************************************************************************/
1698 MonikerCommonPrefixWith(IMoniker
* pmkThis
,IMoniker
* pmkOther
,IMoniker
** ppmkCommon
)
1700 FIXME("(),stub!\n");