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) + TRACE("%p, %p, %p, %p.\n", iface, pbc, toleft, changetime); + + if (!changetime || !pbc) return E_INVALIDARG; - /* 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) + if (FAILED(hr = composite_get_rightmost(moniker, &left, &rightmost))) + return hr; + + if (toleft) { - IRunningObjectTable* rot; - - res = IMoniker_ComposeWith(pmkToLeft, iface, FALSE, &leftMk); - if (FAILED(res)) - return res; - - res = IBindCtx_GetRunningObjectTable(pbc,&rot); - if (FAILED(res)) - { - IMoniker_Release(leftMk); - return res; - } - - if (IRunningObjectTable_GetTimeOfLastChange(rot,leftMk,pCompositeTime)==S_OK) - { - IMoniker_Release(leftMk); - return res; - } + /* 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 - leftMk = iface; + { + composed_left = left; + IMoniker_AddRef(composed_left); + running = iface; + IMoniker_AddRef(running); + } - IMoniker_Enum(iface, FALSE, &enumMoniker); - IEnumMoniker_Next(enumMoniker, 1, &rightMostMk, NULL); - IEnumMoniker_Release(enumMoniker); + if (SUCCEEDED(hr)) + { + if (SUCCEEDED(hr = IBindCtx_GetRunningObjectTable(pbc, &rot))) + { + if (IRunningObjectTable_GetTimeOfLastChange(rot, running, changetime) != S_OK) + hr = IMoniker_GetTimeOfLastChange(rightmost, pbc, composed_left, changetime); + IRunningObjectTable_Release(rot); + } + } - res = CreateAntiMoniker(&antiMk); - res = IMoniker_ComposeWith(leftMk, antiMk, 0, &tempMk); - IMoniker_Release(antiMk); + if (composed_left) + IMoniker_Release(composed_left); + if (running) + IMoniker_Release(running); + IMoniker_Release(rightmost); + IMoniker_Release(left); - res = IMoniker_GetTimeOfLastChange(rightMostMk, pbc, tempMk, pCompositeTime); - - IMoniker_Release(tempMk); - IMoniker_Release(rightMostMk); - - if (pmkToLeft) - IMoniker_Release(leftMk); - - 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); }