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 ***************************************************************************************/
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"
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 */
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) )
210 /* Initialize the return parameter */
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
)
220 else if (IsEqualIID(&IID_IROTData
, riid
))
221 *ppvObject
= (IROTData
*)&(This
->lpvtbl2
);
223 /* Check that we obtained an interface.*/
225 return E_NOINTERFACE
;
227 /* Query Interface always increases the reference count by one when it is successful */
228 CompositeMonikerImpl_AddRef(iface
);
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
);
253 TRACE("(%p)\n",This
);
257 /* destroy the object if there's no more reference on it */
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
);
271 /******************************************************************************
272 * CompositeMoniker_GetClassID
273 ******************************************************************************/
274 HRESULT WINAPI
CompositeMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
276 TRACE("(%p,%p),stub!\n",iface
,pClassID
);
281 *pClassID
= CLSID_CompositeMoniker
;
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
);
300 /******************************************************************************
301 * CompositeMoniker_Load
302 ******************************************************************************/
303 HRESULT WINAPI
CompositeMonikerImpl_Load(IMoniker
* iface
,IStream
* pStm
)
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)
324 res
=OleLoadFromStream(pStm
,&IID_IMoniker
,(void**)&This
->tabMoniker
[This
->tabLastIndex
]);
326 res
=ReadClassStm(pStm
,&clsid
);
327 DPRINTF("res=%ld",res
);
331 if (IsEqualIID(&clsid
,&CLSID_FileMoniker
)){
332 res
=CreateFileMoniker(string
,&This
->tabMoniker
[This
->tabLastIndex
]);
335 res
=IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
339 else if (IsEqualIID(&clsid
,&CLSID_ItemMoniker
)){
340 CreateItemMoniker(string
,string
,&This
->tabMoniker
[This
->tabLastIndex
]);
343 IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
347 else if (IsEqualIID(&clsid
,&CLSID_AntiMoniker
)){
348 CreateAntiMoniker(&This
->tabMoniker
[This
->tabLastIndex
]);
351 IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
355 else if (IsEqualIID(&clsid
,&CLSID_CompositeMoniker
))
361 /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */
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
;
380 /******************************************************************************
381 * CompositeMoniker_Save
382 ******************************************************************************/
383 HRESULT WINAPI
CompositeMonikerImpl_Save(IMoniker
* iface
,IStream
* pStm
,BOOL fClearDirty
)
386 IEnumMoniker
*enumMk
;
390 TRACE("(%p,%p,%d)\n",iface
,pStm
,fClearDirty
);
392 /* This function calls OleSaveToStream function for each moniker within
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
);
410 IEnumMoniker_Release(pmk
);
415 IEnumMoniker_Release(enumMk
);
420 /******************************************************************************
421 * CompositeMoniker_GetSizeMax
422 ******************************************************************************/
423 HRESULT WINAPI
CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
,ULARGE_INTEGER
* pcbSize
)
425 IEnumMoniker
*enumMk
;
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
);
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
);
458 /******************************************************************************
459 * Composite-Moniker_Construct (local function)
460 *******************************************************************************/
461 HRESULT WINAPI
CompositeMonikerImpl_Construct(CompositeMonikerImpl
* This
,LPMONIKER pmkFirst
, LPMONIKER pmkRest
)
464 IEnumMoniker
*enumMoniker
;
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
;
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
);
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
;
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
;
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
--;
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
);
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
);
616 /******************************************************************************
617 * CompositeMoniker_BindToObject
618 ******************************************************************************/
619 HRESULT WINAPI
CompositeMonikerImpl_BindToObject(IMoniker
* iface
,
626 IRunningObjectTable
*prot
;
627 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
628 IEnumMoniker
*enumMoniker
;
630 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
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. */
640 res
=IBindCtx_GetRunningObjectTable(pbc
,&prot
);
644 /* if the requested class was loaded befor ! we dont need to reload it */
645 res
= IRunningObjectTable_GetObject(prot
,iface
,(IUnknown
**)ppvResult
);
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
);
672 /******************************************************************************
673 * CompositeMoniker_BindToStorage
674 ******************************************************************************/
675 HRESULT WINAPI
CompositeMonikerImpl_BindToStorage(IMoniker
* iface
,
682 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
683 IEnumMoniker
*enumMoniker
;
685 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
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
);
711 return IMoniker_BindToStorage(iface
,pbc
,NULL
,riid
,ppvResult
);
714 /******************************************************************************
715 * CompositeMoniker_Reduce
716 ******************************************************************************/
717 HRESULT WINAPI
CompositeMonikerImpl_Reduce(IMoniker
* iface
,
719 DWORD dwReduceHowFar
,
720 IMoniker
** ppmkToLeft
,
721 IMoniker
** ppmkReduced
)
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
)
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
);
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
);
770 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
772 IMoniker_AddRef(iface
);
776 return MK_S_REDUCED_TO_SELF
;
781 /******************************************************************************
782 * CompositeMoniker_ComposeWith
783 ******************************************************************************/
784 HRESULT WINAPI
CompositeMonikerImpl_ComposeWith(IMoniker
* iface
,
786 BOOL fOnlyIfNotGeneric
,
787 IMoniker
** ppmkComposite
)
789 TRACE("(%p,%p,%d,%p)\n",iface
,pmkRight
,fOnlyIfNotGeneric
,ppmkComposite
);
791 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
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
)
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
)
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
)
842 IMoniker_Enum(iface
,TRUE
,&enumMoniker2
);
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
){
858 else if ( (res1
==S_FALSE
) && (res2
==S_FALSE
) ){
868 IMoniker_Release(tempMk1
);
871 IMoniker_Release(tempMk2
);
874 IEnumMoniker_Release(enumMoniker1
);
875 IEnumMoniker_Release(enumMoniker2
);
879 /******************************************************************************
880 * CompositeMoniker_Hash
881 ******************************************************************************/
882 HRESULT WINAPI
CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
889 /******************************************************************************
890 * CompositeMoniker_IsRunning
891 ******************************************************************************/
892 HRESULT WINAPI
CompositeMonikerImpl_IsRunning(IMoniker
* iface
,
895 IMoniker
* pmkNewlyRunning
)
897 IRunningObjectTable
* rot
;
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
);
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
)
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
);
942 res
= IRunningObjectTable_IsRunning(rot
,iface
);
943 IRunningObjectTable_Release(rot
);
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
);
968 /******************************************************************************
969 * CompositeMoniker_GetTimeOfLastChange
970 ******************************************************************************/
971 HRESULT WINAPI
CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
,
974 FILETIME
* pCompositeTime
)
976 IRunningObjectTable
* rot
;
978 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
979 IEnumMoniker
*enumMoniker
;
981 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pCompositeTime
);
983 if (pCompositeTime
==NULL
)
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
);
999 if (IRunningObjectTable_GetTimeOfLastChange(rot
,tempMk
,pCompositeTime
)==S_OK
)
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
);
1019 return IMoniker_GetTimeOfLastChange(iface
,pbc
,NULL
,pCompositeTime
);
1022 /******************************************************************************
1023 * CompositeMoniker_Inverse
1024 ******************************************************************************/
1025 HRESULT WINAPI
CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
1028 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*tempInvMk
,*mostRigthInvMk
;
1029 IEnumMoniker
*enumMoniker
;
1031 TRACE("(%p,%p)\n",iface
,ppmk
);
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
);
1045 return IMoniker_Inverse(iface
,ppmk
);
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
);
1067 /******************************************************************************
1068 * CompositeMoniker_CommonPrefixWith
1069 ******************************************************************************/
1070 HRESULT WINAPI
CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
,IMoniker
** ppmkPrefix
)
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
)
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
);
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.*/
1106 IMoniker_AddRef(iface
);
1109 else if ((res1
==S_OK
) && (res2
==S_OK
)){
1111 if (IMoniker_IsEqual(mostLeftMk1
,mostLeftMk2
)==S_OK
)
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
;
1127 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1128 /* to this moniker. */
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. */
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 */
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
;
1170 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1171 *ppmkPrefix
=tempMk1
;
1177 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1180 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
1182 IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
1184 if (IMoniker_IsEqual(pmkOther
,mostLeftMk1
)==S_OK
){
1186 *ppmkPrefix
=pmkOther
;
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
;
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
);
1220 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1221 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
1223 if ((res1
==S_FALSE
)||(res2
==S_FALSE
)){
1229 IMoniker_Release(tempMk1
);
1230 IMoniker_Release(tempMk1
);
1234 IMoniker_Release(tempMk1
);
1235 IMoniker_Release(tempMk1
);
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
);;
1253 /* create a generic composite moniker with monikers located after the common prefix */
1254 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
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
);
1283 /******************************************************************************
1284 * CompositeMoniker_RelativePathTo
1285 ******************************************************************************/
1286 HRESULT WINAPI
CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmkOther
, IMoniker
** ppmkRelPath
)
1289 IMoniker
*restOtherMk
=0,*restThisMk
=0,*invRestThisMk
=0,*commonMk
=0;
1291 TRACE("(%p,%p,%p)\n",iface
,pmkOther
,ppmkRelPath
);
1293 if (ppmkRelPath
==NULL
)
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
);
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 */
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
);
1343 /******************************************************************************
1344 * CompositeMoniker_GetDisplayName
1345 ******************************************************************************/
1346 HRESULT WINAPI
CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
,
1348 IMoniker
* pmkToLeft
,
1349 LPOLESTR
*ppszDisplayName
)
1352 IEnumMoniker
*enumMoniker
;
1356 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
1358 if (ppszDisplayName
==NULL
)
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 */
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
);
1395 /******************************************************************************
1396 * CompositeMoniker_ParseDisplayName
1397 ******************************************************************************/
1398 HRESULT WINAPI
CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
,
1400 IMoniker
* pmkToLeft
,
1401 LPOLESTR pszDisplayName
,
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
);
1433 (*pwdMksys
)=MKSYS_GENERICCOMPOSITE
;
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
,
1483 FIXME("(),stub!\n");
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 */
1503 /* Compare the riid with the interface IDs implemented by this object.*/
1504 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IEnumMoniker
, riid
))
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
);
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
);
1538 TRACE("(%p)\n",This
);
1542 /* destroy the object if there's no more reference on it */
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
);
1556 /******************************************************************************
1557 * EnumMonikerImpl_Next
1558 ******************************************************************************/
1559 HRESULT WINAPI
EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
, IMoniker
** rgelt
, ULONG
* pceltFethed
){
1561 ICOM_THIS(EnumMonikerImpl
,iface
);
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
)
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
)
1588 This
->currentPos
+=celt
;
1593 /******************************************************************************
1594 * EnumMonikerImpl_Reset
1595 ******************************************************************************/
1596 HRESULT WINAPI
EnumMonikerImpl_Reset(IEnumMoniker
* iface
){
1598 ICOM_THIS(EnumMonikerImpl
,iface
);
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
,
1622 IEnumMoniker
** ppmk
)
1624 EnumMonikerImpl
* newEnumMoniker
;
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
;
1649 for (i
=0;i
<tabSize
;i
++){
1651 newEnumMoniker
->tabMoniker
[i
]=tabMoniker
[i
];
1652 IMoniker_AddRef(tabMoniker
[i
]);
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
;
1666 /******************************************************************************
1667 * CreateGenericComposite [OLE32.56]
1668 ******************************************************************************/
1669 HRESULT WINAPI
CreateGenericComposite(LPMONIKER pmkFirst
, LPMONIKER pmkRest
, LPMONIKER
* ppmkComposite
)
1671 CompositeMonikerImpl
* newCompositeMoniker
= 0;
1674 TRACE("(%p,%p,%p)\n",pmkFirst
,pmkRest
,ppmkComposite
);
1676 if (ppmkComposite
==NULL
)
1681 if (pmkFirst
==NULL
&& pmkRest
!=NULL
){
1683 *ppmkComposite
=pmkRest
;
1686 else if (pmkFirst
!=NULL
&& pmkRest
==NULL
){
1687 *ppmkComposite
=pmkFirst
;
1690 else if (pmkFirst
==NULL
&& pmkRest
==NULL
)
1693 newCompositeMoniker
= HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl
));
1695 if (newCompositeMoniker
== 0)
1696 return STG_E_INSUFFICIENTMEMORY
;
1698 hr
= CompositeMonikerImpl_Construct(newCompositeMoniker
,pmkFirst
,pmkRest
);
1702 HeapFree(GetProcessHeap(),0,newCompositeMoniker
);
1705 if (newCompositeMoniker
->tabLastIndex
==1)
1707 hr
= IMoniker_QueryInterface(newCompositeMoniker
->tabMoniker
[0],&IID_IMoniker
,(void**)ppmkComposite
);
1710 hr
= CompositeMonikerImpl_QueryInterface((IMoniker
*)newCompositeMoniker
,&IID_IMoniker
,(void**)ppmkComposite
);
1715 /******************************************************************************
1716 * MonikerCommonPrefixWith [OLE32.82]
1717 ******************************************************************************/
1718 HRESULT WINAPI
MonikerCommonPrefixWith(IMoniker
* pmkThis
,IMoniker
* pmkOther
,IMoniker
** ppmkCommon
)
1720 FIXME("(),stub!\n");