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"
35 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
37 #define BLOCK_TAB_SIZE 5 /* represent the first size table and its increment block size */
39 /* CompositeMoniker data structure */
40 typedef struct CompositeMonikerImpl
{
41 IMoniker IMoniker_iface
;
42 IROTData IROTData_iface
;
43 IMarshal IMarshal_iface
;
45 IMoniker
** tabMoniker
; /* dynamic table containing all components (monikers) of this composite moniker */
46 ULONG tabSize
; /* size of tabMoniker */
47 ULONG tabLastIndex
; /* first free index in tabMoniker */
48 } CompositeMonikerImpl
;
50 static inline CompositeMonikerImpl
*impl_from_IMoniker(IMoniker
*iface
)
52 return CONTAINING_RECORD(iface
, CompositeMonikerImpl
, IMoniker_iface
);
55 static inline CompositeMonikerImpl
*impl_from_IROTData(IROTData
*iface
)
57 return CONTAINING_RECORD(iface
, CompositeMonikerImpl
, IROTData_iface
);
60 static inline CompositeMonikerImpl
*impl_from_IMarshal(IMarshal
*iface
)
62 return CONTAINING_RECORD(iface
, CompositeMonikerImpl
, IMarshal_iface
);
65 /* EnumMoniker data structure */
66 typedef struct EnumMonikerImpl
{
67 IEnumMoniker IEnumMoniker_iface
;
69 IMoniker
** tabMoniker
; /* dynamic table containing the enumerated monikers */
70 ULONG tabSize
; /* size of tabMoniker */
71 ULONG currentPos
; /* index pointer on the current moniker */
74 static inline EnumMonikerImpl
*impl_from_IEnumMoniker(IEnumMoniker
*iface
)
76 return CONTAINING_RECORD(iface
, EnumMonikerImpl
, IEnumMoniker_iface
);
79 static HRESULT
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,ULONG tabSize
,ULONG currentPos
,BOOL leftToRight
,IEnumMoniker
** ppmk
);
81 /*******************************************************************************
82 * CompositeMoniker_QueryInterface
83 *******************************************************************************/
85 CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
87 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
89 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppvObject
);
91 /* Perform a sanity check on the parameters.*/
95 /* Initialize the return parameter */
98 /* Compare the riid with the interface IDs implemented by this object.*/
99 if (IsEqualIID(&IID_IUnknown
, riid
) ||
100 IsEqualIID(&IID_IPersist
, riid
) ||
101 IsEqualIID(&IID_IPersistStream
, riid
) ||
102 IsEqualIID(&IID_IMoniker
, riid
)
105 else if (IsEqualIID(&IID_IROTData
, riid
))
106 *ppvObject
= &This
->IROTData_iface
;
107 else if (IsEqualIID(&IID_IMarshal
, riid
))
108 *ppvObject
= &This
->IMarshal_iface
;
110 /* Check that we obtained an interface.*/
112 return E_NOINTERFACE
;
114 /* Query Interface always increases the reference count by one when it is successful */
115 IMoniker_AddRef(iface
);
120 /******************************************************************************
121 * CompositeMoniker_AddRef
122 ******************************************************************************/
124 CompositeMonikerImpl_AddRef(IMoniker
* iface
)
126 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
128 TRACE("(%p)\n",This
);
130 return InterlockedIncrement(&This
->ref
);
133 static void CompositeMonikerImpl_ReleaseMonikersInTable(CompositeMonikerImpl
*This
)
137 for (i
= 0; i
< This
->tabLastIndex
; i
++)
138 IMoniker_Release(This
->tabMoniker
[i
]);
140 This
->tabLastIndex
= 0;
143 /******************************************************************************
144 * CompositeMoniker_Release
145 ******************************************************************************/
147 CompositeMonikerImpl_Release(IMoniker
* iface
)
149 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
152 TRACE("(%p)\n",This
);
154 ref
= InterlockedDecrement(&This
->ref
);
156 /* destroy the object if there are no more references to it */
159 /* release all the components before destroying this object */
160 CompositeMonikerImpl_ReleaseMonikersInTable(This
);
162 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
163 HeapFree(GetProcessHeap(),0,This
);
168 /******************************************************************************
169 * CompositeMoniker_GetClassID
170 ******************************************************************************/
171 static HRESULT WINAPI
172 CompositeMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
174 TRACE("(%p,%p)\n",iface
,pClassID
);
179 *pClassID
= CLSID_CompositeMoniker
;
184 /******************************************************************************
185 * CompositeMoniker_IsDirty
186 ******************************************************************************/
187 static HRESULT WINAPI
188 CompositeMonikerImpl_IsDirty(IMoniker
* iface
)
190 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
191 method in the OLE-provided moniker interfaces always return S_FALSE because
192 their internal state never changes. */
194 TRACE("(%p)\n",iface
);
199 /******************************************************************************
200 * CompositeMoniker_Load
201 ******************************************************************************/
202 static HRESULT WINAPI
203 CompositeMonikerImpl_Load(IMoniker
* iface
,IStream
* pStm
)
205 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
210 TRACE("(%p,%p)\n",iface
,pStm
);
212 /* this function call OleLoadFromStream function for each moniker within this object */
214 res
=IStream_Read(pStm
,&moniker_count
,sizeof(DWORD
),NULL
);
217 ERR("couldn't reading moniker count from stream\n");
221 CompositeMonikerImpl_ReleaseMonikersInTable(This
);
223 for (i
= 0; i
< moniker_count
; i
++)
225 res
=OleLoadFromStream(pStm
,&IID_IMoniker
,(void**)&This
->tabMoniker
[This
->tabLastIndex
]);
228 ERR("couldn't load moniker from stream, res = 0x%08x\n", res
);
232 /* resize the table if needed */
233 if (++This
->tabLastIndex
==This
->tabSize
){
235 This
->tabSize
+=BLOCK_TAB_SIZE
;
236 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(This
->tabMoniker
[0]));
238 if (This
->tabMoniker
==NULL
)
239 return E_OUTOFMEMORY
;
246 /******************************************************************************
247 * CompositeMoniker_Save
248 ******************************************************************************/
249 static HRESULT WINAPI
250 CompositeMonikerImpl_Save(IMoniker
* iface
,IStream
* pStm
,BOOL fClearDirty
)
252 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
254 IEnumMoniker
*enumMk
;
256 DWORD moniker_count
= This
->tabLastIndex
;
258 TRACE("(%p,%p,%d)\n",iface
,pStm
,fClearDirty
);
260 /* This function calls OleSaveToStream function for each moniker within
262 * When I tested this function in windows, I usually found this constant
263 * at the beginning of the stream. I don't known why (there's no
264 * indication in the specification) !
266 res
=IStream_Write(pStm
,&moniker_count
,sizeof(moniker_count
),NULL
);
267 if (FAILED(res
)) return res
;
269 IMoniker_Enum(iface
,TRUE
,&enumMk
);
271 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
273 res
=OleSaveToStream((IPersistStream
*)pmk
,pStm
);
275 IMoniker_Release(pmk
);
279 IEnumMoniker_Release(enumMk
);
284 IEnumMoniker_Release(enumMk
);
289 /******************************************************************************
290 * CompositeMoniker_GetSizeMax
291 ******************************************************************************/
292 static HRESULT WINAPI
293 CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
,ULARGE_INTEGER
* pcbSize
)
295 IEnumMoniker
*enumMk
;
297 ULARGE_INTEGER ptmpSize
;
299 /* The sizeMax of this object is calculated by calling GetSizeMax on
300 * each moniker within this object then summing all returned values
303 TRACE("(%p,%p)\n",iface
,pcbSize
);
308 pcbSize
->QuadPart
= sizeof(DWORD
);
310 IMoniker_Enum(iface
,TRUE
,&enumMk
);
312 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
314 IMoniker_GetSizeMax(pmk
,&ptmpSize
);
316 IMoniker_Release(pmk
);
318 pcbSize
->QuadPart
+= ptmpSize
.QuadPart
+ sizeof(CLSID
);
321 IEnumMoniker_Release(enumMk
);
326 /******************************************************************************
327 * CompositeMoniker_BindToObject
328 ******************************************************************************/
329 static HRESULT WINAPI
330 CompositeMonikerImpl_BindToObject(IMoniker
* iface
, IBindCtx
* pbc
,
331 IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
)
334 IRunningObjectTable
*prot
;
335 IMoniker
*tempMk
,*antiMk
,*rightMostMk
;
336 IEnumMoniker
*enumMoniker
;
338 TRACE("(%p,%p,%p,%s,%p)\n",iface
,pbc
,pmkToLeft
,debugstr_guid(riid
),ppvResult
);
344 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
345 /* object for the requested interface pointer. */
348 res
=IBindCtx_GetRunningObjectTable(pbc
,&prot
);
352 /* if the requested class was loaded before ! we don't need to reload it */
353 res
= IRunningObjectTable_GetObject(prot
,iface
,(IUnknown
**)ppvResult
);
360 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
361 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
363 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
364 IEnumMoniker_Next(enumMoniker
,1,&rightMostMk
,NULL
);
365 IEnumMoniker_Release(enumMoniker
);
367 res
=CreateAntiMoniker(&antiMk
);
368 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
369 IMoniker_Release(antiMk
);
371 res
=IMoniker_BindToObject(rightMostMk
,pbc
,tempMk
,riid
,ppvResult
);
373 IMoniker_Release(tempMk
);
374 IMoniker_Release(rightMostMk
);
380 /******************************************************************************
381 * CompositeMoniker_BindToStorage
382 ******************************************************************************/
383 static HRESULT WINAPI
384 CompositeMonikerImpl_BindToStorage(IMoniker
* iface
, IBindCtx
* pbc
,
385 IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
)
388 IMoniker
*tempMk
,*antiMk
,*rightMostMk
,*leftMk
;
389 IEnumMoniker
*enumMoniker
;
391 TRACE("(%p,%p,%p,%s,%p)\n",iface
,pbc
,pmkToLeft
,debugstr_guid(riid
),ppvResult
);
395 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
396 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
400 res
= IMoniker_ComposeWith(pmkToLeft
, iface
, FALSE
, &leftMk
);
401 if (FAILED(res
)) return res
;
406 IMoniker_Enum(iface
, FALSE
, &enumMoniker
);
407 IEnumMoniker_Next(enumMoniker
, 1, &rightMostMk
, NULL
);
408 IEnumMoniker_Release(enumMoniker
);
410 res
= CreateAntiMoniker(&antiMk
);
411 if (FAILED(res
)) return res
;
412 res
= IMoniker_ComposeWith(leftMk
, antiMk
, 0, &tempMk
);
413 if (FAILED(res
)) return res
;
414 IMoniker_Release(antiMk
);
416 res
= IMoniker_BindToStorage(rightMostMk
, pbc
, tempMk
, riid
, ppvResult
);
418 IMoniker_Release(tempMk
);
420 IMoniker_Release(rightMostMk
);
423 IMoniker_Release(leftMk
);
428 /******************************************************************************
429 * CompositeMoniker_Reduce
430 ******************************************************************************/
431 static HRESULT WINAPI
432 CompositeMonikerImpl_Reduce(IMoniker
* iface
, IBindCtx
* pbc
, DWORD dwReduceHowFar
,
433 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 res
= IMoniker_Reduce(rightMostMk
,pbc
,dwReduceHowFar
,&tempMk
, ppmkReduced
);
457 IMoniker_Release(tempMk
);
458 IMoniker_Release(rightMostMk
);
462 else if (*ppmkToLeft
==NULL
)
464 return IMoniker_Reduce(iface
,pbc
,dwReduceHowFar
,NULL
,ppmkReduced
);
468 /* separate the composite moniker in to left and right moniker */
469 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
470 IEnumMoniker_Next(enumMoniker
,1,&rightMostMk
,NULL
);
471 IEnumMoniker_Release(enumMoniker
);
473 CreateAntiMoniker(&antiMk
);
474 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
475 IMoniker_Release(antiMk
);
477 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
478 /* of the reduced components */
479 if (IMoniker_Reduce(rightMostMk
,pbc
,dwReduceHowFar
,NULL
,&rightMostReducedMk
) &&
480 IMoniker_Reduce(rightMostMk
,pbc
,dwReduceHowFar
,&tempMk
,&leftReducedComposedMk
) ){
481 IMoniker_Release(tempMk
);
482 IMoniker_Release(rightMostMk
);
484 return CreateGenericComposite(leftReducedComposedMk
,rightMostReducedMk
,ppmkReduced
);
487 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
488 IMoniker_Release(tempMk
);
489 IMoniker_Release(rightMostMk
);
491 IMoniker_AddRef(iface
);
495 return MK_S_REDUCED_TO_SELF
;
500 /******************************************************************************
501 * CompositeMoniker_ComposeWith
502 ******************************************************************************/
503 static HRESULT WINAPI
504 CompositeMonikerImpl_ComposeWith(IMoniker
* iface
, IMoniker
* pmkRight
,
505 BOOL fOnlyIfNotGeneric
, IMoniker
** ppmkComposite
)
507 TRACE("(%p,%p,%d,%p)\n",iface
,pmkRight
,fOnlyIfNotGeneric
,ppmkComposite
);
509 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
514 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
515 /* otherwise, the method returns the result of combining the two monikers by calling the */
516 /* CreateGenericComposite function */
518 if (fOnlyIfNotGeneric
)
519 return MK_E_NEEDGENERIC
;
521 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
524 /******************************************************************************
525 * CompositeMoniker_Enum
526 ******************************************************************************/
527 static HRESULT WINAPI
528 CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
530 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
532 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
534 if (ppenumMoniker
== NULL
)
537 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabLastIndex
,0,fForward
,ppenumMoniker
);
540 /******************************************************************************
541 * CompositeMoniker_IsEqual
542 ******************************************************************************/
543 static HRESULT WINAPI
544 CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
)
546 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
547 IMoniker
*tempMk1
,*tempMk2
;
548 HRESULT res1
,res2
,res
;
551 TRACE("(%p,%p)\n",iface
,pmkOtherMoniker
);
553 if (pmkOtherMoniker
==NULL
)
556 /* This method returns S_OK if the components of both monikers are equal when compared in the */
557 /* left-to-right order.*/
558 IMoniker_Enum(pmkOtherMoniker
,TRUE
,&enumMoniker1
);
560 if (enumMoniker1
==NULL
)
563 IMoniker_Enum(iface
,TRUE
,&enumMoniker2
);
567 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
568 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
570 if((res1
==S_OK
)&&(res2
==S_OK
)){
571 done
= (res
= IMoniker_IsEqual(tempMk1
,tempMk2
)) == S_FALSE
;
575 res
= (res1
==S_FALSE
) && (res2
==S_FALSE
);
580 IMoniker_Release(tempMk1
);
583 IMoniker_Release(tempMk2
);
586 IEnumMoniker_Release(enumMoniker1
);
587 IEnumMoniker_Release(enumMoniker2
);
591 /******************************************************************************
592 * CompositeMoniker_Hash
593 ******************************************************************************/
594 static HRESULT WINAPI
595 CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
597 IEnumMoniker
*enumMoniker
;
602 TRACE("(%p,%p)\n",iface
,pdwHash
);
607 res
= IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
613 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
614 res
= IMoniker_Hash(tempMk
, &tempHash
);
617 *pdwHash
= *pdwHash
^ tempHash
;
619 IMoniker_Release(tempMk
);
622 IEnumMoniker_Release(enumMoniker
);
627 /******************************************************************************
628 * CompositeMoniker_IsRunning
629 ******************************************************************************/
630 static HRESULT WINAPI
631 CompositeMonikerImpl_IsRunning(IMoniker
* iface
, IBindCtx
* pbc
,
632 IMoniker
* pmkToLeft
, IMoniker
* pmkNewlyRunning
)
634 IRunningObjectTable
* rot
;
636 IMoniker
*tempMk
,*antiMk
,*rightMostMk
;
637 IEnumMoniker
*enumMoniker
;
639 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
641 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
642 if (pmkToLeft
!=NULL
){
644 CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
646 res
= IMoniker_IsRunning(tempMk
,pbc
,NULL
,pmkNewlyRunning
);
648 IMoniker_Release(tempMk
);
653 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
654 /* to this moniker */
656 if (pmkNewlyRunning
!=NULL
)
658 if (IMoniker_IsEqual(iface
,pmkNewlyRunning
)==S_OK
)
669 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
670 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
671 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
672 /* the composite as the pmkToLeft parameter for that call. */
674 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
679 res
= IRunningObjectTable_IsRunning(rot
,iface
);
680 IRunningObjectTable_Release(rot
);
687 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
688 IEnumMoniker_Next(enumMoniker
,1,&rightMostMk
,NULL
);
689 IEnumMoniker_Release(enumMoniker
);
691 res
=CreateAntiMoniker(&antiMk
);
692 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
693 IMoniker_Release(antiMk
);
695 res
=IMoniker_IsRunning(rightMostMk
,pbc
,tempMk
,pmkNewlyRunning
);
697 IMoniker_Release(tempMk
);
698 IMoniker_Release(rightMostMk
);
705 /******************************************************************************
706 * CompositeMoniker_GetTimeOfLastChange
707 ******************************************************************************/
708 static HRESULT WINAPI
709 CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
, IBindCtx
* pbc
,
710 IMoniker
* pmkToLeft
, FILETIME
* pCompositeTime
)
713 IMoniker
*tempMk
,*antiMk
,*rightMostMk
,*leftMk
;
714 IEnumMoniker
*enumMoniker
;
716 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pCompositeTime
);
718 if (pCompositeTime
==NULL
)
721 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
722 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
723 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
724 /* of the composite as the pmkToLeft parameter for that call. */
727 IRunningObjectTable
* rot
;
729 res
= IMoniker_ComposeWith(pmkToLeft
, iface
, FALSE
, &leftMk
);
733 res
= IBindCtx_GetRunningObjectTable(pbc
,&rot
);
736 IMoniker_Release(leftMk
);
740 if (IRunningObjectTable_GetTimeOfLastChange(rot
,leftMk
,pCompositeTime
)==S_OK
)
742 IMoniker_Release(leftMk
);
749 IMoniker_Enum(iface
, FALSE
, &enumMoniker
);
750 IEnumMoniker_Next(enumMoniker
, 1, &rightMostMk
, NULL
);
751 IEnumMoniker_Release(enumMoniker
);
753 res
= CreateAntiMoniker(&antiMk
);
754 res
= IMoniker_ComposeWith(leftMk
, antiMk
, 0, &tempMk
);
755 IMoniker_Release(antiMk
);
757 res
= IMoniker_GetTimeOfLastChange(rightMostMk
, pbc
, tempMk
, pCompositeTime
);
759 IMoniker_Release(tempMk
);
760 IMoniker_Release(rightMostMk
);
763 IMoniker_Release(leftMk
);
768 /******************************************************************************
769 * CompositeMoniker_Inverse
770 ******************************************************************************/
771 static HRESULT WINAPI
772 CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
775 IMoniker
*tempMk
,*antiMk
,*rightMostMk
,*tempInvMk
,*rightMostInvMk
;
776 IEnumMoniker
*enumMoniker
;
778 TRACE("(%p,%p)\n",iface
,ppmk
);
783 /* This method returns a composite moniker that consists of the inverses of each of the components */
784 /* of the original composite, stored in reverse order */
788 res
=CreateAntiMoniker(&antiMk
);
792 res
=IMoniker_ComposeWith(iface
,antiMk
,FALSE
,&tempMk
);
793 IMoniker_Release(antiMk
);
799 return IMoniker_Inverse(iface
,ppmk
);
803 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
804 IEnumMoniker_Next(enumMoniker
,1,&rightMostMk
,NULL
);
805 IEnumMoniker_Release(enumMoniker
);
807 IMoniker_Inverse(rightMostMk
,&rightMostInvMk
);
808 CompositeMonikerImpl_Inverse(tempMk
,&tempInvMk
);
810 res
=CreateGenericComposite(rightMostInvMk
,tempInvMk
,ppmk
);
812 IMoniker_Release(tempMk
);
813 IMoniker_Release(rightMostMk
);
814 IMoniker_Release(tempInvMk
);
815 IMoniker_Release(rightMostInvMk
);
821 /******************************************************************************
822 * CompositeMoniker_CommonPrefixWith
823 ******************************************************************************/
824 static HRESULT WINAPI
825 CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
, IMoniker
* pmkOther
,
826 IMoniker
** ppmkPrefix
)
830 IMoniker
*tempMk1
,*tempMk2
,*mostLeftMk1
,*mostLeftMk2
;
831 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
832 ULONG i
,nbCommonMk
=0;
834 /* If the other moniker is a composite, this method compares the components of each composite from left */
835 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
836 /* of the leftmost components were common to both monikers. */
838 if (ppmkPrefix
==NULL
)
844 return MK_E_NOPREFIX
;
846 IMoniker_IsSystemMoniker(pmkOther
,&mkSys
);
848 if(mkSys
==MKSYS_GENERICCOMPOSITE
){
850 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
851 IMoniker_Enum(pmkOther
,TRUE
,&enumMoniker2
);
855 res1
=IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
856 res2
=IEnumMoniker_Next(enumMoniker2
,1,&mostLeftMk2
,NULL
);
858 if ((res1
==S_FALSE
) && (res2
==S_FALSE
)){
860 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
862 IMoniker_AddRef(iface
);
865 else if ((res1
==S_OK
) && (res2
==S_OK
)){
867 if (IMoniker_IsEqual(mostLeftMk1
,mostLeftMk2
)==S_OK
)
875 else if (res1
==S_OK
){
877 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
878 /* ppmkPrefix to the other moniker. */
879 *ppmkPrefix
=pmkOther
;
883 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
884 /* to this moniker. */
890 IEnumMoniker_Release(enumMoniker1
);
891 IEnumMoniker_Release(enumMoniker2
);
893 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
895 return MK_E_NOPREFIX
;
897 IEnumMoniker_Reset(enumMoniker1
);
899 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
901 /* if we have more than one common moniker the result will be a composite moniker */
904 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
905 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
906 CreateGenericComposite(tempMk1
,tempMk2
,ppmkPrefix
);
907 IMoniker_Release(tempMk1
);
908 IMoniker_Release(tempMk2
);
910 /* compose all common monikers in a composite moniker */
911 for(i
=0;i
<nbCommonMk
;i
++){
913 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
915 CreateGenericComposite(*ppmkPrefix
,tempMk1
,&tempMk2
);
917 IMoniker_Release(*ppmkPrefix
);
919 IMoniker_Release(tempMk1
);
926 /* if we have only one common moniker the result will be a simple moniker which is the most-left one*/
933 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
936 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
938 IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
940 if (IMoniker_IsEqual(pmkOther
,mostLeftMk1
)==S_OK
){
942 *ppmkPrefix
=pmkOther
;
947 return MK_E_NOPREFIX
;
951 /***************************************************************************************************
952 * GetAfterCommonPrefix (local function)
953 * This function returns a moniker that consist of the remainder when the common prefix is removed
954 ***************************************************************************************************/
955 static VOID
GetAfterCommonPrefix(IMoniker
* pGenMk
,IMoniker
* commonMk
,IMoniker
** restMk
)
957 IMoniker
*tempMk
,*tempMk1
,*tempMk2
;
958 IEnumMoniker
*enumMoniker1
,*enumMoniker2
,*enumMoniker3
;
965 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
966 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
967 /* on the first difference. */
968 IMoniker_Enum(pGenMk
,TRUE
,&enumMoniker1
);
970 IMoniker_IsSystemMoniker(commonMk
,&mkSys
);
972 if (mkSys
==MKSYS_GENERICCOMPOSITE
){
974 IMoniker_Enum(commonMk
,TRUE
,&enumMoniker2
);
977 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
978 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
980 if ((res1
==S_FALSE
)||(res2
==S_FALSE
)){
986 IMoniker_Release(tempMk1
);
987 IMoniker_Release(tempMk2
);
991 IMoniker_Release(tempMk1
);
992 IMoniker_Release(tempMk2
);
996 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
997 IMoniker_Release(tempMk1
);
1000 /* count the number of elements in the enumerator after the common prefix */
1001 IEnumMoniker_Clone(enumMoniker1
,&enumMoniker3
);
1003 for(;IEnumMoniker_Next(enumMoniker3
,1,&tempMk
,NULL
)==S_OK
;nbRestMk
++)
1005 IMoniker_Release(tempMk
);
1010 /* create a generic composite moniker with monikers located after the common prefix */
1011 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1020 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1022 CreateGenericComposite(tempMk1
,tempMk2
,restMk
);
1024 IMoniker_Release(tempMk1
);
1026 IMoniker_Release(tempMk2
);
1028 while(IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
)==S_OK
){
1030 CreateGenericComposite(*restMk
,tempMk1
,&tempMk2
);
1032 IMoniker_Release(tempMk1
);
1034 IMoniker_Release(*restMk
);
1041 /******************************************************************************
1042 * CompositeMoniker_RelativePathTo
1043 ******************************************************************************/
1044 static HRESULT WINAPI
1045 CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmkOther
,
1046 IMoniker
** ppmkRelPath
)
1049 IMoniker
*restOtherMk
=0,*restThisMk
=0,*invRestThisMk
=0,*commonMk
=0;
1051 TRACE("(%p,%p,%p)\n",iface
,pmkOther
,ppmkRelPath
);
1053 if (ppmkRelPath
==NULL
)
1058 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1059 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1060 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1062 /* finds the common prefix of the two monikers */
1063 res
=IMoniker_CommonPrefixWith(iface
,pmkOther
,&commonMk
);
1065 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1066 if ((res
== MK_E_NOPREFIX
)||(res
==MK_S_US
)){
1068 *ppmkRelPath
=pmkOther
;
1069 IMoniker_AddRef(pmkOther
);
1073 GetAfterCommonPrefix(iface
,commonMk
,&restThisMk
);
1074 GetAfterCommonPrefix(pmkOther
,commonMk
,&restOtherMk
);
1076 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1077 /* moniker when the common prefix is removed */
1080 IMoniker_Inverse(restThisMk
,ppmkRelPath
);
1081 IMoniker_Release(restThisMk
);
1083 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1084 /* when the common prefix is removed */
1085 else if (res
==MK_S_ME
){
1087 *ppmkRelPath
=restOtherMk
;
1088 IMoniker_AddRef(restOtherMk
);
1090 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1091 /* moniker on the right of it. */
1092 else if (res
==S_OK
){
1094 IMoniker_Inverse(restThisMk
,&invRestThisMk
);
1095 IMoniker_Release(restThisMk
);
1096 CreateGenericComposite(invRestThisMk
,restOtherMk
,ppmkRelPath
);
1097 IMoniker_Release(invRestThisMk
);
1098 IMoniker_Release(restOtherMk
);
1103 /******************************************************************************
1104 * CompositeMoniker_GetDisplayName
1105 ******************************************************************************/
1106 static HRESULT WINAPI
1107 CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
1108 IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
)
1111 IEnumMoniker
*enumMoniker
;
1115 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
1117 if (ppszDisplayName
==NULL
)
1120 *ppszDisplayName
=CoTaskMemAlloc(sizeof(WCHAR
));
1122 if (*ppszDisplayName
==NULL
)
1123 return E_OUTOFMEMORY
;
1125 /* This method returns the concatenation of the display names returned by each component moniker of */
1128 **ppszDisplayName
=0;
1130 IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
1132 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
1134 IMoniker_GetDisplayName(tempMk
,pbc
,NULL
,&tempStr
);
1136 lengthStr
+=lstrlenW(tempStr
);
1138 *ppszDisplayName
=CoTaskMemRealloc(*ppszDisplayName
,lengthStr
* sizeof(WCHAR
));
1140 if (*ppszDisplayName
==NULL
)
1141 return E_OUTOFMEMORY
;
1143 lstrcatW(*ppszDisplayName
,tempStr
);
1145 CoTaskMemFree(tempStr
);
1146 IMoniker_Release(tempMk
);
1149 IEnumMoniker_Release(enumMoniker
);
1154 /******************************************************************************
1155 * CompositeMoniker_ParseDisplayName
1156 ******************************************************************************/
1157 static HRESULT WINAPI
1158 CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
1159 IMoniker
* pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
* pchEaten
,
1162 IEnumMoniker
*enumMoniker
;
1163 IMoniker
*tempMk
,*rightMostMk
,*antiMk
;
1164 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1165 /* passing everything else as the pmkToLeft parameter for that call. */
1167 /* get the most right moniker */
1168 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1169 IEnumMoniker_Next(enumMoniker
,1,&rightMostMk
,NULL
);
1170 IEnumMoniker_Release(enumMoniker
);
1172 /* get the left moniker */
1173 CreateAntiMoniker(&antiMk
);
1174 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1175 IMoniker_Release(antiMk
);
1177 return IMoniker_ParseDisplayName(rightMostMk
,pbc
,tempMk
,pszDisplayName
,pchEaten
,ppmkOut
);
1180 /******************************************************************************
1181 * CompositeMoniker_IsSystemMoniker
1182 ******************************************************************************/
1183 static HRESULT WINAPI
1184 CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
1186 TRACE("(%p,%p)\n",iface
,pwdMksys
);
1191 (*pwdMksys
)=MKSYS_GENERICCOMPOSITE
;
1196 /*******************************************************************************
1197 * CompositeMonikerIROTData_QueryInterface
1198 *******************************************************************************/
1199 static HRESULT WINAPI
1200 CompositeMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,
1203 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
1205 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppvObject
);
1207 return CompositeMonikerImpl_QueryInterface(&This
->IMoniker_iface
, riid
, ppvObject
);
1210 /***********************************************************************
1211 * CompositeMonikerIROTData_AddRef
1214 CompositeMonikerROTDataImpl_AddRef(IROTData
*iface
)
1216 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
1218 TRACE("(%p)\n",iface
);
1220 return IMoniker_AddRef(&This
->IMoniker_iface
);
1223 /***********************************************************************
1224 * CompositeMonikerIROTData_Release
1226 static ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
)
1228 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
1230 TRACE("(%p)\n",iface
);
1232 return IMoniker_Release(&This
->IMoniker_iface
);
1235 /******************************************************************************
1236 * CompositeMonikerIROTData_GetComparisonData
1237 ******************************************************************************/
1238 static HRESULT WINAPI
1239 CompositeMonikerROTDataImpl_GetComparisonData(IROTData
* iface
,
1240 BYTE
* pbData
, ULONG cbMax
, ULONG
* pcbData
)
1242 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
1243 IEnumMoniker
*pEnumMk
;
1247 TRACE("(%p, %u, %p)\n", pbData
, cbMax
, pcbData
);
1249 *pcbData
= sizeof(CLSID
);
1251 hr
= IMoniker_Enum(&This
->IMoniker_iface
, TRUE
, &pEnumMk
);
1252 if (FAILED(hr
)) return hr
;
1254 while(IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1257 hr
= IMoniker_QueryInterface(pmk
, &IID_IROTData
, (void **)&pROTData
);
1259 ERR("moniker doesn't support IROTData interface\n");
1264 hr
= IROTData_GetComparisonData(pROTData
, NULL
, 0, &cbData
);
1265 IROTData_Release(pROTData
);
1266 if (SUCCEEDED(hr
) || (hr
== E_OUTOFMEMORY
))
1272 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr
);
1275 IMoniker_Release(pmk
);
1279 IEnumMoniker_Release(pEnumMk
);
1283 if (cbMax
< *pcbData
)
1284 return E_OUTOFMEMORY
;
1286 IEnumMoniker_Reset(pEnumMk
);
1288 memcpy(pbData
, &CLSID_CompositeMoniker
, sizeof(CLSID
));
1289 pbData
+= sizeof(CLSID
);
1290 cbMax
-= sizeof(CLSID
);
1292 while (IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1295 hr
= IMoniker_QueryInterface(pmk
, &IID_IROTData
, (void **)&pROTData
);
1297 ERR("moniker doesn't support IROTData interface\n");
1302 hr
= IROTData_GetComparisonData(pROTData
, pbData
, cbMax
, &cbData
);
1303 IROTData_Release(pROTData
);
1310 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr
);
1313 IMoniker_Release(pmk
);
1317 IEnumMoniker_Release(pEnumMk
);
1322 IEnumMoniker_Release(pEnumMk
);
1327 static HRESULT WINAPI
CompositeMonikerMarshalImpl_QueryInterface(IMarshal
*iface
, REFIID riid
, LPVOID
*ppv
)
1329 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1331 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppv
);
1333 return CompositeMonikerImpl_QueryInterface(&This
->IMoniker_iface
, riid
, ppv
);
1336 static ULONG WINAPI
CompositeMonikerMarshalImpl_AddRef(IMarshal
*iface
)
1338 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1340 TRACE("(%p)\n",iface
);
1342 return CompositeMonikerImpl_AddRef(&This
->IMoniker_iface
);
1345 static ULONG WINAPI
CompositeMonikerMarshalImpl_Release(IMarshal
*iface
)
1347 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1349 TRACE("(%p)\n",iface
);
1351 return CompositeMonikerImpl_Release(&This
->IMoniker_iface
);
1354 static HRESULT WINAPI
CompositeMonikerMarshalImpl_GetUnmarshalClass(
1355 IMarshal
*iface
, REFIID riid
, void *pv
, DWORD dwDestContext
,
1356 void* pvDestContext
, DWORD mshlflags
, CLSID
* pCid
)
1358 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1360 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid
), pv
,
1361 dwDestContext
, pvDestContext
, mshlflags
, pCid
);
1363 return IMoniker_GetClassID(&This
->IMoniker_iface
, pCid
);
1366 static HRESULT WINAPI
CompositeMonikerMarshalImpl_GetMarshalSizeMax(
1367 IMarshal
*iface
, REFIID riid
, void *pv
, DWORD dwDestContext
,
1368 void* pvDestContext
, DWORD mshlflags
, DWORD
* pSize
)
1370 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1371 IEnumMoniker
*pEnumMk
;
1374 ULARGE_INTEGER size
;
1376 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid
), pv
,
1377 dwDestContext
, pvDestContext
, mshlflags
, pSize
);
1379 *pSize
= 0x10; /* to match native */
1381 hr
= IMoniker_Enum(&This
->IMoniker_iface
, TRUE
, &pEnumMk
);
1382 if (FAILED(hr
)) return hr
;
1384 hr
= IMoniker_GetSizeMax(&This
->IMoniker_iface
, &size
);
1386 while (IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1390 hr
= CoGetMarshalSizeMax(&size
, &IID_IMoniker
, (IUnknown
*)pmk
, dwDestContext
, pvDestContext
, mshlflags
);
1394 IMoniker_Release(pmk
);
1398 IEnumMoniker_Release(pEnumMk
);
1403 IEnumMoniker_Release(pEnumMk
);
1408 static HRESULT WINAPI
CompositeMonikerMarshalImpl_MarshalInterface(IMarshal
*iface
, IStream
*pStm
,
1409 REFIID riid
, void* pv
, DWORD dwDestContext
,
1410 void* pvDestContext
, DWORD mshlflags
)
1412 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1413 IEnumMoniker
*pEnumMk
;
1418 TRACE("(%p, %s, %p, %x, %p, %x)\n", pStm
, debugstr_guid(riid
), pv
,
1419 dwDestContext
, pvDestContext
, mshlflags
);
1421 hr
= IMoniker_Enum(&This
->IMoniker_iface
, TRUE
, &pEnumMk
);
1422 if (FAILED(hr
)) return hr
;
1424 while (IEnumMoniker_Next(pEnumMk
, 1, &pmk
, NULL
) == S_OK
)
1426 hr
= CoMarshalInterface(pStm
, &IID_IMoniker
, (IUnknown
*)pmk
, dwDestContext
, pvDestContext
, mshlflags
);
1428 IMoniker_Release(pmk
);
1432 IEnumMoniker_Release(pEnumMk
);
1439 FIXME("moniker count of %d not supported\n", i
);
1441 IEnumMoniker_Release(pEnumMk
);
1446 static HRESULT WINAPI
CompositeMonikerMarshalImpl_UnmarshalInterface(IMarshal
*iface
, IStream
*pStm
,
1447 REFIID riid
, void **ppv
)
1449 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1452 TRACE("(%p, %s, %p)\n", pStm
, debugstr_guid(riid
), ppv
);
1454 CompositeMonikerImpl_ReleaseMonikersInTable(This
);
1456 /* resize the table if needed */
1457 if (This
->tabLastIndex
+ 2 > This
->tabSize
)
1459 This
->tabSize
+= max(BLOCK_TAB_SIZE
, 2);
1460 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(This
->tabMoniker
[0]));
1462 if (This
->tabMoniker
==NULL
)
1463 return E_OUTOFMEMORY
;
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
++;
1473 hr
= CoUnmarshalInterface(pStm
, &IID_IMoniker
, (void**)&This
->tabMoniker
[This
->tabLastIndex
]);
1476 ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr
);
1479 This
->tabLastIndex
++;
1481 return IMoniker_QueryInterface(&This
->IMoniker_iface
, riid
, ppv
);
1484 static HRESULT WINAPI
CompositeMonikerMarshalImpl_ReleaseMarshalData(IMarshal
*iface
, IStream
*pStm
)
1486 TRACE("(%p)\n", pStm
);
1487 /* can't release a state-based marshal as nothing on server side to
1492 static HRESULT WINAPI
CompositeMonikerMarshalImpl_DisconnectObject(IMarshal
*iface
,
1495 TRACE("(0x%x)\n", dwReserved
);
1496 /* can't disconnect a state-based marshal as nothing on server side to
1497 * disconnect from */
1501 /******************************************************************************
1502 * EnumMonikerImpl_QueryInterface
1503 ******************************************************************************/
1504 static HRESULT WINAPI
1505 EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
)
1507 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1509 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppvObject
);
1511 /* Perform a sanity check on the parameters.*/
1513 return E_INVALIDARG
;
1515 /* Initialize the return parameter */
1518 /* Compare the riid with the interface IDs implemented by this object.*/
1519 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IEnumMoniker
, riid
))
1522 /* Check that we obtained an interface.*/
1523 if ((*ppvObject
)==0)
1524 return E_NOINTERFACE
;
1526 /* Query Interface always increases the reference count by one when it is successful */
1527 IEnumMoniker_AddRef(iface
);
1532 /******************************************************************************
1533 * EnumMonikerImpl_AddRef
1534 ******************************************************************************/
1536 EnumMonikerImpl_AddRef(IEnumMoniker
* iface
)
1538 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1540 TRACE("(%p)\n",This
);
1542 return InterlockedIncrement(&This
->ref
);
1546 /******************************************************************************
1547 * EnumMonikerImpl_Release
1548 ******************************************************************************/
1550 EnumMonikerImpl_Release(IEnumMoniker
* iface
)
1552 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1555 TRACE("(%p)\n",This
);
1557 ref
= InterlockedDecrement(&This
->ref
);
1559 /* destroy the object if there are no more references to it */
1562 for(i
=0;i
<This
->tabSize
;i
++)
1563 IMoniker_Release(This
->tabMoniker
[i
]);
1565 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
1566 HeapFree(GetProcessHeap(),0,This
);
1571 /******************************************************************************
1572 * EnumMonikerImpl_Next
1573 ******************************************************************************/
1574 static HRESULT WINAPI
1575 EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
, IMoniker
** rgelt
,
1578 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1581 /* retrieve the requested number of moniker from the current position */
1582 for(i
=0;((This
->currentPos
< This
->tabSize
) && (i
< celt
));i
++)
1584 rgelt
[i
]=This
->tabMoniker
[This
->currentPos
++];
1585 IMoniker_AddRef(rgelt
[i
]);
1588 if (pceltFethed
!=NULL
)
1597 /******************************************************************************
1598 * EnumMonikerImpl_Skip
1599 ******************************************************************************/
1600 static HRESULT WINAPI
1601 EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
)
1603 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1605 if ((This
->currentPos
+celt
) >= This
->tabSize
)
1608 This
->currentPos
+=celt
;
1613 /******************************************************************************
1614 * EnumMonikerImpl_Reset
1615 ******************************************************************************/
1616 static HRESULT WINAPI
1617 EnumMonikerImpl_Reset(IEnumMoniker
* iface
)
1619 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1626 /******************************************************************************
1627 * EnumMonikerImpl_Clone
1628 ******************************************************************************/
1629 static HRESULT WINAPI
1630 EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
)
1632 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1634 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabSize
,This
->currentPos
,TRUE
,ppenum
);
1637 /********************************************************************************/
1638 /* Virtual function table for the IROTData class */
1639 static const IEnumMonikerVtbl VT_EnumMonikerImpl
=
1641 EnumMonikerImpl_QueryInterface
,
1642 EnumMonikerImpl_AddRef
,
1643 EnumMonikerImpl_Release
,
1644 EnumMonikerImpl_Next
,
1645 EnumMonikerImpl_Skip
,
1646 EnumMonikerImpl_Reset
,
1647 EnumMonikerImpl_Clone
1650 /******************************************************************************
1651 * EnumMonikerImpl_CreateEnumMoniker
1652 ******************************************************************************/
1654 EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
, ULONG tabSize
,
1655 ULONG currentPos
, BOOL leftToRight
, IEnumMoniker
** ppmk
)
1657 EnumMonikerImpl
* newEnumMoniker
;
1660 if (currentPos
> tabSize
)
1661 return E_INVALIDARG
;
1663 newEnumMoniker
= HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl
));
1665 if (newEnumMoniker
== 0)
1666 return STG_E_INSUFFICIENTMEMORY
;
1668 /* Initialize the virtual function table. */
1669 newEnumMoniker
->IEnumMoniker_iface
.lpVtbl
= &VT_EnumMonikerImpl
;
1670 newEnumMoniker
->ref
= 1;
1672 newEnumMoniker
->tabSize
=tabSize
;
1673 newEnumMoniker
->currentPos
=currentPos
;
1675 newEnumMoniker
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,tabSize
*sizeof(newEnumMoniker
->tabMoniker
[0]));
1677 if (newEnumMoniker
->tabMoniker
==NULL
) {
1678 HeapFree(GetProcessHeap(), 0, newEnumMoniker
);
1679 return E_OUTOFMEMORY
;
1683 for (i
=0;i
<tabSize
;i
++){
1685 newEnumMoniker
->tabMoniker
[i
]=tabMoniker
[i
];
1686 IMoniker_AddRef(tabMoniker
[i
]);
1689 for (i
= tabSize
; i
> 0; i
--){
1691 newEnumMoniker
->tabMoniker
[tabSize
-i
]=tabMoniker
[i
- 1];
1692 IMoniker_AddRef(tabMoniker
[i
- 1]);
1695 *ppmk
=&newEnumMoniker
->IEnumMoniker_iface
;
1700 /********************************************************************************/
1701 /* Virtual function table for the CompositeMonikerImpl class which includes */
1702 /* IPersist, IPersistStream and IMoniker functions. */
1704 static const IMonikerVtbl VT_CompositeMonikerImpl
=
1706 CompositeMonikerImpl_QueryInterface
,
1707 CompositeMonikerImpl_AddRef
,
1708 CompositeMonikerImpl_Release
,
1709 CompositeMonikerImpl_GetClassID
,
1710 CompositeMonikerImpl_IsDirty
,
1711 CompositeMonikerImpl_Load
,
1712 CompositeMonikerImpl_Save
,
1713 CompositeMonikerImpl_GetSizeMax
,
1714 CompositeMonikerImpl_BindToObject
,
1715 CompositeMonikerImpl_BindToStorage
,
1716 CompositeMonikerImpl_Reduce
,
1717 CompositeMonikerImpl_ComposeWith
,
1718 CompositeMonikerImpl_Enum
,
1719 CompositeMonikerImpl_IsEqual
,
1720 CompositeMonikerImpl_Hash
,
1721 CompositeMonikerImpl_IsRunning
,
1722 CompositeMonikerImpl_GetTimeOfLastChange
,
1723 CompositeMonikerImpl_Inverse
,
1724 CompositeMonikerImpl_CommonPrefixWith
,
1725 CompositeMonikerImpl_RelativePathTo
,
1726 CompositeMonikerImpl_GetDisplayName
,
1727 CompositeMonikerImpl_ParseDisplayName
,
1728 CompositeMonikerImpl_IsSystemMoniker
1731 /********************************************************************************/
1732 /* Virtual function table for the IROTData class. */
1733 static const IROTDataVtbl VT_ROTDataImpl
=
1735 CompositeMonikerROTDataImpl_QueryInterface
,
1736 CompositeMonikerROTDataImpl_AddRef
,
1737 CompositeMonikerROTDataImpl_Release
,
1738 CompositeMonikerROTDataImpl_GetComparisonData
1741 static const IMarshalVtbl VT_MarshalImpl
=
1743 CompositeMonikerMarshalImpl_QueryInterface
,
1744 CompositeMonikerMarshalImpl_AddRef
,
1745 CompositeMonikerMarshalImpl_Release
,
1746 CompositeMonikerMarshalImpl_GetUnmarshalClass
,
1747 CompositeMonikerMarshalImpl_GetMarshalSizeMax
,
1748 CompositeMonikerMarshalImpl_MarshalInterface
,
1749 CompositeMonikerMarshalImpl_UnmarshalInterface
,
1750 CompositeMonikerMarshalImpl_ReleaseMarshalData
,
1751 CompositeMonikerMarshalImpl_DisconnectObject
1754 /******************************************************************************
1755 * Composite-Moniker_Construct (local function)
1756 *******************************************************************************/
1758 CompositeMonikerImpl_Construct(IMoniker
**ppMoniker
, IMoniker
*pmkFirst
, IMoniker
*pmkRest
)
1761 IEnumMoniker
*enumMoniker
;
1764 CompositeMonikerImpl
*This
;
1767 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1770 return E_OUTOFMEMORY
;
1772 TRACE("(%p,%p,%p)\n",This
,pmkFirst
,pmkRest
);
1774 /* Initialize the virtual function table. */
1775 This
->IMoniker_iface
.lpVtbl
= &VT_CompositeMonikerImpl
;
1776 This
->IROTData_iface
.lpVtbl
= &VT_ROTDataImpl
;
1777 This
->IMarshal_iface
.lpVtbl
= &VT_MarshalImpl
;
1780 This
->tabSize
=BLOCK_TAB_SIZE
;
1781 This
->tabLastIndex
=0;
1783 This
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,This
->tabSize
*sizeof(This
->tabMoniker
[0]));
1784 if (This
->tabMoniker
==NULL
) {
1785 HeapFree(GetProcessHeap(), 0, This
);
1786 return E_OUTOFMEMORY
;
1789 if (!pmkFirst
&& !pmkRest
)
1791 *ppMoniker
= &This
->IMoniker_iface
;
1795 IMoniker_IsSystemMoniker(pmkFirst
,&mkSys
);
1797 /* put the first moniker contents in the beginning of the table */
1798 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
1800 This
->tabMoniker
[(This
->tabLastIndex
)++]=pmkFirst
;
1801 IMoniker_AddRef(pmkFirst
);
1805 IMoniker_Enum(pmkFirst
,TRUE
,&enumMoniker
);
1807 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
1810 if (++This
->tabLastIndex
==This
->tabSize
){
1811 IMoniker
**tab_moniker
= This
->tabMoniker
;
1813 This
->tabSize
+=BLOCK_TAB_SIZE
;
1814 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(This
->tabMoniker
[0]));
1816 if (This
->tabMoniker
==NULL
){
1817 for (i
= 0; i
< This
->tabLastIndex
; i
++)
1818 IMoniker_Release(tab_moniker
[i
]);
1819 HeapFree(GetProcessHeap(), 0, tab_moniker
);
1820 HeapFree(GetProcessHeap(), 0, This
);
1821 return E_OUTOFMEMORY
;
1826 IEnumMoniker_Release(enumMoniker
);
1829 /* put the rest moniker contents after the first one and make simplification if needed */
1831 IMoniker_IsSystemMoniker(pmkRest
,&mkSys
);
1833 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
1835 /* add a simple moniker to the moniker table */
1837 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],pmkRest
,TRUE
,&tempMk
);
1839 if (res
==MK_E_NEEDGENERIC
){
1841 /* there's no simplification in this case */
1842 This
->tabMoniker
[This
->tabLastIndex
]=pmkRest
;
1844 This
->tabLastIndex
++;
1846 IMoniker_AddRef(pmkRest
);
1848 else if (tempMk
==NULL
){
1850 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
1851 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1853 This
->tabLastIndex
--;
1855 else if (SUCCEEDED(res
)){
1857 /* the non-generic composition was successful so we can make a simplification in this case */
1858 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1860 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
1862 for (i
= 0; i
< This
->tabLastIndex
; i
++)
1863 IMoniker_Release(This
->tabMoniker
[i
]);
1864 HeapFree(GetProcessHeap(), 0, This
->tabMoniker
);
1865 HeapFree(GetProcessHeap(), 0, This
);
1869 /* resize tabMoniker if needed */
1870 if (This
->tabLastIndex
==This
->tabSize
){
1871 IMoniker
**tab_moniker
= This
->tabMoniker
;
1873 This
->tabSize
+=BLOCK_TAB_SIZE
;
1875 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
1877 if (This
->tabMoniker
==NULL
){
1878 for (i
= 0; i
< This
->tabLastIndex
; i
++)
1879 IMoniker_Release(tab_moniker
[i
]);
1880 HeapFree(GetProcessHeap(), 0, tab_moniker
);
1881 HeapFree(GetProcessHeap(), 0, This
);
1882 return E_OUTOFMEMORY
;
1888 /* add a composite moniker to the moniker table (do the same thing
1889 * for each moniker within the composite moniker as a simple moniker
1890 * (see above for how to add a simple moniker case) )
1892 IMoniker_Enum(pmkRest
,TRUE
,&enumMoniker
);
1894 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
1896 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],This
->tabMoniker
[This
->tabLastIndex
],TRUE
,&tempMk
);
1898 if (res
==MK_E_NEEDGENERIC
){
1900 This
->tabLastIndex
++;
1902 else if (tempMk
==NULL
){
1904 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1905 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
]);
1906 This
->tabLastIndex
--;
1910 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
1912 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
1915 if (This
->tabLastIndex
==This
->tabSize
){
1916 IMoniker
**tab_moniker
= This
->tabMoniker
;
1918 This
->tabSize
+=BLOCK_TAB_SIZE
;
1920 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(This
->tabMoniker
[0]));
1922 if (This
->tabMoniker
==NULL
){
1923 for (i
= 0; i
< This
->tabLastIndex
; i
++)
1924 IMoniker_Release(tab_moniker
[i
]);
1925 HeapFree(GetProcessHeap(), 0, tab_moniker
);
1926 HeapFree(GetProcessHeap(), 0, This
);
1927 return E_OUTOFMEMORY
;
1932 IEnumMoniker_Release(enumMoniker
);
1935 /* only one moniker, then just return it */
1936 if (This
->tabLastIndex
== 1)
1938 *ppMoniker
= This
->tabMoniker
[0];
1939 IMoniker_AddRef(*ppMoniker
);
1940 IMoniker_Release(&This
->IMoniker_iface
);
1943 *ppMoniker
= &This
->IMoniker_iface
;
1948 /******************************************************************************
1949 * CreateGenericComposite [OLE32.@]
1950 ******************************************************************************/
1952 CreateGenericComposite(IMoniker
*pmkFirst
, IMoniker
*pmkRest
, IMoniker
**ppmkComposite
)
1954 IMoniker
* moniker
= 0;
1957 TRACE("(%p,%p,%p)\n",pmkFirst
,pmkRest
,ppmkComposite
);
1959 if (ppmkComposite
==NULL
)
1964 if (pmkFirst
==NULL
&& pmkRest
!=NULL
){
1966 *ppmkComposite
=pmkRest
;
1967 IMoniker_AddRef(pmkRest
);
1970 else if (pmkFirst
!=NULL
&& pmkRest
==NULL
){
1971 *ppmkComposite
=pmkFirst
;
1972 IMoniker_AddRef(pmkFirst
);
1975 else if (pmkFirst
==NULL
&& pmkRest
==NULL
)
1978 hr
= CompositeMonikerImpl_Construct(&moniker
,pmkFirst
,pmkRest
);
1983 hr
= IMoniker_QueryInterface(moniker
,&IID_IMoniker
,(void**)ppmkComposite
);
1984 IMoniker_Release(moniker
);
1989 /******************************************************************************
1990 * MonikerCommonPrefixWith [OLE32.@]
1991 ******************************************************************************/
1993 MonikerCommonPrefixWith(IMoniker
* pmkThis
,IMoniker
* pmkOther
,IMoniker
** ppmkCommon
)
1995 FIXME("(),stub!\n");
1999 HRESULT WINAPI
CompositeMoniker_CreateInstance(IClassFactory
*iface
,
2000 IUnknown
*pUnk
, REFIID riid
, void **ppv
)
2005 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
2010 return CLASS_E_NOAGGREGATION
;
2012 hr
= CompositeMonikerImpl_Construct(&pMoniker
, NULL
, NULL
);
2016 hr
= IMoniker_QueryInterface(pMoniker
, riid
, ppv
);
2017 IMoniker_Release(pMoniker
);