[PATCH 4/4] mscoree: Update install process to account for shared installs.

Vincent Povirk vincent at codeweavers.com
Thu Apr 4 10:05:32 CDT 2019


This will install the support MSI if it's found in a shared
install. Otherwise, it'll fall back to appwiz as before.

Signed-off-by: Vincent Povirk <vincent at codeweavers.com>
---
 dlls/mscoree/metahost.c        |   4 +-
 dlls/mscoree/mscoree_main.c    | 166 +++++++++++++++++++++++----------
 dlls/mscoree/mscoree_private.h |   2 +
 3 files changed, 122 insertions(+), 50 deletions(-)

diff --git a/dlls/mscoree/metahost.c b/dlls/mscoree/metahost.c
index 3c4f803717b..50d43b30ead 100644
--- a/dlls/mscoree/metahost.c
+++ b/dlls/mscoree/metahost.c
@@ -129,8 +129,6 @@ void (CDECL *mono_thread_manage)(void);
 void (CDECL *mono_trace_set_print_handler)(MonoPrintCallback callback);
 void (CDECL *mono_trace_set_printerr_handler)(MonoPrintCallback callback);
 
-static BOOL get_mono_path(LPWSTR path);
-
 static BOOL find_mono_dll(LPCWSTR path, LPWSTR dll_path);
 
 static MonoAssembly* CDECL mono_assembly_preload_hook_fn(MonoAssemblyName *aname, char **assemblies_path, void *user_data);
@@ -772,7 +770,7 @@ static BOOL get_mono_path_datadir(LPWSTR path)
     return ret;
 }
 
-static BOOL get_mono_path(LPWSTR path)
+BOOL get_mono_path(LPWSTR path)
 {
     return get_mono_path_local(path) ||
         get_mono_path_registry(path) ||
diff --git a/dlls/mscoree/mscoree_main.c b/dlls/mscoree/mscoree_main.c
index 7bb63592882..6393af8c6c5 100644
--- a/dlls/mscoree/mscoree_main.c
+++ b/dlls/mscoree/mscoree_main.c
@@ -665,30 +665,81 @@ static void parse_msi_version_string(const char *version, int *parts)
     }
 }
 
