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