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
{
44 IMoniker IMoniker_iface
;
45 IROTData IROTData_iface
;
46 IMarshal IMarshal_iface
;
48 IMoniker
** tabMoniker
; /* dynamic table containing all components (monikers) of this composite moniker */
49 ULONG tabSize
; /* size of tabMoniker */
50 ULONG tabLastIndex
; /* first free index in tabMoniker */
51 } CompositeMonikerImpl
;
53 static inline CompositeMonikerImpl
*impl_from_IMoniker(IMoniker
*iface
)
55 return CONTAINING_RECORD(iface
, CompositeMonikerImpl
, IMoniker_iface
);
58 static inline CompositeMonikerImpl
*impl_from_IROTData(IROTData
*iface
)
60 return CONTAINING_RECORD(iface
, CompositeMonikerImpl
, IROTData_iface
);
63 static inline CompositeMonikerImpl
*impl_from_IMarshal(IMarshal
*iface
)
65 return CONTAINING_RECORD(iface
, CompositeMonikerImpl
, IMarshal_iface
);
68 /* EnumMoniker data structure */
69 typedef struct EnumMonikerImpl
{
70 IEnumMoniker IEnumMoniker_iface
;
72 IMoniker
** tabMoniker
; /* dynamic table containing the enumerated monikers */
73 ULONG tabSize
; /* size of tabMoniker */
74 ULONG currentPos
; /* index pointer on the current moniker */
77 static inline EnumMonikerImpl
*impl_from_IEnumMoniker(IEnumMoniker
*iface
)
79 return CONTAINING_RECORD(iface
, EnumMonikerImpl
, IEnumMoniker_iface
);
82 static HRESULT
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,ULONG tabSize
,ULONG currentPos
,BOOL leftToRigth
,IEnumMoniker
** ppmk
);
84 /*******************************************************************************
85 * CompositeMoniker_QueryInterface
86 *******************************************************************************/
88 CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
90 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
92 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
94 /* Perform a sanity check on the parameters.*/
98 /* Initialize the return parameter */
101 /* Compare the riid with the interface IDs implemented by this object.*/
102 if (IsEqualIID(&IID_IUnknown
, riid
) ||
103 IsEqualIID(&IID_IPersist
, riid
) ||
104 IsEqualIID(&IID_IPersistStream
, riid
) ||
105 IsEqualIID(&IID_IMoniker
, riid
)
108 else if (IsEqualIID(&IID_IROTData
, riid
))
109 *ppvObject
= &This
->IROTData_iface
;
110 else if (IsEqualIID(&IID_IMarshal
, riid
))
111 *ppvObject
= &This
->IMarshal_iface
;
113 /* Check that we obtained an interface.*/
115 return E_NOINTERFACE
;
117 /* Query Interface always increases the reference count by one when it is successful */
118 IMoniker_AddRef(iface
);
123 /******************************************************************************
124 * CompositeMoniker_AddRef
125 ******************************************************************************/
127 CompositeMonikerImpl_AddRef(IMoniker
* iface
)
129 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
131 TRACE("(%p)\n",This
);
133 return InterlockedIncrement(&This
->ref
);
136 static void CompositeMonikerImpl_ReleaseMonikersInTable(CompositeMonikerImpl
*This
)
140 for (i
= 0; i
< This
->tabLastIndex
; i
++)
141 IMoniker_Release(This
->tabMoniker
[i
]);
143 This
->tabLastIndex
= 0;
146 /******************************************************************************
147 * CompositeMoniker_Release
148 ******************************************************************************/
150 CompositeMonikerImpl_Release(IMoniker
* iface
)
152 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
155 TRACE("(%p)\n",This
);
157 ref
= InterlockedDecrement(&This
->ref
);
159 /* destroy the object if there are no more references to it */
162 /* release all the components before destroying this object */
163 CompositeMonikerImpl_ReleaseMonikersInTable(This
);
165 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
166 HeapFree(GetProcessHeap(),0,This
);
171 /******************************************************************************
172 * CompositeMoniker_GetClassID
173 ******************************************************************************/
174 static HRESULT WINAPI
175 CompositeMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
177 TRACE("(%p,%p)\n",iface
,pClassID
);
182 *pClassID
= CLSID_CompositeMoniker
;
187 /******************************************************************************
188 * CompositeMoniker_IsDirty
189 ******************************************************************************/
190 static HRESULT WINAPI
191 CompositeMonikerImpl_IsDirty(IMoniker
* iface
)
193 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
194 method in the OLE-provided moniker interfaces always return S_FALSE because
195 their internal state never changes. */
197 TRACE("(%p)\n",iface
);
202 /******************************************************************************
203 * CompositeMoniker_Load
204 ******************************************************************************/
205 static HRESULT WINAPI
206 CompositeMonikerImpl_Load(IMoniker
* iface
,IStream
* pStm
)
208 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
213 TRACE("(%p,%p)\n",iface
,pStm
);
215 /* this function call OleLoadFromStream function for each moniker within this object */
217 res
=IStream_Read(pStm
,&moniker_count
,sizeof(DWORD
),NULL
);
220 ERR("couldn't reading moniker count from stream\n");
224 CompositeMonikerImpl_ReleaseMonikersInTable(This
);
226 for (i
= 0; i
< moniker_count
; i
++)
228 res
=OleLoadFromStream(pStm
,&IID_IMoniker
,(void**)&This
->tabMoniker
[This
->tabLastIndex
]);
231 ERR("couldn't load moniker from stream, res = 0x%08x\n", res
);
235 /* resize the table if needed */
236 if (++This
->tabLastIndex
==This
->tabSize
){
238 This
->tabSize
+=BLOCK_TAB_SIZE
;
239 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(This
->tabMoniker
[0]));
241 if (This
->tabMoniker
==NULL
)
242 return E_OUTOFMEMORY
;
249 /******************************************************************************
250 * CompositeMoniker_Save
251 ******************************************************************************/
252 static HRESULT WINAPI
253 CompositeMonikerImpl_Save(IMoniker
* iface
,IStream
* pStm
,BOOL fClearDirty
)
255 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
257 IEnumMoniker
*enumMk
;
259 DWORD moniker_count
= This
->tabLastIndex
;
261 TRACE("(%p,%p,%d)\n",iface
,pStm
,fClearDirty
);
263 /* This function calls OleSaveToStream function for each moniker within
265 * When I tested this function in windows, I usually found this constant
266 * at the beginning of the stream. I don't known why (there's no
267 * indication in the specification) !
269 res
=IStream_Write(pStm
,&moniker_count
,sizeof(moniker_count
),NULL
);
270 if (FAILED(res
)) return res
;
272 IMoniker_Enum(iface
,TRUE
,&enumMk
);
274 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
276 res
=OleSaveToStream((IPersistStream
*)pmk
,pStm
);
278 IMoniker_Release(pmk
);
282 IEnumMoniker_Release(enumMk
);
287 IEnumMoniker_Release(enumMk
);
292 /******************************************************************************
293 * CompositeMoniker_GetSizeMax
294 ******************************************************************************/
295 static HRESULT WINAPI
296 CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
,ULARGE_INTEGER
* pcbSize
)
298 IEnumMoniker
*enumMk
;
300 ULARGE_INTEGER ptmpSize
;
302 /* The sizeMax of this object is calculated by calling GetSizeMax on
303 * each moniker within this object then summing all returned values
306 TRACE("(%p,%p)\n",iface
,pcbSize
);
311 pcbSize
->QuadPart
= sizeof(DWORD
);
313 IMoniker_Enum(iface
,TRUE
,&enumMk
);
315 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
317 IMoniker_GetSizeMax(pmk
,&ptmpSize
);
319 IMoniker_Release(pmk
);
321 pcbSize
->QuadPart
= ptmpSize
.QuadPart
+ sizeof(CLSID
);
324 IEnumMoniker_Release(enumMk
);
329 /******************************************************************************
330 * CompositeMoniker_BindToObject
331 ******************************************************************************/
332 static HRESULT WINAPI
333 CompositeMonikerImpl_BindToObject(IMoniker
* iface
, IBindCtx
* pbc
,
334 IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
)
337 IRunningObjectTable
*prot
;
338 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
339 IEnumMoniker
*enumMoniker
;
341 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
347 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
348 /* object for the requested interface pointer. */
351 res
=IBindCtx_GetRunningObjectTable(pbc
,&prot
);
355 /* if the requested class was loaded before ! we don't need to reload it */
356 res
= IRunningObjectTable_GetObject(prot
,iface
,(IUnknown
**)ppvResult
);
363 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
364 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
366 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
367 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
368 IEnumMoniker_Release(enumMoniker
);
370 res
=CreateAntiMoniker(&antiMk
);
371 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
372 IMoniker_Release(antiMk
);
374 res
=IMoniker_BindToObject(mostRigthMk
,pbc
,tempMk
,riid
,ppvResult
);
376 IMoniker_Release(tempMk
);
377 IMoniker_Release(mostRigthMk
);
383 /******************************************************************************
384 * CompositeMoniker_BindToStorage
385 ******************************************************************************/
386 static HRESULT WINAPI
387 CompositeMonikerImpl_BindToStorage(IMoniker
* iface
, IBindCtx
* pbc
,
388 IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
)
391 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*leftMk
;
392 IEnumMoniker
*enumMoniker
;
394 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
398 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
399 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
403 res
= IMoniker_ComposeWith(pmkToLeft
, iface
, FALSE
, &leftMk
);
404 if (FAILED(res
)) return res
;
409 IMoniker_Enum(iface
, FALSE
, &enumMoniker
);
410 IEnumMoniker_Next(enumMoniker
, 1, &mostRigthMk
, NULL
);
411 IEnumMoniker_Release(enumMoniker
);
413 res
= CreateAntiMoniker(&antiMk
);
414 if (FAILED(res
)) return res
;
415 res
= IMoniker_ComposeWith(leftMk
, antiMk
, 0, &tempMk
);
416 if (FAILED(res
)) return res
;
417 IMoniker_Release(antiMk
);
419 res
= IMoniker_BindToStorage(mostRigthMk
, pbc
, tempMk
, riid
, ppvResult
);
421 IMoniker_Release(tempMk
);
423 IMoniker_Release(mostRigthMk
);
426 IMoniker_Release(leftMk
);
431 /******************************************************************************
432 * CompositeMoniker_Reduce
433 ******************************************************************************/
434 static HRESULT WINAPI
435 CompositeMonikerImpl_Reduce(IMoniker
* iface
, IBindCtx
* pbc
, DWORD dwReduceHowFar
,
436 IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
)
438 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*leftReducedComposedMk
,*mostRigthReducedMk
;
439 IEnumMoniker
*enumMoniker
;
441 TRACE("(%p,%p,%d,%p,%p)\n",iface
,pbc
,dwReduceHowFar
,ppmkToLeft
,ppmkReduced
);
443 if (ppmkReduced
==NULL
)
446 /* This method recursively calls Reduce for each of its component monikers. */
448 if (ppmkToLeft
==NULL
){
450 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
451 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
452 IEnumMoniker_Release(enumMoniker
);
454 CreateAntiMoniker(&antiMk
);
455 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
456 IMoniker_Release(antiMk
);
458 return IMoniker_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
, ppmkReduced
);
460 else if (*ppmkToLeft
==NULL
)
462 return IMoniker_Reduce(iface
,pbc
,dwReduceHowFar
,NULL
,ppmkReduced
);
466 /* separate the composite moniker in to left and right moniker */
467 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
468 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
469 IEnumMoniker_Release(enumMoniker
);
471 CreateAntiMoniker(&antiMk
);
472 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
473 IMoniker_Release(antiMk
);
475 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
476 /* of the reduced components */
477 if (IMoniker_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,NULL
,&mostRigthReducedMk
) &&
478 IMoniker_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
,&leftReducedComposedMk
)
481 return CreateGenericComposite(leftReducedComposedMk
,mostRigthReducedMk
,ppmkReduced
);
484 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
486 IMoniker_AddRef(iface
);
490 return MK_S_REDUCED_TO_SELF
;
495 /******************************************************************************
496 * CompositeMoniker_ComposeWith
497 ******************************************************************************/
498 static HRESULT WINAPI
499 CompositeMonikerImpl_ComposeWith(IMoniker
* iface
, IMoniker
* pmkRight
,
500 BOOL fOnlyIfNotGeneric
, IMoniker
** ppmkComposite
)
502 TRACE("(%p,%p,%d,%p)\n",iface
,pmkRight
,fOnlyIfNotGeneric
,ppmkComposite
);
504 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
509 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
510 /* otherwise, the method returns the result of combining the two monikers by calling the */
511 /* CreateGenericComposite function */
513 if (fOnlyIfNotGeneric
)
514 return MK_E_NEEDGENERIC
;
516 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
519 /******************************************************************************
520 * CompositeMoniker_Enum
521 ******************************************************************************/
522 static HRESULT WINAPI
523 CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
525 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
527 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
529 if (ppenumMoniker
== NULL
)
532 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabLastIndex
,0,fForward
,ppenumMoniker
);
535 /******************************************************************************
536 * CompositeMoniker_IsEqual
537 ******************************************************************************/
538 static HRESULT WINAPI
539 CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
)
541 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
542 IMoniker
*tempMk1
,*tempMk2
;
543 HRESULT res1
,res2
,res
;
546 TRACE("(%p,%p)\n",iface
,pmkOtherMoniker
);
548 if (pmkOtherMoniker
==NULL
)
551 /* This method returns S_OK if the components of both monikers are equal when compared in the */
552 /* left-to-right order.*/
553 IMoniker_Enum(pmkOtherMoniker
,TRUE
,&enumMoniker1
);
555 if (enumMoniker1
==NULL
)
558 IMoniker_Enum(iface
,TRUE
,&enumMoniker2
);
562 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
563 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
565 if((res1
==S_OK
)&&(res2
==S_OK
)){
566 done
= (res
= IMoniker_IsEqual(tempMk1
,tempMk2
)) == S_FALSE
;
570 res
= (res1
==S_FALSE
) && (res2
==S_FALSE
);
575 IMoniker_Release(tempMk1
);
578 IMoniker_Release(tempMk2
);
581 IEnumMoniker_Release(enumMoniker1
);
582 IEnumMoniker_Release(enumMoniker2
);
586 /******************************************************************************
587 * CompositeMoniker_Hash
588 ******************************************************************************/
589 static HRESULT WINAPI
590 CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
592 IEnumMoniker
*enumMoniker
;
597 TRACE("(%p,%p)\n",iface
,pdwHash
);
602 res
= IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
608 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
609 res
= IMoniker_Hash(tempMk
, &tempHash
);
612 *pdwHash
= *pdwHash
^ tempHash
;
614 IMoniker_Release(tempMk
);
617 IEnumMoniker_Release(enumMoniker
);
622 /******************************************************************************
623 * CompositeMoniker_IsRunning
624 ******************************************************************************/
625 static HRESULT WINAPI
626 CompositeMonikerImpl_IsRunning(IMoniker
* iface
, IBindCtx
* pbc
,
627 IMoniker
* pmkToLeft
, IMoniker
* pmkNewlyRunning
)
629 IRunningObjectTable
* rot
;
631 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
632 IEnumMoniker
*enumMoniker
;
634 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
636 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
637 if (pmkToLeft
!=NULL
){
639 CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
641 res
= IMoniker_IsRunning(tempMk
,pbc
,NULL
,pmkNewlyRunning
);
643 IMoniker_Release(tempMk
);
648 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
649 /* to this moniker */
651 if (pmkNewlyRunning
!=NULL
)
653 if (IMoniker_IsEqual(iface
,pmkNewlyRunning
)==S_OK
)
664 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
665 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
666 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
667 /* the composite as the pmkToLeft parameter for that call. */
669 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
674 res
= IRunningObjectTable_IsRunning(rot
,iface
);
675 IRunningObjectTable_Release(rot
);
682 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
683 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
684 IEnumMoniker_Release(enumMoniker
);
686 res
=CreateAntiMoniker(&antiMk
);
687 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
688 IMoniker_Release(antiMk
);
690 res
=IMoniker_IsRunning(mostRigthMk
,pbc
,tempMk
,pmkNewlyRunning
);
692 IMoniker_Release(tempMk
);
693 IMoniker_Release(mostRigthMk
);
700 /******************************************************************************
701 * CompositeMoniker_GetTimeOfLastChange
702 ******************************************************************************/
703 static HRESULT WINAPI
704 CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
, IBindCtx
* pbc
,
705 IMoniker
* pmkToLeft
, FILETIME
* pCompositeTime
)
708 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*leftMk
;
709 IEnumMoniker
*enumMoniker
;
711 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pCompositeTime
);
713 if (pCompositeTime
==NULL
)
716 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
717 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
718 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
719 /* of the composite as the pmkToLeft parameter for that call. */
722 IRunningObjectTable
* rot
;
724 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, &mostRigthMk
, 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(mostRigthMk
, pbc
, tempMk
, pCompositeTime
);
752 IMoniker_Release(tempMk
);
753 IMoniker_Release(mostRigthMk
);
756 IMoniker_Release(leftMk
);
761 /******************************************************************************
762 * CompositeMoniker_Inverse
763 ******************************************************************************/
764 static HRESULT WINAPI
765 CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
768 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*tempInvMk
,*mostRigthInvMk
;
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 */
779 res
=CreateAntiMoniker(&antiMk
);
780 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
781 IMoniker_Release(antiMk
);
785 return IMoniker_Inverse(iface
,ppmk
);
789 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
790 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
791 IEnumMoniker_Release(enumMoniker
);
793 IMoniker_Inverse(mostRigthMk
,&mostRigthInvMk
);
794 CompositeMonikerImpl_Inverse(tempMk
,&tempInvMk
);
796 res
=CreateGenericComposite(mostRigthInvMk
,tempInvMk
,ppmk
);
798 IMoniker_Release(tempMk
);
799 IMoniker_Release(mostRigthMk
);
800 IMoniker_Release(tempInvMk
);
801 IMoniker_Release(mostRigthInvMk
);
807 /******************************************************************************
808 * CompositeMoniker_CommonPrefixWith
809 ******************************************************************************/
810 static HRESULT WINAPI
811 CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
, IMoniker
* pmkOther
,
812 IMoniker
** ppmkPrefix
)
816 IMoniker
*tempMk1
,*tempMk2
,*mostLeftMk1
,*mostLeftMk2
;
817 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
818 ULONG i
,nbCommonMk
=0;
820 /* If the other moniker is a composite, this method compares the components of each composite from left */
821 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
822 /* of the leftmost components were common to both monikers. */
824 if (ppmkPrefix
==NULL
)
830 return MK_E_NOPREFIX
;
832 IMoniker_IsSystemMoniker(pmkOther
,&mkSys
);
834 if(mkSys
==MKSYS_GENERICCOMPOSITE
){
836 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
837 IMoniker_Enum(pmkOther
,TRUE
,&enumMoniker2
);
841 res1
=IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
842 res2
=IEnumMoniker_Next(enumMoniker2
,1,&mostLeftMk2
,NULL
);
844 if ((res1
==S_FALSE
) && (res2
==S_FALSE
)){
846 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
848 IMoniker_AddRef(iface
);
851 else if ((res1
==S_OK
) && (res2
==S_OK
)){
853 if (IMoniker_IsEqual(mostLeftMk1
,mostLeftMk2
)==S_OK
)
861 else if (res1
==S_OK
){
863 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
864 /* ppmkPrefix to the other moniker. */
865 *ppmkPrefix
=pmkOther
;
869 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
870 /* to this moniker. */
876 IEnumMoniker_Release(enumMoniker1
);
877 IEnumMoniker_Release(enumMoniker2
);
879 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
881 return MK_E_NOPREFIX
;
883 IEnumMoniker_Reset(enumMoniker1
);
885 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
887 /* if we have more than one common moniker the result will be a composite moniker */
890 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
891 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
892 CreateGenericComposite(tempMk1
,tempMk2
,ppmkPrefix
);
893 IMoniker_Release(tempMk1
);
894 IMoniker_Release(tempMk2
);
896 /* compose all common monikers in a composite moniker */
897 for(i
=0;i
<nbCommonMk
;i
++){
899 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
901 CreateGenericComposite(*ppmkPrefix
,tempMk1
,&tempMk2
);
903 IMoniker_Release(*ppmkPrefix
);
905 IMoniker_Release(tempMk1
);
912 /* if we have only one common moniker the result will be a simple moniker which is the most-left one*/
919 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
922 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
924 IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
926 if (IMoniker_IsEqual(pmkOther
,mostLeftMk1
)==S_OK
){
928 *ppmkPrefix
=pmkOther
;
933 return MK_E_NOPREFIX
;
937 /***************************************************************************************************
938 * GetAfterCommonPrefix (local function)
939 * This function returns a moniker that consist of the remainder when the common prefix is removed
940 ***************************************************************************************************/
941 static VOID
GetAfterCommonPrefix(IMoniker
* pGenMk
,IMoniker
* commonMk
,IMoniker
** restMk
)
943 IMoniker
*tempMk
,*tempMk1
,*tempMk2
;
944 IEnumMoniker
*enumMoniker1
,*enumMoniker2
,*enumMoniker3
;
951 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
952 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
953 /* on the first difference. */
954 IMoniker_Enum(pGenMk
,TRUE
,&enumMoniker1
);
956 IMoniker_IsSystemMoniker(commonMk
,&mkSys
);
958 if (mkSys
==MKSYS_GENERICCOMPOSITE
){
960 IMoniker_Enum(commonMk
,TRUE
,&enumMoniker2
);
963 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
964 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
966 if ((res1
==S_FALSE
)||(res2
==S_FALSE
)){
972 IMoniker_Release(tempMk1
);
973 IMoniker_Release(tempMk2
);
977 IMoniker_Release(tempMk1
);
978 IMoniker_Release(tempMk2
);
982 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
983 IMoniker_Release(tempMk1
);
986 /* count the number of elements in the enumerator after the common prefix */
987 IEnumMoniker_Clone(enumMoniker1
,&enumMoniker3
);
989 for(;IEnumMoniker_Next(enumMoniker3
,1,&tempMk
,NULL
)==S_OK
;nbRestMk
++)
991 IMoniker_Release(tempMk
);
996 /* create a generic composite moniker with monikers located after the common prefix */
997 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1006 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1008 CreateGenericComposite(tempMk1
,tempMk2
,restMk
);
1010 IMoniker_Release(tempMk1
);
1012 IMoniker_Release(tempMk2
);
1014 while(IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
)==S_OK
){
1016 CreateGenericComposite(*restMk
,tempMk1
,&tempMk2
);
1018 IMoniker_Release(tempMk1
);
1020 IMoniker_Release(*restMk
);
1027 /******************************************************************************
1028 * CompositeMoniker_RelativePathTo
1029 ******************************************************************************/
1030 static HRESULT WINAPI
1031 CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmkOther
,
1032 IMoniker
** ppmkRelPath
)
1035 IMoniker
*restOtherMk
=0,*restThisMk
=0,*invRestThisMk
=0,*commonMk
=0;
1037 TRACE("(%p,%p,%p)\n",iface
,pmkOther
,ppmkRelPath
);
1039 if (ppmkRelPath
==NULL
)
1044 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1045 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1046 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1048 /* finds the common prefix of the two monikers */
1049 res
=IMoniker_CommonPrefixWith(iface
,pmkOther
,&commonMk
);
1051 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1052 if ((res
== MK_E_NOPREFIX
)||(res
==MK_S_US
)){
1054 *ppmkRelPath
=pmkOther
;
1055 IMoniker_AddRef(pmkOther
);
1059 GetAfterCommonPrefix(iface
,commonMk
,&restThisMk
);
1060 GetAfterCommonPrefix(pmkOther
,commonMk
,&restOtherMk
);
1062 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1063 /* moniker when the common prefix is removed */
1066 IMoniker_Inverse(restThisMk
,ppmkRelPath
);
1067 IMoniker_Release(restThisMk
);
1069 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1070 /* when the common prefix is removed */
1071 else if (res
==MK_S_ME
){
1073 *ppmkRelPath
=restOtherMk
;
1074 IMoniker_AddRef(restOtherMk
);
1076 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1077 /* moniker on the right of it. */
1078 else if (res
==S_OK
){
1080 IMoniker_Inverse(restThisMk
,&invRestThisMk
);
1081 IMoniker_Release(restThisMk
);
1082 CreateGenericComposite(invRestThisMk
,restOtherMk
,ppmkRelPath
);
1083 IMoniker_Release(invRestThisMk
);
1084 IMoniker_Release(restOtherMk
);
1089 /******************************************************************************
1090 * CompositeMoniker_GetDisplayName
1091 ******************************************************************************/
1092 static HRESULT WINAPI
1093 CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
1094 IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
)
1097 IEnumMoniker
*enumMoniker
;
1101 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
1103 if (ppszDisplayName
==NULL
)
1106 *ppszDisplayName
=CoTaskMemAlloc(sizeof(WCHAR
));
1108 if (*ppszDisplayName
==NULL
)
1109 return E_OUTOFMEMORY
;
1111 /* This method returns the concatenation of the display names returned by each component moniker of */
1114 **ppszDisplayName
=0;
1116 IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
1118 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
1120 IMoniker_GetDisplayName(tempMk
,pbc
,NULL
,&tempStr
);
1122 lengthStr
+=lstrlenW(tempStr
);
1124 *ppszDisplayName
=CoTaskMemRealloc(*ppszDisplayName
,lengthStr
* sizeof(WCHAR
));
1126 if (*ppszDisplayName
==NULL
)
1127 return E_OUTOFMEMORY
;
1129 strcatW(*ppszDisplayName
,tempStr
);
1131 CoTaskMemFree(tempStr
);
1132 IMoniker_Release(tempMk
);
1135 IEnumMoniker_Release(enumMoniker
);
1140 /******************************************************************************
1141 * CompositeMoniker_ParseDisplayName
1142 ******************************************************************************/
1143 static HRESULT WINAPI
1144 CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
1145 IMoniker
* pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
* pchEaten
,
1148 IEnumMoniker
*enumMoniker
;
1149 IMoniker
*tempMk
,*mostRigthMk
,*antiMk
;
1150 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1151 /* passing everything else as the pmkToLeft parameter for that call. */
1153 /* get the most right moniker */
1154 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1155 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1156 IEnumMoniker_Release(enumMoniker
);
1158 /* get the left moniker */
1159 CreateAntiMoniker(&antiMk
);
1160 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1161 IMoniker_Release(antiMk
);
1163 return IMoniker_ParseDisplayName(mostRigthMk
,pbc
,tempMk
,pszDisplayName
,pchEaten
,ppmkOut
);
1166 /******************************************************************************
1167 * CompositeMoniker_IsSystemMoniker
1168 ******************************************************************************/
1169 static HRESULT WINAPI
1170 CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
1172 TRACE("(%p,%p)\n",iface
,pwdMksys
);
1177 (*pwdMksys
)=MKSYS_GENERICCOMPOSITE
;
1182 /*******************************************************************************
1183 * CompositeMonikerIROTData_QueryInterface
1184 *******************************************************************************/
1185 static HRESULT WINAPI
1186 CompositeMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,
1189 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
1191 TRACE("(%p,%p,%p)\n",iface
,riid
,ppvObject
);
1193 return CompositeMonikerImpl_QueryInterface(&This
->IMoniker_iface
, riid
, ppvObject
);
1196 /***********************************************************************
1197 * CompositeMonikerIROTData_AddRef
1200 CompositeMonikerROTDataImpl_AddRef(IROTData
*iface
)
1202 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
1204 TRACE("(%p)\n",iface
);
1206 return IMoniker_AddRef(&This
->IMoniker_iface
);
1209 /***********************************************************************
1210 * CompositeMonikerIROTData_Release
1212 static ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
)
1214 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
1216 TRACE("(%p)\n",iface
);
1218 return IMoniker_Release(&This
->IMoniker_iface
);
1221 /******************************************************************************
1222 * CompositeMonikerIROTData_GetComparisonData
1223 ******************************************************************************/
1224 static HRESULT WINAPI
1225 CompositeMonikerROTDataImpl_GetComparisonData(IROTData
* iface
,
1226 BYTE
* pbData
, ULONG cbMax
, ULONG
* pcbData
)
1228 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
1229 IEnumMoniker
*pEnumMk
;
1233 TRACE("(%p, %u, %p)\n", pbData
, cbMax
, pcbData
);
1235 *pcbData
= sizeof(CLSID
);
1237 hr
= IMoniker_Enum(&This
->IMoniker_iface
, TRUE
, &pEnumMk
);
1238 if (FAILED(hr
)) return hr
;
1240 while(IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1243 hr
= IMoniker_QueryInterface(pmk
, &IID_IROTData
, (void **)&pROTData
);
1245 ERR("moniker doesn't support IROTData interface\n");
1250 hr
= IROTData_GetComparisonData(pROTData
, NULL
, 0, &cbData
);
1251 IROTData_Release(pROTData
);
1252 if (SUCCEEDED(hr
) || (hr
== E_OUTOFMEMORY
))
1258 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr
);
1261 IMoniker_Release(pmk
);
1265 IEnumMoniker_Release(pEnumMk
);
1269 if (cbMax
< *pcbData
)
1270 return E_OUTOFMEMORY
;
1272 IEnumMoniker_Reset(pEnumMk
);
1274 memcpy(pbData
, &CLSID_CompositeMoniker
, sizeof(CLSID
));
1275 pbData
+= sizeof(CLSID
);
1276 cbMax
-= sizeof(CLSID
);
1278 while (IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1281 hr
= IMoniker_QueryInterface(pmk
, &IID_IROTData
, (void **)&pROTData
);
1283 ERR("moniker doesn't support IROTData interface\n");
1288 hr
= IROTData_GetComparisonData(pROTData
, pbData
, cbMax
, &cbData
);
1289 IROTData_Release(pROTData
);
1296 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr
);
1299 IMoniker_Release(pmk
);
1303 IEnumMoniker_Release(pEnumMk
);
1308 IEnumMoniker_Release(pEnumMk
);
1313 static HRESULT WINAPI
CompositeMonikerMarshalImpl_QueryInterface(IMarshal
*iface
, REFIID riid
, LPVOID
*ppv
)
1315 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1317 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppv
);
1319 return CompositeMonikerImpl_QueryInterface(&This
->IMoniker_iface
, riid
, ppv
);
1322 static ULONG WINAPI
CompositeMonikerMarshalImpl_AddRef(IMarshal
*iface
)
1324 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1326 TRACE("(%p)\n",iface
);
1328 return CompositeMonikerImpl_AddRef(&This
->IMoniker_iface
);
1331 static ULONG WINAPI
CompositeMonikerMarshalImpl_Release(IMarshal
*iface
)
1333 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1335 TRACE("(%p)\n",iface
);
1337 return CompositeMonikerImpl_Release(&This
->IMoniker_iface
);
1340 static HRESULT WINAPI
CompositeMonikerMarshalImpl_GetUnmarshalClass(
1341 IMarshal
*iface
, REFIID riid
, void *pv
, DWORD dwDestContext
,
1342 void* pvDestContext
, DWORD mshlflags
, CLSID
* pCid
)
1344 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1346 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid
), pv
,
1347 dwDestContext
, pvDestContext
, mshlflags
, pCid
);
1349 return IMoniker_GetClassID(&This
->IMoniker_iface
, pCid
);
1352 static HRESULT WINAPI
CompositeMonikerMarshalImpl_GetMarshalSizeMax(
1353 IMarshal
*iface
, REFIID riid
, void *pv
, DWORD dwDestContext
,
1354 void* pvDestContext
, DWORD mshlflags
, DWORD
* pSize
)
1356 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1357 IEnumMoniker
*pEnumMk
;
1360 ULARGE_INTEGER size
;
1362 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid
), pv
,
1363 dwDestContext
, pvDestContext
, mshlflags
, pSize
);
1365 *pSize
= 0x10; /* to match native */
1367 hr
= IMoniker_Enum(&This
->IMoniker_iface
, TRUE
, &pEnumMk
);
1368 if (FAILED(hr
)) return hr
;
1370 hr
= IMoniker_GetSizeMax(&This
->IMoniker_iface
, &size
);
1372 while (IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1376 hr
= CoGetMarshalSizeMax(&size
, &IID_IMoniker
, (IUnknown
*)pmk
, dwDestContext
, pvDestContext
, mshlflags
);
1380 IMoniker_Release(pmk
);
1384 IEnumMoniker_Release(pEnumMk
);
1389 IEnumMoniker_Release(pEnumMk
);
1394 static HRESULT WINAPI
CompositeMonikerMarshalImpl_MarshalInterface(IMarshal
*iface
, IStream
*pStm
,
1395 REFIID riid
, void* pv
, DWORD dwDestContext
,
1396 void* pvDestContext
, DWORD mshlflags
)
1398 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1399 IEnumMoniker
*pEnumMk
;
1404 TRACE("(%p, %s, %p, %x, %p, %x)\n", pStm
, debugstr_guid(riid
), pv
,
1405 dwDestContext
, pvDestContext
, mshlflags
);
1407 hr
= IMoniker_Enum(&This
->IMoniker_iface
, TRUE
, &pEnumMk
);
1408 if (FAILED(hr
)) return hr
;
1410 while (IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1412 hr
= CoMarshalInterface(pStm
, &IID_IMoniker
, (IUnknown
*)pmk
, dwDestContext
, pvDestContext
, mshlflags
);
1414 IMoniker_Release(pmk
);
1418 IEnumMoniker_Release(pEnumMk
);
1425 FIXME("moniker count of %d not supported\n", i
);
1427 IEnumMoniker_Release(pEnumMk
);
1432 static HRESULT WINAPI
CompositeMonikerMarshalImpl_UnmarshalInterface(IMarshal
*iface
, IStream
*pStm
,
1433 REFIID riid
, void **ppv
)
1435 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1438 TRACE("(%p, %s, %p)\n", pStm
, debugstr_guid(riid
), ppv
);
1440 CompositeMonikerImpl_ReleaseMonikersInTable(This
);
1442 /* resize the table if needed */
1443 if (This
->tabLastIndex
+ 2 > This
->tabSize
)
1445 This
->tabSize
+= max(BLOCK_TAB_SIZE
, 2);
1446 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(This
->tabMoniker
[0]));
1448 if (This
->tabMoniker
==NULL
)
1449 return E_OUTOFMEMORY
;
1452 hr
= CoUnmarshalInterface(pStm
, &IID_IMoniker
, (void**)&This
->tabMoniker
[This
->tabLastIndex
]);
1455 ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr
);
1458 This
->tabLastIndex
++;
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
++;
1467 return IMoniker_QueryInterface(&This
->IMoniker_iface
, riid
, ppv
);
1470 static HRESULT WINAPI
CompositeMonikerMarshalImpl_ReleaseMarshalData(IMarshal
*iface
, IStream
*pStm
)
1472 TRACE("(%p)\n", pStm
);
1473 /* can't release a state-based marshal as nothing on server side to
1478 static HRESULT WINAPI
CompositeMonikerMarshalImpl_DisconnectObject(IMarshal
*iface
,
1481 TRACE("(0x%x)\n", dwReserved
);
1482 /* can't disconnect a state-based marshal as nothing on server side to
1483 * disconnect from */
1487 /******************************************************************************
1488 * EnumMonikerImpl_QueryInterface
1489 ******************************************************************************/
1490 static HRESULT WINAPI
1491 EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
)
1493 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1495 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
1497 /* Perform a sanity check on the parameters.*/
1499 return E_INVALIDARG
;
1501 /* Initialize the return parameter */
1504 /* Compare the riid with the interface IDs implemented by this object.*/
1505 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IEnumMoniker
, riid
))
1508 /* Check that we obtained an interface.*/
1509 if ((*ppvObject
)==0)
1510 return E_NOINTERFACE
;
1512 /* Query Interface always increases the reference count by one when it is successful */
1513 IEnumMoniker_AddRef(iface
);
1518 /******************************************************************************
1519 * EnumMonikerImpl_AddRef
1520 ******************************************************************************/
1522 EnumMonikerImpl_AddRef(IEnumMoniker
* iface
)
1524 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1526 TRACE("(%p)\n",This
);
1528 return InterlockedIncrement(&This
->ref
);
1532 /******************************************************************************
1533 * EnumMonikerImpl_Release
1534 ******************************************************************************/
1536 EnumMonikerImpl_Release(IEnumMoniker
* iface
)
1538 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1541 TRACE("(%p)\n",This
);
1543 ref
= InterlockedDecrement(&This
->ref
);
1545 /* destroy the object if there are no more references to it */
1548 for(i
=0;i
<This
->tabSize
;i
++)
1549 IMoniker_Release(This
->tabMoniker
[i
]);
1551 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
1552 HeapFree(GetProcessHeap(),0,This
);
1557 /******************************************************************************
1558 * EnumMonikerImpl_Next
1559 ******************************************************************************/
1560 static HRESULT WINAPI
1561 EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
, IMoniker
** rgelt
,
1564 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1567 /* retrieve the requested number of moniker from the current position */
1568 for(i
=0;((This
->currentPos
< This
->tabSize
) && (i
< celt
));i
++)
1570 rgelt
[i
]=This
->tabMoniker
[This
->currentPos
++];
1571 IMoniker_AddRef(rgelt
[i
]);
1574 if (pceltFethed
!=NULL
)
1583 /******************************************************************************
1584 * EnumMonikerImpl_Skip
1585 ******************************************************************************/
1586 static HRESULT WINAPI
1587 EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
)
1589 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1591 if ((This
->currentPos
+celt
) >= This
->tabSize
)
1594 This
->currentPos
+=celt
;
1599 /******************************************************************************
1600 * EnumMonikerImpl_Reset
1601 ******************************************************************************/
1602 static HRESULT WINAPI
1603 EnumMonikerImpl_Reset(IEnumMoniker
* iface
)
1605 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1612 /******************************************************************************
1613 * EnumMonikerImpl_Clone
1614 ******************************************************************************/
1615 static HRESULT WINAPI
1616 EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
)
1618 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1620 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabSize
,This
->currentPos
,TRUE
,ppenum
);
1623 /********************************************************************************/
1624 /* Virtual function table for the IROTData class */
1625 static const IEnumMonikerVtbl VT_EnumMonikerImpl
=
1627 EnumMonikerImpl_QueryInterface
,
1628 EnumMonikerImpl_AddRef
,
1629 EnumMonikerImpl_Release
,
1630 EnumMonikerImpl_Next
,
1631 EnumMonikerImpl_Skip
,
1632 EnumMonikerImpl_Reset
,
1633 EnumMonikerImpl_Clone
1636 /******************************************************************************
1637 * EnumMonikerImpl_CreateEnumMoniker
1638 ******************************************************************************/
1640 EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
, ULONG tabSize
,
1641 ULONG currentPos
, BOOL leftToRight
, IEnumMoniker
** ppmk
)
1643 EnumMonikerImpl
* newEnumMoniker
;
1646 if (currentPos
> tabSize
)
1647 return E_INVALIDARG
;
1649 newEnumMoniker
= HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl
));
1651 if (newEnumMoniker
== 0)
1652 return STG_E_INSUFFICIENTMEMORY
;
1654 /* Initialize the virtual function table. */
1655 newEnumMoniker
->IEnumMoniker_iface
.lpVtbl
= &VT_EnumMonikerImpl
;
1656 newEnumMoniker
->ref
= 1;
1658 newEnumMoniker
->tabSize
=tabSize
;
1659 newEnumMoniker
->currentPos
=currentPos
;
1661 newEnumMoniker
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,tabSize
*sizeof(newEnumMoniker
->tabMoniker
[0]));
1663 if (newEnumMoniker
->tabMoniker
==NULL
) {
1664 HeapFree(GetProcessHeap(), 0, newEnumMoniker
);
1665 return E_OUTOFMEMORY
;
1669 for (i
=0;i
<tabSize
;i
++){
1671 newEnumMoniker
->tabMoniker
[i
]=tabMoniker
[i
];
1672 IMoniker_AddRef(tabMoniker
[i
]);
1675 for (i
= tabSize
; i
> 0; i
--){
1677 newEnumMoniker
->tabMoniker
[tabSize
-i
]=tabMoniker
[i
- 1];
1678 IMoniker_AddRef(tabMoniker
[i
- 1]);
1681 *ppmk
=&newEnumMoniker
->IEnumMoniker_iface
;
1686 /********************************************************************************/
1687 /* Virtual function table for the CompositeMonikerImpl class which includes */
1688 /* IPersist, IPersistStream and IMoniker functions. */
1690 static const IMonikerVtbl VT_CompositeMonikerImpl
=
1692 CompositeMonikerImpl_QueryInterface
,
1693 CompositeMonikerImpl_AddRef
,
1694 CompositeMonikerImpl_Release
,
1695 CompositeMonikerImpl_GetClassID
,
1696 CompositeMonikerImpl_IsDirty
,
1697 CompositeMonikerImpl_Load
,
1698 CompositeMonikerImpl_Save
,
1699 CompositeMonikerImpl_GetSizeMax
,
1700 CompositeMonikerImpl_BindToObject
,
1701 CompositeMonikerImpl_BindToStorage
,
1702 CompositeMonikerImpl_Reduce
,
1703 CompositeMonikerImpl_ComposeWith
,
1704 CompositeMonikerImpl_Enum
,
1705 CompositeMonikerImpl_IsEqual
,
1706 CompositeMonikerImpl_Hash
,
1707 CompositeMonikerImpl_IsRunning
,
1708 CompositeMonikerImpl_GetTimeOfLastChange
,
1709 CompositeMonikerImpl_Inverse
,
1710 CompositeMonikerImpl_CommonPrefixWith
,
1711 CompositeMonikerImpl_RelativePathTo
,
1712 CompositeMonikerImpl_GetDisplayName
,
1713 CompositeMonikerImpl_ParseDisplayName
,
1714 CompositeMonikerImpl_IsSystemMoniker
1717 /********************************************************************************/
1718 /* Virtual function table for the IROTData class. */
1719 static const IROTDataVtbl VT_ROTDataImpl
=
1721 CompositeMonikerROTDataImpl_QueryInterface
,
1722 CompositeMonikerROTDataImpl_AddRef
,
1723 CompositeMonikerROTDataImpl_Release
,
1724 CompositeMonikerROTDataImpl_GetComparisonData
1727 static const IMarshalVtbl VT_MarshalImpl
=
1729 CompositeMonikerMarshalImpl_QueryInterface
,
1730 CompositeMonikerMarshalImpl_AddRef
,
1731 CompositeMonikerMarshalImpl_Release
,
1732 CompositeMonikerMarshalImpl_GetUnmarshalClass
,
1733 CompositeMonikerMarshalImpl_GetMarshalSizeMax
,
1734 CompositeMonikerMarshalImpl_MarshalInterface
,
1735 CompositeMonikerMarshalImpl_UnmarshalInterface
,
1736 CompositeMonikerMarshalImpl_ReleaseMarshalData
,
1737 CompositeMonikerMarshalImpl_DisconnectObject
1740 /******************************************************************************
1741 * Composite-Moniker_Construct (local function)
1742 *******************************************************************************/
1744 CompositeMonikerImpl_Construct(IMoniker
**ppMoniker
, IMoniker
*pmkFirst
, IMoniker
*pmkRest
)
1747 IEnumMoniker
*enumMoniker
;
1750 CompositeMonikerImpl
*This
;
1752 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1755 return E_OUTOFMEMORY
;
1757 TRACE("(%p,%p,%p)\n",This
,pmkFirst
,pmkRest
);
1759 /* Initialize the virtual function table. */
1760 This
->IMoniker_iface
.lpVtbl
= &VT_CompositeMonikerImpl
;
1761 This
->IROTData_iface
.lpVtbl
= &VT_ROTDataImpl
;
1762 This
->IMarshal_iface
.lpVtbl
= &VT_MarshalImpl
;
1765 This
->tabSize
=BLOCK_TAB_SIZE
;
1766 This
->tabLastIndex
=0;
1768 This
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,This
->tabSize
*sizeof(This
->tabMoniker
[0]));
1769 if (This
->tabMoniker
==NULL
) {
1770 HeapFree(GetProcessHeap(), 0, This
);
1771 return E_OUTOFMEMORY
;
1774 if (!pmkFirst
&& !pmkRest
)
1776 *ppMoniker
= &This
->IMoniker_iface
;
1780 IMoniker_IsSystemMoniker(pmkFirst
,&mkSys
);
1782 /* put the first moniker contents in the beginning of the table */
1783 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
1785 This
->tabMoniker
[(This
->tabLastIndex
)++]=pmkFirst
;
1786 IMoniker_AddRef(pmkFirst
);
1790 IMoniker_Enum(pmkFirst
,TRUE
,&enumMoniker
);
1792 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
1795 if (++This
->tabLastIndex
==This
->tabSize
){
1796 LPVOID tab_moniker
= This
->tabMoniker
;
1798 This
->tabSize
+=BLOCK_TAB_SIZE
;
1799 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1801 if (This
->tabMoniker
==NULL
){
1802 HeapFree(GetProcessHeap(), 0, tab_moniker
);
1803 HeapFree(GetProcessHeap(), 0, This
);
1804 return E_OUTOFMEMORY
;
1809 IEnumMoniker_Release(enumMoniker
);
1812 /* put the rest moniker contents after the first one and make simplification if needed */
1814 IMoniker_IsSystemMoniker(pmkRest
,&mkSys
);
1816 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
1818 /* add a simple moniker to the moniker table */
1820 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],pmkRest
,TRUE
,&tempMk
);
1822 if (res
==MK_E_NEEDGENERIC
){
1824 /* there's no simplification in this case */
1825 This
->tabMoniker
[This
->tabLastIndex
]=pmkRest
;
1827 This
->tabLastIndex
++;
1829 IMoniker_AddRef(pmkRest
);
1831 else if (tempMk
==NULL
){
1833 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
1834 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1836 This
->tabLastIndex
--;
1838 else if (SUCCEEDED(res
)){
1840 /* the non-generic composition was successful so we can make a simplification in this case */
1841 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1843 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
1847 /* resize tabMoniker if needed */
1848 if (This
->tabLastIndex
==This
->tabSize
){
1849 LPVOID tab_moniker
= This
->tabMoniker
;
1851 This
->tabSize
+=BLOCK_TAB_SIZE
;
1853 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1855 if (This
->tabMoniker
==NULL
){
1856 HeapFree(GetProcessHeap(), 0, tab_moniker
);
1857 HeapFree(GetProcessHeap(), 0, This
);
1858 return E_OUTOFMEMORY
;
1864 /* add a composite moniker to the moniker table (do the same thing
1865 * for each moniker within the composite moniker as a simple moniker
1866 * (see above for how to add a simple moniker case) )
1868 IMoniker_Enum(pmkRest
,TRUE
,&enumMoniker
);
1870 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
1872 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],This
->tabMoniker
[This
->tabLastIndex
],TRUE
,&tempMk
);
1874 if (res
==MK_E_NEEDGENERIC
){
1876 This
->tabLastIndex
++;
1878 else if (tempMk
==NULL
){
1880 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1881 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
]);
1882 This
->tabLastIndex
--;
1886 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1888 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
1891 if (This
->tabLastIndex
==This
->tabSize
){
1892 LPVOID tab_moniker
= This
->tabMoniker
;
1894 This
->tabSize
+=BLOCK_TAB_SIZE
;
1896 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(This
->tabMoniker
[0]));
1898 if (This
->tabMoniker
==NULL
){
1899 HeapFree(GetProcessHeap(), 0, tab_moniker
);
1900 HeapFree(GetProcessHeap(), 0, This
);
1901 return E_OUTOFMEMORY
;
1906 IEnumMoniker_Release(enumMoniker
);
1909 /* only one moniker, then just return it */
1910 if (This
->tabLastIndex
== 1)
1912 *ppMoniker
= This
->tabMoniker
[0];
1913 IMoniker_AddRef(*ppMoniker
);
1914 IMoniker_Release(&This
->IMoniker_iface
);
1917 *ppMoniker
= &This
->IMoniker_iface
;
1922 /******************************************************************************
1923 * CreateGenericComposite [OLE32.@]
1924 ******************************************************************************/
1926 CreateGenericComposite(IMoniker
*pmkFirst
, IMoniker
*pmkRest
, IMoniker
**ppmkComposite
)
1928 IMoniker
* moniker
= 0;
1931 TRACE("(%p,%p,%p)\n",pmkFirst
,pmkRest
,ppmkComposite
);
1933 if (ppmkComposite
==NULL
)
1938 if (pmkFirst
==NULL
&& pmkRest
!=NULL
){
1940 *ppmkComposite
=pmkRest
;
1943 else if (pmkFirst
!=NULL
&& pmkRest
==NULL
){
1944 *ppmkComposite
=pmkFirst
;
1947 else if (pmkFirst
==NULL
&& pmkRest
==NULL
)
1950 hr
= CompositeMonikerImpl_Construct(&moniker
,pmkFirst
,pmkRest
);
1955 hr
= IMoniker_QueryInterface(moniker
,&IID_IMoniker
,(void**)ppmkComposite
);
1956 IMoniker_Release(moniker
);
1961 /******************************************************************************
1962 * MonikerCommonPrefixWith [OLE32.@]
1963 ******************************************************************************/
1965 MonikerCommonPrefixWith(IMoniker
* pmkThis
,IMoniker
* pmkOther
,IMoniker
** ppmkCommon
)
1967 FIXME("(),stub!\n");
1971 static HRESULT WINAPI
CompositeMonikerCF_QueryInterface(IClassFactory
*iface
, REFIID riid
, void **ppv
)
1974 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IClassFactory
))
1977 IClassFactory_AddRef(iface
);
1980 return E_NOINTERFACE
;
1983 static ULONG WINAPI
CompositeMonikerCF_AddRef(LPCLASSFACTORY iface
)
1985 return 2; /* non-heap based object */
1988 static ULONG WINAPI
CompositeMonikerCF_Release(LPCLASSFACTORY iface
)
1990 return 1; /* non-heap based object */
1993 static HRESULT WINAPI
CompositeMonikerCF_CreateInstance(LPCLASSFACTORY iface
,
1994 LPUNKNOWN pUnk
, REFIID riid
, LPVOID
*ppv
)
1999 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
2004 return CLASS_E_NOAGGREGATION
;
2006 hr
= CompositeMonikerImpl_Construct(&pMoniker
, NULL
, NULL
);
2010 hr
= IMoniker_QueryInterface(pMoniker
, riid
, ppv
);
2011 IMoniker_Release(pMoniker
);
2017 static HRESULT WINAPI
CompositeMonikerCF_LockServer(LPCLASSFACTORY iface
, BOOL fLock
)
2019 FIXME("(%d), stub!\n",fLock
);
2023 static const IClassFactoryVtbl CompositeMonikerCFVtbl
=
2025 CompositeMonikerCF_QueryInterface
,
2026 CompositeMonikerCF_AddRef
,
2027 CompositeMonikerCF_Release
,
2028 CompositeMonikerCF_CreateInstance
,
2029 CompositeMonikerCF_LockServer
2031 static const IClassFactoryVtbl
*CompositeMonikerCF
= &CompositeMonikerCFVtbl
;
2033 HRESULT
CompositeMonikerCF_Create(REFIID riid
, LPVOID
*ppv
)
2035 return IClassFactory_QueryInterface((IClassFactory
*)&CompositeMonikerCF
, riid
, ppv
);