1 /***************************************************************************************
2 * CompositeMonikers implementation
4 * Copyright 1999 Noomen Hamza
5 ***************************************************************************************/
15 #include "wine/obj_inplace.h"
18 DEFAULT_DEBUG_CHANNEL(ole
)
20 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
22 /* CompositeMoniker data structure */
23 typedef struct CompositeMonikerImpl
{
25 ICOM_VTABLE(IMoniker
)* lpvtbl1
; /* VTable relative to the IMoniker interface.*/
27 /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
28 * two monikers are equal. That's whay IROTData interface is implemented by monikers.
30 ICOM_VTABLE(IROTData
)* lpvtbl2
; /* VTable relative to the IROTData interface.*/
32 ULONG ref
; /* reference counter for this object */
34 IMoniker
** tabMoniker
; /* dynamaic table containing all components (monikers) of this composite moniker */
36 ULONG tabSize
; /* size of tabMoniker */
38 ULONG tabLastIndex
; /* first free index in tabMoniker */
40 } CompositeMonikerImpl
;
43 /* EnumMoniker data structure */
44 typedef struct EnumMonikerImpl
{
46 ICOM_VTABLE(IEnumMoniker
)* lpvtbl
; /* VTable relative to the IEnumMoniker interface.*/
48 ULONG ref
; /* reference counter for this object */
50 IMoniker
** tabMoniker
; /* dynamic table containing the enumerated monikers */
52 ULONG tabSize
; /* size of tabMoniker */
54 ULONG currentPos
; /* index pointer on the current moniker */
59 /********************************************************************************/
60 /* CompositeMoniker prototype functions : */
62 /* IUnknown prototype functions */
63 static HRESULT WINAPI
CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
);
64 static ULONG WINAPI
CompositeMonikerImpl_AddRef(IMoniker
* iface
);
65 static ULONG WINAPI
CompositeMonikerImpl_Release(IMoniker
* iface
);
67 /* IPersist prototype functions */
68 static HRESULT WINAPI
CompositeMonikerImpl_GetClassID(const IMoniker
* iface
, CLSID
*pClassID
);
70 /* IPersistStream prototype functions */
71 static HRESULT WINAPI
CompositeMonikerImpl_IsDirty(IMoniker
* iface
);
72 static HRESULT WINAPI
CompositeMonikerImpl_Load(IMoniker
* iface
, IStream
* pStm
);
73 static HRESULT WINAPI
CompositeMonikerImpl_Save(IMoniker
* iface
, IStream
* pStm
, BOOL fClearDirty
);
74 static HRESULT WINAPI
CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
, ULARGE_INTEGER
* pcbSize
);
76 /* IMoniker prototype functions */
77 static HRESULT WINAPI
CompositeMonikerImpl_BindToObject(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
);
78 static HRESULT WINAPI
CompositeMonikerImpl_BindToStorage(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
);
79 static HRESULT WINAPI
CompositeMonikerImpl_Reduce(IMoniker
* iface
,IBindCtx
* pbc
, DWORD dwReduceHowFar
,IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
);
80 static HRESULT WINAPI
CompositeMonikerImpl_ComposeWith(IMoniker
* iface
,IMoniker
* pmkRight
,BOOL fOnlyIfNotGeneric
, IMoniker
** ppmkComposite
);
81 static HRESULT WINAPI
CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
);
82 static HRESULT WINAPI
CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
);
83 static HRESULT WINAPI
CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
);
84 static HRESULT WINAPI
CompositeMonikerImpl_IsRunning(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, IMoniker
* pmkNewlyRunning
);
85 static HRESULT WINAPI
CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
, FILETIME
* pCompositeTime
);
86 static HRESULT WINAPI
CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
);
87 static HRESULT WINAPI
CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
, IMoniker
** ppmkPrefix
);
88 static HRESULT WINAPI
CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmOther
, IMoniker
** ppmkRelPath
);
89 static HRESULT WINAPI
CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
);
90 static HRESULT WINAPI
CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
* pchEaten
, IMoniker
** ppmkOut
);
91 static HRESULT WINAPI
CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
);
93 /********************************************************************************/
94 /* IROTData prototype functions */
96 /* IUnknown prototype functions */
97 static HRESULT WINAPI
CompositeMonikerROTDataImpl_QueryInterface(IROTData
* iface
,REFIID riid
,VOID
** ppvObject
);
98 static ULONG WINAPI
CompositeMonikerROTDataImpl_AddRef(IROTData
* iface
);
99 static ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
);
101 /* IROTData prototype function */
102 static HRESULT WINAPI
CompositeMonikerROTDataImpl_GetComparaisonData(IROTData
* iface
,BYTE
* pbData
,ULONG cbMax
,ULONG
* pcbData
);
104 /* Local function used by CompositeMoniker implementation */
105 HRESULT WINAPI
CompositeMonikerImpl_Construct(CompositeMonikerImpl
* This
,LPMONIKER pmkFirst
, LPMONIKER pmkRest
);
106 HRESULT WINAPI
CompositeMonikerImpl_Destroy(CompositeMonikerImpl
* iface
);
108 /********************************************************************************/
109 /* IEnumMoniker prototype functions */
111 /* IUnknown prototype functions */
112 static HRESULT WINAPI
EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
);
113 static ULONG WINAPI
EnumMonikerImpl_AddRef(IEnumMoniker
* iface
);
114 static ULONG WINAPI
EnumMonikerImpl_Release(IEnumMoniker
* iface
);
116 /* IEnumMonker prototype functions */
117 static HRESULT WINAPI
EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
,IMoniker
** rgelt
,ULONG
* pceltFetched
);
118 static HRESULT WINAPI
EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
);
119 static HRESULT WINAPI
EnumMonikerImpl_Reset(IEnumMoniker
* iface
);
120 static HRESULT WINAPI
EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
);
122 HRESULT WINAPI
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,ULONG tabSize
,ULONG currentPos
,BOOL leftToRigth
,IEnumMoniker
** ppmk
);
124 /********************************************************************************/
125 /* Virtual function table for the CompositeMonikerImpl class witch include */
126 /* Ipersist, IPersistStream and IMoniker functions. */
128 static ICOM_VTABLE(IMoniker
) VT_CompositeMonikerImpl
=
130 CompositeMonikerImpl_QueryInterface
,
131 CompositeMonikerImpl_AddRef
,
132 CompositeMonikerImpl_Release
,
133 CompositeMonikerImpl_GetClassID
,
134 CompositeMonikerImpl_IsDirty
,
135 CompositeMonikerImpl_Load
,
136 CompositeMonikerImpl_Save
,
137 CompositeMonikerImpl_GetSizeMax
,
138 CompositeMonikerImpl_BindToObject
,
139 CompositeMonikerImpl_BindToStorage
,
140 CompositeMonikerImpl_Reduce
,
141 CompositeMonikerImpl_ComposeWith
,
142 CompositeMonikerImpl_Enum
,
143 CompositeMonikerImpl_IsEqual
,
144 CompositeMonikerImpl_Hash
,
145 CompositeMonikerImpl_IsRunning
,
146 CompositeMonikerImpl_GetTimeOfLastChange
,
147 CompositeMonikerImpl_Inverse
,
148 CompositeMonikerImpl_CommonPrefixWith
,
149 CompositeMonikerImpl_RelativePathTo
,
150 CompositeMonikerImpl_GetDisplayName
,
151 CompositeMonikerImpl_ParseDisplayName
,
152 CompositeMonikerImpl_IsSystemMoniker
155 /********************************************************************************/
156 /* Virtual function table for the IROTData class. */
157 static ICOM_VTABLE(IROTData
) VT_ROTDataImpl
=
159 CompositeMonikerROTDataImpl_QueryInterface
,
160 CompositeMonikerROTDataImpl_AddRef
,
161 CompositeMonikerROTDataImpl_Release
,
162 CompositeMonikerROTDataImpl_GetComparaisonData
165 /********************************************************************************/
166 /* Virtual function table for the IROTData class */
167 static ICOM_VTABLE(IEnumMoniker
) VT_EnumMonikerImpl
=
169 EnumMonikerImpl_QueryInterface
,
170 EnumMonikerImpl_AddRef
,
171 EnumMonikerImpl_Release
,
172 EnumMonikerImpl_Next
,
173 EnumMonikerImpl_Skip
,
174 EnumMonikerImpl_Reset
,
175 EnumMonikerImpl_Clone
178 /*******************************************************************************
179 * CompositeMoniker_QueryInterface
180 *******************************************************************************/
181 HRESULT WINAPI
CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
183 ICOM_THIS(CompositeMonikerImpl
,iface
);
185 TRACE(ole
,"(%p,%p,%p)\n",This
,riid
,ppvObject
);
187 /* Perform a sanity check on the parameters.*/
188 if ( (This
==0) || (ppvObject
==0) )
191 /* Initialize the return parameter */
194 /* Compare the riid with the interface IDs implemented by this object.*/
195 if (IsEqualIID(&IID_IUnknown
, riid
) ||
196 IsEqualIID(&IID_IPersist
, riid
) ||
197 IsEqualIID(&IID_IPersistStream
, riid
) ||
198 IsEqualIID(&IID_IMoniker
, riid
)
201 else if (IsEqualIID(&IID_IROTData
, riid
))
202 *ppvObject
= (IROTData
*)&(This
->lpvtbl2
);
204 /* Check that we obtained an interface.*/
206 return E_NOINTERFACE
;
208 /* Query Interface always increases the reference count by one when it is successful */
209 CompositeMonikerImpl_AddRef(iface
);
214 /******************************************************************************
215 * CompositeMoniker_AddRef
216 ******************************************************************************/
217 ULONG WINAPI
CompositeMonikerImpl_AddRef(IMoniker
* iface
)
219 ICOM_THIS(CompositeMonikerImpl
,iface
);
221 TRACE(ole
,"(%p)\n",This
);
223 return ++(This
->ref
);
226 /******************************************************************************
227 * CompositeMoniker_Release
228 ******************************************************************************/
229 ULONG WINAPI
CompositeMonikerImpl_Release(IMoniker
* iface
)
231 ICOM_THIS(CompositeMonikerImpl
,iface
);
234 TRACE(ole
,"(%p)\n",This
);
238 /* destroy the object if there's no more reference on it */
241 /* release all the components before destroying this object */
242 for (i
=0;i
<This
->tabLastIndex
;i
++)
243 IMoniker_Release(This
->tabMoniker
[i
]);
245 CompositeMonikerImpl_Destroy(This
);
252 /******************************************************************************
253 * CompositeMoniker_GetClassID
254 ******************************************************************************/
255 HRESULT WINAPI
CompositeMonikerImpl_GetClassID(const IMoniker
* iface
,CLSID
*pClassID
)
257 TRACE(ole
,"(%p,%p),stub!\n",iface
,pClassID
);
262 *pClassID
= CLSID_CompositeMoniker
;
267 /******************************************************************************
268 * CompositeMoniker_IsDirty
269 ******************************************************************************/
270 HRESULT WINAPI
CompositeMonikerImpl_IsDirty(IMoniker
* iface
)
272 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
273 method in the OLE-provided moniker interfaces always return S_FALSE because
274 their internal state never changes. */
276 TRACE(ole
,"(%p)\n",iface
);
281 /******************************************************************************
282 * CompositeMoniker_Load
283 ******************************************************************************/
284 HRESULT WINAPI
CompositeMonikerImpl_Load(IMoniker
* iface
,IStream
* pStm
)
291 ICOM_THIS(CompositeMonikerImpl
,iface
);
293 TRACE(ole
,"(%p,%p)\n",iface
,pStm
);
295 /* this function call OleLoadFromStream function for each moniker within this object */
297 /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
298 res
=IStream_Read(pStm
,&constant
,sizeof(DWORD
),NULL
);
300 if (SUCCEEDED(res
)&& constant
!=3)
305 res
=OleLoadFromStream(pStm
,&IID_IMoniker
,(void**)&This
->tabMoniker
[This
->tabLastIndex
]);
307 res
=ReadClassStm(pStm
,&clsid
);
308 printf("res=%ld",res
);
312 if (IsEqualIID(&clsid
,&CLSID_FileMoniker
)){
313 res
=CreateFileMoniker(string
,&This
->tabMoniker
[This
->tabLastIndex
]);
316 res
=IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
320 else if (IsEqualIID(&clsid
,&CLSID_ItemMoniker
)){
321 CreateItemMoniker(string
,string
,&This
->tabMoniker
[This
->tabLastIndex
]);
324 IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
328 else if (IsEqualIID(&clsid
,&CLSID_AntiMoniker
)){
329 CreateAntiMoniker(&This
->tabMoniker
[This
->tabLastIndex
]);
332 IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
336 else if (IsEqualIID(&clsid
,&CLSID_CompositeMoniker
))
345 /* resize the table if needed */
346 if (++This
->tabLastIndex
==This
->tabSize
){
348 This
->tabSize
+=BLOCK_TAB_SIZE
;
349 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
351 if (This
->tabMoniker
==NULL
)
352 return E_OUTOFMEMORY
;
359 /******************************************************************************
360 * CompositeMoniker_Save
361 ******************************************************************************/
362 HRESULT WINAPI
CompositeMonikerImpl_Save(IMoniker
* iface
,IStream
* pStm
,BOOL fClearDirty
)
365 IEnumMoniker
*enumMk
;
369 TRACE(ole
,"(%p,%p,%d)\n",iface
,pStm
,fClearDirty
);
371 /* this function call OleSaveToStream function for each moniker within this object */
373 /* when I tested this function in windows system ! I usually found this constant in the begining of */
374 /* the stream I dont known why (there's no indication in specification) ! */
375 res
=IStream_Write(pStm
,&constant
,sizeof(constant
),NULL
);
377 IMoniker_Enum(iface
,TRUE
,&enumMk
);
379 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
381 res
=OleSaveToStream((IPersistStream
*)pmk
,pStm
);
383 IMoniker_Release(pmk
);
387 IEnumMoniker_Release(pmk
);
392 IEnumMoniker_Release(enumMk
);
397 /******************************************************************************
398 * CompositeMoniker_GetSizeMax
399 ******************************************************************************/
400 HRESULT WINAPI
CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
,ULARGE_INTEGER
* pcbSize
)
402 IEnumMoniker
*enumMk
;
404 ULARGE_INTEGER ptmpSize
;
406 /* the sizeMax of this object is calculated by calling GetSizeMax on each moniker within this object then */
407 /* suming all returned sizemax */
409 TRACE(ole
,"(%p,%p)\n",iface
,pcbSize
);
417 IMoniker_Enum(iface
,TRUE
,&enumMk
);
419 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==TRUE
){
421 IMoniker_GetSizeMax(pmk
,&ptmpSize
);
423 IMoniker_Release(pmk
);
425 pcbSize
->LowPart
+=ptmpSize
.LowPart
;
426 pcbSize
->HighPart
+=ptmpSize
.HighPart
;
429 IEnumMoniker_Release(enumMk
);
434 /******************************************************************************
435 * Composite-Moniker_Construct (local function)
436 *******************************************************************************/
437 HRESULT WINAPI
CompositeMonikerImpl_Construct(CompositeMonikerImpl
* This
,LPMONIKER pmkFirst
, LPMONIKER pmkRest
)
440 IEnumMoniker
*enumMoniker
;
444 TRACE(ole
,"(%p,%p,%p)\n",This
,pmkFirst
,pmkRest
);
446 /* Initialize the virtual fgunction table. */
447 This
->lpvtbl1
= &VT_CompositeMonikerImpl
;
448 This
->lpvtbl2
= &VT_ROTDataImpl
;
451 This
->tabSize
=BLOCK_TAB_SIZE
;
452 This
->tabLastIndex
=0;
454 This
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,This
->tabSize
*sizeof(IMoniker
));
455 if (This
->tabMoniker
==NULL
)
456 return E_OUTOFMEMORY
;
458 IMoniker_IsSystemMoniker(pmkFirst
,&mkSys
);
460 /* put the first moniker contents in the begining of the table */
461 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
463 This
->tabMoniker
[(This
->tabLastIndex
)++]=pmkFirst
;
464 IMoniker_AddRef(pmkFirst
);
468 IMoniker_Enum(pmkFirst
,TRUE
,&enumMoniker
);
470 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
473 if (++This
->tabLastIndex
==This
->tabSize
){
475 This
->tabSize
+=BLOCK_TAB_SIZE
;
476 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
478 if (This
->tabMoniker
==NULL
)
479 return E_OUTOFMEMORY
;
483 IEnumMoniker_Release(enumMoniker
);
486 /* put the rest moniker contents after the first one and make simplification if needed */
488 IMoniker_IsSystemMoniker(pmkRest
,&mkSys
);
490 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
492 /* add a simple moniker to the moniker table */
494 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],pmkRest
,TRUE
,&tempMk
);
496 if (res
==MK_E_NEEDGENERIC
){
498 /* there's no simplification in this case */
499 This
->tabMoniker
[This
->tabLastIndex
]=pmkRest
;
501 This
->tabLastIndex
++;
503 IMoniker_AddRef(pmkRest
);
505 else if (tempMk
==NULL
){
507 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
508 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
510 This
->tabLastIndex
--;
512 else if (SUCCEEDED(res
)){
514 /* the non-generic composition was successful so we can make a simplification in this case */
515 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
517 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
521 /* resize tabMoniker if needed */
522 if (This
->tabLastIndex
==This
->tabSize
){
524 This
->tabSize
+=BLOCK_TAB_SIZE
;
526 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
528 if (This
->tabMoniker
==NULL
)
529 return E_OUTOFMEMORY
;
534 /* add a composite moniker to the moniker table (do the same thing for each moniker within the */
535 /* composite moniker as a simple moniker (see above how to add a simple moniker case) ) */
536 IMoniker_Enum(pmkRest
,TRUE
,&enumMoniker
);
538 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
540 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],This
->tabMoniker
[This
->tabLastIndex
],TRUE
,&tempMk
);
542 if (res
==MK_E_NEEDGENERIC
){
544 This
->tabLastIndex
++;
546 else if (tempMk
==NULL
){
548 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
549 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
]);
550 This
->tabLastIndex
--;
554 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
556 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
559 if (This
->tabLastIndex
==This
->tabSize
){
561 This
->tabSize
+=BLOCK_TAB_SIZE
;
563 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
565 if (This
->tabMoniker
==NULL
)
566 return E_OUTOFMEMORY
;
570 IEnumMoniker_Release(enumMoniker
);
576 /******************************************************************************
577 * CompositeMoniker_Destroy (local function)
578 *******************************************************************************/
579 HRESULT WINAPI
CompositeMonikerImpl_Destroy(CompositeMonikerImpl
* This
)
581 TRACE(ole
,"(%p)\n",This
);
583 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
585 HeapFree(GetProcessHeap(),0,This
);
590 /******************************************************************************
591 * CompositeMoniker_BindToObject
592 ******************************************************************************/
593 HRESULT WINAPI
CompositeMonikerImpl_BindToObject(IMoniker
* iface
,
600 IRunningObjectTable
*prot
;
601 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
602 IEnumMoniker
*enumMoniker
;
604 TRACE(ole
,"(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
610 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
611 /* object for the requested interface pointer. */
614 res
=IBindCtx_GetRunningObjectTable(pbc
,&prot
);
618 /* if the requested class was loaded befor ! we dont need to reload it */
619 res
= IRunningObjectTable_GetObject(prot
,iface
,(IUnknown
**)ppvResult
);
626 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
627 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
629 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
630 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
631 IEnumMoniker_Release(enumMoniker
);
633 res
=CreateAntiMoniker(&antiMk
);
634 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
635 IMoniker_Release(antiMk
);
637 res
=CompositeMonikerImpl_BindToObject(mostRigthMk
,pbc
,tempMk
,riid
,ppvResult
);
639 IMoniker_Release(tempMk
);
640 IMoniker_Release(mostRigthMk
);
646 /******************************************************************************
647 * CompositeMoniker_BindToStorage
648 ******************************************************************************/
649 HRESULT WINAPI
CompositeMonikerImpl_BindToStorage(IMoniker
* iface
,
656 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
657 IEnumMoniker
*enumMoniker
;
659 TRACE(ole
,"(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
663 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
664 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
666 if (pmkToLeft
!=NULL
){
668 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
669 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
670 IEnumMoniker_Release(enumMoniker
);
672 res
=CreateAntiMoniker(&antiMk
);
673 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
674 IMoniker_Release(antiMk
);
676 res
=CompositeMonikerImpl_BindToStorage(mostRigthMk
,pbc
,tempMk
,riid
,ppvResult
);
678 IMoniker_Release(tempMk
);
680 IMoniker_Release(mostRigthMk
);
685 return IMoniker_BindToStorage(iface
,pbc
,NULL
,riid
,ppvResult
);
688 /******************************************************************************
689 * CompositeMoniker_Reduce
690 ******************************************************************************/
691 HRESULT WINAPI
CompositeMonikerImpl_Reduce(IMoniker
* iface
,
693 DWORD dwReduceHowFar
,
694 IMoniker
** ppmkToLeft
,
695 IMoniker
** ppmkReduced
)
698 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*leftReducedComposedMk
,*mostRigthReducedMk
;
699 IEnumMoniker
*enumMoniker
;
701 TRACE(ole
,"(%p,%p,%ld,%p,%p)\n",iface
,pbc
,dwReduceHowFar
,ppmkToLeft
,ppmkReduced
);
703 if (ppmkReduced
==NULL
)
706 /* This method recursively calls Reduce for each of its component monikers. */
708 if (ppmkToLeft
==NULL
){
710 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
711 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
712 IEnumMoniker_Release(enumMoniker
);
714 res
=CreateAntiMoniker(&antiMk
);
715 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
716 IMoniker_Release(antiMk
);
718 return CompositeMonikerImpl_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
, ppmkReduced
);
720 else if (*ppmkToLeft
==NULL
)
722 return IMoniker_Reduce(iface
,pbc
,dwReduceHowFar
,NULL
,ppmkReduced
);
726 /* separate the copmosite moniker in to left and wrigth moniker */
727 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
728 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
729 IEnumMoniker_Release(enumMoniker
);
731 res
=CreateAntiMoniker(&antiMk
);
732 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
733 IMoniker_Release(antiMk
);
735 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
736 /* of the reduced components */
737 if (IMoniker_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,NULL
,&mostRigthReducedMk
) &&
738 CompositeMonikerImpl_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
,&leftReducedComposedMk
)
741 return CreateGenericComposite(leftReducedComposedMk
,mostRigthReducedMk
,ppmkReduced
);
744 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
746 IMoniker_AddRef(iface
);
750 return MK_S_REDUCED_TO_SELF
;
755 /******************************************************************************
756 * CompositeMoniker_ComposeWith
757 ******************************************************************************/
758 HRESULT WINAPI
CompositeMonikerImpl_ComposeWith(IMoniker
* iface
,
760 BOOL fOnlyIfNotGeneric
,
761 IMoniker
** ppmkComposite
)
763 TRACE(ole
,"(%p,%p,%d,%p)\n",iface
,pmkRight
,fOnlyIfNotGeneric
,ppmkComposite
);
765 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
770 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
771 /* otherwise, the method returns the result of combining the two monikers by calling the */
772 /* CreateGenericComposite function */
774 if (fOnlyIfNotGeneric
)
775 return MK_E_NEEDGENERIC
;
777 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
780 /******************************************************************************
781 * CompositeMoniker_Enum
782 ******************************************************************************/
783 HRESULT WINAPI
CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
785 ICOM_THIS(CompositeMonikerImpl
,iface
);
787 TRACE(ole
,"(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
789 if (ppenumMoniker
== NULL
)
792 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabLastIndex
,0,fForward
,ppenumMoniker
);
795 /******************************************************************************
796 * CompositeMoniker_IsEqual
797 ******************************************************************************/
798 HRESULT WINAPI
CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
)
800 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
801 IMoniker
*tempMk1
,*tempMk2
;
802 HRESULT res1
,res2
,res
;
804 TRACE(ole
,"(%p,%p)\n",iface
,pmkOtherMoniker
);
806 if (pmkOtherMoniker
==NULL
)
809 /* This method returns S_OK if the components of both monikers are equal when compared in the */
810 /* left-to-right order.*/
811 IMoniker_Enum(pmkOtherMoniker
,TRUE
,&enumMoniker1
);
813 if (enumMoniker1
==NULL
)
816 IMoniker_Enum(iface
,TRUE
,&enumMoniker2
);
820 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
821 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
823 if((res1
==S_OK
)&&(res2
==S_OK
)){
825 if(IMoniker_IsEqual(tempMk1
,tempMk2
)==S_FALSE
){
832 else if ( (res1
==S_FALSE
) && (res2
==S_FALSE
) ){
842 IMoniker_Release(tempMk1
);
845 IMoniker_Release(tempMk2
);
848 IEnumMoniker_Release(enumMoniker1
);
849 IEnumMoniker_Release(enumMoniker2
);
853 /******************************************************************************
854 * CompositeMoniker_Hash
855 ******************************************************************************/
856 HRESULT WINAPI
CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
858 FIXME(ole
,"(),stub!\n");
863 /******************************************************************************
864 * CompositeMoniker_IsRunning
865 ******************************************************************************/
866 HRESULT WINAPI
CompositeMonikerImpl_IsRunning(IMoniker
* iface
,
869 IMoniker
* pmkNewlyRunning
)
871 IRunningObjectTable
* rot
;
873 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
874 IEnumMoniker
*enumMoniker
;
876 TRACE(ole
,"(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
878 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
879 if (pmkToLeft
!=NULL
){
881 CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
883 res
= IMoniker_IsRunning(tempMk
,pbc
,NULL
,pmkNewlyRunning
);
885 IMoniker_Release(tempMk
);
890 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
891 /* to this moniker */
893 if (pmkNewlyRunning
!=NULL
)
895 if (IMoniker_IsEqual(iface
,pmkNewlyRunning
)==S_OK
)
906 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
907 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
908 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
909 /* the composite as the pmkToLeft parameter for that call. */
911 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
916 res
= IRunningObjectTable_IsRunning(rot
,iface
);
917 IRunningObjectTable_Release(rot
);
924 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
925 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
926 IEnumMoniker_Release(enumMoniker
);
928 res
=CreateAntiMoniker(&antiMk
);
929 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
930 IMoniker_Release(antiMk
);
932 res
=IMoniker_IsRunning(mostRigthMk
,pbc
,tempMk
,pmkNewlyRunning
);
934 IMoniker_Release(tempMk
);
935 IMoniker_Release(mostRigthMk
);
942 /******************************************************************************
943 * CompositeMoniker_GetTimeOfLastChange
944 ******************************************************************************/
945 HRESULT WINAPI
CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
,
948 FILETIME
* pCompositeTime
)
950 IRunningObjectTable
* rot
;
952 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
953 IEnumMoniker
*enumMoniker
;
955 TRACE(ole
,"(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pCompositeTime
);
957 if (pCompositeTime
==NULL
)
960 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
961 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
962 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
963 /* of the composite as the pmkToLeft parameter for that call. */
964 if (pmkToLeft
!=NULL
){
966 res
=CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
968 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
973 if (IRunningObjectTable_GetTimeOfLastChange(rot
,tempMk
,pCompositeTime
)==S_OK
)
977 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
978 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
979 IEnumMoniker_Release(enumMoniker
);
981 res
=CreateAntiMoniker(&antiMk
);
982 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
983 IMoniker_Release(antiMk
);
985 res
=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk
,pbc
,tempMk
,pCompositeTime
);
987 IMoniker_Release(tempMk
);
988 IMoniker_Release(mostRigthMk
);
993 return IMoniker_GetTimeOfLastChange(iface
,pbc
,NULL
,pCompositeTime
);
996 /******************************************************************************
997 * CompositeMoniker_Inverse
998 ******************************************************************************/
999 HRESULT WINAPI
CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
1002 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*tempInvMk
,*mostRigthInvMk
;
1003 IEnumMoniker
*enumMoniker
;
1005 TRACE(ole
,"(%p,%p)\n",iface
,ppmk
);
1010 /* This method returns a composite moniker that consists of the inverses of each of the components */
1011 /* of the original composite, stored in reverse order */
1013 res
=CreateAntiMoniker(&antiMk
);
1014 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1015 IMoniker_Release(antiMk
);
1019 return IMoniker_Inverse(iface
,ppmk
);
1023 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1024 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1025 IEnumMoniker_Release(enumMoniker
);
1027 IMoniker_Inverse(mostRigthMk
,&mostRigthInvMk
);
1028 CompositeMonikerImpl_Inverse(tempMk
,&tempInvMk
);
1030 res
=CreateGenericComposite(mostRigthInvMk
,tempInvMk
,ppmk
);
1032 IMoniker_Release(tempMk
);
1033 IMoniker_Release(mostRigthMk
);
1034 IMoniker_Release(tempInvMk
);
1035 IMoniker_Release(mostRigthInvMk
);
1041 /******************************************************************************
1042 * CompositeMoniker_CommonPrefixWith
1043 ******************************************************************************/
1044 HRESULT WINAPI
CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
,IMoniker
** ppmkPrefix
)
1048 IMoniker
*tempMk1
,*tempMk2
,*mostLeftMk1
,*mostLeftMk2
;
1049 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
1050 ULONG i
,nbCommonMk
=0;
1052 /* If the other moniker is a composite, this method compares the components of each composite from left */
1053 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1054 /* of the leftmost components were common to both monikers. */
1056 if (ppmkPrefix
==NULL
)
1062 return MK_E_NOPREFIX
;
1064 IMoniker_IsSystemMoniker(pmkOther
,&mkSys
);
1066 if((mkSys
==MKSYS_GENERICCOMPOSITE
)){
1068 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
1069 IMoniker_Enum(pmkOther
,TRUE
,&enumMoniker2
);
1073 res1
=IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
1074 res2
=IEnumMoniker_Next(enumMoniker2
,1,&mostLeftMk2
,NULL
);
1076 if ((res1
==S_FALSE
) && (res2
==S_FALSE
)){
1078 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1080 IMoniker_AddRef(iface
);
1083 else if ((res1
==S_OK
) && (res2
==S_OK
)){
1085 if (IMoniker_IsEqual(mostLeftMk1
,mostLeftMk2
)==S_OK
)
1093 else if (res1
==S_OK
){
1095 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1096 /* ppmkPrefix to the other moniker. */
1097 *ppmkPrefix
=pmkOther
;
1101 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1102 /* to this moniker. */
1108 IEnumMoniker_Release(enumMoniker1
);
1109 IEnumMoniker_Release(enumMoniker2
);
1111 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1113 return MK_E_NOPREFIX
;
1115 IEnumMoniker_Reset(enumMoniker1
);
1117 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1119 /* if we have more than one commun moniker the result will be a composite moniker */
1122 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1123 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1124 CreateGenericComposite(tempMk1
,tempMk2
,ppmkPrefix
);
1125 IMoniker_Release(tempMk1
);
1126 IMoniker_Release(tempMk2
);
1128 /* compose all common monikers in a composite moniker */
1129 for(i
=0;i
<nbCommonMk
;i
++){
1131 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1133 CreateGenericComposite(*ppmkPrefix
,tempMk1
,&tempMk2
);
1135 IMoniker_Release(*ppmkPrefix
);
1137 IMoniker_Release(tempMk1
);
1139 *ppmkPrefix
=tempMk2
;
1144 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1145 *ppmkPrefix
=tempMk1
;
1151 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1154 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
1156 IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
1158 if (IMoniker_IsEqual(pmkOther
,mostLeftMk1
)==S_OK
){
1160 *ppmkPrefix
=pmkOther
;
1165 return MK_E_NOPREFIX
;
1168 /***************************************************************************************************
1169 * GetAfterCommonPrefix (local function)
1170 * This function returns a moniker that consist of the remainder when the common prefix is removed
1171 ***************************************************************************************************/
1172 VOID WINAPI
GetAfterCommonPrefix(IMoniker
* pGenMk
,IMoniker
* commonMk
,IMoniker
** restMk
)
1174 IMoniker
*tempMk
,*tempMk1
,*tempMk2
;
1175 IEnumMoniker
*enumMoniker1
,*enumMoniker2
,*enumMoniker3
;
1182 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1183 /* prefix: enum the two monikers (left-wrigth) then compare these enumerations (left-wrigth) and stop */
1184 /* on the first difference. */
1185 IMoniker_Enum(pGenMk
,TRUE
,&enumMoniker1
);
1187 IMoniker_IsSystemMoniker(commonMk
,&mkSys
);
1189 if (mkSys
==MKSYS_GENERICCOMPOSITE
){
1191 IMoniker_Enum(commonMk
,TRUE
,&enumMoniker2
);
1194 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1195 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
1197 if ((res1
==S_FALSE
)||(res2
==S_FALSE
)){
1203 IMoniker_Release(tempMk1
);
1204 IMoniker_Release(tempMk1
);
1208 IMoniker_Release(tempMk1
);
1209 IMoniker_Release(tempMk1
);
1213 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1214 IMoniker_Release(tempMk1
);
1217 /* count the number of elements in the enumerator after the common prefix */
1218 IEnumMoniker_Clone(enumMoniker1
,&enumMoniker3
);
1220 for(;IEnumMoniker_Next(enumMoniker3
,1,&tempMk
,NULL
)==S_OK
;nbRestMk
++)
1222 IMoniker_Release(tempMk
);;
1227 /* create a generic composite moniker with monikers located after the common prefix */
1228 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1237 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1239 CreateGenericComposite(tempMk1
,tempMk2
,restMk
);
1241 IMoniker_Release(tempMk1
);
1243 IMoniker_Release(tempMk2
);
1245 while(IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
)==S_OK
){
1247 CreateGenericComposite(*restMk
,tempMk1
,&tempMk2
);
1249 IMoniker_Release(tempMk1
);
1251 IMoniker_Release(*restMk
);
1257 /******************************************************************************
1258 * CompositeMoniker_RelativePathTo
1259 ******************************************************************************/
1260 HRESULT WINAPI
CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmkOther
, IMoniker
** ppmkRelPath
)
1263 IMoniker
*restOtherMk
=0,*restThisMk
=0,*invRestThisMk
=0,*commonMk
=0;
1265 TRACE(ole
,"(%p,%p,%p)\n",iface
,pmkOther
,ppmkRelPath
);
1267 if (ppmkRelPath
==NULL
)
1272 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1273 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1274 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1276 /* finds the common prefix of the two monikers */
1277 res
=IMoniker_CommonPrefixWith(iface
,pmkOther
,&commonMk
);
1279 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1280 if ((res
== MK_E_NOPREFIX
)||(res
==MK_S_US
)){
1282 *ppmkRelPath
=pmkOther
;
1283 IMoniker_AddRef(pmkOther
);
1287 GetAfterCommonPrefix(iface
,commonMk
,&restThisMk
);
1288 GetAfterCommonPrefix(pmkOther
,commonMk
,&restOtherMk
);
1290 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1291 /* moniker when the common prefix is removed */
1294 IMoniker_Inverse(restThisMk
,ppmkRelPath
);
1295 IMoniker_Release(restThisMk
);
1297 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1298 /* when the common prefix is removed */
1299 else if (res
==MK_S_ME
){
1301 *ppmkRelPath
=restOtherMk
;
1302 IMoniker_AddRef(restOtherMk
);
1304 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1305 /* moniker on the right of it. */
1306 else if (res
==S_OK
){
1308 IMoniker_Inverse(restThisMk
,&invRestThisMk
);
1309 IMoniker_Release(restThisMk
);
1310 CreateGenericComposite(invRestThisMk
,restOtherMk
,ppmkRelPath
);
1311 IMoniker_Release(invRestThisMk
);
1312 IMoniker_Release(restOtherMk
);
1317 /******************************************************************************
1318 * CompositeMoniker_GetDisplayName
1319 ******************************************************************************/
1320 HRESULT WINAPI
CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
,
1322 IMoniker
* pmkToLeft
,
1323 LPOLESTR
*ppszDisplayName
)
1326 IEnumMoniker
*enumMoniker
;
1330 TRACE(ole
,"(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
1332 if (ppszDisplayName
==NULL
)
1335 *ppszDisplayName
=CoTaskMemAlloc(sizeof(WCHAR
));
1337 if (*ppszDisplayName
==NULL
)
1338 return E_OUTOFMEMORY
;
1340 /* This method returns the concatenation of the display names returned by each component moniker of */
1343 **ppszDisplayName
=0;
1345 IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
1347 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
1349 IMoniker_GetDisplayName(tempMk
,pbc
,NULL
,&tempStr
);
1351 lengthStr
+=lstrlenW(tempStr
);
1353 *ppszDisplayName
=CoTaskMemRealloc(*ppszDisplayName
,lengthStr
* sizeof(WCHAR
));
1355 if (*ppszDisplayName
==NULL
)
1356 return E_OUTOFMEMORY
;
1358 lstrcatW(*ppszDisplayName
,tempStr
);
1360 CoTaskMemFree(tempStr
);
1361 IMoniker_Release(tempMk
);
1364 IEnumMoniker_Release(enumMoniker
);
1369 /******************************************************************************
1370 * CompositeMoniker_ParseDisplayName
1371 ******************************************************************************/
1372 HRESULT WINAPI
CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
,
1374 IMoniker
* pmkToLeft
,
1375 LPOLESTR pszDisplayName
,
1379 IEnumMoniker
*enumMoniker
;
1380 IMoniker
*tempMk
,*mostRigthMk
,*antiMk
;
1381 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1382 /* passing everything else as the pmkToLeft parameter for that call. */
1384 /* get the most rigth moniker */
1385 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1386 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1387 IEnumMoniker_Release(enumMoniker
);
1389 /* get the left moniker */
1390 CreateAntiMoniker(&antiMk
);
1391 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1392 IMoniker_Release(antiMk
);
1394 return IMoniker_ParseDisplayName(mostRigthMk
,pbc
,tempMk
,pszDisplayName
,pchEaten
,ppmkOut
);
1397 /******************************************************************************
1398 * CompositeMoniker_IsSystemMonker
1399 ******************************************************************************/
1400 HRESULT WINAPI
CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
1402 TRACE(ole
,"(%p,%p)\n",iface
,pwdMksys
);
1407 (*pwdMksys
)=MKSYS_GENERICCOMPOSITE
;
1412 /*******************************************************************************
1413 * CompositeMonikerIROTData_QueryInterface
1414 *******************************************************************************/
1415 HRESULT WINAPI
CompositeMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,VOID
** ppvObject
)
1418 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1420 TRACE(ole
,"(%p,%p,%p)\n",iface
,riid
,ppvObject
);
1422 return CompositeMonikerImpl_QueryInterface(This
, riid
, ppvObject
);
1425 /***********************************************************************
1426 * CompositeMonikerIROTData_AddRef
1428 ULONG WINAPI
CompositeMonikerROTDataImpl_AddRef(IROTData
*iface
)
1430 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1432 TRACE(ole
,"(%p)\n",iface
);
1434 return CompositeMonikerImpl_AddRef(This
);
1437 /***********************************************************************
1438 * CompositeMonikerIROTData_Release
1440 ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
)
1442 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1444 TRACE(ole
,"(%p)\n",iface
);
1446 return CompositeMonikerImpl_Release(This
);
1449 /******************************************************************************
1450 * CompositeMonikerIROTData_GetComparaisonData
1451 ******************************************************************************/
1452 HRESULT WINAPI
CompositeMonikerROTDataImpl_GetComparaisonData(IROTData
* iface
,
1457 FIXME(ole
,"(),stub!\n");
1461 /******************************************************************************
1462 * EnumMonikerImpl_QueryInterface
1463 ******************************************************************************/
1464 HRESULT WINAPI
EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
)
1466 ICOM_THIS(EnumMonikerImpl
,iface
);
1468 TRACE(ole
,"(%p,%p,%p)\n",This
,riid
,ppvObject
);
1470 /* Perform a sanity check on the parameters.*/
1471 if ( (This
==0) || (ppvObject
==0) )
1472 return E_INVALIDARG
;
1474 /* Initialize the return parameter */
1477 /* Compare the riid with the interface IDs implemented by this object.*/
1478 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IEnumMoniker
, riid
))
1481 /* Check that we obtained an interface.*/
1482 if ((*ppvObject
)==0)
1483 return E_NOINTERFACE
;
1485 /* Query Interface always increases the reference count by one when it is successful */
1486 EnumMonikerImpl_AddRef(iface
);
1491 /******************************************************************************
1492 * EnumMonikerImpl_AddRef
1493 ******************************************************************************/
1494 ULONG WINAPI
EnumMonikerImpl_AddRef(IEnumMoniker
* iface
)
1496 ICOM_THIS(EnumMonikerImpl
,iface
);
1498 TRACE(ole
,"(%p)\n",This
);
1500 return ++(This
->ref
);
1504 /******************************************************************************
1505 * EnumMonikerImpl_Release
1506 ******************************************************************************/
1507 ULONG WINAPI
EnumMonikerImpl_Release(IEnumMoniker
* iface
)
1509 ICOM_THIS(EnumMonikerImpl
,iface
);
1512 TRACE(ole
,"(%p)\n",This
);
1516 /* destroy the object if there's no more reference on it */
1519 for(i
=0;i
<This
->tabSize
;i
++)
1520 IMoniker_Release(This
->tabMoniker
[i
]);
1522 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
1523 HeapFree(GetProcessHeap(),0,This
);
1530 /******************************************************************************
1531 * EnumMonikerImpl_Next
1532 ******************************************************************************/
1533 HRESULT WINAPI
EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
, IMoniker
** rgelt
, ULONG
* pceltFethed
){
1535 ICOM_THIS(EnumMonikerImpl
,iface
);
1538 /* retrieve the requested number of moniker from the current position */
1539 for(i
=0;((This
->currentPos
< This
->tabSize
) && (i
< celt
));i
++)
1541 rgelt
[i
]=This
->tabMoniker
[This
->currentPos
++];
1543 if (pceltFethed
!=NULL
)
1552 /******************************************************************************
1553 * EnumMonikerImpl_Skip
1554 ******************************************************************************/
1555 HRESULT WINAPI
EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
){
1557 ICOM_THIS(EnumMonikerImpl
,iface
);
1559 if ((This
->currentPos
+celt
) >= This
->tabSize
)
1562 This
->currentPos
+=celt
;
1567 /******************************************************************************
1568 * EnumMonikerImpl_Reset
1569 ******************************************************************************/
1570 HRESULT WINAPI
EnumMonikerImpl_Reset(IEnumMoniker
* iface
){
1572 ICOM_THIS(EnumMonikerImpl
,iface
);
1579 /******************************************************************************
1580 * EnumMonikerImpl_Clone
1581 ******************************************************************************/
1582 HRESULT WINAPI
EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
){
1584 ICOM_THIS(EnumMonikerImpl
,iface
);
1586 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabSize
,This
->currentPos
,TRUE
,ppenum
);
1589 /******************************************************************************
1590 * EnumMonikerImpl_CreateEnumMoniker
1591 ******************************************************************************/
1592 HRESULT WINAPI
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,
1596 IEnumMoniker
** ppmk
)
1598 EnumMonikerImpl
* newEnumMoniker
;
1602 newEnumMoniker
= HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl
));
1604 if (newEnumMoniker
== 0)
1605 return STG_E_INSUFFICIENTMEMORY
;
1607 if (currentPos
> tabSize
)
1608 return E_INVALIDARG
;
1610 /* Initialize the virtual function table. */
1611 newEnumMoniker
->lpvtbl
= &VT_EnumMonikerImpl
;
1612 newEnumMoniker
->ref
= 0;
1614 newEnumMoniker
->tabSize
=tabSize
;
1615 newEnumMoniker
->currentPos
=currentPos
;
1617 newEnumMoniker
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,tabSize
*sizeof(IMoniker
));
1619 if (newEnumMoniker
->tabMoniker
==NULL
)
1620 return E_OUTOFMEMORY
;
1623 for (i
=0;i
<tabSize
;i
++){
1625 newEnumMoniker
->tabMoniker
[i
]=tabMoniker
[i
];
1626 IMoniker_AddRef(tabMoniker
[i
]);
1629 for (i
=tabSize
-1;i
>=0;i
--){
1631 newEnumMoniker
->tabMoniker
[tabSize
-i
-1]=tabMoniker
[i
];
1632 IMoniker_AddRef(tabMoniker
[i
]);
1635 *ppmk
=(IEnumMoniker
*)newEnumMoniker
;
1640 /******************************************************************************
1641 * CreateCompositeMoniker [OLE.55]
1642 ******************************************************************************/
1643 HRESULT WINAPI
CreateGenericComposite(LPMONIKER pmkFirst
, LPMONIKER pmkRest
, LPMONIKER
* ppmkComposite
)
1645 CompositeMonikerImpl
* newCompositeMoniker
= 0;
1648 TRACE(ole
,"(%p,%p,%p)\n",pmkFirst
,pmkRest
,ppmkComposite
);
1650 if (ppmkComposite
==NULL
)
1655 if (pmkFirst
==NULL
&& pmkRest
!=NULL
){
1657 *ppmkComposite
=pmkRest
;
1660 else if (pmkFirst
!=NULL
&& pmkRest
==NULL
){
1661 *ppmkComposite
=pmkFirst
;
1664 else if (pmkFirst
==NULL
&& pmkRest
==NULL
)
1667 newCompositeMoniker
= HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl
));
1669 if (newCompositeMoniker
== 0)
1670 return STG_E_INSUFFICIENTMEMORY
;
1672 hr
= CompositeMonikerImpl_Construct(newCompositeMoniker
,pmkFirst
,pmkRest
);
1676 HeapFree(GetProcessHeap(),0,newCompositeMoniker
);
1679 if (newCompositeMoniker
->tabLastIndex
==1)
1681 hr
= IMoniker_QueryInterface(newCompositeMoniker
->tabMoniker
[0],&IID_IMoniker
,(void**)ppmkComposite
);
1684 hr
= CompositeMonikerImpl_QueryInterface((IMoniker
*)newCompositeMoniker
,&IID_IMoniker
,(void**)ppmkComposite
);
1689 /******************************************************************************
1690 * MonikerCommonPrefixWith [OLE.55]
1691 ******************************************************************************/
1692 HRESULT WINAPI
MonikerCommonPrefixWith(IMoniker
* pmkThis
,IMoniker
* pmkOther
,IMoniker
** ppmkCommon
)
1694 FIXME(ole
,"(),stub!\n");