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