wusa: Parse update descriptions.

Based on patches by Michael Müller and Sebastian Lackner.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
stable
Hans Leidekker 2019-12-02 10:11:51 +01:00 committed by Alexandre Julliard
parent bf46a16711
commit 45b59c85ca
3 changed files with 154 additions and 0 deletions

View File

@ -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:

View File

@ -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;
}

View File

@ -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)