Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/tests/moniker.c | 167 +++++++++++++++++++++---------------- 1 file changed, 96 insertions(+), 71 deletions(-)
diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index ef1d3869b63..5042f24320b 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -68,15 +68,6 @@ DEFINE_OLEGUID(CLSID_CompositeMoniker, 0x309, 0, 0); DEFINE_OLEGUID(CLSID_ClassMoniker, 0x31a, 0, 0); DEFINE_OLEGUID(CLSID_PointerMoniker, 0x306, 0, 0);
-#define EXPECT_REF(obj,ref) _expect_ref((IUnknown *)obj, ref, __LINE__) -static void _expect_ref(IUnknown* obj, ULONG ref, int line) -{ - ULONG refcount; - IUnknown_AddRef(obj); - refcount = IUnknown_Release(obj); - ok_(__FILE__, line)(refcount == ref, "Unexpected got %u.\n", refcount); -} - #define TEST_MONIKER_TYPE_TODO(m,t) _test_moniker_type(m, t, TRUE, __LINE__) #define TEST_MONIKER_TYPE(m,t) _test_moniker_type(m, t, FALSE, __LINE__) static void _test_moniker_type(IMoniker *moniker, DWORD type, BOOL todo, int line) @@ -2902,9 +2893,65 @@ todo_wine IMoniker_Release(moniker2); }
+static HRESULT create_moniker_from_desc(const char *desc, unsigned int *eaten, + IMoniker **moniker) +{ + IMoniker *left, *right; + WCHAR nameW[3]; + HRESULT hr; + + desc += *eaten; + + switch (*desc) + { + case 'I': + nameW[0] = desc[0]; + nameW[1] = desc[1]; + nameW[2] = 0; + *eaten += 2; + return CreateItemMoniker(L"!", nameW, moniker); + case 'A': + *eaten += 2; + *moniker = create_antimoniker(desc[1] - '0'); + return S_OK; + case 'C': + (*eaten)++; + hr = create_moniker_from_desc(desc, eaten, &left); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = create_moniker_from_desc(desc, eaten, &right); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = CreateGenericComposite(left, right, moniker); + IMoniker_Release(left); + IMoniker_Release(right); + return hr; + default: + ok(0, "Unexpected description %s.\n", desc); + return E_NOTIMPL; + } +} + static void test_generic_composite_moniker(void) { - IMoniker *moniker, *inverse, *inverse2, *moniker1, *moniker2, *moniker3, *moniker4; + static const struct simplify_test + { + const char *left; + const char *right; + unsigned int result_type; + const WCHAR *name; + } + simplify_tests[] = + { + { "I1", "I2", MKSYS_GENERICCOMPOSITE, L"!I1!I2" }, + { "I1", "A2", MKSYS_ANTIMONIKER, L"\.." }, + { "A1", "A1", MKSYS_GENERICCOMPOSITE, L"\..\.." }, + { "A2", "A1", MKSYS_GENERICCOMPOSITE, L"\..\..\.." }, + { "CI1I2", "A1", MKSYS_ITEMMONIKER, L"!I1" }, + { "I1", "A1", MKSYS_NONE }, + { "CI1I2", "A2", MKSYS_NONE }, + { "CI1I2", "A3", MKSYS_ANTIMONIKER, L"\.." }, + { "CI1I3", "CA1I2", MKSYS_GENERICCOMPOSITE, L"!I1!I2" }, + }; + IMoniker *moniker, *inverse, *moniker1, *moniker2; IEnumMoniker *enummoniker; IRunningObjectTable *rot; DWORD hash, cookie; @@ -2915,84 +2962,62 @@ static void test_generic_composite_moniker(void) IROTData *rotdata; IMarshal *marshal; IStream *stream; + unsigned int i; WCHAR *str; ULONG len;
hr = CreateBindCtx(0, &bindctx); ok(hr == S_OK, "Failed to create bind context, hr %#x.\n", hr);
- hr = CreateItemMoniker(L"!", L"Test", &moniker1); - ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr); - hr = CreateItemMoniker(L"#", L"Wine", &moniker2); - ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr); - hr = CreateGenericComposite(moniker1, moniker2, &moniker); - ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr); + for (i = 0; i < ARRAY_SIZE(simplify_tests); ++i) + { + IMoniker *left, *right, *composite = NULL; + unsigned int moniker_type, eaten; + WCHAR *name;
- /* Compose with itself. */ - EXPECT_REF(moniker1, 2); - hr = CreateGenericComposite(moniker1, moniker1, &moniker); - ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr); - EXPECT_REF(moniker1, 4); - TEST_MONIKER_TYPE(moniker, MKSYS_GENERICCOMPOSITE); - IMoniker_Release(moniker); + winetest_push_context("simplify[%u]", i);
- /* (I) + (A) -> () */ - hr = IMoniker_Inverse(moniker1, &inverse); - ok(hr == S_OK, "Failed to invert, hr %#x.\n", hr); - hr = CreateGenericComposite(moniker1, inverse, &moniker); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); - ok(!moniker, "Unexpected pointer.\n"); + eaten = 0; + hr = create_moniker_from_desc(simplify_tests[i].left, &eaten, &left); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + eaten = 0; + hr = create_moniker_from_desc(simplify_tests[i].right, &eaten, &right); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = CreateGenericComposite(left, right, &composite); + ok(hr == S_OK, "Failed to create a composite, hr %#x.\n", hr);
- /* (I1,I2) + (A,A) -> (I1,I2+A,A) -> (I1,A) -> () */ - hr = CreateGenericComposite(moniker1, moniker2, &moniker); - ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr); - hr = CreateGenericComposite(inverse, inverse, &moniker3); - ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr); - TEST_MONIKER_TYPE(moniker3, MKSYS_GENERICCOMPOSITE); + if (composite) + { + hr = IMoniker_IsSystemMoniker(composite, &moniker_type); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(moniker_type == simplify_tests[i].result_type, "Unexpected result type %u.\n", moniker_type);
- hr = CreateGenericComposite(moniker, moniker3, &moniker4); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); - ok(!moniker4, "Unexpected pointer.\n"); + hr = IMoniker_GetDisplayName(composite, bindctx, NULL, &name); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!lstrcmpW(name, simplify_tests[i].name), "Unexpected result name %s.\n", wine_dbgstr_w(name)); + CoTaskMemFree(name);
- IMoniker_Release(moniker); - IMoniker_Release(moniker3); + IMoniker_Release(composite); + } + else + ok(simplify_tests[i].result_type == MKSYS_NONE, "Unexpected result type.\n");
- /* (I1,I2) + (A2,A) -> (I1,I2+A2,A) -> (I1,A,A) -> (I1+A,A) -> (A) */ - hr = CreateGenericComposite(moniker1, moniker2, &moniker); - ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr); - ok(!!moniker, "Unexpected pointer.\n"); - inverse2 = create_antimoniker(2); - hr = CreateGenericComposite(inverse2, inverse, &moniker3); - ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr); - ok(!!moniker3, "Unexpected pointer.\n"); - IMoniker_Release(inverse2); + winetest_pop_context();
- hr = CreateGenericComposite(moniker, moniker3, &moniker4); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); - TEST_MONIKER_TYPE(moniker4, MKSYS_ANTIMONIKER); - IMoniker_Release(moniker4); - IMoniker_Release(moniker); - IMoniker_Release(moniker3); + IMoniker_Release(left); + IMoniker_Release(right); + }
- /* (I1,I2) + (A,I2) -> (I1,I2+A,I2) -> (I1,I2) */ + hr = CreateItemMoniker(L"!", L"Test", &moniker1); + ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr); + hr = CreateItemMoniker(L"#", L"Wine", &moniker2); + ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr); hr = CreateGenericComposite(moniker1, moniker2, &moniker); - ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr); - ok(!!moniker, "Unexpected pointer.\n"); + ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
- hr = CreateGenericComposite(inverse, moniker2, &moniker3); + hr = CreateGenericComposite(moniker1, moniker2, &moniker); ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr); - ok(!!moniker3, "Unexpected pointer.\n"); - - hr = CreateGenericComposite(moniker, moniker3, &moniker4); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); - TEST_MONIKER_TYPE(moniker4, MKSYS_GENERICCOMPOSITE); - - TEST_DISPLAY_NAME(moniker4, L"!Test#Wine"); - - IMoniker_Release(moniker4); - IMoniker_Release(moniker3); - - IMoniker_Release(inverse); + TEST_MONIKER_TYPE(moniker, MKSYS_GENERICCOMPOSITE);
/* Generic composite is special, as it does not addref in this case. */ hr = IMoniker_QueryInterface(moniker, &CLSID_CompositeMoniker, (void **)&unknown);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/compositemoniker.c | 81 ++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 20 deletions(-)
diff --git a/dlls/ole32/compositemoniker.c b/dlls/ole32/compositemoniker.c index 7abbd51090f..0dbe27f4c76 100644 --- a/dlls/ole32/compositemoniker.c +++ b/dlls/ole32/compositemoniker.c @@ -87,6 +87,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);
/******************************************************************************* * CompositeMoniker_QueryInterface @@ -1132,30 +1133,28 @@ static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker *iface, IBind return S_OK; }
-/****************************************************************************** - * CompositeMoniker_ParseDisplayName - ******************************************************************************/ -static HRESULT WINAPI -CompositeMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, - IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, - IMoniker** ppmkOut) +static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker *iface, IBindCtx *pbc, + IMoniker *pmkToLeft, LPOLESTR name, ULONG *eaten, IMoniker **result) { - IEnumMoniker *enumMoniker; - IMoniker *tempMk,*rightMostMk,*antiMk; - /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/ - /* passing everything else as the pmkToLeft parameter for that call. */ + CompositeMonikerImpl *moniker = impl_from_IMoniker(iface); + IMoniker *left, *rightmost; + HRESULT hr;
- /* get the most right moniker */ - IMoniker_Enum(iface,FALSE,&enumMoniker); - IEnumMoniker_Next(enumMoniker,1,&rightMostMk,NULL); - IEnumMoniker_Release(enumMoniker); + TRACE("%p, %p, %p, %s, %p, %p.\n", iface, pbc, pmkToLeft, debugstr_w(name), eaten, result);
- /* get the left moniker */ - CreateAntiMoniker(&antiMk); - IMoniker_ComposeWith(iface,antiMk,0,&tempMk); - IMoniker_Release(antiMk); + if (!pbc) + return E_INVALIDARG;
- return IMoniker_ParseDisplayName(rightMostMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut); + if (FAILED(hr = composite_get_rightmost(moniker, &left, &rightmost))) + return hr; + + /* Let rightmost component parse the name, using what's left of the composite as a left side. */ + hr = IMoniker_ParseDisplayName(rightmost, pbc, left, name, eaten, result); + + IMoniker_Release(left); + IMoniker_Release(rightmost); + + return hr; }
/****************************************************************************** @@ -1830,6 +1829,48 @@ static void moniker_get_tree_comp_count(const struct comp_node *root, unsigned i moniker_get_tree_comp_count(root->right, count); }
+static HRESULT composite_get_rightmost(CompositeMonikerImpl *composite, IMoniker **left, IMoniker **rightmost) +{ + struct comp_node *root, *node; + unsigned int count; + HRESULT hr; + + /* Shortcut for trivial case when right component is non-composite */ + if (!unsafe_impl_from_IMoniker(composite->right)) + { + *left = composite->left; + IMoniker_AddRef(*left); + *rightmost = composite->right; + IMoniker_AddRef(*rightmost); + return S_OK; + } + + *left = *rightmost = NULL; + + if (FAILED(hr = moniker_get_tree_representation(&composite->IMoniker_iface, NULL, &root))) + return hr; + + if (!(node = moniker_tree_get_rightmost(root))) + { + WARN("Couldn't get right most component.\n"); + return E_FAIL; + } + + *rightmost = node->moniker; + IMoniker_AddRef(*rightmost); + moniker_tree_discard(node, TRUE); + + hr = moniker_create_from_tree(root, &count, left); + moniker_tree_release(root); + if (FAILED(hr)) + { + IMoniker_Release(*rightmost); + *rightmost = NULL; + } + + return hr; +} + static HRESULT moniker_simplify_composition(IMoniker *left, IMoniker *right, unsigned int *count, IMoniker **new_left, IMoniker **new_right) {
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/compositemoniker.c | 92 ++++++++++++++++------------------- dlls/ole32/tests/moniker.c | 51 ++++++++++++++++++- 2 files changed, 93 insertions(+), 50 deletions(-)
diff --git a/dlls/ole32/compositemoniker.c b/dlls/ole32/compositemoniker.c index 0dbe27f4c76..0907950cb17 100644 --- a/dlls/ole32/compositemoniker.c +++ b/dlls/ole32/compositemoniker.c @@ -702,67 +702,61 @@ CompositeMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, } }
-/****************************************************************************** - * CompositeMoniker_GetTimeOfLastChange - ******************************************************************************/ -static HRESULT WINAPI -CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, - IMoniker* pmkToLeft, FILETIME* pCompositeTime) +static HRESULT compose_with(IMoniker *left, IMoniker *right, IMoniker **c) { - HRESULT res; - IMoniker *tempMk,*antiMk,*rightMostMk,*leftMk; - IEnumMoniker *enumMoniker; + HRESULT hr = IMoniker_ComposeWith(left, right, TRUE, c); + if (FAILED(hr) && hr != MK_E_NEEDGENERIC) return hr; + return CreateGenericComposite(left, right, c); +}
- TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime); +static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker *iface, IBindCtx *pbc, + IMoniker *toleft, FILETIME *changetime) +{ + CompositeMonikerImpl *moniker = impl_from_IMoniker(iface); + IMoniker *left, *rightmost, *composed_left = NULL, *running = NULL; + IRunningObjectTable *rot; + HRESULT hr;
- if (pCompositeTime==NULL) - return E_INVALIDARG; + TRACE("%p, %p, %p, %p.\n", iface, pbc, toleft, changetime);
- /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */ - /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */ - /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */ - /* of the composite as the pmkToLeft parameter for that call. */ - if (pmkToLeft) - { - IRunningObjectTable* rot; + if (!changetime || !pbc) + return E_INVALIDARG;
- res = IMoniker_ComposeWith(pmkToLeft, iface, FALSE, &leftMk); - if (FAILED(res)) - return res; + if (FAILED(hr = composite_get_rightmost(moniker, &left, &rightmost))) + return hr;
- res = IBindCtx_GetRunningObjectTable(pbc,&rot); - if (FAILED(res)) - { - IMoniker_Release(leftMk); - return res; - } + if (toleft) + { + /* Compose (toleft, left) and check that against rightmost */ + if (SUCCEEDED(hr = compose_with(toleft, left, &composed_left)) && composed_left) + hr = compose_with(composed_left, rightmost, &running); + } + else + { + composed_left = left; + IMoniker_AddRef(composed_left); + running = iface; + IMoniker_AddRef(running); + }
- if (IRunningObjectTable_GetTimeOfLastChange(rot,leftMk,pCompositeTime)==S_OK) + if (SUCCEEDED(hr)) + { + if (SUCCEEDED(hr = IBindCtx_GetRunningObjectTable(pbc, &rot))) { - IMoniker_Release(leftMk); - return res; + if (IRunningObjectTable_GetTimeOfLastChange(rot, running, changetime) != S_OK) + hr = IMoniker_GetTimeOfLastChange(rightmost, pbc, composed_left, changetime); + IRunningObjectTable_Release(rot); } } - else - leftMk = iface; - - IMoniker_Enum(iface, FALSE, &enumMoniker); - IEnumMoniker_Next(enumMoniker, 1, &rightMostMk, NULL); - IEnumMoniker_Release(enumMoniker); - - res = CreateAntiMoniker(&antiMk); - res = IMoniker_ComposeWith(leftMk, antiMk, 0, &tempMk); - IMoniker_Release(antiMk); - - res = IMoniker_GetTimeOfLastChange(rightMostMk, pbc, tempMk, pCompositeTime); - - IMoniker_Release(tempMk); - IMoniker_Release(rightMostMk);
- if (pmkToLeft) - IMoniker_Release(leftMk); + if (composed_left) + IMoniker_Release(composed_left); + if (running) + IMoniker_Release(running); + IMoniker_Release(rightmost); + IMoniker_Release(left);
- return res; + return hr; }
/****************************************************************************** diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index 5042f24320b..4d40dcb6e4b 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -2954,6 +2954,7 @@ static void test_generic_composite_moniker(void) IMoniker *moniker, *inverse, *moniker1, *moniker2; IEnumMoniker *enummoniker; IRunningObjectTable *rot; + unsigned int eaten, i; DWORD hash, cookie; HRESULT hr; IBindCtx *bindctx; @@ -2962,7 +2963,7 @@ static void test_generic_composite_moniker(void) IROTData *rotdata; IMarshal *marshal; IStream *stream; - unsigned int i; + FILETIME ft; WCHAR *str; ULONG len;
@@ -3142,6 +3143,54 @@ todo_wine
IMoniker_Release(moniker);
+ /* GetTimeOfLastChange() */ + eaten = 0; + hr = create_moniker_from_desc("CI1I2", &eaten, &moniker); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + eaten = 0; + hr = create_moniker_from_desc("I1", &eaten, &moniker1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + /* See if non-generic composition is possible */ + hr = IMoniker_ComposeWith(moniker1, moniker, TRUE, &moniker2); +todo_wine + ok(hr == MK_E_NEEDGENERIC, "Unexpected hr %#x.\n", hr); + + hr = IBindCtx_GetRunningObjectTable(bindctx, &rot); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, moniker1, &ft); + ok(hr == MK_E_NOTBINDABLE, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &ft); + ok(hr == MK_E_NOTBINDABLE, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, NULL); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_GetTimeOfLastChange(moniker, NULL, NULL, &ft); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = IRunningObjectTable_Register(rot, ROTFLAGS_REGISTRATIONKEEPSALIVE, (IUnknown *)moniker, + moniker, &cookie); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &ft); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, moniker1, &ft); +todo_wine + ok(hr == MK_E_NOTBINDABLE, "Unexpected hr %#x.\n", hr); + + hr = IRunningObjectTable_Revoke(rot, cookie); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + IRunningObjectTable_Release(rot); + + IMoniker_Release(moniker); + IMoniker_Release(moniker1); + IBindCtx_Release(bindctx); }