[PATCH 6/7] comsvcs: Support progid in "new" moniker serialization stream.

Nikolay Sivov nsivov at codeweavers.com
Mon Nov 11 01:36:56 CST 2019


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/comsvcs/main.c          |  71 ++++++++++++++++-----
 dlls/comsvcs/tests/comsvcs.c | 115 ++++++++++++++++++++++++-----------
 2 files changed, 138 insertions(+), 48 deletions(-)

diff --git a/dlls/comsvcs/main.c b/dlls/comsvcs/main.c
index 7bfde03b34..9ab77dfced 100644
--- a/dlls/comsvcs/main.c
+++ b/dlls/comsvcs/main.c
@@ -57,6 +57,7 @@ struct new_moniker
     IROTData IROTData_iface;
     LONG refcount;
     CLSID clsid;
+    WCHAR *progid;
 };
 
 static HRESULT new_moniker_parse_displayname(IBindCtx *pbc, LPOLESTR name, ULONG *eaten, IMoniker **ret);
@@ -481,7 +482,10 @@ static ULONG WINAPI new_moniker_Release(IMoniker* iface)
     TRACE("%p, refcount %u.\n", iface, refcount);
 
     if (!refcount)
+    {
+        heap_free(moniker->progid);
         heap_free(moniker);
+    }
 
     return refcount;
 }
