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
);
756 heap_free(prefix_components
);
757 return MK_E_NOPREFIX
;
760 last
= prefix_components
[0];
761 for (i
= 1; i
< prefix_len
; ++i
)
763 hr
= CreateGenericComposite(last
, prefix_components
[i
], &c
);
764 IMoniker_Release(last
);
765 IMoniker_Release(prefix_components
[i
]);
766 if (FAILED(hr
)) break;
769 heap_free(prefix_components
);
774 if (IMoniker_IsEqual(iface
, *prefix
) == S_OK
)
776 else if (prefix_len
< count
)
779 hr
= prefix_len
== moniker
->comp_count
? MK_S_ME
: MK_S_HIM
;
785 /* For non-composite, compare to leftmost component */
786 if (SUCCEEDED(hr
= composite_get_leftmost(moniker
, &leftmost
)))
788 if ((hr
= IMoniker_IsEqual(leftmost
, other
)) == S_OK
)
791 IMoniker_AddRef(*prefix
);
794 hr
= hr
== S_OK
? MK_S_HIM
: MK_E_NOPREFIX
;
795 IMoniker_Release(leftmost
);
801 static HRESULT
composite_compose_components(IMoniker
**comp
, unsigned int count
, IMoniker
**ret
)
808 IMoniker_AddRef(last
);
810 for (i
= 1; i
< count
; ++i
)
812 hr
= CreateGenericComposite(last
, comp
[i
], &c
);
813 IMoniker_Release(last
);
814 if (FAILED(hr
)) break;
818 *ret
= SUCCEEDED(hr
) ? last
: NULL
;
823 static HRESULT WINAPI
CompositeMonikerImpl_RelativePathTo(IMoniker
*iface
, IMoniker
*other
,
826 unsigned int count
, this_count
, other_count
, prefix_len
= 0;
827 IMoniker
*inv
, *tail
= NULL
, *other_tail
= NULL
, *rel
= NULL
;
828 IMoniker
**components
, **other_components
;
829 unsigned int start
= 0, other_start
= 0;
832 TRACE("%p, %p, %p.\n", iface
, other
, relpath
);
839 if (FAILED(hr
= composite_get_components_alloc(iface
, &this_count
, &components
))) return hr
;
840 if (FAILED(hr
= composite_get_components_alloc(other
, &other_count
, &other_components
)))
842 heap_free(components
);
846 /* Skip common prefix of equal components */
847 count
= min(other_count
, this_count
);
848 while (IMoniker_IsEqual(components
[prefix_len
], other_components
[prefix_len
]) == S_OK
)
850 if (++prefix_len
== count
) break;
855 this_count
-= prefix_len
;
856 other_count
-= prefix_len
;
857 other_start
+= prefix_len
;
862 /* Replace first component of the other tail with relative path */
863 if (SUCCEEDED(hr
= IMoniker_RelativePathTo(*components
, *other_components
, &rel
)))
864 *other_components
= rel
;
870 /* Invert left side tail */
871 if (this_count
&& SUCCEEDED(hr
))
873 if (SUCCEEDED(hr
= composite_compose_components(&components
[start
], this_count
, &tail
)))
875 hr
= IMoniker_Inverse(tail
, &inv
);
876 IMoniker_Release(tail
);
881 if (other_count
&& SUCCEEDED(hr
))
882 hr
= composite_compose_components(&other_components
[other_start
], other_count
, &other_tail
);
884 if (tail
|| other_tail
)
885 hr
= CreateGenericComposite(tail
, other_tail
, relpath
);
886 else if (SUCCEEDED(hr
))
889 IMoniker_AddRef(*relpath
);
894 IMoniker_Release(rel
);
896 IMoniker_Release(tail
);
898 IMoniker_Release(other_tail
);
900 heap_free(other_components
);
901 heap_free(components
);
906 static HRESULT WINAPI
CompositeMonikerImpl_GetDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
907 IMoniker
*pmkToLeft
, LPOLESTR
*displayname
)
909 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
910 WCHAR
*left_name
= NULL
, *right_name
= NULL
;
913 TRACE("%p, %p, %p, %p\n", iface
, pbc
, pmkToLeft
, displayname
);
915 if (!pbc
|| !displayname
|| !moniker
->comp_count
)
918 if (FAILED(hr
= IMoniker_GetDisplayName(moniker
->left
, pbc
, NULL
, &left_name
))) return hr
;
919 if (FAILED(hr
= IMoniker_GetDisplayName(moniker
->right
, pbc
, NULL
, &right_name
)))
921 CoTaskMemFree(left_name
);
925 if (!(*displayname
= CoTaskMemAlloc((lstrlenW(left_name
) + lstrlenW(right_name
) + 1) * sizeof(WCHAR
))))
927 CoTaskMemFree(left_name
);
928 CoTaskMemFree(right_name
);
929 return E_OUTOFMEMORY
;
932 lstrcpyW(*displayname
, left_name
);
933 lstrcatW(*displayname
, right_name
);
935 CoTaskMemFree(left_name
);
936 CoTaskMemFree(right_name
);
941 static HRESULT WINAPI
CompositeMonikerImpl_ParseDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
942 IMoniker
*pmkToLeft
, LPOLESTR name
, ULONG
*eaten
, IMoniker
**result
)
944 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
945 IMoniker
*left
, *rightmost
;
948 TRACE("%p, %p, %p, %s, %p, %p.\n", iface
, pbc
, pmkToLeft
, debugstr_w(name
), eaten
, result
);
953 if (FAILED(hr
= composite_get_rightmost(moniker
, &left
, &rightmost
)))
956 /* Let rightmost component parse the name, using what's left of the composite as a left side. */
957 hr
= IMoniker_ParseDisplayName(rightmost
, pbc
, left
, name
, eaten
, result
);
959 IMoniker_Release(left
);
960 IMoniker_Release(rightmost
);
965 /******************************************************************************
966 * CompositeMoniker_IsSystemMoniker
967 ******************************************************************************/
968 static HRESULT WINAPI
969 CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
971 TRACE("(%p,%p)\n",iface
,pwdMksys
);
976 (*pwdMksys
)=MKSYS_GENERICCOMPOSITE
;
981 /*******************************************************************************
982 * CompositeMonikerIROTData_QueryInterface
983 *******************************************************************************/
984 static HRESULT WINAPI
985 CompositeMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,
988 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
990 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppvObject
);
992 return CompositeMonikerImpl_QueryInterface(&This
->IMoniker_iface
, riid
, ppvObject
);
995 /***********************************************************************
996 * CompositeMonikerIROTData_AddRef
999 CompositeMonikerROTDataImpl_AddRef(IROTData
*iface
)
1001 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
1003 TRACE("(%p)\n",iface
);
1005 return IMoniker_AddRef(&This
->IMoniker_iface
);
1008 /***********************************************************************
1009 * CompositeMonikerIROTData_Release
1011 static ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
)
1013 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
1015 TRACE("(%p)\n",iface
);
1017 return IMoniker_Release(&This
->IMoniker_iface
);
1020 static HRESULT
composite_get_moniker_comparison_data(IMoniker
*moniker
,
1021 BYTE
*data
, ULONG max_len
, ULONG
*ret_len
)
1026 if (FAILED(hr
= IMoniker_QueryInterface(moniker
, &IID_IROTData
, (void **)&rot_data
)))
1028 WARN("Failed to get IROTData for component moniker, hr %#lx.\n", hr
);
1032 hr
= IROTData_GetComparisonData(rot_data
, data
, max_len
, ret_len
);
1033 IROTData_Release(rot_data
);
1038 static HRESULT WINAPI
CompositeMonikerROTDataImpl_GetComparisonData(IROTData
*iface
,
1039 BYTE
*data
, ULONG max_len
, ULONG
*ret_len
)
1041 CompositeMonikerImpl
*moniker
= impl_from_IROTData(iface
);
1045 TRACE("%p, %p, %lu, %p\n", iface
, data
, max_len
, ret_len
);
1047 if (!moniker
->comp_count
)
1048 return E_UNEXPECTED
;
1050 /* Get required size first */
1051 *ret_len
= sizeof(CLSID
);
1054 hr
= composite_get_moniker_comparison_data(moniker
->left
, NULL
, 0, &len
);
1055 if (SUCCEEDED(hr
) || hr
== E_OUTOFMEMORY
)
1059 WARN("Failed to get comparison data length for left component, hr %#lx.\n", hr
);
1064 hr
= composite_get_moniker_comparison_data(moniker
->right
, NULL
, 0, &len
);
1065 if (SUCCEEDED(hr
) || hr
== E_OUTOFMEMORY
)
1069 WARN("Failed to get comparison data length for right component, hr %#lx.\n", hr
);
1073 if (max_len
< *ret_len
)
1074 return E_OUTOFMEMORY
;
1076 memcpy(data
, &CLSID_CompositeMoniker
, sizeof(CLSID
));
1077 data
+= sizeof(CLSID
);
1078 max_len
-= sizeof(CLSID
);
1079 if (FAILED(hr
= composite_get_moniker_comparison_data(moniker
->left
, data
, max_len
, &len
)))
1081 WARN("Failed to get comparison data for left component, hr %#lx.\n", hr
);
1086 if (FAILED(hr
= composite_get_moniker_comparison_data(moniker
->right
, data
, max_len
, &len
)))
1088 WARN("Failed to get comparison data for right component, hr %#lx.\n", hr
);
1095 static HRESULT WINAPI
CompositeMonikerMarshalImpl_QueryInterface(IMarshal
*iface
, REFIID riid
, LPVOID
*ppv
)
1097 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1099 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppv
);
1101 return CompositeMonikerImpl_QueryInterface(&This
->IMoniker_iface
, riid
, ppv
);
1104 static ULONG WINAPI
CompositeMonikerMarshalImpl_AddRef(IMarshal
*iface
)
1106 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1108 TRACE("(%p)\n",iface
);
1110 return CompositeMonikerImpl_AddRef(&This
->IMoniker_iface
);
1113 static ULONG WINAPI
CompositeMonikerMarshalImpl_Release(IMarshal
*iface
)
1115 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1117 TRACE("(%p)\n",iface
);
1119 return CompositeMonikerImpl_Release(&This
->IMoniker_iface
);
1122 static HRESULT WINAPI
CompositeMonikerMarshalImpl_GetUnmarshalClass(
1123 IMarshal
*iface
, REFIID riid
, void *pv
, DWORD dwDestContext
,
1124 void* pvDestContext
, DWORD mshlflags
, CLSID
* pCid
)
1126 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1128 TRACE("%s, %p, %lx, %p, %lx, %p.\n", debugstr_guid(riid
), pv
,
1129 dwDestContext
, pvDestContext
, mshlflags
, pCid
);
1131 return IMoniker_GetClassID(&This
->IMoniker_iface
, pCid
);
1134 static HRESULT WINAPI
CompositeMonikerMarshalImpl_GetMarshalSizeMax(
1135 IMarshal
*iface
, REFIID riid
, void *pv
, DWORD dwDestContext
,
1136 void* pvDestContext
, DWORD mshlflags
, DWORD
* pSize
)
1138 CompositeMonikerImpl
*moniker
= impl_from_IMarshal(iface
);
1142 TRACE("%s, %p, %lx, %p, %lx, %p.\n", debugstr_guid(riid
), pv
,
1143 dwDestContext
, pvDestContext
, mshlflags
, pSize
);
1145 if (!moniker
->comp_count
)
1146 return E_UNEXPECTED
;
1148 *pSize
= 0x10; /* to match native */
1150 if (FAILED(hr
= CoGetMarshalSizeMax(&size
, &IID_IMoniker
, (IUnknown
*)moniker
->left
, dwDestContext
,
1151 pvDestContext
, mshlflags
)))
1157 if (FAILED(hr
= CoGetMarshalSizeMax(&size
, &IID_IMoniker
, (IUnknown
*)moniker
->right
, dwDestContext
,
1158 pvDestContext
, mshlflags
)))
1167 static HRESULT WINAPI
CompositeMonikerMarshalImpl_MarshalInterface(IMarshal
*iface
, IStream
*stream
,
1168 REFIID riid
, void *pv
, DWORD dwDestContext
, void *pvDestContext
, DWORD flags
)
1170 CompositeMonikerImpl
*moniker
= impl_from_IMarshal(iface
);
1173 TRACE("%p, %p, %s, %p, %lx, %p, %#lx\n", iface
, stream
, debugstr_guid(riid
), pv
, dwDestContext
, pvDestContext
, flags
);
1175 if (!moniker
->comp_count
)
1176 return E_UNEXPECTED
;
1178 if (FAILED(hr
= CoMarshalInterface(stream
, &IID_IMoniker
, (IUnknown
*)moniker
->left
, dwDestContext
, pvDestContext
, flags
)))
1180 WARN("Failed to marshal left component, hr %#lx.\n", hr
);
1184 if (FAILED(hr
= CoMarshalInterface(stream
, &IID_IMoniker
, (IUnknown
*)moniker
->right
, dwDestContext
, pvDestContext
, flags
)))
1185 WARN("Failed to marshal right component, hr %#lx.\n", hr
);
1190 static HRESULT WINAPI
CompositeMonikerMarshalImpl_UnmarshalInterface(IMarshal
*iface
, IStream
*stream
,
1191 REFIID riid
, void **ppv
)
1193 CompositeMonikerImpl
*moniker
= impl_from_IMarshal(iface
);
1196 TRACE("%p, %p, %s, %p\n", iface
, stream
, debugstr_guid(riid
), ppv
);
1200 IMoniker_Release(moniker
->left
);
1201 moniker
->left
= NULL
;
1206 IMoniker_Release(moniker
->right
);
1207 moniker
->right
= NULL
;
1210 if (FAILED(hr
= CoUnmarshalInterface(stream
, &IID_IMoniker
, (void **)&moniker
->left
)))
1212 WARN("Failed to unmarshal left moniker, hr %#lx.\n", hr
);
1216 if (FAILED(hr
= CoUnmarshalInterface(stream
, &IID_IMoniker
, (void **)&moniker
->right
)))
1218 WARN("Failed to unmarshal right moniker, hr %#lx.\n", hr
);
1222 return IMoniker_QueryInterface(&moniker
->IMoniker_iface
, riid
, ppv
);
1225 static HRESULT WINAPI
CompositeMonikerMarshalImpl_ReleaseMarshalData(IMarshal
*iface
, IStream
*pStm
)
1227 TRACE("(%p)\n", pStm
);
1228 /* can't release a state-based marshal as nothing on server side to
1233 static HRESULT WINAPI
CompositeMonikerMarshalImpl_DisconnectObject(IMarshal
*iface
,
1236 TRACE("%#lx\n", dwReserved
);
1237 /* can't disconnect a state-based marshal as nothing on server side to
1238 * disconnect from */
1242 /******************************************************************************
1243 * EnumMonikerImpl_QueryInterface
1244 ******************************************************************************/
1245 static HRESULT WINAPI
1246 EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
)
1248 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1250 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppvObject
);
1252 /* Perform a sanity check on the parameters.*/
1254 return E_INVALIDARG
;
1256 /* Initialize the return parameter */
1259 /* Compare the riid with the interface IDs implemented by this object.*/
1260 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IEnumMoniker
, riid
))
1263 /* Check that we obtained an interface.*/
1264 if ((*ppvObject
)==0)
1265 return E_NOINTERFACE
;
1267 /* Query Interface always increases the reference count by one when it is successful */
1268 IEnumMoniker_AddRef(iface
);
1273 /******************************************************************************
1274 * EnumMonikerImpl_AddRef
1275 ******************************************************************************/
1277 EnumMonikerImpl_AddRef(IEnumMoniker
* iface
)
1279 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1281 TRACE("(%p)\n",This
);
1283 return InterlockedIncrement(&This
->ref
);
1287 static ULONG WINAPI
EnumMonikerImpl_Release(IEnumMoniker
*iface
)
1289 EnumMonikerImpl
*e
= impl_from_IEnumMoniker(iface
);
1290 ULONG refcount
= InterlockedDecrement(&e
->ref
);
1293 TRACE("%p, refcount %lu.\n", iface
, refcount
);
1297 for (i
= 0; i
< e
->count
; ++i
)
1298 IMoniker_Release(e
->monikers
[i
]);
1299 heap_free(e
->monikers
);
1306 static HRESULT WINAPI
EnumMonikerImpl_Next(IEnumMoniker
*iface
, ULONG count
,
1307 IMoniker
**m
, ULONG
*fetched
)
1309 EnumMonikerImpl
*e
= impl_from_IEnumMoniker(iface
);
1312 TRACE("%p, %lu, %p, %p.\n", iface
, count
, m
, fetched
);
1315 return E_INVALIDARG
;
1319 /* retrieve the requested number of moniker from the current position */
1320 for (i
= 0; (e
->pos
< e
->count
) && (i
< count
); ++i
)
1322 m
[i
] = e
->monikers
[e
->pos
++];
1323 IMoniker_AddRef(m
[i
]);
1329 return i
== count
? S_OK
: S_FALSE
;
1332 static HRESULT WINAPI
EnumMonikerImpl_Skip(IEnumMoniker
*iface
, ULONG count
)
1334 EnumMonikerImpl
*e
= impl_from_IEnumMoniker(iface
);
1336 TRACE("%p, %lu.\n", iface
, count
);
1341 if ((e
->pos
+ count
) >= e
->count
)
1349 static HRESULT WINAPI
EnumMonikerImpl_Reset(IEnumMoniker
* iface
)
1351 EnumMonikerImpl
*e
= impl_from_IEnumMoniker(iface
);
1353 TRACE("%p.\n", iface
);
1360 static HRESULT WINAPI
EnumMonikerImpl_Clone(IEnumMoniker
*iface
, IEnumMoniker
**ret
)
1362 TRACE("%p, %p.\n", iface
, ret
);
1365 return E_INVALIDARG
;
1372 static const IEnumMonikerVtbl VT_EnumMonikerImpl
=
1374 EnumMonikerImpl_QueryInterface
,
1375 EnumMonikerImpl_AddRef
,
1376 EnumMonikerImpl_Release
,
1377 EnumMonikerImpl_Next
,
1378 EnumMonikerImpl_Skip
,
1379 EnumMonikerImpl_Reset
,
1380 EnumMonikerImpl_Clone
1383 static HRESULT
create_enumerator(IMoniker
**components
, unsigned int count
, BOOL forward
, IEnumMoniker
**ret
)
1385 EnumMonikerImpl
*object
;
1388 if (!(object
= heap_alloc_zero(sizeof(*object
))))
1389 return E_OUTOFMEMORY
;
1391 object
->IEnumMoniker_iface
.lpVtbl
= &VT_EnumMonikerImpl
;
1393 object
->count
= count
;
1395 if (!(object
->monikers
= heap_calloc(count
, sizeof(*object
->monikers
))))
1398 return E_OUTOFMEMORY
;
1401 for (i
= 0; i
< count
; ++i
)
1403 object
->monikers
[i
] = forward
? components
[i
] : components
[count
- i
- 1];
1404 IMoniker_AddRef(object
->monikers
[i
]);
1407 *ret
= &object
->IEnumMoniker_iface
;
1412 static const IMonikerVtbl VT_CompositeMonikerImpl
=
1414 CompositeMonikerImpl_QueryInterface
,
1415 CompositeMonikerImpl_AddRef
,
1416 CompositeMonikerImpl_Release
,
1417 CompositeMonikerImpl_GetClassID
,
1418 CompositeMonikerImpl_IsDirty
,
1419 CompositeMonikerImpl_Load
,
1420 CompositeMonikerImpl_Save
,
1421 CompositeMonikerImpl_GetSizeMax
,
1422 CompositeMonikerImpl_BindToObject
,
1423 CompositeMonikerImpl_BindToStorage
,
1424 CompositeMonikerImpl_Reduce
,
1425 CompositeMonikerImpl_ComposeWith
,
1426 CompositeMonikerImpl_Enum
,
1427 CompositeMonikerImpl_IsEqual
,
1428 CompositeMonikerImpl_Hash
,
1429 CompositeMonikerImpl_IsRunning
,
1430 CompositeMonikerImpl_GetTimeOfLastChange
,
1431 CompositeMonikerImpl_Inverse
,
1432 CompositeMonikerImpl_CommonPrefixWith
,
1433 CompositeMonikerImpl_RelativePathTo
,
1434 CompositeMonikerImpl_GetDisplayName
,
1435 CompositeMonikerImpl_ParseDisplayName
,
1436 CompositeMonikerImpl_IsSystemMoniker
1439 /********************************************************************************/
1440 /* Virtual function table for the IROTData class. */
1441 static const IROTDataVtbl VT_ROTDataImpl
=
1443 CompositeMonikerROTDataImpl_QueryInterface
,
1444 CompositeMonikerROTDataImpl_AddRef
,
1445 CompositeMonikerROTDataImpl_Release
,
1446 CompositeMonikerROTDataImpl_GetComparisonData
1449 static const IMarshalVtbl VT_MarshalImpl
=
1451 CompositeMonikerMarshalImpl_QueryInterface
,
1452 CompositeMonikerMarshalImpl_AddRef
,
1453 CompositeMonikerMarshalImpl_Release
,
1454 CompositeMonikerMarshalImpl_GetUnmarshalClass
,
1455 CompositeMonikerMarshalImpl_GetMarshalSizeMax
,
1456 CompositeMonikerMarshalImpl_MarshalInterface
,
1457 CompositeMonikerMarshalImpl_UnmarshalInterface
,
1458 CompositeMonikerMarshalImpl_ReleaseMarshalData
,
1459 CompositeMonikerMarshalImpl_DisconnectObject
1465 struct comp_node
*parent
;
1466 struct comp_node
*left
;
1467 struct comp_node
*right
;
1470 static HRESULT
moniker_get_tree_representation(IMoniker
*moniker
, struct comp_node
*parent
,
1471 struct comp_node
**ret
)
1473 CompositeMonikerImpl
*comp_moniker
;
1474 struct comp_node
*node
;
1476 if (!(node
= heap_alloc_zero(sizeof(*node
))))
1477 return E_OUTOFMEMORY
;
1478 node
->parent
= parent
;
1480 if ((comp_moniker
= unsafe_impl_from_IMoniker(moniker
)))
1482 moniker_get_tree_representation(comp_moniker
->left
, node
, &node
->left
);
1483 moniker_get_tree_representation(comp_moniker
->right
, node
, &node
->right
);
1487 node
->moniker
= moniker
;
1488 IMoniker_AddRef(node
->moniker
);
1496 static struct comp_node
*moniker_tree_get_rightmost(struct comp_node
*root
)
1498 if (!root
->left
&& !root
->right
) return root
->moniker
? root
: NULL
;
1499 while (root
->right
) root
= root
->right
;
1503 static struct comp_node
*moniker_tree_get_leftmost(struct comp_node
*root
)
1505 if (!root
->left
&& !root
->right
) return root
->moniker
? root
: NULL
;
1506 while (root
->left
) root
= root
->left
;
1510 static void moniker_tree_node_release(struct comp_node
*node
)
1513 IMoniker_Release(node
->moniker
);
1517 static void moniker_tree_release(struct comp_node
*node
)
1520 moniker_tree_node_release(node
->left
);
1522 moniker_tree_node_release(node
->right
);
1523 moniker_tree_node_release(node
);
1526 static void moniker_tree_replace_node(struct comp_node
*node
, struct comp_node
*replace_with
)
1530 if (node
->parent
->left
== node
) node
->parent
->left
= replace_with
;
1531 else node
->parent
->right
= replace_with
;
1532 replace_with
->parent
= node
->parent
;
1534 else if (replace_with
->moniker
)
1536 /* Replacing root with non-composite */
1537 node
->moniker
= replace_with
->moniker
;
1538 IMoniker_AddRef(node
->moniker
);
1539 node
->left
= node
->right
= NULL
;
1540 moniker_tree_node_release(replace_with
);
1544 /* Attaching composite branches to the root */
1545 node
->left
= replace_with
->left
;
1546 node
->right
= replace_with
->right
;
1547 moniker_tree_node_release(replace_with
);
1551 static void moniker_tree_discard(struct comp_node
*node
, BOOL left
)
1555 moniker_tree_replace_node(node
->parent
, left
? node
->parent
->left
: node
->parent
->right
);
1556 moniker_tree_node_release(node
);
1560 IMoniker_Release(node
->moniker
);
1561 node
->moniker
= NULL
;
1565 static HRESULT
moniker_create_from_tree(const struct comp_node
*root
, unsigned int *count
, IMoniker
**moniker
)
1567 IMoniker
*left_moniker
, *right_moniker
;
1572 /* Non-composite node */
1573 if (!root
->left
&& !root
->right
)
1576 *moniker
= root
->moniker
;
1577 if (*moniker
) IMoniker_AddRef(*moniker
);
1581 if (FAILED(hr
= moniker_create_from_tree(root
->left
, count
, &left_moniker
))) return hr
;
1582 if (FAILED(hr
= moniker_create_from_tree(root
->right
, count
, &right_moniker
)))
1584 IMoniker_Release(left_moniker
);
1588 hr
= CreateGenericComposite(left_moniker
, right_moniker
, moniker
);
1589 IMoniker_Release(left_moniker
);
1590 IMoniker_Release(right_moniker
);
1594 static void moniker_get_tree_comp_count(const struct comp_node
*root
, unsigned int *count
)
1596 if (!root
->left
&& !root
->right
)
1602 moniker_get_tree_comp_count(root
->left
, count
);
1603 moniker_get_tree_comp_count(root
->right
, count
);
1606 static HRESULT
composite_get_rightmost(CompositeMonikerImpl
*composite
, IMoniker
**left
, IMoniker
**rightmost
)
1608 struct comp_node
*root
, *node
;
1612 /* Shortcut for trivial case when right component is non-composite */
1613 if (!unsafe_impl_from_IMoniker(composite
->right
))
1615 *left
= composite
->left
;
1616 IMoniker_AddRef(*left
);
1617 *rightmost
= composite
->right
;
1618 IMoniker_AddRef(*rightmost
);
1622 *left
= *rightmost
= NULL
;
1624 if (FAILED(hr
= moniker_get_tree_representation(&composite
->IMoniker_iface
, NULL
, &root
)))
1627 if (!(node
= moniker_tree_get_rightmost(root
)))
1629 WARN("Couldn't get right most component.\n");
1630 moniker_tree_release(root
);
1634 *rightmost
= node
->moniker
;
1635 IMoniker_AddRef(*rightmost
);
1636 moniker_tree_discard(node
, TRUE
);
1638 hr
= moniker_create_from_tree(root
, &count
, left
);
1639 moniker_tree_release(root
);
1642 IMoniker_Release(*rightmost
);
1649 static HRESULT
composite_get_leftmost(CompositeMonikerImpl
*composite
, IMoniker
**leftmost
)
1651 struct comp_node
*root
, *node
;
1654 if (!unsafe_impl_from_IMoniker(composite
->left
))
1656 *leftmost
= composite
->left
;
1657 IMoniker_AddRef(*leftmost
);
1661 if (FAILED(hr
= moniker_get_tree_representation(&composite
->IMoniker_iface
, NULL
, &root
)))
1664 if (!(node
= moniker_tree_get_leftmost(root
)))
1666 WARN("Couldn't get left most component.\n");
1667 moniker_tree_release(root
);
1671 *leftmost
= node
->moniker
;
1672 IMoniker_AddRef(*leftmost
);
1674 moniker_tree_release(root
);
1679 static HRESULT
moniker_simplify_composition(IMoniker
*left
, IMoniker
*right
,
1680 unsigned int *count
, IMoniker
**new_left
, IMoniker
**new_right
)
1682 struct comp_node
*left_tree
, *right_tree
;
1683 unsigned int modified
= 0;
1689 moniker_get_tree_representation(left
, NULL
, &left_tree
);
1690 moniker_get_tree_representation(right
, NULL
, &right_tree
);
1692 /* Simplify by composing trees together, in a non-generic way. */
1695 struct comp_node
*l
, *r
;
1697 if (!(l
= moniker_tree_get_rightmost(left_tree
))) break;
1698 if (!(r
= moniker_tree_get_leftmost(right_tree
))) break;
1701 if (FAILED(IMoniker_ComposeWith(l
->moniker
, r
->moniker
, TRUE
, &c
))) break;
1706 /* Replace with composed moniker on the left side */
1707 IMoniker_Release(l
->moniker
);
1711 moniker_tree_discard(l
, TRUE
);
1712 moniker_tree_discard(r
, FALSE
);
1718 IMoniker_AddRef(*new_left
);
1720 IMoniker_AddRef(*new_right
);
1722 moniker_get_tree_comp_count(left_tree
, count
);
1723 moniker_get_tree_comp_count(right_tree
, count
);
1727 hr
= moniker_create_from_tree(left_tree
, count
, new_left
);
1729 hr
= moniker_create_from_tree(right_tree
, count
, new_right
);
1732 moniker_tree_release(left_tree
);
1733 moniker_tree_release(right_tree
);
1737 if (*new_left
) IMoniker_Release(*new_left
);
1738 if (*new_right
) IMoniker_Release(*new_right
);
1739 *new_left
= *new_right
= NULL
;
1745 static HRESULT
create_composite(IMoniker
*left
, IMoniker
*right
, IMoniker
**moniker
)
1747 IMoniker
*new_left
, *new_right
;
1748 CompositeMonikerImpl
*object
;
1753 if (!(object
= heap_alloc_zero(sizeof(*object
))))
1754 return E_OUTOFMEMORY
;
1756 object
->IMoniker_iface
.lpVtbl
= &VT_CompositeMonikerImpl
;
1757 object
->IROTData_iface
.lpVtbl
= &VT_ROTDataImpl
;
1758 object
->IMarshal_iface
.lpVtbl
= &VT_MarshalImpl
;
1761 /* Uninitialized moniker created by object activation */
1762 if (!left
&& !right
)
1764 *moniker
= &object
->IMoniker_iface
;
1768 if (FAILED(hr
= moniker_simplify_composition(left
, right
, &object
->comp_count
, &new_left
, &new_right
)))
1770 IMoniker_Release(&object
->IMoniker_iface
);
1774 if (!new_left
|| !new_right
)
1776 *moniker
= new_left
? new_left
: new_right
;
1777 IMoniker_Release(&object
->IMoniker_iface
);
1781 object
->left
= new_left
;
1782 object
->right
= new_right
;
1784 *moniker
= &object
->IMoniker_iface
;
1789 /******************************************************************************
1790 * CreateGenericComposite [OLE32.@]
1791 ******************************************************************************/
1792 HRESULT WINAPI
CreateGenericComposite(IMoniker
*left
, IMoniker
*right
, IMoniker
**composite
)
1794 TRACE("%p, %p, %p\n", left
, right
, composite
);
1802 IMoniker_AddRef(*composite
);
1805 else if (left
&& !right
)
1808 IMoniker_AddRef(*composite
);
1811 else if (!left
&& !right
)
1814 return create_composite(left
, right
, composite
);
1817 /******************************************************************************
1818 * MonikerCommonPrefixWith [OLE32.@]
1819 ******************************************************************************/
1821 MonikerCommonPrefixWith(IMoniker
* pmkThis
,IMoniker
* pmkOther
,IMoniker
** ppmkCommon
)
1823 FIXME("(),stub!\n");
1827 HRESULT WINAPI
CompositeMoniker_CreateInstance(IClassFactory
*iface
,
1828 IUnknown
*pUnk
, REFIID riid
, void **ppv
)
1833 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
1838 return CLASS_E_NOAGGREGATION
;
1840 hr
= create_composite(NULL
, NULL
, &pMoniker
);
1844 hr
= IMoniker_QueryInterface(pMoniker
, riid
, ppv
);
1845 IMoniker_Release(pMoniker
);