Signed-off-by: Vincent Povirk vincent@codeweavers.com --- This fixes upgrades from a local runtime install to a shared install.
We should give the local install special treatment because installing the support msi will remove any runtime msi that doesn't match. If the other parts of the search path have an outdated version, installing the support msi won't fix that, and they shouldn't because the path contains the version.
dlls/mscoree/metahost.c | 6 +- dlls/mscoree/mscoree_main.c | 102 +++++++++++++++++++++------------ dlls/mscoree/mscoree_private.h | 2 +- 3 files changed, 68 insertions(+), 42 deletions(-)
diff --git a/dlls/mscoree/metahost.c b/dlls/mscoree/metahost.c index 1b2abd26e4..b268acc449 100644 --- a/dlls/mscoree/metahost.c +++ b/dlls/mscoree/metahost.c @@ -339,7 +339,7 @@ static HRESULT CLRRuntimeInfo_GetRuntimeHost(CLRRuntimeInfo *This, RuntimeHost * return hr; }
- if (!get_mono_path(mono_path)) + if (!get_mono_path(mono_path, FALSE)) { ERR("Wine Mono is not installed\n"); return CLR_E_SHIM_RUNTIME; @@ -778,9 +778,9 @@ static BOOL get_mono_path_datadir(LPWSTR path) return ret; }
-BOOL get_mono_path(LPWSTR path) +BOOL get_mono_path(LPWSTR path, BOOL skip_local) { - return get_mono_path_local(path) || + return (!skip_local && get_mono_path_local(path)) || get_mono_path_registry(path) || get_mono_path_datadir(path) || get_mono_path_unix(INSTALL_DATADIR "/wine/mono/wine-mono-" WINE_MONO_VERSION, path) || diff --git a/dlls/mscoree/mscoree_main.c b/dlls/mscoree/mscoree_main.c index 6393af8c6c..40577de714 100644 --- a/dlls/mscoree/mscoree_main.c +++ b/dlls/mscoree/mscoree_main.c @@ -717,23 +717,65 @@ static BOOL invoke_appwiz(void) return ret; }
-static BOOL install_wine_mono(void) +static BOOL get_support_msi(LPCWSTR mono_path, LPWSTR msi_path) { 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}; + UINT (WINAPI *pMsiOpenPackageW)(LPCWSTR,ULONG*); + UINT (WINAPI *pMsiGetProductPropertyA)(ULONG,LPCSTR,LPSTR,LPDWORD); + UINT (WINAPI *pMsiCloseHandle)(ULONG); + HMODULE hmsi = NULL; + char versionstringbuf[15]; + UINT res; + DWORD buffer_size; + ULONG msiproduct; + BOOL ret=FALSE; + + hmsi = GetModuleHandleA("msi"); + + strcpyW(msi_path, mono_path); + strcatW(msi_path, support_msi_relative); + + pMsiOpenPackageW = (void*)GetProcAddress(hmsi, "MsiOpenPackageW"); + + res = pMsiOpenPackageW(msi_path, &msiproduct); + + if (res == ERROR_SUCCESS) + { + buffer_size = sizeof(versionstringbuf); + + pMsiGetProductPropertyA = (void*)GetProcAddress(hmsi, "MsiGetProductPropertyA"); + + res = pMsiGetProductPropertyA(msiproduct, "ProductVersion", versionstringbuf, &buffer_size); + + pMsiCloseHandle = (void*)GetProcAddress(hmsi, "MsiCloseHandle"); + + pMsiCloseHandle(msiproduct); + } + + if (res == ERROR_SUCCESS) { + TRACE("found support msi version %s at %s\n", versionstringbuf, debugstr_w(msi_path)); + + if (compare_versions(WINE_MONO_VERSION, versionstringbuf) <= 0) + { + ret = TRUE; + } + } + + return ret; +} + +static BOOL install_wine_mono(void) +{ 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]; @@ -750,7 +792,7 @@ static BOOL install_wine_mono(void)
TRACE("searching for mono runtime\n");
- if (!get_mono_path(mono_path)) + if (!get_mono_path(mono_path, FALSE)) { TRACE("mono runtime not found\n"); return invoke_appwiz(); @@ -795,47 +837,31 @@ static BOOL install_wine_mono(void) } }
- 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) + ret = get_support_msi(mono_path, support_msi_path); + if (!ret) { - buffer_size = sizeof(versionstringbuf); - - pMsiGetProductPropertyA = (void*)GetProcAddress(hmsi, "MsiGetProductPropertyA"); - - res = pMsiGetProductPropertyA(msiproduct, "ProductVersion", versionstringbuf, &buffer_size); - - pMsiCloseHandle = (void*)GetProcAddress(hmsi, "MsiCloseHandle"); - - pMsiCloseHandle(msiproduct); + /* Try looking outside c:\windows\mono */ + ret = (get_mono_path(mono_path, TRUE) && + get_support_msi(mono_path, support_msi_path)); }
- 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) - { - TRACE("installing support msi\n"); + if (ret) + { + TRACE("installing support msi\n");
- pMsiInstallProductW = (void*)GetProcAddress(hmsi, "MsiInstallProductW"); + pMsiInstallProductW = (void*)GetProcAddress(hmsi, "MsiInstallProductW");
- res = pMsiInstallProductW(support_msi_path, NULL); + res = pMsiInstallProductW(support_msi_path, NULL);
- if (res == ERROR_SUCCESS) - { - ret = TRUE; - goto end; - } - else - ERR("MsiInstallProduct failed, err=%i\n", res); + if (res == ERROR_SUCCESS) + { + ret = TRUE; + goto end; } + else + ERR("MsiInstallProduct failed, err=%i\n", res); }
ret = invoke_appwiz(); diff --git a/dlls/mscoree/mscoree_private.h b/dlls/mscoree/mscoree_private.h index 43209fd187..3a3631e708 100644 --- a/dlls/mscoree/mscoree_private.h +++ b/dlls/mscoree/mscoree_private.h @@ -108,7 +108,7 @@ 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 BOOL get_mono_path(LPWSTR path, BOOL skip_local) DECLSPEC_HIDDEN;
extern HRESULT ICLRRuntimeInfo_GetRuntimeHost(ICLRRuntimeInfo *iface, RuntimeHost **result) DECLSPEC_HIDDEN;