diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index e8ed1c61..30e22731 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -323,6 +323,7 @@ patch_enable_all () enable_winedevice_Default_Drivers="$1" enable_winemapi_user_xdg_mail="$1" enable_winemenubuilder_Desktop_Icon_Path="$1" + enable_winemenubuilder_integration="$1" enable_wineps_drv_PostScript_Fixes="$1" enable_winepulse_PulseAudio_Support="$1" enable_wineqtdecoder_fix_compilation="$1" @@ -1081,6 +1082,9 @@ patch_enable () winemenubuilder-Desktop_Icon_Path) enable_winemenubuilder_Desktop_Icon_Path="$2" ;; + winemenubuilder-integration) + enable_winemenubuilder_integration="$2" + ;; wineps.drv-PostScript_Fixes) enable_wineps_drv_PostScript_Fixes="$2" ;; @@ -6797,6 +6801,24 @@ if test "$enable_winemenubuilder_Desktop_Icon_Path" -eq 1; then ) >> "$patchlist" fi +# Patchset winemenubuilder-integration +# | +# | This patchset fixes the following Wine bugs: +# | * [#41275] Winemenubuilder should respect existing defaults for filetype associations +# | * [#22904] Register URL protocol handlers under Linux +# | +# | Modified files: +# | * dlls/mshtml/mshtml.inf, loader/wine.inf.in, programs/winemenubuilder/winemenubuilder.c +# | +if test "$enable_winemenubuilder_integration" -eq 1; then + patch_apply winemenubuilder-integration/0001-winemenubuilder-Blacklist-desktop-integration-for-ce.patch + patch_apply winemenubuilder-integration/0002-winemenubuilder-Create-.desktop-files-for-programs-t.patch + ( + printf '%s\n' '+ { "Alex Henrie", "winemenubuilder: Blacklist desktop integration for certain associations.", 1 },'; + printf '%s\n' '+ { "Alex Henrie", "winemenubuilder: Create .desktop files for programs that open URIs.", 1 },'; + ) >> "$patchlist" +fi + # Patchset wineps.drv-PostScript_Fixes # | # | This patchset fixes the following Wine bugs: @@ -7284,15 +7306,15 @@ fi # | * [#48684] BlazBlue: Calamity Trigger requires for xactengine 3.3 interface. # | # | Modified files: -# | * configure.ac, dlls/xactengine3_0/Makefile.in, dlls/xactengine3_0/xactengine3_0.spec, dlls/xactengine3_1/Makefile.in, -# | dlls/xactengine3_1/xactengine3_1.spec, dlls/xactengine3_2/Makefile.in, dlls/xactengine3_2/xactengine3_2.spec, -# | dlls/xactengine3_3/Makefile.in, dlls/xactengine3_3/xactengine3_3.spec, dlls/xactengine3_4/Makefile.in, -# | dlls/xactengine3_4/xactengine3_4.spec, dlls/xactengine3_5/Makefile.in, dlls/xactengine3_5/xactengine3_5.spec, -# | dlls/xactengine3_6/Makefile.in, dlls/xactengine3_6/xactengine3_6.spec, dlls/xactengine3_7/Makefile.in, -# | dlls/xactengine3_7/xactengine3_7.spec, dlls/xaudio2_7/Makefile.in, dlls/xaudio2_7/tests/Makefile.in, -# | dlls/xaudio2_7/tests/globals.xgs, dlls/xaudio2_7/tests/rsrc.rc, dlls/xaudio2_7/tests/xact.c, -# | dlls/xaudio2_7/tests/xaudio2.c, dlls/xaudio2_7/xact_classes.idl, dlls/xaudio2_7/xact_dll.c, dlls/xaudio2_7/xaudio_dll.c, -# | include/Makefile.in, include/config.h.in, include/xact3.idl, include/xact3wb.h +# | * configure.ac, dlls/x3daudio1_7/Makefile.in, dlls/xactengine3_0/Makefile.in, dlls/xactengine3_0/xactengine3_0.spec, +# | dlls/xactengine3_1/Makefile.in, dlls/xactengine3_1/xactengine3_1.spec, dlls/xactengine3_2/Makefile.in, +# | dlls/xactengine3_2/xactengine3_2.spec, dlls/xactengine3_3/Makefile.in, dlls/xactengine3_3/xactengine3_3.spec, +# | dlls/xactengine3_4/Makefile.in, dlls/xactengine3_4/xactengine3_4.spec, dlls/xactengine3_5/Makefile.in, +# | dlls/xactengine3_5/xactengine3_5.spec, dlls/xactengine3_6/Makefile.in, dlls/xactengine3_6/xactengine3_6.spec, +# | dlls/xactengine3_7/Makefile.in, dlls/xactengine3_7/xactengine3_7.spec, dlls/xaudio2_7/Makefile.in, +# | dlls/xaudio2_7/tests/Makefile.in, dlls/xaudio2_7/tests/globals.xgs, dlls/xaudio2_7/tests/rsrc.rc, +# | dlls/xaudio2_7/tests/xact.c, dlls/xaudio2_7/tests/xaudio2.c, dlls/xaudio2_7/xact_classes.idl, dlls/xaudio2_7/xact_dll.c, +# | dlls/xaudio2_7/xaudio_dll.c, include/Makefile.in, include/config.h.in, include/xact3.idl, include/xact3wb.h # | if test "$enable_xactengine_initial" -eq 1; then patch_apply xactengine-initial/0001-include-Add-xact3.idl.patch diff --git a/patches/winemenubuilder-integration/0001-winemenubuilder-Blacklist-desktop-integration-for-ce.patch b/patches/winemenubuilder-integration/0001-winemenubuilder-Blacklist-desktop-integration-for-ce.patch new file mode 100644 index 00000000..262a2a8c --- /dev/null +++ b/patches/winemenubuilder-integration/0001-winemenubuilder-Blacklist-desktop-integration-for-ce.patch @@ -0,0 +1,183 @@ +From 1867195b928ed636b61830abf45594591b40c834 Mon Sep 17 00:00:00 2001 +From: Alex Henrie +Date: Sun, 1 Mar 2020 17:58:12 -0700 +Subject: [PATCH 1/2] winemenubuilder: Blacklist desktop integration for + certain associations + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=41275 +Signed-off-by: Alex Henrie +--- + dlls/mshtml/mshtml.inf | 6 +++ + loader/wine.inf.in | 10 ++++ + programs/winemenubuilder/winemenubuilder.c | 54 +++++++++++++++++++--- + 3 files changed, 63 insertions(+), 7 deletions(-) + +diff --git a/dlls/mshtml/mshtml.inf b/dlls/mshtml/mshtml.inf +index 4a650b444f..548739f432 100644 +--- a/dlls/mshtml/mshtml.inf ++++ b/dlls/mshtml/mshtml.inf +@@ -111,6 +111,7 @@ HKCR,"giffile\shell\open\ddeexec",,,"""file:%%1"",,-1,,,,," + HKCR,"giffile\shell\open\ddeexec\Application",,,"IExplore" + HKCR,"giffile\shell\open\ddeexec\Topic",,,"WWW_OpenURL" + ;; HKCR,"giffile\DefaultIcon",,,"%16422%\Internet Explorer\iexplore.exe,9" ++HKCU,Software\Wine\FileOpenBlacklist\.gif,"iexplore",,"""%16422%\Internet Explorer\iexplore.exe"" -nohome" + + ;; GZIP + HKCR,"MIME\Database\Content Type\application/x-gzip","Extension",,".gz" +@@ -158,6 +159,7 @@ HKCR,"jpegfile\shell\open\ddeexec",,,"""file:%%1"",,-1,,,,," + HKCR,"jpegfile\shell\open\ddeexec\Application",,,"IExplore" + HKCR,"jpegfile\shell\open\ddeexec\Topic",,,"WWW_OpenURL" + ;; HKCR,"jpegfile\DefaultIcon",,,"%16422%\Internet Explorer\iexplore.exe,8" ++HKCU,Software\Wine\FileOpenBlacklist\.jpe,"iexplore",,"""%16422%\Internet Explorer\iexplore.exe"" -nohome" + + ;; JPEG + HKCR,"MIME\Database\Content Type\image/jpeg","CLSID",,"%CLSID_HTMLDocument%" +@@ -173,6 +175,7 @@ HKCR,"jpegfile\shell\open\ddeexec",,,"""file:%%1"",,-1,,,,," + HKCR,"jpegfile\shell\open\ddeexec\Application",,,"IExplore" + HKCR,"jpegfile\shell\open\ddeexec\Topic",,,"WWW_OpenURL" + ;; HKCR,"jpegfile\DefaultIcon",,,"%16422%\Internet Explorer\iexplore.exe,8" ++HKCU,Software\Wine\FileOpenBlacklist\.jpeg,"iexplore",,"""%16422%\Internet Explorer\iexplore.exe"" -nohome" + + ;; JPG + HKCR,".jpg",,2,"jpegfile" +@@ -184,6 +187,7 @@ HKCR,"jpegfile\shell\open\ddeexec",,,"""file:%%1"",,-1,,,,," + HKCR,"jpegfile\shell\open\ddeexec\Application",,,"IExplore" + HKCR,"jpegfile\shell\open\ddeexec\Topic",,,"WWW_OpenURL" + ;; HKCR,"jpegfile\DefaultIcon",,,"%16422%\Internet Explorer\iexplore.exe,8" ++HKCU,Software\Wine\FileOpenBlacklist\.jpg,"iexplore",,"""%16422%\Internet Explorer\iexplore.exe"" -nohome" + + ;; MHTML + HKCR,"MIME\Database\Content Type\message/rfc822","CLSID",,"%CLSID_MHTMLDocument%" +@@ -221,6 +225,7 @@ HKCR,"pjpegfile\shell\open\ddeexec",,,"""file:%%1"",,-1,,,,," + HKCR,"pjpegfile\shell\open\ddeexec\Application",,,"IExplore" + HKCR,"pjpegfile\shell\open\ddeexec\Topic",,,"WWW_OpenURL" + ;; HKCR,"pjpegfile\DefaultIcon",,,"%16422%\Internet Explorer\iexplore.exe,8" ++HKCU,Software\Wine\FileOpenBlacklist\.jfif,"iexplore",,"""%16422%\Internet Explorer\iexplore.exe"" -nohome" + + ;; PNG + HKCR,"MIME\Database\Content Type\image/png","Extension",,".png" +@@ -234,6 +239,7 @@ HKCR,"pngfile\shell\open\ddeexec",,,"""file:%%1"",,-1,,,,," + HKCR,"pngfile\shell\open\ddeexec\Application",,,"IExplore" + HKCR,"pngfile\shell\open\ddeexec\Topic",,,"WWW_OpenURL" + ;; HKCR,"pngfile\DefaultIcon",,,"%16422%\Internet Explorer\iexplore.exe,9" ++HKCU,Software\Wine\FileOpenBlacklist\.png,"iexplore",,"""%16422%\Internet Explorer\iexplore.exe"" -nohome" + + ;; PS + HKCR,"MIME\Database\Content Type\application/postscript","Extension",,".ps" +diff --git a/loader/wine.inf.in b/loader/wine.inf.in +index 8267ef34dc..6c34e20d58 100644 +--- a/loader/wine.inf.in ++++ b/loader/wine.inf.in +@@ -501,6 +501,16 @@ HKCR,MIME\Database\Charset\us-ascii,"AliasForCharset",,iso-8859-1 + HKCR,MIME\Database\Charset\visual,"AliasForCharset",,iso-8859-8 + HKCR,MIME\Database\Charset\Windows-1254,"AliasForCharset",,iso-8859-9 + ++HKCU,Software\Wine\FileOpenBlacklist\.htm,"winebrowser",,"""%11%\winebrowser.exe"" -nohome" ++HKCU,Software\Wine\FileOpenBlacklist\.html,"winebrowser",,"""%11%\winebrowser.exe"" -nohome" ++HKCU,Software\Wine\FileOpenBlacklist\.ini,"notepad",,"%11%\notepad.exe %1" ++HKCU,Software\Wine\FileOpenBlacklist\.pdf,"winebrowser",,"""%11%\winebrowser.exe"" -nohome" ++HKCU,Software\Wine\FileOpenBlacklist\.rtf,"wordpad",,"""%16422%\Windows NT\Accessories\wordpad.exe"" %1" ++HKCU,Software\Wine\FileOpenBlacklist\.txt,"notepad",,"%11%\notepad.exe %1" ++HKCU,Software\Wine\FileOpenBlacklist\.url,"ieframe",,"rundll32.exe ieframe.dll,OpenURL %l" ++HKCU,Software\Wine\FileOpenBlacklist\.wri,"wordpad",,"""%16422%\Windows NT\Accessories\wordpad.exe"" %1" ++HKCU,Software\Wine\FileOpenBlacklist\.xml,"winebrowser",,"""%11%\winebrowser.exe"" -nohome" ++ + [ContentIndex] + HKLM,System\CurrentControlSet\Control\ContentIndex\Language\Neutral,"WBreakerClass",,"{369647e0-17b0-11ce-9950-00aa004bbb1f}" + HKLM,System\CurrentControlSet\Control\ContentIndex\Language\Neutral,"StemmerClass",,"" +diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c +index fa700f8c19..6f1dd7c571 100644 +--- a/programs/winemenubuilder/winemenubuilder.c ++++ b/programs/winemenubuilder/winemenubuilder.c +@@ -2465,7 +2465,7 @@ static BOOL write_freedesktop_mime_type_entry(const char *packages_dir, const ch + return ret; + } + +-static BOOL is_extension_blacklisted(LPCWSTR extension) ++static BOOL is_hard_blacklisted(const WCHAR *extension) + { + /* These are managed through external tools like wine.desktop, to evade malware created file type associations */ + static const WCHAR comW[] = {'.','c','o','m',0}; +@@ -2479,6 +2479,42 @@ static BOOL is_extension_blacklisted(LPCWSTR extension) + return FALSE; + } + ++static BOOL is_soft_blacklisted(const WCHAR *extension, const WCHAR *command) ++{ ++ static const WCHAR FileOpenBlacklistW[] = {'S','o','f','t','w','a','r','e','\\', ++ 'W','i','n','e','\\', ++ 'F','i','l','e','O','p','e','n','B','l','a','c','k','l','i','s','t','\\',0}; ++ WCHAR blacklist_key_path[MAX_PATH]; ++ HKEY blacklist_key; ++ WCHAR program_name[MAX_PATH], *blacklisted_command; ++ DWORD len = ARRAY_SIZE(program_name); ++ DWORD i = 0; ++ ++ if (ARRAY_SIZE(FileOpenBlacklistW) + lstrlenW(extension) > ARRAY_SIZE(blacklist_key_path)) ++ return FALSE; ++ ++ lstrcpyW(blacklist_key_path, FileOpenBlacklistW); ++ lstrcatW(blacklist_key_path, extension); ++ ++ if (RegOpenKeyExW(HKEY_CURRENT_USER, blacklist_key_path, 0, KEY_QUERY_VALUE, &blacklist_key) != ERROR_SUCCESS) ++ return FALSE; ++ ++ while (RegEnumValueW(blacklist_key, i, program_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) ++ { ++ blacklisted_command = reg_get_valW(HKEY_CURRENT_USER, blacklist_key_path, program_name); ++ if (strcmpW(command, blacklisted_command) == 0) ++ { ++ RegCloseKey(blacklist_key); ++ return TRUE; ++ } ++ len = ARRAY_SIZE(program_name); ++ i++; ++ } ++ ++ RegCloseKey(blacklist_key); ++ return FALSE; ++} ++ + static const char* get_special_mime_type(LPCWSTR extension) + { + static const WCHAR lnkW[] = {'.','l','n','k',0}; +@@ -2552,7 +2588,7 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package + size *= 2; + } while (ret == ERROR_MORE_DATA); + +- if (ret == ERROR_SUCCESS && extensionW[0] == '.' && !is_extension_blacklisted(extensionW)) ++ if (ret == ERROR_SUCCESS && extensionW[0] == '.' && !is_hard_blacklisted(extensionW)) + { + char *extensionA = NULL; + WCHAR *commandW = NULL; +@@ -2570,6 +2606,15 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package + char *progIdA = NULL; + char *mimeProgId = NULL; + ++ commandW = assoc_query(ASSOCSTR_COMMAND, extensionW, openW); ++ if (commandW == NULL) ++ /* no command => no application is associated */ ++ goto end; ++ ++ if (is_soft_blacklisted(extensionW, commandW)) ++ /* command is on the blacklist => desktop integration is not desirable */ ++ goto end; ++ + extensionA = wchars_to_utf8_chars(strlwrW(extensionW)); + if (extensionA == NULL) + { +@@ -2638,11 +2683,6 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package + } + } + +- commandW = assoc_query(ASSOCSTR_COMMAND, extensionW, openW); +- if (commandW == NULL) +- /* no command => no application is associated */ +- goto end; +- + executableW = assoc_query(ASSOCSTR_EXECUTABLE, extensionW, openW); + if (executableW) + openWithIconA = extract_icon(executableW, 0, NULL, FALSE); +-- +2.25.1 + diff --git a/patches/winemenubuilder-integration/0002-winemenubuilder-Create-.desktop-files-for-programs-t.patch b/patches/winemenubuilder-integration/0002-winemenubuilder-Create-.desktop-files-for-programs-t.patch new file mode 100644 index 00000000..0e8c23d5 --- /dev/null +++ b/patches/winemenubuilder-integration/0002-winemenubuilder-Create-.desktop-files-for-programs-t.patch @@ -0,0 +1,412 @@ +From 01b5423e308b7206400b602feddab2b07529775a Mon Sep 17 00:00:00 2001 +From: Alex Henrie +Date: Sun, 1 Mar 2020 17:58:12 -0700 +Subject: [PATCH] winemenubuilder: Create .desktop files for programs that open + URIs + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=22904 +Signed-off-by: Alex Henrie +--- + loader/wine.inf.in | 4 + + programs/winemenubuilder/winemenubuilder.c | 225 ++++++++++++--------- + 2 files changed, 129 insertions(+), 100 deletions(-) + +diff --git a/loader/wine.inf.in b/loader/wine.inf.in +index 51ed312051f..00a7e35026e 100644 +--- a/loader/wine.inf.in ++++ b/loader/wine.inf.in +@@ -515,6 +515,10 @@ HKCU,Software\Wine\FileOpenBlacklist\.txt,"notepad",,"%11%\notepad.exe %1" + HKCU,Software\Wine\FileOpenBlacklist\.url,"ieframe",,"rundll32.exe ieframe.dll,OpenURL %l" + HKCU,Software\Wine\FileOpenBlacklist\.wri,"wordpad",,"""%16422%\Windows NT\Accessories\wordpad.exe"" %1" + HKCU,Software\Wine\FileOpenBlacklist\.xml,"winebrowser",,"""%11%\winebrowser.exe"" -nohome" ++HKCU,Software\Wine\FileOpenBlacklist\ftp,"winebrowser",,"""%11%\winebrowser.exe"" -nohome" ++HKCU,Software\Wine\FileOpenBlacklist\http,"winebrowser",,"""%11%\winebrowser.exe"" -nohome" ++HKCU,Software\Wine\FileOpenBlacklist\https,"winebrowser",,"""%11%\winebrowser.exe"" -nohome" ++HKCU,Software\Wine\FileOpenBlacklist\mailto,"winebrowser",,"%11%\winebrowser %1" + + [ContentIndex] + HKLM,System\CurrentControlSet\Control\ContentIndex\Language\Neutral,"WBreakerClass",,"{369647e0-17b0-11ce-9950-00aa004bbb1f}" +diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c +index 97d4eb658e3..4baac7ac729 100644 +--- a/programs/winemenubuilder/winemenubuilder.c ++++ b/programs/winemenubuilder/winemenubuilder.c +@@ -2261,10 +2261,13 @@ static BOOL has_association_changed(LPCWSTR extensionW, LPCSTR mimeType, LPCWSTR + ret = TRUE; + HeapFree(GetProcessHeap(), 0, valueA); + +- value = reg_get_valW(assocKey, extensionW, ProgIDW); +- if (!value || strcmpW(value, progId)) +- ret = TRUE; +- HeapFree(GetProcessHeap(), 0, value); ++ if (progId) ++ { ++ value = reg_get_valW(assocKey, extensionW, ProgIDW); ++ if (!value || strcmpW(value, progId)) ++ ret = TRUE; ++ HeapFree(GetProcessHeap(), 0, value); ++ } + + valueA = reg_get_val_utf8(assocKey, extensionW, AppNameW); + if (!valueA || lstrcmpA(valueA, appName)) +@@ -2348,7 +2351,7 @@ static void update_association(LPCWSTR extension, LPCSTR mimeType, LPCWSTR progI + } + + RegSetValueExW(subkey, MimeTypeW, 0, REG_SZ, (const BYTE*) mimeTypeW, (lstrlenW(mimeTypeW) + 1) * sizeof(WCHAR)); +- RegSetValueExW(subkey, ProgIDW, 0, REG_SZ, (const BYTE*) progId, (lstrlenW(progId) + 1) * sizeof(WCHAR)); ++ if (progId) RegSetValueExW(subkey, ProgIDW, 0, REG_SZ, (const BYTE*) progId, (lstrlenW(progId) + 1) * sizeof(WCHAR)); + RegSetValueExW(subkey, AppNameW, 0, REG_SZ, (const BYTE*) appNameW, (lstrlenW(appNameW) + 1) * sizeof(WCHAR)); + RegSetValueExW(subkey, DesktopFileW, 0, REG_SZ, (const BYTE*) desktopFileW, (lstrlenW(desktopFileW) + 1) * sizeof(WCHAR)); + if (openWithIcon) +@@ -2487,7 +2490,7 @@ static BOOL is_hard_blacklisted(const WCHAR *extension) + return FALSE; + } + +-static BOOL is_soft_blacklisted(const WCHAR *extension, const WCHAR *command) ++static BOOL is_soft_blacklisted(const WCHAR *win_type, const WCHAR *command) + { + static const WCHAR FileOpenBlacklistW[] = {'S','o','f','t','w','a','r','e','\\', + 'W','i','n','e','\\', +@@ -2498,11 +2501,11 @@ static BOOL is_soft_blacklisted(const WCHAR *extension, const WCHAR *command) + DWORD len = ARRAY_SIZE(program_name); + DWORD i = 0; + +- if (ARRAY_SIZE(FileOpenBlacklistW) + lstrlenW(extension) > ARRAY_SIZE(blacklist_key_path)) ++ if (ARRAY_SIZE(FileOpenBlacklistW) + lstrlenW(win_type) > ARRAY_SIZE(blacklist_key_path)) + return FALSE; + + lstrcpyW(blacklist_key_path, FileOpenBlacklistW); +- lstrcatW(blacklist_key_path, extension); ++ lstrcatW(blacklist_key_path, win_type); + + if (RegOpenKeyExW(HKEY_CURRENT_USER, blacklist_key_path, 0, KEY_QUERY_VALUE, &blacklist_key) != ERROR_SUCCESS) + return FALSE; +@@ -2531,15 +2534,15 @@ static const char* get_special_mime_type(LPCWSTR extension) + return NULL; + } + +-static BOOL write_freedesktop_association_entry(const char *desktopPath, const char *dot_extension, ++static BOOL write_freedesktop_association_entry(const char *desktopPath, const char *winType, + const char *friendlyAppName, const char *mimeType, + const char *progId, const char *openWithIcon) + { + BOOL ret = FALSE; + FILE *desktop; + +- WINE_TRACE("writing association for file type %s, friendlyAppName=%s, MIME type %s, progID=%s, icon=%s to file %s\n", +- wine_dbgstr_a(dot_extension), wine_dbgstr_a(friendlyAppName), wine_dbgstr_a(mimeType), ++ WINE_TRACE("writing association for type %s, friendlyAppName=%s, MIME type %s, progID=%s, icon=%s to file %s\n", ++ wine_dbgstr_a(winType), wine_dbgstr_a(friendlyAppName), wine_dbgstr_a(mimeType), + wine_dbgstr_a(progId), wine_dbgstr_a(openWithIcon), wine_dbgstr_a(desktopPath)); + + desktop = fopen(desktopPath, "w"); +@@ -2549,8 +2552,11 @@ static BOOL write_freedesktop_association_entry(const char *desktopPath, const c + fprintf(desktop, "Type=Application\n"); + fprintf(desktop, "Name=%s\n", friendlyAppName); + fprintf(desktop, "MimeType=%s;\n", mimeType); +- fprintf(desktop, "Exec=env WINEPREFIX=\"%s\" %s start /ProgIDOpen %s %%f\n", +- wine_get_config_dir(), wine_path, progId); ++ fprintf(desktop, "Exec=env WINEPREFIX=\"%s\" wine start", wine_get_config_dir()); ++ if (progId) /* file association */ ++ fprintf(desktop, " /ProgIDOpen %s %%f\n", progId); ++ else /* protocol association */ ++ fprintf(desktop, " %%u\n"); + fprintf(desktop, "NoDisplay=true\n"); + fprintf(desktop, "StartupNotify=true\n"); + if (openWithIcon) +@@ -2566,6 +2572,7 @@ static BOOL write_freedesktop_association_entry(const char *desktopPath, const c + static BOOL generate_associations(const char *xdg_data_home, const char *packages_dir, const char *applications_dir) + { + static const WCHAR openW[] = {'o','p','e','n',0}; ++ static const WCHAR UrlProtocolW[] = {'U','R','L',' ','P','r','o','t','o','c','o','l',0}; + struct wine_rb_tree mimeProgidTree = { winemenubuilder_rb_string_compare }; + struct list nativeMimeTypes = LIST_INIT(nativeMimeTypes); + LSTATUS ret = 0; +@@ -2580,26 +2587,33 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package + + for (i = 0; ; i++) + { +- WCHAR *extensionW = NULL; ++ WCHAR *winTypeW = NULL; + DWORD size = 1024; ++ BOOL is_protocol_type = FALSE; + + do + { +- HeapFree(GetProcessHeap(), 0, extensionW); +- extensionW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); +- if (extensionW == NULL) ++ HeapFree(GetProcessHeap(), 0, winTypeW); ++ winTypeW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); ++ if (winTypeW == NULL) + { + WINE_ERR("out of memory\n"); + ret = ERROR_OUTOFMEMORY; + break; + } +- ret = RegEnumKeyExW(HKEY_CLASSES_ROOT, i, extensionW, &size, NULL, NULL, NULL, NULL); ++ ret = RegEnumKeyExW(HKEY_CLASSES_ROOT, i, winTypeW, &size, NULL, NULL, NULL, NULL); + size *= 2; + } while (ret == ERROR_MORE_DATA); + +- if (ret == ERROR_SUCCESS && extensionW[0] == '.' && !is_hard_blacklisted(extensionW)) ++ if (ret == ERROR_SUCCESS && winTypeW[0] != '.') ++ { ++ if (RegGetValueW(HKEY_CLASSES_ROOT, winTypeW, UrlProtocolW, RRF_RT_ANY, NULL, NULL, NULL) == ERROR_SUCCESS) ++ is_protocol_type = TRUE; ++ } ++ ++ if (ret == ERROR_SUCCESS && (is_protocol_type || (winTypeW[0] == '.' && !is_hard_blacklisted(winTypeW)))) + { +- char *extensionA = NULL; ++ char *winTypeA = NULL; + WCHAR *commandW = NULL; + WCHAR *executableW = NULL; + char *openWithIconA = NULL; +@@ -2615,23 +2629,23 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package + char *progIdA = NULL; + char *mimeProgId = NULL; + +- commandW = assoc_query(ASSOCSTR_COMMAND, extensionW, openW); ++ commandW = assoc_query(ASSOCSTR_COMMAND, winTypeW, openW); + if (commandW == NULL) + /* no command => no application is associated */ + goto end; + +- if (is_soft_blacklisted(extensionW, commandW)) ++ if (is_soft_blacklisted(winTypeW, commandW)) + /* command is on the blacklist => desktop integration is not desirable */ + goto end; + +- extensionA = wchars_to_utf8_chars(strlwrW(extensionW)); +- if (extensionA == NULL) ++ winTypeA = wchars_to_utf8_chars(strlwrW(winTypeW)); ++ if (winTypeA == NULL) + { + WINE_ERR("out of memory\n"); + goto end; + } + +- friendlyDocNameW = assoc_query(ASSOCSTR_FRIENDLYDOCNAME, extensionW, NULL); ++ friendlyDocNameW = assoc_query(ASSOCSTR_FRIENDLYDOCNAME, winTypeW, NULL); + if (friendlyDocNameW) + { + friendlyDocNameA = wchars_to_utf8_chars(friendlyDocNameW); +@@ -2642,61 +2656,105 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package + } + } + +- iconW = assoc_query(ASSOCSTR_DEFAULTICON, extensionW, NULL); ++ iconW = assoc_query(ASSOCSTR_DEFAULTICON, winTypeW, NULL); + +- contentTypeW = assoc_query(ASSOCSTR_CONTENTTYPE, extensionW, NULL); ++ contentTypeW = assoc_query(ASSOCSTR_CONTENTTYPE, winTypeW, NULL); + if (contentTypeW) + strlwrW(contentTypeW); + +- if (!freedesktop_mime_type_for_extension(&nativeMimeTypes, extensionA, extensionW, &mimeTypeA)) +- goto end; +- +- if (mimeTypeA == NULL) ++ if (is_protocol_type) + { +- if (contentTypeW != NULL && strchrW(contentTypeW, '/')) +- mimeTypeA = wchars_to_utf8_chars(contentTypeW); +- else if ((get_special_mime_type(extensionW))) +- mimeTypeA = strdupA(get_special_mime_type(extensionW)); +- else +- mimeTypeA = heap_printf("application/x-wine-extension-%s", &extensionA[1]); ++ mimeTypeA = heap_printf("x-scheme-handler/%s", winTypeA); ++ } ++ else ++ { ++ if (!freedesktop_mime_type_for_extension(&nativeMimeTypes, winTypeA, winTypeW, &mimeTypeA)) ++ goto end; + +- if (mimeTypeA != NULL) ++ if (mimeTypeA == NULL) + { +- /* GNOME seems to ignore the tag in MIME packages, +- * and the default name is more intuitive anyway. +- */ +- if (iconW) ++ if (contentTypeW != NULL && strchrW(contentTypeW, '/')) ++ mimeTypeA = wchars_to_utf8_chars(contentTypeW); ++ else if ((get_special_mime_type(winTypeW))) ++ mimeTypeA = strdupA(get_special_mime_type(winTypeW)); ++ else ++ mimeTypeA = heap_printf("application/x-wine-extension-%s", winTypeA+1); ++ ++ if (mimeTypeA != NULL) + { +- char *flattened_mime = slashes_to_minuses(mimeTypeA); +- if (flattened_mime) ++ /* GNOME seems to ignore the tag in MIME packages, ++ * and the default name is more intuitive anyway. ++ */ ++ if (iconW) + { +- int index = 0; +- WCHAR *comma = strrchrW(iconW, ','); +- if (comma) ++ char *flattened_mime = slashes_to_minuses(mimeTypeA); ++ if (flattened_mime) + { +- *comma = 0; +- index = atoiW(comma + 1); ++ int index = 0; ++ WCHAR *comma = strrchrW(iconW, ','); ++ if (comma) ++ { ++ *comma = 0; ++ index = atoiW(comma + 1); ++ } ++ iconA = extract_icon(iconW, index, flattened_mime, FALSE); ++ HeapFree(GetProcessHeap(), 0, flattened_mime); + } +- iconA = extract_icon(iconW, index, flattened_mime, FALSE); +- HeapFree(GetProcessHeap(), 0, flattened_mime); + } ++ ++ write_freedesktop_mime_type_entry(packages_dir, winTypeA, mimeTypeA, friendlyDocNameA); ++ hasChanged = TRUE; ++ } ++ else ++ { ++ WINE_FIXME("out of memory\n"); ++ goto end; + } ++ } + +- write_freedesktop_mime_type_entry(packages_dir, extensionA, mimeTypeA, friendlyDocNameA); +- hasChanged = TRUE; ++ progIdW = reg_get_valW(HKEY_CLASSES_ROOT, winTypeW, NULL); ++ if (progIdW) ++ { ++ progIdA = escape(progIdW); ++ if (progIdA == NULL) ++ { ++ WINE_ERR("out of memory\n"); ++ goto end; ++ } + } + else ++ goto end; /* no progID => not a file type association */ ++ ++ /* Do not allow duplicate ProgIDs for a MIME type, it causes unnecessary duplication in Open dialogs */ ++ mimeProgId = heap_printf("%s=>%s", mimeTypeA, progIdA); ++ if (mimeProgId) + { +- WINE_FIXME("out of memory\n"); +- goto end; ++ struct rb_string_entry *entry; ++ if (wine_rb_get(&mimeProgidTree, mimeProgId)) ++ { ++ HeapFree(GetProcessHeap(), 0, mimeProgId); ++ goto end; ++ } ++ entry = HeapAlloc(GetProcessHeap(), 0, sizeof(struct rb_string_entry)); ++ if (!entry) ++ { ++ WINE_ERR("out of memory allocating rb_string_entry\n"); ++ goto end; ++ } ++ entry->string = mimeProgId; ++ if (wine_rb_put(&mimeProgidTree, mimeProgId, &entry->entry)) ++ { ++ WINE_ERR("error updating rb tree\n"); ++ goto end; ++ } + } + } + +- executableW = assoc_query(ASSOCSTR_EXECUTABLE, extensionW, openW); ++ executableW = assoc_query(ASSOCSTR_EXECUTABLE, winTypeW, openW); + if (executableW) + openWithIconA = extract_icon(executableW, 0, NULL, FALSE); + +- friendlyAppNameW = assoc_query(ASSOCSTR_FRIENDLYAPPNAME, extensionW, openW); ++ friendlyAppNameW = assoc_query(ASSOCSTR_FRIENDLYAPPNAME, winTypeW, openW); + if (friendlyAppNameW) + { + friendlyAppNameA = wchars_to_utf8_chars(friendlyAppNameW); +@@ -2716,59 +2774,26 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package + } + } + +- progIdW = reg_get_valW(HKEY_CLASSES_ROOT, extensionW, NULL); +- if (progIdW) +- { +- progIdA = escape(progIdW); +- if (progIdA == NULL) +- { +- WINE_ERR("out of memory\n"); +- goto end; +- } +- } +- else +- goto end; /* no progID => not a file type association */ +- +- /* Do not allow duplicate ProgIDs for a MIME type, it causes unnecessary duplication in Open dialogs */ +- mimeProgId = heap_printf("%s=>%s", mimeTypeA, progIdA); +- if (mimeProgId) +- { +- struct rb_string_entry *entry; +- if (wine_rb_get(&mimeProgidTree, mimeProgId)) +- { +- HeapFree(GetProcessHeap(), 0, mimeProgId); +- goto end; +- } +- entry = HeapAlloc(GetProcessHeap(), 0, sizeof(struct rb_string_entry)); +- if (!entry) +- { +- WINE_ERR("out of memory allocating rb_string_entry\n"); +- goto end; +- } +- entry->string = mimeProgId; +- if (wine_rb_put(&mimeProgidTree, mimeProgId, &entry->entry)) +- { +- WINE_ERR("error updating rb tree\n"); +- goto end; +- } +- } +- +- if (has_association_changed(extensionW, mimeTypeA, progIdW, friendlyAppNameA, openWithIconA)) ++ if (has_association_changed(winTypeW, mimeTypeA, progIdW, friendlyAppNameA, openWithIconA)) + { +- char *desktopPath = heap_printf("%s/wine-extension-%s.desktop", applications_dir, &extensionA[1]); ++ char *desktopPath; ++ if (is_protocol_type) ++ desktopPath = heap_printf("%s/wine-protocol-%s.desktop", applications_dir, winTypeA); ++ else ++ desktopPath = heap_printf("%s/wine-extension-%s.desktop", applications_dir, winTypeA+1); + if (desktopPath) + { +- if (write_freedesktop_association_entry(desktopPath, extensionA, friendlyAppNameA, mimeTypeA, progIdA, openWithIconA)) ++ if (write_freedesktop_association_entry(desktopPath, winTypeA, friendlyAppNameA, mimeTypeA, progIdA, openWithIconA)) + { + hasChanged = TRUE; +- update_association(extensionW, mimeTypeA, progIdW, friendlyAppNameA, desktopPath, openWithIconA); ++ update_association(winTypeW, mimeTypeA, progIdW, friendlyAppNameA, desktopPath, openWithIconA); + } + HeapFree(GetProcessHeap(), 0, desktopPath); + } + } + + end: +- HeapFree(GetProcessHeap(), 0, extensionA); ++ HeapFree(GetProcessHeap(), 0, winTypeA); + HeapFree(GetProcessHeap(), 0, commandW); + HeapFree(GetProcessHeap(), 0, executableW); + HeapFree(GetProcessHeap(), 0, openWithIconA); +@@ -2783,7 +2808,7 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package + HeapFree(GetProcessHeap(), 0, progIdW); + HeapFree(GetProcessHeap(), 0, progIdA); + } +- HeapFree(GetProcessHeap(), 0, extensionW); ++ HeapFree(GetProcessHeap(), 0, winTypeW); + if (ret != ERROR_SUCCESS) + break; + } +-- +2.25.1 + diff --git a/patches/winemenubuilder-integration/definition b/patches/winemenubuilder-integration/definition new file mode 100644 index 00000000..dc8d5457 --- /dev/null +++ b/patches/winemenubuilder-integration/definition @@ -0,0 +1,2 @@ +Fixes: [41275] Winemenubuilder should respect existing defaults for filetype associations +Fixes: [22904] Register URL protocol handlers under Linux