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"
36 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
38 typedef struct CompositeMonikerImpl
40 IMoniker IMoniker_iface
;
41 IROTData IROTData_iface
;
42 IMarshal IMarshal_iface
;
47 unsigned int comp_count
;
48 } CompositeMonikerImpl
;
50 static inline CompositeMonikerImpl
*impl_from_IMoniker(IMoniker
*iface
)
52 return CONTAINING_RECORD(iface
, CompositeMonikerImpl
, IMoniker_iface
);
55 static const IMonikerVtbl VT_CompositeMonikerImpl
;
57 static CompositeMonikerImpl
*unsafe_impl_from_IMoniker(IMoniker
*iface
)
59 if (iface
->lpVtbl
!= &VT_CompositeMonikerImpl
)
61 return CONTAINING_RECORD(iface
, CompositeMonikerImpl
, IMoniker_iface
);
64 static inline CompositeMonikerImpl
*impl_from_IROTData(IROTData
*iface
)
66 return CONTAINING_RECORD(iface
, CompositeMonikerImpl
, IROTData_iface
);
69 static inline CompositeMonikerImpl
*impl_from_IMarshal(IMarshal
*iface
)
71 return CONTAINING_RECORD(iface
, CompositeMonikerImpl
, IMarshal_iface
);
74 typedef struct EnumMonikerImpl
76 IEnumMoniker IEnumMoniker_iface
;
83 static inline EnumMonikerImpl
*impl_from_IEnumMoniker(IEnumMoniker
*iface
)
85 return CONTAINING_RECORD(iface
, EnumMonikerImpl
, IEnumMoniker_iface
);
88 static HRESULT
create_enumerator(IMoniker
**components
, unsigned int count
, BOOL forward
, IEnumMoniker
**ret
);
89 static HRESULT
composite_get_rightmost(CompositeMonikerImpl
*composite
, IMoniker
**left
, IMoniker
**rightmost
);
90 static HRESULT
composite_get_leftmost(CompositeMonikerImpl
*composite
, IMoniker
**leftmost
);
92 /*******************************************************************************
93 * CompositeMoniker_QueryInterface
94 *******************************************************************************/
96 CompositeMonikerImpl_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
98 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
100 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppvObject
);
102 /* Perform a sanity check on the parameters.*/
106 /* Initialize the return parameter */
109 /* Compare the riid with the interface IDs implemented by this object.*/
110 if (IsEqualIID(&IID_IUnknown
, riid
) ||
111 IsEqualIID(&IID_IPersist
, riid
) ||
112 IsEqualIID(&IID_IPersistStream
, riid
) ||
113 IsEqualIID(&IID_IMoniker
, riid
)
116 else if (IsEqualIID(&IID_IROTData
, riid
))
117 *ppvObject
= &This
->IROTData_iface
;
118 else if (IsEqualIID(&IID_IMarshal
, riid
))
119 *ppvObject
= &This
->IMarshal_iface
;
121 /* Check that we obtained an interface.*/
123 return E_NOINTERFACE
;
125 /* Query Interface always increases the reference count by one when it is successful */
126 IMoniker_AddRef(iface
);
131 /******************************************************************************
132 * CompositeMoniker_AddRef
133 ******************************************************************************/
135 CompositeMonikerImpl_AddRef(IMoniker
* iface
)
137 CompositeMonikerImpl
*This
= impl_from_IMoniker(iface
);
139 TRACE("(%p)\n",This
);
141 return InterlockedIncrement(&This
->ref
);
144 static ULONG WINAPI
CompositeMonikerImpl_Release(IMoniker
* iface
)
146 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
147 ULONG refcount
= InterlockedDecrement(&moniker
->ref
);
149 TRACE("%p, refcount %lu\n", iface
, refcount
);
153 if (moniker
->left
) IMoniker_Release(moniker
->left
);
154 if (moniker
->right
) IMoniker_Release(moniker
->right
);
161 /******************************************************************************
162 * CompositeMoniker_GetClassID
163 ******************************************************************************/
164 static HRESULT WINAPI
165 CompositeMonikerImpl_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
167 TRACE("(%p,%p)\n",iface
,pClassID
);
172 *pClassID
= CLSID_CompositeMoniker
;
177 /******************************************************************************
178 * CompositeMoniker_IsDirty
179 ******************************************************************************/
180 static HRESULT WINAPI
181 CompositeMonikerImpl_IsDirty(IMoniker
* iface
)
183 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
184 method in the OLE-provided moniker interfaces always return S_FALSE because
185 their internal state never changes. */
187 TRACE("(%p)\n",iface
);
192 static HRESULT WINAPI
CompositeMonikerImpl_Load(IMoniker
*iface
, IStream
*stream
)
194 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
195 IMoniker
*last
, *m
, *c
;
199 TRACE("%p, %p\n", iface
, stream
);
201 if (moniker
->comp_count
)
204 hr
= IStream_Read(stream
, &count
, sizeof(DWORD
), NULL
);
207 WARN("Failed to read component count, hr %#lx.\n", hr
);
213 WARN("Unexpected component count %lu.\n", count
);
217 if (FAILED(hr
= OleLoadFromStream(stream
, &IID_IMoniker
, (void **)&last
)))
220 for (i
= 1; i
< count
- 1; ++i
)
222 if (FAILED(hr
= OleLoadFromStream(stream
, &IID_IMoniker
, (void **)&m
)))
224 WARN("Failed to initialize component %lu, hr %#lx.\n", i
, hr
);
225 IMoniker_Release(last
);
228 hr
= CreateGenericComposite(last
, m
, &c
);
229 IMoniker_Release(last
);
231 if (FAILED(hr
)) return hr
;
235 if (FAILED(hr
= OleLoadFromStream(stream
, &IID_IMoniker
, (void **)&m
)))
237 IMoniker_Release(last
);
241 moniker
->left
= last
;
243 moniker
->comp_count
= count
;
248 static HRESULT
composite_save_components(IMoniker
*moniker
, IStream
*stream
)
250 CompositeMonikerImpl
*comp_moniker
;
253 if ((comp_moniker
= unsafe_impl_from_IMoniker(moniker
)))
255 if (SUCCEEDED(hr
= composite_save_components(comp_moniker
->left
, stream
)))
256 hr
= composite_save_components(comp_moniker
->right
, stream
);
259 hr
= OleSaveToStream((IPersistStream
*)moniker
, stream
);
264 static HRESULT WINAPI
CompositeMonikerImpl_Save(IMoniker
*iface
, IStream
*stream
, BOOL clear_dirty
)
266 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
269 TRACE("%p, %p, %d\n", iface
, stream
, clear_dirty
);
271 if (!moniker
->comp_count
)
274 hr
= IStream_Write(stream
, &moniker
->comp_count
, sizeof(moniker
->comp_count
), NULL
);
275 if (FAILED(hr
)) return hr
;
277 return composite_save_components(iface
, stream
);
280 /******************************************************************************
281 * CompositeMoniker_GetSizeMax
282 ******************************************************************************/
283 static HRESULT WINAPI
284 CompositeMonikerImpl_GetSizeMax(IMoniker
* iface
,ULARGE_INTEGER
* pcbSize
)
286 IEnumMoniker
*enumMk
;
288 ULARGE_INTEGER ptmpSize
;
290 /* The sizeMax of this object is calculated by calling GetSizeMax on
291 * each moniker within this object then summing all returned values
294 TRACE("(%p,%p)\n",iface
,pcbSize
);
299 pcbSize
->QuadPart
= sizeof(DWORD
);
301 IMoniker_Enum(iface
,TRUE
,&enumMk
);
303 while(IEnumMoniker_Next(enumMk
,1,&pmk
,NULL
)==S_OK
){
305 IMoniker_GetSizeMax(pmk
,&ptmpSize
);
307 IMoniker_Release(pmk
);
309 pcbSize
->QuadPart
+= ptmpSize
.QuadPart
+ sizeof(CLSID
);
312 IEnumMoniker_Release(enumMk
);
317 static HRESULT
compose_with(IMoniker
*left
, IMoniker
*right
, IMoniker
**c
)
319 HRESULT hr
= IMoniker_ComposeWith(left
, right
, TRUE
, c
);
320 if (FAILED(hr
) && hr
!= MK_E_NEEDGENERIC
) return hr
;
321 return CreateGenericComposite(left
, right
, c
);
324 static HRESULT WINAPI
CompositeMonikerImpl_BindToObject(IMoniker
*iface
, IBindCtx
*pbc
,
325 IMoniker
*toleft
, REFIID riid
, void **result
)
327 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
328 IMoniker
*left
, *rightmost
, *c
;
329 IRunningObjectTable
*rot
;
333 TRACE("%p, %p, %p, %s, %p.\n", iface
, pbc
, toleft
, debugstr_guid(riid
), result
);
342 hr
= IBindCtx_GetRunningObjectTable(pbc
, &rot
);
345 hr
= IRunningObjectTable_GetObject(rot
, iface
, &object
);
346 IRunningObjectTable_Release(rot
);
347 if (FAILED(hr
)) return E_INVALIDARG
;
349 hr
= IUnknown_QueryInterface(object
, riid
, result
);
350 IUnknown_Release(object
);
356 /* Try to bind rightmost component with (toleft, composite->left) composite at its left side */
357 if (FAILED(hr
= composite_get_rightmost(moniker
, &left
, &rightmost
)))
360 hr
= compose_with(toleft
, left
, &c
);
361 IMoniker_Release(left
);
365 hr
= IMoniker_BindToObject(rightmost
, pbc
, c
, riid
, result
);
369 IMoniker_Release(rightmost
);
374 static HRESULT WINAPI
CompositeMonikerImpl_BindToStorage(IMoniker
*iface
, IBindCtx
*pbc
,
375 IMoniker
*toleft
, REFIID riid
, void **result
)
377 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
378 IMoniker
*left
, *rightmost
, *composed_left
;
381 TRACE("%p, %p, %p, %s, %p.\n", iface
, pbc
, toleft
, debugstr_guid(riid
), result
);
385 if (FAILED(hr
= composite_get_rightmost(moniker
, &left
, &rightmost
)))
390 hr
= compose_with(toleft
, left
, &composed_left
);
394 composed_left
= left
;
395 IMoniker_AddRef(composed_left
);
400 hr
= IMoniker_BindToStorage(rightmost
, pbc
, composed_left
, riid
, result
);
401 IMoniker_Release(composed_left
);
404 IMoniker_Release(rightmost
);
405 IMoniker_Release(left
);
410 static HRESULT WINAPI
CompositeMonikerImpl_Reduce(IMoniker
*iface
, IBindCtx
*pbc
, DWORD howfar
,
411 IMoniker
**toleft
, IMoniker
**reduced
)
413 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
414 IMoniker
*m
, *reduced_left
, *reduced_right
;
418 TRACE("%p, %p, %ld, %p, %p.\n", iface
, pbc
, howfar
, toleft
, reduced
);
420 if (!pbc
|| !reduced
)
423 if (FAILED(hr
= IMoniker_Reduce(moniker
->left
, pbc
, howfar
, NULL
, &reduced_left
)))
427 if (FAILED(hr
= IMoniker_Reduce(moniker
->right
, pbc
, howfar
, &m
, &reduced_right
)))
429 IMoniker_Release(reduced_left
);
433 if ((was_reduced
= (reduced_left
!= moniker
->left
|| reduced_right
!= moniker
->right
)))
435 hr
= CreateGenericComposite(reduced_left
, reduced_right
, reduced
);
440 IMoniker_AddRef(*reduced
);
443 IMoniker_Release(reduced_left
);
444 IMoniker_Release(reduced_right
);
446 return was_reduced
? hr
: MK_S_REDUCED_TO_SELF
;
449 static HRESULT WINAPI
CompositeMonikerImpl_ComposeWith(IMoniker
*iface
, IMoniker
*right
,
450 BOOL only_if_not_generic
, IMoniker
**composite
)
452 TRACE("%p, %p, %d, %p.\n", iface
, right
, only_if_not_generic
, composite
);
456 return only_if_not_generic
? MK_E_NEEDGENERIC
: CreateGenericComposite(iface
, right
, composite
);
459 static void composite_get_components(IMoniker
*moniker
, IMoniker
**components
, unsigned int *index
)
461 CompositeMonikerImpl
*comp_moniker
;
463 if ((comp_moniker
= unsafe_impl_from_IMoniker(moniker
)))
465 composite_get_components(comp_moniker
->left
, components
, index
);
466 composite_get_components(comp_moniker
->right
, components
, index
);
470 components
[*index
] = moniker
;
475 static HRESULT
composite_get_components_alloc(IMoniker
*iface
, unsigned int *count
, IMoniker
***components
)
477 CompositeMonikerImpl
*moniker
;
480 if ((moniker
= unsafe_impl_from_IMoniker(iface
)))
481 *count
= moniker
->comp_count
;
485 if (!(*components
= malloc(*count
* sizeof(**components
))))
486 return E_OUTOFMEMORY
;
489 composite_get_components(iface
, *components
, &index
);
494 static HRESULT WINAPI
CompositeMonikerImpl_Enum(IMoniker
*iface
, BOOL forward
, IEnumMoniker
**ret_enum
)
500 TRACE("%p, %d, %p\n", iface
, forward
, ret_enum
);
505 if (FAILED(hr
= composite_get_components_alloc(iface
, &count
, &monikers
)))
508 hr
= create_enumerator(monikers
, count
, forward
, ret_enum
);
514 static HRESULT WINAPI
CompositeMonikerImpl_IsEqual(IMoniker
*iface
, IMoniker
*other
)
516 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
), *other_moniker
;
517 IMoniker
**components
, **other_components
;
518 unsigned int i
, count
;
521 TRACE("%p, %p.\n", iface
, other
);
526 if (!(other_moniker
= unsafe_impl_from_IMoniker(other
)))
529 if (moniker
->comp_count
!= other_moniker
->comp_count
)
532 if (FAILED(hr
= composite_get_components_alloc(iface
, &count
, &components
))) return hr
;
533 if (FAILED(hr
= composite_get_components_alloc(other
, &count
, &other_components
)))
539 for (i
= 0; i
< moniker
->comp_count
; ++i
)
541 if ((hr
= IMoniker_IsEqual(components
[i
], other_components
[i
]) != S_OK
))
545 free(other_components
);
551 static HRESULT WINAPI
CompositeMonikerImpl_Hash(IMoniker
*iface
, DWORD
*hash
)
553 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
554 DWORD left_hash
, right_hash
;
557 TRACE("%p, %p\n", iface
, hash
);
562 if (!moniker
->comp_count
)
567 if (FAILED(hr
= IMoniker_Hash(moniker
->left
, &left_hash
))) return hr
;
568 if (FAILED(hr
= IMoniker_Hash(moniker
->right
, &right_hash
))) return hr
;
570 *hash
= left_hash
^ right_hash
;
575 static HRESULT WINAPI
CompositeMonikerImpl_IsRunning(IMoniker
*iface
, IBindCtx
*pbc
,
576 IMoniker
*toleft
, IMoniker
*newly_running
)
578 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
579 IMoniker
*c
, *left
, *rightmost
;
580 IRunningObjectTable
*rot
;
583 TRACE("%p, %p, %p, %p.\n", iface
, pbc
, toleft
, newly_running
);
590 if (SUCCEEDED(hr
= CreateGenericComposite(toleft
, iface
, &c
)))
592 hr
= IMoniker_IsRunning(c
, pbc
, NULL
, newly_running
);
600 return IMoniker_IsEqual(iface
, newly_running
);
602 if (FAILED(hr
= IBindCtx_GetRunningObjectTable(pbc
, &rot
)))
605 hr
= IRunningObjectTable_IsRunning(rot
, iface
);
606 IRunningObjectTable_Release(rot
);
607 if (hr
== S_OK
) return S_OK
;
609 if (FAILED(hr
= composite_get_rightmost(moniker
, &left
, &rightmost
)))
612 hr
= IMoniker_IsRunning(rightmost
, pbc
, left
, NULL
);
614 IMoniker_Release(left
);
615 IMoniker_Release(rightmost
);
620 static HRESULT WINAPI
CompositeMonikerImpl_GetTimeOfLastChange(IMoniker
*iface
, IBindCtx
*pbc
,
621 IMoniker
*toleft
, FILETIME
*changetime
)
623 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
624 IMoniker
*left
, *rightmost
, *composed_left
= NULL
, *running
= NULL
;
625 IRunningObjectTable
*rot
;
628 TRACE("%p, %p, %p, %p.\n", iface
, pbc
, toleft
, changetime
);
630 if (!changetime
|| !pbc
)
633 if (FAILED(hr
= composite_get_rightmost(moniker
, &left
, &rightmost
)))
638 /* Compose (toleft, left) and check that against rightmost */
639 if (SUCCEEDED(hr
= compose_with(toleft
, left
, &composed_left
)) && composed_left
)
640 hr
= compose_with(composed_left
, rightmost
, &running
);
644 composed_left
= left
;
645 IMoniker_AddRef(composed_left
);
647 IMoniker_AddRef(running
);
652 if (SUCCEEDED(hr
= IBindCtx_GetRunningObjectTable(pbc
, &rot
)))
654 if (IRunningObjectTable_GetTimeOfLastChange(rot
, running
, changetime
) != S_OK
)
655 hr
= IMoniker_GetTimeOfLastChange(rightmost
, pbc
, composed_left
, changetime
);
656 IRunningObjectTable_Release(rot
);
661 IMoniker_Release(composed_left
);
663 IMoniker_Release(running
);
664 IMoniker_Release(rightmost
);
665 IMoniker_Release(left
);
670 static HRESULT WINAPI
CompositeMonikerImpl_Inverse(IMoniker
*iface
, IMoniker
**inverse
)
672 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
673 IMoniker
*right_inverted
, *left_inverted
;
676 TRACE("%p, %p.\n", iface
, inverse
);
683 if (FAILED(hr
= IMoniker_Inverse(moniker
->right
, &right_inverted
))) return hr
;
684 if (FAILED(hr
= IMoniker_Inverse(moniker
->left
, &left_inverted
)))
686 IMoniker_Release(right_inverted
);
690 hr
= CreateGenericComposite(right_inverted
, left_inverted
, inverse
);
692 IMoniker_Release(left_inverted
);
693 IMoniker_Release(right_inverted
);
698 static HRESULT WINAPI
CompositeMonikerImpl_CommonPrefixWith(IMoniker
*iface
, IMoniker
*other
,
701 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
), *other_moniker
;
702 unsigned int i
, count
, prefix_len
= 0;
706 TRACE("%p, %p, %p.\n", iface
, other
, prefix
);
708 /* If the other moniker is a composite, this method compares the components of each composite from left */
709 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
710 /* of the leftmost components were common to both monikers. */
715 if (!other
|| !prefix
)
718 if ((other_moniker
= unsafe_impl_from_IMoniker(other
)))
720 IMoniker
**components
, **other_components
, **prefix_components
;
723 if (FAILED(hr
= composite_get_components_alloc(iface
, &count
, &components
))) return hr
;
724 if (FAILED(hr
= composite_get_components_alloc(other
, &count
, &other_components
)))
730 count
= min(moniker
->comp_count
, other_moniker
->comp_count
);
731 if (!(prefix_components
= calloc(count
, sizeof(*prefix_components
))))
734 free(other_components
);
735 return E_OUTOFMEMORY
;
738 /* Collect prefix components */
739 for (i
= 0; i
< count
; ++i
)
743 if (FAILED(hr
= IMoniker_CommonPrefixWith(components
[i
], other_components
[i
], &p
)))
745 prefix_components
[prefix_len
++] = p
;
746 /* S_OK means that prefix was found and is neither of tested monikers */
747 if (hr
== S_OK
) break;
751 free(other_components
);
755 free(prefix_components
);
756 return MK_E_NOPREFIX
;
759 last
= prefix_components
[0];
760 for (i
= 1; i
< prefix_len
; ++i
)
762 hr
= CreateGenericComposite(last
, prefix_components
[i
], &c
);
763 IMoniker_Release(last
);
764 IMoniker_Release(prefix_components
[i
]);
765 if (FAILED(hr
)) break;
768 free(prefix_components
);
773 if (IMoniker_IsEqual(iface
, *prefix
) == S_OK
)
775 else if (prefix_len
< count
)
778 hr
= prefix_len
== moniker
->comp_count
? MK_S_ME
: MK_S_HIM
;
784 /* For non-composite, compare to leftmost component */
785 if (SUCCEEDED(hr
= composite_get_leftmost(moniker
, &leftmost
)))
787 if ((hr
= IMoniker_IsEqual(leftmost
, other
)) == S_OK
)
790 IMoniker_AddRef(*prefix
);
793 hr
= hr
== S_OK
? MK_S_HIM
: MK_E_NOPREFIX
;
794 IMoniker_Release(leftmost
);
800 static HRESULT
composite_compose_components(IMoniker
**comp
, unsigned int count
, IMoniker
**ret
)
807 IMoniker_AddRef(last
);
809 for (i
= 1; i
< count
; ++i
)
811 hr
= CreateGenericComposite(last
, comp
[i
], &c
);
812 IMoniker_Release(last
);
813 if (FAILED(hr
)) break;
817 *ret
= SUCCEEDED(hr
) ? last
: NULL
;
822 static HRESULT WINAPI
CompositeMonikerImpl_RelativePathTo(IMoniker
*iface
, IMoniker
*other
,
825 unsigned int count
, this_count
, other_count
, prefix_len
= 0;
826 IMoniker
*inv
, *tail
= NULL
, *other_tail
= NULL
, *rel
= NULL
;
827 IMoniker
**components
, **other_components
;
828 unsigned int start
= 0, other_start
= 0;
831 TRACE("%p, %p, %p.\n", iface
, other
, relpath
);
838 if (FAILED(hr
= composite_get_components_alloc(iface
, &this_count
, &components
))) return hr
;
839 if (FAILED(hr
= composite_get_components_alloc(other
, &other_count
, &other_components
)))
845 /* Skip common prefix of equal components */
846 count
= min(other_count
, this_count
);
847 while (IMoniker_IsEqual(components
[prefix_len
], other_components
[prefix_len
]) == S_OK
)
849 if (++prefix_len
== count
) break;
854 this_count
-= prefix_len
;
855 other_count
-= prefix_len
;
856 other_start
+= prefix_len
;
861 /* Replace first component of the other tail with relative path */
862 if (SUCCEEDED(hr
= IMoniker_RelativePathTo(*components
, *other_components
, &rel
)))
863 *other_components
= rel
;
869 /* Invert left side tail */
870 if (this_count
&& SUCCEEDED(hr
))
872 if (SUCCEEDED(hr
= composite_compose_components(&components
[start
], this_count
, &tail
)))
874 hr
= IMoniker_Inverse(tail
, &inv
);
875 IMoniker_Release(tail
);
880 if (other_count
&& SUCCEEDED(hr
))
881 hr
= composite_compose_components(&other_components
[other_start
], other_count
, &other_tail
);
883 if (tail
|| other_tail
)
884 hr
= CreateGenericComposite(tail
, other_tail
, relpath
);
885 else if (SUCCEEDED(hr
))
888 IMoniker_AddRef(*relpath
);
893 IMoniker_Release(rel
);
895 IMoniker_Release(tail
);
897 IMoniker_Release(other_tail
);
899 free(other_components
);
905 static HRESULT WINAPI
CompositeMonikerImpl_GetDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
906 IMoniker
*pmkToLeft
, LPOLESTR
*displayname
)
908 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
909 WCHAR
*left_name
= NULL
, *right_name
= NULL
;
912 TRACE("%p, %p, %p, %p\n", iface
, pbc
, pmkToLeft
, displayname
);
914 if (!pbc
|| !displayname
|| !moniker
->comp_count
)
917 if (FAILED(hr
= IMoniker_GetDisplayName(moniker
->left
, pbc
, NULL
, &left_name
))) return hr
;
918 if (FAILED(hr
= IMoniker_GetDisplayName(moniker
->right
, pbc
, NULL
, &right_name
)))
920 CoTaskMemFree(left_name
);
924 if (!(*displayname
= CoTaskMemAlloc((lstrlenW(left_name
) + lstrlenW(right_name
) + 1) * sizeof(WCHAR
))))
926 CoTaskMemFree(left_name
);
927 CoTaskMemFree(right_name
);
928 return E_OUTOFMEMORY
;
931 lstrcpyW(*displayname
, left_name
);
932 lstrcatW(*displayname
, right_name
);
934 CoTaskMemFree(left_name
);
935 CoTaskMemFree(right_name
);
940 static HRESULT WINAPI
CompositeMonikerImpl_ParseDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
941 IMoniker
*pmkToLeft
, LPOLESTR name
, ULONG
*eaten
, IMoniker
**result
)
943 CompositeMonikerImpl
*moniker
= impl_from_IMoniker(iface
);
944 IMoniker
*left
, *rightmost
;
947 TRACE("%p, %p, %p, %s, %p, %p.\n", iface
, pbc
, pmkToLeft
, debugstr_w(name
), eaten
, result
);
952 if (FAILED(hr
= composite_get_rightmost(moniker
, &left
, &rightmost
)))
955 /* Let rightmost component parse the name, using what's left of the composite as a left side. */
956 hr
= IMoniker_ParseDisplayName(rightmost
, pbc
, left
, name
, eaten
, result
);
958 IMoniker_Release(left
);
959 IMoniker_Release(rightmost
);
964 /******************************************************************************
965 * CompositeMoniker_IsSystemMoniker
966 ******************************************************************************/
967 static HRESULT WINAPI
968 CompositeMonikerImpl_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
970 TRACE("(%p,%p)\n",iface
,pwdMksys
);
975 (*pwdMksys
)=MKSYS_GENERICCOMPOSITE
;
980 /*******************************************************************************
981 * CompositeMonikerIROTData_QueryInterface
982 *******************************************************************************/
983 static HRESULT WINAPI
984 CompositeMonikerROTDataImpl_QueryInterface(IROTData
*iface
,REFIID riid
,
987 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
989 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppvObject
);
991 return CompositeMonikerImpl_QueryInterface(&This
->IMoniker_iface
, riid
, ppvObject
);
994 /***********************************************************************
995 * CompositeMonikerIROTData_AddRef
998 CompositeMonikerROTDataImpl_AddRef(IROTData
*iface
)
1000 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
1002 TRACE("(%p)\n",iface
);
1004 return IMoniker_AddRef(&This
->IMoniker_iface
);
1007 /***********************************************************************
1008 * CompositeMonikerIROTData_Release
1010 static ULONG WINAPI
CompositeMonikerROTDataImpl_Release(IROTData
* iface
)
1012 CompositeMonikerImpl
*This
= impl_from_IROTData(iface
);
1014 TRACE("(%p)\n",iface
);
1016 return IMoniker_Release(&This
->IMoniker_iface
);
1019 static HRESULT
composite_get_moniker_comparison_data(IMoniker
*moniker
,
1020 BYTE
*data
, ULONG max_len
, ULONG
*ret_len
)
1025 if (FAILED(hr
= IMoniker_QueryInterface(moniker
, &IID_IROTData
, (void **)&rot_data
)))
1027 WARN("Failed to get IROTData for component moniker, hr %#lx.\n", hr
);
1031 hr
= IROTData_GetComparisonData(rot_data
, data
, max_len
, ret_len
);
1032 IROTData_Release(rot_data
);
1037 static HRESULT WINAPI
CompositeMonikerROTDataImpl_GetComparisonData(IROTData
*iface
,
1038 BYTE
*data
, ULONG max_len
, ULONG
*ret_len
)
1040 CompositeMonikerImpl
*moniker
= impl_from_IROTData(iface
);
1044 TRACE("%p, %p, %lu, %p\n", iface
, data
, max_len
, ret_len
);
1046 if (!moniker
->comp_count
)
1047 return E_UNEXPECTED
;
1049 /* Get required size first */
1050 *ret_len
= sizeof(CLSID
);
1053 hr
= composite_get_moniker_comparison_data(moniker
->left
, NULL
, 0, &len
);
1054 if (SUCCEEDED(hr
) || hr
== E_OUTOFMEMORY
)
1058 WARN("Failed to get comparison data length for left component, hr %#lx.\n", hr
);
1063 hr
= composite_get_moniker_comparison_data(moniker
->right
, NULL
, 0, &len
);
1064 if (SUCCEEDED(hr
) || hr
== E_OUTOFMEMORY
)
1068 WARN("Failed to get comparison data length for right component, hr %#lx.\n", hr
);
1072 if (max_len
< *ret_len
)
1073 return E_OUTOFMEMORY
;
1075 memcpy(data
, &CLSID_CompositeMoniker
, sizeof(CLSID
));
1076 data
+= sizeof(CLSID
);
1077 max_len
-= sizeof(CLSID
);
1078 if (FAILED(hr
= composite_get_moniker_comparison_data(moniker
->left
, data
, max_len
, &len
)))
1080 WARN("Failed to get comparison data for left component, hr %#lx.\n", hr
);
1085 if (FAILED(hr
= composite_get_moniker_comparison_data(moniker
->right
, data
, max_len
, &len
)))
1087 WARN("Failed to get comparison data for right component, hr %#lx.\n", hr
);
1094 static HRESULT WINAPI
CompositeMonikerMarshalImpl_QueryInterface(IMarshal
*iface
, REFIID riid
, LPVOID
*ppv
)
1096 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1098 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppv
);
1100 return CompositeMonikerImpl_QueryInterface(&This
->IMoniker_iface
, riid
, ppv
);
1103 static ULONG WINAPI
CompositeMonikerMarshalImpl_AddRef(IMarshal
*iface
)
1105 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1107 TRACE("(%p)\n",iface
);
1109 return CompositeMonikerImpl_AddRef(&This
->IMoniker_iface
);
1112 static ULONG WINAPI
CompositeMonikerMarshalImpl_Release(IMarshal
*iface
)
1114 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1116 TRACE("(%p)\n",iface
);
1118 return CompositeMonikerImpl_Release(&This
->IMoniker_iface
);
1121 static HRESULT WINAPI
CompositeMonikerMarshalImpl_GetUnmarshalClass(
1122 IMarshal
*iface
, REFIID riid
, void *pv
, DWORD dwDestContext
,
1123 void* pvDestContext
, DWORD mshlflags
, CLSID
* pCid
)
1125 CompositeMonikerImpl
*This
= impl_from_IMarshal(iface
);
1127 TRACE("%s, %p, %lx, %p, %lx, %p.\n", debugstr_guid(riid
), pv
,
1128 dwDestContext
, pvDestContext
, mshlflags
, pCid
);
1130 return IMoniker_GetClassID(&This
->IMoniker_iface
, pCid
);
1133 static HRESULT WINAPI
CompositeMonikerMarshalImpl_GetMarshalSizeMax(
1134 IMarshal
*iface
, REFIID riid
, void *pv
, DWORD dwDestContext
,
1135 void* pvDestContext
, DWORD mshlflags
, DWORD
* pSize
)
1137 CompositeMonikerImpl
*moniker
= impl_from_IMarshal(iface
);
1141 TRACE("%s, %p, %lx, %p, %lx, %p.\n", debugstr_guid(riid
), pv
,
1142 dwDestContext
, pvDestContext
, mshlflags
, pSize
);
1144 if (!moniker
->comp_count
)
1145 return E_UNEXPECTED
;
1147 *pSize
= 0x10; /* to match native */
1149 if (FAILED(hr
= CoGetMarshalSizeMax(&size
, &IID_IMoniker
, (IUnknown
*)moniker
->left
, dwDestContext
,
1150 pvDestContext
, mshlflags
)))
1156 if (FAILED(hr
= CoGetMarshalSizeMax(&size
, &IID_IMoniker
, (IUnknown
*)moniker
->right
, dwDestContext
,
1157 pvDestContext
, mshlflags
)))
1166 static HRESULT WINAPI
CompositeMonikerMarshalImpl_MarshalInterface(IMarshal
*iface
, IStream
*stream
,
1167 REFIID riid
, void *pv
, DWORD dwDestContext
, void *pvDestContext
, DWORD flags
)
1169 CompositeMonikerImpl
*moniker
= impl_from_IMarshal(iface
);
1172 TRACE("%p, %p, %s, %p, %lx, %p, %#lx\n", iface
, stream
, debugstr_guid(riid
), pv
, dwDestContext
, pvDestContext
, flags
);
1174 if (!moniker
->comp_count
)
1175 return E_UNEXPECTED
;
1177 if (FAILED(hr
= CoMarshalInterface(stream
, &IID_IMoniker
, (IUnknown
*)moniker
->left
, dwDestContext
, pvDestContext
, flags
)))
1179 WARN("Failed to marshal left component, hr %#lx.\n", hr
);
1183 if (FAILED(hr
= CoMarshalInterface(stream
, &IID_IMoniker
, (IUnknown
*)moniker
->right
, dwDestContext
, pvDestContext
, flags
)))
1184 WARN("Failed to marshal right component, hr %#lx.\n", hr
);
1189 static HRESULT WINAPI
CompositeMonikerMarshalImpl_UnmarshalInterface(IMarshal
*iface
, IStream
*stream
,
1190 REFIID riid
, void **ppv
)
1192 CompositeMonikerImpl
*moniker
= impl_from_IMarshal(iface
);
1195 TRACE("%p, %p, %s, %p\n", iface
, stream
, debugstr_guid(riid
), ppv
);
1199 IMoniker_Release(moniker
->left
);
1200 moniker
->left
= NULL
;
1205 IMoniker_Release(moniker
->right
);
1206 moniker
->right
= NULL
;
1209 if (FAILED(hr
= CoUnmarshalInterface(stream
, &IID_IMoniker
, (void **)&moniker
->left
)))
1211 WARN("Failed to unmarshal left moniker, hr %#lx.\n", hr
);
1215 if (FAILED(hr
= CoUnmarshalInterface(stream
, &IID_IMoniker
, (void **)&moniker
->right
)))
1217 WARN("Failed to unmarshal right moniker, hr %#lx.\n", hr
);
1221 return IMoniker_QueryInterface(&moniker
->IMoniker_iface
, riid
, ppv
);
1224 static HRESULT WINAPI
CompositeMonikerMarshalImpl_ReleaseMarshalData(IMarshal
*iface
, IStream
*pStm
)
1226 TRACE("(%p)\n", pStm
);
1227 /* can't release a state-based marshal as nothing on server side to
1232 static HRESULT WINAPI
CompositeMonikerMarshalImpl_DisconnectObject(IMarshal
*iface
,
1235 TRACE("%#lx\n", dwReserved
);
1236 /* can't disconnect a state-based marshal as nothing on server side to
1237 * disconnect from */
1241 /******************************************************************************
1242 * EnumMonikerImpl_QueryInterface
1243 ******************************************************************************/
1244 static HRESULT WINAPI
1245 EnumMonikerImpl_QueryInterface(IEnumMoniker
* iface
,REFIID riid
,void** ppvObject
)
1247 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1249 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppvObject
);
1251 /* Perform a sanity check on the parameters.*/
1253 return E_INVALIDARG
;
1255 /* Initialize the return parameter */
1258 /* Compare the riid with the interface IDs implemented by this object.*/
1259 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IEnumMoniker
, riid
))
1262 /* Check that we obtained an interface.*/
1263 if ((*ppvObject
)==0)
1264 return E_NOINTERFACE
;
1266 /* Query Interface always increases the reference count by one when it is successful */
1267 IEnumMoniker_AddRef(iface
);
1272 /******************************************************************************
1273 * EnumMonikerImpl_AddRef
1274 ******************************************************************************/
1276 EnumMonikerImpl_AddRef(IEnumMoniker
* iface
)
1278 EnumMonikerImpl
*This
= impl_from_IEnumMoniker(iface
);
1280 TRACE("(%p)\n",This
);
1282 return InterlockedIncrement(&This
->ref
);
1286 static ULONG WINAPI
EnumMonikerImpl_Release(IEnumMoniker
*iface
)
1288 EnumMonikerImpl
*e
= impl_from_IEnumMoniker(iface
);
1289 ULONG refcount
= InterlockedDecrement(&e
->ref
);
1292 TRACE("%p, refcount %lu.\n", iface
, refcount
);
1296 for (i
= 0; i
< e
->count
; ++i
)
1297 IMoniker_Release(e
->monikers
[i
]);
1305 static HRESULT WINAPI
EnumMonikerImpl_Next(IEnumMoniker
*iface
, ULONG count
,
1306 IMoniker
**m
, ULONG
*fetched
)
1308 EnumMonikerImpl
*e
= impl_from_IEnumMoniker(iface
);
1311 TRACE("%p, %lu, %p, %p.\n", iface
, count
, m
, fetched
);
1314 return E_INVALIDARG
;
1318 /* retrieve the requested number of moniker from the current position */
1319 for (i
= 0; (e
->pos
< e
->count
) && (i
< count
); ++i
)
1321 m
[i
] = e
->monikers
[e
->pos
++];
1322 IMoniker_AddRef(m
[i
]);
1328 return i
== count
? S_OK
: S_FALSE
;
1331 static HRESULT WINAPI
EnumMonikerImpl_Skip(IEnumMoniker
*iface
, ULONG count
)
1333 EnumMonikerImpl
*e
= impl_from_IEnumMoniker(iface
);
1335 TRACE("%p, %lu.\n", iface
, count
);
1340 if ((e
->pos
+ count
) >= e
->count
)
1348 static HRESULT WINAPI
EnumMonikerImpl_Reset(IEnumMoniker
* iface
)
1350 EnumMonikerImpl
*e
= impl_from_IEnumMoniker(iface
);
1352 TRACE("%p.\n", iface
);
1359 static HRESULT WINAPI
EnumMonikerImpl_Clone(IEnumMoniker
*iface
, IEnumMoniker
**ret
)
1361 TRACE("%p, %p.\n", iface
, ret
);
1364 return E_INVALIDARG
;
1371 static const IEnumMonikerVtbl VT_EnumMonikerImpl
=
1373 EnumMonikerImpl_QueryInterface
,
1374 EnumMonikerImpl_AddRef
,
1375 EnumMonikerImpl_Release
,
1376 EnumMonikerImpl_Next
,
1377 EnumMonikerImpl_Skip
,
1378 EnumMonikerImpl_Reset
,
1379 EnumMonikerImpl_Clone
1382 static HRESULT
create_enumerator(IMoniker
**components
, unsigned int count
, BOOL forward
, IEnumMoniker
**ret
)
1384 EnumMonikerImpl
*object
;
1387 if (!(object
= calloc(1, sizeof(*object
))))
1388 return E_OUTOFMEMORY
;
1390 object
->IEnumMoniker_iface
.lpVtbl
= &VT_EnumMonikerImpl
;
1392 object
->count
= count
;
1394 if (!(object
->monikers
= calloc(count
, sizeof(*object
->monikers
))))
1397 return E_OUTOFMEMORY
;
1400 for (i
= 0; i
< count
; ++i
)
1402 object
->monikers
[i
] = forward
? components
[i
] : components
[count
- i
- 1];
1403 IMoniker_AddRef(object
->monikers
[i
]);
1406 *ret
= &object
->IEnumMoniker_iface
;
1411 static const IMonikerVtbl VT_CompositeMonikerImpl
=
1413 CompositeMonikerImpl_QueryInterface
,
1414 CompositeMonikerImpl_AddRef
,
1415 CompositeMonikerImpl_Release
,
1416 CompositeMonikerImpl_GetClassID
,
1417 CompositeMonikerImpl_IsDirty
,
1418 CompositeMonikerImpl_Load
,
1419 CompositeMonikerImpl_Save
,
1420 CompositeMonikerImpl_GetSizeMax
,
1421 CompositeMonikerImpl_BindToObject
,
1422 CompositeMonikerImpl_BindToStorage
,
1423 CompositeMonikerImpl_Reduce
,
1424 CompositeMonikerImpl_ComposeWith
,
1425 CompositeMonikerImpl_Enum
,
1426 CompositeMonikerImpl_IsEqual
,
1427 CompositeMonikerImpl_Hash
,
1428 CompositeMonikerImpl_IsRunning
,
1429 CompositeMonikerImpl_GetTimeOfLastChange
,
1430 CompositeMonikerImpl_Inverse
,
1431 CompositeMonikerImpl_CommonPrefixWith
,
1432 CompositeMonikerImpl_RelativePathTo
,
1433 CompositeMonikerImpl_GetDisplayName
,
1434 CompositeMonikerImpl_ParseDisplayName
,
1435 CompositeMonikerImpl_IsSystemMoniker
1438 /********************************************************************************/
1439 /* Virtual function table for the IROTData class. */
1440 static const IROTDataVtbl VT_ROTDataImpl
=
1442 CompositeMonikerROTDataImpl_QueryInterface
,
1443 CompositeMonikerROTDataImpl_AddRef
,
1444 CompositeMonikerROTDataImpl_Release
,
1445 CompositeMonikerROTDataImpl_GetComparisonData
1448 static const IMarshalVtbl VT_MarshalImpl
=
1450 CompositeMonikerMarshalImpl_QueryInterface
,
1451 CompositeMonikerMarshalImpl_AddRef
,
1452 CompositeMonikerMarshalImpl_Release
,
1453 CompositeMonikerMarshalImpl_GetUnmarshalClass
,
1454 CompositeMonikerMarshalImpl_GetMarshalSizeMax
,
1455 CompositeMonikerMarshalImpl_MarshalInterface
,
1456 CompositeMonikerMarshalImpl_UnmarshalInterface
,
1457 CompositeMonikerMarshalImpl_ReleaseMarshalData
,
1458 CompositeMonikerMarshalImpl_DisconnectObject
1464 struct comp_node
*parent
;
1465 struct comp_node
*left
;
1466 struct comp_node
*right
;
1469 static HRESULT
moniker_get_tree_representation(IMoniker
*moniker
, struct comp_node
*parent
,
1470 struct comp_node
**ret
)
1472 CompositeMonikerImpl
*comp_moniker
;
1473 struct comp_node
*node
;
1475 if (!(node
= calloc(1, sizeof(*node
))))
1476 return E_OUTOFMEMORY
;
1477 node
->parent
= parent
;
1479 if ((comp_moniker
= unsafe_impl_from_IMoniker(moniker
)))
1481 moniker_get_tree_representation(comp_moniker
->left
, node
, &node
->left
);
1482 moniker_get_tree_representation(comp_moniker
->right
, node
, &node
->right
);
1486 node
->moniker
= moniker
;
1487 IMoniker_AddRef(node
->moniker
);
1495 static struct comp_node
*moniker_tree_get_rightmost(struct comp_node
*root
)
1497 if (!root
->left
&& !root
->right
) return root
->moniker
? root
: NULL
;
1498 while (root
->right
) root
= root
->right
;
1502 static struct comp_node
*moniker_tree_get_leftmost(struct comp_node
*root
)
1504 if (!root
->left
&& !root
->right
) return root
->moniker
? root
: NULL
;
1505 while (root
->left
) root
= root
->left
;
1509 static void moniker_tree_node_release(struct comp_node
*node
)
1512 IMoniker_Release(node
->moniker
);
1516 static void moniker_tree_release(struct comp_node
*node
)
1519 moniker_tree_node_release(node
->left
);
1521 moniker_tree_node_release(node
->right
);
1522 moniker_tree_node_release(node
);
1525 static void moniker_tree_replace_node(struct comp_node
*node
, struct comp_node
*replace_with
)
1529 if (node
->parent
->left
== node
) node
->parent
->left
= replace_with
;
1530 else node
->parent
->right
= replace_with
;
1531 replace_with
->parent
= node
->parent
;
1533 else if (replace_with
->moniker
)
1535 /* Replacing root with non-composite */
1536 node
->moniker
= replace_with
->moniker
;
1537 IMoniker_AddRef(node
->moniker
);
1538 node
->left
= node
->right
= NULL
;
1539 moniker_tree_node_release(replace_with
);
1543 /* Attaching composite branches to the root */
1544 node
->left
= replace_with
->left
;
1545 node
->right
= replace_with
->right
;
1546 moniker_tree_node_release(replace_with
);
1550 static void moniker_tree_discard(struct comp_node
*node
, BOOL left
)
1554 moniker_tree_replace_node(node
->parent
, left
? node
->parent
->left
: node
->parent
->right
);
1555 moniker_tree_node_release(node
);
1559 IMoniker_Release(node
->moniker
);
1560 node
->moniker
= NULL
;
1564 static HRESULT
moniker_create_from_tree(const struct comp_node
*root
, unsigned int *count
, IMoniker
**moniker
)
1566 IMoniker
*left_moniker
, *right_moniker
;
1571 /* Non-composite node */
1572 if (!root
->left
&& !root
->right
)
1575 *moniker
= root
->moniker
;
1576 if (*moniker
) IMoniker_AddRef(*moniker
);
1580 if (FAILED(hr
= moniker_create_from_tree(root
->left
, count
, &left_moniker
))) return hr
;
1581 if (FAILED(hr
= moniker_create_from_tree(root
->right
, count
, &right_moniker
)))
1583 IMoniker_Release(left_moniker
);
1587 hr
= CreateGenericComposite(left_moniker
, right_moniker
, moniker
);
1588 IMoniker_Release(left_moniker
);
1589 IMoniker_Release(right_moniker
);
1593 static void moniker_get_tree_comp_count(const struct comp_node
*root
, unsigned int *count
)
1595 if (!root
->left
&& !root
->right
)
1601 moniker_get_tree_comp_count(root
->left
, count
);
1602 moniker_get_tree_comp_count(root
->right
, count
);
1605 static HRESULT
composite_get_rightmost(CompositeMonikerImpl
*composite
, IMoniker
**left
, IMoniker
**rightmost
)
1607 struct comp_node
*root
, *node
;
1611 /* Shortcut for trivial case when right component is non-composite */
1612 if (!unsafe_impl_from_IMoniker(composite
->right
))
1614 *left
= composite
->left
;
1615 IMoniker_AddRef(*left
);
1616 *rightmost
= composite
->right
;
1617 IMoniker_AddRef(*rightmost
);
1621 *left
= *rightmost
= NULL
;
1623 if (FAILED(hr
= moniker_get_tree_representation(&composite
->IMoniker_iface
, NULL
, &root
)))
1626 if (!(node
= moniker_tree_get_rightmost(root
)))
1628 WARN("Couldn't get right most component.\n");
1629 moniker_tree_release(root
);
1633 *rightmost
= node
->moniker
;
1634 IMoniker_AddRef(*rightmost
);
1635 moniker_tree_discard(node
, TRUE
);
1637 hr
= moniker_create_from_tree(root
, &count
, left
);
1638 moniker_tree_release(root
);
1641 IMoniker_Release(*rightmost
);
1648 static HRESULT
composite_get_leftmost(CompositeMonikerImpl
*composite
, IMoniker
**leftmost
)
1650 struct comp_node
*root
, *node
;
1653 if (!unsafe_impl_from_IMoniker(composite
->left
))
1655 *leftmost
= composite
->left
;
1656 IMoniker_AddRef(*leftmost
);
1660 if (FAILED(hr
= moniker_get_tree_representation(&composite
->IMoniker_iface
, NULL
, &root
)))
1663 if (!(node
= moniker_tree_get_leftmost(root
)))
1665 WARN("Couldn't get left most component.\n");
1666 moniker_tree_release(root
);
1670 *leftmost
= node
->moniker
;
1671 IMoniker_AddRef(*leftmost
);
1673 moniker_tree_release(root
);
1678 static HRESULT
moniker_simplify_composition(IMoniker
*left
, IMoniker
*right
,
1679 unsigned int *count
, IMoniker
**new_left
, IMoniker
**new_right
)
1681 struct comp_node
*left_tree
, *right_tree
;
1682 unsigned int modified
= 0;
1688 moniker_get_tree_representation(left
, NULL
, &left_tree
);
1689 moniker_get_tree_representation(right
, NULL
, &right_tree
);
1691 /* Simplify by composing trees together, in a non-generic way. */
1694 struct comp_node
*l
, *r
;
1696 if (!(l
= moniker_tree_get_rightmost(left_tree
))) break;
1697 if (!(r
= moniker_tree_get_leftmost(right_tree
))) break;
1700 if (FAILED(IMoniker_ComposeWith(l
->moniker
, r
->moniker
, TRUE
, &c
))) break;
1705 /* Replace with composed moniker on the left side */
1706 IMoniker_Release(l
->moniker
);
1710 moniker_tree_discard(l
, TRUE
);
1711 moniker_tree_discard(r
, FALSE
);
1717 IMoniker_AddRef(*new_left
);
1719 IMoniker_AddRef(*new_right
);
1721 moniker_get_tree_comp_count(left_tree
, count
);
1722 moniker_get_tree_comp_count(right_tree
, count
);
1726 hr
= moniker_create_from_tree(left_tree
, count
, new_left
);
1728 hr
= moniker_create_from_tree(right_tree
, count
, new_right
);
1731 moniker_tree_release(left_tree
);
1732 moniker_tree_release(right_tree
);
1736 if (*new_left
) IMoniker_Release(*new_left
);
1737 if (*new_right
) IMoniker_Release(*new_right
);
1738 *new_left
= *new_right
= NULL
;
1744 static HRESULT
create_composite(IMoniker
*left
, IMoniker
*right
, IMoniker
**moniker
)
1746 IMoniker
*new_left
, *new_right
;
1747 CompositeMonikerImpl
*object
;
1752 if (!(object
= calloc(1, sizeof(*object
))))
1753 return E_OUTOFMEMORY
;
1755 object
->IMoniker_iface
.lpVtbl
= &VT_CompositeMonikerImpl
;
1756 object
->IROTData_iface
.lpVtbl
= &VT_ROTDataImpl
;
1757 object
->IMarshal_iface
.lpVtbl
= &VT_MarshalImpl
;
1760 /* Uninitialized moniker created by object activation */
1761 if (!left
&& !right
)
1763 *moniker
= &object
->IMoniker_iface
;
1767 if (FAILED(hr
= moniker_simplify_composition(left
, right
, &object
->comp_count
, &new_left
, &new_right
)))
1769 IMoniker_Release(&object
->IMoniker_iface
);
1773 if (!new_left
|| !new_right
)
1775 *moniker
= new_left
? new_left
: new_right
;
1776 IMoniker_Release(&object
->IMoniker_iface
);
1780 object
->left
= new_left
;
1781 object
->right
= new_right
;
1783 *moniker
= &object
->IMoniker_iface
;
1788 /******************************************************************************
1789 * CreateGenericComposite [OLE32.@]
1790 ******************************************************************************/
1791 HRESULT WINAPI
CreateGenericComposite(IMoniker
*left
, IMoniker
*right
, IMoniker
**composite
)
1793 TRACE("%p, %p, %p\n", left
, right
, composite
);
1801 IMoniker_AddRef(*composite
);
1804 else if (left
&& !right
)
1807 IMoniker_AddRef(*composite
);
1810 else if (!left
&& !right
)
1813 return create_composite(left
, right
, composite
);
1816 /******************************************************************************
1817 * MonikerCommonPrefixWith [OLE32.@]
1818 ******************************************************************************/
1820 MonikerCommonPrefixWith(IMoniker
* pmkThis
,IMoniker
* pmkOther
,IMoniker
** ppmkCommon
)
1822 FIXME("(),stub!\n");
1826 HRESULT WINAPI
CompositeMoniker_CreateInstance(IClassFactory
*iface
,
1827 IUnknown
*pUnk
, REFIID riid
, void **ppv
)
1832 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
1837 return CLASS_E_NOAGGREGATION
;
1839 hr
= create_composite(NULL
, NULL
, &pMoniker
);
1843 hr
= IMoniker_QueryInterface(pMoniker
, riid
, ppv
);
1844 IMoniker_Release(pMoniker
);