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