:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / lib / ole32 / compositemoniker.c
1 /***************************************************************************************
2  *                            CompositeMonikers implementation
3  *
4  *               Copyright 1999  Noomen Hamza
5  ***************************************************************************************/
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include <windows.h>
12 #include <ole32/ole32.h>
13 #include <compobj.h>
14 #include <storage32.h>
15
16 #include <debug.h>
17
18
19 #define  BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
20
21 /* CompositeMoniker data structure */
22 typedef struct CompositeMonikerImpl{
23
24     ICOM_VTABLE(IMoniker)*  lpvtbl1;  /* VTable relative to the IMoniker interface.*/
25
26     /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether 
27      * two monikers are equal. That's whay IROTData interface is implemented by monikers.
28      */
29     ICOM_VTABLE(IROTData)*  lpvtbl2;  /* VTable relative to the IROTData interface.*/
30
31     ULONG ref; /* reference counter for this object */
32
33     IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */
34
35     ULONG    tabSize;      /* size of tabMoniker */
36
37     ULONG    tabLastIndex;  /* first free index in tabMoniker */
38
39 } CompositeMonikerImpl;
40
41
42 /* EnumMoniker data structure */
43 typedef struct EnumMonikerImpl{
44
45     ICOM_VFIELD(IEnumMoniker);  /* VTable relative to the IEnumMoniker interface.*/
46
47     ULONG ref; /* reference counter for this object */
48
49     IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
50
51     ULONG      tabSize; /* size of tabMoniker */
52
53     ULONG      currentPos;  /* index pointer on the current moniker */
54
55 } EnumMonikerImpl;
56
57
58 /********************************************************************************/
59 /* CompositeMoniker prototype functions :                                       */
60
61 /* IUnknown prototype functions */
62 static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
63 static ULONG   WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface);
64 static ULONG   WINAPI CompositeMonikerImpl_Release(IMoniker* iface);
65
66 /* IPersist prototype functions */
67 static HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
68
69 /* IPersistStream prototype functions */
70 static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface);
71 static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm);
72 static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
73 static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
74
75 /* IMoniker prototype functions */
76 static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
77 static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
78 static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
79 static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
80 static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
81 static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
82 static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
83 static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
84 static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime);
85 static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
86 static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
87 static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
88 static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
89 static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
90 static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
91
92 /********************************************************************************/
93 /* IROTData prototype functions                                                 */
94
95 /* IUnknown prototype functions */
96 static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
97 static ULONG   WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface);
98 static ULONG   WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface);
99
100 /* IROTData prototype function */
101 static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
102
103 /* Local function used by CompositeMoniker implementation */
104 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest);
105 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface);
106
107 /********************************************************************************/
108 /* IEnumMoniker prototype functions                                             */
109
110 /* IUnknown prototype functions */
111 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject);
112 static ULONG   WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface);
113 static ULONG   WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface);
114
115 /* IEnumMoniker prototype functions */
116 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched);
117 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt);
118 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface);
119 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum);
120
121 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
122
123 /********************************************************************************/
124 /* Virtual function table for the CompositeMonikerImpl class which includes     */
125 /* IPersist, IPersistStream and IMoniker functions.                             */
126
127 static ICOM_VTABLE(IMoniker) VT_CompositeMonikerImpl =
128 {
129     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
130     CompositeMonikerImpl_QueryInterface,
131     CompositeMonikerImpl_AddRef,
132     CompositeMonikerImpl_Release,
133     CompositeMonikerImpl_GetClassID,
134     CompositeMonikerImpl_IsDirty,
135     CompositeMonikerImpl_Load,
136     CompositeMonikerImpl_Save,
137     CompositeMonikerImpl_GetSizeMax,
138     CompositeMonikerImpl_BindToObject,
139     CompositeMonikerImpl_BindToStorage,
140     CompositeMonikerImpl_Reduce,
141     CompositeMonikerImpl_ComposeWith,
142     CompositeMonikerImpl_Enum,
143     CompositeMonikerImpl_IsEqual,
144     CompositeMonikerImpl_Hash,
145     CompositeMonikerImpl_IsRunning,
146     CompositeMonikerImpl_GetTimeOfLastChange,
147     CompositeMonikerImpl_Inverse,
148     CompositeMonikerImpl_CommonPrefixWith,
149     CompositeMonikerImpl_RelativePathTo,
150     CompositeMonikerImpl_GetDisplayName,
151     CompositeMonikerImpl_ParseDisplayName,
152     CompositeMonikerImpl_IsSystemMoniker
153 };
154
155 /********************************************************************************/
156 /* Virtual function table for the IROTData class.                               */
157 static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
158 {
159     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
160     CompositeMonikerROTDataImpl_QueryInterface,
161     CompositeMonikerROTDataImpl_AddRef,
162     CompositeMonikerROTDataImpl_Release,
163     CompositeMonikerROTDataImpl_GetComparaisonData
164 };
165
166 /********************************************************************************/
167 /* Virtual function table for the IROTData class                                */
168 static ICOM_VTABLE(IEnumMoniker) VT_EnumMonikerImpl =
169 {
170     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
171     EnumMonikerImpl_QueryInterface,
172     EnumMonikerImpl_AddRef,
173     EnumMonikerImpl_Release,
174     EnumMonikerImpl_Next,
175     EnumMonikerImpl_Skip,
176     EnumMonikerImpl_Reset,
177     EnumMonikerImpl_Clone
178 };
179
180 /*******************************************************************************
181  *        CompositeMoniker_QueryInterface
182  *******************************************************************************/
183 HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
184 {
185     ICOM_THIS(CompositeMonikerImpl,iface);
186   
187     Print(MAX_TRACE, ("(%p,%p,%p)\n",This,riid,ppvObject));
188
189     /* Perform a sanity check on the parameters.*/
190     if ( (This==0) || (ppvObject==0) )
191         return E_INVALIDARG;
192   
193     /* Initialize the return parameter */
194     *ppvObject = 0;
195
196     /* Compare the riid with the interface IDs implemented by this object.*/
197     if (IsEqualIID(&IID_IUnknown, riid) ||
198         IsEqualIID(&IID_IPersist, riid) ||
199         IsEqualIID(&IID_IPersistStream, riid) ||
200         IsEqualIID(&IID_IMoniker, riid)
201        )
202         *ppvObject = iface;
203     else if (IsEqualIID(&IID_IROTData, riid))
204         *ppvObject = (IROTData*)&(This->lpvtbl2);
205
206     /* Check that we obtained an interface.*/
207     if ((*ppvObject)==0)
208         return E_NOINTERFACE;
209
210     /* Query Interface always increases the reference count by one when it is successful */
211     CompositeMonikerImpl_AddRef(iface);
212
213     return S_OK;
214 }
215
216 /******************************************************************************
217  *        CompositeMoniker_AddRef
218  ******************************************************************************/
219 ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)
220 {
221     ICOM_THIS(CompositeMonikerImpl,iface);
222
223     Print(MAX_TRACE, ("(%p)\n",This));
224
225     return ++(This->ref);
226 }
227
228 /******************************************************************************
229  *        CompositeMoniker_Release
230  ******************************************************************************/
231 ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
232 {
233     ICOM_THIS(CompositeMonikerImpl,iface);
234     ULONG i;
235     
236     Print(MAX_TRACE, ("(%p)\n",This));
237
238     This->ref--;
239
240     /* destroy the object if there's no more reference on it */
241     if (This->ref==0){
242
243         /* release all the components before destroying this object */
244         for (i=0;i<This->tabLastIndex;i++)
245             IMoniker_Release(This->tabMoniker[i]);
246         
247         CompositeMonikerImpl_Destroy(This);
248
249         return 0;
250     }
251     return This->ref;;
252 }
253
254 /******************************************************************************
255  *        CompositeMoniker_GetClassID
256  ******************************************************************************/
257 HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
258 {
259     Print(MAX_TRACE, ("(%p,%p),stub!\n",iface,pClassID));
260
261     if (pClassID==NULL)
262         return E_POINTER;
263             
264     *pClassID = CLSID_CompositeMoniker;
265         
266     return S_OK;
267 }
268
269 /******************************************************************************
270  *        CompositeMoniker_IsDirty
271  ******************************************************************************/
272 HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)
273 {
274     /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
275        method in the OLE-provided moniker interfaces always return S_FALSE because
276        their internal state never changes. */
277
278     Print(MAX_TRACE, ("(%p)\n",iface));
279
280     return S_FALSE;
281 }
282
283 /******************************************************************************
284  *        CompositeMoniker_Load
285  ******************************************************************************/
286 HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
287 {
288     HRESULT res;
289     DWORD constant;
290     CLSID clsid;
291     WCHAR string[1]={0};
292     
293     ICOM_THIS(CompositeMonikerImpl,iface);    
294
295     Print(MAX_TRACE, ("(%p,%p)\n",iface,pStm));
296
297     /* this function call OleLoadFromStream function for each moniker within this object */
298
299     /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
300     res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
301
302     if (SUCCEEDED(res)&& constant!=3)
303         return E_FAIL;
304
305     while(1){
306 #if 0
307         res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
308 #endif
309         res=ReadClassStm(pStm,&clsid);
310         Print(MAX_TRACE, ("res=%ld",res));
311         if (FAILED(res))
312             break;
313
314         if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
315             res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
316             if (FAILED(res))
317                 break;
318             res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
319             if (FAILED(res))
320                 break;
321         }
322         else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
323             CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
324             if (res!=S_OK)
325                 break;
326             IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
327             if (FAILED(res))
328                 break;
329         }
330         else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
331             CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
332             if (FAILED(res))
333                 break;
334             IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
335             if (FAILED(res))
336                 break;
337         }
338         else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
339             return E_FAIL;
340
341         else
342         {
343             Print(MIN_TRACE, ("()\n"));
344             /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */
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     Print(MAX_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     Print(MAX_TRACE, ("(%p,%p)\n",iface,pcbSize));
414
415     if (pcbSize!=NULL)
416         return E_POINTER;
417
418     pcbSize->u.LowPart =0;
419     pcbSize->u.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->u.LowPart +=ptmpSize.u.LowPart;
430         pcbSize->u.HighPart+=ptmpSize.u.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     Print(MAX_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     Print(MAX_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     Print(MAX_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     Print(MAX_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     Print(MAX_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 composite moniker in to left and right 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     Print(MAX_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     Print(MAX_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     Print(MAX_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     Print(MIN_TRACE, ("(),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     Print(MAX_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     Print(MAX_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     Print(MAX_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-right) then compare these enumerations (left-right) 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     Print(MAX_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     Print(MAX_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         lstrcatW(*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 right 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_IsSystemMoniker
1403  ******************************************************************************/
1404 HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1405 {
1406     Print(MAX_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     Print(MAX_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     Print(MAX_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     Print(MAX_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     Print(MIN_TRACE, ("(),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     Print(MAX_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     Print(MAX_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     Print(MAX_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     Print(MAX_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     Print(MIN_TRACE, ("(),stub!\n"));
1699     return E_NOTIMPL;
1700 }
1701
1702