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