~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/ole32/compositemoniker.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.