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>
This commit is contained in:
parent
bf46a16711
commit
45b59c85ca
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue