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