Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=22904 Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- loader/wine.inf.in | 4 + programs/winemenubuilder/winemenubuilder.c | 172 ++++++++++++--------- 2 files changed, 102 insertions(+), 74 deletions(-)
diff --git a/loader/wine.inf.in b/loader/wine.inf.in index b2747ad9a34..ef1a0e759d7 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -516,6 +516,10 @@ HKCU,Software\Wine\FileOpenNoIntegration.txt,"notepad",,"""%11%\notepad.exe"" " HKCU,Software\Wine\FileOpenNoIntegration.url,"ieframe",,"rundll32.exe ieframe.dll,OpenURL %l" HKCU,Software\Wine\FileOpenNoIntegration.wri,"wordpad",,"""%16422%\Windows NT\Accessories\wordpad.exe"" ""%1""" HKCU,Software\Wine\FileOpenNoIntegration.xml,"winebrowser",,"""%11%\winebrowser.exe"" ""%1""" +HKCU,Software\Wine\FileOpenNoIntegration\ftp,"winebrowser",,"""%11%\winebrowser.exe"" ""%1""" +HKCU,Software\Wine\FileOpenNoIntegration\http,"winebrowser",,"""%11%\winebrowser.exe"" ""%1""" +HKCU,Software\Wine\FileOpenNoIntegration\https,"winebrowser",,"""%11%\winebrowser.exe"" ""%1""" +HKCU,Software\Wine\FileOpenNoIntegration\mailto,"winebrowser",,"""%11%\winebrowser.exe"" ""%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 a2790cf203d..88d41cd9e7b 100644 --- a/programs/winemenubuilder/winemenubuilder.c +++ b/programs/winemenubuilder/winemenubuilder.c @@ -1933,10 +1933,13 @@ static BOOL has_association_changed(LPCWSTR extensionW, const WCHAR *mimeType, c ret = TRUE; heap_free(value);
- value = reg_get_valW(assocKey, extensionW, L"ProgID"); - if (!value || wcscmp(value, progId)) - ret = TRUE; - heap_free(value); + if (progId) + { + value = reg_get_valW(assocKey, extensionW, L"ProgID"); + if (!value || wcscmp(value, progId)) + ret = TRUE; + heap_free(value); + }
value = reg_get_valW(assocKey, extensionW, L"AppName"); if (!value || wcscmp(value, appName)) @@ -1980,7 +1983,7 @@ static void update_association(LPCWSTR extension, const WCHAR *mimeType, const W }
RegSetValueExW(subkey, L"MimeType", 0, REG_SZ, (const BYTE*) mimeType, (lstrlenW(mimeType) + 1) * sizeof(WCHAR)); - RegSetValueExW(subkey, L"ProgID", 0, REG_SZ, (const BYTE*) progId, (lstrlenW(progId) + 1) * sizeof(WCHAR)); + if (progId) RegSetValueExW(subkey, L"ProgID", 0, REG_SZ, (const BYTE*) progId, (lstrlenW(progId) + 1) * sizeof(WCHAR)); RegSetValueExW(subkey, L"AppName", 0, REG_SZ, (const BYTE*) appName, (lstrlenW(appName) + 1) * sizeof(WCHAR)); RegSetValueExW(subkey, L"DesktopFile", 0, REG_SZ, (const BYTE*) desktopFile, (lstrlenW(desktopFile) + 1) * sizeof(WCHAR)); if (openWithIcon) @@ -2091,7 +2094,7 @@ static BOOL is_extension_banned(LPCWSTR extension) return FALSE; }
-static BOOL on_exclude_list(const WCHAR *extension, const WCHAR *command) +static BOOL on_exclude_list(const WCHAR *win_type, const WCHAR *command) { static const WCHAR FileOpenNoIntegrationW[] = L"Software\Wine\FileOpenNoIntegration\"; WCHAR key_path[MAX_PATH]; @@ -2100,11 +2103,11 @@ static BOOL on_exclude_list(const WCHAR *extension, const WCHAR *command) DWORD len = ARRAY_SIZE(program_name); DWORD i = 0;
- if (ARRAY_SIZE(FileOpenNoIntegrationW) + lstrlenW(extension) > ARRAY_SIZE(key_path)) + if (ARRAY_SIZE(FileOpenNoIntegrationW) + lstrlenW(win_type) > ARRAY_SIZE(key_path)) return FALSE;
lstrcpyW(key_path, FileOpenNoIntegrationW); - lstrcatW(key_path, extension); + lstrcatW(key_path, win_type);
if (RegOpenKeyExW(HKEY_CURRENT_USER, key_path, 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) return FALSE; @@ -2134,15 +2137,15 @@ static WCHAR *get_special_mime_type(LPCWSTR extension) return NULL; }
-static BOOL write_freedesktop_association_entry(const WCHAR *desktopPath, const WCHAR *friendlyAppName, - const WCHAR *mimeType, const WCHAR *progId, - const WCHAR *openWithIcon) +static BOOL write_freedesktop_association_entry(const WCHAR *desktopPath, const WCHAR *winType, + const WCHAR *friendlyAppName, const WCHAR *mimeType, + const WCHAR *progId, const WCHAR *openWithIcon) { FILE *desktop; const WCHAR *prefix = _wgetenv( L"WINECONFIGDIR" );
- WINE_TRACE("friendlyAppName=%s, MIME type %s, progID=%s, icon=%s to file %s\n", - wine_dbgstr_w(friendlyAppName), wine_dbgstr_w(mimeType), + WINE_TRACE("winType=%s, friendlyAppName=%s, MIME type %s, progID=%s, icon=%s to file %s\n", + wine_dbgstr_w(winType), wine_dbgstr_w(friendlyAppName), wine_dbgstr_w(mimeType), wine_dbgstr_w(progId), wine_dbgstr_w(openWithIcon), wine_dbgstr_w(desktopPath));
desktop = _wfopen( desktopPath, L"wb" ); @@ -2159,11 +2162,15 @@ static BOOL write_freedesktop_association_entry(const WCHAR *desktopPath, const if (prefix) { char *path = wine_get_unix_file_name( prefix ); - fprintf(desktop, "Exec=env WINEPREFIX="%s" wine start /ProgIDOpen %s %%f\n", path, escape(progId)); + fprintf(desktop, "Exec=env WINEPREFIX="%s" wine start ", path); heap_free( path ); } else - fprintf(desktop, "Exec=wine start /ProgIDOpen %s %%f\n", escape(progId)); + fprintf(desktop, "Exec=wine start "); + if (progId) /* file association */ + fprintf(desktop, "/ProgIDOpen %s %%f\n", escape(progId)); + else /* protocol association */ + fprintf(desktop, "%%u\n"); fprintf(desktop, "NoDisplay=true\n"); fprintf(desktop, "StartupNotify=true\n"); if (openWithIcon) @@ -2188,7 +2195,7 @@ static BOOL generate_associations(const WCHAR *packages_dir, const WCHAR *applic
for (i = 0; ; i++) { - WCHAR *extensionW = NULL; + WCHAR *winTypeW = NULL; DWORD size = 1024; WCHAR *commandW = NULL; WCHAR *executableW = NULL; @@ -2201,102 +2208,119 @@ static BOOL generate_associations(const WCHAR *packages_dir, const WCHAR *applic WCHAR *progIdW = NULL; WCHAR *mimeProgId = NULL; struct rb_string_entry *entry; + BOOL is_protocol_type = FALSE;
do { - heap_free(extensionW); - extensionW = xmalloc(size * sizeof(WCHAR)); - ret = RegEnumKeyExW(HKEY_CLASSES_ROOT, i, extensionW, &size, NULL, NULL, NULL, NULL); + heap_free(winTypeW); + winTypeW = xmalloc(size * sizeof(WCHAR)); + ret = RegEnumKeyExW(HKEY_CLASSES_ROOT, i, winTypeW, &size, NULL, NULL, NULL, NULL); size *= 2; } while (ret == ERROR_MORE_DATA);
if (ret != ERROR_SUCCESS) { - heap_free(extensionW); + heap_free(winTypeW); break; }
- if (extensionW[0] != '.' || is_extension_banned(extensionW)) + if (winTypeW[0] != '.') + { + if (RegGetValueW(HKEY_CLASSES_ROOT, winTypeW, L"URL Protocol", RRF_RT_ANY, NULL, NULL, NULL) == ERROR_SUCCESS) + is_protocol_type = TRUE; + } + + if (!is_protocol_type && (winTypeW[0] != '.' || is_extension_banned(winTypeW))) goto end;
- commandW = assoc_query(ASSOCSTR_COMMAND, extensionW, L"open"); + commandW = assoc_query(ASSOCSTR_COMMAND, winTypeW, L"open"); if (commandW == NULL) /* no command => no application is associated */ goto end;
- if (on_exclude_list(extensionW, commandW)) + if (on_exclude_list(winTypeW, commandW)) /* command is on the exclude list => desktop integration is not desirable */ goto end;
- wcslwr(extensionW); - friendlyDocNameW = assoc_query(ASSOCSTR_FRIENDLYDOCNAME, extensionW, NULL); + wcslwr(winTypeW); + friendlyDocNameW = assoc_query(ASSOCSTR_FRIENDLYDOCNAME, winTypeW, NULL);
- iconW = assoc_query(ASSOCSTR_DEFAULTICON, extensionW, NULL); + iconW = assoc_query(ASSOCSTR_DEFAULTICON, winTypeW, NULL);
- mimeType = freedesktop_mime_type_for_extension(&nativeMimeTypes, extensionW); - - if (mimeType == NULL) + if (is_protocol_type) { - contentTypeW = assoc_query(ASSOCSTR_CONTENTTYPE, extensionW, NULL); - if (contentTypeW != NULL && wcschr(contentTypeW, '/')) - mimeType = xwcsdup(wcslwr(contentTypeW)); - else if (!(mimeType = get_special_mime_type(extensionW))) - mimeType = heap_wprintf(L"application/x-wine-extension-%s", &extensionW[1]); + mimeType = heap_wprintf(L"x-scheme-handler/%s", winTypeW); + } + else + { + mimeType = freedesktop_mime_type_for_extension(&nativeMimeTypes, winTypeW);
- /* GNOME seems to ignore the <icon> tag in MIME packages, - * and the default name is more intuitive anyway. - */ - if (iconW) + if (mimeType == NULL) { - WCHAR *flattened_mime = slashes_to_minuses(mimeType); - int index = 0; - WCHAR *comma = wcsrchr(iconW, ','); - if (comma) + contentTypeW = assoc_query(ASSOCSTR_CONTENTTYPE, winTypeW, NULL); + if (contentTypeW != NULL && wcschr(contentTypeW, '/')) + mimeType = xwcsdup(wcslwr(contentTypeW)); + else if (!(mimeType = get_special_mime_type(winTypeW))) + mimeType = heap_wprintf(L"application/x-wine-extension-%s", &winTypeW[1]); + + /* GNOME seems to ignore the <icon> tag in MIME packages, + * and the default name is more intuitive anyway. + */ + if (iconW) { - *comma = 0; - index = wcstol(comma + 1, NULL, 10); + WCHAR *flattened_mime = slashes_to_minuses(mimeType); + int index = 0; + WCHAR *comma = wcsrchr(iconW, ','); + if (comma) + { + *comma = 0; + index = wcstol(comma + 1, NULL, 10); + } + extract_icon(iconW, index, flattened_mime, FALSE); + heap_free(flattened_mime); } - extract_icon(iconW, index, flattened_mime, FALSE); - heap_free(flattened_mime); + + write_freedesktop_mime_type_entry(packages_dir, winTypeW, mimeType, friendlyDocNameW); + hasChanged = TRUE; }
- write_freedesktop_mime_type_entry(packages_dir, extensionW, mimeType, friendlyDocNameW); - hasChanged = TRUE; + progIdW = reg_get_valW(HKEY_CLASSES_ROOT, winTypeW, NULL); + if (!progIdW) 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_wprintf(L"%s=>%s", mimeType, progIdW); + if (wine_rb_get(&mimeProgidTree, mimeProgId)) + { + heap_free(mimeProgId); + goto end; + } + entry = xmalloc(sizeof(struct rb_string_entry)); + 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, L"open"); + executableW = assoc_query(ASSOCSTR_EXECUTABLE, winTypeW, L"open"); if (executableW) openWithIcon = compute_native_identifier(0, executableW, NULL);
- friendlyAppName = assoc_query(ASSOCSTR_FRIENDLYAPPNAME, extensionW, L"open"); + friendlyAppName = assoc_query(ASSOCSTR_FRIENDLYAPPNAME, winTypeW, L"open"); if (!friendlyAppName) friendlyAppName = L"A Wine application";
- progIdW = reg_get_valW(HKEY_CLASSES_ROOT, extensionW, NULL); - if (!progIdW) 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_wprintf(L"%s=>%s", mimeType, progIdW); - if (wine_rb_get(&mimeProgidTree, mimeProgId)) + if (has_association_changed(winTypeW, mimeType, progIdW, friendlyAppName, openWithIcon)) { - heap_free(mimeProgId); - goto end; - } - entry = xmalloc(sizeof(struct rb_string_entry)); - 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, mimeType, progIdW, friendlyAppName, openWithIcon)) - { - WCHAR *desktopPath = heap_wprintf(L"%s\wine-extension-%s.desktop", - applications_dir, extensionW + 1 ); - if (write_freedesktop_association_entry(desktopPath, friendlyAppName, mimeType, progIdW, openWithIcon)) + WCHAR *desktopPath; + if (is_protocol_type) + desktopPath = heap_wprintf(L"%s\wine-protocol-%s.desktop", applications_dir, winTypeW); + else + desktopPath = heap_wprintf(L"%s\wine-extension-%s.desktop", applications_dir, winTypeW+1); + if (write_freedesktop_association_entry(desktopPath, winTypeW, friendlyAppName, mimeType, progIdW, openWithIcon)) { hasChanged = TRUE; - update_association(extensionW, mimeType, progIdW, friendlyAppName, desktopPath, openWithIcon); + update_association(winTypeW, mimeType, progIdW, friendlyAppName, desktopPath, openWithIcon); } heap_free(desktopPath); } @@ -2312,7 +2336,7 @@ static BOOL generate_associations(const WCHAR *packages_dir, const WCHAR *applic heap_free(contentTypeW); heap_free(mimeType); heap_free(progIdW); - heap_free(extensionW); + heap_free(winTypeW); }
wine_rb_destroy(&mimeProgidTree, winemenubuilder_rb_destroy, NULL);