comsvcs: Support progid in "new" moniker serialization stream.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
2485f2d035
commit
f055e369ee
|
@ -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)
|
||||||
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)
|
||||||
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,29 +523,49 @@ 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, &progid_len, sizeof(progid_len), &len);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr) && progid_len)
|
||||||
|
{
|
||||||
|
if (!(progid = heap_alloc(progid_len)))
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
hr = IStream_Read(stream, progid, progid_len, &len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip terminator. */
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
hr = IStream_Read(stream, &pad, sizeof(pad), &len);
|
hr = IStream_Read(stream, &pad, sizeof(pad), &len);
|
||||||
if (FAILED(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
if (pad.QuadPart != 0)
|
|
||||||
return E_FAIL;
|
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr) && pad == 0)
|
||||||
|
{
|
||||||
moniker->clsid = clsid;
|
moniker->clsid = clsid;
|
||||||
|
heap_free(moniker->progid);
|
||||||
|
moniker->progid = progid;
|
||||||
|
progid = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return S_OK;
|
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))
|
||||||
|
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))
|
if (SUCCEEDED(hr))
|
||||||
hr = IStream_Write(stream, &pad, sizeof(pad), &written);
|
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)
|
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)
|
||||||
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))
|
||||||
|
{
|
||||||
|
if (FAILED(CLSIDFromProgID(str, &guid)))
|
||||||
return MK_E_SYNTAX;
|
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
|
||||||
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)
|
||||||
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
|
||||||
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
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue