ole32: Improve class moniker display name parsing.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
44d57a615f
commit
a5a333572c
|
@ -654,106 +654,95 @@ static const IROTDataVtbl ROTDataVtbl =
|
||||||
ClassMonikerROTData_GetComparisonData
|
ClassMonikerROTData_GetComparisonData
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************
|
static HRESULT create_class_moniker(const CLSID *clsid, const WCHAR *data,
|
||||||
* CreateClassMoniker [OLE32.@]
|
unsigned int data_len, IMoniker **moniker)
|
||||||
******************************************************************************/
|
|
||||||
HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker **moniker)
|
|
||||||
{
|
{
|
||||||
ClassMoniker *object;
|
ClassMoniker *object;
|
||||||
|
|
||||||
TRACE("%s, %p\n", debugstr_guid(rclsid), moniker);
|
if (!(object = heap_alloc_zero(sizeof(*object))))
|
||||||
|
|
||||||
if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
|
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
object->IMoniker_iface.lpVtbl = &ClassMonikerVtbl;
|
object->IMoniker_iface.lpVtbl = &ClassMonikerVtbl;
|
||||||
object->IROTData_iface.lpVtbl = &ROTDataVtbl;
|
object->IROTData_iface.lpVtbl = &ROTDataVtbl;
|
||||||
object->ref = 1;
|
object->ref = 1;
|
||||||
object->header.clsid = *rclsid;
|
object->header.clsid = *clsid;
|
||||||
|
if (data_len)
|
||||||
|
{
|
||||||
|
object->header.data_len = (data_len + 1) * sizeof(WCHAR);
|
||||||
|
|
||||||
|
if (!(object->data = heap_alloc(object->header.data_len)))
|
||||||
|
{
|
||||||
|
IMoniker_Release(&object->IMoniker_iface);
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
memcpy(object->data, data, data_len * sizeof(WCHAR));
|
||||||
|
object->data[data_len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
*moniker = &object->IMoniker_iface;
|
*moniker = &object->IMoniker_iface;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT ClassMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName, LPDWORD pchEaten,
|
/******************************************************************************
|
||||||
IMoniker **ppmk)
|
* CreateClassMoniker [OLE32.@]
|
||||||
|
******************************************************************************/
|
||||||
|
HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker **moniker)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
TRACE("%s, %p\n", debugstr_guid(rclsid), moniker);
|
||||||
LPCWSTR s = wcschr(szDisplayName, ':');
|
|
||||||
LPCWSTR end;
|
|
||||||
CLSID clsid;
|
|
||||||
BYTE table[256];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!s)
|
return create_class_moniker(rclsid, NULL, 0, moniker);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT ClassMoniker_CreateFromDisplayName(LPBC pbc, const WCHAR *display_name,
|
||||||
|
DWORD *eaten, IMoniker **moniker)
|
||||||
|
{
|
||||||
|
const WCHAR *end, *s;
|
||||||
|
BOOL has_braces;
|
||||||
|
WCHAR uuid[37];
|
||||||
|
CLSID clsid;
|
||||||
|
HRESULT hr;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
s = display_name;
|
||||||
|
|
||||||
|
/* Skip prefix */
|
||||||
|
if (wcsnicmp(s, L"clsid:", 6)) return MK_E_SYNTAX;
|
||||||
|
s += 6;
|
||||||
|
|
||||||
|
/* Terminating marker is optional */
|
||||||
|
if (!(end = wcschr(s, ':')))
|
||||||
|
end = s + lstrlenW(s);
|
||||||
|
|
||||||
|
len = end - s;
|
||||||
|
if (len < 36)
|
||||||
return MK_E_SYNTAX;
|
return MK_E_SYNTAX;
|
||||||
|
|
||||||
s++;
|
if ((has_braces = *s == '{')) s++;
|
||||||
|
|
||||||
for (end = s; *end && (*end != ':'); end++)
|
memcpy(uuid, s, 36 * sizeof(WCHAR));
|
||||||
;
|
uuid[36] = 0;
|
||||||
|
|
||||||
TRACE("parsing %s\n", debugstr_wn(s, end - s));
|
if (UuidFromStringW(uuid, &clsid))
|
||||||
|
|
||||||
/* validate the CLSID string */
|
|
||||||
if (s[0] == '{')
|
|
||||||
{
|
{
|
||||||
if ((end - s != 38) || (s[37] != '}'))
|
WARN("Failed to parse clsid string.\n");
|
||||||
return MK_E_SYNTAX;
|
return MK_E_SYNTAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
s += 36;
|
||||||
|
if (has_braces)
|
||||||
|
{
|
||||||
|
if (*s != '}') return MK_E_SYNTAX;
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if (end - s != 36)
|
|
||||||
return MK_E_SYNTAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<36; i++)
|
/* Consume terminal marker */
|
||||||
{
|
len = end - s;
|
||||||
if ((i == 8)||(i == 13)||(i == 18)||(i == 23))
|
if (*end == ':') end++;
|
||||||
{
|
|
||||||
if (s[i] != '-')
|
|
||||||
return MK_E_SYNTAX;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!(((s[i] >= '0') && (s[i] <= '9')) ||
|
|
||||||
((s[i] >= 'a') && (s[i] <= 'f')) ||
|
|
||||||
((s[i] >= 'A') && (s[i] <= 'F'))))
|
|
||||||
return MK_E_SYNTAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* quick lookup table */
|
hr = create_class_moniker(&clsid, len ? s : NULL, len, moniker);
|
||||||
memset(table, 0, 256);
|
|
||||||
|
|
||||||
for (i = 0; i < 10; i++)
|
|
||||||
table['0' + i] = i;
|
|
||||||
for (i = 0; i < 6; i++)
|
|
||||||
{
|
|
||||||
table['A' + i] = i+10;
|
|
||||||
table['a' + i] = i+10;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
|
|
||||||
|
|
||||||
clsid.Data1 = (table[s[0]] << 28 | table[s[1]] << 24 | table[s[2]] << 20 | table[s[3]] << 16 |
|
|
||||||
table[s[4]] << 12 | table[s[5]] << 8 | table[s[6]] << 4 | table[s[7]]);
|
|
||||||
clsid.Data2 = table[s[9]] << 12 | table[s[10]] << 8 | table[s[11]] << 4 | table[s[12]];
|
|
||||||
clsid.Data3 = table[s[14]] << 12 | table[s[15]] << 8 | table[s[16]] << 4 | table[s[17]];
|
|
||||||
|
|
||||||
/* these are just sequential bytes */
|
|
||||||
clsid.Data4[0] = table[s[19]] << 4 | table[s[20]];
|
|
||||||
clsid.Data4[1] = table[s[21]] << 4 | table[s[22]];
|
|
||||||
clsid.Data4[2] = table[s[24]] << 4 | table[s[25]];
|
|
||||||
clsid.Data4[3] = table[s[26]] << 4 | table[s[27]];
|
|
||||||
clsid.Data4[4] = table[s[28]] << 4 | table[s[29]];
|
|
||||||
clsid.Data4[5] = table[s[30]] << 4 | table[s[31]];
|
|
||||||
clsid.Data4[6] = table[s[32]] << 4 | table[s[33]];
|
|
||||||
clsid.Data4[7] = table[s[34]] << 4 | table[s[35]];
|
|
||||||
|
|
||||||
hr = CreateClassMoniker(&clsid, ppmk);
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
*pchEaten = (*end == ':' ? end + 1 : end) - szDisplayName;
|
*eaten = end - display_name;
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -827,7 +827,6 @@ HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
|
||||||
LPDWORD pchEaten, LPMONIKER *ppmk)
|
LPDWORD pchEaten, LPMONIKER *ppmk)
|
||||||
{
|
{
|
||||||
HRESULT hr = MK_E_SYNTAX;
|
HRESULT hr = MK_E_SYNTAX;
|
||||||
static const WCHAR wszClsidColon[] = {'c','l','s','i','d',':'};
|
|
||||||
IMoniker *moniker;
|
IMoniker *moniker;
|
||||||
DWORD chEaten;
|
DWORD chEaten;
|
||||||
|
|
||||||
|
@ -845,7 +844,7 @@ HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
|
||||||
*pchEaten = 0;
|
*pchEaten = 0;
|
||||||
*ppmk = NULL;
|
*ppmk = NULL;
|
||||||
|
|
||||||
if (!wcsnicmp(szDisplayName, wszClsidColon, ARRAY_SIZE(wszClsidColon)))
|
if (!wcsnicmp(szDisplayName, L"clsid:", 6))
|
||||||
{
|
{
|
||||||
hr = ClassMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
|
hr = ClassMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
|
||||||
if (FAILED(hr) && (hr != MK_E_SYNTAX))
|
if (FAILED(hr) && (hr != MK_E_SYNTAX))
|
||||||
|
|
|
@ -1767,6 +1767,22 @@ todo_wine_if(moniker_type == MKSYS_GENERICCOMPOSITE)
|
||||||
|
|
||||||
static void test_class_moniker(void)
|
static void test_class_moniker(void)
|
||||||
{
|
{
|
||||||
|
static const struct parse_test
|
||||||
|
{
|
||||||
|
const WCHAR *name;
|
||||||
|
ULONG eaten;
|
||||||
|
HRESULT hr;
|
||||||
|
}
|
||||||
|
tests[] =
|
||||||
|
{
|
||||||
|
{ L"clsid:11111111-0000-0000-2222-444444444444;extra data:", 54 },
|
||||||
|
{ L"clsid:11111111-0000-0000-2222-444444444444extra data", 52 },
|
||||||
|
{ L"clsid:11111111-0000-0000-2222-444444444444:", 43 },
|
||||||
|
{ L"clsid:11111111-0000-0000-2222-444444444444", 42 },
|
||||||
|
{ L"clsid:{11111111-0000-0000-2222-444444444444}", 44 },
|
||||||
|
{ L"clsid:{11111111-0000-0000-2222-444444444444", 0, MK_E_SYNTAX },
|
||||||
|
{ L"clsid:11111111-0000-0000-2222-444444444444}", 43 },
|
||||||
|
};
|
||||||
IMoniker *moniker, *moniker2, *inverse, *reduced, *anti;
|
IMoniker *moniker, *moniker2, *inverse, *reduced, *anti;
|
||||||
IEnumMoniker *enummoniker;
|
IEnumMoniker *enummoniker;
|
||||||
ULONG length, eaten;
|
ULONG length, eaten;
|
||||||
|
@ -1780,38 +1796,51 @@ static void test_class_moniker(void)
|
||||||
FILETIME filetime;
|
FILETIME filetime;
|
||||||
IStream *stream;
|
IStream *stream;
|
||||||
BYTE buffer[100];
|
BYTE buffer[100];
|
||||||
|
HGLOBAL hglobal;
|
||||||
|
unsigned int i;
|
||||||
|
DWORD *data;
|
||||||
|
|
||||||
hr = CreateBindCtx(0, &bindctx);
|
hr = CreateBindCtx(0, &bindctx);
|
||||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(tests); ++i)
|
||||||
|
{
|
||||||
|
eaten = 0xdeadbeef;
|
||||||
|
hr = MkParseDisplayName(bindctx, tests[i].name, &eaten, &moniker);
|
||||||
|
todo_wine_if(i == 5)
|
||||||
|
ok(hr == tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
|
||||||
|
ok(eaten == tests[i].eaten, "%u: unexpected eaten length %u, expected %u.\n", i, eaten, tests[i].eaten);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
TEST_MONIKER_TYPE(moniker, MKSYS_CLASSMONIKER);
|
||||||
|
IMoniker_Release(moniker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Extended syntax, handled by class moniker directly, only CLSID is meaningful for equality. */
|
/* Extended syntax, handled by class moniker directly, only CLSID is meaningful for equality. */
|
||||||
hr = MkParseDisplayName(bindctx, L"clsid:11111111-0000-0000-2222-444444444444;extra data:", &eaten, &moniker);
|
hr = MkParseDisplayName(bindctx, L"clsid:11111111-0000-0000-2222-444444444444;extra data:", &eaten, &moniker);
|
||||||
todo_wine
|
|
||||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||||
if (SUCCEEDED(hr))
|
ok(eaten == 54, "Unexpected length %u.\n", eaten);
|
||||||
{
|
|
||||||
ok(eaten == 54, "Unexpected length %u.\n", eaten);
|
|
||||||
|
|
||||||
hr = MkParseDisplayName(bindctx, L"clsid:11111111-0000-0000-2222-444444444444;different extra data:", &eaten, &moniker2);
|
hr = MkParseDisplayName(bindctx, L"clsid:11111111-0000-0000-2222-444444444444;different extra data:", &eaten, &moniker2);
|
||||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
TEST_DISPLAY_NAME(moniker, L"clsid:11111111-0000-0000-2222-444444444444;extra data:");
|
TEST_DISPLAY_NAME(moniker, L"clsid:11111111-0000-0000-2222-444444444444;extra data:");
|
||||||
TEST_MONIKER_TYPE(moniker, MKSYS_CLASSMONIKER);
|
TEST_MONIKER_TYPE(moniker, MKSYS_CLASSMONIKER);
|
||||||
hr = IMoniker_GetSizeMax(moniker, &size);
|
hr = IMoniker_GetSizeMax(moniker, &size);
|
||||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||||
ok(size.LowPart == 44, "Unexpected size %u.\n", size.LowPart);
|
ok(size.LowPart == 44, "Unexpected size %u.\n", size.LowPart);
|
||||||
|
|
||||||
TEST_MONIKER_TYPE(moniker2, MKSYS_CLASSMONIKER);
|
TEST_MONIKER_TYPE(moniker2, MKSYS_CLASSMONIKER);
|
||||||
|
|
||||||
hr = IMoniker_IsEqual(moniker, moniker2);
|
hr = IMoniker_IsEqual(moniker, moniker2);
|
||||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
hr = IMoniker_IsEqual(moniker2, moniker);
|
hr = IMoniker_IsEqual(moniker2, moniker);
|
||||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
IMoniker_Release(moniker2);
|
IMoniker_Release(moniker2);
|
||||||
IMoniker_Release(moniker);
|
IMoniker_Release(moniker);
|
||||||
}
|
|
||||||
|
|
||||||
/* From persistent state */
|
/* From persistent state */
|
||||||
hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
|
hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
|
||||||
|
@ -1842,6 +1871,27 @@ todo_wine
|
||||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||||
ok(size.QuadPart == 30, "Unexpected size %u.\n", size.LowPart);
|
ok(size.QuadPart == 30, "Unexpected size %u.\n", size.LowPart);
|
||||||
TEST_DISPLAY_NAME(moniker, L"clsid:0002E005-0000-0000-C000-000000000046data:");
|
TEST_DISPLAY_NAME(moniker, L"clsid:0002E005-0000-0000-C000-000000000046data:");
|
||||||
|
IStream_Release(stream);
|
||||||
|
|
||||||
|
hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
|
||||||
|
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = GetHGlobalFromStream(stream, &hglobal);
|
||||||
|
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = IMoniker_Save(moniker, stream, FALSE);
|
||||||
|
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
|
length = GlobalSize(hglobal);
|
||||||
|
data = GlobalLock(hglobal);
|
||||||
|
ok(length == 30, "Unexpected stream size %u.\n", length);
|
||||||
|
ok(IsEqualGUID((CLSID *)data, &CLSID_StdComponentCategoriesMgr), "Unexpected clsid.\n");
|
||||||
|
data += sizeof(CLSID) / sizeof(*data);
|
||||||
|
ok(*data == 10, "Unexpected data length %u.\n", *data);
|
||||||
|
data++;
|
||||||
|
ok(!lstrcmpW((WCHAR *)data, L"data"), "Unexpected data.\n");
|
||||||
|
|
||||||
|
IStream_Release(stream);
|
||||||
|
|
||||||
/* Extra data does not affect comparison */
|
/* Extra data does not affect comparison */
|
||||||
hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
|
hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
|
||||||
|
@ -1852,7 +1902,6 @@ todo_wine
|
||||||
ok(!memcmp(buffer, expected_class_moniker_comparison_data, length), "Unexpected data.\n");
|
ok(!memcmp(buffer, expected_class_moniker_comparison_data, length), "Unexpected data.\n");
|
||||||
IROTData_Release(rotdata);
|
IROTData_Release(rotdata);
|
||||||
|
|
||||||
IStream_Release(stream);
|
|
||||||
IMoniker_Release(moniker);
|
IMoniker_Release(moniker);
|
||||||
|
|
||||||
hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
|
hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
|
||||||
|
|
Loading…
Reference in New Issue