Commit bf46a167 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

wusa: Parse assembly manifests.

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 9934b253
MODULE = wusa.exe
IMPORTS = cabinet shlwapi
IMPORTS = cabinet shlwapi ole32 oleaut32
EXTRADLLFLAGS = -mconsole -municode -mno-cygwin
C_SRCS = \
main.c
main.c \
manifest.c
......@@ -40,6 +40,7 @@ struct installer_state
BOOL norestart;
BOOL quiet;
struct list tempdirs;
struct list assemblies;
};
static void * CDECL cabinet_alloc(ULONG cb)
......@@ -315,6 +316,7 @@ static BOOL delete_directory(const WCHAR *path)
static void installer_cleanup(struct installer_state *state)
{
struct installer_tempdir *tempdir, *tempdir2;
struct assembly_entry *assembly, *assembly2;
LIST_FOR_EACH_ENTRY_SAFE(tempdir, tempdir2, &state->tempdirs, struct installer_tempdir, entry)
{
......@@ -323,14 +325,79 @@ static void installer_cleanup(struct installer_state *state)
heap_free(tempdir->path);
heap_free(tempdir);
}
LIST_FOR_EACH_ENTRY_SAFE(assembly, assembly2, &state->assemblies, struct assembly_entry, entry)
{
list_remove(&assembly->entry);
free_assembly(assembly);
}
}
static BOOL str_ends_with(const WCHAR *str, const WCHAR *suffix)
{
DWORD str_len = lstrlenW(str), suffix_len = lstrlenW(suffix);
if (suffix_len > str_len) return FALSE;
return !wcsicmp(str + str_len - suffix_len, suffix);
}
static BOOL load_assemblies_from_cab(const WCHAR *filename, struct installer_state *state)
{
struct assembly_entry *assembly;
const WCHAR *temp_path;
WIN32_FIND_DATAW data;
HANDLE search;
WCHAR *path;
TRACE("Processing cab file %s\n", debugstr_w(filename));
if (!(temp_path = create_temp_directory(state))) return FALSE;
if (!extract_cabinet(filename, temp_path))
{
ERR("Failed to extract %s\n", debugstr_w(filename));
return FALSE;
}
if (!(path = path_combine(temp_path, L"_manifest_.cix.xml"))) return FALSE;
if (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
{
FIXME("Cabinet uses proprietary msdelta file compression which is not (yet) supported\n");
FIXME("Installation of msu file will most likely fail\n");
}
heap_free(path);
if (!(path = path_combine(temp_path, L"*"))) return FALSE;
search = FindFirstFileW(path, &data);
heap_free(path);
if (search != INVALID_HANDLE_VALUE)
{
do
{
if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
if (!str_ends_with(data.cFileName, L".manifest") &&
!str_ends_with(data.cFileName, L".mum")) continue;
if (!(path = path_combine(temp_path, data.cFileName))) continue;
if ((assembly = load_manifest(path)))
list_add_tail(&state->assemblies, &assembly->entry);
heap_free(path);
}
while (FindNextFileW(search, &data));
FindClose(search);
}
return TRUE;
}
static BOOL install_msu(const WCHAR *filename, struct installer_state *state)
{
const WCHAR *temp_path;
WIN32_FIND_DATAW data;
HANDLE search;
WCHAR *path;
BOOL ret = FALSE;
list_init(&state->tempdirs);
list_init(&state->assemblies);
CoInitialize(NULL);
TRACE("Processing msu file %s\n", debugstr_w(filename));
......@@ -341,6 +408,26 @@ static BOOL install_msu(const WCHAR *filename, struct installer_state *state)
goto done;
}
/* load all manifests from contained cabinet archives */
if (!(path = path_combine(temp_path, L"*.cab"))) goto done;
search = FindFirstFileW(path, &data);
heap_free(path);
if (search != INVALID_HANDLE_VALUE)
{
do
{
if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
if (!wcsicmp(data.cFileName, L"WSUSSCAN.cab")) continue;
if (!(path = path_combine(temp_path, data.cFileName))) continue;
if (!load_assemblies_from_cab(path, state))
ERR("Failed to load all manifests from %s, ignoring\n", debugstr_w(path));
heap_free(path);
}
while (FindNextFileW(search, &data));
FindClose(search);
}
ret = TRUE;
done:
......
......@@ -17,12 +17,77 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
enum
{
ASSEMBLY_STATUS_NONE,
ASSEMBLY_STATUS_IN_PROGRESS,
ASSEMBLY_STATUS_INSTALLED,
};
struct assembly_identity
{
WCHAR *name;
WCHAR *version;
WCHAR *architecture;
WCHAR *language;
WCHAR *pubkey_token;
};
struct dependency_entry
{
struct list entry;
struct assembly_identity identity;
};
struct fileop_entry
{
struct list entry;
WCHAR *source;
WCHAR *target;
};
struct registrykv_entry
{
struct list entry;
WCHAR *name;
WCHAR *value_type;
WCHAR *value;
};
struct registryop_entry
{
struct list entry;
WCHAR *key;
struct list keyvalues;
};
struct assembly_entry
{
struct list entry;
DWORD status;
WCHAR *filename;
WCHAR *displayname;
struct assembly_identity identity;
struct list dependencies;
struct list fileops;
struct list registryops;
};
void free_assembly(struct assembly_entry *entry) DECLSPEC_HIDDEN;
struct assembly_entry *load_manifest(const WCHAR *filename) DECLSPEC_HIDDEN;
static void *heap_alloc(size_t len) __WINE_ALLOC_SIZE(1);
static inline void *heap_alloc(size_t len)
{
return HeapAlloc(GetProcessHeap(), 0, len);
}
static void *heap_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1);
static inline void *heap_alloc_zero(size_t len)
{
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
}
static inline BOOL heap_free(void *mem)
{
return HeapFree(GetProcessHeap(), 0, mem);
......
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