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
)
619 IEnumMoniker
*enumMoniker
;
624 TRACE("(%p,%p)\n",iface
,pdwHash
);
629 res
= IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
634 res
=IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
);
638 res
= IMoniker_Hash(tempMk
, &tempHash
);
641 *pdwHash
= (*pdwHash
* 37) + tempHash
;
643 IMoniker_Release(tempMk
);
646 IEnumMoniker_Release(enumMoniker
);
651 /******************************************************************************
652 * CompositeMoniker_IsRunning
653 ******************************************************************************/
654 static HRESULT WINAPI
655 CompositeMonikerImpl_IsRunning(IMoniker
* iface
, IBindCtx
* pbc
,
656 IMoniker
* pmkToLeft
, IMoniker
* pmkNewlyRunning
)
658 IRunningObjectTable
* rot
;
660 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
661 IEnumMoniker
*enumMoniker
;
663 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
665 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
666 if (pmkToLeft
!=NULL
){
668 CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
670 res
= IMoniker_IsRunning(tempMk
,pbc
,NULL
,pmkNewlyRunning
);
672 IMoniker_Release(tempMk
);
677 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
678 /* to this moniker */
680 if (pmkNewlyRunning
!=NULL
)
682 if (IMoniker_IsEqual(iface
,pmkNewlyRunning
)==S_OK
)
693 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
694 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
695 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
696 /* the composite as the pmkToLeft parameter for that call. */
698 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
703 res
= IRunningObjectTable_IsRunning(rot
,iface
);
704 IRunningObjectTable_Release(rot
);
711 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
712 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
713 IEnumMoniker_Release(enumMoniker
);
715 res
=CreateAntiMoniker(&antiMk
);
716 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
717 IMoniker_Release(antiMk
);
719 res
=IMoniker_IsRunning(mostRigthMk
,pbc
,tempMk
,pmkNewlyRunning
);
721 IMoniker_Release(tempMk
);
722 IMoniker_Release(mostRigthMk
);
729 /******************************************************************************
730 * CompositeMoniker_GetTimeOfLastChange
731 ******************************************************************************/
732 static HRESULT WINAPI
733 CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
, IBindCtx
* pbc
,
734 IMoniker
* pmkToLeft
, FILETIME
* pCompositeTime
)
736 IRunningObjectTable
* rot
;
738 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
739 IEnumMoniker
*enumMoniker
;
741 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pCompositeTime
);
743 if (pCompositeTime
==NULL
)
746 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
747 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
748 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
749 /* of the composite as the pmkToLeft parameter for that call. */
750 if (pmkToLeft
!=NULL
){
752 res
=CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
754 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
759 if (IRunningObjectTable_GetTimeOfLastChange(rot
,tempMk
,pCompositeTime
)==S_OK
)
763 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
764 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
765 IEnumMoniker_Release(enumMoniker
);
767 res
=CreateAntiMoniker(&antiMk
);
768 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
769 IMoniker_Release(antiMk
);
771 res
=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk
,pbc
,tempMk
,pCompositeTime
);
773 IMoniker_Release(tempMk
);
774 IMoniker_Release(mostRigthMk
);
779 return IMoniker_GetTimeOfLastChange(iface
,pbc
,NULL
,pCompositeTime
);
782 /******************************************************************************
783 * CompositeMoniker_Inverse
784 ******************************************************************************/
785 static HRESULT WINAPI
786 CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
789 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*tempInvMk
,*mostRigthInvMk
;
790 IEnumMoniker
*enumMoniker
;
792 TRACE("(%p,%p)\n",iface
,ppmk
);
797 /* This method returns a composite moniker that consists of the inverses of each of the components */
798 /* of the original composite, stored in reverse order */
800 res
=CreateAntiMoniker(&antiMk
);
801 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
802 IMoniker_Release(antiMk
);
806 return IMoniker_Inverse(iface
,ppmk
);
810 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
811 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
812 IEnumMoniker_Release(enumMoniker
);
814 IMoniker_Inverse(mostRigthMk
,&mostRigthInvMk
);
815 CompositeMonikerImpl_Inverse(tempMk
,&tempInvMk
);
817 res
=CreateGenericComposite(mostRigthInvMk
,tempInvMk
,ppmk
);
819 IMoniker_Release(tempMk
);
820 IMoniker_Release(mostRigthMk
);
821 IMoniker_Release(tempInvMk
);
822 IMoniker_Release(mostRigthInvMk
);
828 /******************************************************************************
829 * CompositeMoniker_CommonPrefixWith
830 ******************************************************************************/
831 static HRESULT WINAPI
832 CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
, IMoniker
* pmkOther
,
833 IMoniker
** ppmkPrefix
)
837 IMoniker
*tempMk1
,*tempMk2
,*mostLeftMk1
,*mostLeftMk2
;
838 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
839 ULONG i
,nbCommonMk
=0;
841 /* If the other moniker is a composite, this method compares the components of each composite from left */
842 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
843 /* of the leftmost components were common to both monikers. */
845 if (ppmkPrefix
==NULL
)
851 return MK_E_NOPREFIX
;
853 IMoniker_IsSystemMoniker(pmkOther
,&mkSys
);
855 if((mkSys
==MKSYS_GENERICCOMPOSITE
)){
857 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
858 IMoniker_Enum(pmkOther
,TRUE
,&enumMoniker2
);
862 res1
=IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
863 res2
=IEnumMoniker_Next(enumMoniker2
,1,&mostLeftMk2
,NULL
);
865 if ((res1
==S_FALSE
) && (res2
==S_FALSE
)){
867 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
869 IMoniker_AddRef(iface
);
872 else if ((res1
==S_OK
) && (res2
==S_OK
)){
874 if (IMoniker_IsEqual(mostLeftMk1
,mostLeftMk2
)==S_OK
)
882 else if (res1
==S_OK
){
884 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
885 /* ppmkPrefix to the other moniker. */
886 *ppmkPrefix
=pmkOther
;
890 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
891 /* to this moniker. */
897 IEnumMoniker_Release(enumMoniker1
);
898 IEnumMoniker_Release(enumMoniker2
);
900 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
902 return MK_E_NOPREFIX
;
904 IEnumMoniker_Reset(enumMoniker1
);
906 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
908 /* if we have more than one commun moniker the result will be a composite moniker */
911 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
912 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
913 CreateGenericComposite(tempMk1
,tempMk2
,ppmkPrefix
);
914 IMoniker_Release(tempMk1
);
915 IMoniker_Release(tempMk2
);
917 /* compose all common monikers in a composite moniker */
918 for(i
=0;i
<nbCommonMk
;i
++){
920 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
922 CreateGenericComposite(*ppmkPrefix
,tempMk1
,&tempMk2
);
924 IMoniker_Release(*ppmkPrefix
);
926 IMoniker_Release(tempMk1
);
933 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
940 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
943 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
945 IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
947 if (IMoniker_IsEqual(pmkOther
,mostLeftMk1
)==S_OK
){
949 *ppmkPrefix
=pmkOther
;
954 return MK_E_NOPREFIX
;
958 /***************************************************************************************************
959 * GetAfterCommonPrefix (local function)
960 * This function returns a moniker that consist of the remainder when the common prefix is removed
961 ***************************************************************************************************/
962 static VOID
GetAfterCommonPrefix(IMoniker
* pGenMk
,IMoniker
* commonMk
,IMoniker
** restMk
)
964 IMoniker
*tempMk
,*tempMk1
,*tempMk2
;
965 IEnumMoniker
*enumMoniker1
,*enumMoniker2
,*enumMoniker3
;
972 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
973 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
974 /* on the first difference. */
975 IMoniker_Enum(pGenMk
,TRUE
,&enumMoniker1
);
977 IMoniker_IsSystemMoniker(commonMk
,&mkSys
);
979 if (mkSys
==MKSYS_GENERICCOMPOSITE
){
981 IMoniker_Enum(commonMk
,TRUE
,&enumMoniker2
);
984 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
985 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
987 if ((res1
==S_FALSE
)||(res2
==S_FALSE
)){
993 IMoniker_Release(tempMk1
);
994 IMoniker_Release(tempMk1
);
998 IMoniker_Release(tempMk1
);
999 IMoniker_Release(tempMk1
);
1003 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1004 IMoniker_Release(tempMk1
);
1007 /* count the number of elements in the enumerator after the common prefix */
1008 IEnumMoniker_Clone(enumMoniker1
,&enumMoniker3
);
1010 for(;IEnumMoniker_Next(enumMoniker3
,1,&tempMk
,NULL
)==S_OK
;nbRestMk
++)
1012 IMoniker_Release(tempMk
);
1017 /* create a generic composite moniker with monikers located after the common prefix */
1018 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1027 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1029 CreateGenericComposite(tempMk1
,tempMk2
,restMk
);
1031 IMoniker_Release(tempMk1
);
1033 IMoniker_Release(tempMk2
);
1035 while(IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
)==S_OK
){
1037 CreateGenericComposite(*restMk
,tempMk1
,&tempMk2
);
1039 IMoniker_Release(tempMk1
);
1041 IMoniker_Release(*restMk
);
1048 /******************************************************************************
1049 * CompositeMoniker_RelativePathTo
1050 ******************************************************************************/
1051 static HRESULT WINAPI
1052 CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmkOther
,
1053 IMoniker
** ppmkRelPath
)
1056 IMoniker
*restOtherMk
=0,*restThisMk
=0,*invRestThisMk
=0,*commonMk
=0;
1058 TRACE("(%p,%p,%p)\n",iface
,pmkOther
,ppmkRelPath
);
1060 if (ppmkRelPath
==NULL
)
1065 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1066 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1067 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1069 /* finds the common prefix of the two monikers */
1070 res
=IMoniker_CommonPrefixWith(iface
,pmkOther
,&commonMk
);
1072 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1073 if ((res
== MK_E_NOPREFIX
)||(res
==MK_S_US
)){
1075 *ppmkRelPath
=pmkOther
;
1076 IMoniker_AddRef(pmkOther
);
1080 GetAfterCommonPrefix(iface
,commonMk
,&restThisMk
);
1081 GetAfterCommonPrefix(pmkOther
,commonMk
,&restOtherMk
);
1083 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1084 /* moniker when the common prefix is removed */
1087 IMoniker_Inverse(restThisMk
,ppmkRelPath
);
1088 IMoniker_Release(restThisMk
);
1090 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1091 /* when the common prefix is removed */
1092 else if (res
==MK_S_ME
){
1094 *ppmkRelPath
=restOtherMk
;
1095 IMoniker_AddRef(restOtherMk
);
1097 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1098 /* moniker on the right of it. */
1099 else if (res
==S_OK
){
1101 IMoniker_Inverse(restThisMk
,&invRestThisMk
);
1102 IMoniker_Release(restThisMk
);
1103 CreateGenericComposite(invRestThisMk
,restOtherMk
,ppmkRelPath
);
1104 IMoniker_Release(invRestThisMk
);
1105 IMoniker_Release(restOtherMk
);
1110 /******************************************************************************
1111 * CompositeMoniker_GetDisplayName
1112 ******************************************************************************/
1113 static HRESULT WINAPI
1114 CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
1115 IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
)
1118 IEnumMoniker
*enumMoniker
;
1122 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
1124 if (ppszDisplayName
==NULL
)
1127 *ppszDisplayName
=CoTaskMemAlloc(sizeof(WCHAR
));
1129 if (*ppszDisplayName
==NULL
)
1130 return E_OUTOFMEMORY
;
1132 /* This method returns the concatenation of the display names returned by each component moniker of */
1135 **ppszDisplayName
=0;
1137 IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
1139 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
1141 IMoniker_GetDisplayName(tempMk
,pbc
,NULL
,&tempStr
);
1143 lengthStr
+=lstrlenW(tempStr
);
1145 *ppszDisplayName
=CoTaskMemRealloc(*ppszDisplayName
,lengthStr
* sizeof(WCHAR
));
1147 if (*ppszDisplayName
==NULL
)
1148 return E_OUTOFMEMORY
;
1150 strcatW(*ppszDisplayName
,tempStr
);
1152 CoTaskMemFree(tempStr
);
1153 IMoniker_Release(tempMk
);
1156 IEnumMoniker_Release(enumMoniker
);
1161 /******************************************************************************
1162 * CompositeMoniker_ParseDisplayName
1163 ******************************************************************************/
1164 static HRESULT WINAPI
1165 CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
1166 IMoniker
* pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
* pchEaten
,
1169 IEnumMoniker
*enumMoniker
;
1170 IMoniker
*tempMk
,*mostRigthMk
,*antiMk
;
1171 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1172 /* passing everything else as the pmkToLeft parameter for that call. */
1174 /* get the most right moniker */
1175 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1176 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1177 IEnumMoniker_Release(enumMoniker
);
1179 /* get the left moniker */
1180 CreateAntiMoniker(&antiMk
);
1181 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1182 IMoniker_Release(antiMk
);
1184 return IMoniker_ParseDisplayName(mostRigthMk
,pbc
,tempMk
,pszDisplayName
,pchEaten
,ppmkOut
);
1187 /******************************************************************************
1188 * CompositeMoniker_IsSystemMoniker
1189 ******************************************************************************/
1190 static HRESULT WINAPI
1191 CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
1193 TRACE("(%p,%p)\n",iface
,pwdMksys
);
1198 (*pwdMksys
)=MKSYS_GENERICCOMPOSITE
;
1203 /*******************************************************************************
1204 * CompositeMonikerIROTData_QueryInterface
1205 *******************************************************************************/
1206 static HRESULT WINAPI
1207 CompositeMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,
1211 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1213 TRACE("(%p,%p,%p)\n",iface
,riid
,ppvObject
);
1215 return CompositeMonikerImpl_QueryInterface(This
, riid
, ppvObject
);
1218 /***********************************************************************
1219 * CompositeMonikerIROTData_AddRef
1222 CompositeMonikerROTDataImpl_AddRef(IROTData
*iface
)
1224 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1226 TRACE("(%p)\n",iface
);
1228 return IMoniker_AddRef(This
);
1231 /***********************************************************************
1232 * CompositeMonikerIROTData_Release
1234 static ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
)
1236 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1238 TRACE("(%p)\n",iface
);
1240 return IMoniker_Release(This
);
1243 /******************************************************************************
1244 * CompositeMonikerIROTData_GetComparaisonData
1245 ******************************************************************************/
1246 static HRESULT WINAPI
1247 CompositeMonikerROTDataImpl_GetComparaisonData(IROTData
* iface
,
1248 BYTE
* pbData
, ULONG cbMax
, ULONG
* pcbData
)
1250 FIXME("(),stub!\n");
1254 /******************************************************************************
1255 * EnumMonikerImpl_QueryInterface
1256 ******************************************************************************/
1257 static HRESULT WINAPI
1258 EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
)
1260 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1262 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
1264 /* Perform a sanity check on the parameters.*/
1265 if ( (This
==0) || (ppvObject
==0) )
1266 return E_INVALIDARG
;
1268 /* Initialize the return parameter */
1271 /* Compare the riid with the interface IDs implemented by this object.*/
1272 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IEnumMoniker
, riid
))
1275 /* Check that we obtained an interface.*/
1276 if ((*ppvObject
)==0)
1277 return E_NOINTERFACE
;
1279 /* Query Interface always increases the reference count by one when it is successful */
1280 IEnumMoniker_AddRef(iface
);
1285 /******************************************************************************
1286 * EnumMonikerImpl_AddRef
1287 ******************************************************************************/
1289 EnumMonikerImpl_AddRef(IEnumMoniker
* iface
)
1291 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1293 TRACE("(%p)\n",This
);
1295 return InterlockedIncrement(&This
->ref
);
1299 /******************************************************************************
1300 * EnumMonikerImpl_Release
1301 ******************************************************************************/
1303 EnumMonikerImpl_Release(IEnumMoniker
* iface
)
1305 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1308 TRACE("(%p)\n",This
);
1310 ref
= InterlockedDecrement(&This
->ref
);
1312 /* destroy the object if there's no more reference on it */
1315 for(i
=0;i
<This
->tabSize
;i
++)
1316 IMoniker_Release(This
->tabMoniker
[i
]);
1318 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
1319 HeapFree(GetProcessHeap(),0,This
);
1324 /******************************************************************************
1325 * EnumMonikerImpl_Next
1326 ******************************************************************************/
1327 static HRESULT WINAPI
1328 EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
, IMoniker
** rgelt
,
1331 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1334 /* retrieve the requested number of moniker from the current position */
1335 for(i
=0;((This
->currentPos
< This
->tabSize
) && (i
< celt
));i
++)
1337 rgelt
[i
]=This
->tabMoniker
[This
->currentPos
++];
1339 if (pceltFethed
!=NULL
)
1348 /******************************************************************************
1349 * EnumMonikerImpl_Skip
1350 ******************************************************************************/
1351 static HRESULT WINAPI
1352 EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
)
1354 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1356 if ((This
->currentPos
+celt
) >= This
->tabSize
)
1359 This
->currentPos
+=celt
;
1364 /******************************************************************************
1365 * EnumMonikerImpl_Reset
1366 ******************************************************************************/
1367 static HRESULT WINAPI
1368 EnumMonikerImpl_Reset(IEnumMoniker
* iface
)
1371 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1378 /******************************************************************************
1379 * EnumMonikerImpl_Clone
1380 ******************************************************************************/
1381 static HRESULT WINAPI
1382 EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
)
1384 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1386 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabSize
,This
->currentPos
,TRUE
,ppenum
);
1389 /********************************************************************************/
1390 /* Virtual function table for the IROTData class */
1391 static IEnumMonikerVtbl VT_EnumMonikerImpl
=
1393 EnumMonikerImpl_QueryInterface
,
1394 EnumMonikerImpl_AddRef
,
1395 EnumMonikerImpl_Release
,
1396 EnumMonikerImpl_Next
,
1397 EnumMonikerImpl_Skip
,
1398 EnumMonikerImpl_Reset
,
1399 EnumMonikerImpl_Clone
1402 /******************************************************************************
1403 * EnumMonikerImpl_CreateEnumMoniker
1404 ******************************************************************************/
1406 EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
, ULONG tabSize
,
1407 ULONG currentPos
, BOOL leftToRigth
, IEnumMoniker
** ppmk
)
1409 EnumMonikerImpl
* newEnumMoniker
;
1412 if (currentPos
> tabSize
)
1413 return E_INVALIDARG
;
1415 newEnumMoniker
= HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl
));
1417 if (newEnumMoniker
== 0)
1418 return STG_E_INSUFFICIENTMEMORY
;
1420 /* Initialize the virtual function table. */
1421 newEnumMoniker
->lpVtbl
= &VT_EnumMonikerImpl
;
1422 newEnumMoniker
->ref
= 0;
1424 newEnumMoniker
->tabSize
=tabSize
;
1425 newEnumMoniker
->currentPos
=currentPos
;
1427 newEnumMoniker
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,tabSize
*sizeof(IMoniker
));
1429 if (newEnumMoniker
->tabMoniker
==NULL
) {
1430 HeapFree(GetProcessHeap(), 0, newEnumMoniker
);
1431 return E_OUTOFMEMORY
;
1435 for (i
=0;i
<tabSize
;i
++){
1437 newEnumMoniker
->tabMoniker
[i
]=tabMoniker
[i
];
1438 IMoniker_AddRef(tabMoniker
[i
]);
1441 for (i
=tabSize
-1;i
>=0;i
--){
1443 newEnumMoniker
->tabMoniker
[tabSize
-i
-1]=tabMoniker
[i
];
1444 IMoniker_AddRef(tabMoniker
[i
]);
1447 *ppmk
=(IEnumMoniker
*)newEnumMoniker
;
1452 /********************************************************************************/
1453 /* Virtual function table for the CompositeMonikerImpl class which includes */
1454 /* IPersist, IPersistStream and IMoniker functions. */
1456 static IMonikerVtbl VT_CompositeMonikerImpl
=
1458 CompositeMonikerImpl_QueryInterface
,
1459 CompositeMonikerImpl_AddRef
,
1460 CompositeMonikerImpl_Release
,
1461 CompositeMonikerImpl_GetClassID
,
1462 CompositeMonikerImpl_IsDirty
,
1463 CompositeMonikerImpl_Load
,
1464 CompositeMonikerImpl_Save
,
1465 CompositeMonikerImpl_GetSizeMax
,
1466 CompositeMonikerImpl_BindToObject
,
1467 CompositeMonikerImpl_BindToStorage
,
1468 CompositeMonikerImpl_Reduce
,
1469 CompositeMonikerImpl_ComposeWith
,
1470 CompositeMonikerImpl_Enum
,
1471 CompositeMonikerImpl_IsEqual
,
1472 CompositeMonikerImpl_Hash
,
1473 CompositeMonikerImpl_IsRunning
,
1474 CompositeMonikerImpl_GetTimeOfLastChange
,
1475 CompositeMonikerImpl_Inverse
,
1476 CompositeMonikerImpl_CommonPrefixWith
,
1477 CompositeMonikerImpl_RelativePathTo
,
1478 CompositeMonikerImpl_GetDisplayName
,
1479 CompositeMonikerImpl_ParseDisplayName
,
1480 CompositeMonikerImpl_IsSystemMoniker
1483 /********************************************************************************/
1484 /* Virtual function table for the IROTData class. */
1485 static IROTDataVtbl VT_ROTDataImpl
=
1487 CompositeMonikerROTDataImpl_QueryInterface
,
1488 CompositeMonikerROTDataImpl_AddRef
,
1489 CompositeMonikerROTDataImpl_Release
,
1490 CompositeMonikerROTDataImpl_GetComparaisonData
1493 /******************************************************************************
1494 * Composite-Moniker_Construct (local function)
1495 *******************************************************************************/
1497 CompositeMonikerImpl_Construct(CompositeMonikerImpl
* This
,
1498 LPMONIKER pmkFirst
, LPMONIKER pmkRest
)
1501 IEnumMoniker
*enumMoniker
;
1505 TRACE("(%p,%p,%p)\n",This
,pmkFirst
,pmkRest
);
1507 /* Initialize the virtual function table. */
1508 This
->lpvtbl1
= &VT_CompositeMonikerImpl
;
1509 This
->lpvtbl2
= &VT_ROTDataImpl
;
1512 This
->tabSize
=BLOCK_TAB_SIZE
;
1513 This
->tabLastIndex
=0;
1515 This
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,This
->tabSize
*sizeof(IMoniker
));
1516 if (This
->tabMoniker
==NULL
)
1517 return E_OUTOFMEMORY
;
1519 IMoniker_IsSystemMoniker(pmkFirst
,&mkSys
);
1521 /* put the first moniker contents in the beginning of the table */
1522 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
1524 This
->tabMoniker
[(This
->tabLastIndex
)++]=pmkFirst
;
1525 IMoniker_AddRef(pmkFirst
);
1529 IMoniker_Enum(pmkFirst
,TRUE
,&enumMoniker
);
1531 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
1534 if (++This
->tabLastIndex
==This
->tabSize
){
1536 This
->tabSize
+=BLOCK_TAB_SIZE
;
1537 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1539 if (This
->tabMoniker
==NULL
)
1540 return E_OUTOFMEMORY
;
1544 IEnumMoniker_Release(enumMoniker
);
1547 /* put the rest moniker contents after the first one and make simplification if needed */
1549 IMoniker_IsSystemMoniker(pmkRest
,&mkSys
);
1551 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
1553 /* add a simple moniker to the moniker table */
1555 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],pmkRest
,TRUE
,&tempMk
);
1557 if (res
==MK_E_NEEDGENERIC
){
1559 /* there's no simplification in this case */
1560 This
->tabMoniker
[This
->tabLastIndex
]=pmkRest
;
1562 This
->tabLastIndex
++;
1564 IMoniker_AddRef(pmkRest
);
1566 else if (tempMk
==NULL
){
1568 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
1569 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1571 This
->tabLastIndex
--;
1573 else if (SUCCEEDED(res
)){
1575 /* the non-generic composition was successful so we can make a simplification in this case */
1576 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1578 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
1582 /* resize tabMoniker if needed */
1583 if (This
->tabLastIndex
==This
->tabSize
){
1585 This
->tabSize
+=BLOCK_TAB_SIZE
;
1587 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1589 if (This
->tabMoniker
==NULL
)
1590 return E_OUTOFMEMORY
;
1595 /* add a composite moniker to the moniker table (do the same thing
1596 * for each moniker within the composite moniker as a simple moniker
1597 * (see above for how to add a simple moniker case) )
1599 IMoniker_Enum(pmkRest
,TRUE
,&enumMoniker
);
1601 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
1603 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],This
->tabMoniker
[This
->tabLastIndex
],TRUE
,&tempMk
);
1605 if (res
==MK_E_NEEDGENERIC
){
1607 This
->tabLastIndex
++;
1609 else if (tempMk
==NULL
){
1611 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1612 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
]);
1613 This
->tabLastIndex
--;
1617 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1619 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
1622 if (This
->tabLastIndex
==This
->tabSize
){
1624 This
->tabSize
+=BLOCK_TAB_SIZE
;
1626 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1628 if (This
->tabMoniker
==NULL
)
1629 return E_OUTOFMEMORY
;
1633 IEnumMoniker_Release(enumMoniker
);
1639 /******************************************************************************
1640 * CreateGenericComposite [OLE32.@]
1641 ******************************************************************************/
1643 CreateGenericComposite(LPMONIKER pmkFirst
, LPMONIKER pmkRest
,
1644 LPMONIKER
* ppmkComposite
)
1646 CompositeMonikerImpl
* newCompositeMoniker
= 0;
1649 TRACE("(%p,%p,%p)\n",pmkFirst
,pmkRest
,ppmkComposite
);
1651 if (ppmkComposite
==NULL
)
1656 if (pmkFirst
==NULL
&& pmkRest
!=NULL
){
1658 *ppmkComposite
=pmkRest
;
1661 else if (pmkFirst
!=NULL
&& pmkRest
==NULL
){
1662 *ppmkComposite
=pmkFirst
;
1665 else if (pmkFirst
==NULL
&& pmkRest
==NULL
)
1668 newCompositeMoniker
= HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl
));
1670 if (newCompositeMoniker
== 0)
1671 return STG_E_INSUFFICIENTMEMORY
;
1673 hr
= CompositeMonikerImpl_Construct(newCompositeMoniker
,pmkFirst
,pmkRest
);
1677 HeapFree(GetProcessHeap(),0,newCompositeMoniker
);
1680 if (newCompositeMoniker
->tabLastIndex
==1)
1682 hr
= IMoniker_QueryInterface(newCompositeMoniker
->tabMoniker
[0],&IID_IMoniker
,(void**)ppmkComposite
);
1685 hr
= IMoniker_QueryInterface((IMoniker
*)newCompositeMoniker
,&IID_IMoniker
,(void**)ppmkComposite
);
1690 /******************************************************************************
1691 * MonikerCommonPrefixWith [OLE32.@]
1692 ******************************************************************************/
1694 MonikerCommonPrefixWith(IMoniker
* pmkThis
,IMoniker
* pmkOther
,IMoniker
** ppmkCommon
)
1696 FIXME("(),stub!\n");