Commit 45b59c85 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

wusa: Parse update descriptions.

Based on patches by Michael Müller and Sebastian Lackner. Signed-off-by: 's avatarHans Leidekker <hans@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent bf46a167
...@@ -41,6 +41,7 @@ struct installer_state ...@@ -41,6 +41,7 @@ struct installer_state
BOOL quiet; BOOL quiet;
struct list tempdirs; struct list tempdirs;
struct list assemblies; struct list assemblies;
struct list updates;
}; };
static void * CDECL cabinet_alloc(ULONG cb) static void * CDECL cabinet_alloc(ULONG cb)
...@@ -317,6 +318,7 @@ static void installer_cleanup(struct installer_state *state) ...@@ -317,6 +318,7 @@ static void installer_cleanup(struct installer_state *state)
{ {
struct installer_tempdir *tempdir, *tempdir2; struct installer_tempdir *tempdir, *tempdir2;
struct assembly_entry *assembly, *assembly2; struct assembly_entry *assembly, *assembly2;
struct dependency_entry *dependency, *dependency2;
LIST_FOR_EACH_ENTRY_SAFE(tempdir, tempdir2, &state->tempdirs, struct installer_tempdir, entry) 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) ...@@ -330,6 +332,11 @@ static void installer_cleanup(struct installer_state *state)
list_remove(&assembly->entry); list_remove(&assembly->entry);
free_assembly(assembly); 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) 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) ...@@ -397,6 +404,7 @@ static BOOL install_msu(const WCHAR *filename, struct installer_state *state)
list_init(&state->tempdirs); list_init(&state->tempdirs);
list_init(&state->assemblies); list_init(&state->assemblies);
list_init(&state->updates);
CoInitialize(NULL); CoInitialize(NULL);
TRACE("Processing msu file %s\n", debugstr_w(filename)); TRACE("Processing msu file %s\n", debugstr_w(filename));
...@@ -428,6 +436,44 @@ static BOOL install_msu(const WCHAR *filename, struct installer_state *state) ...@@ -428,6 +436,44 @@ static BOOL install_msu(const WCHAR *filename, struct installer_state *state)
FindClose(search); 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; ret = TRUE;
done: done:
......
...@@ -565,3 +565,109 @@ done: ...@@ -565,3 +565,109 @@ done:
IXMLDOMElement_Release(root); IXMLDOMElement_Release(root);
return entry; 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;
}
...@@ -74,7 +74,9 @@ struct assembly_entry ...@@ -74,7 +74,9 @@ struct assembly_entry
}; };
void free_assembly(struct assembly_entry *entry) DECLSPEC_HIDDEN; 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; 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 void *heap_alloc(size_t len) __WINE_ALLOC_SIZE(1);
static inline void *heap_alloc(size_t len) static inline void *heap_alloc(size_t len)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment