From: Michael Müller michael@fds-team.de
Signed-off-by: Vijay Kiran Kamuju infyquest@gmail.com --- programs/wusa/main.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 166 insertions(+), 5 deletions(-)
diff --git a/programs/wusa/main.c b/programs/wusa/main.c index aa7a38fe178..77dd46d8bd4 100644 --- a/programs/wusa/main.c +++ b/programs/wusa/main.c @@ -1,5 +1,7 @@ /* * Copyright 2012 Austin English + * Copyright 2015 Michael Müller + * Copyright 2015 Sebastian Lackner * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,17 +19,176 @@ */
#include "wine/debug.h" +#include "wine/heap.h" +#include "wine/list.h" +#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(wusa);
+struct installer_tempdir { + struct list entry; + WCHAR *path; +}; + +struct installer_state { + BOOL norestart; + BOOL quiet; + struct list tempdirs; +}; + +static const WCHAR *path_combine(const WCHAR *path, const WCHAR *filename) +{ + static const WCHAR backslashW[] = {'\',0}; + WCHAR *result; + DWORD length; + + if (!path || !filename) + return NULL; + length = strlenW(path) + strlenW(filename) + 2; + if (!(result = heap_alloc(length * sizeof(WCHAR)))) + return NULL; + + strcpyW(result,path); + if (result[0] && result[strlenW(result) - 1] != '\') + strcatW(result, backslashW); + strcatW(result,filename); + return result; +} + +static BOOL delete_directory(const WCHAR *path) +{ + static const WCHAR starW[] = {'*',0}; + static const WCHAR dotW[] = {'.',0}; + static const WCHAR dotdotW[] = {'.','.',0}; + WIN32_FIND_DATAW data; + WCHAR *full_path; + HANDLE search; + + if (!(full_path = (WCHAR *)path_combine(path, starW))) + return FALSE; + search = FindFirstFileW(full_path, &data); + heap_free(full_path); + + if (search != INVALID_HANDLE_VALUE) + { + do + { + if (!strcmpW(data.cFileName, dotW)) + continue; + if (!strcmpW(data.cFileName, dotdotW)) + continue; + if (!(full_path = (WCHAR *)path_combine(path, data.cFileName))) + continue; + if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + delete_directory(full_path); + else + DeleteFileW(full_path); + heap_free(full_path); + } while (FindNextFileW(search, &data)); + FindClose(search); + } + + return RemoveDirectoryW(full_path); +} + +static const WCHAR *create_temp_directory(struct installer_state *state) +{ + static const WCHAR msuW[] = {'m','s','u',0}; + static UINT id; + struct installer_tempdir *entry; + WCHAR tmp[MAX_PATH]; + + if (!GetTempPathW(sizeof(tmp)/sizeof(WCHAR), tmp)) + return NULL; + if (!(entry = heap_alloc(sizeof(*entry)))) + return NULL; + if (!(entry->path = heap_alloc((MAX_PATH+20)*sizeof(WCHAR)))) + { + heap_free(entry); + return NULL; + } + + for(;;) + { + if (!GetTempFileNameW(tmp, msuW, ++id, entry->path)) + { + heap_free(entry->path); + heap_free(entry); + return NULL; + } + if (CreateDirectoryW(entry->path, NULL)) + break; + } + + list_add_tail(&state->tempdirs, &entry->entry); + return entry->path; +} + +static void installer_cleanup(struct installer_state *state) +{ + struct installer_tempdir *tempdir, *tempdir2; + + LIST_FOR_EACH_ENTRY_SAFE(tempdir, tempdir2, &state->tempdirs, struct installer_tempdir, entry) + { + list_remove(&tempdir->entry); + delete_directory(tempdir->path); + heap_free(tempdir->path); + heap_free(tempdir); + } +} + +static BOOL install_msu(WCHAR *filename, struct installer_state *state) +{ + const WCHAR *temp_path; + + list_init(&state->tempdirs); + + WINE_TRACE("Processing msu file %s\n", wine_dbgstr_w(filename)); + if (!(temp_path = create_temp_directory(state))) + return FALSE; + + installer_cleanup(state); + return TRUE; +} + int wmain(int argc, WCHAR *argv[]) { + static const WCHAR norestartW[] = {'/','n','o','r','e','s','t','a','r','t',0}; + static const WCHAR quietW[] = {'/','q','u','i','e','t',0}; + struct installer_state state; + WCHAR *filename = NULL; int i;
- WINE_FIXME("stub:"); - for (i = 0; i < argc; i++) - WINE_FIXME(" %s", wine_dbgstr_w(argv[i])); - WINE_FIXME("\n"); + if (TRACE_ON(wusa)) + { + WINE_TRACE("Command line :"); + for (i = 0; i < argc; i++) + WINE_TRACE(" %s", wine_dbgstr_w(argv[i])); + WINE_TRACE("\n"); + } + + for (i = 1; i < argc; i++) + { + if (argv[i][0] == '/') + { + if (!strcmpW(argv[i], norestartW)) + state.norestart = TRUE; + else if (!strcmpW(argv[i], quietW)) + state.quiet = TRUE; + else + WINE_FIXME("Unknown option: %s\n", wine_dbgstr_w(argv[i])); + } + else if (!filename) + filename = argv[i]; + else + WINE_FIXME("Unknown option: %s\n", wine_dbgstr_w(argv[i])); + } + + if (!filename) + { + WINE_FIXME("Missing filename argument\n"); + return 1; + }
- return 0; + return !install_msu(filename, &state); }