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
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
33 #include "wine/debug.h"
34 #include "wine/unicode.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
40 const CLSID CLSID_CompositeMoniker
= {
41 0x309, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
44 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
46 /* CompositeMoniker data structure */
47 typedef struct CompositeMonikerImpl
{
49 IMonikerVtbl
* lpvtbl1
; /* VTable relative to the IMoniker interface.*/
51 /* The ROT (RunningObjectTable implementation) uses the IROTData
52 * interface to test whether two monikers are equal. That's why IROTData
53 * interface is implemented by monikers.
55 IROTDataVtbl
* lpvtbl2
; /* VTable relative to the IROTData interface.*/
57 ULONG ref
; /* reference counter for this object */
59 IMoniker
** tabMoniker
; /* dynamaic table containing all components (monikers) of this composite moniker */
61 ULONG tabSize
; /* size of tabMoniker */
63 ULONG tabLastIndex
; /* first free index in tabMoniker */
65 } CompositeMonikerImpl
;
68 /* EnumMoniker data structure */
69 typedef struct EnumMonikerImpl
{
71 IEnumMonikerVtbl
*lpVtbl
; /* VTable relative to the IEnumMoniker interface.*/
73 ULONG ref
; /* reference counter for this object */
75 IMoniker
** tabMoniker
; /* dynamic table containing the enumerated monikers */
77 ULONG tabSize
; /* size of tabMoniker */
79 ULONG currentPos
; /* index pointer on the current moniker */
84 /********************************************************************************/
85 /* CompositeMoniker prototype functions : */
87 /* IUnknown prototype functions */
88 static HRESULT WINAPI
CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
);
89 static ULONG WINAPI
CompositeMonikerImpl_AddRef(IMoniker
* iface
);
90 static ULONG WINAPI
CompositeMonikerImpl_Release(IMoniker
* iface
);
92 /* IPersist prototype functions */
93 static HRESULT WINAPI
CompositeMonikerImpl_GetClassID(IMoniker
* iface
, CLSID
*pClassID
);
95 /* IPersistStream prototype functions */
96 static HRESULT WINAPI
CompositeMonikerImpl_IsDirty(IMoniker
* iface
);
97 static HRESULT WINAPI
CompositeMonikerImpl_Load(IMoniker
* iface
, IStream
* pStm
);
98 static HRESULT WINAPI
CompositeMonikerImpl_Save(IMoniker
* iface
, IStream
* pStm
, BOOL fClearDirty
);
99 static HRESULT WINAPI
CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
, ULARGE_INTEGER
* pcbSize
);
101 /* IMoniker prototype functions */
102 static HRESULT WINAPI
CompositeMonikerImpl_BindToObject(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
);
103 static HRESULT WINAPI
CompositeMonikerImpl_BindToStorage(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, REFIID riid
, VOID
** ppvResult
);
104 static HRESULT WINAPI
CompositeMonikerImpl_Reduce(IMoniker
* iface
,IBindCtx
* pbc
, DWORD dwReduceHowFar
,IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
);
105 static HRESULT WINAPI
CompositeMonikerImpl_ComposeWith(IMoniker
* iface
,IMoniker
* pmkRight
,BOOL fOnlyIfNotGeneric
, IMoniker
** ppmkComposite
);
106 static HRESULT WINAPI
CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
);
107 static HRESULT WINAPI
CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
);
108 static HRESULT WINAPI
CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
);
109 static HRESULT WINAPI
CompositeMonikerImpl_IsRunning(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, IMoniker
* pmkNewlyRunning
);
110 static HRESULT WINAPI
CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
, FILETIME
* pCompositeTime
);
111 static HRESULT WINAPI
CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
);
112 static HRESULT WINAPI
CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
, IMoniker
** ppmkPrefix
);
113 static HRESULT WINAPI
CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmOther
, IMoniker
** ppmkRelPath
);
114 static HRESULT WINAPI
CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
);
115 static HRESULT WINAPI
CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
,IBindCtx
* pbc
, IMoniker
* pmkToLeft
, LPOLESTR pszDisplayName
, ULONG
* pchEaten
, IMoniker
** ppmkOut
);
116 static HRESULT WINAPI
CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
);
118 /********************************************************************************/
119 /* IROTData prototype functions */
121 /* IUnknown prototype functions */
122 static HRESULT WINAPI
CompositeMonikerROTDataImpl_QueryInterface(IROTData
* iface
,REFIID riid
,VOID
** ppvObject
);
123 static ULONG WINAPI
CompositeMonikerROTDataImpl_AddRef(IROTData
* iface
);
124 static ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
);
126 /* IROTData prototype function */
127 static HRESULT WINAPI
CompositeMonikerROTDataImpl_GetComparaisonData(IROTData
* iface
,BYTE
* pbData
,ULONG cbMax
,ULONG
* pcbData
);
129 /* Local function used by CompositeMoniker implementation */
130 HRESULT WINAPI
CompositeMonikerImpl_Construct(CompositeMonikerImpl
* This
,LPMONIKER pmkFirst
, LPMONIKER pmkRest
);
131 HRESULT WINAPI
CompositeMonikerImpl_Destroy(CompositeMonikerImpl
* iface
);
133 /********************************************************************************/
134 /* IEnumMoniker prototype functions */
136 /* IUnknown prototype functions */
137 static HRESULT WINAPI
EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
);
138 static ULONG WINAPI
EnumMonikerImpl_AddRef(IEnumMoniker
* iface
);
139 static ULONG WINAPI
EnumMonikerImpl_Release(IEnumMoniker
* iface
);
141 /* IEnumMoniker prototype functions */
142 static HRESULT WINAPI
EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
,IMoniker
** rgelt
,ULONG
* pceltFetched
);
143 static HRESULT WINAPI
EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
);
144 static HRESULT WINAPI
EnumMonikerImpl_Reset(IEnumMoniker
* iface
);
145 static HRESULT WINAPI
EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
);
147 HRESULT WINAPI
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,ULONG tabSize
,ULONG currentPos
,BOOL leftToRigth
,IEnumMoniker
** ppmk
);
149 /********************************************************************************/
150 /* Virtual function table for the CompositeMonikerImpl class which includes */
151 /* IPersist, IPersistStream and IMoniker functions. */
153 static IMonikerVtbl VT_CompositeMonikerImpl
=
155 CompositeMonikerImpl_QueryInterface
,
156 CompositeMonikerImpl_AddRef
,
157 CompositeMonikerImpl_Release
,
158 CompositeMonikerImpl_GetClassID
,
159 CompositeMonikerImpl_IsDirty
,
160 CompositeMonikerImpl_Load
,
161 CompositeMonikerImpl_Save
,
162 CompositeMonikerImpl_GetSizeMax
,
163 CompositeMonikerImpl_BindToObject
,
164 CompositeMonikerImpl_BindToStorage
,
165 CompositeMonikerImpl_Reduce
,
166 CompositeMonikerImpl_ComposeWith
,
167 CompositeMonikerImpl_Enum
,
168 CompositeMonikerImpl_IsEqual
,
169 CompositeMonikerImpl_Hash
,
170 CompositeMonikerImpl_IsRunning
,
171 CompositeMonikerImpl_GetTimeOfLastChange
,
172 CompositeMonikerImpl_Inverse
,
173 CompositeMonikerImpl_CommonPrefixWith
,
174 CompositeMonikerImpl_RelativePathTo
,
175 CompositeMonikerImpl_GetDisplayName
,
176 CompositeMonikerImpl_ParseDisplayName
,
177 CompositeMonikerImpl_IsSystemMoniker
180 /********************************************************************************/
181 /* Virtual function table for the IROTData class. */
182 static IROTDataVtbl VT_ROTDataImpl
=
184 CompositeMonikerROTDataImpl_QueryInterface
,
185 CompositeMonikerROTDataImpl_AddRef
,
186 CompositeMonikerROTDataImpl_Release
,
187 CompositeMonikerROTDataImpl_GetComparaisonData
190 /********************************************************************************/
191 /* Virtual function table for the IROTData class */
192 static IEnumMonikerVtbl VT_EnumMonikerImpl
=
194 EnumMonikerImpl_QueryInterface
,
195 EnumMonikerImpl_AddRef
,
196 EnumMonikerImpl_Release
,
197 EnumMonikerImpl_Next
,
198 EnumMonikerImpl_Skip
,
199 EnumMonikerImpl_Reset
,
200 EnumMonikerImpl_Clone
203 /*******************************************************************************
204 * CompositeMoniker_QueryInterface
205 *******************************************************************************/
206 HRESULT WINAPI
CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
208 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
210 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
212 /* Perform a sanity check on the parameters.*/
213 if ( (This
==0) || (ppvObject
==0) )
216 /* Initialize the return parameter */
219 /* Compare the riid with the interface IDs implemented by this object.*/
220 if (IsEqualIID(&IID_IUnknown
, riid
) ||
221 IsEqualIID(&IID_IPersist
, riid
) ||
222 IsEqualIID(&IID_IPersistStream
, riid
) ||
223 IsEqualIID(&IID_IMoniker
, riid
)
226 else if (IsEqualIID(&IID_IROTData
, riid
))
227 *ppvObject
= (IROTData
*)&(This
->lpvtbl2
);
229 /* Check that we obtained an interface.*/
231 return E_NOINTERFACE
;
233 /* Query Interface always increases the reference count by one when it is successful */
234 CompositeMonikerImpl_AddRef(iface
);
239 /******************************************************************************
240 * CompositeMoniker_AddRef
241 ******************************************************************************/
242 ULONG WINAPI
CompositeMonikerImpl_AddRef(IMoniker
* iface
)
244 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
246 TRACE("(%p)\n",This
);
248 return InterlockedIncrement(&This
->ref
);
251 /******************************************************************************
252 * CompositeMoniker_Release
253 ******************************************************************************/
254 ULONG WINAPI
CompositeMonikerImpl_Release(IMoniker
* iface
)
256 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
260 TRACE("(%p)\n",This
);
262 ref
= InterlockedDecrement(&This
->ref
);
264 /* destroy the object if there's no more reference on it */
267 /* release all the components before destroying this object */
268 for (i
=0;i
<This
->tabLastIndex
;i
++)
269 IMoniker_Release(This
->tabMoniker
[i
]);
271 CompositeMonikerImpl_Destroy(This
);
276 /******************************************************************************
277 * CompositeMoniker_GetClassID
278 ******************************************************************************/
279 HRESULT WINAPI
CompositeMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
281 TRACE("(%p,%p),stub!\n",iface
,pClassID
);
286 *pClassID
= CLSID_CompositeMoniker
;
291 /******************************************************************************
292 * CompositeMoniker_IsDirty
293 ******************************************************************************/
294 HRESULT WINAPI
CompositeMonikerImpl_IsDirty(IMoniker
* iface
)
296 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
297 method in the OLE-provided moniker interfaces always return S_FALSE because
298 their internal state never changes. */
300 TRACE("(%p)\n",iface
);
305 /******************************************************************************
306 * CompositeMoniker_Load
307 ******************************************************************************/
308 HRESULT WINAPI
CompositeMonikerImpl_Load(IMoniker
* iface
,IStream
* pStm
)
315 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
317 TRACE("(%p,%p)\n",iface
,pStm
);
319 /* this function call OleLoadFromStream function for each moniker within this object */
321 /* read the a constant written by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
322 res
=IStream_Read(pStm
,&constant
,sizeof(DWORD
),NULL
);
324 if (SUCCEEDED(res
)&& constant
!=3)
329 res
=OleLoadFromStream(pStm
,&IID_IMoniker
,(void**)&This
->tabMoniker
[This
->tabLastIndex
]);
331 res
=ReadClassStm(pStm
,&clsid
);
332 DPRINTF("res=%ld",res
);
336 if (IsEqualIID(&clsid
,&CLSID_FileMoniker
)){
337 res
=CreateFileMoniker(string
,&This
->tabMoniker
[This
->tabLastIndex
]);
340 res
=IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
344 else if (IsEqualIID(&clsid
,&CLSID_ItemMoniker
)){
345 CreateItemMoniker(string
,string
,&This
->tabMoniker
[This
->tabLastIndex
]);
348 IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
352 else if (IsEqualIID(&clsid
,&CLSID_AntiMoniker
)){
353 CreateAntiMoniker(&This
->tabMoniker
[This
->tabLastIndex
]);
356 IMoniker_Load(This
->tabMoniker
[This
->tabLastIndex
],pStm
);
360 else if (IsEqualIID(&clsid
,&CLSID_CompositeMoniker
))
366 /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */
371 /* resize the table if needed */
372 if (++This
->tabLastIndex
==This
->tabSize
){
374 This
->tabSize
+=BLOCK_TAB_SIZE
;
375 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
377 if (This
->tabMoniker
==NULL
)
378 return E_OUTOFMEMORY
;
385 /******************************************************************************
386 * CompositeMoniker_Save
387 ******************************************************************************/
388 HRESULT WINAPI
CompositeMonikerImpl_Save(IMoniker
* iface
,IStream
* pStm
,BOOL fClearDirty
)
391 IEnumMoniker
*enumMk
;
395 TRACE("(%p,%p,%d)\n",iface
,pStm
,fClearDirty
);
397 /* This function calls OleSaveToStream function for each moniker within
399 * When I tested this function in windows, I usually found this constant
400 * at the beginning of the stream. I don't known why (there's no
401 * indication in the specification) !
403 res
=IStream_Write(pStm
,&constant
,sizeof(constant
),NULL
);
405 IMoniker_Enum(iface
,TRUE
,&enumMk
);
407 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
409 res
=OleSaveToStream((IPersistStream
*)pmk
,pStm
);
411 IMoniker_Release(pmk
);
415 IEnumMoniker_Release(pmk
);
420 IEnumMoniker_Release(enumMk
);
425 /******************************************************************************
426 * CompositeMoniker_GetSizeMax
427 ******************************************************************************/
428 HRESULT WINAPI
CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
,ULARGE_INTEGER
* pcbSize
)
430 IEnumMoniker
*enumMk
;
432 ULARGE_INTEGER ptmpSize
;
434 /* The sizeMax of this object is calculated by calling GetSizeMax on
435 * each moniker within this object then summing all returned values
438 TRACE("(%p,%p)\n",iface
,pcbSize
);
443 pcbSize
->u
.LowPart
=0;
444 pcbSize
->u
.HighPart
=0;
446 IMoniker_Enum(iface
,TRUE
,&enumMk
);
448 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)){
450 IMoniker_GetSizeMax(pmk
,&ptmpSize
);
452 IMoniker_Release(pmk
);
454 pcbSize
->u
.LowPart
+=ptmpSize
.u
.LowPart
;
455 pcbSize
->u
.HighPart
+=ptmpSize
.u
.HighPart
;
458 IEnumMoniker_Release(enumMk
);
463 /******************************************************************************
464 * Composite-Moniker_Construct (local function)
465 *******************************************************************************/
466 HRESULT WINAPI
CompositeMonikerImpl_Construct(CompositeMonikerImpl
* This
,LPMONIKER pmkFirst
, LPMONIKER pmkRest
)
469 IEnumMoniker
*enumMoniker
;
473 TRACE("(%p,%p,%p)\n",This
,pmkFirst
,pmkRest
);
475 /* Initialize the virtual function table. */
476 This
->lpvtbl1
= &VT_CompositeMonikerImpl
;
477 This
->lpvtbl2
= &VT_ROTDataImpl
;
480 This
->tabSize
=BLOCK_TAB_SIZE
;
481 This
->tabLastIndex
=0;
483 This
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,This
->tabSize
*sizeof(IMoniker
));
484 if (This
->tabMoniker
==NULL
)
485 return E_OUTOFMEMORY
;
487 IMoniker_IsSystemMoniker(pmkFirst
,&mkSys
);
489 /* put the first moniker contents in the beginning of the table */
490 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
492 This
->tabMoniker
[(This
->tabLastIndex
)++]=pmkFirst
;
493 IMoniker_AddRef(pmkFirst
);
497 IMoniker_Enum(pmkFirst
,TRUE
,&enumMoniker
);
499 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
502 if (++This
->tabLastIndex
==This
->tabSize
){
504 This
->tabSize
+=BLOCK_TAB_SIZE
;
505 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
507 if (This
->tabMoniker
==NULL
)
508 return E_OUTOFMEMORY
;
512 IEnumMoniker_Release(enumMoniker
);
515 /* put the rest moniker contents after the first one and make simplification if needed */
517 IMoniker_IsSystemMoniker(pmkRest
,&mkSys
);
519 if (mkSys
!=MKSYS_GENERICCOMPOSITE
){
521 /* add a simple moniker to the moniker table */
523 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],pmkRest
,TRUE
,&tempMk
);
525 if (res
==MK_E_NEEDGENERIC
){
527 /* there's no simplification in this case */
528 This
->tabMoniker
[This
->tabLastIndex
]=pmkRest
;
530 This
->tabLastIndex
++;
532 IMoniker_AddRef(pmkRest
);
534 else if (tempMk
==NULL
){
536 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
537 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
539 This
->tabLastIndex
--;
541 else if (SUCCEEDED(res
)){
543 /* the non-generic composition was successful so we can make a simplification in this case */
544 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
546 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
550 /* resize tabMoniker if needed */
551 if (This
->tabLastIndex
==This
->tabSize
){
553 This
->tabSize
+=BLOCK_TAB_SIZE
;
555 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
557 if (This
->tabMoniker
==NULL
)
558 return E_OUTOFMEMORY
;
563 /* add a composite moniker to the moniker table (do the same thing
564 * for each moniker within the composite moniker as a simple moniker
565 * (see above for how to add a simple moniker case) )
567 IMoniker_Enum(pmkRest
,TRUE
,&enumMoniker
);
569 while(IEnumMoniker_Next(enumMoniker
,1,&This
->tabMoniker
[This
->tabLastIndex
],NULL
)==S_OK
){
571 res
=IMoniker_ComposeWith(This
->tabMoniker
[This
->tabLastIndex
-1],This
->tabMoniker
[This
->tabLastIndex
],TRUE
,&tempMk
);
573 if (res
==MK_E_NEEDGENERIC
){
575 This
->tabLastIndex
++;
577 else if (tempMk
==NULL
){
579 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
580 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
]);
581 This
->tabLastIndex
--;
585 IMoniker_Release(This
->tabMoniker
[This
->tabLastIndex
-1]);
587 This
->tabMoniker
[This
->tabLastIndex
-1]=tempMk
;
590 if (This
->tabLastIndex
==This
->tabSize
){
592 This
->tabSize
+=BLOCK_TAB_SIZE
;
594 This
->tabMoniker
=HeapReAlloc(GetProcessHeap(),0,This
->tabMoniker
,This
->tabSize
*sizeof(IMoniker
));
596 if (This
->tabMoniker
==NULL
)
597 return E_OUTOFMEMORY
;
601 IEnumMoniker_Release(enumMoniker
);
607 /******************************************************************************
608 * CompositeMoniker_Destroy (local function)
609 *******************************************************************************/
610 HRESULT WINAPI
CompositeMonikerImpl_Destroy(CompositeMonikerImpl
* This
)
612 TRACE("(%p)\n",This
);
614 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
616 HeapFree(GetProcessHeap(),0,This
);
621 /******************************************************************************
622 * CompositeMoniker_BindToObject
623 ******************************************************************************/
624 HRESULT WINAPI
CompositeMonikerImpl_BindToObject(IMoniker
* iface
,
631 IRunningObjectTable
*prot
;
632 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
633 IEnumMoniker
*enumMoniker
;
635 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
641 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
642 /* object for the requested interface pointer. */
645 res
=IBindCtx_GetRunningObjectTable(pbc
,&prot
);
649 /* if the requested class was loaded before ! we don't need to reload it */
650 res
= IRunningObjectTable_GetObject(prot
,iface
,(IUnknown
**)ppvResult
);
657 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
658 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
660 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
661 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
662 IEnumMoniker_Release(enumMoniker
);
664 res
=CreateAntiMoniker(&antiMk
);
665 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
666 IMoniker_Release(antiMk
);
668 res
=CompositeMonikerImpl_BindToObject(mostRigthMk
,pbc
,tempMk
,riid
,ppvResult
);
670 IMoniker_Release(tempMk
);
671 IMoniker_Release(mostRigthMk
);
677 /******************************************************************************
678 * CompositeMoniker_BindToStorage
679 ******************************************************************************/
680 HRESULT WINAPI
CompositeMonikerImpl_BindToStorage(IMoniker
* iface
,
687 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
688 IEnumMoniker
*enumMoniker
;
690 TRACE("(%p,%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,riid
,ppvResult
);
694 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
695 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
697 if (pmkToLeft
!=NULL
){
699 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
700 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
701 IEnumMoniker_Release(enumMoniker
);
703 res
=CreateAntiMoniker(&antiMk
);
704 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
705 IMoniker_Release(antiMk
);
707 res
=CompositeMonikerImpl_BindToStorage(mostRigthMk
,pbc
,tempMk
,riid
,ppvResult
);
709 IMoniker_Release(tempMk
);
711 IMoniker_Release(mostRigthMk
);
716 return IMoniker_BindToStorage(iface
,pbc
,NULL
,riid
,ppvResult
);
719 /******************************************************************************
720 * CompositeMoniker_Reduce
721 ******************************************************************************/
722 HRESULT WINAPI
CompositeMonikerImpl_Reduce(IMoniker
* iface
,
724 DWORD dwReduceHowFar
,
725 IMoniker
** ppmkToLeft
,
726 IMoniker
** ppmkReduced
)
729 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*leftReducedComposedMk
,*mostRigthReducedMk
;
730 IEnumMoniker
*enumMoniker
;
732 TRACE("(%p,%p,%ld,%p,%p)\n",iface
,pbc
,dwReduceHowFar
,ppmkToLeft
,ppmkReduced
);
734 if (ppmkReduced
==NULL
)
737 /* This method recursively calls Reduce for each of its component monikers. */
739 if (ppmkToLeft
==NULL
){
741 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
742 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
743 IEnumMoniker_Release(enumMoniker
);
745 res
=CreateAntiMoniker(&antiMk
);
746 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
747 IMoniker_Release(antiMk
);
749 return CompositeMonikerImpl_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
, ppmkReduced
);
751 else if (*ppmkToLeft
==NULL
)
753 return IMoniker_Reduce(iface
,pbc
,dwReduceHowFar
,NULL
,ppmkReduced
);
757 /* separate the composite moniker in to left and right moniker */
758 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
759 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
760 IEnumMoniker_Release(enumMoniker
);
762 res
=CreateAntiMoniker(&antiMk
);
763 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
764 IMoniker_Release(antiMk
);
766 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
767 /* of the reduced components */
768 if (IMoniker_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,NULL
,&mostRigthReducedMk
) &&
769 CompositeMonikerImpl_Reduce(mostRigthMk
,pbc
,dwReduceHowFar
,&tempMk
,&leftReducedComposedMk
)
772 return CreateGenericComposite(leftReducedComposedMk
,mostRigthReducedMk
,ppmkReduced
);
775 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
777 IMoniker_AddRef(iface
);
781 return MK_S_REDUCED_TO_SELF
;
786 /******************************************************************************
787 * CompositeMoniker_ComposeWith
788 ******************************************************************************/
789 HRESULT WINAPI
CompositeMonikerImpl_ComposeWith(IMoniker
* iface
,
791 BOOL fOnlyIfNotGeneric
,
792 IMoniker
** ppmkComposite
)
794 TRACE("(%p,%p,%d,%p)\n",iface
,pmkRight
,fOnlyIfNotGeneric
,ppmkComposite
);
796 if ((ppmkComposite
==NULL
)||(pmkRight
==NULL
))
801 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
802 /* otherwise, the method returns the result of combining the two monikers by calling the */
803 /* CreateGenericComposite function */
805 if (fOnlyIfNotGeneric
)
806 return MK_E_NEEDGENERIC
;
808 return CreateGenericComposite(iface
,pmkRight
,ppmkComposite
);
811 /******************************************************************************
812 * CompositeMoniker_Enum
813 ******************************************************************************/
814 HRESULT WINAPI
CompositeMonikerImpl_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
816 CompositeMonikerImpl
*This
= (CompositeMonikerImpl
*)iface
;
818 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
820 if (ppenumMoniker
== NULL
)
823 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabLastIndex
,0,fForward
,ppenumMoniker
);
826 /******************************************************************************
827 * CompositeMoniker_IsEqual
828 ******************************************************************************/
829 HRESULT WINAPI
CompositeMonikerImpl_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
)
831 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
832 IMoniker
*tempMk1
,*tempMk2
;
833 HRESULT res1
,res2
,res
;
835 TRACE("(%p,%p)\n",iface
,pmkOtherMoniker
);
837 if (pmkOtherMoniker
==NULL
)
840 /* This method returns S_OK if the components of both monikers are equal when compared in the */
841 /* left-to-right order.*/
842 IMoniker_Enum(pmkOtherMoniker
,TRUE
,&enumMoniker1
);
844 if (enumMoniker1
==NULL
)
847 IMoniker_Enum(iface
,TRUE
,&enumMoniker2
);
851 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
852 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
854 if((res1
==S_OK
)&&(res2
==S_OK
)){
856 if(IMoniker_IsEqual(tempMk1
,tempMk2
)==S_FALSE
){
863 else if ( (res1
==S_FALSE
) && (res2
==S_FALSE
) ){
873 IMoniker_Release(tempMk1
);
876 IMoniker_Release(tempMk2
);
879 IEnumMoniker_Release(enumMoniker1
);
880 IEnumMoniker_Release(enumMoniker2
);
884 /******************************************************************************
885 * CompositeMoniker_Hash
886 ******************************************************************************/
887 HRESULT WINAPI
CompositeMonikerImpl_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
894 /******************************************************************************
895 * CompositeMoniker_IsRunning
896 ******************************************************************************/
897 HRESULT WINAPI
CompositeMonikerImpl_IsRunning(IMoniker
* iface
,
900 IMoniker
* pmkNewlyRunning
)
902 IRunningObjectTable
* rot
;
904 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
905 IEnumMoniker
*enumMoniker
;
907 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pmkNewlyRunning
);
909 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
910 if (pmkToLeft
!=NULL
){
912 CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
914 res
= IMoniker_IsRunning(tempMk
,pbc
,NULL
,pmkNewlyRunning
);
916 IMoniker_Release(tempMk
);
921 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
922 /* to this moniker */
924 if (pmkNewlyRunning
!=NULL
)
926 if (IMoniker_IsEqual(iface
,pmkNewlyRunning
)==S_OK
)
937 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
938 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
939 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
940 /* the composite as the pmkToLeft parameter for that call. */
942 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
947 res
= IRunningObjectTable_IsRunning(rot
,iface
);
948 IRunningObjectTable_Release(rot
);
955 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
956 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
957 IEnumMoniker_Release(enumMoniker
);
959 res
=CreateAntiMoniker(&antiMk
);
960 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
961 IMoniker_Release(antiMk
);
963 res
=IMoniker_IsRunning(mostRigthMk
,pbc
,tempMk
,pmkNewlyRunning
);
965 IMoniker_Release(tempMk
);
966 IMoniker_Release(mostRigthMk
);
973 /******************************************************************************
974 * CompositeMoniker_GetTimeOfLastChange
975 ******************************************************************************/
976 HRESULT WINAPI
CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
* iface
,
979 FILETIME
* pCompositeTime
)
981 IRunningObjectTable
* rot
;
983 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
;
984 IEnumMoniker
*enumMoniker
;
986 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,pCompositeTime
);
988 if (pCompositeTime
==NULL
)
991 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
992 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
993 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
994 /* of the composite as the pmkToLeft parameter for that call. */
995 if (pmkToLeft
!=NULL
){
997 res
=CreateGenericComposite(pmkToLeft
,iface
,&tempMk
);
999 res
=IBindCtx_GetRunningObjectTable(pbc
,&rot
);
1004 if (IRunningObjectTable_GetTimeOfLastChange(rot
,tempMk
,pCompositeTime
)==S_OK
)
1008 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1009 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1010 IEnumMoniker_Release(enumMoniker
);
1012 res
=CreateAntiMoniker(&antiMk
);
1013 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1014 IMoniker_Release(antiMk
);
1016 res
=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk
,pbc
,tempMk
,pCompositeTime
);
1018 IMoniker_Release(tempMk
);
1019 IMoniker_Release(mostRigthMk
);
1024 return IMoniker_GetTimeOfLastChange(iface
,pbc
,NULL
,pCompositeTime
);
1027 /******************************************************************************
1028 * CompositeMoniker_Inverse
1029 ******************************************************************************/
1030 HRESULT WINAPI
CompositeMonikerImpl_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
1033 IMoniker
*tempMk
,*antiMk
,*mostRigthMk
,*tempInvMk
,*mostRigthInvMk
;
1034 IEnumMoniker
*enumMoniker
;
1036 TRACE("(%p,%p)\n",iface
,ppmk
);
1041 /* This method returns a composite moniker that consists of the inverses of each of the components */
1042 /* of the original composite, stored in reverse order */
1044 res
=CreateAntiMoniker(&antiMk
);
1045 res
=IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1046 IMoniker_Release(antiMk
);
1050 return IMoniker_Inverse(iface
,ppmk
);
1054 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1055 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1056 IEnumMoniker_Release(enumMoniker
);
1058 IMoniker_Inverse(mostRigthMk
,&mostRigthInvMk
);
1059 CompositeMonikerImpl_Inverse(tempMk
,&tempInvMk
);
1061 res
=CreateGenericComposite(mostRigthInvMk
,tempInvMk
,ppmk
);
1063 IMoniker_Release(tempMk
);
1064 IMoniker_Release(mostRigthMk
);
1065 IMoniker_Release(tempInvMk
);
1066 IMoniker_Release(mostRigthInvMk
);
1072 /******************************************************************************
1073 * CompositeMoniker_CommonPrefixWith
1074 ******************************************************************************/
1075 HRESULT WINAPI
CompositeMonikerImpl_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
,IMoniker
** ppmkPrefix
)
1079 IMoniker
*tempMk1
,*tempMk2
,*mostLeftMk1
,*mostLeftMk2
;
1080 IEnumMoniker
*enumMoniker1
,*enumMoniker2
;
1081 ULONG i
,nbCommonMk
=0;
1083 /* If the other moniker is a composite, this method compares the components of each composite from left */
1084 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1085 /* of the leftmost components were common to both monikers. */
1087 if (ppmkPrefix
==NULL
)
1093 return MK_E_NOPREFIX
;
1095 IMoniker_IsSystemMoniker(pmkOther
,&mkSys
);
1097 if((mkSys
==MKSYS_GENERICCOMPOSITE
)){
1099 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
1100 IMoniker_Enum(pmkOther
,TRUE
,&enumMoniker2
);
1104 res1
=IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
1105 res2
=IEnumMoniker_Next(enumMoniker2
,1,&mostLeftMk2
,NULL
);
1107 if ((res1
==S_FALSE
) && (res2
==S_FALSE
)){
1109 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1111 IMoniker_AddRef(iface
);
1114 else if ((res1
==S_OK
) && (res2
==S_OK
)){
1116 if (IMoniker_IsEqual(mostLeftMk1
,mostLeftMk2
)==S_OK
)
1124 else if (res1
==S_OK
){
1126 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1127 /* ppmkPrefix to the other moniker. */
1128 *ppmkPrefix
=pmkOther
;
1132 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1133 /* to this moniker. */
1139 IEnumMoniker_Release(enumMoniker1
);
1140 IEnumMoniker_Release(enumMoniker2
);
1142 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1144 return MK_E_NOPREFIX
;
1146 IEnumMoniker_Reset(enumMoniker1
);
1148 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1150 /* if we have more than one commun moniker the result will be a composite moniker */
1153 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1154 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1155 CreateGenericComposite(tempMk1
,tempMk2
,ppmkPrefix
);
1156 IMoniker_Release(tempMk1
);
1157 IMoniker_Release(tempMk2
);
1159 /* compose all common monikers in a composite moniker */
1160 for(i
=0;i
<nbCommonMk
;i
++){
1162 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1164 CreateGenericComposite(*ppmkPrefix
,tempMk1
,&tempMk2
);
1166 IMoniker_Release(*ppmkPrefix
);
1168 IMoniker_Release(tempMk1
);
1170 *ppmkPrefix
=tempMk2
;
1175 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1176 *ppmkPrefix
=tempMk1
;
1182 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1185 IMoniker_Enum(iface
,TRUE
,&enumMoniker1
);
1187 IEnumMoniker_Next(enumMoniker1
,1,&mostLeftMk1
,NULL
);
1189 if (IMoniker_IsEqual(pmkOther
,mostLeftMk1
)==S_OK
){
1191 *ppmkPrefix
=pmkOther
;
1196 return MK_E_NOPREFIX
;
1199 /***************************************************************************************************
1200 * GetAfterCommonPrefix (local function)
1201 * This function returns a moniker that consist of the remainder when the common prefix is removed
1202 ***************************************************************************************************/
1203 VOID WINAPI
GetAfterCommonPrefix(IMoniker
* pGenMk
,IMoniker
* commonMk
,IMoniker
** restMk
)
1205 IMoniker
*tempMk
,*tempMk1
,*tempMk2
;
1206 IEnumMoniker
*enumMoniker1
,*enumMoniker2
,*enumMoniker3
;
1213 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1214 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
1215 /* on the first difference. */
1216 IMoniker_Enum(pGenMk
,TRUE
,&enumMoniker1
);
1218 IMoniker_IsSystemMoniker(commonMk
,&mkSys
);
1220 if (mkSys
==MKSYS_GENERICCOMPOSITE
){
1222 IMoniker_Enum(commonMk
,TRUE
,&enumMoniker2
);
1225 res1
=IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1226 res2
=IEnumMoniker_Next(enumMoniker2
,1,&tempMk2
,NULL
);
1228 if ((res1
==S_FALSE
)||(res2
==S_FALSE
)){
1234 IMoniker_Release(tempMk1
);
1235 IMoniker_Release(tempMk1
);
1239 IMoniker_Release(tempMk1
);
1240 IMoniker_Release(tempMk1
);
1244 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1245 IMoniker_Release(tempMk1
);
1248 /* count the number of elements in the enumerator after the common prefix */
1249 IEnumMoniker_Clone(enumMoniker1
,&enumMoniker3
);
1251 for(;IEnumMoniker_Next(enumMoniker3
,1,&tempMk
,NULL
)==S_OK
;nbRestMk
++)
1253 IMoniker_Release(tempMk
);
1258 /* create a generic composite moniker with monikers located after the common prefix */
1259 IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
);
1268 IEnumMoniker_Next(enumMoniker1
,1,&tempMk2
,NULL
);
1270 CreateGenericComposite(tempMk1
,tempMk2
,restMk
);
1272 IMoniker_Release(tempMk1
);
1274 IMoniker_Release(tempMk2
);
1276 while(IEnumMoniker_Next(enumMoniker1
,1,&tempMk1
,NULL
)==S_OK
){
1278 CreateGenericComposite(*restMk
,tempMk1
,&tempMk2
);
1280 IMoniker_Release(tempMk1
);
1282 IMoniker_Release(*restMk
);
1288 /******************************************************************************
1289 * CompositeMoniker_RelativePathTo
1290 ******************************************************************************/
1291 HRESULT WINAPI
CompositeMonikerImpl_RelativePathTo(IMoniker
* iface
,IMoniker
* pmkOther
, IMoniker
** ppmkRelPath
)
1294 IMoniker
*restOtherMk
=0,*restThisMk
=0,*invRestThisMk
=0,*commonMk
=0;
1296 TRACE("(%p,%p,%p)\n",iface
,pmkOther
,ppmkRelPath
);
1298 if (ppmkRelPath
==NULL
)
1303 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1304 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1305 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1307 /* finds the common prefix of the two monikers */
1308 res
=IMoniker_CommonPrefixWith(iface
,pmkOther
,&commonMk
);
1310 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1311 if ((res
== MK_E_NOPREFIX
)||(res
==MK_S_US
)){
1313 *ppmkRelPath
=pmkOther
;
1314 IMoniker_AddRef(pmkOther
);
1318 GetAfterCommonPrefix(iface
,commonMk
,&restThisMk
);
1319 GetAfterCommonPrefix(pmkOther
,commonMk
,&restOtherMk
);
1321 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1322 /* moniker when the common prefix is removed */
1325 IMoniker_Inverse(restThisMk
,ppmkRelPath
);
1326 IMoniker_Release(restThisMk
);
1328 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1329 /* when the common prefix is removed */
1330 else if (res
==MK_S_ME
){
1332 *ppmkRelPath
=restOtherMk
;
1333 IMoniker_AddRef(restOtherMk
);
1335 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1336 /* moniker on the right of it. */
1337 else if (res
==S_OK
){
1339 IMoniker_Inverse(restThisMk
,&invRestThisMk
);
1340 IMoniker_Release(restThisMk
);
1341 CreateGenericComposite(invRestThisMk
,restOtherMk
,ppmkRelPath
);
1342 IMoniker_Release(invRestThisMk
);
1343 IMoniker_Release(restOtherMk
);
1348 /******************************************************************************
1349 * CompositeMoniker_GetDisplayName
1350 ******************************************************************************/
1351 HRESULT WINAPI
CompositeMonikerImpl_GetDisplayName(IMoniker
* iface
,
1353 IMoniker
* pmkToLeft
,
1354 LPOLESTR
*ppszDisplayName
)
1357 IEnumMoniker
*enumMoniker
;
1361 TRACE("(%p,%p,%p,%p)\n",iface
,pbc
,pmkToLeft
,ppszDisplayName
);
1363 if (ppszDisplayName
==NULL
)
1366 *ppszDisplayName
=CoTaskMemAlloc(sizeof(WCHAR
));
1368 if (*ppszDisplayName
==NULL
)
1369 return E_OUTOFMEMORY
;
1371 /* This method returns the concatenation of the display names returned by each component moniker of */
1374 **ppszDisplayName
=0;
1376 IMoniker_Enum(iface
,TRUE
,&enumMoniker
);
1378 while(IEnumMoniker_Next(enumMoniker
,1,&tempMk
,NULL
)==S_OK
){
1380 IMoniker_GetDisplayName(tempMk
,pbc
,NULL
,&tempStr
);
1382 lengthStr
+=lstrlenW(tempStr
);
1384 *ppszDisplayName
=CoTaskMemRealloc(*ppszDisplayName
,lengthStr
* sizeof(WCHAR
));
1386 if (*ppszDisplayName
==NULL
)
1387 return E_OUTOFMEMORY
;
1389 strcatW(*ppszDisplayName
,tempStr
);
1391 CoTaskMemFree(tempStr
);
1392 IMoniker_Release(tempMk
);
1395 IEnumMoniker_Release(enumMoniker
);
1400 /******************************************************************************
1401 * CompositeMoniker_ParseDisplayName
1402 ******************************************************************************/
1403 HRESULT WINAPI
CompositeMonikerImpl_ParseDisplayName(IMoniker
* iface
,
1405 IMoniker
* pmkToLeft
,
1406 LPOLESTR pszDisplayName
,
1410 IEnumMoniker
*enumMoniker
;
1411 IMoniker
*tempMk
,*mostRigthMk
,*antiMk
;
1412 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1413 /* passing everything else as the pmkToLeft parameter for that call. */
1415 /* get the most right moniker */
1416 IMoniker_Enum(iface
,FALSE
,&enumMoniker
);
1417 IEnumMoniker_Next(enumMoniker
,1,&mostRigthMk
,NULL
);
1418 IEnumMoniker_Release(enumMoniker
);
1420 /* get the left moniker */
1421 CreateAntiMoniker(&antiMk
);
1422 IMoniker_ComposeWith(iface
,antiMk
,0,&tempMk
);
1423 IMoniker_Release(antiMk
);
1425 return IMoniker_ParseDisplayName(mostRigthMk
,pbc
,tempMk
,pszDisplayName
,pchEaten
,ppmkOut
);
1428 /******************************************************************************
1429 * CompositeMoniker_IsSystemMoniker
1430 ******************************************************************************/
1431 HRESULT WINAPI
CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
1433 TRACE("(%p,%p)\n",iface
,pwdMksys
);
1438 (*pwdMksys
)=MKSYS_GENERICCOMPOSITE
;
1443 /*******************************************************************************
1444 * CompositeMonikerIROTData_QueryInterface
1445 *******************************************************************************/
1446 HRESULT WINAPI
CompositeMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,VOID
** ppvObject
)
1449 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1451 TRACE("(%p,%p,%p)\n",iface
,riid
,ppvObject
);
1453 return CompositeMonikerImpl_QueryInterface(This
, riid
, ppvObject
);
1456 /***********************************************************************
1457 * CompositeMonikerIROTData_AddRef
1459 ULONG WINAPI
CompositeMonikerROTDataImpl_AddRef(IROTData
*iface
)
1461 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1463 TRACE("(%p)\n",iface
);
1465 return CompositeMonikerImpl_AddRef(This
);
1468 /***********************************************************************
1469 * CompositeMonikerIROTData_Release
1471 ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
)
1473 ICOM_THIS_From_IROTData(IMoniker
, iface
);
1475 TRACE("(%p)\n",iface
);
1477 return CompositeMonikerImpl_Release(This
);
1480 /******************************************************************************
1481 * CompositeMonikerIROTData_GetComparaisonData
1482 ******************************************************************************/
1483 HRESULT WINAPI
CompositeMonikerROTDataImpl_GetComparaisonData(IROTData
* iface
,
1488 FIXME("(),stub!\n");
1492 /******************************************************************************
1493 * EnumMonikerImpl_QueryInterface
1494 ******************************************************************************/
1495 HRESULT WINAPI
EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
)
1497 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1499 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
1501 /* Perform a sanity check on the parameters.*/
1502 if ( (This
==0) || (ppvObject
==0) )
1503 return E_INVALIDARG
;
1505 /* Initialize the return parameter */
1508 /* Compare the riid with the interface IDs implemented by this object.*/
1509 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IEnumMoniker
, riid
))
1512 /* Check that we obtained an interface.*/
1513 if ((*ppvObject
)==0)
1514 return E_NOINTERFACE
;
1516 /* Query Interface always increases the reference count by one when it is successful */
1517 EnumMonikerImpl_AddRef(iface
);
1522 /******************************************************************************
1523 * EnumMonikerImpl_AddRef
1524 ******************************************************************************/
1525 ULONG WINAPI
EnumMonikerImpl_AddRef(IEnumMoniker
* iface
)
1527 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1529 TRACE("(%p)\n",This
);
1531 return InterlockedIncrement(&This
->ref
);
1535 /******************************************************************************
1536 * EnumMonikerImpl_Release
1537 ******************************************************************************/
1538 ULONG WINAPI
EnumMonikerImpl_Release(IEnumMoniker
* iface
)
1540 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1543 TRACE("(%p)\n",This
);
1545 ref
= InterlockedDecrement(&This
->ref
);
1547 /* destroy the object if there's no more reference on it */
1550 for(i
=0;i
<This
->tabSize
;i
++)
1551 IMoniker_Release(This
->tabMoniker
[i
]);
1553 HeapFree(GetProcessHeap(),0,This
->tabMoniker
);
1554 HeapFree(GetProcessHeap(),0,This
);
1559 /******************************************************************************
1560 * EnumMonikerImpl_Next
1561 ******************************************************************************/
1562 HRESULT WINAPI
EnumMonikerImpl_Next(IEnumMoniker
* iface
,ULONG celt
, IMoniker
** rgelt
, ULONG
* pceltFethed
){
1564 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1567 /* retrieve the requested number of moniker from the current position */
1568 for(i
=0;((This
->currentPos
< This
->tabSize
) && (i
< celt
));i
++)
1570 rgelt
[i
]=This
->tabMoniker
[This
->currentPos
++];
1572 if (pceltFethed
!=NULL
)
1581 /******************************************************************************
1582 * EnumMonikerImpl_Skip
1583 ******************************************************************************/
1584 HRESULT WINAPI
EnumMonikerImpl_Skip(IEnumMoniker
* iface
,ULONG celt
){
1586 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1588 if ((This
->currentPos
+celt
) >= This
->tabSize
)
1591 This
->currentPos
+=celt
;
1596 /******************************************************************************
1597 * EnumMonikerImpl_Reset
1598 ******************************************************************************/
1599 HRESULT WINAPI
EnumMonikerImpl_Reset(IEnumMoniker
* iface
){
1601 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1608 /******************************************************************************
1609 * EnumMonikerImpl_Clone
1610 ******************************************************************************/
1611 HRESULT WINAPI
EnumMonikerImpl_Clone(IEnumMoniker
* iface
,IEnumMoniker
** ppenum
){
1613 EnumMonikerImpl
*This
= (EnumMonikerImpl
*)iface
;
1615 return EnumMonikerImpl_CreateEnumMoniker(This
->tabMoniker
,This
->tabSize
,This
->currentPos
,TRUE
,ppenum
);
1618 /******************************************************************************
1619 * EnumMonikerImpl_CreateEnumMoniker
1620 ******************************************************************************/
1621 HRESULT WINAPI
EnumMonikerImpl_CreateEnumMoniker(IMoniker
** tabMoniker
,
1625 IEnumMoniker
** ppmk
)
1627 EnumMonikerImpl
* newEnumMoniker
;
1631 if (currentPos
> tabSize
)
1632 return E_INVALIDARG
;
1634 newEnumMoniker
= HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl
));
1636 if (newEnumMoniker
== 0)
1637 return STG_E_INSUFFICIENTMEMORY
;
1639 /* Initialize the virtual function table. */
1640 newEnumMoniker
->lpVtbl
= &VT_EnumMonikerImpl
;
1641 newEnumMoniker
->ref
= 0;
1643 newEnumMoniker
->tabSize
=tabSize
;
1644 newEnumMoniker
->currentPos
=currentPos
;
1646 newEnumMoniker
->tabMoniker
=HeapAlloc(GetProcessHeap(),0,tabSize
*sizeof(IMoniker
));
1648 if (newEnumMoniker
->tabMoniker
==NULL
) {
1649 HeapFree(GetProcessHeap(), 0, newEnumMoniker
);
1650 return E_OUTOFMEMORY
;
1654 for (i
=0;i
<tabSize
;i
++){
1656 newEnumMoniker
->tabMoniker
[i
]=tabMoniker
[i
];
1657 IMoniker_AddRef(tabMoniker
[i
]);
1660 for (i
=tabSize
-1;i
>=0;i
--){
1662 newEnumMoniker
->tabMoniker
[tabSize
-i
-1]=tabMoniker
[i
];
1663 IMoniker_AddRef(tabMoniker
[i
]);
1666 *ppmk
=(IEnumMoniker
*)newEnumMoniker
;
1671 /******************************************************************************
1672 * CreateGenericComposite [OLE32.@]
1673 ******************************************************************************/
1674 HRESULT WINAPI
CreateGenericComposite(LPMONIKER pmkFirst
, LPMONIKER pmkRest
, LPMONIKER
* ppmkComposite
)
1676 CompositeMonikerImpl
* newCompositeMoniker
= 0;
1679 TRACE("(%p,%p,%p)\n",pmkFirst
,pmkRest
,ppmkComposite
);
1681 if (ppmkComposite
==NULL
)
1686 if (pmkFirst
==NULL
&& pmkRest
!=NULL
){
1688 *ppmkComposite
=pmkRest
;
1691 else if (pmkFirst
!=NULL
&& pmkRest
==NULL
){
1692 *ppmkComposite
=pmkFirst
;
1695 else if (pmkFirst
==NULL
&& pmkRest
==NULL
)
1698 newCompositeMoniker
= HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl
));
1700 if (newCompositeMoniker
== 0)
1701 return STG_E_INSUFFICIENTMEMORY
;
1703 hr
= CompositeMonikerImpl_Construct(newCompositeMoniker
,pmkFirst
,pmkRest
);
1707 HeapFree(GetProcessHeap(),0,newCompositeMoniker
);
1710 if (newCompositeMoniker
->tabLastIndex
==1)
1712 hr
= IMoniker_QueryInterface(newCompositeMoniker
->tabMoniker
[0],&IID_IMoniker
,(void**)ppmkComposite
);
1715 hr
= CompositeMonikerImpl_QueryInterface((IMoniker
*)newCompositeMoniker
,&IID_IMoniker
,(void**)ppmkComposite
);
1720 /******************************************************************************
1721 * MonikerCommonPrefixWith [OLE32.@]
1722 ******************************************************************************/
1723 HRESULT WINAPI
MonikerCommonPrefixWith(IMoniker
* pmkThis
,IMoniker
* pmkOther
,IMoniker
** ppmkCommon
)
1725 FIXME("(),stub!\n");