[PATCH 3/4] wusa: Parse update descriptions.

Hans Leidekker hans at codeweavers.com
Mon Dec 2 03:11:51 CST 2019


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 programs/wusa/main.c     |  46 +++++++++++++++++
 programs/wusa/manifest.c | 106 +++++++++++++++++++++++++++++++++++++++
 programs/wusa/wusa.h     |   2 +
 3 files changed, 154 insertions(+)

diff --git a/programs/wusa/main.c b/programs/wusa/main.c
index a1cdea4ee8..8df8731e2b 100644
--- a/programs/wusa/main.c
+++ b/programs/wusa/main.c
@@ -41,6 +41,7 @@ struct installer_state
     BOOL quiet;
     struct list tempdirs;
     struct list assemblies;
+    struct list updates;
 };
 
 static void * CDECL cabinet_alloc(ULONG cb)
@@ -317,6 +318,7 @@ static void installer_cleanup(struct installer_state *state)
 {
     struct installer_tempdir *tempdir, *tempdir2;
     struct assembly_entry *assembly, *assembly2;
+    struct dependency_entry *dependency, *dependency2;
 
     LIST_FOR_EACH_ENTRY_SAFE(tempdir, tempdir2, &state->tempdirs, struct installer_tempdir, entry)
     {
@@ -330,6 +332,11 @@ static void installer_cleanup(struct installer_state *state)
         list_remove(&assembly->entry);
         free_assembly(assembly);
     }
+    LIST_FOR_EACH_ENTRY_SAFE(dependency, dependency2, &state->updates, struct dependency_entry, entry)
+    {
+        list_remove(&dependency->entry);
+        free_dependency(dependency);
+    }
 }
 
 static BOOL str_ends_with(const WCHAR *str, const WCHAR *suffix)
@@ -397,6 +404,7 @@ static BOOL install_msu(const WCHAR *filename, struct installer_state *state)
 
     list_init(&state->tempdirs);
     list_init(&state->assemblies);
+    list_init(&state->updates);
     CoInitialize(NULL);
 
     TRACE("Processing msu file %s\n", debugstr_w(filename));
@@ -428,6 +436,44 @@ static BOOL install_msu(const WCHAR *filename, struct installer_state *state)
         FindClose(search);
     }
 
+    /* load all update descriptions */
+    if (!(path = path_combine(temp_path, L"*.xml"))) goto done;
+    search = FindFirstFileW(path, &data);
+    heap_free(path);
+
+    if (search != INVALID_HANDLE_VALUE)
+    {
+        do
+        {
+            if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
+            if (!(path = path_combine(temp_path, data.cFileName))) continue;
+            if (!load_update(path, &state->updates))
+                ERR("Failed to load all updates from %s, ignoring\n", debugstr_w(path));
+            heap_free(path);
+        }
+        while (FindNextFileW(search, &data));
+        FindClose(search);
+    }
+
+    /* dump package information (for debugging) */
+    if (TRACE_ON(wusa))
+    {
+        struct dependency_entry *dependency;
+        struct assembly_entry *assembly;
+
+        TRACE("List of updates:\n");
+        LIST_FOR_EACH_ENTRY(dependency, &state->updates, struct dependency_entry, entry)
+            TRACE(" * %s\n", debugstr_w(dependency->identity.name));
+
+        TRACE("List of manifests (with dependencies):\n");
+        LIST_FOR_EACH_ENTRY(assembly, &state->assemblies, struct assembly_entry, entry)
+        {
+            TRACE(" * %s\n", debugstr_w(assembly->identity.name));
+            LIST_FOR_EACH_ENTRY(dependency, &assembly->dependencies, struct dependency_entry, entry)
+                TRACE("   -> %s\n", debugstr_w(dependency->identity.name));
+        }
+    }
+
     ret = TRUE;
 
 done:
diff --git a/programs/wusa/manifest.c b/programs/wusa/manifest.c
index 44c263f6c0..e80c11998c 100644
--- a/programs/wusa/manifest.c
+++ b/programs/wusa/manifest.c
@@ -565,3 +565,109 @@ done:
     IXMLDOMElement_Release(root);
     return entry;
 }
