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(a)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