Signed-off-by: Nikolay Sivov nsivov@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); }