Jacek Caban : scrobj: Add registration element parser.

Alexandre Julliard julliard at winehq.org
Thu Sep 19 16:35:18 CDT 2019


Module: wine
Branch: master
Commit: e8d99613fc0abe6b9eb9fefcef0099b8fb9c2485
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=e8d99613fc0abe6b9eb9fefcef0099b8fb9c2485

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu Sep 19 17:28:54 2019 +0200

scrobj: Add registration element parser.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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;




More information about the wine-cvs mailing list