Don't announce the WNetDirectoryNotify capability WNetGetConnection.
[wine/hacks.git] / ole / compositemoniker.c
blob31c90fe2a956556f6b382ff3659d1bb6350f3c58
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 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
20 /* CompositeMoniker data structure */
21 typedef struct CompositeMonikerImpl{
23 ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/
25 /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
26 * two monikers are equal. That's whay IROTData interface is implemented by monikers.
28 ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/
30 ULONG ref; /* reference counter for this object */
32 IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */
34 ULONG tabSize; /* size of tabMoniker */
36 ULONG tabLastIndex; /* first free index in tabMoniker */
38 } CompositeMonikerImpl;
41 /* EnumMoniker data structure */
42 typedef struct EnumMonikerImpl{
44 ICOM_VTABLE(IEnumMoniker)* lpvtbl; /* VTable relative to the IEnumMoniker interface.*/
46 ULONG ref; /* reference counter for this object */
48 IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
50 ULONG tabSize; /* size of tabMoniker */
52 ULONG currentPos; /* index pointer on the current moniker */
54 } EnumMonikerImpl;
57 /********************************************************************************/
58 /* CompositeMoniker prototype functions : */
60 /* IUnknown prototype functions */
61 static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
62 static ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface);
63 static ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface);
65 /* IPersist prototype functions */
66 static HRESULT WINAPI CompositeMonikerImpl_GetClassID(const IMoniker* iface, CLSID *pClassID);
68 /* IPersistStream prototype functions */
69 static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface);
70 static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm);
71 static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
72 static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
74 /* IMoniker prototype functions */
75 static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
76 static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
77 static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
78 static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
79 static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
80 static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
81 static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
82 static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
83 static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime);
84 static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
85 static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
86 static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
87 static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
88 static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
89 static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
91 /********************************************************************************/
92 /* IROTData prototype functions */
94 /* IUnknown prototype functions */
95 static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
96 static ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface);
97 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface);
99 /* IROTData prototype function */
100 static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
102 /* Local function used by CompositeMoniker implementation */
103 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest);
104 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface);
106 /********************************************************************************/
107 /* IEnumMoniker prototype functions */
109 /* IUnknown prototype functions */
110 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject);
111 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface);
112 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface);
114 /* IEnumMonker prototype functions */
115 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched);
116 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt);
117 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface);
118 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum);
120 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
122 /********************************************************************************/
123 /* Virtual function table for the CompositeMonikerImpl class witch include */
124 /* Ipersist, IPersistStream and IMoniker functions. */
126 static ICOM_VTABLE(IMoniker) VT_CompositeMonikerImpl =
128 CompositeMonikerImpl_QueryInterface,
129 CompositeMonikerImpl_AddRef,
130 CompositeMonikerImpl_Release,
131 CompositeMonikerImpl_GetClassID,
132 CompositeMonikerImpl_IsDirty,
133 CompositeMonikerImpl_Load,
134 CompositeMonikerImpl_Save,
135 CompositeMonikerImpl_GetSizeMax,
136 CompositeMonikerImpl_BindToObject,
137 CompositeMonikerImpl_BindToStorage,
138 CompositeMonikerImpl_Reduce,
139 CompositeMonikerImpl_ComposeWith,
140 CompositeMonikerImpl_Enum,
141 CompositeMonikerImpl_IsEqual,
142 CompositeMonikerImpl_Hash,
143 CompositeMonikerImpl_IsRunning,
144 CompositeMonikerImpl_GetTimeOfLastChange,
145 CompositeMonikerImpl_Inverse,
146 CompositeMonikerImpl_CommonPrefixWith,
147 CompositeMonikerImpl_RelativePathTo,
148 CompositeMonikerImpl_GetDisplayName,
149 CompositeMonikerImpl_ParseDisplayName,
150 CompositeMonikerImpl_IsSystemMoniker
153 /********************************************************************************/
154 /* Virtual function table for the IROTData class. */
155 static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
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 EnumMonikerImpl_QueryInterface,
168 EnumMonikerImpl_AddRef,
169 EnumMonikerImpl_Release,
170 EnumMonikerImpl_Next,
171 EnumMonikerImpl_Skip,
172 EnumMonikerImpl_Reset,
173 EnumMonikerImpl_Clone
176 /*******************************************************************************
177 * CompositeMoniker_QueryInterface
178 *******************************************************************************/
179 HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
181 ICOM_THIS(CompositeMonikerImpl,iface);
183 TRACE(ole,"(%p,%p,%p)\n",This,riid,ppvObject);
185 /* Perform a sanity check on the parameters.*/
186 if ( (This==0) || (ppvObject==0) )
187 return E_INVALIDARG;
189 /* Initialize the return parameter */
190 *ppvObject = 0;
192 /* Compare the riid with the interface IDs implemented by this object.*/
193 if (IsEqualIID(&IID_IUnknown, riid) ||
194 IsEqualIID(&IID_IPersist, riid) ||
195 IsEqualIID(&IID_IPersistStream, riid) ||
196 IsEqualIID(&IID_IMoniker, riid)
198 *ppvObject = iface;
199 else if (IsEqualIID(&IID_IROTData, riid))
200 *ppvObject = (IROTData*)&(This->lpvtbl2);
202 /* Check that we obtained an interface.*/
203 if ((*ppvObject)==0)
204 return E_NOINTERFACE;
206 /* Query Interface always increases the reference count by one when it is successful */
207 CompositeMonikerImpl_AddRef(iface);
209 return S_OK;
212 /******************************************************************************
213 * CompositeMoniker_AddRef
214 ******************************************************************************/
215 ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)
217 ICOM_THIS(CompositeMonikerImpl,iface);
219 TRACE(ole,"(%p)\n",This);
221 return ++(This->ref);
224 /******************************************************************************
225 * CompositeMoniker_Release
226 ******************************************************************************/
227 ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
229 ICOM_THIS(CompositeMonikerImpl,iface);
230 ULONG i;
232 TRACE(ole,"(%p)\n",This);
234 This->ref--;
236 /* destroy the object if there's no more reference on it */
237 if (This->ref==0){
239 /* release all the components before destroying this object */
240 for (i=0;i<This->tabLastIndex;i++)
241 IMoniker_Release(This->tabMoniker[i]);
243 CompositeMonikerImpl_Destroy(This);
245 return 0;
247 return This->ref;;
250 /******************************************************************************
251 * CompositeMoniker_GetClassID
252 ******************************************************************************/
253 HRESULT WINAPI CompositeMonikerImpl_GetClassID(const IMoniker* iface,CLSID *pClassID)
255 TRACE(ole,"(%p,%p),stub!\n",iface,pClassID);
257 if (pClassID==NULL)
258 return E_POINTER;
260 *pClassID = CLSID_CompositeMoniker;
262 return S_OK;
265 /******************************************************************************
266 * CompositeMoniker_IsDirty
267 ******************************************************************************/
268 HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)
270 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
271 method in the OLE-provided moniker interfaces always return S_FALSE because
272 their internal state never changes. */
274 TRACE(ole,"(%p)\n",iface);
276 return S_FALSE;
279 /******************************************************************************
280 * CompositeMoniker_Load
281 ******************************************************************************/
282 HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
284 HRESULT res;
285 DWORD constant;
286 CLSID clsid;
287 WCHAR string[1]={0};
289 ICOM_THIS(CompositeMonikerImpl,iface);
291 TRACE(ole,"(%p,%p)\n",iface,pStm);
293 /* this function call OleLoadFromStream function for each moniker within this object */
295 /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
296 res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
298 if (SUCCEEDED(res)&& constant!=3)
299 return E_FAIL;
301 while(1){
303 //res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
304 res=ReadClassStm(pStm,&clsid);
305 printf("res=%ld",res);
306 if (FAILED(res))
307 break;
309 if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
310 res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
311 if (FAILED(res))
312 break;
313 res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
314 if (FAILED(res))
315 break;
317 else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
318 CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
319 if (res!=S_OK)
320 break;
321 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
322 if (FAILED(res))
323 break;
325 else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
326 CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
327 if (FAILED(res))
328 break;
329 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
330 if (FAILED(res))
331 break;
333 else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
334 return E_FAIL;
336 else{
337 FIXME(ole,"()");
338 break;
339 return E_NOTIMPL;
342 /* resize the table if needed */
343 if (++This->tabLastIndex==This->tabSize){
345 This->tabSize+=BLOCK_TAB_SIZE;
346 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,sizeof(IMoniker[This->tabSize]));
348 if (This->tabMoniker==NULL)
349 return E_OUTOFMEMORY;
353 return res;
356 /******************************************************************************
357 * CompositeMoniker_Save
358 ******************************************************************************/
359 HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
361 HRESULT res;
362 IEnumMoniker *enumMk;
363 IMoniker *pmk;
364 DWORD constant=3;
366 TRACE(ole,"(%p,%p,%d)\n",iface,pStm,fClearDirty);
368 /* this function call OleSaveToStream function for each moniker within this object */
370 /* when I tested this function in windows system ! I usually found this constant in the begining of */
371 /* the stream I dont known why (there's no indication in specification) ! */
372 res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
374 IMoniker_Enum(iface,TRUE,&enumMk);
376 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
378 res=OleSaveToStream((IPersistStream*)pmk,pStm);
380 IMoniker_Release(pmk);
382 if (FAILED(res)){
384 IEnumMoniker_Release(pmk);
385 return res;
389 IEnumMoniker_Release(enumMk);
391 return S_OK;
394 /******************************************************************************
395 * CompositeMoniker_GetSizeMax
396 ******************************************************************************/
397 HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
399 IEnumMoniker *enumMk;
400 IMoniker *pmk;
401 ULARGE_INTEGER ptmpSize;
403 /* the sizeMax of this object is calculated by calling GetSizeMax on each moniker within this object then */
404 /* suming all returned sizemax */
406 TRACE(ole,"(%p,%p)\n",iface,pcbSize);
408 if (pcbSize!=NULL)
409 return E_POINTER;
411 pcbSize->LowPart =0;
412 pcbSize->HighPart=0;
414 IMoniker_Enum(iface,TRUE,&enumMk);
416 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){
418 IMoniker_GetSizeMax(pmk,&ptmpSize);
420 IMoniker_Release(pmk);
422 pcbSize->LowPart +=ptmpSize.LowPart;
423 pcbSize->HighPart+=ptmpSize.HighPart;
426 IEnumMoniker_Release(enumMk);
428 return S_OK;
431 /******************************************************************************
432 * Composite-Moniker_Construct (local function)
433 *******************************************************************************/
434 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest)
436 DWORD mkSys;
437 IEnumMoniker *enumMoniker;
438 IMoniker *tempMk;
439 HRESULT res;
441 TRACE(ole,"(%p,%p,%p)\n",This,pmkFirst,pmkRest);
443 /* Initialize the virtual fgunction table. */
444 This->lpvtbl1 = &VT_CompositeMonikerImpl;
445 This->lpvtbl2 = &VT_ROTDataImpl;
446 This->ref = 0;
448 This->tabSize=BLOCK_TAB_SIZE;
449 This->tabLastIndex=0;
451 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,sizeof(IMoniker[This->tabSize]));
452 if (This->tabMoniker==NULL)
453 return E_OUTOFMEMORY;
455 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
457 /* put the first moniker contents in the begining of the table */
458 if (mkSys!=MKSYS_GENERICCOMPOSITE){
460 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
461 IMoniker_AddRef(pmkFirst);
463 else{
465 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
467 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
470 if (++This->tabLastIndex==This->tabSize){
472 This->tabSize+=BLOCK_TAB_SIZE;
473 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,sizeof(IMoniker[This->tabSize]));
475 if (This->tabMoniker==NULL)
476 return E_OUTOFMEMORY;
480 IEnumMoniker_Release(enumMoniker);
483 /* put the rest moniker contents after the first one and make simplification if needed */
485 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
487 if (mkSys!=MKSYS_GENERICCOMPOSITE){
489 /* add a simple moniker to the moniker table */
491 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
493 if (res==MK_E_NEEDGENERIC){
495 /* there's no simplification in this case */
496 This->tabMoniker[This->tabLastIndex]=pmkRest;
498 This->tabLastIndex++;
500 IMoniker_AddRef(pmkRest);
502 else if (tempMk==NULL){
504 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
505 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
507 This->tabLastIndex--;
509 else if (SUCCEEDED(res)){
511 /* the non-generic composition was successful so we can make a simplification in this case */
512 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
514 This->tabMoniker[This->tabLastIndex-1]=tempMk;
515 } else
516 return res;
518 /* resize tabMoniker if needed */
519 if (This->tabLastIndex==This->tabSize){
521 This->tabSize+=BLOCK_TAB_SIZE;
523 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,sizeof(IMoniker[This->tabSize]));
525 if (This->tabMoniker==NULL)
526 return E_OUTOFMEMORY;
529 else{
531 /* add a composite moniker to the moniker table (do the same thing for each moniker within the */
532 /* composite moniker as a simple moniker (see above how to add a simple moniker case) ) */
533 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
535 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
537 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
539 if (res==MK_E_NEEDGENERIC){
541 This->tabLastIndex++;
543 else if (tempMk==NULL){
545 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
546 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
547 This->tabLastIndex--;
549 else{
551 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
553 This->tabMoniker[This->tabLastIndex-1]=tempMk;
556 if (This->tabLastIndex==This->tabSize){
558 This->tabSize+=BLOCK_TAB_SIZE;
560 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,sizeof(IMoniker[This->tabSize]));
562 if (This->tabMoniker==NULL)
563 return E_OUTOFMEMORY;
567 IEnumMoniker_Release(enumMoniker);
570 return S_OK;
573 /******************************************************************************
574 * CompositeMoniker_Destroy (local function)
575 *******************************************************************************/
576 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This)
578 TRACE(ole,"(%p)\n",This);
580 HeapFree(GetProcessHeap(),0,This->tabMoniker);
582 HeapFree(GetProcessHeap(),0,This);
584 return S_OK;
587 /******************************************************************************
588 * CompositeMoniker_BindToObject
589 ******************************************************************************/
590 HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,
591 IBindCtx* pbc,
592 IMoniker* pmkToLeft,
593 REFIID riid,
594 VOID** ppvResult)
596 HRESULT res;
597 IRunningObjectTable *prot;
598 IMoniker *tempMk,*antiMk,*mostRigthMk;
599 IEnumMoniker *enumMoniker;
601 TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
603 if (ppvResult==NULL)
604 return E_POINTER;
606 *ppvResult=0;
607 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
608 /* object for the requested interface pointer. */
609 if(pmkToLeft==NULL){
611 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
613 if (SUCCEEDED(res)){
615 /* if the requested class was loaded befor ! we dont need to reload it */
616 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
618 if (res==S_OK)
619 return res;
622 else{
623 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
624 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
626 IMoniker_Enum(iface,FALSE,&enumMoniker);
627 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
628 IEnumMoniker_Release(enumMoniker);
630 res=CreateAntiMoniker(&antiMk);
631 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
632 IMoniker_Release(antiMk);
634 res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
636 IMoniker_Release(tempMk);
637 IMoniker_Release(mostRigthMk);
640 return res;
643 /******************************************************************************
644 * CompositeMoniker_BindToStorage
645 ******************************************************************************/
646 HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,
647 IBindCtx* pbc,
648 IMoniker* pmkToLeft,
649 REFIID riid,
650 VOID** ppvResult)
652 HRESULT res;
653 IMoniker *tempMk,*antiMk,*mostRigthMk;
654 IEnumMoniker *enumMoniker;
656 TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
658 *ppvResult=0;
660 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
661 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
663 if (pmkToLeft!=NULL){
665 IMoniker_Enum(iface,FALSE,&enumMoniker);
666 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
667 IEnumMoniker_Release(enumMoniker);
669 res=CreateAntiMoniker(&antiMk);
670 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
671 IMoniker_Release(antiMk);
673 res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
675 IMoniker_Release(tempMk);
677 IMoniker_Release(mostRigthMk);
679 return res;
681 else
682 return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
685 /******************************************************************************
686 * CompositeMoniker_Reduce
687 ******************************************************************************/
688 HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,
689 IBindCtx* pbc,
690 DWORD dwReduceHowFar,
691 IMoniker** ppmkToLeft,
692 IMoniker** ppmkReduced)
694 HRESULT res;
695 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
696 IEnumMoniker *enumMoniker;
698 TRACE(ole,"(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
700 if (ppmkReduced==NULL)
701 return E_POINTER;
703 /* This method recursively calls Reduce for each of its component monikers. */
705 if (ppmkToLeft==NULL){
707 IMoniker_Enum(iface,FALSE,&enumMoniker);
708 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
709 IEnumMoniker_Release(enumMoniker);
711 res=CreateAntiMoniker(&antiMk);
712 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
713 IMoniker_Release(antiMk);
715 return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
717 else if (*ppmkToLeft==NULL)
719 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
721 else{
723 /* separate the copmosite moniker in to left and wrigth moniker */
724 IMoniker_Enum(iface,FALSE,&enumMoniker);
725 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
726 IEnumMoniker_Release(enumMoniker);
728 res=CreateAntiMoniker(&antiMk);
729 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
730 IMoniker_Release(antiMk);
732 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
733 /* of the reduced components */
734 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
735 CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
738 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
740 else{
741 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
743 IMoniker_AddRef(iface);
745 *ppmkReduced=iface;
747 return MK_S_REDUCED_TO_SELF;
752 /******************************************************************************
753 * CompositeMoniker_ComposeWith
754 ******************************************************************************/
755 HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,
756 IMoniker* pmkRight,
757 BOOL fOnlyIfNotGeneric,
758 IMoniker** ppmkComposite)
760 TRACE(ole,"(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
762 if ((ppmkComposite==NULL)||(pmkRight==NULL))
763 return E_POINTER;
765 *ppmkComposite=0;
767 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
768 /* otherwise, the method returns the result of combining the two monikers by calling the */
769 /* CreateGenericComposite function */
771 if (fOnlyIfNotGeneric)
772 return MK_E_NEEDGENERIC;
774 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
777 /******************************************************************************
778 * CompositeMoniker_Enum
779 ******************************************************************************/
780 HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
782 ICOM_THIS(CompositeMonikerImpl,iface);
784 TRACE(ole,"(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
786 if (ppenumMoniker == NULL)
787 return E_POINTER;
789 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
792 /******************************************************************************
793 * CompositeMoniker_IsEqual
794 ******************************************************************************/
795 HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
797 IEnumMoniker *enumMoniker1,*enumMoniker2;
798 IMoniker *tempMk1,*tempMk2;
799 HRESULT res1,res2,res;
801 TRACE(ole,"(%p,%p)\n",iface,pmkOtherMoniker);
803 if (pmkOtherMoniker==NULL)
804 return S_FALSE;
806 /* This method returns S_OK if the components of both monikers are equal when compared in the */
807 /* left-to-right order.*/
808 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
810 if (enumMoniker1==NULL)
811 return S_FALSE;
813 IMoniker_Enum(iface,TRUE,&enumMoniker2);
815 while(1){
817 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
818 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
820 if((res1==S_OK)&&(res2==S_OK)){
822 if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
823 res= S_FALSE;
824 break;
826 else
827 continue;
829 else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
830 res = S_OK;
831 break;
833 else{
834 res = S_FALSE;
835 break;
838 if (res1==S_OK)
839 IMoniker_Release(tempMk1);
841 if (res2==S_OK)
842 IMoniker_Release(tempMk2);
845 IEnumMoniker_Release(enumMoniker1);
846 IEnumMoniker_Release(enumMoniker2);
848 return res;
850 /******************************************************************************
851 * CompositeMoniker_Hash
852 ******************************************************************************/
853 HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
855 FIXME(ole,"(),stub!\n");
857 return E_NOTIMPL;
860 /******************************************************************************
861 * CompositeMoniker_IsRunning
862 ******************************************************************************/
863 HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,
864 IBindCtx* pbc,
865 IMoniker* pmkToLeft,
866 IMoniker* pmkNewlyRunning)
868 IRunningObjectTable* rot;
869 HRESULT res;
870 IMoniker *tempMk,*antiMk,*mostRigthMk;
871 IEnumMoniker *enumMoniker;
873 TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
875 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
876 if (pmkToLeft!=NULL){
878 CreateGenericComposite(pmkToLeft,iface,&tempMk);
880 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
882 IMoniker_Release(tempMk);
884 return res;
886 else
887 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
888 /* to this moniker */
890 if (pmkNewlyRunning!=NULL)
892 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
893 return S_OK;
895 else
896 return S_FALSE;
898 else{
900 if (pbc==NULL)
901 return E_POINTER;
903 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
904 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
905 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
906 /* the composite as the pmkToLeft parameter for that call. */
908 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
910 if (FAILED(res))
911 return res;
913 res = IRunningObjectTable_IsRunning(rot,iface);
914 IRunningObjectTable_Release(rot);
916 if(res==S_OK)
917 return S_OK;
919 else{
921 IMoniker_Enum(iface,FALSE,&enumMoniker);
922 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
923 IEnumMoniker_Release(enumMoniker);
925 res=CreateAntiMoniker(&antiMk);
926 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
927 IMoniker_Release(antiMk);
929 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
931 IMoniker_Release(tempMk);
932 IMoniker_Release(mostRigthMk);
934 return res;
939 /******************************************************************************
940 * CompositeMoniker_GetTimeOfLastChange
941 ******************************************************************************/
942 HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
943 IBindCtx* pbc,
944 IMoniker* pmkToLeft,
945 FILETIME* pCompositeTime)
947 IRunningObjectTable* rot;
948 HRESULT res;
949 IMoniker *tempMk,*antiMk,*mostRigthMk;
950 IEnumMoniker *enumMoniker;
952 TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
954 if (pCompositeTime==NULL)
955 return E_INVALIDARG;
957 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
958 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
959 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
960 /* of the composite as the pmkToLeft parameter for that call. */
961 if (pmkToLeft!=NULL){
963 res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
965 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
967 if (FAILED(res))
968 return res;
970 if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
971 return res;
972 else
974 IMoniker_Enum(iface,FALSE,&enumMoniker);
975 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
976 IEnumMoniker_Release(enumMoniker);
978 res=CreateAntiMoniker(&antiMk);
979 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
980 IMoniker_Release(antiMk);
982 res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
984 IMoniker_Release(tempMk);
985 IMoniker_Release(mostRigthMk);
987 return res;
989 else
990 return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
993 /******************************************************************************
994 * CompositeMoniker_Inverse
995 ******************************************************************************/
996 HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
998 HRESULT res;
999 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
1000 IEnumMoniker *enumMoniker;
1002 TRACE(ole,"(%p,%p)\n",iface,ppmk);
1004 if (ppmk==NULL)
1005 return E_POINTER;
1007 /* This method returns a composite moniker that consists of the inverses of each of the components */
1008 /* of the original composite, stored in reverse order */
1010 res=CreateAntiMoniker(&antiMk);
1011 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1012 IMoniker_Release(antiMk);
1014 if (tempMk==NULL)
1016 return IMoniker_Inverse(iface,ppmk);
1018 else{
1020 IMoniker_Enum(iface,FALSE,&enumMoniker);
1021 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1022 IEnumMoniker_Release(enumMoniker);
1024 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
1025 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
1027 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
1029 IMoniker_Release(tempMk);
1030 IMoniker_Release(mostRigthMk);
1031 IMoniker_Release(tempInvMk);
1032 IMoniker_Release(mostRigthInvMk);
1034 return res;
1038 /******************************************************************************
1039 * CompositeMoniker_CommonPrefixWith
1040 ******************************************************************************/
1041 HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1043 DWORD mkSys;
1044 HRESULT res1,res2;
1045 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
1046 IEnumMoniker *enumMoniker1,*enumMoniker2;
1047 ULONG i,nbCommonMk=0;
1049 /* If the other moniker is a composite, this method compares the components of each composite from left */
1050 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1051 /* of the leftmost components were common to both monikers. */
1053 if (ppmkPrefix==NULL)
1054 return E_POINTER;
1056 *ppmkPrefix=0;
1058 if (pmkOther==NULL)
1059 return MK_E_NOPREFIX;
1061 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1063 if((mkSys==MKSYS_GENERICCOMPOSITE)){
1065 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1066 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
1068 while(1){
1070 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1071 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
1073 if ((res1==S_FALSE) && (res2==S_FALSE)){
1075 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1076 *ppmkPrefix=iface;
1077 IMoniker_AddRef(iface);
1078 return MK_S_US;
1080 else if ((res1==S_OK) && (res2==S_OK)){
1082 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
1084 nbCommonMk++;
1086 else
1087 break;
1090 else if (res1==S_OK){
1092 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1093 /* ppmkPrefix to the other moniker. */
1094 *ppmkPrefix=pmkOther;
1095 return MK_S_HIM;
1097 else{
1098 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1099 /* to this moniker. */
1100 *ppmkPrefix=iface;
1101 return MK_S_ME;
1105 IEnumMoniker_Release(enumMoniker1);
1106 IEnumMoniker_Release(enumMoniker2);
1108 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1109 if (nbCommonMk==0)
1110 return MK_E_NOPREFIX;
1112 IEnumMoniker_Reset(enumMoniker1);
1114 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1116 /* if we have more than one commun moniker the result will be a composite moniker */
1117 if (nbCommonMk>1){
1119 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1120 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1121 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
1122 IMoniker_Release(tempMk1);
1123 IMoniker_Release(tempMk2);
1125 /* compose all common monikers in a composite moniker */
1126 for(i=0;i<nbCommonMk;i++){
1128 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1130 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
1132 IMoniker_Release(*ppmkPrefix);
1134 IMoniker_Release(tempMk1);
1136 *ppmkPrefix=tempMk2;
1138 return S_OK;
1140 else{
1141 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1142 *ppmkPrefix=tempMk1;
1144 return S_OK;
1147 else{
1148 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1149 of this moniker.*/
1151 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1153 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1155 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
1157 *ppmkPrefix=pmkOther;
1159 return MK_S_HIM;
1161 else
1162 return MK_E_NOPREFIX;
1165 /***************************************************************************************************
1166 * GetAfterCommonPrefix (local function)
1167 * This function returns a moniker that consist of the remainder when the common prefix is removed
1168 ***************************************************************************************************/
1169 VOID WINAPI GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
1171 IMoniker *tempMk,*tempMk1,*tempMk2;
1172 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
1173 ULONG nbRestMk=0;
1174 DWORD mkSys;
1175 HRESULT res1,res2;
1177 *restMk=0;
1179 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1180 /* prefix: enum the two monikers (left-wrigth) then compare these enumerations (left-wrigth) and stop */
1181 /* on the first difference. */
1182 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
1184 IMoniker_IsSystemMoniker(commonMk,&mkSys);
1186 if (mkSys==MKSYS_GENERICCOMPOSITE){
1188 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
1189 while(1){
1191 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1192 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
1194 if ((res1==S_FALSE)||(res2==S_FALSE)){
1196 if (res1==S_OK)
1198 nbRestMk++;
1200 IMoniker_Release(tempMk1);
1201 IMoniker_Release(tempMk1);
1203 break;
1205 IMoniker_Release(tempMk1);
1206 IMoniker_Release(tempMk1);
1209 else{
1210 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1211 IMoniker_Release(tempMk1);
1214 /* count the number of elements in the enumerator after the common prefix */
1215 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1217 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1219 IMoniker_Release(tempMk);;
1221 if (nbRestMk==0)
1222 return;
1224 /* create a generic composite moniker with monikers located after the common prefix */
1225 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1227 if (nbRestMk==1){
1229 *restMk= tempMk1;
1230 return;
1232 else {
1234 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1236 CreateGenericComposite(tempMk1,tempMk2,restMk);
1238 IMoniker_Release(tempMk1);
1240 IMoniker_Release(tempMk2);
1242 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1244 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1246 IMoniker_Release(tempMk1);
1248 IMoniker_Release(*restMk);
1250 *restMk=tempMk2;
1254 /******************************************************************************
1255 * CompositeMoniker_RelativePathTo
1256 ******************************************************************************/
1257 HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkRelPath)
1259 HRESULT res;
1260 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1262 TRACE(ole,"(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1264 if (ppmkRelPath==NULL)
1265 return E_POINTER;
1267 *ppmkRelPath=0;
1269 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1270 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1271 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1273 /* finds the common prefix of the two monikers */
1274 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1276 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1277 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1279 *ppmkRelPath=pmkOther;
1280 IMoniker_AddRef(pmkOther);
1281 return MK_S_HIM;
1284 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1285 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1287 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1288 /* moniker when the common prefix is removed */
1289 if (res==MK_S_HIM){
1291 IMoniker_Inverse(restThisMk,ppmkRelPath);
1292 IMoniker_Release(restThisMk);
1294 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1295 /* when the common prefix is removed */
1296 else if (res==MK_S_ME){
1298 *ppmkRelPath=restOtherMk;
1299 IMoniker_AddRef(restOtherMk);
1301 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1302 /* moniker on the right of it. */
1303 else if (res==S_OK){
1305 IMoniker_Inverse(restThisMk,&invRestThisMk);
1306 IMoniker_Release(restThisMk);
1307 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1308 IMoniker_Release(invRestThisMk);
1309 IMoniker_Release(restOtherMk);
1311 return S_OK;
1314 /******************************************************************************
1315 * CompositeMoniker_GetDisplayName
1316 ******************************************************************************/
1317 HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,
1318 IBindCtx* pbc,
1319 IMoniker* pmkToLeft,
1320 LPOLESTR *ppszDisplayName)
1322 ULONG lengthStr=1;
1323 IEnumMoniker *enumMoniker;
1324 IMoniker* tempMk;
1325 LPOLESTR tempStr;
1327 TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1329 if (ppszDisplayName==NULL)
1330 return E_POINTER;
1332 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1334 if (*ppszDisplayName==NULL)
1335 return E_OUTOFMEMORY;
1337 /* This method returns the concatenation of the display names returned by each component moniker of */
1338 /* the composite */
1340 **ppszDisplayName=0;
1342 IMoniker_Enum(iface,TRUE,&enumMoniker);
1344 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1346 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1348 lengthStr+=lstrlenW(tempStr);
1350 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1352 if (*ppszDisplayName==NULL)
1353 return E_OUTOFMEMORY;
1355 lstrcatW(*ppszDisplayName,tempStr);
1357 CoTaskMemFree(tempStr);
1358 IMoniker_Release(tempMk);
1361 IEnumMoniker_Release(enumMoniker);
1363 return S_OK;
1366 /******************************************************************************
1367 * CompositeMoniker_ParseDisplayName
1368 ******************************************************************************/
1369 HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,
1370 IBindCtx* pbc,
1371 IMoniker* pmkToLeft,
1372 LPOLESTR pszDisplayName,
1373 ULONG* pchEaten,
1374 IMoniker** ppmkOut)
1376 IEnumMoniker *enumMoniker;
1377 IMoniker *tempMk,*mostRigthMk,*antiMk;
1378 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1379 /* passing everything else as the pmkToLeft parameter for that call. */
1381 /* get the most rigth moniker */
1382 IMoniker_Enum(iface,FALSE,&enumMoniker);
1383 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1384 IEnumMoniker_Release(enumMoniker);
1386 /* get the left moniker */
1387 CreateAntiMoniker(&antiMk);
1388 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1389 IMoniker_Release(antiMk);
1391 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1394 /******************************************************************************
1395 * CompositeMoniker_IsSystemMonker
1396 ******************************************************************************/
1397 HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1399 TRACE(ole,"(%p,%p)\n",iface,pwdMksys);
1401 if (!pwdMksys)
1402 return E_POINTER;
1404 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1406 return S_OK;
1409 /*******************************************************************************
1410 * CompositeMonikerIROTData_QueryInterface
1411 *******************************************************************************/
1412 HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1415 ICOM_THIS_From_IROTData(IMoniker, iface);
1417 TRACE(ole,"(%p,%p,%p)\n",iface,riid,ppvObject);
1419 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1422 /***********************************************************************
1423 * CompositeMonikerIROTData_AddRef
1425 ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1427 ICOM_THIS_From_IROTData(IMoniker, iface);
1429 TRACE(ole,"(%p)\n",iface);
1431 return CompositeMonikerImpl_AddRef(This);
1434 /***********************************************************************
1435 * CompositeMonikerIROTData_Release
1437 ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1439 ICOM_THIS_From_IROTData(IMoniker, iface);
1441 TRACE(ole,"(%p)\n",iface);
1443 return CompositeMonikerImpl_Release(This);
1446 /******************************************************************************
1447 * CompositeMonikerIROTData_GetComparaisonData
1448 ******************************************************************************/
1449 HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1450 BYTE* pbData,
1451 ULONG cbMax,
1452 ULONG* pcbData)
1454 FIXME(ole,"(),stub!\n");
1455 return E_NOTIMPL;
1458 /******************************************************************************
1459 * EnumMonikerImpl_QueryInterface
1460 ******************************************************************************/
1461 HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1463 ICOM_THIS(EnumMonikerImpl,iface);
1465 TRACE(ole,"(%p,%p,%p)\n",This,riid,ppvObject);
1467 /* Perform a sanity check on the parameters.*/
1468 if ( (This==0) || (ppvObject==0) )
1469 return E_INVALIDARG;
1471 /* Initialize the return parameter */
1472 *ppvObject = 0;
1474 /* Compare the riid with the interface IDs implemented by this object.*/
1475 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1476 *ppvObject = iface;
1478 /* Check that we obtained an interface.*/
1479 if ((*ppvObject)==0)
1480 return E_NOINTERFACE;
1482 /* Query Interface always increases the reference count by one when it is successful */
1483 EnumMonikerImpl_AddRef(iface);
1485 return S_OK;
1488 /******************************************************************************
1489 * EnumMonikerImpl_AddRef
1490 ******************************************************************************/
1491 ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1493 ICOM_THIS(EnumMonikerImpl,iface);
1495 TRACE(ole,"(%p)\n",This);
1497 return ++(This->ref);
1501 /******************************************************************************
1502 * EnumMonikerImpl_Release
1503 ******************************************************************************/
1504 ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1506 ICOM_THIS(EnumMonikerImpl,iface);
1507 ULONG i
1509 TRACE(ole,"(%p)\n",This);
1511 This->ref--;
1513 /* destroy the object if there's no more reference on it */
1514 if (This->ref==0){
1516 for(i=0;i<This->tabSize;i++)
1517 IMoniker_Release(This->tabMoniker[i]);
1519 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1520 HeapFree(GetProcessHeap(),0,This);
1522 return 0;
1524 return This->ref;;
1527 /******************************************************************************
1528 * EnumMonikerImpl_Next
1529 ******************************************************************************/
1530 HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){
1532 ICOM_THIS(EnumMonikerImpl,iface);
1533 ULONG i;
1535 /* retrieve the requested number of moniker from the current position */
1536 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1538 rgelt[i]=This->tabMoniker[This->currentPos++];
1540 if (pceltFethed!=NULL)
1541 *pceltFethed= i;
1543 if (i==celt)
1544 return S_OK;
1545 else
1546 return S_FALSE;
1549 /******************************************************************************
1550 * EnumMonikerImpl_Skip
1551 ******************************************************************************/
1552 HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){
1554 ICOM_THIS(EnumMonikerImpl,iface);
1556 if ((This->currentPos+celt) >= This->tabSize)
1557 return S_FALSE;
1559 This->currentPos+=celt;
1561 return S_OK;
1564 /******************************************************************************
1565 * EnumMonikerImpl_Reset
1566 ******************************************************************************/
1567 HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){
1569 ICOM_THIS(EnumMonikerImpl,iface);
1571 This->currentPos=0;
1573 return S_OK;
1576 /******************************************************************************
1577 * EnumMonikerImpl_Clone
1578 ******************************************************************************/
1579 HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){
1581 ICOM_THIS(EnumMonikerImpl,iface);
1583 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1586 /******************************************************************************
1587 * EnumMonikerImpl_CreateEnumMoniker
1588 ******************************************************************************/
1589 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,
1590 ULONG tabSize,
1591 ULONG currentPos,
1592 BOOL leftToRigth,
1593 IEnumMoniker ** ppmk)
1595 EnumMonikerImpl* newEnumMoniker;
1596 int i;
1599 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1601 if (newEnumMoniker == 0)
1602 return STG_E_INSUFFICIENTMEMORY;
1604 if (currentPos > tabSize)
1605 return E_INVALIDARG;
1607 /* Initialize the virtual function table. */
1608 newEnumMoniker->lpvtbl = &VT_EnumMonikerImpl;
1609 newEnumMoniker->ref = 0;
1611 newEnumMoniker->tabSize=tabSize;
1612 newEnumMoniker->currentPos=currentPos;
1614 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,sizeof(IMoniker[tabSize]));
1616 if (newEnumMoniker->tabMoniker==NULL)
1617 return E_OUTOFMEMORY;
1619 if (leftToRigth)
1620 for (i=0;i<tabSize;i++){
1622 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1623 IMoniker_AddRef(tabMoniker[i]);
1625 else
1626 for (i=tabSize-1;i>=0;i--){
1628 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1629 IMoniker_AddRef(tabMoniker[i]);
1632 *ppmk=(IEnumMoniker*)newEnumMoniker;
1634 return S_OK;
1637 /******************************************************************************
1638 * CreateCompositeMoniker [OLE.55]
1639 ******************************************************************************/
1640 HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite)
1642 CompositeMonikerImpl* newCompositeMoniker = 0;
1643 HRESULT hr = S_OK;
1645 TRACE(ole,"(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1647 if (ppmkComposite==NULL)
1648 return E_POINTER;
1650 *ppmkComposite=0;
1652 if (pmkFirst==NULL && pmkRest!=NULL){
1654 *ppmkComposite=pmkRest;
1655 return S_OK;
1657 else if (pmkFirst!=NULL && pmkRest==NULL){
1658 *ppmkComposite=pmkFirst;
1659 return S_OK;
1661 else if (pmkFirst==NULL && pmkRest==NULL)
1662 return S_OK;
1664 newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
1666 if (newCompositeMoniker == 0)
1667 return STG_E_INSUFFICIENTMEMORY;
1669 hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
1671 if (FAILED(hr)){
1673 HeapFree(GetProcessHeap(),0,newCompositeMoniker);
1674 return hr;
1676 if (newCompositeMoniker->tabLastIndex==1)
1678 hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
1679 else
1681 hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
1683 return hr;
1686 /******************************************************************************
1687 * MonikerCommonPrefixWith [OLE.55]
1688 ******************************************************************************/
1689 HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1691 FIXME(ole,"(),stub!\n");
1692 return E_NOTIMPL;