From 558e84660825b406e244750cc7a4136a99f8207a Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 28 Sep 2021 15:56:27 +0300 Subject: [PATCH] ole32/composite: Reimplement Inverse(). Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/ole32/compositemoniker.c | 65 ++++++++----------------- dlls/ole32/tests/moniker.c | 92 ++++++++++++++++++++++++++++++----- 2 files changed, 99 insertions(+), 58 deletions(-) diff --git a/dlls/ole32/compositemoniker.c b/dlls/ole32/compositemoniker.c index 40889ae42b2..b2ec02e1150 100644 --- a/dlls/ole32/compositemoniker.c +++ b/dlls/ole32/compositemoniker.c @@ -740,57 +740,32 @@ static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker *iface, return hr; } -/****************************************************************************** - * CompositeMoniker_Inverse - ******************************************************************************/ -static HRESULT WINAPI -CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk) +static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker *iface, IMoniker **inverse) { - HRESULT res; - IMoniker *tempMk,*antiMk,*rightMostMk,*tempInvMk,*rightMostInvMk; - IEnumMoniker *enumMoniker; + CompositeMonikerImpl *moniker = impl_from_IMoniker(iface); + IMoniker *right_inverted, *left_inverted; + HRESULT hr; - TRACE("(%p,%p)\n",iface,ppmk); + TRACE("%p, %p.\n", iface, inverse); - if (ppmk==NULL) - return E_POINTER; + if (!inverse) + return E_INVALIDARG; - /* This method returns a composite moniker that consists of the inverses of each of the components */ - /* of the original composite, stored in reverse order */ + *inverse = NULL; - *ppmk = NULL; - - res=CreateAntiMoniker(&antiMk); - if (FAILED(res)) - return res; - - res=IMoniker_ComposeWith(iface,antiMk,FALSE,&tempMk); - IMoniker_Release(antiMk); - if (FAILED(res)) - return res; - - if (tempMk==NULL) - - return IMoniker_Inverse(iface,ppmk); - - else{ - - IMoniker_Enum(iface,FALSE,&enumMoniker); - IEnumMoniker_Next(enumMoniker,1,&rightMostMk,NULL); - IEnumMoniker_Release(enumMoniker); - - IMoniker_Inverse(rightMostMk,&rightMostInvMk); - CompositeMonikerImpl_Inverse(tempMk,&tempInvMk); - - res=CreateGenericComposite(rightMostInvMk,tempInvMk,ppmk); - - IMoniker_Release(tempMk); - IMoniker_Release(rightMostMk); - IMoniker_Release(tempInvMk); - IMoniker_Release(rightMostInvMk); - - return res; + if (FAILED(hr = IMoniker_Inverse(moniker->right, &right_inverted))) return hr; + if (FAILED(hr = IMoniker_Inverse(moniker->left, &left_inverted))) + { + IMoniker_Release(right_inverted); + return hr; } + + hr = CreateGenericComposite(right_inverted, left_inverted, inverse); + + IMoniker_Release(left_inverted); + IMoniker_Release(right_inverted); + + return hr; } static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker *iface, IMoniker *other, diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index 7d88c132d3d..7f0b9ec5841 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -53,18 +53,21 @@ static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOO #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr) -#define CHECK_EXPECTED_METHOD(method_name) \ -do { \ - ok(*expected_method_list != NULL, "Extra method %s called\n", method_name); \ - if (*expected_method_list) \ - { \ - ok(!strcmp(*expected_method_list, method_name), "Expected %s to be called instead of %s\n", \ - *expected_method_list, method_name); \ - expected_method_list++; \ - } \ -} while(0) - static char const * const *expected_method_list; + +#define CHECK_EXPECTED_METHOD(method_name) check_expected_method_(__LINE__, method_name) +static void check_expected_method_(unsigned int line, const char *method_name) +{ + if (!expected_method_list) return; + ok(*expected_method_list != NULL, "Extra method %s called\n", method_name); + if (*expected_method_list) + { + ok(!strcmp(*expected_method_list, method_name), "Expected %s to be called instead of %s\n", + *expected_method_list, method_name); + expected_method_list++; + } +} + static const WCHAR wszFileName1[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','1','.','d','o','c',0}; static const WCHAR wszFileName2[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','2','.','d','o','c',0}; @@ -384,6 +387,7 @@ struct test_moniker IOleItemContainer IOleItemContainer_iface; IParseDisplayName IParseDisplayName_iface; LONG refcount; + const char *inverse; BOOL no_IROTData; }; @@ -665,7 +669,7 @@ Moniker_ComposeWith(IMoniker* iface, IMoniker* pmkRight, BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite) { CHECK_EXPECTED_METHOD("Moniker_ComposeWith"); - return E_NOTIMPL; + return MK_E_NEEDGENERIC; } static HRESULT WINAPI @@ -714,8 +718,9 @@ Moniker_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, static HRESULT WINAPI Moniker_Inverse(IMoniker* iface,IMoniker** ppmk) { + struct test_moniker *moniker = impl_from_IMoniker(iface); CHECK_EXPECTED_METHOD("Moniker_Inverse"); - return E_NOTIMPL; + return create_moniker_from_desc(moniker->inverse, ppmk); } static HRESULT WINAPI @@ -933,6 +938,7 @@ static void test_ROT(void) hr = IRunningObjectTable_IsRunning(pROT, &test_moniker->IMoniker_iface); ok_ole_success(hr, IRunningObjectTable_IsRunning); ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list); + expected_method_list = NULL; hr = IRunningObjectTable_Revoke(pROT, dwCookie); ok_ole_success(hr, IRunningObjectTable_Revoke); @@ -2545,6 +2551,7 @@ static void test_item_moniker(void) expected_method_list = methods_isrunning; hr = IMoniker_IsRunning(moniker, bindctx, &container_moniker->IMoniker_iface, moniker2); ok(hr == 0x8beef000, "Unexpected hr %#x.\n", hr); + expected_method_list = NULL; IMoniker_Release(moniker2); @@ -3043,6 +3050,7 @@ static void test_generic_composite_moniker(void) { "CI1I3", "CA1I2", MKSYS_GENERICCOMPOSITE, L"!I1!I2" }, }; IMoniker *moniker, *inverse, *moniker1, *moniker2, *moniker3; + struct test_moniker *m, *m2; IEnumMoniker *enummoniker; IRunningObjectTable *rot; DWORD hash, cookie; @@ -3377,6 +3385,64 @@ todo_wine IMoniker_Release(moniker2); IMoniker_Release(moniker1); + /* Inverse() */ + hr = create_moniker_from_desc("CI1I2", &moniker1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IMoniker_Inverse(moniker1, NULL); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + hr = IMoniker_Inverse(moniker1, &inverse); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + TEST_MONIKER_TYPE(inverse, MKSYS_GENERICCOMPOSITE); + TEST_DISPLAY_NAME(inverse, L"\\..\\.."); + IMoniker_Release(inverse); + IMoniker_Release(moniker1); + + hr = create_moniker_from_desc("CA1A2", &moniker1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + inverse = (void *)0xdeadbeef; + hr = IMoniker_Inverse(moniker1, &inverse); + ok(hr == MK_E_NOINVERSE, "Unexpected hr %#x.\n", hr); + ok(!inverse, "Unexpected pointer.\n"); + IMoniker_Release(moniker1); + + hr = create_moniker_from_desc("CI1A2", &moniker1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + inverse = (void *)0xdeadbeef; + hr = IMoniker_Inverse(moniker1, &inverse); + ok(hr == MK_E_NOINVERSE, "Unexpected hr %#x.\n", hr); + ok(!inverse, "Unexpected pointer.\n"); + IMoniker_Release(moniker1); + + /* Now with custom moniker to observe inverse order */ + m = create_test_moniker(); + m->inverse = "I5"; + hr = create_moniker_from_desc("I1", &moniker1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = CreateGenericComposite(moniker1, &m->IMoniker_iface, &moniker2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + TEST_MONIKER_TYPE(moniker2, MKSYS_GENERICCOMPOSITE); + inverse = (void *)0xdeadbeef; + hr = IMoniker_Inverse(moniker2, &inverse); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!inverse, "Unexpected pointer.\n"); + IMoniker_Release(moniker1); + + /* Use custom monikers for both, so they don't invert to anti monikers. */ + m2 = create_test_moniker(); + m2->inverse = "I4"; + + hr = CreateGenericComposite(&m2->IMoniker_iface, &m->IMoniker_iface, &moniker2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IMoniker_Inverse(moniker2, &inverse); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + TEST_MONIKER_TYPE(inverse, MKSYS_GENERICCOMPOSITE); + TEST_DISPLAY_NAME(inverse, L"!I5!I4"); + IMoniker_Release(inverse); + IMoniker_Release(moniker2); + + IMoniker_Release(&m->IMoniker_iface); + IMoniker_Release(&m2->IMoniker_iface); + IBindCtx_Release(bindctx); }