[PATCH 3/5] ole32/composite: Implement CommonPrefixWith() without iterators.
Nikolay Sivov
nsivov at codeweavers.com
Mon Sep 27 07:31:38 CDT 2021
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/ole32/compositemoniker.c | 230 +++++++++++++++++-----------------
dlls/ole32/tests/moniker.c | 15 ++-
2 files changed, 128 insertions(+), 117 deletions(-)
diff --git a/dlls/ole32/compositemoniker.c b/dlls/ole32/compositemoniker.c
index efb0e9de9e8..4eb9b32fe5e 100644
--- a/dlls/ole32/compositemoniker.c
+++ b/dlls/ole32/compositemoniker.c
@@ -88,6 +88,7 @@ static inline EnumMonikerImpl *impl_from_IEnumMoniker(IEnumMoniker *iface)
static HRESULT EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRight,IEnumMoniker ** ppmk);
static HRESULT composite_get_rightmost(CompositeMonikerImpl *composite, IMoniker **left, IMoniker **rightmost);
+static HRESULT composite_get_leftmost(CompositeMonikerImpl *composite, IMoniker **leftmost);
/*******************************************************************************
* CompositeMoniker_QueryInterface
@@ -524,11 +525,23 @@ static void composite_get_components(IMoniker *moniker, IMoniker **components, u
}
}
+static HRESULT composite_get_components_alloc(CompositeMonikerImpl *moniker, IMoniker ***components)
+{
+ unsigned int index;
+
+ if (!(*components = heap_alloc(moniker->comp_count * sizeof(**components))))
+ return E_OUTOFMEMORY;
+
+ index = 0;
+ composite_get_components(&moniker->IMoniker_iface, *components, &index);
+
+ return S_OK;
+}
+
static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker *iface, BOOL forward, IEnumMoniker **ppenumMoniker)
{
CompositeMonikerImpl *moniker = impl_from_IMoniker(iface);
IMoniker **monikers;
- unsigned int index;
HRESULT hr;
TRACE("%p, %d, %p\n", iface, forward, ppenumMoniker);
@@ -536,11 +549,8 @@ static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker *iface, BOOL forward, I
if (!ppenumMoniker)
return E_POINTER;
- if (!(monikers = heap_alloc(moniker->comp_count * sizeof(*monikers))))
- return E_OUTOFMEMORY;
-
- index = 0;
- composite_get_components(iface, monikers, &index);
+ if (FAILED(hr = composite_get_components_alloc(moniker, &monikers)))
+ return hr;
hr = EnumMonikerImpl_CreateEnumMoniker(monikers, moniker->comp_count, 0, forward, ppenumMoniker);
heap_free(monikers);
@@ -812,135 +822,102 @@ CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
}
}
-/******************************************************************************
- * CompositeMoniker_CommonPrefixWith
- ******************************************************************************/
-static HRESULT WINAPI
-CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface, IMoniker* pmkOther,
- IMoniker** ppmkPrefix)
+static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker *iface, IMoniker *other,
+ IMoniker **prefix)
{
- DWORD mkSys;
- HRESULT res1,res2;
- IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
- IEnumMoniker *enumMoniker1,*enumMoniker2;
- ULONG i,nbCommonMk=0;
+ CompositeMonikerImpl *moniker = impl_from_IMoniker(iface), *other_moniker;
+ unsigned int i, count, prefix_len = 0;
+ IMoniker *leftmost;
+ HRESULT hr;
+
+ TRACE("%p, %p, %p.\n", iface, other, prefix);
/* If the other moniker is a composite, this method compares the components of each composite from left */
/* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
/* of the leftmost components were common to both monikers. */
- if (ppmkPrefix==NULL)
- return E_POINTER;
-
- *ppmkPrefix=0;
-
- if (pmkOther==NULL)
- return MK_E_NOPREFIX;
+ if (prefix)
+ *prefix = NULL;
- IMoniker_IsSystemMoniker(pmkOther,&mkSys);
-
- if(mkSys==MKSYS_GENERICCOMPOSITE){
-
- IMoniker_Enum(iface,TRUE,&enumMoniker1);
- IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
-
- while(1){
-
- res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
- res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
-
- if ((res1==S_FALSE) && (res2==S_FALSE)){
-
- /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
- *ppmkPrefix=iface;
- IMoniker_AddRef(iface);
- return MK_S_US;
- }
- else if ((res1==S_OK) && (res2==S_OK)){
-
- if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
-
- nbCommonMk++;
-
- else
- break;
+ if (!other || !prefix)
+ return E_INVALIDARG;
- }
- else if (res1==S_OK){
+ if ((other_moniker = unsafe_impl_from_IMoniker(other)))
+ {
+ IMoniker **components, **other_components, **prefix_components;
+ IMoniker *last, *c;
- /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
- /* ppmkPrefix to the other moniker. */
- *ppmkPrefix=pmkOther;
- return MK_S_HIM;
- }
- else{
- /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
- /* to this moniker. */
- *ppmkPrefix=iface;
- return MK_S_ME;
- }
+ if (FAILED(hr = composite_get_components_alloc(moniker, &components))) return hr;
+ if (FAILED(hr = composite_get_components_alloc(other_moniker, &other_components)))
+ {
+ heap_free(components);
+ return hr;
}
- IEnumMoniker_Release(enumMoniker1);
- IEnumMoniker_Release(enumMoniker2);
-
- /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
- if (nbCommonMk==0)
- return MK_E_NOPREFIX;
-
- IEnumMoniker_Reset(enumMoniker1);
-
- IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
-
- /* if we have more than one common moniker the result will be a composite moniker */
- if (nbCommonMk>1){
-
- /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
- IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
- CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
- IMoniker_Release(tempMk1);
- IMoniker_Release(tempMk2);
-
- /* compose all common monikers in a composite moniker */
- for(i=0;i<nbCommonMk;i++){
+ count = min(moniker->comp_count, other_moniker->comp_count);
+ if (!(prefix_components = heap_calloc(count, sizeof(*prefix_components))))
+ {
+ heap_free(components);
+ heap_free(other_components);
+ return E_OUTOFMEMORY;
+ }
- IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
+ /* Collect prefix components */
+ for (i = 0; i < count; ++i)
+ {
+ IMoniker *p;
- CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
+ if (FAILED(hr = IMoniker_CommonPrefixWith(components[i], other_components[i], &p)))
+ break;
+ prefix_components[prefix_len++] = p;
+ /* S_OK means that prefix was found and is neither of tested monikers */
+ if (hr == S_OK) break;
+ }
- IMoniker_Release(*ppmkPrefix);
+ heap_free(components);
+ heap_free(other_components);
- IMoniker_Release(tempMk1);
+ if (!prefix_len) return MK_E_NOPREFIX;
- *ppmkPrefix=tempMk2;
- }
- return S_OK;
+ last = prefix_components[0];
+ for (i = 1; i < prefix_len; ++i)
+ {
+ hr = CreateGenericComposite(last, prefix_components[i], &c);
+ IMoniker_Release(last);
+ IMoniker_Release(prefix_components[i]);
+ if (FAILED(hr)) break;
+ last = c;
}
- else{
- /* if we have only one common moniker the result will be a simple moniker which is the most-left one*/
- *ppmkPrefix=tempMk1;
+ heap_free(prefix_components);
- return S_OK;
+ if (SUCCEEDED(hr))
+ {
+ *prefix = last;
+ if (IMoniker_IsEqual(iface, *prefix) == S_OK)
+ hr = MK_S_US;
+ else if (prefix_len < count)
+ hr = S_OK;
+ else
+ hr = prefix_len == moniker->comp_count ? MK_S_ME : MK_S_HIM;
}
- }
- else{
- /* If the other moniker is not a composite, the method simply compares it to the leftmost component
- of this moniker.*/
-
- IMoniker_Enum(iface,TRUE,&enumMoniker1);
-
- IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
- if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
-
- *ppmkPrefix=pmkOther;
- IMoniker_AddRef(*ppmkPrefix);
+ return hr;
+ }
- return MK_S_HIM;
+ /* For non-composite, compare to leftmost component */
+ if (SUCCEEDED(hr = composite_get_leftmost(moniker, &leftmost)))
+ {
+ if ((hr = IMoniker_IsEqual(leftmost, other)) == S_OK)
+ {
+ *prefix = leftmost;
+ IMoniker_AddRef(*prefix);
}
- else
- return MK_E_NOPREFIX;
+
+ hr = hr == S_OK ? MK_S_HIM : MK_E_NOPREFIX;
+ IMoniker_Release(leftmost);
}
+
+ return hr;
}
/***************************************************************************************************
@@ -1866,6 +1843,35 @@ static HRESULT composite_get_rightmost(CompositeMonikerImpl *composite, IMoniker
return hr;
}
+static HRESULT composite_get_leftmost(CompositeMonikerImpl *composite, IMoniker **leftmost)
+{
+ struct comp_node *root, *node;
+ HRESULT hr;
+
+ if (!unsafe_impl_from_IMoniker(composite->left))
+ {
+ *leftmost = composite->left;
+ IMoniker_AddRef(*leftmost);
+ return S_OK;
+ }
+
+ if (FAILED(hr = moniker_get_tree_representation(&composite->IMoniker_iface, NULL, &root)))
+ return hr;
+
+ if (!(node = moniker_tree_get_leftmost(root)))
+ {
+ WARN("Couldn't get right most component.\n");
+ return E_FAIL;
+ }
+
+ *leftmost = node->moniker;
+ IMoniker_AddRef(*leftmost);
+
+ moniker_tree_release(root);
+
+ return S_OK;
+}
+
static HRESULT moniker_simplify_composition(IMoniker *left, IMoniker *right,
unsigned int *count, IMoniker **new_left, IMoniker **new_right)
{
diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c
index ed55ec3e825..1e4c2e0211d 100644
--- a/dlls/ole32/tests/moniker.c
+++ b/dlls/ole32/tests/moniker.c
@@ -3290,24 +3290,30 @@ todo_wine
hr = create_moniker_from_desc("CI1I2", &moniker1);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ hr = IMoniker_CommonPrefixWith(moniker, NULL, NULL);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+ hr = IMoniker_CommonPrefixWith(moniker, moniker1, NULL);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
moniker2 = (void *)0xdeadbeef;
hr = IMoniker_CommonPrefixWith(moniker, NULL, &moniker2);
-todo_wine
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
ok(!moniker2, "Unexpected pointer.\n");
/* With itself */
hr = IMoniker_CommonPrefixWith(moniker, moniker, &moniker2);
+todo_wine
ok(hr == MK_S_US, "Unexpected hr %#x.\n", hr);
+ hr = IMoniker_IsEqual(moniker, moniker2);
todo_wine
- ok(moniker2 != moniker, "Unexpected object.\n");
- TEST_DISPLAY_NAME(moniker2, L"!I1!I2");
+ ok(hr == S_OK && moniker2 != moniker, "Unexpected hr %#x.\n", hr);
IMoniker_Release(moniker2);
/* Equal composites */
hr = IMoniker_CommonPrefixWith(moniker, moniker1, &moniker2);
- ok(hr == MK_S_US, "Unexpected hr %#x.\n", hr);
todo_wine
+ ok(hr == MK_S_US, "Unexpected hr %#x.\n", hr);
ok(moniker2 != moniker && moniker2 != moniker1, "Unexpected object.\n");
hr = IMoniker_IsEqual(moniker, moniker2);
todo_wine
@@ -3325,7 +3331,6 @@ todo_wine
hr = IMoniker_CommonPrefixWith(moniker, moniker2, &moniker3);
ok(hr == MK_S_HIM, "Unexpected hr %#x.\n", hr);
hr = IMoniker_IsEqual(moniker2, moniker3);
-todo_wine
ok(hr == S_OK && moniker3 != moniker2, "Unexpected object.\n");
IMoniker_Release(moniker3);
--
2.33.0
More information about the wine-devel
mailing list