1 /***************************************************************************************
2 * CompositeMonikers implementation
4 * Copyright 1999 Noomen Hamza
5 ***************************************************************************************/
9 #include "debugtools.h"
10 #include "wine/obj_inplace.h"
11 #include "wine/unicode.h"
14 DEFAULT_DEBUG_CHANNEL(ole
);
16 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
18 /* CompositeMoniker data structure */
19 typedef struct CompositeMonikerImpl
{
21 ICOM_VTABLE(IMoniker
)* lpvtbl1
; /* VTable relative to the IMoniker interface.*/
23 /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
24 * two monikers are equal. That's whay IROTData interface is implemented by monikers.
26 ICOM_VTABLE(IROTData
)* lpvtbl2
; /* VTable relative to the IROTData interface.*/
28 ULONG ref
; /* reference counter for this object */
30 IMoniker
** tabMoniker
; /* dynamaic table containing all components (monikers) of this composite moniker */
32 ULONG tabSize
; /* size of tabMoniker */
34 ULONG tabLastIndex
; /* first free index in tabMoniker */
36 } CompositeMonikerImpl
;
39 /* EnumMoniker data structure */
40 typedef struct EnumMonikerImpl
{
42 ICOM_VFIELD(IEnumMoniker
); /* VTable relative to the IEnumMoniker interface.*/
44 ULONG ref
; /* reference counter for this object */
46 IMoniker
** tabMoniker
; /* dynamic table containing the enumerated monikers */
48 ULONG tabSize
; /* size of tabMoniker */
50 ULONG currentPos
; /* index pointer on the current moniker */
55 /********************************************************************************/
56 /* CompositeMoniker prototype functions : */
58 /* IUnknown prototype functions */
59 static HRESULT WINAPI
CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
);
60 static ULONG WINAPI
CompositeMonikerImpl_AddRef(IMoniker
* iface
);
61 static ULONG WINAPI
CompositeMonikerImpl_Release(IMoniker
* iface
);
63 /* IPersist prototype functions */
64 static HRESULT WINAPI
CompositeMonikerImpl_GetClassID(IMoniker
* iface
, CLSID
*pClassID
);
66 /* IPersistStream prototype functions */
67 static HRESULT WINAPI
CompositeMonikerImpl_IsDirty(IMoniker
* iface
);
68 static HRESULT WINAPI
CompositeMonikerImpl_Load(IMoniker
* iface
, IStream
* pStm
);
69 static HRESULT WINAPI
CompositeMonikerImpl_Save(IMoniker
* iface
, IStream
* pStm
, BOOL fClearDirty
);
70 static HRESULT WINAPI
CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
, ULARGE_INTEGER
* pcbSize
);
72 /* IMoniker prototype functions */
73 static HRESULT WINAPI
CompositeMonikerImpl_BindToObject(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
);
74 static HRESULT WINAPI
CompositeMonikerImpl_BindToStorage(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
);
75 static HRESULT WINAPI
CompositeMonikerImpl_Reduce(IMoniker
* iface
,IBindCtx
* pbc
, DWORD dwReduceHowFar
,IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
);
76 static HRESULT WINAPI
CompositeMonikerImpl_ComposeWith(IMoniker
* iface
,IMoniker
* pmkRight
,BOOL fOnlyIfNotGeneric
, IMoniker
** ppmkComposite
);
77 static HRESULT WINAPI
CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
);
78 static HRESULT WINAPI
CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
);
79 static HRESULT WINAPI
CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
);
80 static HRESULT WINAPI
CompositeMonikerImpl_IsRunning(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, IMoniker
* pmkNewlyRunning
);
81 static HRESULT WINAPI
CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
, FILETIME
* pCompositeTime
);
82 static HRESULT WINAPI
CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
);
83 static HRESULT WINAPI
CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
, IMoniker
** ppmkPrefix
);
84 static HRESULT WINAPI
CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmOther
, IMoniker
** ppmkRelPath
);
85 static HRESULT WINAPI
CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
);
86 static HRESULT WINAPI
CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
* pchEaten
, IMoniker
** ppmkOut
);
87 static HRESULT WINAPI
CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
);
89 /********************************************************************************/
90 /* IROTData prototype functions */
92 /* IUnknown prototype functions */
93 static HRESULT WINAPI
CompositeMonikerROTDataImpl_QueryInterface(IROTData
* iface
,REFIID riid
,VOID
** ppvObject
);
94 static ULONG WINAPI
CompositeMonikerROTDataImpl_AddRef(IROTData
* iface
);
95 static ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
);
97 /* IROTData prototype function */
98 static HRESULT WINAPI
CompositeMonikerROTDataImpl_GetComparaisonData(IROTData
* iface
,BYTE
* pbData
,ULONG cbMax
,ULONG
* pcbData
);
100 /* Local function used by CompositeMoniker implementation */
101 HRESULT WINAPI
CompositeMonikerImpl_Construct(CompositeMonikerImpl
* This
,LPMONIKER pmkFirst
, LPMONIKER pmkRest
);
102 HRESULT WINAPI
CompositeMonikerImpl_Destroy(CompositeMonikerImpl
* iface
);
104 /********************************************************************************/
105 /* IEnumMoniker prototype functions */
107 /* IUnknown prototype functions */
108 static HRESULT WINAPI
EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
);
109 static ULONG WINAPI
EnumMonikerImpl_AddRef(IEnumMoniker
* iface
);
110 static ULONG WINAPI
EnumMonikerImpl_Release(IEnumMoniker
* iface
);
112 /* IEnumMonker prototype functions */
113 static HRESULT WINAPI
EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
,IMoniker
** rgelt
,ULONG
* pceltFetched
);
114 static HRESULT WINAPI
EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
);
115 static HRESULT WINAPI
EnumMonikerImpl_Reset(IEnumMoniker
* iface
);
116 static HRESULT WINAPI
EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
);
118 HRESULT WINAPI
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,ULONG tabSize
,ULONG currentPos
,BOOL leftToRigth
,IEnumMoniker
** ppmk
);
120 /********************************************************************************/
121 /* Virtual function table for the CompositeMonikerImpl class witch include */
122 /* Ipersist, IPersistStream and IMoniker functions. */
124 static ICOM_VTABLE(IMoniker
) VT_CompositeMonikerImpl
=
126 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
127 CompositeMonikerImpl_QueryInterface
,
128 CompositeMonikerImpl_AddRef
,
129 CompositeMonikerImpl_Release
,
130 CompositeMonikerImpl_GetClassID
,
131 CompositeMonikerImpl_IsDirty
,
132 CompositeMonikerImpl_Load
,
133 CompositeMonikerImpl_Save
,
134 CompositeMonikerImpl_GetSizeMax
,
135 CompositeMonikerImpl_BindToObject
,
136 CompositeMonikerImpl_BindToStorage
,
137 CompositeMonikerImpl_Reduce
,
138 CompositeMonikerImpl_ComposeWith
,
139 CompositeMonikerImpl_Enum
,
140 CompositeMonikerImpl_IsEqual
,
141 CompositeMonikerImpl_Hash
,
142 CompositeMonikerImpl_IsRunning
,
143 CompositeMonikerImpl_GetTimeOfLastChange
,
144 CompositeMonikerImpl_Inverse
,
145 CompositeMonikerImpl_CommonPrefixWith
,
146 CompositeMonikerImpl_RelativePathTo
,
147 CompositeMonikerImpl_GetDisplayName
,
148 CompositeMonikerImpl_ParseDisplayName
,
149 CompositeMonikerImpl_IsSystemMoniker
152 /********************************************************************************/
153 /* Virtual function table for the IROTData class. */
154 static ICOM_VTABLE(IROTData
) VT_ROTDataImpl
=
156 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
157 CompositeMonikerROTDataImpl_QueryInterface
,
158 CompositeMonikerROTDataImpl_AddRef
,
159 CompositeMonikerROTDataImpl_Release
,
160 CompositeMonikerROTDataImpl_GetComparaisonData
163 /********************************************************************************/
164 /* Virtual function table for the IROTData class */
165 static ICOM_VTABLE(IEnumMoniker
) VT_EnumMonikerImpl
=
167 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
168 EnumMonikerImpl_QueryInterface
,
169 EnumMonikerImpl_AddRef
,
170 EnumMonikerImpl_Release
,
171 EnumMonikerImpl_Next
,
172 EnumMonikerImpl_Skip
,
173 EnumMonikerImpl_Reset
,
174 EnumMonikerImpl_Clone
177 /*******************************************************************************
178 * CompositeMoniker_QueryInterface
179 *******************************************************************************/
180 HRESULT WINAPI
CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
182 ICOM_THIS(CompositeMonikerImpl
,iface
);
184 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
186 /* Perform a sanity check on the parameters.*/
187 if ( (This
==0) || (ppvObject
==0) )
190 /* Initialize the return parameter */
193 /* Compare the riid with the interface IDs implemented by this object.*/
194 if (IsEqualIID(&IID_IUnknown
, riid
) ||
195 IsEqualIID(&IID_IPersist
, riid
) ||
196 IsEqualIID(&IID_IPersistStream
, riid
) ||
197 IsEqualIID(&IID_IMoniker
, riid
)
200 else if (IsEqualIID(&IID_IROTData
, riid
))
201 *ppvObject
= (IROTData
*)&(This
->lpvtbl2
);
203 /* Check that we obtained an interface.*/
205 return E_NOINTERFACE
;
207 /* Query Interface always increases the reference count by one when it is successful */
208 CompositeMonikerImpl_AddRef(iface
);
213 /******************************************************************************
214 * CompositeMoniker_AddRef
215 ******************************************************************************/
216 ULONG WINAPI
CompositeMonikerImpl_AddRef(IMoniker
* iface
)
218 ICOM_THIS(CompositeMonikerImpl
,iface
);
220 TRACE("(%p)\n",This
);
222 return ++(This
->ref
);
225 /******************************************************************************
226 * CompositeMoniker_Release
227 ******************************************************************************/
228 ULONG WINAPI
CompositeMonikerImpl_Release(IMoniker
* iface
)
230 ICOM_THIS(CompositeMonikerImpl
,iface
);
233 TRACE("(%p)\n",This
);
237 /* destroy the object if there's no more reference on it */
240 /* release all the components before destroying this object */
241 for (i
=0;i
<This
->tabLastIndex
;i
++)
242 IMoniker_Release(This
->tabMoniker
[i
]);
244 CompositeMonikerImpl_Destroy(This
);
251 /******************************************************************************
252 * CompositeMoniker_GetClassID
253 ******************************************************************************/
254 HRESULT WINAPI
CompositeMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
256 TRACE("(%p,%p),stub!\n",iface
,pClassID
);
261 *pClassID
= CLSID_CompositeMoniker
;
266 /******************************************************************************
267 * CompositeMoniker_IsDirty
268 ******************************************************************************/
269 HRESULT WINAPI
CompositeMonikerImpl_IsDirty(IMoniker
* iface
)
271 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
272 method in the OLE-provided moniker interfaces always return S_FALSE because
273 their internal state never changes. */
275 TRACE("(%p)\n",iface
);
280 /******************************************************************************
281 * CompositeMoniker_Load
282 ******************************************************************************/
283 HRESULT WINAPI
CompositeMonikerImpl_Load(IMoniker
* iface
,IStream
* pStm
)
290 ICOM_THIS(CompositeMonikerImpl
,iface
);
292 TRACE("(%p,%p)\n",iface
,pStm
);
294 /* this function call OleLoadFromStream function for each moniker within this object */
296 /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
297 res
=IStream_Read(pStm
,&constant
,sizeof(DWORD
),NULL
);
299 if (SUCCEEDED(res
)&& constant
!=3)
304 res
=OleLoadFromStream(pStm
,&IID_IMoniker
,(void**)&This
->tabMoniker
[This
->tabLastIndex
]);
306 res
=ReadClassStm(pStm
,&clsid
);
307 DPRINTF("res=%ld",res
);
311 if (IsEqualIID(&clsid
,&CLSID_FileMoniker
)){
312 res
=CreateFileMoniker(string
,&This
->tabMoniker
[This
->tabLastIndex
]);
315 res
=IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
319 else if (IsEqualIID(&clsid
,&CLSID_ItemMoniker
)){
320 CreateItemMoniker(string
,string
,&This
->tabMoniker
[This
->tabLastIndex
]);
323 IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
327 else if (IsEqualIID(&clsid
,&CLSID_AntiMoniker
)){
328 CreateAntiMoniker(&This
->tabMoniker
[This
->tabLastIndex
]);
331 IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
335 else if (IsEqualIID(&clsid
,&CLSID_CompositeMoniker
))
344 /* resize the table if needed */
345 if (++This
->tabLastIndex
==This
->tabSize
){
347 This
->tabSize
+=BLOCK_TAB_SIZE
;
348 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
350 if (This
->tabMoniker
==NULL
)
351 return E_OUTOFMEMORY
;
358 /******************************************************************************
359 * CompositeMoniker_Save
360 ******************************************************************************/
361 HRESULT WINAPI
CompositeMonikerImpl_Save(IMoniker
* iface
,IStream
* pStm
,BOOL fClearDirty
)
364 IEnumMoniker
*enumMk
;
368 TRACE("(%p,%p,%d)\n",iface
,pStm
,fClearDirty
);
370 /* this function call OleSaveToStream function for each moniker within this object */
372 /* when I tested this function in windows system ! I usually found this constant in the begining of */
373 /* the stream I dont known why (there's no indication in specification) ! */
374 res
=IStream_Write(pStm
,&constant
,sizeof(constant
),NULL
);
376 IMoniker_Enum(iface
,TRUE
,&enumMk
);
378 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
380 res
=OleSaveToStream((IPersistStream
*)pmk
,pStm
);
382 IMoniker_Release(pmk
);
386 IEnumMoniker_Release(pmk
);
391 IEnumMoniker_Release(enumMk
);
396 /******************************************************************************
397 * CompositeMoniker_GetSizeMax
398 ******************************************************************************/
399 HRESULT WINAPI
CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
,ULARGE_INTEGER
* pcbSize
)
401 IEnumMoniker
*enumMk
;
403 ULARGE_INTEGER ptmpSize
;
405 /* the sizeMax of this object is calculated by calling GetSizeMax on each moniker within this object then */
406 /* suming all returned sizemax */
408 TRACE("(%p,%p)\n",iface
,pcbSize
);
413 pcbSize
->s
.LowPart
=0;
414 pcbSize
->s
.HighPart
=0;
416 IMoniker_Enum(iface
,TRUE
,&enumMk
);
418 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==TRUE
){
420 IMoniker_GetSizeMax(pmk
,&ptmpSize
);
422 IMoniker_Release(pmk
);
424 pcbSize
->s
.LowPart
+=ptmpSize
.s
.LowPart
;
425 pcbSize
->s
.HighPart
+=ptmpSize
.s
.HighPart
;
428 IEnumMoniker_Release(enumMk
);
433 /******************************************************************************
434 * Composite-Moniker_Construct (local function)
435 *******************************************************************************/
436 HRESULT WINAPI
CompositeMonikerImpl_Construct(CompositeMonikerImpl
* This
,LPMONIKER pmkFirst
, LPMONIKER pmkRest
)
439 IEnumMoniker
*enumMoniker
;
443 TRACE("(%p,%p,%p)\n",This
,pmkFirst
,pmkRest
);
445 /* Initialize the virtual fgunction table. */
446 This
->lpvtbl1
= &VT_CompositeMonikerImpl
;
447 This
->lpvtbl2
= &VT_ROTDataImpl
;
450 This
->tabSize
=BLOCK_TAB_SIZE
;
451 This
->tabLastIndex
=0;
453 This
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,This
->tabSize
*sizeof(IMoniker
));
454 if (This
->tabMoniker
==NULL
)
455 return E_OUTOFMEMORY
;
457 IMoniker_IsSystemMoniker(pmkFirst
,&mkSys
);
459 /* put the first moniker contents in the begining of the table */
460 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
462 This
->tabMoniker
[(This
->tabLastIndex
)++]=pmkFirst
;
463 IMoniker_AddRef(pmkFirst
);
467 IMoniker_Enum(pmkFirst
,TRUE
,&enumMoniker
);
469 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
472 if (++This
->tabLastIndex
==This
->tabSize
){
474 This
->tabSize
+=BLOCK_TAB_SIZE
;
475 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
477 if (This
->tabMoniker
==NULL
)
478 return E_OUTOFMEMORY
;
482 IEnumMoniker_Release(enumMoniker
);
485 /* put the rest moniker contents after the first one and make simplification if needed */
487 IMoniker_IsSystemMoniker(pmkRest
,&mkSys
);
489 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
491 /* add a simple moniker to the moniker table */
493 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],pmkRest
,TRUE
,&tempMk
);
495 if (res
==MK_E_NEEDGENERIC
){
497 /* there's no simplification in this case */
498 This
->tabMoniker
[This
->tabLastIndex
]=pmkRest
;
500 This
->tabLastIndex
++;
502 IMoniker_AddRef(pmkRest
);
504 else if (tempMk
==NULL
){
506 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
507 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
509 This
->tabLastIndex
--;
511 else if (SUCCEEDED(res
)){
513 /* the non-generic composition was successful so we can make a simplification in this case */
514 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
516 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
520 /* resize tabMoniker if needed */
521 if (This
->tabLastIndex
==This
->tabSize
){
523 This
->tabSize
+=BLOCK_TAB_SIZE
;
525 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
527 if (This
->tabMoniker
==NULL
)
528 return E_OUTOFMEMORY
;
533 /* add a composite moniker to the moniker table (do the same thing for each moniker within the */
534 /* composite moniker as a simple moniker (see above how to add a simple moniker case) ) */
535 IMoniker_Enum(pmkRest
,TRUE
,&enumMoniker
);
537 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
539 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],This
->tabMoniker
[This
->tabLastIndex
],TRUE
,&tempMk
);
541 if (res
==MK_E_NEEDGENERIC
){
543 This
->tabLastIndex
++;
545 else if (tempMk
==NULL
){
547 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
548 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
]);
549 This
->tabLastIndex
--;
553 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
555 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
558 if (This
->tabLastIndex
==This
->tabSize
){
560 This
->tabSize
+=BLOCK_TAB_SIZE
;
562 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
564 if (This
->tabMoniker
==NULL
)
565 return E_OUTOFMEMORY
;
569 IEnumMoniker_Release(enumMoniker
);
575 /******************************************************************************
576 * CompositeMoniker_Destroy (local function)
577 *******************************************************************************/
578 HRESULT WINAPI
CompositeMonikerImpl_Destroy(CompositeMonikerImpl
* This
)
580 TRACE("(%p)\n",This
);
582 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
584 HeapFree(GetProcessHeap(),0,This
);
589 /******************************************************************************
590 * CompositeMoniker_BindToObject
591 ******************************************************************************/
592 HRESULT WINAPI
CompositeMonikerImpl_BindToObject(IMoniker
* iface
,
599 IRunningObjectTable
*prot
;
600 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
601 IEnumMoniker
*enumMoniker
;
603 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
609 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
610 /* object for the requested interface pointer. */
613 res
=IBindCtx_GetRunningObjectTable(pbc
,&prot
);
617 /* if the requested class was loaded befor ! we dont need to reload it */
618 res
= IRunningObjectTable_GetObject(prot
,iface
,(IUnknown
**)ppvResult
);
625 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
626 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
628 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
629 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
630 IEnumMoniker_Release(enumMoniker
);
632 res
=CreateAntiMoniker(&antiMk
);
633 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
634 IMoniker_Release(antiMk
);
636 res
=CompositeMonikerImpl_BindToObject(mostRigthMk
,pbc
,tempMk
,riid
,ppvResult
);
638 IMoniker_Release(tempMk
);
639 IMoniker_Release(mostRigthMk
);
645 /******************************************************************************
646 * CompositeMoniker_BindToStorage
647 ******************************************************************************/
648 HRESULT WINAPI
CompositeMonikerImpl_BindToStorage(IMoniker
* iface
,
655 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
656 IEnumMoniker
*enumMoniker
;
658 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
662 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
663 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
665 if (pmkToLeft
!=NULL
){
667 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
668 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
669 IEnumMoniker_Release(enumMoniker
);
671 res
=CreateAntiMoniker(&antiMk
);
672 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
673 IMoniker_Release(antiMk
);
675 res
=CompositeMonikerImpl_BindToStorage(mostRigthMk
,pbc
,tempMk
,riid
,ppvResult
);
677 IMoniker_Release(tempMk
);
679 IMoniker_Release(mostRigthMk
);
684 return IMoniker_BindToStorage(iface
,pbc
,NULL
,riid
,ppvResult
);
687 /******************************************************************************
688 * CompositeMoniker_Reduce
689 ******************************************************************************/
690 HRESULT WINAPI
CompositeMonikerImpl_Reduce(IMoniker
* iface
,
692 DWORD dwReduceHowFar
,
693 IMoniker
** ppmkToLeft
,
694 IMoniker
** ppmkReduced
)
697 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*leftReducedComposedMk
,*mostRigthReducedMk
;
698 IEnumMoniker
*enumMoniker
;
700 TRACE("(%p,%p,%ld,%p,%p)\n",iface
,pbc
,dwReduceHowFar
,ppmkToLeft
,ppmkReduced
);
702 if (ppmkReduced
==NULL
)
705 /* This method recursively calls Reduce for each of its component monikers. */
707 if (ppmkToLeft
==NULL
){
709 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
710 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
711 IEnumMoniker_Release(enumMoniker
);
713 res
=CreateAntiMoniker(&antiMk
);
714 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
715 IMoniker_Release(antiMk
);
717 return CompositeMonikerImpl_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
, ppmkReduced
);
719 else if (*ppmkToLeft
==NULL
)
721 return IMoniker_Reduce(iface
,pbc
,dwReduceHowFar
,NULL
,ppmkReduced
);
725 /* separate the copmosite moniker in to left and wrigth moniker */
726 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
727 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
728 IEnumMoniker_Release(enumMoniker
);
730 res
=CreateAntiMoniker(&antiMk
);
731 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
732 IMoniker_Release(antiMk
);
734 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
735 /* of the reduced components */
736 if (IMoniker_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,NULL
,&mostRigthReducedMk
) &&
737 CompositeMonikerImpl_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
,&leftReducedComposedMk
)
740 return CreateGenericComposite(leftReducedComposedMk
,mostRigthReducedMk
,ppmkReduced
);
743 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
745 IMoniker_AddRef(iface
);
749 return MK_S_REDUCED_TO_SELF
;
754 /******************************************************************************
755 * CompositeMoniker_ComposeWith
756 ******************************************************************************/
757 HRESULT WINAPI
CompositeMonikerImpl_ComposeWith(IMoniker
* iface
,
759 BOOL fOnlyIfNotGeneric
,
760 IMoniker
** ppmkComposite
)
762 TRACE("(%p,%p,%d,%p)\n",iface
,pmkRight
,fOnlyIfNotGeneric
,ppmkComposite
);
764 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
769 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
770 /* otherwise, the method returns the result of combining the two monikers by calling the */
771 /* CreateGenericComposite function */
773 if (fOnlyIfNotGeneric
)
774 return MK_E_NEEDGENERIC
;
776 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
779 /******************************************************************************
780 * CompositeMoniker_Enum
781 ******************************************************************************/
782 HRESULT WINAPI
CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
784 ICOM_THIS(CompositeMonikerImpl
,iface
);
786 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
788 if (ppenumMoniker
== NULL
)
791 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabLastIndex
,0,fForward
,ppenumMoniker
);
794 /******************************************************************************
795 * CompositeMoniker_IsEqual
796 ******************************************************************************/
797 HRESULT WINAPI
CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
)
799 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
800 IMoniker
*tempMk1
,*tempMk2
;
801 HRESULT res1
,res2
,res
;
803 TRACE("(%p,%p)\n",iface
,pmkOtherMoniker
);
805 if (pmkOtherMoniker
==NULL
)
808 /* This method returns S_OK if the components of both monikers are equal when compared in the */
809 /* left-to-right order.*/
810 IMoniker_Enum(pmkOtherMoniker
,TRUE
,&enumMoniker1
);
812 if (enumMoniker1
==NULL
)
815 IMoniker_Enum(iface
,TRUE
,&enumMoniker2
);
819 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
820 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
822 if((res1
==S_OK
)&&(res2
==S_OK
)){
824 if(IMoniker_IsEqual(tempMk1
,tempMk2
)==S_FALSE
){
831 else if ( (res1
==S_FALSE
) && (res2
==S_FALSE
) ){
841 IMoniker_Release(tempMk1
);
844 IMoniker_Release(tempMk2
);
847 IEnumMoniker_Release(enumMoniker1
);
848 IEnumMoniker_Release(enumMoniker2
);
852 /******************************************************************************
853 * CompositeMoniker_Hash
854 ******************************************************************************/
855 HRESULT WINAPI
CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
862 /******************************************************************************
863 * CompositeMoniker_IsRunning
864 ******************************************************************************/
865 HRESULT WINAPI
CompositeMonikerImpl_IsRunning(IMoniker
* iface
,
868 IMoniker
* pmkNewlyRunning
)
870 IRunningObjectTable
* rot
;
872 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
873 IEnumMoniker
*enumMoniker
;
875 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
877 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
878 if (pmkToLeft
!=NULL
){
880 CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
882 res
= IMoniker_IsRunning(tempMk
,pbc
,NULL
,pmkNewlyRunning
);
884 IMoniker_Release(tempMk
);
889 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
890 /* to this moniker */
892 if (pmkNewlyRunning
!=NULL
)
894 if (IMoniker_IsEqual(iface
,pmkNewlyRunning
)==S_OK
)
905 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
906 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
907 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
908 /* the composite as the pmkToLeft parameter for that call. */
910 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
915 res
= IRunningObjectTable_IsRunning(rot
,iface
);
916 IRunningObjectTable_Release(rot
);
923 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
924 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
925 IEnumMoniker_Release(enumMoniker
);
927 res
=CreateAntiMoniker(&antiMk
);
928 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
929 IMoniker_Release(antiMk
);
931 res
=IMoniker_IsRunning(mostRigthMk
,pbc
,tempMk
,pmkNewlyRunning
);
933 IMoniker_Release(tempMk
);
934 IMoniker_Release(mostRigthMk
);
941 /******************************************************************************
942 * CompositeMoniker_GetTimeOfLastChange
943 ******************************************************************************/
944 HRESULT WINAPI
CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
,
947 FILETIME
* pCompositeTime
)
949 IRunningObjectTable
* rot
;
951 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
952 IEnumMoniker
*enumMoniker
;
954 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pCompositeTime
);
956 if (pCompositeTime
==NULL
)
959 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
960 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
961 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
962 /* of the composite as the pmkToLeft parameter for that call. */
963 if (pmkToLeft
!=NULL
){
965 res
=CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
967 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
972 if (IRunningObjectTable_GetTimeOfLastChange(rot
,tempMk
,pCompositeTime
)==S_OK
)
976 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
977 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
978 IEnumMoniker_Release(enumMoniker
);
980 res
=CreateAntiMoniker(&antiMk
);
981 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
982 IMoniker_Release(antiMk
);
984 res
=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk
,pbc
,tempMk
,pCompositeTime
);
986 IMoniker_Release(tempMk
);
987 IMoniker_Release(mostRigthMk
);
992 return IMoniker_GetTimeOfLastChange(iface
,pbc
,NULL
,pCompositeTime
);
995 /******************************************************************************
996 * CompositeMoniker_Inverse
997 ******************************************************************************/
998 HRESULT WINAPI
CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
1001 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*tempInvMk
,*mostRigthInvMk
;
1002 IEnumMoniker
*enumMoniker
;
1004 TRACE("(%p,%p)\n",iface
,ppmk
);
1009 /* This method returns a composite moniker that consists of the inverses of each of the components */
1010 /* of the original composite, stored in reverse order */
1012 res
=CreateAntiMoniker(&antiMk
);
1013 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1014 IMoniker_Release(antiMk
);
1018 return IMoniker_Inverse(iface
,ppmk
);
1022 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1023 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1024 IEnumMoniker_Release(enumMoniker
);
1026 IMoniker_Inverse(mostRigthMk
,&mostRigthInvMk
);
1027 CompositeMonikerImpl_Inverse(tempMk
,&tempInvMk
);
1029 res
=CreateGenericComposite(mostRigthInvMk
,tempInvMk
,ppmk
);
1031 IMoniker_Release(tempMk
);
1032 IMoniker_Release(mostRigthMk
);
1033 IMoniker_Release(tempInvMk
);
1034 IMoniker_Release(mostRigthInvMk
);
1040 /******************************************************************************
1041 * CompositeMoniker_CommonPrefixWith
1042 ******************************************************************************/
1043 HRESULT WINAPI
CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
,IMoniker
** ppmkPrefix
)
1047 IMoniker
*tempMk1
,*tempMk2
,*mostLeftMk1
,*mostLeftMk2
;
1048 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
1049 ULONG i
,nbCommonMk
=0;
1051 /* If the other moniker is a composite, this method compares the components of each composite from left */
1052 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1053 /* of the leftmost components were common to both monikers. */
1055 if (ppmkPrefix
==NULL
)
1061 return MK_E_NOPREFIX
;
1063 IMoniker_IsSystemMoniker(pmkOther
,&mkSys
);
1065 if((mkSys
==MKSYS_GENERICCOMPOSITE
)){
1067 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
1068 IMoniker_Enum(pmkOther
,TRUE
,&enumMoniker2
);
1072 res1
=IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
1073 res2
=IEnumMoniker_Next(enumMoniker2
,1,&mostLeftMk2
,NULL
);
1075 if ((res1
==S_FALSE
) && (res2
==S_FALSE
)){
1077 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1079 IMoniker_AddRef(iface
);
1082 else if ((res1
==S_OK
) && (res2
==S_OK
)){
1084 if (IMoniker_IsEqual(mostLeftMk1
,mostLeftMk2
)==S_OK
)
1092 else if (res1
==S_OK
){
1094 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1095 /* ppmkPrefix to the other moniker. */
1096 *ppmkPrefix
=pmkOther
;
1100 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1101 /* to this moniker. */
1107 IEnumMoniker_Release(enumMoniker1
);
1108 IEnumMoniker_Release(enumMoniker2
);
1110 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1112 return MK_E_NOPREFIX
;
1114 IEnumMoniker_Reset(enumMoniker1
);
1116 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1118 /* if we have more than one commun moniker the result will be a composite moniker */
1121 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1122 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1123 CreateGenericComposite(tempMk1
,tempMk2
,ppmkPrefix
);
1124 IMoniker_Release(tempMk1
);
1125 IMoniker_Release(tempMk2
);
1127 /* compose all common monikers in a composite moniker */
1128 for(i
=0;i
<nbCommonMk
;i
++){
1130 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1132 CreateGenericComposite(*ppmkPrefix
,tempMk1
,&tempMk2
);
1134 IMoniker_Release(*ppmkPrefix
);
1136 IMoniker_Release(tempMk1
);
1138 *ppmkPrefix
=tempMk2
;
1143 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1144 *ppmkPrefix
=tempMk1
;
1150 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1153 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
1155 IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
1157 if (IMoniker_IsEqual(pmkOther
,mostLeftMk1
)==S_OK
){
1159 *ppmkPrefix
=pmkOther
;
1164 return MK_E_NOPREFIX
;
1167 /***************************************************************************************************
1168 * GetAfterCommonPrefix (local function)
1169 * This function returns a moniker that consist of the remainder when the common prefix is removed
1170 ***************************************************************************************************/
1171 VOID WINAPI
GetAfterCommonPrefix(IMoniker
* pGenMk
,IMoniker
* commonMk
,IMoniker
** restMk
)
1173 IMoniker
*tempMk
,*tempMk1
,*tempMk2
;
1174 IEnumMoniker
*enumMoniker1
,*enumMoniker2
,*enumMoniker3
;
1181 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1182 /* prefix: enum the two monikers (left-wrigth) then compare these enumerations (left-wrigth) and stop */
1183 /* on the first difference. */
1184 IMoniker_Enum(pGenMk
,TRUE
,&enumMoniker1
);
1186 IMoniker_IsSystemMoniker(commonMk
,&mkSys
);
1188 if (mkSys
==MKSYS_GENERICCOMPOSITE
){
1190 IMoniker_Enum(commonMk
,TRUE
,&enumMoniker2
);
1193 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1194 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
1196 if ((res1
==S_FALSE
)||(res2
==S_FALSE
)){
1202 IMoniker_Release(tempMk1
);
1203 IMoniker_Release(tempMk1
);
1207 IMoniker_Release(tempMk1
);
1208 IMoniker_Release(tempMk1
);
1212 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1213 IMoniker_Release(tempMk1
);
1216 /* count the number of elements in the enumerator after the common prefix */
1217 IEnumMoniker_Clone(enumMoniker1
,&enumMoniker3
);
1219 for(;IEnumMoniker_Next(enumMoniker3
,1,&tempMk
,NULL
)==S_OK
;nbRestMk
++)
1221 IMoniker_Release(tempMk
);;
1226 /* create a generic composite moniker with monikers located after the common prefix */
1227 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1236 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1238 CreateGenericComposite(tempMk1
,tempMk2
,restMk
);
1240 IMoniker_Release(tempMk1
);
1242 IMoniker_Release(tempMk2
);
1244 while(IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
)==S_OK
){
1246 CreateGenericComposite(*restMk
,tempMk1
,&tempMk2
);
1248 IMoniker_Release(tempMk1
);
1250 IMoniker_Release(*restMk
);
1256 /******************************************************************************
1257 * CompositeMoniker_RelativePathTo
1258 ******************************************************************************/
1259 HRESULT WINAPI
CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmkOther
, IMoniker
** ppmkRelPath
)
1262 IMoniker
*restOtherMk
=0,*restThisMk
=0,*invRestThisMk
=0,*commonMk
=0;
1264 TRACE("(%p,%p,%p)\n",iface
,pmkOther
,ppmkRelPath
);
1266 if (ppmkRelPath
==NULL
)
1271 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1272 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1273 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1275 /* finds the common prefix of the two monikers */
1276 res
=IMoniker_CommonPrefixWith(iface
,pmkOther
,&commonMk
);
1278 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1279 if ((res
== MK_E_NOPREFIX
)||(res
==MK_S_US
)){
1281 *ppmkRelPath
=pmkOther
;
1282 IMoniker_AddRef(pmkOther
);
1286 GetAfterCommonPrefix(iface
,commonMk
,&restThisMk
);
1287 GetAfterCommonPrefix(pmkOther
,commonMk
,&restOtherMk
);
1289 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1290 /* moniker when the common prefix is removed */
1293 IMoniker_Inverse(restThisMk
,ppmkRelPath
);
1294 IMoniker_Release(restThisMk
);
1296 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1297 /* when the common prefix is removed */
1298 else if (res
==MK_S_ME
){
1300 *ppmkRelPath
=restOtherMk
;
1301 IMoniker_AddRef(restOtherMk
);
1303 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1304 /* moniker on the right of it. */
1305 else if (res
==S_OK
){
1307 IMoniker_Inverse(restThisMk
,&invRestThisMk
);
1308 IMoniker_Release(restThisMk
);
1309 CreateGenericComposite(invRestThisMk
,restOtherMk
,ppmkRelPath
);
1310 IMoniker_Release(invRestThisMk
);
1311 IMoniker_Release(restOtherMk
);
1316 /******************************************************************************
1317 * CompositeMoniker_GetDisplayName
1318 ******************************************************************************/
1319 HRESULT WINAPI
CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
,
1321 IMoniker
* pmkToLeft
,
1322 LPOLESTR
*ppszDisplayName
)
1325 IEnumMoniker
*enumMoniker
;
1329 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
1331 if (ppszDisplayName
==NULL
)
1334 *ppszDisplayName
=CoTaskMemAlloc(sizeof(WCHAR
));
1336 if (*ppszDisplayName
==NULL
)
1337 return E_OUTOFMEMORY
;
1339 /* This method returns the concatenation of the display names returned by each component moniker of */
1342 **ppszDisplayName
=0;
1344 IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
1346 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
1348 IMoniker_GetDisplayName(tempMk
,pbc
,NULL
,&tempStr
);
1350 lengthStr
+=lstrlenW(tempStr
);
1352 *ppszDisplayName
=CoTaskMemRealloc(*ppszDisplayName
,lengthStr
* sizeof(WCHAR
));
1354 if (*ppszDisplayName
==NULL
)
1355 return E_OUTOFMEMORY
;
1357 strcatW(*ppszDisplayName
,tempStr
);
1359 CoTaskMemFree(tempStr
);
1360 IMoniker_Release(tempMk
);
1363 IEnumMoniker_Release(enumMoniker
);
1368 /******************************************************************************
1369 * CompositeMoniker_ParseDisplayName
1370 ******************************************************************************/
1371 HRESULT WINAPI
CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
,
1373 IMoniker
* pmkToLeft
,
1374 LPOLESTR pszDisplayName
,
1378 IEnumMoniker
*enumMoniker
;
1379 IMoniker
*tempMk
,*mostRigthMk
,*antiMk
;
1380 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1381 /* passing everything else as the pmkToLeft parameter for that call. */
1383 /* get the most rigth moniker */
1384 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1385 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1386 IEnumMoniker_Release(enumMoniker
);
1388 /* get the left moniker */
1389 CreateAntiMoniker(&antiMk
);
1390 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1391 IMoniker_Release(antiMk
);
1393 return IMoniker_ParseDisplayName(mostRigthMk
,pbc
,tempMk
,pszDisplayName
,pchEaten
,ppmkOut
);
1396 /******************************************************************************
1397 * CompositeMoniker_IsSystemMonker
1398 ******************************************************************************/
1399 HRESULT WINAPI
CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
1401 TRACE("(%p,%p)\n",iface
,pwdMksys
);
1406 (*pwdMksys
)=MKSYS_GENERICCOMPOSITE
;
1411 /*******************************************************************************
1412 * CompositeMonikerIROTData_QueryInterface
1413 *******************************************************************************/
1414 HRESULT WINAPI
CompositeMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,VOID
** ppvObject
)
1417 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1419 TRACE("(%p,%p,%p)\n",iface
,riid
,ppvObject
);
1421 return CompositeMonikerImpl_QueryInterface(This
, riid
, ppvObject
);
1424 /***********************************************************************
1425 * CompositeMonikerIROTData_AddRef
1427 ULONG WINAPI
CompositeMonikerROTDataImpl_AddRef(IROTData
*iface
)
1429 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1431 TRACE("(%p)\n",iface
);
1433 return CompositeMonikerImpl_AddRef(This
);
1436 /***********************************************************************
1437 * CompositeMonikerIROTData_Release
1439 ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
)
1441 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1443 TRACE("(%p)\n",iface
);
1445 return CompositeMonikerImpl_Release(This
);
1448 /******************************************************************************
1449 * CompositeMonikerIROTData_GetComparaisonData
1450 ******************************************************************************/
1451 HRESULT WINAPI
CompositeMonikerROTDataImpl_GetComparaisonData(IROTData
* iface
,
1456 FIXME("(),stub!\n");
1460 /******************************************************************************
1461 * EnumMonikerImpl_QueryInterface
1462 ******************************************************************************/
1463 HRESULT WINAPI
EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
)
1465 ICOM_THIS(EnumMonikerImpl
,iface
);
1467 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
1469 /* Perform a sanity check on the parameters.*/
1470 if ( (This
==0) || (ppvObject
==0) )
1471 return E_INVALIDARG
;
1473 /* Initialize the return parameter */
1476 /* Compare the riid with the interface IDs implemented by this object.*/
1477 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IEnumMoniker
, riid
))
1480 /* Check that we obtained an interface.*/
1481 if ((*ppvObject
)==0)
1482 return E_NOINTERFACE
;
1484 /* Query Interface always increases the reference count by one when it is successful */
1485 EnumMonikerImpl_AddRef(iface
);
1490 /******************************************************************************
1491 * EnumMonikerImpl_AddRef
1492 ******************************************************************************/
1493 ULONG WINAPI
EnumMonikerImpl_AddRef(IEnumMoniker
* iface
)
1495 ICOM_THIS(EnumMonikerImpl
,iface
);
1497 TRACE("(%p)\n",This
);
1499 return ++(This
->ref
);
1503 /******************************************************************************
1504 * EnumMonikerImpl_Release
1505 ******************************************************************************/
1506 ULONG WINAPI
EnumMonikerImpl_Release(IEnumMoniker
* iface
)
1508 ICOM_THIS(EnumMonikerImpl
,iface
);
1511 TRACE("(%p)\n",This
);
1515 /* destroy the object if there's no more reference on it */
1518 for(i
=0;i
<This
->tabSize
;i
++)
1519 IMoniker_Release(This
->tabMoniker
[i
]);
1521 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
1522 HeapFree(GetProcessHeap(),0,This
);
1529 /******************************************************************************
1530 * EnumMonikerImpl_Next
1531 ******************************************************************************/
1532 HRESULT WINAPI
EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
, IMoniker
** rgelt
, ULONG
* pceltFethed
){
1534 ICOM_THIS(EnumMonikerImpl
,iface
);
1537 /* retrieve the requested number of moniker from the current position */
1538 for(i
=0;((This
->currentPos
< This
->tabSize
) && (i
< celt
));i
++)
1540 rgelt
[i
]=This
->tabMoniker
[This
->currentPos
++];
1542 if (pceltFethed
!=NULL
)
1551 /******************************************************************************
1552 * EnumMonikerImpl_Skip
1553 ******************************************************************************/
1554 HRESULT WINAPI
EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
){
1556 ICOM_THIS(EnumMonikerImpl
,iface
);
1558 if ((This
->currentPos
+celt
) >= This
->tabSize
)
1561 This
->currentPos
+=celt
;
1566 /******************************************************************************
1567 * EnumMonikerImpl_Reset
1568 ******************************************************************************/
1569 HRESULT WINAPI
EnumMonikerImpl_Reset(IEnumMoniker
* iface
){
1571 ICOM_THIS(EnumMonikerImpl
,iface
);
1578 /******************************************************************************
1579 * EnumMonikerImpl_Clone
1580 ******************************************************************************/
1581 HRESULT WINAPI
EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
){
1583 ICOM_THIS(EnumMonikerImpl
,iface
);
1585 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabSize
,This
->currentPos
,TRUE
,ppenum
);
1588 /******************************************************************************
1589 * EnumMonikerImpl_CreateEnumMoniker
1590 ******************************************************************************/
1591 HRESULT WINAPI
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,
1595 IEnumMoniker
** ppmk
)
1597 EnumMonikerImpl
* newEnumMoniker
;
1601 newEnumMoniker
= HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl
));
1603 if (newEnumMoniker
== 0)
1604 return STG_E_INSUFFICIENTMEMORY
;
1606 if (currentPos
> tabSize
)
1607 return E_INVALIDARG
;
1609 /* Initialize the virtual function table. */
1610 ICOM_VTBL(newEnumMoniker
) = &VT_EnumMonikerImpl
;
1611 newEnumMoniker
->ref
= 0;
1613 newEnumMoniker
->tabSize
=tabSize
;
1614 newEnumMoniker
->currentPos
=currentPos
;
1616 newEnumMoniker
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,tabSize
*sizeof(IMoniker
));
1618 if (newEnumMoniker
->tabMoniker
==NULL
)
1619 return E_OUTOFMEMORY
;
1622 for (i
=0;i
<tabSize
;i
++){
1624 newEnumMoniker
->tabMoniker
[i
]=tabMoniker
[i
];
1625 IMoniker_AddRef(tabMoniker
[i
]);
1628 for (i
=tabSize
-1;i
>=0;i
--){
1630 newEnumMoniker
->tabMoniker
[tabSize
-i
-1]=tabMoniker
[i
];
1631 IMoniker_AddRef(tabMoniker
[i
]);
1634 *ppmk
=(IEnumMoniker
*)newEnumMoniker
;
1639 /******************************************************************************
1640 * CreateGenericComposite [OLE.55]
1641 ******************************************************************************/
1642 HRESULT WINAPI
CreateGenericComposite(LPMONIKER pmkFirst
, LPMONIKER pmkRest
, LPMONIKER
* ppmkComposite
)
1644 CompositeMonikerImpl
* newCompositeMoniker
= 0;
1647 TRACE("(%p,%p,%p)\n",pmkFirst
,pmkRest
,ppmkComposite
);
1649 if (ppmkComposite
==NULL
)
1654 if (pmkFirst
==NULL
&& pmkRest
!=NULL
){
1656 *ppmkComposite
=pmkRest
;
1659 else if (pmkFirst
!=NULL
&& pmkRest
==NULL
){
1660 *ppmkComposite
=pmkFirst
;
1663 else if (pmkFirst
==NULL
&& pmkRest
==NULL
)
1666 newCompositeMoniker
= HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl
));
1668 if (newCompositeMoniker
== 0)
1669 return STG_E_INSUFFICIENTMEMORY
;
1671 hr
= CompositeMonikerImpl_Construct(newCompositeMoniker
,pmkFirst
,pmkRest
);
1675 HeapFree(GetProcessHeap(),0,newCompositeMoniker
);
1678 if (newCompositeMoniker
->tabLastIndex
==1)
1680 hr
= IMoniker_QueryInterface(newCompositeMoniker
->tabMoniker
[0],&IID_IMoniker
,(void**)ppmkComposite
);
1683 hr
= CompositeMonikerImpl_QueryInterface((IMoniker
*)newCompositeMoniker
,&IID_IMoniker
,(void**)ppmkComposite
);
1688 /******************************************************************************
1689 * MonikerCommonPrefixWith [OLE.55]
1690 ******************************************************************************/
1691 HRESULT WINAPI
MonikerCommonPrefixWith(IMoniker
* pmkThis
,IMoniker
* pmkOther
,IMoniker
** ppmkCommon
)
1693 FIXME("(),stub!\n");