Don't test i386 types on non i386.
[wine/multimedia.git] / dlls / ole32 / compositemoniker.c
blob6cc0c63e533bdff5c2d997418431a0a4e9b84735
1 /*
2 * CompositeMonikers implementation
4 * Copyright 1999 Noomen Hamza
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <string.h>
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winerror.h"
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
33 #include "ole2.h"
34 #include "moniker.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ole);
38 const CLSID CLSID_CompositeMoniker = {
39 0x309, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
42 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
44 /* CompositeMoniker data structure */
45 typedef struct CompositeMonikerImpl{
47 ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/
49 /* The ROT (RunningObjectTable implementation) uses the IROTData
50 * interface to test whether two monikers are equal. That's why IROTData
51 * interface is implemented by monikers.
53 ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/
55 ULONG ref; /* reference counter for this object */
57 IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */
59 ULONG tabSize; /* size of tabMoniker */
61 ULONG tabLastIndex; /* first free index in tabMoniker */
63 } CompositeMonikerImpl;
66 /* EnumMoniker data structure */
67 typedef struct EnumMonikerImpl{
69 ICOM_VFIELD(IEnumMoniker); /* VTable relative to the IEnumMoniker interface.*/
71 ULONG ref; /* reference counter for this object */
73 IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
75 ULONG tabSize; /* size of tabMoniker */
77 ULONG currentPos; /* index pointer on the current moniker */
79 } EnumMonikerImpl;
82 /********************************************************************************/
83 /* CompositeMoniker prototype functions : */
85 /* IUnknown prototype functions */
86 static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
87 static ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface);
88 static ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface);
90 /* IPersist prototype functions */
91 static HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
93 /* IPersistStream prototype functions */
94 static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface);
95 static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm);
96 static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
97 static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
99 /* IMoniker prototype functions */
100 static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
101 static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
102 static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
103 static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
104 static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
105 static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
106 static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
107 static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
108 static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime);
109 static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
110 static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
111 static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
112 static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
113 static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
114 static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
116 /********************************************************************************/
117 /* IROTData prototype functions */
119 /* IUnknown prototype functions */
120 static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
121 static ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface);
122 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface);
124 /* IROTData prototype function */
125 static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
127 /* Local function used by CompositeMoniker implementation */
128 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest);
129 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface);
131 /********************************************************************************/
132 /* IEnumMoniker prototype functions */
134 /* IUnknown prototype functions */
135 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject);
136 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface);
137 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface);
139 /* IEnumMoniker prototype functions */
140 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched);
141 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt);
142 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface);
143 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum);
145 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
147 /********************************************************************************/
148 /* Virtual function table for the CompositeMonikerImpl class which includes */
149 /* IPersist, IPersistStream and IMoniker functions. */
151 static ICOM_VTABLE(IMoniker) VT_CompositeMonikerImpl =
153 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
154 CompositeMonikerImpl_QueryInterface,
155 CompositeMonikerImpl_AddRef,
156 CompositeMonikerImpl_Release,
157 CompositeMonikerImpl_GetClassID,
158 CompositeMonikerImpl_IsDirty,
159 CompositeMonikerImpl_Load,
160 CompositeMonikerImpl_Save,
161 CompositeMonikerImpl_GetSizeMax,
162 CompositeMonikerImpl_BindToObject,
163 CompositeMonikerImpl_BindToStorage,
164 CompositeMonikerImpl_Reduce,
165 CompositeMonikerImpl_ComposeWith,
166 CompositeMonikerImpl_Enum,
167 CompositeMonikerImpl_IsEqual,
168 CompositeMonikerImpl_Hash,
169 CompositeMonikerImpl_IsRunning,
170 CompositeMonikerImpl_GetTimeOfLastChange,
171 CompositeMonikerImpl_Inverse,
172 CompositeMonikerImpl_CommonPrefixWith,
173 CompositeMonikerImpl_RelativePathTo,
174 CompositeMonikerImpl_GetDisplayName,
175 CompositeMonikerImpl_ParseDisplayName,
176 CompositeMonikerImpl_IsSystemMoniker
179 /********************************************************************************/
180 /* Virtual function table for the IROTData class. */
181 static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
183 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
184 CompositeMonikerROTDataImpl_QueryInterface,
185 CompositeMonikerROTDataImpl_AddRef,
186 CompositeMonikerROTDataImpl_Release,
187 CompositeMonikerROTDataImpl_GetComparaisonData
190 /********************************************************************************/
191 /* Virtual function table for the IROTData class */
192 static ICOM_VTABLE(IEnumMoniker) VT_EnumMonikerImpl =
194 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
195 EnumMonikerImpl_QueryInterface,
196 EnumMonikerImpl_AddRef,
197 EnumMonikerImpl_Release,
198 EnumMonikerImpl_Next,
199 EnumMonikerImpl_Skip,
200 EnumMonikerImpl_Reset,
201 EnumMonikerImpl_Clone
204 /*******************************************************************************
205 * CompositeMoniker_QueryInterface
206 *******************************************************************************/
207 HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
209 ICOM_THIS(CompositeMonikerImpl,iface);
211 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
213 /* Perform a sanity check on the parameters.*/
214 if ( (This==0) || (ppvObject==0) )
215 return E_INVALIDARG;
217 /* Initialize the return parameter */
218 *ppvObject = 0;
220 /* Compare the riid with the interface IDs implemented by this object.*/
221 if (IsEqualIID(&IID_IUnknown, riid) ||
222 IsEqualIID(&IID_IPersist, riid) ||
223 IsEqualIID(&IID_IPersistStream, riid) ||
224 IsEqualIID(&IID_IMoniker, riid)
226 *ppvObject = iface;
227 else if (IsEqualIID(&IID_IROTData, riid))
228 *ppvObject = (IROTData*)&(This->lpvtbl2);
230 /* Check that we obtained an interface.*/
231 if ((*ppvObject)==0)
232 return E_NOINTERFACE;
234 /* Query Interface always increases the reference count by one when it is successful */
235 CompositeMonikerImpl_AddRef(iface);
237 return S_OK;
240 /******************************************************************************
241 * CompositeMoniker_AddRef
242 ******************************************************************************/
243 ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)
245 ICOM_THIS(CompositeMonikerImpl,iface);
247 TRACE("(%p)\n",This);
249 return ++(This->ref);
252 /******************************************************************************
253 * CompositeMoniker_Release
254 ******************************************************************************/
255 ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
257 ICOM_THIS(CompositeMonikerImpl,iface);
258 ULONG i;
260 TRACE("(%p)\n",This);
262 This->ref--;
264 /* destroy the object if there's no more reference on it */
265 if (This->ref==0){
267 /* release all the components before destroying this object */
268 for (i=0;i<This->tabLastIndex;i++)
269 IMoniker_Release(This->tabMoniker[i]);
271 CompositeMonikerImpl_Destroy(This);
273 return 0;
275 return This->ref;
278 /******************************************************************************
279 * CompositeMoniker_GetClassID
280 ******************************************************************************/
281 HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
283 TRACE("(%p,%p),stub!\n",iface,pClassID);
285 if (pClassID==NULL)
286 return E_POINTER;
288 *pClassID = CLSID_CompositeMoniker;
290 return S_OK;
293 /******************************************************************************
294 * CompositeMoniker_IsDirty
295 ******************************************************************************/
296 HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)
298 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
299 method in the OLE-provided moniker interfaces always return S_FALSE because
300 their internal state never changes. */
302 TRACE("(%p)\n",iface);
304 return S_FALSE;
307 /******************************************************************************
308 * CompositeMoniker_Load
309 ******************************************************************************/
310 HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
312 HRESULT res;
313 DWORD constant;
314 CLSID clsid;
315 WCHAR string[1]={0};
317 ICOM_THIS(CompositeMonikerImpl,iface);
319 TRACE("(%p,%p)\n",iface,pStm);
321 /* this function call OleLoadFromStream function for each moniker within this object */
323 /* read the a constant written by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
324 res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
326 if (SUCCEEDED(res)&& constant!=3)
327 return E_FAIL;
329 while(1){
330 #if 0
331 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
332 #endif
333 res=ReadClassStm(pStm,&clsid);
334 DPRINTF("res=%ld",res);
335 if (FAILED(res))
336 break;
338 if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
339 res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
340 if (FAILED(res))
341 break;
342 res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
343 if (FAILED(res))
344 break;
346 else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
347 CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
348 if (res!=S_OK)
349 break;
350 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
351 if (FAILED(res))
352 break;
354 else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
355 CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
356 if (FAILED(res))
357 break;
358 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
359 if (FAILED(res))
360 break;
362 else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
363 return E_FAIL;
365 else
367 FIXME("()\n");
368 /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */
369 break;
370 return E_NOTIMPL;
373 /* resize the table if needed */
374 if (++This->tabLastIndex==This->tabSize){
376 This->tabSize+=BLOCK_TAB_SIZE;
377 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
379 if (This->tabMoniker==NULL)
380 return E_OUTOFMEMORY;
384 return res;
387 /******************************************************************************
388 * CompositeMoniker_Save
389 ******************************************************************************/
390 HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
392 HRESULT res;
393 IEnumMoniker *enumMk;
394 IMoniker *pmk;
395 DWORD constant=3;
397 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
399 /* This function calls OleSaveToStream function for each moniker within
400 * this object.
401 * When I tested this function in windows, I usually found this constant
402 * at the beginning of the stream. I don't known why (there's no
403 * indication in the specification) !
405 res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
407 IMoniker_Enum(iface,TRUE,&enumMk);
409 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
411 res=OleSaveToStream((IPersistStream*)pmk,pStm);
413 IMoniker_Release(pmk);
415 if (FAILED(res)){
417 IEnumMoniker_Release(pmk);
418 return res;
422 IEnumMoniker_Release(enumMk);
424 return S_OK;
427 /******************************************************************************
428 * CompositeMoniker_GetSizeMax
429 ******************************************************************************/
430 HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
432 IEnumMoniker *enumMk;
433 IMoniker *pmk;
434 ULARGE_INTEGER ptmpSize;
436 /* The sizeMax of this object is calculated by calling GetSizeMax on
437 * each moniker within this object then summing all returned values
440 TRACE("(%p,%p)\n",iface,pcbSize);
442 if (pcbSize!=NULL)
443 return E_POINTER;
445 pcbSize->u.LowPart =0;
446 pcbSize->u.HighPart=0;
448 IMoniker_Enum(iface,TRUE,&enumMk);
450 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){
452 IMoniker_GetSizeMax(pmk,&ptmpSize);
454 IMoniker_Release(pmk);
456 pcbSize->u.LowPart +=ptmpSize.u.LowPart;
457 pcbSize->u.HighPart+=ptmpSize.u.HighPart;
460 IEnumMoniker_Release(enumMk);
462 return S_OK;
465 /******************************************************************************
466 * Composite-Moniker_Construct (local function)
467 *******************************************************************************/
468 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest)
470 DWORD mkSys;
471 IEnumMoniker *enumMoniker;
472 IMoniker *tempMk;
473 HRESULT res;
475 TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
477 /* Initialize the virtual function table. */
478 This->lpvtbl1 = &VT_CompositeMonikerImpl;
479 This->lpvtbl2 = &VT_ROTDataImpl;
480 This->ref = 0;
482 This->tabSize=BLOCK_TAB_SIZE;
483 This->tabLastIndex=0;
485 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
486 if (This->tabMoniker==NULL)
487 return E_OUTOFMEMORY;
489 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
491 /* put the first moniker contents in the beginning of the table */
492 if (mkSys!=MKSYS_GENERICCOMPOSITE){
494 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
495 IMoniker_AddRef(pmkFirst);
497 else{
499 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
501 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
504 if (++This->tabLastIndex==This->tabSize){
506 This->tabSize+=BLOCK_TAB_SIZE;
507 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
509 if (This->tabMoniker==NULL)
510 return E_OUTOFMEMORY;
514 IEnumMoniker_Release(enumMoniker);
517 /* put the rest moniker contents after the first one and make simplification if needed */
519 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
521 if (mkSys!=MKSYS_GENERICCOMPOSITE){
523 /* add a simple moniker to the moniker table */
525 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
527 if (res==MK_E_NEEDGENERIC){
529 /* there's no simplification in this case */
530 This->tabMoniker[This->tabLastIndex]=pmkRest;
532 This->tabLastIndex++;
534 IMoniker_AddRef(pmkRest);
536 else if (tempMk==NULL){
538 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
539 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
541 This->tabLastIndex--;
543 else if (SUCCEEDED(res)){
545 /* the non-generic composition was successful so we can make a simplification in this case */
546 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
548 This->tabMoniker[This->tabLastIndex-1]=tempMk;
549 } else
550 return res;
552 /* resize tabMoniker if needed */
553 if (This->tabLastIndex==This->tabSize){
555 This->tabSize+=BLOCK_TAB_SIZE;
557 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
559 if (This->tabMoniker==NULL)
560 return E_OUTOFMEMORY;
563 else{
565 /* add a composite moniker to the moniker table (do the same thing
566 * for each moniker within the composite moniker as a simple moniker
567 * (see above for how to add a simple moniker case) )
569 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
571 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
573 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
575 if (res==MK_E_NEEDGENERIC){
577 This->tabLastIndex++;
579 else if (tempMk==NULL){
581 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
582 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
583 This->tabLastIndex--;
585 else{
587 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
589 This->tabMoniker[This->tabLastIndex-1]=tempMk;
592 if (This->tabLastIndex==This->tabSize){
594 This->tabSize+=BLOCK_TAB_SIZE;
596 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
598 if (This->tabMoniker==NULL)
599 return E_OUTOFMEMORY;
603 IEnumMoniker_Release(enumMoniker);
606 return S_OK;
609 /******************************************************************************
610 * CompositeMoniker_Destroy (local function)
611 *******************************************************************************/
612 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This)
614 TRACE("(%p)\n",This);
616 HeapFree(GetProcessHeap(),0,This->tabMoniker);
618 HeapFree(GetProcessHeap(),0,This);
620 return S_OK;
623 /******************************************************************************
624 * CompositeMoniker_BindToObject
625 ******************************************************************************/
626 HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,
627 IBindCtx* pbc,
628 IMoniker* pmkToLeft,
629 REFIID riid,
630 VOID** ppvResult)
632 HRESULT res;
633 IRunningObjectTable *prot;
634 IMoniker *tempMk,*antiMk,*mostRigthMk;
635 IEnumMoniker *enumMoniker;
637 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
639 if (ppvResult==NULL)
640 return E_POINTER;
642 *ppvResult=0;
643 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
644 /* object for the requested interface pointer. */
645 if(pmkToLeft==NULL){
647 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
649 if (SUCCEEDED(res)){
651 /* if the requested class was loaded before ! we don't need to reload it */
652 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
654 if (res==S_OK)
655 return res;
658 else{
659 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
660 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
662 IMoniker_Enum(iface,FALSE,&enumMoniker);
663 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
664 IEnumMoniker_Release(enumMoniker);
666 res=CreateAntiMoniker(&antiMk);
667 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
668 IMoniker_Release(antiMk);
670 res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
672 IMoniker_Release(tempMk);
673 IMoniker_Release(mostRigthMk);
676 return res;
679 /******************************************************************************
680 * CompositeMoniker_BindToStorage
681 ******************************************************************************/
682 HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,
683 IBindCtx* pbc,
684 IMoniker* pmkToLeft,
685 REFIID riid,
686 VOID** ppvResult)
688 HRESULT res;
689 IMoniker *tempMk,*antiMk,*mostRigthMk;
690 IEnumMoniker *enumMoniker;
692 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
694 *ppvResult=0;
696 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
697 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
699 if (pmkToLeft!=NULL){
701 IMoniker_Enum(iface,FALSE,&enumMoniker);
702 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
703 IEnumMoniker_Release(enumMoniker);
705 res=CreateAntiMoniker(&antiMk);
706 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
707 IMoniker_Release(antiMk);
709 res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
711 IMoniker_Release(tempMk);
713 IMoniker_Release(mostRigthMk);
715 return res;
717 else
718 return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
721 /******************************************************************************
722 * CompositeMoniker_Reduce
723 ******************************************************************************/
724 HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,
725 IBindCtx* pbc,
726 DWORD dwReduceHowFar,
727 IMoniker** ppmkToLeft,
728 IMoniker** ppmkReduced)
730 HRESULT res;
731 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
732 IEnumMoniker *enumMoniker;
734 TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
736 if (ppmkReduced==NULL)
737 return E_POINTER;
739 /* This method recursively calls Reduce for each of its component monikers. */
741 if (ppmkToLeft==NULL){
743 IMoniker_Enum(iface,FALSE,&enumMoniker);
744 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
745 IEnumMoniker_Release(enumMoniker);
747 res=CreateAntiMoniker(&antiMk);
748 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
749 IMoniker_Release(antiMk);
751 return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
753 else if (*ppmkToLeft==NULL)
755 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
757 else{
759 /* separate the composite moniker in to left and right moniker */
760 IMoniker_Enum(iface,FALSE,&enumMoniker);
761 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
762 IEnumMoniker_Release(enumMoniker);
764 res=CreateAntiMoniker(&antiMk);
765 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
766 IMoniker_Release(antiMk);
768 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
769 /* of the reduced components */
770 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
771 CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
774 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
776 else{
777 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
779 IMoniker_AddRef(iface);
781 *ppmkReduced=iface;
783 return MK_S_REDUCED_TO_SELF;
788 /******************************************************************************
789 * CompositeMoniker_ComposeWith
790 ******************************************************************************/
791 HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,
792 IMoniker* pmkRight,
793 BOOL fOnlyIfNotGeneric,
794 IMoniker** ppmkComposite)
796 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
798 if ((ppmkComposite==NULL)||(pmkRight==NULL))
799 return E_POINTER;
801 *ppmkComposite=0;
803 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
804 /* otherwise, the method returns the result of combining the two monikers by calling the */
805 /* CreateGenericComposite function */
807 if (fOnlyIfNotGeneric)
808 return MK_E_NEEDGENERIC;
810 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
813 /******************************************************************************
814 * CompositeMoniker_Enum
815 ******************************************************************************/
816 HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
818 ICOM_THIS(CompositeMonikerImpl,iface);
820 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
822 if (ppenumMoniker == NULL)
823 return E_POINTER;
825 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
828 /******************************************************************************
829 * CompositeMoniker_IsEqual
830 ******************************************************************************/
831 HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
833 IEnumMoniker *enumMoniker1,*enumMoniker2;
834 IMoniker *tempMk1,*tempMk2;
835 HRESULT res1,res2,res;
837 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
839 if (pmkOtherMoniker==NULL)
840 return S_FALSE;
842 /* This method returns S_OK if the components of both monikers are equal when compared in the */
843 /* left-to-right order.*/
844 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
846 if (enumMoniker1==NULL)
847 return S_FALSE;
849 IMoniker_Enum(iface,TRUE,&enumMoniker2);
851 while(1){
853 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
854 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
856 if((res1==S_OK)&&(res2==S_OK)){
858 if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
859 res= S_FALSE;
860 break;
862 else
863 continue;
865 else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
866 res = S_OK;
867 break;
869 else{
870 res = S_FALSE;
871 break;
874 if (res1==S_OK)
875 IMoniker_Release(tempMk1);
877 if (res2==S_OK)
878 IMoniker_Release(tempMk2);
881 IEnumMoniker_Release(enumMoniker1);
882 IEnumMoniker_Release(enumMoniker2);
884 return res;
886 /******************************************************************************
887 * CompositeMoniker_Hash
888 ******************************************************************************/
889 HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
891 FIXME("(),stub!\n");
893 return E_NOTIMPL;
896 /******************************************************************************
897 * CompositeMoniker_IsRunning
898 ******************************************************************************/
899 HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,
900 IBindCtx* pbc,
901 IMoniker* pmkToLeft,
902 IMoniker* pmkNewlyRunning)
904 IRunningObjectTable* rot;
905 HRESULT res;
906 IMoniker *tempMk,*antiMk,*mostRigthMk;
907 IEnumMoniker *enumMoniker;
909 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
911 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
912 if (pmkToLeft!=NULL){
914 CreateGenericComposite(pmkToLeft,iface,&tempMk);
916 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
918 IMoniker_Release(tempMk);
920 return res;
922 else
923 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
924 /* to this moniker */
926 if (pmkNewlyRunning!=NULL)
928 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
929 return S_OK;
931 else
932 return S_FALSE;
934 else{
936 if (pbc==NULL)
937 return E_POINTER;
939 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
940 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
941 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
942 /* the composite as the pmkToLeft parameter for that call. */
944 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
946 if (FAILED(res))
947 return res;
949 res = IRunningObjectTable_IsRunning(rot,iface);
950 IRunningObjectTable_Release(rot);
952 if(res==S_OK)
953 return S_OK;
955 else{
957 IMoniker_Enum(iface,FALSE,&enumMoniker);
958 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
959 IEnumMoniker_Release(enumMoniker);
961 res=CreateAntiMoniker(&antiMk);
962 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
963 IMoniker_Release(antiMk);
965 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
967 IMoniker_Release(tempMk);
968 IMoniker_Release(mostRigthMk);
970 return res;
975 /******************************************************************************
976 * CompositeMoniker_GetTimeOfLastChange
977 ******************************************************************************/
978 HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
979 IBindCtx* pbc,
980 IMoniker* pmkToLeft,
981 FILETIME* pCompositeTime)
983 IRunningObjectTable* rot;
984 HRESULT res;
985 IMoniker *tempMk,*antiMk,*mostRigthMk;
986 IEnumMoniker *enumMoniker;
988 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
990 if (pCompositeTime==NULL)
991 return E_INVALIDARG;
993 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
994 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
995 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
996 /* of the composite as the pmkToLeft parameter for that call. */
997 if (pmkToLeft!=NULL){
999 res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
1001 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
1003 if (FAILED(res))
1004 return res;
1006 if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
1007 return res;
1008 else
1010 IMoniker_Enum(iface,FALSE,&enumMoniker);
1011 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1012 IEnumMoniker_Release(enumMoniker);
1014 res=CreateAntiMoniker(&antiMk);
1015 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1016 IMoniker_Release(antiMk);
1018 res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
1020 IMoniker_Release(tempMk);
1021 IMoniker_Release(mostRigthMk);
1023 return res;
1025 else
1026 return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
1029 /******************************************************************************
1030 * CompositeMoniker_Inverse
1031 ******************************************************************************/
1032 HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
1034 HRESULT res;
1035 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
1036 IEnumMoniker *enumMoniker;
1038 TRACE("(%p,%p)\n",iface,ppmk);
1040 if (ppmk==NULL)
1041 return E_POINTER;
1043 /* This method returns a composite moniker that consists of the inverses of each of the components */
1044 /* of the original composite, stored in reverse order */
1046 res=CreateAntiMoniker(&antiMk);
1047 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1048 IMoniker_Release(antiMk);
1050 if (tempMk==NULL)
1052 return IMoniker_Inverse(iface,ppmk);
1054 else{
1056 IMoniker_Enum(iface,FALSE,&enumMoniker);
1057 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1058 IEnumMoniker_Release(enumMoniker);
1060 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
1061 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
1063 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
1065 IMoniker_Release(tempMk);
1066 IMoniker_Release(mostRigthMk);
1067 IMoniker_Release(tempInvMk);
1068 IMoniker_Release(mostRigthInvMk);
1070 return res;
1074 /******************************************************************************
1075 * CompositeMoniker_CommonPrefixWith
1076 ******************************************************************************/
1077 HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1079 DWORD mkSys;
1080 HRESULT res1,res2;
1081 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
1082 IEnumMoniker *enumMoniker1,*enumMoniker2;
1083 ULONG i,nbCommonMk=0;
1085 /* If the other moniker is a composite, this method compares the components of each composite from left */
1086 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1087 /* of the leftmost components were common to both monikers. */
1089 if (ppmkPrefix==NULL)
1090 return E_POINTER;
1092 *ppmkPrefix=0;
1094 if (pmkOther==NULL)
1095 return MK_E_NOPREFIX;
1097 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1099 if((mkSys==MKSYS_GENERICCOMPOSITE)){
1101 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1102 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
1104 while(1){
1106 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1107 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
1109 if ((res1==S_FALSE) && (res2==S_FALSE)){
1111 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1112 *ppmkPrefix=iface;
1113 IMoniker_AddRef(iface);
1114 return MK_S_US;
1116 else if ((res1==S_OK) && (res2==S_OK)){
1118 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
1120 nbCommonMk++;
1122 else
1123 break;
1126 else if (res1==S_OK){
1128 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1129 /* ppmkPrefix to the other moniker. */
1130 *ppmkPrefix=pmkOther;
1131 return MK_S_HIM;
1133 else{
1134 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1135 /* to this moniker. */
1136 *ppmkPrefix=iface;
1137 return MK_S_ME;
1141 IEnumMoniker_Release(enumMoniker1);
1142 IEnumMoniker_Release(enumMoniker2);
1144 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1145 if (nbCommonMk==0)
1146 return MK_E_NOPREFIX;
1148 IEnumMoniker_Reset(enumMoniker1);
1150 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1152 /* if we have more than one commun moniker the result will be a composite moniker */
1153 if (nbCommonMk>1){
1155 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1156 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1157 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
1158 IMoniker_Release(tempMk1);
1159 IMoniker_Release(tempMk2);
1161 /* compose all common monikers in a composite moniker */
1162 for(i=0;i<nbCommonMk;i++){
1164 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1166 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
1168 IMoniker_Release(*ppmkPrefix);
1170 IMoniker_Release(tempMk1);
1172 *ppmkPrefix=tempMk2;
1174 return S_OK;
1176 else{
1177 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1178 *ppmkPrefix=tempMk1;
1180 return S_OK;
1183 else{
1184 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1185 of this moniker.*/
1187 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1189 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1191 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
1193 *ppmkPrefix=pmkOther;
1195 return MK_S_HIM;
1197 else
1198 return MK_E_NOPREFIX;
1201 /***************************************************************************************************
1202 * GetAfterCommonPrefix (local function)
1203 * This function returns a moniker that consist of the remainder when the common prefix is removed
1204 ***************************************************************************************************/
1205 VOID WINAPI GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
1207 IMoniker *tempMk,*tempMk1,*tempMk2;
1208 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
1209 ULONG nbRestMk=0;
1210 DWORD mkSys;
1211 HRESULT res1,res2;
1213 *restMk=0;
1215 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1216 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
1217 /* on the first difference. */
1218 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
1220 IMoniker_IsSystemMoniker(commonMk,&mkSys);
1222 if (mkSys==MKSYS_GENERICCOMPOSITE){
1224 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
1225 while(1){
1227 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1228 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
1230 if ((res1==S_FALSE)||(res2==S_FALSE)){
1232 if (res1==S_OK)
1234 nbRestMk++;
1236 IMoniker_Release(tempMk1);
1237 IMoniker_Release(tempMk1);
1239 break;
1241 IMoniker_Release(tempMk1);
1242 IMoniker_Release(tempMk1);
1245 else{
1246 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1247 IMoniker_Release(tempMk1);
1250 /* count the number of elements in the enumerator after the common prefix */
1251 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1253 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1255 IMoniker_Release(tempMk);
1257 if (nbRestMk==0)
1258 return;
1260 /* create a generic composite moniker with monikers located after the common prefix */
1261 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1263 if (nbRestMk==1){
1265 *restMk= tempMk1;
1266 return;
1268 else {
1270 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1272 CreateGenericComposite(tempMk1,tempMk2,restMk);
1274 IMoniker_Release(tempMk1);
1276 IMoniker_Release(tempMk2);
1278 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1280 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1282 IMoniker_Release(tempMk1);
1284 IMoniker_Release(*restMk);
1286 *restMk=tempMk2;
1290 /******************************************************************************
1291 * CompositeMoniker_RelativePathTo
1292 ******************************************************************************/
1293 HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkRelPath)
1295 HRESULT res;
1296 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1298 TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1300 if (ppmkRelPath==NULL)
1301 return E_POINTER;
1303 *ppmkRelPath=0;
1305 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1306 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1307 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1309 /* finds the common prefix of the two monikers */
1310 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1312 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1313 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1315 *ppmkRelPath=pmkOther;
1316 IMoniker_AddRef(pmkOther);
1317 return MK_S_HIM;
1320 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1321 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1323 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1324 /* moniker when the common prefix is removed */
1325 if (res==MK_S_HIM){
1327 IMoniker_Inverse(restThisMk,ppmkRelPath);
1328 IMoniker_Release(restThisMk);
1330 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1331 /* when the common prefix is removed */
1332 else if (res==MK_S_ME){
1334 *ppmkRelPath=restOtherMk;
1335 IMoniker_AddRef(restOtherMk);
1337 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1338 /* moniker on the right of it. */
1339 else if (res==S_OK){
1341 IMoniker_Inverse(restThisMk,&invRestThisMk);
1342 IMoniker_Release(restThisMk);
1343 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1344 IMoniker_Release(invRestThisMk);
1345 IMoniker_Release(restOtherMk);
1347 return S_OK;
1350 /******************************************************************************
1351 * CompositeMoniker_GetDisplayName
1352 ******************************************************************************/
1353 HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,
1354 IBindCtx* pbc,
1355 IMoniker* pmkToLeft,
1356 LPOLESTR *ppszDisplayName)
1358 ULONG lengthStr=1;
1359 IEnumMoniker *enumMoniker;
1360 IMoniker* tempMk;
1361 LPOLESTR tempStr;
1363 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1365 if (ppszDisplayName==NULL)
1366 return E_POINTER;
1368 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1370 if (*ppszDisplayName==NULL)
1371 return E_OUTOFMEMORY;
1373 /* This method returns the concatenation of the display names returned by each component moniker of */
1374 /* the composite */
1376 **ppszDisplayName=0;
1378 IMoniker_Enum(iface,TRUE,&enumMoniker);
1380 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1382 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1384 lengthStr+=lstrlenW(tempStr);
1386 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1388 if (*ppszDisplayName==NULL)
1389 return E_OUTOFMEMORY;
1391 strcatW(*ppszDisplayName,tempStr);
1393 CoTaskMemFree(tempStr);
1394 IMoniker_Release(tempMk);
1397 IEnumMoniker_Release(enumMoniker);
1399 return S_OK;
1402 /******************************************************************************
1403 * CompositeMoniker_ParseDisplayName
1404 ******************************************************************************/
1405 HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,
1406 IBindCtx* pbc,
1407 IMoniker* pmkToLeft,
1408 LPOLESTR pszDisplayName,
1409 ULONG* pchEaten,
1410 IMoniker** ppmkOut)
1412 IEnumMoniker *enumMoniker;
1413 IMoniker *tempMk,*mostRigthMk,*antiMk;
1414 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1415 /* passing everything else as the pmkToLeft parameter for that call. */
1417 /* get the most right moniker */
1418 IMoniker_Enum(iface,FALSE,&enumMoniker);
1419 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1420 IEnumMoniker_Release(enumMoniker);
1422 /* get the left moniker */
1423 CreateAntiMoniker(&antiMk);
1424 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1425 IMoniker_Release(antiMk);
1427 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1430 /******************************************************************************
1431 * CompositeMoniker_IsSystemMoniker
1432 ******************************************************************************/
1433 HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1435 TRACE("(%p,%p)\n",iface,pwdMksys);
1437 if (!pwdMksys)
1438 return E_POINTER;
1440 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1442 return S_OK;
1445 /*******************************************************************************
1446 * CompositeMonikerIROTData_QueryInterface
1447 *******************************************************************************/
1448 HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1451 ICOM_THIS_From_IROTData(IMoniker, iface);
1453 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
1455 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1458 /***********************************************************************
1459 * CompositeMonikerIROTData_AddRef
1461 ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1463 ICOM_THIS_From_IROTData(IMoniker, iface);
1465 TRACE("(%p)\n",iface);
1467 return CompositeMonikerImpl_AddRef(This);
1470 /***********************************************************************
1471 * CompositeMonikerIROTData_Release
1473 ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1475 ICOM_THIS_From_IROTData(IMoniker, iface);
1477 TRACE("(%p)\n",iface);
1479 return CompositeMonikerImpl_Release(This);
1482 /******************************************************************************
1483 * CompositeMonikerIROTData_GetComparaisonData
1484 ******************************************************************************/
1485 HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1486 BYTE* pbData,
1487 ULONG cbMax,
1488 ULONG* pcbData)
1490 FIXME("(),stub!\n");
1491 return E_NOTIMPL;
1494 /******************************************************************************
1495 * EnumMonikerImpl_QueryInterface
1496 ******************************************************************************/
1497 HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1499 ICOM_THIS(EnumMonikerImpl,iface);
1501 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1503 /* Perform a sanity check on the parameters.*/
1504 if ( (This==0) || (ppvObject==0) )
1505 return E_INVALIDARG;
1507 /* Initialize the return parameter */
1508 *ppvObject = 0;
1510 /* Compare the riid with the interface IDs implemented by this object.*/
1511 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1512 *ppvObject = iface;
1514 /* Check that we obtained an interface.*/
1515 if ((*ppvObject)==0)
1516 return E_NOINTERFACE;
1518 /* Query Interface always increases the reference count by one when it is successful */
1519 EnumMonikerImpl_AddRef(iface);
1521 return S_OK;
1524 /******************************************************************************
1525 * EnumMonikerImpl_AddRef
1526 ******************************************************************************/
1527 ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1529 ICOM_THIS(EnumMonikerImpl,iface);
1531 TRACE("(%p)\n",This);
1533 return ++(This->ref);
1537 /******************************************************************************
1538 * EnumMonikerImpl_Release
1539 ******************************************************************************/
1540 ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1542 ICOM_THIS(EnumMonikerImpl,iface);
1543 ULONG i
1545 TRACE("(%p)\n",This);
1547 This->ref--;
1549 /* destroy the object if there's no more reference on it */
1550 if (This->ref==0){
1552 for(i=0;i<This->tabSize;i++)
1553 IMoniker_Release(This->tabMoniker[i]);
1555 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1556 HeapFree(GetProcessHeap(),0,This);
1558 return 0;
1560 return This->ref;
1563 /******************************************************************************
1564 * EnumMonikerImpl_Next
1565 ******************************************************************************/
1566 HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){
1568 ICOM_THIS(EnumMonikerImpl,iface);
1569 ULONG i;
1571 /* retrieve the requested number of moniker from the current position */
1572 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1574 rgelt[i]=This->tabMoniker[This->currentPos++];
1576 if (pceltFethed!=NULL)
1577 *pceltFethed= i;
1579 if (i==celt)
1580 return S_OK;
1581 else
1582 return S_FALSE;
1585 /******************************************************************************
1586 * EnumMonikerImpl_Skip
1587 ******************************************************************************/
1588 HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){
1590 ICOM_THIS(EnumMonikerImpl,iface);
1592 if ((This->currentPos+celt) >= This->tabSize)
1593 return S_FALSE;
1595 This->currentPos+=celt;
1597 return S_OK;
1600 /******************************************************************************
1601 * EnumMonikerImpl_Reset
1602 ******************************************************************************/
1603 HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){
1605 ICOM_THIS(EnumMonikerImpl,iface);
1607 This->currentPos=0;
1609 return S_OK;
1612 /******************************************************************************
1613 * EnumMonikerImpl_Clone
1614 ******************************************************************************/
1615 HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){
1617 ICOM_THIS(EnumMonikerImpl,iface);
1619 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1622 /******************************************************************************
1623 * EnumMonikerImpl_CreateEnumMoniker
1624 ******************************************************************************/
1625 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,
1626 ULONG tabSize,
1627 ULONG currentPos,
1628 BOOL leftToRigth,
1629 IEnumMoniker ** ppmk)
1631 EnumMonikerImpl* newEnumMoniker;
1632 int i;
1635 if (currentPos > tabSize)
1636 return E_INVALIDARG;
1638 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1640 if (newEnumMoniker == 0)
1641 return STG_E_INSUFFICIENTMEMORY;
1643 /* Initialize the virtual function table. */
1644 newEnumMoniker->lpVtbl = &VT_EnumMonikerImpl;
1645 newEnumMoniker->ref = 0;
1647 newEnumMoniker->tabSize=tabSize;
1648 newEnumMoniker->currentPos=currentPos;
1650 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1652 if (newEnumMoniker->tabMoniker==NULL) {
1653 HeapFree(GetProcessHeap(), 0, newEnumMoniker);
1654 return E_OUTOFMEMORY;
1657 if (leftToRigth)
1658 for (i=0;i<tabSize;i++){
1660 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1661 IMoniker_AddRef(tabMoniker[i]);
1663 else
1664 for (i=tabSize-1;i>=0;i--){
1666 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1667 IMoniker_AddRef(tabMoniker[i]);
1670 *ppmk=(IEnumMoniker*)newEnumMoniker;
1672 return S_OK;
1675 /******************************************************************************
1676 * CreateGenericComposite [OLE32.@]
1677 ******************************************************************************/
1678 HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite)
1680 CompositeMonikerImpl* newCompositeMoniker = 0;
1681 HRESULT hr = S_OK;
1683 TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1685 if (ppmkComposite==NULL)
1686 return E_POINTER;
1688 *ppmkComposite=0;
1690 if (pmkFirst==NULL && pmkRest!=NULL){
1692 *ppmkComposite=pmkRest;
1693 return S_OK;
1695 else if (pmkFirst!=NULL && pmkRest==NULL){
1696 *ppmkComposite=pmkFirst;
1697 return S_OK;
1699 else if (pmkFirst==NULL && pmkRest==NULL)
1700 return S_OK;
1702 newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
1704 if (newCompositeMoniker == 0)
1705 return STG_E_INSUFFICIENTMEMORY;
1707 hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
1709 if (FAILED(hr)){
1711 HeapFree(GetProcessHeap(),0,newCompositeMoniker);
1712 return hr;
1714 if (newCompositeMoniker->tabLastIndex==1)
1716 hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
1717 else
1719 hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
1721 return hr;
1724 /******************************************************************************
1725 * MonikerCommonPrefixWith [OLE32.@]
1726 ******************************************************************************/
1727 HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1729 FIXME("(),stub!\n");
1730 return E_NOTIMPL;