+static int compare_versions(const char *a, const char *b)
+{
+    int a_parts[3], b_parts[3], i;
+
+    parse_msi_version_string(a, a_parts);
+    parse_msi_version_string(b, b_parts);
+
+    for (i=0; i<3; i++)
+        if (a_parts[i] != b_parts[i])
+            return a_parts[i] - b_parts[i];
+
+    return 0;
+}
+
+static BOOL invoke_appwiz(void)
+{
+    PROCESS_INFORMATION pi;
+    STARTUPINFOW si;
+    WCHAR app[MAX_PATH];
+    WCHAR *args;
+    LONG len;
+    BOOL ret;
+
+    static const WCHAR controlW[] = {'\\','c','o','n','t','r','o','l','.','e','x','e',0};
+    static const WCHAR argsW[] =
+        {' ','a','p','p','w','i','z','.','c','p','l',' ','i','n','s','t','a','l','l','_','m','o','n','o',0};
+
+    len = GetSystemDirectoryW(app, MAX_PATH - ARRAY_SIZE(controlW));
+    memcpy(app+len, controlW, sizeof(controlW));
+
+    args = HeapAlloc(GetProcessHeap(), 0, (len*sizeof(WCHAR) + sizeof(controlW) + sizeof(argsW)));
+    if(!args)
+        return FALSE;
+
+    memcpy(args, app, len*sizeof(WCHAR) + sizeof(controlW));
+    memcpy(args + len + ARRAY_SIZE(controlW) - 1, argsW, sizeof(argsW));
+
+    TRACE("starting %s\n", debugstr_w(args));
+
+    memset(&si, 0, sizeof(si));
+    si.cb = sizeof(si);
+    ret = CreateProcessW(app, args, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+    HeapFree(GetProcessHeap(), 0, args);
+    if (ret) {
+        CloseHandle(pi.hThread);
+        WaitForSingleObject(pi.hProcess, INFINITE);
+        CloseHandle(pi.hProcess);
+    }
+
+    return ret;
+}
+
 static BOOL install_wine_mono(void)
 {
+    static const WCHAR support_msi_relative[] = {'\\','s','u','p','p','o','r','t','\\','w','i','n','e','m','o','n','o','-','s','u','p','p','o','r','t','.','m','s','i',0};
     BOOL is_wow64 = FALSE;
-    HMODULE hmsi;
+    HMODULE hmsi = NULL;
+    HRESULT initresult = E_FAIL;
     UINT (WINAPI *pMsiEnumRelatedProductsA)(LPCSTR,DWORD,DWORD,LPSTR);
     UINT (WINAPI *pMsiGetProductInfoA)(LPCSTR,LPCSTR,LPSTR,DWORD*);
+    UINT (WINAPI *pMsiOpenPackageW)(LPCWSTR,ULONG*);
+    UINT (WINAPI *pMsiGetProductPropertyA)(ULONG,LPCSTR,LPSTR,LPDWORD);
+    UINT (WINAPI *pMsiCloseHandle)(ULONG);
+    UINT (WINAPI *pMsiInstallProductW)(LPCWSTR,LPCWSTR);
     char versionstringbuf[15];
     char productcodebuf[39];
     UINT res;
     DWORD buffer_size;
-    PROCESS_INFORMATION pi;
-    STARTUPINFOW si;
-    WCHAR app[MAX_PATH];
-    WCHAR *args;
-    LONG len;
+    ULONG msiproduct;
     BOOL ret;
+    WCHAR mono_path[MAX_PATH];
+    WCHAR support_msi_path[MAX_PATH];
 
-    static const char* mono_version = WINE_MONO_VERSION;
     static const char* mono_upgrade_code = "{DE624609-C6B5-486A-9274-EF0B854F6BC5}";
 
-    static const WCHAR controlW[] = {'\\','c','o','n','t','r','o','l','.','e','x','e',0};
-    static const WCHAR argsW[] =
-        {' ','a','p','p','w','i','z','.','c','p','l',' ','i','n','s','t','a','l','l','_','m','o','n','o',0};
-
     IsWow64Process(GetCurrentProcess(), &is_wow64);
 
     if (is_wow64)
@@ -697,6 +748,16 @@ static BOOL install_wine_mono(void)
         return TRUE;
     }
 
+    TRACE("searching for mono runtime\n");
+
+    if (!get_mono_path(mono_path))
+    {
+        TRACE("mono runtime not found\n");
+        return invoke_appwiz();
+    }
+
+    TRACE("mono runtime is at %s\n", debugstr_w(mono_path));
+
     hmsi = LoadLibraryA("msi");
 
     if (!hmsi)
@@ -722,57 +783,68 @@ static BOOL install_wine_mono(void)
         ERR("MsiEnumRelatedProducts failed, err=%u\n", res);
     }
 
-    FreeLibrary(hmsi);
+    if (res == ERROR_SUCCESS)
+    {
+        TRACE("found installed support package %s\n", versionstringbuf);
+
+        if (compare_versions(WINE_MONO_VERSION, versionstringbuf) <= 0)
+        {
+            TRACE("support package is at least %s, quitting\n", WINE_MONO_VERSION);
+            ret = TRUE;
+            goto end;
+        }
+    }
+
+    strcpyW(support_msi_path, mono_path);
+    strcatW(support_msi_path, support_msi_relative);
+
+    initresult = CoInitialize(NULL);
+
+    pMsiOpenPackageW = (void*)GetProcAddress(hmsi, "MsiOpenPackageW");
+
+    res = pMsiOpenPackageW(support_msi_path, &msiproduct);
 
     if (res == ERROR_SUCCESS)
     {
-        int current_version[3], wanted_version[3], i;
+        buffer_size = sizeof(versionstringbuf);
 
-        TRACE("found installed version %s\n", versionstringbuf);
+        pMsiGetProductPropertyA = (void*)GetProcAddress(hmsi, "MsiGetProductPropertyA");
 
-        parse_msi_version_string(versionstringbuf, current_version);
-        parse_msi_version_string(mono_version, wanted_version);
+        res = pMsiGetProductPropertyA(msiproduct, "ProductVersion", versionstringbuf, &buffer_size);
 
-        for (i=0; i<3; i++)
-        {
-            if (current_version[i] < wanted_version[i])
-                break;
-            else if (current_version[i] > wanted_version[i])
-            {
-                TRACE("installed version is newer than %s, quitting\n", mono_version);
-                return TRUE;
-            }
-        }
+        pMsiCloseHandle = (void*)GetProcAddress(hmsi, "MsiCloseHandle");
 
-        if (i == 3)
-        {
-            TRACE("version %s is already installed, quitting\n", mono_version);
-            return TRUE;
-        }
+        pMsiCloseHandle(msiproduct);
     }
 
