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