Module: wine Branch: master Commit: e8d99613fc0abe6b9eb9fefcef0099b8fb9c2485 URL: https://source.winehq.org/git/wine.git/?a=commit;h=e8d99613fc0abe6b9eb9fefce...
Author: Jacek Caban jacek@codeweavers.com Date: Thu Sep 19 17:28:54 2019 +0200
scrobj: Add registration element parser.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/scrobj/scrobj.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 140 insertions(+), 2 deletions(-)
diff --git a/dlls/scrobj/scrobj.c b/dlls/scrobj/scrobj.c index 2bc746a179..83a9b099d7 100644 --- a/dlls/scrobj/scrobj.c +++ b/dlls/scrobj/scrobj.c @@ -44,6 +44,14 @@ struct scriptlet_factory
IXmlReader *xml_reader; IMoniker *moniker; + + BOOL have_registration; + WCHAR *description; + WCHAR *progid; + WCHAR *versioned_progid; + WCHAR *version; + WCHAR *classid_str; + CLSID classid; };
typedef enum tid_t @@ -148,6 +156,19 @@ static BOOL is_xml_name(struct scriptlet_factory *factory, const WCHAR *name) return hres == S_OK && len == wcslen(name) && !memcmp(qname, name, len * sizeof(WCHAR)); }
+static HRESULT expect_end_element(struct scriptlet_factory *factory) +{ + XmlNodeType node_type; + HRESULT hres; + hres = next_xml_node(factory, &node_type); + if (hres != S_OK || node_type != XmlNodeType_EndElement) + { + FIXME("Unexpected node %u %s\n", node_type, debugstr_xml_name(factory)); + return E_FAIL; + } + return S_OK; +} + static HRESULT expect_no_attributes(struct scriptlet_factory *factory) { UINT count; @@ -159,10 +180,122 @@ static HRESULT expect_no_attributes(struct scriptlet_factory *factory) return E_FAIL; }
+static BOOL is_case_xml_name(struct scriptlet_factory *factory, const WCHAR *name) +{ + const WCHAR *qname; + UINT len; + HRESULT hres; + hres = IXmlReader_GetQualifiedName(factory->xml_reader, &qname, &len); + return hres == S_OK && len == wcslen(name) && !memicmp(qname, name, len * sizeof(WCHAR)); +} + +static HRESULT read_xml_value(struct scriptlet_factory *factory, WCHAR **ret) +{ + const WCHAR *str; + UINT len; + HRESULT hres; + hres = IXmlReader_GetValue(factory->xml_reader, &str, &len); + if (FAILED(hres)) return hres; + if (!(*ret = heap_alloc((len + 1) * sizeof(WCHAR)))) return E_OUTOFMEMORY; + memcpy(*ret, str, len * sizeof(WCHAR)); + (*ret)[len] = 0; + return S_OK; +} + static HRESULT parse_scriptlet_registration(struct scriptlet_factory *factory) { - FIXME("\n"); - return E_NOTIMPL; + HRESULT hres; + + if (factory->have_registration) + { + FIXME("duplicated registration element\n"); + return E_FAIL; + } + factory->have_registration = TRUE; + + for (;;) + { + hres = IXmlReader_MoveToNextAttribute(factory->xml_reader); + if (hres != S_OK) break; + + if (is_xml_name(factory, L"description")) + { + if (factory->description) + { + FIXME("Duplicated description\n"); + return E_FAIL; + } + hres = read_xml_value(factory, &factory->description); + if (FAILED(hres)) return hres; + } + else if (is_case_xml_name(factory, L"progid")) + { + if (factory->progid) + { + FIXME("Duplicated progid\n"); + return E_FAIL; + } + hres = read_xml_value(factory, &factory->progid); + if (FAILED(hres)) return hres; + } + else if (is_xml_name(factory, L"version")) + { + if (factory->version) + { + FIXME("Duplicated version\n"); + return E_FAIL; + } + hres = read_xml_value(factory, &factory->version); + if (FAILED(hres)) return hres; + } + else if (is_xml_name(factory, L"classid")) + { + if (factory->classid_str) + { + FIXME("Duplicated classid attribute\n"); + return E_FAIL; + } + hres = read_xml_value(factory, &factory->classid_str); + if (FAILED(hres)) return hres; + hres = IIDFromString(factory->classid_str, &factory->classid); + if (FAILED(hres)) + { + FIXME("Invalid classid %s\n", debugstr_w(factory->classid_str)); + + return E_FAIL; + } + } + else + { + FIXME("Unexpected attribute\n"); + return E_NOTIMPL; + } + } + + if (!factory->progid && !factory->classid_str) + { + FIXME("Incomplet registration element\n"); + return E_FAIL; + } + + if (factory->progid) + { + size_t progid_len = wcslen(factory->progid); + size_t version_len = wcslen(factory->version); + + if (!(factory->versioned_progid = heap_alloc((progid_len + version_len + 2) * sizeof(WCHAR)))) + return E_OUTOFMEMORY; + + memcpy(factory->versioned_progid, factory->progid, (progid_len + 1) * sizeof(WCHAR)); + if (version_len) + { + factory->versioned_progid[progid_len++] = '.'; + wcscpy(factory->versioned_progid + progid_len, factory->version); + } + else factory->versioned_progid[progid_len] = 0; + } + + return expect_end_element(factory); }
static HRESULT parse_scriptlet_public(struct scriptlet_factory *factory) @@ -305,6 +438,11 @@ static ULONG WINAPI scriptlet_factory_Release(IClassFactory *iface) { if (This->moniker) IMoniker_Release(This->moniker); if (This->xml_reader) IXmlReader_Release(This->xml_reader); + heap_free(This->classid_str); + heap_free(This->description); + heap_free(This->versioned_progid); + heap_free(This->progid); + heap_free(This->version); heap_free(This); } return ref;