Commit 23181b40 authored by Vincent Povirk's avatar Vincent Povirk Committed by Alexandre Julliard

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: 's avatarVincent Povirk <vincent@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent dc2c580b
...@@ -129,8 +129,6 @@ void (CDECL *mono_thread_manage)(void); ...@@ -129,8 +129,6 @@ void (CDECL *mono_thread_manage)(void);
void (CDECL *mono_trace_set_print_handler)(MonoPrintCallback callback); void (CDECL *mono_trace_set_print_handler)(MonoPrintCallback callback);
void (CDECL *mono_trace_set_printerr_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 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); 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) ...@@ -772,7 +770,7 @@ static BOOL get_mono_path_datadir(LPWSTR path)
return ret; return ret;
} }
static BOOL get_mono_path(LPWSTR path) BOOL get_mono_path(LPWSTR path)
{ {
return get_mono_path_local(path) || return get_mono_path_local(path) ||
get_mono_path_registry(path) || get_mono_path_registry(path) ||
......
...@@ -665,30 +665,81 @@ static void parse_msi_version_string(const char *version, int *parts) ...@@ -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 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; BOOL is_wow64 = FALSE;
HMODULE hmsi; HMODULE hmsi = NULL;
HRESULT initresult = E_FAIL;
UINT (WINAPI *pMsiEnumRelatedProductsA)(LPCSTR,DWORD,DWORD,LPSTR); UINT (WINAPI *pMsiEnumRelatedProductsA)(LPCSTR,DWORD,DWORD,LPSTR);
UINT (WINAPI *pMsiGetProductInfoA)(LPCSTR,LPCSTR,LPSTR,DWORD*); 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 versionstringbuf[15];
char productcodebuf[39]; char productcodebuf[39];
UINT res; UINT res;
DWORD buffer_size; DWORD buffer_size;
PROCESS_INFORMATION pi; ULONG msiproduct;
STARTUPINFOW si;
WCHAR app[MAX_PATH];
WCHAR *args;
LONG len;
BOOL ret; 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 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); IsWow64Process(GetCurrentProcess(), &is_wow64);
if (is_wow64) if (is_wow64)
...@@ -697,6 +748,16 @@ static BOOL install_wine_mono(void) ...@@ -697,6 +748,16 @@ static BOOL install_wine_mono(void)
return TRUE; 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"); hmsi = LoadLibraryA("msi");
if (!hmsi) if (!hmsi)
...@@ -722,57 +783,68 @@ static BOOL install_wine_mono(void) ...@@ -722,57 +783,68 @@ static BOOL install_wine_mono(void)
ERR("MsiEnumRelatedProducts failed, err=%u\n", res); ERR("MsiEnumRelatedProducts failed, err=%u\n", res);
} }
FreeLibrary(hmsi);
if (res == ERROR_SUCCESS) if (res == ERROR_SUCCESS)
{ {
int current_version[3], wanted_version[3], i; TRACE("found installed support package %s\n", versionstringbuf);
TRACE("found installed version %s\n", versionstringbuf);
parse_msi_version_string(versionstringbuf, current_version); if (compare_versions(WINE_MONO_VERSION, versionstringbuf) <= 0)
parse_msi_version_string(mono_version, wanted_version);
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); TRACE("support package is at least %s, quitting\n", WINE_MONO_VERSION);
return TRUE; ret = TRUE;
goto end;
} }
} }
if (i == 3) 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)
{ {
TRACE("version %s is already installed, quitting\n", mono_version); buffer_size = sizeof(versionstringbuf);
return TRUE;
} pMsiGetProductPropertyA = (void*)GetProcAddress(hmsi, "MsiGetProductPropertyA");
res = pMsiGetProductPropertyA(msiproduct, "ProductVersion", versionstringbuf, &buffer_size);
pMsiCloseHandle = (void*)GetProcAddress(hmsi, "MsiCloseHandle");
pMsiCloseHandle(msiproduct);
} }
len = GetSystemDirectoryW(app, MAX_PATH - ARRAY_SIZE(controlW)); if (res == ERROR_SUCCESS) {
memcpy(app+len, controlW, sizeof(controlW)); 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 (compare_versions(WINE_MONO_VERSION, versionstringbuf) <= 0)
if(!args) {
return FALSE; TRACE("installing support msi\n");
memcpy(args, app, len*sizeof(WCHAR) + sizeof(controlW)); pMsiInstallProductW = (void*)GetProcAddress(hmsi, "MsiInstallProductW");
memcpy(args + len + ARRAY_SIZE(controlW) - 1, argsW, sizeof(argsW));
TRACE("starting %s\n", debugstr_w(args)); res = pMsiInstallProductW(support_msi_path, NULL);
memset(&si, 0, sizeof(si)); if (res == ERROR_SUCCESS)
si.cb = sizeof(si); {
ret = CreateProcessW(app, args, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); ret = TRUE;
HeapFree(GetProcessHeap(), 0, args); goto end;
if (ret) { }
CloseHandle(pi.hThread); else
WaitForSingleObject(pi.hProcess, INFINITE); ERR("MsiInstallProduct failed, err=%i\n", res);
CloseHandle(pi.hProcess);
} }
}
ret = invoke_appwiz();
end:
if (hmsi)
FreeLibrary(hmsi);
if (SUCCEEDED(initresult))
CoUninitialize();
return ret; return ret;
} }
......
...@@ -108,6 +108,8 @@ extern HRESULT get_runtime_info(LPCWSTR exefile, LPCWSTR version, LPCWSTR config ...@@ -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, IStream *config_stream, DWORD startup_flags, DWORD runtimeinfo_flags, BOOL legacy,
ICLRRuntimeInfo **result) DECLSPEC_HIDDEN; 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 ICLRRuntimeInfo_GetRuntimeHost(ICLRRuntimeInfo *iface, RuntimeHost **result) DECLSPEC_HIDDEN;
extern HRESULT MetaDataDispenser_CreateInstance(IUnknown **ppUnk) DECLSPEC_HIDDEN; extern HRESULT MetaDataDispenser_CreateInstance(IUnknown **ppUnk) DECLSPEC_HIDDEN;
......
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