1 /***************************************************************************************
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
19 ***************************************************************************************/
24 #include "wine/debug.h"
25 #include "wine/unicode.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(ole);
30 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
32 /* CompositeMoniker data structure */
33 typedef struct CompositeMonikerImpl{
35 ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/
37 /* The ROT (RunningObjectTable implementation) uses the IROTData
38 * interface to test whether two monikers are equal. That's why IROTData
39 * interface is implemented by monikers.
41 ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/
43 ULONG ref; /* reference counter for this object */
45 IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */
47 ULONG tabSize; /* size of tabMoniker */
49 ULONG tabLastIndex; /* first free index in tabMoniker */
51 } CompositeMonikerImpl;
54 /* EnumMoniker data structure */
55 typedef struct EnumMonikerImpl{
57 ICOM_VFIELD(IEnumMoniker); /* VTable relative to the IEnumMoniker interface.*/
59 ULONG ref; /* reference counter for this object */
61 IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
63 ULONG tabSize; /* size of tabMoniker */
65 ULONG currentPos; /* index pointer on the current moniker */
70 /********************************************************************************/
71 /* CompositeMoniker prototype functions : */
73 /* IUnknown prototype functions */
74 static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
75 static ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface);
76 static ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface);
78 /* IPersist prototype functions */
79 static HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
81 /* IPersistStream prototype functions */
82 static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface);
83 static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm);
84 static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
85 static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
87 /* IMoniker prototype functions */
88 static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
89 static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
90 static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
91 static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
92 static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
93 static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
94 static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
95 static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
96 static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime);
97 static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
98 static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
99 static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
100 static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
101 static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
102 static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
104 /********************************************************************************/
105 /* IROTData prototype functions */
107 /* IUnknown prototype functions */
108 static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
109 static ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface);
110 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface);
112 /* IROTData prototype function */
113 static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
115 /* Local function used by CompositeMoniker implementation */
116 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest);
117 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface);
119 /********************************************************************************/
120 /* IEnumMoniker prototype functions */
122 /* IUnknown prototype functions */
123 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject);
124 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface);
125 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface);
127 /* IEnumMoniker prototype functions */
128 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched);
129 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt);
130 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface);
131 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum);
133 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
135 /********************************************************************************/
136 /* Virtual function table for the CompositeMonikerImpl class which includes */
137 /* IPersist, IPersistStream and IMoniker functions. */
139 static ICOM_VTABLE(IMoniker) VT_CompositeMonikerImpl =
141 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
142 CompositeMonikerImpl_QueryInterface,
143 CompositeMonikerImpl_AddRef,
144 CompositeMonikerImpl_Release,
145 CompositeMonikerImpl_GetClassID,
146 CompositeMonikerImpl_IsDirty,
147 CompositeMonikerImpl_Load,
148 CompositeMonikerImpl_Save,
149 CompositeMonikerImpl_GetSizeMax,
150 CompositeMonikerImpl_BindToObject,
151 CompositeMonikerImpl_BindToStorage,
152 CompositeMonikerImpl_Reduce,
153 CompositeMonikerImpl_ComposeWith,
154 CompositeMonikerImpl_Enum,
155 CompositeMonikerImpl_IsEqual,
156 CompositeMonikerImpl_Hash,
157 CompositeMonikerImpl_IsRunning,
158 CompositeMonikerImpl_GetTimeOfLastChange,
159 CompositeMonikerImpl_Inverse,
160 CompositeMonikerImpl_CommonPrefixWith,
161 CompositeMonikerImpl_RelativePathTo,
162 CompositeMonikerImpl_GetDisplayName,
163 CompositeMonikerImpl_ParseDisplayName,
164 CompositeMonikerImpl_IsSystemMoniker
167 /********************************************************************************/
168 /* Virtual function table for the IROTData class. */
169 static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
171 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
172 CompositeMonikerROTDataImpl_QueryInterface,
173 CompositeMonikerROTDataImpl_AddRef,
174 CompositeMonikerROTDataImpl_Release,
175 CompositeMonikerROTDataImpl_GetComparaisonData
178 /********************************************************************************/
179 /* Virtual function table for the IROTData class */
180 static ICOM_VTABLE(IEnumMoniker) VT_EnumMonikerImpl =
182 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
183 EnumMonikerImpl_QueryInterface,
184 EnumMonikerImpl_AddRef,
185 EnumMonikerImpl_Release,
186 EnumMonikerImpl_Next,
187 EnumMonikerImpl_Skip,
188 EnumMonikerImpl_Reset,
189 EnumMonikerImpl_Clone
192 /*******************************************************************************
193 * CompositeMoniker_QueryInterface
194 *******************************************************************************/
195 HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
197 ICOM_THIS(CompositeMonikerImpl,iface);
199 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
201 /* Perform a sanity check on the parameters.*/
202 if ( (This==0) || (ppvObject==0) )
205 /* Initialize the return parameter */
208 /* Compare the riid with the interface IDs implemented by this object.*/
209 if (IsEqualIID(&IID_IUnknown, riid) ||
210 IsEqualIID(&IID_IPersist, riid) ||
211 IsEqualIID(&IID_IPersistStream, riid) ||
212 IsEqualIID(&IID_IMoniker, riid)
215 else if (IsEqualIID(&IID_IROTData, riid))
216 *ppvObject = (IROTData*)&(This->lpvtbl2);
218 /* Check that we obtained an interface.*/
220 return E_NOINTERFACE;
222 /* Query Interface always increases the reference count by one when it is successful */
223 CompositeMonikerImpl_AddRef(iface);
228 /******************************************************************************
229 * CompositeMoniker_AddRef
230 ******************************************************************************/
231 ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)
233 ICOM_THIS(CompositeMonikerImpl,iface);
235 TRACE("(%p)\n",This);
237 return ++(This->ref);
240 /******************************************************************************
241 * CompositeMoniker_Release
242 ******************************************************************************/
243 ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
245 ICOM_THIS(CompositeMonikerImpl,iface);
248 TRACE("(%p)\n",This);
252 /* destroy the object if there's no more reference on it */
255 /* release all the components before destroying this object */
256 for (i=0;i<This->tabLastIndex;i++)
257 IMoniker_Release(This->tabMoniker[i]);
259 CompositeMonikerImpl_Destroy(This);
266 /******************************************************************************
267 * CompositeMoniker_GetClassID
268 ******************************************************************************/
269 HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
271 TRACE("(%p,%p),stub!\n",iface,pClassID);
276 *pClassID = CLSID_CompositeMoniker;
281 /******************************************************************************
282 * CompositeMoniker_IsDirty
283 ******************************************************************************/
284 HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)
286 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
287 method in the OLE-provided moniker interfaces always return S_FALSE because
288 their internal state never changes. */
290 TRACE("(%p)\n",iface);
295 /******************************************************************************
296 * CompositeMoniker_Load
297 ******************************************************************************/
298 HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
305 ICOM_THIS(CompositeMonikerImpl,iface);
307 TRACE("(%p,%p)\n",iface,pStm);
309 /* this function call OleLoadFromStream function for each moniker within this object */
311 /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
312 res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
314 if (SUCCEEDED(res)&& constant!=3)
319 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
321 res=ReadClassStm(pStm,&clsid);
322 DPRINTF("res=%ld",res);
326 if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
327 res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
330 res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
334 else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
335 CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
338 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
342 else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
343 CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
346 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
350 else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
356 /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */
361 /* resize the table if needed */
362 if (++This->tabLastIndex==This->tabSize){
364 This->tabSize+=BLOCK_TAB_SIZE;
365 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
367 if (This->tabMoniker==NULL)
368 return E_OUTOFMEMORY;
375 /******************************************************************************
376 * CompositeMoniker_Save
377 ******************************************************************************/
378 HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
381 IEnumMoniker *enumMk;
385 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
387 /* This function calls OleSaveToStream function for each moniker within
389 * When I tested this function in windows, I usually found this constant
390 * at the beginning of the stream. I don't known why (there's no
391 * indication in the specification) !
393 res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
395 IMoniker_Enum(iface,TRUE,&enumMk);
397 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
399 res=OleSaveToStream((IPersistStream*)pmk,pStm);
401 IMoniker_Release(pmk);
405 IEnumMoniker_Release(pmk);
410 IEnumMoniker_Release(enumMk);
415 /******************************************************************************
416 * CompositeMoniker_GetSizeMax
417 ******************************************************************************/
418 HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
420 IEnumMoniker *enumMk;
422 ULARGE_INTEGER ptmpSize;
424 /* The sizeMax of this object is calculated by calling GetSizeMax on
425 * each moniker within this object then summing all returned values
428 TRACE("(%p,%p)\n",iface,pcbSize);
433 pcbSize->s.LowPart =0;
434 pcbSize->s.HighPart=0;
436 IMoniker_Enum(iface,TRUE,&enumMk);
438 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){
440 IMoniker_GetSizeMax(pmk,&ptmpSize);
442 IMoniker_Release(pmk);
444 pcbSize->s.LowPart +=ptmpSize.s.LowPart;
445 pcbSize->s.HighPart+=ptmpSize.s.HighPart;
448 IEnumMoniker_Release(enumMk);
453 /******************************************************************************
454 * Composite-Moniker_Construct (local function)
455 *******************************************************************************/
456 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest)
459 IEnumMoniker *enumMoniker;
463 TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
465 /* Initialize the virtual function table. */
466 This->lpvtbl1 = &VT_CompositeMonikerImpl;
467 This->lpvtbl2 = &VT_ROTDataImpl;
470 This->tabSize=BLOCK_TAB_SIZE;
471 This->tabLastIndex=0;
473 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
474 if (This->tabMoniker==NULL)
475 return E_OUTOFMEMORY;
477 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
479 /* put the first moniker contents in the beginning of the table */
480 if (mkSys!=MKSYS_GENERICCOMPOSITE){
482 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
483 IMoniker_AddRef(pmkFirst);
487 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
489 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
492 if (++This->tabLastIndex==This->tabSize){
494 This->tabSize+=BLOCK_TAB_SIZE;
495 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
497 if (This->tabMoniker==NULL)
498 return E_OUTOFMEMORY;
502 IEnumMoniker_Release(enumMoniker);
505 /* put the rest moniker contents after the first one and make simplification if needed */
507 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
509 if (mkSys!=MKSYS_GENERICCOMPOSITE){
511 /* add a simple moniker to the moniker table */
513 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
515 if (res==MK_E_NEEDGENERIC){
517 /* there's no simplification in this case */
518 This->tabMoniker[This->tabLastIndex]=pmkRest;
520 This->tabLastIndex++;
522 IMoniker_AddRef(pmkRest);
524 else if (tempMk==NULL){
526 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
527 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
529 This->tabLastIndex--;
531 else if (SUCCEEDED(res)){
533 /* the non-generic composition was successful so we can make a simplification in this case */
534 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
536 This->tabMoniker[This->tabLastIndex-1]=tempMk;
540 /* resize tabMoniker if needed */
541 if (This->tabLastIndex==This->tabSize){
543 This->tabSize+=BLOCK_TAB_SIZE;
545 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
547 if (This->tabMoniker==NULL)
548 return E_OUTOFMEMORY;
553 /* add a composite moniker to the moniker table (do the same thing
554 * for each moniker within the composite moniker as a simple moniker
555 * (see above for how to add a simple moniker case) )
557 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
559 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
561 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
563 if (res==MK_E_NEEDGENERIC){
565 This->tabLastIndex++;
567 else if (tempMk==NULL){
569 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
570 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
571 This->tabLastIndex--;
575 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
577 This->tabMoniker[This->tabLastIndex-1]=tempMk;
580 if (This->tabLastIndex==This->tabSize){
582 This->tabSize+=BLOCK_TAB_SIZE;
584 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
586 if (This->tabMoniker==NULL)
587 return E_OUTOFMEMORY;
591 IEnumMoniker_Release(enumMoniker);
597 /******************************************************************************
598 * CompositeMoniker_Destroy (local function)
599 *******************************************************************************/
600 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This)
602 TRACE("(%p)\n",This);
604 HeapFree(GetProcessHeap(),0,This->tabMoniker);
606 HeapFree(GetProcessHeap(),0,This);
611 /******************************************************************************
612 * CompositeMoniker_BindToObject
613 ******************************************************************************/
614 HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,
621 IRunningObjectTable *prot;
622 IMoniker *tempMk,*antiMk,*mostRigthMk;
623 IEnumMoniker *enumMoniker;
625 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
631 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
632 /* object for the requested interface pointer. */
635 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
639 /* if the requested class was loaded befor ! we dont need to reload it */
640 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
647 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
648 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
650 IMoniker_Enum(iface,FALSE,&enumMoniker);
651 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
652 IEnumMoniker_Release(enumMoniker);
654 res=CreateAntiMoniker(&antiMk);
655 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
656 IMoniker_Release(antiMk);
658 res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
660 IMoniker_Release(tempMk);
661 IMoniker_Release(mostRigthMk);
667 /******************************************************************************
668 * CompositeMoniker_BindToStorage
669 ******************************************************************************/
670 HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,
677 IMoniker *tempMk,*antiMk,*mostRigthMk;
678 IEnumMoniker *enumMoniker;
680 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
684 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
685 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
687 if (pmkToLeft!=NULL){
689 IMoniker_Enum(iface,FALSE,&enumMoniker);
690 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
691 IEnumMoniker_Release(enumMoniker);
693 res=CreateAntiMoniker(&antiMk);
694 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
695 IMoniker_Release(antiMk);
697 res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
699 IMoniker_Release(tempMk);
701 IMoniker_Release(mostRigthMk);
706 return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
709 /******************************************************************************
710 * CompositeMoniker_Reduce
711 ******************************************************************************/
712 HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,
714 DWORD dwReduceHowFar,
715 IMoniker** ppmkToLeft,
716 IMoniker** ppmkReduced)
719 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
720 IEnumMoniker *enumMoniker;
722 TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
724 if (ppmkReduced==NULL)
727 /* This method recursively calls Reduce for each of its component monikers. */
729 if (ppmkToLeft==NULL){
731 IMoniker_Enum(iface,FALSE,&enumMoniker);
732 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
733 IEnumMoniker_Release(enumMoniker);
735 res=CreateAntiMoniker(&antiMk);
736 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
737 IMoniker_Release(antiMk);
739 return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
741 else if (*ppmkToLeft==NULL)
743 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
747 /* separate the composite moniker in to left and right moniker */
748 IMoniker_Enum(iface,FALSE,&enumMoniker);
749 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
750 IEnumMoniker_Release(enumMoniker);
752 res=CreateAntiMoniker(&antiMk);
753 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
754 IMoniker_Release(antiMk);
756 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
757 /* of the reduced components */
758 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
759 CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
762 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
765 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
767 IMoniker_AddRef(iface);
771 return MK_S_REDUCED_TO_SELF;
776 /******************************************************************************
777 * CompositeMoniker_ComposeWith
778 ******************************************************************************/
779 HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,
781 BOOL fOnlyIfNotGeneric,
782 IMoniker** ppmkComposite)
784 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
786 if ((ppmkComposite==NULL)||(pmkRight==NULL))
791 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
792 /* otherwise, the method returns the result of combining the two monikers by calling the */
793 /* CreateGenericComposite function */
795 if (fOnlyIfNotGeneric)
796 return MK_E_NEEDGENERIC;
798 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
801 /******************************************************************************
802 * CompositeMoniker_Enum
803 ******************************************************************************/
804 HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
806 ICOM_THIS(CompositeMonikerImpl,iface);
808 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
810 if (ppenumMoniker == NULL)
813 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
816 /******************************************************************************
817 * CompositeMoniker_IsEqual
818 ******************************************************************************/
819 HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
821 IEnumMoniker *enumMoniker1,*enumMoniker2;
822 IMoniker *tempMk1,*tempMk2;
823 HRESULT res1,res2,res;
825 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
827 if (pmkOtherMoniker==NULL)
830 /* This method returns S_OK if the components of both monikers are equal when compared in the */
831 /* left-to-right order.*/
832 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
834 if (enumMoniker1==NULL)
837 IMoniker_Enum(iface,TRUE,&enumMoniker2);
841 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
842 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
844 if((res1==S_OK)&&(res2==S_OK)){
846 if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
853 else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
863 IMoniker_Release(tempMk1);
866 IMoniker_Release(tempMk2);
869 IEnumMoniker_Release(enumMoniker1);
870 IEnumMoniker_Release(enumMoniker2);
874 /******************************************************************************
875 * CompositeMoniker_Hash
876 ******************************************************************************/
877 HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
884 /******************************************************************************
885 * CompositeMoniker_IsRunning
886 ******************************************************************************/
887 HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,
890 IMoniker* pmkNewlyRunning)
892 IRunningObjectTable* rot;
894 IMoniker *tempMk,*antiMk,*mostRigthMk;
895 IEnumMoniker *enumMoniker;
897 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
899 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
900 if (pmkToLeft!=NULL){
902 CreateGenericComposite(pmkToLeft,iface,&tempMk);
904 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
906 IMoniker_Release(tempMk);
911 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
912 /* to this moniker */
914 if (pmkNewlyRunning!=NULL)
916 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
927 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
928 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
929 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
930 /* the composite as the pmkToLeft parameter for that call. */
932 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
937 res = IRunningObjectTable_IsRunning(rot,iface);
938 IRunningObjectTable_Release(rot);
945 IMoniker_Enum(iface,FALSE,&enumMoniker);
946 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
947 IEnumMoniker_Release(enumMoniker);
949 res=CreateAntiMoniker(&antiMk);
950 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
951 IMoniker_Release(antiMk);
953 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
955 IMoniker_Release(tempMk);
956 IMoniker_Release(mostRigthMk);
963 /******************************************************************************
964 * CompositeMoniker_GetTimeOfLastChange
965 ******************************************************************************/
966 HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
969 FILETIME* pCompositeTime)
971 IRunningObjectTable* rot;
973 IMoniker *tempMk,*antiMk,*mostRigthMk;
974 IEnumMoniker *enumMoniker;
976 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
978 if (pCompositeTime==NULL)
981 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
982 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
983 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
984 /* of the composite as the pmkToLeft parameter for that call. */
985 if (pmkToLeft!=NULL){
987 res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
989 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
994 if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
998 IMoniker_Enum(iface,FALSE,&enumMoniker);
999 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1000 IEnumMoniker_Release(enumMoniker);
1002 res=CreateAntiMoniker(&antiMk);
1003 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1004 IMoniker_Release(antiMk);
1006 res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
1008 IMoniker_Release(tempMk);
1009 IMoniker_Release(mostRigthMk);
1014 return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
1017 /******************************************************************************
1018 * CompositeMoniker_Inverse
1019 ******************************************************************************/
1020 HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
1023 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
1024 IEnumMoniker *enumMoniker;
1026 TRACE("(%p,%p)\n",iface,ppmk);
1031 /* This method returns a composite moniker that consists of the inverses of each of the components */
1032 /* of the original composite, stored in reverse order */
1034 res=CreateAntiMoniker(&antiMk);
1035 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1036 IMoniker_Release(antiMk);
1040 return IMoniker_Inverse(iface,ppmk);
1044 IMoniker_Enum(iface,FALSE,&enumMoniker);
1045 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1046 IEnumMoniker_Release(enumMoniker);
1048 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
1049 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
1051 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
1053 IMoniker_Release(tempMk);
1054 IMoniker_Release(mostRigthMk);
1055 IMoniker_Release(tempInvMk);
1056 IMoniker_Release(mostRigthInvMk);
1062 /******************************************************************************
1063 * CompositeMoniker_CommonPrefixWith
1064 ******************************************************************************/
1065 HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1069 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
1070 IEnumMoniker *enumMoniker1,*enumMoniker2;
1071 ULONG i,nbCommonMk=0;
1073 /* If the other moniker is a composite, this method compares the components of each composite from left */
1074 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1075 /* of the leftmost components were common to both monikers. */
1077 if (ppmkPrefix==NULL)
1083 return MK_E_NOPREFIX;
1085 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1087 if((mkSys==MKSYS_GENERICCOMPOSITE)){
1089 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1090 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
1094 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1095 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
1097 if ((res1==S_FALSE) && (res2==S_FALSE)){
1099 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1101 IMoniker_AddRef(iface);
1104 else if ((res1==S_OK) && (res2==S_OK)){
1106 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
1114 else if (res1==S_OK){
1116 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1117 /* ppmkPrefix to the other moniker. */
1118 *ppmkPrefix=pmkOther;
1122 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1123 /* to this moniker. */
1129 IEnumMoniker_Release(enumMoniker1);
1130 IEnumMoniker_Release(enumMoniker2);
1132 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1134 return MK_E_NOPREFIX;
1136 IEnumMoniker_Reset(enumMoniker1);
1138 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1140 /* if we have more than one commun moniker the result will be a composite moniker */
1143 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1144 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1145 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
1146 IMoniker_Release(tempMk1);
1147 IMoniker_Release(tempMk2);
1149 /* compose all common monikers in a composite moniker */
1150 for(i=0;i<nbCommonMk;i++){
1152 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1154 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
1156 IMoniker_Release(*ppmkPrefix);
1158 IMoniker_Release(tempMk1);
1160 *ppmkPrefix=tempMk2;
1165 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1166 *ppmkPrefix=tempMk1;
1172 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1175 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1177 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1179 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
1181 *ppmkPrefix=pmkOther;
1186 return MK_E_NOPREFIX;
1189 /***************************************************************************************************
1190 * GetAfterCommonPrefix (local function)
1191 * This function returns a moniker that consist of the remainder when the common prefix is removed
1192 ***************************************************************************************************/
1193 VOID WINAPI GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
1195 IMoniker *tempMk,*tempMk1,*tempMk2;
1196 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
1203 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1204 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
1205 /* on the first difference. */
1206 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
1208 IMoniker_IsSystemMoniker(commonMk,&mkSys);
1210 if (mkSys==MKSYS_GENERICCOMPOSITE){
1212 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
1215 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1216 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
1218 if ((res1==S_FALSE)||(res2==S_FALSE)){
1224 IMoniker_Release(tempMk1);
1225 IMoniker_Release(tempMk1);
1229 IMoniker_Release(tempMk1);
1230 IMoniker_Release(tempMk1);
1234 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1235 IMoniker_Release(tempMk1);
1238 /* count the number of elements in the enumerator after the common prefix */
1239 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1241 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1243 IMoniker_Release(tempMk);
1248 /* create a generic composite moniker with monikers located after the common prefix */
1249 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1258 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1260 CreateGenericComposite(tempMk1,tempMk2,restMk);
1262 IMoniker_Release(tempMk1);
1264 IMoniker_Release(tempMk2);
1266 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1268 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1270 IMoniker_Release(tempMk1);
1272 IMoniker_Release(*restMk);
1278 /******************************************************************************
1279 * CompositeMoniker_RelativePathTo
1280 ******************************************************************************/
1281 HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkRelPath)
1284 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1286 TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1288 if (ppmkRelPath==NULL)
1293 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1294 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1295 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1297 /* finds the common prefix of the two monikers */
1298 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1300 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1301 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1303 *ppmkRelPath=pmkOther;
1304 IMoniker_AddRef(pmkOther);
1308 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1309 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1311 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1312 /* moniker when the common prefix is removed */
1315 IMoniker_Inverse(restThisMk,ppmkRelPath);
1316 IMoniker_Release(restThisMk);
1318 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1319 /* when the common prefix is removed */
1320 else if (res==MK_S_ME){
1322 *ppmkRelPath=restOtherMk;
1323 IMoniker_AddRef(restOtherMk);
1325 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1326 /* moniker on the right of it. */
1327 else if (res==S_OK){
1329 IMoniker_Inverse(restThisMk,&invRestThisMk);
1330 IMoniker_Release(restThisMk);
1331 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1332 IMoniker_Release(invRestThisMk);
1333 IMoniker_Release(restOtherMk);
1338 /******************************************************************************
1339 * CompositeMoniker_GetDisplayName
1340 ******************************************************************************/
1341 HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,
1343 IMoniker* pmkToLeft,
1344 LPOLESTR *ppszDisplayName)
1347 IEnumMoniker *enumMoniker;
1351 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1353 if (ppszDisplayName==NULL)
1356 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1358 if (*ppszDisplayName==NULL)
1359 return E_OUTOFMEMORY;
1361 /* This method returns the concatenation of the display names returned by each component moniker of */
1364 **ppszDisplayName=0;
1366 IMoniker_Enum(iface,TRUE,&enumMoniker);
1368 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1370 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1372 lengthStr+=lstrlenW(tempStr);
1374 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1376 if (*ppszDisplayName==NULL)
1377 return E_OUTOFMEMORY;
1379 strcatW(*ppszDisplayName,tempStr);
1381 CoTaskMemFree(tempStr);
1382 IMoniker_Release(tempMk);
1385 IEnumMoniker_Release(enumMoniker);
1390 /******************************************************************************
1391 * CompositeMoniker_ParseDisplayName
1392 ******************************************************************************/
1393 HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,
1395 IMoniker* pmkToLeft,
1396 LPOLESTR pszDisplayName,
1400 IEnumMoniker *enumMoniker;
1401 IMoniker *tempMk,*mostRigthMk,*antiMk;
1402 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1403 /* passing everything else as the pmkToLeft parameter for that call. */
1405 /* get the most right moniker */
1406 IMoniker_Enum(iface,FALSE,&enumMoniker);
1407 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1408 IEnumMoniker_Release(enumMoniker);
1410 /* get the left moniker */
1411 CreateAntiMoniker(&antiMk);
1412 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1413 IMoniker_Release(antiMk);
1415 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1418 /******************************************************************************
1419 * CompositeMoniker_IsSystemMoniker
1420 ******************************************************************************/
1421 HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1423 TRACE("(%p,%p)\n",iface,pwdMksys);
1428 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1433 /*******************************************************************************
1434 * CompositeMonikerIROTData_QueryInterface
1435 *******************************************************************************/
1436 HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1439 ICOM_THIS_From_IROTData(IMoniker, iface);
1441 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
1443 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1446 /***********************************************************************
1447 * CompositeMonikerIROTData_AddRef
1449 ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1451 ICOM_THIS_From_IROTData(IMoniker, iface);
1453 TRACE("(%p)\n",iface);
1455 return CompositeMonikerImpl_AddRef(This);
1458 /***********************************************************************
1459 * CompositeMonikerIROTData_Release
1461 ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1463 ICOM_THIS_From_IROTData(IMoniker, iface);
1465 TRACE("(%p)\n",iface);
1467 return CompositeMonikerImpl_Release(This);
1470 /******************************************************************************
1471 * CompositeMonikerIROTData_GetComparaisonData
1472 ******************************************************************************/
1473 HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1478 FIXME("(),stub!\n");
1482 /******************************************************************************
1483 * EnumMonikerImpl_QueryInterface
1484 ******************************************************************************/
1485 HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1487 ICOM_THIS(EnumMonikerImpl,iface);
1489 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1491 /* Perform a sanity check on the parameters.*/
1492 if ( (This==0) || (ppvObject==0) )
1493 return E_INVALIDARG;
1495 /* Initialize the return parameter */
1498 /* Compare the riid with the interface IDs implemented by this object.*/
1499 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1502 /* Check that we obtained an interface.*/
1503 if ((*ppvObject)==0)
1504 return E_NOINTERFACE;
1506 /* Query Interface always increases the reference count by one when it is successful */
1507 EnumMonikerImpl_AddRef(iface);
1512 /******************************************************************************
1513 * EnumMonikerImpl_AddRef
1514 ******************************************************************************/
1515 ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1517 ICOM_THIS(EnumMonikerImpl,iface);
1519 TRACE("(%p)\n",This);
1521 return ++(This->ref);
1525 /******************************************************************************
1526 * EnumMonikerImpl_Release
1527 ******************************************************************************/
1528 ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1530 ICOM_THIS(EnumMonikerImpl,iface);
1533 TRACE("(%p)\n",This);
1537 /* destroy the object if there's no more reference on it */
1540 for(i=0;i<This->tabSize;i++)
1541 IMoniker_Release(This->tabMoniker[i]);
1543 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1544 HeapFree(GetProcessHeap(),0,This);
1551 /******************************************************************************
1552 * EnumMonikerImpl_Next
1553 ******************************************************************************/
1554 HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){
1556 ICOM_THIS(EnumMonikerImpl,iface);
1559 /* retrieve the requested number of moniker from the current position */
1560 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1562 rgelt[i]=This->tabMoniker[This->currentPos++];
1564 if (pceltFethed!=NULL)
1573 /******************************************************************************
1574 * EnumMonikerImpl_Skip
1575 ******************************************************************************/
1576 HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){
1578 ICOM_THIS(EnumMonikerImpl,iface);
1580 if ((This->currentPos+celt) >= This->tabSize)
1583 This->currentPos+=celt;
1588 /******************************************************************************
1589 * EnumMonikerImpl_Reset
1590 ******************************************************************************/
1591 HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){
1593 ICOM_THIS(EnumMonikerImpl,iface);
1600 /******************************************************************************
1601 * EnumMonikerImpl_Clone
1602 ******************************************************************************/
1603 HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){
1605 ICOM_THIS(EnumMonikerImpl,iface);
1607 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1610 /******************************************************************************
1611 * EnumMonikerImpl_CreateEnumMoniker
1612 ******************************************************************************/
1613 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,
1617 IEnumMoniker ** ppmk)
1619 EnumMonikerImpl* newEnumMoniker;
1623 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1625 if (newEnumMoniker == 0)
1626 return STG_E_INSUFFICIENTMEMORY;
1628 if (currentPos > tabSize)
1629 return E_INVALIDARG;
1631 /* Initialize the virtual function table. */
1632 ICOM_VTBL(newEnumMoniker) = &VT_EnumMonikerImpl;
1633 newEnumMoniker->ref = 0;
1635 newEnumMoniker->tabSize=tabSize;
1636 newEnumMoniker->currentPos=currentPos;
1638 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1640 if (newEnumMoniker->tabMoniker==NULL)
1641 return E_OUTOFMEMORY;
1644 for (i=0;i<tabSize;i++){
1646 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1647 IMoniker_AddRef(tabMoniker[i]);
1650 for (i=tabSize-1;i>=0;i--){
1652 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1653 IMoniker_AddRef(tabMoniker[i]);
1656 *ppmk=(IEnumMoniker*)newEnumMoniker;
1661 /******************************************************************************
1662 * CreateGenericComposite [OLE32.56]
1663 ******************************************************************************/
1664 HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite)
1666 CompositeMonikerImpl* newCompositeMoniker = 0;
1669 TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1671 if (ppmkComposite==NULL)
1676 if (pmkFirst==NULL && pmkRest!=NULL){
1678 *ppmkComposite=pmkRest;
1681 else if (pmkFirst!=NULL && pmkRest==NULL){
1682 *ppmkComposite=pmkFirst;
1685 else if (pmkFirst==NULL && pmkRest==NULL)
1688 newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
1690 if (newCompositeMoniker == 0)
1691 return STG_E_INSUFFICIENTMEMORY;
1693 hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
1697 HeapFree(GetProcessHeap(),0,newCompositeMoniker);
1700 if (newCompositeMoniker->tabLastIndex==1)
1702 hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
1705 hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
1710 /******************************************************************************
1711 * MonikerCommonPrefixWith [OLE32.82]
1712 ******************************************************************************/
1713 HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1715 FIXME("(),stub!\n");