-    len = GetSystemDirectoryW(app, MAX_PATH - ARRAY_SIZE(controlW));
-    memcpy(app+len, controlW, sizeof(controlW));
+    if (res == ERROR_SUCCESS) {
+        TRACE("found support msi version %s at %s\n", versionstringbuf, debugstr_w(support_msi_path));
 
-    args = HeapAlloc(GetProcessHeap(), 0, (len*sizeof(WCHAR) + sizeof(controlW) + sizeof(argsW)));
-    if(!args)
-        return FALSE;
+        if (compare_versions(WINE_MONO_VERSION, versionstringbuf) <= 0)
+        {
+            TRACE("installing support msi\n");
 
-    memcpy(args, app, len*sizeof(WCHAR) + sizeof(controlW));
-    memcpy(args + len + ARRAY_SIZE(controlW) - 1, argsW, sizeof(argsW));
+            pMsiInstallProductW = (void*)GetProcAddress(hmsi, "MsiInstallProductW");
 
-    TRACE("starting %s\n", debugstr_w(args));
+            res = pMsiInstallProductW(support_msi_path, NULL);
 
-    memset(&si, 0, sizeof(si));
-    si.cb = sizeof(si);
-    ret = CreateProcessW(app, args, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
-    HeapFree(GetProcessHeap(), 0, args);
-    if (ret) {
-        CloseHandle(pi.hThread);
-        WaitForSingleObject(pi.hProcess, INFINITE);
-        CloseHandle(pi.hProcess);
+            if (res == ERROR_SUCCESS)
+            {
+                ret = TRUE;
+                goto end;
+            }
+            else
+                ERR("MsiInstallProduct failed, err=%i\n", res);
+        }
     }
 
+    ret = invoke_appwiz();
+
+end:
+    if (hmsi)
+        FreeLibrary(hmsi);
+    if (SUCCEEDED(initresult))
+        CoUninitialize();
     return ret;
 }
 
diff --git a/dlls/mscoree/mscoree_private.h b/dlls/mscoree/mscoree_private.h
index 77610994359..43209fd1877 100644
--- a/dlls/mscoree/mscoree_private.h
+++ b/dlls/mscoree/mscoree_private.h
@@ -108,6 +108,8 @@ extern HRESULT get_runtime_info(LPCWSTR exefile, LPCWSTR version, LPCWSTR config
     IStream *config_stream, DWORD startup_flags, DWORD runtimeinfo_flags, BOOL legacy,
     ICLRRuntimeInfo **result) DECLSPEC_HIDDEN;
 
+extern BOOL get_mono_path(LPWSTR path) DECLSPEC_HIDDEN;
+
 extern HRESULT ICLRRuntimeInfo_GetRuntimeHost(ICLRRuntimeInfo *iface, RuntimeHost **result) DECLSPEC_HIDDEN;
 
 extern HRESULT MetaDataDispenser_CreateInstance(IUnknown **ppUnk) DECLSPEC_HIDDEN;
-- 
2.17.1




More information about the wine-devel mailing list