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
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
38 const CLSID CLSID_CompositeMoniker
= {
39 0x309, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
42 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
44 /* CompositeMoniker data structure */
45 typedef struct CompositeMonikerImpl
{
47 ICOM_VTABLE(IMoniker
)* lpvtbl1
; /* VTable relative to the IMoniker interface.*/
49 /* The ROT (RunningObjectTable implementation) uses the IROTData
50 * interface to test whether two monikers are equal. That's why IROTData
51 * interface is implemented by monikers.
53 ICOM_VTABLE(IROTData
)* lpvtbl2
; /* VTable relative to the IROTData interface.*/
55 ULONG ref
; /* reference counter for this object */
57 IMoniker
** tabMoniker
; /* dynamaic table containing all components (monikers) of this composite moniker */
59 ULONG tabSize
; /* size of tabMoniker */
61 ULONG tabLastIndex
; /* first free index in tabMoniker */
63 } CompositeMonikerImpl
;
66 /* EnumMoniker data structure */
67 typedef struct EnumMonikerImpl
{
69 ICOM_VFIELD(IEnumMoniker
); /* VTable relative to the IEnumMoniker interface.*/
71 ULONG ref
; /* reference counter for this object */
73 IMoniker
** tabMoniker
; /* dynamic table containing the enumerated monikers */
75 ULONG tabSize
; /* size of tabMoniker */
77 ULONG currentPos
; /* index pointer on the current moniker */
82 /********************************************************************************/
83 /* CompositeMoniker prototype functions : */
85 /* IUnknown prototype functions */
86 static HRESULT WINAPI
CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
);
87 static ULONG WINAPI
CompositeMonikerImpl_AddRef(IMoniker
* iface
);
88 static ULONG WINAPI
CompositeMonikerImpl_Release(IMoniker
* iface
);
90 /* IPersist prototype functions */
91 static HRESULT WINAPI
CompositeMonikerImpl_GetClassID(IMoniker
* iface
, CLSID
*pClassID
);
93 /* IPersistStream prototype functions */
94 static HRESULT WINAPI
CompositeMonikerImpl_IsDirty(IMoniker
* iface
);
95 static HRESULT WINAPI
CompositeMonikerImpl_Load(IMoniker
* iface
, IStream
* pStm
);
96 static HRESULT WINAPI
CompositeMonikerImpl_Save(IMoniker
* iface
, IStream
* pStm
, BOOL fClearDirty
);
97 static HRESULT WINAPI
CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
, ULARGE_INTEGER
* pcbSize
);
99 /* IMoniker prototype functions */
100 static HRESULT WINAPI
CompositeMonikerImpl_BindToObject(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
);
101 static HRESULT WINAPI
CompositeMonikerImpl_BindToStorage(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
);
102 static HRESULT WINAPI
CompositeMonikerImpl_Reduce(IMoniker
* iface
,IBindCtx
* pbc
, DWORD dwReduceHowFar
,IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
);
103 static HRESULT WINAPI
CompositeMonikerImpl_ComposeWith(IMoniker
* iface
,IMoniker
* pmkRight
,BOOL fOnlyIfNotGeneric
, IMoniker
** ppmkComposite
);
104 static HRESULT WINAPI
CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
);
105 static HRESULT WINAPI
CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
);
106 static HRESULT WINAPI
CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
);
107 static HRESULT WINAPI
CompositeMonikerImpl_IsRunning(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, IMoniker
* pmkNewlyRunning
);
108 static HRESULT WINAPI
CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
, FILETIME
* pCompositeTime
);
109 static HRESULT WINAPI
CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
);
110 static HRESULT WINAPI
CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
, IMoniker
** ppmkPrefix
);
111 static HRESULT WINAPI
CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmOther
, IMoniker
** ppmkRelPath
);
112 static HRESULT WINAPI
CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
);
113 static HRESULT WINAPI
CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
* pchEaten
, IMoniker
** ppmkOut
);
114 static HRESULT WINAPI
CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
);
116 /********************************************************************************/
117 /* IROTData prototype functions */
119 /* IUnknown prototype functions */
120 static HRESULT WINAPI
CompositeMonikerROTDataImpl_QueryInterface(IROTData
* iface
,REFIID riid
,VOID
** ppvObject
);
121 static ULONG WINAPI
CompositeMonikerROTDataImpl_AddRef(IROTData
* iface
);
122 static ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
);
124 /* IROTData prototype function */
125 static HRESULT WINAPI
CompositeMonikerROTDataImpl_GetComparaisonData(IROTData
* iface
,BYTE
* pbData
,ULONG cbMax
,ULONG
* pcbData
);
127 /* Local function used by CompositeMoniker implementation */
128 HRESULT WINAPI
CompositeMonikerImpl_Construct(CompositeMonikerImpl
* This
,LPMONIKER pmkFirst
, LPMONIKER pmkRest
);
129 HRESULT WINAPI
CompositeMonikerImpl_Destroy(CompositeMonikerImpl
* iface
);
131 /********************************************************************************/
132 /* IEnumMoniker prototype functions */
134 /* IUnknown prototype functions */
135 static HRESULT WINAPI
EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
);
136 static ULONG WINAPI
EnumMonikerImpl_AddRef(IEnumMoniker
* iface
);
137 static ULONG WINAPI
EnumMonikerImpl_Release(IEnumMoniker
* iface
);
139 /* IEnumMoniker prototype functions */
140 static HRESULT WINAPI
EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
,IMoniker
** rgelt
,ULONG
* pceltFetched
);
141 static HRESULT WINAPI
EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
);
142 static HRESULT WINAPI
EnumMonikerImpl_Reset(IEnumMoniker
* iface
);
143 static HRESULT WINAPI
EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
);
145 HRESULT WINAPI
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,ULONG tabSize
,ULONG currentPos
,BOOL leftToRigth
,IEnumMoniker
** ppmk
);
147 /********************************************************************************/
148 /* Virtual function table for the CompositeMonikerImpl class which includes */
149 /* IPersist, IPersistStream and IMoniker functions. */
151 static ICOM_VTABLE(IMoniker
) VT_CompositeMonikerImpl
=
153 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
154 CompositeMonikerImpl_QueryInterface
,
155 CompositeMonikerImpl_AddRef
,
156 CompositeMonikerImpl_Release
,
157 CompositeMonikerImpl_GetClassID
,
158 CompositeMonikerImpl_IsDirty
,
159 CompositeMonikerImpl_Load
,
160 CompositeMonikerImpl_Save
,
161 CompositeMonikerImpl_GetSizeMax
,
162 CompositeMonikerImpl_BindToObject
,
163 CompositeMonikerImpl_BindToStorage
,
164 CompositeMonikerImpl_Reduce
,
165 CompositeMonikerImpl_ComposeWith
,
166 CompositeMonikerImpl_Enum
,
167 CompositeMonikerImpl_IsEqual
,
168 CompositeMonikerImpl_Hash
,
169 CompositeMonikerImpl_IsRunning
,
170 CompositeMonikerImpl_GetTimeOfLastChange
,
171 CompositeMonikerImpl_Inverse
,
172 CompositeMonikerImpl_CommonPrefixWith
,
173 CompositeMonikerImpl_RelativePathTo
,
174 CompositeMonikerImpl_GetDisplayName
,
175 CompositeMonikerImpl_ParseDisplayName
,
176 CompositeMonikerImpl_IsSystemMoniker
179 /********************************************************************************/
180 /* Virtual function table for the IROTData class. */
181 static ICOM_VTABLE(IROTData
) VT_ROTDataImpl
=
183 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
184 CompositeMonikerROTDataImpl_QueryInterface
,
185 CompositeMonikerROTDataImpl_AddRef
,
186 CompositeMonikerROTDataImpl_Release
,
187 CompositeMonikerROTDataImpl_GetComparaisonData
190 /********************************************************************************/
191 /* Virtual function table for the IROTData class */
192 static ICOM_VTABLE(IEnumMoniker
) VT_EnumMonikerImpl
=
194 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
195 EnumMonikerImpl_QueryInterface
,
196 EnumMonikerImpl_AddRef
,
197 EnumMonikerImpl_Release
,
198 EnumMonikerImpl_Next
,
199 EnumMonikerImpl_Skip
,
200 EnumMonikerImpl_Reset
,
201 EnumMonikerImpl_Clone
204 /*******************************************************************************
205 * CompositeMoniker_QueryInterface
206 *******************************************************************************/
207 HRESULT WINAPI
CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
209 ICOM_THIS(CompositeMonikerImpl
,iface
);
211 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
213 /* Perform a sanity check on the parameters.*/
214 if ( (This
==0) || (ppvObject
==0) )
217 /* Initialize the return parameter */
220 /* Compare the riid with the interface IDs implemented by this object.*/
221 if (IsEqualIID(&IID_IUnknown
, riid
) ||
222 IsEqualIID(&IID_IPersist
, riid
) ||
223 IsEqualIID(&IID_IPersistStream
, riid
) ||
224 IsEqualIID(&IID_IMoniker
, riid
)
227 else if (IsEqualIID(&IID_IROTData
, riid
))
228 *ppvObject
= (IROTData
*)&(This
->lpvtbl2
);
230 /* Check that we obtained an interface.*/
232 return E_NOINTERFACE
;
234 /* Query Interface always increases the reference count by one when it is successful */
235 CompositeMonikerImpl_AddRef(iface
);
240 /******************************************************************************
241 * CompositeMoniker_AddRef
242 ******************************************************************************/
243 ULONG WINAPI
CompositeMonikerImpl_AddRef(IMoniker
* iface
)
245 ICOM_THIS(CompositeMonikerImpl
,iface
);
247 TRACE("(%p)\n",This
);
249 return ++(This
->ref
);
252 /******************************************************************************
253 * CompositeMoniker_Release
254 ******************************************************************************/
255 ULONG WINAPI
CompositeMonikerImpl_Release(IMoniker
* iface
)
257 ICOM_THIS(CompositeMonikerImpl
,iface
);
260 TRACE("(%p)\n",This
);
264 /* destroy the object if there's no more reference on it */
267 /* release all the components before destroying this object */
268 for (i
=0;i
<This
->tabLastIndex
;i
++)
269 IMoniker_Release(This
->tabMoniker
[i
]);
271 CompositeMonikerImpl_Destroy(This
);
278 /******************************************************************************
279 * CompositeMoniker_GetClassID
280 ******************************************************************************/
281 HRESULT WINAPI
CompositeMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
283 TRACE("(%p,%p),stub!\n",iface
,pClassID
);
288 *pClassID
= CLSID_CompositeMoniker
;
293 /******************************************************************************
294 * CompositeMoniker_IsDirty
295 ******************************************************************************/
296 HRESULT WINAPI
CompositeMonikerImpl_IsDirty(IMoniker
* iface
)
298 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
299 method in the OLE-provided moniker interfaces always return S_FALSE because
300 their internal state never changes. */
302 TRACE("(%p)\n",iface
);
307 /******************************************************************************
308 * CompositeMoniker_Load
309 ******************************************************************************/
310 HRESULT WINAPI
CompositeMonikerImpl_Load(IMoniker
* iface
,IStream
* pStm
)
317 ICOM_THIS(CompositeMonikerImpl
,iface
);
319 TRACE("(%p,%p)\n",iface
,pStm
);
321 /* this function call OleLoadFromStream function for each moniker within this object */
323 /* read the a constant written by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
324 res
=IStream_Read(pStm
,&constant
,sizeof(DWORD
),NULL
);
326 if (SUCCEEDED(res
)&& constant
!=3)
331 res
=OleLoadFromStream(pStm
,&IID_IMoniker
,(void**)&This
->tabMoniker
[This
->tabLastIndex
]);
333 res
=ReadClassStm(pStm
,&clsid
);
334 DPRINTF("res=%ld",res
);
338 if (IsEqualIID(&clsid
,&CLSID_FileMoniker
)){
339 res
=CreateFileMoniker(string
,&This
->tabMoniker
[This
->tabLastIndex
]);
342 res
=IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
346 else if (IsEqualIID(&clsid
,&CLSID_ItemMoniker
)){
347 CreateItemMoniker(string
,string
,&This
->tabMoniker
[This
->tabLastIndex
]);
350 IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
354 else if (IsEqualIID(&clsid
,&CLSID_AntiMoniker
)){
355 CreateAntiMoniker(&This
->tabMoniker
[This
->tabLastIndex
]);
358 IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
362 else if (IsEqualIID(&clsid
,&CLSID_CompositeMoniker
))
368 /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */
373 /* resize the table if needed */
374 if (++This
->tabLastIndex
==This
->tabSize
){
376 This
->tabSize
+=BLOCK_TAB_SIZE
;
377 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
379 if (This
->tabMoniker
==NULL
)
380 return E_OUTOFMEMORY
;
387 /******************************************************************************
388 * CompositeMoniker_Save
389 ******************************************************************************/
390 HRESULT WINAPI
CompositeMonikerImpl_Save(IMoniker
* iface
,IStream
* pStm
,BOOL fClearDirty
)
393 IEnumMoniker
*enumMk
;
397 TRACE("(%p,%p,%d)\n",iface
,pStm
,fClearDirty
);
399 /* This function calls OleSaveToStream function for each moniker within
401 * When I tested this function in windows, I usually found this constant
402 * at the beginning of the stream. I don't known why (there's no
403 * indication in the specification) !
405 res
=IStream_Write(pStm
,&constant
,sizeof(constant
),NULL
);
407 IMoniker_Enum(iface
,TRUE
,&enumMk
);
409 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
411 res
=OleSaveToStream((IPersistStream
*)pmk
,pStm
);
413 IMoniker_Release(pmk
);
417 IEnumMoniker_Release(pmk
);
422 IEnumMoniker_Release(enumMk
);
427 /******************************************************************************
428 * CompositeMoniker_GetSizeMax
429 ******************************************************************************/
430 HRESULT WINAPI
CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
,ULARGE_INTEGER
* pcbSize
)
432 IEnumMoniker
*enumMk
;
434 ULARGE_INTEGER ptmpSize
;
436 /* The sizeMax of this object is calculated by calling GetSizeMax on
437 * each moniker within this object then summing all returned values
440 TRACE("(%p,%p)\n",iface
,pcbSize
);
445 pcbSize
->u
.LowPart
=0;
446 pcbSize
->u
.HighPart
=0;
448 IMoniker_Enum(iface
,TRUE
,&enumMk
);
450 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==TRUE
){
452 IMoniker_GetSizeMax(pmk
,&ptmpSize
);
454 IMoniker_Release(pmk
);
456 pcbSize
->u
.LowPart
+=ptmpSize
.u
.LowPart
;
457 pcbSize
->u
.HighPart
+=ptmpSize
.u
.HighPart
;
460 IEnumMoniker_Release(enumMk
);
465 /******************************************************************************
466 * Composite-Moniker_Construct (local function)
467 *******************************************************************************/
468 HRESULT WINAPI
CompositeMonikerImpl_Construct(CompositeMonikerImpl
* This
,LPMONIKER pmkFirst
, LPMONIKER pmkRest
)
471 IEnumMoniker
*enumMoniker
;
475 TRACE("(%p,%p,%p)\n",This
,pmkFirst
,pmkRest
);
477 /* Initialize the virtual function table. */
478 This
->lpvtbl1
= &VT_CompositeMonikerImpl
;
479 This
->lpvtbl2
= &VT_ROTDataImpl
;
482 This
->tabSize
=BLOCK_TAB_SIZE
;
483 This
->tabLastIndex
=0;
485 This
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,This
->tabSize
*sizeof(IMoniker
));
486 if (This
->tabMoniker
==NULL
)
487 return E_OUTOFMEMORY
;
489 IMoniker_IsSystemMoniker(pmkFirst
,&mkSys
);
491 /* put the first moniker contents in the beginning of the table */
492 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
494 This
->tabMoniker
[(This
->tabLastIndex
)++]=pmkFirst
;
495 IMoniker_AddRef(pmkFirst
);
499 IMoniker_Enum(pmkFirst
,TRUE
,&enumMoniker
);
501 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
504 if (++This
->tabLastIndex
==This
->tabSize
){
506 This
->tabSize
+=BLOCK_TAB_SIZE
;
507 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
509 if (This
->tabMoniker
==NULL
)
510 return E_OUTOFMEMORY
;
514 IEnumMoniker_Release(enumMoniker
);
517 /* put the rest moniker contents after the first one and make simplification if needed */
519 IMoniker_IsSystemMoniker(pmkRest
,&mkSys
);
521 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
523 /* add a simple moniker to the moniker table */
525 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],pmkRest
,TRUE
,&tempMk
);
527 if (res
==MK_E_NEEDGENERIC
){
529 /* there's no simplification in this case */
530 This
->tabMoniker
[This
->tabLastIndex
]=pmkRest
;
532 This
->tabLastIndex
++;
534 IMoniker_AddRef(pmkRest
);
536 else if (tempMk
==NULL
){
538 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
539 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
541 This
->tabLastIndex
--;
543 else if (SUCCEEDED(res
)){
545 /* the non-generic composition was successful so we can make a simplification in this case */
546 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
548 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
552 /* resize tabMoniker if needed */
553 if (This
->tabLastIndex
==This
->tabSize
){
555 This
->tabSize
+=BLOCK_TAB_SIZE
;
557 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
559 if (This
->tabMoniker
==NULL
)
560 return E_OUTOFMEMORY
;
565 /* add a composite moniker to the moniker table (do the same thing
566 * for each moniker within the composite moniker as a simple moniker
567 * (see above for how to add a simple moniker case) )
569 IMoniker_Enum(pmkRest
,TRUE
,&enumMoniker
);
571 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
573 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],This
->tabMoniker
[This
->tabLastIndex
],TRUE
,&tempMk
);
575 if (res
==MK_E_NEEDGENERIC
){
577 This
->tabLastIndex
++;
579 else if (tempMk
==NULL
){
581 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
582 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
]);
583 This
->tabLastIndex
--;
587 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
589 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
592 if (This
->tabLastIndex
==This
->tabSize
){
594 This
->tabSize
+=BLOCK_TAB_SIZE
;
596 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
598 if (This
->tabMoniker
==NULL
)
599 return E_OUTOFMEMORY
;
603 IEnumMoniker_Release(enumMoniker
);
609 /******************************************************************************
610 * CompositeMoniker_Destroy (local function)
611 *******************************************************************************/
612 HRESULT WINAPI
CompositeMonikerImpl_Destroy(CompositeMonikerImpl
* This
)
614 TRACE("(%p)\n",This
);
616 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
618 HeapFree(GetProcessHeap(),0,This
);
623 /******************************************************************************
624 * CompositeMoniker_BindToObject
625 ******************************************************************************/
626 HRESULT WINAPI
CompositeMonikerImpl_BindToObject(IMoniker
* iface
,
633 IRunningObjectTable
*prot
;
634 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
635 IEnumMoniker
*enumMoniker
;
637 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
643 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
644 /* object for the requested interface pointer. */
647 res
=IBindCtx_GetRunningObjectTable(pbc
,&prot
);
651 /* if the requested class was loaded before ! we don't need to reload it */
652 res
= IRunningObjectTable_GetObject(prot
,iface
,(IUnknown
**)ppvResult
);
659 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
660 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
662 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
663 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
664 IEnumMoniker_Release(enumMoniker
);
666 res
=CreateAntiMoniker(&antiMk
);
667 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
668 IMoniker_Release(antiMk
);
670 res
=CompositeMonikerImpl_BindToObject(mostRigthMk
,pbc
,tempMk
,riid
,ppvResult
);
672 IMoniker_Release(tempMk
);
673 IMoniker_Release(mostRigthMk
);
679 /******************************************************************************
680 * CompositeMoniker_BindToStorage
681 ******************************************************************************/
682 HRESULT WINAPI
CompositeMonikerImpl_BindToStorage(IMoniker
* iface
,
689 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
690 IEnumMoniker
*enumMoniker
;
692 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
696 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
697 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
699 if (pmkToLeft
!=NULL
){
701 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
702 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
703 IEnumMoniker_Release(enumMoniker
);
705 res
=CreateAntiMoniker(&antiMk
);
706 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
707 IMoniker_Release(antiMk
);
709 res
=CompositeMonikerImpl_BindToStorage(mostRigthMk
,pbc
,tempMk
,riid
,ppvResult
);
711 IMoniker_Release(tempMk
);
713 IMoniker_Release(mostRigthMk
);
718 return IMoniker_BindToStorage(iface
,pbc
,NULL
,riid
,ppvResult
);
721 /******************************************************************************
722 * CompositeMoniker_Reduce
723 ******************************************************************************/
724 HRESULT WINAPI
CompositeMonikerImpl_Reduce(IMoniker
* iface
,
726 DWORD dwReduceHowFar
,
727 IMoniker
** ppmkToLeft
,
728 IMoniker
** ppmkReduced
)
731 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*leftReducedComposedMk
,*mostRigthReducedMk
;
732 IEnumMoniker
*enumMoniker
;
734 TRACE("(%p,%p,%ld,%p,%p)\n",iface
,pbc
,dwReduceHowFar
,ppmkToLeft
,ppmkReduced
);
736 if (ppmkReduced
==NULL
)
739 /* This method recursively calls Reduce for each of its component monikers. */
741 if (ppmkToLeft
==NULL
){
743 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
744 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
745 IEnumMoniker_Release(enumMoniker
);
747 res
=CreateAntiMoniker(&antiMk
);
748 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
749 IMoniker_Release(antiMk
);
751 return CompositeMonikerImpl_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
, ppmkReduced
);
753 else if (*ppmkToLeft
==NULL
)
755 return IMoniker_Reduce(iface
,pbc
,dwReduceHowFar
,NULL
,ppmkReduced
);
759 /* separate the composite moniker in to left and right moniker */
760 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
761 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
762 IEnumMoniker_Release(enumMoniker
);
764 res
=CreateAntiMoniker(&antiMk
);
765 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
766 IMoniker_Release(antiMk
);
768 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
769 /* of the reduced components */
770 if (IMoniker_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,NULL
,&mostRigthReducedMk
) &&
771 CompositeMonikerImpl_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
,&leftReducedComposedMk
)
774 return CreateGenericComposite(leftReducedComposedMk
,mostRigthReducedMk
,ppmkReduced
);
777 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
779 IMoniker_AddRef(iface
);
783 return MK_S_REDUCED_TO_SELF
;
788 /******************************************************************************
789 * CompositeMoniker_ComposeWith
790 ******************************************************************************/
791 HRESULT WINAPI
CompositeMonikerImpl_ComposeWith(IMoniker
* iface
,
793 BOOL fOnlyIfNotGeneric
,
794 IMoniker
** ppmkComposite
)
796 TRACE("(%p,%p,%d,%p)\n",iface
,pmkRight
,fOnlyIfNotGeneric
,ppmkComposite
);
798 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
803 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
804 /* otherwise, the method returns the result of combining the two monikers by calling the */
805 /* CreateGenericComposite function */
807 if (fOnlyIfNotGeneric
)
808 return MK_E_NEEDGENERIC
;
810 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
813 /******************************************************************************
814 * CompositeMoniker_Enum
815 ******************************************************************************/
816 HRESULT WINAPI
CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
818 ICOM_THIS(CompositeMonikerImpl
,iface
);
820 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
822 if (ppenumMoniker
== NULL
)
825 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabLastIndex
,0,fForward
,ppenumMoniker
);
828 /******************************************************************************
829 * CompositeMoniker_IsEqual
830 ******************************************************************************/
831 HRESULT WINAPI
CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
)
833 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
834 IMoniker
*tempMk1
,*tempMk2
;
835 HRESULT res1
,res2
,res
;
837 TRACE("(%p,%p)\n",iface
,pmkOtherMoniker
);
839 if (pmkOtherMoniker
==NULL
)
842 /* This method returns S_OK if the components of both monikers are equal when compared in the */
843 /* left-to-right order.*/
844 IMoniker_Enum(pmkOtherMoniker
,TRUE
,&enumMoniker1
);
846 if (enumMoniker1
==NULL
)
849 IMoniker_Enum(iface
,TRUE
,&enumMoniker2
);
853 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
854 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
856 if((res1
==S_OK
)&&(res2
==S_OK
)){
858 if(IMoniker_IsEqual(tempMk1
,tempMk2
)==S_FALSE
){
865 else if ( (res1
==S_FALSE
) && (res2
==S_FALSE
) ){
875 IMoniker_Release(tempMk1
);
878 IMoniker_Release(tempMk2
);
881 IEnumMoniker_Release(enumMoniker1
);
882 IEnumMoniker_Release(enumMoniker2
);
886 /******************************************************************************
887 * CompositeMoniker_Hash
888 ******************************************************************************/
889 HRESULT WINAPI
CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
896 /******************************************************************************
897 * CompositeMoniker_IsRunning
898 ******************************************************************************/
899 HRESULT WINAPI
CompositeMonikerImpl_IsRunning(IMoniker
* iface
,
902 IMoniker
* pmkNewlyRunning
)
904 IRunningObjectTable
* rot
;
906 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
907 IEnumMoniker
*enumMoniker
;
909 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
911 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
912 if (pmkToLeft
!=NULL
){
914 CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
916 res
= IMoniker_IsRunning(tempMk
,pbc
,NULL
,pmkNewlyRunning
);
918 IMoniker_Release(tempMk
);
923 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
924 /* to this moniker */
926 if (pmkNewlyRunning
!=NULL
)
928 if (IMoniker_IsEqual(iface
,pmkNewlyRunning
)==S_OK
)
939 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
940 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
941 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
942 /* the composite as the pmkToLeft parameter for that call. */
944 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
949 res
= IRunningObjectTable_IsRunning(rot
,iface
);
950 IRunningObjectTable_Release(rot
);
957 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
958 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
959 IEnumMoniker_Release(enumMoniker
);
961 res
=CreateAntiMoniker(&antiMk
);
962 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
963 IMoniker_Release(antiMk
);
965 res
=IMoniker_IsRunning(mostRigthMk
,pbc
,tempMk
,pmkNewlyRunning
);
967 IMoniker_Release(tempMk
);
968 IMoniker_Release(mostRigthMk
);
975 /******************************************************************************
976 * CompositeMoniker_GetTimeOfLastChange
977 ******************************************************************************/
978 HRESULT WINAPI
CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
,
981 FILETIME
* pCompositeTime
)
983 IRunningObjectTable
* rot
;
985 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
986 IEnumMoniker
*enumMoniker
;
988 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pCompositeTime
);
990 if (pCompositeTime
==NULL
)
993 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
994 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
995 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
996 /* of the composite as the pmkToLeft parameter for that call. */
997 if (pmkToLeft
!=NULL
){
999 res
=CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
1001 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
1006 if (IRunningObjectTable_GetTimeOfLastChange(rot
,tempMk
,pCompositeTime
)==S_OK
)
1010 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1011 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1012 IEnumMoniker_Release(enumMoniker
);
1014 res
=CreateAntiMoniker(&antiMk
);
1015 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1016 IMoniker_Release(antiMk
);
1018 res
=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk
,pbc
,tempMk
,pCompositeTime
);
1020 IMoniker_Release(tempMk
);
1021 IMoniker_Release(mostRigthMk
);
1026 return IMoniker_GetTimeOfLastChange(iface
,pbc
,NULL
,pCompositeTime
);
1029 /******************************************************************************
1030 * CompositeMoniker_Inverse
1031 ******************************************************************************/
1032 HRESULT WINAPI
CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
1035 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*tempInvMk
,*mostRigthInvMk
;
1036 IEnumMoniker
*enumMoniker
;
1038 TRACE("(%p,%p)\n",iface
,ppmk
);
1043 /* This method returns a composite moniker that consists of the inverses of each of the components */
1044 /* of the original composite, stored in reverse order */
1046 res
=CreateAntiMoniker(&antiMk
);
1047 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1048 IMoniker_Release(antiMk
);
1052 return IMoniker_Inverse(iface
,ppmk
);
1056 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1057 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1058 IEnumMoniker_Release(enumMoniker
);
1060 IMoniker_Inverse(mostRigthMk
,&mostRigthInvMk
);
1061 CompositeMonikerImpl_Inverse(tempMk
,&tempInvMk
);
1063 res
=CreateGenericComposite(mostRigthInvMk
,tempInvMk
,ppmk
);
1065 IMoniker_Release(tempMk
);
1066 IMoniker_Release(mostRigthMk
);
1067 IMoniker_Release(tempInvMk
);
1068 IMoniker_Release(mostRigthInvMk
);
1074 /******************************************************************************
1075 * CompositeMoniker_CommonPrefixWith
1076 ******************************************************************************/
1077 HRESULT WINAPI
CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
,IMoniker
** ppmkPrefix
)
1081 IMoniker
*tempMk1
,*tempMk2
,*mostLeftMk1
,*mostLeftMk2
;
1082 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
1083 ULONG i
,nbCommonMk
=0;
1085 /* If the other moniker is a composite, this method compares the components of each composite from left */
1086 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1087 /* of the leftmost components were common to both monikers. */
1089 if (ppmkPrefix
==NULL
)
1095 return MK_E_NOPREFIX
;
1097 IMoniker_IsSystemMoniker(pmkOther
,&mkSys
);
1099 if((mkSys
==MKSYS_GENERICCOMPOSITE
)){
1101 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
1102 IMoniker_Enum(pmkOther
,TRUE
,&enumMoniker2
);
1106 res1
=IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
1107 res2
=IEnumMoniker_Next(enumMoniker2
,1,&mostLeftMk2
,NULL
);
1109 if ((res1
==S_FALSE
) && (res2
==S_FALSE
)){
1111 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1113 IMoniker_AddRef(iface
);
1116 else if ((res1
==S_OK
) && (res2
==S_OK
)){
1118 if (IMoniker_IsEqual(mostLeftMk1
,mostLeftMk2
)==S_OK
)
1126 else if (res1
==S_OK
){
1128 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1129 /* ppmkPrefix to the other moniker. */
1130 *ppmkPrefix
=pmkOther
;
1134 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1135 /* to this moniker. */
1141 IEnumMoniker_Release(enumMoniker1
);
1142 IEnumMoniker_Release(enumMoniker2
);
1144 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1146 return MK_E_NOPREFIX
;
1148 IEnumMoniker_Reset(enumMoniker1
);
1150 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1152 /* if we have more than one commun moniker the result will be a composite moniker */
1155 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1156 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1157 CreateGenericComposite(tempMk1
,tempMk2
,ppmkPrefix
);
1158 IMoniker_Release(tempMk1
);
1159 IMoniker_Release(tempMk2
);
1161 /* compose all common monikers in a composite moniker */
1162 for(i
=0;i
<nbCommonMk
;i
++){
1164 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1166 CreateGenericComposite(*ppmkPrefix
,tempMk1
,&tempMk2
);
1168 IMoniker_Release(*ppmkPrefix
);
1170 IMoniker_Release(tempMk1
);
1172 *ppmkPrefix
=tempMk2
;
1177 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1178 *ppmkPrefix
=tempMk1
;
1184 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1187 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
1189 IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
1191 if (IMoniker_IsEqual(pmkOther
,mostLeftMk1
)==S_OK
){
1193 *ppmkPrefix
=pmkOther
;
1198 return MK_E_NOPREFIX
;
1201 /***************************************************************************************************
1202 * GetAfterCommonPrefix (local function)
1203 * This function returns a moniker that consist of the remainder when the common prefix is removed
1204 ***************************************************************************************************/
1205 VOID WINAPI
GetAfterCommonPrefix(IMoniker
* pGenMk
,IMoniker
* commonMk
,IMoniker
** restMk
)
1207 IMoniker
*tempMk
,*tempMk1
,*tempMk2
;
1208 IEnumMoniker
*enumMoniker1
,*enumMoniker2
,*enumMoniker3
;
1215 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1216 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
1217 /* on the first difference. */
1218 IMoniker_Enum(pGenMk
,TRUE
,&enumMoniker1
);
1220 IMoniker_IsSystemMoniker(commonMk
,&mkSys
);
1222 if (mkSys
==MKSYS_GENERICCOMPOSITE
){
1224 IMoniker_Enum(commonMk
,TRUE
,&enumMoniker2
);
1227 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1228 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
1230 if ((res1
==S_FALSE
)||(res2
==S_FALSE
)){
1236 IMoniker_Release(tempMk1
);
1237 IMoniker_Release(tempMk1
);
1241 IMoniker_Release(tempMk1
);
1242 IMoniker_Release(tempMk1
);
1246 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1247 IMoniker_Release(tempMk1
);
1250 /* count the number of elements in the enumerator after the common prefix */
1251 IEnumMoniker_Clone(enumMoniker1
,&enumMoniker3
);
1253 for(;IEnumMoniker_Next(enumMoniker3
,1,&tempMk
,NULL
)==S_OK
;nbRestMk
++)
1255 IMoniker_Release(tempMk
);
1260 /* create a generic composite moniker with monikers located after the common prefix */
1261 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1270 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1272 CreateGenericComposite(tempMk1
,tempMk2
,restMk
);
1274 IMoniker_Release(tempMk1
);
1276 IMoniker_Release(tempMk2
);
1278 while(IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
)==S_OK
){
1280 CreateGenericComposite(*restMk
,tempMk1
,&tempMk2
);
1282 IMoniker_Release(tempMk1
);
1284 IMoniker_Release(*restMk
);
1290 /******************************************************************************
1291 * CompositeMoniker_RelativePathTo
1292 ******************************************************************************/
1293 HRESULT WINAPI
CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmkOther
, IMoniker
** ppmkRelPath
)
1296 IMoniker
*restOtherMk
=0,*restThisMk
=0,*invRestThisMk
=0,*commonMk
=0;
1298 TRACE("(%p,%p,%p)\n",iface
,pmkOther
,ppmkRelPath
);
1300 if (ppmkRelPath
==NULL
)
1305 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1306 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1307 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1309 /* finds the common prefix of the two monikers */
1310 res
=IMoniker_CommonPrefixWith(iface
,pmkOther
,&commonMk
);
1312 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1313 if ((res
== MK_E_NOPREFIX
)||(res
==MK_S_US
)){
1315 *ppmkRelPath
=pmkOther
;
1316 IMoniker_AddRef(pmkOther
);
1320 GetAfterCommonPrefix(iface
,commonMk
,&restThisMk
);
1321 GetAfterCommonPrefix(pmkOther
,commonMk
,&restOtherMk
);
1323 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1324 /* moniker when the common prefix is removed */
1327 IMoniker_Inverse(restThisMk
,ppmkRelPath
);
1328 IMoniker_Release(restThisMk
);
1330 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1331 /* when the common prefix is removed */
1332 else if (res
==MK_S_ME
){
1334 *ppmkRelPath
=restOtherMk
;
1335 IMoniker_AddRef(restOtherMk
);
1337 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1338 /* moniker on the right of it. */
1339 else if (res
==S_OK
){
1341 IMoniker_Inverse(restThisMk
,&invRestThisMk
);
1342 IMoniker_Release(restThisMk
);
1343 CreateGenericComposite(invRestThisMk
,restOtherMk
,ppmkRelPath
);
1344 IMoniker_Release(invRestThisMk
);
1345 IMoniker_Release(restOtherMk
);
1350 /******************************************************************************
1351 * CompositeMoniker_GetDisplayName
1352 ******************************************************************************/
1353 HRESULT WINAPI
CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
,
1355 IMoniker
* pmkToLeft
,
1356 LPOLESTR
*ppszDisplayName
)
1359 IEnumMoniker
*enumMoniker
;
1363 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
1365 if (ppszDisplayName
==NULL
)
1368 *ppszDisplayName
=CoTaskMemAlloc(sizeof(WCHAR
));
1370 if (*ppszDisplayName
==NULL
)
1371 return E_OUTOFMEMORY
;
1373 /* This method returns the concatenation of the display names returned by each component moniker of */
1376 **ppszDisplayName
=0;
1378 IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
1380 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
1382 IMoniker_GetDisplayName(tempMk
,pbc
,NULL
,&tempStr
);
1384 lengthStr
+=lstrlenW(tempStr
);
1386 *ppszDisplayName
=CoTaskMemRealloc(*ppszDisplayName
,lengthStr
* sizeof(WCHAR
));
1388 if (*ppszDisplayName
==NULL
)
1389 return E_OUTOFMEMORY
;
1391 strcatW(*ppszDisplayName
,tempStr
);
1393 CoTaskMemFree(tempStr
);
1394 IMoniker_Release(tempMk
);
1397 IEnumMoniker_Release(enumMoniker
);
1402 /******************************************************************************
1403 * CompositeMoniker_ParseDisplayName
1404 ******************************************************************************/
1405 HRESULT WINAPI
CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
,
1407 IMoniker
* pmkToLeft
,
1408 LPOLESTR pszDisplayName
,
1412 IEnumMoniker
*enumMoniker
;
1413 IMoniker
*tempMk
,*mostRigthMk
,*antiMk
;
1414 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1415 /* passing everything else as the pmkToLeft parameter for that call. */
1417 /* get the most right moniker */
1418 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1419 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1420 IEnumMoniker_Release(enumMoniker
);
1422 /* get the left moniker */
1423 CreateAntiMoniker(&antiMk
);
1424 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1425 IMoniker_Release(antiMk
);
1427 return IMoniker_ParseDisplayName(mostRigthMk
,pbc
,tempMk
,pszDisplayName
,pchEaten
,ppmkOut
);
1430 /******************************************************************************
1431 * CompositeMoniker_IsSystemMoniker
1432 ******************************************************************************/
1433 HRESULT WINAPI
CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
1435 TRACE("(%p,%p)\n",iface
,pwdMksys
);
1440 (*pwdMksys
)=MKSYS_GENERICCOMPOSITE
;
1445 /*******************************************************************************
1446 * CompositeMonikerIROTData_QueryInterface
1447 *******************************************************************************/
1448 HRESULT WINAPI
CompositeMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,VOID
** ppvObject
)
1451 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1453 TRACE("(%p,%p,%p)\n",iface
,riid
,ppvObject
);
1455 return CompositeMonikerImpl_QueryInterface(This
, riid
, ppvObject
);
1458 /***********************************************************************
1459 * CompositeMonikerIROTData_AddRef
1461 ULONG WINAPI
CompositeMonikerROTDataImpl_AddRef(IROTData
*iface
)
1463 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1465 TRACE("(%p)\n",iface
);
1467 return CompositeMonikerImpl_AddRef(This
);
1470 /***********************************************************************
1471 * CompositeMonikerIROTData_Release
1473 ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
)
1475 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1477 TRACE("(%p)\n",iface
);
1479 return CompositeMonikerImpl_Release(This
);
1482 /******************************************************************************
1483 * CompositeMonikerIROTData_GetComparaisonData
1484 ******************************************************************************/
1485 HRESULT WINAPI
CompositeMonikerROTDataImpl_GetComparaisonData(IROTData
* iface
,
1490 FIXME("(),stub!\n");
1494 /******************************************************************************
1495 * EnumMonikerImpl_QueryInterface
1496 ******************************************************************************/
1497 HRESULT WINAPI
EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
)
1499 ICOM_THIS(EnumMonikerImpl
,iface
);
1501 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
1503 /* Perform a sanity check on the parameters.*/
1504 if ( (This
==0) || (ppvObject
==0) )
1505 return E_INVALIDARG
;
1507 /* Initialize the return parameter */
1510 /* Compare the riid with the interface IDs implemented by this object.*/
1511 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IEnumMoniker
, riid
))
1514 /* Check that we obtained an interface.*/
1515 if ((*ppvObject
)==0)
1516 return E_NOINTERFACE
;
1518 /* Query Interface always increases the reference count by one when it is successful */
1519 EnumMonikerImpl_AddRef(iface
);
1524 /******************************************************************************
1525 * EnumMonikerImpl_AddRef
1526 ******************************************************************************/
1527 ULONG WINAPI
EnumMonikerImpl_AddRef(IEnumMoniker
* iface
)
1529 ICOM_THIS(EnumMonikerImpl
,iface
);
1531 TRACE("(%p)\n",This
);
1533 return ++(This
->ref
);
1537 /******************************************************************************
1538 * EnumMonikerImpl_Release
1539 ******************************************************************************/
1540 ULONG WINAPI
EnumMonikerImpl_Release(IEnumMoniker
* iface
)
1542 ICOM_THIS(EnumMonikerImpl
,iface
);
1545 TRACE("(%p)\n",This
);
1549 /* destroy the object if there's no more reference on it */
1552 for(i
=0;i
<This
->tabSize
;i
++)
1553 IMoniker_Release(This
->tabMoniker
[i
]);
1555 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
1556 HeapFree(GetProcessHeap(),0,This
);
1563 /******************************************************************************
1564 * EnumMonikerImpl_Next
1565 ******************************************************************************/
1566 HRESULT WINAPI
EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
, IMoniker
** rgelt
, ULONG
* pceltFethed
){
1568 ICOM_THIS(EnumMonikerImpl
,iface
);
1571 /* retrieve the requested number of moniker from the current position */
1572 for(i
=0;((This
->currentPos
< This
->tabSize
) && (i
< celt
));i
++)
1574 rgelt
[i
]=This
->tabMoniker
[This
->currentPos
++];
1576 if (pceltFethed
!=NULL
)
1585 /******************************************************************************
1586 * EnumMonikerImpl_Skip
1587 ******************************************************************************/
1588 HRESULT WINAPI
EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
){
1590 ICOM_THIS(EnumMonikerImpl
,iface
);
1592 if ((This
->currentPos
+celt
) >= This
->tabSize
)
1595 This
->currentPos
+=celt
;
1600 /******************************************************************************
1601 * EnumMonikerImpl_Reset
1602 ******************************************************************************/
1603 HRESULT WINAPI
EnumMonikerImpl_Reset(IEnumMoniker
* iface
){
1605 ICOM_THIS(EnumMonikerImpl
,iface
);
1612 /******************************************************************************
1613 * EnumMonikerImpl_Clone
1614 ******************************************************************************/
1615 HRESULT WINAPI
EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
){
1617 ICOM_THIS(EnumMonikerImpl
,iface
);
1619 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabSize
,This
->currentPos
,TRUE
,ppenum
);
1622 /******************************************************************************
1623 * EnumMonikerImpl_CreateEnumMoniker
1624 ******************************************************************************/
1625 HRESULT WINAPI
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,
1629 IEnumMoniker
** ppmk
)
1631 EnumMonikerImpl
* newEnumMoniker
;
1635 if (currentPos
> tabSize
)
1636 return E_INVALIDARG
;
1638 newEnumMoniker
= HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl
));
1640 if (newEnumMoniker
== 0)
1641 return STG_E_INSUFFICIENTMEMORY
;
1643 /* Initialize the virtual function table. */
1644 newEnumMoniker
->lpVtbl
= &VT_EnumMonikerImpl
;
1645 newEnumMoniker
->ref
= 0;
1647 newEnumMoniker
->tabSize
=tabSize
;
1648 newEnumMoniker
->currentPos
=currentPos
;
1650 newEnumMoniker
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,tabSize
*sizeof(IMoniker
));
1652 if (newEnumMoniker
->tabMoniker
==NULL
) {
1653 HeapFree(GetProcessHeap(), 0, newEnumMoniker
);
1654 return E_OUTOFMEMORY
;
1658 for (i
=0;i
<tabSize
;i
++){
1660 newEnumMoniker
->tabMoniker
[i
]=tabMoniker
[i
];
1661 IMoniker_AddRef(tabMoniker
[i
]);
1664 for (i
=tabSize
-1;i
>=0;i
--){
1666 newEnumMoniker
->tabMoniker
[tabSize
-i
-1]=tabMoniker
[i
];
1667 IMoniker_AddRef(tabMoniker
[i
]);
1670 *ppmk
=(IEnumMoniker
*)newEnumMoniker
;
1675 /******************************************************************************
1676 * CreateGenericComposite [OLE32.@]
1677 ******************************************************************************/
1678 HRESULT WINAPI
CreateGenericComposite(LPMONIKER pmkFirst
, LPMONIKER pmkRest
, LPMONIKER
* ppmkComposite
)
1680 CompositeMonikerImpl
* newCompositeMoniker
= 0;
1683 TRACE("(%p,%p,%p)\n",pmkFirst
,pmkRest
,ppmkComposite
);
1685 if (ppmkComposite
==NULL
)
1690 if (pmkFirst
==NULL
&& pmkRest
!=NULL
){
1692 *ppmkComposite
=pmkRest
;
1695 else if (pmkFirst
!=NULL
&& pmkRest
==NULL
){
1696 *ppmkComposite
=pmkFirst
;
1699 else if (pmkFirst
==NULL
&& pmkRest
==NULL
)
1702 newCompositeMoniker
= HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl
));
1704 if (newCompositeMoniker
== 0)
1705 return STG_E_INSUFFICIENTMEMORY
;
1707 hr
= CompositeMonikerImpl_Construct(newCompositeMoniker
,pmkFirst
,pmkRest
);
1711 HeapFree(GetProcessHeap(),0,newCompositeMoniker
);
1714 if (newCompositeMoniker
->tabLastIndex
==1)
1716 hr
= IMoniker_QueryInterface(newCompositeMoniker
->tabMoniker
[0],&IID_IMoniker
,(void**)ppmkComposite
);
1719 hr
= CompositeMonikerImpl_QueryInterface((IMoniker
*)newCompositeMoniker
,&IID_IMoniker
,(void**)ppmkComposite
);
1724 /******************************************************************************
1725 * MonikerCommonPrefixWith [OLE32.@]
1726 ******************************************************************************/
1727 HRESULT WINAPI
MonikerCommonPrefixWith(IMoniker
* pmkThis
,IMoniker
* pmkOther
,IMoniker
** ppmkCommon
)
1729 FIXME("(),stub!\n");