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
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* CreateClassMoniker [OLE32.@]
|
||||
******************************************************************************/
|
||||
HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker **moniker)
|
||||
static HRESULT create_class_moniker(const CLSID *clsid, const WCHAR *data,
|
||||
unsigned int data_len, IMoniker **moniker)
|
||||
{
|
||||
ClassMoniker *object;
|
||||
|
||||
TRACE("%s, %p\n", debugstr_guid(rclsid), moniker);
|
||||
|
||||
if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
|
||||
if (!(object = heap_alloc_zero(sizeof(*object))))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
object->IMoniker_iface.lpVtbl = &ClassMonikerVtbl;
|
||||
object->IROTData_iface.lpVtbl = &ROTDataVtbl;
|
||||
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;
|
||||
|
||||
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;
|
||||
LPCWSTR s = wcschr(szDisplayName, ':');
|
||||
LPCWSTR end;
|
||||
TRACE("%s, %p\n", debugstr_guid(rclsid), moniker);
|
||||
|
||||
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;
|
||||
BYTE table[256];
|
||||
int i;
|
||||
HRESULT hr;
|
||||
int len;
|
||||
|
||||
if (!s)
|
||||
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;
|
||||
|
||||
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));
|
||||
|
||||
/* validate the CLSID string */
|
||||
if (s[0] == '{')
|
||||
if (UuidFromStringW(uuid, &clsid))
|
||||
{
|
||||
if ((end - s != 38) || (s[37] != '}'))
|
||||
WARN("Failed to parse clsid string.\n");
|
||||
return MK_E_SYNTAX;
|
||||
}
|
||||
|
||||
s += 36;
|
||||
if (has_braces)
|
||||
{
|
||||
if (*s != '}') return MK_E_SYNTAX;
|
||||
s++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (end - s != 36)
|
||||
return MK_E_SYNTAX;
|
||||
}
|
||||
|
||||
for (i=0; i<36; i++)
|
||||
{
|
||||
if ((i == 8)||(i == 13)||(i == 18)||(i == 23))
|
||||
{
|
||||
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;
|
||||
}
|
||||
/* Consume terminal marker */
|
||||
len = end - s;
|
||||
if (*end == ':') end++;
|
||||
|
||||
/* quick lookup table */
|
||||
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);
|
||||
hr = create_class_moniker(&clsid, len ? s : NULL, len, moniker);
|
||||
if (SUCCEEDED(hr))
|
||||
*pchEaten = (*end == ':' ? end + 1 : end) - szDisplayName;
|
||||
*eaten = end - display_name;
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
|
|
@ -827,7 +827,6 @@ HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
|
|||
LPDWORD pchEaten, LPMONIKER *ppmk)
|
||||
{
|
||||
HRESULT hr = MK_E_SYNTAX;
|
||||
static const WCHAR wszClsidColon[] = {'c','l','s','i','d',':'};
|
||||
IMoniker *moniker;
|
||||
DWORD chEaten;
|
||||
|
||||
|
@ -845,7 +844,7 @@ HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
|
|||
*pchEaten = 0;
|
||||
*ppmk = NULL;
|
||||
|
||||
if (!wcsnicmp(szDisplayName, wszClsidColon, ARRAY_SIZE(wszClsidColon)))
|
||||
if (!wcsnicmp(szDisplayName, L"clsid:", 6))
|
||||
{
|
||||
hr = ClassMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
|
||||
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 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;
|
||||
IEnumMoniker *enummoniker;
|
||||
ULONG length, eaten;
|
||||
|
@ -1780,16 +1796,30 @@ static void test_class_moniker(void)
|
|||
FILETIME filetime;
|
||||
IStream *stream;
|
||||
BYTE buffer[100];
|
||||
HGLOBAL hglobal;
|
||||
unsigned int i;
|
||||
DWORD *data;
|
||||
|
||||
hr = CreateBindCtx(0, &bindctx);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
/* 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);
|
||||
todo_wine
|
||||
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. */
|
||||
hr = MkParseDisplayName(bindctx, L"clsid:11111111-0000-0000-2222-444444444444;extra data:", &eaten, &moniker);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
ok(eaten == 54, "Unexpected length %u.\n", eaten);
|
||||
|
||||
hr = MkParseDisplayName(bindctx, L"clsid:11111111-0000-0000-2222-444444444444;different extra data:", &eaten, &moniker2);
|
||||
|
@ -1811,7 +1841,6 @@ todo_wine
|
|||
|
||||
IMoniker_Release(moniker2);
|
||||
IMoniker_Release(moniker);
|
||||
}
|
||||
|
||||
/* From persistent state */
|
||||
hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
|
||||
|
@ -1842,6 +1871,27 @@ todo_wine
|
|||
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:");
|
||||
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 */
|
||||
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");
|
||||
IROTData_Release(rotdata);
|
||||
|
||||
IStream_Release(stream);
|
||||
IMoniker_Release(moniker);
|
||||
|
||||
hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
|
||||
|
|
Loading…
Reference in New Issue