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
29 * interface to test whether two monikers are equal. That's why IROTData
30 * interface is implemented by monikers.
32 ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/
34 ULONG ref; /* reference counter for this object */
36 IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */
38 ULONG tabSize; /* size of tabMoniker */
40 ULONG tabLastIndex; /* first free index in tabMoniker */
42 } CompositeMonikerImpl;
45 /* EnumMoniker data structure */
46 typedef struct EnumMonikerImpl{
48 ICOM_VFIELD(IEnumMoniker); /* VTable relative to the IEnumMoniker interface.*/
50 ULONG ref; /* reference counter for this object */
52 IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
54 ULONG tabSize; /* size of tabMoniker */
56 ULONG currentPos; /* index pointer on the current moniker */
61 /********************************************************************************/
62 /* CompositeMoniker prototype functions : */
64 /* IUnknown prototype functions */
65 static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
66 static ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface);
67 static ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface);
69 /* IPersist prototype functions */
70 static HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
72 /* IPersistStream prototype functions */
73 static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface);
74 static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm);
75 static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
76 static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
78 /* IMoniker prototype functions */
79 static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
80 static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
81 static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
82 static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
83 static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
84 static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
85 static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
86 static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
87 static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime);
88 static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
89 static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
90 static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
91 static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
92 static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
93 static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
95 /********************************************************************************/
96 /* IROTData prototype functions */
98 /* IUnknown prototype functions */
99 static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
100 static ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface);
101 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface);
103 /* IROTData prototype function */
104 static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
106 /* Local function used by CompositeMoniker implementation */
107 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest);
108 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface);
110 /********************************************************************************/
111 /* IEnumMoniker prototype functions */
113 /* IUnknown prototype functions */
114 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject);
115 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface);
116 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface);
118 /* IEnumMoniker prototype functions */
119 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched);
120 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt);
121 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface);
122 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum);
124 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
126 /********************************************************************************/
127 /* Virtual function table for the CompositeMonikerImpl class which includes */
128 /* IPersist, IPersistStream and IMoniker functions. */
130 static ICOM_VTABLE(IMoniker) VT_CompositeMonikerImpl =
132 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
133 CompositeMonikerImpl_QueryInterface,
134 CompositeMonikerImpl_AddRef,
135 CompositeMonikerImpl_Release,
136 CompositeMonikerImpl_GetClassID,
137 CompositeMonikerImpl_IsDirty,
138 CompositeMonikerImpl_Load,
139 CompositeMonikerImpl_Save,
140 CompositeMonikerImpl_GetSizeMax,
141 CompositeMonikerImpl_BindToObject,
142 CompositeMonikerImpl_BindToStorage,
143 CompositeMonikerImpl_Reduce,
144 CompositeMonikerImpl_ComposeWith,
145 CompositeMonikerImpl_Enum,
146 CompositeMonikerImpl_IsEqual,
147 CompositeMonikerImpl_Hash,
148 CompositeMonikerImpl_IsRunning,
149 CompositeMonikerImpl_GetTimeOfLastChange,
150 CompositeMonikerImpl_Inverse,
151 CompositeMonikerImpl_CommonPrefixWith,
152 CompositeMonikerImpl_RelativePathTo,
153 CompositeMonikerImpl_GetDisplayName,
154 CompositeMonikerImpl_ParseDisplayName,
155 CompositeMonikerImpl_IsSystemMoniker
158 /********************************************************************************/
159 /* Virtual function table for the IROTData class. */
160 static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
162 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
163 CompositeMonikerROTDataImpl_QueryInterface,
164 CompositeMonikerROTDataImpl_AddRef,
165 CompositeMonikerROTDataImpl_Release,
166 CompositeMonikerROTDataImpl_GetComparaisonData
169 /********************************************************************************/
170 /* Virtual function table for the IROTData class */
171 static ICOM_VTABLE(IEnumMoniker) VT_EnumMonikerImpl =
173 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
174 EnumMonikerImpl_QueryInterface,
175 EnumMonikerImpl_AddRef,
176 EnumMonikerImpl_Release,
177 EnumMonikerImpl_Next,
178 EnumMonikerImpl_Skip,
179 EnumMonikerImpl_Reset,
180 EnumMonikerImpl_Clone
183 /*******************************************************************************
184 * CompositeMoniker_QueryInterface
185 *******************************************************************************/
186 HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
188 ICOM_THIS(CompositeMonikerImpl,iface);
190 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
192 /* Perform a sanity check on the parameters.*/
193 if ( (This==0) || (ppvObject==0) )
196 /* Initialize the return parameter */
199 /* Compare the riid with the interface IDs implemented by this object.*/
200 if (IsEqualIID(&IID_IUnknown, riid) ||
201 IsEqualIID(&IID_IPersist, riid) ||
202 IsEqualIID(&IID_IPersistStream, riid) ||
203 IsEqualIID(&IID_IMoniker, riid)
206 else if (IsEqualIID(&IID_IROTData, riid))
207 *ppvObject = (IROTData*)&(This->lpvtbl2);
209 /* Check that we obtained an interface.*/
211 return E_NOINTERFACE;
213 /* Query Interface always increases the reference count by one when it is successful */
214 CompositeMonikerImpl_AddRef(iface);
219 /******************************************************************************
220 * CompositeMoniker_AddRef
221 ******************************************************************************/
222 ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)
224 ICOM_THIS(CompositeMonikerImpl,iface);
226 TRACE("(%p)\n",This);
228 return ++(This->ref);
231 /******************************************************************************
232 * CompositeMoniker_Release
233 ******************************************************************************/
234 ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
236 ICOM_THIS(CompositeMonikerImpl,iface);
239 TRACE("(%p)\n",This);
243 /* destroy the object if there's no more reference on it */
246 /* release all the components before destroying this object */
247 for (i=0;i<This->tabLastIndex;i++)
248 IMoniker_Release(This->tabMoniker[i]);
250 CompositeMonikerImpl_Destroy(This);
257 /******************************************************************************
258 * CompositeMoniker_GetClassID
259 ******************************************************************************/
260 HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
262 TRACE("(%p,%p),stub!\n",iface,pClassID);
267 *pClassID = CLSID_CompositeMoniker;
272 /******************************************************************************
273 * CompositeMoniker_IsDirty
274 ******************************************************************************/
275 HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)
277 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
278 method in the OLE-provided moniker interfaces always return S_FALSE because
279 their internal state never changes. */
281 TRACE("(%p)\n",iface);
286 /******************************************************************************
287 * CompositeMoniker_Load
288 ******************************************************************************/
289 HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
296 ICOM_THIS(CompositeMonikerImpl,iface);
298 TRACE("(%p,%p)\n",iface,pStm);
300 /* this function call OleLoadFromStream function for each moniker within this object */
302 /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
303 res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
305 if (SUCCEEDED(res)&& constant!=3)
310 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
312 res=ReadClassStm(pStm,&clsid);
313 DPRINTF("res=%ld",res);
317 if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
318 res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
321 res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
325 else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
326 CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
329 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
333 else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
334 CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
337 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
341 else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
347 /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */
352 /* resize the table if needed */
353 if (++This->tabLastIndex==This->tabSize){
355 This->tabSize+=BLOCK_TAB_SIZE;
356 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
358 if (This->tabMoniker==NULL)
359 return E_OUTOFMEMORY;
366 /******************************************************************************
367 * CompositeMoniker_Save
368 ******************************************************************************/
369 HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
372 IEnumMoniker *enumMk;
376 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
378 /* This function calls OleSaveToStream function for each moniker within
380 * When I tested this function in windows, I usually found this constant
381 * at the beginning of the stream. I don't known why (there's no
382 * indication in the specification) !
384 res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
386 IMoniker_Enum(iface,TRUE,&enumMk);
388 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
390 res=OleSaveToStream((IPersistStream*)pmk,pStm);
392 IMoniker_Release(pmk);
396 IEnumMoniker_Release(pmk);
401 IEnumMoniker_Release(enumMk);
406 /******************************************************************************
407 * CompositeMoniker_GetSizeMax
408 ******************************************************************************/
409 HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
411 IEnumMoniker *enumMk;
413 ULARGE_INTEGER ptmpSize;
415 /* The sizeMax of this object is calculated by calling GetSizeMax on
416 * each moniker within this object then summing all returned values
419 TRACE("(%p,%p)\n",iface,pcbSize);
424 pcbSize->s.LowPart =0;
425 pcbSize->s.HighPart=0;
427 IMoniker_Enum(iface,TRUE,&enumMk);
429 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){
431 IMoniker_GetSizeMax(pmk,&ptmpSize);
433 IMoniker_Release(pmk);
435 pcbSize->s.LowPart +=ptmpSize.s.LowPart;
436 pcbSize->s.HighPart+=ptmpSize.s.HighPart;
439 IEnumMoniker_Release(enumMk);
444 /******************************************************************************
445 * Composite-Moniker_Construct (local function)
446 *******************************************************************************/
447 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest)
450 IEnumMoniker *enumMoniker;
454 TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
456 /* Initialize the virtual function table. */
457 This->lpvtbl1 = &VT_CompositeMonikerImpl;
458 This->lpvtbl2 = &VT_ROTDataImpl;
461 This->tabSize=BLOCK_TAB_SIZE;
462 This->tabLastIndex=0;
464 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
465 if (This->tabMoniker==NULL)
466 return E_OUTOFMEMORY;
468 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
470 /* put the first moniker contents in the beginning of the table */
471 if (mkSys!=MKSYS_GENERICCOMPOSITE){
473 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
474 IMoniker_AddRef(pmkFirst);
478 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
480 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
483 if (++This->tabLastIndex==This->tabSize){
485 This->tabSize+=BLOCK_TAB_SIZE;
486 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
488 if (This->tabMoniker==NULL)
489 return E_OUTOFMEMORY;
493 IEnumMoniker_Release(enumMoniker);
496 /* put the rest moniker contents after the first one and make simplification if needed */
498 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
500 if (mkSys!=MKSYS_GENERICCOMPOSITE){
502 /* add a simple moniker to the moniker table */
504 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
506 if (res==MK_E_NEEDGENERIC){
508 /* there's no simplification in this case */
509 This->tabMoniker[This->tabLastIndex]=pmkRest;
511 This->tabLastIndex++;
513 IMoniker_AddRef(pmkRest);
515 else if (tempMk==NULL){
517 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
518 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
520 This->tabLastIndex--;
522 else if (SUCCEEDED(res)){
524 /* the non-generic composition was successful so we can make a simplification in this case */
525 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
527 This->tabMoniker[This->tabLastIndex-1]=tempMk;
531 /* resize tabMoniker if needed */
532 if (This->tabLastIndex==This->tabSize){
534 This->tabSize+=BLOCK_TAB_SIZE;
536 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
538 if (This->tabMoniker==NULL)
539 return E_OUTOFMEMORY;
544 /* add a composite moniker to the moniker table (do the same thing
545 * for each moniker within the composite moniker as a simple moniker
546 * (see above for how to add a simple moniker case) )
548 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
550 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
552 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
554 if (res==MK_E_NEEDGENERIC){
556 This->tabLastIndex++;
558 else if (tempMk==NULL){
560 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
561 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
562 This->tabLastIndex--;
566 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
568 This->tabMoniker[This->tabLastIndex-1]=tempMk;
571 if (This->tabLastIndex==This->tabSize){
573 This->tabSize+=BLOCK_TAB_SIZE;
575 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
577 if (This->tabMoniker==NULL)
578 return E_OUTOFMEMORY;
582 IEnumMoniker_Release(enumMoniker);
588 /******************************************************************************
589 * CompositeMoniker_Destroy (local function)
590 *******************************************************************************/
591 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This)
593 TRACE("(%p)\n",This);
595 HeapFree(GetProcessHeap(),0,This->tabMoniker);
597 HeapFree(GetProcessHeap(),0,This);
602 /******************************************************************************
603 * CompositeMoniker_BindToObject
604 ******************************************************************************/
605 HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,
612 IRunningObjectTable *prot;
613 IMoniker *tempMk,*antiMk,*mostRigthMk;
614 IEnumMoniker *enumMoniker;
616 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
622 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
623 /* object for the requested interface pointer. */
626 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
630 /* if the requested class was loaded befor ! we dont need to reload it */
631 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
638 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
639 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
641 IMoniker_Enum(iface,FALSE,&enumMoniker);
642 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
643 IEnumMoniker_Release(enumMoniker);
645 res=CreateAntiMoniker(&antiMk);
646 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
647 IMoniker_Release(antiMk);
649 res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
651 IMoniker_Release(tempMk);
652 IMoniker_Release(mostRigthMk);
658 /******************************************************************************
659 * CompositeMoniker_BindToStorage
660 ******************************************************************************/
661 HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,
668 IMoniker *tempMk,*antiMk,*mostRigthMk;
669 IEnumMoniker *enumMoniker;
671 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
675 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
676 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
678 if (pmkToLeft!=NULL){
680 IMoniker_Enum(iface,FALSE,&enumMoniker);
681 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
682 IEnumMoniker_Release(enumMoniker);
684 res=CreateAntiMoniker(&antiMk);
685 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
686 IMoniker_Release(antiMk);
688 res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
690 IMoniker_Release(tempMk);
692 IMoniker_Release(mostRigthMk);
697 return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
700 /******************************************************************************
701 * CompositeMoniker_Reduce
702 ******************************************************************************/
703 HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,
705 DWORD dwReduceHowFar,
706 IMoniker** ppmkToLeft,
707 IMoniker** ppmkReduced)
710 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
711 IEnumMoniker *enumMoniker;
713 TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
715 if (ppmkReduced==NULL)
718 /* This method recursively calls Reduce for each of its component monikers. */
720 if (ppmkToLeft==NULL){
722 IMoniker_Enum(iface,FALSE,&enumMoniker);
723 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
724 IEnumMoniker_Release(enumMoniker);
726 res=CreateAntiMoniker(&antiMk);
727 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
728 IMoniker_Release(antiMk);
730 return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
732 else if (*ppmkToLeft==NULL)
734 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
738 /* separate the composite moniker in to left and right moniker */
739 IMoniker_Enum(iface,FALSE,&enumMoniker);
740 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
741 IEnumMoniker_Release(enumMoniker);
743 res=CreateAntiMoniker(&antiMk);
744 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
745 IMoniker_Release(antiMk);
747 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
748 /* of the reduced components */
749 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
750 CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
753 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
756 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
758 IMoniker_AddRef(iface);
762 return MK_S_REDUCED_TO_SELF;
767 /******************************************************************************
768 * CompositeMoniker_ComposeWith
769 ******************************************************************************/
770 HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,
772 BOOL fOnlyIfNotGeneric,
773 IMoniker** ppmkComposite)
775 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
777 if ((ppmkComposite==NULL)||(pmkRight==NULL))
782 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
783 /* otherwise, the method returns the result of combining the two monikers by calling the */
784 /* CreateGenericComposite function */
786 if (fOnlyIfNotGeneric)
787 return MK_E_NEEDGENERIC;
789 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
792 /******************************************************************************
793 * CompositeMoniker_Enum
794 ******************************************************************************/
795 HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
797 ICOM_THIS(CompositeMonikerImpl,iface);
799 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
801 if (ppenumMoniker == NULL)
804 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
807 /******************************************************************************
808 * CompositeMoniker_IsEqual
809 ******************************************************************************/
810 HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
812 IEnumMoniker *enumMoniker1,*enumMoniker2;
813 IMoniker *tempMk1,*tempMk2;
814 HRESULT res1,res2,res;
816 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
818 if (pmkOtherMoniker==NULL)
821 /* This method returns S_OK if the components of both monikers are equal when compared in the */
822 /* left-to-right order.*/
823 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
825 if (enumMoniker1==NULL)
828 IMoniker_Enum(iface,TRUE,&enumMoniker2);
832 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
833 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
835 if((res1==S_OK)&&(res2==S_OK)){
837 if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
844 else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
854 IMoniker_Release(tempMk1);
857 IMoniker_Release(tempMk2);
860 IEnumMoniker_Release(enumMoniker1);
861 IEnumMoniker_Release(enumMoniker2);
865 /******************************************************************************
866 * CompositeMoniker_Hash
867 ******************************************************************************/
868 HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
875 /******************************************************************************
876 * CompositeMoniker_IsRunning
877 ******************************************************************************/
878 HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,
881 IMoniker* pmkNewlyRunning)
883 IRunningObjectTable* rot;
885 IMoniker *tempMk,*antiMk,*mostRigthMk;
886 IEnumMoniker *enumMoniker;
888 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
890 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
891 if (pmkToLeft!=NULL){
893 CreateGenericComposite(pmkToLeft,iface,&tempMk);
895 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
897 IMoniker_Release(tempMk);
902 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
903 /* to this moniker */
905 if (pmkNewlyRunning!=NULL)
907 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
918 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
919 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
920 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
921 /* the composite as the pmkToLeft parameter for that call. */
923 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
928 res = IRunningObjectTable_IsRunning(rot,iface);
929 IRunningObjectTable_Release(rot);
936 IMoniker_Enum(iface,FALSE,&enumMoniker);
937 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
938 IEnumMoniker_Release(enumMoniker);
940 res=CreateAntiMoniker(&antiMk);
941 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
942 IMoniker_Release(antiMk);
944 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
946 IMoniker_Release(tempMk);
947 IMoniker_Release(mostRigthMk);
954 /******************************************************************************
955 * CompositeMoniker_GetTimeOfLastChange
956 ******************************************************************************/
957 HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
960 FILETIME* pCompositeTime)
962 IRunningObjectTable* rot;
964 IMoniker *tempMk,*antiMk,*mostRigthMk;
965 IEnumMoniker *enumMoniker;
967 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
969 if (pCompositeTime==NULL)
972 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
973 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
974 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
975 /* of the composite as the pmkToLeft parameter for that call. */
976 if (pmkToLeft!=NULL){
978 res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
980 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
985 if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
989 IMoniker_Enum(iface,FALSE,&enumMoniker);
990 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
991 IEnumMoniker_Release(enumMoniker);
993 res=CreateAntiMoniker(&antiMk);
994 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
995 IMoniker_Release(antiMk);
997 res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
999 IMoniker_Release(tempMk);
1000 IMoniker_Release(mostRigthMk);
1005 return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
1008 /******************************************************************************
1009 * CompositeMoniker_Inverse
1010 ******************************************************************************/
1011 HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
1014 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
1015 IEnumMoniker *enumMoniker;
1017 TRACE("(%p,%p)\n",iface,ppmk);
1022 /* This method returns a composite moniker that consists of the inverses of each of the components */
1023 /* of the original composite, stored in reverse order */
1025 res=CreateAntiMoniker(&antiMk);
1026 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1027 IMoniker_Release(antiMk);
1031 return IMoniker_Inverse(iface,ppmk);
1035 IMoniker_Enum(iface,FALSE,&enumMoniker);
1036 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1037 IEnumMoniker_Release(enumMoniker);
1039 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
1040 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
1042 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
1044 IMoniker_Release(tempMk);
1045 IMoniker_Release(mostRigthMk);
1046 IMoniker_Release(tempInvMk);
1047 IMoniker_Release(mostRigthInvMk);
1053 /******************************************************************************
1054 * CompositeMoniker_CommonPrefixWith
1055 ******************************************************************************/
1056 HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1060 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
1061 IEnumMoniker *enumMoniker1,*enumMoniker2;
1062 ULONG i,nbCommonMk=0;
1064 /* If the other moniker is a composite, this method compares the components of each composite from left */
1065 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1066 /* of the leftmost components were common to both monikers. */
1068 if (ppmkPrefix==NULL)
1074 return MK_E_NOPREFIX;
1076 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1078 if((mkSys==MKSYS_GENERICCOMPOSITE)){
1080 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1081 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
1085 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1086 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
1088 if ((res1==S_FALSE) && (res2==S_FALSE)){
1090 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1092 IMoniker_AddRef(iface);
1095 else if ((res1==S_OK) && (res2==S_OK)){
1097 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
1105 else if (res1==S_OK){
1107 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1108 /* ppmkPrefix to the other moniker. */
1109 *ppmkPrefix=pmkOther;
1113 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1114 /* to this moniker. */
1120 IEnumMoniker_Release(enumMoniker1);
1121 IEnumMoniker_Release(enumMoniker2);
1123 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1125 return MK_E_NOPREFIX;
1127 IEnumMoniker_Reset(enumMoniker1);
1129 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1131 /* if we have more than one commun moniker the result will be a composite moniker */
1134 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1135 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1136 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
1137 IMoniker_Release(tempMk1);
1138 IMoniker_Release(tempMk2);
1140 /* compose all common monikers in a composite moniker */
1141 for(i=0;i<nbCommonMk;i++){
1143 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1145 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
1147 IMoniker_Release(*ppmkPrefix);
1149 IMoniker_Release(tempMk1);
1151 *ppmkPrefix=tempMk2;
1156 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1157 *ppmkPrefix=tempMk1;
1163 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1166 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1168 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1170 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
1172 *ppmkPrefix=pmkOther;
1177 return MK_E_NOPREFIX;
1180 /***************************************************************************************************
1181 * GetAfterCommonPrefix (local function)
1182 * This function returns a moniker that consist of the remainder when the common prefix is removed
1183 ***************************************************************************************************/
1184 VOID WINAPI GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
1186 IMoniker *tempMk,*tempMk1,*tempMk2;
1187 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
1194 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1195 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
1196 /* on the first difference. */
1197 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
1199 IMoniker_IsSystemMoniker(commonMk,&mkSys);
1201 if (mkSys==MKSYS_GENERICCOMPOSITE){
1203 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
1206 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1207 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
1209 if ((res1==S_FALSE)||(res2==S_FALSE)){
1215 IMoniker_Release(tempMk1);
1216 IMoniker_Release(tempMk1);
1220 IMoniker_Release(tempMk1);
1221 IMoniker_Release(tempMk1);
1225 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1226 IMoniker_Release(tempMk1);
1229 /* count the number of elements in the enumerator after the common prefix */
1230 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1232 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1234 IMoniker_Release(tempMk);;
1239 /* create a generic composite moniker with monikers located after the common prefix */
1240 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1249 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1251 CreateGenericComposite(tempMk1,tempMk2,restMk);
1253 IMoniker_Release(tempMk1);
1255 IMoniker_Release(tempMk2);
1257 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1259 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1261 IMoniker_Release(tempMk1);
1263 IMoniker_Release(*restMk);
1269 /******************************************************************************
1270 * CompositeMoniker_RelativePathTo
1271 ******************************************************************************/
1272 HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkRelPath)
1275 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1277 TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1279 if (ppmkRelPath==NULL)
1284 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1285 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1286 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1288 /* finds the common prefix of the two monikers */
1289 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1291 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1292 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1294 *ppmkRelPath=pmkOther;
1295 IMoniker_AddRef(pmkOther);
1299 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1300 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1302 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1303 /* moniker when the common prefix is removed */
1306 IMoniker_Inverse(restThisMk,ppmkRelPath);
1307 IMoniker_Release(restThisMk);
1309 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1310 /* when the common prefix is removed */
1311 else if (res==MK_S_ME){
1313 *ppmkRelPath=restOtherMk;
1314 IMoniker_AddRef(restOtherMk);
1316 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1317 /* moniker on the right of it. */
1318 else if (res==S_OK){
1320 IMoniker_Inverse(restThisMk,&invRestThisMk);
1321 IMoniker_Release(restThisMk);
1322 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1323 IMoniker_Release(invRestThisMk);
1324 IMoniker_Release(restOtherMk);
1329 /******************************************************************************
1330 * CompositeMoniker_GetDisplayName
1331 ******************************************************************************/
1332 HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,
1334 IMoniker* pmkToLeft,
1335 LPOLESTR *ppszDisplayName)
1338 IEnumMoniker *enumMoniker;
1342 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1344 if (ppszDisplayName==NULL)
1347 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1349 if (*ppszDisplayName==NULL)
1350 return E_OUTOFMEMORY;
1352 /* This method returns the concatenation of the display names returned by each component moniker of */
1355 **ppszDisplayName=0;
1357 IMoniker_Enum(iface,TRUE,&enumMoniker);
1359 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1361 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1363 lengthStr+=lstrlenW(tempStr);
1365 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1367 if (*ppszDisplayName==NULL)
1368 return E_OUTOFMEMORY;
1370 strcatW(*ppszDisplayName,tempStr);
1372 CoTaskMemFree(tempStr);
1373 IMoniker_Release(tempMk);
1376 IEnumMoniker_Release(enumMoniker);
1381 /******************************************************************************
1382 * CompositeMoniker_ParseDisplayName
1383 ******************************************************************************/
1384 HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,
1386 IMoniker* pmkToLeft,
1387 LPOLESTR pszDisplayName,
1391 IEnumMoniker *enumMoniker;
1392 IMoniker *tempMk,*mostRigthMk,*antiMk;
1393 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1394 /* passing everything else as the pmkToLeft parameter for that call. */
1396 /* get the most right moniker */
1397 IMoniker_Enum(iface,FALSE,&enumMoniker);
1398 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1399 IEnumMoniker_Release(enumMoniker);
1401 /* get the left moniker */
1402 CreateAntiMoniker(&antiMk);
1403 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1404 IMoniker_Release(antiMk);
1406 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1409 /******************************************************************************
1410 * CompositeMoniker_IsSystemMoniker
1411 ******************************************************************************/
1412 HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1414 TRACE("(%p,%p)\n",iface,pwdMksys);
1419 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1424 /*******************************************************************************
1425 * CompositeMonikerIROTData_QueryInterface
1426 *******************************************************************************/
1427 HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1430 ICOM_THIS_From_IROTData(IMoniker, iface);
1432 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
1434 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1437 /***********************************************************************
1438 * CompositeMonikerIROTData_AddRef
1440 ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1442 ICOM_THIS_From_IROTData(IMoniker, iface);
1444 TRACE("(%p)\n",iface);
1446 return CompositeMonikerImpl_AddRef(This);
1449 /***********************************************************************
1450 * CompositeMonikerIROTData_Release
1452 ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1454 ICOM_THIS_From_IROTData(IMoniker, iface);
1456 TRACE("(%p)\n",iface);
1458 return CompositeMonikerImpl_Release(This);
1461 /******************************************************************************
1462 * CompositeMonikerIROTData_GetComparaisonData
1463 ******************************************************************************/
1464 HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1469 FIXME("(),stub!\n");
1473 /******************************************************************************
1474 * EnumMonikerImpl_QueryInterface
1475 ******************************************************************************/
1476 HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1478 ICOM_THIS(EnumMonikerImpl,iface);
1480 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1482 /* Perform a sanity check on the parameters.*/
1483 if ( (This==0) || (ppvObject==0) )
1484 return E_INVALIDARG;
1486 /* Initialize the return parameter */
1489 /* Compare the riid with the interface IDs implemented by this object.*/
1490 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1493 /* Check that we obtained an interface.*/
1494 if ((*ppvObject)==0)
1495 return E_NOINTERFACE;
1497 /* Query Interface always increases the reference count by one when it is successful */
1498 EnumMonikerImpl_AddRef(iface);
1503 /******************************************************************************
1504 * EnumMonikerImpl_AddRef
1505 ******************************************************************************/
1506 ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1508 ICOM_THIS(EnumMonikerImpl,iface);
1510 TRACE("(%p)\n",This);
1512 return ++(This->ref);
1516 /******************************************************************************
1517 * EnumMonikerImpl_Release
1518 ******************************************************************************/
1519 ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1521 ICOM_THIS(EnumMonikerImpl,iface);
1524 TRACE("(%p)\n",This);
1528 /* destroy the object if there's no more reference on it */
1531 for(i=0;i<This->tabSize;i++)
1532 IMoniker_Release(This->tabMoniker[i]);
1534 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1535 HeapFree(GetProcessHeap(),0,This);
1542 /******************************************************************************
1543 * EnumMonikerImpl_Next
1544 ******************************************************************************/
1545 HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){
1547 ICOM_THIS(EnumMonikerImpl,iface);
1550 /* retrieve the requested number of moniker from the current position */
1551 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1553 rgelt[i]=This->tabMoniker[This->currentPos++];
1555 if (pceltFethed!=NULL)
1564 /******************************************************************************
1565 * EnumMonikerImpl_Skip
1566 ******************************************************************************/
1567 HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){
1569 ICOM_THIS(EnumMonikerImpl,iface);
1571 if ((This->currentPos+celt) >= This->tabSize)
1574 This->currentPos+=celt;
1579 /******************************************************************************
1580 * EnumMonikerImpl_Reset
1581 ******************************************************************************/
1582 HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){
1584 ICOM_THIS(EnumMonikerImpl,iface);
1591 /******************************************************************************
1592 * EnumMonikerImpl_Clone
1593 ******************************************************************************/
1594 HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){
1596 ICOM_THIS(EnumMonikerImpl,iface);
1598 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1601 /******************************************************************************
1602 * EnumMonikerImpl_CreateEnumMoniker
1603 ******************************************************************************/
1604 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,
1608 IEnumMoniker ** ppmk)
1610 EnumMonikerImpl* newEnumMoniker;
1614 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1616 if (newEnumMoniker == 0)
1617 return STG_E_INSUFFICIENTMEMORY;
1619 if (currentPos > tabSize)
1620 return E_INVALIDARG;
1622 /* Initialize the virtual function table. */
1623 ICOM_VTBL(newEnumMoniker) = &VT_EnumMonikerImpl;
1624 newEnumMoniker->ref = 0;
1626 newEnumMoniker->tabSize=tabSize;
1627 newEnumMoniker->currentPos=currentPos;
1629 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1631 if (newEnumMoniker->tabMoniker==NULL)
1632 return E_OUTOFMEMORY;
1635 for (i=0;i<tabSize;i++){
1637 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1638 IMoniker_AddRef(tabMoniker[i]);
1641 for (i=tabSize-1;i>=0;i--){
1643 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1644 IMoniker_AddRef(tabMoniker[i]);
1647 *ppmk=(IEnumMoniker*)newEnumMoniker;
1652 /******************************************************************************
1653 * CreateGenericComposite [OLE32.56]
1654 ******************************************************************************/
1655 HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite)
1657 CompositeMonikerImpl* newCompositeMoniker = 0;
1660 TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1662 if (ppmkComposite==NULL)
1667 if (pmkFirst==NULL && pmkRest!=NULL){
1669 *ppmkComposite=pmkRest;
1672 else if (pmkFirst!=NULL && pmkRest==NULL){
1673 *ppmkComposite=pmkFirst;
1676 else if (pmkFirst==NULL && pmkRest==NULL)
1679 newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
1681 if (newCompositeMoniker == 0)
1682 return STG_E_INSUFFICIENTMEMORY;
1684 hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
1688 HeapFree(GetProcessHeap(),0,newCompositeMoniker);
1691 if (newCompositeMoniker->tabLastIndex==1)
1693 hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
1696 hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
1701 /******************************************************************************
1702 * MonikerCommonPrefixWith [OLE32.82]
1703 ******************************************************************************/
1704 HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1706 FIXME("(),stub!\n");