2 * CompositeMonikers implementation
4 * Copyright 1999 Noomen Hamza
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
30 #include "wine/debug.h"
31 #include "wine/unicode.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ole);
37 const CLSID CLSID_CompositeMoniker = {
38 0x309, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
41 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
43 /* CompositeMoniker data structure */
44 typedef struct CompositeMonikerImpl{
46 ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/
48 /* The ROT (RunningObjectTable implementation) uses the IROTData
49 * interface to test whether two monikers are equal. That's why IROTData
50 * interface is implemented by monikers.
52 ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/
54 ULONG ref; /* reference counter for this object */
56 IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */
58 ULONG tabSize; /* size of tabMoniker */
60 ULONG tabLastIndex; /* first free index in tabMoniker */
62 } CompositeMonikerImpl;
65 /* EnumMoniker data structure */
66 typedef struct EnumMonikerImpl{
68 ICOM_VFIELD(IEnumMoniker); /* VTable relative to the IEnumMoniker interface.*/
70 ULONG ref; /* reference counter for this object */
72 IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
74 ULONG tabSize; /* size of tabMoniker */
76 ULONG currentPos; /* index pointer on the current moniker */
81 /********************************************************************************/
82 /* CompositeMoniker prototype functions : */
84 /* IUnknown prototype functions */
85 static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
86 static ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface);
87 static ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface);
89 /* IPersist prototype functions */
90 static HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
92 /* IPersistStream prototype functions */
93 static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface);
94 static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm);
95 static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
96 static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
98 /* IMoniker prototype functions */
99 static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
100 static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
101 static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
102 static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
103 static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
104 static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
105 static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
106 static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
107 static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime);
108 static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
109 static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
110 static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
111 static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
112 static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
113 static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
115 /********************************************************************************/
116 /* IROTData prototype functions */
118 /* IUnknown prototype functions */
119 static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
120 static ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface);
121 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface);
123 /* IROTData prototype function */
124 static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
126 /* Local function used by CompositeMoniker implementation */
127 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest);
128 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface);
130 /********************************************************************************/
131 /* IEnumMoniker prototype functions */
133 /* IUnknown prototype functions */
134 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject);
135 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface);
136 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface);
138 /* IEnumMoniker prototype functions */
139 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched);
140 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt);
141 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface);
142 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum);
144 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
146 /********************************************************************************/
147 /* Virtual function table for the CompositeMonikerImpl class which includes */
148 /* IPersist, IPersistStream and IMoniker functions. */
150 static ICOM_VTABLE(IMoniker) VT_CompositeMonikerImpl =
152 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
153 CompositeMonikerImpl_QueryInterface,
154 CompositeMonikerImpl_AddRef,
155 CompositeMonikerImpl_Release,
156 CompositeMonikerImpl_GetClassID,
157 CompositeMonikerImpl_IsDirty,
158 CompositeMonikerImpl_Load,
159 CompositeMonikerImpl_Save,
160 CompositeMonikerImpl_GetSizeMax,
161 CompositeMonikerImpl_BindToObject,
162 CompositeMonikerImpl_BindToStorage,
163 CompositeMonikerImpl_Reduce,
164 CompositeMonikerImpl_ComposeWith,
165 CompositeMonikerImpl_Enum,
166 CompositeMonikerImpl_IsEqual,
167 CompositeMonikerImpl_Hash,
168 CompositeMonikerImpl_IsRunning,
169 CompositeMonikerImpl_GetTimeOfLastChange,
170 CompositeMonikerImpl_Inverse,
171 CompositeMonikerImpl_CommonPrefixWith,
172 CompositeMonikerImpl_RelativePathTo,
173 CompositeMonikerImpl_GetDisplayName,
174 CompositeMonikerImpl_ParseDisplayName,
175 CompositeMonikerImpl_IsSystemMoniker
178 /********************************************************************************/
179 /* Virtual function table for the IROTData class. */
180 static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
182 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
183 CompositeMonikerROTDataImpl_QueryInterface,
184 CompositeMonikerROTDataImpl_AddRef,
185 CompositeMonikerROTDataImpl_Release,
186 CompositeMonikerROTDataImpl_GetComparaisonData
189 /********************************************************************************/
190 /* Virtual function table for the IROTData class */
191 static ICOM_VTABLE(IEnumMoniker) VT_EnumMonikerImpl =
193 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
194 EnumMonikerImpl_QueryInterface,
195 EnumMonikerImpl_AddRef,
196 EnumMonikerImpl_Release,
197 EnumMonikerImpl_Next,
198 EnumMonikerImpl_Skip,
199 EnumMonikerImpl_Reset,
200 EnumMonikerImpl_Clone
203 /*******************************************************************************
204 * CompositeMoniker_QueryInterface
205 *******************************************************************************/
206 HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
208 ICOM_THIS(CompositeMonikerImpl,iface);
210 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
212 /* Perform a sanity check on the parameters.*/
213 if ( (This==0) || (ppvObject==0) )
216 /* Initialize the return parameter */
219 /* Compare the riid with the interface IDs implemented by this object.*/
220 if (IsEqualIID(&IID_IUnknown, riid) ||
221 IsEqualIID(&IID_IPersist, riid) ||
222 IsEqualIID(&IID_IPersistStream, riid) ||
223 IsEqualIID(&IID_IMoniker, riid)
226 else if (IsEqualIID(&IID_IROTData, riid))
227 *ppvObject = (IROTData*)&(This->lpvtbl2);
229 /* Check that we obtained an interface.*/
231 return E_NOINTERFACE;
233 /* Query Interface always increases the reference count by one when it is successful */
234 CompositeMonikerImpl_AddRef(iface);
239 /******************************************************************************
240 * CompositeMoniker_AddRef
241 ******************************************************************************/
242 ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)
244 ICOM_THIS(CompositeMonikerImpl,iface);
246 TRACE("(%p)\n",This);
248 return ++(This->ref);
251 /******************************************************************************
252 * CompositeMoniker_Release
253 ******************************************************************************/
254 ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
256 ICOM_THIS(CompositeMonikerImpl,iface);
259 TRACE("(%p)\n",This);
263 /* destroy the object if there's no more reference on it */
266 /* release all the components before destroying this object */
267 for (i=0;i<This->tabLastIndex;i++)
268 IMoniker_Release(This->tabMoniker[i]);
270 CompositeMonikerImpl_Destroy(This);
277 /******************************************************************************
278 * CompositeMoniker_GetClassID
279 ******************************************************************************/
280 HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
282 TRACE("(%p,%p),stub!\n",iface,pClassID);
287 *pClassID = CLSID_CompositeMoniker;
292 /******************************************************************************
293 * CompositeMoniker_IsDirty
294 ******************************************************************************/
295 HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)
297 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
298 method in the OLE-provided moniker interfaces always return S_FALSE because
299 their internal state never changes. */
301 TRACE("(%p)\n",iface);
306 /******************************************************************************
307 * CompositeMoniker_Load
308 ******************************************************************************/
309 HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
316 ICOM_THIS(CompositeMonikerImpl,iface);
318 TRACE("(%p,%p)\n",iface,pStm);
320 /* this function call OleLoadFromStream function for each moniker within this object */
322 /* read the a constant written by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
323 res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
325 if (SUCCEEDED(res)&& constant!=3)
330 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
332 res=ReadClassStm(pStm,&clsid);
333 DPRINTF("res=%ld",res);
337 if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
338 res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
341 res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
345 else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
346 CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
349 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
353 else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
354 CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
357 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
361 else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
367 /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */
372 /* resize the table if needed */
373 if (++This->tabLastIndex==This->tabSize){
375 This->tabSize+=BLOCK_TAB_SIZE;
376 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
378 if (This->tabMoniker==NULL)
379 return E_OUTOFMEMORY;
386 /******************************************************************************
387 * CompositeMoniker_Save
388 ******************************************************************************/
389 HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
392 IEnumMoniker *enumMk;
396 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
398 /* This function calls OleSaveToStream function for each moniker within
400 * When I tested this function in windows, I usually found this constant
401 * at the beginning of the stream. I don't known why (there's no
402 * indication in the specification) !
404 res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
406 IMoniker_Enum(iface,TRUE,&enumMk);
408 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
410 res=OleSaveToStream((IPersistStream*)pmk,pStm);
412 IMoniker_Release(pmk);
416 IEnumMoniker_Release(pmk);
421 IEnumMoniker_Release(enumMk);
426 /******************************************************************************
427 * CompositeMoniker_GetSizeMax
428 ******************************************************************************/
429 HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
431 IEnumMoniker *enumMk;
433 ULARGE_INTEGER ptmpSize;
435 /* The sizeMax of this object is calculated by calling GetSizeMax on
436 * each moniker within this object then summing all returned values
439 TRACE("(%p,%p)\n",iface,pcbSize);
444 pcbSize->s.LowPart =0;
445 pcbSize->s.HighPart=0;
447 IMoniker_Enum(iface,TRUE,&enumMk);
449 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){
451 IMoniker_GetSizeMax(pmk,&ptmpSize);
453 IMoniker_Release(pmk);
455 pcbSize->s.LowPart +=ptmpSize.s.LowPart;
456 pcbSize->s.HighPart+=ptmpSize.s.HighPart;
459 IEnumMoniker_Release(enumMk);
464 /******************************************************************************
465 * Composite-Moniker_Construct (local function)
466 *******************************************************************************/
467 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest)
470 IEnumMoniker *enumMoniker;
474 TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
476 /* Initialize the virtual function table. */
477 This->lpvtbl1 = &VT_CompositeMonikerImpl;
478 This->lpvtbl2 = &VT_ROTDataImpl;
481 This->tabSize=BLOCK_TAB_SIZE;
482 This->tabLastIndex=0;
484 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
485 if (This->tabMoniker==NULL)
486 return E_OUTOFMEMORY;
488 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
490 /* put the first moniker contents in the beginning of the table */
491 if (mkSys!=MKSYS_GENERICCOMPOSITE){
493 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
494 IMoniker_AddRef(pmkFirst);
498 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
500 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
503 if (++This->tabLastIndex==This->tabSize){
505 This->tabSize+=BLOCK_TAB_SIZE;
506 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
508 if (This->tabMoniker==NULL)
509 return E_OUTOFMEMORY;
513 IEnumMoniker_Release(enumMoniker);
516 /* put the rest moniker contents after the first one and make simplification if needed */
518 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
520 if (mkSys!=MKSYS_GENERICCOMPOSITE){
522 /* add a simple moniker to the moniker table */
524 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
526 if (res==MK_E_NEEDGENERIC){
528 /* there's no simplification in this case */
529 This->tabMoniker[This->tabLastIndex]=pmkRest;
531 This->tabLastIndex++;
533 IMoniker_AddRef(pmkRest);
535 else if (tempMk==NULL){
537 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
538 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
540 This->tabLastIndex--;
542 else if (SUCCEEDED(res)){
544 /* the non-generic composition was successful so we can make a simplification in this case */
545 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
547 This->tabMoniker[This->tabLastIndex-1]=tempMk;
551 /* resize tabMoniker if needed */
552 if (This->tabLastIndex==This->tabSize){
554 This->tabSize+=BLOCK_TAB_SIZE;
556 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
558 if (This->tabMoniker==NULL)
559 return E_OUTOFMEMORY;
564 /* add a composite moniker to the moniker table (do the same thing
565 * for each moniker within the composite moniker as a simple moniker
566 * (see above for how to add a simple moniker case) )
568 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
570 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
572 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
574 if (res==MK_E_NEEDGENERIC){
576 This->tabLastIndex++;
578 else if (tempMk==NULL){
580 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
581 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
582 This->tabLastIndex--;
586 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
588 This->tabMoniker[This->tabLastIndex-1]=tempMk;
591 if (This->tabLastIndex==This->tabSize){
593 This->tabSize+=BLOCK_TAB_SIZE;
595 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
597 if (This->tabMoniker==NULL)
598 return E_OUTOFMEMORY;
602 IEnumMoniker_Release(enumMoniker);
608 /******************************************************************************
609 * CompositeMoniker_Destroy (local function)
610 *******************************************************************************/
611 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This)
613 TRACE("(%p)\n",This);
615 HeapFree(GetProcessHeap(),0,This->tabMoniker);
617 HeapFree(GetProcessHeap(),0,This);
622 /******************************************************************************
623 * CompositeMoniker_BindToObject
624 ******************************************************************************/
625 HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,
632 IRunningObjectTable *prot;
633 IMoniker *tempMk,*antiMk,*mostRigthMk;
634 IEnumMoniker *enumMoniker;
636 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
642 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
643 /* object for the requested interface pointer. */
646 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
650 /* if the requested class was loaded befor ! we dont need to reload it */
651 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
658 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
659 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
661 IMoniker_Enum(iface,FALSE,&enumMoniker);
662 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
663 IEnumMoniker_Release(enumMoniker);
665 res=CreateAntiMoniker(&antiMk);
666 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
667 IMoniker_Release(antiMk);
669 res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
671 IMoniker_Release(tempMk);
672 IMoniker_Release(mostRigthMk);
678 /******************************************************************************
679 * CompositeMoniker_BindToStorage
680 ******************************************************************************/
681 HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,
688 IMoniker *tempMk,*antiMk,*mostRigthMk;
689 IEnumMoniker *enumMoniker;
691 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
695 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
696 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
698 if (pmkToLeft!=NULL){
700 IMoniker_Enum(iface,FALSE,&enumMoniker);
701 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
702 IEnumMoniker_Release(enumMoniker);
704 res=CreateAntiMoniker(&antiMk);
705 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
706 IMoniker_Release(antiMk);
708 res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
710 IMoniker_Release(tempMk);
712 IMoniker_Release(mostRigthMk);
717 return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
720 /******************************************************************************
721 * CompositeMoniker_Reduce
722 ******************************************************************************/
723 HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,
725 DWORD dwReduceHowFar,
726 IMoniker** ppmkToLeft,
727 IMoniker** ppmkReduced)
730 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
731 IEnumMoniker *enumMoniker;
733 TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
735 if (ppmkReduced==NULL)
738 /* This method recursively calls Reduce for each of its component monikers. */
740 if (ppmkToLeft==NULL){
742 IMoniker_Enum(iface,FALSE,&enumMoniker);
743 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
744 IEnumMoniker_Release(enumMoniker);
746 res=CreateAntiMoniker(&antiMk);
747 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
748 IMoniker_Release(antiMk);
750 return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
752 else if (*ppmkToLeft==NULL)
754 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
758 /* separate the composite moniker in to left and right moniker */
759 IMoniker_Enum(iface,FALSE,&enumMoniker);
760 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
761 IEnumMoniker_Release(enumMoniker);
763 res=CreateAntiMoniker(&antiMk);
764 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
765 IMoniker_Release(antiMk);
767 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
768 /* of the reduced components */
769 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
770 CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
773 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
776 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
778 IMoniker_AddRef(iface);
782 return MK_S_REDUCED_TO_SELF;
787 /******************************************************************************
788 * CompositeMoniker_ComposeWith
789 ******************************************************************************/
790 HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,
792 BOOL fOnlyIfNotGeneric,
793 IMoniker** ppmkComposite)
795 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
797 if ((ppmkComposite==NULL)||(pmkRight==NULL))
802 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
803 /* otherwise, the method returns the result of combining the two monikers by calling the */
804 /* CreateGenericComposite function */
806 if (fOnlyIfNotGeneric)
807 return MK_E_NEEDGENERIC;
809 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
812 /******************************************************************************
813 * CompositeMoniker_Enum
814 ******************************************************************************/
815 HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
817 ICOM_THIS(CompositeMonikerImpl,iface);
819 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
821 if (ppenumMoniker == NULL)
824 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
827 /******************************************************************************
828 * CompositeMoniker_IsEqual
829 ******************************************************************************/
830 HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
832 IEnumMoniker *enumMoniker1,*enumMoniker2;
833 IMoniker *tempMk1,*tempMk2;
834 HRESULT res1,res2,res;
836 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
838 if (pmkOtherMoniker==NULL)
841 /* This method returns S_OK if the components of both monikers are equal when compared in the */
842 /* left-to-right order.*/
843 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
845 if (enumMoniker1==NULL)
848 IMoniker_Enum(iface,TRUE,&enumMoniker2);
852 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
853 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
855 if((res1==S_OK)&&(res2==S_OK)){
857 if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
864 else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
874 IMoniker_Release(tempMk1);
877 IMoniker_Release(tempMk2);
880 IEnumMoniker_Release(enumMoniker1);
881 IEnumMoniker_Release(enumMoniker2);
885 /******************************************************************************
886 * CompositeMoniker_Hash
887 ******************************************************************************/
888 HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
895 /******************************************************************************
896 * CompositeMoniker_IsRunning
897 ******************************************************************************/
898 HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,
901 IMoniker* pmkNewlyRunning)
903 IRunningObjectTable* rot;
905 IMoniker *tempMk,*antiMk,*mostRigthMk;
906 IEnumMoniker *enumMoniker;
908 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
910 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
911 if (pmkToLeft!=NULL){
913 CreateGenericComposite(pmkToLeft,iface,&tempMk);
915 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
917 IMoniker_Release(tempMk);
922 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
923 /* to this moniker */
925 if (pmkNewlyRunning!=NULL)
927 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
938 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
939 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
940 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
941 /* the composite as the pmkToLeft parameter for that call. */
943 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
948 res = IRunningObjectTable_IsRunning(rot,iface);
949 IRunningObjectTable_Release(rot);
956 IMoniker_Enum(iface,FALSE,&enumMoniker);
957 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
958 IEnumMoniker_Release(enumMoniker);
960 res=CreateAntiMoniker(&antiMk);
961 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
962 IMoniker_Release(antiMk);
964 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
966 IMoniker_Release(tempMk);
967 IMoniker_Release(mostRigthMk);
974 /******************************************************************************
975 * CompositeMoniker_GetTimeOfLastChange
976 ******************************************************************************/
977 HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
980 FILETIME* pCompositeTime)
982 IRunningObjectTable* rot;
984 IMoniker *tempMk,*antiMk,*mostRigthMk;
985 IEnumMoniker *enumMoniker;
987 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
989 if (pCompositeTime==NULL)
992 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
993 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
994 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
995 /* of the composite as the pmkToLeft parameter for that call. */
996 if (pmkToLeft!=NULL){
998 res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
1000 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
1005 if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
1009 IMoniker_Enum(iface,FALSE,&enumMoniker);
1010 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1011 IEnumMoniker_Release(enumMoniker);
1013 res=CreateAntiMoniker(&antiMk);
1014 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1015 IMoniker_Release(antiMk);
1017 res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
1019 IMoniker_Release(tempMk);
1020 IMoniker_Release(mostRigthMk);
1025 return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
1028 /******************************************************************************
1029 * CompositeMoniker_Inverse
1030 ******************************************************************************/
1031 HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
1034 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
1035 IEnumMoniker *enumMoniker;
1037 TRACE("(%p,%p)\n",iface,ppmk);
1042 /* This method returns a composite moniker that consists of the inverses of each of the components */
1043 /* of the original composite, stored in reverse order */
1045 res=CreateAntiMoniker(&antiMk);
1046 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1047 IMoniker_Release(antiMk);
1051 return IMoniker_Inverse(iface,ppmk);
1055 IMoniker_Enum(iface,FALSE,&enumMoniker);
1056 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1057 IEnumMoniker_Release(enumMoniker);
1059 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
1060 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
1062 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
1064 IMoniker_Release(tempMk);
1065 IMoniker_Release(mostRigthMk);
1066 IMoniker_Release(tempInvMk);
1067 IMoniker_Release(mostRigthInvMk);
1073 /******************************************************************************
1074 * CompositeMoniker_CommonPrefixWith
1075 ******************************************************************************/
1076 HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1080 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
1081 IEnumMoniker *enumMoniker1,*enumMoniker2;
1082 ULONG i,nbCommonMk=0;
1084 /* If the other moniker is a composite, this method compares the components of each composite from left */
1085 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1086 /* of the leftmost components were common to both monikers. */
1088 if (ppmkPrefix==NULL)
1094 return MK_E_NOPREFIX;
1096 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1098 if((mkSys==MKSYS_GENERICCOMPOSITE)){
1100 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1101 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
1105 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1106 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
1108 if ((res1==S_FALSE) && (res2==S_FALSE)){
1110 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1112 IMoniker_AddRef(iface);
1115 else if ((res1==S_OK) && (res2==S_OK)){
1117 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
1125 else if (res1==S_OK){
1127 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1128 /* ppmkPrefix to the other moniker. */
1129 *ppmkPrefix=pmkOther;
1133 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1134 /* to this moniker. */
1140 IEnumMoniker_Release(enumMoniker1);
1141 IEnumMoniker_Release(enumMoniker2);
1143 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1145 return MK_E_NOPREFIX;
1147 IEnumMoniker_Reset(enumMoniker1);
1149 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1151 /* if we have more than one commun moniker the result will be a composite moniker */
1154 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1155 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1156 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
1157 IMoniker_Release(tempMk1);
1158 IMoniker_Release(tempMk2);
1160 /* compose all common monikers in a composite moniker */
1161 for(i=0;i<nbCommonMk;i++){
1163 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1165 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
1167 IMoniker_Release(*ppmkPrefix);
1169 IMoniker_Release(tempMk1);
1171 *ppmkPrefix=tempMk2;
1176 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1177 *ppmkPrefix=tempMk1;
1183 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1186 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1188 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1190 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
1192 *ppmkPrefix=pmkOther;
1197 return MK_E_NOPREFIX;
1200 /***************************************************************************************************
1201 * GetAfterCommonPrefix (local function)
1202 * This function returns a moniker that consist of the remainder when the common prefix is removed
1203 ***************************************************************************************************/
1204 VOID WINAPI GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
1206 IMoniker *tempMk,*tempMk1,*tempMk2;
1207 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
1214 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1215 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
1216 /* on the first difference. */
1217 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
1219 IMoniker_IsSystemMoniker(commonMk,&mkSys);
1221 if (mkSys==MKSYS_GENERICCOMPOSITE){
1223 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
1226 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1227 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
1229 if ((res1==S_FALSE)||(res2==S_FALSE)){
1235 IMoniker_Release(tempMk1);
1236 IMoniker_Release(tempMk1);
1240 IMoniker_Release(tempMk1);
1241 IMoniker_Release(tempMk1);
1245 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1246 IMoniker_Release(tempMk1);
1249 /* count the number of elements in the enumerator after the common prefix */
1250 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1252 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1254 IMoniker_Release(tempMk);
1259 /* create a generic composite moniker with monikers located after the common prefix */
1260 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1269 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1271 CreateGenericComposite(tempMk1,tempMk2,restMk);
1273 IMoniker_Release(tempMk1);
1275 IMoniker_Release(tempMk2);
1277 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1279 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1281 IMoniker_Release(tempMk1);
1283 IMoniker_Release(*restMk);
1289 /******************************************************************************
1290 * CompositeMoniker_RelativePathTo
1291 ******************************************************************************/
1292 HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkRelPath)
1295 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1297 TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1299 if (ppmkRelPath==NULL)
1304 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1305 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1306 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1308 /* finds the common prefix of the two monikers */
1309 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1311 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1312 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1314 *ppmkRelPath=pmkOther;
1315 IMoniker_AddRef(pmkOther);
1319 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1320 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1322 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1323 /* moniker when the common prefix is removed */
1326 IMoniker_Inverse(restThisMk,ppmkRelPath);
1327 IMoniker_Release(restThisMk);
1329 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1330 /* when the common prefix is removed */
1331 else if (res==MK_S_ME){
1333 *ppmkRelPath=restOtherMk;
1334 IMoniker_AddRef(restOtherMk);
1336 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1337 /* moniker on the right of it. */
1338 else if (res==S_OK){
1340 IMoniker_Inverse(restThisMk,&invRestThisMk);
1341 IMoniker_Release(restThisMk);
1342 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1343 IMoniker_Release(invRestThisMk);
1344 IMoniker_Release(restOtherMk);
1349 /******************************************************************************
1350 * CompositeMoniker_GetDisplayName
1351 ******************************************************************************/
1352 HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,
1354 IMoniker* pmkToLeft,
1355 LPOLESTR *ppszDisplayName)
1358 IEnumMoniker *enumMoniker;
1362 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1364 if (ppszDisplayName==NULL)
1367 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1369 if (*ppszDisplayName==NULL)
1370 return E_OUTOFMEMORY;
1372 /* This method returns the concatenation of the display names returned by each component moniker of */
1375 **ppszDisplayName=0;
1377 IMoniker_Enum(iface,TRUE,&enumMoniker);
1379 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1381 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1383 lengthStr+=lstrlenW(tempStr);
1385 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1387 if (*ppszDisplayName==NULL)
1388 return E_OUTOFMEMORY;
1390 strcatW(*ppszDisplayName,tempStr);
1392 CoTaskMemFree(tempStr);
1393 IMoniker_Release(tempMk);
1396 IEnumMoniker_Release(enumMoniker);
1401 /******************************************************************************
1402 * CompositeMoniker_ParseDisplayName
1403 ******************************************************************************/
1404 HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,
1406 IMoniker* pmkToLeft,
1407 LPOLESTR pszDisplayName,
1411 IEnumMoniker *enumMoniker;
1412 IMoniker *tempMk,*mostRigthMk,*antiMk;
1413 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1414 /* passing everything else as the pmkToLeft parameter for that call. */
1416 /* get the most right moniker */
1417 IMoniker_Enum(iface,FALSE,&enumMoniker);
1418 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1419 IEnumMoniker_Release(enumMoniker);
1421 /* get the left moniker */
1422 CreateAntiMoniker(&antiMk);
1423 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1424 IMoniker_Release(antiMk);
1426 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1429 /******************************************************************************
1430 * CompositeMoniker_IsSystemMoniker
1431 ******************************************************************************/
1432 HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1434 TRACE("(%p,%p)\n",iface,pwdMksys);
1439 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1444 /*******************************************************************************
1445 * CompositeMonikerIROTData_QueryInterface
1446 *******************************************************************************/
1447 HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1450 ICOM_THIS_From_IROTData(IMoniker, iface);
1452 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
1454 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1457 /***********************************************************************
1458 * CompositeMonikerIROTData_AddRef
1460 ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1462 ICOM_THIS_From_IROTData(IMoniker, iface);
1464 TRACE("(%p)\n",iface);
1466 return CompositeMonikerImpl_AddRef(This);
1469 /***********************************************************************
1470 * CompositeMonikerIROTData_Release
1472 ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1474 ICOM_THIS_From_IROTData(IMoniker, iface);
1476 TRACE("(%p)\n",iface);
1478 return CompositeMonikerImpl_Release(This);
1481 /******************************************************************************
1482 * CompositeMonikerIROTData_GetComparaisonData
1483 ******************************************************************************/
1484 HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1489 FIXME("(),stub!\n");
1493 /******************************************************************************
1494 * EnumMonikerImpl_QueryInterface
1495 ******************************************************************************/
1496 HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1498 ICOM_THIS(EnumMonikerImpl,iface);
1500 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1502 /* Perform a sanity check on the parameters.*/
1503 if ( (This==0) || (ppvObject==0) )
1504 return E_INVALIDARG;
1506 /* Initialize the return parameter */
1509 /* Compare the riid with the interface IDs implemented by this object.*/
1510 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1513 /* Check that we obtained an interface.*/
1514 if ((*ppvObject)==0)
1515 return E_NOINTERFACE;
1517 /* Query Interface always increases the reference count by one when it is successful */
1518 EnumMonikerImpl_AddRef(iface);
1523 /******************************************************************************
1524 * EnumMonikerImpl_AddRef
1525 ******************************************************************************/
1526 ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1528 ICOM_THIS(EnumMonikerImpl,iface);
1530 TRACE("(%p)\n",This);
1532 return ++(This->ref);
1536 /******************************************************************************
1537 * EnumMonikerImpl_Release
1538 ******************************************************************************/
1539 ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1541 ICOM_THIS(EnumMonikerImpl,iface);
1544 TRACE("(%p)\n",This);
1548 /* destroy the object if there's no more reference on it */
1551 for(i=0;i<This->tabSize;i++)
1552 IMoniker_Release(This->tabMoniker[i]);
1554 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1555 HeapFree(GetProcessHeap(),0,This);
1562 /******************************************************************************
1563 * EnumMonikerImpl_Next
1564 ******************************************************************************/
1565 HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){
1567 ICOM_THIS(EnumMonikerImpl,iface);
1570 /* retrieve the requested number of moniker from the current position */
1571 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1573 rgelt[i]=This->tabMoniker[This->currentPos++];
1575 if (pceltFethed!=NULL)
1584 /******************************************************************************
1585 * EnumMonikerImpl_Skip
1586 ******************************************************************************/
1587 HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){
1589 ICOM_THIS(EnumMonikerImpl,iface);
1591 if ((This->currentPos+celt) >= This->tabSize)
1594 This->currentPos+=celt;
1599 /******************************************************************************
1600 * EnumMonikerImpl_Reset
1601 ******************************************************************************/
1602 HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){
1604 ICOM_THIS(EnumMonikerImpl,iface);
1611 /******************************************************************************
1612 * EnumMonikerImpl_Clone
1613 ******************************************************************************/
1614 HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){
1616 ICOM_THIS(EnumMonikerImpl,iface);
1618 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1621 /******************************************************************************
1622 * EnumMonikerImpl_CreateEnumMoniker
1623 ******************************************************************************/
1624 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,
1628 IEnumMoniker ** ppmk)
1630 EnumMonikerImpl* newEnumMoniker;
1634 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1636 if (newEnumMoniker == 0)
1637 return STG_E_INSUFFICIENTMEMORY;
1639 if (currentPos > tabSize)
1640 return E_INVALIDARG;
1642 /* Initialize the virtual function table. */
1643 newEnumMoniker->lpVtbl = &VT_EnumMonikerImpl;
1644 newEnumMoniker->ref = 0;
1646 newEnumMoniker->tabSize=tabSize;
1647 newEnumMoniker->currentPos=currentPos;
1649 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1651 if (newEnumMoniker->tabMoniker==NULL)
1652 return E_OUTOFMEMORY;
1655 for (i=0;i<tabSize;i++){
1657 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1658 IMoniker_AddRef(tabMoniker[i]);
1661 for (i=tabSize-1;i>=0;i--){
1663 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1664 IMoniker_AddRef(tabMoniker[i]);
1667 *ppmk=(IEnumMoniker*)newEnumMoniker;
1672 /******************************************************************************
1673 * CreateGenericComposite [OLE32.56]
1674 ******************************************************************************/
1675 HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite)
1677 CompositeMonikerImpl* newCompositeMoniker = 0;
1680 TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1682 if (ppmkComposite==NULL)
1687 if (pmkFirst==NULL && pmkRest!=NULL){
1689 *ppmkComposite=pmkRest;
1692 else if (pmkFirst!=NULL && pmkRest==NULL){
1693 *ppmkComposite=pmkFirst;
1696 else if (pmkFirst==NULL && pmkRest==NULL)
1699 newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
1701 if (newCompositeMoniker == 0)
1702 return STG_E_INSUFFICIENTMEMORY;
1704 hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
1708 HeapFree(GetProcessHeap(),0,newCompositeMoniker);
1711 if (newCompositeMoniker->tabLastIndex==1)
1713 hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
1716 hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
1721 /******************************************************************************
1722 * MonikerCommonPrefixWith [OLE32.82]
1723 ******************************************************************************/
1724 HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1726 FIXME("(),stub!\n");