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

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

Version: ~ [ 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 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  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 = (IROTData*)&(This->lpvtbl2);
119     else if (IsEqualIID(&IID_IMarshal, riid))
120         *ppvObject = (IROTData*)&(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