[PATCH 2/5] ole32/composite: Do not use enumerators and antimoniker composition in RelativePathTo().
Nikolay Sivov
nsivov at codeweavers.com
Thu Sep 30 03:26:46 CDT 2021
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/ole32/compositemoniker.c | 233 ++++++++++++++--------------------
dlls/ole32/tests/moniker.c | 12 ++
2 files changed, 108 insertions(+), 137 deletions(-)
diff --git a/dlls/ole32/compositemoniker.c b/dlls/ole32/compositemoniker.c
index e5437c8880f..cde3f1762f0 100644
--- a/dlls/ole32/compositemoniker.c
+++ b/dlls/ole32/compositemoniker.c
@@ -473,23 +473,29 @@ static void composite_get_components(IMoniker *moniker, IMoniker **components, u
}
}
-static HRESULT composite_get_components_alloc(CompositeMonikerImpl *moniker, IMoniker ***components)
+static HRESULT composite_get_components_alloc(IMoniker *iface, unsigned int *count, IMoniker ***components)
{
+ CompositeMonikerImpl *moniker;
unsigned int index;
- if (!(*components = heap_alloc(moniker->comp_count * sizeof(**components))))
+ if ((moniker = unsafe_impl_from_IMoniker(iface)))
+ *count = moniker->comp_count;
+ else
+ *count = 1;
+
+ if (!(*components = heap_alloc(*count * sizeof(**components))))
return E_OUTOFMEMORY;
index = 0;
- composite_get_components(&moniker->IMoniker_iface, *components, &index);
+ composite_get_components(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 count;
HRESULT hr;
TRACE("%p, %d, %p\n", iface, forward, ppenumMoniker);
@@ -497,10 +503,10 @@ static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker *iface, BOOL forward, I
if (!ppenumMoniker)
return E_INVALIDARG;
- if (FAILED(hr = composite_get_components_alloc(moniker, &monikers)))
+ if (FAILED(hr = composite_get_components_alloc(iface, &count, &monikers)))
return hr;
- hr = EnumMonikerImpl_CreateEnumMoniker(monikers, moniker->comp_count, 0, forward, ppenumMoniker);
+ hr = EnumMonikerImpl_CreateEnumMoniker(monikers, count, 0, forward, ppenumMoniker);
heap_free(monikers);
return hr;
@@ -510,7 +516,7 @@ static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker *iface, IMoniker *ot
{
CompositeMonikerImpl *moniker = impl_from_IMoniker(iface), *other_moniker;
IMoniker **components, **other_components;
- unsigned int i;
+ unsigned int i, count;
HRESULT hr;
TRACE("%p, %p.\n", iface, other);
@@ -524,8 +530,8 @@ static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker *iface, IMoniker *ot
if (moniker->comp_count != other_moniker->comp_count)
return S_FALSE;
- if (FAILED(hr = composite_get_components_alloc(moniker, &components))) return hr;
- if (FAILED(hr = composite_get_components_alloc(other_moniker, &other_components)))
+ if (FAILED(hr = composite_get_components_alloc(iface, &count, &components))) return hr;
+ if (FAILED(hr = composite_get_components_alloc(other, &count, &other_components)))
{
heap_free(components);
return hr;
@@ -715,8 +721,8 @@ static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker *iface, IMo
IMoniker **components, **other_components, **prefix_components;
IMoniker *last, *c;
- if (FAILED(hr = composite_get_components_alloc(moniker, &components))) return hr;
- if (FAILED(hr = composite_get_components_alloc(other_moniker, &other_components)))
+ if (FAILED(hr = composite_get_components_alloc(iface, &count, &components))) return hr;
+ if (FAILED(hr = composite_get_components_alloc(other, &count, &other_components)))
{
heap_free(components);
return hr;
@@ -788,156 +794,109 @@ static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker *iface, IMo
return hr;
}
-/***************************************************************************************************
- * GetAfterCommonPrefix (local function)
- * This function returns a moniker that consist of the remainder when the common prefix is removed
- ***************************************************************************************************/
-static VOID GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
+static HRESULT composite_compose_components(IMoniker **comp, unsigned int count, IMoniker **ret)
{
- IMoniker *tempMk,*tempMk1,*tempMk2;
- IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
- ULONG nbRestMk=0;
- DWORD mkSys;
- HRESULT res1,res2;
-
- *restMk=0;
-
- /* to create an enumerator for pGenMk with current position pointed on the first element after common */
- /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
- /* on the first difference. */
- IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
-
- IMoniker_IsSystemMoniker(commonMk,&mkSys);
-
- if (mkSys==MKSYS_GENERICCOMPOSITE){
-
- IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
- while(1){
-
- res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
- res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
-
- if ((res1==S_FALSE)||(res2==S_FALSE)){
-
- if (res1==S_OK)
-
- nbRestMk++;
+ IMoniker *last, *c;
+ HRESULT hr = S_OK;
+ unsigned int i;
- IMoniker_Release(tempMk1);
- IMoniker_Release(tempMk2);
+ last = comp[0];
+ IMoniker_AddRef(last);
- break;
- }
- IMoniker_Release(tempMk1);
- IMoniker_Release(tempMk2);
- }
- }
- else{
- IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
- IMoniker_Release(tempMk1);
+ for (i = 1; i < count; ++i)
+ {
+ hr = CreateGenericComposite(last, comp[i], &c);
+ IMoniker_Release(last);
+ if (FAILED(hr)) break;
+ last = c;
}
- /* count the number of elements in the enumerator after the common prefix */
- IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
+ *ret = SUCCEEDED(hr) ? last : NULL;
- for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
+ return hr;
+}
- IMoniker_Release(tempMk);
+static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker *iface, IMoniker *other,
+ IMoniker **relpath)
+{
+ unsigned int count, this_count, other_count, prefix_len = 0;
+ IMoniker *inv, *tail = NULL, *other_tail = NULL, *rel = NULL;
+ IMoniker **components, **other_components;
+ unsigned int start = 0, other_start = 0;
+ HRESULT hr;
- if (nbRestMk==0)
- return;
+ TRACE("%p, %p, %p.\n", iface, other, relpath);
- /* create a generic composite moniker with monikers located after the common prefix */
- IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
+ if (!relpath)
+ return E_INVALIDARG;
- if (nbRestMk==1){
+ *relpath = NULL;
- *restMk= tempMk1;
- return;
+ if (FAILED(hr = composite_get_components_alloc(iface, &this_count, &components))) return hr;
+ if (FAILED(hr = composite_get_components_alloc(other, &other_count, &other_components)))
+ {
+ heap_free(components);
+ return hr;
}
- else {
-
- IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
-
- CreateGenericComposite(tempMk1,tempMk2,restMk);
- IMoniker_Release(tempMk1);
-
- IMoniker_Release(tempMk2);
-
- while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
-
- CreateGenericComposite(*restMk,tempMk1,&tempMk2);
+ /* Skip common prefix of equal components */
+ count = min(other_count, this_count);
+ while (IMoniker_IsEqual(components[prefix_len], other_components[prefix_len]) == S_OK)
+ {
+ if (++prefix_len == count) break;
+ }
- IMoniker_Release(tempMk1);
+ if (prefix_len)
+ {
+ this_count -= prefix_len;
+ other_count -= prefix_len;
+ other_start += prefix_len;
+ start += prefix_len;
+ }
+ else
+ {
+ /* Replace first component of the other tail with relative path */
+ if (SUCCEEDED(hr = IMoniker_RelativePathTo(*components, *other_components, &rel)))
+ *other_components = rel;
- IMoniker_Release(*restMk);
+ this_count--;
+ start++;
+ }
- *restMk=tempMk2;
+ /* Invert left side tail */
+ if (this_count && SUCCEEDED(hr))
+ {
+ if (SUCCEEDED(hr = composite_compose_components(&components[start], this_count, &tail)))
+ {
+ hr = IMoniker_Inverse(tail, &inv);
+ IMoniker_Release(tail);
+ tail = inv;
}
}
-}
-
-/******************************************************************************
- * CompositeMoniker_RelativePathTo
- ******************************************************************************/
-static HRESULT WINAPI
-CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther,
- IMoniker** ppmkRelPath)
-{
- HRESULT res;
- IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
-
- TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
-
- if (ppmkRelPath==NULL)
- return E_POINTER;
-
- *ppmkRelPath=0;
- /* This method finds the common prefix of the two monikers and creates two monikers that consist */
- /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
- /* of this moniker and composes the remainder of the other moniker on the right of it. */
+ if (other_count && SUCCEEDED(hr))
+ hr = composite_compose_components(&other_components[other_start], other_count, &other_tail);
- /* finds the common prefix of the two monikers */
- res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
-
- /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
- if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
-
- *ppmkRelPath=pmkOther;
- IMoniker_AddRef(pmkOther);
- return MK_S_HIM;
+ if (tail || other_tail)
+ hr = CreateGenericComposite(tail, other_tail, relpath);
+ else if (SUCCEEDED(hr))
+ {
+ *relpath = other;
+ IMoniker_AddRef(*relpath);
+ hr = MK_S_HIM;
}
- GetAfterCommonPrefix(iface,commonMk,&restThisMk);
- GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
-
- /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
- /* moniker when the common prefix is removed */
- if (res==MK_S_HIM){
+ if (rel)
+ IMoniker_Release(rel);
+ if (tail)
+ IMoniker_Release(tail);
+ if (other_tail)
+ IMoniker_Release(other_tail);
- IMoniker_Inverse(restThisMk,ppmkRelPath);
- IMoniker_Release(restThisMk);
- }
- /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
- /* when the common prefix is removed */
- else if (res==MK_S_ME){
-
- *ppmkRelPath=restOtherMk;
- IMoniker_AddRef(restOtherMk);
- }
- /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
- /* moniker on the right of it. */
- else if (res==S_OK){
+ heap_free(other_components);
+ heap_free(components);
- IMoniker_Inverse(restThisMk,&invRestThisMk);
- IMoniker_Release(restThisMk);
- CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
- IMoniker_Release(invRestThisMk);
- IMoniker_Release(restOtherMk);
- }
- return S_OK;
+ return hr;
}
static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c
index ed2accff6a9..a60472951f7 100644
--- a/dlls/ole32/tests/moniker.c
+++ b/dlls/ole32/tests/moniker.c
@@ -3810,6 +3810,18 @@ todo_wine {
IMoniker_Release(moniker);
+ /* RelativePathTo() */
+ hr = create_moniker_from_desc("CI1I2", &moniker1);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = create_moniker_from_desc("CI2I3", &moniker2);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMoniker_RelativePathTo(moniker1, NULL, NULL);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+ hr = IMoniker_RelativePathTo(moniker1, moniker2, &moniker3);
+ ok(hr == MK_E_NOTBINDABLE, "Unexpected hr %#x.\n", hr);
+
IBindCtx_Release(bindctx);
}
--
2.33.0
More information about the wine-devel
mailing list