ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

compositemoniker.c
Go to the documentation of this file.
00001 /*
00002  * CompositeMonikers implementation
00003  *
00004  * Copyright 1999  Noomen Hamza
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include <assert.h>
00022 #include <stdarg.h>
00023 #include <string.h>
00024 
00025 #define COBJMACROS
00026 #define NONAMELESSUNION
00027 #define NONAMELESSSTRUCT
00028 
00029 #include "windef.h"
00030 #include "winbase.h"
00031 #include "winuser.h"
00032 #include "winerror.h"
00033 #include "wine/debug.h"
00034 #include "wine/unicode.h"
00035 #include "ole2.h"
00036 #include "moniker.h"
00037 
00038 WINE_DEFAULT_DEBUG_CHANNEL(ole);
00039 
00040 #define  BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
00041 
00042 /* CompositeMoniker data structure */
00043 typedef struct CompositeMonikerImpl{
00044     IMoniker IMoniker_iface;
00045     IROTData IROTData_iface;
00046     IMarshal IMarshal_iface;
00047     LONG ref;
00048     IMoniker** tabMoniker; /* dynamic table containing all components (monikers) of this composite moniker */
00049     ULONG    tabSize;      /* size of tabMoniker */
00050     ULONG    tabLastIndex; /* first free index in tabMoniker */
00051 } CompositeMonikerImpl;
00052 
00053 static inline CompositeMonikerImpl *impl_from_IMoniker(IMoniker *iface)
00054 {
00055     return CONTAINING_RECORD(iface, CompositeMonikerImpl, IMoniker_iface);
00056 }
00057 
00058 static inline CompositeMonikerImpl *impl_from_IROTData(IROTData *iface)
00059 {
00060     return CONTAINING_RECORD(iface, CompositeMonikerImpl, IROTData_iface);
00061 }
00062 
00063 static inline CompositeMonikerImpl *impl_from_IMarshal(IMarshal *iface)
00064 {
00065     return CONTAINING_RECORD(iface, CompositeMonikerImpl, IMarshal_iface);
00066 }
00067 
00068 /* EnumMoniker data structure */
00069 typedef struct EnumMonikerImpl{
00070     IEnumMoniker IEnumMoniker_iface;
00071     LONG ref;
00072     IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
00073     ULONG      tabSize; /* size of tabMoniker */
00074     ULONG      currentPos;  /* index pointer on the current moniker */
00075 } EnumMonikerImpl;
00076 
00077 static inline EnumMonikerImpl *impl_from_IEnumMoniker(IEnumMoniker *iface)
00078 {
00079     return CONTAINING_RECORD(iface, EnumMonikerImpl, IEnumMoniker_iface);
00080 }
00081 
00082 static HRESULT EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
00083 
00084 /*******************************************************************************
00085  *        CompositeMoniker_QueryInterface
00086  *******************************************************************************/
00087 static HRESULT WINAPI
00088 CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
00089 {
00090     CompositeMonikerImpl *This = impl_from_IMoniker(iface);
00091 
00092     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
00093 
00094     /* Perform a sanity check on the parameters.*/
00095     if ( ppvObject==0 )
00096     return E_INVALIDARG;
00097 
00098     /* Initialize the return parameter */
00099     *ppvObject = 0;
00100 
00101     /* Compare the riid with the interface IDs implemented by this object.*/
00102     if (IsEqualIID(&IID_IUnknown, riid) ||
00103         IsEqualIID(&IID_IPersist, riid) ||
00104         IsEqualIID(&IID_IPersistStream, riid) ||
00105         IsEqualIID(&IID_IMoniker, riid)
00106        )
00107         *ppvObject = iface;
00108     else if (IsEqualIID(&IID_IROTData, riid))
00109         *ppvObject = &This->IROTData_iface;
00110     else if (IsEqualIID(&IID_IMarshal, riid))
00111         *ppvObject = &This->IMarshal_iface;
00112 
00113     /* Check that we obtained an interface.*/
00114     if ((*ppvObject)==0)
00115         return E_NOINTERFACE;
00116 
00117     /* Query Interface always increases the reference count by one when it is successful */
00118     IMoniker_AddRef(iface);
00119 
00120     return S_OK;
00121 }
00122 
00123 /******************************************************************************
00124  *        CompositeMoniker_AddRef
00125  ******************************************************************************/
00126 static ULONG WINAPI
00127 CompositeMonikerImpl_AddRef(IMoniker* iface)
00128 {
00129     CompositeMonikerImpl *This = impl_from_IMoniker(iface);
00130 
00131     TRACE("(%p)\n",This);
00132 
00133     return InterlockedIncrement(&This->ref);
00134 }
00135 
00136 static void CompositeMonikerImpl_ReleaseMonikersInTable(CompositeMonikerImpl *This)
00137 {
00138     ULONG i;
00139 
00140     for (i = 0; i < This->tabLastIndex; i++)
00141         IMoniker_Release(This->tabMoniker[i]);
00142 
00143     This->tabLastIndex = 0;
00144 }
00145 
00146 /******************************************************************************
00147  *        CompositeMoniker_Release
00148  ******************************************************************************/
00149 static ULONG WINAPI
00150 CompositeMonikerImpl_Release(IMoniker* iface)
00151 {
00152     CompositeMonikerImpl *This = impl_from_IMoniker(iface);
00153     ULONG ref;
00154 
00155     TRACE("(%p)\n",This);
00156 
00157     ref = InterlockedDecrement(&This->ref);
00158 
00159     /* destroy the object if there's no more reference on it */
00160     if (ref == 0){
00161 
00162         /* release all the components before destroying this object */
00163         CompositeMonikerImpl_ReleaseMonikersInTable(This);
00164 
00165         HeapFree(GetProcessHeap(),0,This->tabMoniker);
00166         HeapFree(GetProcessHeap(),0,This);
00167     }
00168     return ref;
00169 }
00170 
00171 /******************************************************************************
00172  *        CompositeMoniker_GetClassID
00173  ******************************************************************************/
00174 static HRESULT WINAPI
00175 CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
00176 {
00177     TRACE("(%p,%p)\n",iface,pClassID);
00178 
00179     if (pClassID==NULL)
00180         return E_POINTER;
00181 
00182     *pClassID = CLSID_CompositeMoniker;
00183 
00184     return S_OK;
00185 }
00186 
00187 /******************************************************************************
00188  *        CompositeMoniker_IsDirty
00189  ******************************************************************************/
00190 static HRESULT WINAPI
00191 CompositeMonikerImpl_IsDirty(IMoniker* iface)
00192 {
00193     /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
00194        method in the OLE-provided moniker interfaces always return S_FALSE because
00195        their internal state never changes. */
00196 
00197     TRACE("(%p)\n",iface);
00198 
00199     return S_FALSE;
00200 }
00201 
00202 /******************************************************************************
00203  *        CompositeMoniker_Load
00204  ******************************************************************************/
00205 static HRESULT WINAPI
00206 CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
00207 {
00208     CompositeMonikerImpl *This = impl_from_IMoniker(iface);
00209     HRESULT res;
00210     DWORD moniker_count;
00211     DWORD i;
00212 
00213     TRACE("(%p,%p)\n",iface,pStm);
00214 
00215     /* this function call OleLoadFromStream function for each moniker within this object */
00216 
00217     res=IStream_Read(pStm,&moniker_count,sizeof(DWORD),NULL);
00218     if (res != S_OK)
00219     {
00220         ERR("couldn't reading moniker count from stream\n");
00221         return E_FAIL;
00222     }
00223 
00224     CompositeMonikerImpl_ReleaseMonikersInTable(This);
00225 
00226     for (i = 0; i < moniker_count; i++)
00227     {
00228         res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
00229         if (FAILED(res))
00230         {
00231             ERR("couldn't load moniker from stream, res = 0x%08x\n", res);
00232             break;
00233         }
00234 
00235         /* resize the table if needed */
00236         if (++This->tabLastIndex==This->tabSize){
00237 
00238             This->tabSize+=BLOCK_TAB_SIZE;
00239             This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
00240 
00241             if (This->tabMoniker==NULL)
00242             return E_OUTOFMEMORY;
00243         }
00244     }
00245 
00246     return res;
00247 }
00248 
00249 /******************************************************************************
00250  *        CompositeMoniker_Save
00251  ******************************************************************************/
00252 static HRESULT WINAPI
00253 CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
00254 {
00255     CompositeMonikerImpl *This = impl_from_IMoniker(iface);
00256     HRESULT res;
00257     IEnumMoniker *enumMk;
00258     IMoniker *pmk;
00259     DWORD moniker_count = This->tabLastIndex;
00260 
00261     TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
00262 
00263     /* This function calls OleSaveToStream function for each moniker within
00264      * this object.
00265      * When I tested this function in windows, I usually found this constant
00266      * at the beginning of the stream. I don't known why (there's no
00267      * indication in the specification) !
00268      */
00269     res=IStream_Write(pStm,&moniker_count,sizeof(moniker_count),NULL);
00270     if (FAILED(res)) return res;
00271 
00272     IMoniker_Enum(iface,TRUE,&enumMk);
00273 
00274     while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
00275 
00276         res=OleSaveToStream((IPersistStream*)pmk,pStm);
00277 
00278         IMoniker_Release(pmk);
00279 
00280         if (FAILED(res)){
00281 
00282             IEnumMoniker_Release(enumMk);
00283             return res;
00284         }
00285     }
00286 
00287     IEnumMoniker_Release(enumMk);
00288 
00289     return S_OK;
00290 }
00291 
00292 /******************************************************************************
00293  *        CompositeMoniker_GetSizeMax
00294  ******************************************************************************/
00295 static HRESULT WINAPI
00296 CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
00297 {
00298     IEnumMoniker *enumMk;
00299     IMoniker *pmk;
00300     ULARGE_INTEGER ptmpSize;
00301 
00302     /* The sizeMax of this object is calculated by calling  GetSizeMax on
00303      * each moniker within this object then summing all returned values
00304      */
00305 
00306     TRACE("(%p,%p)\n",iface,pcbSize);
00307 
00308     if (!pcbSize)
00309         return E_POINTER;
00310 
00311     pcbSize->QuadPart = sizeof(DWORD);
00312 
00313     IMoniker_Enum(iface,TRUE,&enumMk);
00314 
00315     while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
00316 
00317         IMoniker_GetSizeMax(pmk,&ptmpSize);
00318 
00319         IMoniker_Release(pmk);
00320 
00321         pcbSize->QuadPart = ptmpSize.QuadPart + sizeof(CLSID);
00322     }
00323 
00324     IEnumMoniker_Release(enumMk);
00325 
00326     return S_OK;
00327 }
00328 
00329 /******************************************************************************
00330  *                  CompositeMoniker_BindToObject
00331  ******************************************************************************/
00332 static HRESULT WINAPI
00333 CompositeMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc,
00334                IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult)
00335 {
00336     HRESULT   res;
00337     IRunningObjectTable *prot;
00338     IMoniker *tempMk,*antiMk,*mostRigthMk;
00339     IEnumMoniker *enumMoniker;
00340 
00341     TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
00342 
00343     if (ppvResult==NULL)
00344         return E_POINTER;
00345 
00346     *ppvResult=0;
00347     /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
00348     /* object for the requested interface pointer. */
00349     if(pmkToLeft==NULL){
00350 
00351         res=IBindCtx_GetRunningObjectTable(pbc,&prot);
00352 
00353         if (SUCCEEDED(res)){
00354 
00355             /* if the requested class was loaded before ! we don't need to reload it */
00356             res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
00357 
00358             if (res==S_OK)
00359                 return res;
00360         }
00361     }
00362     else{
00363         /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
00364         /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
00365 
00366         IMoniker_Enum(iface,FALSE,&enumMoniker);
00367         IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
00368         IEnumMoniker_Release(enumMoniker);
00369 
00370         res=CreateAntiMoniker(&antiMk);
00371         res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
00372         IMoniker_Release(antiMk);
00373 
00374         res=IMoniker_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
00375 
00376         IMoniker_Release(tempMk);
00377         IMoniker_Release(mostRigthMk);
00378     }
00379 
00380     return res;
00381 }
00382 
00383 /******************************************************************************
00384  *        CompositeMoniker_BindToStorage
00385  ******************************************************************************/
00386 static HRESULT WINAPI
00387 CompositeMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc,
00388                IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult)
00389 {
00390     HRESULT   res;
00391     IMoniker *tempMk,*antiMk,*mostRigthMk,*leftMk;
00392     IEnumMoniker *enumMoniker;
00393 
00394     TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
00395 
00396     *ppvResult=0;
00397 
00398     /* This method recursively calls BindToStorage on the rightmost component of the composite, */
00399     /* passing the rest of the composite as the pmkToLeft parameter for that call. */
00400 
00401     if (pmkToLeft)
00402     {
00403         res = IMoniker_ComposeWith(pmkToLeft, iface, FALSE, &leftMk);
00404         if (FAILED(res)) return res;
00405     }
00406     else
00407         leftMk = iface;
00408 
00409     IMoniker_Enum(iface, FALSE, &enumMoniker);
00410     IEnumMoniker_Next(enumMoniker, 1, &mostRigthMk, NULL);
00411     IEnumMoniker_Release(enumMoniker);
00412 
00413     res = CreateAntiMoniker(&antiMk);
00414     if (FAILED(res)) return res;
00415     res = IMoniker_ComposeWith(leftMk, antiMk, 0, &tempMk);
00416     if (FAILED(res)) return res;
00417     IMoniker_Release(antiMk);
00418 
00419     res = IMoniker_BindToStorage(mostRigthMk, pbc, tempMk, riid, ppvResult);
00420 
00421     IMoniker_Release(tempMk);
00422 
00423     IMoniker_Release(mostRigthMk);
00424 
00425     if (pmkToLeft)
00426         IMoniker_Release(leftMk);
00427 
00428     return res;
00429 }
00430 
00431 /******************************************************************************
00432  *        CompositeMoniker_Reduce
00433  ******************************************************************************/
00434 static HRESULT WINAPI
00435 CompositeMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
00436                IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
00437 {
00438     IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
00439     IEnumMoniker *enumMoniker;
00440 
00441     TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
00442 
00443     if (ppmkReduced==NULL)
00444         return E_POINTER;
00445 
00446     /* This method recursively calls Reduce for each of its component monikers. */
00447 
00448     if (ppmkToLeft==NULL){
00449 
00450         IMoniker_Enum(iface,FALSE,&enumMoniker);
00451         IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
00452         IEnumMoniker_Release(enumMoniker);
00453 
00454         CreateAntiMoniker(&antiMk);
00455         IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
00456         IMoniker_Release(antiMk);
00457 
00458         return IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
00459     }
00460     else if (*ppmkToLeft==NULL)
00461 
00462         return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
00463 
00464     else{
00465 
00466         /* separate the composite moniker in to left and right moniker */
00467         IMoniker_Enum(iface,FALSE,&enumMoniker);
00468         IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
00469         IEnumMoniker_Release(enumMoniker);
00470 
00471         CreateAntiMoniker(&antiMk);
00472         IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
00473         IMoniker_Release(antiMk);
00474 
00475         /* If any of the components  reduces itself, the method returns S_OK and passes back a composite */
00476         /* of the reduced components */
00477         if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
00478             IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
00479            )
00480 
00481             return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
00482 
00483         else{
00484             /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
00485 
00486             IMoniker_AddRef(iface);
00487 
00488             *ppmkReduced=iface;
00489 
00490             return MK_S_REDUCED_TO_SELF;
00491         }
00492     }
00493 }
00494 
00495 /******************************************************************************
00496  *        CompositeMoniker_ComposeWith
00497  ******************************************************************************/
00498 static HRESULT WINAPI
00499 CompositeMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
00500                BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
00501 {
00502     TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
00503 
00504     if ((ppmkComposite==NULL)||(pmkRight==NULL))
00505     return E_POINTER;
00506 
00507     *ppmkComposite=0;
00508 
00509     /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
00510     /* otherwise, the method returns the result of combining the two monikers by calling the */
00511     /* CreateGenericComposite function */
00512 
00513     if (fOnlyIfNotGeneric)
00514         return MK_E_NEEDGENERIC;
00515 
00516     return CreateGenericComposite(iface,pmkRight,ppmkComposite);
00517 }
00518 
00519 /******************************************************************************
00520  *        CompositeMoniker_Enum
00521  ******************************************************************************/
00522 static HRESULT WINAPI
00523 CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
00524 {
00525     CompositeMonikerImpl *This = impl_from_IMoniker(iface);
00526 
00527     TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
00528 
00529     if (ppenumMoniker == NULL)
00530         return E_POINTER;
00531 
00532     return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
00533 }
00534 
00535 /******************************************************************************
00536  *        CompositeMoniker_IsEqual
00537  ******************************************************************************/
00538 static HRESULT WINAPI
00539 CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
00540 {
00541     IEnumMoniker *enumMoniker1,*enumMoniker2;
00542     IMoniker *tempMk1,*tempMk2;
00543     HRESULT res1,res2,res;
00544     BOOL done;
00545 
00546     TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
00547 
00548     if (pmkOtherMoniker==NULL)
00549         return S_FALSE;
00550 
00551     /* This method returns S_OK if the components of both monikers are equal when compared in the */
00552     /* left-to-right order.*/
00553     IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
00554 
00555     if (enumMoniker1==NULL)
00556         return S_FALSE;
00557 
00558     IMoniker_Enum(iface,TRUE,&enumMoniker2);
00559 
00560     do {
00561 
00562         res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
00563         res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
00564 
00565         if((res1==S_OK)&&(res2==S_OK)){
00566             done = (res = IMoniker_IsEqual(tempMk1,tempMk2)) == S_FALSE;
00567         }
00568         else
00569         {
00570             res = (res1==S_FALSE) && (res2==S_FALSE);
00571             done = TRUE;
00572         }
00573 
00574         if (res1==S_OK)
00575             IMoniker_Release(tempMk1);
00576 
00577         if (res2==S_OK)
00578             IMoniker_Release(tempMk2);
00579     } while (!done);
00580 
00581     IEnumMoniker_Release(enumMoniker1);
00582     IEnumMoniker_Release(enumMoniker2);
00583 
00584     return res;
00585 }
00586 /******************************************************************************
00587  *        CompositeMoniker_Hash
00588  ******************************************************************************/
00589 static HRESULT WINAPI
00590 CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
00591 {
00592     IEnumMoniker *enumMoniker;
00593     IMoniker *tempMk;
00594     HRESULT res;
00595     DWORD tempHash;
00596 
00597     TRACE("(%p,%p)\n",iface,pdwHash);
00598 
00599     if (pdwHash==NULL)
00600         return E_POINTER;
00601 
00602     res = IMoniker_Enum(iface,TRUE,&enumMoniker);
00603     if(FAILED(res))
00604         return res;
00605 
00606     *pdwHash = 0;
00607 
00608     while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
00609         res = IMoniker_Hash(tempMk, &tempHash);
00610         if(FAILED(res))
00611             break;
00612         *pdwHash = *pdwHash ^ tempHash;
00613         
00614         IMoniker_Release(tempMk);
00615     }
00616 
00617     IEnumMoniker_Release(enumMoniker);
00618 
00619     return res;
00620 }
00621 
00622 /******************************************************************************
00623  *        CompositeMoniker_IsRunning
00624  ******************************************************************************/
00625 static HRESULT WINAPI
00626 CompositeMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc,
00627                IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning)
00628 {
00629     IRunningObjectTable* rot;
00630     HRESULT res;
00631     IMoniker *tempMk,*antiMk,*mostRigthMk;
00632     IEnumMoniker *enumMoniker;
00633 
00634     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
00635 
00636     /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
00637     if (pmkToLeft!=NULL){
00638 
00639         CreateGenericComposite(pmkToLeft,iface,&tempMk);
00640 
00641         res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
00642 
00643         IMoniker_Release(tempMk);
00644 
00645         return res;
00646     }
00647     else
00648         /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
00649         /* to this moniker */
00650 
00651         if (pmkNewlyRunning!=NULL)
00652 
00653             if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
00654                 return S_OK;
00655 
00656             else
00657                 return S_FALSE;
00658 
00659         else{
00660 
00661             if (pbc==NULL)
00662                 return E_INVALIDARG;
00663 
00664             /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
00665             /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls   */
00666             /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
00667             /* the composite as the pmkToLeft parameter for that call.                                   */
00668 
00669              res=IBindCtx_GetRunningObjectTable(pbc,&rot);
00670 
00671             if (FAILED(res))
00672                 return res;
00673 
00674             res = IRunningObjectTable_IsRunning(rot,iface);
00675             IRunningObjectTable_Release(rot);
00676 
00677             if(res==S_OK)
00678                 return S_OK;
00679 
00680             else{
00681 
00682                 IMoniker_Enum(iface,FALSE,&enumMoniker);
00683                 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
00684                 IEnumMoniker_Release(enumMoniker);
00685 
00686                 res=CreateAntiMoniker(&antiMk);
00687                 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
00688                 IMoniker_Release(antiMk);
00689 
00690                 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
00691 
00692                 IMoniker_Release(tempMk);
00693                 IMoniker_Release(mostRigthMk);
00694 
00695                 return res;
00696             }
00697         }
00698 }
00699 
00700 /******************************************************************************
00701  *        CompositeMoniker_GetTimeOfLastChange
00702  ******************************************************************************/
00703 static HRESULT WINAPI
00704 CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
00705                IMoniker* pmkToLeft, FILETIME* pCompositeTime)
00706 {
00707     HRESULT res;
00708     IMoniker *tempMk,*antiMk,*mostRigthMk,*leftMk;
00709     IEnumMoniker *enumMoniker;
00710 
00711     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
00712 
00713     if (pCompositeTime==NULL)
00714         return E_INVALIDARG;
00715 
00716     /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to  */
00717     /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls  */
00718     /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
00719     /* of the composite as the pmkToLeft parameter for that call.                                       */
00720     if (pmkToLeft)
00721     {
00722         IRunningObjectTable* rot;
00723 
00724         res = IMoniker_ComposeWith(pmkToLeft, iface, FALSE, &leftMk);
00725 
00726         res = IBindCtx_GetRunningObjectTable(pbc,&rot);
00727         if (FAILED(res))
00728         {
00729             IMoniker_Release(leftMk);
00730             return res;
00731         }
00732 
00733         if (IRunningObjectTable_GetTimeOfLastChange(rot,leftMk,pCompositeTime)==S_OK)
00734         {
00735             IMoniker_Release(leftMk);
00736             return res;
00737         }
00738     }
00739     else
00740         leftMk = iface;
00741 
00742     IMoniker_Enum(iface, FALSE, &enumMoniker);
00743     IEnumMoniker_Next(enumMoniker, 1, &mostRigthMk, NULL);
00744     IEnumMoniker_Release(enumMoniker);
00745 
00746     res = CreateAntiMoniker(&antiMk);
00747     res = IMoniker_ComposeWith(leftMk, antiMk, 0, &tempMk);
00748     IMoniker_Release(antiMk);
00749 
00750     res = IMoniker_GetTimeOfLastChange(mostRigthMk, pbc, tempMk, pCompositeTime);
00751 
00752     IMoniker_Release(tempMk);
00753     IMoniker_Release(mostRigthMk);
00754 
00755     if (pmkToLeft)
00756         IMoniker_Release(leftMk);
00757 
00758     return res;
00759 }
00760 
00761 /******************************************************************************
00762  *        CompositeMoniker_Inverse
00763  ******************************************************************************/
00764 static HRESULT WINAPI
00765 CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
00766 {
00767     HRESULT res;
00768     IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
00769     IEnumMoniker *enumMoniker;
00770 
00771     TRACE("(%p,%p)\n",iface,ppmk);
00772 
00773     if (ppmk==NULL)
00774         return E_POINTER;
00775 
00776     /* This method returns a composite moniker that consists of the inverses of each of the components */
00777     /* of the original composite, stored in reverse order */
00778 
00779     res=CreateAntiMoniker(&antiMk);
00780     res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
00781     IMoniker_Release(antiMk);
00782 
00783     if (tempMk==NULL)
00784 
00785         return IMoniker_Inverse(iface,ppmk);
00786 
00787     else{
00788 
00789         IMoniker_Enum(iface,FALSE,&enumMoniker);
00790         IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
00791         IEnumMoniker_Release(enumMoniker);
00792 
00793         IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
00794         CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
00795 
00796         res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
00797 
00798         IMoniker_Release(tempMk);
00799         IMoniker_Release(mostRigthMk);
00800         IMoniker_Release(tempInvMk);
00801         IMoniker_Release(mostRigthInvMk);
00802 
00803         return res;
00804     }
00805 }
00806 
00807 /******************************************************************************
00808  *        CompositeMoniker_CommonPrefixWith
00809  ******************************************************************************/
00810 static HRESULT WINAPI
00811 CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface, IMoniker* pmkOther,
00812                IMoniker** ppmkPrefix)
00813 {
00814     DWORD mkSys;
00815     HRESULT res1,res2;
00816     IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
00817     IEnumMoniker *enumMoniker1,*enumMoniker2;
00818     ULONG i,nbCommonMk=0;
00819 
00820     /* If the other moniker is a composite, this method compares the components of each composite from left  */
00821     /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
00822     /* of the leftmost components were common to both monikers.                                              */
00823 
00824     if (ppmkPrefix==NULL)
00825         return E_POINTER;
00826 
00827     *ppmkPrefix=0;
00828 
00829     if (pmkOther==NULL)
00830         return MK_E_NOPREFIX;
00831 
00832     IMoniker_IsSystemMoniker(pmkOther,&mkSys);
00833 
00834     if(mkSys==MKSYS_GENERICCOMPOSITE){
00835 
00836         IMoniker_Enum(iface,TRUE,&enumMoniker1);
00837         IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
00838 
00839         while(1){
00840 
00841             res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
00842             res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
00843 
00844             if ((res1==S_FALSE) && (res2==S_FALSE)){
00845 
00846                 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
00847                 *ppmkPrefix=iface;
00848                 IMoniker_AddRef(iface);
00849                 return  MK_S_US;
00850             }
00851             else if ((res1==S_OK) && (res2==S_OK)){
00852 
00853                 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
00854 
00855                     nbCommonMk++;
00856 
00857                 else
00858                     break;
00859 
00860             }
00861             else if (res1==S_OK){
00862 
00863                 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
00864                 /* ppmkPrefix to the other moniker.                                                       */
00865                 *ppmkPrefix=pmkOther;
00866                 return MK_S_HIM;
00867             }
00868             else{
00869                 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
00870                 /* to this moniker.                                                                          */
00871                 *ppmkPrefix=iface;
00872                 return MK_S_ME;
00873             }
00874         }
00875 
00876         IEnumMoniker_Release(enumMoniker1);
00877         IEnumMoniker_Release(enumMoniker2);
00878 
00879         /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
00880         if (nbCommonMk==0)
00881             return MK_E_NOPREFIX;
00882 
00883         IEnumMoniker_Reset(enumMoniker1);
00884 
00885         IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
00886 
00887         /* if we have more than one common moniker the result will be a composite moniker */
00888         if (nbCommonMk>1){
00889 
00890             /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
00891             IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
00892             CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
00893             IMoniker_Release(tempMk1);
00894             IMoniker_Release(tempMk2);
00895 
00896             /* compose all common monikers in a composite moniker */
00897             for(i=0;i<nbCommonMk;i++){
00898 
00899                 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
00900 
00901                 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
00902 
00903                 IMoniker_Release(*ppmkPrefix);
00904 
00905                 IMoniker_Release(tempMk1);
00906 
00907                 *ppmkPrefix=tempMk2;
00908             }
00909             return S_OK;
00910         }
00911         else{
00912             /* if we have only one common moniker the result will be a simple moniker which is the most-left one*/
00913             *ppmkPrefix=tempMk1;
00914 
00915             return S_OK;
00916         }
00917     }
00918     else{
00919         /* If the other moniker is not a composite, the method simply compares it to the leftmost component
00920          of this moniker.*/
00921 
00922         IMoniker_Enum(iface,TRUE,&enumMoniker1);
00923 
00924         IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
00925 
00926         if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
00927 
00928             *ppmkPrefix=pmkOther;
00929 
00930             return MK_S_HIM;
00931         }
00932         else
00933             return MK_E_NOPREFIX;
00934     }
00935 }
00936 
00937 /***************************************************************************************************
00938  *        GetAfterCommonPrefix (local function)
00939  *  This function returns a moniker that consist of the remainder when the common prefix is removed
00940  ***************************************************************************************************/
00941 static VOID GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
00942 {
00943     IMoniker *tempMk,*tempMk1,*tempMk2;
00944     IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
00945     ULONG nbRestMk=0;
00946     DWORD mkSys;
00947     HRESULT res1,res2;
00948 
00949     *restMk=0;
00950 
00951     /* to create an enumerator for pGenMk with current position pointed on the first element after common  */
00952     /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop  */
00953     /* on the first difference. */
00954     IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
00955 
00956     IMoniker_IsSystemMoniker(commonMk,&mkSys);
00957 
00958     if (mkSys==MKSYS_GENERICCOMPOSITE){
00959 
00960         IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
00961         while(1){
00962 
00963             res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
00964             res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
00965 
00966             if ((res1==S_FALSE)||(res2==S_FALSE)){
00967 
00968                 if (res1==S_OK)
00969 
00970                     nbRestMk++;
00971 
00972                 IMoniker_Release(tempMk1);
00973                 IMoniker_Release(tempMk2);
00974 
00975                 break;
00976             }
00977             IMoniker_Release(tempMk1);
00978             IMoniker_Release(tempMk2);
00979         }
00980     }
00981     else{
00982         IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
00983         IMoniker_Release(tempMk1);
00984     }
00985 
00986     /* count the number of elements in the enumerator after the common prefix */
00987     IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
00988 
00989     for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
00990 
00991         IMoniker_Release(tempMk);
00992 
00993     if (nbRestMk==0)
00994         return;
00995 
00996     /* create a generic composite moniker with monikers located after the common prefix */
00997     IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
00998 
00999     if (nbRestMk==1){
01000 
01001         *restMk= tempMk1;
01002         return;
01003     }
01004     else {
01005 
01006         IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
01007 
01008         CreateGenericComposite(tempMk1,tempMk2,restMk);
01009 
01010         IMoniker_Release(tempMk1);
01011 
01012         IMoniker_Release(tempMk2);
01013 
01014         while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
01015 
01016             CreateGenericComposite(*restMk,tempMk1,&tempMk2);
01017 
01018             IMoniker_Release(tempMk1);
01019 
01020             IMoniker_Release(*restMk);
01021 
01022             *restMk=tempMk2;
01023         }
01024     }
01025 }
01026 
01027 /******************************************************************************
01028  *        CompositeMoniker_RelativePathTo
01029  ******************************************************************************/
01030 static HRESULT WINAPI
01031 CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther,
01032                IMoniker** ppmkRelPath)
01033 {
01034     HRESULT res;
01035     IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
01036 
01037     TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
01038 
01039     if (ppmkRelPath==NULL)
01040         return E_POINTER;
01041 
01042     *ppmkRelPath=0;
01043 
01044     /* This method finds the common prefix of the two monikers and creates two monikers that consist     */
01045     /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
01046     /* of this moniker and composes the remainder of the other moniker on the right of it.               */
01047 
01048     /* finds the common prefix of the two monikers */
01049     res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
01050 
01051     /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
01052     if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
01053 
01054         *ppmkRelPath=pmkOther;
01055         IMoniker_AddRef(pmkOther);
01056         return MK_S_HIM;
01057     }
01058 
01059     GetAfterCommonPrefix(iface,commonMk,&restThisMk);
01060     GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
01061 
01062     /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
01063     /* moniker when the common prefix is removed                                                           */
01064     if (res==MK_S_HIM){
01065 
01066         IMoniker_Inverse(restThisMk,ppmkRelPath);
01067         IMoniker_Release(restThisMk);
01068     }
01069     /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
01070     /* when the common prefix is removed                                                                     */
01071     else if (res==MK_S_ME){
01072 
01073         *ppmkRelPath=restOtherMk;
01074         IMoniker_AddRef(restOtherMk);
01075     }
01076     /* the relative path is the inverse for the remainder of this moniker and the remainder of the other  */
01077     /* moniker on the right of it.                                                                        */
01078     else if (res==S_OK){
01079 
01080         IMoniker_Inverse(restThisMk,&invRestThisMk);
01081         IMoniker_Release(restThisMk);
01082         CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
01083         IMoniker_Release(invRestThisMk);
01084         IMoniker_Release(restOtherMk);
01085     }
01086     return S_OK;
01087 }
01088 
01089 /******************************************************************************
01090  *        CompositeMoniker_GetDisplayName
01091  ******************************************************************************/
01092 static HRESULT WINAPI
01093 CompositeMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
01094                IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
01095 {
01096     ULONG lengthStr=1;
01097     IEnumMoniker *enumMoniker;
01098     IMoniker* tempMk;
01099     LPOLESTR tempStr;
01100 
01101     TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
01102 
01103     if (ppszDisplayName==NULL)
01104         return E_POINTER;
01105 
01106     *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
01107 
01108     if (*ppszDisplayName==NULL)
01109         return E_OUTOFMEMORY;
01110 
01111     /* This method returns the concatenation of the display names returned by each component moniker of */
01112     /* the composite */
01113 
01114     **ppszDisplayName=0;
01115 
01116     IMoniker_Enum(iface,TRUE,&enumMoniker);
01117 
01118     while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
01119 
01120         IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
01121 
01122         lengthStr+=lstrlenW(tempStr);
01123 
01124         *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
01125 
01126         if (*ppszDisplayName==NULL)
01127             return E_OUTOFMEMORY;
01128 
01129         strcatW(*ppszDisplayName,tempStr);
01130 
01131         CoTaskMemFree(tempStr);
01132         IMoniker_Release(tempMk);
01133     }
01134 
01135     IEnumMoniker_Release(enumMoniker);
01136 
01137     return S_OK;
01138 }
01139 
01140 /******************************************************************************
01141  *        CompositeMoniker_ParseDisplayName
01142  ******************************************************************************/
01143 static HRESULT WINAPI
01144 CompositeMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,
01145                IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten,
01146                IMoniker** ppmkOut)
01147 {
01148     IEnumMoniker *enumMoniker;
01149     IMoniker *tempMk,*mostRigthMk,*antiMk;
01150     /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
01151     /* passing everything else as the pmkToLeft parameter for that call. */
01152 
01153     /* get the most right moniker */
01154     IMoniker_Enum(iface,FALSE,&enumMoniker);
01155     IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
01156     IEnumMoniker_Release(enumMoniker);
01157 
01158     /* get the left moniker */
01159     CreateAntiMoniker(&antiMk);
01160     IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
01161     IMoniker_Release(antiMk);
01162 
01163     return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
01164 }
01165 
01166 /******************************************************************************
01167  *        CompositeMoniker_IsSystemMoniker
01168  ******************************************************************************/
01169 static HRESULT WINAPI
01170 CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
01171 {
01172     TRACE("(%p,%p)\n",iface,pwdMksys);
01173 
01174     if (!pwdMksys)
01175         return E_POINTER;
01176 
01177     (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
01178 
01179     return S_OK;
01180 }
01181 
01182 /*******************************************************************************
01183  *        CompositeMonikerIROTData_QueryInterface
01184  *******************************************************************************/
01185 static HRESULT WINAPI
01186 CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,
01187                VOID** ppvObject)
01188 {
01189     CompositeMonikerImpl *This = impl_from_IROTData(iface);
01190 
01191     TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
01192 
01193     return CompositeMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject);
01194 }
01195 
01196 /***********************************************************************
01197  *        CompositeMonikerIROTData_AddRef
01198  */
01199 static ULONG WINAPI
01200 CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
01201 {
01202     CompositeMonikerImpl *This = impl_from_IROTData(iface);
01203 
01204     TRACE("(%p)\n",iface);
01205 
01206     return IMoniker_AddRef(&This->IMoniker_iface);
01207 }
01208 
01209 /***********************************************************************
01210  *        CompositeMonikerIROTData_Release
01211  */
01212 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
01213 {
01214     CompositeMonikerImpl *This = impl_from_IROTData(iface);
01215 
01216     TRACE("(%p)\n",iface);
01217 
01218     return IMoniker_Release(&This->IMoniker_iface);
01219 }
01220 
01221 /******************************************************************************
01222  *        CompositeMonikerIROTData_GetComparisonData
01223  ******************************************************************************/
01224 static HRESULT WINAPI
01225 CompositeMonikerROTDataImpl_GetComparisonData(IROTData* iface,
01226                BYTE* pbData, ULONG cbMax, ULONG* pcbData)
01227 {
01228     CompositeMonikerImpl *This = impl_from_IROTData(iface);
01229     IEnumMoniker *pEnumMk;
01230     IMoniker *pmk;
01231     HRESULT hr;
01232 
01233     TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData);
01234 
01235     *pcbData = sizeof(CLSID);
01236 
01237     hr = IMoniker_Enum(&This->IMoniker_iface, TRUE, &pEnumMk);
01238     if (FAILED(hr)) return hr;
01239 
01240     while(IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
01241     {
01242         IROTData *pROTData;
01243         hr = IMoniker_QueryInterface(pmk, &IID_IROTData, (void **)&pROTData);
01244         if (FAILED(hr))
01245             ERR("moniker doesn't support IROTData interface\n");
01246 
01247         if (SUCCEEDED(hr))
01248         {
01249             ULONG cbData;
01250             hr = IROTData_GetComparisonData(pROTData, NULL, 0, &cbData);
01251             IROTData_Release(pROTData);
01252             if (SUCCEEDED(hr) || (hr == E_OUTOFMEMORY))
01253             {
01254                 *pcbData += cbData;
01255                 hr = S_OK;
01256             }
01257             else
01258                 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr);
01259         }
01260 
01261         IMoniker_Release(pmk);
01262 
01263         if (FAILED(hr))
01264         {
01265             IEnumMoniker_Release(pEnumMk);
01266             return hr;
01267         }
01268     }
01269     if (cbMax < *pcbData)
01270         return E_OUTOFMEMORY;
01271 
01272     IEnumMoniker_Reset(pEnumMk);
01273 
01274     memcpy(pbData, &CLSID_CompositeMoniker, sizeof(CLSID));
01275     pbData += sizeof(CLSID);
01276     cbMax -= sizeof(CLSID);
01277 
01278     while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
01279     {
01280         IROTData *pROTData;
01281         hr = IMoniker_QueryInterface(pmk, &IID_IROTData, (void **)&pROTData);
01282         if (FAILED(hr))
01283             ERR("moniker doesn't support IROTData interface\n");
01284 
01285         if (SUCCEEDED(hr))
01286         {
01287             ULONG cbData;
01288             hr = IROTData_GetComparisonData(pROTData, pbData, cbMax, &cbData);
01289             IROTData_Release(pROTData);
01290             if (SUCCEEDED(hr))
01291             {
01292                 pbData += cbData;
01293                 cbMax -= cbData;
01294             }
01295             else
01296                 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr);
01297         }
01298 
01299         IMoniker_Release(pmk);
01300 
01301         if (FAILED(hr))
01302         {
01303             IEnumMoniker_Release(pEnumMk);
01304             return hr;
01305         }
01306     }
01307 
01308     IEnumMoniker_Release(pEnumMk);
01309 
01310     return S_OK;
01311 }
01312 
01313 static HRESULT WINAPI CompositeMonikerMarshalImpl_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv)
01314 {
01315     CompositeMonikerImpl *This = impl_from_IMarshal(iface);
01316 
01317     TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppv);
01318 
01319     return CompositeMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppv);
01320 }
01321 
01322 static ULONG WINAPI CompositeMonikerMarshalImpl_AddRef(IMarshal *iface)
01323 {
01324     CompositeMonikerImpl *This = impl_from_IMarshal(iface);
01325 
01326     TRACE("(%p)\n",iface);
01327 
01328     return CompositeMonikerImpl_AddRef(&This->IMoniker_iface);
01329 }
01330 
01331 static ULONG WINAPI CompositeMonikerMarshalImpl_Release(IMarshal *iface)
01332 {
01333     CompositeMonikerImpl *This = impl_from_IMarshal(iface);
01334 
01335     TRACE("(%p)\n",iface);
01336 
01337     return CompositeMonikerImpl_Release(&This->IMoniker_iface);
01338 }
01339 
01340 static HRESULT WINAPI CompositeMonikerMarshalImpl_GetUnmarshalClass(
01341   IMarshal *iface, REFIID riid, void *pv, DWORD dwDestContext,
01342   void* pvDestContext, DWORD mshlflags, CLSID* pCid)
01343 {
01344     CompositeMonikerImpl *This = impl_from_IMarshal(iface);
01345 
01346     TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv,
01347         dwDestContext, pvDestContext, mshlflags, pCid);
01348 
01349     return IMoniker_GetClassID(&This->IMoniker_iface, pCid);
01350 }
01351 
01352 static HRESULT WINAPI CompositeMonikerMarshalImpl_GetMarshalSizeMax(
01353   IMarshal *iface, REFIID riid, void *pv, DWORD dwDestContext,
01354   void* pvDestContext, DWORD mshlflags, DWORD* pSize)
01355 {
01356     CompositeMonikerImpl *This = impl_from_IMarshal(iface);
01357     IEnumMoniker *pEnumMk;
01358     IMoniker *pmk;
01359     HRESULT hr;
01360     ULARGE_INTEGER size;
01361 
01362     TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv,
01363         dwDestContext, pvDestContext, mshlflags, pSize);
01364 
01365     *pSize = 0x10; /* to match native */
01366 
01367     hr = IMoniker_Enum(&This->IMoniker_iface, TRUE, &pEnumMk);
01368     if (FAILED(hr)) return hr;
01369 
01370     hr = IMoniker_GetSizeMax(&This->IMoniker_iface, &size);
01371 
01372     while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
01373     {
01374         ULONG size;
01375 
01376         hr = CoGetMarshalSizeMax(&size, &IID_IMoniker, (IUnknown *)pmk, dwDestContext, pvDestContext, mshlflags);
01377         if (SUCCEEDED(hr))
01378             *pSize += size;
01379 
01380         IMoniker_Release(pmk);
01381 
01382         if (FAILED(hr))
01383         {
01384             IEnumMoniker_Release(pEnumMk);
01385             return hr;
01386         }
01387     }
01388 
01389     IEnumMoniker_Release(pEnumMk);
01390 
01391     return S_OK;
01392 }
01393 
01394 static HRESULT WINAPI CompositeMonikerMarshalImpl_MarshalInterface(IMarshal *iface, IStream *pStm,
01395     REFIID riid, void* pv, DWORD dwDestContext,
01396     void* pvDestContext, DWORD mshlflags)
01397 {
01398     CompositeMonikerImpl *This = impl_from_IMarshal(iface);
01399     IEnumMoniker *pEnumMk;
01400     IMoniker *pmk;
01401     HRESULT hr;
01402     ULONG i = 0;
01403 
01404     TRACE("(%p, %s, %p, %x, %p, %x)\n", pStm, debugstr_guid(riid), pv,
01405         dwDestContext, pvDestContext, mshlflags);
01406 
01407     hr = IMoniker_Enum(&This->IMoniker_iface, TRUE, &pEnumMk);
01408     if (FAILED(hr)) return hr;
01409 
01410     while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
01411     {
01412         hr = CoMarshalInterface(pStm, &IID_IMoniker, (IUnknown *)pmk, dwDestContext, pvDestContext, mshlflags);
01413 
01414         IMoniker_Release(pmk);
01415 
01416         if (FAILED(hr))
01417         {
01418             IEnumMoniker_Release(pEnumMk);
01419             return hr;
01420         }
01421         i++;
01422     }
01423 
01424     if (i != 2)
01425         FIXME("moniker count of %d not supported\n", i);
01426 
01427     IEnumMoniker_Release(pEnumMk);
01428 
01429     return S_OK;
01430 }
01431 
01432 static HRESULT WINAPI CompositeMonikerMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm,
01433     REFIID riid, void **ppv)
01434 {
01435     CompositeMonikerImpl *This = impl_from_IMarshal(iface);
01436     HRESULT hr;
01437 
01438     TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
01439 
01440     CompositeMonikerImpl_ReleaseMonikersInTable(This);
01441 
01442     /* resize the table if needed */
01443     if (This->tabLastIndex + 2 > This->tabSize)
01444     {
01445         This->tabSize += max(BLOCK_TAB_SIZE, 2);
01446         This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
01447 
01448         if (This->tabMoniker==NULL)
01449             return E_OUTOFMEMORY;
01450     }
01451 
01452     hr = CoUnmarshalInterface(pStm, &IID_IMoniker, (void**)&This->tabMoniker[This->tabLastIndex]);
01453     if (FAILED(hr))
01454     {
01455         ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr);
01456         return hr;
01457     }
01458     This->tabLastIndex++;
01459     hr = CoUnmarshalInterface(pStm, &IID_IMoniker, (void**)&This->tabMoniker[This->tabLastIndex]);
01460     if (FAILED(hr))
01461     {
01462         ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr);
01463         return hr;
01464     }
01465     This->tabLastIndex++;
01466 
01467     return IMoniker_QueryInterface(&This->IMoniker_iface, riid, ppv);
01468 }
01469 
01470 static HRESULT WINAPI CompositeMonikerMarshalImpl_ReleaseMarshalData(IMarshal *iface, IStream *pStm)
01471 {
01472     TRACE("(%p)\n", pStm);
01473     /* can't release a state-based marshal as nothing on server side to
01474      * release */
01475     return S_OK;
01476 }
01477 
01478 static HRESULT WINAPI CompositeMonikerMarshalImpl_DisconnectObject(IMarshal *iface,
01479     DWORD dwReserved)
01480 {
01481     TRACE("(0x%x)\n", dwReserved);
01482     /* can't disconnect a state-based marshal as nothing on server side to
01483      * disconnect from */
01484     return S_OK;
01485 }
01486 
01487 /******************************************************************************
01488  *        EnumMonikerImpl_QueryInterface
01489  ******************************************************************************/
01490 static HRESULT WINAPI
01491 EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
01492 {
01493     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
01494 
01495     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
01496 
01497     /* Perform a sanity check on the parameters.*/
01498     if ( ppvObject==0 )
01499     return E_INVALIDARG;
01500 
01501     /* Initialize the return parameter */
01502     *ppvObject = 0;
01503 
01504     /* Compare the riid with the interface IDs implemented by this object.*/
01505     if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
01506         *ppvObject = iface;
01507 
01508     /* Check that we obtained an interface.*/
01509     if ((*ppvObject)==0)
01510         return E_NOINTERFACE;
01511 
01512     /* Query Interface always increases the reference count by one when it is successful */
01513     IEnumMoniker_AddRef(iface);
01514 
01515     return S_OK;
01516 }
01517 
01518 /******************************************************************************
01519  *        EnumMonikerImpl_AddRef
01520  ******************************************************************************/
01521 static ULONG WINAPI
01522 EnumMonikerImpl_AddRef(IEnumMoniker* iface)
01523 {
01524     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
01525 
01526     TRACE("(%p)\n",This);
01527 
01528     return InterlockedIncrement(&This->ref);
01529 
01530 }
01531 
01532 /******************************************************************************
01533  *        EnumMonikerImpl_Release
01534  ******************************************************************************/
01535 static ULONG WINAPI
01536 EnumMonikerImpl_Release(IEnumMoniker* iface)
01537 {
01538     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
01539     ULONG i;
01540     ULONG ref;
01541     TRACE("(%p)\n",This);
01542 
01543     ref = InterlockedDecrement(&This->ref);
01544 
01545     /* destroy the object if there's no more reference on it */
01546     if (ref == 0) {
01547 
01548         for(i=0;i<This->tabSize;i++)
01549             IMoniker_Release(This->tabMoniker[i]);
01550 
01551         HeapFree(GetProcessHeap(),0,This->tabMoniker);
01552         HeapFree(GetProcessHeap(),0,This);
01553     }
01554     return ref;
01555 }
01556 
01557 /******************************************************************************
01558  *        EnumMonikerImpl_Next
01559  ******************************************************************************/
01560 static HRESULT WINAPI
01561 EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt,
01562                ULONG* pceltFethed)
01563 {
01564     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
01565     ULONG i;
01566 
01567     /* retrieve the requested number of moniker from the current position */
01568     for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
01569     {
01570         rgelt[i]=This->tabMoniker[This->currentPos++];
01571         IMoniker_AddRef(rgelt[i]);
01572     }
01573 
01574     if (pceltFethed!=NULL)
01575         *pceltFethed= i;
01576 
01577     if (i==celt)
01578         return S_OK;
01579     else
01580         return S_FALSE;
01581 }
01582 
01583 /******************************************************************************
01584  *        EnumMonikerImpl_Skip
01585  ******************************************************************************/
01586 static HRESULT WINAPI
01587 EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt)
01588 {
01589     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
01590 
01591     if ((This->currentPos+celt) >= This->tabSize)
01592         return S_FALSE;
01593 
01594     This->currentPos+=celt;
01595 
01596     return S_OK;
01597 }
01598 
01599 /******************************************************************************
01600  *        EnumMonikerImpl_Reset
01601  ******************************************************************************/
01602 static HRESULT WINAPI
01603 EnumMonikerImpl_Reset(IEnumMoniker* iface)
01604 {
01605     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
01606 
01607     This->currentPos=0;
01608 
01609     return S_OK;
01610 }
01611 
01612 /******************************************************************************
01613  *        EnumMonikerImpl_Clone
01614  ******************************************************************************/
01615 static HRESULT WINAPI
01616 EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum)
01617 {
01618     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
01619 
01620     return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
01621 }
01622 
01623 /********************************************************************************/
01624 /* Virtual function table for the IROTData class                                */
01625 static const IEnumMonikerVtbl VT_EnumMonikerImpl =
01626 {
01627     EnumMonikerImpl_QueryInterface,
01628     EnumMonikerImpl_AddRef,
01629     EnumMonikerImpl_Release,
01630     EnumMonikerImpl_Next,
01631     EnumMonikerImpl_Skip,
01632     EnumMonikerImpl_Reset,
01633     EnumMonikerImpl_Clone
01634 };
01635 
01636 /******************************************************************************
01637  *        EnumMonikerImpl_CreateEnumMoniker
01638  ******************************************************************************/
01639 static HRESULT
01640 EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker, ULONG tabSize,
01641                ULONG currentPos, BOOL leftToRigth, IEnumMoniker ** ppmk)
01642 {
01643     EnumMonikerImpl* newEnumMoniker;
01644     int i;
01645 
01646     if (currentPos > tabSize)
01647         return E_INVALIDARG;
01648 
01649     newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
01650 
01651     if (newEnumMoniker == 0)
01652         return STG_E_INSUFFICIENTMEMORY;
01653 
01654     /* Initialize the virtual function table. */
01655     newEnumMoniker->IEnumMoniker_iface.lpVtbl = &VT_EnumMonikerImpl;
01656     newEnumMoniker->ref          = 1;
01657 
01658     newEnumMoniker->tabSize=tabSize;
01659     newEnumMoniker->currentPos=currentPos;
01660 
01661     newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
01662 
01663     if (newEnumMoniker->tabMoniker==NULL) {
01664         HeapFree(GetProcessHeap(), 0, newEnumMoniker);
01665         return E_OUTOFMEMORY;
01666     }
01667 
01668     if (leftToRigth)
01669         for (i=0;i<tabSize;i++){
01670 
01671             newEnumMoniker->tabMoniker[i]=tabMoniker[i];
01672             IMoniker_AddRef(tabMoniker[i]);
01673         }
01674     else
01675         for (i=tabSize-1;i>=0;i--){
01676 
01677             newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
01678             IMoniker_AddRef(tabMoniker[i]);
01679         }
01680 
01681     *ppmk=&newEnumMoniker->IEnumMoniker_iface;
01682 
01683     return S_OK;
01684 }
01685 
01686 /********************************************************************************/
01687 /* Virtual function table for the CompositeMonikerImpl class which includes     */
01688 /* IPersist, IPersistStream and IMoniker functions.                             */
01689 
01690 static const IMonikerVtbl VT_CompositeMonikerImpl =
01691 {
01692     CompositeMonikerImpl_QueryInterface,
01693     CompositeMonikerImpl_AddRef,
01694     CompositeMonikerImpl_Release,
01695     CompositeMonikerImpl_GetClassID,
01696     CompositeMonikerImpl_IsDirty,
01697     CompositeMonikerImpl_Load,
01698     CompositeMonikerImpl_Save,
01699     CompositeMonikerImpl_GetSizeMax,
01700     CompositeMonikerImpl_BindToObject,
01701     CompositeMonikerImpl_BindToStorage,
01702     CompositeMonikerImpl_Reduce,
01703     CompositeMonikerImpl_ComposeWith,
01704     CompositeMonikerImpl_Enum,
01705     CompositeMonikerImpl_IsEqual,
01706     CompositeMonikerImpl_Hash,
01707     CompositeMonikerImpl_IsRunning,
01708     CompositeMonikerImpl_GetTimeOfLastChange,
01709     CompositeMonikerImpl_Inverse,
01710     CompositeMonikerImpl_CommonPrefixWith,
01711     CompositeMonikerImpl_RelativePathTo,
01712     CompositeMonikerImpl_GetDisplayName,
01713     CompositeMonikerImpl_ParseDisplayName,
01714     CompositeMonikerImpl_IsSystemMoniker
01715 };
01716 
01717 /********************************************************************************/
01718 /* Virtual function table for the IROTData class.                               */
01719 static const IROTDataVtbl VT_ROTDataImpl =
01720 {
01721     CompositeMonikerROTDataImpl_QueryInterface,
01722     CompositeMonikerROTDataImpl_AddRef,
01723     CompositeMonikerROTDataImpl_Release,
01724     CompositeMonikerROTDataImpl_GetComparisonData
01725 };
01726 
01727 static const IMarshalVtbl VT_MarshalImpl =
01728 {
01729     CompositeMonikerMarshalImpl_QueryInterface,
01730     CompositeMonikerMarshalImpl_AddRef,
01731     CompositeMonikerMarshalImpl_Release,
01732     CompositeMonikerMarshalImpl_GetUnmarshalClass,
01733     CompositeMonikerMarshalImpl_GetMarshalSizeMax,
01734     CompositeMonikerMarshalImpl_MarshalInterface,
01735     CompositeMonikerMarshalImpl_UnmarshalInterface,
01736     CompositeMonikerMarshalImpl_ReleaseMarshalData,
01737     CompositeMonikerMarshalImpl_DisconnectObject
01738 };
01739 
01740 /******************************************************************************
01741  *         Composite-Moniker_Construct (local function)
01742  *******************************************************************************/
01743 static HRESULT
01744 CompositeMonikerImpl_Construct(IMoniker **ppMoniker, IMoniker *pmkFirst, IMoniker *pmkRest)
01745 {
01746     DWORD mkSys;
01747     IEnumMoniker *enumMoniker;
01748     IMoniker *tempMk;
01749     HRESULT res;
01750     CompositeMonikerImpl *This;
01751 
01752     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
01753 
01754     if (!This)
01755         return E_OUTOFMEMORY;
01756 
01757     TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
01758 
01759     /* Initialize the virtual function table. */
01760     This->IMoniker_iface.lpVtbl = &VT_CompositeMonikerImpl;
01761     This->IROTData_iface.lpVtbl = &VT_ROTDataImpl;
01762     This->IMarshal_iface.lpVtbl = &VT_MarshalImpl;
01763     This->ref          = 1;
01764 
01765     This->tabSize=BLOCK_TAB_SIZE;
01766     This->tabLastIndex=0;
01767 
01768     This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
01769     if (This->tabMoniker==NULL) {
01770         HeapFree(GetProcessHeap(), 0, This);
01771         return E_OUTOFMEMORY;
01772     }
01773 
01774     if (!pmkFirst && !pmkRest)
01775     {
01776         *ppMoniker = &This->IMoniker_iface;
01777         return S_OK;
01778     }
01779 
01780     IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
01781 
01782     /* put the first moniker contents in the beginning of the table */
01783     if (mkSys!=MKSYS_GENERICCOMPOSITE){
01784 
01785         This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
01786         IMoniker_AddRef(pmkFirst);
01787     }
01788     else{
01789 
01790         IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
01791 
01792         while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
01793 
01794 
01795             if (++This->tabLastIndex==This->tabSize){
01796                 LPVOID tab_moniker = This->tabMoniker;
01797 
01798                 This->tabSize+=BLOCK_TAB_SIZE;
01799                 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
01800 
01801                 if (This->tabMoniker==NULL){
01802                     HeapFree(GetProcessHeap(), 0, tab_moniker);
01803                     HeapFree(GetProcessHeap(), 0, This);
01804                     return E_OUTOFMEMORY;
01805                 }
01806             }
01807         }
01808 
01809         IEnumMoniker_Release(enumMoniker);
01810     }
01811 
01812     /* put the rest moniker contents after the first one and make simplification if needed */
01813 
01814     IMoniker_IsSystemMoniker(pmkRest,&mkSys);
01815 
01816     if (mkSys!=MKSYS_GENERICCOMPOSITE){
01817 
01818         /* add a simple moniker to the moniker table */
01819 
01820         res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
01821 
01822         if (res==MK_E_NEEDGENERIC){
01823 
01824             /* there's no simplification in this case */
01825             This->tabMoniker[This->tabLastIndex]=pmkRest;
01826 
01827             This->tabLastIndex++;
01828 
01829             IMoniker_AddRef(pmkRest);
01830         }
01831         else if (tempMk==NULL){
01832 
01833             /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
01834             IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
01835 
01836             This->tabLastIndex--;
01837         }
01838         else if (SUCCEEDED(res)){
01839 
01840             /* the non-generic composition was successful so we can make a simplification in this case */
01841             IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
01842 
01843             This->tabMoniker[This->tabLastIndex-1]=tempMk;
01844         } else
01845             return res;
01846 
01847         /* resize tabMoniker if needed */
01848         if (This->tabLastIndex==This->tabSize){
01849             LPVOID tab_moniker = This->tabMoniker;
01850 
01851             This->tabSize+=BLOCK_TAB_SIZE;
01852 
01853             This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
01854 
01855             if (This->tabMoniker==NULL){
01856                 HeapFree(GetProcessHeap(), 0, tab_moniker);
01857                 HeapFree(GetProcessHeap(), 0, This);
01858                 return E_OUTOFMEMORY;
01859             }
01860         }
01861     }
01862     else{
01863 
01864         /* add a composite moniker to the moniker table (do the same thing
01865          * for each moniker within the composite moniker as a simple moniker
01866          * (see above for how to add a simple moniker case) )
01867          */
01868         IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
01869 
01870         while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
01871 
01872             res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
01873 
01874             if (res==MK_E_NEEDGENERIC){
01875 
01876                 This->tabLastIndex++;
01877             }
01878             else if (tempMk==NULL){
01879 
01880                 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
01881                 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
01882                 This->tabLastIndex--;
01883             }
01884             else{
01885 
01886                 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
01887 
01888                 This->tabMoniker[This->tabLastIndex-1]=tempMk;
01889             }
01890 
01891             if (This->tabLastIndex==This->tabSize){
01892                 LPVOID tab_moniker = This->tabMoniker;
01893 
01894                 This->tabSize+=BLOCK_TAB_SIZE;
01895 
01896                 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
01897 
01898                 if (This->tabMoniker==NULL){
01899                     HeapFree(GetProcessHeap(), 0, tab_moniker);
01900                     HeapFree(GetProcessHeap(), 0, This);
01901                     return E_OUTOFMEMORY;
01902                 }
01903             }
01904         }
01905 
01906         IEnumMoniker_Release(enumMoniker);
01907     }
01908 
01909     /* only one moniker, then just return it */
01910     if (This->tabLastIndex == 1)
01911     {
01912         *ppMoniker = This->tabMoniker[0];
01913         IMoniker_AddRef(*ppMoniker);
01914         IMoniker_Release(&This->IMoniker_iface);
01915     }
01916     else
01917         *ppMoniker = &This->IMoniker_iface;
01918 
01919     return S_OK;
01920 }
01921 
01922 /******************************************************************************
01923  *        CreateGenericComposite    [OLE32.@]
01924  ******************************************************************************/
01925 HRESULT WINAPI
01926 CreateGenericComposite(IMoniker *pmkFirst, IMoniker *pmkRest, IMoniker **ppmkComposite)
01927 {
01928     IMoniker* moniker = 0;
01929     HRESULT        hr = S_OK;
01930 
01931     TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
01932 
01933     if (ppmkComposite==NULL)
01934         return E_POINTER;
01935 
01936     *ppmkComposite=0;
01937 
01938     if (pmkFirst==NULL && pmkRest!=NULL){
01939 
01940         *ppmkComposite=pmkRest;
01941         return S_OK;
01942     }
01943     else if (pmkFirst!=NULL && pmkRest==NULL){
01944         *ppmkComposite=pmkFirst;
01945         return S_OK;
01946     }
01947     else  if (pmkFirst==NULL && pmkRest==NULL)
01948         return S_OK;
01949 
01950     hr = CompositeMonikerImpl_Construct(&moniker,pmkFirst,pmkRest);
01951 
01952     if (FAILED(hr))
01953         return hr;
01954 
01955     hr = IMoniker_QueryInterface(moniker,&IID_IMoniker,(void**)ppmkComposite);
01956     IMoniker_Release(moniker);
01957 
01958     return hr;
01959 }
01960 
01961 /******************************************************************************
01962  *        MonikerCommonPrefixWith   [OLE32.@]
01963  ******************************************************************************/
01964 HRESULT WINAPI
01965 MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
01966 {
01967     FIXME("(),stub!\n");
01968     return E_NOTIMPL;
01969 }
01970 
01971 static HRESULT WINAPI CompositeMonikerCF_QueryInterface(LPCLASSFACTORY iface,
01972                                                   REFIID riid, LPVOID *ppv)
01973 {
01974     *ppv = NULL;
01975     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
01976     {
01977         *ppv = iface;
01978         IUnknown_AddRef(iface);
01979         return S_OK;
01980     }
01981     return E_NOINTERFACE;
01982 }
01983 
01984 static ULONG WINAPI CompositeMonikerCF_AddRef(LPCLASSFACTORY iface)
01985 {
01986     return 2; /* non-heap based object */
01987 }
01988 
01989 static ULONG WINAPI CompositeMonikerCF_Release(LPCLASSFACTORY iface)
01990 {
01991     return 1; /* non-heap based object */
01992 }
01993 
01994 static HRESULT WINAPI CompositeMonikerCF_CreateInstance(LPCLASSFACTORY iface,
01995     LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
01996 {
01997     IMoniker* pMoniker;
01998     HRESULT  hr;
01999 
02000     TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
02001 
02002     *ppv = NULL;
02003 
02004     if (pUnk)
02005         return CLASS_E_NOAGGREGATION;
02006 
02007     hr = CompositeMonikerImpl_Construct(&pMoniker, NULL, NULL);
02008 
02009     if (SUCCEEDED(hr))
02010     {
02011         hr = IMoniker_QueryInterface(pMoniker, riid, ppv);
02012         IMoniker_Release(pMoniker);
02013     }
02014 
02015     return hr;
02016 }
02017 
02018 static HRESULT WINAPI CompositeMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
02019 {
02020     FIXME("(%d), stub!\n",fLock);
02021     return S_OK;
02022 }
02023 
02024 static const IClassFactoryVtbl CompositeMonikerCFVtbl =
02025 {
02026     CompositeMonikerCF_QueryInterface,
02027     CompositeMonikerCF_AddRef,
02028     CompositeMonikerCF_Release,
02029     CompositeMonikerCF_CreateInstance,
02030     CompositeMonikerCF_LockServer
02031 };
02032 static const IClassFactoryVtbl *CompositeMonikerCF = &CompositeMonikerCFVtbl;
02033 
02034 HRESULT CompositeMonikerCF_Create(REFIID riid, LPVOID *ppv)
02035 {
02036     return IClassFactory_QueryInterface((IClassFactory *)&CompositeMonikerCF, riid, ppv);
02037 }

Generated on Sun May 27 2012 04:25:35 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.