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
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
28 #include "wine/debug.h"
29 #include "wine/unicode.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
35 const CLSID CLSID_CompositeMoniker
= {
36 0x309, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
39 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
41 /* CompositeMoniker data structure */
42 typedef struct CompositeMonikerImpl
{
44 ICOM_VTABLE(IMoniker
)* lpvtbl1
; /* VTable relative to the IMoniker interface.*/
46 /* The ROT (RunningObjectTable implementation) uses the IROTData
47 * interface to test whether two monikers are equal. That's why IROTData
48 * interface is implemented by monikers.
50 ICOM_VTABLE(IROTData
)* lpvtbl2
; /* VTable relative to the IROTData interface.*/
52 ULONG ref
; /* reference counter for this object */
54 IMoniker
** tabMoniker
; /* dynamaic table containing all components (monikers) of this composite moniker */
56 ULONG tabSize
; /* size of tabMoniker */
58 ULONG tabLastIndex
; /* first free index in tabMoniker */
60 } CompositeMonikerImpl
;
63 /* EnumMoniker data structure */
64 typedef struct EnumMonikerImpl
{
66 ICOM_VFIELD(IEnumMoniker
); /* VTable relative to the IEnumMoniker interface.*/
68 ULONG ref
; /* reference counter for this object */
70 IMoniker
** tabMoniker
; /* dynamic table containing the enumerated monikers */
72 ULONG tabSize
; /* size of tabMoniker */
74 ULONG currentPos
; /* index pointer on the current moniker */
79 /********************************************************************************/
80 /* CompositeMoniker prototype functions : */
82 /* IUnknown prototype functions */
83 static HRESULT WINAPI
CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
);
84 static ULONG WINAPI
CompositeMonikerImpl_AddRef(IMoniker
* iface
);
85 static ULONG WINAPI
CompositeMonikerImpl_Release(IMoniker
* iface
);
87 /* IPersist prototype functions */
88 static HRESULT WINAPI
CompositeMonikerImpl_GetClassID(IMoniker
* iface
, CLSID
*pClassID
);
90 /* IPersistStream prototype functions */
91 static HRESULT WINAPI
CompositeMonikerImpl_IsDirty(IMoniker
* iface
);
92 static HRESULT WINAPI
CompositeMonikerImpl_Load(IMoniker
* iface
, IStream
* pStm
);
93 static HRESULT WINAPI
CompositeMonikerImpl_Save(IMoniker
* iface
, IStream
* pStm
, BOOL fClearDirty
);
94 static HRESULT WINAPI
CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
, ULARGE_INTEGER
* pcbSize
);
96 /* IMoniker prototype functions */
97 static HRESULT WINAPI
CompositeMonikerImpl_BindToObject(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
);
98 static HRESULT WINAPI
CompositeMonikerImpl_BindToStorage(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
);
99 static HRESULT WINAPI
CompositeMonikerImpl_Reduce(IMoniker
* iface
,IBindCtx
* pbc
, DWORD dwReduceHowFar
,IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
);
100 static HRESULT WINAPI
CompositeMonikerImpl_ComposeWith(IMoniker
* iface
,IMoniker
* pmkRight
,BOOL fOnlyIfNotGeneric
, IMoniker
** ppmkComposite
);
101 static HRESULT WINAPI
CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
);
102 static HRESULT WINAPI
CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
);
103 static HRESULT WINAPI
CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
);
104 static HRESULT WINAPI
CompositeMonikerImpl_IsRunning(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, IMoniker
* pmkNewlyRunning
);
105 static HRESULT WINAPI
CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
, FILETIME
* pCompositeTime
);
106 static HRESULT WINAPI
CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
);
107 static HRESULT WINAPI
CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
, IMoniker
** ppmkPrefix
);
108 static HRESULT WINAPI
CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmOther
, IMoniker
** ppmkRelPath
);
109 static HRESULT WINAPI
CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
);
110 static HRESULT WINAPI
CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
* pchEaten
, IMoniker
** ppmkOut
);
111 static HRESULT WINAPI
CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
);
113 /********************************************************************************/
114 /* IROTData prototype functions */
116 /* IUnknown prototype functions */
117 static HRESULT WINAPI
CompositeMonikerROTDataImpl_QueryInterface(IROTData
* iface
,REFIID riid
,VOID
** ppvObject
);
118 static ULONG WINAPI
CompositeMonikerROTDataImpl_AddRef(IROTData
* iface
);
119 static ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
);
121 /* IROTData prototype function */
122 static HRESULT WINAPI
CompositeMonikerROTDataImpl_GetComparaisonData(IROTData
* iface
,BYTE
* pbData
,ULONG cbMax
,ULONG
* pcbData
);
124 /* Local function used by CompositeMoniker implementation */
125 HRESULT WINAPI
CompositeMonikerImpl_Construct(CompositeMonikerImpl
* This
,LPMONIKER pmkFirst
, LPMONIKER pmkRest
);
126 HRESULT WINAPI
CompositeMonikerImpl_Destroy(CompositeMonikerImpl
* iface
);
128 /********************************************************************************/
129 /* IEnumMoniker prototype functions */
131 /* IUnknown prototype functions */
132 static HRESULT WINAPI
EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
);
133 static ULONG WINAPI
EnumMonikerImpl_AddRef(IEnumMoniker
* iface
);
134 static ULONG WINAPI
EnumMonikerImpl_Release(IEnumMoniker
* iface
);
136 /* IEnumMoniker prototype functions */
137 static HRESULT WINAPI
EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
,IMoniker
** rgelt
,ULONG
* pceltFetched
);
138 static HRESULT WINAPI
EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
);
139 static HRESULT WINAPI
EnumMonikerImpl_Reset(IEnumMoniker
* iface
);
140 static HRESULT WINAPI
EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
);
142 HRESULT WINAPI
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,ULONG tabSize
,ULONG currentPos
,BOOL leftToRigth
,IEnumMoniker
** ppmk
);
144 /********************************************************************************/
145 /* Virtual function table for the CompositeMonikerImpl class which includes */
146 /* IPersist, IPersistStream and IMoniker functions. */
148 static ICOM_VTABLE(IMoniker
) VT_CompositeMonikerImpl
=
150 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
151 CompositeMonikerImpl_QueryInterface
,
152 CompositeMonikerImpl_AddRef
,
153 CompositeMonikerImpl_Release
,
154 CompositeMonikerImpl_GetClassID
,
155 CompositeMonikerImpl_IsDirty
,
156 CompositeMonikerImpl_Load
,
157 CompositeMonikerImpl_Save
,
158 CompositeMonikerImpl_GetSizeMax
,
159 CompositeMonikerImpl_BindToObject
,
160 CompositeMonikerImpl_BindToStorage
,
161 CompositeMonikerImpl_Reduce
,
162 CompositeMonikerImpl_ComposeWith
,
163 CompositeMonikerImpl_Enum
,
164 CompositeMonikerImpl_IsEqual
,
165 CompositeMonikerImpl_Hash
,
166 CompositeMonikerImpl_IsRunning
,
167 CompositeMonikerImpl_GetTimeOfLastChange
,
168 CompositeMonikerImpl_Inverse
,
169 CompositeMonikerImpl_CommonPrefixWith
,
170 CompositeMonikerImpl_RelativePathTo
,
171 CompositeMonikerImpl_GetDisplayName
,
172 CompositeMonikerImpl_ParseDisplayName
,
173 CompositeMonikerImpl_IsSystemMoniker
176 /********************************************************************************/
177 /* Virtual function table for the IROTData class. */
178 static ICOM_VTABLE(IROTData
) VT_ROTDataImpl
=
180 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
181 CompositeMonikerROTDataImpl_QueryInterface
,
182 CompositeMonikerROTDataImpl_AddRef
,
183 CompositeMonikerROTDataImpl_Release
,
184 CompositeMonikerROTDataImpl_GetComparaisonData
187 /********************************************************************************/
188 /* Virtual function table for the IROTData class */
189 static ICOM_VTABLE(IEnumMoniker
) VT_EnumMonikerImpl
=
191 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
192 EnumMonikerImpl_QueryInterface
,
193 EnumMonikerImpl_AddRef
,
194 EnumMonikerImpl_Release
,
195 EnumMonikerImpl_Next
,
196 EnumMonikerImpl_Skip
,
197 EnumMonikerImpl_Reset
,
198 EnumMonikerImpl_Clone
201 /*******************************************************************************
202 * CompositeMoniker_QueryInterface
203 *******************************************************************************/
204 HRESULT WINAPI
CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
206 ICOM_THIS(CompositeMonikerImpl
,iface
);
208 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
210 /* Perform a sanity check on the parameters.*/
211 if ( (This
==0) || (ppvObject
==0) )
214 /* Initialize the return parameter */
217 /* Compare the riid with the interface IDs implemented by this object.*/
218 if (IsEqualIID(&IID_IUnknown
, riid
) ||
219 IsEqualIID(&IID_IPersist
, riid
) ||
220 IsEqualIID(&IID_IPersistStream
, riid
) ||
221 IsEqualIID(&IID_IMoniker
, riid
)
224 else if (IsEqualIID(&IID_IROTData
, riid
))
225 *ppvObject
= (IROTData
*)&(This
->lpvtbl2
);
227 /* Check that we obtained an interface.*/
229 return E_NOINTERFACE
;
231 /* Query Interface always increases the reference count by one when it is successful */
232 CompositeMonikerImpl_AddRef(iface
);
237 /******************************************************************************
238 * CompositeMoniker_AddRef
239 ******************************************************************************/
240 ULONG WINAPI
CompositeMonikerImpl_AddRef(IMoniker
* iface
)
242 ICOM_THIS(CompositeMonikerImpl
,iface
);
244 TRACE("(%p)\n",This
);
246 return ++(This
->ref
);
249 /******************************************************************************
250 * CompositeMoniker_Release
251 ******************************************************************************/
252 ULONG WINAPI
CompositeMonikerImpl_Release(IMoniker
* iface
)
254 ICOM_THIS(CompositeMonikerImpl
,iface
);
257 TRACE("(%p)\n",This
);
261 /* destroy the object if there's no more reference on it */
264 /* release all the components before destroying this object */
265 for (i
=0;i
<This
->tabLastIndex
;i
++)
266 IMoniker_Release(This
->tabMoniker
[i
]);
268 CompositeMonikerImpl_Destroy(This
);
275 /******************************************************************************
276 * CompositeMoniker_GetClassID
277 ******************************************************************************/
278 HRESULT WINAPI
CompositeMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
280 TRACE("(%p,%p),stub!\n",iface
,pClassID
);
285 *pClassID
= CLSID_CompositeMoniker
;
290 /******************************************************************************
291 * CompositeMoniker_IsDirty
292 ******************************************************************************/
293 HRESULT WINAPI
CompositeMonikerImpl_IsDirty(IMoniker
* iface
)
295 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
296 method in the OLE-provided moniker interfaces always return S_FALSE because
297 their internal state never changes. */
299 TRACE("(%p)\n",iface
);
304 /******************************************************************************
305 * CompositeMoniker_Load
306 ******************************************************************************/
307 HRESULT WINAPI
CompositeMonikerImpl_Load(IMoniker
* iface
,IStream
* pStm
)
314 ICOM_THIS(CompositeMonikerImpl
,iface
);
316 TRACE("(%p,%p)\n",iface
,pStm
);
318 /* this function call OleLoadFromStream function for each moniker within this object */
320 /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
321 res
=IStream_Read(pStm
,&constant
,sizeof(DWORD
),NULL
);
323 if (SUCCEEDED(res
)&& constant
!=3)
328 res
=OleLoadFromStream(pStm
,&IID_IMoniker
,(void**)&This
->tabMoniker
[This
->tabLastIndex
]);
330 res
=ReadClassStm(pStm
,&clsid
);
331 DPRINTF("res=%ld",res
);
335 if (IsEqualIID(&clsid
,&CLSID_FileMoniker
)){
336 res
=CreateFileMoniker(string
,&This
->tabMoniker
[This
->tabLastIndex
]);
339 res
=IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
343 else if (IsEqualIID(&clsid
,&CLSID_ItemMoniker
)){
344 CreateItemMoniker(string
,string
,&This
->tabMoniker
[This
->tabLastIndex
]);
347 IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
351 else if (IsEqualIID(&clsid
,&CLSID_AntiMoniker
)){
352 CreateAntiMoniker(&This
->tabMoniker
[This
->tabLastIndex
]);
355 IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
359 else if (IsEqualIID(&clsid
,&CLSID_CompositeMoniker
))
365 /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */
370 /* resize the table if needed */
371 if (++This
->tabLastIndex
==This
->tabSize
){
373 This
->tabSize
+=BLOCK_TAB_SIZE
;
374 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
376 if (This
->tabMoniker
==NULL
)
377 return E_OUTOFMEMORY
;
384 /******************************************************************************
385 * CompositeMoniker_Save
386 ******************************************************************************/
387 HRESULT WINAPI
CompositeMonikerImpl_Save(IMoniker
* iface
,IStream
* pStm
,BOOL fClearDirty
)
390 IEnumMoniker
*enumMk
;
394 TRACE("(%p,%p,%d)\n",iface
,pStm
,fClearDirty
);
396 /* This function calls OleSaveToStream function for each moniker within
398 * When I tested this function in windows, I usually found this constant
399 * at the beginning of the stream. I don't known why (there's no
400 * indication in the specification) !
402 res
=IStream_Write(pStm
,&constant
,sizeof(constant
),NULL
);
404 IMoniker_Enum(iface
,TRUE
,&enumMk
);
406 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
408 res
=OleSaveToStream((IPersistStream
*)pmk
,pStm
);
410 IMoniker_Release(pmk
);
414 IEnumMoniker_Release(pmk
);
419 IEnumMoniker_Release(enumMk
);
424 /******************************************************************************
425 * CompositeMoniker_GetSizeMax
426 ******************************************************************************/
427 HRESULT WINAPI
CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
,ULARGE_INTEGER
* pcbSize
)
429 IEnumMoniker
*enumMk
;
431 ULARGE_INTEGER ptmpSize
;
433 /* The sizeMax of this object is calculated by calling GetSizeMax on
434 * each moniker within this object then summing all returned values
437 TRACE("(%p,%p)\n",iface
,pcbSize
);
442 pcbSize
->s
.LowPart
=0;
443 pcbSize
->s
.HighPart
=0;
445 IMoniker_Enum(iface
,TRUE
,&enumMk
);
447 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==TRUE
){
449 IMoniker_GetSizeMax(pmk
,&ptmpSize
);
451 IMoniker_Release(pmk
);
453 pcbSize
->s
.LowPart
+=ptmpSize
.s
.LowPart
;
454 pcbSize
->s
.HighPart
+=ptmpSize
.s
.HighPart
;
457 IEnumMoniker_Release(enumMk
);
462 /******************************************************************************
463 * Composite-Moniker_Construct (local function)
464 *******************************************************************************/
465 HRESULT WINAPI
CompositeMonikerImpl_Construct(CompositeMonikerImpl
* This
,LPMONIKER pmkFirst
, LPMONIKER pmkRest
)
468 IEnumMoniker
*enumMoniker
;
472 TRACE("(%p,%p,%p)\n",This
,pmkFirst
,pmkRest
);
474 /* Initialize the virtual function table. */
475 This
->lpvtbl1
= &VT_CompositeMonikerImpl
;
476 This
->lpvtbl2
= &VT_ROTDataImpl
;
479 This
->tabSize
=BLOCK_TAB_SIZE
;
480 This
->tabLastIndex
=0;
482 This
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,This
->tabSize
*sizeof(IMoniker
));
483 if (This
->tabMoniker
==NULL
)
484 return E_OUTOFMEMORY
;
486 IMoniker_IsSystemMoniker(pmkFirst
,&mkSys
);
488 /* put the first moniker contents in the beginning of the table */
489 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
491 This
->tabMoniker
[(This
->tabLastIndex
)++]=pmkFirst
;
492 IMoniker_AddRef(pmkFirst
);
496 IMoniker_Enum(pmkFirst
,TRUE
,&enumMoniker
);
498 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
501 if (++This
->tabLastIndex
==This
->tabSize
){
503 This
->tabSize
+=BLOCK_TAB_SIZE
;
504 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
506 if (This
->tabMoniker
==NULL
)
507 return E_OUTOFMEMORY
;
511 IEnumMoniker_Release(enumMoniker
);
514 /* put the rest moniker contents after the first one and make simplification if needed */
516 IMoniker_IsSystemMoniker(pmkRest
,&mkSys
);
518 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
520 /* add a simple moniker to the moniker table */
522 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],pmkRest
,TRUE
,&tempMk
);
524 if (res
==MK_E_NEEDGENERIC
){
526 /* there's no simplification in this case */
527 This
->tabMoniker
[This
->tabLastIndex
]=pmkRest
;
529 This
->tabLastIndex
++;
531 IMoniker_AddRef(pmkRest
);
533 else if (tempMk
==NULL
){
535 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
536 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
538 This
->tabLastIndex
--;
540 else if (SUCCEEDED(res
)){
542 /* the non-generic composition was successful so we can make a simplification in this case */
543 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
545 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
549 /* resize tabMoniker if needed */
550 if (This
->tabLastIndex
==This
->tabSize
){
552 This
->tabSize
+=BLOCK_TAB_SIZE
;
554 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
556 if (This
->tabMoniker
==NULL
)
557 return E_OUTOFMEMORY
;
562 /* add a composite moniker to the moniker table (do the same thing
563 * for each moniker within the composite moniker as a simple moniker
564 * (see above for how to add a simple moniker case) )
566 IMoniker_Enum(pmkRest
,TRUE
,&enumMoniker
);
568 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
570 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],This
->tabMoniker
[This
->tabLastIndex
],TRUE
,&tempMk
);
572 if (res
==MK_E_NEEDGENERIC
){
574 This
->tabLastIndex
++;
576 else if (tempMk
==NULL
){
578 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
579 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
]);
580 This
->tabLastIndex
--;
584 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
586 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
589 if (This
->tabLastIndex
==This
->tabSize
){
591 This
->tabSize
+=BLOCK_TAB_SIZE
;
593 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
595 if (This
->tabMoniker
==NULL
)
596 return E_OUTOFMEMORY
;
600 IEnumMoniker_Release(enumMoniker
);
606 /******************************************************************************
607 * CompositeMoniker_Destroy (local function)
608 *******************************************************************************/
609 HRESULT WINAPI
CompositeMonikerImpl_Destroy(CompositeMonikerImpl
* This
)
611 TRACE("(%p)\n",This
);
613 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
615 HeapFree(GetProcessHeap(),0,This
);
620 /******************************************************************************
621 * CompositeMoniker_BindToObject
622 ******************************************************************************/
623 HRESULT WINAPI
CompositeMonikerImpl_BindToObject(IMoniker
* iface
,
630 IRunningObjectTable
*prot
;
631 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
632 IEnumMoniker
*enumMoniker
;
634 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
640 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
641 /* object for the requested interface pointer. */
644 res
=IBindCtx_GetRunningObjectTable(pbc
,&prot
);
648 /* if the requested class was loaded befor ! we dont need to reload it */
649 res
= IRunningObjectTable_GetObject(prot
,iface
,(IUnknown
**)ppvResult
);
656 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
657 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
659 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
660 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
661 IEnumMoniker_Release(enumMoniker
);
663 res
=CreateAntiMoniker(&antiMk
);
664 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
665 IMoniker_Release(antiMk
);
667 res
=CompositeMonikerImpl_BindToObject(mostRigthMk
,pbc
,tempMk
,riid
,ppvResult
);
669 IMoniker_Release(tempMk
);
670 IMoniker_Release(mostRigthMk
);
676 /******************************************************************************
677 * CompositeMoniker_BindToStorage
678 ******************************************************************************/
679 HRESULT WINAPI
CompositeMonikerImpl_BindToStorage(IMoniker
* iface
,
686 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
687 IEnumMoniker
*enumMoniker
;
689 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
693 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
694 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
696 if (pmkToLeft
!=NULL
){
698 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
699 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
700 IEnumMoniker_Release(enumMoniker
);
702 res
=CreateAntiMoniker(&antiMk
);
703 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
704 IMoniker_Release(antiMk
);
706 res
=CompositeMonikerImpl_BindToStorage(mostRigthMk
,pbc
,tempMk
,riid
,ppvResult
);
708 IMoniker_Release(tempMk
);
710 IMoniker_Release(mostRigthMk
);
715 return IMoniker_BindToStorage(iface
,pbc
,NULL
,riid
,ppvResult
);
718 /******************************************************************************
719 * CompositeMoniker_Reduce
720 ******************************************************************************/
721 HRESULT WINAPI
CompositeMonikerImpl_Reduce(IMoniker
* iface
,
723 DWORD dwReduceHowFar
,
724 IMoniker
** ppmkToLeft
,
725 IMoniker
** ppmkReduced
)
728 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*leftReducedComposedMk
,*mostRigthReducedMk
;
729 IEnumMoniker
*enumMoniker
;
731 TRACE("(%p,%p,%ld,%p,%p)\n",iface
,pbc
,dwReduceHowFar
,ppmkToLeft
,ppmkReduced
);
733 if (ppmkReduced
==NULL
)
736 /* This method recursively calls Reduce for each of its component monikers. */
738 if (ppmkToLeft
==NULL
){
740 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
741 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
742 IEnumMoniker_Release(enumMoniker
);
744 res
=CreateAntiMoniker(&antiMk
);
745 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
746 IMoniker_Release(antiMk
);
748 return CompositeMonikerImpl_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
, ppmkReduced
);
750 else if (*ppmkToLeft
==NULL
)
752 return IMoniker_Reduce(iface
,pbc
,dwReduceHowFar
,NULL
,ppmkReduced
);
756 /* separate the composite moniker in to left and right moniker */
757 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
758 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
759 IEnumMoniker_Release(enumMoniker
);
761 res
=CreateAntiMoniker(&antiMk
);
762 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
763 IMoniker_Release(antiMk
);
765 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
766 /* of the reduced components */
767 if (IMoniker_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,NULL
,&mostRigthReducedMk
) &&
768 CompositeMonikerImpl_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
,&leftReducedComposedMk
)
771 return CreateGenericComposite(leftReducedComposedMk
,mostRigthReducedMk
,ppmkReduced
);
774 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
776 IMoniker_AddRef(iface
);
780 return MK_S_REDUCED_TO_SELF
;
785 /******************************************************************************
786 * CompositeMoniker_ComposeWith
787 ******************************************************************************/
788 HRESULT WINAPI
CompositeMonikerImpl_ComposeWith(IMoniker
* iface
,
790 BOOL fOnlyIfNotGeneric
,
791 IMoniker
** ppmkComposite
)
793 TRACE("(%p,%p,%d,%p)\n",iface
,pmkRight
,fOnlyIfNotGeneric
,ppmkComposite
);
795 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
800 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
801 /* otherwise, the method returns the result of combining the two monikers by calling the */
802 /* CreateGenericComposite function */
804 if (fOnlyIfNotGeneric
)
805 return MK_E_NEEDGENERIC
;
807 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
810 /******************************************************************************
811 * CompositeMoniker_Enum
812 ******************************************************************************/
813 HRESULT WINAPI
CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
815 ICOM_THIS(CompositeMonikerImpl
,iface
);
817 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
819 if (ppenumMoniker
== NULL
)
822 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabLastIndex
,0,fForward
,ppenumMoniker
);
825 /******************************************************************************
826 * CompositeMoniker_IsEqual
827 ******************************************************************************/
828 HRESULT WINAPI
CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
)
830 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
831 IMoniker
*tempMk1
,*tempMk2
;
832 HRESULT res1
,res2
,res
;
834 TRACE("(%p,%p)\n",iface
,pmkOtherMoniker
);
836 if (pmkOtherMoniker
==NULL
)
839 /* This method returns S_OK if the components of both monikers are equal when compared in the */
840 /* left-to-right order.*/
841 IMoniker_Enum(pmkOtherMoniker
,TRUE
,&enumMoniker1
);
843 if (enumMoniker1
==NULL
)
846 IMoniker_Enum(iface
,TRUE
,&enumMoniker2
);
850 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
851 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
853 if((res1
==S_OK
)&&(res2
==S_OK
)){
855 if(IMoniker_IsEqual(tempMk1
,tempMk2
)==S_FALSE
){
862 else if ( (res1
==S_FALSE
) && (res2
==S_FALSE
) ){
872 IMoniker_Release(tempMk1
);
875 IMoniker_Release(tempMk2
);
878 IEnumMoniker_Release(enumMoniker1
);
879 IEnumMoniker_Release(enumMoniker2
);
883 /******************************************************************************
884 * CompositeMoniker_Hash
885 ******************************************************************************/
886 HRESULT WINAPI
CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
893 /******************************************************************************
894 * CompositeMoniker_IsRunning
895 ******************************************************************************/
896 HRESULT WINAPI
CompositeMonikerImpl_IsRunning(IMoniker
* iface
,
899 IMoniker
* pmkNewlyRunning
)
901 IRunningObjectTable
* rot
;
903 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
904 IEnumMoniker
*enumMoniker
;
906 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
908 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
909 if (pmkToLeft
!=NULL
){
911 CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
913 res
= IMoniker_IsRunning(tempMk
,pbc
,NULL
,pmkNewlyRunning
);
915 IMoniker_Release(tempMk
);
920 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
921 /* to this moniker */
923 if (pmkNewlyRunning
!=NULL
)
925 if (IMoniker_IsEqual(iface
,pmkNewlyRunning
)==S_OK
)
936 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
937 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
938 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
939 /* the composite as the pmkToLeft parameter for that call. */
941 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
946 res
= IRunningObjectTable_IsRunning(rot
,iface
);
947 IRunningObjectTable_Release(rot
);
954 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
955 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
956 IEnumMoniker_Release(enumMoniker
);
958 res
=CreateAntiMoniker(&antiMk
);
959 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
960 IMoniker_Release(antiMk
);
962 res
=IMoniker_IsRunning(mostRigthMk
,pbc
,tempMk
,pmkNewlyRunning
);
964 IMoniker_Release(tempMk
);
965 IMoniker_Release(mostRigthMk
);
972 /******************************************************************************
973 * CompositeMoniker_GetTimeOfLastChange
974 ******************************************************************************/
975 HRESULT WINAPI
CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
,
978 FILETIME
* pCompositeTime
)
980 IRunningObjectTable
* rot
;
982 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
983 IEnumMoniker
*enumMoniker
;
985 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pCompositeTime
);
987 if (pCompositeTime
==NULL
)
990 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
991 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
992 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
993 /* of the composite as the pmkToLeft parameter for that call. */
994 if (pmkToLeft
!=NULL
){
996 res
=CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
998 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
1003 if (IRunningObjectTable_GetTimeOfLastChange(rot
,tempMk
,pCompositeTime
)==S_OK
)
1007 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1008 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1009 IEnumMoniker_Release(enumMoniker
);
1011 res
=CreateAntiMoniker(&antiMk
);
1012 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1013 IMoniker_Release(antiMk
);
1015 res
=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk
,pbc
,tempMk
,pCompositeTime
);
1017 IMoniker_Release(tempMk
);
1018 IMoniker_Release(mostRigthMk
);
1023 return IMoniker_GetTimeOfLastChange(iface
,pbc
,NULL
,pCompositeTime
);
1026 /******************************************************************************
1027 * CompositeMoniker_Inverse
1028 ******************************************************************************/
1029 HRESULT WINAPI
CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
1032 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*tempInvMk
,*mostRigthInvMk
;
1033 IEnumMoniker
*enumMoniker
;
1035 TRACE("(%p,%p)\n",iface
,ppmk
);
1040 /* This method returns a composite moniker that consists of the inverses of each of the components */
1041 /* of the original composite, stored in reverse order */
1043 res
=CreateAntiMoniker(&antiMk
);
1044 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1045 IMoniker_Release(antiMk
);
1049 return IMoniker_Inverse(iface
,ppmk
);
1053 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1054 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1055 IEnumMoniker_Release(enumMoniker
);
1057 IMoniker_Inverse(mostRigthMk
,&mostRigthInvMk
);
1058 CompositeMonikerImpl_Inverse(tempMk
,&tempInvMk
);
1060 res
=CreateGenericComposite(mostRigthInvMk
,tempInvMk
,ppmk
);
1062 IMoniker_Release(tempMk
);
1063 IMoniker_Release(mostRigthMk
);
1064 IMoniker_Release(tempInvMk
);
1065 IMoniker_Release(mostRigthInvMk
);
1071 /******************************************************************************
1072 * CompositeMoniker_CommonPrefixWith
1073 ******************************************************************************/
1074 HRESULT WINAPI
CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
,IMoniker
** ppmkPrefix
)
1078 IMoniker
*tempMk1
,*tempMk2
,*mostLeftMk1
,*mostLeftMk2
;
1079 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
1080 ULONG i
,nbCommonMk
=0;
1082 /* If the other moniker is a composite, this method compares the components of each composite from left */
1083 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1084 /* of the leftmost components were common to both monikers. */
1086 if (ppmkPrefix
==NULL
)
1092 return MK_E_NOPREFIX
;
1094 IMoniker_IsSystemMoniker(pmkOther
,&mkSys
);
1096 if((mkSys
==MKSYS_GENERICCOMPOSITE
)){
1098 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
1099 IMoniker_Enum(pmkOther
,TRUE
,&enumMoniker2
);
1103 res1
=IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
1104 res2
=IEnumMoniker_Next(enumMoniker2
,1,&mostLeftMk2
,NULL
);
1106 if ((res1
==S_FALSE
) && (res2
==S_FALSE
)){
1108 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1110 IMoniker_AddRef(iface
);
1113 else if ((res1
==S_OK
) && (res2
==S_OK
)){
1115 if (IMoniker_IsEqual(mostLeftMk1
,mostLeftMk2
)==S_OK
)
1123 else if (res1
==S_OK
){
1125 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1126 /* ppmkPrefix to the other moniker. */
1127 *ppmkPrefix
=pmkOther
;
1131 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1132 /* to this moniker. */
1138 IEnumMoniker_Release(enumMoniker1
);
1139 IEnumMoniker_Release(enumMoniker2
);
1141 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1143 return MK_E_NOPREFIX
;
1145 IEnumMoniker_Reset(enumMoniker1
);
1147 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1149 /* if we have more than one commun moniker the result will be a composite moniker */
1152 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1153 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1154 CreateGenericComposite(tempMk1
,tempMk2
,ppmkPrefix
);
1155 IMoniker_Release(tempMk1
);
1156 IMoniker_Release(tempMk2
);
1158 /* compose all common monikers in a composite moniker */
1159 for(i
=0;i
<nbCommonMk
;i
++){
1161 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1163 CreateGenericComposite(*ppmkPrefix
,tempMk1
,&tempMk2
);
1165 IMoniker_Release(*ppmkPrefix
);
1167 IMoniker_Release(tempMk1
);
1169 *ppmkPrefix
=tempMk2
;
1174 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1175 *ppmkPrefix
=tempMk1
;
1181 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1184 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
1186 IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
1188 if (IMoniker_IsEqual(pmkOther
,mostLeftMk1
)==S_OK
){
1190 *ppmkPrefix
=pmkOther
;
1195 return MK_E_NOPREFIX
;
1198 /***************************************************************************************************
1199 * GetAfterCommonPrefix (local function)
1200 * This function returns a moniker that consist of the remainder when the common prefix is removed
1201 ***************************************************************************************************/
1202 VOID WINAPI
GetAfterCommonPrefix(IMoniker
* pGenMk
,IMoniker
* commonMk
,IMoniker
** restMk
)
1204 IMoniker
*tempMk
,*tempMk1
,*tempMk2
;
1205 IEnumMoniker
*enumMoniker1
,*enumMoniker2
,*enumMoniker3
;
1212 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1213 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
1214 /* on the first difference. */
1215 IMoniker_Enum(pGenMk
,TRUE
,&enumMoniker1
);
1217 IMoniker_IsSystemMoniker(commonMk
,&mkSys
);
1219 if (mkSys
==MKSYS_GENERICCOMPOSITE
){
1221 IMoniker_Enum(commonMk
,TRUE
,&enumMoniker2
);
1224 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1225 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
1227 if ((res1
==S_FALSE
)||(res2
==S_FALSE
)){
1233 IMoniker_Release(tempMk1
);
1234 IMoniker_Release(tempMk1
);
1238 IMoniker_Release(tempMk1
);
1239 IMoniker_Release(tempMk1
);
1243 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1244 IMoniker_Release(tempMk1
);
1247 /* count the number of elements in the enumerator after the common prefix */
1248 IEnumMoniker_Clone(enumMoniker1
,&enumMoniker3
);
1250 for(;IEnumMoniker_Next(enumMoniker3
,1,&tempMk
,NULL
)==S_OK
;nbRestMk
++)
1252 IMoniker_Release(tempMk
);
1257 /* create a generic composite moniker with monikers located after the common prefix */
1258 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1267 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1269 CreateGenericComposite(tempMk1
,tempMk2
,restMk
);
1271 IMoniker_Release(tempMk1
);
1273 IMoniker_Release(tempMk2
);
1275 while(IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
)==S_OK
){
1277 CreateGenericComposite(*restMk
,tempMk1
,&tempMk2
);
1279 IMoniker_Release(tempMk1
);
1281 IMoniker_Release(*restMk
);
1287 /******************************************************************************
1288 * CompositeMoniker_RelativePathTo
1289 ******************************************************************************/
1290 HRESULT WINAPI
CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmkOther
, IMoniker
** ppmkRelPath
)
1293 IMoniker
*restOtherMk
=0,*restThisMk
=0,*invRestThisMk
=0,*commonMk
=0;
1295 TRACE("(%p,%p,%p)\n",iface
,pmkOther
,ppmkRelPath
);
1297 if (ppmkRelPath
==NULL
)
1302 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1303 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1304 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1306 /* finds the common prefix of the two monikers */
1307 res
=IMoniker_CommonPrefixWith(iface
,pmkOther
,&commonMk
);
1309 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1310 if ((res
== MK_E_NOPREFIX
)||(res
==MK_S_US
)){
1312 *ppmkRelPath
=pmkOther
;
1313 IMoniker_AddRef(pmkOther
);
1317 GetAfterCommonPrefix(iface
,commonMk
,&restThisMk
);
1318 GetAfterCommonPrefix(pmkOther
,commonMk
,&restOtherMk
);
1320 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1321 /* moniker when the common prefix is removed */
1324 IMoniker_Inverse(restThisMk
,ppmkRelPath
);
1325 IMoniker_Release(restThisMk
);
1327 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1328 /* when the common prefix is removed */
1329 else if (res
==MK_S_ME
){
1331 *ppmkRelPath
=restOtherMk
;
1332 IMoniker_AddRef(restOtherMk
);
1334 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1335 /* moniker on the right of it. */
1336 else if (res
==S_OK
){
1338 IMoniker_Inverse(restThisMk
,&invRestThisMk
);
1339 IMoniker_Release(restThisMk
);
1340 CreateGenericComposite(invRestThisMk
,restOtherMk
,ppmkRelPath
);
1341 IMoniker_Release(invRestThisMk
);
1342 IMoniker_Release(restOtherMk
);
1347 /******************************************************************************
1348 * CompositeMoniker_GetDisplayName
1349 ******************************************************************************/
1350 HRESULT WINAPI
CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
,
1352 IMoniker
* pmkToLeft
,
1353 LPOLESTR
*ppszDisplayName
)
1356 IEnumMoniker
*enumMoniker
;
1360 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
1362 if (ppszDisplayName
==NULL
)
1365 *ppszDisplayName
=CoTaskMemAlloc(sizeof(WCHAR
));
1367 if (*ppszDisplayName
==NULL
)
1368 return E_OUTOFMEMORY
;
1370 /* This method returns the concatenation of the display names returned by each component moniker of */
1373 **ppszDisplayName
=0;
1375 IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
1377 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
1379 IMoniker_GetDisplayName(tempMk
,pbc
,NULL
,&tempStr
);
1381 lengthStr
+=lstrlenW(tempStr
);
1383 *ppszDisplayName
=CoTaskMemRealloc(*ppszDisplayName
,lengthStr
* sizeof(WCHAR
));
1385 if (*ppszDisplayName
==NULL
)
1386 return E_OUTOFMEMORY
;
1388 strcatW(*ppszDisplayName
,tempStr
);
1390 CoTaskMemFree(tempStr
);
1391 IMoniker_Release(tempMk
);
1394 IEnumMoniker_Release(enumMoniker
);
1399 /******************************************************************************
1400 * CompositeMoniker_ParseDisplayName
1401 ******************************************************************************/
1402 HRESULT WINAPI
CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
,
1404 IMoniker
* pmkToLeft
,
1405 LPOLESTR pszDisplayName
,
1409 IEnumMoniker
*enumMoniker
;
1410 IMoniker
*tempMk
,*mostRigthMk
,*antiMk
;
1411 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1412 /* passing everything else as the pmkToLeft parameter for that call. */
1414 /* get the most right moniker */
1415 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1416 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1417 IEnumMoniker_Release(enumMoniker
);
1419 /* get the left moniker */
1420 CreateAntiMoniker(&antiMk
);
1421 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1422 IMoniker_Release(antiMk
);
1424 return IMoniker_ParseDisplayName(mostRigthMk
,pbc
,tempMk
,pszDisplayName
,pchEaten
,ppmkOut
);
1427 /******************************************************************************
1428 * CompositeMoniker_IsSystemMoniker
1429 ******************************************************************************/
1430 HRESULT WINAPI
CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
1432 TRACE("(%p,%p)\n",iface
,pwdMksys
);
1437 (*pwdMksys
)=MKSYS_GENERICCOMPOSITE
;
1442 /*******************************************************************************
1443 * CompositeMonikerIROTData_QueryInterface
1444 *******************************************************************************/
1445 HRESULT WINAPI
CompositeMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,VOID
** ppvObject
)
1448 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1450 TRACE("(%p,%p,%p)\n",iface
,riid
,ppvObject
);
1452 return CompositeMonikerImpl_QueryInterface(This
, riid
, ppvObject
);
1455 /***********************************************************************
1456 * CompositeMonikerIROTData_AddRef
1458 ULONG WINAPI
CompositeMonikerROTDataImpl_AddRef(IROTData
*iface
)
1460 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1462 TRACE("(%p)\n",iface
);
1464 return CompositeMonikerImpl_AddRef(This
);
1467 /***********************************************************************
1468 * CompositeMonikerIROTData_Release
1470 ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
)
1472 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1474 TRACE("(%p)\n",iface
);
1476 return CompositeMonikerImpl_Release(This
);
1479 /******************************************************************************
1480 * CompositeMonikerIROTData_GetComparaisonData
1481 ******************************************************************************/
1482 HRESULT WINAPI
CompositeMonikerROTDataImpl_GetComparaisonData(IROTData
* iface
,
1487 FIXME("(),stub!\n");
1491 /******************************************************************************
1492 * EnumMonikerImpl_QueryInterface
1493 ******************************************************************************/
1494 HRESULT WINAPI
EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
)
1496 ICOM_THIS(EnumMonikerImpl
,iface
);
1498 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
1500 /* Perform a sanity check on the parameters.*/
1501 if ( (This
==0) || (ppvObject
==0) )
1502 return E_INVALIDARG
;
1504 /* Initialize the return parameter */
1507 /* Compare the riid with the interface IDs implemented by this object.*/
1508 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IEnumMoniker
, riid
))
1511 /* Check that we obtained an interface.*/
1512 if ((*ppvObject
)==0)
1513 return E_NOINTERFACE
;
1515 /* Query Interface always increases the reference count by one when it is successful */
1516 EnumMonikerImpl_AddRef(iface
);
1521 /******************************************************************************
1522 * EnumMonikerImpl_AddRef
1523 ******************************************************************************/
1524 ULONG WINAPI
EnumMonikerImpl_AddRef(IEnumMoniker
* iface
)
1526 ICOM_THIS(EnumMonikerImpl
,iface
);
1528 TRACE("(%p)\n",This
);
1530 return ++(This
->ref
);
1534 /******************************************************************************
1535 * EnumMonikerImpl_Release
1536 ******************************************************************************/
1537 ULONG WINAPI
EnumMonikerImpl_Release(IEnumMoniker
* iface
)
1539 ICOM_THIS(EnumMonikerImpl
,iface
);
1542 TRACE("(%p)\n",This
);
1546 /* destroy the object if there's no more reference on it */
1549 for(i
=0;i
<This
->tabSize
;i
++)
1550 IMoniker_Release(This
->tabMoniker
[i
]);
1552 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
1553 HeapFree(GetProcessHeap(),0,This
);
1560 /******************************************************************************
1561 * EnumMonikerImpl_Next
1562 ******************************************************************************/
1563 HRESULT WINAPI
EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
, IMoniker
** rgelt
, ULONG
* pceltFethed
){
1565 ICOM_THIS(EnumMonikerImpl
,iface
);
1568 /* retrieve the requested number of moniker from the current position */
1569 for(i
=0;((This
->currentPos
< This
->tabSize
) && (i
< celt
));i
++)
1571 rgelt
[i
]=This
->tabMoniker
[This
->currentPos
++];
1573 if (pceltFethed
!=NULL
)
1582 /******************************************************************************
1583 * EnumMonikerImpl_Skip
1584 ******************************************************************************/
1585 HRESULT WINAPI
EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
){
1587 ICOM_THIS(EnumMonikerImpl
,iface
);
1589 if ((This
->currentPos
+celt
) >= This
->tabSize
)
1592 This
->currentPos
+=celt
;
1597 /******************************************************************************
1598 * EnumMonikerImpl_Reset
1599 ******************************************************************************/
1600 HRESULT WINAPI
EnumMonikerImpl_Reset(IEnumMoniker
* iface
){
1602 ICOM_THIS(EnumMonikerImpl
,iface
);
1609 /******************************************************************************
1610 * EnumMonikerImpl_Clone
1611 ******************************************************************************/
1612 HRESULT WINAPI
EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
){
1614 ICOM_THIS(EnumMonikerImpl
,iface
);
1616 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabSize
,This
->currentPos
,TRUE
,ppenum
);
1619 /******************************************************************************
1620 * EnumMonikerImpl_CreateEnumMoniker
1621 ******************************************************************************/
1622 HRESULT WINAPI
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,
1626 IEnumMoniker
** ppmk
)
1628 EnumMonikerImpl
* newEnumMoniker
;
1632 newEnumMoniker
= HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl
));
1634 if (newEnumMoniker
== 0)
1635 return STG_E_INSUFFICIENTMEMORY
;
1637 if (currentPos
> tabSize
)
1638 return E_INVALIDARG
;
1640 /* Initialize the virtual function table. */
1641 newEnumMoniker
->lpVtbl
= &VT_EnumMonikerImpl
;
1642 newEnumMoniker
->ref
= 0;
1644 newEnumMoniker
->tabSize
=tabSize
;
1645 newEnumMoniker
->currentPos
=currentPos
;
1647 newEnumMoniker
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,tabSize
*sizeof(IMoniker
));
1649 if (newEnumMoniker
->tabMoniker
==NULL
)
1650 return E_OUTOFMEMORY
;
1653 for (i
=0;i
<tabSize
;i
++){
1655 newEnumMoniker
->tabMoniker
[i
]=tabMoniker
[i
];
1656 IMoniker_AddRef(tabMoniker
[i
]);
1659 for (i
=tabSize
-1;i
>=0;i
--){
1661 newEnumMoniker
->tabMoniker
[tabSize
-i
-1]=tabMoniker
[i
];
1662 IMoniker_AddRef(tabMoniker
[i
]);
1665 *ppmk
=(IEnumMoniker
*)newEnumMoniker
;
1670 /******************************************************************************
1671 * CreateGenericComposite [OLE32.56]
1672 ******************************************************************************/
1673 HRESULT WINAPI
CreateGenericComposite(LPMONIKER pmkFirst
, LPMONIKER pmkRest
, LPMONIKER
* ppmkComposite
)
1675 CompositeMonikerImpl
* newCompositeMoniker
= 0;
1678 TRACE("(%p,%p,%p)\n",pmkFirst
,pmkRest
,ppmkComposite
);
1680 if (ppmkComposite
==NULL
)
1685 if (pmkFirst
==NULL
&& pmkRest
!=NULL
){
1687 *ppmkComposite
=pmkRest
;
1690 else if (pmkFirst
!=NULL
&& pmkRest
==NULL
){
1691 *ppmkComposite
=pmkFirst
;
1694 else if (pmkFirst
==NULL
&& pmkRest
==NULL
)
1697 newCompositeMoniker
= HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl
));
1699 if (newCompositeMoniker
== 0)
1700 return STG_E_INSUFFICIENTMEMORY
;
1702 hr
= CompositeMonikerImpl_Construct(newCompositeMoniker
,pmkFirst
,pmkRest
);
1706 HeapFree(GetProcessHeap(),0,newCompositeMoniker
);
1709 if (newCompositeMoniker
->tabLastIndex
==1)
1711 hr
= IMoniker_QueryInterface(newCompositeMoniker
->tabMoniker
[0],&IID_IMoniker
,(void**)ppmkComposite
);
1714 hr
= CompositeMonikerImpl_QueryInterface((IMoniker
*)newCompositeMoniker
,&IID_IMoniker
,(void**)ppmkComposite
);
1719 /******************************************************************************
1720 * MonikerCommonPrefixWith [OLE32.82]
1721 ******************************************************************************/
1722 HRESULT WINAPI
MonikerCommonPrefixWith(IMoniker
* pmkThis
,IMoniker
* pmkOther
,IMoniker
** ppmkCommon
)
1724 FIXME("(),stub!\n");