Fixed some issues found by winapi_check.
[wine/dcerpc.git] / dlls / ole32 / compositemoniker.c
blob90aa77f4aaa45308708f65bdd963ee4ff67427d9
1 /***************************************************************************************
2 * CompositeMonikers implementation
4 * Copyright 1999 Noomen Hamza
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ***************************************************************************************/
20 #include <assert.h>
21 #include <string.h>
22 #include "winbase.h"
23 #include "winerror.h"
24 #include "wine/debug.h"
25 #include "wine/obj_base.h"
26 #include "wine/obj_misc.h"
27 #include "wine/obj_storage.h"
28 #include "wine/obj_moniker.h"
29 #include "wine/obj_inplace.h"
30 #include "wine/unicode.h"
31 #include "ole2.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(ole);
35 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
37 /* CompositeMoniker data structure */
38 typedef struct CompositeMonikerImpl{
40 ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/
42 /* The ROT (RunningObjectTable implementation) uses the IROTData
43 * interface to test whether two monikers are equal. That's why IROTData
44 * interface is implemented by monikers.
46 ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/
48 ULONG ref; /* reference counter for this object */
50 IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */
52 ULONG tabSize; /* size of tabMoniker */
54 ULONG tabLastIndex; /* first free index in tabMoniker */
56 } CompositeMonikerImpl;
59 /* EnumMoniker data structure */
60 typedef struct EnumMonikerImpl{
62 ICOM_VFIELD(IEnumMoniker); /* VTable relative to the IEnumMoniker interface.*/
64 ULONG ref; /* reference counter for this object */
66 IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
68 ULONG tabSize; /* size of tabMoniker */
70 ULONG currentPos; /* index pointer on the current moniker */
72 } EnumMonikerImpl;
75 /********************************************************************************/
76 /* CompositeMoniker prototype functions : */
78 /* IUnknown prototype functions */
79 static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
80 static ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface);
81 static ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface);
83 /* IPersist prototype functions */
84 static HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
86 /* IPersistStream prototype functions */
87 static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface);
88 static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm);
89 static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
90 static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
92 /* IMoniker prototype functions */
93 static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
94 static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
95 static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
96 static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
97 static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
98 static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
99 static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
100 static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
101 static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime);
102 static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
103 static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
104 static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
105 static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
106 static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
107 static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
109 /********************************************************************************/
110 /* IROTData prototype functions */
112 /* IUnknown prototype functions */
113 static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
114 static ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface);
115 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface);
117 /* IROTData prototype function */
118 static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
120 /* Local function used by CompositeMoniker implementation */
121 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest);
122 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface);
124 /********************************************************************************/
125 /* IEnumMoniker prototype functions */
127 /* IUnknown prototype functions */
128 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject);
129 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface);
130 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface);
132 /* IEnumMoniker prototype functions */
133 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched);
134 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt);
135 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface);
136 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum);
138 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
140 /********************************************************************************/
141 /* Virtual function table for the CompositeMonikerImpl class which includes */
142 /* IPersist, IPersistStream and IMoniker functions. */
144 static ICOM_VTABLE(IMoniker) VT_CompositeMonikerImpl =
146 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
147 CompositeMonikerImpl_QueryInterface,
148 CompositeMonikerImpl_AddRef,
149 CompositeMonikerImpl_Release,
150 CompositeMonikerImpl_GetClassID,
151 CompositeMonikerImpl_IsDirty,
152 CompositeMonikerImpl_Load,
153 CompositeMonikerImpl_Save,
154 CompositeMonikerImpl_GetSizeMax,
155 CompositeMonikerImpl_BindToObject,
156 CompositeMonikerImpl_BindToStorage,
157 CompositeMonikerImpl_Reduce,
158 CompositeMonikerImpl_ComposeWith,
159 CompositeMonikerImpl_Enum,
160 CompositeMonikerImpl_IsEqual,
161 CompositeMonikerImpl_Hash,
162 CompositeMonikerImpl_IsRunning,
163 CompositeMonikerImpl_GetTimeOfLastChange,
164 CompositeMonikerImpl_Inverse,
165 CompositeMonikerImpl_CommonPrefixWith,
166 CompositeMonikerImpl_RelativePathTo,
167 CompositeMonikerImpl_GetDisplayName,
168 CompositeMonikerImpl_ParseDisplayName,
169 CompositeMonikerImpl_IsSystemMoniker
172 /********************************************************************************/
173 /* Virtual function table for the IROTData class. */
174 static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
176 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
177 CompositeMonikerROTDataImpl_QueryInterface,
178 CompositeMonikerROTDataImpl_AddRef,
179 CompositeMonikerROTDataImpl_Release,
180 CompositeMonikerROTDataImpl_GetComparaisonData
183 /********************************************************************************/
184 /* Virtual function table for the IROTData class */
185 static ICOM_VTABLE(IEnumMoniker) VT_EnumMonikerImpl =
187 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
188 EnumMonikerImpl_QueryInterface,
189 EnumMonikerImpl_AddRef,
190 EnumMonikerImpl_Release,
191 EnumMonikerImpl_Next,
192 EnumMonikerImpl_Skip,
193 EnumMonikerImpl_Reset,
194 EnumMonikerImpl_Clone
197 /*******************************************************************************
198 * CompositeMoniker_QueryInterface
199 *******************************************************************************/
200 HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
202 ICOM_THIS(CompositeMonikerImpl,iface);
204 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
206 /* Perform a sanity check on the parameters.*/
207 if ( (This==0) || (ppvObject==0) )
208 return E_INVALIDARG;
210 /* Initialize the return parameter */
211 *ppvObject = 0;
213 /* Compare the riid with the interface IDs implemented by this object.*/
214 if (IsEqualIID(&IID_IUnknown, riid) ||
215 IsEqualIID(&IID_IPersist, riid) ||
216 IsEqualIID(&IID_IPersistStream, riid) ||
217 IsEqualIID(&IID_IMoniker, riid)
219 *ppvObject = iface;
220 else if (IsEqualIID(&IID_IROTData, riid))
221 *ppvObject = (IROTData*)&(This->lpvtbl2);
223 /* Check that we obtained an interface.*/
224 if ((*ppvObject)==0)
225 return E_NOINTERFACE;
227 /* Query Interface always increases the reference count by one when it is successful */
228 CompositeMonikerImpl_AddRef(iface);
230 return S_OK;
233 /******************************************************************************
234 * CompositeMoniker_AddRef
235 ******************************************************************************/
236 ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)
238 ICOM_THIS(CompositeMonikerImpl,iface);
240 TRACE("(%p)\n",This);
242 return ++(This->ref);
245 /******************************************************************************
246 * CompositeMoniker_Release
247 ******************************************************************************/
248 ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
250 ICOM_THIS(CompositeMonikerImpl,iface);
251 ULONG i;
253 TRACE("(%p)\n",This);
255 This->ref--;
257 /* destroy the object if there's no more reference on it */
258 if (This->ref==0){
260 /* release all the components before destroying this object */
261 for (i=0;i<This->tabLastIndex;i++)
262 IMoniker_Release(This->tabMoniker[i]);
264 CompositeMonikerImpl_Destroy(This);
266 return 0;
268 return This->ref;;
271 /******************************************************************************
272 * CompositeMoniker_GetClassID
273 ******************************************************************************/
274 HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
276 TRACE("(%p,%p),stub!\n",iface,pClassID);
278 if (pClassID==NULL)
279 return E_POINTER;
281 *pClassID = CLSID_CompositeMoniker;
283 return S_OK;
286 /******************************************************************************
287 * CompositeMoniker_IsDirty
288 ******************************************************************************/
289 HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)
291 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
292 method in the OLE-provided moniker interfaces always return S_FALSE because
293 their internal state never changes. */
295 TRACE("(%p)\n",iface);
297 return S_FALSE;
300 /******************************************************************************
301 * CompositeMoniker_Load
302 ******************************************************************************/
303 HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
305 HRESULT res;
306 DWORD constant;
307 CLSID clsid;
308 WCHAR string[1]={0};
310 ICOM_THIS(CompositeMonikerImpl,iface);
312 TRACE("(%p,%p)\n",iface,pStm);
314 /* this function call OleLoadFromStream function for each moniker within this object */
316 /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
317 res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
319 if (SUCCEEDED(res)&& constant!=3)
320 return E_FAIL;
322 while(1){
323 #if 0
324 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
325 #endif
326 res=ReadClassStm(pStm,&clsid);
327 DPRINTF("res=%ld",res);
328 if (FAILED(res))
329 break;
331 if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
332 res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
333 if (FAILED(res))
334 break;
335 res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
336 if (FAILED(res))
337 break;
339 else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
340 CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
341 if (res!=S_OK)
342 break;
343 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
344 if (FAILED(res))
345 break;
347 else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
348 CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
349 if (FAILED(res))
350 break;
351 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
352 if (FAILED(res))
353 break;
355 else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
356 return E_FAIL;
358 else
360 FIXME("()\n");
361 /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */
362 break;
363 return E_NOTIMPL;
366 /* resize the table if needed */
367 if (++This->tabLastIndex==This->tabSize){
369 This->tabSize+=BLOCK_TAB_SIZE;
370 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
372 if (This->tabMoniker==NULL)
373 return E_OUTOFMEMORY;
377 return res;
380 /******************************************************************************
381 * CompositeMoniker_Save
382 ******************************************************************************/
383 HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
385 HRESULT res;
386 IEnumMoniker *enumMk;
387 IMoniker *pmk;
388 DWORD constant=3;
390 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
392 /* This function calls OleSaveToStream function for each moniker within
393 * this object.
394 * When I tested this function in windows, I usually found this constant
395 * at the beginning of the stream. I don't known why (there's no
396 * indication in the specification) !
398 res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
400 IMoniker_Enum(iface,TRUE,&enumMk);
402 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
404 res=OleSaveToStream((IPersistStream*)pmk,pStm);
406 IMoniker_Release(pmk);
408 if (FAILED(res)){
410 IEnumMoniker_Release(pmk);
411 return res;
415 IEnumMoniker_Release(enumMk);
417 return S_OK;
420 /******************************************************************************
421 * CompositeMoniker_GetSizeMax
422 ******************************************************************************/
423 HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
425 IEnumMoniker *enumMk;
426 IMoniker *pmk;
427 ULARGE_INTEGER ptmpSize;
429 /* The sizeMax of this object is calculated by calling GetSizeMax on
430 * each moniker within this object then summing all returned values
433 TRACE("(%p,%p)\n",iface,pcbSize);
435 if (pcbSize!=NULL)
436 return E_POINTER;
438 pcbSize->s.LowPart =0;
439 pcbSize->s.HighPart=0;
441 IMoniker_Enum(iface,TRUE,&enumMk);
443 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){
445 IMoniker_GetSizeMax(pmk,&ptmpSize);
447 IMoniker_Release(pmk);
449 pcbSize->s.LowPart +=ptmpSize.s.LowPart;
450 pcbSize->s.HighPart+=ptmpSize.s.HighPart;
453 IEnumMoniker_Release(enumMk);
455 return S_OK;
458 /******************************************************************************
459 * Composite-Moniker_Construct (local function)
460 *******************************************************************************/
461 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest)
463 DWORD mkSys;
464 IEnumMoniker *enumMoniker;
465 IMoniker *tempMk;
466 HRESULT res;
468 TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
470 /* Initialize the virtual function table. */
471 This->lpvtbl1 = &VT_CompositeMonikerImpl;
472 This->lpvtbl2 = &VT_ROTDataImpl;
473 This->ref = 0;
475 This->tabSize=BLOCK_TAB_SIZE;
476 This->tabLastIndex=0;
478 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
479 if (This->tabMoniker==NULL)
480 return E_OUTOFMEMORY;
482 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
484 /* put the first moniker contents in the beginning of the table */
485 if (mkSys!=MKSYS_GENERICCOMPOSITE){
487 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
488 IMoniker_AddRef(pmkFirst);
490 else{
492 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
494 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
497 if (++This->tabLastIndex==This->tabSize){
499 This->tabSize+=BLOCK_TAB_SIZE;
500 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
502 if (This->tabMoniker==NULL)
503 return E_OUTOFMEMORY;
507 IEnumMoniker_Release(enumMoniker);
510 /* put the rest moniker contents after the first one and make simplification if needed */
512 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
514 if (mkSys!=MKSYS_GENERICCOMPOSITE){
516 /* add a simple moniker to the moniker table */
518 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
520 if (res==MK_E_NEEDGENERIC){
522 /* there's no simplification in this case */
523 This->tabMoniker[This->tabLastIndex]=pmkRest;
525 This->tabLastIndex++;
527 IMoniker_AddRef(pmkRest);
529 else if (tempMk==NULL){
531 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
532 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
534 This->tabLastIndex--;
536 else if (SUCCEEDED(res)){
538 /* the non-generic composition was successful so we can make a simplification in this case */
539 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
541 This->tabMoniker[This->tabLastIndex-1]=tempMk;
542 } else
543 return res;
545 /* resize tabMoniker if needed */
546 if (This->tabLastIndex==This->tabSize){
548 This->tabSize+=BLOCK_TAB_SIZE;
550 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
552 if (This->tabMoniker==NULL)
553 return E_OUTOFMEMORY;
556 else{
558 /* add a composite moniker to the moniker table (do the same thing
559 * for each moniker within the composite moniker as a simple moniker
560 * (see above for how to add a simple moniker case) )
562 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
564 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
566 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
568 if (res==MK_E_NEEDGENERIC){
570 This->tabLastIndex++;
572 else if (tempMk==NULL){
574 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
575 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
576 This->tabLastIndex--;
578 else{
580 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
582 This->tabMoniker[This->tabLastIndex-1]=tempMk;
585 if (This->tabLastIndex==This->tabSize){
587 This->tabSize+=BLOCK_TAB_SIZE;
589 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
591 if (This->tabMoniker==NULL)
592 return E_OUTOFMEMORY;
596 IEnumMoniker_Release(enumMoniker);
599 return S_OK;
602 /******************************************************************************
603 * CompositeMoniker_Destroy (local function)
604 *******************************************************************************/
605 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This)
607 TRACE("(%p)\n",This);
609 HeapFree(GetProcessHeap(),0,This->tabMoniker);
611 HeapFree(GetProcessHeap(),0,This);
613 return S_OK;
616 /******************************************************************************
617 * CompositeMoniker_BindToObject
618 ******************************************************************************/
619 HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,
620 IBindCtx* pbc,
621 IMoniker* pmkToLeft,
622 REFIID riid,
623 VOID** ppvResult)
625 HRESULT res;
626 IRunningObjectTable *prot;
627 IMoniker *tempMk,*antiMk,*mostRigthMk;
628 IEnumMoniker *enumMoniker;
630 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
632 if (ppvResult==NULL)
633 return E_POINTER;
635 *ppvResult=0;
636 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
637 /* object for the requested interface pointer. */
638 if(pmkToLeft==NULL){
640 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
642 if (SUCCEEDED(res)){
644 /* if the requested class was loaded befor ! we dont need to reload it */
645 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
647 if (res==S_OK)
648 return res;
651 else{
652 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
653 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
655 IMoniker_Enum(iface,FALSE,&enumMoniker);
656 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
657 IEnumMoniker_Release(enumMoniker);
659 res=CreateAntiMoniker(&antiMk);
660 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
661 IMoniker_Release(antiMk);
663 res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
665 IMoniker_Release(tempMk);
666 IMoniker_Release(mostRigthMk);
669 return res;
672 /******************************************************************************
673 * CompositeMoniker_BindToStorage
674 ******************************************************************************/
675 HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,
676 IBindCtx* pbc,
677 IMoniker* pmkToLeft,
678 REFIID riid,
679 VOID** ppvResult)
681 HRESULT res;
682 IMoniker *tempMk,*antiMk,*mostRigthMk;
683 IEnumMoniker *enumMoniker;
685 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
687 *ppvResult=0;
689 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
690 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
692 if (pmkToLeft!=NULL){
694 IMoniker_Enum(iface,FALSE,&enumMoniker);
695 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
696 IEnumMoniker_Release(enumMoniker);
698 res=CreateAntiMoniker(&antiMk);
699 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
700 IMoniker_Release(antiMk);
702 res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
704 IMoniker_Release(tempMk);
706 IMoniker_Release(mostRigthMk);
708 return res;
710 else
711 return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
714 /******************************************************************************
715 * CompositeMoniker_Reduce
716 ******************************************************************************/
717 HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,
718 IBindCtx* pbc,
719 DWORD dwReduceHowFar,
720 IMoniker** ppmkToLeft,
721 IMoniker** ppmkReduced)
723 HRESULT res;
724 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
725 IEnumMoniker *enumMoniker;
727 TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
729 if (ppmkReduced==NULL)
730 return E_POINTER;
732 /* This method recursively calls Reduce for each of its component monikers. */
734 if (ppmkToLeft==NULL){
736 IMoniker_Enum(iface,FALSE,&enumMoniker);
737 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
738 IEnumMoniker_Release(enumMoniker);
740 res=CreateAntiMoniker(&antiMk);
741 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
742 IMoniker_Release(antiMk);
744 return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
746 else if (*ppmkToLeft==NULL)
748 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
750 else{
752 /* separate the composite moniker in to left and right moniker */
753 IMoniker_Enum(iface,FALSE,&enumMoniker);
754 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
755 IEnumMoniker_Release(enumMoniker);
757 res=CreateAntiMoniker(&antiMk);
758 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
759 IMoniker_Release(antiMk);
761 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
762 /* of the reduced components */
763 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
764 CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
767 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
769 else{
770 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
772 IMoniker_AddRef(iface);
774 *ppmkReduced=iface;
776 return MK_S_REDUCED_TO_SELF;
781 /******************************************************************************
782 * CompositeMoniker_ComposeWith
783 ******************************************************************************/
784 HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,
785 IMoniker* pmkRight,
786 BOOL fOnlyIfNotGeneric,
787 IMoniker** ppmkComposite)
789 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
791 if ((ppmkComposite==NULL)||(pmkRight==NULL))
792 return E_POINTER;
794 *ppmkComposite=0;
796 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
797 /* otherwise, the method returns the result of combining the two monikers by calling the */
798 /* CreateGenericComposite function */
800 if (fOnlyIfNotGeneric)
801 return MK_E_NEEDGENERIC;
803 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
806 /******************************************************************************
807 * CompositeMoniker_Enum
808 ******************************************************************************/
809 HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
811 ICOM_THIS(CompositeMonikerImpl,iface);
813 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
815 if (ppenumMoniker == NULL)
816 return E_POINTER;
818 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
821 /******************************************************************************
822 * CompositeMoniker_IsEqual
823 ******************************************************************************/
824 HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
826 IEnumMoniker *enumMoniker1,*enumMoniker2;
827 IMoniker *tempMk1,*tempMk2;
828 HRESULT res1,res2,res;
830 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
832 if (pmkOtherMoniker==NULL)
833 return S_FALSE;
835 /* This method returns S_OK if the components of both monikers are equal when compared in the */
836 /* left-to-right order.*/
837 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
839 if (enumMoniker1==NULL)
840 return S_FALSE;
842 IMoniker_Enum(iface,TRUE,&enumMoniker2);
844 while(1){
846 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
847 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
849 if((res1==S_OK)&&(res2==S_OK)){
851 if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
852 res= S_FALSE;
853 break;
855 else
856 continue;
858 else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
859 res = S_OK;
860 break;
862 else{
863 res = S_FALSE;
864 break;
867 if (res1==S_OK)
868 IMoniker_Release(tempMk1);
870 if (res2==S_OK)
871 IMoniker_Release(tempMk2);
874 IEnumMoniker_Release(enumMoniker1);
875 IEnumMoniker_Release(enumMoniker2);
877 return res;
879 /******************************************************************************
880 * CompositeMoniker_Hash
881 ******************************************************************************/
882 HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
884 FIXME("(),stub!\n");
886 return E_NOTIMPL;
889 /******************************************************************************
890 * CompositeMoniker_IsRunning
891 ******************************************************************************/
892 HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,
893 IBindCtx* pbc,
894 IMoniker* pmkToLeft,
895 IMoniker* pmkNewlyRunning)
897 IRunningObjectTable* rot;
898 HRESULT res;
899 IMoniker *tempMk,*antiMk,*mostRigthMk;
900 IEnumMoniker *enumMoniker;
902 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
904 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
905 if (pmkToLeft!=NULL){
907 CreateGenericComposite(pmkToLeft,iface,&tempMk);
909 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
911 IMoniker_Release(tempMk);
913 return res;
915 else
916 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
917 /* to this moniker */
919 if (pmkNewlyRunning!=NULL)
921 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
922 return S_OK;
924 else
925 return S_FALSE;
927 else{
929 if (pbc==NULL)
930 return E_POINTER;
932 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
933 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
934 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
935 /* the composite as the pmkToLeft parameter for that call. */
937 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
939 if (FAILED(res))
940 return res;
942 res = IRunningObjectTable_IsRunning(rot,iface);
943 IRunningObjectTable_Release(rot);
945 if(res==S_OK)
946 return S_OK;
948 else{
950 IMoniker_Enum(iface,FALSE,&enumMoniker);
951 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
952 IEnumMoniker_Release(enumMoniker);
954 res=CreateAntiMoniker(&antiMk);
955 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
956 IMoniker_Release(antiMk);
958 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
960 IMoniker_Release(tempMk);
961 IMoniker_Release(mostRigthMk);
963 return res;
968 /******************************************************************************
969 * CompositeMoniker_GetTimeOfLastChange
970 ******************************************************************************/
971 HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
972 IBindCtx* pbc,
973 IMoniker* pmkToLeft,
974 FILETIME* pCompositeTime)
976 IRunningObjectTable* rot;
977 HRESULT res;
978 IMoniker *tempMk,*antiMk,*mostRigthMk;
979 IEnumMoniker *enumMoniker;
981 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
983 if (pCompositeTime==NULL)
984 return E_INVALIDARG;
986 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
987 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
988 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
989 /* of the composite as the pmkToLeft parameter for that call. */
990 if (pmkToLeft!=NULL){
992 res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
994 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
996 if (FAILED(res))
997 return res;
999 if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
1000 return res;
1001 else
1003 IMoniker_Enum(iface,FALSE,&enumMoniker);
1004 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1005 IEnumMoniker_Release(enumMoniker);
1007 res=CreateAntiMoniker(&antiMk);
1008 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1009 IMoniker_Release(antiMk);
1011 res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
1013 IMoniker_Release(tempMk);
1014 IMoniker_Release(mostRigthMk);
1016 return res;
1018 else
1019 return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
1022 /******************************************************************************
1023 * CompositeMoniker_Inverse
1024 ******************************************************************************/
1025 HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
1027 HRESULT res;
1028 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
1029 IEnumMoniker *enumMoniker;
1031 TRACE("(%p,%p)\n",iface,ppmk);
1033 if (ppmk==NULL)
1034 return E_POINTER;
1036 /* This method returns a composite moniker that consists of the inverses of each of the components */
1037 /* of the original composite, stored in reverse order */
1039 res=CreateAntiMoniker(&antiMk);
1040 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1041 IMoniker_Release(antiMk);
1043 if (tempMk==NULL)
1045 return IMoniker_Inverse(iface,ppmk);
1047 else{
1049 IMoniker_Enum(iface,FALSE,&enumMoniker);
1050 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1051 IEnumMoniker_Release(enumMoniker);
1053 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
1054 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
1056 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
1058 IMoniker_Release(tempMk);
1059 IMoniker_Release(mostRigthMk);
1060 IMoniker_Release(tempInvMk);
1061 IMoniker_Release(mostRigthInvMk);
1063 return res;
1067 /******************************************************************************
1068 * CompositeMoniker_CommonPrefixWith
1069 ******************************************************************************/
1070 HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1072 DWORD mkSys;
1073 HRESULT res1,res2;
1074 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
1075 IEnumMoniker *enumMoniker1,*enumMoniker2;
1076 ULONG i,nbCommonMk=0;
1078 /* If the other moniker is a composite, this method compares the components of each composite from left */
1079 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1080 /* of the leftmost components were common to both monikers. */
1082 if (ppmkPrefix==NULL)
1083 return E_POINTER;
1085 *ppmkPrefix=0;
1087 if (pmkOther==NULL)
1088 return MK_E_NOPREFIX;
1090 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1092 if((mkSys==MKSYS_GENERICCOMPOSITE)){
1094 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1095 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
1097 while(1){
1099 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1100 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
1102 if ((res1==S_FALSE) && (res2==S_FALSE)){
1104 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1105 *ppmkPrefix=iface;
1106 IMoniker_AddRef(iface);
1107 return MK_S_US;
1109 else if ((res1==S_OK) && (res2==S_OK)){
1111 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
1113 nbCommonMk++;
1115 else
1116 break;
1119 else if (res1==S_OK){
1121 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1122 /* ppmkPrefix to the other moniker. */
1123 *ppmkPrefix=pmkOther;
1124 return MK_S_HIM;
1126 else{
1127 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1128 /* to this moniker. */
1129 *ppmkPrefix=iface;
1130 return MK_S_ME;
1134 IEnumMoniker_Release(enumMoniker1);
1135 IEnumMoniker_Release(enumMoniker2);
1137 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1138 if (nbCommonMk==0)
1139 return MK_E_NOPREFIX;
1141 IEnumMoniker_Reset(enumMoniker1);
1143 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1145 /* if we have more than one commun moniker the result will be a composite moniker */
1146 if (nbCommonMk>1){
1148 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1149 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1150 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
1151 IMoniker_Release(tempMk1);
1152 IMoniker_Release(tempMk2);
1154 /* compose all common monikers in a composite moniker */
1155 for(i=0;i<nbCommonMk;i++){
1157 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1159 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
1161 IMoniker_Release(*ppmkPrefix);
1163 IMoniker_Release(tempMk1);
1165 *ppmkPrefix=tempMk2;
1167 return S_OK;
1169 else{
1170 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1171 *ppmkPrefix=tempMk1;
1173 return S_OK;
1176 else{
1177 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1178 of this moniker.*/
1180 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1182 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1184 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
1186 *ppmkPrefix=pmkOther;
1188 return MK_S_HIM;
1190 else
1191 return MK_E_NOPREFIX;
1194 /***************************************************************************************************
1195 * GetAfterCommonPrefix (local function)
1196 * This function returns a moniker that consist of the remainder when the common prefix is removed
1197 ***************************************************************************************************/
1198 VOID WINAPI GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
1200 IMoniker *tempMk,*tempMk1,*tempMk2;
1201 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
1202 ULONG nbRestMk=0;
1203 DWORD mkSys;
1204 HRESULT res1,res2;
1206 *restMk=0;
1208 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1209 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
1210 /* on the first difference. */
1211 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
1213 IMoniker_IsSystemMoniker(commonMk,&mkSys);
1215 if (mkSys==MKSYS_GENERICCOMPOSITE){
1217 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
1218 while(1){
1220 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1221 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
1223 if ((res1==S_FALSE)||(res2==S_FALSE)){
1225 if (res1==S_OK)
1227 nbRestMk++;
1229 IMoniker_Release(tempMk1);
1230 IMoniker_Release(tempMk1);
1232 break;
1234 IMoniker_Release(tempMk1);
1235 IMoniker_Release(tempMk1);
1238 else{
1239 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1240 IMoniker_Release(tempMk1);
1243 /* count the number of elements in the enumerator after the common prefix */
1244 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1246 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1248 IMoniker_Release(tempMk);;
1250 if (nbRestMk==0)
1251 return;
1253 /* create a generic composite moniker with monikers located after the common prefix */
1254 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1256 if (nbRestMk==1){
1258 *restMk= tempMk1;
1259 return;
1261 else {
1263 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1265 CreateGenericComposite(tempMk1,tempMk2,restMk);
1267 IMoniker_Release(tempMk1);
1269 IMoniker_Release(tempMk2);
1271 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1273 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1275 IMoniker_Release(tempMk1);
1277 IMoniker_Release(*restMk);
1279 *restMk=tempMk2;
1283 /******************************************************************************
1284 * CompositeMoniker_RelativePathTo
1285 ******************************************************************************/
1286 HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkRelPath)
1288 HRESULT res;
1289 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1291 TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1293 if (ppmkRelPath==NULL)
1294 return E_POINTER;
1296 *ppmkRelPath=0;
1298 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1299 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1300 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1302 /* finds the common prefix of the two monikers */
1303 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1305 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1306 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1308 *ppmkRelPath=pmkOther;
1309 IMoniker_AddRef(pmkOther);
1310 return MK_S_HIM;
1313 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1314 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1316 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1317 /* moniker when the common prefix is removed */
1318 if (res==MK_S_HIM){
1320 IMoniker_Inverse(restThisMk,ppmkRelPath);
1321 IMoniker_Release(restThisMk);
1323 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1324 /* when the common prefix is removed */
1325 else if (res==MK_S_ME){
1327 *ppmkRelPath=restOtherMk;
1328 IMoniker_AddRef(restOtherMk);
1330 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1331 /* moniker on the right of it. */
1332 else if (res==S_OK){
1334 IMoniker_Inverse(restThisMk,&invRestThisMk);
1335 IMoniker_Release(restThisMk);
1336 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1337 IMoniker_Release(invRestThisMk);
1338 IMoniker_Release(restOtherMk);
1340 return S_OK;
1343 /******************************************************************************
1344 * CompositeMoniker_GetDisplayName
1345 ******************************************************************************/
1346 HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,
1347 IBindCtx* pbc,
1348 IMoniker* pmkToLeft,
1349 LPOLESTR *ppszDisplayName)
1351 ULONG lengthStr=1;
1352 IEnumMoniker *enumMoniker;
1353 IMoniker* tempMk;
1354 LPOLESTR tempStr;
1356 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1358 if (ppszDisplayName==NULL)
1359 return E_POINTER;
1361 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1363 if (*ppszDisplayName==NULL)
1364 return E_OUTOFMEMORY;
1366 /* This method returns the concatenation of the display names returned by each component moniker of */
1367 /* the composite */
1369 **ppszDisplayName=0;
1371 IMoniker_Enum(iface,TRUE,&enumMoniker);
1373 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1375 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1377 lengthStr+=lstrlenW(tempStr);
1379 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1381 if (*ppszDisplayName==NULL)
1382 return E_OUTOFMEMORY;
1384 strcatW(*ppszDisplayName,tempStr);
1386 CoTaskMemFree(tempStr);
1387 IMoniker_Release(tempMk);
1390 IEnumMoniker_Release(enumMoniker);
1392 return S_OK;
1395 /******************************************************************************
1396 * CompositeMoniker_ParseDisplayName
1397 ******************************************************************************/
1398 HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,
1399 IBindCtx* pbc,
1400 IMoniker* pmkToLeft,
1401 LPOLESTR pszDisplayName,
1402 ULONG* pchEaten,
1403 IMoniker** ppmkOut)
1405 IEnumMoniker *enumMoniker;
1406 IMoniker *tempMk,*mostRigthMk,*antiMk;
1407 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1408 /* passing everything else as the pmkToLeft parameter for that call. */
1410 /* get the most right moniker */
1411 IMoniker_Enum(iface,FALSE,&enumMoniker);
1412 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1413 IEnumMoniker_Release(enumMoniker);
1415 /* get the left moniker */
1416 CreateAntiMoniker(&antiMk);
1417 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1418 IMoniker_Release(antiMk);
1420 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1423 /******************************************************************************
1424 * CompositeMoniker_IsSystemMoniker
1425 ******************************************************************************/
1426 HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1428 TRACE("(%p,%p)\n",iface,pwdMksys);
1430 if (!pwdMksys)
1431 return E_POINTER;
1433 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1435 return S_OK;
1438 /*******************************************************************************
1439 * CompositeMonikerIROTData_QueryInterface
1440 *******************************************************************************/
1441 HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1444 ICOM_THIS_From_IROTData(IMoniker, iface);
1446 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
1448 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1451 /***********************************************************************
1452 * CompositeMonikerIROTData_AddRef
1454 ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1456 ICOM_THIS_From_IROTData(IMoniker, iface);
1458 TRACE("(%p)\n",iface);
1460 return CompositeMonikerImpl_AddRef(This);
1463 /***********************************************************************
1464 * CompositeMonikerIROTData_Release
1466 ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1468 ICOM_THIS_From_IROTData(IMoniker, iface);
1470 TRACE("(%p)\n",iface);
1472 return CompositeMonikerImpl_Release(This);
1475 /******************************************************************************
1476 * CompositeMonikerIROTData_GetComparaisonData
1477 ******************************************************************************/
1478 HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1479 BYTE* pbData,
1480 ULONG cbMax,
1481 ULONG* pcbData)
1483 FIXME("(),stub!\n");
1484 return E_NOTIMPL;
1487 /******************************************************************************
1488 * EnumMonikerImpl_QueryInterface
1489 ******************************************************************************/
1490 HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1492 ICOM_THIS(EnumMonikerImpl,iface);
1494 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1496 /* Perform a sanity check on the parameters.*/
1497 if ( (This==0) || (ppvObject==0) )
1498 return E_INVALIDARG;
1500 /* Initialize the return parameter */
1501 *ppvObject = 0;
1503 /* Compare the riid with the interface IDs implemented by this object.*/
1504 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1505 *ppvObject = iface;
1507 /* Check that we obtained an interface.*/
1508 if ((*ppvObject)==0)
1509 return E_NOINTERFACE;
1511 /* Query Interface always increases the reference count by one when it is successful */
1512 EnumMonikerImpl_AddRef(iface);
1514 return S_OK;
1517 /******************************************************************************
1518 * EnumMonikerImpl_AddRef
1519 ******************************************************************************/
1520 ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1522 ICOM_THIS(EnumMonikerImpl,iface);
1524 TRACE("(%p)\n",This);
1526 return ++(This->ref);
1530 /******************************************************************************
1531 * EnumMonikerImpl_Release
1532 ******************************************************************************/
1533 ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1535 ICOM_THIS(EnumMonikerImpl,iface);
1536 ULONG i
1538 TRACE("(%p)\n",This);
1540 This->ref--;
1542 /* destroy the object if there's no more reference on it */
1543 if (This->ref==0){
1545 for(i=0;i<This->tabSize;i++)
1546 IMoniker_Release(This->tabMoniker[i]);
1548 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1549 HeapFree(GetProcessHeap(),0,This);
1551 return 0;
1553 return This->ref;;
1556 /******************************************************************************
1557 * EnumMonikerImpl_Next
1558 ******************************************************************************/
1559 HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){
1561 ICOM_THIS(EnumMonikerImpl,iface);
1562 ULONG i;
1564 /* retrieve the requested number of moniker from the current position */
1565 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1567 rgelt[i]=This->tabMoniker[This->currentPos++];
1569 if (pceltFethed!=NULL)
1570 *pceltFethed= i;
1572 if (i==celt)
1573 return S_OK;
1574 else
1575 return S_FALSE;
1578 /******************************************************************************
1579 * EnumMonikerImpl_Skip
1580 ******************************************************************************/
1581 HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){
1583 ICOM_THIS(EnumMonikerImpl,iface);
1585 if ((This->currentPos+celt) >= This->tabSize)
1586 return S_FALSE;
1588 This->currentPos+=celt;
1590 return S_OK;
1593 /******************************************************************************
1594 * EnumMonikerImpl_Reset
1595 ******************************************************************************/
1596 HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){
1598 ICOM_THIS(EnumMonikerImpl,iface);
1600 This->currentPos=0;
1602 return S_OK;
1605 /******************************************************************************
1606 * EnumMonikerImpl_Clone
1607 ******************************************************************************/
1608 HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){
1610 ICOM_THIS(EnumMonikerImpl,iface);
1612 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1615 /******************************************************************************
1616 * EnumMonikerImpl_CreateEnumMoniker
1617 ******************************************************************************/
1618 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,
1619 ULONG tabSize,
1620 ULONG currentPos,
1621 BOOL leftToRigth,
1622 IEnumMoniker ** ppmk)
1624 EnumMonikerImpl* newEnumMoniker;
1625 int i;
1628 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1630 if (newEnumMoniker == 0)
1631 return STG_E_INSUFFICIENTMEMORY;
1633 if (currentPos > tabSize)
1634 return E_INVALIDARG;
1636 /* Initialize the virtual function table. */
1637 ICOM_VTBL(newEnumMoniker) = &VT_EnumMonikerImpl;
1638 newEnumMoniker->ref = 0;
1640 newEnumMoniker->tabSize=tabSize;
1641 newEnumMoniker->currentPos=currentPos;
1643 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1645 if (newEnumMoniker->tabMoniker==NULL)
1646 return E_OUTOFMEMORY;
1648 if (leftToRigth)
1649 for (i=0;i<tabSize;i++){
1651 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1652 IMoniker_AddRef(tabMoniker[i]);
1654 else
1655 for (i=tabSize-1;i>=0;i--){
1657 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1658 IMoniker_AddRef(tabMoniker[i]);
1661 *ppmk=(IEnumMoniker*)newEnumMoniker;
1663 return S_OK;
1666 /******************************************************************************
1667 * CreateGenericComposite [OLE32.56]
1668 ******************************************************************************/
1669 HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite)
1671 CompositeMonikerImpl* newCompositeMoniker = 0;
1672 HRESULT hr = S_OK;
1674 TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1676 if (ppmkComposite==NULL)
1677 return E_POINTER;
1679 *ppmkComposite=0;
1681 if (pmkFirst==NULL && pmkRest!=NULL){
1683 *ppmkComposite=pmkRest;
1684 return S_OK;
1686 else if (pmkFirst!=NULL && pmkRest==NULL){
1687 *ppmkComposite=pmkFirst;
1688 return S_OK;
1690 else if (pmkFirst==NULL && pmkRest==NULL)
1691 return S_OK;
1693 newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
1695 if (newCompositeMoniker == 0)
1696 return STG_E_INSUFFICIENTMEMORY;
1698 hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
1700 if (FAILED(hr)){
1702 HeapFree(GetProcessHeap(),0,newCompositeMoniker);
1703 return hr;
1705 if (newCompositeMoniker->tabLastIndex==1)
1707 hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
1708 else
1710 hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
1712 return hr;
1715 /******************************************************************************
1716 * MonikerCommonPrefixWith [OLE32.82]
1717 ******************************************************************************/
1718 HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1720 FIXME("(),stub!\n");
1721 return E_NOTIMPL;