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 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
42 /* CompositeMoniker data structure */
43 typedef struct CompositeMonikerImpl
{
45 const IMonikerVtbl
* lpvtbl1
; /* VTable relative to the IMoniker interface.*/
47 /* The ROT (RunningObjectTable implementation) uses the IROTData
48 * interface to test whether two monikers are equal. That's why IROTData
49 * interface is implemented by monikers.
51 const IROTDataVtbl
* lpvtbl2
; /* VTable relative to the IROTData interface.*/
53 const IMarshalVtbl
* lpvtblMarshal
; /* VTable relative to the IMarshal interface.*/
55 LONG ref
; /* reference counter for this object */
57 IMoniker
** tabMoniker
; /* dynamic table containing all components (monikers) of this composite moniker */
59 ULONG tabSize
; /* size of tabMoniker */
61 ULONG tabLastIndex
; /* first free index in tabMoniker */
63 } CompositeMonikerImpl
;
66 /* EnumMoniker data structure */
67 typedef struct EnumMonikerImpl
{
69 const IEnumMonikerVtbl
*lpVtbl
; /* VTable relative to the IEnumMoniker interface.*/
71 LONG ref
; /* reference counter for this object */
73 IMoniker
** tabMoniker
; /* dynamic table containing the enumerated monikers */
75 ULONG tabSize
; /* size of tabMoniker */
77 ULONG currentPos
; /* index pointer on the current moniker */
81 static inline IMoniker
*impl_from_IROTData( IROTData
*iface
)
83 return (IMoniker
*)((char*)iface
- FIELD_OFFSET(CompositeMonikerImpl
, lpvtbl2
));
86 static inline IMoniker
*impl_from_IMarshal( IMarshal
*iface
)
88 return (IMoniker
*)((char*)iface
- FIELD_OFFSET(CompositeMonikerImpl
, lpvtblMarshal
));
91 static HRESULT
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,ULONG tabSize
,ULONG currentPos
,BOOL leftToRigth
,IEnumMoniker
** ppmk
);
93 /*******************************************************************************
94 * CompositeMoniker_QueryInterface
95 *******************************************************************************/
97 CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
99 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
101 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
103 /* Perform a sanity check on the parameters.*/
104 if ( (This
==0) || (ppvObject
==0) )
107 /* Initialize the return parameter */
110 /* Compare the riid with the interface IDs implemented by this object.*/
111 if (IsEqualIID(&IID_IUnknown
, riid
) ||
112 IsEqualIID(&IID_IPersist
, riid
) ||
113 IsEqualIID(&IID_IPersistStream
, riid
) ||
114 IsEqualIID(&IID_IMoniker
, riid
)
117 else if (IsEqualIID(&IID_IROTData
, riid
))
118 *ppvObject
= &This
->lpvtbl2
;
119 else if (IsEqualIID(&IID_IMarshal
, riid
))
120 *ppvObject
= &This
->lpvtblMarshal
;
122 /* Check that we obtained an interface.*/
124 return E_NOINTERFACE
;
126 /* Query Interface always increases the reference count by one when it is successful */
127 IMoniker_AddRef(iface
);
132 /******************************************************************************
133 * CompositeMoniker_AddRef
134 ******************************************************************************/
136 CompositeMonikerImpl_AddRef(IMoniker
* iface
)
138 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
140 TRACE("(%p)\n",This
);
142 return InterlockedIncrement(&This
->ref
);
145 static void CompositeMonikerImpl_ReleaseMonikersInTable(CompositeMonikerImpl
*This
)
149 for (i
= 0; i
< This
->tabLastIndex
; i
++)
150 IMoniker_Release(This
->tabMoniker
[i
]);
152 This
->tabLastIndex
= 0;
155 /******************************************************************************
156 * CompositeMoniker_Release
157 ******************************************************************************/
159 CompositeMonikerImpl_Release(IMoniker
* iface
)
161 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
164 TRACE("(%p)\n",This
);
166 ref
= InterlockedDecrement(&This
->ref
);
168 /* destroy the object if there's no more reference on it */
171 /* release all the components before destroying this object */
172 CompositeMonikerImpl_ReleaseMonikersInTable(This
);
174 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
175 HeapFree(GetProcessHeap(),0,This
);
180 /******************************************************************************
181 * CompositeMoniker_GetClassID
182 ******************************************************************************/
183 static HRESULT WINAPI
184 CompositeMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
186 TRACE("(%p,%p)\n",iface
,pClassID
);
191 *pClassID
= CLSID_CompositeMoniker
;
196 /******************************************************************************
197 * CompositeMoniker_IsDirty
198 ******************************************************************************/
199 static HRESULT WINAPI
200 CompositeMonikerImpl_IsDirty(IMoniker
* iface
)
202 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
203 method in the OLE-provided moniker interfaces always return S_FALSE because
204 their internal state never changes. */
206 TRACE("(%p)\n",iface
);
211 /******************************************************************************
212 * CompositeMoniker_Load
213 ******************************************************************************/
214 static HRESULT WINAPI
215 CompositeMonikerImpl_Load(IMoniker
* iface
,IStream
* pStm
)
221 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
223 TRACE("(%p,%p)\n",iface
,pStm
);
225 /* this function call OleLoadFromStream function for each moniker within this object */
227 res
=IStream_Read(pStm
,&moniker_count
,sizeof(DWORD
),NULL
);
230 ERR("couldn't reading moniker count from stream\n");
234 CompositeMonikerImpl_ReleaseMonikersInTable(This
);
236 for (i
= 0; i
< moniker_count
; i
++)
238 res
=OleLoadFromStream(pStm
,&IID_IMoniker
,(void**)&This
->tabMoniker
[This
->tabLastIndex
]);
241 ERR("couldn't load moniker from stream, res = 0x%08x\n", res
);
245 /* resize the table if needed */
246 if (++This
->tabLastIndex
==This
->tabSize
){
248 This
->tabSize
+=BLOCK_TAB_SIZE
;
249 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
251 if (This
->tabMoniker
==NULL
)
252 return E_OUTOFMEMORY
;
259 /******************************************************************************
260 * CompositeMoniker_Save
261 ******************************************************************************/
262 static HRESULT WINAPI
263 CompositeMonikerImpl_Save(IMoniker
* iface
,IStream
* pStm
,BOOL fClearDirty
)
265 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
267 IEnumMoniker
*enumMk
;
269 DWORD moniker_count
= This
->tabLastIndex
;
271 TRACE("(%p,%p,%d)\n",iface
,pStm
,fClearDirty
);
273 /* This function calls OleSaveToStream function for each moniker within
275 * When I tested this function in windows, I usually found this constant
276 * at the beginning of the stream. I don't known why (there's no
277 * indication in the specification) !
279 res
=IStream_Write(pStm
,&moniker_count
,sizeof(moniker_count
),NULL
);
280 if (FAILED(res
)) return res
;
282 IMoniker_Enum(iface
,TRUE
,&enumMk
);
284 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
286 res
=OleSaveToStream((IPersistStream
*)pmk
,pStm
);
288 IMoniker_Release(pmk
);
292 IEnumMoniker_Release(enumMk
);
297 IEnumMoniker_Release(enumMk
);
302 /******************************************************************************
303 * CompositeMoniker_GetSizeMax
304 ******************************************************************************/
305 static HRESULT WINAPI
306 CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
,ULARGE_INTEGER
* pcbSize
)
308 IEnumMoniker
*enumMk
;
310 ULARGE_INTEGER ptmpSize
;
312 /* The sizeMax of this object is calculated by calling GetSizeMax on
313 * each moniker within this object then summing all returned values
316 TRACE("(%p,%p)\n",iface
,pcbSize
);
321 pcbSize
->QuadPart
= sizeof(DWORD
);
323 IMoniker_Enum(iface
,TRUE
,&enumMk
);
325 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
327 IMoniker_GetSizeMax(pmk
,&ptmpSize
);
329 IMoniker_Release(pmk
);
331 pcbSize
->QuadPart
= ptmpSize
.QuadPart
+ sizeof(CLSID
);
334 IEnumMoniker_Release(enumMk
);
339 /******************************************************************************
340 * CompositeMoniker_BindToObject
341 ******************************************************************************/
342 static HRESULT WINAPI
343 CompositeMonikerImpl_BindToObject(IMoniker
* iface
, IBindCtx
* pbc
,
344 IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
)
347 IRunningObjectTable
*prot
;
348 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
349 IEnumMoniker
*enumMoniker
;
351 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
357 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
358 /* object for the requested interface pointer. */
361 res
=IBindCtx_GetRunningObjectTable(pbc
,&prot
);
365 /* if the requested class was loaded before ! we don't need to reload it */
366 res
= IRunningObjectTable_GetObject(prot
,iface
,(IUnknown
**)ppvResult
);
373 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
374 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
376 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
377 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
378 IEnumMoniker_Release(enumMoniker
);
380 res
=CreateAntiMoniker(&antiMk
);
381 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
382 IMoniker_Release(antiMk
);
384 res
=IMoniker_BindToObject(mostRigthMk
,pbc
,tempMk
,riid
,ppvResult
);
386 IMoniker_Release(tempMk
);
387 IMoniker_Release(mostRigthMk
);
393 /******************************************************************************
394 * CompositeMoniker_BindToStorage
395 ******************************************************************************/
396 static HRESULT WINAPI
397 CompositeMonikerImpl_BindToStorage(IMoniker
* iface
, IBindCtx
* pbc
,
398 IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
)
401 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*leftMk
;
402 IEnumMoniker
*enumMoniker
;
404 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
408 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
409 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
413 res
= IMoniker_ComposeWith(pmkToLeft
, iface
, FALSE
, &leftMk
);
414 if (FAILED(res
)) return res
;
419 IMoniker_Enum(iface
, FALSE
, &enumMoniker
);
420 IEnumMoniker_Next(enumMoniker
, 1, &mostRigthMk
, NULL
);
421 IEnumMoniker_Release(enumMoniker
);
423 res
= CreateAntiMoniker(&antiMk
);
424 if (FAILED(res
)) return res
;
425 res
= IMoniker_ComposeWith(leftMk
, antiMk
, 0, &tempMk
);
426 if (FAILED(res
)) return res
;
427 IMoniker_Release(antiMk
);
429 res
= IMoniker_BindToStorage(mostRigthMk
, pbc
, tempMk
, riid
, ppvResult
);
431 IMoniker_Release(tempMk
);
433 IMoniker_Release(mostRigthMk
);
436 IMoniker_Release(leftMk
);
441 /******************************************************************************
442 * CompositeMoniker_Reduce
443 ******************************************************************************/
444 static HRESULT WINAPI
445 CompositeMonikerImpl_Reduce(IMoniker
* iface
, IBindCtx
* pbc
, DWORD dwReduceHowFar
,
446 IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
)
449 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*leftReducedComposedMk
,*mostRigthReducedMk
;
450 IEnumMoniker
*enumMoniker
;
452 TRACE("(%p,%p,%d,%p,%p)\n",iface
,pbc
,dwReduceHowFar
,ppmkToLeft
,ppmkReduced
);
454 if (ppmkReduced
==NULL
)
457 /* This method recursively calls Reduce for each of its component monikers. */
459 if (ppmkToLeft
==NULL
){
461 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
462 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
463 IEnumMoniker_Release(enumMoniker
);
465 res
=CreateAntiMoniker(&antiMk
);
466 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
467 IMoniker_Release(antiMk
);
469 return IMoniker_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
, ppmkReduced
);
471 else if (*ppmkToLeft
==NULL
)
473 return IMoniker_Reduce(iface
,pbc
,dwReduceHowFar
,NULL
,ppmkReduced
);
477 /* separate the composite moniker in to left and right moniker */
478 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
479 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
480 IEnumMoniker_Release(enumMoniker
);
482 res
=CreateAntiMoniker(&antiMk
);
483 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
484 IMoniker_Release(antiMk
);
486 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
487 /* of the reduced components */
488 if (IMoniker_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,NULL
,&mostRigthReducedMk
) &&
489 IMoniker_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
,&leftReducedComposedMk
)
492 return CreateGenericComposite(leftReducedComposedMk
,mostRigthReducedMk
,ppmkReduced
);
495 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
497 IMoniker_AddRef(iface
);
501 return MK_S_REDUCED_TO_SELF
;
506 /******************************************************************************
507 * CompositeMoniker_ComposeWith
508 ******************************************************************************/
509 static HRESULT WINAPI
510 CompositeMonikerImpl_ComposeWith(IMoniker
* iface
, IMoniker
* pmkRight
,
511 BOOL fOnlyIfNotGeneric
, IMoniker
** ppmkComposite
)
513 TRACE("(%p,%p,%d,%p)\n",iface
,pmkRight
,fOnlyIfNotGeneric
,ppmkComposite
);
515 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
520 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
521 /* otherwise, the method returns the result of combining the two monikers by calling the */
522 /* CreateGenericComposite function */
524 if (fOnlyIfNotGeneric
)
525 return MK_E_NEEDGENERIC
;
527 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
530 /******************************************************************************
531 * CompositeMoniker_Enum
532 ******************************************************************************/
533 static HRESULT WINAPI
534 CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
536 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
538 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
540 if (ppenumMoniker
== NULL
)
543 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabLastIndex
,0,fForward
,ppenumMoniker
);
546 /******************************************************************************
547 * CompositeMoniker_IsEqual
548 ******************************************************************************/
549 static HRESULT WINAPI
550 CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
)
552 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
553 IMoniker
*tempMk1
,*tempMk2
;
554 HRESULT res1
,res2
,res
;
557 TRACE("(%p,%p)\n",iface
,pmkOtherMoniker
);
559 if (pmkOtherMoniker
==NULL
)
562 /* This method returns S_OK if the components of both monikers are equal when compared in the */
563 /* left-to-right order.*/
564 IMoniker_Enum(pmkOtherMoniker
,TRUE
,&enumMoniker1
);
566 if (enumMoniker1
==NULL
)
569 IMoniker_Enum(iface
,TRUE
,&enumMoniker2
);
573 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
574 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
576 if((res1
==S_OK
)&&(res2
==S_OK
)){
577 done
= (res
= IMoniker_IsEqual(tempMk1
,tempMk2
)) == S_FALSE
;
581 res
= (res1
==S_FALSE
) && (res2
==S_FALSE
);
586 IMoniker_Release(tempMk1
);
589 IMoniker_Release(tempMk2
);
592 IEnumMoniker_Release(enumMoniker1
);
593 IEnumMoniker_Release(enumMoniker2
);
597 /******************************************************************************
598 * CompositeMoniker_Hash
599 ******************************************************************************/
600 static HRESULT WINAPI
601 CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
603 IEnumMoniker
*enumMoniker
;
608 TRACE("(%p,%p)\n",iface
,pdwHash
);
613 res
= IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
619 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
620 res
= IMoniker_Hash(tempMk
, &tempHash
);
623 *pdwHash
= *pdwHash
^ tempHash
;
625 IMoniker_Release(tempMk
);
628 IEnumMoniker_Release(enumMoniker
);
633 /******************************************************************************
634 * CompositeMoniker_IsRunning
635 ******************************************************************************/
636 static HRESULT WINAPI
637 CompositeMonikerImpl_IsRunning(IMoniker
* iface
, IBindCtx
* pbc
,
638 IMoniker
* pmkToLeft
, IMoniker
* pmkNewlyRunning
)
640 IRunningObjectTable
* rot
;
642 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
643 IEnumMoniker
*enumMoniker
;
645 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
647 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
648 if (pmkToLeft
!=NULL
){
650 CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
652 res
= IMoniker_IsRunning(tempMk
,pbc
,NULL
,pmkNewlyRunning
);
654 IMoniker_Release(tempMk
);
659 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
660 /* to this moniker */
662 if (pmkNewlyRunning
!=NULL
)
664 if (IMoniker_IsEqual(iface
,pmkNewlyRunning
)==S_OK
)
675 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
676 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
677 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
678 /* the composite as the pmkToLeft parameter for that call. */
680 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
685 res
= IRunningObjectTable_IsRunning(rot
,iface
);
686 IRunningObjectTable_Release(rot
);
693 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
694 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
695 IEnumMoniker_Release(enumMoniker
);
697 res
=CreateAntiMoniker(&antiMk
);
698 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
699 IMoniker_Release(antiMk
);
701 res
=IMoniker_IsRunning(mostRigthMk
,pbc
,tempMk
,pmkNewlyRunning
);
703 IMoniker_Release(tempMk
);
704 IMoniker_Release(mostRigthMk
);
711 /******************************************************************************
712 * CompositeMoniker_GetTimeOfLastChange
713 ******************************************************************************/
714 static HRESULT WINAPI
715 CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
, IBindCtx
* pbc
,
716 IMoniker
* pmkToLeft
, FILETIME
* pCompositeTime
)
719 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*leftMk
;
720 IEnumMoniker
*enumMoniker
;
722 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pCompositeTime
);
724 if (pCompositeTime
==NULL
)
727 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
728 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
729 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
730 /* of the composite as the pmkToLeft parameter for that call. */
733 IRunningObjectTable
* rot
;
735 res
= IMoniker_ComposeWith(pmkToLeft
, iface
, FALSE
, &leftMk
);
737 res
= IBindCtx_GetRunningObjectTable(pbc
,&rot
);
740 IMoniker_Release(leftMk
);
744 if (IRunningObjectTable_GetTimeOfLastChange(rot
,leftMk
,pCompositeTime
)==S_OK
)
746 IMoniker_Release(leftMk
);
753 IMoniker_Enum(iface
, FALSE
, &enumMoniker
);
754 IEnumMoniker_Next(enumMoniker
, 1, &mostRigthMk
, NULL
);
755 IEnumMoniker_Release(enumMoniker
);
757 res
= CreateAntiMoniker(&antiMk
);
758 res
= IMoniker_ComposeWith(leftMk
, antiMk
, 0, &tempMk
);
759 IMoniker_Release(antiMk
);
761 res
= IMoniker_GetTimeOfLastChange(mostRigthMk
, pbc
, tempMk
, pCompositeTime
);
763 IMoniker_Release(tempMk
);
764 IMoniker_Release(mostRigthMk
);
767 IMoniker_Release(leftMk
);
772 /******************************************************************************
773 * CompositeMoniker_Inverse
774 ******************************************************************************/
775 static HRESULT WINAPI
776 CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
779 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*tempInvMk
,*mostRigthInvMk
;
780 IEnumMoniker
*enumMoniker
;
782 TRACE("(%p,%p)\n",iface
,ppmk
);
787 /* This method returns a composite moniker that consists of the inverses of each of the components */
788 /* of the original composite, stored in reverse order */
790 res
=CreateAntiMoniker(&antiMk
);
791 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
792 IMoniker_Release(antiMk
);
796 return IMoniker_Inverse(iface
,ppmk
);
800 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
801 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
802 IEnumMoniker_Release(enumMoniker
);
804 IMoniker_Inverse(mostRigthMk
,&mostRigthInvMk
);
805 CompositeMonikerImpl_Inverse(tempMk
,&tempInvMk
);
807 res
=CreateGenericComposite(mostRigthInvMk
,tempInvMk
,ppmk
);
809 IMoniker_Release(tempMk
);
810 IMoniker_Release(mostRigthMk
);
811 IMoniker_Release(tempInvMk
);
812 IMoniker_Release(mostRigthInvMk
);
818 /******************************************************************************
819 * CompositeMoniker_CommonPrefixWith
820 ******************************************************************************/
821 static HRESULT WINAPI
822 CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
, IMoniker
* pmkOther
,
823 IMoniker
** ppmkPrefix
)
827 IMoniker
*tempMk1
,*tempMk2
,*mostLeftMk1
,*mostLeftMk2
;
828 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
829 ULONG i
,nbCommonMk
=0;
831 /* If the other moniker is a composite, this method compares the components of each composite from left */
832 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
833 /* of the leftmost components were common to both monikers. */
835 if (ppmkPrefix
==NULL
)
841 return MK_E_NOPREFIX
;
843 IMoniker_IsSystemMoniker(pmkOther
,&mkSys
);
845 if((mkSys
==MKSYS_GENERICCOMPOSITE
)){
847 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
848 IMoniker_Enum(pmkOther
,TRUE
,&enumMoniker2
);
852 res1
=IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
853 res2
=IEnumMoniker_Next(enumMoniker2
,1,&mostLeftMk2
,NULL
);
855 if ((res1
==S_FALSE
) && (res2
==S_FALSE
)){
857 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
859 IMoniker_AddRef(iface
);
862 else if ((res1
==S_OK
) && (res2
==S_OK
)){
864 if (IMoniker_IsEqual(mostLeftMk1
,mostLeftMk2
)==S_OK
)
872 else if (res1
==S_OK
){
874 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
875 /* ppmkPrefix to the other moniker. */
876 *ppmkPrefix
=pmkOther
;
880 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
881 /* to this moniker. */
887 IEnumMoniker_Release(enumMoniker1
);
888 IEnumMoniker_Release(enumMoniker2
);
890 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
892 return MK_E_NOPREFIX
;
894 IEnumMoniker_Reset(enumMoniker1
);
896 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
898 /* if we have more than one common moniker the result will be a composite moniker */
901 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
902 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
903 CreateGenericComposite(tempMk1
,tempMk2
,ppmkPrefix
);
904 IMoniker_Release(tempMk1
);
905 IMoniker_Release(tempMk2
);
907 /* compose all common monikers in a composite moniker */
908 for(i
=0;i
<nbCommonMk
;i
++){
910 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
912 CreateGenericComposite(*ppmkPrefix
,tempMk1
,&tempMk2
);
914 IMoniker_Release(*ppmkPrefix
);
916 IMoniker_Release(tempMk1
);
923 /* if we have only one common moniker the result will be a simple moniker which is the most-left one*/
930 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
933 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
935 IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
937 if (IMoniker_IsEqual(pmkOther
,mostLeftMk1
)==S_OK
){
939 *ppmkPrefix
=pmkOther
;
944 return MK_E_NOPREFIX
;
948 /***************************************************************************************************
949 * GetAfterCommonPrefix (local function)
950 * This function returns a moniker that consist of the remainder when the common prefix is removed
951 ***************************************************************************************************/
952 static VOID
GetAfterCommonPrefix(IMoniker
* pGenMk
,IMoniker
* commonMk
,IMoniker
** restMk
)
954 IMoniker
*tempMk
,*tempMk1
,*tempMk2
;
955 IEnumMoniker
*enumMoniker1
,*enumMoniker2
,*enumMoniker3
;
962 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
963 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
964 /* on the first difference. */
965 IMoniker_Enum(pGenMk
,TRUE
,&enumMoniker1
);
967 IMoniker_IsSystemMoniker(commonMk
,&mkSys
);
969 if (mkSys
==MKSYS_GENERICCOMPOSITE
){
971 IMoniker_Enum(commonMk
,TRUE
,&enumMoniker2
);
974 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
975 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
977 if ((res1
==S_FALSE
)||(res2
==S_FALSE
)){
983 IMoniker_Release(tempMk1
);
984 IMoniker_Release(tempMk2
);
988 IMoniker_Release(tempMk1
);
989 IMoniker_Release(tempMk2
);
993 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
994 IMoniker_Release(tempMk1
);
997 /* count the number of elements in the enumerator after the common prefix */
998 IEnumMoniker_Clone(enumMoniker1
,&enumMoniker3
);
1000 for(;IEnumMoniker_Next(enumMoniker3
,1,&tempMk
,NULL
)==S_OK
;nbRestMk
++)
1002 IMoniker_Release(tempMk
);
1007 /* create a generic composite moniker with monikers located after the common prefix */
1008 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1017 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1019 CreateGenericComposite(tempMk1
,tempMk2
,restMk
);
1021 IMoniker_Release(tempMk1
);
1023 IMoniker_Release(tempMk2
);
1025 while(IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
)==S_OK
){
1027 CreateGenericComposite(*restMk
,tempMk1
,&tempMk2
);
1029 IMoniker_Release(tempMk1
);
1031 IMoniker_Release(*restMk
);
1038 /******************************************************************************
1039 * CompositeMoniker_RelativePathTo
1040 ******************************************************************************/
1041 static HRESULT WINAPI
1042 CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmkOther
,
1043 IMoniker
** ppmkRelPath
)
1046 IMoniker
*restOtherMk
=0,*restThisMk
=0,*invRestThisMk
=0,*commonMk
=0;
1048 TRACE("(%p,%p,%p)\n",iface
,pmkOther
,ppmkRelPath
);
1050 if (ppmkRelPath
==NULL
)
1055 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1056 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1057 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1059 /* finds the common prefix of the two monikers */
1060 res
=IMoniker_CommonPrefixWith(iface
,pmkOther
,&commonMk
);
1062 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1063 if ((res
== MK_E_NOPREFIX
)||(res
==MK_S_US
)){
1065 *ppmkRelPath
=pmkOther
;
1066 IMoniker_AddRef(pmkOther
);
1070 GetAfterCommonPrefix(iface
,commonMk
,&restThisMk
);
1071 GetAfterCommonPrefix(pmkOther
,commonMk
,&restOtherMk
);
1073 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1074 /* moniker when the common prefix is removed */
1077 IMoniker_Inverse(restThisMk
,ppmkRelPath
);
1078 IMoniker_Release(restThisMk
);
1080 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1081 /* when the common prefix is removed */
1082 else if (res
==MK_S_ME
){
1084 *ppmkRelPath
=restOtherMk
;
1085 IMoniker_AddRef(restOtherMk
);
1087 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1088 /* moniker on the right of it. */
1089 else if (res
==S_OK
){
1091 IMoniker_Inverse(restThisMk
,&invRestThisMk
);
1092 IMoniker_Release(restThisMk
);
1093 CreateGenericComposite(invRestThisMk
,restOtherMk
,ppmkRelPath
);
1094 IMoniker_Release(invRestThisMk
);
1095 IMoniker_Release(restOtherMk
);
1100 /******************************************************************************
1101 * CompositeMoniker_GetDisplayName
1102 ******************************************************************************/
1103 static HRESULT WINAPI
1104 CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
1105 IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
)
1108 IEnumMoniker
*enumMoniker
;
1112 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
1114 if (ppszDisplayName
==NULL
)
1117 *ppszDisplayName
=CoTaskMemAlloc(sizeof(WCHAR
));
1119 if (*ppszDisplayName
==NULL
)
1120 return E_OUTOFMEMORY
;
1122 /* This method returns the concatenation of the display names returned by each component moniker of */
1125 **ppszDisplayName
=0;
1127 IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
1129 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
1131 IMoniker_GetDisplayName(tempMk
,pbc
,NULL
,&tempStr
);
1133 lengthStr
+=lstrlenW(tempStr
);
1135 *ppszDisplayName
=CoTaskMemRealloc(*ppszDisplayName
,lengthStr
* sizeof(WCHAR
));
1137 if (*ppszDisplayName
==NULL
)
1138 return E_OUTOFMEMORY
;
1140 strcatW(*ppszDisplayName
,tempStr
);
1142 CoTaskMemFree(tempStr
);
1143 IMoniker_Release(tempMk
);
1146 IEnumMoniker_Release(enumMoniker
);
1151 /******************************************************************************
1152 * CompositeMoniker_ParseDisplayName
1153 ******************************************************************************/
1154 static HRESULT WINAPI
1155 CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
1156 IMoniker
* pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
* pchEaten
,
1159 IEnumMoniker
*enumMoniker
;
1160 IMoniker
*tempMk
,*mostRigthMk
,*antiMk
;
1161 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1162 /* passing everything else as the pmkToLeft parameter for that call. */
1164 /* get the most right moniker */
1165 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1166 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1167 IEnumMoniker_Release(enumMoniker
);
1169 /* get the left moniker */
1170 CreateAntiMoniker(&antiMk
);
1171 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1172 IMoniker_Release(antiMk
);
1174 return IMoniker_ParseDisplayName(mostRigthMk
,pbc
,tempMk
,pszDisplayName
,pchEaten
,ppmkOut
);
1177 /******************************************************************************
1178 * CompositeMoniker_IsSystemMoniker
1179 ******************************************************************************/
1180 static HRESULT WINAPI
1181 CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
1183 TRACE("(%p,%p)\n",iface
,pwdMksys
);
1188 (*pwdMksys
)=MKSYS_GENERICCOMPOSITE
;
1193 /*******************************************************************************
1194 * CompositeMonikerIROTData_QueryInterface
1195 *******************************************************************************/
1196 static HRESULT WINAPI
1197 CompositeMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,
1201 IMoniker
*This
= impl_from_IROTData(iface
);
1203 TRACE("(%p,%p,%p)\n",iface
,riid
,ppvObject
);
1205 return CompositeMonikerImpl_QueryInterface(This
, riid
, ppvObject
);
1208 /***********************************************************************
1209 * CompositeMonikerIROTData_AddRef
1212 CompositeMonikerROTDataImpl_AddRef(IROTData
*iface
)
1214 IMoniker
*This
= impl_from_IROTData(iface
);
1216 TRACE("(%p)\n",iface
);
1218 return IMoniker_AddRef(This
);
1221 /***********************************************************************
1222 * CompositeMonikerIROTData_Release
1224 static ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
)
1226 IMoniker
*This
= impl_from_IROTData(iface
);
1228 TRACE("(%p)\n",iface
);
1230 return IMoniker_Release(This
);
1233 /******************************************************************************
1234 * CompositeMonikerIROTData_GetComparisonData
1235 ******************************************************************************/
1236 static HRESULT WINAPI
1237 CompositeMonikerROTDataImpl_GetComparisonData(IROTData
* iface
,
1238 BYTE
* pbData
, ULONG cbMax
, ULONG
* pcbData
)
1240 IMoniker
*This
= impl_from_IROTData(iface
);
1241 IEnumMoniker
*pEnumMk
;
1245 TRACE("(%p, %u, %p)\n", pbData
, cbMax
, pcbData
);
1247 *pcbData
= sizeof(CLSID
);
1249 hr
= IMoniker_Enum(This
, TRUE
, &pEnumMk
);
1250 if (FAILED(hr
)) return hr
;
1252 while(IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1255 hr
= IMoniker_QueryInterface(pmk
, &IID_IROTData
, (void **)&pROTData
);
1257 ERR("moniker doesn't support IROTData interface\n");
1262 hr
= IROTData_GetComparisonData(pROTData
, NULL
, 0, &cbData
);
1263 IROTData_Release(pROTData
);
1264 if (SUCCEEDED(hr
) || (hr
== E_OUTOFMEMORY
))
1270 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr
);
1273 IMoniker_Release(pmk
);
1277 IEnumMoniker_Release(pEnumMk
);
1281 if (cbMax
< *pcbData
)
1282 return E_OUTOFMEMORY
;
1284 IEnumMoniker_Reset(pEnumMk
);
1286 memcpy(pbData
, &CLSID_CompositeMoniker
, sizeof(CLSID
));
1287 pbData
+= sizeof(CLSID
);
1288 cbMax
-= sizeof(CLSID
);
1290 while (IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1293 hr
= IMoniker_QueryInterface(pmk
, &IID_IROTData
, (void **)&pROTData
);
1295 ERR("moniker doesn't support IROTData interface\n");
1300 hr
= IROTData_GetComparisonData(pROTData
, pbData
, cbMax
, &cbData
);
1301 IROTData_Release(pROTData
);
1308 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr
);
1311 IMoniker_Release(pmk
);
1315 IEnumMoniker_Release(pEnumMk
);
1320 IEnumMoniker_Release(pEnumMk
);
1325 static HRESULT WINAPI
CompositeMonikerMarshalImpl_QueryInterface(IMarshal
*iface
, REFIID riid
, LPVOID
*ppv
)
1327 IMoniker
*This
= impl_from_IMarshal(iface
);
1329 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppv
);
1331 return CompositeMonikerImpl_QueryInterface(This
, riid
, ppv
);
1334 static ULONG WINAPI
CompositeMonikerMarshalImpl_AddRef(IMarshal
*iface
)
1336 IMoniker
*This
= impl_from_IMarshal(iface
);
1338 TRACE("(%p)\n",iface
);
1340 return CompositeMonikerImpl_AddRef(This
);
1343 static ULONG WINAPI
CompositeMonikerMarshalImpl_Release(IMarshal
*iface
)
1345 IMoniker
*This
= impl_from_IMarshal(iface
);
1347 TRACE("(%p)\n",iface
);
1349 return CompositeMonikerImpl_Release(This
);
1352 static HRESULT WINAPI
CompositeMonikerMarshalImpl_GetUnmarshalClass(
1353 LPMARSHAL iface
, REFIID riid
, void* pv
, DWORD dwDestContext
,
1354 void* pvDestContext
, DWORD mshlflags
, CLSID
* pCid
)
1356 IMoniker
*This
= impl_from_IMarshal(iface
);
1358 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid
), pv
,
1359 dwDestContext
, pvDestContext
, mshlflags
, pCid
);
1361 return IMoniker_GetClassID(This
, pCid
);
1364 static HRESULT WINAPI
CompositeMonikerMarshalImpl_GetMarshalSizeMax(
1365 LPMARSHAL iface
, REFIID riid
, void* pv
, DWORD dwDestContext
,
1366 void* pvDestContext
, DWORD mshlflags
, DWORD
* pSize
)
1368 IMoniker
*This
= impl_from_IMarshal(iface
);
1369 IEnumMoniker
*pEnumMk
;
1372 ULARGE_INTEGER size
;
1374 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid
), pv
,
1375 dwDestContext
, pvDestContext
, mshlflags
, pSize
);
1377 *pSize
= 0x10; /* to match native */
1379 hr
= IMoniker_Enum(This
, TRUE
, &pEnumMk
);
1380 if (FAILED(hr
)) return hr
;
1382 hr
= IMoniker_GetSizeMax(This
, &size
);
1384 while (IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1388 hr
= CoGetMarshalSizeMax(&size
, &IID_IMoniker
, (IUnknown
*)pmk
, dwDestContext
, pvDestContext
, mshlflags
);
1392 IMoniker_Release(pmk
);
1396 IEnumMoniker_Release(pEnumMk
);
1401 IEnumMoniker_Release(pEnumMk
);
1406 static HRESULT WINAPI
CompositeMonikerMarshalImpl_MarshalInterface(LPMARSHAL iface
, IStream
*pStm
,
1407 REFIID riid
, void* pv
, DWORD dwDestContext
,
1408 void* pvDestContext
, DWORD mshlflags
)
1410 IMoniker
*This
= impl_from_IMarshal(iface
);
1411 IEnumMoniker
*pEnumMk
;
1416 TRACE("(%p, %s, %p, %x, %p, %x)\n", pStm
, debugstr_guid(riid
), pv
,
1417 dwDestContext
, pvDestContext
, mshlflags
);
1419 hr
= IMoniker_Enum(This
, TRUE
, &pEnumMk
);
1420 if (FAILED(hr
)) return hr
;
1422 while (IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1424 hr
= CoMarshalInterface(pStm
, &IID_IMoniker
, (IUnknown
*)pmk
, dwDestContext
, pvDestContext
, mshlflags
);
1426 IMoniker_Release(pmk
);
1430 IEnumMoniker_Release(pEnumMk
);
1437 FIXME("moniker count of %d not supported\n", i
);
1439 IEnumMoniker_Release(pEnumMk
);
1444 static HRESULT WINAPI
CompositeMonikerMarshalImpl_UnmarshalInterface(LPMARSHAL iface
, IStream
*pStm
, REFIID riid
, void **ppv
)
1446 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)impl_from_IMarshal(iface
);
1449 TRACE("(%p, %s, %p)\n", pStm
, debugstr_guid(riid
), ppv
);
1451 CompositeMonikerImpl_ReleaseMonikersInTable(This
);
1453 /* resize the table if needed */
1454 if (This
->tabLastIndex
+ 2 > This
->tabSize
)
1456 This
->tabSize
+= max(BLOCK_TAB_SIZE
, 2);
1457 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1459 if (This
->tabMoniker
==NULL
)
1460 return E_OUTOFMEMORY
;
1463 hr
= CoUnmarshalInterface(pStm
, &IID_IMoniker
, (void**)&This
->tabMoniker
[This
->tabLastIndex
]);
1466 ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr
);
1469 This
->tabLastIndex
++;
1470 hr
= CoUnmarshalInterface(pStm
, &IID_IMoniker
, (void**)&This
->tabMoniker
[This
->tabLastIndex
]);
1473 ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr
);
1476 This
->tabLastIndex
++;
1478 return IMoniker_QueryInterface((IMoniker
*)&This
->lpvtbl1
, riid
, ppv
);
1481 static HRESULT WINAPI
CompositeMonikerMarshalImpl_ReleaseMarshalData(LPMARSHAL iface
, IStream
*pStm
)
1483 TRACE("(%p)\n", pStm
);
1484 /* can't release a state-based marshal as nothing on server side to
1489 static HRESULT WINAPI
CompositeMonikerMarshalImpl_DisconnectObject(LPMARSHAL iface
, DWORD dwReserved
)
1491 TRACE("(0x%x)\n", dwReserved
);
1492 /* can't disconnect a state-based marshal as nothing on server side to
1493 * disconnect from */
1497 /******************************************************************************
1498 * EnumMonikerImpl_QueryInterface
1499 ******************************************************************************/
1500 static HRESULT WINAPI
1501 EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
)
1503 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1505 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
1507 /* Perform a sanity check on the parameters.*/
1508 if ( (This
==0) || (ppvObject
==0) )
1509 return E_INVALIDARG
;
1511 /* Initialize the return parameter */
1514 /* Compare the riid with the interface IDs implemented by this object.*/
1515 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IEnumMoniker
, riid
))
1518 /* Check that we obtained an interface.*/
1519 if ((*ppvObject
)==0)
1520 return E_NOINTERFACE
;
1522 /* Query Interface always increases the reference count by one when it is successful */
1523 IEnumMoniker_AddRef(iface
);
1528 /******************************************************************************
1529 * EnumMonikerImpl_AddRef
1530 ******************************************************************************/
1532 EnumMonikerImpl_AddRef(IEnumMoniker
* iface
)
1534 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1536 TRACE("(%p)\n",This
);
1538 return InterlockedIncrement(&This
->ref
);
1542 /******************************************************************************
1543 * EnumMonikerImpl_Release
1544 ******************************************************************************/
1546 EnumMonikerImpl_Release(IEnumMoniker
* iface
)
1548 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1551 TRACE("(%p)\n",This
);
1553 ref
= InterlockedDecrement(&This
->ref
);
1555 /* destroy the object if there's no more reference on it */
1558 for(i
=0;i
<This
->tabSize
;i
++)
1559 IMoniker_Release(This
->tabMoniker
[i
]);
1561 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
1562 HeapFree(GetProcessHeap(),0,This
);
1567 /******************************************************************************
1568 * EnumMonikerImpl_Next
1569 ******************************************************************************/
1570 static HRESULT WINAPI
1571 EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
, IMoniker
** rgelt
,
1574 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1577 /* retrieve the requested number of moniker from the current position */
1578 for(i
=0;((This
->currentPos
< This
->tabSize
) && (i
< celt
));i
++)
1580 rgelt
[i
]=This
->tabMoniker
[This
->currentPos
++];
1581 IMoniker_AddRef(rgelt
[i
]);
1584 if (pceltFethed
!=NULL
)
1593 /******************************************************************************
1594 * EnumMonikerImpl_Skip
1595 ******************************************************************************/
1596 static HRESULT WINAPI
1597 EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
)
1599 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1601 if ((This
->currentPos
+celt
) >= This
->tabSize
)
1604 This
->currentPos
+=celt
;
1609 /******************************************************************************
1610 * EnumMonikerImpl_Reset
1611 ******************************************************************************/
1612 static HRESULT WINAPI
1613 EnumMonikerImpl_Reset(IEnumMoniker
* iface
)
1616 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1623 /******************************************************************************
1624 * EnumMonikerImpl_Clone
1625 ******************************************************************************/
1626 static HRESULT WINAPI
1627 EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
)
1629 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1631 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabSize
,This
->currentPos
,TRUE
,ppenum
);
1634 /********************************************************************************/
1635 /* Virtual function table for the IROTData class */
1636 static const IEnumMonikerVtbl VT_EnumMonikerImpl
=
1638 EnumMonikerImpl_QueryInterface
,
1639 EnumMonikerImpl_AddRef
,
1640 EnumMonikerImpl_Release
,
1641 EnumMonikerImpl_Next
,
1642 EnumMonikerImpl_Skip
,
1643 EnumMonikerImpl_Reset
,
1644 EnumMonikerImpl_Clone
1647 /******************************************************************************
1648 * EnumMonikerImpl_CreateEnumMoniker
1649 ******************************************************************************/
1651 EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
, ULONG tabSize
,
1652 ULONG currentPos
, BOOL leftToRigth
, IEnumMoniker
** ppmk
)
1654 EnumMonikerImpl
* newEnumMoniker
;
1657 if (currentPos
> tabSize
)
1658 return E_INVALIDARG
;
1660 newEnumMoniker
= HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl
));
1662 if (newEnumMoniker
== 0)
1663 return STG_E_INSUFFICIENTMEMORY
;
1665 /* Initialize the virtual function table. */
1666 newEnumMoniker
->lpVtbl
= &VT_EnumMonikerImpl
;
1667 newEnumMoniker
->ref
= 1;
1669 newEnumMoniker
->tabSize
=tabSize
;
1670 newEnumMoniker
->currentPos
=currentPos
;
1672 newEnumMoniker
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,tabSize
*sizeof(IMoniker
));
1674 if (newEnumMoniker
->tabMoniker
==NULL
) {
1675 HeapFree(GetProcessHeap(), 0, newEnumMoniker
);
1676 return E_OUTOFMEMORY
;
1680 for (i
=0;i
<tabSize
;i
++){
1682 newEnumMoniker
->tabMoniker
[i
]=tabMoniker
[i
];
1683 IMoniker_AddRef(tabMoniker
[i
]);
1686 for (i
=tabSize
-1;i
>=0;i
--){
1688 newEnumMoniker
->tabMoniker
[tabSize
-i
-1]=tabMoniker
[i
];
1689 IMoniker_AddRef(tabMoniker
[i
]);
1692 *ppmk
=(IEnumMoniker
*)newEnumMoniker
;
1697 /********************************************************************************/
1698 /* Virtual function table for the CompositeMonikerImpl class which includes */
1699 /* IPersist, IPersistStream and IMoniker functions. */
1701 static const IMonikerVtbl VT_CompositeMonikerImpl
=
1703 CompositeMonikerImpl_QueryInterface
,
1704 CompositeMonikerImpl_AddRef
,
1705 CompositeMonikerImpl_Release
,
1706 CompositeMonikerImpl_GetClassID
,
1707 CompositeMonikerImpl_IsDirty
,
1708 CompositeMonikerImpl_Load
,
1709 CompositeMonikerImpl_Save
,
1710 CompositeMonikerImpl_GetSizeMax
,
1711 CompositeMonikerImpl_BindToObject
,
1712 CompositeMonikerImpl_BindToStorage
,
1713 CompositeMonikerImpl_Reduce
,
1714 CompositeMonikerImpl_ComposeWith
,
1715 CompositeMonikerImpl_Enum
,
1716 CompositeMonikerImpl_IsEqual
,
1717 CompositeMonikerImpl_Hash
,
1718 CompositeMonikerImpl_IsRunning
,
1719 CompositeMonikerImpl_GetTimeOfLastChange
,
1720 CompositeMonikerImpl_Inverse
,
1721 CompositeMonikerImpl_CommonPrefixWith
,
1722 CompositeMonikerImpl_RelativePathTo
,
1723 CompositeMonikerImpl_GetDisplayName
,
1724 CompositeMonikerImpl_ParseDisplayName
,
1725 CompositeMonikerImpl_IsSystemMoniker
1728 /********************************************************************************/
1729 /* Virtual function table for the IROTData class. */
1730 static const IROTDataVtbl VT_ROTDataImpl
=
1732 CompositeMonikerROTDataImpl_QueryInterface
,
1733 CompositeMonikerROTDataImpl_AddRef
,
1734 CompositeMonikerROTDataImpl_Release
,
1735 CompositeMonikerROTDataImpl_GetComparisonData
1738 static const IMarshalVtbl VT_MarshalImpl
=
1740 CompositeMonikerMarshalImpl_QueryInterface
,
1741 CompositeMonikerMarshalImpl_AddRef
,
1742 CompositeMonikerMarshalImpl_Release
,
1743 CompositeMonikerMarshalImpl_GetUnmarshalClass
,
1744 CompositeMonikerMarshalImpl_GetMarshalSizeMax
,
1745 CompositeMonikerMarshalImpl_MarshalInterface
,
1746 CompositeMonikerMarshalImpl_UnmarshalInterface
,
1747 CompositeMonikerMarshalImpl_ReleaseMarshalData
,
1748 CompositeMonikerMarshalImpl_DisconnectObject
1751 /******************************************************************************
1752 * Composite-Moniker_Construct (local function)
1753 *******************************************************************************/
1755 CompositeMonikerImpl_Construct(IMoniker
** ppMoniker
,
1756 LPMONIKER pmkFirst
, LPMONIKER pmkRest
)
1759 IEnumMoniker
*enumMoniker
;
1762 CompositeMonikerImpl
*This
;
1764 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1767 return E_OUTOFMEMORY
;
1769 TRACE("(%p,%p,%p)\n",This
,pmkFirst
,pmkRest
);
1771 /* Initialize the virtual function table. */
1772 This
->lpvtbl1
= &VT_CompositeMonikerImpl
;
1773 This
->lpvtbl2
= &VT_ROTDataImpl
;
1774 This
->lpvtblMarshal
= &VT_MarshalImpl
;
1777 This
->tabSize
=BLOCK_TAB_SIZE
;
1778 This
->tabLastIndex
=0;
1780 This
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,This
->tabSize
*sizeof(IMoniker
));
1781 if (This
->tabMoniker
==NULL
) {
1782 HeapFree(GetProcessHeap(), 0, This
);
1783 return E_OUTOFMEMORY
;
1786 if (!pmkFirst
&& !pmkRest
)
1788 *ppMoniker
= (IMoniker
*)This
;
1792 IMoniker_IsSystemMoniker(pmkFirst
,&mkSys
);
1794 /* put the first moniker contents in the beginning of the table */
1795 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
1797 This
->tabMoniker
[(This
->tabLastIndex
)++]=pmkFirst
;
1798 IMoniker_AddRef(pmkFirst
);
1802 IMoniker_Enum(pmkFirst
,TRUE
,&enumMoniker
);
1804 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
1807 if (++This
->tabLastIndex
==This
->tabSize
){
1808 LPVOID tab_moniker
= This
->tabMoniker
;
1810 This
->tabSize
+=BLOCK_TAB_SIZE
;
1811 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1813 if (This
->tabMoniker
==NULL
){
1814 HeapFree(GetProcessHeap(), 0, tab_moniker
);
1815 HeapFree(GetProcessHeap(), 0, This
);
1816 return E_OUTOFMEMORY
;
1821 IEnumMoniker_Release(enumMoniker
);
1824 /* put the rest moniker contents after the first one and make simplification if needed */
1826 IMoniker_IsSystemMoniker(pmkRest
,&mkSys
);
1828 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
1830 /* add a simple moniker to the moniker table */
1832 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],pmkRest
,TRUE
,&tempMk
);
1834 if (res
==MK_E_NEEDGENERIC
){
1836 /* there's no simplification in this case */
1837 This
->tabMoniker
[This
->tabLastIndex
]=pmkRest
;
1839 This
->tabLastIndex
++;
1841 IMoniker_AddRef(pmkRest
);
1843 else if (tempMk
==NULL
){
1845 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
1846 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1848 This
->tabLastIndex
--;
1850 else if (SUCCEEDED(res
)){
1852 /* the non-generic composition was successful so we can make a simplification in this case */
1853 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1855 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
1859 /* resize tabMoniker if needed */
1860 if (This
->tabLastIndex
==This
->tabSize
){
1861 LPVOID tab_moniker
= This
->tabMoniker
;
1863 This
->tabSize
+=BLOCK_TAB_SIZE
;
1865 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1867 if (This
->tabMoniker
==NULL
){
1868 HeapFree(GetProcessHeap(), 0, tab_moniker
);
1869 HeapFree(GetProcessHeap(), 0, This
);
1870 return E_OUTOFMEMORY
;
1876 /* add a composite moniker to the moniker table (do the same thing
1877 * for each moniker within the composite moniker as a simple moniker
1878 * (see above for how to add a simple moniker case) )
1880 IMoniker_Enum(pmkRest
,TRUE
,&enumMoniker
);
1882 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
1884 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],This
->tabMoniker
[This
->tabLastIndex
],TRUE
,&tempMk
);
1886 if (res
==MK_E_NEEDGENERIC
){
1888 This
->tabLastIndex
++;
1890 else if (tempMk
==NULL
){
1892 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1893 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
]);
1894 This
->tabLastIndex
--;
1898 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1900 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
1903 if (This
->tabLastIndex
==This
->tabSize
){
1904 LPVOID tab_moniker
= This
->tabMoniker
;
1906 This
->tabSize
+=BLOCK_TAB_SIZE
;
1908 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1910 if (This
->tabMoniker
==NULL
){
1911 HeapFree(GetProcessHeap(), 0, tab_moniker
);
1912 HeapFree(GetProcessHeap(), 0, This
);
1913 return E_OUTOFMEMORY
;
1918 IEnumMoniker_Release(enumMoniker
);
1921 /* only one moniker, then just return it */
1922 if (This
->tabLastIndex
== 1)
1924 *ppMoniker
= This
->tabMoniker
[0];
1925 IMoniker_AddRef(*ppMoniker
);
1926 IMoniker_Release((IMoniker
*)This
);
1929 *ppMoniker
= (IMoniker
*)This
;
1934 /******************************************************************************
1935 * CreateGenericComposite [OLE32.@]
1936 ******************************************************************************/
1938 CreateGenericComposite(LPMONIKER pmkFirst
, LPMONIKER pmkRest
,
1939 LPMONIKER
* ppmkComposite
)
1941 IMoniker
* moniker
= 0;
1944 TRACE("(%p,%p,%p)\n",pmkFirst
,pmkRest
,ppmkComposite
);
1946 if (ppmkComposite
==NULL
)
1951 if (pmkFirst
==NULL
&& pmkRest
!=NULL
){
1953 *ppmkComposite
=pmkRest
;
1956 else if (pmkFirst
!=NULL
&& pmkRest
==NULL
){
1957 *ppmkComposite
=pmkFirst
;
1960 else if (pmkFirst
==NULL
&& pmkRest
==NULL
)
1963 hr
= CompositeMonikerImpl_Construct(&moniker
,pmkFirst
,pmkRest
);
1968 hr
= IMoniker_QueryInterface(moniker
,&IID_IMoniker
,(void**)ppmkComposite
);
1969 IMoniker_Release(moniker
);
1974 /******************************************************************************
1975 * MonikerCommonPrefixWith [OLE32.@]
1976 ******************************************************************************/
1978 MonikerCommonPrefixWith(IMoniker
* pmkThis
,IMoniker
* pmkOther
,IMoniker
** ppmkCommon
)
1980 FIXME("(),stub!\n");
1984 static HRESULT WINAPI
CompositeMonikerCF_QueryInterface(LPCLASSFACTORY iface
,
1985 REFIID riid
, LPVOID
*ppv
)
1988 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IClassFactory
))
1991 IUnknown_AddRef(iface
);
1994 return E_NOINTERFACE
;
1997 static ULONG WINAPI
CompositeMonikerCF_AddRef(LPCLASSFACTORY iface
)
1999 return 2; /* non-heap based object */
2002 static ULONG WINAPI
CompositeMonikerCF_Release(LPCLASSFACTORY iface
)
2004 return 1; /* non-heap based object */
2007 static HRESULT WINAPI
CompositeMonikerCF_CreateInstance(LPCLASSFACTORY iface
,
2008 LPUNKNOWN pUnk
, REFIID riid
, LPVOID
*ppv
)
2013 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
2018 return CLASS_E_NOAGGREGATION
;
2020 hr
= CompositeMonikerImpl_Construct(&pMoniker
, NULL
, NULL
);
2024 hr
= IMoniker_QueryInterface(pMoniker
, riid
, ppv
);
2025 IMoniker_Release(pMoniker
);
2031 static HRESULT WINAPI
CompositeMonikerCF_LockServer(LPCLASSFACTORY iface
, BOOL fLock
)
2033 FIXME("(%d), stub!\n",fLock
);
2037 static const IClassFactoryVtbl CompositeMonikerCFVtbl
=
2039 CompositeMonikerCF_QueryInterface
,
2040 CompositeMonikerCF_AddRef
,
2041 CompositeMonikerCF_Release
,
2042 CompositeMonikerCF_CreateInstance
,
2043 CompositeMonikerCF_LockServer
2045 static const IClassFactoryVtbl
*CompositeMonikerCF
= &CompositeMonikerCFVtbl
;
2047 HRESULT
CompositeMonikerCF_Create(REFIID riid
, LPVOID
*ppv
)
2049 return IClassFactory_QueryInterface((IClassFactory
*)&CompositeMonikerCF
, riid
, ppv
);