+
+/* <unattend><servicing><package> */
+static BOOL read_update_package(IXMLDOMElement *child, WCHAR *tagname, void *context)
+{
+    struct dependency_entry *entry;
+    struct list *update_list = context;
+
+    if (!wcscmp(tagname, L"source")) return TRUE;
+    if (wcscmp(tagname, L"assemblyIdentity"))
+    {
+        TRACE("Ignoring unexpected tag %s\n", debugstr_w(tagname));
+        return TRUE;
+    }
+
+    if ((entry = alloc_dependency()))
+    {
+        if (read_identity(child, &entry->identity))
+        {
+            TRACE("Found update %s\n", debugstr_w(entry->identity.name));
+            list_add_tail(update_list, &entry->entry);
+            return TRUE;
+        }
+        free_dependency(entry);
+    }
+
+    return FALSE;
+}
+
+static BOOL iter_update_package(IXMLDOMElement *root, struct list *update_list)
+{
+    return call_xml_callbacks(root, read_update_package, update_list);
+}
+
+/* <unattend><servicing> */
+static BOOL read_servicing(IXMLDOMElement *child, WCHAR *tagname, void *context)
+{
+    struct list *update_list = context;
+    WCHAR *action;
+    BOOL ret = TRUE;
+
+    if (wcscmp(tagname, L"package"))
+    {
+        FIXME("Ignoring unexpected tag %s\n", debugstr_w(tagname));
+        return TRUE;
+    }
+
+    if (!(action = get_xml_attribute(child, L"action")))
+    {
+        FIXME("Servicing tag doesn't specify action\n");
+        return FALSE;
+    }
+
+    if (!wcscmp(action, L"install"))
+        ret = iter_update_package(child, update_list);
+    else
+        FIXME("action %s not supported\n", debugstr_w(action));
+
+    heap_free(action);
+    return ret;
+}
+
+static BOOL iter_servicing(IXMLDOMElement *root, struct list *update_list)
+{
+    return call_xml_callbacks(root, read_servicing, update_list);
+}
+
+/* <unattend> */
+static BOOL read_unattend(IXMLDOMElement *child, WCHAR *tagname, void *context)
+{
+    struct list *update_list = context;
+
+    if (wcscmp(tagname, L"servicing"))
+    {
+        FIXME("Ignoring unexpected tag %s\n", debugstr_w(tagname));
+        return TRUE;
+    }
+
+    return iter_servicing(child, update_list);
+
+}
+
+static BOOL iter_unattend(IXMLDOMElement *root, struct list *update_list)
+{
+    return call_xml_callbacks(root, read_unattend, update_list);
+}
+
+BOOL load_update(const WCHAR *filename, struct list *update_list)
+{
+    IXMLDOMElement *root = NULL;
+    BOOL ret = FALSE;
+
+    TRACE("Reading update %s\n", debugstr_w(filename));
+
+    if (!(root = load_xml(filename))) return FALSE;
+    if (!check_xml_tagname(root, L"unattend"))
+    {
+        FIXME("Didn't find unattend root node?\n");
+        goto done;
+    }
+
+    ret = iter_unattend(root, update_list);
+
+done:
+    IXMLDOMElement_Release(root);
+    return ret;
+}
diff --git a/programs/wusa/wusa.h b/programs/wusa/wusa.h
index 2c81b639b9..e717fad6e0 100644
--- a/programs/wusa/wusa.h
+++ b/programs/wusa/wusa.h
@@ -74,7 +74,9 @@ struct assembly_entry
 };
 
 void free_assembly(struct assembly_entry *entry) DECLSPEC_HIDDEN;
+void free_dependency(struct dependency_entry *entry) DECLSPEC_HIDDEN;
 struct assembly_entry *load_manifest(const WCHAR *filename) DECLSPEC_HIDDEN;
+BOOL load_update(const WCHAR *filename, struct list *update_list) DECLSPEC_HIDDEN;
 
 static void *heap_alloc(size_t len) __WINE_ALLOC_SIZE(1);
 static inline void *heap_alloc(size_t len)
-- 
2.20.1




More information about the wine-devel mailing list