- Implement interprocess clipboard communication.
[wine.git] / ole / compositemoniker.c
blob72d7b370bc7d8abadc5366411b2141e2ff19ee23
1 /***************************************************************************************
2 * CompositeMonikers implementation
4 * Copyright 1999 Noomen Hamza
5 ***************************************************************************************/
6 #include <assert.h>
7 #include "winbase.h"
8 #include "winerror.h"
9 #include "debugtools.h"
10 #include "wine/obj_inplace.h"
11 #include "ole2.h"
13 DEFAULT_DEBUG_CHANNEL(ole)
15 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
17 /* CompositeMoniker data structure */
18 typedef struct CompositeMonikerImpl{
20 ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/
22 /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
23 * two monikers are equal. That's whay IROTData interface is implemented by monikers.
25 ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/
27 ULONG ref; /* reference counter for this object */
29 IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */
31 ULONG tabSize; /* size of tabMoniker */
33 ULONG tabLastIndex; /* first free index in tabMoniker */
35 } CompositeMonikerImpl;
38 /* EnumMoniker data structure */
39 typedef struct EnumMonikerImpl{
41 ICOM_VTABLE(IEnumMoniker)* lpvtbl; /* VTable relative to the IEnumMoniker interface.*/
43 ULONG ref; /* reference counter for this object */
45 IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
47 ULONG tabSize; /* size of tabMoniker */
49 ULONG currentPos; /* index pointer on the current moniker */
51 } EnumMonikerImpl;
54 /********************************************************************************/
55 /* CompositeMoniker prototype functions : */
57 /* IUnknown prototype functions */
58 static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
59 static ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface);
60 static ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface);
62 /* IPersist prototype functions */
63 static HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
65 /* IPersistStream prototype functions */
66 static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface);
67 static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm);
68 static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
69 static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
71 /* IMoniker prototype functions */
72 static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
73 static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
74 static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
75 static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
76 static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
77 static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
78 static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
79 static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
80 static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime);
81 static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
82 static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
83 static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
84 static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
85 static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
86 static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
88 /********************************************************************************/
89 /* IROTData prototype functions */
91 /* IUnknown prototype functions */
92 static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
93 static ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface);
94 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface);
96 /* IROTData prototype function */
97 static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
99 /* Local function used by CompositeMoniker implementation */
100 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest);
101 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface);
103 /********************************************************************************/
104 /* IEnumMoniker prototype functions */
106 /* IUnknown prototype functions */
107 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject);
108 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface);
109 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface);
111 /* IEnumMonker prototype functions */
112 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched);
113 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt);
114 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface);
115 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum);
117 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
119 /********************************************************************************/
120 /* Virtual function table for the CompositeMonikerImpl class witch include */
121 /* Ipersist, IPersistStream and IMoniker functions. */
123 static ICOM_VTABLE(IMoniker) VT_CompositeMonikerImpl =
125 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
126 CompositeMonikerImpl_QueryInterface,
127 CompositeMonikerImpl_AddRef,
128 CompositeMonikerImpl_Release,
129 CompositeMonikerImpl_GetClassID,
130 CompositeMonikerImpl_IsDirty,
131 CompositeMonikerImpl_Load,
132 CompositeMonikerImpl_Save,
133 CompositeMonikerImpl_GetSizeMax,
134 CompositeMonikerImpl_BindToObject,
135 CompositeMonikerImpl_BindToStorage,
136 CompositeMonikerImpl_Reduce,
137 CompositeMonikerImpl_ComposeWith,
138 CompositeMonikerImpl_Enum,
139 CompositeMonikerImpl_IsEqual,
140 CompositeMonikerImpl_Hash,
141 CompositeMonikerImpl_IsRunning,
142 CompositeMonikerImpl_GetTimeOfLastChange,
143 CompositeMonikerImpl_Inverse,
144 CompositeMonikerImpl_CommonPrefixWith,
145 CompositeMonikerImpl_RelativePathTo,
146 CompositeMonikerImpl_GetDisplayName,
147 CompositeMonikerImpl_ParseDisplayName,
148 CompositeMonikerImpl_IsSystemMoniker
151 /********************************************************************************/
152 /* Virtual function table for the IROTData class. */
153 static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
155 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
156 CompositeMonikerROTDataImpl_QueryInterface,
157 CompositeMonikerROTDataImpl_AddRef,
158 CompositeMonikerROTDataImpl_Release,
159 CompositeMonikerROTDataImpl_GetComparaisonData
162 /********************************************************************************/
163 /* Virtual function table for the IROTData class */
164 static ICOM_VTABLE(IEnumMoniker) VT_EnumMonikerImpl =
166 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
167 EnumMonikerImpl_QueryInterface,
168 EnumMonikerImpl_AddRef,
169 EnumMonikerImpl_Release,
170 EnumMonikerImpl_Next,
171 EnumMonikerImpl_Skip,
172 EnumMonikerImpl_Reset,
173 EnumMonikerImpl_Clone
176 /*******************************************************************************
177 * CompositeMoniker_QueryInterface
178 *******************************************************************************/
179 HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
181 ICOM_THIS(CompositeMonikerImpl,iface);
183 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
185 /* Perform a sanity check on the parameters.*/
186 if ( (This==0) || (ppvObject==0) )
187 return E_INVALIDARG;
189 /* Initialize the return parameter */
190 *ppvObject = 0;
192 /* Compare the riid with the interface IDs implemented by this object.*/
193 if (IsEqualIID(&IID_IUnknown, riid) ||
194 IsEqualIID(&IID_IPersist, riid) ||
195 IsEqualIID(&IID_IPersistStream, riid) ||
196 IsEqualIID(&IID_IMoniker, riid)
198 *ppvObject = iface;
199 else if (IsEqualIID(&IID_IROTData, riid))
200 *ppvObject = (IROTData*)&(This->lpvtbl2);
202 /* Check that we obtained an interface.*/
203 if ((*ppvObject)==0)
204 return E_NOINTERFACE;
206 /* Query Interface always increases the reference count by one when it is successful */
207 CompositeMonikerImpl_AddRef(iface);
209 return S_OK;
212 /******************************************************************************
213 * CompositeMoniker_AddRef
214 ******************************************************************************/
215 ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)
217 ICOM_THIS(CompositeMonikerImpl,iface);
219 TRACE("(%p)\n",This);
221 return ++(This->ref);
224 /******************************************************************************
225 * CompositeMoniker_Release
226 ******************************************************************************/
227 ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
229 ICOM_THIS(CompositeMonikerImpl,iface);
230 ULONG i;
232 TRACE("(%p)\n",This);
234 This->ref--;
236 /* destroy the object if there's no more reference on it */
237 if (This->ref==0){
239 /* release all the components before destroying this object */
240 for (i=0;i<This->tabLastIndex;i++)
241 IMoniker_Release(This->tabMoniker[i]);
243 CompositeMonikerImpl_Destroy(This);
245 return 0;
247 return This->ref;;
250 /******************************************************************************
251 * CompositeMoniker_GetClassID
252 ******************************************************************************/
253 HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
255 TRACE("(%p,%p),stub!\n",iface,pClassID);
257 if (pClassID==NULL)
258 return E_POINTER;
260 *pClassID = CLSID_CompositeMoniker;
262 return S_OK;
265 /******************************************************************************
266 * CompositeMoniker_IsDirty
267 ******************************************************************************/
268 HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)
270 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
271 method in the OLE-provided moniker interfaces always return S_FALSE because
272 their internal state never changes. */
274 TRACE("(%p)\n",iface);
276 return S_FALSE;
279 /******************************************************************************
280 * CompositeMoniker_Load
281 ******************************************************************************/
282 HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
284 HRESULT res;
285 DWORD constant;
286 CLSID clsid;
287 WCHAR string[1]={0};
289 ICOM_THIS(CompositeMonikerImpl,iface);
291 TRACE("(%p,%p)\n",iface,pStm);
293 /* this function call OleLoadFromStream function for each moniker within this object */
295 /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
296 res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
298 if (SUCCEEDED(res)&& constant!=3)
299 return E_FAIL;
301 while(1){
302 #if 0
303 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
304 #endif
305 res=ReadClassStm(pStm,&clsid);
306 printf("res=%ld",res);
307 if (FAILED(res))
308 break;
310 if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
311 res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
312 if (FAILED(res))
313 break;
314 res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
315 if (FAILED(res))
316 break;
318 else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
319 CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
320 if (res!=S_OK)
321 break;
322 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
323 if (FAILED(res))
324 break;
326 else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
327 CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
328 if (FAILED(res))
329 break;
330 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
331 if (FAILED(res))
332 break;
334 else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
335 return E_FAIL;
337 else{
338 FIXME("()");
339 break;
340 return E_NOTIMPL;
343 /* resize the table if needed */
344 if (++This->tabLastIndex==This->tabSize){
346 This->tabSize+=BLOCK_TAB_SIZE;
347 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
349 if (This->tabMoniker==NULL)
350 return E_OUTOFMEMORY;
354 return res;
357 /******************************************************************************
358 * CompositeMoniker_Save
359 ******************************************************************************/
360 HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
362 HRESULT res;
363 IEnumMoniker *enumMk;
364 IMoniker *pmk;
365 DWORD constant=3;
367 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
369 /* this function call OleSaveToStream function for each moniker within this object */
371 /* when I tested this function in windows system ! I usually found this constant in the begining of */
372 /* the stream I dont known why (there's no indication in specification) ! */
373 res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
375 IMoniker_Enum(iface,TRUE,&enumMk);
377 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
379 res=OleSaveToStream((IPersistStream*)pmk,pStm);
381 IMoniker_Release(pmk);
383 if (FAILED(res)){
385 IEnumMoniker_Release(pmk);
386 return res;
390 IEnumMoniker_Release(enumMk);
392 return S_OK;
395 /******************************************************************************
396 * CompositeMoniker_GetSizeMax
397 ******************************************************************************/
398 HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
400 IEnumMoniker *enumMk;
401 IMoniker *pmk;
402 ULARGE_INTEGER ptmpSize;
404 /* the sizeMax of this object is calculated by calling GetSizeMax on each moniker within this object then */
405 /* suming all returned sizemax */
407 TRACE("(%p,%p)\n",iface,pcbSize);
409 if (pcbSize!=NULL)
410 return E_POINTER;
412 pcbSize->LowPart =0;
413 pcbSize->HighPart=0;
415 IMoniker_Enum(iface,TRUE,&enumMk);
417 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){
419 IMoniker_GetSizeMax(pmk,&ptmpSize);
421 IMoniker_Release(pmk);
423 pcbSize->LowPart +=ptmpSize.LowPart;
424 pcbSize->HighPart+=ptmpSize.HighPart;
427 IEnumMoniker_Release(enumMk);
429 return S_OK;
432 /******************************************************************************
433 * Composite-Moniker_Construct (local function)
434 *******************************************************************************/
435 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest)
437 DWORD mkSys;
438 IEnumMoniker *enumMoniker;
439 IMoniker *tempMk;
440 HRESULT res;
442 TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
444 /* Initialize the virtual fgunction table. */
445 This->lpvtbl1 = &VT_CompositeMonikerImpl;
446 This->lpvtbl2 = &VT_ROTDataImpl;
447 This->ref = 0;
449 This->tabSize=BLOCK_TAB_SIZE;
450 This->tabLastIndex=0;
452 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
453 if (This->tabMoniker==NULL)
454 return E_OUTOFMEMORY;
456 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
458 /* put the first moniker contents in the begining of the table */
459 if (mkSys!=MKSYS_GENERICCOMPOSITE){
461 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
462 IMoniker_AddRef(pmkFirst);
464 else{
466 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
468 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
471 if (++This->tabLastIndex==This->tabSize){
473 This->tabSize+=BLOCK_TAB_SIZE;
474 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
476 if (This->tabMoniker==NULL)
477 return E_OUTOFMEMORY;
481 IEnumMoniker_Release(enumMoniker);
484 /* put the rest moniker contents after the first one and make simplification if needed */
486 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
488 if (mkSys!=MKSYS_GENERICCOMPOSITE){
490 /* add a simple moniker to the moniker table */
492 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
494 if (res==MK_E_NEEDGENERIC){
496 /* there's no simplification in this case */
497 This->tabMoniker[This->tabLastIndex]=pmkRest;
499 This->tabLastIndex++;
501 IMoniker_AddRef(pmkRest);
503 else if (tempMk==NULL){
505 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
506 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
508 This->tabLastIndex--;
510 else if (SUCCEEDED(res)){
512 /* the non-generic composition was successful so we can make a simplification in this case */
513 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
515 This->tabMoniker[This->tabLastIndex-1]=tempMk;
516 } else
517 return res;
519 /* resize tabMoniker if needed */
520 if (This->tabLastIndex==This->tabSize){
522 This->tabSize+=BLOCK_TAB_SIZE;
524 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
526 if (This->tabMoniker==NULL)
527 return E_OUTOFMEMORY;
530 else{
532 /* add a composite moniker to the moniker table (do the same thing for each moniker within the */
533 /* composite moniker as a simple moniker (see above how to add a simple moniker case) ) */
534 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
536 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
538 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
540 if (res==MK_E_NEEDGENERIC){
542 This->tabLastIndex++;
544 else if (tempMk==NULL){
546 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
547 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
548 This->tabLastIndex--;
550 else{
552 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
554 This->tabMoniker[This->tabLastIndex-1]=tempMk;
557 if (This->tabLastIndex==This->tabSize){
559 This->tabSize+=BLOCK_TAB_SIZE;
561 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
563 if (This->tabMoniker==NULL)
564 return E_OUTOFMEMORY;
568 IEnumMoniker_Release(enumMoniker);
571 return S_OK;
574 /******************************************************************************
575 * CompositeMoniker_Destroy (local function)
576 *******************************************************************************/
577 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This)
579 TRACE("(%p)\n",This);
581 HeapFree(GetProcessHeap(),0,This->tabMoniker);
583 HeapFree(GetProcessHeap(),0,This);
585 return S_OK;
588 /******************************************************************************
589 * CompositeMoniker_BindToObject
590 ******************************************************************************/
591 HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,
592 IBindCtx* pbc,
593 IMoniker* pmkToLeft,
594 REFIID riid,
595 VOID** ppvResult)
597 HRESULT res;
598 IRunningObjectTable *prot;
599 IMoniker *tempMk,*antiMk,*mostRigthMk;
600 IEnumMoniker *enumMoniker;
602 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
604 if (ppvResult==NULL)
605 return E_POINTER;
607 *ppvResult=0;
608 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
609 /* object for the requested interface pointer. */
610 if(pmkToLeft==NULL){
612 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
614 if (SUCCEEDED(res)){
616 /* if the requested class was loaded befor ! we dont need to reload it */
617 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
619 if (res==S_OK)
620 return res;
623 else{
624 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
625 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
627 IMoniker_Enum(iface,FALSE,&enumMoniker);
628 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
629 IEnumMoniker_Release(enumMoniker);
631 res=CreateAntiMoniker(&antiMk);
632 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
633 IMoniker_Release(antiMk);
635 res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
637 IMoniker_Release(tempMk);
638 IMoniker_Release(mostRigthMk);
641 return res;
644 /******************************************************************************
645 * CompositeMoniker_BindToStorage
646 ******************************************************************************/
647 HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,
648 IBindCtx* pbc,
649 IMoniker* pmkToLeft,
650 REFIID riid,
651 VOID** ppvResult)
653 HRESULT res;
654 IMoniker *tempMk,*antiMk,*mostRigthMk;
655 IEnumMoniker *enumMoniker;
657 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
659 *ppvResult=0;
661 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
662 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
664 if (pmkToLeft!=NULL){
666 IMoniker_Enum(iface,FALSE,&enumMoniker);
667 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
668 IEnumMoniker_Release(enumMoniker);
670 res=CreateAntiMoniker(&antiMk);
671 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
672 IMoniker_Release(antiMk);
674 res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
676 IMoniker_Release(tempMk);
678 IMoniker_Release(mostRigthMk);
680 return res;
682 else
683 return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
686 /******************************************************************************
687 * CompositeMoniker_Reduce
688 ******************************************************************************/
689 HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,
690 IBindCtx* pbc,
691 DWORD dwReduceHowFar,
692 IMoniker** ppmkToLeft,
693 IMoniker** ppmkReduced)
695 HRESULT res;
696 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
697 IEnumMoniker *enumMoniker;
699 TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
701 if (ppmkReduced==NULL)
702 return E_POINTER;
704 /* This method recursively calls Reduce for each of its component monikers. */
706 if (ppmkToLeft==NULL){
708 IMoniker_Enum(iface,FALSE,&enumMoniker);
709 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
710 IEnumMoniker_Release(enumMoniker);
712 res=CreateAntiMoniker(&antiMk);
713 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
714 IMoniker_Release(antiMk);
716 return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
718 else if (*ppmkToLeft==NULL)
720 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
722 else{
724 /* separate the copmosite moniker in to left and wrigth moniker */
725 IMoniker_Enum(iface,FALSE,&enumMoniker);
726 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
727 IEnumMoniker_Release(enumMoniker);
729 res=CreateAntiMoniker(&antiMk);
730 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
731 IMoniker_Release(antiMk);
733 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
734 /* of the reduced components */
735 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
736 CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
739 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
741 else{
742 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
744 IMoniker_AddRef(iface);
746 *ppmkReduced=iface;
748 return MK_S_REDUCED_TO_SELF;
753 /******************************************************************************
754 * CompositeMoniker_ComposeWith
755 ******************************************************************************/
756 HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,
757 IMoniker* pmkRight,
758 BOOL fOnlyIfNotGeneric,
759 IMoniker** ppmkComposite)
761 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
763 if ((ppmkComposite==NULL)||(pmkRight==NULL))
764 return E_POINTER;
766 *ppmkComposite=0;
768 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
769 /* otherwise, the method returns the result of combining the two monikers by calling the */
770 /* CreateGenericComposite function */
772 if (fOnlyIfNotGeneric)
773 return MK_E_NEEDGENERIC;
775 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
778 /******************************************************************************
779 * CompositeMoniker_Enum
780 ******************************************************************************/
781 HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
783 ICOM_THIS(CompositeMonikerImpl,iface);
785 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
787 if (ppenumMoniker == NULL)
788 return E_POINTER;
790 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
793 /******************************************************************************
794 * CompositeMoniker_IsEqual
795 ******************************************************************************/
796 HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
798 IEnumMoniker *enumMoniker1,*enumMoniker2;
799 IMoniker *tempMk1,*tempMk2;
800 HRESULT res1,res2,res;
802 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
804 if (pmkOtherMoniker==NULL)
805 return S_FALSE;
807 /* This method returns S_OK if the components of both monikers are equal when compared in the */
808 /* left-to-right order.*/
809 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
811 if (enumMoniker1==NULL)
812 return S_FALSE;
814 IMoniker_Enum(iface,TRUE,&enumMoniker2);
816 while(1){
818 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
819 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
821 if((res1==S_OK)&&(res2==S_OK)){
823 if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
824 res= S_FALSE;
825 break;
827 else
828 continue;
830 else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
831 res = S_OK;
832 break;
834 else{
835 res = S_FALSE;
836 break;
839 if (res1==S_OK)
840 IMoniker_Release(tempMk1);
842 if (res2==S_OK)
843 IMoniker_Release(tempMk2);
846 IEnumMoniker_Release(enumMoniker1);
847 IEnumMoniker_Release(enumMoniker2);
849 return res;
851 /******************************************************************************
852 * CompositeMoniker_Hash
853 ******************************************************************************/
854 HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
856 FIXME("(),stub!\n");
858 return E_NOTIMPL;
861 /******************************************************************************
862 * CompositeMoniker_IsRunning
863 ******************************************************************************/
864 HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,
865 IBindCtx* pbc,
866 IMoniker* pmkToLeft,
867 IMoniker* pmkNewlyRunning)
869 IRunningObjectTable* rot;
870 HRESULT res;
871 IMoniker *tempMk,*antiMk,*mostRigthMk;
872 IEnumMoniker *enumMoniker;
874 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
876 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
877 if (pmkToLeft!=NULL){
879 CreateGenericComposite(pmkToLeft,iface,&tempMk);
881 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
883 IMoniker_Release(tempMk);
885 return res;
887 else
888 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
889 /* to this moniker */
891 if (pmkNewlyRunning!=NULL)
893 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
894 return S_OK;
896 else
897 return S_FALSE;
899 else{
901 if (pbc==NULL)
902 return E_POINTER;
904 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
905 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
906 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
907 /* the composite as the pmkToLeft parameter for that call. */
909 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
911 if (FAILED(res))
912 return res;
914 res = IRunningObjectTable_IsRunning(rot,iface);
915 IRunningObjectTable_Release(rot);
917 if(res==S_OK)
918 return S_OK;
920 else{
922 IMoniker_Enum(iface,FALSE,&enumMoniker);
923 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
924 IEnumMoniker_Release(enumMoniker);
926 res=CreateAntiMoniker(&antiMk);
927 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
928 IMoniker_Release(antiMk);
930 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
932 IMoniker_Release(tempMk);
933 IMoniker_Release(mostRigthMk);
935 return res;
940 /******************************************************************************
941 * CompositeMoniker_GetTimeOfLastChange
942 ******************************************************************************/
943 HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
944 IBindCtx* pbc,
945 IMoniker* pmkToLeft,
946 FILETIME* pCompositeTime)
948 IRunningObjectTable* rot;
949 HRESULT res;
950 IMoniker *tempMk,*antiMk,*mostRigthMk;
951 IEnumMoniker *enumMoniker;
953 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
955 if (pCompositeTime==NULL)
956 return E_INVALIDARG;
958 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
959 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
960 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
961 /* of the composite as the pmkToLeft parameter for that call. */
962 if (pmkToLeft!=NULL){
964 res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
966 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
968 if (FAILED(res))
969 return res;
971 if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
972 return res;
973 else
975 IMoniker_Enum(iface,FALSE,&enumMoniker);
976 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
977 IEnumMoniker_Release(enumMoniker);
979 res=CreateAntiMoniker(&antiMk);
980 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
981 IMoniker_Release(antiMk);
983 res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
985 IMoniker_Release(tempMk);
986 IMoniker_Release(mostRigthMk);
988 return res;
990 else
991 return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
994 /******************************************************************************
995 * CompositeMoniker_Inverse
996 ******************************************************************************/
997 HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
999 HRESULT res;
1000 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
1001 IEnumMoniker *enumMoniker;
1003 TRACE("(%p,%p)\n",iface,ppmk);
1005 if (ppmk==NULL)
1006 return E_POINTER;
1008 /* This method returns a composite moniker that consists of the inverses of each of the components */
1009 /* of the original composite, stored in reverse order */
1011 res=CreateAntiMoniker(&antiMk);
1012 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1013 IMoniker_Release(antiMk);
1015 if (tempMk==NULL)
1017 return IMoniker_Inverse(iface,ppmk);
1019 else{
1021 IMoniker_Enum(iface,FALSE,&enumMoniker);
1022 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1023 IEnumMoniker_Release(enumMoniker);
1025 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
1026 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
1028 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
1030 IMoniker_Release(tempMk);
1031 IMoniker_Release(mostRigthMk);
1032 IMoniker_Release(tempInvMk);
1033 IMoniker_Release(mostRigthInvMk);
1035 return res;
1039 /******************************************************************************
1040 * CompositeMoniker_CommonPrefixWith
1041 ******************************************************************************/
1042 HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1044 DWORD mkSys;
1045 HRESULT res1,res2;
1046 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
1047 IEnumMoniker *enumMoniker1,*enumMoniker2;
1048 ULONG i,nbCommonMk=0;
1050 /* If the other moniker is a composite, this method compares the components of each composite from left */
1051 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1052 /* of the leftmost components were common to both monikers. */
1054 if (ppmkPrefix==NULL)
1055 return E_POINTER;
1057 *ppmkPrefix=0;
1059 if (pmkOther==NULL)
1060 return MK_E_NOPREFIX;
1062 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1064 if((mkSys==MKSYS_GENERICCOMPOSITE)){
1066 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1067 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
1069 while(1){
1071 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1072 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
1074 if ((res1==S_FALSE) && (res2==S_FALSE)){
1076 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1077 *ppmkPrefix=iface;
1078 IMoniker_AddRef(iface);
1079 return MK_S_US;
1081 else if ((res1==S_OK) && (res2==S_OK)){
1083 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
1085 nbCommonMk++;
1087 else
1088 break;
1091 else if (res1==S_OK){
1093 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1094 /* ppmkPrefix to the other moniker. */
1095 *ppmkPrefix=pmkOther;
1096 return MK_S_HIM;
1098 else{
1099 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1100 /* to this moniker. */
1101 *ppmkPrefix=iface;
1102 return MK_S_ME;
1106 IEnumMoniker_Release(enumMoniker1);
1107 IEnumMoniker_Release(enumMoniker2);
1109 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1110 if (nbCommonMk==0)
1111 return MK_E_NOPREFIX;
1113 IEnumMoniker_Reset(enumMoniker1);
1115 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1117 /* if we have more than one commun moniker the result will be a composite moniker */
1118 if (nbCommonMk>1){
1120 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1121 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1122 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
1123 IMoniker_Release(tempMk1);
1124 IMoniker_Release(tempMk2);
1126 /* compose all common monikers in a composite moniker */
1127 for(i=0;i<nbCommonMk;i++){
1129 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1131 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
1133 IMoniker_Release(*ppmkPrefix);
1135 IMoniker_Release(tempMk1);
1137 *ppmkPrefix=tempMk2;
1139 return S_OK;
1141 else{
1142 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1143 *ppmkPrefix=tempMk1;
1145 return S_OK;
1148 else{
1149 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1150 of this moniker.*/
1152 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1154 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1156 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
1158 *ppmkPrefix=pmkOther;
1160 return MK_S_HIM;
1162 else
1163 return MK_E_NOPREFIX;
1166 /***************************************************************************************************
1167 * GetAfterCommonPrefix (local function)
1168 * This function returns a moniker that consist of the remainder when the common prefix is removed
1169 ***************************************************************************************************/
1170 VOID WINAPI GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
1172 IMoniker *tempMk,*tempMk1,*tempMk2;
1173 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
1174 ULONG nbRestMk=0;
1175 DWORD mkSys;
1176 HRESULT res1,res2;
1178 *restMk=0;
1180 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1181 /* prefix: enum the two monikers (left-wrigth) then compare these enumerations (left-wrigth) and stop */
1182 /* on the first difference. */
1183 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
1185 IMoniker_IsSystemMoniker(commonMk,&mkSys);
1187 if (mkSys==MKSYS_GENERICCOMPOSITE){
1189 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
1190 while(1){
1192 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1193 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
1195 if ((res1==S_FALSE)||(res2==S_FALSE)){
1197 if (res1==S_OK)
1199 nbRestMk++;
1201 IMoniker_Release(tempMk1);
1202 IMoniker_Release(tempMk1);
1204 break;
1206 IMoniker_Release(tempMk1);
1207 IMoniker_Release(tempMk1);
1210 else{
1211 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1212 IMoniker_Release(tempMk1);
1215 /* count the number of elements in the enumerator after the common prefix */
1216 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1218 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1220 IMoniker_Release(tempMk);;
1222 if (nbRestMk==0)
1223 return;
1225 /* create a generic composite moniker with monikers located after the common prefix */
1226 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1228 if (nbRestMk==1){
1230 *restMk= tempMk1;
1231 return;
1233 else {
1235 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1237 CreateGenericComposite(tempMk1,tempMk2,restMk);
1239 IMoniker_Release(tempMk1);
1241 IMoniker_Release(tempMk2);
1243 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1245 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1247 IMoniker_Release(tempMk1);
1249 IMoniker_Release(*restMk);
1251 *restMk=tempMk2;
1255 /******************************************************************************
1256 * CompositeMoniker_RelativePathTo
1257 ******************************************************************************/
1258 HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkRelPath)
1260 HRESULT res;
1261 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1263 TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1265 if (ppmkRelPath==NULL)
1266 return E_POINTER;
1268 *ppmkRelPath=0;
1270 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1271 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1272 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1274 /* finds the common prefix of the two monikers */
1275 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1277 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1278 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1280 *ppmkRelPath=pmkOther;
1281 IMoniker_AddRef(pmkOther);
1282 return MK_S_HIM;
1285 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1286 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1288 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1289 /* moniker when the common prefix is removed */
1290 if (res==MK_S_HIM){
1292 IMoniker_Inverse(restThisMk,ppmkRelPath);
1293 IMoniker_Release(restThisMk);
1295 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1296 /* when the common prefix is removed */
1297 else if (res==MK_S_ME){
1299 *ppmkRelPath=restOtherMk;
1300 IMoniker_AddRef(restOtherMk);
1302 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1303 /* moniker on the right of it. */
1304 else if (res==S_OK){
1306 IMoniker_Inverse(restThisMk,&invRestThisMk);
1307 IMoniker_Release(restThisMk);
1308 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1309 IMoniker_Release(invRestThisMk);
1310 IMoniker_Release(restOtherMk);
1312 return S_OK;
1315 /******************************************************************************
1316 * CompositeMoniker_GetDisplayName
1317 ******************************************************************************/
1318 HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,
1319 IBindCtx* pbc,
1320 IMoniker* pmkToLeft,
1321 LPOLESTR *ppszDisplayName)
1323 ULONG lengthStr=1;
1324 IEnumMoniker *enumMoniker;
1325 IMoniker* tempMk;
1326 LPOLESTR tempStr;
1328 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1330 if (ppszDisplayName==NULL)
1331 return E_POINTER;
1333 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1335 if (*ppszDisplayName==NULL)
1336 return E_OUTOFMEMORY;
1338 /* This method returns the concatenation of the display names returned by each component moniker of */
1339 /* the composite */
1341 **ppszDisplayName=0;
1343 IMoniker_Enum(iface,TRUE,&enumMoniker);
1345 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1347 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1349 lengthStr+=lstrlenW(tempStr);
1351 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1353 if (*ppszDisplayName==NULL)
1354 return E_OUTOFMEMORY;
1356 lstrcatW(*ppszDisplayName,tempStr);
1358 CoTaskMemFree(tempStr);
1359 IMoniker_Release(tempMk);
1362 IEnumMoniker_Release(enumMoniker);
1364 return S_OK;
1367 /******************************************************************************
1368 * CompositeMoniker_ParseDisplayName
1369 ******************************************************************************/
1370 HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,
1371 IBindCtx* pbc,
1372 IMoniker* pmkToLeft,
1373 LPOLESTR pszDisplayName,
1374 ULONG* pchEaten,
1375 IMoniker** ppmkOut)
1377 IEnumMoniker *enumMoniker;
1378 IMoniker *tempMk,*mostRigthMk,*antiMk;
1379 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1380 /* passing everything else as the pmkToLeft parameter for that call. */
1382 /* get the most rigth moniker */
1383 IMoniker_Enum(iface,FALSE,&enumMoniker);
1384 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1385 IEnumMoniker_Release(enumMoniker);
1387 /* get the left moniker */
1388 CreateAntiMoniker(&antiMk);
1389 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1390 IMoniker_Release(antiMk);
1392 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1395 /******************************************************************************
1396 * CompositeMoniker_IsSystemMonker
1397 ******************************************************************************/
1398 HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1400 TRACE("(%p,%p)\n",iface,pwdMksys);
1402 if (!pwdMksys)
1403 return E_POINTER;
1405 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1407 return S_OK;
1410 /*******************************************************************************
1411 * CompositeMonikerIROTData_QueryInterface
1412 *******************************************************************************/
1413 HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1416 ICOM_THIS_From_IROTData(IMoniker, iface);
1418 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
1420 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1423 /***********************************************************************
1424 * CompositeMonikerIROTData_AddRef
1426 ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1428 ICOM_THIS_From_IROTData(IMoniker, iface);
1430 TRACE("(%p)\n",iface);
1432 return CompositeMonikerImpl_AddRef(This);
1435 /***********************************************************************
1436 * CompositeMonikerIROTData_Release
1438 ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1440 ICOM_THIS_From_IROTData(IMoniker, iface);
1442 TRACE("(%p)\n",iface);
1444 return CompositeMonikerImpl_Release(This);
1447 /******************************************************************************
1448 * CompositeMonikerIROTData_GetComparaisonData
1449 ******************************************************************************/
1450 HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1451 BYTE* pbData,
1452 ULONG cbMax,
1453 ULONG* pcbData)
1455 FIXME("(),stub!\n");
1456 return E_NOTIMPL;
1459 /******************************************************************************
1460 * EnumMonikerImpl_QueryInterface
1461 ******************************************************************************/
1462 HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1464 ICOM_THIS(EnumMonikerImpl,iface);
1466 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1468 /* Perform a sanity check on the parameters.*/
1469 if ( (This==0) || (ppvObject==0) )
1470 return E_INVALIDARG;
1472 /* Initialize the return parameter */
1473 *ppvObject = 0;
1475 /* Compare the riid with the interface IDs implemented by this object.*/
1476 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1477 *ppvObject = iface;
1479 /* Check that we obtained an interface.*/
1480 if ((*ppvObject)==0)
1481 return E_NOINTERFACE;
1483 /* Query Interface always increases the reference count by one when it is successful */
1484 EnumMonikerImpl_AddRef(iface);
1486 return S_OK;
1489 /******************************************************************************
1490 * EnumMonikerImpl_AddRef
1491 ******************************************************************************/
1492 ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1494 ICOM_THIS(EnumMonikerImpl,iface);
1496 TRACE("(%p)\n",This);
1498 return ++(This->ref);
1502 /******************************************************************************
1503 * EnumMonikerImpl_Release
1504 ******************************************************************************/
1505 ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1507 ICOM_THIS(EnumMonikerImpl,iface);
1508 ULONG i
1510 TRACE("(%p)\n",This);
1512 This->ref--;
1514 /* destroy the object if there's no more reference on it */
1515 if (This->ref==0){
1517 for(i=0;i<This->tabSize;i++)
1518 IMoniker_Release(This->tabMoniker[i]);
1520 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1521 HeapFree(GetProcessHeap(),0,This);
1523 return 0;
1525 return This->ref;;
1528 /******************************************************************************
1529 * EnumMonikerImpl_Next
1530 ******************************************************************************/
1531 HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){
1533 ICOM_THIS(EnumMonikerImpl,iface);
1534 ULONG i;
1536 /* retrieve the requested number of moniker from the current position */
1537 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1539 rgelt[i]=This->tabMoniker[This->currentPos++];
1541 if (pceltFethed!=NULL)
1542 *pceltFethed= i;
1544 if (i==celt)
1545 return S_OK;
1546 else
1547 return S_FALSE;
1550 /******************************************************************************
1551 * EnumMonikerImpl_Skip
1552 ******************************************************************************/
1553 HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){
1555 ICOM_THIS(EnumMonikerImpl,iface);
1557 if ((This->currentPos+celt) >= This->tabSize)
1558 return S_FALSE;
1560 This->currentPos+=celt;
1562 return S_OK;
1565 /******************************************************************************
1566 * EnumMonikerImpl_Reset
1567 ******************************************************************************/
1568 HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){
1570 ICOM_THIS(EnumMonikerImpl,iface);
1572 This->currentPos=0;
1574 return S_OK;
1577 /******************************************************************************
1578 * EnumMonikerImpl_Clone
1579 ******************************************************************************/
1580 HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){
1582 ICOM_THIS(EnumMonikerImpl,iface);
1584 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1587 /******************************************************************************
1588 * EnumMonikerImpl_CreateEnumMoniker
1589 ******************************************************************************/
1590 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,
1591 ULONG tabSize,
1592 ULONG currentPos,
1593 BOOL leftToRigth,
1594 IEnumMoniker ** ppmk)
1596 EnumMonikerImpl* newEnumMoniker;
1597 int i;
1600 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1602 if (newEnumMoniker == 0)
1603 return STG_E_INSUFFICIENTMEMORY;
1605 if (currentPos > tabSize)
1606 return E_INVALIDARG;
1608 /* Initialize the virtual function table. */
1609 newEnumMoniker->lpvtbl = &VT_EnumMonikerImpl;
1610 newEnumMoniker->ref = 0;
1612 newEnumMoniker->tabSize=tabSize;
1613 newEnumMoniker->currentPos=currentPos;
1615 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1617 if (newEnumMoniker->tabMoniker==NULL)
1618 return E_OUTOFMEMORY;
1620 if (leftToRigth)
1621 for (i=0;i<tabSize;i++){
1623 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1624 IMoniker_AddRef(tabMoniker[i]);
1626 else
1627 for (i=tabSize-1;i>=0;i--){
1629 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1630 IMoniker_AddRef(tabMoniker[i]);
1633 *ppmk=(IEnumMoniker*)newEnumMoniker;
1635 return S_OK;
1638 /******************************************************************************
1639 * CreateCompositeMoniker [OLE.55]
1640 ******************************************************************************/
1641 HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite)
1643 CompositeMonikerImpl* newCompositeMoniker = 0;
1644 HRESULT hr = S_OK;
1646 TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1648 if (ppmkComposite==NULL)
1649 return E_POINTER;
1651 *ppmkComposite=0;
1653 if (pmkFirst==NULL && pmkRest!=NULL){
1655 *ppmkComposite=pmkRest;
1656 return S_OK;
1658 else if (pmkFirst!=NULL && pmkRest==NULL){
1659 *ppmkComposite=pmkFirst;
1660 return S_OK;
1662 else if (pmkFirst==NULL && pmkRest==NULL)
1663 return S_OK;
1665 newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
1667 if (newCompositeMoniker == 0)
1668 return STG_E_INSUFFICIENTMEMORY;
1670 hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
1672 if (FAILED(hr)){
1674 HeapFree(GetProcessHeap(),0,newCompositeMoniker);
1675 return hr;
1677 if (newCompositeMoniker->tabLastIndex==1)
1679 hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
1680 else
1682 hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
1684 return hr;
1687 /******************************************************************************
1688 * MonikerCommonPrefixWith [OLE.55]
1689 ******************************************************************************/
1690 HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1692 FIXME("(),stub!\n");
1693 return E_NOTIMPL;