Get rid of the no longer used ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
[wine/multimedia.git] / dlls / ole32 / compositemoniker.c
blob08cffcda700ca496fc710fe5972b96282759127e
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 IMonikerVtbl* 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 IROTDataVtbl* 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 IEnumMonikerVtbl *lpVtbl; /* 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 IMonikerVtbl VT_CompositeMonikerImpl =
153 CompositeMonikerImpl_QueryInterface,
154 CompositeMonikerImpl_AddRef,
155 CompositeMonikerImpl_Release,
156 CompositeMonikerImpl_GetClassID,
157 CompositeMonikerImpl_IsDirty,
158 CompositeMonikerImpl_Load,
159 CompositeMonikerImpl_Save,
160 CompositeMonikerImpl_GetSizeMax,
161 CompositeMonikerImpl_BindToObject,
162 CompositeMonikerImpl_BindToStorage,
163 CompositeMonikerImpl_Reduce,
164 CompositeMonikerImpl_ComposeWith,
165 CompositeMonikerImpl_Enum,
166 CompositeMonikerImpl_IsEqual,
167 CompositeMonikerImpl_Hash,
168 CompositeMonikerImpl_IsRunning,
169 CompositeMonikerImpl_GetTimeOfLastChange,
170 CompositeMonikerImpl_Inverse,
171 CompositeMonikerImpl_CommonPrefixWith,
172 CompositeMonikerImpl_RelativePathTo,
173 CompositeMonikerImpl_GetDisplayName,
174 CompositeMonikerImpl_ParseDisplayName,
175 CompositeMonikerImpl_IsSystemMoniker
178 /********************************************************************************/
179 /* Virtual function table for the IROTData class. */
180 static IROTDataVtbl VT_ROTDataImpl =
182 CompositeMonikerROTDataImpl_QueryInterface,
183 CompositeMonikerROTDataImpl_AddRef,
184 CompositeMonikerROTDataImpl_Release,
185 CompositeMonikerROTDataImpl_GetComparaisonData
188 /********************************************************************************/
189 /* Virtual function table for the IROTData class */
190 static IEnumMonikerVtbl VT_EnumMonikerImpl =
192 EnumMonikerImpl_QueryInterface,
193 EnumMonikerImpl_AddRef,
194 EnumMonikerImpl_Release,
195 EnumMonikerImpl_Next,
196 EnumMonikerImpl_Skip,
197 EnumMonikerImpl_Reset,
198 EnumMonikerImpl_Clone
201 /*******************************************************************************
202 * CompositeMoniker_QueryInterface
203 *******************************************************************************/
204 HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
206 ICOM_THIS(CompositeMonikerImpl,iface);
208 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
210 /* Perform a sanity check on the parameters.*/
211 if ( (This==0) || (ppvObject==0) )
212 return E_INVALIDARG;
214 /* Initialize the return parameter */
215 *ppvObject = 0;
217 /* Compare the riid with the interface IDs implemented by this object.*/
218 if (IsEqualIID(&IID_IUnknown, riid) ||
219 IsEqualIID(&IID_IPersist, riid) ||
220 IsEqualIID(&IID_IPersistStream, riid) ||
221 IsEqualIID(&IID_IMoniker, riid)
223 *ppvObject = iface;
224 else if (IsEqualIID(&IID_IROTData, riid))
225 *ppvObject = (IROTData*)&(This->lpvtbl2);
227 /* Check that we obtained an interface.*/
228 if ((*ppvObject)==0)
229 return E_NOINTERFACE;
231 /* Query Interface always increases the reference count by one when it is successful */
232 CompositeMonikerImpl_AddRef(iface);
234 return S_OK;
237 /******************************************************************************
238 * CompositeMoniker_AddRef
239 ******************************************************************************/
240 ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)
242 ICOM_THIS(CompositeMonikerImpl,iface);
244 TRACE("(%p)\n",This);
246 return ++(This->ref);
249 /******************************************************************************
250 * CompositeMoniker_Release
251 ******************************************************************************/
252 ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
254 ICOM_THIS(CompositeMonikerImpl,iface);
255 ULONG i;
257 TRACE("(%p)\n",This);
259 This->ref--;
261 /* destroy the object if there's no more reference on it */
262 if (This->ref==0){
264 /* release all the components before destroying this object */
265 for (i=0;i<This->tabLastIndex;i++)
266 IMoniker_Release(This->tabMoniker[i]);
268 CompositeMonikerImpl_Destroy(This);
270 return 0;
272 return This->ref;
275 /******************************************************************************
276 * CompositeMoniker_GetClassID
277 ******************************************************************************/
278 HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
280 TRACE("(%p,%p),stub!\n",iface,pClassID);
282 if (pClassID==NULL)
283 return E_POINTER;
285 *pClassID = CLSID_CompositeMoniker;
287 return S_OK;
290 /******************************************************************************
291 * CompositeMoniker_IsDirty
292 ******************************************************************************/
293 HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)
295 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
296 method in the OLE-provided moniker interfaces always return S_FALSE because
297 their internal state never changes. */
299 TRACE("(%p)\n",iface);
301 return S_FALSE;
304 /******************************************************************************
305 * CompositeMoniker_Load
306 ******************************************************************************/
307 HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
309 HRESULT res;
310 DWORD constant;
311 CLSID clsid;
312 WCHAR string[1]={0};
314 ICOM_THIS(CompositeMonikerImpl,iface);
316 TRACE("(%p,%p)\n",iface,pStm);
318 /* this function call OleLoadFromStream function for each moniker within this object */
320 /* read the a constant written by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
321 res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
323 if (SUCCEEDED(res)&& constant!=3)
324 return E_FAIL;
326 while(1){
327 #if 0
328 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
329 #endif
330 res=ReadClassStm(pStm,&clsid);
331 DPRINTF("res=%ld",res);
332 if (FAILED(res))
333 break;
335 if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
336 res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
337 if (FAILED(res))
338 break;
339 res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
340 if (FAILED(res))
341 break;
343 else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
344 CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
345 if (res!=S_OK)
346 break;
347 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
348 if (FAILED(res))
349 break;
351 else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
352 CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
353 if (FAILED(res))
354 break;
355 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
356 if (FAILED(res))
357 break;
359 else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
360 return E_FAIL;
362 else
364 FIXME("()\n");
365 /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */
366 break;
367 return E_NOTIMPL;
370 /* resize the table if needed */
371 if (++This->tabLastIndex==This->tabSize){
373 This->tabSize+=BLOCK_TAB_SIZE;
374 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
376 if (This->tabMoniker==NULL)
377 return E_OUTOFMEMORY;
381 return res;
384 /******************************************************************************
385 * CompositeMoniker_Save
386 ******************************************************************************/
387 HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
389 HRESULT res;
390 IEnumMoniker *enumMk;
391 IMoniker *pmk;
392 DWORD constant=3;
394 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
396 /* This function calls OleSaveToStream function for each moniker within
397 * this object.
398 * When I tested this function in windows, I usually found this constant
399 * at the beginning of the stream. I don't known why (there's no
400 * indication in the specification) !
402 res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
404 IMoniker_Enum(iface,TRUE,&enumMk);
406 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
408 res=OleSaveToStream((IPersistStream*)pmk,pStm);
410 IMoniker_Release(pmk);
412 if (FAILED(res)){
414 IEnumMoniker_Release(pmk);
415 return res;
419 IEnumMoniker_Release(enumMk);
421 return S_OK;
424 /******************************************************************************
425 * CompositeMoniker_GetSizeMax
426 ******************************************************************************/
427 HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
429 IEnumMoniker *enumMk;
430 IMoniker *pmk;
431 ULARGE_INTEGER ptmpSize;
433 /* The sizeMax of this object is calculated by calling GetSizeMax on
434 * each moniker within this object then summing all returned values
437 TRACE("(%p,%p)\n",iface,pcbSize);
439 if (pcbSize!=NULL)
440 return E_POINTER;
442 pcbSize->u.LowPart =0;
443 pcbSize->u.HighPart=0;
445 IMoniker_Enum(iface,TRUE,&enumMk);
447 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){
449 IMoniker_GetSizeMax(pmk,&ptmpSize);
451 IMoniker_Release(pmk);
453 pcbSize->u.LowPart +=ptmpSize.u.LowPart;
454 pcbSize->u.HighPart+=ptmpSize.u.HighPart;
457 IEnumMoniker_Release(enumMk);
459 return S_OK;
462 /******************************************************************************
463 * Composite-Moniker_Construct (local function)
464 *******************************************************************************/
465 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest)
467 DWORD mkSys;
468 IEnumMoniker *enumMoniker;
469 IMoniker *tempMk;
470 HRESULT res;
472 TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
474 /* Initialize the virtual function table. */
475 This->lpvtbl1 = &VT_CompositeMonikerImpl;
476 This->lpvtbl2 = &VT_ROTDataImpl;
477 This->ref = 0;
479 This->tabSize=BLOCK_TAB_SIZE;
480 This->tabLastIndex=0;
482 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
483 if (This->tabMoniker==NULL)
484 return E_OUTOFMEMORY;
486 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
488 /* put the first moniker contents in the beginning of the table */
489 if (mkSys!=MKSYS_GENERICCOMPOSITE){
491 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
492 IMoniker_AddRef(pmkFirst);
494 else{
496 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
498 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
501 if (++This->tabLastIndex==This->tabSize){
503 This->tabSize+=BLOCK_TAB_SIZE;
504 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
506 if (This->tabMoniker==NULL)
507 return E_OUTOFMEMORY;
511 IEnumMoniker_Release(enumMoniker);
514 /* put the rest moniker contents after the first one and make simplification if needed */
516 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
518 if (mkSys!=MKSYS_GENERICCOMPOSITE){
520 /* add a simple moniker to the moniker table */
522 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
524 if (res==MK_E_NEEDGENERIC){
526 /* there's no simplification in this case */
527 This->tabMoniker[This->tabLastIndex]=pmkRest;
529 This->tabLastIndex++;
531 IMoniker_AddRef(pmkRest);
533 else if (tempMk==NULL){
535 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
536 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
538 This->tabLastIndex--;
540 else if (SUCCEEDED(res)){
542 /* the non-generic composition was successful so we can make a simplification in this case */
543 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
545 This->tabMoniker[This->tabLastIndex-1]=tempMk;
546 } else
547 return res;
549 /* resize tabMoniker if needed */
550 if (This->tabLastIndex==This->tabSize){
552 This->tabSize+=BLOCK_TAB_SIZE;
554 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
556 if (This->tabMoniker==NULL)
557 return E_OUTOFMEMORY;
560 else{
562 /* add a composite moniker to the moniker table (do the same thing
563 * for each moniker within the composite moniker as a simple moniker
564 * (see above for how to add a simple moniker case) )
566 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
568 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
570 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
572 if (res==MK_E_NEEDGENERIC){
574 This->tabLastIndex++;
576 else if (tempMk==NULL){
578 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
579 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
580 This->tabLastIndex--;
582 else{
584 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
586 This->tabMoniker[This->tabLastIndex-1]=tempMk;
589 if (This->tabLastIndex==This->tabSize){
591 This->tabSize+=BLOCK_TAB_SIZE;
593 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
595 if (This->tabMoniker==NULL)
596 return E_OUTOFMEMORY;
600 IEnumMoniker_Release(enumMoniker);
603 return S_OK;
606 /******************************************************************************
607 * CompositeMoniker_Destroy (local function)
608 *******************************************************************************/
609 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This)
611 TRACE("(%p)\n",This);
613 HeapFree(GetProcessHeap(),0,This->tabMoniker);
615 HeapFree(GetProcessHeap(),0,This);
617 return S_OK;
620 /******************************************************************************
621 * CompositeMoniker_BindToObject
622 ******************************************************************************/
623 HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,
624 IBindCtx* pbc,
625 IMoniker* pmkToLeft,
626 REFIID riid,
627 VOID** ppvResult)
629 HRESULT res;
630 IRunningObjectTable *prot;
631 IMoniker *tempMk,*antiMk,*mostRigthMk;
632 IEnumMoniker *enumMoniker;
634 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
636 if (ppvResult==NULL)
637 return E_POINTER;
639 *ppvResult=0;
640 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
641 /* object for the requested interface pointer. */
642 if(pmkToLeft==NULL){
644 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
646 if (SUCCEEDED(res)){
648 /* if the requested class was loaded before ! we don't need to reload it */
649 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
651 if (res==S_OK)
652 return res;
655 else{
656 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
657 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
659 IMoniker_Enum(iface,FALSE,&enumMoniker);
660 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
661 IEnumMoniker_Release(enumMoniker);
663 res=CreateAntiMoniker(&antiMk);
664 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
665 IMoniker_Release(antiMk);
667 res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
669 IMoniker_Release(tempMk);
670 IMoniker_Release(mostRigthMk);
673 return res;
676 /******************************************************************************
677 * CompositeMoniker_BindToStorage
678 ******************************************************************************/
679 HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,
680 IBindCtx* pbc,
681 IMoniker* pmkToLeft,
682 REFIID riid,
683 VOID** ppvResult)
685 HRESULT res;
686 IMoniker *tempMk,*antiMk,*mostRigthMk;
687 IEnumMoniker *enumMoniker;
689 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
691 *ppvResult=0;
693 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
694 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
696 if (pmkToLeft!=NULL){
698 IMoniker_Enum(iface,FALSE,&enumMoniker);
699 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
700 IEnumMoniker_Release(enumMoniker);
702 res=CreateAntiMoniker(&antiMk);
703 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
704 IMoniker_Release(antiMk);
706 res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
708 IMoniker_Release(tempMk);
710 IMoniker_Release(mostRigthMk);
712 return res;
714 else
715 return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
718 /******************************************************************************
719 * CompositeMoniker_Reduce
720 ******************************************************************************/
721 HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,
722 IBindCtx* pbc,
723 DWORD dwReduceHowFar,
724 IMoniker** ppmkToLeft,
725 IMoniker** ppmkReduced)
727 HRESULT res;
728 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
729 IEnumMoniker *enumMoniker;
731 TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
733 if (ppmkReduced==NULL)
734 return E_POINTER;
736 /* This method recursively calls Reduce for each of its component monikers. */
738 if (ppmkToLeft==NULL){
740 IMoniker_Enum(iface,FALSE,&enumMoniker);
741 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
742 IEnumMoniker_Release(enumMoniker);
744 res=CreateAntiMoniker(&antiMk);
745 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
746 IMoniker_Release(antiMk);
748 return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
750 else if (*ppmkToLeft==NULL)
752 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
754 else{
756 /* separate the composite moniker in to left and right moniker */
757 IMoniker_Enum(iface,FALSE,&enumMoniker);
758 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
759 IEnumMoniker_Release(enumMoniker);
761 res=CreateAntiMoniker(&antiMk);
762 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
763 IMoniker_Release(antiMk);
765 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
766 /* of the reduced components */
767 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
768 CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
771 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
773 else{
774 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
776 IMoniker_AddRef(iface);
778 *ppmkReduced=iface;
780 return MK_S_REDUCED_TO_SELF;
785 /******************************************************************************
786 * CompositeMoniker_ComposeWith
787 ******************************************************************************/
788 HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,
789 IMoniker* pmkRight,
790 BOOL fOnlyIfNotGeneric,
791 IMoniker** ppmkComposite)
793 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
795 if ((ppmkComposite==NULL)||(pmkRight==NULL))
796 return E_POINTER;
798 *ppmkComposite=0;
800 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
801 /* otherwise, the method returns the result of combining the two monikers by calling the */
802 /* CreateGenericComposite function */
804 if (fOnlyIfNotGeneric)
805 return MK_E_NEEDGENERIC;
807 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
810 /******************************************************************************
811 * CompositeMoniker_Enum
812 ******************************************************************************/
813 HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
815 ICOM_THIS(CompositeMonikerImpl,iface);
817 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
819 if (ppenumMoniker == NULL)
820 return E_POINTER;
822 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
825 /******************************************************************************
826 * CompositeMoniker_IsEqual
827 ******************************************************************************/
828 HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
830 IEnumMoniker *enumMoniker1,*enumMoniker2;
831 IMoniker *tempMk1,*tempMk2;
832 HRESULT res1,res2,res;
834 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
836 if (pmkOtherMoniker==NULL)
837 return S_FALSE;
839 /* This method returns S_OK if the components of both monikers are equal when compared in the */
840 /* left-to-right order.*/
841 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
843 if (enumMoniker1==NULL)
844 return S_FALSE;
846 IMoniker_Enum(iface,TRUE,&enumMoniker2);
848 while(1){
850 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
851 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
853 if((res1==S_OK)&&(res2==S_OK)){
855 if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
856 res= S_FALSE;
857 break;
859 else
860 continue;
862 else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
863 res = S_OK;
864 break;
866 else{
867 res = S_FALSE;
868 break;
871 if (res1==S_OK)
872 IMoniker_Release(tempMk1);
874 if (res2==S_OK)
875 IMoniker_Release(tempMk2);
878 IEnumMoniker_Release(enumMoniker1);
879 IEnumMoniker_Release(enumMoniker2);
881 return res;
883 /******************************************************************************
884 * CompositeMoniker_Hash
885 ******************************************************************************/
886 HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
888 FIXME("(),stub!\n");
890 return E_NOTIMPL;
893 /******************************************************************************
894 * CompositeMoniker_IsRunning
895 ******************************************************************************/
896 HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,
897 IBindCtx* pbc,
898 IMoniker* pmkToLeft,
899 IMoniker* pmkNewlyRunning)
901 IRunningObjectTable* rot;
902 HRESULT res;
903 IMoniker *tempMk,*antiMk,*mostRigthMk;
904 IEnumMoniker *enumMoniker;
906 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
908 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
909 if (pmkToLeft!=NULL){
911 CreateGenericComposite(pmkToLeft,iface,&tempMk);
913 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
915 IMoniker_Release(tempMk);
917 return res;
919 else
920 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
921 /* to this moniker */
923 if (pmkNewlyRunning!=NULL)
925 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
926 return S_OK;
928 else
929 return S_FALSE;
931 else{
933 if (pbc==NULL)
934 return E_POINTER;
936 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
937 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
938 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
939 /* the composite as the pmkToLeft parameter for that call. */
941 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
943 if (FAILED(res))
944 return res;
946 res = IRunningObjectTable_IsRunning(rot,iface);
947 IRunningObjectTable_Release(rot);
949 if(res==S_OK)
950 return S_OK;
952 else{
954 IMoniker_Enum(iface,FALSE,&enumMoniker);
955 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
956 IEnumMoniker_Release(enumMoniker);
958 res=CreateAntiMoniker(&antiMk);
959 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
960 IMoniker_Release(antiMk);
962 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
964 IMoniker_Release(tempMk);
965 IMoniker_Release(mostRigthMk);
967 return res;
972 /******************************************************************************
973 * CompositeMoniker_GetTimeOfLastChange
974 ******************************************************************************/
975 HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
976 IBindCtx* pbc,
977 IMoniker* pmkToLeft,
978 FILETIME* pCompositeTime)
980 IRunningObjectTable* rot;
981 HRESULT res;
982 IMoniker *tempMk,*antiMk,*mostRigthMk;
983 IEnumMoniker *enumMoniker;
985 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
987 if (pCompositeTime==NULL)
988 return E_INVALIDARG;
990 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
991 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
992 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
993 /* of the composite as the pmkToLeft parameter for that call. */
994 if (pmkToLeft!=NULL){
996 res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
998 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
1000 if (FAILED(res))
1001 return res;
1003 if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
1004 return res;
1005 else
1007 IMoniker_Enum(iface,FALSE,&enumMoniker);
1008 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1009 IEnumMoniker_Release(enumMoniker);
1011 res=CreateAntiMoniker(&antiMk);
1012 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1013 IMoniker_Release(antiMk);
1015 res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
1017 IMoniker_Release(tempMk);
1018 IMoniker_Release(mostRigthMk);
1020 return res;
1022 else
1023 return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
1026 /******************************************************************************
1027 * CompositeMoniker_Inverse
1028 ******************************************************************************/
1029 HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
1031 HRESULT res;
1032 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
1033 IEnumMoniker *enumMoniker;
1035 TRACE("(%p,%p)\n",iface,ppmk);
1037 if (ppmk==NULL)
1038 return E_POINTER;
1040 /* This method returns a composite moniker that consists of the inverses of each of the components */
1041 /* of the original composite, stored in reverse order */
1043 res=CreateAntiMoniker(&antiMk);
1044 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1045 IMoniker_Release(antiMk);
1047 if (tempMk==NULL)
1049 return IMoniker_Inverse(iface,ppmk);
1051 else{
1053 IMoniker_Enum(iface,FALSE,&enumMoniker);
1054 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1055 IEnumMoniker_Release(enumMoniker);
1057 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
1058 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
1060 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
1062 IMoniker_Release(tempMk);
1063 IMoniker_Release(mostRigthMk);
1064 IMoniker_Release(tempInvMk);
1065 IMoniker_Release(mostRigthInvMk);
1067 return res;
1071 /******************************************************************************
1072 * CompositeMoniker_CommonPrefixWith
1073 ******************************************************************************/
1074 HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1076 DWORD mkSys;
1077 HRESULT res1,res2;
1078 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
1079 IEnumMoniker *enumMoniker1,*enumMoniker2;
1080 ULONG i,nbCommonMk=0;
1082 /* If the other moniker is a composite, this method compares the components of each composite from left */
1083 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1084 /* of the leftmost components were common to both monikers. */
1086 if (ppmkPrefix==NULL)
1087 return E_POINTER;
1089 *ppmkPrefix=0;
1091 if (pmkOther==NULL)
1092 return MK_E_NOPREFIX;
1094 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1096 if((mkSys==MKSYS_GENERICCOMPOSITE)){
1098 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1099 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
1101 while(1){
1103 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1104 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
1106 if ((res1==S_FALSE) && (res2==S_FALSE)){
1108 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1109 *ppmkPrefix=iface;
1110 IMoniker_AddRef(iface);
1111 return MK_S_US;
1113 else if ((res1==S_OK) && (res2==S_OK)){
1115 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
1117 nbCommonMk++;
1119 else
1120 break;
1123 else if (res1==S_OK){
1125 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1126 /* ppmkPrefix to the other moniker. */
1127 *ppmkPrefix=pmkOther;
1128 return MK_S_HIM;
1130 else{
1131 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1132 /* to this moniker. */
1133 *ppmkPrefix=iface;
1134 return MK_S_ME;
1138 IEnumMoniker_Release(enumMoniker1);
1139 IEnumMoniker_Release(enumMoniker2);
1141 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1142 if (nbCommonMk==0)
1143 return MK_E_NOPREFIX;
1145 IEnumMoniker_Reset(enumMoniker1);
1147 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1149 /* if we have more than one commun moniker the result will be a composite moniker */
1150 if (nbCommonMk>1){
1152 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1153 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1154 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
1155 IMoniker_Release(tempMk1);
1156 IMoniker_Release(tempMk2);
1158 /* compose all common monikers in a composite moniker */
1159 for(i=0;i<nbCommonMk;i++){
1161 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1163 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
1165 IMoniker_Release(*ppmkPrefix);
1167 IMoniker_Release(tempMk1);
1169 *ppmkPrefix=tempMk2;
1171 return S_OK;
1173 else{
1174 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1175 *ppmkPrefix=tempMk1;
1177 return S_OK;
1180 else{
1181 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1182 of this moniker.*/
1184 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1186 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1188 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
1190 *ppmkPrefix=pmkOther;
1192 return MK_S_HIM;
1194 else
1195 return MK_E_NOPREFIX;
1198 /***************************************************************************************************
1199 * GetAfterCommonPrefix (local function)
1200 * This function returns a moniker that consist of the remainder when the common prefix is removed
1201 ***************************************************************************************************/
1202 VOID WINAPI GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
1204 IMoniker *tempMk,*tempMk1,*tempMk2;
1205 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
1206 ULONG nbRestMk=0;
1207 DWORD mkSys;
1208 HRESULT res1,res2;
1210 *restMk=0;
1212 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1213 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
1214 /* on the first difference. */
1215 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
1217 IMoniker_IsSystemMoniker(commonMk,&mkSys);
1219 if (mkSys==MKSYS_GENERICCOMPOSITE){
1221 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
1222 while(1){
1224 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1225 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
1227 if ((res1==S_FALSE)||(res2==S_FALSE)){
1229 if (res1==S_OK)
1231 nbRestMk++;
1233 IMoniker_Release(tempMk1);
1234 IMoniker_Release(tempMk1);
1236 break;
1238 IMoniker_Release(tempMk1);
1239 IMoniker_Release(tempMk1);
1242 else{
1243 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1244 IMoniker_Release(tempMk1);
1247 /* count the number of elements in the enumerator after the common prefix */
1248 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1250 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1252 IMoniker_Release(tempMk);
1254 if (nbRestMk==0)
1255 return;
1257 /* create a generic composite moniker with monikers located after the common prefix */
1258 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1260 if (nbRestMk==1){
1262 *restMk= tempMk1;
1263 return;
1265 else {
1267 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1269 CreateGenericComposite(tempMk1,tempMk2,restMk);
1271 IMoniker_Release(tempMk1);
1273 IMoniker_Release(tempMk2);
1275 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1277 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1279 IMoniker_Release(tempMk1);
1281 IMoniker_Release(*restMk);
1283 *restMk=tempMk2;
1287 /******************************************************************************
1288 * CompositeMoniker_RelativePathTo
1289 ******************************************************************************/
1290 HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkRelPath)
1292 HRESULT res;
1293 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1295 TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1297 if (ppmkRelPath==NULL)
1298 return E_POINTER;
1300 *ppmkRelPath=0;
1302 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1303 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1304 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1306 /* finds the common prefix of the two monikers */
1307 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1309 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1310 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1312 *ppmkRelPath=pmkOther;
1313 IMoniker_AddRef(pmkOther);
1314 return MK_S_HIM;
1317 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1318 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1320 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1321 /* moniker when the common prefix is removed */
1322 if (res==MK_S_HIM){
1324 IMoniker_Inverse(restThisMk,ppmkRelPath);
1325 IMoniker_Release(restThisMk);
1327 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1328 /* when the common prefix is removed */
1329 else if (res==MK_S_ME){
1331 *ppmkRelPath=restOtherMk;
1332 IMoniker_AddRef(restOtherMk);
1334 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1335 /* moniker on the right of it. */
1336 else if (res==S_OK){
1338 IMoniker_Inverse(restThisMk,&invRestThisMk);
1339 IMoniker_Release(restThisMk);
1340 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1341 IMoniker_Release(invRestThisMk);
1342 IMoniker_Release(restOtherMk);
1344 return S_OK;
1347 /******************************************************************************
1348 * CompositeMoniker_GetDisplayName
1349 ******************************************************************************/
1350 HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,
1351 IBindCtx* pbc,
1352 IMoniker* pmkToLeft,
1353 LPOLESTR *ppszDisplayName)
1355 ULONG lengthStr=1;
1356 IEnumMoniker *enumMoniker;
1357 IMoniker* tempMk;
1358 LPOLESTR tempStr;
1360 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1362 if (ppszDisplayName==NULL)
1363 return E_POINTER;
1365 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1367 if (*ppszDisplayName==NULL)
1368 return E_OUTOFMEMORY;
1370 /* This method returns the concatenation of the display names returned by each component moniker of */
1371 /* the composite */
1373 **ppszDisplayName=0;
1375 IMoniker_Enum(iface,TRUE,&enumMoniker);
1377 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1379 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1381 lengthStr+=lstrlenW(tempStr);
1383 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1385 if (*ppszDisplayName==NULL)
1386 return E_OUTOFMEMORY;
1388 strcatW(*ppszDisplayName,tempStr);
1390 CoTaskMemFree(tempStr);
1391 IMoniker_Release(tempMk);
1394 IEnumMoniker_Release(enumMoniker);
1396 return S_OK;
1399 /******************************************************************************
1400 * CompositeMoniker_ParseDisplayName
1401 ******************************************************************************/
1402 HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,
1403 IBindCtx* pbc,
1404 IMoniker* pmkToLeft,
1405 LPOLESTR pszDisplayName,
1406 ULONG* pchEaten,
1407 IMoniker** ppmkOut)
1409 IEnumMoniker *enumMoniker;
1410 IMoniker *tempMk,*mostRigthMk,*antiMk;
1411 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1412 /* passing everything else as the pmkToLeft parameter for that call. */
1414 /* get the most right moniker */
1415 IMoniker_Enum(iface,FALSE,&enumMoniker);
1416 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1417 IEnumMoniker_Release(enumMoniker);
1419 /* get the left moniker */
1420 CreateAntiMoniker(&antiMk);
1421 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1422 IMoniker_Release(antiMk);
1424 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1427 /******************************************************************************
1428 * CompositeMoniker_IsSystemMoniker
1429 ******************************************************************************/
1430 HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1432 TRACE("(%p,%p)\n",iface,pwdMksys);
1434 if (!pwdMksys)
1435 return E_POINTER;
1437 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1439 return S_OK;
1442 /*******************************************************************************
1443 * CompositeMonikerIROTData_QueryInterface
1444 *******************************************************************************/
1445 HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1448 ICOM_THIS_From_IROTData(IMoniker, iface);
1450 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
1452 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1455 /***********************************************************************
1456 * CompositeMonikerIROTData_AddRef
1458 ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1460 ICOM_THIS_From_IROTData(IMoniker, iface);
1462 TRACE("(%p)\n",iface);
1464 return CompositeMonikerImpl_AddRef(This);
1467 /***********************************************************************
1468 * CompositeMonikerIROTData_Release
1470 ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1472 ICOM_THIS_From_IROTData(IMoniker, iface);
1474 TRACE("(%p)\n",iface);
1476 return CompositeMonikerImpl_Release(This);
1479 /******************************************************************************
1480 * CompositeMonikerIROTData_GetComparaisonData
1481 ******************************************************************************/
1482 HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1483 BYTE* pbData,
1484 ULONG cbMax,
1485 ULONG* pcbData)
1487 FIXME("(),stub!\n");
1488 return E_NOTIMPL;
1491 /******************************************************************************
1492 * EnumMonikerImpl_QueryInterface
1493 ******************************************************************************/
1494 HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1496 ICOM_THIS(EnumMonikerImpl,iface);
1498 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1500 /* Perform a sanity check on the parameters.*/
1501 if ( (This==0) || (ppvObject==0) )
1502 return E_INVALIDARG;
1504 /* Initialize the return parameter */
1505 *ppvObject = 0;
1507 /* Compare the riid with the interface IDs implemented by this object.*/
1508 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1509 *ppvObject = iface;
1511 /* Check that we obtained an interface.*/
1512 if ((*ppvObject)==0)
1513 return E_NOINTERFACE;
1515 /* Query Interface always increases the reference count by one when it is successful */
1516 EnumMonikerImpl_AddRef(iface);
1518 return S_OK;
1521 /******************************************************************************
1522 * EnumMonikerImpl_AddRef
1523 ******************************************************************************/
1524 ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1526 ICOM_THIS(EnumMonikerImpl,iface);
1528 TRACE("(%p)\n",This);
1530 return ++(This->ref);
1534 /******************************************************************************
1535 * EnumMonikerImpl_Release
1536 ******************************************************************************/
1537 ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1539 ICOM_THIS(EnumMonikerImpl,iface);
1540 ULONG i
1542 TRACE("(%p)\n",This);
1544 This->ref--;
1546 /* destroy the object if there's no more reference on it */
1547 if (This->ref==0){
1549 for(i=0;i<This->tabSize;i++)
1550 IMoniker_Release(This->tabMoniker[i]);
1552 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1553 HeapFree(GetProcessHeap(),0,This);
1555 return 0;
1557 return This->ref;
1560 /******************************************************************************
1561 * EnumMonikerImpl_Next
1562 ******************************************************************************/
1563 HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){
1565 ICOM_THIS(EnumMonikerImpl,iface);
1566 ULONG i;
1568 /* retrieve the requested number of moniker from the current position */
1569 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1571 rgelt[i]=This->tabMoniker[This->currentPos++];
1573 if (pceltFethed!=NULL)
1574 *pceltFethed= i;
1576 if (i==celt)
1577 return S_OK;
1578 else
1579 return S_FALSE;
1582 /******************************************************************************
1583 * EnumMonikerImpl_Skip
1584 ******************************************************************************/
1585 HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){
1587 ICOM_THIS(EnumMonikerImpl,iface);
1589 if ((This->currentPos+celt) >= This->tabSize)
1590 return S_FALSE;
1592 This->currentPos+=celt;
1594 return S_OK;
1597 /******************************************************************************
1598 * EnumMonikerImpl_Reset
1599 ******************************************************************************/
1600 HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){
1602 ICOM_THIS(EnumMonikerImpl,iface);
1604 This->currentPos=0;
1606 return S_OK;
1609 /******************************************************************************
1610 * EnumMonikerImpl_Clone
1611 ******************************************************************************/
1612 HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){
1614 ICOM_THIS(EnumMonikerImpl,iface);
1616 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1619 /******************************************************************************
1620 * EnumMonikerImpl_CreateEnumMoniker
1621 ******************************************************************************/
1622 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,
1623 ULONG tabSize,
1624 ULONG currentPos,
1625 BOOL leftToRigth,
1626 IEnumMoniker ** ppmk)
1628 EnumMonikerImpl* newEnumMoniker;
1629 int i;
1632 if (currentPos > tabSize)
1633 return E_INVALIDARG;
1635 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1637 if (newEnumMoniker == 0)
1638 return STG_E_INSUFFICIENTMEMORY;
1640 /* Initialize the virtual function table. */
1641 newEnumMoniker->lpVtbl = &VT_EnumMonikerImpl;
1642 newEnumMoniker->ref = 0;
1644 newEnumMoniker->tabSize=tabSize;
1645 newEnumMoniker->currentPos=currentPos;
1647 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1649 if (newEnumMoniker->tabMoniker==NULL) {
1650 HeapFree(GetProcessHeap(), 0, newEnumMoniker);
1651 return E_OUTOFMEMORY;
1654 if (leftToRigth)
1655 for (i=0;i<tabSize;i++){
1657 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1658 IMoniker_AddRef(tabMoniker[i]);
1660 else
1661 for (i=tabSize-1;i>=0;i--){
1663 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1664 IMoniker_AddRef(tabMoniker[i]);
1667 *ppmk=(IEnumMoniker*)newEnumMoniker;
1669 return S_OK;
1672 /******************************************************************************
1673 * CreateGenericComposite [OLE32.@]
1674 ******************************************************************************/
1675 HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite)
1677 CompositeMonikerImpl* newCompositeMoniker = 0;
1678 HRESULT hr = S_OK;
1680 TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1682 if (ppmkComposite==NULL)
1683 return E_POINTER;
1685 *ppmkComposite=0;
1687 if (pmkFirst==NULL && pmkRest!=NULL){
1689 *ppmkComposite=pmkRest;
1690 return S_OK;
1692 else if (pmkFirst!=NULL && pmkRest==NULL){
1693 *ppmkComposite=pmkFirst;
1694 return S_OK;
1696 else if (pmkFirst==NULL && pmkRest==NULL)
1697 return S_OK;
1699 newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
1701 if (newCompositeMoniker == 0)
1702 return STG_E_INSUFFICIENTMEMORY;
1704 hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
1706 if (FAILED(hr)){
1708 HeapFree(GetProcessHeap(),0,newCompositeMoniker);
1709 return hr;
1711 if (newCompositeMoniker->tabLastIndex==1)
1713 hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
1714 else
1716 hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
1718 return hr;
1721 /******************************************************************************
1722 * MonikerCommonPrefixWith [OLE32.@]
1723 ******************************************************************************/
1724 HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1726 FIXME("(),stub!\n");
1727 return E_NOTIMPL;