Commit f055e369 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

comsvcs: Support progid in "new" moniker serialization stream.

parent 2485f2d0
...@@ -57,6 +57,7 @@ struct new_moniker ...@@ -57,6 +57,7 @@ struct new_moniker
IROTData IROTData_iface; IROTData IROTData_iface;
LONG refcount; LONG refcount;
CLSID clsid; CLSID clsid;
WCHAR *progid;
}; };
static HRESULT new_moniker_parse_displayname(IBindCtx *pbc, LPOLESTR name, ULONG *eaten, IMoniker **ret); 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) ...@@ -481,7 +482,10 @@ static ULONG WINAPI new_moniker_Release(IMoniker* iface)
TRACE("%p, refcount %u.\n", iface, refcount); TRACE("%p, refcount %u.\n", iface, refcount);
if (!refcount) if (!refcount)
{
heap_free(moniker->progid);
heap_free(moniker); heap_free(moniker);
}
return refcount; return refcount;
} }
...@@ -508,10 +512,10 @@ static HRESULT WINAPI new_moniker_IsDirty(IMoniker* iface) ...@@ -508,10 +512,10 @@ static HRESULT WINAPI new_moniker_IsDirty(IMoniker* iface)
static HRESULT WINAPI new_moniker_Load(IMoniker *iface, IStream *stream) static HRESULT WINAPI new_moniker_Load(IMoniker *iface, IStream *stream)
{ {
struct new_moniker *moniker = impl_from_IMoniker(iface); struct new_moniker *moniker = impl_from_IMoniker(iface);
ULARGE_INTEGER pad; DWORD progid_len = 0, len, pad = ~0u;
WCHAR *progid = NULL;
CLSID clsid; CLSID clsid;
HRESULT hr; HRESULT hr;
DWORD len;
TRACE("%p, %p.\n", iface, stream); TRACE("%p, %p.\n", iface, stream);
...@@ -519,30 +523,50 @@ static HRESULT WINAPI new_moniker_Load(IMoniker *iface, IStream *stream) ...@@ -519,30 +523,50 @@ static HRESULT WINAPI new_moniker_Load(IMoniker *iface, IStream *stream)
if (FAILED(hr)) if (FAILED(hr))
return hr; return hr;
pad.QuadPart = 1; if (SUCCEEDED(hr))
hr = IStream_Read(stream, &pad, sizeof(pad), &len); hr = IStream_Read(stream, &progid_len, sizeof(progid_len), &len);
if (FAILED(hr))
return hr;
if (pad.QuadPart != 0) if (SUCCEEDED(hr) && progid_len)
return E_FAIL; {
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) static HRESULT WINAPI new_moniker_Save(IMoniker *iface, IStream *stream, BOOL clear_dirty)
{ {
struct new_moniker *moniker = impl_from_IMoniker(iface); struct new_moniker *moniker = impl_from_IMoniker(iface);
static const ULARGE_INTEGER pad; ULONG written, pad = 0, progid_len = 0;
ULONG written;
HRESULT hr; HRESULT hr;
TRACE("%p, %p, %d.\n", iface, stream, clear_dirty); 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); hr = IStream_Write(stream, &moniker->clsid, sizeof(moniker->clsid), &written);
if (SUCCEEDED(hr)) 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); hr = IStream_Write(stream, &pad, sizeof(pad), &written);
return hr; return hr;
...@@ -550,12 +574,16 @@ static HRESULT WINAPI new_moniker_Save(IMoniker *iface, IStream *stream, BOOL cl ...@@ -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) 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); TRACE("%p, %p.\n", iface, size);
if (!size) if (!size)
return E_POINTER; return E_POINTER;
size->QuadPart = sizeof(CLSID) + 2 * sizeof(DWORD); size->QuadPart = sizeof(CLSID) + 2 * sizeof(DWORD);
if (moniker->progid)
size->QuadPart += lstrlenW(moniker->progid) * sizeof(WCHAR);
return S_OK; return S_OK;
} }
...@@ -867,15 +895,21 @@ static HRESULT guid_from_string(const WCHAR *s, GUID *ret) ...@@ -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) static HRESULT new_moniker_parse_displayname(IBindCtx *pbc, LPOLESTR name, ULONG *eaten, IMoniker **ret)
{ {
struct new_moniker *moniker; struct new_moniker *moniker;
WCHAR *progid = NULL, *str;
GUID guid; GUID guid;
*ret = NULL; *ret = NULL;
if (wcsnicmp(name, L"new:", 4)) if (wcsnicmp(name, L"new:", 4))
return MK_E_SYNTAX; return MK_E_SYNTAX;
str = name + 4;
if (!guid_from_string(name + 4, &guid) && FAILED(CLSIDFromProgID(name + 4, &guid))) if (!guid_from_string(str, &guid))
return MK_E_SYNTAX; {
if (FAILED(CLSIDFromProgID(str, &guid)))
return MK_E_SYNTAX;
progid = str;
}
moniker = heap_alloc_zero(sizeof(*moniker)); moniker = heap_alloc_zero(sizeof(*moniker));
if (!moniker) if (!moniker)
...@@ -885,6 +919,15 @@ static HRESULT new_moniker_parse_displayname(IBindCtx *pbc, LPOLESTR name, ULONG ...@@ -885,6 +919,15 @@ static HRESULT new_moniker_parse_displayname(IBindCtx *pbc, LPOLESTR name, ULONG
moniker->IROTData_iface.lpVtbl = &new_moniker_rotdata_vtbl; moniker->IROTData_iface.lpVtbl = &new_moniker_rotdata_vtbl;
moniker->refcount = 1; moniker->refcount = 1;
moniker->clsid = guid; 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; *ret = &moniker->IMoniker_iface;
......
...@@ -293,23 +293,90 @@ static void create_dispenser(void) ...@@ -293,23 +293,90 @@ static void create_dispenser(void)
IDispenserManager_Release(dispenser); 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) static void test_new_moniker(void)
{ {
IMoniker *moniker, *moniker2, *inverse, *class_moniker, *moniker_left; IMoniker *moniker, *moniker2, *inverse, *class_moniker, *moniker_left;
IRunningObjectTable *rot; IRunningObjectTable *rot;
IUnknown *obj, *obj2; IUnknown *obj, *obj2;
BIND_OPTS2 bind_opts; BIND_OPTS2 bind_opts;
ULARGE_INTEGER size;
DWORD moniker_type; DWORD moniker_type;
IROTData *rot_data; IROTData *rot_data;
IBindCtx *bindctx; IBindCtx *bindctx;
FILETIME filetime; FILETIME filetime;
DWORD hash, eaten; DWORD hash, eaten;
IStream *stream;
HGLOBAL hglobal;
CLSID clsid; CLSID clsid;
HRESULT hr; HRESULT hr;
void *ptr; WCHAR *str;
hr = CreateBindCtx(0, &bindctx); hr = CreateBindCtx(0, &bindctx);
ok(hr == S_OK, "Failed to create bind context, hr %#x.\n", hr); ok(hr == S_OK, "Failed to create bind context, hr %#x.\n", hr);
...@@ -424,36 +491,7 @@ todo_wine ...@@ -424,36 +491,7 @@ todo_wine
ok(obj == NULL, "Unexpected return value.\n"); ok(obj == NULL, "Unexpected return value.\n");
/* Serialization. */ /* Serialization. */
hr = IMoniker_GetSizeMax(moniker, NULL); test_new_moniker_serialize(L"{20d04fe0-3aea-1069-a2d8-08002b30309d}", NULL, moniker);
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);
hr = IMoniker_IsDirty(moniker); hr = IMoniker_IsDirty(moniker);
ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr); ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
...@@ -483,6 +521,15 @@ todo_wine ...@@ -483,6 +521,15 @@ todo_wine
ok(hr == S_OK, "Failed to parse display name, hr %#x.\n", hr); ok(hr == S_OK, "Failed to parse display name, hr %#x.\n", hr);
ok(eaten, "Unexpected eaten length %u.\n", eaten); 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); hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&obj);
ok(hr == S_OK, "Failed to bind to object, hr %#x.\n", hr); ok(hr == S_OK, "Failed to bind to object, hr %#x.\n", hr);
EXPECT_REF(obj, 1); EXPECT_REF(obj, 1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment