[PATCH 3/3] ole32/composite: Always go through running object table in GetTimeOfLastChange().
Nikolay Sivov
nsivov at codeweavers.com
Thu Sep 23 05:53:12 CDT 2021
Signed-off-by: Nikolay Sivov <nsivov at 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);
}
--
2.33.0
More information about the wine-devel
mailing list