Replaced all lstr* calls from inside Wine code by their str* equivalent.
[wine.git] / dlls / ole32 / compositemoniker.c
bloba53c627dbce1d1734f2e226de58541e61bb70060
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 "wine/unicode.h"
12 #include "ole2.h"
14 DEFAULT_DEBUG_CHANNEL(ole);
16 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
18 /* CompositeMoniker data structure */
19 typedef struct CompositeMonikerImpl{
21 ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/
23 /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
24 * two monikers are equal. That's whay IROTData interface is implemented by monikers.
26 ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/
28 ULONG ref; /* reference counter for this object */
30 IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */
32 ULONG tabSize; /* size of tabMoniker */
34 ULONG tabLastIndex; /* first free index in tabMoniker */
36 } CompositeMonikerImpl;
39 /* EnumMoniker data structure */
40 typedef struct EnumMonikerImpl{
42 ICOM_VFIELD(IEnumMoniker); /* VTable relative to the IEnumMoniker interface.*/
44 ULONG ref; /* reference counter for this object */
46 IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
48 ULONG tabSize; /* size of tabMoniker */
50 ULONG currentPos; /* index pointer on the current moniker */
52 } EnumMonikerImpl;
55 /********************************************************************************/
56 /* CompositeMoniker prototype functions : */
58 /* IUnknown prototype functions */
59 static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
60 static ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface);
61 static ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface);
63 /* IPersist prototype functions */
64 static HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
66 /* IPersistStream prototype functions */
67 static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface);
68 static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm);
69 static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
70 static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
72 /* IMoniker prototype functions */
73 static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
74 static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
75 static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
76 static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
77 static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
78 static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
79 static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
80 static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
81 static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime);
82 static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
83 static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
84 static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
85 static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
86 static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
87 static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
89 /********************************************************************************/
90 /* IROTData prototype functions */
92 /* IUnknown prototype functions */
93 static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
94 static ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface);
95 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface);
97 /* IROTData prototype function */
98 static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
100 /* Local function used by CompositeMoniker implementation */
101 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest);
102 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface);
104 /********************************************************************************/
105 /* IEnumMoniker prototype functions */
107 /* IUnknown prototype functions */
108 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject);
109 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface);
110 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface);
112 /* IEnumMonker prototype functions */
113 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched);
114 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt);
115 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface);
116 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum);
118 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
120 /********************************************************************************/
121 /* Virtual function table for the CompositeMonikerImpl class witch include */
122 /* Ipersist, IPersistStream and IMoniker functions. */
124 static ICOM_VTABLE(IMoniker) VT_CompositeMonikerImpl =
126 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
127 CompositeMonikerImpl_QueryInterface,
128 CompositeMonikerImpl_AddRef,
129 CompositeMonikerImpl_Release,
130 CompositeMonikerImpl_GetClassID,
131 CompositeMonikerImpl_IsDirty,
132 CompositeMonikerImpl_Load,
133 CompositeMonikerImpl_Save,
134 CompositeMonikerImpl_GetSizeMax,
135 CompositeMonikerImpl_BindToObject,
136 CompositeMonikerImpl_BindToStorage,
137 CompositeMonikerImpl_Reduce,
138 CompositeMonikerImpl_ComposeWith,
139 CompositeMonikerImpl_Enum,
140 CompositeMonikerImpl_IsEqual,
141 CompositeMonikerImpl_Hash,
142 CompositeMonikerImpl_IsRunning,
143 CompositeMonikerImpl_GetTimeOfLastChange,
144 CompositeMonikerImpl_Inverse,
145 CompositeMonikerImpl_CommonPrefixWith,
146 CompositeMonikerImpl_RelativePathTo,
147 CompositeMonikerImpl_GetDisplayName,
148 CompositeMonikerImpl_ParseDisplayName,
149 CompositeMonikerImpl_IsSystemMoniker
152 /********************************************************************************/
153 /* Virtual function table for the IROTData class. */
154 static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
156 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
157 CompositeMonikerROTDataImpl_QueryInterface,
158 CompositeMonikerROTDataImpl_AddRef,
159 CompositeMonikerROTDataImpl_Release,
160 CompositeMonikerROTDataImpl_GetComparaisonData
163 /********************************************************************************/
164 /* Virtual function table for the IROTData class */
165 static ICOM_VTABLE(IEnumMoniker) VT_EnumMonikerImpl =
167 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
168 EnumMonikerImpl_QueryInterface,
169 EnumMonikerImpl_AddRef,
170 EnumMonikerImpl_Release,
171 EnumMonikerImpl_Next,
172 EnumMonikerImpl_Skip,
173 EnumMonikerImpl_Reset,
174 EnumMonikerImpl_Clone
177 /*******************************************************************************
178 * CompositeMoniker_QueryInterface
179 *******************************************************************************/
180 HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
182 ICOM_THIS(CompositeMonikerImpl,iface);
184 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
186 /* Perform a sanity check on the parameters.*/
187 if ( (This==0) || (ppvObject==0) )
188 return E_INVALIDARG;
190 /* Initialize the return parameter */
191 *ppvObject = 0;
193 /* Compare the riid with the interface IDs implemented by this object.*/
194 if (IsEqualIID(&IID_IUnknown, riid) ||
195 IsEqualIID(&IID_IPersist, riid) ||
196 IsEqualIID(&IID_IPersistStream, riid) ||
197 IsEqualIID(&IID_IMoniker, riid)
199 *ppvObject = iface;
200 else if (IsEqualIID(&IID_IROTData, riid))
201 *ppvObject = (IROTData*)&(This->lpvtbl2);
203 /* Check that we obtained an interface.*/
204 if ((*ppvObject)==0)
205 return E_NOINTERFACE;
207 /* Query Interface always increases the reference count by one when it is successful */
208 CompositeMonikerImpl_AddRef(iface);
210 return S_OK;
213 /******************************************************************************
214 * CompositeMoniker_AddRef
215 ******************************************************************************/
216 ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)
218 ICOM_THIS(CompositeMonikerImpl,iface);
220 TRACE("(%p)\n",This);
222 return ++(This->ref);
225 /******************************************************************************
226 * CompositeMoniker_Release
227 ******************************************************************************/
228 ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
230 ICOM_THIS(CompositeMonikerImpl,iface);
231 ULONG i;
233 TRACE("(%p)\n",This);
235 This->ref--;
237 /* destroy the object if there's no more reference on it */
238 if (This->ref==0){
240 /* release all the components before destroying this object */
241 for (i=0;i<This->tabLastIndex;i++)
242 IMoniker_Release(This->tabMoniker[i]);
244 CompositeMonikerImpl_Destroy(This);
246 return 0;
248 return This->ref;;
251 /******************************************************************************
252 * CompositeMoniker_GetClassID
253 ******************************************************************************/
254 HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
256 TRACE("(%p,%p),stub!\n",iface,pClassID);
258 if (pClassID==NULL)
259 return E_POINTER;
261 *pClassID = CLSID_CompositeMoniker;
263 return S_OK;
266 /******************************************************************************
267 * CompositeMoniker_IsDirty
268 ******************************************************************************/
269 HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)
271 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
272 method in the OLE-provided moniker interfaces always return S_FALSE because
273 their internal state never changes. */
275 TRACE("(%p)\n",iface);
277 return S_FALSE;
280 /******************************************************************************
281 * CompositeMoniker_Load
282 ******************************************************************************/
283 HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
285 HRESULT res;
286 DWORD constant;
287 CLSID clsid;
288 WCHAR string[1]={0};
290 ICOM_THIS(CompositeMonikerImpl,iface);
292 TRACE("(%p,%p)\n",iface,pStm);
294 /* this function call OleLoadFromStream function for each moniker within this object */
296 /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
297 res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
299 if (SUCCEEDED(res)&& constant!=3)
300 return E_FAIL;
302 while(1){
303 #if 0
304 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
305 #endif
306 res=ReadClassStm(pStm,&clsid);
307 DPRINTF("res=%ld",res);
308 if (FAILED(res))
309 break;
311 if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
312 res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
313 if (FAILED(res))
314 break;
315 res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
316 if (FAILED(res))
317 break;
319 else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
320 CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
321 if (res!=S_OK)
322 break;
323 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
324 if (FAILED(res))
325 break;
327 else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
328 CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
329 if (FAILED(res))
330 break;
331 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
332 if (FAILED(res))
333 break;
335 else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
336 return E_FAIL;
338 else{
339 FIXME("()");
340 break;
341 return E_NOTIMPL;
344 /* resize the table if needed */
345 if (++This->tabLastIndex==This->tabSize){
347 This->tabSize+=BLOCK_TAB_SIZE;
348 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
350 if (This->tabMoniker==NULL)
351 return E_OUTOFMEMORY;
355 return res;
358 /******************************************************************************
359 * CompositeMoniker_Save
360 ******************************************************************************/
361 HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
363 HRESULT res;
364 IEnumMoniker *enumMk;
365 IMoniker *pmk;
366 DWORD constant=3;
368 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
370 /* this function call OleSaveToStream function for each moniker within this object */
372 /* when I tested this function in windows system ! I usually found this constant in the begining of */
373 /* the stream I dont known why (there's no indication in specification) ! */
374 res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
376 IMoniker_Enum(iface,TRUE,&enumMk);
378 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
380 res=OleSaveToStream((IPersistStream*)pmk,pStm);
382 IMoniker_Release(pmk);
384 if (FAILED(res)){
386 IEnumMoniker_Release(pmk);
387 return res;
391 IEnumMoniker_Release(enumMk);
393 return S_OK;
396 /******************************************************************************
397 * CompositeMoniker_GetSizeMax
398 ******************************************************************************/
399 HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
401 IEnumMoniker *enumMk;
402 IMoniker *pmk;
403 ULARGE_INTEGER ptmpSize;
405 /* the sizeMax of this object is calculated by calling GetSizeMax on each moniker within this object then */
406 /* suming all returned sizemax */
408 TRACE("(%p,%p)\n",iface,pcbSize);
410 if (pcbSize!=NULL)
411 return E_POINTER;
413 pcbSize->s.LowPart =0;
414 pcbSize->s.HighPart=0;
416 IMoniker_Enum(iface,TRUE,&enumMk);
418 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){
420 IMoniker_GetSizeMax(pmk,&ptmpSize);
422 IMoniker_Release(pmk);
424 pcbSize->s.LowPart +=ptmpSize.s.LowPart;
425 pcbSize->s.HighPart+=ptmpSize.s.HighPart;
428 IEnumMoniker_Release(enumMk);
430 return S_OK;
433 /******************************************************************************
434 * Composite-Moniker_Construct (local function)
435 *******************************************************************************/
436 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest)
438 DWORD mkSys;
439 IEnumMoniker *enumMoniker;
440 IMoniker *tempMk;
441 HRESULT res;
443 TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
445 /* Initialize the virtual fgunction table. */
446 This->lpvtbl1 = &VT_CompositeMonikerImpl;
447 This->lpvtbl2 = &VT_ROTDataImpl;
448 This->ref = 0;
450 This->tabSize=BLOCK_TAB_SIZE;
451 This->tabLastIndex=0;
453 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
454 if (This->tabMoniker==NULL)
455 return E_OUTOFMEMORY;
457 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
459 /* put the first moniker contents in the begining of the table */
460 if (mkSys!=MKSYS_GENERICCOMPOSITE){
462 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
463 IMoniker_AddRef(pmkFirst);
465 else{
467 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
469 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
472 if (++This->tabLastIndex==This->tabSize){
474 This->tabSize+=BLOCK_TAB_SIZE;
475 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
477 if (This->tabMoniker==NULL)
478 return E_OUTOFMEMORY;
482 IEnumMoniker_Release(enumMoniker);
485 /* put the rest moniker contents after the first one and make simplification if needed */
487 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
489 if (mkSys!=MKSYS_GENERICCOMPOSITE){
491 /* add a simple moniker to the moniker table */
493 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
495 if (res==MK_E_NEEDGENERIC){
497 /* there's no simplification in this case */
498 This->tabMoniker[This->tabLastIndex]=pmkRest;
500 This->tabLastIndex++;
502 IMoniker_AddRef(pmkRest);
504 else if (tempMk==NULL){
506 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
507 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
509 This->tabLastIndex--;
511 else if (SUCCEEDED(res)){
513 /* the non-generic composition was successful so we can make a simplification in this case */
514 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
516 This->tabMoniker[This->tabLastIndex-1]=tempMk;
517 } else
518 return res;
520 /* resize tabMoniker if needed */
521 if (This->tabLastIndex==This->tabSize){
523 This->tabSize+=BLOCK_TAB_SIZE;
525 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
527 if (This->tabMoniker==NULL)
528 return E_OUTOFMEMORY;
531 else{
533 /* add a composite moniker to the moniker table (do the same thing for each moniker within the */
534 /* composite moniker as a simple moniker (see above how to add a simple moniker case) ) */
535 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
537 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
539 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
541 if (res==MK_E_NEEDGENERIC){
543 This->tabLastIndex++;
545 else if (tempMk==NULL){
547 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
548 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
549 This->tabLastIndex--;
551 else{
553 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
555 This->tabMoniker[This->tabLastIndex-1]=tempMk;
558 if (This->tabLastIndex==This->tabSize){
560 This->tabSize+=BLOCK_TAB_SIZE;
562 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
564 if (This->tabMoniker==NULL)
565 return E_OUTOFMEMORY;
569 IEnumMoniker_Release(enumMoniker);
572 return S_OK;
575 /******************************************************************************
576 * CompositeMoniker_Destroy (local function)
577 *******************************************************************************/
578 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This)
580 TRACE("(%p)\n",This);
582 HeapFree(GetProcessHeap(),0,This->tabMoniker);
584 HeapFree(GetProcessHeap(),0,This);
586 return S_OK;
589 /******************************************************************************
590 * CompositeMoniker_BindToObject
591 ******************************************************************************/
592 HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,
593 IBindCtx* pbc,
594 IMoniker* pmkToLeft,
595 REFIID riid,
596 VOID** ppvResult)
598 HRESULT res;
599 IRunningObjectTable *prot;
600 IMoniker *tempMk,*antiMk,*mostRigthMk;
601 IEnumMoniker *enumMoniker;
603 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
605 if (ppvResult==NULL)
606 return E_POINTER;
608 *ppvResult=0;
609 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
610 /* object for the requested interface pointer. */
611 if(pmkToLeft==NULL){
613 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
615 if (SUCCEEDED(res)){
617 /* if the requested class was loaded befor ! we dont need to reload it */
618 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
620 if (res==S_OK)
621 return res;
624 else{
625 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
626 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
628 IMoniker_Enum(iface,FALSE,&enumMoniker);
629 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
630 IEnumMoniker_Release(enumMoniker);
632 res=CreateAntiMoniker(&antiMk);
633 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
634 IMoniker_Release(antiMk);
636 res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
638 IMoniker_Release(tempMk);
639 IMoniker_Release(mostRigthMk);
642 return res;
645 /******************************************************************************
646 * CompositeMoniker_BindToStorage
647 ******************************************************************************/
648 HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,
649 IBindCtx* pbc,
650 IMoniker* pmkToLeft,
651 REFIID riid,
652 VOID** ppvResult)
654 HRESULT res;
655 IMoniker *tempMk,*antiMk,*mostRigthMk;
656 IEnumMoniker *enumMoniker;
658 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
660 *ppvResult=0;
662 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
663 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
665 if (pmkToLeft!=NULL){
667 IMoniker_Enum(iface,FALSE,&enumMoniker);
668 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
669 IEnumMoniker_Release(enumMoniker);
671 res=CreateAntiMoniker(&antiMk);
672 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
673 IMoniker_Release(antiMk);
675 res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
677 IMoniker_Release(tempMk);
679 IMoniker_Release(mostRigthMk);
681 return res;
683 else
684 return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
687 /******************************************************************************
688 * CompositeMoniker_Reduce
689 ******************************************************************************/
690 HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,
691 IBindCtx* pbc,
692 DWORD dwReduceHowFar,
693 IMoniker** ppmkToLeft,
694 IMoniker** ppmkReduced)
696 HRESULT res;
697 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
698 IEnumMoniker *enumMoniker;
700 TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
702 if (ppmkReduced==NULL)
703 return E_POINTER;
705 /* This method recursively calls Reduce for each of its component monikers. */
707 if (ppmkToLeft==NULL){
709 IMoniker_Enum(iface,FALSE,&enumMoniker);
710 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
711 IEnumMoniker_Release(enumMoniker);
713 res=CreateAntiMoniker(&antiMk);
714 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
715 IMoniker_Release(antiMk);
717 return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
719 else if (*ppmkToLeft==NULL)
721 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
723 else{
725 /* separate the copmosite moniker in to left and wrigth moniker */
726 IMoniker_Enum(iface,FALSE,&enumMoniker);
727 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
728 IEnumMoniker_Release(enumMoniker);
730 res=CreateAntiMoniker(&antiMk);
731 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
732 IMoniker_Release(antiMk);
734 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
735 /* of the reduced components */
736 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
737 CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
740 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
742 else{
743 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
745 IMoniker_AddRef(iface);
747 *ppmkReduced=iface;
749 return MK_S_REDUCED_TO_SELF;
754 /******************************************************************************
755 * CompositeMoniker_ComposeWith
756 ******************************************************************************/
757 HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,
758 IMoniker* pmkRight,
759 BOOL fOnlyIfNotGeneric,
760 IMoniker** ppmkComposite)
762 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
764 if ((ppmkComposite==NULL)||(pmkRight==NULL))
765 return E_POINTER;
767 *ppmkComposite=0;
769 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
770 /* otherwise, the method returns the result of combining the two monikers by calling the */
771 /* CreateGenericComposite function */
773 if (fOnlyIfNotGeneric)
774 return MK_E_NEEDGENERIC;
776 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
779 /******************************************************************************
780 * CompositeMoniker_Enum
781 ******************************************************************************/
782 HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
784 ICOM_THIS(CompositeMonikerImpl,iface);
786 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
788 if (ppenumMoniker == NULL)
789 return E_POINTER;
791 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
794 /******************************************************************************
795 * CompositeMoniker_IsEqual
796 ******************************************************************************/
797 HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
799 IEnumMoniker *enumMoniker1,*enumMoniker2;
800 IMoniker *tempMk1,*tempMk2;
801 HRESULT res1,res2,res;
803 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
805 if (pmkOtherMoniker==NULL)
806 return S_FALSE;
808 /* This method returns S_OK if the components of both monikers are equal when compared in the */
809 /* left-to-right order.*/
810 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
812 if (enumMoniker1==NULL)
813 return S_FALSE;
815 IMoniker_Enum(iface,TRUE,&enumMoniker2);
817 while(1){
819 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
820 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
822 if((res1==S_OK)&&(res2==S_OK)){
824 if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
825 res= S_FALSE;
826 break;
828 else
829 continue;
831 else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
832 res = S_OK;
833 break;
835 else{
836 res = S_FALSE;
837 break;
840 if (res1==S_OK)
841 IMoniker_Release(tempMk1);
843 if (res2==S_OK)
844 IMoniker_Release(tempMk2);
847 IEnumMoniker_Release(enumMoniker1);
848 IEnumMoniker_Release(enumMoniker2);
850 return res;
852 /******************************************************************************
853 * CompositeMoniker_Hash
854 ******************************************************************************/
855 HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
857 FIXME("(),stub!\n");
859 return E_NOTIMPL;
862 /******************************************************************************
863 * CompositeMoniker_IsRunning
864 ******************************************************************************/
865 HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,
866 IBindCtx* pbc,
867 IMoniker* pmkToLeft,
868 IMoniker* pmkNewlyRunning)
870 IRunningObjectTable* rot;
871 HRESULT res;
872 IMoniker *tempMk,*antiMk,*mostRigthMk;
873 IEnumMoniker *enumMoniker;
875 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
877 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
878 if (pmkToLeft!=NULL){
880 CreateGenericComposite(pmkToLeft,iface,&tempMk);
882 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
884 IMoniker_Release(tempMk);
886 return res;
888 else
889 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
890 /* to this moniker */
892 if (pmkNewlyRunning!=NULL)
894 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
895 return S_OK;
897 else
898 return S_FALSE;
900 else{
902 if (pbc==NULL)
903 return E_POINTER;
905 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
906 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
907 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
908 /* the composite as the pmkToLeft parameter for that call. */
910 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
912 if (FAILED(res))
913 return res;
915 res = IRunningObjectTable_IsRunning(rot,iface);
916 IRunningObjectTable_Release(rot);
918 if(res==S_OK)
919 return S_OK;
921 else{
923 IMoniker_Enum(iface,FALSE,&enumMoniker);
924 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
925 IEnumMoniker_Release(enumMoniker);
927 res=CreateAntiMoniker(&antiMk);
928 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
929 IMoniker_Release(antiMk);
931 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
933 IMoniker_Release(tempMk);
934 IMoniker_Release(mostRigthMk);
936 return res;
941 /******************************************************************************
942 * CompositeMoniker_GetTimeOfLastChange
943 ******************************************************************************/
944 HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
945 IBindCtx* pbc,
946 IMoniker* pmkToLeft,
947 FILETIME* pCompositeTime)
949 IRunningObjectTable* rot;
950 HRESULT res;
951 IMoniker *tempMk,*antiMk,*mostRigthMk;
952 IEnumMoniker *enumMoniker;
954 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
956 if (pCompositeTime==NULL)
957 return E_INVALIDARG;
959 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
960 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
961 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
962 /* of the composite as the pmkToLeft parameter for that call. */
963 if (pmkToLeft!=NULL){
965 res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
967 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
969 if (FAILED(res))
970 return res;
972 if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
973 return res;
974 else
976 IMoniker_Enum(iface,FALSE,&enumMoniker);
977 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
978 IEnumMoniker_Release(enumMoniker);
980 res=CreateAntiMoniker(&antiMk);
981 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
982 IMoniker_Release(antiMk);
984 res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
986 IMoniker_Release(tempMk);
987 IMoniker_Release(mostRigthMk);
989 return res;
991 else
992 return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
995 /******************************************************************************
996 * CompositeMoniker_Inverse
997 ******************************************************************************/
998 HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
1000 HRESULT res;
1001 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
1002 IEnumMoniker *enumMoniker;
1004 TRACE("(%p,%p)\n",iface,ppmk);
1006 if (ppmk==NULL)
1007 return E_POINTER;
1009 /* This method returns a composite moniker that consists of the inverses of each of the components */
1010 /* of the original composite, stored in reverse order */
1012 res=CreateAntiMoniker(&antiMk);
1013 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1014 IMoniker_Release(antiMk);
1016 if (tempMk==NULL)
1018 return IMoniker_Inverse(iface,ppmk);
1020 else{
1022 IMoniker_Enum(iface,FALSE,&enumMoniker);
1023 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1024 IEnumMoniker_Release(enumMoniker);
1026 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
1027 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
1029 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
1031 IMoniker_Release(tempMk);
1032 IMoniker_Release(mostRigthMk);
1033 IMoniker_Release(tempInvMk);
1034 IMoniker_Release(mostRigthInvMk);
1036 return res;
1040 /******************************************************************************
1041 * CompositeMoniker_CommonPrefixWith
1042 ******************************************************************************/
1043 HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1045 DWORD mkSys;
1046 HRESULT res1,res2;
1047 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
1048 IEnumMoniker *enumMoniker1,*enumMoniker2;
1049 ULONG i,nbCommonMk=0;
1051 /* If the other moniker is a composite, this method compares the components of each composite from left */
1052 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1053 /* of the leftmost components were common to both monikers. */
1055 if (ppmkPrefix==NULL)
1056 return E_POINTER;
1058 *ppmkPrefix=0;
1060 if (pmkOther==NULL)
1061 return MK_E_NOPREFIX;
1063 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1065 if((mkSys==MKSYS_GENERICCOMPOSITE)){
1067 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1068 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
1070 while(1){
1072 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1073 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
1075 if ((res1==S_FALSE) && (res2==S_FALSE)){
1077 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1078 *ppmkPrefix=iface;
1079 IMoniker_AddRef(iface);
1080 return MK_S_US;
1082 else if ((res1==S_OK) && (res2==S_OK)){
1084 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
1086 nbCommonMk++;
1088 else
1089 break;
1092 else if (res1==S_OK){
1094 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1095 /* ppmkPrefix to the other moniker. */
1096 *ppmkPrefix=pmkOther;
1097 return MK_S_HIM;
1099 else{
1100 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1101 /* to this moniker. */
1102 *ppmkPrefix=iface;
1103 return MK_S_ME;
1107 IEnumMoniker_Release(enumMoniker1);
1108 IEnumMoniker_Release(enumMoniker2);
1110 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1111 if (nbCommonMk==0)
1112 return MK_E_NOPREFIX;
1114 IEnumMoniker_Reset(enumMoniker1);
1116 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1118 /* if we have more than one commun moniker the result will be a composite moniker */
1119 if (nbCommonMk>1){
1121 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1122 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1123 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
1124 IMoniker_Release(tempMk1);
1125 IMoniker_Release(tempMk2);
1127 /* compose all common monikers in a composite moniker */
1128 for(i=0;i<nbCommonMk;i++){
1130 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1132 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
1134 IMoniker_Release(*ppmkPrefix);
1136 IMoniker_Release(tempMk1);
1138 *ppmkPrefix=tempMk2;
1140 return S_OK;
1142 else{
1143 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1144 *ppmkPrefix=tempMk1;
1146 return S_OK;
1149 else{
1150 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1151 of this moniker.*/
1153 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1155 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1157 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
1159 *ppmkPrefix=pmkOther;
1161 return MK_S_HIM;
1163 else
1164 return MK_E_NOPREFIX;
1167 /***************************************************************************************************
1168 * GetAfterCommonPrefix (local function)
1169 * This function returns a moniker that consist of the remainder when the common prefix is removed
1170 ***************************************************************************************************/
1171 VOID WINAPI GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
1173 IMoniker *tempMk,*tempMk1,*tempMk2;
1174 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
1175 ULONG nbRestMk=0;
1176 DWORD mkSys;
1177 HRESULT res1,res2;
1179 *restMk=0;
1181 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1182 /* prefix: enum the two monikers (left-wrigth) then compare these enumerations (left-wrigth) and stop */
1183 /* on the first difference. */
1184 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
1186 IMoniker_IsSystemMoniker(commonMk,&mkSys);
1188 if (mkSys==MKSYS_GENERICCOMPOSITE){
1190 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
1191 while(1){
1193 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1194 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
1196 if ((res1==S_FALSE)||(res2==S_FALSE)){
1198 if (res1==S_OK)
1200 nbRestMk++;
1202 IMoniker_Release(tempMk1);
1203 IMoniker_Release(tempMk1);
1205 break;
1207 IMoniker_Release(tempMk1);
1208 IMoniker_Release(tempMk1);
1211 else{
1212 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1213 IMoniker_Release(tempMk1);
1216 /* count the number of elements in the enumerator after the common prefix */
1217 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1219 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1221 IMoniker_Release(tempMk);;
1223 if (nbRestMk==0)
1224 return;
1226 /* create a generic composite moniker with monikers located after the common prefix */
1227 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1229 if (nbRestMk==1){
1231 *restMk= tempMk1;
1232 return;
1234 else {
1236 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1238 CreateGenericComposite(tempMk1,tempMk2,restMk);
1240 IMoniker_Release(tempMk1);
1242 IMoniker_Release(tempMk2);
1244 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1246 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1248 IMoniker_Release(tempMk1);
1250 IMoniker_Release(*restMk);
1252 *restMk=tempMk2;
1256 /******************************************************************************
1257 * CompositeMoniker_RelativePathTo
1258 ******************************************************************************/
1259 HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkRelPath)
1261 HRESULT res;
1262 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1264 TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1266 if (ppmkRelPath==NULL)
1267 return E_POINTER;
1269 *ppmkRelPath=0;
1271 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1272 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1273 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1275 /* finds the common prefix of the two monikers */
1276 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1278 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1279 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1281 *ppmkRelPath=pmkOther;
1282 IMoniker_AddRef(pmkOther);
1283 return MK_S_HIM;
1286 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1287 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1289 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1290 /* moniker when the common prefix is removed */
1291 if (res==MK_S_HIM){
1293 IMoniker_Inverse(restThisMk,ppmkRelPath);
1294 IMoniker_Release(restThisMk);
1296 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1297 /* when the common prefix is removed */
1298 else if (res==MK_S_ME){
1300 *ppmkRelPath=restOtherMk;
1301 IMoniker_AddRef(restOtherMk);
1303 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1304 /* moniker on the right of it. */
1305 else if (res==S_OK){
1307 IMoniker_Inverse(restThisMk,&invRestThisMk);
1308 IMoniker_Release(restThisMk);
1309 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1310 IMoniker_Release(invRestThisMk);
1311 IMoniker_Release(restOtherMk);
1313 return S_OK;
1316 /******************************************************************************
1317 * CompositeMoniker_GetDisplayName
1318 ******************************************************************************/
1319 HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,
1320 IBindCtx* pbc,
1321 IMoniker* pmkToLeft,
1322 LPOLESTR *ppszDisplayName)
1324 ULONG lengthStr=1;
1325 IEnumMoniker *enumMoniker;
1326 IMoniker* tempMk;
1327 LPOLESTR tempStr;
1329 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1331 if (ppszDisplayName==NULL)
1332 return E_POINTER;
1334 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1336 if (*ppszDisplayName==NULL)
1337 return E_OUTOFMEMORY;
1339 /* This method returns the concatenation of the display names returned by each component moniker of */
1340 /* the composite */
1342 **ppszDisplayName=0;
1344 IMoniker_Enum(iface,TRUE,&enumMoniker);
1346 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1348 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1350 lengthStr+=lstrlenW(tempStr);
1352 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1354 if (*ppszDisplayName==NULL)
1355 return E_OUTOFMEMORY;
1357 strcatW(*ppszDisplayName,tempStr);
1359 CoTaskMemFree(tempStr);
1360 IMoniker_Release(tempMk);
1363 IEnumMoniker_Release(enumMoniker);
1365 return S_OK;
1368 /******************************************************************************
1369 * CompositeMoniker_ParseDisplayName
1370 ******************************************************************************/
1371 HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,
1372 IBindCtx* pbc,
1373 IMoniker* pmkToLeft,
1374 LPOLESTR pszDisplayName,
1375 ULONG* pchEaten,
1376 IMoniker** ppmkOut)
1378 IEnumMoniker *enumMoniker;
1379 IMoniker *tempMk,*mostRigthMk,*antiMk;
1380 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1381 /* passing everything else as the pmkToLeft parameter for that call. */
1383 /* get the most rigth moniker */
1384 IMoniker_Enum(iface,FALSE,&enumMoniker);
1385 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1386 IEnumMoniker_Release(enumMoniker);
1388 /* get the left moniker */
1389 CreateAntiMoniker(&antiMk);
1390 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1391 IMoniker_Release(antiMk);
1393 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1396 /******************************************************************************
1397 * CompositeMoniker_IsSystemMonker
1398 ******************************************************************************/
1399 HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1401 TRACE("(%p,%p)\n",iface,pwdMksys);
1403 if (!pwdMksys)
1404 return E_POINTER;
1406 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1408 return S_OK;
1411 /*******************************************************************************
1412 * CompositeMonikerIROTData_QueryInterface
1413 *******************************************************************************/
1414 HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1417 ICOM_THIS_From_IROTData(IMoniker, iface);
1419 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
1421 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1424 /***********************************************************************
1425 * CompositeMonikerIROTData_AddRef
1427 ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1429 ICOM_THIS_From_IROTData(IMoniker, iface);
1431 TRACE("(%p)\n",iface);
1433 return CompositeMonikerImpl_AddRef(This);
1436 /***********************************************************************
1437 * CompositeMonikerIROTData_Release
1439 ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1441 ICOM_THIS_From_IROTData(IMoniker, iface);
1443 TRACE("(%p)\n",iface);
1445 return CompositeMonikerImpl_Release(This);
1448 /******************************************************************************
1449 * CompositeMonikerIROTData_GetComparaisonData
1450 ******************************************************************************/
1451 HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1452 BYTE* pbData,
1453 ULONG cbMax,
1454 ULONG* pcbData)
1456 FIXME("(),stub!\n");
1457 return E_NOTIMPL;
1460 /******************************************************************************
1461 * EnumMonikerImpl_QueryInterface
1462 ******************************************************************************/
1463 HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1465 ICOM_THIS(EnumMonikerImpl,iface);
1467 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1469 /* Perform a sanity check on the parameters.*/
1470 if ( (This==0) || (ppvObject==0) )
1471 return E_INVALIDARG;
1473 /* Initialize the return parameter */
1474 *ppvObject = 0;
1476 /* Compare the riid with the interface IDs implemented by this object.*/
1477 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1478 *ppvObject = iface;
1480 /* Check that we obtained an interface.*/
1481 if ((*ppvObject)==0)
1482 return E_NOINTERFACE;
1484 /* Query Interface always increases the reference count by one when it is successful */
1485 EnumMonikerImpl_AddRef(iface);
1487 return S_OK;
1490 /******************************************************************************
1491 * EnumMonikerImpl_AddRef
1492 ******************************************************************************/
1493 ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1495 ICOM_THIS(EnumMonikerImpl,iface);
1497 TRACE("(%p)\n",This);
1499 return ++(This->ref);
1503 /******************************************************************************
1504 * EnumMonikerImpl_Release
1505 ******************************************************************************/
1506 ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1508 ICOM_THIS(EnumMonikerImpl,iface);
1509 ULONG i
1511 TRACE("(%p)\n",This);
1513 This->ref--;
1515 /* destroy the object if there's no more reference on it */
1516 if (This->ref==0){
1518 for(i=0;i<This->tabSize;i++)
1519 IMoniker_Release(This->tabMoniker[i]);
1521 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1522 HeapFree(GetProcessHeap(),0,This);
1524 return 0;
1526 return This->ref;;
1529 /******************************************************************************
1530 * EnumMonikerImpl_Next
1531 ******************************************************************************/
1532 HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){
1534 ICOM_THIS(EnumMonikerImpl,iface);
1535 ULONG i;
1537 /* retrieve the requested number of moniker from the current position */
1538 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1540 rgelt[i]=This->tabMoniker[This->currentPos++];
1542 if (pceltFethed!=NULL)
1543 *pceltFethed= i;
1545 if (i==celt)
1546 return S_OK;
1547 else
1548 return S_FALSE;
1551 /******************************************************************************
1552 * EnumMonikerImpl_Skip
1553 ******************************************************************************/
1554 HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){
1556 ICOM_THIS(EnumMonikerImpl,iface);
1558 if ((This->currentPos+celt) >= This->tabSize)
1559 return S_FALSE;
1561 This->currentPos+=celt;
1563 return S_OK;
1566 /******************************************************************************
1567 * EnumMonikerImpl_Reset
1568 ******************************************************************************/
1569 HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){
1571 ICOM_THIS(EnumMonikerImpl,iface);
1573 This->currentPos=0;
1575 return S_OK;
1578 /******************************************************************************
1579 * EnumMonikerImpl_Clone
1580 ******************************************************************************/
1581 HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){
1583 ICOM_THIS(EnumMonikerImpl,iface);
1585 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1588 /******************************************************************************
1589 * EnumMonikerImpl_CreateEnumMoniker
1590 ******************************************************************************/
1591 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,
1592 ULONG tabSize,
1593 ULONG currentPos,
1594 BOOL leftToRigth,
1595 IEnumMoniker ** ppmk)
1597 EnumMonikerImpl* newEnumMoniker;
1598 int i;
1601 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1603 if (newEnumMoniker == 0)
1604 return STG_E_INSUFFICIENTMEMORY;
1606 if (currentPos > tabSize)
1607 return E_INVALIDARG;
1609 /* Initialize the virtual function table. */
1610 ICOM_VTBL(newEnumMoniker) = &VT_EnumMonikerImpl;
1611 newEnumMoniker->ref = 0;
1613 newEnumMoniker->tabSize=tabSize;
1614 newEnumMoniker->currentPos=currentPos;
1616 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1618 if (newEnumMoniker->tabMoniker==NULL)
1619 return E_OUTOFMEMORY;
1621 if (leftToRigth)
1622 for (i=0;i<tabSize;i++){
1624 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1625 IMoniker_AddRef(tabMoniker[i]);
1627 else
1628 for (i=tabSize-1;i>=0;i--){
1630 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1631 IMoniker_AddRef(tabMoniker[i]);
1634 *ppmk=(IEnumMoniker*)newEnumMoniker;
1636 return S_OK;
1639 /******************************************************************************
1640 * CreateGenericComposite [OLE.55]
1641 ******************************************************************************/
1642 HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite)
1644 CompositeMonikerImpl* newCompositeMoniker = 0;
1645 HRESULT hr = S_OK;
1647 TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1649 if (ppmkComposite==NULL)
1650 return E_POINTER;
1652 *ppmkComposite=0;
1654 if (pmkFirst==NULL && pmkRest!=NULL){
1656 *ppmkComposite=pmkRest;
1657 return S_OK;
1659 else if (pmkFirst!=NULL && pmkRest==NULL){
1660 *ppmkComposite=pmkFirst;
1661 return S_OK;
1663 else if (pmkFirst==NULL && pmkRest==NULL)
1664 return S_OK;
1666 newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
1668 if (newCompositeMoniker == 0)
1669 return STG_E_INSUFFICIENTMEMORY;
1671 hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
1673 if (FAILED(hr)){
1675 HeapFree(GetProcessHeap(),0,newCompositeMoniker);
1676 return hr;
1678 if (newCompositeMoniker->tabLastIndex==1)
1680 hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
1681 else
1683 hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
1685 return hr;
1688 /******************************************************************************
1689 * MonikerCommonPrefixWith [OLE.55]
1690 ******************************************************************************/
1691 HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1693 FIXME("(),stub!\n");
1694 return E_NOTIMPL;