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
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
38 #define BLOCK_TAB_SIZE 5 /* represent the first size table and its increment block size */
40 /* CompositeMoniker data structure */
41 typedef struct CompositeMonikerImpl
{
42 IMoniker IMoniker_iface
;
43 IROTData IROTData_iface
;
44 IMarshal IMarshal_iface
;
46 IMoniker
** tabMoniker
; /* dynamic table containing all components (monikers) of this composite moniker */
47 ULONG tabSize
; /* size of tabMoniker */
48 ULONG tabLastIndex
; /* first free index in tabMoniker */
49 } CompositeMonikerImpl
;
51 static inline CompositeMonikerImpl
*impl_from_IMoniker(IMoniker
*iface
)
53 return CONTAINING_RECORD(iface
, CompositeMonikerImpl
, IMoniker_iface
);
56 static inline CompositeMonikerImpl
*impl_from_IROTData(IROTData
*iface
)
58 return CONTAINING_RECORD(iface
, CompositeMonikerImpl
, IROTData_iface
);
61 static inline CompositeMonikerImpl
*impl_from_IMarshal(IMarshal
*iface
)
63 return CONTAINING_RECORD(iface
, CompositeMonikerImpl
, IMarshal_iface
);
66 /* EnumMoniker data structure */
67 typedef struct EnumMonikerImpl
{
68 IEnumMoniker IEnumMoniker_iface
;
70 IMoniker
** tabMoniker
; /* dynamic table containing the enumerated monikers */
71 ULONG tabSize
; /* size of tabMoniker */
72 ULONG currentPos
; /* index pointer on the current moniker */
75 static inline EnumMonikerImpl
*impl_from_IEnumMoniker(IEnumMoniker
*iface
)
77 return CONTAINING_RECORD(iface
, EnumMonikerImpl
, IEnumMoniker_iface
);
80 static HRESULT
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,ULONG tabSize
,ULONG currentPos
,BOOL leftToRight
,IEnumMoniker
** ppmk
);
82 /*******************************************************************************
83 * CompositeMoniker_QueryInterface
84 *******************************************************************************/
86 CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
88 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
90 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppvObject
);
92 /* Perform a sanity check on the parameters.*/
96 /* Initialize the return parameter */
99 /* Compare the riid with the interface IDs implemented by this object.*/
100 if (IsEqualIID(&IID_IUnknown
, riid
) ||
101 IsEqualIID(&IID_IPersist
, riid
) ||
102 IsEqualIID(&IID_IPersistStream
, riid
) ||
103 IsEqualIID(&IID_IMoniker
, riid
)
106 else if (IsEqualIID(&IID_IROTData
, riid
))
107 *ppvObject
= &This
->IROTData_iface
;
108 else if (IsEqualIID(&IID_IMarshal
, riid
))
109 *ppvObject
= &This
->IMarshal_iface
;
111 /* Check that we obtained an interface.*/
113 return E_NOINTERFACE
;
115 /* Query Interface always increases the reference count by one when it is successful */
116 IMoniker_AddRef(iface
);
121 /******************************************************************************
122 * CompositeMoniker_AddRef
123 ******************************************************************************/
125 CompositeMonikerImpl_AddRef(IMoniker
* iface
)
127 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
129 TRACE("(%p)\n",This
);
131 return InterlockedIncrement(&This
->ref
);
134 static void CompositeMonikerImpl_ReleaseMonikersInTable(CompositeMonikerImpl
*This
)
138 for (i
= 0; i
< This
->tabLastIndex
; i
++)
139 IMoniker_Release(This
->tabMoniker
[i
]);
141 This
->tabLastIndex
= 0;
144 /******************************************************************************
145 * CompositeMoniker_Release
146 ******************************************************************************/
148 CompositeMonikerImpl_Release(IMoniker
* iface
)
150 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
153 TRACE("(%p)\n",This
);
155 ref
= InterlockedDecrement(&This
->ref
);
157 /* destroy the object if there are no more references to it */
160 /* release all the components before destroying this object */
161 CompositeMonikerImpl_ReleaseMonikersInTable(This
);
163 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
164 HeapFree(GetProcessHeap(),0,This
);
169 /******************************************************************************
170 * CompositeMoniker_GetClassID
171 ******************************************************************************/
172 static HRESULT WINAPI
173 CompositeMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
175 TRACE("(%p,%p)\n",iface
,pClassID
);
180 *pClassID
= CLSID_CompositeMoniker
;
185 /******************************************************************************
186 * CompositeMoniker_IsDirty
187 ******************************************************************************/
188 static HRESULT WINAPI
189 CompositeMonikerImpl_IsDirty(IMoniker
* iface
)
191 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
192 method in the OLE-provided moniker interfaces always return S_FALSE because
193 their internal state never changes. */
195 TRACE("(%p)\n",iface
);
200 /******************************************************************************
201 * CompositeMoniker_Load
202 ******************************************************************************/
203 static HRESULT WINAPI
204 CompositeMonikerImpl_Load(IMoniker
* iface
,IStream
* pStm
)
206 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
211 TRACE("(%p,%p)\n",iface
,pStm
);
213 /* this function call OleLoadFromStream function for each moniker within this object */
215 res
=IStream_Read(pStm
,&moniker_count
,sizeof(DWORD
),NULL
);
218 ERR("couldn't reading moniker count from stream\n");
222 CompositeMonikerImpl_ReleaseMonikersInTable(This
);
224 for (i
= 0; i
< moniker_count
; i
++)
226 res
=OleLoadFromStream(pStm
,&IID_IMoniker
,(void**)&This
->tabMoniker
[This
->tabLastIndex
]);
229 ERR("couldn't load moniker from stream, res = 0x%08x\n", res
);
233 /* resize the table if needed */
234 if (++This
->tabLastIndex
==This
->tabSize
){
236 This
->tabSize
+=BLOCK_TAB_SIZE
;
237 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(This
->tabMoniker
[0]));
239 if (This
->tabMoniker
==NULL
)
240 return E_OUTOFMEMORY
;
247 /******************************************************************************
248 * CompositeMoniker_Save
249 ******************************************************************************/
250 static HRESULT WINAPI
251 CompositeMonikerImpl_Save(IMoniker
* iface
,IStream
* pStm
,BOOL fClearDirty
)
253 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
255 IEnumMoniker
*enumMk
;
257 DWORD moniker_count
= This
->tabLastIndex
;
259 TRACE("(%p,%p,%d)\n",iface
,pStm
,fClearDirty
);
261 /* This function calls OleSaveToStream function for each moniker within
263 * When I tested this function in windows, I usually found this constant
264 * at the beginning of the stream. I don't known why (there's no
265 * indication in the specification) !
267 res
=IStream_Write(pStm
,&moniker_count
,sizeof(moniker_count
),NULL
);
268 if (FAILED(res
)) return res
;
270 IMoniker_Enum(iface
,TRUE
,&enumMk
);
272 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
274 res
=OleSaveToStream((IPersistStream
*)pmk
,pStm
);
276 IMoniker_Release(pmk
);
280 IEnumMoniker_Release(enumMk
);
285 IEnumMoniker_Release(enumMk
);
290 /******************************************************************************
291 * CompositeMoniker_GetSizeMax
292 ******************************************************************************/
293 static HRESULT WINAPI
294 CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
,ULARGE_INTEGER
* pcbSize
)
296 IEnumMoniker
*enumMk
;
298 ULARGE_INTEGER ptmpSize
;
300 /* The sizeMax of this object is calculated by calling GetSizeMax on
301 * each moniker within this object then summing all returned values
304 TRACE("(%p,%p)\n",iface
,pcbSize
);
309 pcbSize
->QuadPart
= sizeof(DWORD
);
311 IMoniker_Enum(iface
,TRUE
,&enumMk
);
313 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
315 IMoniker_GetSizeMax(pmk
,&ptmpSize
);
317 IMoniker_Release(pmk
);
319 pcbSize
->QuadPart
= ptmpSize
.QuadPart
+ sizeof(CLSID
);
322 IEnumMoniker_Release(enumMk
);
327 /******************************************************************************
328 * CompositeMoniker_BindToObject
329 ******************************************************************************/
330 static HRESULT WINAPI
331 CompositeMonikerImpl_BindToObject(IMoniker
* iface
, IBindCtx
* pbc
,
332 IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
)
335 IRunningObjectTable
*prot
;
336 IMoniker
*tempMk
,*antiMk
,*rightMostMk
;
337 IEnumMoniker
*enumMoniker
;
339 TRACE("(%p,%p,%p,%s,%p)\n",iface
,pbc
,pmkToLeft
,debugstr_guid(riid
),ppvResult
);
345 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
346 /* object for the requested interface pointer. */
349 res
=IBindCtx_GetRunningObjectTable(pbc
,&prot
);
353 /* if the requested class was loaded before ! we don't need to reload it */
354 res
= IRunningObjectTable_GetObject(prot
,iface
,(IUnknown
**)ppvResult
);
361 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
362 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
364 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
365 IEnumMoniker_Next(enumMoniker
,1,&rightMostMk
,NULL
);
366 IEnumMoniker_Release(enumMoniker
);
368 res
=CreateAntiMoniker(&antiMk
);
369 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
370 IMoniker_Release(antiMk
);
372 res
=IMoniker_BindToObject(rightMostMk
,pbc
,tempMk
,riid
,ppvResult
);
374 IMoniker_Release(tempMk
);
375 IMoniker_Release(rightMostMk
);
381 /******************************************************************************
382 * CompositeMoniker_BindToStorage
383 ******************************************************************************/
384 static HRESULT WINAPI
385 CompositeMonikerImpl_BindToStorage(IMoniker
* iface
, IBindCtx
* pbc
,
386 IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
)
389 IMoniker
*tempMk
,*antiMk
,*rightMostMk
,*leftMk
;
390 IEnumMoniker
*enumMoniker
;
392 TRACE("(%p,%p,%p,%s,%p)\n",iface
,pbc
,pmkToLeft
,debugstr_guid(riid
),ppvResult
);
396 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
397 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
401 res
= IMoniker_ComposeWith(pmkToLeft
, iface
, FALSE
, &leftMk
);
402 if (FAILED(res
)) return res
;
407 IMoniker_Enum(iface
, FALSE
, &enumMoniker
);
408 IEnumMoniker_Next(enumMoniker
, 1, &rightMostMk
, NULL
);
409 IEnumMoniker_Release(enumMoniker
);
411 res
= CreateAntiMoniker(&antiMk
);
412 if (FAILED(res
)) return res
;
413 res
= IMoniker_ComposeWith(leftMk
, antiMk
, 0, &tempMk
);
414 if (FAILED(res
)) return res
;
415 IMoniker_Release(antiMk
);
417 res
= IMoniker_BindToStorage(rightMostMk
, pbc
, tempMk
, riid
, ppvResult
);
419 IMoniker_Release(tempMk
);
421 IMoniker_Release(rightMostMk
);
424 IMoniker_Release(leftMk
);
429 /******************************************************************************
430 * CompositeMoniker_Reduce
431 ******************************************************************************/
432 static HRESULT WINAPI
433 CompositeMonikerImpl_Reduce(IMoniker
* iface
, IBindCtx
* pbc
, DWORD dwReduceHowFar
,
434 IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
)
436 IMoniker
*tempMk
,*antiMk
,*rightMostMk
,*leftReducedComposedMk
,*rightMostReducedMk
;
437 IEnumMoniker
*enumMoniker
;
439 TRACE("(%p,%p,%d,%p,%p)\n",iface
,pbc
,dwReduceHowFar
,ppmkToLeft
,ppmkReduced
);
441 if (ppmkReduced
==NULL
)
444 /* This method recursively calls Reduce for each of its component monikers. */
446 if (ppmkToLeft
==NULL
){
448 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
449 IEnumMoniker_Next(enumMoniker
,1,&rightMostMk
,NULL
);
450 IEnumMoniker_Release(enumMoniker
);
452 CreateAntiMoniker(&antiMk
);
453 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
454 IMoniker_Release(antiMk
);
456 return IMoniker_Reduce(rightMostMk
,pbc
,dwReduceHowFar
,&tempMk
, ppmkReduced
);
458 else if (*ppmkToLeft
==NULL
)
460 return IMoniker_Reduce(iface
,pbc
,dwReduceHowFar
,NULL
,ppmkReduced
);
464 /* separate the composite moniker in to left and right moniker */
465 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
466 IEnumMoniker_Next(enumMoniker
,1,&rightMostMk
,NULL
);
467 IEnumMoniker_Release(enumMoniker
);
469 CreateAntiMoniker(&antiMk
);
470 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
471 IMoniker_Release(antiMk
);
473 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
474 /* of the reduced components */
475 if (IMoniker_Reduce(rightMostMk
,pbc
,dwReduceHowFar
,NULL
,&rightMostReducedMk
) &&
476 IMoniker_Reduce(rightMostMk
,pbc
,dwReduceHowFar
,&tempMk
,&leftReducedComposedMk
)
479 return CreateGenericComposite(leftReducedComposedMk
,rightMostReducedMk
,ppmkReduced
);
482 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
484 IMoniker_AddRef(iface
);
488 return MK_S_REDUCED_TO_SELF
;
493 /******************************************************************************
494 * CompositeMoniker_ComposeWith
495 ******************************************************************************/
496 static HRESULT WINAPI
497 CompositeMonikerImpl_ComposeWith(IMoniker
* iface
, IMoniker
* pmkRight
,
498 BOOL fOnlyIfNotGeneric
, IMoniker
** ppmkComposite
)
500 TRACE("(%p,%p,%d,%p)\n",iface
,pmkRight
,fOnlyIfNotGeneric
,ppmkComposite
);
502 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
507 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
508 /* otherwise, the method returns the result of combining the two monikers by calling the */
509 /* CreateGenericComposite function */
511 if (fOnlyIfNotGeneric
)
512 return MK_E_NEEDGENERIC
;
514 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
517 /******************************************************************************
518 * CompositeMoniker_Enum
519 ******************************************************************************/
520 static HRESULT WINAPI
521 CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
523 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
525 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
527 if (ppenumMoniker
== NULL
)
530 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabLastIndex
,0,fForward
,ppenumMoniker
);
533 /******************************************************************************
534 * CompositeMoniker_IsEqual
535 ******************************************************************************/
536 static HRESULT WINAPI
537 CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
)
539 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
540 IMoniker
*tempMk1
,*tempMk2
;
541 HRESULT res1
,res2
,res
;
544 TRACE("(%p,%p)\n",iface
,pmkOtherMoniker
);
546 if (pmkOtherMoniker
==NULL
)
549 /* This method returns S_OK if the components of both monikers are equal when compared in the */
550 /* left-to-right order.*/
551 IMoniker_Enum(pmkOtherMoniker
,TRUE
,&enumMoniker1
);
553 if (enumMoniker1
==NULL
)
556 IMoniker_Enum(iface
,TRUE
,&enumMoniker2
);
560 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
561 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
563 if((res1
==S_OK
)&&(res2
==S_OK
)){
564 done
= (res
= IMoniker_IsEqual(tempMk1
,tempMk2
)) == S_FALSE
;
568 res
= (res1
==S_FALSE
) && (res2
==S_FALSE
);
573 IMoniker_Release(tempMk1
);
576 IMoniker_Release(tempMk2
);
579 IEnumMoniker_Release(enumMoniker1
);
580 IEnumMoniker_Release(enumMoniker2
);
584 /******************************************************************************
585 * CompositeMoniker_Hash
586 ******************************************************************************/
587 static HRESULT WINAPI
588 CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
590 IEnumMoniker
*enumMoniker
;
595 TRACE("(%p,%p)\n",iface
,pdwHash
);
600 res
= IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
606 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
607 res
= IMoniker_Hash(tempMk
, &tempHash
);
610 *pdwHash
= *pdwHash
^ tempHash
;
612 IMoniker_Release(tempMk
);
615 IEnumMoniker_Release(enumMoniker
);
620 /******************************************************************************
621 * CompositeMoniker_IsRunning
622 ******************************************************************************/
623 static HRESULT WINAPI
624 CompositeMonikerImpl_IsRunning(IMoniker
* iface
, IBindCtx
* pbc
,
625 IMoniker
* pmkToLeft
, IMoniker
* pmkNewlyRunning
)
627 IRunningObjectTable
* rot
;
629 IMoniker
*tempMk
,*antiMk
,*rightMostMk
;
630 IEnumMoniker
*enumMoniker
;
632 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
634 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
635 if (pmkToLeft
!=NULL
){
637 CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
639 res
= IMoniker_IsRunning(tempMk
,pbc
,NULL
,pmkNewlyRunning
);
641 IMoniker_Release(tempMk
);
646 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
647 /* to this moniker */
649 if (pmkNewlyRunning
!=NULL
)
651 if (IMoniker_IsEqual(iface
,pmkNewlyRunning
)==S_OK
)
662 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
663 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
664 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
665 /* the composite as the pmkToLeft parameter for that call. */
667 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
672 res
= IRunningObjectTable_IsRunning(rot
,iface
);
673 IRunningObjectTable_Release(rot
);
680 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
681 IEnumMoniker_Next(enumMoniker
,1,&rightMostMk
,NULL
);
682 IEnumMoniker_Release(enumMoniker
);
684 res
=CreateAntiMoniker(&antiMk
);
685 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
686 IMoniker_Release(antiMk
);
688 res
=IMoniker_IsRunning(rightMostMk
,pbc
,tempMk
,pmkNewlyRunning
);
690 IMoniker_Release(tempMk
);
691 IMoniker_Release(rightMostMk
);
698 /******************************************************************************
699 * CompositeMoniker_GetTimeOfLastChange
700 ******************************************************************************/
701 static HRESULT WINAPI
702 CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
, IBindCtx
* pbc
,
703 IMoniker
* pmkToLeft
, FILETIME
* pCompositeTime
)
706 IMoniker
*tempMk
,*antiMk
,*rightMostMk
,*leftMk
;
707 IEnumMoniker
*enumMoniker
;
709 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pCompositeTime
);
711 if (pCompositeTime
==NULL
)
714 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
715 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
716 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
717 /* of the composite as the pmkToLeft parameter for that call. */
720 IRunningObjectTable
* rot
;
722 res
= IMoniker_ComposeWith(pmkToLeft
, iface
, FALSE
, &leftMk
);
726 res
= IBindCtx_GetRunningObjectTable(pbc
,&rot
);
729 IMoniker_Release(leftMk
);
733 if (IRunningObjectTable_GetTimeOfLastChange(rot
,leftMk
,pCompositeTime
)==S_OK
)
735 IMoniker_Release(leftMk
);
742 IMoniker_Enum(iface
, FALSE
, &enumMoniker
);
743 IEnumMoniker_Next(enumMoniker
, 1, &rightMostMk
, NULL
);
744 IEnumMoniker_Release(enumMoniker
);
746 res
= CreateAntiMoniker(&antiMk
);
747 res
= IMoniker_ComposeWith(leftMk
, antiMk
, 0, &tempMk
);
748 IMoniker_Release(antiMk
);
750 res
= IMoniker_GetTimeOfLastChange(rightMostMk
, pbc
, tempMk
, pCompositeTime
);
752 IMoniker_Release(tempMk
);
753 IMoniker_Release(rightMostMk
);
756 IMoniker_Release(leftMk
);
761 /******************************************************************************
762 * CompositeMoniker_Inverse
763 ******************************************************************************/
764 static HRESULT WINAPI
765 CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
768 IMoniker
*tempMk
,*antiMk
,*rightMostMk
,*tempInvMk
,*rightMostInvMk
;
769 IEnumMoniker
*enumMoniker
;
771 TRACE("(%p,%p)\n",iface
,ppmk
);
776 /* This method returns a composite moniker that consists of the inverses of each of the components */
777 /* of the original composite, stored in reverse order */
781 res
=CreateAntiMoniker(&antiMk
);
785 res
=IMoniker_ComposeWith(iface
,antiMk
,FALSE
,&tempMk
);
786 IMoniker_Release(antiMk
);
792 return IMoniker_Inverse(iface
,ppmk
);
796 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
797 IEnumMoniker_Next(enumMoniker
,1,&rightMostMk
,NULL
);
798 IEnumMoniker_Release(enumMoniker
);
800 IMoniker_Inverse(rightMostMk
,&rightMostInvMk
);
801 CompositeMonikerImpl_Inverse(tempMk
,&tempInvMk
);
803 res
=CreateGenericComposite(rightMostInvMk
,tempInvMk
,ppmk
);
805 IMoniker_Release(tempMk
);
806 IMoniker_Release(rightMostMk
);
807 IMoniker_Release(tempInvMk
);
808 IMoniker_Release(rightMostInvMk
);
814 /******************************************************************************
815 * CompositeMoniker_CommonPrefixWith
816 ******************************************************************************/
817 static HRESULT WINAPI
818 CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
, IMoniker
* pmkOther
,
819 IMoniker
** ppmkPrefix
)
823 IMoniker
*tempMk1
,*tempMk2
,*mostLeftMk1
,*mostLeftMk2
;
824 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
825 ULONG i
,nbCommonMk
=0;
827 /* If the other moniker is a composite, this method compares the components of each composite from left */
828 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
829 /* of the leftmost components were common to both monikers. */
831 if (ppmkPrefix
==NULL
)
837 return MK_E_NOPREFIX
;
839 IMoniker_IsSystemMoniker(pmkOther
,&mkSys
);
841 if(mkSys
==MKSYS_GENERICCOMPOSITE
){
843 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
844 IMoniker_Enum(pmkOther
,TRUE
,&enumMoniker2
);
848 res1
=IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
849 res2
=IEnumMoniker_Next(enumMoniker2
,1,&mostLeftMk2
,NULL
);
851 if ((res1
==S_FALSE
) && (res2
==S_FALSE
)){
853 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
855 IMoniker_AddRef(iface
);
858 else if ((res1
==S_OK
) && (res2
==S_OK
)){
860 if (IMoniker_IsEqual(mostLeftMk1
,mostLeftMk2
)==S_OK
)
868 else if (res1
==S_OK
){
870 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
871 /* ppmkPrefix to the other moniker. */
872 *ppmkPrefix
=pmkOther
;
876 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
877 /* to this moniker. */
883 IEnumMoniker_Release(enumMoniker1
);
884 IEnumMoniker_Release(enumMoniker2
);
886 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
888 return MK_E_NOPREFIX
;
890 IEnumMoniker_Reset(enumMoniker1
);
892 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
894 /* if we have more than one common moniker the result will be a composite moniker */
897 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
898 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
899 CreateGenericComposite(tempMk1
,tempMk2
,ppmkPrefix
);
900 IMoniker_Release(tempMk1
);
901 IMoniker_Release(tempMk2
);
903 /* compose all common monikers in a composite moniker */
904 for(i
=0;i
<nbCommonMk
;i
++){
906 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
908 CreateGenericComposite(*ppmkPrefix
,tempMk1
,&tempMk2
);
910 IMoniker_Release(*ppmkPrefix
);
912 IMoniker_Release(tempMk1
);
919 /* if we have only one common moniker the result will be a simple moniker which is the most-left one*/
926 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
929 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
931 IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
933 if (IMoniker_IsEqual(pmkOther
,mostLeftMk1
)==S_OK
){
935 *ppmkPrefix
=pmkOther
;
940 return MK_E_NOPREFIX
;
944 /***************************************************************************************************
945 * GetAfterCommonPrefix (local function)
946 * This function returns a moniker that consist of the remainder when the common prefix is removed
947 ***************************************************************************************************/
948 static VOID
GetAfterCommonPrefix(IMoniker
* pGenMk
,IMoniker
* commonMk
,IMoniker
** restMk
)
950 IMoniker
*tempMk
,*tempMk1
,*tempMk2
;
951 IEnumMoniker
*enumMoniker1
,*enumMoniker2
,*enumMoniker3
;
958 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
959 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
960 /* on the first difference. */
961 IMoniker_Enum(pGenMk
,TRUE
,&enumMoniker1
);
963 IMoniker_IsSystemMoniker(commonMk
,&mkSys
);
965 if (mkSys
==MKSYS_GENERICCOMPOSITE
){
967 IMoniker_Enum(commonMk
,TRUE
,&enumMoniker2
);
970 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
971 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
973 if ((res1
==S_FALSE
)||(res2
==S_FALSE
)){
979 IMoniker_Release(tempMk1
);
980 IMoniker_Release(tempMk2
);
984 IMoniker_Release(tempMk1
);
985 IMoniker_Release(tempMk2
);
989 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
990 IMoniker_Release(tempMk1
);
993 /* count the number of elements in the enumerator after the common prefix */
994 IEnumMoniker_Clone(enumMoniker1
,&enumMoniker3
);
996 for(;IEnumMoniker_Next(enumMoniker3
,1,&tempMk
,NULL
)==S_OK
;nbRestMk
++)
998 IMoniker_Release(tempMk
);
1003 /* create a generic composite moniker with monikers located after the common prefix */
1004 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1013 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1015 CreateGenericComposite(tempMk1
,tempMk2
,restMk
);
1017 IMoniker_Release(tempMk1
);
1019 IMoniker_Release(tempMk2
);
1021 while(IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
)==S_OK
){
1023 CreateGenericComposite(*restMk
,tempMk1
,&tempMk2
);
1025 IMoniker_Release(tempMk1
);
1027 IMoniker_Release(*restMk
);
1034 /******************************************************************************
1035 * CompositeMoniker_RelativePathTo
1036 ******************************************************************************/
1037 static HRESULT WINAPI
1038 CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmkOther
,
1039 IMoniker
** ppmkRelPath
)
1042 IMoniker
*restOtherMk
=0,*restThisMk
=0,*invRestThisMk
=0,*commonMk
=0;
1044 TRACE("(%p,%p,%p)\n",iface
,pmkOther
,ppmkRelPath
);
1046 if (ppmkRelPath
==NULL
)
1051 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1052 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1053 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1055 /* finds the common prefix of the two monikers */
1056 res
=IMoniker_CommonPrefixWith(iface
,pmkOther
,&commonMk
);
1058 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1059 if ((res
== MK_E_NOPREFIX
)||(res
==MK_S_US
)){
1061 *ppmkRelPath
=pmkOther
;
1062 IMoniker_AddRef(pmkOther
);
1066 GetAfterCommonPrefix(iface
,commonMk
,&restThisMk
);
1067 GetAfterCommonPrefix(pmkOther
,commonMk
,&restOtherMk
);
1069 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1070 /* moniker when the common prefix is removed */
1073 IMoniker_Inverse(restThisMk
,ppmkRelPath
);
1074 IMoniker_Release(restThisMk
);
1076 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1077 /* when the common prefix is removed */
1078 else if (res
==MK_S_ME
){
1080 *ppmkRelPath
=restOtherMk
;
1081 IMoniker_AddRef(restOtherMk
);
1083 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1084 /* moniker on the right of it. */
1085 else if (res
==S_OK
){
1087 IMoniker_Inverse(restThisMk
,&invRestThisMk
);
1088 IMoniker_Release(restThisMk
);
1089 CreateGenericComposite(invRestThisMk
,restOtherMk
,ppmkRelPath
);
1090 IMoniker_Release(invRestThisMk
);
1091 IMoniker_Release(restOtherMk
);
1096 /******************************************************************************
1097 * CompositeMoniker_GetDisplayName
1098 ******************************************************************************/
1099 static HRESULT WINAPI
1100 CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
1101 IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
)
1104 IEnumMoniker
*enumMoniker
;
1108 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
1110 if (ppszDisplayName
==NULL
)
1113 *ppszDisplayName
=CoTaskMemAlloc(sizeof(WCHAR
));
1115 if (*ppszDisplayName
==NULL
)
1116 return E_OUTOFMEMORY
;
1118 /* This method returns the concatenation of the display names returned by each component moniker of */
1121 **ppszDisplayName
=0;
1123 IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
1125 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
1127 IMoniker_GetDisplayName(tempMk
,pbc
,NULL
,&tempStr
);
1129 lengthStr
+=lstrlenW(tempStr
);
1131 *ppszDisplayName
=CoTaskMemRealloc(*ppszDisplayName
,lengthStr
* sizeof(WCHAR
));
1133 if (*ppszDisplayName
==NULL
)
1134 return E_OUTOFMEMORY
;
1136 strcatW(*ppszDisplayName
,tempStr
);
1138 CoTaskMemFree(tempStr
);
1139 IMoniker_Release(tempMk
);
1142 IEnumMoniker_Release(enumMoniker
);
1147 /******************************************************************************
1148 * CompositeMoniker_ParseDisplayName
1149 ******************************************************************************/
1150 static HRESULT WINAPI
1151 CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
1152 IMoniker
* pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
* pchEaten
,
1155 IEnumMoniker
*enumMoniker
;
1156 IMoniker
*tempMk
,*rightMostMk
,*antiMk
;
1157 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1158 /* passing everything else as the pmkToLeft parameter for that call. */
1160 /* get the most right moniker */
1161 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1162 IEnumMoniker_Next(enumMoniker
,1,&rightMostMk
,NULL
);
1163 IEnumMoniker_Release(enumMoniker
);
1165 /* get the left moniker */
1166 CreateAntiMoniker(&antiMk
);
1167 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1168 IMoniker_Release(antiMk
);
1170 return IMoniker_ParseDisplayName(rightMostMk
,pbc
,tempMk
,pszDisplayName
,pchEaten
,ppmkOut
);
1173 /******************************************************************************
1174 * CompositeMoniker_IsSystemMoniker
1175 ******************************************************************************/
1176 static HRESULT WINAPI
1177 CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
1179 TRACE("(%p,%p)\n",iface
,pwdMksys
);
1184 (*pwdMksys
)=MKSYS_GENERICCOMPOSITE
;
1189 /*******************************************************************************
1190 * CompositeMonikerIROTData_QueryInterface
1191 *******************************************************************************/
1192 static HRESULT WINAPI
1193 CompositeMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,
1196 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
1198 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppvObject
);
1200 return CompositeMonikerImpl_QueryInterface(&This
->IMoniker_iface
, riid
, ppvObject
);
1203 /***********************************************************************
1204 * CompositeMonikerIROTData_AddRef
1207 CompositeMonikerROTDataImpl_AddRef(IROTData
*iface
)
1209 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
1211 TRACE("(%p)\n",iface
);
1213 return IMoniker_AddRef(&This
->IMoniker_iface
);
1216 /***********************************************************************
1217 * CompositeMonikerIROTData_Release
1219 static ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
)
1221 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
1223 TRACE("(%p)\n",iface
);
1225 return IMoniker_Release(&This
->IMoniker_iface
);
1228 /******************************************************************************
1229 * CompositeMonikerIROTData_GetComparisonData
1230 ******************************************************************************/
1231 static HRESULT WINAPI
1232 CompositeMonikerROTDataImpl_GetComparisonData(IROTData
* iface
,
1233 BYTE
* pbData
, ULONG cbMax
, ULONG
* pcbData
)
1235 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
1236 IEnumMoniker
*pEnumMk
;
1240 TRACE("(%p, %u, %p)\n", pbData
, cbMax
, pcbData
);
1242 *pcbData
= sizeof(CLSID
);
1244 hr
= IMoniker_Enum(&This
->IMoniker_iface
, TRUE
, &pEnumMk
);
1245 if (FAILED(hr
)) return hr
;
1247 while(IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1250 hr
= IMoniker_QueryInterface(pmk
, &IID_IROTData
, (void **)&pROTData
);
1252 ERR("moniker doesn't support IROTData interface\n");
1257 hr
= IROTData_GetComparisonData(pROTData
, NULL
, 0, &cbData
);
1258 IROTData_Release(pROTData
);
1259 if (SUCCEEDED(hr
) || (hr
== E_OUTOFMEMORY
))
1265 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr
);
1268 IMoniker_Release(pmk
);
1272 IEnumMoniker_Release(pEnumMk
);
1276 if (cbMax
< *pcbData
)
1277 return E_OUTOFMEMORY
;
1279 IEnumMoniker_Reset(pEnumMk
);
1281 memcpy(pbData
, &CLSID_CompositeMoniker
, sizeof(CLSID
));
1282 pbData
+= sizeof(CLSID
);
1283 cbMax
-= sizeof(CLSID
);
1285 while (IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1288 hr
= IMoniker_QueryInterface(pmk
, &IID_IROTData
, (void **)&pROTData
);
1290 ERR("moniker doesn't support IROTData interface\n");
1295 hr
= IROTData_GetComparisonData(pROTData
, pbData
, cbMax
, &cbData
);
1296 IROTData_Release(pROTData
);
1303 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr
);
1306 IMoniker_Release(pmk
);
1310 IEnumMoniker_Release(pEnumMk
);
1315 IEnumMoniker_Release(pEnumMk
);
1320 static HRESULT WINAPI
CompositeMonikerMarshalImpl_QueryInterface(IMarshal
*iface
, REFIID riid
, LPVOID
*ppv
)
1322 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1324 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppv
);
1326 return CompositeMonikerImpl_QueryInterface(&This
->IMoniker_iface
, riid
, ppv
);
1329 static ULONG WINAPI
CompositeMonikerMarshalImpl_AddRef(IMarshal
*iface
)
1331 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1333 TRACE("(%p)\n",iface
);
1335 return CompositeMonikerImpl_AddRef(&This
->IMoniker_iface
);
1338 static ULONG WINAPI
CompositeMonikerMarshalImpl_Release(IMarshal
*iface
)
1340 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1342 TRACE("(%p)\n",iface
);
1344 return CompositeMonikerImpl_Release(&This
->IMoniker_iface
);
1347 static HRESULT WINAPI
CompositeMonikerMarshalImpl_GetUnmarshalClass(
1348 IMarshal
*iface
, REFIID riid
, void *pv
, DWORD dwDestContext
,
1349 void* pvDestContext
, DWORD mshlflags
, CLSID
* pCid
)
1351 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1353 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid
), pv
,
1354 dwDestContext
, pvDestContext
, mshlflags
, pCid
);
1356 return IMoniker_GetClassID(&This
->IMoniker_iface
, pCid
);
1359 static HRESULT WINAPI
CompositeMonikerMarshalImpl_GetMarshalSizeMax(
1360 IMarshal
*iface
, REFIID riid
, void *pv
, DWORD dwDestContext
,
1361 void* pvDestContext
, DWORD mshlflags
, DWORD
* pSize
)
1363 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1364 IEnumMoniker
*pEnumMk
;
1367 ULARGE_INTEGER size
;
1369 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid
), pv
,
1370 dwDestContext
, pvDestContext
, mshlflags
, pSize
);
1372 *pSize
= 0x10; /* to match native */
1374 hr
= IMoniker_Enum(&This
->IMoniker_iface
, TRUE
, &pEnumMk
);
1375 if (FAILED(hr
)) return hr
;
1377 hr
= IMoniker_GetSizeMax(&This
->IMoniker_iface
, &size
);
1379 while (IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1383 hr
= CoGetMarshalSizeMax(&size
, &IID_IMoniker
, (IUnknown
*)pmk
, dwDestContext
, pvDestContext
, mshlflags
);
1387 IMoniker_Release(pmk
);
1391 IEnumMoniker_Release(pEnumMk
);
1396 IEnumMoniker_Release(pEnumMk
);
1401 static HRESULT WINAPI
CompositeMonikerMarshalImpl_MarshalInterface(IMarshal
*iface
, IStream
*pStm
,
1402 REFIID riid
, void* pv
, DWORD dwDestContext
,
1403 void* pvDestContext
, DWORD mshlflags
)
1405 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1406 IEnumMoniker
*pEnumMk
;
1411 TRACE("(%p, %s, %p, %x, %p, %x)\n", pStm
, debugstr_guid(riid
), pv
,
1412 dwDestContext
, pvDestContext
, mshlflags
);
1414 hr
= IMoniker_Enum(&This
->IMoniker_iface
, TRUE
, &pEnumMk
);
1415 if (FAILED(hr
)) return hr
;
1417 while (IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1419 hr
= CoMarshalInterface(pStm
, &IID_IMoniker
, (IUnknown
*)pmk
, dwDestContext
, pvDestContext
, mshlflags
);
1421 IMoniker_Release(pmk
);
1425 IEnumMoniker_Release(pEnumMk
);
1432 FIXME("moniker count of %d not supported\n", i
);
1434 IEnumMoniker_Release(pEnumMk
);
1439 static HRESULT WINAPI
CompositeMonikerMarshalImpl_UnmarshalInterface(IMarshal
*iface
, IStream
*pStm
,
1440 REFIID riid
, void **ppv
)
1442 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1445 TRACE("(%p, %s, %p)\n", pStm
, debugstr_guid(riid
), ppv
);
1447 CompositeMonikerImpl_ReleaseMonikersInTable(This
);
1449 /* resize the table if needed */
1450 if (This
->tabLastIndex
+ 2 > This
->tabSize
)
1452 This
->tabSize
+= max(BLOCK_TAB_SIZE
, 2);
1453 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(This
->tabMoniker
[0]));
1455 if (This
->tabMoniker
==NULL
)
1456 return E_OUTOFMEMORY
;
1459 hr
= CoUnmarshalInterface(pStm
, &IID_IMoniker
, (void**)&This
->tabMoniker
[This
->tabLastIndex
]);
1462 ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr
);
1465 This
->tabLastIndex
++;
1466 hr
= CoUnmarshalInterface(pStm
, &IID_IMoniker
, (void**)&This
->tabMoniker
[This
->tabLastIndex
]);
1469 ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr
);
1472 This
->tabLastIndex
++;
1474 return IMoniker_QueryInterface(&This
->IMoniker_iface
, riid
, ppv
);
1477 static HRESULT WINAPI
CompositeMonikerMarshalImpl_ReleaseMarshalData(IMarshal
*iface
, IStream
*pStm
)
1479 TRACE("(%p)\n", pStm
);
1480 /* can't release a state-based marshal as nothing on server side to
1485 static HRESULT WINAPI
CompositeMonikerMarshalImpl_DisconnectObject(IMarshal
*iface
,
1488 TRACE("(0x%x)\n", dwReserved
);
1489 /* can't disconnect a state-based marshal as nothing on server side to
1490 * disconnect from */
1494 /******************************************************************************
1495 * EnumMonikerImpl_QueryInterface
1496 ******************************************************************************/
1497 static HRESULT WINAPI
1498 EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
)
1500 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1502 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppvObject
);
1504 /* Perform a sanity check on the parameters.*/
1506 return E_INVALIDARG
;
1508 /* Initialize the return parameter */
1511 /* Compare the riid with the interface IDs implemented by this object.*/
1512 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IEnumMoniker
, riid
))
1515 /* Check that we obtained an interface.*/
1516 if ((*ppvObject
)==0)
1517 return E_NOINTERFACE
;
1519 /* Query Interface always increases the reference count by one when it is successful */
1520 IEnumMoniker_AddRef(iface
);
1525 /******************************************************************************
1526 * EnumMonikerImpl_AddRef
1527 ******************************************************************************/
1529 EnumMonikerImpl_AddRef(IEnumMoniker
* iface
)
1531 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1533 TRACE("(%p)\n",This
);
1535 return InterlockedIncrement(&This
->ref
);
1539 /******************************************************************************
1540 * EnumMonikerImpl_Release
1541 ******************************************************************************/
1543 EnumMonikerImpl_Release(IEnumMoniker
* iface
)
1545 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1548 TRACE("(%p)\n",This
);
1550 ref
= InterlockedDecrement(&This
->ref
);
1552 /* destroy the object if there are no more references to it */
1555 for(i
=0;i
<This
->tabSize
;i
++)
1556 IMoniker_Release(This
->tabMoniker
[i
]);
1558 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
1559 HeapFree(GetProcessHeap(),0,This
);
1564 /******************************************************************************
1565 * EnumMonikerImpl_Next
1566 ******************************************************************************/
1567 static HRESULT WINAPI
1568 EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
, IMoniker
** rgelt
,
1571 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1574 /* retrieve the requested number of moniker from the current position */
1575 for(i
=0;((This
->currentPos
< This
->tabSize
) && (i
< celt
));i
++)
1577 rgelt
[i
]=This
->tabMoniker
[This
->currentPos
++];
1578 IMoniker_AddRef(rgelt
[i
]);
1581 if (pceltFethed
!=NULL
)
1590 /******************************************************************************
1591 * EnumMonikerImpl_Skip
1592 ******************************************************************************/
1593 static HRESULT WINAPI
1594 EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
)
1596 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1598 if ((This
->currentPos
+celt
) >= This
->tabSize
)
1601 This
->currentPos
+=celt
;
1606 /******************************************************************************
1607 * EnumMonikerImpl_Reset
1608 ******************************************************************************/
1609 static HRESULT WINAPI
1610 EnumMonikerImpl_Reset(IEnumMoniker
* iface
)
1612 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1619 /******************************************************************************
1620 * EnumMonikerImpl_Clone
1621 ******************************************************************************/
1622 static HRESULT WINAPI
1623 EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
)
1625 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1627 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabSize
,This
->currentPos
,TRUE
,ppenum
);
1630 /********************************************************************************/
1631 /* Virtual function table for the IROTData class */
1632 static const IEnumMonikerVtbl VT_EnumMonikerImpl
=
1634 EnumMonikerImpl_QueryInterface
,
1635 EnumMonikerImpl_AddRef
,
1636 EnumMonikerImpl_Release
,
1637 EnumMonikerImpl_Next
,
1638 EnumMonikerImpl_Skip
,
1639 EnumMonikerImpl_Reset
,
1640 EnumMonikerImpl_Clone
1643 /******************************************************************************
1644 * EnumMonikerImpl_CreateEnumMoniker
1645 ******************************************************************************/
1647 EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
, ULONG tabSize
,
1648 ULONG currentPos
, BOOL leftToRight
, IEnumMoniker
** ppmk
)
1650 EnumMonikerImpl
* newEnumMoniker
;
1653 if (currentPos
> tabSize
)
1654 return E_INVALIDARG
;
1656 newEnumMoniker
= HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl
));
1658 if (newEnumMoniker
== 0)
1659 return STG_E_INSUFFICIENTMEMORY
;
1661 /* Initialize the virtual function table. */
1662 newEnumMoniker
->IEnumMoniker_iface
.lpVtbl
= &VT_EnumMonikerImpl
;
1663 newEnumMoniker
->ref
= 1;
1665 newEnumMoniker
->tabSize
=tabSize
;
1666 newEnumMoniker
->currentPos
=currentPos
;
1668 newEnumMoniker
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,tabSize
*sizeof(newEnumMoniker
->tabMoniker
[0]));
1670 if (newEnumMoniker
->tabMoniker
==NULL
) {
1671 HeapFree(GetProcessHeap(), 0, newEnumMoniker
);
1672 return E_OUTOFMEMORY
;
1676 for (i
=0;i
<tabSize
;i
++){
1678 newEnumMoniker
->tabMoniker
[i
]=tabMoniker
[i
];
1679 IMoniker_AddRef(tabMoniker
[i
]);
1682 for (i
= tabSize
; i
> 0; i
--){
1684 newEnumMoniker
->tabMoniker
[tabSize
-i
]=tabMoniker
[i
- 1];
1685 IMoniker_AddRef(tabMoniker
[i
- 1]);
1688 *ppmk
=&newEnumMoniker
->IEnumMoniker_iface
;
1693 /********************************************************************************/
1694 /* Virtual function table for the CompositeMonikerImpl class which includes */
1695 /* IPersist, IPersistStream and IMoniker functions. */
1697 static const IMonikerVtbl VT_CompositeMonikerImpl
=
1699 CompositeMonikerImpl_QueryInterface
,
1700 CompositeMonikerImpl_AddRef
,
1701 CompositeMonikerImpl_Release
,
1702 CompositeMonikerImpl_GetClassID
,
1703 CompositeMonikerImpl_IsDirty
,
1704 CompositeMonikerImpl_Load
,
1705 CompositeMonikerImpl_Save
,
1706 CompositeMonikerImpl_GetSizeMax
,
1707 CompositeMonikerImpl_BindToObject
,
1708 CompositeMonikerImpl_BindToStorage
,
1709 CompositeMonikerImpl_Reduce
,
1710 CompositeMonikerImpl_ComposeWith
,
1711 CompositeMonikerImpl_Enum
,
1712 CompositeMonikerImpl_IsEqual
,
1713 CompositeMonikerImpl_Hash
,
1714 CompositeMonikerImpl_IsRunning
,
1715 CompositeMonikerImpl_GetTimeOfLastChange
,
1716 CompositeMonikerImpl_Inverse
,
1717 CompositeMonikerImpl_CommonPrefixWith
,
1718 CompositeMonikerImpl_RelativePathTo
,
1719 CompositeMonikerImpl_GetDisplayName
,
1720 CompositeMonikerImpl_ParseDisplayName
,
1721 CompositeMonikerImpl_IsSystemMoniker
1724 /********************************************************************************/
1725 /* Virtual function table for the IROTData class. */
1726 static const IROTDataVtbl VT_ROTDataImpl
=
1728 CompositeMonikerROTDataImpl_QueryInterface
,
1729 CompositeMonikerROTDataImpl_AddRef
,
1730 CompositeMonikerROTDataImpl_Release
,
1731 CompositeMonikerROTDataImpl_GetComparisonData
1734 static const IMarshalVtbl VT_MarshalImpl
=
1736 CompositeMonikerMarshalImpl_QueryInterface
,
1737 CompositeMonikerMarshalImpl_AddRef
,
1738 CompositeMonikerMarshalImpl_Release
,
1739 CompositeMonikerMarshalImpl_GetUnmarshalClass
,
1740 CompositeMonikerMarshalImpl_GetMarshalSizeMax
,
1741 CompositeMonikerMarshalImpl_MarshalInterface
,
1742 CompositeMonikerMarshalImpl_UnmarshalInterface
,
1743 CompositeMonikerMarshalImpl_ReleaseMarshalData
,
1744 CompositeMonikerMarshalImpl_DisconnectObject
1747 /******************************************************************************
1748 * Composite-Moniker_Construct (local function)
1749 *******************************************************************************/
1751 CompositeMonikerImpl_Construct(IMoniker
**ppMoniker
, IMoniker
*pmkFirst
, IMoniker
*pmkRest
)
1754 IEnumMoniker
*enumMoniker
;
1757 CompositeMonikerImpl
*This
;
1760 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1763 return E_OUTOFMEMORY
;
1765 TRACE("(%p,%p,%p)\n",This
,pmkFirst
,pmkRest
);
1767 /* Initialize the virtual function table. */
1768 This
->IMoniker_iface
.lpVtbl
= &VT_CompositeMonikerImpl
;
1769 This
->IROTData_iface
.lpVtbl
= &VT_ROTDataImpl
;
1770 This
->IMarshal_iface
.lpVtbl
= &VT_MarshalImpl
;
1773 This
->tabSize
=BLOCK_TAB_SIZE
;
1774 This
->tabLastIndex
=0;
1776 This
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,This
->tabSize
*sizeof(This
->tabMoniker
[0]));
1777 if (This
->tabMoniker
==NULL
) {
1778 HeapFree(GetProcessHeap(), 0, This
);
1779 return E_OUTOFMEMORY
;
1782 if (!pmkFirst
&& !pmkRest
)
1784 *ppMoniker
= &This
->IMoniker_iface
;
1788 IMoniker_IsSystemMoniker(pmkFirst
,&mkSys
);
1790 /* put the first moniker contents in the beginning of the table */
1791 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
1793 This
->tabMoniker
[(This
->tabLastIndex
)++]=pmkFirst
;
1794 IMoniker_AddRef(pmkFirst
);
1798 IMoniker_Enum(pmkFirst
,TRUE
,&enumMoniker
);
1800 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
1803 if (++This
->tabLastIndex
==This
->tabSize
){
1804 IMoniker
**tab_moniker
= This
->tabMoniker
;
1806 This
->tabSize
+=BLOCK_TAB_SIZE
;
1807 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(This
->tabMoniker
[0]));
1809 if (This
->tabMoniker
==NULL
){
1810 for (i
= 0; i
< This
->tabLastIndex
; i
++)
1811 IMoniker_Release(tab_moniker
[i
]);
1812 HeapFree(GetProcessHeap(), 0, tab_moniker
);
1813 HeapFree(GetProcessHeap(), 0, This
);
1814 return E_OUTOFMEMORY
;
1819 IEnumMoniker_Release(enumMoniker
);
1822 /* put the rest moniker contents after the first one and make simplification if needed */
1824 IMoniker_IsSystemMoniker(pmkRest
,&mkSys
);
1826 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
1828 /* add a simple moniker to the moniker table */
1830 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],pmkRest
,TRUE
,&tempMk
);
1832 if (res
==MK_E_NEEDGENERIC
){
1834 /* there's no simplification in this case */
1835 This
->tabMoniker
[This
->tabLastIndex
]=pmkRest
;
1837 This
->tabLastIndex
++;
1839 IMoniker_AddRef(pmkRest
);
1841 else if (tempMk
==NULL
){
1843 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
1844 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1846 This
->tabLastIndex
--;
1848 else if (SUCCEEDED(res
)){
1850 /* the non-generic composition was successful so we can make a simplification in this case */
1851 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1853 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
1855 for (i
= 0; i
< This
->tabLastIndex
; i
++)
1856 IMoniker_Release(This
->tabMoniker
[i
]);
1857 HeapFree(GetProcessHeap(), 0, This
->tabMoniker
);
1858 HeapFree(GetProcessHeap(), 0, This
);
1862 /* resize tabMoniker if needed */
1863 if (This
->tabLastIndex
==This
->tabSize
){
1864 IMoniker
**tab_moniker
= This
->tabMoniker
;
1866 This
->tabSize
+=BLOCK_TAB_SIZE
;
1868 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1870 if (This
->tabMoniker
==NULL
){
1871 for (i
= 0; i
< This
->tabLastIndex
; i
++)
1872 IMoniker_Release(tab_moniker
[i
]);
1873 HeapFree(GetProcessHeap(), 0, tab_moniker
);
1874 HeapFree(GetProcessHeap(), 0, This
);
1875 return E_OUTOFMEMORY
;
1881 /* add a composite moniker to the moniker table (do the same thing
1882 * for each moniker within the composite moniker as a simple moniker
1883 * (see above for how to add a simple moniker case) )
1885 IMoniker_Enum(pmkRest
,TRUE
,&enumMoniker
);
1887 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
1889 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],This
->tabMoniker
[This
->tabLastIndex
],TRUE
,&tempMk
);
1891 if (res
==MK_E_NEEDGENERIC
){
1893 This
->tabLastIndex
++;
1895 else if (tempMk
==NULL
){
1897 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1898 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
]);
1899 This
->tabLastIndex
--;
1903 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1905 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
1908 if (This
->tabLastIndex
==This
->tabSize
){
1909 IMoniker
**tab_moniker
= This
->tabMoniker
;
1911 This
->tabSize
+=BLOCK_TAB_SIZE
;
1913 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(This
->tabMoniker
[0]));
1915 if (This
->tabMoniker
==NULL
){
1916 for (i
= 0; i
< This
->tabLastIndex
; i
++)
1917 IMoniker_Release(tab_moniker
[i
]);
1918 HeapFree(GetProcessHeap(), 0, tab_moniker
);
1919 HeapFree(GetProcessHeap(), 0, This
);
1920 return E_OUTOFMEMORY
;
1925 IEnumMoniker_Release(enumMoniker
);
1928 /* only one moniker, then just return it */
1929 if (This
->tabLastIndex
== 1)
1931 *ppMoniker
= This
->tabMoniker
[0];
1932 IMoniker_AddRef(*ppMoniker
);
1933 IMoniker_Release(&This
->IMoniker_iface
);
1936 *ppMoniker
= &This
->IMoniker_iface
;
1941 /******************************************************************************
1942 * CreateGenericComposite [OLE32.@]
1943 ******************************************************************************/
1945 CreateGenericComposite(IMoniker
*pmkFirst
, IMoniker
*pmkRest
, IMoniker
**ppmkComposite
)
1947 IMoniker
* moniker
= 0;
1950 TRACE("(%p,%p,%p)\n",pmkFirst
,pmkRest
,ppmkComposite
);
1952 if (ppmkComposite
==NULL
)
1957 if (pmkFirst
==NULL
&& pmkRest
!=NULL
){
1959 *ppmkComposite
=pmkRest
;
1960 IMoniker_AddRef(pmkRest
);
1963 else if (pmkFirst
!=NULL
&& pmkRest
==NULL
){
1964 *ppmkComposite
=pmkFirst
;
1965 IMoniker_AddRef(pmkFirst
);
1968 else if (pmkFirst
==NULL
&& pmkRest
==NULL
)
1971 hr
= CompositeMonikerImpl_Construct(&moniker
,pmkFirst
,pmkRest
);
1976 hr
= IMoniker_QueryInterface(moniker
,&IID_IMoniker
,(void**)ppmkComposite
);
1977 IMoniker_Release(moniker
);
1982 /******************************************************************************
1983 * MonikerCommonPrefixWith [OLE32.@]
1984 ******************************************************************************/
1986 MonikerCommonPrefixWith(IMoniker
* pmkThis
,IMoniker
* pmkOther
,IMoniker
** ppmkCommon
)
1988 FIXME("(),stub!\n");
1992 static HRESULT WINAPI
CompositeMonikerCF_QueryInterface(IClassFactory
*iface
, REFIID riid
, void **ppv
)
1995 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IClassFactory
))
1998 IClassFactory_AddRef(iface
);
2001 return E_NOINTERFACE
;
2004 static ULONG WINAPI
CompositeMonikerCF_AddRef(LPCLASSFACTORY iface
)
2006 return 2; /* non-heap based object */
2009 static ULONG WINAPI
CompositeMonikerCF_Release(LPCLASSFACTORY iface
)
2011 return 1; /* non-heap based object */
2014 static HRESULT WINAPI
CompositeMonikerCF_CreateInstance(LPCLASSFACTORY iface
,
2015 LPUNKNOWN pUnk
, REFIID riid
, LPVOID
*ppv
)
2020 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
2025 return CLASS_E_NOAGGREGATION
;
2027 hr
= CompositeMonikerImpl_Construct(&pMoniker
, NULL
, NULL
);
2031 hr
= IMoniker_QueryInterface(pMoniker
, riid
, ppv
);
2032 IMoniker_Release(pMoniker
);
2038 static HRESULT WINAPI
CompositeMonikerCF_LockServer(LPCLASSFACTORY iface
, BOOL fLock
)
2040 FIXME("(%d), stub!\n",fLock
);
2044 static const IClassFactoryVtbl CompositeMonikerCFVtbl
=
2046 CompositeMonikerCF_QueryInterface
,
2047 CompositeMonikerCF_AddRef
,
2048 CompositeMonikerCF_Release
,
2049 CompositeMonikerCF_CreateInstance
,
2050 CompositeMonikerCF_LockServer
2052 static const IClassFactoryVtbl
*CompositeMonikerCF
= &CompositeMonikerCFVtbl
;
2054 HRESULT
CompositeMonikerCF_Create(REFIID riid
, LPVOID
*ppv
)
2056 return IClassFactory_QueryInterface((IClassFactory
*)&CompositeMonikerCF
, riid
, ppv
);