1 /***************************************************************************************
2 * CompositeMonikers implementation
4 * Copyright 1999 Noomen Hamza
5 ***************************************************************************************/
10 #include "debugtools.h"
11 #include "wine/obj_base.h"
12 #include "wine/obj_misc.h"
13 #include "wine/obj_storage.h"
14 #include "wine/obj_moniker.h"
15 #include "wine/obj_inplace.h"
16 #include "wine/unicode.h"
19 DEFAULT_DEBUG_CHANNEL(ole
);
21 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
23 /* CompositeMoniker data structure */
24 typedef struct CompositeMonikerImpl
{
26 ICOM_VTABLE(IMoniker
)* lpvtbl1
; /* VTable relative to the IMoniker interface.*/
28 /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
29 * two monikers are equal. That's whay IROTData interface is implemented by monikers.
31 ICOM_VTABLE(IROTData
)* lpvtbl2
; /* VTable relative to the IROTData interface.*/
33 ULONG ref
; /* reference counter for this object */
35 IMoniker
** tabMoniker
; /* dynamaic table containing all components (monikers) of this composite moniker */
37 ULONG tabSize
; /* size of tabMoniker */
39 ULONG tabLastIndex
; /* first free index in tabMoniker */
41 } CompositeMonikerImpl
;
44 /* EnumMoniker data structure */
45 typedef struct EnumMonikerImpl
{
47 ICOM_VFIELD(IEnumMoniker
); /* VTable relative to the IEnumMoniker interface.*/
49 ULONG ref
; /* reference counter for this object */
51 IMoniker
** tabMoniker
; /* dynamic table containing the enumerated monikers */
53 ULONG tabSize
; /* size of tabMoniker */
55 ULONG currentPos
; /* index pointer on the current moniker */
60 /********************************************************************************/
61 /* CompositeMoniker prototype functions : */
63 /* IUnknown prototype functions */
64 static HRESULT WINAPI
CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
);
65 static ULONG WINAPI
CompositeMonikerImpl_AddRef(IMoniker
* iface
);
66 static ULONG WINAPI
CompositeMonikerImpl_Release(IMoniker
* iface
);
68 /* IPersist prototype functions */
69 static HRESULT WINAPI
CompositeMonikerImpl_GetClassID(IMoniker
* iface
, CLSID
*pClassID
);
71 /* IPersistStream prototype functions */
72 static HRESULT WINAPI
CompositeMonikerImpl_IsDirty(IMoniker
* iface
);
73 static HRESULT WINAPI
CompositeMonikerImpl_Load(IMoniker
* iface
, IStream
* pStm
);
74 static HRESULT WINAPI
CompositeMonikerImpl_Save(IMoniker
* iface
, IStream
* pStm
, BOOL fClearDirty
);
75 static HRESULT WINAPI
CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
, ULARGE_INTEGER
* pcbSize
);
77 /* IMoniker prototype functions */
78 static HRESULT WINAPI
CompositeMonikerImpl_BindToObject(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
);
79 static HRESULT WINAPI
CompositeMonikerImpl_BindToStorage(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
);
80 static HRESULT WINAPI
CompositeMonikerImpl_Reduce(IMoniker
* iface
,IBindCtx
* pbc
, DWORD dwReduceHowFar
,IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
);
81 static HRESULT WINAPI
CompositeMonikerImpl_ComposeWith(IMoniker
* iface
,IMoniker
* pmkRight
,BOOL fOnlyIfNotGeneric
, IMoniker
** ppmkComposite
);
82 static HRESULT WINAPI
CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
);
83 static HRESULT WINAPI
CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
);
84 static HRESULT WINAPI
CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
);
85 static HRESULT WINAPI
CompositeMonikerImpl_IsRunning(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, IMoniker
* pmkNewlyRunning
);
86 static HRESULT WINAPI
CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
, FILETIME
* pCompositeTime
);
87 static HRESULT WINAPI
CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
);
88 static HRESULT WINAPI
CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
, IMoniker
** ppmkPrefix
);
89 static HRESULT WINAPI
CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmOther
, IMoniker
** ppmkRelPath
);
90 static HRESULT WINAPI
CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
);
91 static HRESULT WINAPI
CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
* pchEaten
, IMoniker
** ppmkOut
);
92 static HRESULT WINAPI
CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
);
94 /********************************************************************************/
95 /* IROTData prototype functions */
97 /* IUnknown prototype functions */
98 static HRESULT WINAPI
CompositeMonikerROTDataImpl_QueryInterface(IROTData
* iface
,REFIID riid
,VOID
** ppvObject
);
99 static ULONG WINAPI
CompositeMonikerROTDataImpl_AddRef(IROTData
* iface
);
100 static ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
);
102 /* IROTData prototype function */
103 static HRESULT WINAPI
CompositeMonikerROTDataImpl_GetComparaisonData(IROTData
* iface
,BYTE
* pbData
,ULONG cbMax
,ULONG
* pcbData
);
105 /* Local function used by CompositeMoniker implementation */
106 HRESULT WINAPI
CompositeMonikerImpl_Construct(CompositeMonikerImpl
* This
,LPMONIKER pmkFirst
, LPMONIKER pmkRest
);
107 HRESULT WINAPI
CompositeMonikerImpl_Destroy(CompositeMonikerImpl
* iface
);
109 /********************************************************************************/
110 /* IEnumMoniker prototype functions */
112 /* IUnknown prototype functions */
113 static HRESULT WINAPI
EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
);
114 static ULONG WINAPI
EnumMonikerImpl_AddRef(IEnumMoniker
* iface
);
115 static ULONG WINAPI
EnumMonikerImpl_Release(IEnumMoniker
* iface
);
117 /* IEnumMoniker prototype functions */
118 static HRESULT WINAPI
EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
,IMoniker
** rgelt
,ULONG
* pceltFetched
);
119 static HRESULT WINAPI
EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
);
120 static HRESULT WINAPI
EnumMonikerImpl_Reset(IEnumMoniker
* iface
);
121 static HRESULT WINAPI
EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
);
123 HRESULT WINAPI
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,ULONG tabSize
,ULONG currentPos
,BOOL leftToRigth
,IEnumMoniker
** ppmk
);
125 /********************************************************************************/
126 /* Virtual function table for the CompositeMonikerImpl class which includes */
127 /* IPersist, IPersistStream and IMoniker functions. */
129 static ICOM_VTABLE(IMoniker
) VT_CompositeMonikerImpl
=
131 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
132 CompositeMonikerImpl_QueryInterface
,
133 CompositeMonikerImpl_AddRef
,
134 CompositeMonikerImpl_Release
,
135 CompositeMonikerImpl_GetClassID
,
136 CompositeMonikerImpl_IsDirty
,
137 CompositeMonikerImpl_Load
,
138 CompositeMonikerImpl_Save
,
139 CompositeMonikerImpl_GetSizeMax
,
140 CompositeMonikerImpl_BindToObject
,
141 CompositeMonikerImpl_BindToStorage
,
142 CompositeMonikerImpl_Reduce
,
143 CompositeMonikerImpl_ComposeWith
,
144 CompositeMonikerImpl_Enum
,
145 CompositeMonikerImpl_IsEqual
,
146 CompositeMonikerImpl_Hash
,
147 CompositeMonikerImpl_IsRunning
,
148 CompositeMonikerImpl_GetTimeOfLastChange
,
149 CompositeMonikerImpl_Inverse
,
150 CompositeMonikerImpl_CommonPrefixWith
,
151 CompositeMonikerImpl_RelativePathTo
,
152 CompositeMonikerImpl_GetDisplayName
,
153 CompositeMonikerImpl_ParseDisplayName
,
154 CompositeMonikerImpl_IsSystemMoniker
157 /********************************************************************************/
158 /* Virtual function table for the IROTData class. */
159 static ICOM_VTABLE(IROTData
) VT_ROTDataImpl
=
161 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
162 CompositeMonikerROTDataImpl_QueryInterface
,
163 CompositeMonikerROTDataImpl_AddRef
,
164 CompositeMonikerROTDataImpl_Release
,
165 CompositeMonikerROTDataImpl_GetComparaisonData
168 /********************************************************************************/
169 /* Virtual function table for the IROTData class */
170 static ICOM_VTABLE(IEnumMoniker
) VT_EnumMonikerImpl
=
172 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
173 EnumMonikerImpl_QueryInterface
,
174 EnumMonikerImpl_AddRef
,
175 EnumMonikerImpl_Release
,
176 EnumMonikerImpl_Next
,
177 EnumMonikerImpl_Skip
,
178 EnumMonikerImpl_Reset
,
179 EnumMonikerImpl_Clone
182 /*******************************************************************************
183 * CompositeMoniker_QueryInterface
184 *******************************************************************************/
185 HRESULT WINAPI
CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
187 ICOM_THIS(CompositeMonikerImpl
,iface
);
189 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
191 /* Perform a sanity check on the parameters.*/
192 if ( (This
==0) || (ppvObject
==0) )
195 /* Initialize the return parameter */
198 /* Compare the riid with the interface IDs implemented by this object.*/
199 if (IsEqualIID(&IID_IUnknown
, riid
) ||
200 IsEqualIID(&IID_IPersist
, riid
) ||
201 IsEqualIID(&IID_IPersistStream
, riid
) ||
202 IsEqualIID(&IID_IMoniker
, riid
)
205 else if (IsEqualIID(&IID_IROTData
, riid
))
206 *ppvObject
= (IROTData
*)&(This
->lpvtbl2
);
208 /* Check that we obtained an interface.*/
210 return E_NOINTERFACE
;
212 /* Query Interface always increases the reference count by one when it is successful */
213 CompositeMonikerImpl_AddRef(iface
);
218 /******************************************************************************
219 * CompositeMoniker_AddRef
220 ******************************************************************************/
221 ULONG WINAPI
CompositeMonikerImpl_AddRef(IMoniker
* iface
)
223 ICOM_THIS(CompositeMonikerImpl
,iface
);
225 TRACE("(%p)\n",This
);
227 return ++(This
->ref
);
230 /******************************************************************************
231 * CompositeMoniker_Release
232 ******************************************************************************/
233 ULONG WINAPI
CompositeMonikerImpl_Release(IMoniker
* iface
)
235 ICOM_THIS(CompositeMonikerImpl
,iface
);
238 TRACE("(%p)\n",This
);
242 /* destroy the object if there's no more reference on it */
245 /* release all the components before destroying this object */
246 for (i
=0;i
<This
->tabLastIndex
;i
++)
247 IMoniker_Release(This
->tabMoniker
[i
]);
249 CompositeMonikerImpl_Destroy(This
);
256 /******************************************************************************
257 * CompositeMoniker_GetClassID
258 ******************************************************************************/
259 HRESULT WINAPI
CompositeMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
261 TRACE("(%p,%p),stub!\n",iface
,pClassID
);
266 *pClassID
= CLSID_CompositeMoniker
;
271 /******************************************************************************
272 * CompositeMoniker_IsDirty
273 ******************************************************************************/
274 HRESULT WINAPI
CompositeMonikerImpl_IsDirty(IMoniker
* iface
)
276 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
277 method in the OLE-provided moniker interfaces always return S_FALSE because
278 their internal state never changes. */
280 TRACE("(%p)\n",iface
);
285 /******************************************************************************
286 * CompositeMoniker_Load
287 ******************************************************************************/
288 HRESULT WINAPI
CompositeMonikerImpl_Load(IMoniker
* iface
,IStream
* pStm
)
295 ICOM_THIS(CompositeMonikerImpl
,iface
);
297 TRACE("(%p,%p)\n",iface
,pStm
);
299 /* this function call OleLoadFromStream function for each moniker within this object */
301 /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
302 res
=IStream_Read(pStm
,&constant
,sizeof(DWORD
),NULL
);
304 if (SUCCEEDED(res
)&& constant
!=3)
309 res
=OleLoadFromStream(pStm
,&IID_IMoniker
,(void**)&This
->tabMoniker
[This
->tabLastIndex
]);
311 res
=ReadClassStm(pStm
,&clsid
);
312 DPRINTF("res=%ld",res
);
316 if (IsEqualIID(&clsid
,&CLSID_FileMoniker
)){
317 res
=CreateFileMoniker(string
,&This
->tabMoniker
[This
->tabLastIndex
]);
320 res
=IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
324 else if (IsEqualIID(&clsid
,&CLSID_ItemMoniker
)){
325 CreateItemMoniker(string
,string
,&This
->tabMoniker
[This
->tabLastIndex
]);
328 IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
332 else if (IsEqualIID(&clsid
,&CLSID_AntiMoniker
)){
333 CreateAntiMoniker(&This
->tabMoniker
[This
->tabLastIndex
]);
336 IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
340 else if (IsEqualIID(&clsid
,&CLSID_CompositeMoniker
))
346 /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */
351 /* resize the table if needed */
352 if (++This
->tabLastIndex
==This
->tabSize
){
354 This
->tabSize
+=BLOCK_TAB_SIZE
;
355 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
357 if (This
->tabMoniker
==NULL
)
358 return E_OUTOFMEMORY
;
365 /******************************************************************************
366 * CompositeMoniker_Save
367 ******************************************************************************/
368 HRESULT WINAPI
CompositeMonikerImpl_Save(IMoniker
* iface
,IStream
* pStm
,BOOL fClearDirty
)
371 IEnumMoniker
*enumMk
;
375 TRACE("(%p,%p,%d)\n",iface
,pStm
,fClearDirty
);
377 /* this function call OleSaveToStream function for each moniker within this object */
379 /* when I tested this function in windows system ! I usually found this constant in the begining of */
380 /* the stream I dont known why (there's no indication in specification) ! */
381 res
=IStream_Write(pStm
,&constant
,sizeof(constant
),NULL
);
383 IMoniker_Enum(iface
,TRUE
,&enumMk
);
385 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
387 res
=OleSaveToStream((IPersistStream
*)pmk
,pStm
);
389 IMoniker_Release(pmk
);
393 IEnumMoniker_Release(pmk
);
398 IEnumMoniker_Release(enumMk
);
403 /******************************************************************************
404 * CompositeMoniker_GetSizeMax
405 ******************************************************************************/
406 HRESULT WINAPI
CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
,ULARGE_INTEGER
* pcbSize
)
408 IEnumMoniker
*enumMk
;
410 ULARGE_INTEGER ptmpSize
;
412 /* the sizeMax of this object is calculated by calling GetSizeMax on each moniker within this object then */
413 /* suming all returned sizemax */
415 TRACE("(%p,%p)\n",iface
,pcbSize
);
420 pcbSize
->s
.LowPart
=0;
421 pcbSize
->s
.HighPart
=0;
423 IMoniker_Enum(iface
,TRUE
,&enumMk
);
425 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==TRUE
){
427 IMoniker_GetSizeMax(pmk
,&ptmpSize
);
429 IMoniker_Release(pmk
);
431 pcbSize
->s
.LowPart
+=ptmpSize
.s
.LowPart
;
432 pcbSize
->s
.HighPart
+=ptmpSize
.s
.HighPart
;
435 IEnumMoniker_Release(enumMk
);
440 /******************************************************************************
441 * Composite-Moniker_Construct (local function)
442 *******************************************************************************/
443 HRESULT WINAPI
CompositeMonikerImpl_Construct(CompositeMonikerImpl
* This
,LPMONIKER pmkFirst
, LPMONIKER pmkRest
)
446 IEnumMoniker
*enumMoniker
;
450 TRACE("(%p,%p,%p)\n",This
,pmkFirst
,pmkRest
);
452 /* Initialize the virtual fgunction table. */
453 This
->lpvtbl1
= &VT_CompositeMonikerImpl
;
454 This
->lpvtbl2
= &VT_ROTDataImpl
;
457 This
->tabSize
=BLOCK_TAB_SIZE
;
458 This
->tabLastIndex
=0;
460 This
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,This
->tabSize
*sizeof(IMoniker
));
461 if (This
->tabMoniker
==NULL
)
462 return E_OUTOFMEMORY
;
464 IMoniker_IsSystemMoniker(pmkFirst
,&mkSys
);
466 /* put the first moniker contents in the begining of the table */
467 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
469 This
->tabMoniker
[(This
->tabLastIndex
)++]=pmkFirst
;
470 IMoniker_AddRef(pmkFirst
);
474 IMoniker_Enum(pmkFirst
,TRUE
,&enumMoniker
);
476 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
479 if (++This
->tabLastIndex
==This
->tabSize
){
481 This
->tabSize
+=BLOCK_TAB_SIZE
;
482 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
484 if (This
->tabMoniker
==NULL
)
485 return E_OUTOFMEMORY
;
489 IEnumMoniker_Release(enumMoniker
);
492 /* put the rest moniker contents after the first one and make simplification if needed */
494 IMoniker_IsSystemMoniker(pmkRest
,&mkSys
);
496 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
498 /* add a simple moniker to the moniker table */
500 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],pmkRest
,TRUE
,&tempMk
);
502 if (res
==MK_E_NEEDGENERIC
){
504 /* there's no simplification in this case */
505 This
->tabMoniker
[This
->tabLastIndex
]=pmkRest
;
507 This
->tabLastIndex
++;
509 IMoniker_AddRef(pmkRest
);
511 else if (tempMk
==NULL
){
513 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
514 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
516 This
->tabLastIndex
--;
518 else if (SUCCEEDED(res
)){
520 /* the non-generic composition was successful so we can make a simplification in this case */
521 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
523 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
527 /* resize tabMoniker if needed */
528 if (This
->tabLastIndex
==This
->tabSize
){
530 This
->tabSize
+=BLOCK_TAB_SIZE
;
532 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
534 if (This
->tabMoniker
==NULL
)
535 return E_OUTOFMEMORY
;
540 /* add a composite moniker to the moniker table (do the same thing for each moniker within the */
541 /* composite moniker as a simple moniker (see above how to add a simple moniker case) ) */
542 IMoniker_Enum(pmkRest
,TRUE
,&enumMoniker
);
544 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
546 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],This
->tabMoniker
[This
->tabLastIndex
],TRUE
,&tempMk
);
548 if (res
==MK_E_NEEDGENERIC
){
550 This
->tabLastIndex
++;
552 else if (tempMk
==NULL
){
554 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
555 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
]);
556 This
->tabLastIndex
--;
560 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
562 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
565 if (This
->tabLastIndex
==This
->tabSize
){
567 This
->tabSize
+=BLOCK_TAB_SIZE
;
569 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
571 if (This
->tabMoniker
==NULL
)
572 return E_OUTOFMEMORY
;
576 IEnumMoniker_Release(enumMoniker
);
582 /******************************************************************************
583 * CompositeMoniker_Destroy (local function)
584 *******************************************************************************/
585 HRESULT WINAPI
CompositeMonikerImpl_Destroy(CompositeMonikerImpl
* This
)
587 TRACE("(%p)\n",This
);
589 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
591 HeapFree(GetProcessHeap(),0,This
);
596 /******************************************************************************
597 * CompositeMoniker_BindToObject
598 ******************************************************************************/
599 HRESULT WINAPI
CompositeMonikerImpl_BindToObject(IMoniker
* iface
,
606 IRunningObjectTable
*prot
;
607 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
608 IEnumMoniker
*enumMoniker
;
610 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
616 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
617 /* object for the requested interface pointer. */
620 res
=IBindCtx_GetRunningObjectTable(pbc
,&prot
);
624 /* if the requested class was loaded befor ! we dont need to reload it */
625 res
= IRunningObjectTable_GetObject(prot
,iface
,(IUnknown
**)ppvResult
);
632 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
633 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
635 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
636 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
637 IEnumMoniker_Release(enumMoniker
);
639 res
=CreateAntiMoniker(&antiMk
);
640 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
641 IMoniker_Release(antiMk
);
643 res
=CompositeMonikerImpl_BindToObject(mostRigthMk
,pbc
,tempMk
,riid
,ppvResult
);
645 IMoniker_Release(tempMk
);
646 IMoniker_Release(mostRigthMk
);
652 /******************************************************************************
653 * CompositeMoniker_BindToStorage
654 ******************************************************************************/
655 HRESULT WINAPI
CompositeMonikerImpl_BindToStorage(IMoniker
* iface
,
662 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
663 IEnumMoniker
*enumMoniker
;
665 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
669 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
670 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
672 if (pmkToLeft
!=NULL
){
674 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
675 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
676 IEnumMoniker_Release(enumMoniker
);
678 res
=CreateAntiMoniker(&antiMk
);
679 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
680 IMoniker_Release(antiMk
);
682 res
=CompositeMonikerImpl_BindToStorage(mostRigthMk
,pbc
,tempMk
,riid
,ppvResult
);
684 IMoniker_Release(tempMk
);
686 IMoniker_Release(mostRigthMk
);
691 return IMoniker_BindToStorage(iface
,pbc
,NULL
,riid
,ppvResult
);
694 /******************************************************************************
695 * CompositeMoniker_Reduce
696 ******************************************************************************/
697 HRESULT WINAPI
CompositeMonikerImpl_Reduce(IMoniker
* iface
,
699 DWORD dwReduceHowFar
,
700 IMoniker
** ppmkToLeft
,
701 IMoniker
** ppmkReduced
)
704 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*leftReducedComposedMk
,*mostRigthReducedMk
;
705 IEnumMoniker
*enumMoniker
;
707 TRACE("(%p,%p,%ld,%p,%p)\n",iface
,pbc
,dwReduceHowFar
,ppmkToLeft
,ppmkReduced
);
709 if (ppmkReduced
==NULL
)
712 /* This method recursively calls Reduce for each of its component monikers. */
714 if (ppmkToLeft
==NULL
){
716 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
717 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
718 IEnumMoniker_Release(enumMoniker
);
720 res
=CreateAntiMoniker(&antiMk
);
721 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
722 IMoniker_Release(antiMk
);
724 return CompositeMonikerImpl_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
, ppmkReduced
);
726 else if (*ppmkToLeft
==NULL
)
728 return IMoniker_Reduce(iface
,pbc
,dwReduceHowFar
,NULL
,ppmkReduced
);
732 /* separate the composite moniker in to left and right moniker */
733 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
734 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
735 IEnumMoniker_Release(enumMoniker
);
737 res
=CreateAntiMoniker(&antiMk
);
738 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
739 IMoniker_Release(antiMk
);
741 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
742 /* of the reduced components */
743 if (IMoniker_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,NULL
,&mostRigthReducedMk
) &&
744 CompositeMonikerImpl_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
,&leftReducedComposedMk
)
747 return CreateGenericComposite(leftReducedComposedMk
,mostRigthReducedMk
,ppmkReduced
);
750 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
752 IMoniker_AddRef(iface
);
756 return MK_S_REDUCED_TO_SELF
;
761 /******************************************************************************
762 * CompositeMoniker_ComposeWith
763 ******************************************************************************/
764 HRESULT WINAPI
CompositeMonikerImpl_ComposeWith(IMoniker
* iface
,
766 BOOL fOnlyIfNotGeneric
,
767 IMoniker
** ppmkComposite
)
769 TRACE("(%p,%p,%d,%p)\n",iface
,pmkRight
,fOnlyIfNotGeneric
,ppmkComposite
);
771 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
776 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
777 /* otherwise, the method returns the result of combining the two monikers by calling the */
778 /* CreateGenericComposite function */
780 if (fOnlyIfNotGeneric
)
781 return MK_E_NEEDGENERIC
;
783 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
786 /******************************************************************************
787 * CompositeMoniker_Enum
788 ******************************************************************************/
789 HRESULT WINAPI
CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
791 ICOM_THIS(CompositeMonikerImpl
,iface
);
793 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
795 if (ppenumMoniker
== NULL
)
798 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabLastIndex
,0,fForward
,ppenumMoniker
);
801 /******************************************************************************
802 * CompositeMoniker_IsEqual
803 ******************************************************************************/
804 HRESULT WINAPI
CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
)
806 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
807 IMoniker
*tempMk1
,*tempMk2
;
808 HRESULT res1
,res2
,res
;
810 TRACE("(%p,%p)\n",iface
,pmkOtherMoniker
);
812 if (pmkOtherMoniker
==NULL
)
815 /* This method returns S_OK if the components of both monikers are equal when compared in the */
816 /* left-to-right order.*/
817 IMoniker_Enum(pmkOtherMoniker
,TRUE
,&enumMoniker1
);
819 if (enumMoniker1
==NULL
)
822 IMoniker_Enum(iface
,TRUE
,&enumMoniker2
);
826 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
827 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
829 if((res1
==S_OK
)&&(res2
==S_OK
)){
831 if(IMoniker_IsEqual(tempMk1
,tempMk2
)==S_FALSE
){
838 else if ( (res1
==S_FALSE
) && (res2
==S_FALSE
) ){
848 IMoniker_Release(tempMk1
);
851 IMoniker_Release(tempMk2
);
854 IEnumMoniker_Release(enumMoniker1
);
855 IEnumMoniker_Release(enumMoniker2
);
859 /******************************************************************************
860 * CompositeMoniker_Hash
861 ******************************************************************************/
862 HRESULT WINAPI
CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
869 /******************************************************************************
870 * CompositeMoniker_IsRunning
871 ******************************************************************************/
872 HRESULT WINAPI
CompositeMonikerImpl_IsRunning(IMoniker
* iface
,
875 IMoniker
* pmkNewlyRunning
)
877 IRunningObjectTable
* rot
;
879 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
880 IEnumMoniker
*enumMoniker
;
882 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
884 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
885 if (pmkToLeft
!=NULL
){
887 CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
889 res
= IMoniker_IsRunning(tempMk
,pbc
,NULL
,pmkNewlyRunning
);
891 IMoniker_Release(tempMk
);
896 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
897 /* to this moniker */
899 if (pmkNewlyRunning
!=NULL
)
901 if (IMoniker_IsEqual(iface
,pmkNewlyRunning
)==S_OK
)
912 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
913 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
914 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
915 /* the composite as the pmkToLeft parameter for that call. */
917 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
922 res
= IRunningObjectTable_IsRunning(rot
,iface
);
923 IRunningObjectTable_Release(rot
);
930 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
931 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
932 IEnumMoniker_Release(enumMoniker
);
934 res
=CreateAntiMoniker(&antiMk
);
935 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
936 IMoniker_Release(antiMk
);
938 res
=IMoniker_IsRunning(mostRigthMk
,pbc
,tempMk
,pmkNewlyRunning
);
940 IMoniker_Release(tempMk
);
941 IMoniker_Release(mostRigthMk
);
948 /******************************************************************************
949 * CompositeMoniker_GetTimeOfLastChange
950 ******************************************************************************/
951 HRESULT WINAPI
CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
,
954 FILETIME
* pCompositeTime
)
956 IRunningObjectTable
* rot
;
958 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
959 IEnumMoniker
*enumMoniker
;
961 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pCompositeTime
);
963 if (pCompositeTime
==NULL
)
966 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
967 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
968 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
969 /* of the composite as the pmkToLeft parameter for that call. */
970 if (pmkToLeft
!=NULL
){
972 res
=CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
974 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
979 if (IRunningObjectTable_GetTimeOfLastChange(rot
,tempMk
,pCompositeTime
)==S_OK
)
983 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
984 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
985 IEnumMoniker_Release(enumMoniker
);
987 res
=CreateAntiMoniker(&antiMk
);
988 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
989 IMoniker_Release(antiMk
);
991 res
=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk
,pbc
,tempMk
,pCompositeTime
);
993 IMoniker_Release(tempMk
);
994 IMoniker_Release(mostRigthMk
);
999 return IMoniker_GetTimeOfLastChange(iface
,pbc
,NULL
,pCompositeTime
);
1002 /******************************************************************************
1003 * CompositeMoniker_Inverse
1004 ******************************************************************************/
1005 HRESULT WINAPI
CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
1008 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*tempInvMk
,*mostRigthInvMk
;
1009 IEnumMoniker
*enumMoniker
;
1011 TRACE("(%p,%p)\n",iface
,ppmk
);
1016 /* This method returns a composite moniker that consists of the inverses of each of the components */
1017 /* of the original composite, stored in reverse order */
1019 res
=CreateAntiMoniker(&antiMk
);
1020 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1021 IMoniker_Release(antiMk
);
1025 return IMoniker_Inverse(iface
,ppmk
);
1029 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1030 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1031 IEnumMoniker_Release(enumMoniker
);
1033 IMoniker_Inverse(mostRigthMk
,&mostRigthInvMk
);
1034 CompositeMonikerImpl_Inverse(tempMk
,&tempInvMk
);
1036 res
=CreateGenericComposite(mostRigthInvMk
,tempInvMk
,ppmk
);
1038 IMoniker_Release(tempMk
);
1039 IMoniker_Release(mostRigthMk
);
1040 IMoniker_Release(tempInvMk
);
1041 IMoniker_Release(mostRigthInvMk
);
1047 /******************************************************************************
1048 * CompositeMoniker_CommonPrefixWith
1049 ******************************************************************************/
1050 HRESULT WINAPI
CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
,IMoniker
** ppmkPrefix
)
1054 IMoniker
*tempMk1
,*tempMk2
,*mostLeftMk1
,*mostLeftMk2
;
1055 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
1056 ULONG i
,nbCommonMk
=0;
1058 /* If the other moniker is a composite, this method compares the components of each composite from left */
1059 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1060 /* of the leftmost components were common to both monikers. */
1062 if (ppmkPrefix
==NULL
)
1068 return MK_E_NOPREFIX
;
1070 IMoniker_IsSystemMoniker(pmkOther
,&mkSys
);
1072 if((mkSys
==MKSYS_GENERICCOMPOSITE
)){
1074 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
1075 IMoniker_Enum(pmkOther
,TRUE
,&enumMoniker2
);
1079 res1
=IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
1080 res2
=IEnumMoniker_Next(enumMoniker2
,1,&mostLeftMk2
,NULL
);
1082 if ((res1
==S_FALSE
) && (res2
==S_FALSE
)){
1084 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1086 IMoniker_AddRef(iface
);
1089 else if ((res1
==S_OK
) && (res2
==S_OK
)){
1091 if (IMoniker_IsEqual(mostLeftMk1
,mostLeftMk2
)==S_OK
)
1099 else if (res1
==S_OK
){
1101 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1102 /* ppmkPrefix to the other moniker. */
1103 *ppmkPrefix
=pmkOther
;
1107 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1108 /* to this moniker. */
1114 IEnumMoniker_Release(enumMoniker1
);
1115 IEnumMoniker_Release(enumMoniker2
);
1117 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1119 return MK_E_NOPREFIX
;
1121 IEnumMoniker_Reset(enumMoniker1
);
1123 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1125 /* if we have more than one commun moniker the result will be a composite moniker */
1128 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1129 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1130 CreateGenericComposite(tempMk1
,tempMk2
,ppmkPrefix
);
1131 IMoniker_Release(tempMk1
);
1132 IMoniker_Release(tempMk2
);
1134 /* compose all common monikers in a composite moniker */
1135 for(i
=0;i
<nbCommonMk
;i
++){
1137 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1139 CreateGenericComposite(*ppmkPrefix
,tempMk1
,&tempMk2
);
1141 IMoniker_Release(*ppmkPrefix
);
1143 IMoniker_Release(tempMk1
);
1145 *ppmkPrefix
=tempMk2
;
1150 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1151 *ppmkPrefix
=tempMk1
;
1157 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1160 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
1162 IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
1164 if (IMoniker_IsEqual(pmkOther
,mostLeftMk1
)==S_OK
){
1166 *ppmkPrefix
=pmkOther
;
1171 return MK_E_NOPREFIX
;
1174 /***************************************************************************************************
1175 * GetAfterCommonPrefix (local function)
1176 * This function returns a moniker that consist of the remainder when the common prefix is removed
1177 ***************************************************************************************************/
1178 VOID WINAPI
GetAfterCommonPrefix(IMoniker
* pGenMk
,IMoniker
* commonMk
,IMoniker
** restMk
)
1180 IMoniker
*tempMk
,*tempMk1
,*tempMk2
;
1181 IEnumMoniker
*enumMoniker1
,*enumMoniker2
,*enumMoniker3
;
1188 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1189 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
1190 /* on the first difference. */
1191 IMoniker_Enum(pGenMk
,TRUE
,&enumMoniker1
);
1193 IMoniker_IsSystemMoniker(commonMk
,&mkSys
);
1195 if (mkSys
==MKSYS_GENERICCOMPOSITE
){
1197 IMoniker_Enum(commonMk
,TRUE
,&enumMoniker2
);
1200 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1201 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
1203 if ((res1
==S_FALSE
)||(res2
==S_FALSE
)){
1209 IMoniker_Release(tempMk1
);
1210 IMoniker_Release(tempMk1
);
1214 IMoniker_Release(tempMk1
);
1215 IMoniker_Release(tempMk1
);
1219 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1220 IMoniker_Release(tempMk1
);
1223 /* count the number of elements in the enumerator after the common prefix */
1224 IEnumMoniker_Clone(enumMoniker1
,&enumMoniker3
);
1226 for(;IEnumMoniker_Next(enumMoniker3
,1,&tempMk
,NULL
)==S_OK
;nbRestMk
++)
1228 IMoniker_Release(tempMk
);;
1233 /* create a generic composite moniker with monikers located after the common prefix */
1234 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1243 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1245 CreateGenericComposite(tempMk1
,tempMk2
,restMk
);
1247 IMoniker_Release(tempMk1
);
1249 IMoniker_Release(tempMk2
);
1251 while(IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
)==S_OK
){
1253 CreateGenericComposite(*restMk
,tempMk1
,&tempMk2
);
1255 IMoniker_Release(tempMk1
);
1257 IMoniker_Release(*restMk
);
1263 /******************************************************************************
1264 * CompositeMoniker_RelativePathTo
1265 ******************************************************************************/
1266 HRESULT WINAPI
CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmkOther
, IMoniker
** ppmkRelPath
)
1269 IMoniker
*restOtherMk
=0,*restThisMk
=0,*invRestThisMk
=0,*commonMk
=0;
1271 TRACE("(%p,%p,%p)\n",iface
,pmkOther
,ppmkRelPath
);
1273 if (ppmkRelPath
==NULL
)
1278 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1279 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1280 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1282 /* finds the common prefix of the two monikers */
1283 res
=IMoniker_CommonPrefixWith(iface
,pmkOther
,&commonMk
);
1285 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1286 if ((res
== MK_E_NOPREFIX
)||(res
==MK_S_US
)){
1288 *ppmkRelPath
=pmkOther
;
1289 IMoniker_AddRef(pmkOther
);
1293 GetAfterCommonPrefix(iface
,commonMk
,&restThisMk
);
1294 GetAfterCommonPrefix(pmkOther
,commonMk
,&restOtherMk
);
1296 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1297 /* moniker when the common prefix is removed */
1300 IMoniker_Inverse(restThisMk
,ppmkRelPath
);
1301 IMoniker_Release(restThisMk
);
1303 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1304 /* when the common prefix is removed */
1305 else if (res
==MK_S_ME
){
1307 *ppmkRelPath
=restOtherMk
;
1308 IMoniker_AddRef(restOtherMk
);
1310 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1311 /* moniker on the right of it. */
1312 else if (res
==S_OK
){
1314 IMoniker_Inverse(restThisMk
,&invRestThisMk
);
1315 IMoniker_Release(restThisMk
);
1316 CreateGenericComposite(invRestThisMk
,restOtherMk
,ppmkRelPath
);
1317 IMoniker_Release(invRestThisMk
);
1318 IMoniker_Release(restOtherMk
);
1323 /******************************************************************************
1324 * CompositeMoniker_GetDisplayName
1325 ******************************************************************************/
1326 HRESULT WINAPI
CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
,
1328 IMoniker
* pmkToLeft
,
1329 LPOLESTR
*ppszDisplayName
)
1332 IEnumMoniker
*enumMoniker
;
1336 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
1338 if (ppszDisplayName
==NULL
)
1341 *ppszDisplayName
=CoTaskMemAlloc(sizeof(WCHAR
));
1343 if (*ppszDisplayName
==NULL
)
1344 return E_OUTOFMEMORY
;
1346 /* This method returns the concatenation of the display names returned by each component moniker of */
1349 **ppszDisplayName
=0;
1351 IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
1353 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
1355 IMoniker_GetDisplayName(tempMk
,pbc
,NULL
,&tempStr
);
1357 lengthStr
+=lstrlenW(tempStr
);
1359 *ppszDisplayName
=CoTaskMemRealloc(*ppszDisplayName
,lengthStr
* sizeof(WCHAR
));
1361 if (*ppszDisplayName
==NULL
)
1362 return E_OUTOFMEMORY
;
1364 strcatW(*ppszDisplayName
,tempStr
);
1366 CoTaskMemFree(tempStr
);
1367 IMoniker_Release(tempMk
);
1370 IEnumMoniker_Release(enumMoniker
);
1375 /******************************************************************************
1376 * CompositeMoniker_ParseDisplayName
1377 ******************************************************************************/
1378 HRESULT WINAPI
CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
,
1380 IMoniker
* pmkToLeft
,
1381 LPOLESTR pszDisplayName
,
1385 IEnumMoniker
*enumMoniker
;
1386 IMoniker
*tempMk
,*mostRigthMk
,*antiMk
;
1387 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1388 /* passing everything else as the pmkToLeft parameter for that call. */
1390 /* get the most right moniker */
1391 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1392 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1393 IEnumMoniker_Release(enumMoniker
);
1395 /* get the left moniker */
1396 CreateAntiMoniker(&antiMk
);
1397 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1398 IMoniker_Release(antiMk
);
1400 return IMoniker_ParseDisplayName(mostRigthMk
,pbc
,tempMk
,pszDisplayName
,pchEaten
,ppmkOut
);
1403 /******************************************************************************
1404 * CompositeMoniker_IsSystemMoniker
1405 ******************************************************************************/
1406 HRESULT WINAPI
CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
1408 TRACE("(%p,%p)\n",iface
,pwdMksys
);
1413 (*pwdMksys
)=MKSYS_GENERICCOMPOSITE
;
1418 /*******************************************************************************
1419 * CompositeMonikerIROTData_QueryInterface
1420 *******************************************************************************/
1421 HRESULT WINAPI
CompositeMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,VOID
** ppvObject
)
1424 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1426 TRACE("(%p,%p,%p)\n",iface
,riid
,ppvObject
);
1428 return CompositeMonikerImpl_QueryInterface(This
, riid
, ppvObject
);
1431 /***********************************************************************
1432 * CompositeMonikerIROTData_AddRef
1434 ULONG WINAPI
CompositeMonikerROTDataImpl_AddRef(IROTData
*iface
)
1436 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1438 TRACE("(%p)\n",iface
);
1440 return CompositeMonikerImpl_AddRef(This
);
1443 /***********************************************************************
1444 * CompositeMonikerIROTData_Release
1446 ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
)
1448 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1450 TRACE("(%p)\n",iface
);
1452 return CompositeMonikerImpl_Release(This
);
1455 /******************************************************************************
1456 * CompositeMonikerIROTData_GetComparaisonData
1457 ******************************************************************************/
1458 HRESULT WINAPI
CompositeMonikerROTDataImpl_GetComparaisonData(IROTData
* iface
,
1463 FIXME("(),stub!\n");
1467 /******************************************************************************
1468 * EnumMonikerImpl_QueryInterface
1469 ******************************************************************************/
1470 HRESULT WINAPI
EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
)
1472 ICOM_THIS(EnumMonikerImpl
,iface
);
1474 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
1476 /* Perform a sanity check on the parameters.*/
1477 if ( (This
==0) || (ppvObject
==0) )
1478 return E_INVALIDARG
;
1480 /* Initialize the return parameter */
1483 /* Compare the riid with the interface IDs implemented by this object.*/
1484 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IEnumMoniker
, riid
))
1487 /* Check that we obtained an interface.*/
1488 if ((*ppvObject
)==0)
1489 return E_NOINTERFACE
;
1491 /* Query Interface always increases the reference count by one when it is successful */
1492 EnumMonikerImpl_AddRef(iface
);
1497 /******************************************************************************
1498 * EnumMonikerImpl_AddRef
1499 ******************************************************************************/
1500 ULONG WINAPI
EnumMonikerImpl_AddRef(IEnumMoniker
* iface
)
1502 ICOM_THIS(EnumMonikerImpl
,iface
);
1504 TRACE("(%p)\n",This
);
1506 return ++(This
->ref
);
1510 /******************************************************************************
1511 * EnumMonikerImpl_Release
1512 ******************************************************************************/
1513 ULONG WINAPI
EnumMonikerImpl_Release(IEnumMoniker
* iface
)
1515 ICOM_THIS(EnumMonikerImpl
,iface
);
1518 TRACE("(%p)\n",This
);
1522 /* destroy the object if there's no more reference on it */
1525 for(i
=0;i
<This
->tabSize
;i
++)
1526 IMoniker_Release(This
->tabMoniker
[i
]);
1528 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
1529 HeapFree(GetProcessHeap(),0,This
);
1536 /******************************************************************************
1537 * EnumMonikerImpl_Next
1538 ******************************************************************************/
1539 HRESULT WINAPI
EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
, IMoniker
** rgelt
, ULONG
* pceltFethed
){
1541 ICOM_THIS(EnumMonikerImpl
,iface
);
1544 /* retrieve the requested number of moniker from the current position */
1545 for(i
=0;((This
->currentPos
< This
->tabSize
) && (i
< celt
));i
++)
1547 rgelt
[i
]=This
->tabMoniker
[This
->currentPos
++];
1549 if (pceltFethed
!=NULL
)
1558 /******************************************************************************
1559 * EnumMonikerImpl_Skip
1560 ******************************************************************************/
1561 HRESULT WINAPI
EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
){
1563 ICOM_THIS(EnumMonikerImpl
,iface
);
1565 if ((This
->currentPos
+celt
) >= This
->tabSize
)
1568 This
->currentPos
+=celt
;
1573 /******************************************************************************
1574 * EnumMonikerImpl_Reset
1575 ******************************************************************************/
1576 HRESULT WINAPI
EnumMonikerImpl_Reset(IEnumMoniker
* iface
){
1578 ICOM_THIS(EnumMonikerImpl
,iface
);
1585 /******************************************************************************
1586 * EnumMonikerImpl_Clone
1587 ******************************************************************************/
1588 HRESULT WINAPI
EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
){
1590 ICOM_THIS(EnumMonikerImpl
,iface
);
1592 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabSize
,This
->currentPos
,TRUE
,ppenum
);
1595 /******************************************************************************
1596 * EnumMonikerImpl_CreateEnumMoniker
1597 ******************************************************************************/
1598 HRESULT WINAPI
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,
1602 IEnumMoniker
** ppmk
)
1604 EnumMonikerImpl
* newEnumMoniker
;
1608 newEnumMoniker
= HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl
));
1610 if (newEnumMoniker
== 0)
1611 return STG_E_INSUFFICIENTMEMORY
;
1613 if (currentPos
> tabSize
)
1614 return E_INVALIDARG
;
1616 /* Initialize the virtual function table. */
1617 ICOM_VTBL(newEnumMoniker
) = &VT_EnumMonikerImpl
;
1618 newEnumMoniker
->ref
= 0;
1620 newEnumMoniker
->tabSize
=tabSize
;
1621 newEnumMoniker
->currentPos
=currentPos
;
1623 newEnumMoniker
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,tabSize
*sizeof(IMoniker
));
1625 if (newEnumMoniker
->tabMoniker
==NULL
)
1626 return E_OUTOFMEMORY
;
1629 for (i
=0;i
<tabSize
;i
++){
1631 newEnumMoniker
->tabMoniker
[i
]=tabMoniker
[i
];
1632 IMoniker_AddRef(tabMoniker
[i
]);
1635 for (i
=tabSize
-1;i
>=0;i
--){
1637 newEnumMoniker
->tabMoniker
[tabSize
-i
-1]=tabMoniker
[i
];
1638 IMoniker_AddRef(tabMoniker
[i
]);
1641 *ppmk
=(IEnumMoniker
*)newEnumMoniker
;
1646 /******************************************************************************
1647 * CreateGenericComposite [OLE32.56]
1648 ******************************************************************************/
1649 HRESULT WINAPI
CreateGenericComposite(LPMONIKER pmkFirst
, LPMONIKER pmkRest
, LPMONIKER
* ppmkComposite
)
1651 CompositeMonikerImpl
* newCompositeMoniker
= 0;
1654 TRACE("(%p,%p,%p)\n",pmkFirst
,pmkRest
,ppmkComposite
);
1656 if (ppmkComposite
==NULL
)
1661 if (pmkFirst
==NULL
&& pmkRest
!=NULL
){
1663 *ppmkComposite
=pmkRest
;
1666 else if (pmkFirst
!=NULL
&& pmkRest
==NULL
){
1667 *ppmkComposite
=pmkFirst
;
1670 else if (pmkFirst
==NULL
&& pmkRest
==NULL
)
1673 newCompositeMoniker
= HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl
));
1675 if (newCompositeMoniker
== 0)
1676 return STG_E_INSUFFICIENTMEMORY
;
1678 hr
= CompositeMonikerImpl_Construct(newCompositeMoniker
,pmkFirst
,pmkRest
);
1682 HeapFree(GetProcessHeap(),0,newCompositeMoniker
);
1685 if (newCompositeMoniker
->tabLastIndex
==1)
1687 hr
= IMoniker_QueryInterface(newCompositeMoniker
->tabMoniker
[0],&IID_IMoniker
,(void**)ppmkComposite
);
1690 hr
= CompositeMonikerImpl_QueryInterface((IMoniker
*)newCompositeMoniker
,&IID_IMoniker
,(void**)ppmkComposite
);
1695 /******************************************************************************
1696 * MonikerCommonPrefixWith [OLE32.82]
1697 ******************************************************************************/
1698 HRESULT WINAPI
MonikerCommonPrefixWith(IMoniker
* pmkThis
,IMoniker
* pmkOther
,IMoniker
** ppmkCommon
)
1700 FIXME("(),stub!\n");