Nikolay Sivov : ole32: Handle extra class moniker data on load/save.
Alexandre Julliard
julliard at winehq.org
Tue Sep 14 16:00:12 CDT 2021
Module: wine
Branch: master
Commit: 44d57a615f2d2ca16b45f346f868a04b608cccdd
URL: https://source.winehq.org/git/wine.git/?a=commit;h=44d57a615f2d2ca16b45f346f868a04b608cccdd
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Tue Sep 14 11:47:56 2021 +0300
ole32: Handle extra class moniker data on load/save.
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ole32/classmoniker.c | 60 +++++++++++++++++++++++++++-------------------
dlls/ole32/tests/moniker.c | 56 ++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 91 insertions(+), 25 deletions(-)
diff --git a/dlls/ole32/classmoniker.c b/dlls/ole32/classmoniker.c
index ac4854347c8..86c2639e8ec 100644
--- a/dlls/ole32/classmoniker.c
+++ b/dlls/ole32/classmoniker.c
@@ -30,6 +30,7 @@
#include "winbase.h"
#include "winuser.h"
#include "wine/debug.h"
+#include "wine/heap.h"
#include "ole2.h"
#include "moniker.h"
@@ -49,6 +50,7 @@ typedef struct ClassMoniker
CLSID clsid;
DWORD data_len;
} header;
+ WCHAR *data;
IUnknown *pMarshal; /* custom marshaler */
} ClassMoniker;
@@ -126,23 +128,18 @@ static ULONG WINAPI ClassMoniker_AddRef(IMoniker* iface)
return InterlockedIncrement(&This->ref);
}
-/******************************************************************************
- * ClassMoniker_Release
- ******************************************************************************/
static ULONG WINAPI ClassMoniker_Release(IMoniker* iface)
{
- ClassMoniker *This = impl_from_IMoniker(iface);
- ULONG ref;
-
- TRACE("(%p)\n",This);
+ ClassMoniker *moniker = impl_from_IMoniker(iface);
+ ULONG ref = InterlockedDecrement(&moniker->ref);
- ref = InterlockedDecrement(&This->ref);
+ TRACE("%p refcount %d\n", iface, ref);
- /* destroy the object if there are no more references to it */
- if (ref == 0)
+ if (!ref)
{
- if (This->pMarshal) IUnknown_Release(This->pMarshal);
- HeapFree(GetProcessHeap(),0,This);
+ if (moniker->pMarshal) IUnknown_Release(moniker->pMarshal);
+ heap_free(moniker->data);
+ heap_free(moniker);
}
return ref;
@@ -190,8 +187,15 @@ static HRESULT WINAPI ClassMoniker_Load(IMoniker *iface, IStream *stream)
if (moniker->header.data_len)
{
- FIXME("Moniker data of length %u was ignored.\n", moniker->header.data_len);
- moniker->header.data_len = 0;
+ heap_free(moniker->data);
+ if (!(moniker->data = heap_alloc(moniker->header.data_len)))
+ {
+ WARN("Failed to allocate moniker data of size %u.\n", moniker->header.data_len);
+ moniker->header.data_len = 0;
+ return E_OUTOFMEMORY;
+ }
+ hr = IStream_Read(stream, moniker->data, moniker->header.data_len, &length);
+ if (hr != S_OK || length != moniker->header.data_len) return STG_E_READFAULT;
}
return S_OK;
@@ -200,21 +204,25 @@ static HRESULT WINAPI ClassMoniker_Load(IMoniker *iface, IStream *stream)
static HRESULT WINAPI ClassMoniker_Save(IMoniker *iface, IStream *stream, BOOL clear_dirty)
{
ClassMoniker *moniker = impl_from_IMoniker(iface);
+ HRESULT hr;
TRACE("%p, %p, %d\n", iface, stream, clear_dirty);
- return IStream_Write(stream, &moniker->header, sizeof(moniker->header), NULL);
+ hr = IStream_Write(stream, &moniker->header, sizeof(moniker->header), NULL);
+
+ if (SUCCEEDED(hr) && moniker->header.data_len)
+ hr = IStream_Write(stream, moniker->data, moniker->header.data_len, NULL);
+
+ return hr;
}
-/******************************************************************************
- * ClassMoniker_GetSizeMax
- ******************************************************************************/
-static HRESULT WINAPI ClassMoniker_GetSizeMax(IMoniker* iface,
- ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */
+static HRESULT WINAPI ClassMoniker_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *size)
{
- TRACE("(%p)\n", pcbSize);
+ ClassMoniker *moniker = impl_from_IMoniker(iface);
+
+ TRACE("%p, %p\n", iface, size);
- pcbSize->QuadPart = sizeof(CLSID) + sizeof(DWORD);
+ size->QuadPart = sizeof(moniker->header) + moniker->header.data_len;
return S_OK;
}
@@ -500,13 +508,17 @@ static HRESULT WINAPI ClassMoniker_GetDisplayName(IMoniker *iface,
if (pmkToLeft)
return E_INVALIDARG;
- if (!(*name = CoTaskMemAlloc(name_len * sizeof(WCHAR))))
+ if (!(*name = CoTaskMemAlloc(name_len * sizeof(WCHAR) + moniker->header.data_len)))
return E_OUTOFMEMORY;
- swprintf(*name, name_len, L"clsid:%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X:",
+ swprintf(*name, name_len, L"clsid:%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1], guid->Data4[2],
guid->Data4[3], guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
+ if (moniker->header.data_len)
+ lstrcatW(*name, moniker->data);
+ lstrcatW(*name, L":");
+
TRACE("Returning %s\n", debugstr_w(*name));
return S_OK;
diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c
index 86b47e28b89..afe40980dd9 100644
--- a/dlls/ole32/tests/moniker.c
+++ b/dlls/ole32/tests/moniker.c
@@ -1769,12 +1769,17 @@ static void test_class_moniker(void)
{
IMoniker *moniker, *moniker2, *inverse, *reduced, *anti;
IEnumMoniker *enummoniker;
+ ULONG length, eaten;
+ ULARGE_INTEGER size;
+ LARGE_INTEGER pos;
+ IROTData *rotdata;
HRESULT hr;
DWORD hash;
IBindCtx *bindctx;
IUnknown *unknown;
FILETIME filetime;
- ULONG eaten;
+ IStream *stream;
+ BYTE buffer[100];
hr = CreateBindCtx(0, &bindctx);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
@@ -1792,6 +1797,9 @@ todo_wine
TEST_DISPLAY_NAME(moniker, L"clsid:11111111-0000-0000-2222-444444444444;extra data:");
TEST_MONIKER_TYPE(moniker, MKSYS_CLASSMONIKER);
+ hr = IMoniker_GetSizeMax(moniker, &size);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(size.LowPart == 44, "Unexpected size %u.\n", size.LowPart);
TEST_MONIKER_TYPE(moniker2, MKSYS_CLASSMONIKER);
@@ -1805,9 +1813,55 @@ todo_wine
IMoniker_Release(moniker);
}
+ /* From persistent state */
+ hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = CreateClassMoniker(&GUID_NULL, &moniker);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMoniker_GetSizeMax(moniker, &size);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(size.QuadPart == 20, "Unexpected size %u.\n", size.LowPart);
+
+ hr = IStream_Write(stream, &CLSID_StdComponentCategoriesMgr, sizeof(CLSID), NULL);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ length = 5 * sizeof(WCHAR);
+ hr = IStream_Write(stream, &length, sizeof(length), NULL);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ hr = IStream_Write(stream, L"data", length, NULL);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ pos.QuadPart = 0;
+ hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMoniker_Load(moniker, stream);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMoniker_GetSizeMax(moniker, &size);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(size.QuadPart == 30, "Unexpected size %u.\n", size.LowPart);
+ TEST_DISPLAY_NAME(moniker, L"clsid:0002E005-0000-0000-C000-000000000046data:");
+
+ /* Extra data does not affect comparison */
+ hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &length);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(length == sizeof(expected_class_moniker_comparison_data), "Unexpected comparison data length %u.\n", length);
+ ok(!memcmp(buffer, expected_class_moniker_comparison_data, length), "Unexpected data.\n");
+ IROTData_Release(rotdata);
+
+ IStream_Release(stream);
+ IMoniker_Release(moniker);
+
hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
ok_ole_success(hr, CreateClassMoniker);
+ hr = IMoniker_GetSizeMax(moniker, &size);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(size.LowPart == 20, "Unexpected size %u.\n", size.LowPart);
+
hr = IMoniker_QueryInterface(moniker, &CLSID_ClassMoniker, (void **)&unknown);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(unknown == (IUnknown *)moniker, "Unexpected interface.\n");
More information about the wine-cvs
mailing list