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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #include "wine/debug.h"
35 #include "wine/heap.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
39 typedef struct CompositeMonikerImpl
41 IMoniker IMoniker_iface
;
42 IROTData IROTData_iface
;
43 IMarshal IMarshal_iface
;
48 unsigned int comp_count
;
49 } CompositeMonikerImpl
;
51 static inline CompositeMonikerImpl
*impl_from_IMoniker(IMoniker
*iface
)
53 return CONTAINING_RECORD(iface
, CompositeMonikerImpl
, IMoniker_iface
);
56 static const IMonikerVtbl VT_CompositeMonikerImpl
;
58 static CompositeMonikerImpl
*unsafe_impl_from_IMoniker(IMoniker
*iface
)
60 if (iface
->lpVtbl
!= &VT_CompositeMonikerImpl
)
62 return CONTAINING_RECORD(iface
, CompositeMonikerImpl
, IMoniker_iface
);
65 static inline CompositeMonikerImpl
*impl_from_IROTData(IROTData
*iface
)
67 return CONTAINING_RECORD(iface
, CompositeMonikerImpl
, IROTData_iface
);
70 static inline CompositeMonikerImpl
*impl_from_IMarshal(IMarshal
*iface
)
72 return CONTAINING_RECORD(iface
, CompositeMonikerImpl
, IMarshal_iface
);
75 typedef struct EnumMonikerImpl
77 IEnumMoniker IEnumMoniker_iface
;
84 static inline EnumMonikerImpl
*impl_from_IEnumMoniker(IEnumMoniker
*iface
)
86 return CONTAINING_RECORD(iface
, EnumMonikerImpl
, IEnumMoniker_iface
);
89 static HRESULT
create_enumerator(IMoniker
**components
, unsigned int count
, BOOL forward
, IEnumMoniker
**ret
);
90 static HRESULT
composite_get_rightmost(CompositeMonikerImpl
*composite
, IMoniker
**left
, IMoniker
**rightmost
);
91 static HRESULT
composite_get_leftmost(CompositeMonikerImpl
*composite
, IMoniker
**leftmost
);
93 /*******************************************************************************
94 * CompositeMoniker_QueryInterface
95 *******************************************************************************/
97 CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
99 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
101 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppvObject
);
103 /* Perform a sanity check on the parameters.*/
107 /* Initialize the return parameter */
110 /* Compare the riid with the interface IDs implemented by this object.*/
111 if (IsEqualIID(&IID_IUnknown
, riid
) ||
112 IsEqualIID(&IID_IPersist
, riid
) ||
113 IsEqualIID(&IID_IPersistStream
, riid
) ||
114 IsEqualIID(&IID_IMoniker
, riid
)
117 else if (IsEqualIID(&IID_IROTData
, riid
))
118 *ppvObject
= &This
->IROTData_iface
;
119 else if (IsEqualIID(&IID_IMarshal
, riid
))
120 *ppvObject
= &This
->IMarshal_iface
;
122 /* Check that we obtained an interface.*/
124 return E_NOINTERFACE
;
126 /* Query Interface always increases the reference count by one when it is successful */
127 IMoniker_AddRef(iface
);
132 /******************************************************************************
133 * CompositeMoniker_AddRef
134 ******************************************************************************/
136 CompositeMonikerImpl_AddRef(IMoniker
* iface
)
138 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
140 TRACE("(%p)\n",This
);
142 return InterlockedIncrement(&This
->ref
);
145 static ULONG WINAPI
CompositeMonikerImpl_Release(IMoniker
* iface
)
147 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
148 ULONG refcount
= InterlockedDecrement(&moniker
->ref
);
150 TRACE("%p, refcount %lu\n", iface
, refcount
);
154 if (moniker
->left
) IMoniker_Release(moniker
->left
);
155 if (moniker
->right
) IMoniker_Release(moniker
->right
);
162 /******************************************************************************
163 * CompositeMoniker_GetClassID
164 ******************************************************************************/
165 static HRESULT WINAPI
166 CompositeMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
168 TRACE("(%p,%p)\n",iface
,pClassID
);
173 *pClassID
= CLSID_CompositeMoniker
;
178 /******************************************************************************
179 * CompositeMoniker_IsDirty
180 ******************************************************************************/
181 static HRESULT WINAPI
182 CompositeMonikerImpl_IsDirty(IMoniker
* iface
)
184 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
185 method in the OLE-provided moniker interfaces always return S_FALSE because
186 their internal state never changes. */
188 TRACE("(%p)\n",iface
);
193 static HRESULT WINAPI
CompositeMonikerImpl_Load(IMoniker
*iface
, IStream
*stream
)
195 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
196 IMoniker
*last
, *m
, *c
;
200 TRACE("%p, %p\n", iface
, stream
);
202 if (moniker
->comp_count
)
205 hr
= IStream_Read(stream
, &count
, sizeof(DWORD
), NULL
);
208 WARN("Failed to read component count, hr %#lx.\n", hr
);
214 WARN("Unexpected component count %lu.\n", count
);
218 if (FAILED(hr
= OleLoadFromStream(stream
, &IID_IMoniker
, (void **)&last
)))
221 for (i
= 1; i
< count
- 1; ++i
)
223 if (FAILED(hr
= OleLoadFromStream(stream
, &IID_IMoniker
, (void **)&m
)))
225 WARN("Failed to initialize component %lu, hr %#lx.\n", i
, hr
);
226 IMoniker_Release(last
);
229 hr
= CreateGenericComposite(last
, m
, &c
);
230 IMoniker_Release(last
);
232 if (FAILED(hr
)) return hr
;
236 if (FAILED(hr
= OleLoadFromStream(stream
, &IID_IMoniker
, (void **)&m
)))
238 IMoniker_Release(last
);
242 moniker
->left
= last
;
244 moniker
->comp_count
= count
;
249 static HRESULT
composite_save_components(IMoniker
*moniker
, IStream
*stream
)
251 CompositeMonikerImpl
*comp_moniker
;
254 if ((comp_moniker
= unsafe_impl_from_IMoniker(moniker
)))
256 if (SUCCEEDED(hr
= composite_save_components(comp_moniker
->left
, stream
)))
257 hr
= composite_save_components(comp_moniker
->right
, stream
);
260 hr
= OleSaveToStream((IPersistStream
*)moniker
, stream
);
265 static HRESULT WINAPI
CompositeMonikerImpl_Save(IMoniker
*iface
, IStream
*stream
, BOOL clear_dirty
)
267 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
270 TRACE("%p, %p, %d\n", iface
, stream
, clear_dirty
);
272 if (!moniker
->comp_count
)
275 hr
= IStream_Write(stream
, &moniker
->comp_count
, sizeof(moniker
->comp_count
), NULL
);
276 if (FAILED(hr
)) return hr
;
278 return composite_save_components(iface
, stream
);
281 /******************************************************************************
282 * CompositeMoniker_GetSizeMax
283 ******************************************************************************/
284 static HRESULT WINAPI
285 CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
,ULARGE_INTEGER
* pcbSize
)
287 IEnumMoniker
*enumMk
;
289 ULARGE_INTEGER ptmpSize
;
291 /* The sizeMax of this object is calculated by calling GetSizeMax on
292 * each moniker within this object then summing all returned values
295 TRACE("(%p,%p)\n",iface
,pcbSize
);
300 pcbSize
->QuadPart
= sizeof(DWORD
);
302 IMoniker_Enum(iface
,TRUE
,&enumMk
);
304 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
306 IMoniker_GetSizeMax(pmk
,&ptmpSize
);
308 IMoniker_Release(pmk
);
310 pcbSize
->QuadPart
+= ptmpSize
.QuadPart
+ sizeof(CLSID
);
313 IEnumMoniker_Release(enumMk
);
318 static HRESULT
compose_with(IMoniker
*left
, IMoniker
*right
, IMoniker
**c
)
320 HRESULT hr
= IMoniker_ComposeWith(left
, right
, TRUE
, c
);
321 if (FAILED(hr
) && hr
!= MK_E_NEEDGENERIC
) return hr
;
322 return CreateGenericComposite(left
, right
, c
);
325 static HRESULT WINAPI
CompositeMonikerImpl_BindToObject(IMoniker
*iface
, IBindCtx
*pbc
,
326 IMoniker
*toleft
, REFIID riid
, void **result
)
328 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
329 IMoniker
*left
, *rightmost
, *c
;
330 IRunningObjectTable
*rot
;
334 TRACE("%p, %p, %p, %s, %p.\n", iface
, pbc
, toleft
, debugstr_guid(riid
), result
);
343 hr
= IBindCtx_GetRunningObjectTable(pbc
, &rot
);
346 hr
= IRunningObjectTable_GetObject(rot
, iface
, &object
);
347 IRunningObjectTable_Release(rot
);
348 if (FAILED(hr
)) return E_INVALIDARG
;
350 hr
= IUnknown_QueryInterface(object
, riid
, result
);
351 IUnknown_Release(object
);
357 /* Try to bind rightmost component with (toleft, composite->left) composite at its left side */
358 if (FAILED(hr
= composite_get_rightmost(moniker
, &left
, &rightmost
)))
361 hr
= compose_with(toleft
, left
, &c
);
362 IMoniker_Release(left
);
366 hr
= IMoniker_BindToObject(rightmost
, pbc
, c
, riid
, result
);
370 IMoniker_Release(rightmost
);
375 static HRESULT WINAPI
CompositeMonikerImpl_BindToStorage(IMoniker
*iface
, IBindCtx
*pbc
,
376 IMoniker
*toleft
, REFIID riid
, void **result
)
378 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
379 IMoniker
*left
, *rightmost
, *composed_left
;
382 TRACE("%p, %p, %p, %s, %p.\n", iface
, pbc
, toleft
, debugstr_guid(riid
), result
);
386 if (FAILED(hr
= composite_get_rightmost(moniker
, &left
, &rightmost
)))
391 hr
= compose_with(toleft
, left
, &composed_left
);
395 composed_left
= left
;
396 IMoniker_AddRef(composed_left
);
401 hr
= IMoniker_BindToStorage(rightmost
, pbc
, composed_left
, riid
, result
);
402 IMoniker_Release(composed_left
);
405 IMoniker_Release(rightmost
);
406 IMoniker_Release(left
);
411 static HRESULT WINAPI
CompositeMonikerImpl_Reduce(IMoniker
*iface
, IBindCtx
*pbc
, DWORD howfar
,
412 IMoniker
**toleft
, IMoniker
**reduced
)
414 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
415 IMoniker
*m
, *reduced_left
, *reduced_right
;
419 TRACE("%p, %p, %ld, %p, %p.\n", iface
, pbc
, howfar
, toleft
, reduced
);
421 if (!pbc
|| !reduced
)
424 if (FAILED(hr
= IMoniker_Reduce(moniker
->left
, pbc
, howfar
, NULL
, &reduced_left
)))
428 if (FAILED(hr
= IMoniker_Reduce(moniker
->right
, pbc
, howfar
, &m
, &reduced_right
)))
430 IMoniker_Release(reduced_left
);
434 if ((was_reduced
= (reduced_left
!= moniker
->left
|| reduced_right
!= moniker
->right
)))
436 hr
= CreateGenericComposite(reduced_left
, reduced_right
, reduced
);
441 IMoniker_AddRef(*reduced
);
444 IMoniker_Release(reduced_left
);
445 IMoniker_Release(reduced_right
);
447 return was_reduced
? hr
: MK_S_REDUCED_TO_SELF
;
450 static HRESULT WINAPI
CompositeMonikerImpl_ComposeWith(IMoniker
*iface
, IMoniker
*right
,
451 BOOL only_if_not_generic
, IMoniker
**composite
)
453 TRACE("%p, %p, %d, %p.\n", iface
, right
, only_if_not_generic
, composite
);
457 return only_if_not_generic
? MK_E_NEEDGENERIC
: CreateGenericComposite(iface
, right
, composite
);
460 static void composite_get_components(IMoniker
*moniker
, IMoniker
**components
, unsigned int *index
)
462 CompositeMonikerImpl
*comp_moniker
;
464 if ((comp_moniker
= unsafe_impl_from_IMoniker(moniker
)))
466 composite_get_components(comp_moniker
->left
, components
, index
);
467 composite_get_components(comp_moniker
->right
, components
, index
);
471 components
[*index
] = moniker
;
476 static HRESULT
composite_get_components_alloc(IMoniker
*iface
, unsigned int *count
, IMoniker
***components
)
478 CompositeMonikerImpl
*moniker
;
481 if ((moniker
= unsafe_impl_from_IMoniker(iface
)))
482 *count
= moniker
->comp_count
;
486 if (!(*components
= heap_alloc(*count
* sizeof(**components
))))
487 return E_OUTOFMEMORY
;
490 composite_get_components(iface
, *components
, &index
);
495 static HRESULT WINAPI
CompositeMonikerImpl_Enum(IMoniker
*iface
, BOOL forward
, IEnumMoniker
**ret_enum
)
501 TRACE("%p, %d, %p\n", iface
, forward
, ret_enum
);
506 if (FAILED(hr
= composite_get_components_alloc(iface
, &count
, &monikers
)))
509 hr
= create_enumerator(monikers
, count
, forward
, ret_enum
);
515 static HRESULT WINAPI
CompositeMonikerImpl_IsEqual(IMoniker
*iface
, IMoniker
*other
)
517 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
), *other_moniker
;
518 IMoniker
**components
, **other_components
;
519 unsigned int i
, count
;
522 TRACE("%p, %p.\n", iface
, other
);
527 if (!(other_moniker
= unsafe_impl_from_IMoniker(other
)))
530 if (moniker
->comp_count
!= other_moniker
->comp_count
)
533 if (FAILED(hr
= composite_get_components_alloc(iface
, &count
, &components
))) return hr
;
534 if (FAILED(hr
= composite_get_components_alloc(other
, &count
, &other_components
)))
536 heap_free(components
);
540 for (i
= 0; i
< moniker
->comp_count
; ++i
)
542 if ((hr
= IMoniker_IsEqual(components
[i
], other_components
[i
]) != S_OK
))
546 heap_free(other_components
);
547 heap_free(components
);
552 static HRESULT WINAPI
CompositeMonikerImpl_Hash(IMoniker
*iface
, DWORD
*hash
)
554 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
555 DWORD left_hash
, right_hash
;
558 TRACE("%p, %p\n", iface
, hash
);
563 if (!moniker
->comp_count
)
568 if (FAILED(hr
= IMoniker_Hash(moniker
->left
, &left_hash
))) return hr
;
569 if (FAILED(hr
= IMoniker_Hash(moniker
->right
, &right_hash
))) return hr
;
571 *hash
= left_hash
^ right_hash
;
576 static HRESULT WINAPI
CompositeMonikerImpl_IsRunning(IMoniker
*iface
, IBindCtx
*pbc
,
577 IMoniker
*toleft
, IMoniker
*newly_running
)
579 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
580 IMoniker
*c
, *left
, *rightmost
;
581 IRunningObjectTable
*rot
;
584 TRACE("%p, %p, %p, %p.\n", iface
, pbc
, toleft
, newly_running
);
591 if (SUCCEEDED(hr
= CreateGenericComposite(toleft
, iface
, &c
)))
593 hr
= IMoniker_IsRunning(c
, pbc
, NULL
, newly_running
);
601 return IMoniker_IsEqual(iface
, newly_running
);
603 if (FAILED(hr
= IBindCtx_GetRunningObjectTable(pbc
, &rot
)))
606 hr
= IRunningObjectTable_IsRunning(rot
, iface
);
607 IRunningObjectTable_Release(rot
);
608 if (hr
== S_OK
) return S_OK
;
610 if (FAILED(hr
= composite_get_rightmost(moniker
, &left
, &rightmost
)))
613 hr
= IMoniker_IsRunning(rightmost
, pbc
, left
, NULL
);
615 IMoniker_Release(left
);
616 IMoniker_Release(rightmost
);
621 static HRESULT WINAPI
CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
*iface
, IBindCtx
*pbc
,
622 IMoniker
*toleft
, FILETIME
*changetime
)
624 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
625 IMoniker
*left
, *rightmost
, *composed_left
= NULL
, *running
= NULL
;
626 IRunningObjectTable
*rot
;
629 TRACE("%p, %p, %p, %p.\n", iface
, pbc
, toleft
, changetime
);
631 if (!changetime
|| !pbc
)
634 if (FAILED(hr
= composite_get_rightmost(moniker
, &left
, &rightmost
)))
639 /* Compose (toleft, left) and check that against rightmost */
640 if (SUCCEEDED(hr
= compose_with(toleft
, left
, &composed_left
)) && composed_left
)
641 hr
= compose_with(composed_left
, rightmost
, &running
);
645 composed_left
= left
;
646 IMoniker_AddRef(composed_left
);
648 IMoniker_AddRef(running
);
653 if (SUCCEEDED(hr
= IBindCtx_GetRunningObjectTable(pbc
, &rot
)))
655 if (IRunningObjectTable_GetTimeOfLastChange(rot
, running
, changetime
) != S_OK
)
656 hr
= IMoniker_GetTimeOfLastChange(rightmost
, pbc
, composed_left
, changetime
);
657 IRunningObjectTable_Release(rot
);
662 IMoniker_Release(composed_left
);
664 IMoniker_Release(running
);
665 IMoniker_Release(rightmost
);
666 IMoniker_Release(left
);
671 static HRESULT WINAPI
CompositeMonikerImpl_Inverse(IMoniker
*iface
, IMoniker
**inverse
)
673 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
674 IMoniker
*right_inverted
, *left_inverted
;
677 TRACE("%p, %p.\n", iface
, inverse
);
684 if (FAILED(hr
= IMoniker_Inverse(moniker
->right
, &right_inverted
))) return hr
;
685 if (FAILED(hr
= IMoniker_Inverse(moniker
->left
, &left_inverted
)))
687 IMoniker_Release(right_inverted
);
691 hr
= CreateGenericComposite(right_inverted
, left_inverted
, inverse
);
693 IMoniker_Release(left_inverted
);
694 IMoniker_Release(right_inverted
);
699 static HRESULT WINAPI
CompositeMonikerImpl_CommonPrefixWith(IMoniker
*iface
, IMoniker
*other
,
702 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
), *other_moniker
;
703 unsigned int i
, count
, prefix_len
= 0;
707 TRACE("%p, %p, %p.\n", iface
, other
, prefix
);
709 /* If the other moniker is a composite, this method compares the components of each composite from left */
710 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
711 /* of the leftmost components were common to both monikers. */
716 if (!other
|| !prefix
)
719 if ((other_moniker
= unsafe_impl_from_IMoniker(other
)))
721 IMoniker
**components
, **other_components
, **prefix_components
;
724 if (FAILED(hr
= composite_get_components_alloc(iface
, &count
, &components
))) return hr
;
725 if (FAILED(hr
= composite_get_components_alloc(other
, &count
, &other_components
)))
727 heap_free(components
);
731 count
= min(moniker
->comp_count
, other_moniker
->comp_count
);
732 if (!(prefix_components
= heap_calloc(count
, sizeof(*prefix_components
))))
734 heap_free(components
);
735 heap_free(other_components
);
736 return E_OUTOFMEMORY
;
739 /* Collect prefix components */
740 for (i
= 0; i
< count
; ++i
)
744 if (FAILED(hr
= IMoniker_CommonPrefixWith(components
[i
], other_components
[i
], &p
)))
746 prefix_components
[prefix_len
++] = p
;
747 /* S_OK means that prefix was found and is neither of tested monikers */
748 if (hr
== S_OK
) break;
751 heap_free(components
);
752 heap_free(other_components
);
754 if (!prefix_len
) return MK_E_NOPREFIX
;
756 last
= prefix_components
[0];
757 for (i
= 1; i
< prefix_len
; ++i
)
759 hr
= CreateGenericComposite(last
, prefix_components
[i
], &c
);
760 IMoniker_Release(last
);
761 IMoniker_Release(prefix_components
[i
]);
762 if (FAILED(hr
)) break;
765 heap_free(prefix_components
);
770 if (IMoniker_IsEqual(iface
, *prefix
) == S_OK
)
772 else if (prefix_len
< count
)
775 hr
= prefix_len
== moniker
->comp_count
? MK_S_ME
: MK_S_HIM
;
781 /* For non-composite, compare to leftmost component */
782 if (SUCCEEDED(hr
= composite_get_leftmost(moniker
, &leftmost
)))
784 if ((hr
= IMoniker_IsEqual(leftmost
, other
)) == S_OK
)
787 IMoniker_AddRef(*prefix
);
790 hr
= hr
== S_OK
? MK_S_HIM
: MK_E_NOPREFIX
;
791 IMoniker_Release(leftmost
);
797 static HRESULT
composite_compose_components(IMoniker
**comp
, unsigned int count
, IMoniker
**ret
)
804 IMoniker_AddRef(last
);
806 for (i
= 1; i
< count
; ++i
)
808 hr
= CreateGenericComposite(last
, comp
[i
], &c
);
809 IMoniker_Release(last
);
810 if (FAILED(hr
)) break;
814 *ret
= SUCCEEDED(hr
) ? last
: NULL
;
819 static HRESULT WINAPI
CompositeMonikerImpl_RelativePathTo(IMoniker
*iface
, IMoniker
*other
,
822 unsigned int count
, this_count
, other_count
, prefix_len
= 0;
823 IMoniker
*inv
, *tail
= NULL
, *other_tail
= NULL
, *rel
= NULL
;
824 IMoniker
**components
, **other_components
;
825 unsigned int start
= 0, other_start
= 0;
828 TRACE("%p, %p, %p.\n", iface
, other
, relpath
);
835 if (FAILED(hr
= composite_get_components_alloc(iface
, &this_count
, &components
))) return hr
;
836 if (FAILED(hr
= composite_get_components_alloc(other
, &other_count
, &other_components
)))
838 heap_free(components
);
842 /* Skip common prefix of equal components */
843 count
= min(other_count
, this_count
);
844 while (IMoniker_IsEqual(components
[prefix_len
], other_components
[prefix_len
]) == S_OK
)
846 if (++prefix_len
== count
) break;
851 this_count
-= prefix_len
;
852 other_count
-= prefix_len
;
853 other_start
+= prefix_len
;
858 /* Replace first component of the other tail with relative path */
859 if (SUCCEEDED(hr
= IMoniker_RelativePathTo(*components
, *other_components
, &rel
)))
860 *other_components
= rel
;
866 /* Invert left side tail */
867 if (this_count
&& SUCCEEDED(hr
))
869 if (SUCCEEDED(hr
= composite_compose_components(&components
[start
], this_count
, &tail
)))
871 hr
= IMoniker_Inverse(tail
, &inv
);
872 IMoniker_Release(tail
);
877 if (other_count
&& SUCCEEDED(hr
))
878 hr
= composite_compose_components(&other_components
[other_start
], other_count
, &other_tail
);
880 if (tail
|| other_tail
)
881 hr
= CreateGenericComposite(tail
, other_tail
, relpath
);
882 else if (SUCCEEDED(hr
))
885 IMoniker_AddRef(*relpath
);
890 IMoniker_Release(rel
);
892 IMoniker_Release(tail
);
894 IMoniker_Release(other_tail
);
896 heap_free(other_components
);
897 heap_free(components
);
902 static HRESULT WINAPI
CompositeMonikerImpl_GetDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
903 IMoniker
*pmkToLeft
, LPOLESTR
*displayname
)
905 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
906 WCHAR
*left_name
= NULL
, *right_name
= NULL
;
909 TRACE("%p, %p, %p, %p\n", iface
, pbc
, pmkToLeft
, displayname
);
911 if (!pbc
|| !displayname
|| !moniker
->comp_count
)
914 if (FAILED(hr
= IMoniker_GetDisplayName(moniker
->left
, pbc
, NULL
, &left_name
))) return hr
;
915 if (FAILED(hr
= IMoniker_GetDisplayName(moniker
->right
, pbc
, NULL
, &right_name
)))
917 CoTaskMemFree(left_name
);
921 if (!(*displayname
= CoTaskMemAlloc((lstrlenW(left_name
) + lstrlenW(right_name
) + 1) * sizeof(WCHAR
))))
923 CoTaskMemFree(left_name
);
924 CoTaskMemFree(right_name
);
925 return E_OUTOFMEMORY
;
928 lstrcpyW(*displayname
, left_name
);
929 lstrcatW(*displayname
, right_name
);
931 CoTaskMemFree(left_name
);
932 CoTaskMemFree(right_name
);
937 static HRESULT WINAPI
CompositeMonikerImpl_ParseDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
938 IMoniker
*pmkToLeft
, LPOLESTR name
, ULONG
*eaten
, IMoniker
**result
)
940 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
941 IMoniker
*left
, *rightmost
;
944 TRACE("%p, %p, %p, %s, %p, %p.\n", iface
, pbc
, pmkToLeft
, debugstr_w(name
), eaten
, result
);
949 if (FAILED(hr
= composite_get_rightmost(moniker
, &left
, &rightmost
)))
952 /* Let rightmost component parse the name, using what's left of the composite as a left side. */
953 hr
= IMoniker_ParseDisplayName(rightmost
, pbc
, left
, name
, eaten
, result
);
955 IMoniker_Release(left
);
956 IMoniker_Release(rightmost
);
961 /******************************************************************************
962 * CompositeMoniker_IsSystemMoniker
963 ******************************************************************************/
964 static HRESULT WINAPI
965 CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
967 TRACE("(%p,%p)\n",iface
,pwdMksys
);
972 (*pwdMksys
)=MKSYS_GENERICCOMPOSITE
;
977 /*******************************************************************************
978 * CompositeMonikerIROTData_QueryInterface
979 *******************************************************************************/
980 static HRESULT WINAPI
981 CompositeMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,
984 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
986 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppvObject
);
988 return CompositeMonikerImpl_QueryInterface(&This
->IMoniker_iface
, riid
, ppvObject
);
991 /***********************************************************************
992 * CompositeMonikerIROTData_AddRef
995 CompositeMonikerROTDataImpl_AddRef(IROTData
*iface
)
997 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
999 TRACE("(%p)\n",iface
);
1001 return IMoniker_AddRef(&This
->IMoniker_iface
);
1004 /***********************************************************************
1005 * CompositeMonikerIROTData_Release
1007 static ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
)
1009 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
1011 TRACE("(%p)\n",iface
);
1013 return IMoniker_Release(&This
->IMoniker_iface
);
1016 static HRESULT
composite_get_moniker_comparison_data(IMoniker
*moniker
,
1017 BYTE
*data
, ULONG max_len
, ULONG
*ret_len
)
1022 if (FAILED(hr
= IMoniker_QueryInterface(moniker
, &IID_IROTData
, (void **)&rot_data
)))
1024 WARN("Failed to get IROTData for component moniker, hr %#lx.\n", hr
);
1028 hr
= IROTData_GetComparisonData(rot_data
, data
, max_len
, ret_len
);
1029 IROTData_Release(rot_data
);
1034 static HRESULT WINAPI
CompositeMonikerROTDataImpl_GetComparisonData(IROTData
*iface
,
1035 BYTE
*data
, ULONG max_len
, ULONG
*ret_len
)
1037 CompositeMonikerImpl
*moniker
= impl_from_IROTData(iface
);
1041 TRACE("%p, %p, %lu, %p\n", iface
, data
, max_len
, ret_len
);
1043 if (!moniker
->comp_count
)
1044 return E_UNEXPECTED
;
1046 /* Get required size first */
1047 *ret_len
= sizeof(CLSID
);
1050 hr
= composite_get_moniker_comparison_data(moniker
->left
, NULL
, 0, &len
);
1051 if (SUCCEEDED(hr
) || hr
== E_OUTOFMEMORY
)
1055 WARN("Failed to get comparison data length for left component, hr %#lx.\n", hr
);
1060 hr
= composite_get_moniker_comparison_data(moniker
->right
, NULL
, 0, &len
);
1061 if (SUCCEEDED(hr
) || hr
== E_OUTOFMEMORY
)
1065 WARN("Failed to get comparison data length for right component, hr %#lx.\n", hr
);
1069 if (max_len
< *ret_len
)
1070 return E_OUTOFMEMORY
;
1072 memcpy(data
, &CLSID_CompositeMoniker
, sizeof(CLSID
));
1073 data
+= sizeof(CLSID
);
1074 max_len
-= sizeof(CLSID
);
1075 if (FAILED(hr
= composite_get_moniker_comparison_data(moniker
->left
, data
, max_len
, &len
)))
1077 WARN("Failed to get comparison data for left component, hr %#lx.\n", hr
);
1082 if (FAILED(hr
= composite_get_moniker_comparison_data(moniker
->right
, data
, max_len
, &len
)))
1084 WARN("Failed to get comparison data for right component, hr %#lx.\n", hr
);
1091 static HRESULT WINAPI
CompositeMonikerMarshalImpl_QueryInterface(IMarshal
*iface
, REFIID riid
, LPVOID
*ppv
)
1093 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1095 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppv
);
1097 return CompositeMonikerImpl_QueryInterface(&This
->IMoniker_iface
, riid
, ppv
);
1100 static ULONG WINAPI
CompositeMonikerMarshalImpl_AddRef(IMarshal
*iface
)
1102 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1104 TRACE("(%p)\n",iface
);
1106 return CompositeMonikerImpl_AddRef(&This
->IMoniker_iface
);
1109 static ULONG WINAPI
CompositeMonikerMarshalImpl_Release(IMarshal
*iface
)
1111 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1113 TRACE("(%p)\n",iface
);
1115 return CompositeMonikerImpl_Release(&This
->IMoniker_iface
);
1118 static HRESULT WINAPI
CompositeMonikerMarshalImpl_GetUnmarshalClass(
1119 IMarshal
*iface
, REFIID riid
, void *pv
, DWORD dwDestContext
,
1120 void* pvDestContext
, DWORD mshlflags
, CLSID
* pCid
)
1122 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1124 TRACE("%s, %p, %lx, %p, %lx, %p.\n", debugstr_guid(riid
), pv
,
1125 dwDestContext
, pvDestContext
, mshlflags
, pCid
);
1127 return IMoniker_GetClassID(&This
->IMoniker_iface
, pCid
);
1130 static HRESULT WINAPI
CompositeMonikerMarshalImpl_GetMarshalSizeMax(
1131 IMarshal
*iface
, REFIID riid
, void *pv
, DWORD dwDestContext
,
1132 void* pvDestContext
, DWORD mshlflags
, DWORD
* pSize
)
1134 CompositeMonikerImpl
*moniker
= impl_from_IMarshal(iface
);
1138 TRACE("%s, %p, %lx, %p, %lx, %p.\n", debugstr_guid(riid
), pv
,
1139 dwDestContext
, pvDestContext
, mshlflags
, pSize
);
1141 if (!moniker
->comp_count
)
1142 return E_UNEXPECTED
;
1144 *pSize
= 0x10; /* to match native */
1146 if (FAILED(hr
= CoGetMarshalSizeMax(&size
, &IID_IMoniker
, (IUnknown
*)moniker
->left
, dwDestContext
,
1147 pvDestContext
, mshlflags
)))
1153 if (FAILED(hr
= CoGetMarshalSizeMax(&size
, &IID_IMoniker
, (IUnknown
*)moniker
->right
, dwDestContext
,
1154 pvDestContext
, mshlflags
)))
1163 static HRESULT WINAPI
CompositeMonikerMarshalImpl_MarshalInterface(IMarshal
*iface
, IStream
*stream
,
1164 REFIID riid
, void *pv
, DWORD dwDestContext
, void *pvDestContext
, DWORD flags
)
1166 CompositeMonikerImpl
*moniker
= impl_from_IMarshal(iface
);
1169 TRACE("%p, %p, %s, %p, %lx, %p, %#lx\n", iface
, stream
, debugstr_guid(riid
), pv
, dwDestContext
, pvDestContext
, flags
);
1171 if (!moniker
->comp_count
)
1172 return E_UNEXPECTED
;
1174 if (FAILED(hr
= CoMarshalInterface(stream
, &IID_IMoniker
, (IUnknown
*)moniker
->left
, dwDestContext
, pvDestContext
, flags
)))
1176 WARN("Failed to marshal left component, hr %#lx.\n", hr
);
1180 if (FAILED(hr
= CoMarshalInterface(stream
, &IID_IMoniker
, (IUnknown
*)moniker
->right
, dwDestContext
, pvDestContext
, flags
)))
1181 WARN("Failed to marshal right component, hr %#lx.\n", hr
);
1186 static HRESULT WINAPI
CompositeMonikerMarshalImpl_UnmarshalInterface(IMarshal
*iface
, IStream
*stream
,
1187 REFIID riid
, void **ppv
)
1189 CompositeMonikerImpl
*moniker
= impl_from_IMarshal(iface
);
1192 TRACE("%p, %p, %s, %p\n", iface
, stream
, debugstr_guid(riid
), ppv
);
1196 IMoniker_Release(moniker
->left
);
1197 moniker
->left
= NULL
;
1202 IMoniker_Release(moniker
->right
);
1203 moniker
->right
= NULL
;
1206 if (FAILED(hr
= CoUnmarshalInterface(stream
, &IID_IMoniker
, (void **)&moniker
->left
)))
1208 WARN("Failed to unmarshal left moniker, hr %#lx.\n", hr
);
1212 if (FAILED(hr
= CoUnmarshalInterface(stream
, &IID_IMoniker
, (void **)&moniker
->right
)))
1214 WARN("Failed to unmarshal right moniker, hr %#lx.\n", hr
);
1218 return IMoniker_QueryInterface(&moniker
->IMoniker_iface
, riid
, ppv
);
1221 static HRESULT WINAPI
CompositeMonikerMarshalImpl_ReleaseMarshalData(IMarshal
*iface
, IStream
*pStm
)
1223 TRACE("(%p)\n", pStm
);
1224 /* can't release a state-based marshal as nothing on server side to
1229 static HRESULT WINAPI
CompositeMonikerMarshalImpl_DisconnectObject(IMarshal
*iface
,
1232 TRACE("%#lx\n", dwReserved
);
1233 /* can't disconnect a state-based marshal as nothing on server side to
1234 * disconnect from */
1238 /******************************************************************************
1239 * EnumMonikerImpl_QueryInterface
1240 ******************************************************************************/
1241 static HRESULT WINAPI
1242 EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
)
1244 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1246 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppvObject
);
1248 /* Perform a sanity check on the parameters.*/
1250 return E_INVALIDARG
;
1252 /* Initialize the return parameter */
1255 /* Compare the riid with the interface IDs implemented by this object.*/
1256 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IEnumMoniker
, riid
))
1259 /* Check that we obtained an interface.*/
1260 if ((*ppvObject
)==0)
1261 return E_NOINTERFACE
;
1263 /* Query Interface always increases the reference count by one when it is successful */
1264 IEnumMoniker_AddRef(iface
);
1269 /******************************************************************************
1270 * EnumMonikerImpl_AddRef
1271 ******************************************************************************/
1273 EnumMonikerImpl_AddRef(IEnumMoniker
* iface
)
1275 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1277 TRACE("(%p)\n",This
);
1279 return InterlockedIncrement(&This
->ref
);
1283 static ULONG WINAPI
EnumMonikerImpl_Release(IEnumMoniker
*iface
)
1285 EnumMonikerImpl
*e
= impl_from_IEnumMoniker(iface
);
1286 ULONG refcount
= InterlockedDecrement(&e
->ref
);
1289 TRACE("%p, refcount %lu.\n", iface
, refcount
);
1293 for (i
= 0; i
< e
->count
; ++i
)
1294 IMoniker_Release(e
->monikers
[i
]);
1295 heap_free(e
->monikers
);
1302 static HRESULT WINAPI
EnumMonikerImpl_Next(IEnumMoniker
*iface
, ULONG count
,
1303 IMoniker
**m
, ULONG
*fetched
)
1305 EnumMonikerImpl
*e
= impl_from_IEnumMoniker(iface
);
1308 TRACE("%p, %lu, %p, %p.\n", iface
, count
, m
, fetched
);
1311 return E_INVALIDARG
;
1315 /* retrieve the requested number of moniker from the current position */
1316 for (i
= 0; (e
->pos
< e
->count
) && (i
< count
); ++i
)
1318 m
[i
] = e
->monikers
[e
->pos
++];
1319 IMoniker_AddRef(m
[i
]);
1325 return i
== count
? S_OK
: S_FALSE
;
1328 static HRESULT WINAPI
EnumMonikerImpl_Skip(IEnumMoniker
*iface
, ULONG count
)
1330 EnumMonikerImpl
*e
= impl_from_IEnumMoniker(iface
);
1332 TRACE("%p, %lu.\n", iface
, count
);
1337 if ((e
->pos
+ count
) >= e
->count
)
1345 static HRESULT WINAPI
EnumMonikerImpl_Reset(IEnumMoniker
* iface
)
1347 EnumMonikerImpl
*e
= impl_from_IEnumMoniker(iface
);
1349 TRACE("%p.\n", iface
);
1356 static HRESULT WINAPI
EnumMonikerImpl_Clone(IEnumMoniker
*iface
, IEnumMoniker
**ret
)
1358 TRACE("%p, %p.\n", iface
, ret
);
1361 return E_INVALIDARG
;
1368 static const IEnumMonikerVtbl VT_EnumMonikerImpl
=
1370 EnumMonikerImpl_QueryInterface
,
1371 EnumMonikerImpl_AddRef
,
1372 EnumMonikerImpl_Release
,
1373 EnumMonikerImpl_Next
,
1374 EnumMonikerImpl_Skip
,
1375 EnumMonikerImpl_Reset
,
1376 EnumMonikerImpl_Clone
1379 static HRESULT
create_enumerator(IMoniker
**components
, unsigned int count
, BOOL forward
, IEnumMoniker
**ret
)
1381 EnumMonikerImpl
*object
;
1384 if (!(object
= heap_alloc_zero(sizeof(*object
))))
1385 return E_OUTOFMEMORY
;
1387 object
->IEnumMoniker_iface
.lpVtbl
= &VT_EnumMonikerImpl
;
1389 object
->count
= count
;
1391 if (!(object
->monikers
= heap_calloc(count
, sizeof(*object
->monikers
))))
1394 return E_OUTOFMEMORY
;
1397 for (i
= 0; i
< count
; ++i
)
1399 object
->monikers
[i
] = forward
? components
[i
] : components
[count
- i
- 1];
1400 IMoniker_AddRef(object
->monikers
[i
]);
1403 *ret
= &object
->IEnumMoniker_iface
;
1408 static const IMonikerVtbl VT_CompositeMonikerImpl
=
1410 CompositeMonikerImpl_QueryInterface
,
1411 CompositeMonikerImpl_AddRef
,
1412 CompositeMonikerImpl_Release
,
1413 CompositeMonikerImpl_GetClassID
,
1414 CompositeMonikerImpl_IsDirty
,
1415 CompositeMonikerImpl_Load
,
1416 CompositeMonikerImpl_Save
,
1417 CompositeMonikerImpl_GetSizeMax
,
1418 CompositeMonikerImpl_BindToObject
,
1419 CompositeMonikerImpl_BindToStorage
,
1420 CompositeMonikerImpl_Reduce
,
1421 CompositeMonikerImpl_ComposeWith
,
1422 CompositeMonikerImpl_Enum
,
1423 CompositeMonikerImpl_IsEqual
,
1424 CompositeMonikerImpl_Hash
,
1425 CompositeMonikerImpl_IsRunning
,
1426 CompositeMonikerImpl_GetTimeOfLastChange
,
1427 CompositeMonikerImpl_Inverse
,
1428 CompositeMonikerImpl_CommonPrefixWith
,
1429 CompositeMonikerImpl_RelativePathTo
,
1430 CompositeMonikerImpl_GetDisplayName
,
1431 CompositeMonikerImpl_ParseDisplayName
,
1432 CompositeMonikerImpl_IsSystemMoniker
1435 /********************************************************************************/
1436 /* Virtual function table for the IROTData class. */
1437 static const IROTDataVtbl VT_ROTDataImpl
=
1439 CompositeMonikerROTDataImpl_QueryInterface
,
1440 CompositeMonikerROTDataImpl_AddRef
,
1441 CompositeMonikerROTDataImpl_Release
,
1442 CompositeMonikerROTDataImpl_GetComparisonData
1445 static const IMarshalVtbl VT_MarshalImpl
=
1447 CompositeMonikerMarshalImpl_QueryInterface
,
1448 CompositeMonikerMarshalImpl_AddRef
,
1449 CompositeMonikerMarshalImpl_Release
,
1450 CompositeMonikerMarshalImpl_GetUnmarshalClass
,
1451 CompositeMonikerMarshalImpl_GetMarshalSizeMax
,
1452 CompositeMonikerMarshalImpl_MarshalInterface
,
1453 CompositeMonikerMarshalImpl_UnmarshalInterface
,
1454 CompositeMonikerMarshalImpl_ReleaseMarshalData
,
1455 CompositeMonikerMarshalImpl_DisconnectObject
1461 struct comp_node
*parent
;
1462 struct comp_node
*left
;
1463 struct comp_node
*right
;
1466 static HRESULT
moniker_get_tree_representation(IMoniker
*moniker
, struct comp_node
*parent
,
1467 struct comp_node
**ret
)
1469 CompositeMonikerImpl
*comp_moniker
;
1470 struct comp_node
*node
;
1472 if (!(node
= heap_alloc_zero(sizeof(*node
))))
1473 return E_OUTOFMEMORY
;
1474 node
->parent
= parent
;
1476 if ((comp_moniker
= unsafe_impl_from_IMoniker(moniker
)))
1478 moniker_get_tree_representation(comp_moniker
->left
, node
, &node
->left
);
1479 moniker_get_tree_representation(comp_moniker
->right
, node
, &node
->right
);
1483 node
->moniker
= moniker
;
1484 IMoniker_AddRef(node
->moniker
);
1492 static struct comp_node
*moniker_tree_get_rightmost(struct comp_node
*root
)
1494 if (!root
->left
&& !root
->right
) return root
->moniker
? root
: NULL
;
1495 while (root
->right
) root
= root
->right
;
1499 static struct comp_node
*moniker_tree_get_leftmost(struct comp_node
*root
)
1501 if (!root
->left
&& !root
->right
) return root
->moniker
? root
: NULL
;
1502 while (root
->left
) root
= root
->left
;
1506 static void moniker_tree_node_release(struct comp_node
*node
)
1509 IMoniker_Release(node
->moniker
);
1513 static void moniker_tree_release(struct comp_node
*node
)
1516 moniker_tree_node_release(node
->left
);
1518 moniker_tree_node_release(node
->right
);
1519 moniker_tree_node_release(node
);
1522 static void moniker_tree_replace_node(struct comp_node
*node
, struct comp_node
*replace_with
)
1526 if (node
->parent
->left
== node
) node
->parent
->left
= replace_with
;
1527 else node
->parent
->right
= replace_with
;
1528 replace_with
->parent
= node
->parent
;
1530 else if (replace_with
->moniker
)
1532 /* Replacing root with non-composite */
1533 node
->moniker
= replace_with
->moniker
;
1534 IMoniker_AddRef(node
->moniker
);
1535 node
->left
= node
->right
= NULL
;
1536 moniker_tree_node_release(replace_with
);
1540 /* Attaching composite branches to the root */
1541 node
->left
= replace_with
->left
;
1542 node
->right
= replace_with
->right
;
1543 moniker_tree_node_release(replace_with
);
1547 static void moniker_tree_discard(struct comp_node
*node
, BOOL left
)
1551 moniker_tree_replace_node(node
->parent
, left
? node
->parent
->left
: node
->parent
->right
);
1552 moniker_tree_node_release(node
);
1556 IMoniker_Release(node
->moniker
);
1557 node
->moniker
= NULL
;
1561 static HRESULT
moniker_create_from_tree(const struct comp_node
*root
, unsigned int *count
, IMoniker
**moniker
)
1563 IMoniker
*left_moniker
, *right_moniker
;
1568 /* Non-composite node */
1569 if (!root
->left
&& !root
->right
)
1572 *moniker
= root
->moniker
;
1573 if (*moniker
) IMoniker_AddRef(*moniker
);
1577 if (FAILED(hr
= moniker_create_from_tree(root
->left
, count
, &left_moniker
))) return hr
;
1578 if (FAILED(hr
= moniker_create_from_tree(root
->right
, count
, &right_moniker
)))
1580 IMoniker_Release(left_moniker
);
1584 hr
= CreateGenericComposite(left_moniker
, right_moniker
, moniker
);
1585 IMoniker_Release(left_moniker
);
1586 IMoniker_Release(right_moniker
);
1590 static void moniker_get_tree_comp_count(const struct comp_node
*root
, unsigned int *count
)
1592 if (!root
->left
&& !root
->right
)
1598 moniker_get_tree_comp_count(root
->left
, count
);
1599 moniker_get_tree_comp_count(root
->right
, count
);
1602 static HRESULT
composite_get_rightmost(CompositeMonikerImpl
*composite
, IMoniker
**left
, IMoniker
**rightmost
)
1604 struct comp_node
*root
, *node
;
1608 /* Shortcut for trivial case when right component is non-composite */
1609 if (!unsafe_impl_from_IMoniker(composite
->right
))
1611 *left
= composite
->left
;
1612 IMoniker_AddRef(*left
);
1613 *rightmost
= composite
->right
;
1614 IMoniker_AddRef(*rightmost
);
1618 *left
= *rightmost
= NULL
;
1620 if (FAILED(hr
= moniker_get_tree_representation(&composite
->IMoniker_iface
, NULL
, &root
)))
1623 if (!(node
= moniker_tree_get_rightmost(root
)))
1625 WARN("Couldn't get right most component.\n");
1629 *rightmost
= node
->moniker
;
1630 IMoniker_AddRef(*rightmost
);
1631 moniker_tree_discard(node
, TRUE
);
1633 hr
= moniker_create_from_tree(root
, &count
, left
);
1634 moniker_tree_release(root
);
1637 IMoniker_Release(*rightmost
);
1644 static HRESULT
composite_get_leftmost(CompositeMonikerImpl
*composite
, IMoniker
**leftmost
)
1646 struct comp_node
*root
, *node
;
1649 if (!unsafe_impl_from_IMoniker(composite
->left
))
1651 *leftmost
= composite
->left
;
1652 IMoniker_AddRef(*leftmost
);
1656 if (FAILED(hr
= moniker_get_tree_representation(&composite
->IMoniker_iface
, NULL
, &root
)))
1659 if (!(node
= moniker_tree_get_leftmost(root
)))
1661 WARN("Couldn't get right most component.\n");
1665 *leftmost
= node
->moniker
;
1666 IMoniker_AddRef(*leftmost
);
1668 moniker_tree_release(root
);
1673 static HRESULT
moniker_simplify_composition(IMoniker
*left
, IMoniker
*right
,
1674 unsigned int *count
, IMoniker
**new_left
, IMoniker
**new_right
)
1676 struct comp_node
*left_tree
, *right_tree
;
1677 unsigned int modified
= 0;
1683 moniker_get_tree_representation(left
, NULL
, &left_tree
);
1684 moniker_get_tree_representation(right
, NULL
, &right_tree
);
1686 /* Simplify by composing trees together, in a non-generic way. */
1689 struct comp_node
*l
, *r
;
1691 if (!(l
= moniker_tree_get_rightmost(left_tree
))) break;
1692 if (!(r
= moniker_tree_get_leftmost(right_tree
))) break;
1695 if (FAILED(IMoniker_ComposeWith(l
->moniker
, r
->moniker
, TRUE
, &c
))) break;
1700 /* Replace with composed moniker on the left side */
1701 IMoniker_Release(l
->moniker
);
1705 moniker_tree_discard(l
, TRUE
);
1706 moniker_tree_discard(r
, FALSE
);
1712 IMoniker_AddRef(*new_left
);
1714 IMoniker_AddRef(*new_right
);
1716 moniker_get_tree_comp_count(left_tree
, count
);
1717 moniker_get_tree_comp_count(right_tree
, count
);
1721 hr
= moniker_create_from_tree(left_tree
, count
, new_left
);
1723 hr
= moniker_create_from_tree(right_tree
, count
, new_right
);
1726 moniker_tree_release(left_tree
);
1727 moniker_tree_release(right_tree
);
1731 if (*new_left
) IMoniker_Release(*new_left
);
1732 if (*new_right
) IMoniker_Release(*new_right
);
1733 *new_left
= *new_right
= NULL
;
1739 static HRESULT
create_composite(IMoniker
*left
, IMoniker
*right
, IMoniker
**moniker
)
1741 IMoniker
*new_left
, *new_right
;
1742 CompositeMonikerImpl
*object
;
1747 if (!(object
= heap_alloc_zero(sizeof(*object
))))
1748 return E_OUTOFMEMORY
;
1750 object
->IMoniker_iface
.lpVtbl
= &VT_CompositeMonikerImpl
;
1751 object
->IROTData_iface
.lpVtbl
= &VT_ROTDataImpl
;
1752 object
->IMarshal_iface
.lpVtbl
= &VT_MarshalImpl
;
1755 /* Uninitialized moniker created by object activation */
1756 if (!left
&& !right
)
1758 *moniker
= &object
->IMoniker_iface
;
1762 if (FAILED(hr
= moniker_simplify_composition(left
, right
, &object
->comp_count
, &new_left
, &new_right
)))
1764 IMoniker_Release(&object
->IMoniker_iface
);
1768 if (!new_left
|| !new_right
)
1770 *moniker
= new_left
? new_left
: new_right
;
1771 IMoniker_Release(&object
->IMoniker_iface
);
1775 object
->left
= new_left
;
1776 object
->right
= new_right
;
1778 *moniker
= &object
->IMoniker_iface
;
1783 /******************************************************************************
1784 * CreateGenericComposite [OLE32.@]
1785 ******************************************************************************/
1786 HRESULT WINAPI
CreateGenericComposite(IMoniker
*left
, IMoniker
*right
, IMoniker
**composite
)
1788 TRACE("%p, %p, %p\n", left
, right
, composite
);
1796 IMoniker_AddRef(*composite
);
1799 else if (left
&& !right
)
1802 IMoniker_AddRef(*composite
);
1805 else if (!left
&& !right
)
1808 return create_composite(left
, right
, composite
);
1811 /******************************************************************************
1812 * MonikerCommonPrefixWith [OLE32.@]
1813 ******************************************************************************/
1815 MonikerCommonPrefixWith(IMoniker
* pmkThis
,IMoniker
* pmkOther
,IMoniker
** ppmkCommon
)
1817 FIXME("(),stub!\n");
1821 HRESULT WINAPI
CompositeMoniker_CreateInstance(IClassFactory
*iface
,
1822 IUnknown
*pUnk
, REFIID riid
, void **ppv
)
1827 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
1832 return CLASS_E_NOAGGREGATION
;
1834 hr
= create_composite(NULL
, NULL
, &pMoniker
);
1838 hr
= IMoniker_QueryInterface(pMoniker
, riid
, ppv
);
1839 IMoniker_Release(pMoniker
);