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