No longer necessary.
[wine/multimedia.git] / ole / compositemoniker.c
blob35bef537d2e875a0e6e53819deb0ad937a8f1d9b
1 /***************************************************************************************
2 * CompositeMonikers implementation
4 * Copyright 1999 Noomen Hamza
5 ***************************************************************************************/
7 #include <assert.h>
8 #include "winerror.h"
9 #include "debug.h"
10 #include "heap.h"
11 #include "winuser.h"
12 #include "file.h"
13 #include "winreg.h"
14 #include "objbase.h"
15 #include "wine/obj_inplace.h"
16 #include "ole2.h"
18 DEFAULT_DEBUG_CHANNEL(ole)
20 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
22 /* CompositeMoniker data structure */
23 typedef struct CompositeMonikerImpl{
25 ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/
27 /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
28 * two monikers are equal. That's whay IROTData interface is implemented by monikers.
30 ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/
32 ULONG ref; /* reference counter for this object */
34 IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */
36 ULONG tabSize; /* size of tabMoniker */
38 ULONG tabLastIndex; /* first free index in tabMoniker */
40 } CompositeMonikerImpl;
43 /* EnumMoniker data structure */
44 typedef struct EnumMonikerImpl{
46 ICOM_VTABLE(IEnumMoniker)* lpvtbl; /* VTable relative to the IEnumMoniker interface.*/
48 ULONG ref; /* reference counter for this object */
50 IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
52 ULONG tabSize; /* size of tabMoniker */
54 ULONG currentPos; /* index pointer on the current moniker */
56 } EnumMonikerImpl;
59 /********************************************************************************/
60 /* CompositeMoniker prototype functions : */
62 /* IUnknown prototype functions */
63 static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
64 static ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface);
65 static ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface);
67 /* IPersist prototype functions */
68 static HRESULT WINAPI CompositeMonikerImpl_GetClassID(const IMoniker* iface, CLSID *pClassID);
70 /* IPersistStream prototype functions */
71 static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface);
72 static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm);
73 static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
74 static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
76 /* IMoniker prototype functions */
77 static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
78 static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
79 static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
80 static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
81 static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
82 static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
83 static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
84 static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
85 static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime);
86 static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
87 static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
88 static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
89 static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
90 static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
91 static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
93 /********************************************************************************/
94 /* IROTData prototype functions */
96 /* IUnknown prototype functions */
97 static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
98 static ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface);
99 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface);
101 /* IROTData prototype function */
102 static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
104 /* Local function used by CompositeMoniker implementation */
105 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest);
106 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface);
108 /********************************************************************************/
109 /* IEnumMoniker prototype functions */
111 /* IUnknown prototype functions */
112 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject);
113 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface);
114 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface);
116 /* IEnumMonker prototype functions */
117 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched);
118 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt);
119 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface);
120 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum);
122 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
124 /********************************************************************************/
125 /* Virtual function table for the CompositeMonikerImpl class witch include */
126 /* Ipersist, IPersistStream and IMoniker functions. */
128 static ICOM_VTABLE(IMoniker) VT_CompositeMonikerImpl =
130 CompositeMonikerImpl_QueryInterface,
131 CompositeMonikerImpl_AddRef,
132 CompositeMonikerImpl_Release,
133 CompositeMonikerImpl_GetClassID,
134 CompositeMonikerImpl_IsDirty,
135 CompositeMonikerImpl_Load,
136 CompositeMonikerImpl_Save,
137 CompositeMonikerImpl_GetSizeMax,
138 CompositeMonikerImpl_BindToObject,
139 CompositeMonikerImpl_BindToStorage,
140 CompositeMonikerImpl_Reduce,
141 CompositeMonikerImpl_ComposeWith,
142 CompositeMonikerImpl_Enum,
143 CompositeMonikerImpl_IsEqual,
144 CompositeMonikerImpl_Hash,
145 CompositeMonikerImpl_IsRunning,
146 CompositeMonikerImpl_GetTimeOfLastChange,
147 CompositeMonikerImpl_Inverse,
148 CompositeMonikerImpl_CommonPrefixWith,
149 CompositeMonikerImpl_RelativePathTo,
150 CompositeMonikerImpl_GetDisplayName,
151 CompositeMonikerImpl_ParseDisplayName,
152 CompositeMonikerImpl_IsSystemMoniker
155 /********************************************************************************/
156 /* Virtual function table for the IROTData class. */
157 static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
159 CompositeMonikerROTDataImpl_QueryInterface,
160 CompositeMonikerROTDataImpl_AddRef,
161 CompositeMonikerROTDataImpl_Release,
162 CompositeMonikerROTDataImpl_GetComparaisonData
165 /********************************************************************************/
166 /* Virtual function table for the IROTData class */
167 static ICOM_VTABLE(IEnumMoniker) VT_EnumMonikerImpl =
169 EnumMonikerImpl_QueryInterface,
170 EnumMonikerImpl_AddRef,
171 EnumMonikerImpl_Release,
172 EnumMonikerImpl_Next,
173 EnumMonikerImpl_Skip,
174 EnumMonikerImpl_Reset,
175 EnumMonikerImpl_Clone
178 /*******************************************************************************
179 * CompositeMoniker_QueryInterface
180 *******************************************************************************/
181 HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
183 ICOM_THIS(CompositeMonikerImpl,iface);
185 TRACE(ole,"(%p,%p,%p)\n",This,riid,ppvObject);
187 /* Perform a sanity check on the parameters.*/
188 if ( (This==0) || (ppvObject==0) )
189 return E_INVALIDARG;
191 /* Initialize the return parameter */
192 *ppvObject = 0;
194 /* Compare the riid with the interface IDs implemented by this object.*/
195 if (IsEqualIID(&IID_IUnknown, riid) ||
196 IsEqualIID(&IID_IPersist, riid) ||
197 IsEqualIID(&IID_IPersistStream, riid) ||
198 IsEqualIID(&IID_IMoniker, riid)
200 *ppvObject = iface;
201 else if (IsEqualIID(&IID_IROTData, riid))
202 *ppvObject = (IROTData*)&(This->lpvtbl2);
204 /* Check that we obtained an interface.*/
205 if ((*ppvObject)==0)
206 return E_NOINTERFACE;
208 /* Query Interface always increases the reference count by one when it is successful */
209 CompositeMonikerImpl_AddRef(iface);
211 return S_OK;
214 /******************************************************************************
215 * CompositeMoniker_AddRef
216 ******************************************************************************/
217 ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)
219 ICOM_THIS(CompositeMonikerImpl,iface);
221 TRACE(ole,"(%p)\n",This);
223 return ++(This->ref);
226 /******************************************************************************
227 * CompositeMoniker_Release
228 ******************************************************************************/
229 ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
231 ICOM_THIS(CompositeMonikerImpl,iface);
232 ULONG i;
234 TRACE(ole,"(%p)\n",This);
236 This->ref--;
238 /* destroy the object if there's no more reference on it */
239 if (This->ref==0){
241 /* release all the components before destroying this object */
242 for (i=0;i<This->tabLastIndex;i++)
243 IMoniker_Release(This->tabMoniker[i]);
245 CompositeMonikerImpl_Destroy(This);
247 return 0;
249 return This->ref;;
252 /******************************************************************************
253 * CompositeMoniker_GetClassID
254 ******************************************************************************/
255 HRESULT WINAPI CompositeMonikerImpl_GetClassID(const IMoniker* iface,CLSID *pClassID)
257 TRACE(ole,"(%p,%p),stub!\n",iface,pClassID);
259 if (pClassID==NULL)
260 return E_POINTER;
262 *pClassID = CLSID_CompositeMoniker;
264 return S_OK;
267 /******************************************************************************
268 * CompositeMoniker_IsDirty
269 ******************************************************************************/
270 HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)
272 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
273 method in the OLE-provided moniker interfaces always return S_FALSE because
274 their internal state never changes. */
276 TRACE(ole,"(%p)\n",iface);
278 return S_FALSE;
281 /******************************************************************************
282 * CompositeMoniker_Load
283 ******************************************************************************/
284 HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
286 HRESULT res;
287 DWORD constant;
288 CLSID clsid;
289 WCHAR string[1]={0};
291 ICOM_THIS(CompositeMonikerImpl,iface);
293 TRACE(ole,"(%p,%p)\n",iface,pStm);
295 /* this function call OleLoadFromStream function for each moniker within this object */
297 /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
298 res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
300 if (SUCCEEDED(res)&& constant!=3)
301 return E_FAIL;
303 while(1){
304 #if 0
305 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
306 #endif
307 res=ReadClassStm(pStm,&clsid);
308 printf("res=%ld",res);
309 if (FAILED(res))
310 break;
312 if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
313 res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
314 if (FAILED(res))
315 break;
316 res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
317 if (FAILED(res))
318 break;
320 else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
321 CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
322 if (res!=S_OK)
323 break;
324 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
325 if (FAILED(res))
326 break;
328 else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
329 CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
330 if (FAILED(res))
331 break;
332 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
333 if (FAILED(res))
334 break;
336 else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
337 return E_FAIL;
339 else{
340 FIXME(ole,"()");
341 break;
342 return E_NOTIMPL;
345 /* resize the table if needed */
346 if (++This->tabLastIndex==This->tabSize){
348 This->tabSize+=BLOCK_TAB_SIZE;
349 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
351 if (This->tabMoniker==NULL)
352 return E_OUTOFMEMORY;
356 return res;
359 /******************************************************************************
360 * CompositeMoniker_Save
361 ******************************************************************************/
362 HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
364 HRESULT res;
365 IEnumMoniker *enumMk;
366 IMoniker *pmk;
367 DWORD constant=3;
369 TRACE(ole,"(%p,%p,%d)\n",iface,pStm,fClearDirty);
371 /* this function call OleSaveToStream function for each moniker within this object */
373 /* when I tested this function in windows system ! I usually found this constant in the begining of */
374 /* the stream I dont known why (there's no indication in specification) ! */
375 res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
377 IMoniker_Enum(iface,TRUE,&enumMk);
379 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
381 res=OleSaveToStream((IPersistStream*)pmk,pStm);
383 IMoniker_Release(pmk);
385 if (FAILED(res)){
387 IEnumMoniker_Release(pmk);
388 return res;
392 IEnumMoniker_Release(enumMk);
394 return S_OK;
397 /******************************************************************************
398 * CompositeMoniker_GetSizeMax
399 ******************************************************************************/
400 HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
402 IEnumMoniker *enumMk;
403 IMoniker *pmk;
404 ULARGE_INTEGER ptmpSize;
406 /* the sizeMax of this object is calculated by calling GetSizeMax on each moniker within this object then */
407 /* suming all returned sizemax */
409 TRACE(ole,"(%p,%p)\n",iface,pcbSize);
411 if (pcbSize!=NULL)
412 return E_POINTER;
414 pcbSize->LowPart =0;
415 pcbSize->HighPart=0;
417 IMoniker_Enum(iface,TRUE,&enumMk);
419 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){
421 IMoniker_GetSizeMax(pmk,&ptmpSize);
423 IMoniker_Release(pmk);
425 pcbSize->LowPart +=ptmpSize.LowPart;
426 pcbSize->HighPart+=ptmpSize.HighPart;
429 IEnumMoniker_Release(enumMk);
431 return S_OK;
434 /******************************************************************************
435 * Composite-Moniker_Construct (local function)
436 *******************************************************************************/
437 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest)
439 DWORD mkSys;
440 IEnumMoniker *enumMoniker;
441 IMoniker *tempMk;
442 HRESULT res;
444 TRACE(ole,"(%p,%p,%p)\n",This,pmkFirst,pmkRest);
446 /* Initialize the virtual fgunction table. */
447 This->lpvtbl1 = &VT_CompositeMonikerImpl;
448 This->lpvtbl2 = &VT_ROTDataImpl;
449 This->ref = 0;
451 This->tabSize=BLOCK_TAB_SIZE;
452 This->tabLastIndex=0;
454 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
455 if (This->tabMoniker==NULL)
456 return E_OUTOFMEMORY;
458 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
460 /* put the first moniker contents in the begining of the table */
461 if (mkSys!=MKSYS_GENERICCOMPOSITE){
463 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
464 IMoniker_AddRef(pmkFirst);
466 else{
468 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
470 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
473 if (++This->tabLastIndex==This->tabSize){
475 This->tabSize+=BLOCK_TAB_SIZE;
476 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
478 if (This->tabMoniker==NULL)
479 return E_OUTOFMEMORY;
483 IEnumMoniker_Release(enumMoniker);
486 /* put the rest moniker contents after the first one and make simplification if needed */
488 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
490 if (mkSys!=MKSYS_GENERICCOMPOSITE){
492 /* add a simple moniker to the moniker table */
494 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
496 if (res==MK_E_NEEDGENERIC){
498 /* there's no simplification in this case */
499 This->tabMoniker[This->tabLastIndex]=pmkRest;
501 This->tabLastIndex++;
503 IMoniker_AddRef(pmkRest);
505 else if (tempMk==NULL){
507 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
508 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
510 This->tabLastIndex--;
512 else if (SUCCEEDED(res)){
514 /* the non-generic composition was successful so we can make a simplification in this case */
515 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
517 This->tabMoniker[This->tabLastIndex-1]=tempMk;
518 } else
519 return res;
521 /* resize tabMoniker if needed */
522 if (This->tabLastIndex==This->tabSize){
524 This->tabSize+=BLOCK_TAB_SIZE;
526 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
528 if (This->tabMoniker==NULL)
529 return E_OUTOFMEMORY;
532 else{
534 /* add a composite moniker to the moniker table (do the same thing for each moniker within the */
535 /* composite moniker as a simple moniker (see above how to add a simple moniker case) ) */
536 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
538 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
540 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
542 if (res==MK_E_NEEDGENERIC){
544 This->tabLastIndex++;
546 else if (tempMk==NULL){
548 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
549 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
550 This->tabLastIndex--;
552 else{
554 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
556 This->tabMoniker[This->tabLastIndex-1]=tempMk;
559 if (This->tabLastIndex==This->tabSize){
561 This->tabSize+=BLOCK_TAB_SIZE;
563 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
565 if (This->tabMoniker==NULL)
566 return E_OUTOFMEMORY;
570 IEnumMoniker_Release(enumMoniker);
573 return S_OK;
576 /******************************************************************************
577 * CompositeMoniker_Destroy (local function)
578 *******************************************************************************/
579 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This)
581 TRACE(ole,"(%p)\n",This);
583 HeapFree(GetProcessHeap(),0,This->tabMoniker);
585 HeapFree(GetProcessHeap(),0,This);
587 return S_OK;
590 /******************************************************************************
591 * CompositeMoniker_BindToObject
592 ******************************************************************************/
593 HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,
594 IBindCtx* pbc,
595 IMoniker* pmkToLeft,
596 REFIID riid,
597 VOID** ppvResult)
599 HRESULT res;
600 IRunningObjectTable *prot;
601 IMoniker *tempMk,*antiMk,*mostRigthMk;
602 IEnumMoniker *enumMoniker;
604 TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
606 if (ppvResult==NULL)
607 return E_POINTER;
609 *ppvResult=0;
610 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
611 /* object for the requested interface pointer. */
612 if(pmkToLeft==NULL){
614 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
616 if (SUCCEEDED(res)){
618 /* if the requested class was loaded befor ! we dont need to reload it */
619 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
621 if (res==S_OK)
622 return res;
625 else{
626 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
627 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
629 IMoniker_Enum(iface,FALSE,&enumMoniker);
630 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
631 IEnumMoniker_Release(enumMoniker);
633 res=CreateAntiMoniker(&antiMk);
634 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
635 IMoniker_Release(antiMk);
637 res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
639 IMoniker_Release(tempMk);
640 IMoniker_Release(mostRigthMk);
643 return res;
646 /******************************************************************************
647 * CompositeMoniker_BindToStorage
648 ******************************************************************************/
649 HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,
650 IBindCtx* pbc,
651 IMoniker* pmkToLeft,
652 REFIID riid,
653 VOID** ppvResult)
655 HRESULT res;
656 IMoniker *tempMk,*antiMk,*mostRigthMk;
657 IEnumMoniker *enumMoniker;
659 TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
661 *ppvResult=0;
663 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
664 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
666 if (pmkToLeft!=NULL){
668 IMoniker_Enum(iface,FALSE,&enumMoniker);
669 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
670 IEnumMoniker_Release(enumMoniker);
672 res=CreateAntiMoniker(&antiMk);
673 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
674 IMoniker_Release(antiMk);
676 res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
678 IMoniker_Release(tempMk);
680 IMoniker_Release(mostRigthMk);
682 return res;
684 else
685 return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
688 /******************************************************************************
689 * CompositeMoniker_Reduce
690 ******************************************************************************/
691 HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,
692 IBindCtx* pbc,
693 DWORD dwReduceHowFar,
694 IMoniker** ppmkToLeft,
695 IMoniker** ppmkReduced)
697 HRESULT res;
698 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
699 IEnumMoniker *enumMoniker;
701 TRACE(ole,"(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
703 if (ppmkReduced==NULL)
704 return E_POINTER;
706 /* This method recursively calls Reduce for each of its component monikers. */
708 if (ppmkToLeft==NULL){
710 IMoniker_Enum(iface,FALSE,&enumMoniker);
711 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
712 IEnumMoniker_Release(enumMoniker);
714 res=CreateAntiMoniker(&antiMk);
715 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
716 IMoniker_Release(antiMk);
718 return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
720 else if (*ppmkToLeft==NULL)
722 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
724 else{
726 /* separate the copmosite moniker in to left and wrigth moniker */
727 IMoniker_Enum(iface,FALSE,&enumMoniker);
728 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
729 IEnumMoniker_Release(enumMoniker);
731 res=CreateAntiMoniker(&antiMk);
732 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
733 IMoniker_Release(antiMk);
735 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
736 /* of the reduced components */
737 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
738 CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
741 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
743 else{
744 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
746 IMoniker_AddRef(iface);
748 *ppmkReduced=iface;
750 return MK_S_REDUCED_TO_SELF;
755 /******************************************************************************
756 * CompositeMoniker_ComposeWith
757 ******************************************************************************/
758 HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,
759 IMoniker* pmkRight,
760 BOOL fOnlyIfNotGeneric,
761 IMoniker** ppmkComposite)
763 TRACE(ole,"(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
765 if ((ppmkComposite==NULL)||(pmkRight==NULL))
766 return E_POINTER;
768 *ppmkComposite=0;
770 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
771 /* otherwise, the method returns the result of combining the two monikers by calling the */
772 /* CreateGenericComposite function */
774 if (fOnlyIfNotGeneric)
775 return MK_E_NEEDGENERIC;
777 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
780 /******************************************************************************
781 * CompositeMoniker_Enum
782 ******************************************************************************/
783 HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
785 ICOM_THIS(CompositeMonikerImpl,iface);
787 TRACE(ole,"(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
789 if (ppenumMoniker == NULL)
790 return E_POINTER;
792 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
795 /******************************************************************************
796 * CompositeMoniker_IsEqual
797 ******************************************************************************/
798 HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
800 IEnumMoniker *enumMoniker1,*enumMoniker2;
801 IMoniker *tempMk1,*tempMk2;
802 HRESULT res1,res2,res;
804 TRACE(ole,"(%p,%p)\n",iface,pmkOtherMoniker);
806 if (pmkOtherMoniker==NULL)
807 return S_FALSE;
809 /* This method returns S_OK if the components of both monikers are equal when compared in the */
810 /* left-to-right order.*/
811 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
813 if (enumMoniker1==NULL)
814 return S_FALSE;
816 IMoniker_Enum(iface,TRUE,&enumMoniker2);
818 while(1){
820 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
821 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
823 if((res1==S_OK)&&(res2==S_OK)){
825 if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
826 res= S_FALSE;
827 break;
829 else
830 continue;
832 else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
833 res = S_OK;
834 break;
836 else{
837 res = S_FALSE;
838 break;
841 if (res1==S_OK)
842 IMoniker_Release(tempMk1);
844 if (res2==S_OK)
845 IMoniker_Release(tempMk2);
848 IEnumMoniker_Release(enumMoniker1);
849 IEnumMoniker_Release(enumMoniker2);
851 return res;
853 /******************************************************************************
854 * CompositeMoniker_Hash
855 ******************************************************************************/
856 HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
858 FIXME(ole,"(),stub!\n");
860 return E_NOTIMPL;
863 /******************************************************************************
864 * CompositeMoniker_IsRunning
865 ******************************************************************************/
866 HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,
867 IBindCtx* pbc,
868 IMoniker* pmkToLeft,
869 IMoniker* pmkNewlyRunning)
871 IRunningObjectTable* rot;
872 HRESULT res;
873 IMoniker *tempMk,*antiMk,*mostRigthMk;
874 IEnumMoniker *enumMoniker;
876 TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
878 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
879 if (pmkToLeft!=NULL){
881 CreateGenericComposite(pmkToLeft,iface,&tempMk);
883 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
885 IMoniker_Release(tempMk);
887 return res;
889 else
890 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
891 /* to this moniker */
893 if (pmkNewlyRunning!=NULL)
895 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
896 return S_OK;
898 else
899 return S_FALSE;
901 else{
903 if (pbc==NULL)
904 return E_POINTER;
906 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
907 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
908 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
909 /* the composite as the pmkToLeft parameter for that call. */
911 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
913 if (FAILED(res))
914 return res;
916 res = IRunningObjectTable_IsRunning(rot,iface);
917 IRunningObjectTable_Release(rot);
919 if(res==S_OK)
920 return S_OK;
922 else{
924 IMoniker_Enum(iface,FALSE,&enumMoniker);
925 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
926 IEnumMoniker_Release(enumMoniker);
928 res=CreateAntiMoniker(&antiMk);
929 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
930 IMoniker_Release(antiMk);
932 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
934 IMoniker_Release(tempMk);
935 IMoniker_Release(mostRigthMk);
937 return res;
942 /******************************************************************************
943 * CompositeMoniker_GetTimeOfLastChange
944 ******************************************************************************/
945 HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
946 IBindCtx* pbc,
947 IMoniker* pmkToLeft,
948 FILETIME* pCompositeTime)
950 IRunningObjectTable* rot;
951 HRESULT res;
952 IMoniker *tempMk,*antiMk,*mostRigthMk;
953 IEnumMoniker *enumMoniker;
955 TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
957 if (pCompositeTime==NULL)
958 return E_INVALIDARG;
960 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
961 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
962 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
963 /* of the composite as the pmkToLeft parameter for that call. */
964 if (pmkToLeft!=NULL){
966 res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
968 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
970 if (FAILED(res))
971 return res;
973 if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
974 return res;
975 else
977 IMoniker_Enum(iface,FALSE,&enumMoniker);
978 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
979 IEnumMoniker_Release(enumMoniker);
981 res=CreateAntiMoniker(&antiMk);
982 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
983 IMoniker_Release(antiMk);
985 res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
987 IMoniker_Release(tempMk);
988 IMoniker_Release(mostRigthMk);
990 return res;
992 else
993 return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
996 /******************************************************************************
997 * CompositeMoniker_Inverse
998 ******************************************************************************/
999 HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
1001 HRESULT res;
1002 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
1003 IEnumMoniker *enumMoniker;
1005 TRACE(ole,"(%p,%p)\n",iface,ppmk);
1007 if (ppmk==NULL)
1008 return E_POINTER;
1010 /* This method returns a composite moniker that consists of the inverses of each of the components */
1011 /* of the original composite, stored in reverse order */
1013 res=CreateAntiMoniker(&antiMk);
1014 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1015 IMoniker_Release(antiMk);
1017 if (tempMk==NULL)
1019 return IMoniker_Inverse(iface,ppmk);
1021 else{
1023 IMoniker_Enum(iface,FALSE,&enumMoniker);
1024 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1025 IEnumMoniker_Release(enumMoniker);
1027 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
1028 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
1030 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
1032 IMoniker_Release(tempMk);
1033 IMoniker_Release(mostRigthMk);
1034 IMoniker_Release(tempInvMk);
1035 IMoniker_Release(mostRigthInvMk);
1037 return res;
1041 /******************************************************************************
1042 * CompositeMoniker_CommonPrefixWith
1043 ******************************************************************************/
1044 HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1046 DWORD mkSys;
1047 HRESULT res1,res2;
1048 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
1049 IEnumMoniker *enumMoniker1,*enumMoniker2;
1050 ULONG i,nbCommonMk=0;
1052 /* If the other moniker is a composite, this method compares the components of each composite from left */
1053 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1054 /* of the leftmost components were common to both monikers. */
1056 if (ppmkPrefix==NULL)
1057 return E_POINTER;
1059 *ppmkPrefix=0;
1061 if (pmkOther==NULL)
1062 return MK_E_NOPREFIX;
1064 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1066 if((mkSys==MKSYS_GENERICCOMPOSITE)){
1068 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1069 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
1071 while(1){
1073 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1074 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
1076 if ((res1==S_FALSE) && (res2==S_FALSE)){
1078 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1079 *ppmkPrefix=iface;
1080 IMoniker_AddRef(iface);
1081 return MK_S_US;
1083 else if ((res1==S_OK) && (res2==S_OK)){
1085 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
1087 nbCommonMk++;
1089 else
1090 break;
1093 else if (res1==S_OK){
1095 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1096 /* ppmkPrefix to the other moniker. */
1097 *ppmkPrefix=pmkOther;
1098 return MK_S_HIM;
1100 else{
1101 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1102 /* to this moniker. */
1103 *ppmkPrefix=iface;
1104 return MK_S_ME;
1108 IEnumMoniker_Release(enumMoniker1);
1109 IEnumMoniker_Release(enumMoniker2);
1111 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1112 if (nbCommonMk==0)
1113 return MK_E_NOPREFIX;
1115 IEnumMoniker_Reset(enumMoniker1);
1117 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1119 /* if we have more than one commun moniker the result will be a composite moniker */
1120 if (nbCommonMk>1){
1122 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1123 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1124 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
1125 IMoniker_Release(tempMk1);
1126 IMoniker_Release(tempMk2);
1128 /* compose all common monikers in a composite moniker */
1129 for(i=0;i<nbCommonMk;i++){
1131 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1133 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
1135 IMoniker_Release(*ppmkPrefix);
1137 IMoniker_Release(tempMk1);
1139 *ppmkPrefix=tempMk2;
1141 return S_OK;
1143 else{
1144 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1145 *ppmkPrefix=tempMk1;
1147 return S_OK;
1150 else{
1151 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1152 of this moniker.*/
1154 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1156 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1158 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
1160 *ppmkPrefix=pmkOther;
1162 return MK_S_HIM;
1164 else
1165 return MK_E_NOPREFIX;
1168 /***************************************************************************************************
1169 * GetAfterCommonPrefix (local function)
1170 * This function returns a moniker that consist of the remainder when the common prefix is removed
1171 ***************************************************************************************************/
1172 VOID WINAPI GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
1174 IMoniker *tempMk,*tempMk1,*tempMk2;
1175 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
1176 ULONG nbRestMk=0;
1177 DWORD mkSys;
1178 HRESULT res1,res2;
1180 *restMk=0;
1182 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1183 /* prefix: enum the two monikers (left-wrigth) then compare these enumerations (left-wrigth) and stop */
1184 /* on the first difference. */
1185 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
1187 IMoniker_IsSystemMoniker(commonMk,&mkSys);
1189 if (mkSys==MKSYS_GENERICCOMPOSITE){
1191 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
1192 while(1){
1194 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1195 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
1197 if ((res1==S_FALSE)||(res2==S_FALSE)){
1199 if (res1==S_OK)
1201 nbRestMk++;
1203 IMoniker_Release(tempMk1);
1204 IMoniker_Release(tempMk1);
1206 break;
1208 IMoniker_Release(tempMk1);
1209 IMoniker_Release(tempMk1);
1212 else{
1213 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1214 IMoniker_Release(tempMk1);
1217 /* count the number of elements in the enumerator after the common prefix */
1218 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1220 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1222 IMoniker_Release(tempMk);;
1224 if (nbRestMk==0)
1225 return;
1227 /* create a generic composite moniker with monikers located after the common prefix */
1228 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1230 if (nbRestMk==1){
1232 *restMk= tempMk1;
1233 return;
1235 else {
1237 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1239 CreateGenericComposite(tempMk1,tempMk2,restMk);
1241 IMoniker_Release(tempMk1);
1243 IMoniker_Release(tempMk2);
1245 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1247 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1249 IMoniker_Release(tempMk1);
1251 IMoniker_Release(*restMk);
1253 *restMk=tempMk2;
1257 /******************************************************************************
1258 * CompositeMoniker_RelativePathTo
1259 ******************************************************************************/
1260 HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkRelPath)
1262 HRESULT res;
1263 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1265 TRACE(ole,"(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1267 if (ppmkRelPath==NULL)
1268 return E_POINTER;
1270 *ppmkRelPath=0;
1272 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1273 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1274 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1276 /* finds the common prefix of the two monikers */
1277 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1279 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1280 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1282 *ppmkRelPath=pmkOther;
1283 IMoniker_AddRef(pmkOther);
1284 return MK_S_HIM;
1287 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1288 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1290 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1291 /* moniker when the common prefix is removed */
1292 if (res==MK_S_HIM){
1294 IMoniker_Inverse(restThisMk,ppmkRelPath);
1295 IMoniker_Release(restThisMk);
1297 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1298 /* when the common prefix is removed */
1299 else if (res==MK_S_ME){
1301 *ppmkRelPath=restOtherMk;
1302 IMoniker_AddRef(restOtherMk);
1304 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1305 /* moniker on the right of it. */
1306 else if (res==S_OK){
1308 IMoniker_Inverse(restThisMk,&invRestThisMk);
1309 IMoniker_Release(restThisMk);
1310 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1311 IMoniker_Release(invRestThisMk);
1312 IMoniker_Release(restOtherMk);
1314 return S_OK;
1317 /******************************************************************************
1318 * CompositeMoniker_GetDisplayName
1319 ******************************************************************************/
1320 HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,
1321 IBindCtx* pbc,
1322 IMoniker* pmkToLeft,
1323 LPOLESTR *ppszDisplayName)
1325 ULONG lengthStr=1;
1326 IEnumMoniker *enumMoniker;
1327 IMoniker* tempMk;
1328 LPOLESTR tempStr;
1330 TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1332 if (ppszDisplayName==NULL)
1333 return E_POINTER;
1335 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1337 if (*ppszDisplayName==NULL)
1338 return E_OUTOFMEMORY;
1340 /* This method returns the concatenation of the display names returned by each component moniker of */
1341 /* the composite */
1343 **ppszDisplayName=0;
1345 IMoniker_Enum(iface,TRUE,&enumMoniker);
1347 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1349 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1351 lengthStr+=lstrlenW(tempStr);
1353 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1355 if (*ppszDisplayName==NULL)
1356 return E_OUTOFMEMORY;
1358 lstrcatW(*ppszDisplayName,tempStr);
1360 CoTaskMemFree(tempStr);
1361 IMoniker_Release(tempMk);
1364 IEnumMoniker_Release(enumMoniker);
1366 return S_OK;
1369 /******************************************************************************
1370 * CompositeMoniker_ParseDisplayName
1371 ******************************************************************************/
1372 HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,
1373 IBindCtx* pbc,
1374 IMoniker* pmkToLeft,
1375 LPOLESTR pszDisplayName,
1376 ULONG* pchEaten,
1377 IMoniker** ppmkOut)
1379 IEnumMoniker *enumMoniker;
1380 IMoniker *tempMk,*mostRigthMk,*antiMk;
1381 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1382 /* passing everything else as the pmkToLeft parameter for that call. */
1384 /* get the most rigth moniker */
1385 IMoniker_Enum(iface,FALSE,&enumMoniker);
1386 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1387 IEnumMoniker_Release(enumMoniker);
1389 /* get the left moniker */
1390 CreateAntiMoniker(&antiMk);
1391 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1392 IMoniker_Release(antiMk);
1394 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1397 /******************************************************************************
1398 * CompositeMoniker_IsSystemMonker
1399 ******************************************************************************/
1400 HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1402 TRACE(ole,"(%p,%p)\n",iface,pwdMksys);
1404 if (!pwdMksys)
1405 return E_POINTER;
1407 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1409 return S_OK;
1412 /*******************************************************************************
1413 * CompositeMonikerIROTData_QueryInterface
1414 *******************************************************************************/
1415 HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1418 ICOM_THIS_From_IROTData(IMoniker, iface);
1420 TRACE(ole,"(%p,%p,%p)\n",iface,riid,ppvObject);
1422 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1425 /***********************************************************************
1426 * CompositeMonikerIROTData_AddRef
1428 ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1430 ICOM_THIS_From_IROTData(IMoniker, iface);
1432 TRACE(ole,"(%p)\n",iface);
1434 return CompositeMonikerImpl_AddRef(This);
1437 /***********************************************************************
1438 * CompositeMonikerIROTData_Release
1440 ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1442 ICOM_THIS_From_IROTData(IMoniker, iface);
1444 TRACE(ole,"(%p)\n",iface);
1446 return CompositeMonikerImpl_Release(This);
1449 /******************************************************************************
1450 * CompositeMonikerIROTData_GetComparaisonData
1451 ******************************************************************************/
1452 HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1453 BYTE* pbData,
1454 ULONG cbMax,
1455 ULONG* pcbData)
1457 FIXME(ole,"(),stub!\n");
1458 return E_NOTIMPL;
1461 /******************************************************************************
1462 * EnumMonikerImpl_QueryInterface
1463 ******************************************************************************/
1464 HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1466 ICOM_THIS(EnumMonikerImpl,iface);
1468 TRACE(ole,"(%p,%p,%p)\n",This,riid,ppvObject);
1470 /* Perform a sanity check on the parameters.*/
1471 if ( (This==0) || (ppvObject==0) )
1472 return E_INVALIDARG;
1474 /* Initialize the return parameter */
1475 *ppvObject = 0;
1477 /* Compare the riid with the interface IDs implemented by this object.*/
1478 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1479 *ppvObject = iface;
1481 /* Check that we obtained an interface.*/
1482 if ((*ppvObject)==0)
1483 return E_NOINTERFACE;
1485 /* Query Interface always increases the reference count by one when it is successful */
1486 EnumMonikerImpl_AddRef(iface);
1488 return S_OK;
1491 /******************************************************************************
1492 * EnumMonikerImpl_AddRef
1493 ******************************************************************************/
1494 ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1496 ICOM_THIS(EnumMonikerImpl,iface);
1498 TRACE(ole,"(%p)\n",This);
1500 return ++(This->ref);
1504 /******************************************************************************
1505 * EnumMonikerImpl_Release
1506 ******************************************************************************/
1507 ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1509 ICOM_THIS(EnumMonikerImpl,iface);
1510 ULONG i
1512 TRACE(ole,"(%p)\n",This);
1514 This->ref--;
1516 /* destroy the object if there's no more reference on it */
1517 if (This->ref==0){
1519 for(i=0;i<This->tabSize;i++)
1520 IMoniker_Release(This->tabMoniker[i]);
1522 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1523 HeapFree(GetProcessHeap(),0,This);
1525 return 0;
1527 return This->ref;;
1530 /******************************************************************************
1531 * EnumMonikerImpl_Next
1532 ******************************************************************************/
1533 HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){
1535 ICOM_THIS(EnumMonikerImpl,iface);
1536 ULONG i;
1538 /* retrieve the requested number of moniker from the current position */
1539 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1541 rgelt[i]=This->tabMoniker[This->currentPos++];
1543 if (pceltFethed!=NULL)
1544 *pceltFethed= i;
1546 if (i==celt)
1547 return S_OK;
1548 else
1549 return S_FALSE;
1552 /******************************************************************************
1553 * EnumMonikerImpl_Skip
1554 ******************************************************************************/
1555 HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){
1557 ICOM_THIS(EnumMonikerImpl,iface);
1559 if ((This->currentPos+celt) >= This->tabSize)
1560 return S_FALSE;
1562 This->currentPos+=celt;
1564 return S_OK;
1567 /******************************************************************************
1568 * EnumMonikerImpl_Reset
1569 ******************************************************************************/
1570 HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){
1572 ICOM_THIS(EnumMonikerImpl,iface);
1574 This->currentPos=0;
1576 return S_OK;
1579 /******************************************************************************
1580 * EnumMonikerImpl_Clone
1581 ******************************************************************************/
1582 HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){
1584 ICOM_THIS(EnumMonikerImpl,iface);
1586 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1589 /******************************************************************************
1590 * EnumMonikerImpl_CreateEnumMoniker
1591 ******************************************************************************/
1592 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,
1593 ULONG tabSize,
1594 ULONG currentPos,
1595 BOOL leftToRigth,
1596 IEnumMoniker ** ppmk)
1598 EnumMonikerImpl* newEnumMoniker;
1599 int i;
1602 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1604 if (newEnumMoniker == 0)
1605 return STG_E_INSUFFICIENTMEMORY;
1607 if (currentPos > tabSize)
1608 return E_INVALIDARG;
1610 /* Initialize the virtual function table. */
1611 newEnumMoniker->lpvtbl = &VT_EnumMonikerImpl;
1612 newEnumMoniker->ref = 0;
1614 newEnumMoniker->tabSize=tabSize;
1615 newEnumMoniker->currentPos=currentPos;
1617 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1619 if (newEnumMoniker->tabMoniker==NULL)
1620 return E_OUTOFMEMORY;
1622 if (leftToRigth)
1623 for (i=0;i<tabSize;i++){
1625 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1626 IMoniker_AddRef(tabMoniker[i]);
1628 else
1629 for (i=tabSize-1;i>=0;i--){
1631 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1632 IMoniker_AddRef(tabMoniker[i]);
1635 *ppmk=(IEnumMoniker*)newEnumMoniker;
1637 return S_OK;
1640 /******************************************************************************
1641 * CreateCompositeMoniker [OLE.55]
1642 ******************************************************************************/
1643 HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite)
1645 CompositeMonikerImpl* newCompositeMoniker = 0;
1646 HRESULT hr = S_OK;
1648 TRACE(ole,"(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1650 if (ppmkComposite==NULL)
1651 return E_POINTER;
1653 *ppmkComposite=0;
1655 if (pmkFirst==NULL && pmkRest!=NULL){
1657 *ppmkComposite=pmkRest;
1658 return S_OK;
1660 else if (pmkFirst!=NULL && pmkRest==NULL){
1661 *ppmkComposite=pmkFirst;
1662 return S_OK;
1664 else if (pmkFirst==NULL && pmkRest==NULL)
1665 return S_OK;
1667 newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
1669 if (newCompositeMoniker == 0)
1670 return STG_E_INSUFFICIENTMEMORY;
1672 hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
1674 if (FAILED(hr)){
1676 HeapFree(GetProcessHeap(),0,newCompositeMoniker);
1677 return hr;
1679 if (newCompositeMoniker->tabLastIndex==1)
1681 hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
1682 else
1684 hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
1686 return hr;
1689 /******************************************************************************
1690 * MonikerCommonPrefixWith [OLE.55]
1691 ******************************************************************************/
1692 HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1694 FIXME(ole,"(),stub!\n");
1695 return E_NOTIMPL;