[PATCH 3/5] ole32: Lock item container on ParseDisplayName().
Nikolay Sivov
nsivov at codeweavers.com
Wed Jan 22 17:03:04 CST 2020
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/ole32/itemmoniker.c | 92 +++++++++++++++++++++++++++++++++++++---
1 file changed, 86 insertions(+), 6 deletions(-)
diff --git a/dlls/ole32/itemmoniker.c b/dlls/ole32/itemmoniker.c
index 0063c323bc..dc7026c4fc 100644
--- a/dlls/ole32/itemmoniker.c
+++ b/dlls/ole32/itemmoniker.c
@@ -57,6 +57,84 @@ static inline ItemMonikerImpl *impl_from_IROTData(IROTData *iface)
return CONTAINING_RECORD(iface, ItemMonikerImpl, IROTData_iface);
}
+struct container_lock
+{
+ IUnknown IUnknown_iface;
+ LONG refcount;
+ IOleItemContainer *container;
+};
+
+static struct container_lock *impl_lock_from_IUnknown(IUnknown *iface)
+{
+ return CONTAINING_RECORD(iface, struct container_lock, IUnknown_iface);
+}
+
+static HRESULT WINAPI container_lock_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
+{
+ if (IsEqualIID(riid, &IID_IUnknown))
+ {
+ *obj = iface;
+ IUnknown_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("Unsupported interface %s.\n", debugstr_guid(riid));
+ *obj = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI container_lock_AddRef(IUnknown *iface)
+{
+ struct container_lock *lock = impl_lock_from_IUnknown(iface);
+ return InterlockedIncrement(&lock->refcount);
+}
+
+static ULONG WINAPI container_lock_Release(IUnknown *iface)
+{
+ struct container_lock *lock = impl_lock_from_IUnknown(iface);
+ ULONG refcount = InterlockedDecrement(&lock->refcount);
+
+ if (!refcount)
+ {
+ IOleItemContainer_LockContainer(lock->container, FALSE);
+ IOleItemContainer_Release(lock->container);
+ heap_free(lock);
+ }
+
+ return refcount;
+}
+
+static const IUnknownVtbl container_lock_vtbl =
+{
+ container_lock_QueryInterface,
+ container_lock_AddRef,
+ container_lock_Release,
+};
+
+static HRESULT set_container_lock(IOleItemContainer *container, IBindCtx *pbc)
+{
+ struct container_lock *lock;
+ HRESULT hr;
+
+ if (!(lock = heap_alloc(sizeof(*lock))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = IOleItemContainer_LockContainer(container, TRUE)))
+ {
+ heap_free(lock);
+ return hr;
+ }
+
+ lock->IUnknown_iface.lpVtbl = &container_lock_vtbl;
+ lock->refcount = 1;
+ lock->container = container;
+ IOleItemContainer_AddRef(lock->container);
+
+ hr = IBindCtx_RegisterObjectBound(pbc, &lock->IUnknown_iface);
+ IUnknown_Release(&lock->IUnknown_iface);
+ return hr;
+}
+
static HRESULT ItemMonikerImpl_Destroy(ItemMonikerImpl* iface);
/*******************************************************************************
@@ -787,13 +865,15 @@ static HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker *iface, IBindCtx
hr = IMoniker_BindToObject(pmkToLeft, pbc, NULL, &IID_IOleItemContainer, (void **)&container);
if (SUCCEEDED(hr))
{
- hr = IOleItemContainer_GetObject(container, This->itemName, get_bind_speed_from_bindctx(pbc), pbc,
- &IID_IParseDisplayName, (void **)&parser);
- if (SUCCEEDED(hr))
+ if (SUCCEEDED(hr = set_container_lock(container, pbc)))
{
- hr = IParseDisplayName_ParseDisplayName(parser, pbc, displayname, eaten, ppmkOut);
-
- IParseDisplayName_Release(parser);
+ hr = IOleItemContainer_GetObject(container, This->itemName, get_bind_speed_from_bindctx(pbc), pbc,
+ &IID_IParseDisplayName, (void **)&parser);
+ if (SUCCEEDED(hr))
+ {
+ hr = IParseDisplayName_ParseDisplayName(parser, pbc, displayname, eaten, ppmkOut);
+ IParseDisplayName_Release(parser);
+ }
}
IOleItemContainer_Release(container);
}
--
2.24.1
More information about the wine-devel
mailing list