mscoree: Update install process to account for shared installs.

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@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Vincent Povirk 2019-04-04 10:05:32 -05:00 committed by Alexandre Julliard
parent dc2c580bdf
commit 23181b40c5
3 changed files with 125 additions and 53 deletions

View File

@ -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) ||

View File

@ -665,16 +665,22 @@ static void parse_msi_version_string(const char *version, int *parts)
}
}
static BOOL install_wine_mono(void)
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)
{
BOOL is_wow64 = FALSE;
HMODULE hmsi;
UINT (WINAPI *pMsiEnumRelatedProductsA)(LPCSTR,DWORD,DWORD,LPSTR);
UINT (WINAPI *pMsiGetProductInfoA)(LPCSTR,LPCSTR,LPSTR,DWORD*);
char versionstringbuf[15];
char productcodebuf[39];
UINT res;
DWORD buffer_size;
PROCESS_INFORMATION pi;
STARTUPINFOW si;
WCHAR app[MAX_PATH];
@ -682,13 +688,58 @@ static BOOL install_wine_mono(void)
LONG len;
BOOL ret;
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};
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 = 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;
ULONG msiproduct;
BOOL ret;
WCHAR mono_path[MAX_PATH];
WCHAR support_msi_path[MAX_PATH];
static const char* mono_upgrade_code = "{DE624609-C6B5-486A-9274-EF0B854F6BC5}";
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++)
pMsiCloseHandle = (void*)GetProcAddress(hmsi, "MsiCloseHandle");
pMsiCloseHandle(msiproduct);
}
if (res == ERROR_SUCCESS) {
TRACE("found support msi version %s at %s\n", versionstringbuf, debugstr_w(support_msi_path));
if (compare_versions(WINE_MONO_VERSION, versionstringbuf) <= 0)
{
if (current_version[i] < wanted_version[i])
break;
else if (current_version[i] > wanted_version[i])
TRACE("installing support msi\n");
pMsiInstallProductW = (void*)GetProcAddress(hmsi, "MsiInstallProductW");
res = pMsiInstallProductW(support_msi_path, NULL);
if (res == ERROR_SUCCESS)
{
TRACE("installed version is newer than %s, quitting\n", mono_version);
return TRUE;
ret = TRUE;
goto end;
}
}
if (i == 3)
{
TRACE("version %s is already installed, quitting\n", mono_version);
return TRUE;
else
ERR("MsiInstallProduct failed, err=%i\n", res);
}
}
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);
}
ret = invoke_appwiz();
end:
if (hmsi)
FreeLibrary(hmsi);
if (SUCCEEDED(initresult))
CoUninitialize();
return ret;
}

View File

@ -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;