~ [ 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 
556     TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
557 
558     if (pmkOtherMoniker==NULL)
559         return S_FALSE;
560 
561     /* This method returns S_OK if the components of both monikers are equal when compared in the */
562     /* left-to-right order.*/
563     IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
564 
565     if (enumMoniker1==NULL)
566         return S_FALSE;
567 
568     IMoniker_Enum(iface,TRUE,&enumMoniker2);
569 
570     while(1){
571 
572         res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
573         res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
574 
575         if((res1==S_OK)&&(res2==S_OK)){
576 
577             if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
578                 res= S_FALSE;
579                 break;
580             }
581             else
582                 continue;
583         }
584         else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
585                 res = S_OK;
586                 break;
587         }
588         else{
589             res = S_FALSE;
590             break;
591         }
592 
593         if (res1==S_OK)
594             IMoniker_Release(tempMk1);
595 
596         if (res2==S_OK)
597             IMoniker_Release(tempMk2);
598     }
599 
600     IEnumMoniker_Release(enumMoniker1);
601     IEnumMoniker_Release(enumMoniker2);
602 
603     return res;
604 }
605 /******************************************************************************
606  *        CompositeMoniker_Hash
607  ******************************************************************************/
608 static HRESULT WINAPI
609 CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
610 {
611     IEnumMoniker *enumMoniker;
612     IMoniker *tempMk;
613     HRESULT res;
614     DWORD tempHash;
615 
616     TRACE("(%p,%p)\n",iface,pdwHash);
617 
618     if (pdwHash==NULL)
619         return E_POINTER;
620 
621     res = IMoniker_Enum(iface,TRUE,&enumMoniker);
622     if(FAILED(res))
623         return res;
624 
625     *pdwHash = 0;
626 
627     while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
628         res = IMoniker_Hash(tempMk, &tempHash);
629         if(FAILED(res))
630             break;
631         *pdwHash = *pdwHash ^ tempHash;
632         
633         IMoniker_Release(tempMk);
634     }
635 
636     IEnumMoniker_Release(enumMoniker);
637 
638     return res;
639 }
640 
641 /******************************************************************************
642  *        CompositeMoniker_IsRunning
643  ******************************************************************************/
644 static HRESULT WINAPI
645 CompositeMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc,
646                IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning)
647 {
648     IRunningObjectTable* rot;
649     HRESULT res;
650     IMoniker *tempMk,*antiMk,*mostRigthMk;
651     IEnumMoniker *enumMoniker;
652 
653     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
654 
655     /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
656     if (pmkToLeft!=NULL){
657 
658         CreateGenericComposite(pmkToLeft,iface,&tempMk);
659 
660         res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
661 
662         IMoniker_Release(tempMk);
663 
664         return res;
665     }
666     else
667         /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
668         /* to this moniker */
669 
670         if (pmkNewlyRunning!=NULL)
671 
672             if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
673                 return S_OK;
674 
675             else
676                 return S_FALSE;
677 
678         else{
679 
680             if (pbc==NULL)
681                 return E_POINTER;
682 
683             /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
684             /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls   */
685             /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
686             /* the composite as the pmkToLeft parameter for that call.                                   */
687 
688              res=IBindCtx_GetRunningObjectTable(pbc,&rot);
689 
690             if (FAILED(res))
691                 return res;
692 
693             res = IRunningObjectTable_IsRunning(rot,iface);
694             IRunningObjectTable_Release(rot);
695 
696             if(res==S_OK)
697                 return S_OK;
698 
699             else{
700 
701                 IMoniker_Enum(iface,FALSE,&enumMoniker);
702                 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
703                 IEnumMoniker_Release(enumMoniker);
704 
705                 res=CreateAntiMoniker(&antiMk);
706                 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
707                 IMoniker_Release(antiMk);
708 
709                 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
710 
711                 IMoniker_Release(tempMk);
712                 IMoniker_Release(mostRigthMk);
713 
714                 return res;
715             }
716         }
717 }
718 
719 /******************************************************************************
720  *        CompositeMoniker_GetTimeOfLastChange
721  ******************************************************************************/
722 static HRESULT WINAPI
723 CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
724                IMoniker* pmkToLeft, FILETIME* pCompositeTime)
725 {
726     HRESULT res;
727     IMoniker *tempMk,*antiMk,*mostRigthMk,*leftMk;
728     IEnumMoniker *enumMoniker;
729 
730     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
731 
732     if (pCompositeTime==NULL)
733         return E_INVALIDARG;
734 
735     /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to  */
736     /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls  */
737     /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
738     /* of the composite as the pmkToLeft parameter for that call.                                       */
739     if (pmkToLeft)
740     {
741         IRunningObjectTable* rot;
742 
743         res = IMoniker_ComposeWith(pmkToLeft, iface, FALSE, &leftMk);
744 
745         res = IBindCtx_GetRunningObjectTable(pbc,&rot);
746         if (FAILED(res))
747         {
748             IMoniker_Release(leftMk);
749             return res;
750         }
751 
752         if (IRunningObjectTable_GetTimeOfLastChange(rot,leftMk,pCompositeTime)==S_OK)
753         {
754             IMoniker_Release(leftMk);
755             return res;
756         }
757     }
758     else
759         leftMk = iface;
760 
761     IMoniker_Enum(iface, FALSE, &enumMoniker);
762     IEnumMoniker_Next(enumMoniker, 1, &mostRigthMk, NULL);
763     IEnumMoniker_Release(enumMoniker);
764 
765     res = CreateAntiMoniker(&antiMk);
766     res = IMoniker_ComposeWith(leftMk, antiMk, 0, &tempMk);
767     IMoniker_Release(antiMk);
768 
769     res = IMoniker_GetTimeOfLastChange(mostRigthMk, pbc, tempMk, pCompositeTime);
770 
771     IMoniker_Release(tempMk);
772     IMoniker_Release(mostRigthMk);
773 
774     if (pmkToLeft)
775         IMoniker_Release(leftMk);
776 
777     return res;
778 }
779 
780 /******************************************************************************
781  *        CompositeMoniker_Inverse
782  ******************************************************************************/
783 static HRESULT WINAPI
784 CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
785 {
786     HRESULT res;
787     IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
788     IEnumMoniker *enumMoniker;
789 
790     TRACE("(%p,%p)\n",iface,ppmk);
791 
792     if (ppmk==NULL)
793         return E_POINTER;
794 
795     /* This method returns a composite moniker that consists of the inverses of each of the components */
796     /* of the original composite, stored in reverse order */
797 
798     res=CreateAntiMoniker(&antiMk);
799     res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
800     IMoniker_Release(antiMk);
801 
802     if (tempMk==NULL)
803 
804         return IMoniker_Inverse(iface,ppmk);
805 
806     else{
807 
808         IMoniker_Enum(iface,FALSE,&enumMoniker);
809         IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
810         IEnumMoniker_Release(enumMoniker);
811 
812         IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
813         CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
814 
815         res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
816 
817         IMoniker_Release(tempMk);
818         IMoniker_Release(mostRigthMk);
819         IMoniker_Release(tempInvMk);
820         IMoniker_Release(mostRigthInvMk);
821 
822         return res;
823     }
824 }
825 
826 /******************************************************************************
827  *        CompositeMoniker_CommonPrefixWith
828  ******************************************************************************/
829 static HRESULT WINAPI
830 CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface, IMoniker* pmkOther,
831                IMoniker** ppmkPrefix)
832 {
833     DWORD mkSys;
834     HRESULT res1,res2;
835     IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
836     IEnumMoniker *enumMoniker1,*enumMoniker2;
837     ULONG i,nbCommonMk=0;
838 
839     /* If the other moniker is a composite, this method compares the components of each composite from left  */
840     /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
841     /* of the leftmost components were common to both monikers.                                              */
842 
843     if (ppmkPrefix==NULL)
844         return E_POINTER;
845 
846     *ppmkPrefix=0;
847 
848     if (pmkOther==NULL)
849         return MK_E_NOPREFIX;
850 
851     IMoniker_IsSystemMoniker(pmkOther,&mkSys);
852 
853     if((mkSys==MKSYS_GENERICCOMPOSITE)){
854 
855         IMoniker_Enum(iface,TRUE,&enumMoniker1);
856         IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
857 
858         while(1){
859 
860             res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
861             res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
862 
863             if ((res1==S_FALSE) && (res2==S_FALSE)){
864 
865                 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
866                 *ppmkPrefix=iface;
867                 IMoniker_AddRef(iface);
868                 return  MK_S_US;
869             }
870             else if ((res1==S_OK) && (res2==S_OK)){
871 
872                 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
873 
874                     nbCommonMk++;
875 
876                 else
877                     break;
878 
879             }
880             else if (res1==S_OK){
881 
882                 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
883                 /* ppmkPrefix to the other moniker.                                                       */
884                 *ppmkPrefix=pmkOther;
885                 return MK_S_HIM;
886             }
887             else{
888                 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
889                 /* to this moniker.                                                                          */
890                 *ppmkPrefix=iface;
891                 return MK_S_ME;
892             }
893         }
894 
895         IEnumMoniker_Release(enumMoniker1);
896         IEnumMoniker_Release(enumMoniker2);
897 
898         /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
899         if (nbCommonMk==0)
900             return MK_E_NOPREFIX;
901 
902         IEnumMoniker_Reset(enumMoniker1);
903 
904         IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
905 
906         /* if we have more than one common moniker the result will be a composite moniker */
907         if (nbCommonMk>1){
908 
909             /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
910             IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
911             CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
912             IMoniker_Release(tempMk1);
913             IMoniker_Release(tempMk2);
914 
915             /* compose all common monikers in a composite moniker */
916             for(i=0;i<nbCommonMk;i++){
917 
918                 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
919 
920                 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
921 
922                 IMoniker_Release(*ppmkPrefix);
923 
924                 IMoniker_Release(tempMk1);
925 
926                 *ppmkPrefix=tempMk2;
927             }
928             return S_OK;
929         }
930         else{
931             /* if we have only one common moniker the result will be a simple moniker which is the most-left one*/
932             *ppmkPrefix=tempMk1;
933 
934             return S_OK;
935         }
936     }
937     else{
938         /* If the other moniker is not a composite, the method simply compares it to the leftmost component
939          of this moniker.*/
940 
941         IMoniker_Enum(iface,TRUE,&enumMoniker1);
942 
943         IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
944 
945         if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
946 
947             *ppmkPrefix=pmkOther;
948 
949             return MK_S_HIM;
950         }
951         else
952             return MK_E_NOPREFIX;
953     }
954 }
955 
956 /***************************************************************************************************
957  *        GetAfterCommonPrefix (local function)
958  *  This function returns a moniker that consist of the remainder when the common prefix is removed
959  ***************************************************************************************************/
960 static VOID GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
961 {
962     IMoniker *tempMk,*tempMk1,*tempMk2;
963     IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
964     ULONG nbRestMk=0;
965     DWORD mkSys;
966     HRESULT res1,res2;
967 
968     *restMk=0;
969 
970     /* to create an enumerator for pGenMk with current position pointed on the first element after common  */
971     /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop  */
972     /* on the first difference. */
973     IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
974 
975     IMoniker_IsSystemMoniker(commonMk,&mkSys);
976 
977     if (mkSys==MKSYS_GENERICCOMPOSITE){
978 
979         IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
980         while(1){
981 
982             res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
983             res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
984 
985             if ((res1==S_FALSE)||(res2==S_FALSE)){
986 
987                 if (res1==S_OK)
988 
989                     nbRestMk++;
990 
991                 IMoniker_Release(tempMk1);
992                 IMoniker_Release(tempMk1);
993 
994                 break;
995             }
996             IMoniker_Release(tempMk1);
997             IMoniker_Release(tempMk1);
998         }
999     }
1000     else{
1001         IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1002         IMoniker_Release(tempMk1);
1003     }
1004 
1005     /* count the number of elements in the enumerator after the common prefix */
1006     IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1007 
1008     for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1009 
1010         IMoniker_Release(tempMk);
1011 
1012     if (nbRestMk==0)
1013         return;
1014 
1015     /* create a generic composite moniker with monikers located after the common prefix */
1016     IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1017 
1018     if (nbRestMk==1){
1019 
1020         *restMk= tempMk1;
1021         return;
1022     }
1023     else {
1024 
1025         IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1026 
1027         CreateGenericComposite(tempMk1,tempMk2,restMk);
1028 
1029         IMoniker_Release(tempMk1);
1030 
1031         IMoniker_Release(tempMk2);
1032 
1033         while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1034 
1035             CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1036 
1037             IMoniker_Release(tempMk1);
1038 
1039             IMoniker_Release(*restMk);
1040 
1041             *restMk=tempMk2;
1042         }
1043     }
1044 }
1045 
1046 /******************************************************************************
1047  *        CompositeMoniker_RelativePathTo
1048  ******************************************************************************/
1049 static HRESULT WINAPI
1050 CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther,
1051                IMoniker** ppmkRelPath)
1052 {
1053     HRESULT res;
1054     IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1055 
1056     TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1057 
1058     if (ppmkRelPath==NULL)
1059         return E_POINTER;
1060 
1061     *ppmkRelPath=0;
1062 
1063     /* This method finds the common prefix of the two monikers and creates two monikers that consist     */
1064     /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1065     /* of this moniker and composes the remainder of the other moniker on the right of it.               */
1066 
1067     /* finds the common prefix of the two monikers */
1068     res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1069 
1070     /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1071     if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1072 
1073         *ppmkRelPath=pmkOther;
1074         IMoniker_AddRef(pmkOther);
1075         return MK_S_HIM;
1076     }
1077 
1078     GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1079     GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1080 
1081     /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1082     /* moniker when the common prefix is removed                                                           */
1083     if (res==MK_S_HIM){
1084 
1085         IMoniker_Inverse(restThisMk,ppmkRelPath);
1086         IMoniker_Release(restThisMk);
1087     }
1088     /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1089     /* when the common prefix is removed                                                                     */
1090     else if (res==MK_S_ME){
1091 
1092         *ppmkRelPath=restOtherMk;
1093         IMoniker_AddRef(restOtherMk);
1094     }
1095     /* the relative path is the inverse for the remainder of this moniker and the remainder of the other  */
1096     /* moniker on the right of it.                                                                        */
1097     else if (res==S_OK){
1098 
1099         IMoniker_Inverse(restThisMk,&invRestThisMk);
1100         IMoniker_Release(restThisMk);
1101         CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1102         IMoniker_Release(invRestThisMk);
1103         IMoniker_Release(restOtherMk);
1104     }
1105     return S_OK;
1106 }
1107 
1108 /******************************************************************************
1109  *        CompositeMoniker_GetDisplayName
1110  ******************************************************************************/
1111 static HRESULT WINAPI
1112 CompositeMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
1113                IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
1114 {
1115     ULONG lengthStr=1;
1116     IEnumMoniker *enumMoniker;
1117     IMoniker* tempMk;
1118     LPOLESTR tempStr;
1119 
1120     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1121 
1122     if (ppszDisplayName==NULL)
1123         return E_POINTER;
1124 
1125     *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1126 
1127     if (*ppszDisplayName==NULL)
1128         return E_OUTOFMEMORY;
1129 
1130     /* This method returns the concatenation of the display names returned by each component moniker of */
1131     /* the composite */
1132 
1133     **ppszDisplayName=0;
1134 
1135     IMoniker_Enum(iface,TRUE,&enumMoniker);
1136 
1137     while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1138 
1139         IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1140 
1141         lengthStr+=lstrlenW(tempStr);
1142 
1143         *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1144 
1145         if (*ppszDisplayName==NULL)
1146             return E_OUTOFMEMORY;
1147 
1148         strcatW(*ppszDisplayName,tempStr);
1149 
1150         CoTaskMemFree(tempStr);
1151         IMoniker_Release(tempMk);
1152     }
1153 
1154     IEnumMoniker_Release(enumMoniker);
1155 
1156     return S_OK;
1157 }
1158 
1159 /******************************************************************************
1160  *        CompositeMoniker_ParseDisplayName
1161  ******************************************************************************/
1162 static HRESULT WINAPI
1163 CompositeMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,
1164                IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten,
1165                IMoniker** ppmkOut)
1166 {
1167     IEnumMoniker *enumMoniker;
1168     IMoniker *tempMk,*mostRigthMk,*antiMk;
1169     /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1170     /* passing everything else as the pmkToLeft parameter for that call. */
1171 
1172     /* get the most right moniker */
1173     IMoniker_Enum(iface,FALSE,&enumMoniker);
1174     IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1175     IEnumMoniker_Release(enumMoniker);
1176 
1177     /* get the left moniker */
1178     CreateAntiMoniker(&antiMk);
1179     IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1180     IMoniker_Release(antiMk);
1181 
1182     return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1183 }
1184 
1185 /******************************************************************************
1186  *        CompositeMoniker_IsSystemMoniker
1187  ******************************************************************************/
1188 static HRESULT WINAPI
1189 CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1190 {
1191     TRACE("(%p,%p)\n",iface,pwdMksys);
1192 
1193     if (!pwdMksys)
1194         return E_POINTER;
1195 
1196     (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1197 
1198     return S_OK;
1199 }
1200 
1201 /*******************************************************************************
1202  *        CompositeMonikerIROTData_QueryInterface
1203  *******************************************************************************/
1204 static HRESULT WINAPI
1205 CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,
1206                VOID** ppvObject)
1207 {
1208 
1209     IMoniker *This = impl_from_IROTData(iface);
1210 
1211     TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
1212 
1213     return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1214 }
1215 
1216 /***********************************************************************
1217  *        CompositeMonikerIROTData_AddRef
1218  */
1219 static ULONG WINAPI
1220 CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1221 {
1222     IMoniker *This = impl_from_IROTData(iface);
1223 
1224     TRACE("(%p)\n",iface);
1225 
1226     return IMoniker_AddRef(This);
1227 }
1228 
1229 /***********************************************************************
1230  *        CompositeMonikerIROTData_Release
1231  */
1232 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1233 {
1234     IMoniker *This = impl_from_IROTData(iface);
1235 
1236     TRACE("(%p)\n",iface);
1237 
1238     return IMoniker_Release(This);
1239 }
1240 
1241 /******************************************************************************
1242  *        CompositeMonikerIROTData_GetComparisonData
1243  ******************************************************************************/
1244 static HRESULT WINAPI
1245 CompositeMonikerROTDataImpl_GetComparisonData(IROTData* iface,
1246                BYTE* pbData, ULONG cbMax, ULONG* pcbData)
1247 {
1248     IMoniker *This = impl_from_IROTData(iface);
1249     IEnumMoniker *pEnumMk;
1250     IMoniker *pmk;
1251     HRESULT hr;
1252 
1253     TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData);
1254 
1255     *pcbData = sizeof(CLSID);
1256 
1257     hr = IMoniker_Enum(This, TRUE, &pEnumMk);
1258     if (FAILED(hr)) return hr;
1259 
1260     while(IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
1261     {
1262         IROTData *pROTData;
1263         hr = IMoniker_QueryInterface(pmk, &IID_IROTData, (void **)&pROTData);
1264         if (FAILED(hr))
1265             ERR("moniker doesn't support IROTData interface\n");
1266 
1267         if (SUCCEEDED(hr))
1268         {
1269             ULONG cbData;
1270             hr = IROTData_GetComparisonData(pROTData, NULL, 0, &cbData);
1271             IROTData_Release(pROTData);
1272             if (SUCCEEDED(hr) || (hr == E_OUTOFMEMORY))
1273             {
1274                 *pcbData += cbData;
1275                 hr = S_OK;
1276             }
1277             else
1278                 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr);
1279         }
1280 
1281         IMoniker_Release(pmk);
1282 
1283         if (FAILED(hr))
1284         {
1285             IEnumMoniker_Release(pEnumMk);
1286             return hr;
1287         }
1288     }
1289     if (cbMax < *pcbData)
1290         return E_OUTOFMEMORY;
1291 
1292     IEnumMoniker_Reset(pEnumMk);
1293 
1294     memcpy(pbData, &CLSID_CompositeMoniker, sizeof(CLSID));
1295     pbData += sizeof(CLSID);
1296     cbMax -= sizeof(CLSID);
1297 
1298     while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
1299     {
1300         IROTData *pROTData;
1301         hr = IMoniker_QueryInterface(pmk, &IID_IROTData, (void **)&pROTData);
1302         if (FAILED(hr))
1303             ERR("moniker doesn't support IROTData interface\n");
1304 
1305         if (SUCCEEDED(hr))
1306         {
1307             ULONG cbData;
1308             hr = IROTData_GetComparisonData(pROTData, pbData, cbMax, &cbData);
1309             IROTData_Release(pROTData);
1310             if (SUCCEEDED(hr))
1311             {
1312                 pbData += cbData;
1313                 cbMax -= cbData;
1314             }
1315             else
1316                 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr);
1317         }
1318 
1319         IMoniker_Release(pmk);
1320 
1321         if (FAILED(hr))
1322         {
1323             IEnumMoniker_Release(pEnumMk);
1324             return hr;
1325         }
1326     }
1327 
1328     IEnumMoniker_Release(pEnumMk);
1329 
1330     return S_OK;
1331 }
1332 
1333 static HRESULT WINAPI CompositeMonikerMarshalImpl_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv)
1334 {
1335     IMoniker *This = impl_from_IMarshal(iface);
1336 
1337     TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppv);
1338 
1339     return CompositeMonikerImpl_QueryInterface(This, riid, ppv);
1340 }
1341 
1342 static ULONG WINAPI CompositeMonikerMarshalImpl_AddRef(IMarshal *iface)
1343 {
1344     IMoniker *This = impl_from_IMarshal(iface);
1345 
1346     TRACE("(%p)\n",iface);
1347 
1348     return CompositeMonikerImpl_AddRef(This);
1349 }
1350 
1351 static ULONG WINAPI CompositeMonikerMarshalImpl_Release(IMarshal *iface)
1352 {
1353     IMoniker *This = impl_from_IMarshal(iface);
1354 
1355     TRACE("(%p)\n",iface);
1356 
1357     return CompositeMonikerImpl_Release(This);
1358 }
1359 
1360 static HRESULT WINAPI CompositeMonikerMarshalImpl_GetUnmarshalClass(
1361   LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1362   void* pvDestContext, DWORD mshlflags, CLSID* pCid)
1363 {
1364     IMoniker *This = impl_from_IMarshal(iface);
1365 
1366     TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv,
1367         dwDestContext, pvDestContext, mshlflags, pCid);
1368 
1369     return IMoniker_GetClassID(This, pCid);
1370 }
1371 
1372 static HRESULT WINAPI CompositeMonikerMarshalImpl_GetMarshalSizeMax(
1373   LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1374   void* pvDestContext, DWORD mshlflags, DWORD* pSize)
1375 {
1376     IMoniker *This = impl_from_IMarshal(iface);
1377     IEnumMoniker *pEnumMk;
1378     IMoniker *pmk;
1379     HRESULT hr;
1380     ULARGE_INTEGER size;
1381 
1382     TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv,
1383         dwDestContext, pvDestContext, mshlflags, pSize);
1384 
1385     *pSize = 0x10; /* to match native */
1386 
1387     hr = IMoniker_Enum(This, TRUE, &pEnumMk);
1388     if (FAILED(hr)) return hr;
1389 
1390     hr = IMoniker_GetSizeMax(This, &size);
1391 
1392     while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
1393     {
1394         ULONG size;
1395 
1396         hr = CoGetMarshalSizeMax(&size, &IID_IMoniker, (IUnknown *)pmk, dwDestContext, pvDestContext, mshlflags);
1397         if (SUCCEEDED(hr))
1398             *pSize += size;
1399 
1400         IMoniker_Release(pmk);
1401 
1402         if (FAILED(hr))
1403         {
1404             IEnumMoniker_Release(pEnumMk);
1405             return hr;
1406         }
1407     }
1408 
1409     IEnumMoniker_Release(pEnumMk);
1410 
1411     return S_OK;
1412 }
1413 
1414 static HRESULT WINAPI CompositeMonikerMarshalImpl_MarshalInterface(LPMARSHAL iface, IStream *pStm, 
1415     REFIID riid, void* pv, DWORD dwDestContext,
1416     void* pvDestContext, DWORD mshlflags)
1417 {
1418     IMoniker *This = impl_from_IMarshal(iface);
1419     IEnumMoniker *pEnumMk;
1420     IMoniker *pmk;
1421     HRESULT hr;
1422     ULONG i = 0;
1423 
1424     TRACE("(%p, %s, %p, %x, %p, %x)\n", pStm, debugstr_guid(riid), pv,
1425         dwDestContext, pvDestContext, mshlflags);
1426 
1427     hr = IMoniker_Enum(This, TRUE, &pEnumMk);
1428     if (FAILED(hr)) return hr;
1429 
1430     while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
1431     {
1432         hr = CoMarshalInterface(pStm, &IID_IMoniker, (IUnknown *)pmk, dwDestContext, pvDestContext, mshlflags);
1433 
1434         IMoniker_Release(pmk);
1435 
1436         if (FAILED(hr))
1437         {
1438             IEnumMoniker_Release(pEnumMk);
1439             return hr;
1440         }
1441         i++;
1442     }
1443 
1444     if (i != 2)
1445         FIXME("moniker count of %d not supported\n", i);
1446 
1447     IEnumMoniker_Release(pEnumMk);
1448 
1449     return S_OK;
1450 }
1451 
1452 static HRESULT WINAPI CompositeMonikerMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv)
1453 {
1454     CompositeMonikerImpl *This = (CompositeMonikerImpl *)impl_from_IMarshal(iface);
1455     HRESULT hr;
1456 
1457     TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
1458 
1459     CompositeMonikerImpl_ReleaseMonikersInTable(This);
1460 
1461     /* resize the table if needed */
1462     if (This->tabLastIndex + 2 > This->tabSize)
1463     {
1464         This->tabSize += max(BLOCK_TAB_SIZE, 2);
1465         This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1466 
1467         if (This->tabMoniker==NULL)
1468             return E_OUTOFMEMORY;
1469     }
1470 
1471     hr = CoUnmarshalInterface(pStm, &IID_IMoniker, (void**)&This->tabMoniker[This->tabLastIndex]);
1472     if (FAILED(hr))
1473     {
1474         ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr);
1475         return hr;
1476     }
1477     This->tabLastIndex++;
1478     hr = CoUnmarshalInterface(pStm, &IID_IMoniker, (void**)&This->tabMoniker[This->tabLastIndex]);
1479     if (FAILED(hr))
1480     {
1481         ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr);
1482         return hr;
1483     }
1484     This->tabLastIndex++;
1485 
1486     return IMoniker_QueryInterface((IMoniker *)&This->lpvtbl1, riid, ppv);
1487 }
1488 
1489 static HRESULT WINAPI CompositeMonikerMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm)
1490 {
1491     TRACE("(%p)\n", pStm);
1492     /* can't release a state-based marshal as nothing on server side to
1493      * release */
1494     return S_OK;
1495 }
1496 
1497 static HRESULT WINAPI CompositeMonikerMarshalImpl_DisconnectObject(LPMARSHAL iface, DWORD dwReserved)
1498 {
1499     TRACE("(0x%x)\n", dwReserved);
1500     /* can't disconnect a state-based marshal as nothing on server side to
1501      * disconnect from */
1502     return S_OK;
1503 }
1504 
1505 /******************************************************************************
1506  *        EnumMonikerImpl_QueryInterface
1507  ******************************************************************************/
1508 static HRESULT WINAPI
1509 EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1510 {
1511     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1512 
1513     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1514 
1515     /* Perform a sanity check on the parameters.*/
1516     if ( (This==0) || (ppvObject==0) )
1517         return E_INVALIDARG;
1518 
1519     /* Initialize the return parameter */
1520     *ppvObject = 0;
1521 
1522     /* Compare the riid with the interface IDs implemented by this object.*/
1523     if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1524         *ppvObject = iface;
1525 
1526     /* Check that we obtained an interface.*/
1527     if ((*ppvObject)==0)
1528         return E_NOINTERFACE;
1529 
1530     /* Query Interface always increases the reference count by one when it is successful */
1531     IEnumMoniker_AddRef(iface);
1532 
1533     return S_OK;
1534 }
1535 
1536 /******************************************************************************
1537  *        EnumMonikerImpl_AddRef
1538  ******************************************************************************/
1539 static ULONG WINAPI
1540 EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1541 {
1542     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1543 
1544     TRACE("(%p)\n",This);
1545 
1546     return InterlockedIncrement(&This->ref);
1547 
1548 }
1549 
1550 /******************************************************************************
1551  *        EnumMonikerImpl_Release
1552  ******************************************************************************/
1553 static ULONG WINAPI
1554 EnumMonikerImpl_Release(IEnumMoniker* iface)
1555 {
1556     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1557     ULONG i;
1558     ULONG ref;
1559     TRACE("(%p)\n",This);
1560 
1561     ref = InterlockedDecrement(&This->ref);
1562 
1563     /* destroy the object if there's no more reference on it */
1564     if (ref == 0) {
1565 
1566         for(i=0;i<This->tabSize;i++)
1567             IMoniker_Release(This->tabMoniker[i]);
1568 
1569         HeapFree(GetProcessHeap(),0,This->tabMoniker);
1570         HeapFree(GetProcessHeap(),0,This);
1571     }
1572     return ref;
1573 }
1574 
1575 /******************************************************************************
1576  *        EnumMonikerImpl_Next
1577  ******************************************************************************/
1578 static HRESULT WINAPI
1579 EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt,
1580                ULONG* pceltFethed)
1581 {
1582     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1583     ULONG i;
1584 
1585     /* retrieve the requested number of moniker from the current position */
1586     for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1587     {
1588         rgelt[i]=This->tabMoniker[This->currentPos++];
1589         IMoniker_AddRef(rgelt[i]);
1590     }
1591 
1592     if (pceltFethed!=NULL)
1593         *pceltFethed= i;
1594 
1595     if (i==celt)
1596         return S_OK;
1597     else
1598         return S_FALSE;
1599 }
1600 
1601 /******************************************************************************
1602  *        EnumMonikerImpl_Skip
1603  ******************************************************************************/
1604 static HRESULT WINAPI
1605 EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt)
1606 {
1607     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1608 
1609     if ((This->currentPos+celt) >= This->tabSize)
1610         return S_FALSE;
1611 
1612     This->currentPos+=celt;
1613 
1614     return S_OK;
1615 }
1616 
1617 /******************************************************************************
1618  *        EnumMonikerImpl_Reset
1619  ******************************************************************************/
1620 static HRESULT WINAPI
1621 EnumMonikerImpl_Reset(IEnumMoniker* iface)
1622 {
1623 
1624     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1625 
1626     This->currentPos=0;
1627 
1628     return S_OK;
1629 }
1630 
1631 /******************************************************************************
1632  *        EnumMonikerImpl_Clone
1633  ******************************************************************************/
1634 static HRESULT WINAPI
1635 EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum)
1636 {
1637     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1638 
1639     return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1640 }
1641 
1642 /********************************************************************************/
1643 /* Virtual function table for the IROTData class                                */
1644 static const IEnumMonikerVtbl VT_EnumMonikerImpl =
1645 {
1646     EnumMonikerImpl_QueryInterface,
1647     EnumMonikerImpl_AddRef,
1648     EnumMonikerImpl_Release,
1649     EnumMonikerImpl_Next,
1650     EnumMonikerImpl_Skip,
1651     EnumMonikerImpl_Reset,
1652     EnumMonikerImpl_Clone
1653 };
1654 
1655 /******************************************************************************
1656  *        EnumMonikerImpl_CreateEnumMoniker
1657  ******************************************************************************/
1658 static HRESULT
1659 EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker, ULONG tabSize,
1660                ULONG currentPos, BOOL leftToRigth, IEnumMoniker ** ppmk)
1661 {
1662     EnumMonikerImpl* newEnumMoniker;
1663     int i;
1664 
1665     if (currentPos > tabSize)
1666         return E_INVALIDARG;
1667 
1668     newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1669 
1670     if (newEnumMoniker == 0)
1671         return STG_E_INSUFFICIENTMEMORY;
1672 
1673     /* Initialize the virtual function table. */
1674     newEnumMoniker->lpVtbl       = &VT_EnumMonikerImpl;
1675     newEnumMoniker->ref          = 1;
1676 
1677     newEnumMoniker->tabSize=tabSize;
1678     newEnumMoniker->currentPos=currentPos;
1679 
1680     newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1681 
1682     if (newEnumMoniker->tabMoniker==NULL) {
1683         HeapFree(GetProcessHeap(), 0, newEnumMoniker);
1684         return E_OUTOFMEMORY;
1685     }
1686 
1687     if (leftToRigth)
1688         for (i=0;i<tabSize;i++){
1689 
1690             newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1691             IMoniker_AddRef(tabMoniker[i]);
1692         }
1693     else
1694         for (i=tabSize-1;i>=0;i--){
1695 
1696             newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1697             IMoniker_AddRef(tabMoniker[i]);
1698         }
1699 
1700     *ppmk=(IEnumMoniker*)newEnumMoniker;
1701 
1702     return S_OK;
1703 }
1704 
1705 /********************************************************************************/
1706 /* Virtual function table for the CompositeMonikerImpl class which includes     */
1707 /* IPersist, IPersistStream and IMoniker functions.                             */
1708 
1709 static const IMonikerVtbl VT_CompositeMonikerImpl =
1710 {
1711     CompositeMonikerImpl_QueryInterface,
1712     CompositeMonikerImpl_AddRef,
1713     CompositeMonikerImpl_Release,
1714     CompositeMonikerImpl_GetClassID,
1715     CompositeMonikerImpl_IsDirty,
1716     CompositeMonikerImpl_Load,
1717     CompositeMonikerImpl_Save,
1718     CompositeMonikerImpl_GetSizeMax,
1719     CompositeMonikerImpl_BindToObject,
1720     CompositeMonikerImpl_BindToStorage,
1721     CompositeMonikerImpl_Reduce,
1722     CompositeMonikerImpl_ComposeWith,
1723     CompositeMonikerImpl_Enum,
1724     CompositeMonikerImpl_IsEqual,
1725     CompositeMonikerImpl_Hash,
1726     CompositeMonikerImpl_IsRunning,
1727     CompositeMonikerImpl_GetTimeOfLastChange,
1728     CompositeMonikerImpl_Inverse,
1729     CompositeMonikerImpl_CommonPrefixWith,
1730     CompositeMonikerImpl_RelativePathTo,
1731     CompositeMonikerImpl_GetDisplayName,
1732     CompositeMonikerImpl_ParseDisplayName,
1733     CompositeMonikerImpl_IsSystemMoniker
1734 };
1735 
1736 /********************************************************************************/
1737 /* Virtual function table for the IROTData class.                               */
1738 static const IROTDataVtbl VT_ROTDataImpl =
1739 {
1740     CompositeMonikerROTDataImpl_QueryInterface,
1741     CompositeMonikerROTDataImpl_AddRef,
1742     CompositeMonikerROTDataImpl_Release,
1743     CompositeMonikerROTDataImpl_GetComparisonData
1744 };
1745 
1746 static const IMarshalVtbl VT_MarshalImpl =
1747 {
1748     CompositeMonikerMarshalImpl_QueryInterface,
1749     CompositeMonikerMarshalImpl_AddRef,
1750     CompositeMonikerMarshalImpl_Release,
1751     CompositeMonikerMarshalImpl_GetUnmarshalClass,
1752     CompositeMonikerMarshalImpl_GetMarshalSizeMax,
1753     CompositeMonikerMarshalImpl_MarshalInterface,
1754     CompositeMonikerMarshalImpl_UnmarshalInterface,
1755     CompositeMonikerMarshalImpl_ReleaseMarshalData,
1756     CompositeMonikerMarshalImpl_DisconnectObject
1757 };
1758 
1759 /******************************************************************************
1760  *         Composite-Moniker_Construct (local function)
1761  *******************************************************************************/
1762 static HRESULT
1763 CompositeMonikerImpl_Construct(IMoniker** ppMoniker,
1764                LPMONIKER pmkFirst, LPMONIKER pmkRest)
1765 {
1766     DWORD mkSys;
1767     IEnumMoniker *enumMoniker;
1768     IMoniker *tempMk;
1769     HRESULT res;
1770     CompositeMonikerImpl *This;
1771 
1772     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1773 
1774     if (!This)
1775         return E_OUTOFMEMORY;
1776 
1777     TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
1778 
1779     /* Initialize the virtual function table. */
1780     This->lpvtbl1      = &VT_CompositeMonikerImpl;
1781     This->lpvtbl2      = &VT_ROTDataImpl;
1782     This->lpvtblMarshal= &VT_MarshalImpl;
1783     This->ref          = 1;
1784 
1785     This->tabSize=BLOCK_TAB_SIZE;
1786     This->tabLastIndex=0;
1787 
1788     This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
1789     if (This->tabMoniker==NULL) {
1790         HeapFree(GetProcessHeap(), 0, This);
1791         return E_OUTOFMEMORY;
1792     }
1793 
1794     if (!pmkFirst && !pmkRest)
1795     {
1796         *ppMoniker = (IMoniker *)This;
1797         return S_OK;
1798     }
1799 
1800     IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
1801 
1802     /* put the first moniker contents in the beginning of the table */
1803     if (mkSys!=MKSYS_GENERICCOMPOSITE){
1804 
1805         This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
1806         IMoniker_AddRef(pmkFirst);
1807     }
1808     else{
1809 
1810         IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
1811 
1812         while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
1813 
1814 
1815             if (++This->tabLastIndex==This->tabSize){
1816                 LPVOID tab_moniker = This->tabMoniker;
1817 
1818                 This->tabSize+=BLOCK_TAB_SIZE;
1819                 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1820 
1821                 if (This->tabMoniker==NULL){
1822                     HeapFree(GetProcessHeap(), 0, tab_moniker);
1823                     HeapFree(GetProcessHeap(), 0, This);
1824                     return E_OUTOFMEMORY;
1825                 }
1826             }
1827         }
1828 
1829         IEnumMoniker_Release(enumMoniker);
1830     }
1831 
1832     /* put the rest moniker contents after the first one and make simplification if needed */
1833 
1834     IMoniker_IsSystemMoniker(pmkRest,&mkSys);
1835 
1836     if (mkSys!=MKSYS_GENERICCOMPOSITE){
1837 
1838         /* add a simple moniker to the moniker table */
1839 
1840         res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
1841 
1842         if (res==MK_E_NEEDGENERIC){
1843 
1844             /* there's no simplification in this case */
1845             This->tabMoniker[This->tabLastIndex]=pmkRest;
1846 
1847             This->tabLastIndex++;
1848 
1849             IMoniker_AddRef(pmkRest);
1850         }
1851         else if (tempMk==NULL){
1852 
1853             /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
1854             IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1855 
1856             This->tabLastIndex--;
1857         }
1858         else if (SUCCEEDED(res)){
1859 
1860             /* the non-generic composition was successful so we can make a simplification in this case */
1861             IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1862 
1863             This->tabMoniker[This->tabLastIndex-1]=tempMk;
1864         } else
1865             return res;
1866 
1867         /* resize tabMoniker if needed */
1868         if (This->tabLastIndex==This->tabSize){
1869             LPVOID tab_moniker = This->tabMoniker;
1870 
1871             This->tabSize+=BLOCK_TAB_SIZE;
1872 
1873             This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1874 
1875             if (This->tabMoniker==NULL){
1876                 HeapFree(GetProcessHeap(), 0, tab_moniker);
1877                 HeapFree(GetProcessHeap(), 0, This);
1878                 return E_OUTOFMEMORY;
1879             }
1880         }
1881     }
1882     else{
1883 
1884         /* add a composite moniker to the moniker table (do the same thing
1885          * for each moniker within the composite moniker as a simple moniker
1886          * (see above for how to add a simple moniker case) )
1887          */
1888         IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
1889 
1890         while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
1891 
1892             res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
1893 
1894             if (res==MK_E_NEEDGENERIC){
1895 
1896                 This->tabLastIndex++;
1897             }
1898             else if (tempMk==NULL){
1899 
1900                 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1901                 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
1902                 This->tabLastIndex--;
1903             }
1904             else{
1905 
1906                 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1907 
1908                 This->tabMoniker[This->tabLastIndex-1]=tempMk;
1909             }
1910 
1911             if (This->tabLastIndex==This->tabSize){
1912                 LPVOID tab_moniker = This->tabMoniker;
1913 
1914                 This->tabSize+=BLOCK_TAB_SIZE;
1915 
1916                 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1917 
1918                 if (This->tabMoniker==NULL){
1919                     HeapFree(GetProcessHeap(), 0, tab_moniker);
1920                     HeapFree(GetProcessHeap(), 0, This);
1921                     return E_OUTOFMEMORY;
1922                 }
1923             }
1924         }
1925 
1926         IEnumMoniker_Release(enumMoniker);
1927     }
1928 
1929     /* only one moniker, then just return it */
1930     if (This->tabLastIndex == 1)
1931     {
1932         *ppMoniker = This->tabMoniker[0];
1933         IMoniker_AddRef(*ppMoniker);
1934         IMoniker_Release((IMoniker *)This);
1935     }
1936     else
1937         *ppMoniker = (IMoniker *)This;
1938 
1939     return S_OK;
1940 }
1941 
1942 /******************************************************************************
1943  *        CreateGenericComposite        [OLE32.@]
1944  ******************************************************************************/
1945 HRESULT WINAPI
1946 CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest,
1947                LPMONIKER* ppmkComposite)
1948 {
1949     IMoniker* moniker = 0;
1950     HRESULT        hr = S_OK;
1951 
1952     TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1953 
1954     if (ppmkComposite==NULL)
1955         return E_POINTER;
1956 
1957     *ppmkComposite=0;
1958 
1959     if (pmkFirst==NULL && pmkRest!=NULL){
1960 
1961         *ppmkComposite=pmkRest;
1962         return S_OK;
1963     }
1964     else if (pmkFirst!=NULL && pmkRest==NULL){
1965         *ppmkComposite=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 static HRESULT WINAPI CompositeMonikerCF_QueryInterface(LPCLASSFACTORY iface,
1993                                                   REFIID riid, LPVOID *ppv)
1994 {
1995     *ppv = NULL;
1996     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
1997     {
1998         *ppv = iface;
1999         IUnknown_AddRef(iface);
2000         return S_OK;
2001     }
2002     return E_NOINTERFACE;
2003 }
2004 
2005 static ULONG WINAPI CompositeMonikerCF_AddRef(LPCLASSFACTORY iface)
2006 {
2007     return 2; /* non-heap based object */
2008 }
2009 
2010 static ULONG WINAPI CompositeMonikerCF_Release(LPCLASSFACTORY iface)
2011 {
2012     return 1; /* non-heap based object */
2013 }
2014 
2015 static HRESULT WINAPI CompositeMonikerCF_CreateInstance(LPCLASSFACTORY iface,
2016     LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
2017 {
2018     IMoniker* pMoniker;
2019     HRESULT  hr;
2020 
2021     TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
2022 
2023     *ppv = NULL;
2024 
2025     if (pUnk)
2026         return CLASS_E_NOAGGREGATION;
2027 
2028     hr = CompositeMonikerImpl_Construct(&pMoniker, NULL, NULL);
2029 
2030     if (SUCCEEDED(hr))
2031     {
2032         hr = IMoniker_QueryInterface(pMoniker, riid, ppv);
2033         IMoniker_Release(pMoniker);
2034     }
2035 
2036     return hr;
2037 }
2038 
2039 static HRESULT WINAPI CompositeMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
2040 {
2041     FIXME("(%d), stub!\n",fLock);
2042     return S_OK;
2043 }
2044 
2045 static const IClassFactoryVtbl CompositeMonikerCFVtbl =
2046 {
2047     CompositeMonikerCF_QueryInterface,
2048     CompositeMonikerCF_AddRef,
2049     CompositeMonikerCF_Release,
2050     CompositeMonikerCF_CreateInstance,
2051     CompositeMonikerCF_LockServer
2052 };
2053 static const IClassFactoryVtbl *CompositeMonikerCF = &CompositeMonikerCFVtbl;
2054 
2055 HRESULT CompositeMonikerCF_Create(REFIID riid, LPVOID *ppv)
2056 {
2057     return IClassFactory_QueryInterface((IClassFactory *)&CompositeMonikerCF, riid, ppv);
2058 }
2059 

~ [ 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.