Eliminate UNICODEVECTOR data type.
[wine/testsucceed.git] / dlls / ole32 / compositemoniker.c
blobe6ee03caee49c127f802a1382439e02ecad68bd9
1 /***************************************************************************************
2 * CompositeMonikers implementation
4 * Copyright 1999 Noomen Hamza
5 ***************************************************************************************/
6 #include <assert.h>
7 #include <string.h>
8 #include "winbase.h"
9 #include "winerror.h"
10 #include "debugtools.h"
11 #include "wine/obj_base.h"
12 #include "wine/obj_misc.h"
13 #include "wine/obj_storage.h"
14 #include "wine/obj_moniker.h"
15 #include "wine/obj_inplace.h"
16 #include "wine/unicode.h"
17 #include "ole2.h"
19 DEFAULT_DEBUG_CHANNEL(ole);
21 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
23 /* CompositeMoniker data structure */
24 typedef struct CompositeMonikerImpl{
26 ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/
28 /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
29 * two monikers are equal. That's whay IROTData interface is implemented by monikers.
31 ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/
33 ULONG ref; /* reference counter for this object */
35 IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */
37 ULONG tabSize; /* size of tabMoniker */
39 ULONG tabLastIndex; /* first free index in tabMoniker */
41 } CompositeMonikerImpl;
44 /* EnumMoniker data structure */
45 typedef struct EnumMonikerImpl{
47 ICOM_VFIELD(IEnumMoniker); /* VTable relative to the IEnumMoniker interface.*/
49 ULONG ref; /* reference counter for this object */
51 IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
53 ULONG tabSize; /* size of tabMoniker */
55 ULONG currentPos; /* index pointer on the current moniker */
57 } EnumMonikerImpl;
60 /********************************************************************************/
61 /* CompositeMoniker prototype functions : */
63 /* IUnknown prototype functions */
64 static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
65 static ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface);
66 static ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface);
68 /* IPersist prototype functions */
69 static HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
71 /* IPersistStream prototype functions */
72 static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface);
73 static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm);
74 static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
75 static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
77 /* IMoniker prototype functions */
78 static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
79 static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
80 static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
81 static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
82 static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
83 static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
84 static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
85 static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
86 static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime);
87 static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
88 static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
89 static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
90 static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
91 static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
92 static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
94 /********************************************************************************/
95 /* IROTData prototype functions */
97 /* IUnknown prototype functions */
98 static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
99 static ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface);
100 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface);
102 /* IROTData prototype function */
103 static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
105 /* Local function used by CompositeMoniker implementation */
106 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest);
107 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface);
109 /********************************************************************************/
110 /* IEnumMoniker prototype functions */
112 /* IUnknown prototype functions */
113 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject);
114 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface);
115 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface);
117 /* IEnumMoniker prototype functions */
118 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched);
119 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt);
120 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface);
121 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum);
123 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
125 /********************************************************************************/
126 /* Virtual function table for the CompositeMonikerImpl class which includes */
127 /* IPersist, IPersistStream and IMoniker functions. */
129 static ICOM_VTABLE(IMoniker) VT_CompositeMonikerImpl =
131 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
132 CompositeMonikerImpl_QueryInterface,
133 CompositeMonikerImpl_AddRef,
134 CompositeMonikerImpl_Release,
135 CompositeMonikerImpl_GetClassID,
136 CompositeMonikerImpl_IsDirty,
137 CompositeMonikerImpl_Load,
138 CompositeMonikerImpl_Save,
139 CompositeMonikerImpl_GetSizeMax,
140 CompositeMonikerImpl_BindToObject,
141 CompositeMonikerImpl_BindToStorage,
142 CompositeMonikerImpl_Reduce,
143 CompositeMonikerImpl_ComposeWith,
144 CompositeMonikerImpl_Enum,
145 CompositeMonikerImpl_IsEqual,
146 CompositeMonikerImpl_Hash,
147 CompositeMonikerImpl_IsRunning,
148 CompositeMonikerImpl_GetTimeOfLastChange,
149 CompositeMonikerImpl_Inverse,
150 CompositeMonikerImpl_CommonPrefixWith,
151 CompositeMonikerImpl_RelativePathTo,
152 CompositeMonikerImpl_GetDisplayName,
153 CompositeMonikerImpl_ParseDisplayName,
154 CompositeMonikerImpl_IsSystemMoniker
157 /********************************************************************************/
158 /* Virtual function table for the IROTData class. */
159 static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
161 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
162 CompositeMonikerROTDataImpl_QueryInterface,
163 CompositeMonikerROTDataImpl_AddRef,
164 CompositeMonikerROTDataImpl_Release,
165 CompositeMonikerROTDataImpl_GetComparaisonData
168 /********************************************************************************/
169 /* Virtual function table for the IROTData class */
170 static ICOM_VTABLE(IEnumMoniker) VT_EnumMonikerImpl =
172 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
173 EnumMonikerImpl_QueryInterface,
174 EnumMonikerImpl_AddRef,
175 EnumMonikerImpl_Release,
176 EnumMonikerImpl_Next,
177 EnumMonikerImpl_Skip,
178 EnumMonikerImpl_Reset,
179 EnumMonikerImpl_Clone
182 /*******************************************************************************
183 * CompositeMoniker_QueryInterface
184 *******************************************************************************/
185 HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
187 ICOM_THIS(CompositeMonikerImpl,iface);
189 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
191 /* Perform a sanity check on the parameters.*/
192 if ( (This==0) || (ppvObject==0) )
193 return E_INVALIDARG;
195 /* Initialize the return parameter */
196 *ppvObject = 0;
198 /* Compare the riid with the interface IDs implemented by this object.*/
199 if (IsEqualIID(&IID_IUnknown, riid) ||
200 IsEqualIID(&IID_IPersist, riid) ||
201 IsEqualIID(&IID_IPersistStream, riid) ||
202 IsEqualIID(&IID_IMoniker, riid)
204 *ppvObject = iface;
205 else if (IsEqualIID(&IID_IROTData, riid))
206 *ppvObject = (IROTData*)&(This->lpvtbl2);
208 /* Check that we obtained an interface.*/
209 if ((*ppvObject)==0)
210 return E_NOINTERFACE;
212 /* Query Interface always increases the reference count by one when it is successful */
213 CompositeMonikerImpl_AddRef(iface);
215 return S_OK;
218 /******************************************************************************
219 * CompositeMoniker_AddRef
220 ******************************************************************************/
221 ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)
223 ICOM_THIS(CompositeMonikerImpl,iface);
225 TRACE("(%p)\n",This);
227 return ++(This->ref);
230 /******************************************************************************
231 * CompositeMoniker_Release
232 ******************************************************************************/
233 ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
235 ICOM_THIS(CompositeMonikerImpl,iface);
236 ULONG i;
238 TRACE("(%p)\n",This);
240 This->ref--;
242 /* destroy the object if there's no more reference on it */
243 if (This->ref==0){
245 /* release all the components before destroying this object */
246 for (i=0;i<This->tabLastIndex;i++)
247 IMoniker_Release(This->tabMoniker[i]);
249 CompositeMonikerImpl_Destroy(This);
251 return 0;
253 return This->ref;;
256 /******************************************************************************
257 * CompositeMoniker_GetClassID
258 ******************************************************************************/
259 HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
261 TRACE("(%p,%p),stub!\n",iface,pClassID);
263 if (pClassID==NULL)
264 return E_POINTER;
266 *pClassID = CLSID_CompositeMoniker;
268 return S_OK;
271 /******************************************************************************
272 * CompositeMoniker_IsDirty
273 ******************************************************************************/
274 HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)
276 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
277 method in the OLE-provided moniker interfaces always return S_FALSE because
278 their internal state never changes. */
280 TRACE("(%p)\n",iface);
282 return S_FALSE;
285 /******************************************************************************
286 * CompositeMoniker_Load
287 ******************************************************************************/
288 HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
290 HRESULT res;
291 DWORD constant;
292 CLSID clsid;
293 WCHAR string[1]={0};
295 ICOM_THIS(CompositeMonikerImpl,iface);
297 TRACE("(%p,%p)\n",iface,pStm);
299 /* this function call OleLoadFromStream function for each moniker within this object */
301 /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
302 res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
304 if (SUCCEEDED(res)&& constant!=3)
305 return E_FAIL;
307 while(1){
308 #if 0
309 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
310 #endif
311 res=ReadClassStm(pStm,&clsid);
312 DPRINTF("res=%ld",res);
313 if (FAILED(res))
314 break;
316 if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
317 res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
318 if (FAILED(res))
319 break;
320 res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
321 if (FAILED(res))
322 break;
324 else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
325 CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
326 if (res!=S_OK)
327 break;
328 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
329 if (FAILED(res))
330 break;
332 else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
333 CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
334 if (FAILED(res))
335 break;
336 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
337 if (FAILED(res))
338 break;
340 else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
341 return E_FAIL;
343 else
345 FIXME("()\n");
346 /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */
347 break;
348 return E_NOTIMPL;
351 /* resize the table if needed */
352 if (++This->tabLastIndex==This->tabSize){
354 This->tabSize+=BLOCK_TAB_SIZE;
355 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
357 if (This->tabMoniker==NULL)
358 return E_OUTOFMEMORY;
362 return res;
365 /******************************************************************************
366 * CompositeMoniker_Save
367 ******************************************************************************/
368 HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
370 HRESULT res;
371 IEnumMoniker *enumMk;
372 IMoniker *pmk;
373 DWORD constant=3;
375 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
377 /* this function call OleSaveToStream function for each moniker within this object */
379 /* when I tested this function in windows system ! I usually found this constant in the begining of */
380 /* the stream I dont known why (there's no indication in specification) ! */
381 res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
383 IMoniker_Enum(iface,TRUE,&enumMk);
385 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
387 res=OleSaveToStream((IPersistStream*)pmk,pStm);
389 IMoniker_Release(pmk);
391 if (FAILED(res)){
393 IEnumMoniker_Release(pmk);
394 return res;
398 IEnumMoniker_Release(enumMk);
400 return S_OK;
403 /******************************************************************************
404 * CompositeMoniker_GetSizeMax
405 ******************************************************************************/
406 HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
408 IEnumMoniker *enumMk;
409 IMoniker *pmk;
410 ULARGE_INTEGER ptmpSize;
412 /* the sizeMax of this object is calculated by calling GetSizeMax on each moniker within this object then */
413 /* suming all returned sizemax */
415 TRACE("(%p,%p)\n",iface,pcbSize);
417 if (pcbSize!=NULL)
418 return E_POINTER;
420 pcbSize->s.LowPart =0;
421 pcbSize->s.HighPart=0;
423 IMoniker_Enum(iface,TRUE,&enumMk);
425 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){
427 IMoniker_GetSizeMax(pmk,&ptmpSize);
429 IMoniker_Release(pmk);
431 pcbSize->s.LowPart +=ptmpSize.s.LowPart;
432 pcbSize->s.HighPart+=ptmpSize.s.HighPart;
435 IEnumMoniker_Release(enumMk);
437 return S_OK;
440 /******************************************************************************
441 * Composite-Moniker_Construct (local function)
442 *******************************************************************************/
443 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest)
445 DWORD mkSys;
446 IEnumMoniker *enumMoniker;
447 IMoniker *tempMk;
448 HRESULT res;
450 TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
452 /* Initialize the virtual fgunction table. */
453 This->lpvtbl1 = &VT_CompositeMonikerImpl;
454 This->lpvtbl2 = &VT_ROTDataImpl;
455 This->ref = 0;
457 This->tabSize=BLOCK_TAB_SIZE;
458 This->tabLastIndex=0;
460 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
461 if (This->tabMoniker==NULL)
462 return E_OUTOFMEMORY;
464 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
466 /* put the first moniker contents in the begining of the table */
467 if (mkSys!=MKSYS_GENERICCOMPOSITE){
469 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
470 IMoniker_AddRef(pmkFirst);
472 else{
474 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
476 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
479 if (++This->tabLastIndex==This->tabSize){
481 This->tabSize+=BLOCK_TAB_SIZE;
482 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
484 if (This->tabMoniker==NULL)
485 return E_OUTOFMEMORY;
489 IEnumMoniker_Release(enumMoniker);
492 /* put the rest moniker contents after the first one and make simplification if needed */
494 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
496 if (mkSys!=MKSYS_GENERICCOMPOSITE){
498 /* add a simple moniker to the moniker table */
500 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
502 if (res==MK_E_NEEDGENERIC){
504 /* there's no simplification in this case */
505 This->tabMoniker[This->tabLastIndex]=pmkRest;
507 This->tabLastIndex++;
509 IMoniker_AddRef(pmkRest);
511 else if (tempMk==NULL){
513 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
514 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
516 This->tabLastIndex--;
518 else if (SUCCEEDED(res)){
520 /* the non-generic composition was successful so we can make a simplification in this case */
521 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
523 This->tabMoniker[This->tabLastIndex-1]=tempMk;
524 } else
525 return res;
527 /* resize tabMoniker if needed */
528 if (This->tabLastIndex==This->tabSize){
530 This->tabSize+=BLOCK_TAB_SIZE;
532 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
534 if (This->tabMoniker==NULL)
535 return E_OUTOFMEMORY;
538 else{
540 /* add a composite moniker to the moniker table (do the same thing for each moniker within the */
541 /* composite moniker as a simple moniker (see above how to add a simple moniker case) ) */
542 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
544 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
546 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
548 if (res==MK_E_NEEDGENERIC){
550 This->tabLastIndex++;
552 else if (tempMk==NULL){
554 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
555 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
556 This->tabLastIndex--;
558 else{
560 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
562 This->tabMoniker[This->tabLastIndex-1]=tempMk;
565 if (This->tabLastIndex==This->tabSize){
567 This->tabSize+=BLOCK_TAB_SIZE;
569 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
571 if (This->tabMoniker==NULL)
572 return E_OUTOFMEMORY;
576 IEnumMoniker_Release(enumMoniker);
579 return S_OK;
582 /******************************************************************************
583 * CompositeMoniker_Destroy (local function)
584 *******************************************************************************/
585 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This)
587 TRACE("(%p)\n",This);
589 HeapFree(GetProcessHeap(),0,This->tabMoniker);
591 HeapFree(GetProcessHeap(),0,This);
593 return S_OK;
596 /******************************************************************************
597 * CompositeMoniker_BindToObject
598 ******************************************************************************/
599 HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,
600 IBindCtx* pbc,
601 IMoniker* pmkToLeft,
602 REFIID riid,
603 VOID** ppvResult)
605 HRESULT res;
606 IRunningObjectTable *prot;
607 IMoniker *tempMk,*antiMk,*mostRigthMk;
608 IEnumMoniker *enumMoniker;
610 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
612 if (ppvResult==NULL)
613 return E_POINTER;
615 *ppvResult=0;
616 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
617 /* object for the requested interface pointer. */
618 if(pmkToLeft==NULL){
620 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
622 if (SUCCEEDED(res)){
624 /* if the requested class was loaded befor ! we dont need to reload it */
625 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
627 if (res==S_OK)
628 return res;
631 else{
632 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
633 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
635 IMoniker_Enum(iface,FALSE,&enumMoniker);
636 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
637 IEnumMoniker_Release(enumMoniker);
639 res=CreateAntiMoniker(&antiMk);
640 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
641 IMoniker_Release(antiMk);
643 res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
645 IMoniker_Release(tempMk);
646 IMoniker_Release(mostRigthMk);
649 return res;
652 /******************************************************************************
653 * CompositeMoniker_BindToStorage
654 ******************************************************************************/
655 HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,
656 IBindCtx* pbc,
657 IMoniker* pmkToLeft,
658 REFIID riid,
659 VOID** ppvResult)
661 HRESULT res;
662 IMoniker *tempMk,*antiMk,*mostRigthMk;
663 IEnumMoniker *enumMoniker;
665 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
667 *ppvResult=0;
669 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
670 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
672 if (pmkToLeft!=NULL){
674 IMoniker_Enum(iface,FALSE,&enumMoniker);
675 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
676 IEnumMoniker_Release(enumMoniker);
678 res=CreateAntiMoniker(&antiMk);
679 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
680 IMoniker_Release(antiMk);
682 res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
684 IMoniker_Release(tempMk);
686 IMoniker_Release(mostRigthMk);
688 return res;
690 else
691 return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
694 /******************************************************************************
695 * CompositeMoniker_Reduce
696 ******************************************************************************/
697 HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,
698 IBindCtx* pbc,
699 DWORD dwReduceHowFar,
700 IMoniker** ppmkToLeft,
701 IMoniker** ppmkReduced)
703 HRESULT res;
704 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
705 IEnumMoniker *enumMoniker;
707 TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
709 if (ppmkReduced==NULL)
710 return E_POINTER;
712 /* This method recursively calls Reduce for each of its component monikers. */
714 if (ppmkToLeft==NULL){
716 IMoniker_Enum(iface,FALSE,&enumMoniker);
717 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
718 IEnumMoniker_Release(enumMoniker);
720 res=CreateAntiMoniker(&antiMk);
721 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
722 IMoniker_Release(antiMk);
724 return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
726 else if (*ppmkToLeft==NULL)
728 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
730 else{
732 /* separate the composite moniker in to left and right moniker */
733 IMoniker_Enum(iface,FALSE,&enumMoniker);
734 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
735 IEnumMoniker_Release(enumMoniker);
737 res=CreateAntiMoniker(&antiMk);
738 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
739 IMoniker_Release(antiMk);
741 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
742 /* of the reduced components */
743 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
744 CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
747 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
749 else{
750 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
752 IMoniker_AddRef(iface);
754 *ppmkReduced=iface;
756 return MK_S_REDUCED_TO_SELF;
761 /******************************************************************************
762 * CompositeMoniker_ComposeWith
763 ******************************************************************************/
764 HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,
765 IMoniker* pmkRight,
766 BOOL fOnlyIfNotGeneric,
767 IMoniker** ppmkComposite)
769 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
771 if ((ppmkComposite==NULL)||(pmkRight==NULL))
772 return E_POINTER;
774 *ppmkComposite=0;
776 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
777 /* otherwise, the method returns the result of combining the two monikers by calling the */
778 /* CreateGenericComposite function */
780 if (fOnlyIfNotGeneric)
781 return MK_E_NEEDGENERIC;
783 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
786 /******************************************************************************
787 * CompositeMoniker_Enum
788 ******************************************************************************/
789 HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
791 ICOM_THIS(CompositeMonikerImpl,iface);
793 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
795 if (ppenumMoniker == NULL)
796 return E_POINTER;
798 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
801 /******************************************************************************
802 * CompositeMoniker_IsEqual
803 ******************************************************************************/
804 HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
806 IEnumMoniker *enumMoniker1,*enumMoniker2;
807 IMoniker *tempMk1,*tempMk2;
808 HRESULT res1,res2,res;
810 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
812 if (pmkOtherMoniker==NULL)
813 return S_FALSE;
815 /* This method returns S_OK if the components of both monikers are equal when compared in the */
816 /* left-to-right order.*/
817 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
819 if (enumMoniker1==NULL)
820 return S_FALSE;
822 IMoniker_Enum(iface,TRUE,&enumMoniker2);
824 while(1){
826 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
827 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
829 if((res1==S_OK)&&(res2==S_OK)){
831 if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
832 res= S_FALSE;
833 break;
835 else
836 continue;
838 else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
839 res = S_OK;
840 break;
842 else{
843 res = S_FALSE;
844 break;
847 if (res1==S_OK)
848 IMoniker_Release(tempMk1);
850 if (res2==S_OK)
851 IMoniker_Release(tempMk2);
854 IEnumMoniker_Release(enumMoniker1);
855 IEnumMoniker_Release(enumMoniker2);
857 return res;
859 /******************************************************************************
860 * CompositeMoniker_Hash
861 ******************************************************************************/
862 HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
864 FIXME("(),stub!\n");
866 return E_NOTIMPL;
869 /******************************************************************************
870 * CompositeMoniker_IsRunning
871 ******************************************************************************/
872 HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,
873 IBindCtx* pbc,
874 IMoniker* pmkToLeft,
875 IMoniker* pmkNewlyRunning)
877 IRunningObjectTable* rot;
878 HRESULT res;
879 IMoniker *tempMk,*antiMk,*mostRigthMk;
880 IEnumMoniker *enumMoniker;
882 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
884 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
885 if (pmkToLeft!=NULL){
887 CreateGenericComposite(pmkToLeft,iface,&tempMk);
889 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
891 IMoniker_Release(tempMk);
893 return res;
895 else
896 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
897 /* to this moniker */
899 if (pmkNewlyRunning!=NULL)
901 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
902 return S_OK;
904 else
905 return S_FALSE;
907 else{
909 if (pbc==NULL)
910 return E_POINTER;
912 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
913 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
914 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
915 /* the composite as the pmkToLeft parameter for that call. */
917 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
919 if (FAILED(res))
920 return res;
922 res = IRunningObjectTable_IsRunning(rot,iface);
923 IRunningObjectTable_Release(rot);
925 if(res==S_OK)
926 return S_OK;
928 else{
930 IMoniker_Enum(iface,FALSE,&enumMoniker);
931 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
932 IEnumMoniker_Release(enumMoniker);
934 res=CreateAntiMoniker(&antiMk);
935 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
936 IMoniker_Release(antiMk);
938 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
940 IMoniker_Release(tempMk);
941 IMoniker_Release(mostRigthMk);
943 return res;
948 /******************************************************************************
949 * CompositeMoniker_GetTimeOfLastChange
950 ******************************************************************************/
951 HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
952 IBindCtx* pbc,
953 IMoniker* pmkToLeft,
954 FILETIME* pCompositeTime)
956 IRunningObjectTable* rot;
957 HRESULT res;
958 IMoniker *tempMk,*antiMk,*mostRigthMk;
959 IEnumMoniker *enumMoniker;
961 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
963 if (pCompositeTime==NULL)
964 return E_INVALIDARG;
966 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
967 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
968 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
969 /* of the composite as the pmkToLeft parameter for that call. */
970 if (pmkToLeft!=NULL){
972 res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
974 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
976 if (FAILED(res))
977 return res;
979 if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
980 return res;
981 else
983 IMoniker_Enum(iface,FALSE,&enumMoniker);
984 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
985 IEnumMoniker_Release(enumMoniker);
987 res=CreateAntiMoniker(&antiMk);
988 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
989 IMoniker_Release(antiMk);
991 res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
993 IMoniker_Release(tempMk);
994 IMoniker_Release(mostRigthMk);
996 return res;
998 else
999 return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
1002 /******************************************************************************
1003 * CompositeMoniker_Inverse
1004 ******************************************************************************/
1005 HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
1007 HRESULT res;
1008 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
1009 IEnumMoniker *enumMoniker;
1011 TRACE("(%p,%p)\n",iface,ppmk);
1013 if (ppmk==NULL)
1014 return E_POINTER;
1016 /* This method returns a composite moniker that consists of the inverses of each of the components */
1017 /* of the original composite, stored in reverse order */
1019 res=CreateAntiMoniker(&antiMk);
1020 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1021 IMoniker_Release(antiMk);
1023 if (tempMk==NULL)
1025 return IMoniker_Inverse(iface,ppmk);
1027 else{
1029 IMoniker_Enum(iface,FALSE,&enumMoniker);
1030 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1031 IEnumMoniker_Release(enumMoniker);
1033 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
1034 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
1036 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
1038 IMoniker_Release(tempMk);
1039 IMoniker_Release(mostRigthMk);
1040 IMoniker_Release(tempInvMk);
1041 IMoniker_Release(mostRigthInvMk);
1043 return res;
1047 /******************************************************************************
1048 * CompositeMoniker_CommonPrefixWith
1049 ******************************************************************************/
1050 HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1052 DWORD mkSys;
1053 HRESULT res1,res2;
1054 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
1055 IEnumMoniker *enumMoniker1,*enumMoniker2;
1056 ULONG i,nbCommonMk=0;
1058 /* If the other moniker is a composite, this method compares the components of each composite from left */
1059 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1060 /* of the leftmost components were common to both monikers. */
1062 if (ppmkPrefix==NULL)
1063 return E_POINTER;
1065 *ppmkPrefix=0;
1067 if (pmkOther==NULL)
1068 return MK_E_NOPREFIX;
1070 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1072 if((mkSys==MKSYS_GENERICCOMPOSITE)){
1074 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1075 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
1077 while(1){
1079 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1080 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
1082 if ((res1==S_FALSE) && (res2==S_FALSE)){
1084 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1085 *ppmkPrefix=iface;
1086 IMoniker_AddRef(iface);
1087 return MK_S_US;
1089 else if ((res1==S_OK) && (res2==S_OK)){
1091 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
1093 nbCommonMk++;
1095 else
1096 break;
1099 else if (res1==S_OK){
1101 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1102 /* ppmkPrefix to the other moniker. */
1103 *ppmkPrefix=pmkOther;
1104 return MK_S_HIM;
1106 else{
1107 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1108 /* to this moniker. */
1109 *ppmkPrefix=iface;
1110 return MK_S_ME;
1114 IEnumMoniker_Release(enumMoniker1);
1115 IEnumMoniker_Release(enumMoniker2);
1117 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1118 if (nbCommonMk==0)
1119 return MK_E_NOPREFIX;
1121 IEnumMoniker_Reset(enumMoniker1);
1123 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1125 /* if we have more than one commun moniker the result will be a composite moniker */
1126 if (nbCommonMk>1){
1128 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1129 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1130 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
1131 IMoniker_Release(tempMk1);
1132 IMoniker_Release(tempMk2);
1134 /* compose all common monikers in a composite moniker */
1135 for(i=0;i<nbCommonMk;i++){
1137 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1139 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
1141 IMoniker_Release(*ppmkPrefix);
1143 IMoniker_Release(tempMk1);
1145 *ppmkPrefix=tempMk2;
1147 return S_OK;
1149 else{
1150 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1151 *ppmkPrefix=tempMk1;
1153 return S_OK;
1156 else{
1157 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1158 of this moniker.*/
1160 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1162 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1164 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
1166 *ppmkPrefix=pmkOther;
1168 return MK_S_HIM;
1170 else
1171 return MK_E_NOPREFIX;
1174 /***************************************************************************************************
1175 * GetAfterCommonPrefix (local function)
1176 * This function returns a moniker that consist of the remainder when the common prefix is removed
1177 ***************************************************************************************************/
1178 VOID WINAPI GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
1180 IMoniker *tempMk,*tempMk1,*tempMk2;
1181 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
1182 ULONG nbRestMk=0;
1183 DWORD mkSys;
1184 HRESULT res1,res2;
1186 *restMk=0;
1188 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1189 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
1190 /* on the first difference. */
1191 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
1193 IMoniker_IsSystemMoniker(commonMk,&mkSys);
1195 if (mkSys==MKSYS_GENERICCOMPOSITE){
1197 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
1198 while(1){
1200 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1201 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
1203 if ((res1==S_FALSE)||(res2==S_FALSE)){
1205 if (res1==S_OK)
1207 nbRestMk++;
1209 IMoniker_Release(tempMk1);
1210 IMoniker_Release(tempMk1);
1212 break;
1214 IMoniker_Release(tempMk1);
1215 IMoniker_Release(tempMk1);
1218 else{
1219 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1220 IMoniker_Release(tempMk1);
1223 /* count the number of elements in the enumerator after the common prefix */
1224 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1226 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1228 IMoniker_Release(tempMk);;
1230 if (nbRestMk==0)
1231 return;
1233 /* create a generic composite moniker with monikers located after the common prefix */
1234 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1236 if (nbRestMk==1){
1238 *restMk= tempMk1;
1239 return;
1241 else {
1243 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1245 CreateGenericComposite(tempMk1,tempMk2,restMk);
1247 IMoniker_Release(tempMk1);
1249 IMoniker_Release(tempMk2);
1251 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1253 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1255 IMoniker_Release(tempMk1);
1257 IMoniker_Release(*restMk);
1259 *restMk=tempMk2;
1263 /******************************************************************************
1264 * CompositeMoniker_RelativePathTo
1265 ******************************************************************************/
1266 HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkRelPath)
1268 HRESULT res;
1269 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1271 TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1273 if (ppmkRelPath==NULL)
1274 return E_POINTER;
1276 *ppmkRelPath=0;
1278 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1279 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1280 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1282 /* finds the common prefix of the two monikers */
1283 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1285 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1286 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1288 *ppmkRelPath=pmkOther;
1289 IMoniker_AddRef(pmkOther);
1290 return MK_S_HIM;
1293 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1294 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1296 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1297 /* moniker when the common prefix is removed */
1298 if (res==MK_S_HIM){
1300 IMoniker_Inverse(restThisMk,ppmkRelPath);
1301 IMoniker_Release(restThisMk);
1303 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1304 /* when the common prefix is removed */
1305 else if (res==MK_S_ME){
1307 *ppmkRelPath=restOtherMk;
1308 IMoniker_AddRef(restOtherMk);
1310 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1311 /* moniker on the right of it. */
1312 else if (res==S_OK){
1314 IMoniker_Inverse(restThisMk,&invRestThisMk);
1315 IMoniker_Release(restThisMk);
1316 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1317 IMoniker_Release(invRestThisMk);
1318 IMoniker_Release(restOtherMk);
1320 return S_OK;
1323 /******************************************************************************
1324 * CompositeMoniker_GetDisplayName
1325 ******************************************************************************/
1326 HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,
1327 IBindCtx* pbc,
1328 IMoniker* pmkToLeft,
1329 LPOLESTR *ppszDisplayName)
1331 ULONG lengthStr=1;
1332 IEnumMoniker *enumMoniker;
1333 IMoniker* tempMk;
1334 LPOLESTR tempStr;
1336 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1338 if (ppszDisplayName==NULL)
1339 return E_POINTER;
1341 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1343 if (*ppszDisplayName==NULL)
1344 return E_OUTOFMEMORY;
1346 /* This method returns the concatenation of the display names returned by each component moniker of */
1347 /* the composite */
1349 **ppszDisplayName=0;
1351 IMoniker_Enum(iface,TRUE,&enumMoniker);
1353 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1355 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1357 lengthStr+=lstrlenW(tempStr);
1359 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1361 if (*ppszDisplayName==NULL)
1362 return E_OUTOFMEMORY;
1364 strcatW(*ppszDisplayName,tempStr);
1366 CoTaskMemFree(tempStr);
1367 IMoniker_Release(tempMk);
1370 IEnumMoniker_Release(enumMoniker);
1372 return S_OK;
1375 /******************************************************************************
1376 * CompositeMoniker_ParseDisplayName
1377 ******************************************************************************/
1378 HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,
1379 IBindCtx* pbc,
1380 IMoniker* pmkToLeft,
1381 LPOLESTR pszDisplayName,
1382 ULONG* pchEaten,
1383 IMoniker** ppmkOut)
1385 IEnumMoniker *enumMoniker;
1386 IMoniker *tempMk,*mostRigthMk,*antiMk;
1387 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1388 /* passing everything else as the pmkToLeft parameter for that call. */
1390 /* get the most right moniker */
1391 IMoniker_Enum(iface,FALSE,&enumMoniker);
1392 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1393 IEnumMoniker_Release(enumMoniker);
1395 /* get the left moniker */
1396 CreateAntiMoniker(&antiMk);
1397 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1398 IMoniker_Release(antiMk);
1400 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1403 /******************************************************************************
1404 * CompositeMoniker_IsSystemMoniker
1405 ******************************************************************************/
1406 HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1408 TRACE("(%p,%p)\n",iface,pwdMksys);
1410 if (!pwdMksys)
1411 return E_POINTER;
1413 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1415 return S_OK;
1418 /*******************************************************************************
1419 * CompositeMonikerIROTData_QueryInterface
1420 *******************************************************************************/
1421 HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1424 ICOM_THIS_From_IROTData(IMoniker, iface);
1426 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
1428 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1431 /***********************************************************************
1432 * CompositeMonikerIROTData_AddRef
1434 ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1436 ICOM_THIS_From_IROTData(IMoniker, iface);
1438 TRACE("(%p)\n",iface);
1440 return CompositeMonikerImpl_AddRef(This);
1443 /***********************************************************************
1444 * CompositeMonikerIROTData_Release
1446 ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1448 ICOM_THIS_From_IROTData(IMoniker, iface);
1450 TRACE("(%p)\n",iface);
1452 return CompositeMonikerImpl_Release(This);
1455 /******************************************************************************
1456 * CompositeMonikerIROTData_GetComparaisonData
1457 ******************************************************************************/
1458 HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1459 BYTE* pbData,
1460 ULONG cbMax,
1461 ULONG* pcbData)
1463 FIXME("(),stub!\n");
1464 return E_NOTIMPL;
1467 /******************************************************************************
1468 * EnumMonikerImpl_QueryInterface
1469 ******************************************************************************/
1470 HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1472 ICOM_THIS(EnumMonikerImpl,iface);
1474 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1476 /* Perform a sanity check on the parameters.*/
1477 if ( (This==0) || (ppvObject==0) )
1478 return E_INVALIDARG;
1480 /* Initialize the return parameter */
1481 *ppvObject = 0;
1483 /* Compare the riid with the interface IDs implemented by this object.*/
1484 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1485 *ppvObject = iface;
1487 /* Check that we obtained an interface.*/
1488 if ((*ppvObject)==0)
1489 return E_NOINTERFACE;
1491 /* Query Interface always increases the reference count by one when it is successful */
1492 EnumMonikerImpl_AddRef(iface);
1494 return S_OK;
1497 /******************************************************************************
1498 * EnumMonikerImpl_AddRef
1499 ******************************************************************************/
1500 ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1502 ICOM_THIS(EnumMonikerImpl,iface);
1504 TRACE("(%p)\n",This);
1506 return ++(This->ref);
1510 /******************************************************************************
1511 * EnumMonikerImpl_Release
1512 ******************************************************************************/
1513 ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1515 ICOM_THIS(EnumMonikerImpl,iface);
1516 ULONG i
1518 TRACE("(%p)\n",This);
1520 This->ref--;
1522 /* destroy the object if there's no more reference on it */
1523 if (This->ref==0){
1525 for(i=0;i<This->tabSize;i++)
1526 IMoniker_Release(This->tabMoniker[i]);
1528 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1529 HeapFree(GetProcessHeap(),0,This);
1531 return 0;
1533 return This->ref;;
1536 /******************************************************************************
1537 * EnumMonikerImpl_Next
1538 ******************************************************************************/
1539 HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){
1541 ICOM_THIS(EnumMonikerImpl,iface);
1542 ULONG i;
1544 /* retrieve the requested number of moniker from the current position */
1545 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1547 rgelt[i]=This->tabMoniker[This->currentPos++];
1549 if (pceltFethed!=NULL)
1550 *pceltFethed= i;
1552 if (i==celt)
1553 return S_OK;
1554 else
1555 return S_FALSE;
1558 /******************************************************************************
1559 * EnumMonikerImpl_Skip
1560 ******************************************************************************/
1561 HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){
1563 ICOM_THIS(EnumMonikerImpl,iface);
1565 if ((This->currentPos+celt) >= This->tabSize)
1566 return S_FALSE;
1568 This->currentPos+=celt;
1570 return S_OK;
1573 /******************************************************************************
1574 * EnumMonikerImpl_Reset
1575 ******************************************************************************/
1576 HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){
1578 ICOM_THIS(EnumMonikerImpl,iface);
1580 This->currentPos=0;
1582 return S_OK;
1585 /******************************************************************************
1586 * EnumMonikerImpl_Clone
1587 ******************************************************************************/
1588 HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){
1590 ICOM_THIS(EnumMonikerImpl,iface);
1592 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1595 /******************************************************************************
1596 * EnumMonikerImpl_CreateEnumMoniker
1597 ******************************************************************************/
1598 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,
1599 ULONG tabSize,
1600 ULONG currentPos,
1601 BOOL leftToRigth,
1602 IEnumMoniker ** ppmk)
1604 EnumMonikerImpl* newEnumMoniker;
1605 int i;
1608 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1610 if (newEnumMoniker == 0)
1611 return STG_E_INSUFFICIENTMEMORY;
1613 if (currentPos > tabSize)
1614 return E_INVALIDARG;
1616 /* Initialize the virtual function table. */
1617 ICOM_VTBL(newEnumMoniker) = &VT_EnumMonikerImpl;
1618 newEnumMoniker->ref = 0;
1620 newEnumMoniker->tabSize=tabSize;
1621 newEnumMoniker->currentPos=currentPos;
1623 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1625 if (newEnumMoniker->tabMoniker==NULL)
1626 return E_OUTOFMEMORY;
1628 if (leftToRigth)
1629 for (i=0;i<tabSize;i++){
1631 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1632 IMoniker_AddRef(tabMoniker[i]);
1634 else
1635 for (i=tabSize-1;i>=0;i--){
1637 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1638 IMoniker_AddRef(tabMoniker[i]);
1641 *ppmk=(IEnumMoniker*)newEnumMoniker;
1643 return S_OK;
1646 /******************************************************************************
1647 * CreateGenericComposite [OLE32.56]
1648 ******************************************************************************/
1649 HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite)
1651 CompositeMonikerImpl* newCompositeMoniker = 0;
1652 HRESULT hr = S_OK;
1654 TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1656 if (ppmkComposite==NULL)
1657 return E_POINTER;
1659 *ppmkComposite=0;
1661 if (pmkFirst==NULL && pmkRest!=NULL){
1663 *ppmkComposite=pmkRest;
1664 return S_OK;
1666 else if (pmkFirst!=NULL && pmkRest==NULL){
1667 *ppmkComposite=pmkFirst;
1668 return S_OK;
1670 else if (pmkFirst==NULL && pmkRest==NULL)
1671 return S_OK;
1673 newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
1675 if (newCompositeMoniker == 0)
1676 return STG_E_INSUFFICIENTMEMORY;
1678 hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
1680 if (FAILED(hr)){
1682 HeapFree(GetProcessHeap(),0,newCompositeMoniker);
1683 return hr;
1685 if (newCompositeMoniker->tabLastIndex==1)
1687 hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
1688 else
1690 hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
1692 return hr;
1695 /******************************************************************************
1696 * MonikerCommonPrefixWith [OLE32.82]
1697 ******************************************************************************/
1698 HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1700 FIXME("(),stub!\n");
1701 return E_NOTIMPL;