Fixed TLB_Read (can easily get count!=bytesread at the end of the file).
[wine/dcerpc.git] / ole / compositemoniker.c
blob2f145f5fcb5fc190154c019ca3606f0a3341917c
1 /***************************************************************************************
2 * CompositeMonikers implementation
4 * Copyright 1999 Noomen Hamza
5 ***************************************************************************************/
7 #include <assert.h>
8 #include "winerror.h"
9 #include "debug.h"
10 #include "heap.h"
11 #include "winuser.h"
12 #include "file.h"
13 #include "winreg.h"
14 #include "objbase.h"
15 #include "wine/obj_inplace.h"
16 #include "ole2.h"
18 DEFAULT_DEBUG_CHANNEL(ole)
20 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
22 /* CompositeMoniker data structure */
23 typedef struct CompositeMonikerImpl{
25 ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/
27 /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
28 * two monikers are equal. That's whay IROTData interface is implemented by monikers.
30 ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/
32 ULONG ref; /* reference counter for this object */
34 IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */
36 ULONG tabSize; /* size of tabMoniker */
38 ULONG tabLastIndex; /* first free index in tabMoniker */
40 } CompositeMonikerImpl;
43 /* EnumMoniker data structure */
44 typedef struct EnumMonikerImpl{
46 ICOM_VTABLE(IEnumMoniker)* lpvtbl; /* VTable relative to the IEnumMoniker interface.*/
48 ULONG ref; /* reference counter for this object */
50 IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
52 ULONG tabSize; /* size of tabMoniker */
54 ULONG currentPos; /* index pointer on the current moniker */
56 } EnumMonikerImpl;
59 /********************************************************************************/
60 /* CompositeMoniker prototype functions : */
62 /* IUnknown prototype functions */
63 static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
64 static ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface);
65 static ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface);
67 /* IPersist prototype functions */
68 static HRESULT WINAPI CompositeMonikerImpl_GetClassID(const IMoniker* iface, CLSID *pClassID);
70 /* IPersistStream prototype functions */
71 static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface);
72 static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm);
73 static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
74 static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
76 /* IMoniker prototype functions */
77 static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
78 static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
79 static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
80 static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
81 static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
82 static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
83 static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
84 static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
85 static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime);
86 static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
87 static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
88 static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
89 static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
90 static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
91 static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
93 /********************************************************************************/
94 /* IROTData prototype functions */
96 /* IUnknown prototype functions */
97 static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
98 static ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface);
99 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface);
101 /* IROTData prototype function */
102 static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
104 /* Local function used by CompositeMoniker implementation */
105 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest);
106 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface);
108 /********************************************************************************/
109 /* IEnumMoniker prototype functions */
111 /* IUnknown prototype functions */
112 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject);
113 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface);
114 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface);
116 /* IEnumMonker prototype functions */
117 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched);
118 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt);
119 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface);
120 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum);
122 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
124 /********************************************************************************/
125 /* Virtual function table for the CompositeMonikerImpl class witch include */
126 /* Ipersist, IPersistStream and IMoniker functions. */
128 static ICOM_VTABLE(IMoniker) VT_CompositeMonikerImpl =
130 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
131 CompositeMonikerImpl_QueryInterface,
132 CompositeMonikerImpl_AddRef,
133 CompositeMonikerImpl_Release,
134 CompositeMonikerImpl_GetClassID,
135 CompositeMonikerImpl_IsDirty,
136 CompositeMonikerImpl_Load,
137 CompositeMonikerImpl_Save,
138 CompositeMonikerImpl_GetSizeMax,
139 CompositeMonikerImpl_BindToObject,
140 CompositeMonikerImpl_BindToStorage,
141 CompositeMonikerImpl_Reduce,
142 CompositeMonikerImpl_ComposeWith,
143 CompositeMonikerImpl_Enum,
144 CompositeMonikerImpl_IsEqual,
145 CompositeMonikerImpl_Hash,
146 CompositeMonikerImpl_IsRunning,
147 CompositeMonikerImpl_GetTimeOfLastChange,
148 CompositeMonikerImpl_Inverse,
149 CompositeMonikerImpl_CommonPrefixWith,
150 CompositeMonikerImpl_RelativePathTo,
151 CompositeMonikerImpl_GetDisplayName,
152 CompositeMonikerImpl_ParseDisplayName,
153 CompositeMonikerImpl_IsSystemMoniker
156 /********************************************************************************/
157 /* Virtual function table for the IROTData class. */
158 static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
160 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
161 CompositeMonikerROTDataImpl_QueryInterface,
162 CompositeMonikerROTDataImpl_AddRef,
163 CompositeMonikerROTDataImpl_Release,
164 CompositeMonikerROTDataImpl_GetComparaisonData
167 /********************************************************************************/
168 /* Virtual function table for the IROTData class */
169 static ICOM_VTABLE(IEnumMoniker) VT_EnumMonikerImpl =
171 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
172 EnumMonikerImpl_QueryInterface,
173 EnumMonikerImpl_AddRef,
174 EnumMonikerImpl_Release,
175 EnumMonikerImpl_Next,
176 EnumMonikerImpl_Skip,
177 EnumMonikerImpl_Reset,
178 EnumMonikerImpl_Clone
181 /*******************************************************************************
182 * CompositeMoniker_QueryInterface
183 *******************************************************************************/
184 HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
186 ICOM_THIS(CompositeMonikerImpl,iface);
188 TRACE(ole,"(%p,%p,%p)\n",This,riid,ppvObject);
190 /* Perform a sanity check on the parameters.*/
191 if ( (This==0) || (ppvObject==0) )
192 return E_INVALIDARG;
194 /* Initialize the return parameter */
195 *ppvObject = 0;
197 /* Compare the riid with the interface IDs implemented by this object.*/
198 if (IsEqualIID(&IID_IUnknown, riid) ||
199 IsEqualIID(&IID_IPersist, riid) ||
200 IsEqualIID(&IID_IPersistStream, riid) ||
201 IsEqualIID(&IID_IMoniker, riid)
203 *ppvObject = iface;
204 else if (IsEqualIID(&IID_IROTData, riid))
205 *ppvObject = (IROTData*)&(This->lpvtbl2);
207 /* Check that we obtained an interface.*/
208 if ((*ppvObject)==0)
209 return E_NOINTERFACE;
211 /* Query Interface always increases the reference count by one when it is successful */
212 CompositeMonikerImpl_AddRef(iface);
214 return S_OK;
217 /******************************************************************************
218 * CompositeMoniker_AddRef
219 ******************************************************************************/
220 ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)
222 ICOM_THIS(CompositeMonikerImpl,iface);
224 TRACE(ole,"(%p)\n",This);
226 return ++(This->ref);
229 /******************************************************************************
230 * CompositeMoniker_Release
231 ******************************************************************************/
232 ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
234 ICOM_THIS(CompositeMonikerImpl,iface);
235 ULONG i;
237 TRACE(ole,"(%p)\n",This);
239 This->ref--;
241 /* destroy the object if there's no more reference on it */
242 if (This->ref==0){
244 /* release all the components before destroying this object */
245 for (i=0;i<This->tabLastIndex;i++)
246 IMoniker_Release(This->tabMoniker[i]);
248 CompositeMonikerImpl_Destroy(This);
250 return 0;
252 return This->ref;;
255 /******************************************************************************
256 * CompositeMoniker_GetClassID
257 ******************************************************************************/
258 HRESULT WINAPI CompositeMonikerImpl_GetClassID(const IMoniker* iface,CLSID *pClassID)
260 TRACE(ole,"(%p,%p),stub!\n",iface,pClassID);
262 if (pClassID==NULL)
263 return E_POINTER;
265 *pClassID = CLSID_CompositeMoniker;
267 return S_OK;
270 /******************************************************************************
271 * CompositeMoniker_IsDirty
272 ******************************************************************************/
273 HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)
275 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
276 method in the OLE-provided moniker interfaces always return S_FALSE because
277 their internal state never changes. */
279 TRACE(ole,"(%p)\n",iface);
281 return S_FALSE;
284 /******************************************************************************
285 * CompositeMoniker_Load
286 ******************************************************************************/
287 HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
289 HRESULT res;
290 DWORD constant;
291 CLSID clsid;
292 WCHAR string[1]={0};
294 ICOM_THIS(CompositeMonikerImpl,iface);
296 TRACE(ole,"(%p,%p)\n",iface,pStm);
298 /* this function call OleLoadFromStream function for each moniker within this object */
300 /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
301 res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
303 if (SUCCEEDED(res)&& constant!=3)
304 return E_FAIL;
306 while(1){
307 #if 0
308 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
309 #endif
310 res=ReadClassStm(pStm,&clsid);
311 printf("res=%ld",res);
312 if (FAILED(res))
313 break;
315 if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
316 res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
317 if (FAILED(res))
318 break;
319 res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
320 if (FAILED(res))
321 break;
323 else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
324 CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
325 if (res!=S_OK)
326 break;
327 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
328 if (FAILED(res))
329 break;
331 else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
332 CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
333 if (FAILED(res))
334 break;
335 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
336 if (FAILED(res))
337 break;
339 else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
340 return E_FAIL;
342 else{
343 FIXME(ole,"()");
344 break;
345 return E_NOTIMPL;
348 /* resize the table if needed */
349 if (++This->tabLastIndex==This->tabSize){
351 This->tabSize+=BLOCK_TAB_SIZE;
352 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
354 if (This->tabMoniker==NULL)
355 return E_OUTOFMEMORY;
359 return res;
362 /******************************************************************************
363 * CompositeMoniker_Save
364 ******************************************************************************/
365 HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
367 HRESULT res;
368 IEnumMoniker *enumMk;
369 IMoniker *pmk;
370 DWORD constant=3;
372 TRACE(ole,"(%p,%p,%d)\n",iface,pStm,fClearDirty);
374 /* this function call OleSaveToStream function for each moniker within this object */
376 /* when I tested this function in windows system ! I usually found this constant in the begining of */
377 /* the stream I dont known why (there's no indication in specification) ! */
378 res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
380 IMoniker_Enum(iface,TRUE,&enumMk);
382 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
384 res=OleSaveToStream((IPersistStream*)pmk,pStm);
386 IMoniker_Release(pmk);
388 if (FAILED(res)){
390 IEnumMoniker_Release(pmk);
391 return res;
395 IEnumMoniker_Release(enumMk);
397 return S_OK;
400 /******************************************************************************
401 * CompositeMoniker_GetSizeMax
402 ******************************************************************************/
403 HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
405 IEnumMoniker *enumMk;
406 IMoniker *pmk;
407 ULARGE_INTEGER ptmpSize;
409 /* the sizeMax of this object is calculated by calling GetSizeMax on each moniker within this object then */
410 /* suming all returned sizemax */
412 TRACE(ole,"(%p,%p)\n",iface,pcbSize);
414 if (pcbSize!=NULL)
415 return E_POINTER;
417 pcbSize->LowPart =0;
418 pcbSize->HighPart=0;
420 IMoniker_Enum(iface,TRUE,&enumMk);
422 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){
424 IMoniker_GetSizeMax(pmk,&ptmpSize);
426 IMoniker_Release(pmk);
428 pcbSize->LowPart +=ptmpSize.LowPart;
429 pcbSize->HighPart+=ptmpSize.HighPart;
432 IEnumMoniker_Release(enumMk);
434 return S_OK;
437 /******************************************************************************
438 * Composite-Moniker_Construct (local function)
439 *******************************************************************************/
440 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest)
442 DWORD mkSys;
443 IEnumMoniker *enumMoniker;
444 IMoniker *tempMk;
445 HRESULT res;
447 TRACE(ole,"(%p,%p,%p)\n",This,pmkFirst,pmkRest);
449 /* Initialize the virtual fgunction table. */
450 This->lpvtbl1 = &VT_CompositeMonikerImpl;
451 This->lpvtbl2 = &VT_ROTDataImpl;
452 This->ref = 0;
454 This->tabSize=BLOCK_TAB_SIZE;
455 This->tabLastIndex=0;
457 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
458 if (This->tabMoniker==NULL)
459 return E_OUTOFMEMORY;
461 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
463 /* put the first moniker contents in the begining of the table */
464 if (mkSys!=MKSYS_GENERICCOMPOSITE){
466 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
467 IMoniker_AddRef(pmkFirst);
469 else{
471 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
473 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
476 if (++This->tabLastIndex==This->tabSize){
478 This->tabSize+=BLOCK_TAB_SIZE;
479 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
481 if (This->tabMoniker==NULL)
482 return E_OUTOFMEMORY;
486 IEnumMoniker_Release(enumMoniker);
489 /* put the rest moniker contents after the first one and make simplification if needed */
491 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
493 if (mkSys!=MKSYS_GENERICCOMPOSITE){
495 /* add a simple moniker to the moniker table */
497 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
499 if (res==MK_E_NEEDGENERIC){
501 /* there's no simplification in this case */
502 This->tabMoniker[This->tabLastIndex]=pmkRest;
504 This->tabLastIndex++;
506 IMoniker_AddRef(pmkRest);
508 else if (tempMk==NULL){
510 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
511 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
513 This->tabLastIndex--;
515 else if (SUCCEEDED(res)){
517 /* the non-generic composition was successful so we can make a simplification in this case */
518 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
520 This->tabMoniker[This->tabLastIndex-1]=tempMk;
521 } else
522 return res;
524 /* resize tabMoniker if needed */
525 if (This->tabLastIndex==This->tabSize){
527 This->tabSize+=BLOCK_TAB_SIZE;
529 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
531 if (This->tabMoniker==NULL)
532 return E_OUTOFMEMORY;
535 else{
537 /* add a composite moniker to the moniker table (do the same thing for each moniker within the */
538 /* composite moniker as a simple moniker (see above how to add a simple moniker case) ) */
539 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
541 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
543 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
545 if (res==MK_E_NEEDGENERIC){
547 This->tabLastIndex++;
549 else if (tempMk==NULL){
551 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
552 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
553 This->tabLastIndex--;
555 else{
557 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
559 This->tabMoniker[This->tabLastIndex-1]=tempMk;
562 if (This->tabLastIndex==This->tabSize){
564 This->tabSize+=BLOCK_TAB_SIZE;
566 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
568 if (This->tabMoniker==NULL)
569 return E_OUTOFMEMORY;
573 IEnumMoniker_Release(enumMoniker);
576 return S_OK;
579 /******************************************************************************
580 * CompositeMoniker_Destroy (local function)
581 *******************************************************************************/
582 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This)
584 TRACE(ole,"(%p)\n",This);
586 HeapFree(GetProcessHeap(),0,This->tabMoniker);
588 HeapFree(GetProcessHeap(),0,This);
590 return S_OK;
593 /******************************************************************************
594 * CompositeMoniker_BindToObject
595 ******************************************************************************/
596 HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,
597 IBindCtx* pbc,
598 IMoniker* pmkToLeft,
599 REFIID riid,
600 VOID** ppvResult)
602 HRESULT res;
603 IRunningObjectTable *prot;
604 IMoniker *tempMk,*antiMk,*mostRigthMk;
605 IEnumMoniker *enumMoniker;
607 TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
609 if (ppvResult==NULL)
610 return E_POINTER;
612 *ppvResult=0;
613 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
614 /* object for the requested interface pointer. */
615 if(pmkToLeft==NULL){
617 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
619 if (SUCCEEDED(res)){
621 /* if the requested class was loaded befor ! we dont need to reload it */
622 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
624 if (res==S_OK)
625 return res;
628 else{
629 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
630 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
632 IMoniker_Enum(iface,FALSE,&enumMoniker);
633 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
634 IEnumMoniker_Release(enumMoniker);
636 res=CreateAntiMoniker(&antiMk);
637 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
638 IMoniker_Release(antiMk);
640 res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
642 IMoniker_Release(tempMk);
643 IMoniker_Release(mostRigthMk);
646 return res;
649 /******************************************************************************
650 * CompositeMoniker_BindToStorage
651 ******************************************************************************/
652 HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,
653 IBindCtx* pbc,
654 IMoniker* pmkToLeft,
655 REFIID riid,
656 VOID** ppvResult)
658 HRESULT res;
659 IMoniker *tempMk,*antiMk,*mostRigthMk;
660 IEnumMoniker *enumMoniker;
662 TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
664 *ppvResult=0;
666 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
667 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
669 if (pmkToLeft!=NULL){
671 IMoniker_Enum(iface,FALSE,&enumMoniker);
672 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
673 IEnumMoniker_Release(enumMoniker);
675 res=CreateAntiMoniker(&antiMk);
676 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
677 IMoniker_Release(antiMk);
679 res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
681 IMoniker_Release(tempMk);
683 IMoniker_Release(mostRigthMk);
685 return res;
687 else
688 return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
691 /******************************************************************************
692 * CompositeMoniker_Reduce
693 ******************************************************************************/
694 HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,
695 IBindCtx* pbc,
696 DWORD dwReduceHowFar,
697 IMoniker** ppmkToLeft,
698 IMoniker** ppmkReduced)
700 HRESULT res;
701 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
702 IEnumMoniker *enumMoniker;
704 TRACE(ole,"(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
706 if (ppmkReduced==NULL)
707 return E_POINTER;
709 /* This method recursively calls Reduce for each of its component monikers. */
711 if (ppmkToLeft==NULL){
713 IMoniker_Enum(iface,FALSE,&enumMoniker);
714 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
715 IEnumMoniker_Release(enumMoniker);
717 res=CreateAntiMoniker(&antiMk);
718 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
719 IMoniker_Release(antiMk);
721 return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
723 else if (*ppmkToLeft==NULL)
725 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
727 else{
729 /* separate the copmosite moniker in to left and wrigth moniker */
730 IMoniker_Enum(iface,FALSE,&enumMoniker);
731 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
732 IEnumMoniker_Release(enumMoniker);
734 res=CreateAntiMoniker(&antiMk);
735 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
736 IMoniker_Release(antiMk);
738 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
739 /* of the reduced components */
740 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
741 CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
744 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
746 else{
747 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
749 IMoniker_AddRef(iface);
751 *ppmkReduced=iface;
753 return MK_S_REDUCED_TO_SELF;
758 /******************************************************************************
759 * CompositeMoniker_ComposeWith
760 ******************************************************************************/
761 HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,
762 IMoniker* pmkRight,
763 BOOL fOnlyIfNotGeneric,
764 IMoniker** ppmkComposite)
766 TRACE(ole,"(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
768 if ((ppmkComposite==NULL)||(pmkRight==NULL))
769 return E_POINTER;
771 *ppmkComposite=0;
773 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
774 /* otherwise, the method returns the result of combining the two monikers by calling the */
775 /* CreateGenericComposite function */
777 if (fOnlyIfNotGeneric)
778 return MK_E_NEEDGENERIC;
780 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
783 /******************************************************************************
784 * CompositeMoniker_Enum
785 ******************************************************************************/
786 HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
788 ICOM_THIS(CompositeMonikerImpl,iface);
790 TRACE(ole,"(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
792 if (ppenumMoniker == NULL)
793 return E_POINTER;
795 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
798 /******************************************************************************
799 * CompositeMoniker_IsEqual
800 ******************************************************************************/
801 HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
803 IEnumMoniker *enumMoniker1,*enumMoniker2;
804 IMoniker *tempMk1,*tempMk2;
805 HRESULT res1,res2,res;
807 TRACE(ole,"(%p,%p)\n",iface,pmkOtherMoniker);
809 if (pmkOtherMoniker==NULL)
810 return S_FALSE;
812 /* This method returns S_OK if the components of both monikers are equal when compared in the */
813 /* left-to-right order.*/
814 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
816 if (enumMoniker1==NULL)
817 return S_FALSE;
819 IMoniker_Enum(iface,TRUE,&enumMoniker2);
821 while(1){
823 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
824 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
826 if((res1==S_OK)&&(res2==S_OK)){
828 if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
829 res= S_FALSE;
830 break;
832 else
833 continue;
835 else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
836 res = S_OK;
837 break;
839 else{
840 res = S_FALSE;
841 break;
844 if (res1==S_OK)
845 IMoniker_Release(tempMk1);
847 if (res2==S_OK)
848 IMoniker_Release(tempMk2);
851 IEnumMoniker_Release(enumMoniker1);
852 IEnumMoniker_Release(enumMoniker2);
854 return res;
856 /******************************************************************************
857 * CompositeMoniker_Hash
858 ******************************************************************************/
859 HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
861 FIXME(ole,"(),stub!\n");
863 return E_NOTIMPL;
866 /******************************************************************************
867 * CompositeMoniker_IsRunning
868 ******************************************************************************/
869 HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,
870 IBindCtx* pbc,
871 IMoniker* pmkToLeft,
872 IMoniker* pmkNewlyRunning)
874 IRunningObjectTable* rot;
875 HRESULT res;
876 IMoniker *tempMk,*antiMk,*mostRigthMk;
877 IEnumMoniker *enumMoniker;
879 TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
881 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
882 if (pmkToLeft!=NULL){
884 CreateGenericComposite(pmkToLeft,iface,&tempMk);
886 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
888 IMoniker_Release(tempMk);
890 return res;
892 else
893 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
894 /* to this moniker */
896 if (pmkNewlyRunning!=NULL)
898 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
899 return S_OK;
901 else
902 return S_FALSE;
904 else{
906 if (pbc==NULL)
907 return E_POINTER;
909 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
910 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
911 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
912 /* the composite as the pmkToLeft parameter for that call. */
914 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
916 if (FAILED(res))
917 return res;
919 res = IRunningObjectTable_IsRunning(rot,iface);
920 IRunningObjectTable_Release(rot);
922 if(res==S_OK)
923 return S_OK;
925 else{
927 IMoniker_Enum(iface,FALSE,&enumMoniker);
928 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
929 IEnumMoniker_Release(enumMoniker);
931 res=CreateAntiMoniker(&antiMk);
932 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
933 IMoniker_Release(antiMk);
935 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
937 IMoniker_Release(tempMk);
938 IMoniker_Release(mostRigthMk);
940 return res;
945 /******************************************************************************
946 * CompositeMoniker_GetTimeOfLastChange
947 ******************************************************************************/
948 HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
949 IBindCtx* pbc,
950 IMoniker* pmkToLeft,
951 FILETIME* pCompositeTime)
953 IRunningObjectTable* rot;
954 HRESULT res;
955 IMoniker *tempMk,*antiMk,*mostRigthMk;
956 IEnumMoniker *enumMoniker;
958 TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
960 if (pCompositeTime==NULL)
961 return E_INVALIDARG;
963 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
964 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
965 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
966 /* of the composite as the pmkToLeft parameter for that call. */
967 if (pmkToLeft!=NULL){
969 res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
971 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
973 if (FAILED(res))
974 return res;
976 if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
977 return res;
978 else
980 IMoniker_Enum(iface,FALSE,&enumMoniker);
981 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
982 IEnumMoniker_Release(enumMoniker);
984 res=CreateAntiMoniker(&antiMk);
985 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
986 IMoniker_Release(antiMk);
988 res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
990 IMoniker_Release(tempMk);
991 IMoniker_Release(mostRigthMk);
993 return res;
995 else
996 return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
999 /******************************************************************************
1000 * CompositeMoniker_Inverse
1001 ******************************************************************************/
1002 HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
1004 HRESULT res;
1005 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
1006 IEnumMoniker *enumMoniker;
1008 TRACE(ole,"(%p,%p)\n",iface,ppmk);
1010 if (ppmk==NULL)
1011 return E_POINTER;
1013 /* This method returns a composite moniker that consists of the inverses of each of the components */
1014 /* of the original composite, stored in reverse order */
1016 res=CreateAntiMoniker(&antiMk);
1017 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1018 IMoniker_Release(antiMk);
1020 if (tempMk==NULL)
1022 return IMoniker_Inverse(iface,ppmk);
1024 else{
1026 IMoniker_Enum(iface,FALSE,&enumMoniker);
1027 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1028 IEnumMoniker_Release(enumMoniker);
1030 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
1031 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
1033 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
1035 IMoniker_Release(tempMk);
1036 IMoniker_Release(mostRigthMk);
1037 IMoniker_Release(tempInvMk);
1038 IMoniker_Release(mostRigthInvMk);
1040 return res;
1044 /******************************************************************************
1045 * CompositeMoniker_CommonPrefixWith
1046 ******************************************************************************/
1047 HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1049 DWORD mkSys;
1050 HRESULT res1,res2;
1051 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
1052 IEnumMoniker *enumMoniker1,*enumMoniker2;
1053 ULONG i,nbCommonMk=0;
1055 /* If the other moniker is a composite, this method compares the components of each composite from left */
1056 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1057 /* of the leftmost components were common to both monikers. */
1059 if (ppmkPrefix==NULL)
1060 return E_POINTER;
1062 *ppmkPrefix=0;
1064 if (pmkOther==NULL)
1065 return MK_E_NOPREFIX;
1067 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1069 if((mkSys==MKSYS_GENERICCOMPOSITE)){
1071 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1072 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
1074 while(1){
1076 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1077 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
1079 if ((res1==S_FALSE) && (res2==S_FALSE)){
1081 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1082 *ppmkPrefix=iface;
1083 IMoniker_AddRef(iface);
1084 return MK_S_US;
1086 else if ((res1==S_OK) && (res2==S_OK)){
1088 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
1090 nbCommonMk++;
1092 else
1093 break;
1096 else if (res1==S_OK){
1098 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1099 /* ppmkPrefix to the other moniker. */
1100 *ppmkPrefix=pmkOther;
1101 return MK_S_HIM;
1103 else{
1104 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1105 /* to this moniker. */
1106 *ppmkPrefix=iface;
1107 return MK_S_ME;
1111 IEnumMoniker_Release(enumMoniker1);
1112 IEnumMoniker_Release(enumMoniker2);
1114 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1115 if (nbCommonMk==0)
1116 return MK_E_NOPREFIX;
1118 IEnumMoniker_Reset(enumMoniker1);
1120 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1122 /* if we have more than one commun moniker the result will be a composite moniker */
1123 if (nbCommonMk>1){
1125 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1126 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1127 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
1128 IMoniker_Release(tempMk1);
1129 IMoniker_Release(tempMk2);
1131 /* compose all common monikers in a composite moniker */
1132 for(i=0;i<nbCommonMk;i++){
1134 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1136 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
1138 IMoniker_Release(*ppmkPrefix);
1140 IMoniker_Release(tempMk1);
1142 *ppmkPrefix=tempMk2;
1144 return S_OK;
1146 else{
1147 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1148 *ppmkPrefix=tempMk1;
1150 return S_OK;
1153 else{
1154 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1155 of this moniker.*/
1157 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1159 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1161 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
1163 *ppmkPrefix=pmkOther;
1165 return MK_S_HIM;
1167 else
1168 return MK_E_NOPREFIX;
1171 /***************************************************************************************************
1172 * GetAfterCommonPrefix (local function)
1173 * This function returns a moniker that consist of the remainder when the common prefix is removed
1174 ***************************************************************************************************/
1175 VOID WINAPI GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
1177 IMoniker *tempMk,*tempMk1,*tempMk2;
1178 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
1179 ULONG nbRestMk=0;
1180 DWORD mkSys;
1181 HRESULT res1,res2;
1183 *restMk=0;
1185 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1186 /* prefix: enum the two monikers (left-wrigth) then compare these enumerations (left-wrigth) and stop */
1187 /* on the first difference. */
1188 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
1190 IMoniker_IsSystemMoniker(commonMk,&mkSys);
1192 if (mkSys==MKSYS_GENERICCOMPOSITE){
1194 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
1195 while(1){
1197 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1198 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
1200 if ((res1==S_FALSE)||(res2==S_FALSE)){
1202 if (res1==S_OK)
1204 nbRestMk++;
1206 IMoniker_Release(tempMk1);
1207 IMoniker_Release(tempMk1);
1209 break;
1211 IMoniker_Release(tempMk1);
1212 IMoniker_Release(tempMk1);
1215 else{
1216 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1217 IMoniker_Release(tempMk1);
1220 /* count the number of elements in the enumerator after the common prefix */
1221 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1223 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1225 IMoniker_Release(tempMk);;
1227 if (nbRestMk==0)
1228 return;
1230 /* create a generic composite moniker with monikers located after the common prefix */
1231 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1233 if (nbRestMk==1){
1235 *restMk= tempMk1;
1236 return;
1238 else {
1240 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1242 CreateGenericComposite(tempMk1,tempMk2,restMk);
1244 IMoniker_Release(tempMk1);
1246 IMoniker_Release(tempMk2);
1248 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1250 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1252 IMoniker_Release(tempMk1);
1254 IMoniker_Release(*restMk);
1256 *restMk=tempMk2;
1260 /******************************************************************************
1261 * CompositeMoniker_RelativePathTo
1262 ******************************************************************************/
1263 HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkRelPath)
1265 HRESULT res;
1266 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1268 TRACE(ole,"(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1270 if (ppmkRelPath==NULL)
1271 return E_POINTER;
1273 *ppmkRelPath=0;
1275 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1276 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1277 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1279 /* finds the common prefix of the two monikers */
1280 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1282 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1283 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1285 *ppmkRelPath=pmkOther;
1286 IMoniker_AddRef(pmkOther);
1287 return MK_S_HIM;
1290 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1291 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1293 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1294 /* moniker when the common prefix is removed */
1295 if (res==MK_S_HIM){
1297 IMoniker_Inverse(restThisMk,ppmkRelPath);
1298 IMoniker_Release(restThisMk);
1300 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1301 /* when the common prefix is removed */
1302 else if (res==MK_S_ME){
1304 *ppmkRelPath=restOtherMk;
1305 IMoniker_AddRef(restOtherMk);
1307 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1308 /* moniker on the right of it. */
1309 else if (res==S_OK){
1311 IMoniker_Inverse(restThisMk,&invRestThisMk);
1312 IMoniker_Release(restThisMk);
1313 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1314 IMoniker_Release(invRestThisMk);
1315 IMoniker_Release(restOtherMk);
1317 return S_OK;
1320 /******************************************************************************
1321 * CompositeMoniker_GetDisplayName
1322 ******************************************************************************/
1323 HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,
1324 IBindCtx* pbc,
1325 IMoniker* pmkToLeft,
1326 LPOLESTR *ppszDisplayName)
1328 ULONG lengthStr=1;
1329 IEnumMoniker *enumMoniker;
1330 IMoniker* tempMk;
1331 LPOLESTR tempStr;
1333 TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1335 if (ppszDisplayName==NULL)
1336 return E_POINTER;
1338 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1340 if (*ppszDisplayName==NULL)
1341 return E_OUTOFMEMORY;
1343 /* This method returns the concatenation of the display names returned by each component moniker of */
1344 /* the composite */
1346 **ppszDisplayName=0;
1348 IMoniker_Enum(iface,TRUE,&enumMoniker);
1350 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1352 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1354 lengthStr+=lstrlenW(tempStr);
1356 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1358 if (*ppszDisplayName==NULL)
1359 return E_OUTOFMEMORY;
1361 lstrcatW(*ppszDisplayName,tempStr);
1363 CoTaskMemFree(tempStr);
1364 IMoniker_Release(tempMk);
1367 IEnumMoniker_Release(enumMoniker);
1369 return S_OK;
1372 /******************************************************************************
1373 * CompositeMoniker_ParseDisplayName
1374 ******************************************************************************/
1375 HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,
1376 IBindCtx* pbc,
1377 IMoniker* pmkToLeft,
1378 LPOLESTR pszDisplayName,
1379 ULONG* pchEaten,
1380 IMoniker** ppmkOut)
1382 IEnumMoniker *enumMoniker;
1383 IMoniker *tempMk,*mostRigthMk,*antiMk;
1384 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1385 /* passing everything else as the pmkToLeft parameter for that call. */
1387 /* get the most rigth moniker */
1388 IMoniker_Enum(iface,FALSE,&enumMoniker);
1389 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1390 IEnumMoniker_Release(enumMoniker);
1392 /* get the left moniker */
1393 CreateAntiMoniker(&antiMk);
1394 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1395 IMoniker_Release(antiMk);
1397 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1400 /******************************************************************************
1401 * CompositeMoniker_IsSystemMonker
1402 ******************************************************************************/
1403 HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1405 TRACE(ole,"(%p,%p)\n",iface,pwdMksys);
1407 if (!pwdMksys)
1408 return E_POINTER;
1410 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1412 return S_OK;
1415 /*******************************************************************************
1416 * CompositeMonikerIROTData_QueryInterface
1417 *******************************************************************************/
1418 HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1421 ICOM_THIS_From_IROTData(IMoniker, iface);
1423 TRACE(ole,"(%p,%p,%p)\n",iface,riid,ppvObject);
1425 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1428 /***********************************************************************
1429 * CompositeMonikerIROTData_AddRef
1431 ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1433 ICOM_THIS_From_IROTData(IMoniker, iface);
1435 TRACE(ole,"(%p)\n",iface);
1437 return CompositeMonikerImpl_AddRef(This);
1440 /***********************************************************************
1441 * CompositeMonikerIROTData_Release
1443 ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1445 ICOM_THIS_From_IROTData(IMoniker, iface);
1447 TRACE(ole,"(%p)\n",iface);
1449 return CompositeMonikerImpl_Release(This);
1452 /******************************************************************************
1453 * CompositeMonikerIROTData_GetComparaisonData
1454 ******************************************************************************/
1455 HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1456 BYTE* pbData,
1457 ULONG cbMax,
1458 ULONG* pcbData)
1460 FIXME(ole,"(),stub!\n");
1461 return E_NOTIMPL;
1464 /******************************************************************************
1465 * EnumMonikerImpl_QueryInterface
1466 ******************************************************************************/
1467 HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1469 ICOM_THIS(EnumMonikerImpl,iface);
1471 TRACE(ole,"(%p,%p,%p)\n",This,riid,ppvObject);
1473 /* Perform a sanity check on the parameters.*/
1474 if ( (This==0) || (ppvObject==0) )
1475 return E_INVALIDARG;
1477 /* Initialize the return parameter */
1478 *ppvObject = 0;
1480 /* Compare the riid with the interface IDs implemented by this object.*/
1481 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1482 *ppvObject = iface;
1484 /* Check that we obtained an interface.*/
1485 if ((*ppvObject)==0)
1486 return E_NOINTERFACE;
1488 /* Query Interface always increases the reference count by one when it is successful */
1489 EnumMonikerImpl_AddRef(iface);
1491 return S_OK;
1494 /******************************************************************************
1495 * EnumMonikerImpl_AddRef
1496 ******************************************************************************/
1497 ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1499 ICOM_THIS(EnumMonikerImpl,iface);
1501 TRACE(ole,"(%p)\n",This);
1503 return ++(This->ref);
1507 /******************************************************************************
1508 * EnumMonikerImpl_Release
1509 ******************************************************************************/
1510 ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1512 ICOM_THIS(EnumMonikerImpl,iface);
1513 ULONG i
1515 TRACE(ole,"(%p)\n",This);
1517 This->ref--;
1519 /* destroy the object if there's no more reference on it */
1520 if (This->ref==0){
1522 for(i=0;i<This->tabSize;i++)
1523 IMoniker_Release(This->tabMoniker[i]);
1525 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1526 HeapFree(GetProcessHeap(),0,This);
1528 return 0;
1530 return This->ref;;
1533 /******************************************************************************
1534 * EnumMonikerImpl_Next
1535 ******************************************************************************/
1536 HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){
1538 ICOM_THIS(EnumMonikerImpl,iface);
1539 ULONG i;
1541 /* retrieve the requested number of moniker from the current position */
1542 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1544 rgelt[i]=This->tabMoniker[This->currentPos++];
1546 if (pceltFethed!=NULL)
1547 *pceltFethed= i;
1549 if (i==celt)
1550 return S_OK;
1551 else
1552 return S_FALSE;
1555 /******************************************************************************
1556 * EnumMonikerImpl_Skip
1557 ******************************************************************************/
1558 HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){
1560 ICOM_THIS(EnumMonikerImpl,iface);
1562 if ((This->currentPos+celt) >= This->tabSize)
1563 return S_FALSE;
1565 This->currentPos+=celt;
1567 return S_OK;
1570 /******************************************************************************
1571 * EnumMonikerImpl_Reset
1572 ******************************************************************************/
1573 HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){
1575 ICOM_THIS(EnumMonikerImpl,iface);
1577 This->currentPos=0;
1579 return S_OK;
1582 /******************************************************************************
1583 * EnumMonikerImpl_Clone
1584 ******************************************************************************/
1585 HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){
1587 ICOM_THIS(EnumMonikerImpl,iface);
1589 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1592 /******************************************************************************
1593 * EnumMonikerImpl_CreateEnumMoniker
1594 ******************************************************************************/
1595 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,
1596 ULONG tabSize,
1597 ULONG currentPos,
1598 BOOL leftToRigth,
1599 IEnumMoniker ** ppmk)
1601 EnumMonikerImpl* newEnumMoniker;
1602 int i;
1605 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1607 if (newEnumMoniker == 0)
1608 return STG_E_INSUFFICIENTMEMORY;
1610 if (currentPos > tabSize)
1611 return E_INVALIDARG;
1613 /* Initialize the virtual function table. */
1614 newEnumMoniker->lpvtbl = &VT_EnumMonikerImpl;
1615 newEnumMoniker->ref = 0;
1617 newEnumMoniker->tabSize=tabSize;
1618 newEnumMoniker->currentPos=currentPos;
1620 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1622 if (newEnumMoniker->tabMoniker==NULL)
1623 return E_OUTOFMEMORY;
1625 if (leftToRigth)
1626 for (i=0;i<tabSize;i++){
1628 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1629 IMoniker_AddRef(tabMoniker[i]);
1631 else
1632 for (i=tabSize-1;i>=0;i--){
1634 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1635 IMoniker_AddRef(tabMoniker[i]);
1638 *ppmk=(IEnumMoniker*)newEnumMoniker;
1640 return S_OK;
1643 /******************************************************************************
1644 * CreateCompositeMoniker [OLE.55]
1645 ******************************************************************************/
1646 HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite)
1648 CompositeMonikerImpl* newCompositeMoniker = 0;
1649 HRESULT hr = S_OK;
1651 TRACE(ole,"(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1653 if (ppmkComposite==NULL)
1654 return E_POINTER;
1656 *ppmkComposite=0;
1658 if (pmkFirst==NULL && pmkRest!=NULL){
1660 *ppmkComposite=pmkRest;
1661 return S_OK;
1663 else if (pmkFirst!=NULL && pmkRest==NULL){
1664 *ppmkComposite=pmkFirst;
1665 return S_OK;
1667 else if (pmkFirst==NULL && pmkRest==NULL)
1668 return S_OK;
1670 newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
1672 if (newCompositeMoniker == 0)
1673 return STG_E_INSUFFICIENTMEMORY;
1675 hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
1677 if (FAILED(hr)){
1679 HeapFree(GetProcessHeap(),0,newCompositeMoniker);
1680 return hr;
1682 if (newCompositeMoniker->tabLastIndex==1)
1684 hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
1685 else
1687 hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
1689 return hr;
1692 /******************************************************************************
1693 * MonikerCommonPrefixWith [OLE.55]
1694 ******************************************************************************/
1695 HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1697 FIXME(ole,"(),stub!\n");
1698 return E_NOTIMPL;