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