From 45b59c85cae39d6d658aa8aea2ba3921dcf6d55c Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Mon, 2 Dec 2019 10:11:51 +0100 Subject: [PATCH] wusa: Parse update descriptions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on patches by Michael Müller and Sebastian Lackner. Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- 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 a1cdea4ee88..8df8731e2b5 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 44c263f6c0e..e80c11998ce 100644 --- a/programs/wusa/manifest.c +++ b/programs/wusa/manifest.c @@ -565,3 +565,109 @@ done: IXMLDOMElement_Release(root); return entry; } + +/* */ +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); +} + +/* */ +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); +} + +/* */ +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 2c81b639b91..e717fad6e00 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)