Return STG_E_FILEALREADYEXISTS in ole32.StgOpenStorage if the file is
[wine] / dlls / ole32 / compositemoniker.c
1 /***************************************************************************************
2  *                            CompositeMonikers implementation
3  *
4  *               Copyright 1999  Noomen Hamza
5  ***************************************************************************************/
6 #include <assert.h>
7 #include <string.h>
8 #include "winbase.h"
9 #include "winerror.h"
10 #include "debugtools.h"
11 #include "wine/obj_base.h"
12 #include "wine/obj_misc.h"
13 #include "wine/obj_storage.h"
14 #include "wine/obj_moniker.h"
15 #include "wine/obj_inplace.h"
16 #include "wine/unicode.h"
17 #include "ole2.h"
18
19 DEFAULT_DEBUG_CHANNEL(ole);
20
21 #define  BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
22
23 /* CompositeMoniker data structure */
24 typedef struct CompositeMonikerImpl{
25
26     ICOM_VTABLE(IMoniker)*  lpvtbl1;  /* VTable relative to the IMoniker interface.*/
27
28     /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether 
29      * two monikers are equal. That's whay IROTData interface is implemented by monikers.
30      */
31     ICOM_VTABLE(IROTData)*  lpvtbl2;  /* VTable relative to the IROTData interface.*/
32
33     ULONG ref; /* reference counter for this object */
34
35     IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */
36
37     ULONG    tabSize;      /* size of tabMoniker */
38
39     ULONG    tabLastIndex;  /* first free index in tabMoniker */
40
41 } CompositeMonikerImpl;
42
43
44 /* EnumMoniker data structure */
45 typedef struct EnumMonikerImpl{
46
47     ICOM_VFIELD(IEnumMoniker);  /* VTable relative to the IEnumMoniker interface.*/
48
49     ULONG ref; /* reference counter for this object */
50
51     IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
52
53     ULONG      tabSize; /* size of tabMoniker */
54
55     ULONG      currentPos;  /* index pointer on the current moniker */
56
57 } EnumMonikerImpl;
58
59
60 /********************************************************************************/
61 /* CompositeMoniker prototype functions :                                       */
62
63 /* IUnknown prototype functions */
64 static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
65 static ULONG   WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface);
66 static ULONG   WINAPI CompositeMonikerImpl_Release(IMoniker* iface);
67
68 /* IPersist prototype functions */
69 static HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
70
71 /* IPersistStream prototype functions */
72 static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface);
73 static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm);
74 static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
75 static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
76
77 /* IMoniker prototype functions */
78 static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
79 static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
80 static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
81 static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
82 static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
83 static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
84 static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
85 static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
86 static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime);
87 static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
88 static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
89 static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
90 static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
91 static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
92 static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
93
94 /********************************************************************************/
95 /* IROTData prototype functions                                                 */
96
97 /* IUnknown prototype functions */
98 static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
99 static ULONG   WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface);
100 static ULONG   WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface);
101
102 /* IROTData prototype function */
103 static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
104
105 /* Local function used by CompositeMoniker implementation */
106 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest);
107 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface);
108
109 /********************************************************************************/
110 /* IEnumMoniker prototype functions                                             */
111
112 /* IUnknown prototype functions */
113 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject);
114 static ULONG   WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface);
115 static ULONG   WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface);
116
117 /* IEnumMonker prototype functions */
118 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched);
119 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt);
120 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface);
121 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum);
122
123 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
124
125 /********************************************************************************/
126 /* Virtual function table for the CompositeMonikerImpl class which includes     */
127 /* IPersist, IPersistStream and IMoniker functions.                             */
128
129 static ICOM_VTABLE(IMoniker) VT_CompositeMonikerImpl =
130 {
131     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
132     CompositeMonikerImpl_QueryInterface,
133     CompositeMonikerImpl_AddRef,
134     CompositeMonikerImpl_Release,
135     CompositeMonikerImpl_GetClassID,
136     CompositeMonikerImpl_IsDirty,
137     CompositeMonikerImpl_Load,
138     CompositeMonikerImpl_Save,
139     CompositeMonikerImpl_GetSizeMax,
140     CompositeMonikerImpl_BindToObject,
141     CompositeMonikerImpl_BindToStorage,
142     CompositeMonikerImpl_Reduce,
143     CompositeMonikerImpl_ComposeWith,
144     CompositeMonikerImpl_Enum,
145     CompositeMonikerImpl_IsEqual,
146     CompositeMonikerImpl_Hash,
147     CompositeMonikerImpl_IsRunning,
148     CompositeMonikerImpl_GetTimeOfLastChange,
149     CompositeMonikerImpl_Inverse,
150     CompositeMonikerImpl_CommonPrefixWith,
151     CompositeMonikerImpl_RelativePathTo,
152     CompositeMonikerImpl_GetDisplayName,
153     CompositeMonikerImpl_ParseDisplayName,
154     CompositeMonikerImpl_IsSystemMoniker
155 };
156
157 /********************************************************************************/
158 /* Virtual function table for the IROTData class.                               */
159 static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
160 {
161     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
162     CompositeMonikerROTDataImpl_QueryInterface,
163     CompositeMonikerROTDataImpl_AddRef,
164     CompositeMonikerROTDataImpl_Release,
165     CompositeMonikerROTDataImpl_GetComparaisonData
166 };
167
168 /********************************************************************************/
169 /* Virtual function table for the IROTData class                                */
170 static ICOM_VTABLE(IEnumMoniker) VT_EnumMonikerImpl =
171 {
172     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
173     EnumMonikerImpl_QueryInterface,
174     EnumMonikerImpl_AddRef,
175     EnumMonikerImpl_Release,
176     EnumMonikerImpl_Next,
177     EnumMonikerImpl_Skip,
178     EnumMonikerImpl_Reset,
179     EnumMonikerImpl_Clone
180 };
181
182 /*******************************************************************************
183  *        CompositeMoniker_QueryInterface
184  *******************************************************************************/
185 HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
186 {
187     ICOM_THIS(CompositeMonikerImpl,iface);
188   
189     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
190
191     /* Perform a sanity check on the parameters.*/
192     if ( (This==0) || (ppvObject==0) )
193         return E_INVALIDARG;
194   
195     /* Initialize the return parameter */
196     *ppvObject = 0;
197
198     /* Compare the riid with the interface IDs implemented by this object.*/
199     if (IsEqualIID(&IID_IUnknown, riid) ||
200         IsEqualIID(&IID_IPersist, riid) ||
201         IsEqualIID(&IID_IPersistStream, riid) ||
202         IsEqualIID(&IID_IMoniker, riid)
203        )
204         *ppvObject = iface;
205     else if (IsEqualIID(&IID_IROTData, riid))
206         *ppvObject = (IROTData*)&(This->lpvtbl2);
207
208     /* Check that we obtained an interface.*/
209     if ((*ppvObject)==0)
210         return E_NOINTERFACE;
211
212     /* Query Interface always increases the reference count by one when it is successful */
213     CompositeMonikerImpl_AddRef(iface);
214
215     return S_OK;
216 }
217
218 /******************************************************************************
219  *        CompositeMoniker_AddRef
220  ******************************************************************************/
221 ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)
222 {
223     ICOM_THIS(CompositeMonikerImpl,iface);
224
225     TRACE("(%p)\n",This);
226
227     return ++(This->ref);
228 }
229
230 /******************************************************************************
231  *        CompositeMoniker_Release
232  ******************************************************************************/
233 ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
234 {
235     ICOM_THIS(CompositeMonikerImpl,iface);
236     ULONG i;
237     
238     TRACE("(%p)\n",This);
239
240     This->ref--;
241
242     /* destroy the object if there's no more reference on it */
243     if (This->ref==0){
244
245         /* release all the components before destroying this object */
246         for (i=0;i<This->tabLastIndex;i++)
247             IMoniker_Release(This->tabMoniker[i]);
248         
249         CompositeMonikerImpl_Destroy(This);
250
251         return 0;
252     }
253     return This->ref;;
254 }
255
256 /******************************************************************************
257  *        CompositeMoniker_GetClassID
258  ******************************************************************************/
259 HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
260 {
261     TRACE("(%p,%p),stub!\n",iface,pClassID);
262
263     if (pClassID==NULL)
264         return E_POINTER;
265             
266     *pClassID = CLSID_CompositeMoniker;
267         
268     return S_OK;
269 }
270
271 /******************************************************************************
272  *        CompositeMoniker_IsDirty
273  ******************************************************************************/
274 HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)
275 {
276     /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
277        method in the OLE-provided moniker interfaces always return S_FALSE because
278        their internal state never changes. */
279
280     TRACE("(%p)\n",iface);
281
282     return S_FALSE;
283 }
284
285 /******************************************************************************
286  *        CompositeMoniker_Load
287  ******************************************************************************/
288 HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
289 {
290     HRESULT res;
291     DWORD constant;
292     CLSID clsid;
293     WCHAR string[1]={0};
294     
295     ICOM_THIS(CompositeMonikerImpl,iface);    
296
297     TRACE("(%p,%p)\n",iface,pStm);
298
299     /* this function call OleLoadFromStream function for each moniker within this object */
300
301     /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
302     res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
303
304     if (SUCCEEDED(res)&& constant!=3)
305         return E_FAIL;
306
307     while(1){
308 #if 0
309         res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
310 #endif
311         res=ReadClassStm(pStm,&clsid);
312         DPRINTF("res=%ld",res);
313         if (FAILED(res))
314             break;
315
316         if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
317             res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
318             if (FAILED(res))
319                 break;
320             res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
321             if (FAILED(res))
322                 break;
323         }
324         else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
325             CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
326             if (res!=S_OK)
327                 break;
328             IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
329             if (FAILED(res))
330                 break;
331         }
332         else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
333             CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
334             if (FAILED(res))
335                 break;
336             IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
337             if (FAILED(res))
338                 break;
339         }
340         else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
341             return E_FAIL;
342
343         else{
344             FIXME("()");
345             break;
346             return E_NOTIMPL;
347         }
348
349         /* resize the table if needed */
350         if (++This->tabLastIndex==This->tabSize){
351                 
352             This->tabSize+=BLOCK_TAB_SIZE;
353             This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
354
355             if (This->tabMoniker==NULL)
356             return E_OUTOFMEMORY;
357         }
358     }
359
360     return res;
361 }
362
363 /******************************************************************************
364  *        CompositeMoniker_Save
365  ******************************************************************************/
366 HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
367 {
368     HRESULT res;
369     IEnumMoniker *enumMk;
370     IMoniker *pmk;
371     DWORD constant=3;
372     
373     TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
374
375     /* this function call OleSaveToStream function for each moniker within this object */
376
377     /* when I tested this function in windows system ! I usually found this constant in the begining of */
378     /* the stream  I dont known why (there's no indication in specification) ! */
379     res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
380
381     IMoniker_Enum(iface,TRUE,&enumMk);
382
383     while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
384
385         res=OleSaveToStream((IPersistStream*)pmk,pStm);
386
387         IMoniker_Release(pmk);
388
389         if (FAILED(res)){
390
391             IEnumMoniker_Release(pmk);
392             return res;
393         }
394     }
395
396     IEnumMoniker_Release(enumMk);
397
398     return S_OK;
399 }
400
401 /******************************************************************************
402  *        CompositeMoniker_GetSizeMax
403  ******************************************************************************/
404 HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
405 {
406     IEnumMoniker *enumMk;
407     IMoniker *pmk;
408     ULARGE_INTEGER ptmpSize;
409
410     /* the sizeMax of this object is calculated by calling  GetSizeMax on each moniker within this object then */
411     /* suming all returned sizemax */
412
413     TRACE("(%p,%p)\n",iface,pcbSize);
414
415     if (pcbSize!=NULL)
416         return E_POINTER;
417
418     pcbSize->s.LowPart =0;
419     pcbSize->s.HighPart=0;
420
421     IMoniker_Enum(iface,TRUE,&enumMk);
422
423     while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){
424
425         IMoniker_GetSizeMax(pmk,&ptmpSize);
426
427         IMoniker_Release(pmk);
428
429         pcbSize->s.LowPart +=ptmpSize.s.LowPart;
430         pcbSize->s.HighPart+=ptmpSize.s.HighPart;
431     }
432
433     IEnumMoniker_Release(enumMk);
434
435     return S_OK;
436 }
437
438 /******************************************************************************
439  *         Composite-Moniker_Construct (local function)
440  *******************************************************************************/
441 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest)
442 {
443     DWORD mkSys;
444     IEnumMoniker *enumMoniker;
445     IMoniker *tempMk;
446     HRESULT res;
447     
448     TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
449
450     /* Initialize the virtual fgunction table. */
451     This->lpvtbl1      = &VT_CompositeMonikerImpl;
452     This->lpvtbl2      = &VT_ROTDataImpl;
453     This->ref          = 0;
454
455     This->tabSize=BLOCK_TAB_SIZE;
456     This->tabLastIndex=0;
457
458     This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
459     if (This->tabMoniker==NULL)
460         return E_OUTOFMEMORY;
461
462     IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
463
464     /* put the first moniker contents in the begining of the table */
465     if (mkSys!=MKSYS_GENERICCOMPOSITE){
466
467         This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
468         IMoniker_AddRef(pmkFirst);
469     }
470     else{
471
472         IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
473         
474         while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
475
476
477             if (++This->tabLastIndex==This->tabSize){
478                 
479                 This->tabSize+=BLOCK_TAB_SIZE;
480                 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
481
482                 if (This->tabMoniker==NULL)
483                     return E_OUTOFMEMORY;
484             }
485         }
486
487         IEnumMoniker_Release(enumMoniker);
488     }
489
490     /* put the rest moniker contents after the first one and make simplification if needed */
491
492     IMoniker_IsSystemMoniker(pmkRest,&mkSys);
493     
494     if (mkSys!=MKSYS_GENERICCOMPOSITE){
495
496         /* add a simple moniker to the moniker table */
497
498         res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
499
500         if (res==MK_E_NEEDGENERIC){ 
501
502             /* there's no simplification in this case */
503             This->tabMoniker[This->tabLastIndex]=pmkRest;
504
505             This->tabLastIndex++;
506
507             IMoniker_AddRef(pmkRest);
508         }
509         else if (tempMk==NULL){ 
510
511             /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
512             IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
513
514             This->tabLastIndex--;
515         }
516         else if (SUCCEEDED(res)){
517
518             /* the non-generic composition was successful so we can make a simplification in this case */
519             IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
520
521             This->tabMoniker[This->tabLastIndex-1]=tempMk;
522         } else
523             return res;
524
525         /* resize tabMoniker if needed */
526         if (This->tabLastIndex==This->tabSize){
527                 
528             This->tabSize+=BLOCK_TAB_SIZE;
529
530             This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
531
532             if (This->tabMoniker==NULL)
533             return E_OUTOFMEMORY;
534         }
535     }
536     else{
537
538         /* add a composite moniker to the moniker table (do the same thing for each moniker within the */
539         /* composite moniker as a simple moniker (see above how to add a simple moniker case) ) */
540         IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
541
542         while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
543
544             res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
545
546             if (res==MK_E_NEEDGENERIC){
547
548                 This->tabLastIndex++;
549             }
550             else if (tempMk==NULL){
551
552                 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
553                 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
554                 This->tabLastIndex--;
555             }
556             else{
557
558                 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
559
560                 This->tabMoniker[This->tabLastIndex-1]=tempMk;
561             }
562
563             if (This->tabLastIndex==This->tabSize){
564                 
565                 This->tabSize+=BLOCK_TAB_SIZE;
566
567                 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
568
569                 if (This->tabMoniker==NULL)
570                     return E_OUTOFMEMORY;
571             }
572         }
573
574         IEnumMoniker_Release(enumMoniker);
575     }
576
577     return S_OK;
578 }
579
580 /******************************************************************************
581  *        CompositeMoniker_Destroy (local function)
582  *******************************************************************************/
583 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This)
584 {
585     TRACE("(%p)\n",This);
586
587     HeapFree(GetProcessHeap(),0,This->tabMoniker);
588
589     HeapFree(GetProcessHeap(),0,This);
590
591     return S_OK;
592 }
593
594 /******************************************************************************
595  *                  CompositeMoniker_BindToObject
596  ******************************************************************************/
597 HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,
598                                                  IBindCtx* pbc,
599                                                  IMoniker* pmkToLeft,
600                                                  REFIID riid,
601                                                  VOID** ppvResult)
602 {
603     HRESULT   res;
604     IRunningObjectTable *prot;
605     IMoniker *tempMk,*antiMk,*mostRigthMk;
606     IEnumMoniker *enumMoniker;
607     
608     TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
609
610     if (ppvResult==NULL)
611         return E_POINTER;
612     
613     *ppvResult=0;
614     /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
615     /* object for the requested interface pointer. */
616     if(pmkToLeft==NULL){
617
618         res=IBindCtx_GetRunningObjectTable(pbc,&prot);
619
620         if (SUCCEEDED(res)){
621
622             /* if the requested class was loaded befor ! we dont need to reload it */
623             res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
624
625             if (res==S_OK)
626                 return res;
627         }
628     }
629     else{
630         /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
631         /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
632
633         IMoniker_Enum(iface,FALSE,&enumMoniker);
634         IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
635         IEnumMoniker_Release(enumMoniker);
636         
637         res=CreateAntiMoniker(&antiMk);
638         res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
639         IMoniker_Release(antiMk);
640         
641         res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
642
643         IMoniker_Release(tempMk);
644         IMoniker_Release(mostRigthMk);
645     }
646
647     return res;
648 }
649
650 /******************************************************************************
651  *        CompositeMoniker_BindToStorage
652  ******************************************************************************/
653 HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,
654                                                   IBindCtx* pbc,
655                                                   IMoniker* pmkToLeft,
656                                                   REFIID riid,
657                                                   VOID** ppvResult)
658 {
659     HRESULT   res;
660     IMoniker *tempMk,*antiMk,*mostRigthMk;
661     IEnumMoniker *enumMoniker;
662
663     TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
664
665     *ppvResult=0;
666
667     /* This method recursively calls BindToStorage on the rightmost component of the composite, */
668     /* passing the rest of the composite as the pmkToLeft parameter for that call. */
669
670     if (pmkToLeft!=NULL){
671         
672         IMoniker_Enum(iface,FALSE,&enumMoniker);
673         IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
674         IEnumMoniker_Release(enumMoniker);
675         
676         res=CreateAntiMoniker(&antiMk);
677         res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
678         IMoniker_Release(antiMk);
679         
680         res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
681
682         IMoniker_Release(tempMk);
683
684         IMoniker_Release(mostRigthMk);
685
686         return res;
687     }
688     else
689         return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
690 }
691
692 /******************************************************************************
693  *        CompositeMoniker_Reduce
694  ******************************************************************************/
695 HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,
696                                            IBindCtx* pbc,
697                                            DWORD dwReduceHowFar,
698                                            IMoniker** ppmkToLeft,
699                                            IMoniker** ppmkReduced)
700 {
701     HRESULT   res;
702     IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
703     IEnumMoniker *enumMoniker;
704
705     TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
706
707     if (ppmkReduced==NULL)
708         return E_POINTER;
709
710     /* This method recursively calls Reduce for each of its component monikers. */
711
712     if (ppmkToLeft==NULL){
713
714         IMoniker_Enum(iface,FALSE,&enumMoniker);
715         IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
716         IEnumMoniker_Release(enumMoniker);
717         
718         res=CreateAntiMoniker(&antiMk);
719         res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
720         IMoniker_Release(antiMk);
721
722         return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
723     }
724     else if (*ppmkToLeft==NULL)
725
726         return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
727
728     else{
729
730         /* separate the copmosite moniker in to left and wrigth moniker */
731         IMoniker_Enum(iface,FALSE,&enumMoniker);
732         IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
733         IEnumMoniker_Release(enumMoniker);
734         
735         res=CreateAntiMoniker(&antiMk);
736         res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
737         IMoniker_Release(antiMk);
738
739         /* If any of the components  reduces itself, the method returns S_OK and passes back a composite */
740         /* of the reduced components */
741         if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
742             CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
743            )
744
745             return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
746
747         else{
748             /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
749
750             IMoniker_AddRef(iface);
751
752             *ppmkReduced=iface;
753
754             return MK_S_REDUCED_TO_SELF;
755         }
756     }
757 }
758
759 /******************************************************************************
760  *        CompositeMoniker_ComposeWith
761  ******************************************************************************/
762 HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,
763                                                 IMoniker* pmkRight,
764                                                 BOOL fOnlyIfNotGeneric,
765                                                 IMoniker** ppmkComposite)
766 {
767     TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
768
769     if ((ppmkComposite==NULL)||(pmkRight==NULL))
770         return E_POINTER;
771
772     *ppmkComposite=0;
773
774     /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
775     /* otherwise, the method returns the result of combining the two monikers by calling the */
776     /* CreateGenericComposite function */
777     
778     if (fOnlyIfNotGeneric)
779         return MK_E_NEEDGENERIC;
780     
781     return CreateGenericComposite(iface,pmkRight,ppmkComposite);
782 }
783
784 /******************************************************************************
785  *        CompositeMoniker_Enum
786  ******************************************************************************/
787 HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
788 {
789     ICOM_THIS(CompositeMonikerImpl,iface);
790
791     TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
792
793     if (ppenumMoniker == NULL)
794         return E_POINTER;
795     
796     return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
797 }
798
799 /******************************************************************************
800  *        CompositeMoniker_IsEqual
801  ******************************************************************************/
802 HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
803 {
804     IEnumMoniker *enumMoniker1,*enumMoniker2;
805     IMoniker *tempMk1,*tempMk2;
806     HRESULT res1,res2,res;
807     
808     TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
809
810     if (pmkOtherMoniker==NULL)
811         return S_FALSE;
812
813     /* This method returns S_OK if the components of both monikers are equal when compared in the */
814     /* left-to-right order.*/
815     IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
816
817     if (enumMoniker1==NULL)
818         return S_FALSE;
819     
820     IMoniker_Enum(iface,TRUE,&enumMoniker2);
821
822     while(1){
823
824         res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
825         res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
826         
827         if((res1==S_OK)&&(res2==S_OK)){
828
829             if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
830                 res= S_FALSE;
831                 break;
832             }
833             else
834                 continue;
835         }
836         else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
837                 res = S_OK;
838                 break;
839         }
840         else{
841             res = S_FALSE;
842             break;
843         }
844
845         if (res1==S_OK)
846             IMoniker_Release(tempMk1);
847
848         if (res2==S_OK)
849             IMoniker_Release(tempMk2);
850     }
851
852     IEnumMoniker_Release(enumMoniker1);
853     IEnumMoniker_Release(enumMoniker2);
854
855     return res;
856 }
857 /******************************************************************************
858  *        CompositeMoniker_Hash
859  ******************************************************************************/
860 HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
861 {
862     FIXME("(),stub!\n");
863
864     return E_NOTIMPL;
865 }
866
867 /******************************************************************************
868  *        CompositeMoniker_IsRunning
869  ******************************************************************************/
870 HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,
871                                               IBindCtx* pbc,
872                                               IMoniker* pmkToLeft,
873                                               IMoniker* pmkNewlyRunning)
874 {
875     IRunningObjectTable* rot;
876     HRESULT res;
877     IMoniker *tempMk,*antiMk,*mostRigthMk;
878     IEnumMoniker *enumMoniker;
879
880     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
881
882     /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
883     if (pmkToLeft!=NULL){
884
885         CreateGenericComposite(pmkToLeft,iface,&tempMk);
886
887         res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
888
889         IMoniker_Release(tempMk);
890
891         return res;
892     }
893     else
894         /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
895         /* to this moniker */
896         
897         if (pmkNewlyRunning!=NULL)
898
899             if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
900                 return S_OK;
901
902             else
903                 return S_FALSE;
904
905         else{
906
907             if (pbc==NULL)
908                 return E_POINTER;
909
910             /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
911             /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls   */
912             /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
913             /* the composite as the pmkToLeft parameter for that call.                                   */
914             
915              res=IBindCtx_GetRunningObjectTable(pbc,&rot);
916
917             if (FAILED(res))
918                 return res;
919
920             res = IRunningObjectTable_IsRunning(rot,iface);
921             IRunningObjectTable_Release(rot);
922
923             if(res==S_OK)
924                 return S_OK;
925
926             else{
927
928                 IMoniker_Enum(iface,FALSE,&enumMoniker);
929                 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
930                 IEnumMoniker_Release(enumMoniker);
931
932                 res=CreateAntiMoniker(&antiMk);
933                 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
934                 IMoniker_Release(antiMk);
935
936                 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
937
938                 IMoniker_Release(tempMk);
939                 IMoniker_Release(mostRigthMk);
940
941                 return res;
942             }
943         }
944 }
945
946 /******************************************************************************
947  *        CompositeMoniker_GetTimeOfLastChange
948  ******************************************************************************/
949 HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
950                                                         IBindCtx* pbc,
951                                                         IMoniker* pmkToLeft,
952                                                         FILETIME* pCompositeTime)
953 {
954     IRunningObjectTable* rot;
955     HRESULT res;
956     IMoniker *tempMk,*antiMk,*mostRigthMk;
957     IEnumMoniker *enumMoniker;
958     
959     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
960
961     if (pCompositeTime==NULL)
962         return E_INVALIDARG;
963
964     /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to  */
965     /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls  */
966     /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
967     /* of the composite as the pmkToLeft parameter for that call.                                       */
968     if (pmkToLeft!=NULL){
969
970         res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
971
972         res=IBindCtx_GetRunningObjectTable(pbc,&rot);
973
974         if (FAILED(res))
975             return res;
976
977         if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
978             return res;
979         else
980
981             IMoniker_Enum(iface,FALSE,&enumMoniker);
982             IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
983             IEnumMoniker_Release(enumMoniker);
984
985             res=CreateAntiMoniker(&antiMk);
986             res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
987             IMoniker_Release(antiMk);
988
989             res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
990
991             IMoniker_Release(tempMk);
992             IMoniker_Release(mostRigthMk);
993
994             return res;
995     }
996     else
997         return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
998 }
999
1000 /******************************************************************************
1001  *        CompositeMoniker_Inverse
1002  ******************************************************************************/
1003 HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
1004 {
1005     HRESULT res;
1006     IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
1007     IEnumMoniker *enumMoniker;
1008
1009     TRACE("(%p,%p)\n",iface,ppmk);
1010
1011     if (ppmk==NULL)
1012         return E_POINTER;
1013
1014     /* This method returns a composite moniker that consists of the inverses of each of the components */
1015     /* of the original composite, stored in reverse order */
1016
1017     res=CreateAntiMoniker(&antiMk);
1018     res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1019     IMoniker_Release(antiMk);
1020
1021     if (tempMk==NULL)
1022
1023         return IMoniker_Inverse(iface,ppmk);
1024
1025     else{
1026
1027         IMoniker_Enum(iface,FALSE,&enumMoniker);
1028         IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1029         IEnumMoniker_Release(enumMoniker);
1030
1031         IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
1032         CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
1033
1034         res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
1035
1036         IMoniker_Release(tempMk);
1037         IMoniker_Release(mostRigthMk);
1038         IMoniker_Release(tempInvMk);
1039         IMoniker_Release(mostRigthInvMk);
1040
1041         return res;
1042     }
1043 }
1044
1045 /******************************************************************************
1046  *        CompositeMoniker_CommonPrefixWith
1047  ******************************************************************************/
1048 HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1049 {
1050     DWORD mkSys;
1051     HRESULT res1,res2;
1052     IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
1053     IEnumMoniker *enumMoniker1,*enumMoniker2;
1054     ULONG i,nbCommonMk=0;
1055     
1056     /* If the other moniker is a composite, this method compares the components of each composite from left  */
1057     /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1058     /* of the leftmost components were common to both monikers.                                              */
1059
1060     if (ppmkPrefix==NULL)
1061         return E_POINTER;
1062     
1063     *ppmkPrefix=0;
1064
1065     if (pmkOther==NULL)
1066         return MK_E_NOPREFIX;
1067     
1068     IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1069
1070     if((mkSys==MKSYS_GENERICCOMPOSITE)){
1071
1072         IMoniker_Enum(iface,TRUE,&enumMoniker1);
1073         IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
1074
1075         while(1){
1076
1077             res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1078             res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
1079
1080             if ((res1==S_FALSE) && (res2==S_FALSE)){
1081
1082                 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1083                 *ppmkPrefix=iface;
1084                 IMoniker_AddRef(iface);
1085                 return  MK_S_US;
1086             }
1087             else if ((res1==S_OK) && (res2==S_OK)){
1088
1089                 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
1090
1091                     nbCommonMk++;
1092
1093                 else
1094                     break;
1095
1096             }
1097             else if (res1==S_OK){
1098
1099                 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1100                 /* ppmkPrefix to the other moniker.                                                       */
1101                 *ppmkPrefix=pmkOther;
1102                 return MK_S_HIM;
1103             }
1104             else{
1105                 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1106                 /* to this moniker.                                                                          */
1107                 *ppmkPrefix=iface;
1108                 return MK_S_ME;
1109             }
1110         }
1111
1112         IEnumMoniker_Release(enumMoniker1);
1113         IEnumMoniker_Release(enumMoniker2);
1114
1115         /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1116         if (nbCommonMk==0)
1117             return MK_E_NOPREFIX;
1118
1119         IEnumMoniker_Reset(enumMoniker1);
1120
1121         IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1122
1123         /* if we have more than one commun moniker the result will be a composite moniker */
1124         if (nbCommonMk>1){
1125
1126             /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1127             IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1128             CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
1129             IMoniker_Release(tempMk1);
1130             IMoniker_Release(tempMk2);
1131             
1132             /* compose all common monikers in a composite moniker */
1133             for(i=0;i<nbCommonMk;i++){
1134
1135                 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1136
1137                 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
1138
1139                 IMoniker_Release(*ppmkPrefix);
1140
1141                 IMoniker_Release(tempMk1);
1142                 
1143                 *ppmkPrefix=tempMk2;
1144             }
1145             return S_OK;
1146         }
1147         else{
1148             /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1149             *ppmkPrefix=tempMk1;
1150
1151             return S_OK;
1152         }
1153     }
1154     else{
1155         /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1156          of this moniker.*/
1157
1158         IMoniker_Enum(iface,TRUE,&enumMoniker1);
1159
1160         IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1161
1162         if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
1163
1164             *ppmkPrefix=pmkOther;
1165
1166             return MK_S_HIM;
1167         }
1168         else
1169             return MK_E_NOPREFIX;
1170     }
1171 }
1172 /***************************************************************************************************
1173  *        GetAfterCommonPrefix (local function)
1174  *  This function returns a moniker that consist of the remainder when the common prefix is removed
1175  ***************************************************************************************************/
1176 VOID WINAPI GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
1177 {
1178     IMoniker *tempMk,*tempMk1,*tempMk2;
1179     IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
1180     ULONG nbRestMk=0;
1181     DWORD mkSys;
1182     HRESULT res1,res2;
1183     
1184     *restMk=0;
1185
1186     /* to create an enumerator for pGenMk with current position pointed on the first element after common  */
1187     /* prefix: enum the two monikers (left-wrigth) then compare these enumerations (left-wrigth) and stop  */
1188     /* on the first difference. */
1189     IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
1190
1191     IMoniker_IsSystemMoniker(commonMk,&mkSys);
1192
1193     if (mkSys==MKSYS_GENERICCOMPOSITE){
1194
1195         IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
1196         while(1){
1197
1198             res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1199             res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
1200
1201             if ((res1==S_FALSE)||(res2==S_FALSE)){
1202
1203                 if (res1==S_OK)
1204
1205                     nbRestMk++;
1206
1207                 IMoniker_Release(tempMk1);
1208                 IMoniker_Release(tempMk1);
1209
1210                 break;
1211             }
1212             IMoniker_Release(tempMk1);
1213             IMoniker_Release(tempMk1);
1214         }
1215     }
1216     else{
1217         IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1218         IMoniker_Release(tempMk1);
1219     }
1220
1221     /* count the number of elements in the enumerator after the common prefix */
1222     IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1223
1224     for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1225
1226         IMoniker_Release(tempMk);;
1227
1228     if (nbRestMk==0)
1229         return;
1230
1231     /* create a generic composite moniker with monikers located after the common prefix */
1232     IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1233
1234     if (nbRestMk==1){
1235
1236         *restMk= tempMk1;
1237         return;
1238     }
1239     else {
1240
1241         IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1242
1243         CreateGenericComposite(tempMk1,tempMk2,restMk);
1244
1245         IMoniker_Release(tempMk1);
1246
1247         IMoniker_Release(tempMk2);
1248
1249         while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1250
1251             CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1252
1253             IMoniker_Release(tempMk1);
1254
1255             IMoniker_Release(*restMk);
1256
1257             *restMk=tempMk2;
1258         }
1259     }
1260 }
1261 /******************************************************************************
1262  *        CompositeMoniker_RelativePathTo
1263  ******************************************************************************/
1264 HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkRelPath)
1265 {
1266     HRESULT res;
1267     IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1268
1269     TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1270
1271     if (ppmkRelPath==NULL)
1272         return E_POINTER;
1273
1274     *ppmkRelPath=0;
1275
1276     /* This method finds the common prefix of the two monikers and creates two monikers that consist     */
1277     /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1278     /* of this moniker and composes the remainder of the other moniker on the right of it.               */
1279
1280     /* finds the common prefix of the two monikers */
1281     res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);    
1282
1283     /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1284     if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1285
1286         *ppmkRelPath=pmkOther;
1287         IMoniker_AddRef(pmkOther);
1288         return MK_S_HIM;
1289     }
1290
1291     GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1292     GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1293
1294     /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1295     /* moniker when the common prefix is removed                                                           */
1296     if (res==MK_S_HIM){
1297
1298         IMoniker_Inverse(restThisMk,ppmkRelPath);
1299         IMoniker_Release(restThisMk);
1300     }
1301     /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1302     /* when the common prefix is removed                                                                     */
1303     else if (res==MK_S_ME){
1304
1305         *ppmkRelPath=restOtherMk;
1306         IMoniker_AddRef(restOtherMk);
1307     }
1308     /* the relative path is the inverse for the remainder of this moniker and the remainder of the other  */
1309     /* moniker on the right of it.                                                                        */
1310     else if (res==S_OK){
1311
1312         IMoniker_Inverse(restThisMk,&invRestThisMk);
1313         IMoniker_Release(restThisMk);
1314         CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1315         IMoniker_Release(invRestThisMk);
1316         IMoniker_Release(restOtherMk);
1317     }
1318     return S_OK;
1319 }
1320
1321 /******************************************************************************
1322  *        CompositeMoniker_GetDisplayName
1323  ******************************************************************************/
1324 HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,
1325                                                    IBindCtx* pbc,
1326                                                    IMoniker* pmkToLeft,
1327                                                    LPOLESTR *ppszDisplayName)
1328 {
1329     ULONG lengthStr=1;
1330     IEnumMoniker *enumMoniker;
1331     IMoniker* tempMk;
1332     LPOLESTR tempStr;
1333
1334     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1335
1336     if (ppszDisplayName==NULL)
1337         return E_POINTER;
1338     
1339     *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1340
1341     if (*ppszDisplayName==NULL)
1342         return E_OUTOFMEMORY;
1343
1344     /* This method returns the concatenation of the display names returned by each component moniker of */
1345     /* the composite */
1346
1347     **ppszDisplayName=0;
1348
1349     IMoniker_Enum(iface,TRUE,&enumMoniker);
1350     
1351     while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1352
1353         IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1354
1355         lengthStr+=lstrlenW(tempStr);
1356
1357         *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1358
1359         if (*ppszDisplayName==NULL)
1360             return E_OUTOFMEMORY;
1361
1362         strcatW(*ppszDisplayName,tempStr);
1363
1364         CoTaskMemFree(tempStr);
1365         IMoniker_Release(tempMk);
1366     }
1367
1368     IEnumMoniker_Release(enumMoniker);
1369
1370     return S_OK;
1371 }
1372
1373 /******************************************************************************
1374  *        CompositeMoniker_ParseDisplayName
1375  ******************************************************************************/
1376 HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,
1377                                                      IBindCtx* pbc,
1378                                                      IMoniker* pmkToLeft,
1379                                                      LPOLESTR pszDisplayName,
1380                                                      ULONG* pchEaten,
1381                                                      IMoniker** ppmkOut)
1382 {
1383     IEnumMoniker *enumMoniker;
1384     IMoniker *tempMk,*mostRigthMk,*antiMk;
1385     /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1386     /* passing everything else as the pmkToLeft parameter for that call. */
1387
1388     /* get the most rigth moniker */
1389     IMoniker_Enum(iface,FALSE,&enumMoniker);
1390     IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1391     IEnumMoniker_Release(enumMoniker);
1392
1393     /* get the left  moniker */
1394     CreateAntiMoniker(&antiMk);
1395     IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1396     IMoniker_Release(antiMk);
1397
1398     return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1399 }
1400
1401 /******************************************************************************
1402  *        CompositeMoniker_IsSystemMonker
1403  ******************************************************************************/
1404 HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1405 {
1406     TRACE("(%p,%p)\n",iface,pwdMksys);
1407
1408     if (!pwdMksys)
1409         return E_POINTER;
1410     
1411     (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1412
1413     return S_OK;
1414 }
1415
1416 /*******************************************************************************
1417  *        CompositeMonikerIROTData_QueryInterface
1418  *******************************************************************************/
1419 HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1420 {
1421
1422     ICOM_THIS_From_IROTData(IMoniker, iface);
1423
1424     TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
1425
1426     return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1427 }
1428
1429 /***********************************************************************
1430  *        CompositeMonikerIROTData_AddRef
1431  */
1432 ULONG   WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1433 {
1434     ICOM_THIS_From_IROTData(IMoniker, iface);
1435
1436     TRACE("(%p)\n",iface);
1437
1438     return CompositeMonikerImpl_AddRef(This);
1439 }
1440
1441 /***********************************************************************
1442  *        CompositeMonikerIROTData_Release
1443  */
1444 ULONG   WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1445 {
1446     ICOM_THIS_From_IROTData(IMoniker, iface);
1447     
1448     TRACE("(%p)\n",iface);
1449
1450     return CompositeMonikerImpl_Release(This);
1451 }
1452
1453 /******************************************************************************
1454  *        CompositeMonikerIROTData_GetComparaisonData
1455  ******************************************************************************/
1456 HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1457                                                               BYTE* pbData,
1458                                                               ULONG cbMax,
1459                                                               ULONG* pcbData)
1460 {
1461     FIXME("(),stub!\n");
1462     return E_NOTIMPL;
1463 }
1464
1465 /******************************************************************************
1466  *        EnumMonikerImpl_QueryInterface
1467  ******************************************************************************/
1468 HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1469 {
1470     ICOM_THIS(EnumMonikerImpl,iface);
1471   
1472     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1473
1474     /* Perform a sanity check on the parameters.*/
1475     if ( (This==0) || (ppvObject==0) )
1476         return E_INVALIDARG;
1477   
1478     /* Initialize the return parameter */
1479     *ppvObject = 0;
1480
1481     /* Compare the riid with the interface IDs implemented by this object.*/
1482     if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1483         *ppvObject = iface;
1484
1485     /* Check that we obtained an interface.*/
1486     if ((*ppvObject)==0)
1487         return E_NOINTERFACE;
1488
1489     /* Query Interface always increases the reference count by one when it is successful */
1490     EnumMonikerImpl_AddRef(iface);
1491
1492     return S_OK;
1493 }
1494
1495 /******************************************************************************
1496  *        EnumMonikerImpl_AddRef
1497  ******************************************************************************/
1498 ULONG   WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1499 {
1500     ICOM_THIS(EnumMonikerImpl,iface);
1501
1502     TRACE("(%p)\n",This);
1503
1504     return ++(This->ref);
1505
1506 }
1507
1508 /******************************************************************************
1509  *        EnumMonikerImpl_Release
1510  ******************************************************************************/
1511 ULONG   WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1512 {
1513     ICOM_THIS(EnumMonikerImpl,iface);
1514     ULONG i
1515         ;
1516     TRACE("(%p)\n",This);
1517
1518     This->ref--;
1519
1520     /* destroy the object if there's no more reference on it */
1521     if (This->ref==0){
1522         
1523         for(i=0;i<This->tabSize;i++)
1524             IMoniker_Release(This->tabMoniker[i]);
1525
1526         HeapFree(GetProcessHeap(),0,This->tabMoniker);
1527         HeapFree(GetProcessHeap(),0,This);
1528
1529         return 0;
1530     }
1531     return This->ref;;
1532 }
1533
1534 /******************************************************************************
1535  *        EnumMonikerImpl_Next
1536  ******************************************************************************/
1537 HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){
1538
1539     ICOM_THIS(EnumMonikerImpl,iface);
1540     ULONG i;
1541
1542     /* retrieve the requested number of moniker from the current position */
1543     for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1544
1545         rgelt[i]=This->tabMoniker[This->currentPos++];
1546
1547     if (pceltFethed!=NULL)
1548         *pceltFethed= i;
1549     
1550     if (i==celt)
1551         return S_OK;
1552     else
1553         return S_FALSE;
1554 }
1555
1556 /******************************************************************************
1557  *        EnumMonikerImpl_Skip
1558  ******************************************************************************/
1559 HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){
1560
1561     ICOM_THIS(EnumMonikerImpl,iface);
1562
1563     if ((This->currentPos+celt) >= This->tabSize)
1564         return S_FALSE;
1565
1566     This->currentPos+=celt;
1567     
1568     return S_OK;
1569 }
1570
1571 /******************************************************************************
1572  *        EnumMonikerImpl_Reset
1573  ******************************************************************************/
1574 HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){
1575
1576     ICOM_THIS(EnumMonikerImpl,iface);
1577
1578     This->currentPos=0;
1579
1580     return S_OK;
1581 }
1582
1583 /******************************************************************************
1584  *        EnumMonikerImpl_Clone
1585  ******************************************************************************/
1586 HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){
1587
1588     ICOM_THIS(EnumMonikerImpl,iface);
1589
1590     return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1591 }
1592
1593 /******************************************************************************
1594  *        EnumMonikerImpl_CreateEnumMoniker
1595  ******************************************************************************/
1596 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,
1597                                                  ULONG tabSize,
1598                                                  ULONG currentPos,
1599                                                  BOOL leftToRigth,
1600                                                  IEnumMoniker ** ppmk)
1601 {
1602     EnumMonikerImpl* newEnumMoniker;
1603     int i;
1604
1605
1606     newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1607
1608     if (newEnumMoniker == 0)
1609         return STG_E_INSUFFICIENTMEMORY;
1610
1611     if (currentPos > tabSize)
1612         return E_INVALIDARG;
1613     
1614     /* Initialize the virtual function table. */
1615     ICOM_VTBL(newEnumMoniker)    = &VT_EnumMonikerImpl;
1616     newEnumMoniker->ref          = 0;
1617
1618     newEnumMoniker->tabSize=tabSize;
1619     newEnumMoniker->currentPos=currentPos;
1620
1621     newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1622
1623     if (newEnumMoniker->tabMoniker==NULL)
1624         return E_OUTOFMEMORY;
1625
1626     if (leftToRigth)
1627         for (i=0;i<tabSize;i++){
1628
1629             newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1630             IMoniker_AddRef(tabMoniker[i]);
1631         }
1632     else
1633         for (i=tabSize-1;i>=0;i--){
1634
1635             newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1636             IMoniker_AddRef(tabMoniker[i]);
1637         }
1638
1639     *ppmk=(IEnumMoniker*)newEnumMoniker;
1640
1641     return S_OK;
1642 }
1643
1644 /******************************************************************************
1645  *        CreateGenericComposite        [OLE.55]
1646  ******************************************************************************/
1647 HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite)
1648 {
1649     CompositeMonikerImpl* newCompositeMoniker = 0;
1650     HRESULT        hr = S_OK;
1651
1652     TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1653
1654     if (ppmkComposite==NULL)
1655         return E_POINTER;
1656     
1657     *ppmkComposite=0;
1658
1659     if (pmkFirst==NULL && pmkRest!=NULL){
1660
1661         *ppmkComposite=pmkRest;
1662         return S_OK;
1663     }
1664     else if (pmkFirst!=NULL && pmkRest==NULL){
1665         *ppmkComposite=pmkFirst;
1666         return S_OK;
1667     }
1668     else  if (pmkFirst==NULL && pmkRest==NULL)
1669         return S_OK;
1670
1671     newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
1672
1673     if (newCompositeMoniker == 0)
1674         return STG_E_INSUFFICIENTMEMORY;
1675
1676     hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
1677
1678     if (FAILED(hr)){
1679
1680         HeapFree(GetProcessHeap(),0,newCompositeMoniker);
1681         return hr;
1682     }
1683     if (newCompositeMoniker->tabLastIndex==1)
1684
1685         hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
1686     else
1687
1688         hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
1689
1690     return hr;
1691 }
1692
1693 /******************************************************************************
1694  *        MonikerCommonPrefixWith       [OLE.55]
1695  ******************************************************************************/
1696 HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1697 {
1698     FIXME("(),stub!\n");
1699     return E_NOTIMPL;
1700 }
1701
1702