@@ -508,10 +512,10 @@ static HRESULT WINAPI new_moniker_IsDirty(IMoniker* iface)
 static HRESULT WINAPI new_moniker_Load(IMoniker *iface, IStream *stream)
 {
     struct new_moniker *moniker = impl_from_IMoniker(iface);
-    ULARGE_INTEGER pad;
+    DWORD progid_len = 0, len, pad = ~0u;
+    WCHAR *progid = NULL;
     CLSID clsid;
     HRESULT hr;
-    DWORD len;
 
     TRACE("%p, %p.\n", iface, stream);
 
@@ -519,29 +523,49 @@ static HRESULT WINAPI new_moniker_Load(IMoniker *iface, IStream *stream)
     if (FAILED(hr))
         return hr;
 
-    pad.QuadPart = 1;
-    hr = IStream_Read(stream, &pad, sizeof(pad), &len);
-    if (FAILED(hr))
-        return hr;
+    if (SUCCEEDED(hr))
+        hr = IStream_Read(stream, &progid_len, sizeof(progid_len), &len);
 
-    if (pad.QuadPart != 0)
-        return E_FAIL;
+    if (SUCCEEDED(hr) && progid_len)
+    {
+        if (!(progid = heap_alloc(progid_len)))
+           return E_OUTOFMEMORY;
+        hr = IStream_Read(stream, progid, progid_len, &len);
+    }
 
-    moniker->clsid = clsid;
+    /* Skip terminator. */
+    if (SUCCEEDED(hr))
+        hr = IStream_Read(stream, &pad, sizeof(pad), &len);
 
-    return S_OK;
+    if (SUCCEEDED(hr) && pad == 0)
+    {
+        moniker->clsid = clsid;
+        heap_free(moniker->progid);
+        moniker->progid = progid;
+        progid = NULL;
+    }
+
+    heap_free(progid);
+
+    return hr;
 }
 
 static HRESULT WINAPI new_moniker_Save(IMoniker *iface, IStream *stream, BOOL clear_dirty)
 {
     struct new_moniker *moniker = impl_from_IMoniker(iface);
-    static const ULARGE_INTEGER pad;
-    ULONG written;
+    ULONG written, pad = 0, progid_len = 0;
     HRESULT hr;
 
     TRACE("%p, %p, %d.\n", iface, stream, clear_dirty);
 
+    if (moniker->progid)
+        progid_len = lstrlenW(moniker->progid) * sizeof(WCHAR);
+
     hr = IStream_Write(stream, &moniker->clsid, sizeof(moniker->clsid), &written);
+    if (SUCCEEDED(hr))
+        hr = IStream_Write(stream, &progid_len, sizeof(progid_len), &written);
+    if (SUCCEEDED(hr) && progid_len)
+        hr = IStream_Write(stream, moniker->progid, progid_len, &written);
     if (SUCCEEDED(hr))
         hr = IStream_Write(stream, &pad, sizeof(pad), &written);
 
@@ -550,12 +574,16 @@ static HRESULT WINAPI new_moniker_Save(IMoniker *iface, IStream *stream, BOOL cl
 
 static HRESULT WINAPI new_moniker_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *size)
 {
+    struct new_moniker *moniker = impl_from_IMoniker(iface);
+
     TRACE("%p, %p.\n", iface, size);
 
     if (!size)
         return E_POINTER;
 
     size->QuadPart = sizeof(CLSID) + 2 * sizeof(DWORD);
+    if (moniker->progid)
+        size->QuadPart += lstrlenW(moniker->progid) * sizeof(WCHAR);
 
     return S_OK;
 }
@@ -867,15 +895,21 @@ static HRESULT guid_from_string(const WCHAR *s, GUID *ret)
 static HRESULT new_moniker_parse_displayname(IBindCtx *pbc, LPOLESTR name, ULONG *eaten, IMoniker **ret)
 {
     struct new_moniker *moniker;
+    WCHAR *progid = NULL, *str;
     GUID guid;
 
     *ret = NULL;
 
     if (wcsnicmp(name, L"new:", 4))
         return MK_E_SYNTAX;
+    str = name + 4;
 
-    if (!guid_from_string(name + 4, &guid) && FAILED(CLSIDFromProgID(name + 4, &guid)))
-        return MK_E_SYNTAX;
+    if (!guid_from_string(str, &guid))
+    {
+        if (FAILED(CLSIDFromProgID(str, &guid)))
+            return MK_E_SYNTAX;
+        progid = str;
+    }
 
     moniker = heap_alloc_zero(sizeof(*moniker));
     if (!moniker)
@@ -885,6 +919,15 @@ static HRESULT new_moniker_parse_displayname(IBindCtx *pbc, LPOLESTR name, ULONG
     moniker->IROTData_iface.lpVtbl = &new_moniker_rotdata_vtbl;
     moniker->refcount = 1;
     moniker->clsid = guid;
+    if (progid)
+    {
+        if (!(moniker->progid = heap_alloc((lstrlenW(progid) + 1) * sizeof(WCHAR))))
+        {
+            IMoniker_Release(&moniker->IMoniker_iface);
+            return E_OUTOFMEMORY;
+        }
+        lstrcpyW(moniker->progid, progid);
+    }
 
     *ret = &moniker->IMoniker_iface;
 
diff --git a/dlls/comsvcs/tests/comsvcs.c b/dlls/comsvcs/tests/comsvcs.c
index 3b15a1f7e6..e6717e0ea3 100644
--- a/dlls/comsvcs/tests/comsvcs.c
+++ b/dlls/comsvcs/tests/comsvcs.c
@@ -293,23 +293,90 @@ static void create_dispenser(void)
     IDispenserManager_Release(dispenser);
 }
 
+static void test_new_moniker_serialize(const WCHAR *clsid, const WCHAR *progid, IMoniker *moniker)
+{
+    DWORD expected_size, progid_len = 0;
+    ULARGE_INTEGER size;
+    IStream *stream;
+    HGLOBAL hglobal;
+    CLSID guid;
+    HRESULT hr;
+    DWORD *ptr;
+
+    hr = IMoniker_GetSizeMax(moniker, NULL);
+    ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
+
+    expected_size = sizeof(GUID) + 2 * sizeof(DWORD);
+    if (progid)
+    {
+        progid_len = lstrlenW(progid) * sizeof(*progid);
+        expected_size += progid_len;
+    }
+
+    size.QuadPart = 0;
+    hr = IMoniker_GetSizeMax(moniker, &size);
+    ok(hr == S_OK, "Failed to get size, hr %#x.\n", hr);
+    ok(size.QuadPart == expected_size, "Unexpected size %s, expected %#x.\n", wine_dbgstr_longlong(size.QuadPart),
+            expected_size);
+
+    hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
+    ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
+
+    hr = IMoniker_Save(moniker, stream, FALSE);
+    ok(hr == S_OK, "Failed to save moniker, hr %#x.\n", hr);
+
+    hr = GetHGlobalFromStream(stream, &hglobal);
+    ok(hr == S_OK, "Failed to get a handle, hr %#x.\n", hr);
+
+    ptr = GlobalLock(hglobal);
+    ok(!!ptr, "Failed to get data pointer.\n");
+
+    hr = CLSIDFromString(clsid, &guid);
+    ok(hr == S_OK, "Failed to get CLSID, hr %#x.\n", hr);
+    ok(IsEqualGUID((GUID *)ptr, &guid), "Unexpected buffer content.\n");
+    ptr += sizeof(GUID)/sizeof(DWORD);
+
+    /* Serialization format:
+
+       GUID guid;
+       DWORD progid_len;
+       WCHAR progid[progid_len/2];
+       DWORD null;
+    */
+
+    if (progid)
+    {
+        ok(*ptr == progid_len, "Unexpected progid length.\n");
+        ptr++;
+        ok(!memcmp(ptr, progid, progid_len), "Unexpected progid.\n");
+        ptr += progid_len / sizeof(DWORD);
+    }
+    else
+    {
+        ok(*ptr == 0, "Unexpected progid length.\n");
+        ptr++;
+    }
+    ok(*ptr == 0, "Unexpected terminator.\n");
+
+    GlobalUnlock(hglobal);
+
+    IStream_Release(stream);
+}
+
 static void test_new_moniker(void)
 {
     IMoniker *moniker, *moniker2, *inverse, *class_moniker, *moniker_left;
     IRunningObjectTable *rot;
     IUnknown *obj, *obj2;
     BIND_OPTS2 bind_opts;
-    ULARGE_INTEGER size;
     DWORD moniker_type;
     IROTData *rot_data;
     IBindCtx *bindctx;
     FILETIME filetime;
     DWORD hash, eaten;
-    IStream *stream;
-    HGLOBAL hglobal;
     CLSID clsid;
     HRESULT hr;
-    void *ptr;
+    WCHAR *str;
 
     hr = CreateBindCtx(0, &bindctx);
     ok(hr == S_OK, "Failed to create bind context, hr %#x.\n", hr);
@@ -424,36 +491,7 @@ todo_wine
     ok(obj == NULL, "Unexpected return value.\n");
 
     /* Serialization. */
-    hr = IMoniker_GetSizeMax(moniker, NULL);
-    ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
-
-    size.QuadPart = 0;
-    hr = IMoniker_GetSizeMax(moniker, &size);
-    ok(hr == S_OK, "Failed to get size, hr %#x.\n", hr);
-    ok(size.QuadPart == (sizeof(GUID) + 2 * sizeof(DWORD)), "Unexpected size %s.\n",
-            wine_dbgstr_longlong(size.QuadPart));
-
-    hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
-    ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
-
-    hr = IMoniker_Save(moniker, stream, FALSE);
-    ok(hr == S_OK, "Failed to save moniker, hr %#x.\n", hr);
-
-    hr = GetHGlobalFromStream(stream, &hglobal);
-    ok(hr == S_OK, "Failed to get a handle, hr %#x.\n", hr);
-
-    ptr = GlobalLock(hglobal);
-    ok(!!ptr, "Failed to get data pointer.\n");
-
-    hr = CLSIDFromString(L"{20d04fe0-3aea-1069-a2d8-08002b30309d}", &clsid);
-    ok(hr == S_OK, "Failed to get CLSID, hr %#x.\n", hr);
-    ok(IsEqualGUID((GUID *)ptr, &clsid), "Unexpected buffer content.\n");
-    ok(*(DWORD *)((BYTE *)ptr + sizeof(GUID)) == 0, "Unexpected buffer content.\n");
-    ok(*(DWORD *)((BYTE *)ptr + sizeof(GUID) + sizeof(DWORD)) == 0, "Unexpected buffer content.\n");
-
-    GlobalUnlock(hglobal);
-
-    IStream_Release(stream);
+    test_new_moniker_serialize(L"{20d04fe0-3aea-1069-a2d8-08002b30309d}", NULL, moniker);
 
     hr = IMoniker_IsDirty(moniker);
     ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
@@ -483,6 +521,15 @@ todo_wine
     ok(hr == S_OK, "Failed to parse display name, hr %#x.\n", hr);
     ok(eaten, "Unexpected eaten length %u.\n", eaten);
 
+    hr = CLSIDFromProgID(L"msxml2.domdocument", &clsid);
+    ok(hr == S_OK, "Failed to get clsid, hr %#x.\n", hr);
+
+    hr = StringFromCLSID(&clsid, &str);
+    ok(hr == S_OK, "Failed to get guid string, hr %#x.\n", hr);
+
+    test_new_moniker_serialize(str, L"msxml2.domdocument", moniker);
+    CoTaskMemFree(str);
+
     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&obj);
     ok(hr == S_OK, "Failed to bind to object, hr %#x.\n", hr);
     EXPECT_REF(obj, 1);
-- 
2.24.0




More information about the wine-devel mailing list