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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 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 const IMarshalVtbl
* lpvtblMarshal
; /* VTable relative to the IMarshal interface.*/
59 LONG ref
; /* reference counter for this object */
61 IMoniker
** tabMoniker
; /* dynamaic table containing all components (monikers) of this composite moniker */
63 ULONG tabSize
; /* size of tabMoniker */
65 ULONG tabLastIndex
; /* first free index in tabMoniker */
67 } CompositeMonikerImpl
;
70 /* EnumMoniker data structure */
71 typedef struct EnumMonikerImpl
{
73 const IEnumMonikerVtbl
*lpVtbl
; /* VTable relative to the IEnumMoniker interface.*/
75 LONG ref
; /* reference counter for this object */
77 IMoniker
** tabMoniker
; /* dynamic table containing the enumerated monikers */
79 ULONG tabSize
; /* size of tabMoniker */
81 ULONG currentPos
; /* index pointer on the current moniker */
85 static inline IMoniker
*impl_from_IROTData( IROTData
*iface
)
87 return (IMoniker
*)((char*)iface
- FIELD_OFFSET(CompositeMonikerImpl
, lpvtbl2
));
90 static inline IMoniker
*impl_from_IMarshal( IMarshal
*iface
)
92 return (IMoniker
*)((char*)iface
- FIELD_OFFSET(CompositeMonikerImpl
, lpvtblMarshal
));
95 static HRESULT
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,ULONG tabSize
,ULONG currentPos
,BOOL leftToRigth
,IEnumMoniker
** ppmk
);
97 /*******************************************************************************
98 * CompositeMoniker_QueryInterface
99 *******************************************************************************/
100 static HRESULT WINAPI
101 CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
103 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
105 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
107 /* Perform a sanity check on the parameters.*/
108 if ( (This
==0) || (ppvObject
==0) )
111 /* Initialize the return parameter */
114 /* Compare the riid with the interface IDs implemented by this object.*/
115 if (IsEqualIID(&IID_IUnknown
, riid
) ||
116 IsEqualIID(&IID_IPersist
, riid
) ||
117 IsEqualIID(&IID_IPersistStream
, riid
) ||
118 IsEqualIID(&IID_IMoniker
, riid
)
121 else if (IsEqualIID(&IID_IROTData
, riid
))
122 *ppvObject
= (IROTData
*)&(This
->lpvtbl2
);
123 else if (IsEqualIID(&IID_IMarshal
, riid
))
124 *ppvObject
= (IROTData
*)&(This
->lpvtblMarshal
);
126 /* Check that we obtained an interface.*/
128 return E_NOINTERFACE
;
130 /* Query Interface always increases the reference count by one when it is successful */
131 IMoniker_AddRef(iface
);
136 /******************************************************************************
137 * CompositeMoniker_AddRef
138 ******************************************************************************/
140 CompositeMonikerImpl_AddRef(IMoniker
* iface
)
142 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
144 TRACE("(%p)\n",This
);
146 return InterlockedIncrement(&This
->ref
);
149 static void CompositeMonikerImpl_ReleaseMonikersInTable(CompositeMonikerImpl
*This
)
153 for (i
= 0; i
< This
->tabLastIndex
; i
++)
154 IMoniker_Release(This
->tabMoniker
[i
]);
156 This
->tabLastIndex
= 0;
159 /******************************************************************************
160 * CompositeMoniker_Release
161 ******************************************************************************/
163 CompositeMonikerImpl_Release(IMoniker
* iface
)
165 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
168 TRACE("(%p)\n",This
);
170 ref
= InterlockedDecrement(&This
->ref
);
172 /* destroy the object if there's no more reference on it */
175 /* release all the components before destroying this object */
176 CompositeMonikerImpl_ReleaseMonikersInTable(This
);
178 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
179 HeapFree(GetProcessHeap(),0,This
);
184 /******************************************************************************
185 * CompositeMoniker_GetClassID
186 ******************************************************************************/
187 static HRESULT WINAPI
188 CompositeMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
190 TRACE("(%p,%p)\n",iface
,pClassID
);
195 *pClassID
= CLSID_CompositeMoniker
;
200 /******************************************************************************
201 * CompositeMoniker_IsDirty
202 ******************************************************************************/
203 static HRESULT WINAPI
204 CompositeMonikerImpl_IsDirty(IMoniker
* iface
)
206 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
207 method in the OLE-provided moniker interfaces always return S_FALSE because
208 their internal state never changes. */
210 TRACE("(%p)\n",iface
);
215 /******************************************************************************
216 * CompositeMoniker_Load
217 ******************************************************************************/
218 static HRESULT WINAPI
219 CompositeMonikerImpl_Load(IMoniker
* iface
,IStream
* pStm
)
225 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
227 TRACE("(%p,%p)\n",iface
,pStm
);
229 /* this function call OleLoadFromStream function for each moniker within this object */
231 res
=IStream_Read(pStm
,&moniker_count
,sizeof(DWORD
),NULL
);
234 ERR("couldn't reading moniker count from stream\n");
238 CompositeMonikerImpl_ReleaseMonikersInTable(This
);
240 for (i
= 0; i
< moniker_count
; i
++)
242 res
=OleLoadFromStream(pStm
,&IID_IMoniker
,(void**)&This
->tabMoniker
[This
->tabLastIndex
]);
245 ERR("couldn't load moniker from stream, res = 0x%08lx\n", res
);
249 /* resize the table if needed */
250 if (++This
->tabLastIndex
==This
->tabSize
){
252 This
->tabSize
+=BLOCK_TAB_SIZE
;
253 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
255 if (This
->tabMoniker
==NULL
)
256 return E_OUTOFMEMORY
;
263 /******************************************************************************
264 * CompositeMoniker_Save
265 ******************************************************************************/
266 static HRESULT WINAPI
267 CompositeMonikerImpl_Save(IMoniker
* iface
,IStream
* pStm
,BOOL fClearDirty
)
269 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
271 IEnumMoniker
*enumMk
;
273 DWORD moniker_count
= This
->tabLastIndex
;
275 TRACE("(%p,%p,%d)\n",iface
,pStm
,fClearDirty
);
277 /* This function calls OleSaveToStream function for each moniker within
279 * When I tested this function in windows, I usually found this constant
280 * at the beginning of the stream. I don't known why (there's no
281 * indication in the specification) !
283 res
=IStream_Write(pStm
,&moniker_count
,sizeof(moniker_count
),NULL
);
284 if (FAILED(res
)) return res
;
286 IMoniker_Enum(iface
,TRUE
,&enumMk
);
288 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
290 res
=OleSaveToStream((IPersistStream
*)pmk
,pStm
);
292 IMoniker_Release(pmk
);
296 IEnumMoniker_Release(enumMk
);
301 IEnumMoniker_Release(enumMk
);
306 /******************************************************************************
307 * CompositeMoniker_GetSizeMax
308 ******************************************************************************/
309 static HRESULT WINAPI
310 CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
,ULARGE_INTEGER
* pcbSize
)
312 IEnumMoniker
*enumMk
;
314 ULARGE_INTEGER ptmpSize
;
316 /* The sizeMax of this object is calculated by calling GetSizeMax on
317 * each moniker within this object then summing all returned values
320 TRACE("(%p,%p)\n",iface
,pcbSize
);
325 pcbSize
->QuadPart
= sizeof(DWORD
);
327 IMoniker_Enum(iface
,TRUE
,&enumMk
);
329 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
331 IMoniker_GetSizeMax(pmk
,&ptmpSize
);
333 IMoniker_Release(pmk
);
335 pcbSize
->QuadPart
= ptmpSize
.QuadPart
+ sizeof(CLSID
);
338 IEnumMoniker_Release(enumMk
);
343 /******************************************************************************
344 * CompositeMoniker_BindToObject
345 ******************************************************************************/
346 static HRESULT WINAPI
347 CompositeMonikerImpl_BindToObject(IMoniker
* iface
, IBindCtx
* pbc
,
348 IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
)
351 IRunningObjectTable
*prot
;
352 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
353 IEnumMoniker
*enumMoniker
;
355 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
361 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
362 /* object for the requested interface pointer. */
365 res
=IBindCtx_GetRunningObjectTable(pbc
,&prot
);
369 /* if the requested class was loaded before ! we don't need to reload it */
370 res
= IRunningObjectTable_GetObject(prot
,iface
,(IUnknown
**)ppvResult
);
377 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
378 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
380 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
381 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
382 IEnumMoniker_Release(enumMoniker
);
384 res
=CreateAntiMoniker(&antiMk
);
385 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
386 IMoniker_Release(antiMk
);
388 res
=IMoniker_BindToObject(mostRigthMk
,pbc
,tempMk
,riid
,ppvResult
);
390 IMoniker_Release(tempMk
);
391 IMoniker_Release(mostRigthMk
);
397 /******************************************************************************
398 * CompositeMoniker_BindToStorage
399 ******************************************************************************/
400 static HRESULT WINAPI
401 CompositeMonikerImpl_BindToStorage(IMoniker
* iface
, IBindCtx
* pbc
,
402 IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
)
405 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*leftMk
;
406 IEnumMoniker
*enumMoniker
;
408 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
412 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
413 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
417 res
= IMoniker_ComposeWith(pmkToLeft
, iface
, FALSE
, &leftMk
);
418 if (FAILED(res
)) return res
;
423 IMoniker_Enum(iface
, FALSE
, &enumMoniker
);
424 IEnumMoniker_Next(enumMoniker
, 1, &mostRigthMk
, NULL
);
425 IEnumMoniker_Release(enumMoniker
);
427 res
= CreateAntiMoniker(&antiMk
);
428 if (FAILED(res
)) return res
;
429 res
= IMoniker_ComposeWith(leftMk
, antiMk
, 0, &tempMk
);
430 if (FAILED(res
)) return res
;
431 IMoniker_Release(antiMk
);
433 res
= IMoniker_BindToStorage(mostRigthMk
, pbc
, tempMk
, riid
, ppvResult
);
435 IMoniker_Release(tempMk
);
437 IMoniker_Release(mostRigthMk
);
440 IMoniker_Release(leftMk
);
445 /******************************************************************************
446 * CompositeMoniker_Reduce
447 ******************************************************************************/
448 static HRESULT WINAPI
449 CompositeMonikerImpl_Reduce(IMoniker
* iface
, IBindCtx
* pbc
, DWORD dwReduceHowFar
,
450 IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
)
453 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*leftReducedComposedMk
,*mostRigthReducedMk
;
454 IEnumMoniker
*enumMoniker
;
456 TRACE("(%p,%p,%ld,%p,%p)\n",iface
,pbc
,dwReduceHowFar
,ppmkToLeft
,ppmkReduced
);
458 if (ppmkReduced
==NULL
)
461 /* This method recursively calls Reduce for each of its component monikers. */
463 if (ppmkToLeft
==NULL
){
465 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
466 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
467 IEnumMoniker_Release(enumMoniker
);
469 res
=CreateAntiMoniker(&antiMk
);
470 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
471 IMoniker_Release(antiMk
);
473 return CompositeMonikerImpl_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
, ppmkReduced
);
475 else if (*ppmkToLeft
==NULL
)
477 return IMoniker_Reduce(iface
,pbc
,dwReduceHowFar
,NULL
,ppmkReduced
);
481 /* separate the composite moniker in to left and right moniker */
482 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
483 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
484 IEnumMoniker_Release(enumMoniker
);
486 res
=CreateAntiMoniker(&antiMk
);
487 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
488 IMoniker_Release(antiMk
);
490 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
491 /* of the reduced components */
492 if (IMoniker_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,NULL
,&mostRigthReducedMk
) &&
493 CompositeMonikerImpl_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
,&leftReducedComposedMk
)
496 return CreateGenericComposite(leftReducedComposedMk
,mostRigthReducedMk
,ppmkReduced
);
499 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
501 IMoniker_AddRef(iface
);
505 return MK_S_REDUCED_TO_SELF
;
510 /******************************************************************************
511 * CompositeMoniker_ComposeWith
512 ******************************************************************************/
513 static HRESULT WINAPI
514 CompositeMonikerImpl_ComposeWith(IMoniker
* iface
, IMoniker
* pmkRight
,
515 BOOL fOnlyIfNotGeneric
, IMoniker
** ppmkComposite
)
517 TRACE("(%p,%p,%d,%p)\n",iface
,pmkRight
,fOnlyIfNotGeneric
,ppmkComposite
);
519 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
524 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
525 /* otherwise, the method returns the result of combining the two monikers by calling the */
526 /* CreateGenericComposite function */
528 if (fOnlyIfNotGeneric
)
529 return MK_E_NEEDGENERIC
;
531 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
534 /******************************************************************************
535 * CompositeMoniker_Enum
536 ******************************************************************************/
537 static HRESULT WINAPI
538 CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
540 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
542 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
544 if (ppenumMoniker
== NULL
)
547 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabLastIndex
,0,fForward
,ppenumMoniker
);
550 /******************************************************************************
551 * CompositeMoniker_IsEqual
552 ******************************************************************************/
553 static HRESULT WINAPI
554 CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
)
556 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
557 IMoniker
*tempMk1
,*tempMk2
;
558 HRESULT res1
,res2
,res
;
560 TRACE("(%p,%p)\n",iface
,pmkOtherMoniker
);
562 if (pmkOtherMoniker
==NULL
)
565 /* This method returns S_OK if the components of both monikers are equal when compared in the */
566 /* left-to-right order.*/
567 IMoniker_Enum(pmkOtherMoniker
,TRUE
,&enumMoniker1
);
569 if (enumMoniker1
==NULL
)
572 IMoniker_Enum(iface
,TRUE
,&enumMoniker2
);
576 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
577 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
579 if((res1
==S_OK
)&&(res2
==S_OK
)){
581 if(IMoniker_IsEqual(tempMk1
,tempMk2
)==S_FALSE
){
588 else if ( (res1
==S_FALSE
) && (res2
==S_FALSE
) ){
598 IMoniker_Release(tempMk1
);
601 IMoniker_Release(tempMk2
);
604 IEnumMoniker_Release(enumMoniker1
);
605 IEnumMoniker_Release(enumMoniker2
);
609 /******************************************************************************
610 * CompositeMoniker_Hash
611 ******************************************************************************/
612 static HRESULT WINAPI
613 CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
615 IEnumMoniker
*enumMoniker
;
620 TRACE("(%p,%p)\n",iface
,pdwHash
);
625 res
= IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
631 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
632 res
= IMoniker_Hash(tempMk
, &tempHash
);
635 *pdwHash
= *pdwHash
^ tempHash
;
637 IMoniker_Release(tempMk
);
640 IEnumMoniker_Release(enumMoniker
);
645 /******************************************************************************
646 * CompositeMoniker_IsRunning
647 ******************************************************************************/
648 static HRESULT WINAPI
649 CompositeMonikerImpl_IsRunning(IMoniker
* iface
, IBindCtx
* pbc
,
650 IMoniker
* pmkToLeft
, IMoniker
* pmkNewlyRunning
)
652 IRunningObjectTable
* rot
;
654 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
655 IEnumMoniker
*enumMoniker
;
657 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
659 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
660 if (pmkToLeft
!=NULL
){
662 CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
664 res
= IMoniker_IsRunning(tempMk
,pbc
,NULL
,pmkNewlyRunning
);
666 IMoniker_Release(tempMk
);
671 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
672 /* to this moniker */
674 if (pmkNewlyRunning
!=NULL
)
676 if (IMoniker_IsEqual(iface
,pmkNewlyRunning
)==S_OK
)
687 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
688 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
689 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
690 /* the composite as the pmkToLeft parameter for that call. */
692 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
697 res
= IRunningObjectTable_IsRunning(rot
,iface
);
698 IRunningObjectTable_Release(rot
);
705 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
706 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
707 IEnumMoniker_Release(enumMoniker
);
709 res
=CreateAntiMoniker(&antiMk
);
710 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
711 IMoniker_Release(antiMk
);
713 res
=IMoniker_IsRunning(mostRigthMk
,pbc
,tempMk
,pmkNewlyRunning
);
715 IMoniker_Release(tempMk
);
716 IMoniker_Release(mostRigthMk
);
723 /******************************************************************************
724 * CompositeMoniker_GetTimeOfLastChange
725 ******************************************************************************/
726 static HRESULT WINAPI
727 CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
, IBindCtx
* pbc
,
728 IMoniker
* pmkToLeft
, FILETIME
* pCompositeTime
)
731 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*leftMk
;
732 IEnumMoniker
*enumMoniker
;
734 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pCompositeTime
);
736 if (pCompositeTime
==NULL
)
739 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
740 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
741 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
742 /* of the composite as the pmkToLeft parameter for that call. */
745 IRunningObjectTable
* rot
;
747 res
= IMoniker_ComposeWith(pmkToLeft
, iface
, FALSE
, &leftMk
);
749 res
= IBindCtx_GetRunningObjectTable(pbc
,&rot
);
752 IMoniker_Release(leftMk
);
756 if (IRunningObjectTable_GetTimeOfLastChange(rot
,leftMk
,pCompositeTime
)==S_OK
)
758 IMoniker_Release(leftMk
);
765 IMoniker_Enum(iface
, FALSE
, &enumMoniker
);
766 IEnumMoniker_Next(enumMoniker
, 1, &mostRigthMk
, NULL
);
767 IEnumMoniker_Release(enumMoniker
);
769 res
= CreateAntiMoniker(&antiMk
);
770 res
= IMoniker_ComposeWith(leftMk
, antiMk
, 0, &tempMk
);
771 IMoniker_Release(antiMk
);
773 res
= IMoniker_GetTimeOfLastChange(mostRigthMk
, pbc
, tempMk
, pCompositeTime
);
775 IMoniker_Release(tempMk
);
776 IMoniker_Release(mostRigthMk
);
779 IMoniker_Release(leftMk
);
784 /******************************************************************************
785 * CompositeMoniker_Inverse
786 ******************************************************************************/
787 static HRESULT WINAPI
788 CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
791 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*tempInvMk
,*mostRigthInvMk
;
792 IEnumMoniker
*enumMoniker
;
794 TRACE("(%p,%p)\n",iface
,ppmk
);
799 /* This method returns a composite moniker that consists of the inverses of each of the components */
800 /* of the original composite, stored in reverse order */
802 res
=CreateAntiMoniker(&antiMk
);
803 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
804 IMoniker_Release(antiMk
);
808 return IMoniker_Inverse(iface
,ppmk
);
812 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
813 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
814 IEnumMoniker_Release(enumMoniker
);
816 IMoniker_Inverse(mostRigthMk
,&mostRigthInvMk
);
817 CompositeMonikerImpl_Inverse(tempMk
,&tempInvMk
);
819 res
=CreateGenericComposite(mostRigthInvMk
,tempInvMk
,ppmk
);
821 IMoniker_Release(tempMk
);
822 IMoniker_Release(mostRigthMk
);
823 IMoniker_Release(tempInvMk
);
824 IMoniker_Release(mostRigthInvMk
);
830 /******************************************************************************
831 * CompositeMoniker_CommonPrefixWith
832 ******************************************************************************/
833 static HRESULT WINAPI
834 CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
, IMoniker
* pmkOther
,
835 IMoniker
** ppmkPrefix
)
839 IMoniker
*tempMk1
,*tempMk2
,*mostLeftMk1
,*mostLeftMk2
;
840 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
841 ULONG i
,nbCommonMk
=0;
843 /* If the other moniker is a composite, this method compares the components of each composite from left */
844 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
845 /* of the leftmost components were common to both monikers. */
847 if (ppmkPrefix
==NULL
)
853 return MK_E_NOPREFIX
;
855 IMoniker_IsSystemMoniker(pmkOther
,&mkSys
);
857 if((mkSys
==MKSYS_GENERICCOMPOSITE
)){
859 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
860 IMoniker_Enum(pmkOther
,TRUE
,&enumMoniker2
);
864 res1
=IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
865 res2
=IEnumMoniker_Next(enumMoniker2
,1,&mostLeftMk2
,NULL
);
867 if ((res1
==S_FALSE
) && (res2
==S_FALSE
)){
869 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
871 IMoniker_AddRef(iface
);
874 else if ((res1
==S_OK
) && (res2
==S_OK
)){
876 if (IMoniker_IsEqual(mostLeftMk1
,mostLeftMk2
)==S_OK
)
884 else if (res1
==S_OK
){
886 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
887 /* ppmkPrefix to the other moniker. */
888 *ppmkPrefix
=pmkOther
;
892 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
893 /* to this moniker. */
899 IEnumMoniker_Release(enumMoniker1
);
900 IEnumMoniker_Release(enumMoniker2
);
902 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
904 return MK_E_NOPREFIX
;
906 IEnumMoniker_Reset(enumMoniker1
);
908 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
910 /* if we have more than one commun moniker the result will be a composite moniker */
913 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
914 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
915 CreateGenericComposite(tempMk1
,tempMk2
,ppmkPrefix
);
916 IMoniker_Release(tempMk1
);
917 IMoniker_Release(tempMk2
);
919 /* compose all common monikers in a composite moniker */
920 for(i
=0;i
<nbCommonMk
;i
++){
922 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
924 CreateGenericComposite(*ppmkPrefix
,tempMk1
,&tempMk2
);
926 IMoniker_Release(*ppmkPrefix
);
928 IMoniker_Release(tempMk1
);
935 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
942 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
945 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
947 IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
949 if (IMoniker_IsEqual(pmkOther
,mostLeftMk1
)==S_OK
){
951 *ppmkPrefix
=pmkOther
;
956 return MK_E_NOPREFIX
;
960 /***************************************************************************************************
961 * GetAfterCommonPrefix (local function)
962 * This function returns a moniker that consist of the remainder when the common prefix is removed
963 ***************************************************************************************************/
964 static VOID
GetAfterCommonPrefix(IMoniker
* pGenMk
,IMoniker
* commonMk
,IMoniker
** restMk
)
966 IMoniker
*tempMk
,*tempMk1
,*tempMk2
;
967 IEnumMoniker
*enumMoniker1
,*enumMoniker2
,*enumMoniker3
;
974 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
975 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
976 /* on the first difference. */
977 IMoniker_Enum(pGenMk
,TRUE
,&enumMoniker1
);
979 IMoniker_IsSystemMoniker(commonMk
,&mkSys
);
981 if (mkSys
==MKSYS_GENERICCOMPOSITE
){
983 IMoniker_Enum(commonMk
,TRUE
,&enumMoniker2
);
986 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
987 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
989 if ((res1
==S_FALSE
)||(res2
==S_FALSE
)){
995 IMoniker_Release(tempMk1
);
996 IMoniker_Release(tempMk1
);
1000 IMoniker_Release(tempMk1
);
1001 IMoniker_Release(tempMk1
);
1005 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1006 IMoniker_Release(tempMk1
);
1009 /* count the number of elements in the enumerator after the common prefix */
1010 IEnumMoniker_Clone(enumMoniker1
,&enumMoniker3
);
1012 for(;IEnumMoniker_Next(enumMoniker3
,1,&tempMk
,NULL
)==S_OK
;nbRestMk
++)
1014 IMoniker_Release(tempMk
);
1019 /* create a generic composite moniker with monikers located after the common prefix */
1020 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1029 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1031 CreateGenericComposite(tempMk1
,tempMk2
,restMk
);
1033 IMoniker_Release(tempMk1
);
1035 IMoniker_Release(tempMk2
);
1037 while(IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
)==S_OK
){
1039 CreateGenericComposite(*restMk
,tempMk1
,&tempMk2
);
1041 IMoniker_Release(tempMk1
);
1043 IMoniker_Release(*restMk
);
1050 /******************************************************************************
1051 * CompositeMoniker_RelativePathTo
1052 ******************************************************************************/
1053 static HRESULT WINAPI
1054 CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmkOther
,
1055 IMoniker
** ppmkRelPath
)
1058 IMoniker
*restOtherMk
=0,*restThisMk
=0,*invRestThisMk
=0,*commonMk
=0;
1060 TRACE("(%p,%p,%p)\n",iface
,pmkOther
,ppmkRelPath
);
1062 if (ppmkRelPath
==NULL
)
1067 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1068 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1069 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1071 /* finds the common prefix of the two monikers */
1072 res
=IMoniker_CommonPrefixWith(iface
,pmkOther
,&commonMk
);
1074 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1075 if ((res
== MK_E_NOPREFIX
)||(res
==MK_S_US
)){
1077 *ppmkRelPath
=pmkOther
;
1078 IMoniker_AddRef(pmkOther
);
1082 GetAfterCommonPrefix(iface
,commonMk
,&restThisMk
);
1083 GetAfterCommonPrefix(pmkOther
,commonMk
,&restOtherMk
);
1085 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1086 /* moniker when the common prefix is removed */
1089 IMoniker_Inverse(restThisMk
,ppmkRelPath
);
1090 IMoniker_Release(restThisMk
);
1092 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1093 /* when the common prefix is removed */
1094 else if (res
==MK_S_ME
){
1096 *ppmkRelPath
=restOtherMk
;
1097 IMoniker_AddRef(restOtherMk
);
1099 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1100 /* moniker on the right of it. */
1101 else if (res
==S_OK
){
1103 IMoniker_Inverse(restThisMk
,&invRestThisMk
);
1104 IMoniker_Release(restThisMk
);
1105 CreateGenericComposite(invRestThisMk
,restOtherMk
,ppmkRelPath
);
1106 IMoniker_Release(invRestThisMk
);
1107 IMoniker_Release(restOtherMk
);
1112 /******************************************************************************
1113 * CompositeMoniker_GetDisplayName
1114 ******************************************************************************/
1115 static HRESULT WINAPI
1116 CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
1117 IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
)
1120 IEnumMoniker
*enumMoniker
;
1124 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
1126 if (ppszDisplayName
==NULL
)
1129 *ppszDisplayName
=CoTaskMemAlloc(sizeof(WCHAR
));
1131 if (*ppszDisplayName
==NULL
)
1132 return E_OUTOFMEMORY
;
1134 /* This method returns the concatenation of the display names returned by each component moniker of */
1137 **ppszDisplayName
=0;
1139 IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
1141 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
1143 IMoniker_GetDisplayName(tempMk
,pbc
,NULL
,&tempStr
);
1145 lengthStr
+=lstrlenW(tempStr
);
1147 *ppszDisplayName
=CoTaskMemRealloc(*ppszDisplayName
,lengthStr
* sizeof(WCHAR
));
1149 if (*ppszDisplayName
==NULL
)
1150 return E_OUTOFMEMORY
;
1152 strcatW(*ppszDisplayName
,tempStr
);
1154 CoTaskMemFree(tempStr
);
1155 IMoniker_Release(tempMk
);
1158 IEnumMoniker_Release(enumMoniker
);
1163 /******************************************************************************
1164 * CompositeMoniker_ParseDisplayName
1165 ******************************************************************************/
1166 static HRESULT WINAPI
1167 CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
1168 IMoniker
* pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
* pchEaten
,
1171 IEnumMoniker
*enumMoniker
;
1172 IMoniker
*tempMk
,*mostRigthMk
,*antiMk
;
1173 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1174 /* passing everything else as the pmkToLeft parameter for that call. */
1176 /* get the most right moniker */
1177 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1178 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1179 IEnumMoniker_Release(enumMoniker
);
1181 /* get the left moniker */
1182 CreateAntiMoniker(&antiMk
);
1183 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1184 IMoniker_Release(antiMk
);
1186 return IMoniker_ParseDisplayName(mostRigthMk
,pbc
,tempMk
,pszDisplayName
,pchEaten
,ppmkOut
);
1189 /******************************************************************************
1190 * CompositeMoniker_IsSystemMoniker
1191 ******************************************************************************/
1192 static HRESULT WINAPI
1193 CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
1195 TRACE("(%p,%p)\n",iface
,pwdMksys
);
1200 (*pwdMksys
)=MKSYS_GENERICCOMPOSITE
;
1205 /*******************************************************************************
1206 * CompositeMonikerIROTData_QueryInterface
1207 *******************************************************************************/
1208 static HRESULT WINAPI
1209 CompositeMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,
1213 IMoniker
*This
= impl_from_IROTData(iface
);
1215 TRACE("(%p,%p,%p)\n",iface
,riid
,ppvObject
);
1217 return CompositeMonikerImpl_QueryInterface(This
, riid
, ppvObject
);
1220 /***********************************************************************
1221 * CompositeMonikerIROTData_AddRef
1224 CompositeMonikerROTDataImpl_AddRef(IROTData
*iface
)
1226 IMoniker
*This
= impl_from_IROTData(iface
);
1228 TRACE("(%p)\n",iface
);
1230 return IMoniker_AddRef(This
);
1233 /***********************************************************************
1234 * CompositeMonikerIROTData_Release
1236 static ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
)
1238 IMoniker
*This
= impl_from_IROTData(iface
);
1240 TRACE("(%p)\n",iface
);
1242 return IMoniker_Release(This
);
1245 /******************************************************************************
1246 * CompositeMonikerIROTData_GetComparisonData
1247 ******************************************************************************/
1248 static HRESULT WINAPI
1249 CompositeMonikerROTDataImpl_GetComparisonData(IROTData
* iface
,
1250 BYTE
* pbData
, ULONG cbMax
, ULONG
* pcbData
)
1252 IMoniker
*This
= impl_from_IROTData(iface
);
1253 IEnumMoniker
*pEnumMk
;
1257 TRACE("(%p, %lu, %p)\n", pbData
, cbMax
, pcbData
);
1259 *pcbData
= sizeof(CLSID
);
1261 hr
= IMoniker_Enum(This
, TRUE
, &pEnumMk
);
1262 if (FAILED(hr
)) return hr
;
1264 while(IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1267 hr
= IMoniker_QueryInterface(pmk
, &IID_IROTData
, (void **)&pROTData
);
1269 ERR("moniker doesn't support IROTData interface\n");
1274 hr
= IROTData_GetComparisonData(pROTData
, NULL
, 0, &cbData
);
1275 IROTData_Release(pROTData
);
1276 if (SUCCEEDED(hr
) || (hr
== E_OUTOFMEMORY
))
1282 ERR("IROTData_GetComparisonData failed with error 0x%08lx\n", hr
);
1285 IMoniker_Release(pmk
);
1289 IEnumMoniker_Release(pEnumMk
);
1293 if (cbMax
< *pcbData
)
1294 return E_OUTOFMEMORY
;
1296 IEnumMoniker_Reset(pEnumMk
);
1298 memcpy(pbData
, &CLSID_CompositeMoniker
, sizeof(CLSID
));
1299 pbData
+= sizeof(CLSID
);
1300 cbMax
-= sizeof(CLSID
);
1302 while (IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1305 hr
= IMoniker_QueryInterface(pmk
, &IID_IROTData
, (void **)&pROTData
);
1307 ERR("moniker doesn't support IROTData interface\n");
1312 hr
= IROTData_GetComparisonData(pROTData
, pbData
, cbMax
, &cbData
);
1313 IROTData_Release(pROTData
);
1320 ERR("IROTData_GetComparisonData failed with error 0x%08lx\n", hr
);
1323 IMoniker_Release(pmk
);
1327 IEnumMoniker_Release(pEnumMk
);
1332 IEnumMoniker_Release(pEnumMk
);
1337 static HRESULT WINAPI
CompositeMonikerMarshalImpl_QueryInterface(IMarshal
*iface
, REFIID riid
, LPVOID
*ppv
)
1339 IMoniker
*This
= impl_from_IMarshal(iface
);
1341 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppv
);
1343 return CompositeMonikerImpl_QueryInterface(This
, riid
, ppv
);
1346 static ULONG WINAPI
CompositeMonikerMarshalImpl_AddRef(IMarshal
*iface
)
1348 IMoniker
*This
= impl_from_IMarshal(iface
);
1350 TRACE("(%p)\n",iface
);
1352 return CompositeMonikerImpl_AddRef(This
);
1355 static ULONG WINAPI
CompositeMonikerMarshalImpl_Release(IMarshal
*iface
)
1357 IMoniker
*This
= impl_from_IMarshal(iface
);
1359 TRACE("(%p)\n",iface
);
1361 return CompositeMonikerImpl_Release(This
);
1364 static HRESULT WINAPI
CompositeMonikerMarshalImpl_GetUnmarshalClass(
1365 LPMARSHAL iface
, REFIID riid
, void* pv
, DWORD dwDestContext
,
1366 void* pvDestContext
, DWORD mshlflags
, CLSID
* pCid
)
1368 IMoniker
*This
= impl_from_IMarshal(iface
);
1370 TRACE("(%s, %p, %lx, %p, %lx, %p)\n", debugstr_guid(riid
), pv
,
1371 dwDestContext
, pvDestContext
, mshlflags
, pCid
);
1373 return IMoniker_GetClassID(This
, pCid
);
1376 static HRESULT WINAPI
CompositeMonikerMarshalImpl_GetMarshalSizeMax(
1377 LPMARSHAL iface
, REFIID riid
, void* pv
, DWORD dwDestContext
,
1378 void* pvDestContext
, DWORD mshlflags
, DWORD
* pSize
)
1380 IMoniker
*This
= impl_from_IMarshal(iface
);
1381 IEnumMoniker
*pEnumMk
;
1384 ULARGE_INTEGER size
;
1386 TRACE("(%s, %p, %lx, %p, %lx, %p)\n", debugstr_guid(riid
), pv
,
1387 dwDestContext
, pvDestContext
, mshlflags
, pSize
);
1389 *pSize
= 0x10; /* to match native */
1391 hr
= IMoniker_Enum(This
, TRUE
, &pEnumMk
);
1392 if (FAILED(hr
)) return hr
;
1394 hr
= IMoniker_GetSizeMax(This
, &size
);
1396 while (IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1400 hr
= CoGetMarshalSizeMax(&size
, &IID_IMoniker
, (IUnknown
*)pmk
, dwDestContext
, pvDestContext
, mshlflags
);
1404 IMoniker_Release(pmk
);
1408 IEnumMoniker_Release(pEnumMk
);
1413 IEnumMoniker_Release(pEnumMk
);
1418 static HRESULT WINAPI
CompositeMonikerMarshalImpl_MarshalInterface(LPMARSHAL iface
, IStream
*pStm
,
1419 REFIID riid
, void* pv
, DWORD dwDestContext
,
1420 void* pvDestContext
, DWORD mshlflags
)
1422 IMoniker
*This
= impl_from_IMarshal(iface
);
1423 IEnumMoniker
*pEnumMk
;
1428 TRACE("(%p, %s, %p, %lx, %p, %lx)\n", pStm
, debugstr_guid(riid
), pv
,
1429 dwDestContext
, pvDestContext
, mshlflags
);
1431 hr
= IMoniker_Enum(This
, TRUE
, &pEnumMk
);
1432 if (FAILED(hr
)) return hr
;
1434 while (IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1436 hr
= CoMarshalInterface(pStm
, &IID_IMoniker
, (IUnknown
*)pmk
, dwDestContext
, pvDestContext
, mshlflags
);
1438 IMoniker_Release(pmk
);
1442 IEnumMoniker_Release(pEnumMk
);
1449 FIXME("moniker count of %ld not supported\n", i
);
1451 IEnumMoniker_Release(pEnumMk
);
1456 static HRESULT WINAPI
CompositeMonikerMarshalImpl_UnmarshalInterface(LPMARSHAL iface
, IStream
*pStm
, REFIID riid
, void **ppv
)
1458 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)impl_from_IMarshal(iface
);
1461 TRACE("(%p, %s, %p)\n", pStm
, debugstr_guid(riid
), ppv
);
1463 CompositeMonikerImpl_ReleaseMonikersInTable(This
);
1465 /* resize the table if needed */
1466 if (This
->tabLastIndex
+ 2 > This
->tabSize
)
1468 This
->tabSize
+= max(BLOCK_TAB_SIZE
, 2);
1469 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1471 if (This
->tabMoniker
==NULL
)
1472 return E_OUTOFMEMORY
;
1475 hr
= CoUnmarshalInterface(pStm
, &IID_IMoniker
, (void**)&This
->tabMoniker
[This
->tabLastIndex
]);
1478 ERR("couldn't unmarshal moniker, hr = 0x%08lx\n", hr
);
1481 This
->tabLastIndex
++;
1482 hr
= CoUnmarshalInterface(pStm
, &IID_IMoniker
, (void**)&This
->tabMoniker
[This
->tabLastIndex
]);
1485 ERR("couldn't unmarshal moniker, hr = 0x%08lx\n", hr
);
1488 This
->tabLastIndex
++;
1490 return IMoniker_QueryInterface((IMoniker
*)&This
->lpvtbl1
, riid
, ppv
);
1493 static HRESULT WINAPI
CompositeMonikerMarshalImpl_ReleaseMarshalData(LPMARSHAL iface
, IStream
*pStm
)
1495 TRACE("(%p)\n", pStm
);
1496 /* can't release a state-based marshal as nothing on server side to
1501 static HRESULT WINAPI
CompositeMonikerMarshalImpl_DisconnectObject(LPMARSHAL iface
, DWORD dwReserved
)
1503 TRACE("(0x%lx)\n", dwReserved
);
1504 /* can't disconnect a state-based marshal as nothing on server side to
1505 * disconnect from */
1509 /******************************************************************************
1510 * EnumMonikerImpl_QueryInterface
1511 ******************************************************************************/
1512 static HRESULT WINAPI
1513 EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
)
1515 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1517 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
1519 /* Perform a sanity check on the parameters.*/
1520 if ( (This
==0) || (ppvObject
==0) )
1521 return E_INVALIDARG
;
1523 /* Initialize the return parameter */
1526 /* Compare the riid with the interface IDs implemented by this object.*/
1527 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IEnumMoniker
, riid
))
1530 /* Check that we obtained an interface.*/
1531 if ((*ppvObject
)==0)
1532 return E_NOINTERFACE
;
1534 /* Query Interface always increases the reference count by one when it is successful */
1535 IEnumMoniker_AddRef(iface
);
1540 /******************************************************************************
1541 * EnumMonikerImpl_AddRef
1542 ******************************************************************************/
1544 EnumMonikerImpl_AddRef(IEnumMoniker
* iface
)
1546 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1548 TRACE("(%p)\n",This
);
1550 return InterlockedIncrement(&This
->ref
);
1554 /******************************************************************************
1555 * EnumMonikerImpl_Release
1556 ******************************************************************************/
1558 EnumMonikerImpl_Release(IEnumMoniker
* iface
)
1560 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1563 TRACE("(%p)\n",This
);
1565 ref
= InterlockedDecrement(&This
->ref
);
1567 /* destroy the object if there's no more reference on it */
1570 for(i
=0;i
<This
->tabSize
;i
++)
1571 IMoniker_Release(This
->tabMoniker
[i
]);
1573 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
1574 HeapFree(GetProcessHeap(),0,This
);
1579 /******************************************************************************
1580 * EnumMonikerImpl_Next
1581 ******************************************************************************/
1582 static HRESULT WINAPI
1583 EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
, IMoniker
** rgelt
,
1586 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1589 /* retrieve the requested number of moniker from the current position */
1590 for(i
=0;((This
->currentPos
< This
->tabSize
) && (i
< celt
));i
++)
1592 rgelt
[i
]=This
->tabMoniker
[This
->currentPos
++];
1593 IMoniker_AddRef(rgelt
[i
]);
1596 if (pceltFethed
!=NULL
)
1605 /******************************************************************************
1606 * EnumMonikerImpl_Skip
1607 ******************************************************************************/
1608 static HRESULT WINAPI
1609 EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
)
1611 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1613 if ((This
->currentPos
+celt
) >= This
->tabSize
)
1616 This
->currentPos
+=celt
;
1621 /******************************************************************************
1622 * EnumMonikerImpl_Reset
1623 ******************************************************************************/
1624 static HRESULT WINAPI
1625 EnumMonikerImpl_Reset(IEnumMoniker
* iface
)
1628 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1635 /******************************************************************************
1636 * EnumMonikerImpl_Clone
1637 ******************************************************************************/
1638 static HRESULT WINAPI
1639 EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
)
1641 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1643 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabSize
,This
->currentPos
,TRUE
,ppenum
);
1646 /********************************************************************************/
1647 /* Virtual function table for the IROTData class */
1648 static const IEnumMonikerVtbl VT_EnumMonikerImpl
=
1650 EnumMonikerImpl_QueryInterface
,
1651 EnumMonikerImpl_AddRef
,
1652 EnumMonikerImpl_Release
,
1653 EnumMonikerImpl_Next
,
1654 EnumMonikerImpl_Skip
,
1655 EnumMonikerImpl_Reset
,
1656 EnumMonikerImpl_Clone
1659 /******************************************************************************
1660 * EnumMonikerImpl_CreateEnumMoniker
1661 ******************************************************************************/
1663 EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
, ULONG tabSize
,
1664 ULONG currentPos
, BOOL leftToRigth
, IEnumMoniker
** ppmk
)
1666 EnumMonikerImpl
* newEnumMoniker
;
1669 if (currentPos
> tabSize
)
1670 return E_INVALIDARG
;
1672 newEnumMoniker
= HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl
));
1674 if (newEnumMoniker
== 0)
1675 return STG_E_INSUFFICIENTMEMORY
;
1677 /* Initialize the virtual function table. */
1678 newEnumMoniker
->lpVtbl
= &VT_EnumMonikerImpl
;
1679 newEnumMoniker
->ref
= 1;
1681 newEnumMoniker
->tabSize
=tabSize
;
1682 newEnumMoniker
->currentPos
=currentPos
;
1684 newEnumMoniker
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,tabSize
*sizeof(IMoniker
));
1686 if (newEnumMoniker
->tabMoniker
==NULL
) {
1687 HeapFree(GetProcessHeap(), 0, newEnumMoniker
);
1688 return E_OUTOFMEMORY
;
1692 for (i
=0;i
<tabSize
;i
++){
1694 newEnumMoniker
->tabMoniker
[i
]=tabMoniker
[i
];
1695 IMoniker_AddRef(tabMoniker
[i
]);
1698 for (i
=tabSize
-1;i
>=0;i
--){
1700 newEnumMoniker
->tabMoniker
[tabSize
-i
-1]=tabMoniker
[i
];
1701 IMoniker_AddRef(tabMoniker
[i
]);
1704 *ppmk
=(IEnumMoniker
*)newEnumMoniker
;
1709 /********************************************************************************/
1710 /* Virtual function table for the CompositeMonikerImpl class which includes */
1711 /* IPersist, IPersistStream and IMoniker functions. */
1713 static const IMonikerVtbl VT_CompositeMonikerImpl
=
1715 CompositeMonikerImpl_QueryInterface
,
1716 CompositeMonikerImpl_AddRef
,
1717 CompositeMonikerImpl_Release
,
1718 CompositeMonikerImpl_GetClassID
,
1719 CompositeMonikerImpl_IsDirty
,
1720 CompositeMonikerImpl_Load
,
1721 CompositeMonikerImpl_Save
,
1722 CompositeMonikerImpl_GetSizeMax
,
1723 CompositeMonikerImpl_BindToObject
,
1724 CompositeMonikerImpl_BindToStorage
,
1725 CompositeMonikerImpl_Reduce
,
1726 CompositeMonikerImpl_ComposeWith
,
1727 CompositeMonikerImpl_Enum
,
1728 CompositeMonikerImpl_IsEqual
,
1729 CompositeMonikerImpl_Hash
,
1730 CompositeMonikerImpl_IsRunning
,
1731 CompositeMonikerImpl_GetTimeOfLastChange
,
1732 CompositeMonikerImpl_Inverse
,
1733 CompositeMonikerImpl_CommonPrefixWith
,
1734 CompositeMonikerImpl_RelativePathTo
,
1735 CompositeMonikerImpl_GetDisplayName
,
1736 CompositeMonikerImpl_ParseDisplayName
,
1737 CompositeMonikerImpl_IsSystemMoniker
1740 /********************************************************************************/
1741 /* Virtual function table for the IROTData class. */
1742 static const IROTDataVtbl VT_ROTDataImpl
=
1744 CompositeMonikerROTDataImpl_QueryInterface
,
1745 CompositeMonikerROTDataImpl_AddRef
,
1746 CompositeMonikerROTDataImpl_Release
,
1747 CompositeMonikerROTDataImpl_GetComparisonData
1750 static const IMarshalVtbl VT_MarshalImpl
=
1752 CompositeMonikerMarshalImpl_QueryInterface
,
1753 CompositeMonikerMarshalImpl_AddRef
,
1754 CompositeMonikerMarshalImpl_Release
,
1755 CompositeMonikerMarshalImpl_GetUnmarshalClass
,
1756 CompositeMonikerMarshalImpl_GetMarshalSizeMax
,
1757 CompositeMonikerMarshalImpl_MarshalInterface
,
1758 CompositeMonikerMarshalImpl_UnmarshalInterface
,
1759 CompositeMonikerMarshalImpl_ReleaseMarshalData
,
1760 CompositeMonikerMarshalImpl_DisconnectObject
1763 /******************************************************************************
1764 * Composite-Moniker_Construct (local function)
1765 *******************************************************************************/
1767 CompositeMonikerImpl_Construct(IMoniker
** ppMoniker
,
1768 LPMONIKER pmkFirst
, LPMONIKER pmkRest
)
1771 IEnumMoniker
*enumMoniker
;
1774 CompositeMonikerImpl
*This
;
1776 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1779 return E_OUTOFMEMORY
;
1781 TRACE("(%p,%p,%p)\n",This
,pmkFirst
,pmkRest
);
1783 /* Initialize the virtual function table. */
1784 This
->lpvtbl1
= &VT_CompositeMonikerImpl
;
1785 This
->lpvtbl2
= &VT_ROTDataImpl
;
1786 This
->lpvtblMarshal
= &VT_MarshalImpl
;
1789 This
->tabSize
=BLOCK_TAB_SIZE
;
1790 This
->tabLastIndex
=0;
1792 This
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,This
->tabSize
*sizeof(IMoniker
));
1793 if (This
->tabMoniker
==NULL
)
1794 return E_OUTOFMEMORY
;
1796 if (!pmkFirst
&& !pmkRest
)
1798 *ppMoniker
= (IMoniker
*)This
;
1802 IMoniker_IsSystemMoniker(pmkFirst
,&mkSys
);
1804 /* put the first moniker contents in the beginning of the table */
1805 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
1807 This
->tabMoniker
[(This
->tabLastIndex
)++]=pmkFirst
;
1808 IMoniker_AddRef(pmkFirst
);
1812 IMoniker_Enum(pmkFirst
,TRUE
,&enumMoniker
);
1814 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
1817 if (++This
->tabLastIndex
==This
->tabSize
){
1819 This
->tabSize
+=BLOCK_TAB_SIZE
;
1820 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1822 if (This
->tabMoniker
==NULL
)
1823 return E_OUTOFMEMORY
;
1827 IEnumMoniker_Release(enumMoniker
);
1830 /* put the rest moniker contents after the first one and make simplification if needed */
1832 IMoniker_IsSystemMoniker(pmkRest
,&mkSys
);
1834 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
1836 /* add a simple moniker to the moniker table */
1838 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],pmkRest
,TRUE
,&tempMk
);
1840 if (res
==MK_E_NEEDGENERIC
){
1842 /* there's no simplification in this case */
1843 This
->tabMoniker
[This
->tabLastIndex
]=pmkRest
;
1845 This
->tabLastIndex
++;
1847 IMoniker_AddRef(pmkRest
);
1849 else if (tempMk
==NULL
){
1851 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
1852 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1854 This
->tabLastIndex
--;
1856 else if (SUCCEEDED(res
)){
1858 /* the non-generic composition was successful so we can make a simplification in this case */
1859 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1861 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
1865 /* resize tabMoniker if needed */
1866 if (This
->tabLastIndex
==This
->tabSize
){
1868 This
->tabSize
+=BLOCK_TAB_SIZE
;
1870 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1872 if (This
->tabMoniker
==NULL
)
1873 return E_OUTOFMEMORY
;
1878 /* add a composite moniker to the moniker table (do the same thing
1879 * for each moniker within the composite moniker as a simple moniker
1880 * (see above for how to add a simple moniker case) )
1882 IMoniker_Enum(pmkRest
,TRUE
,&enumMoniker
);
1884 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
1886 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],This
->tabMoniker
[This
->tabLastIndex
],TRUE
,&tempMk
);
1888 if (res
==MK_E_NEEDGENERIC
){
1890 This
->tabLastIndex
++;
1892 else if (tempMk
==NULL
){
1894 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1895 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
]);
1896 This
->tabLastIndex
--;
1900 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1902 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
1905 if (This
->tabLastIndex
==This
->tabSize
){
1907 This
->tabSize
+=BLOCK_TAB_SIZE
;
1909 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1911 if (This
->tabMoniker
==NULL
)
1912 return E_OUTOFMEMORY
;
1916 IEnumMoniker_Release(enumMoniker
);
1919 /* only one moniker, then just return it */
1920 if (This
->tabLastIndex
== 1)
1922 *ppMoniker
= This
->tabMoniker
[0];
1923 IMoniker_AddRef(*ppMoniker
);
1924 IMoniker_Release((IMoniker
*)This
);
1927 *ppMoniker
= (IMoniker
*)This
;
1932 /******************************************************************************
1933 * CreateGenericComposite [OLE32.@]
1934 ******************************************************************************/
1936 CreateGenericComposite(LPMONIKER pmkFirst
, LPMONIKER pmkRest
,
1937 LPMONIKER
* ppmkComposite
)
1939 IMoniker
* moniker
= 0;
1942 TRACE("(%p,%p,%p)\n",pmkFirst
,pmkRest
,ppmkComposite
);
1944 if (ppmkComposite
==NULL
)
1949 if (pmkFirst
==NULL
&& pmkRest
!=NULL
){
1951 *ppmkComposite
=pmkRest
;
1954 else if (pmkFirst
!=NULL
&& pmkRest
==NULL
){
1955 *ppmkComposite
=pmkFirst
;
1958 else if (pmkFirst
==NULL
&& pmkRest
==NULL
)
1961 hr
= CompositeMonikerImpl_Construct(&moniker
,pmkFirst
,pmkRest
);
1966 hr
= IMoniker_QueryInterface(moniker
,&IID_IMoniker
,(void**)ppmkComposite
);
1967 IMoniker_Release(moniker
);
1972 /******************************************************************************
1973 * MonikerCommonPrefixWith [OLE32.@]
1974 ******************************************************************************/
1976 MonikerCommonPrefixWith(IMoniker
* pmkThis
,IMoniker
* pmkOther
,IMoniker
** ppmkCommon
)
1978 FIXME("(),stub!\n");
1982 static HRESULT WINAPI
CompositeMonikerCF_QueryInterface(LPCLASSFACTORY iface
,
1983 REFIID riid
, LPVOID
*ppv
)
1986 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IClassFactory
))
1989 IUnknown_AddRef(iface
);
1992 return E_NOINTERFACE
;
1995 static ULONG WINAPI
CompositeMonikerCF_AddRef(LPCLASSFACTORY iface
)
1997 return 2; /* non-heap based object */
2000 static ULONG WINAPI
CompositeMonikerCF_Release(LPCLASSFACTORY iface
)
2002 return 1; /* non-heap based object */
2005 static HRESULT WINAPI
CompositeMonikerCF_CreateInstance(LPCLASSFACTORY iface
,
2006 LPUNKNOWN pUnk
, REFIID riid
, LPVOID
*ppv
)
2011 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
2016 return CLASS_E_NOAGGREGATION
;
2018 hr
= CompositeMonikerImpl_Construct(&pMoniker
, NULL
, NULL
);
2022 hr
= IMoniker_QueryInterface(pMoniker
, riid
, ppv
);
2023 IMoniker_Release(pMoniker
);
2029 static HRESULT WINAPI
CompositeMonikerCF_LockServer(LPCLASSFACTORY iface
, BOOL fLock
)
2031 FIXME("(%d), stub!\n",fLock
);
2035 static const IClassFactoryVtbl CompositeMonikerCFVtbl
=
2037 CompositeMonikerCF_QueryInterface
,
2038 CompositeMonikerCF_AddRef
,
2039 CompositeMonikerCF_Release
,
2040 CompositeMonikerCF_CreateInstance
,
2041 CompositeMonikerCF_LockServer
2043 static const IClassFactoryVtbl
*CompositeMonikerCF
= &CompositeMonikerCFVtbl
;
2045 HRESULT
CompositeMonikerCF_Create(REFIID riid
, LPVOID
*ppv
)
2047 return IClassFactory_QueryInterface((IClassFactory
*)&CompositeMonikerCF
, riid
, ppv
);