diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index ad860106..04c73991 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -397,6 +397,7 @@ patch_enable_all () enable_winedbg_Process_Arguments="$1" enable_winedevice_Default_Drivers="$1" enable_winedevice_Fix_Relocation="$1" + enable_winemapi_user_xdg_mail="$1" enable_winemenubuilder_Desktop_Icon_Path="$1" enable_winemp3_acm_MPEG3_StreamOpen="$1" enable_wineps_drv_PostScript_Fixes="$1" @@ -1382,6 +1383,9 @@ patch_enable () winedevice-Fix_Relocation) enable_winedevice_Fix_Relocation="$2" ;; + winemapi-user-xdg-mail) + enable_winemapi_user_xdg_mail="$2" + ;; winemenubuilder-Desktop_Icon_Path) enable_winemenubuilder_Desktop_Icon_Path="$2" ;; @@ -8132,6 +8136,18 @@ if test "$enable_winedevice_Fix_Relocation" -eq 1; then ) >> "$patchlist" fi +# Patchset winemapi-user-xdg-mail +# | +# | Modified files: +# | * dlls/winemapi/Makefile.in, dlls/winemapi/sendmail.c, dlls/winemapi/winemapi_private.h, dlls/winemapi/xdg-email.c +# | +if test "$enable_winemapi_user_xdg_mail" -eq 1; then + patch_apply winemapi-user-xdg-mail/0001-winemapi-Directly-use-xdg-email-if-available-enablin.patch + ( + printf '%s\n' '+ { "Jeremy White", "winemapi: Directly use xdg-email if available, enabling file attachments.", 1 },'; + ) >> "$patchlist" +fi + # Patchset winemenubuilder-Desktop_Icon_Path # | # | Modified files: diff --git a/patches/winemapi-user-xdg-mail/0001-winemapi-Directly-use-xdg-email-if-available-enablin.patch b/patches/winemapi-user-xdg-mail/0001-winemapi-Directly-use-xdg-email-if-available-enablin.patch new file mode 100644 index 00000000..c72105e9 --- /dev/null +++ b/patches/winemapi-user-xdg-mail/0001-winemapi-Directly-use-xdg-email-if-available-enablin.patch @@ -0,0 +1,396 @@ +From 3e1de8370f31d9d472a6ff61996479aabff16ab1 Mon Sep 17 00:00:00 2001 +From: Jeremy White +Date: Thu, 29 Mar 2018 11:58:25 +1100 +Subject: [PATCH] winemapi: Directly use xdg-email if available, enabling file + attachments. + +This addresses https://bugs.winehq.org/show_bug.cgi?id=11770 for systems with xdg-email. + +v2: +Use new heap_* function. + +Signed-off-by: Jeremy White +--- + dlls/winemapi/Makefile.in | 3 +- + dlls/winemapi/sendmail.c | 48 +++++--- + dlls/winemapi/winemapi_private.h | 27 +++++ + dlls/winemapi/xdg-email.c | 246 +++++++++++++++++++++++++++++++++++++++ + 4 files changed, 309 insertions(+), 15 deletions(-) + create mode 100644 dlls/winemapi/winemapi_private.h + create mode 100644 dlls/winemapi/xdg-email.c + +diff --git a/dlls/winemapi/Makefile.in b/dlls/winemapi/Makefile.in +index 813ee42..d6f79b4 100644 +--- a/dlls/winemapi/Makefile.in ++++ b/dlls/winemapi/Makefile.in +@@ -3,4 +3,5 @@ IMPORTS = shlwapi shell32 mapi32 + + C_SRCS = \ + main.c \ +- sendmail.c ++ sendmail.c \ ++ xdg-email.c +diff --git a/dlls/winemapi/sendmail.c b/dlls/winemapi/sendmail.c +index 03a29ba..686e061 100644 +--- a/dlls/winemapi/sendmail.c ++++ b/dlls/winemapi/sendmail.c +@@ -36,6 +36,8 @@ + #include "shlwapi.h" + #include "wine/debug.h" + ++#include "winemapi_private.h" ++ + WINE_DEFAULT_DEBUG_CHANNEL(winemapi); + + /* Escapes a string for use in mailto: URL */ +@@ -70,23 +72,12 @@ static char *escape_string(char *in, char *empty_string) + } + + /************************************************************************** +- * MAPISendMail ++ * BrowserSendMail + * +- * Send a message using a native mail client. +- * +- * PARAMS +- * session [I] Handle to a MAPI session. +- * uiparam [I] Parent window handle. +- * message [I] Pointer to a MAPIMessage structure. +- * flags [I] Flags. +- * reserved [I] Reserved, pass 0. +- * +- * RETURNS +- * Success: SUCCESS_SUCCESS +- * Failure: MAPI_E_FAILURE ++ * Send an email by forming a mailto uri and invoking a browser. + * + */ +-ULONG WINAPI MAPISendMail(LHANDLE session, ULONG_PTR uiparam, ++static ULONG BrowserSendMail(LHANDLE session, ULONG_PTR uiparam, + lpMapiMessage message, FLAGS flags, ULONG reserved) + { + ULONG ret = MAPI_E_FAILURE; +@@ -291,6 +282,35 @@ exit: + return ret; + } + ++/************************************************************************** ++ * MAPISendMail ++ * ++ * Send a message using a native mail client. ++ * ++ * PARAMS ++ * session [I] Handle to a MAPI session. ++ * uiparam [I] Parent window handle. ++ * message [I] Pointer to a MAPIMessage structure. ++ * flags [I] Flags. ++ * reserved [I] Reserved, pass 0. ++ * ++ * RETURNS ++ * Success: SUCCESS_SUCCESS ++ * Failure: MAPI_E_FAILURE ++ * ++ */ ++ULONG WINAPI MAPISendMail(LHANDLE session, ULONG_PTR uiparam, ++ lpMapiMessage message, FLAGS flags, ULONG reserved) ++{ ++ TRACE("(0x%08lx 0x%08lx %p 0x%08x 0x%08x)\n", session, uiparam, ++ message, flags, reserved); ++ ++ if (XDGMailAvailable()) ++ return XDGSendMail(session, uiparam, message, flags, reserved); ++ ++ return BrowserSendMail(session, uiparam, message, flags, reserved); ++} ++ + ULONG WINAPI MAPISendDocuments(ULONG_PTR uiparam, LPSTR delim, LPSTR paths, + LPSTR filenames, ULONG reserved) + { +diff --git a/dlls/winemapi/winemapi_private.h b/dlls/winemapi/winemapi_private.h +new file mode 100644 +index 0000000..a8bb8c5 +--- /dev/null ++++ b/dlls/winemapi/winemapi_private.h +@@ -0,0 +1,27 @@ ++/* ++ * ++ * Copyright 2016 Jeremy White ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ */ ++ ++#ifndef __WINEMAPI_PRIVATE_INCLUDED__ ++#define __WINEMAPI_PRIVATE_INCLUDED__ ++ ++ULONG XDGSendMail(LHANDLE session, ULONG_PTR uiparam, ++ lpMapiMessage message, FLAGS flags, ULONG reserved); ++BOOLEAN XDGMailAvailable(void); ++ ++#endif /* __WINEMAPI_PRIVATE_INCLUDED__ */ +diff --git a/dlls/winemapi/xdg-email.c b/dlls/winemapi/xdg-email.c +new file mode 100644 +index 0000000..6b42066 +--- /dev/null ++++ b/dlls/winemapi/xdg-email.c +@@ -0,0 +1,246 @@ ++/* ++ * MAPISendMail implementation for xdg-email ++ * ++ * Copyright 2016 Jeremy White for CodeWeavers ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ */ ++ ++#include "config.h" ++#include "wine/port.h" ++ ++#include ++ ++#define COBJMACROS ++ ++#include "windef.h" ++#include "winbase.h" ++#include "winerror.h" ++#include "winnls.h" ++#include "mapi.h" ++#include "wine/heap.h" ++#include "wine/debug.h" ++#ifdef HAVE_UNISTD_H ++#include ++#endif ++ ++#include "winemapi_private.h" ++ ++WINE_DEFAULT_DEBUG_CHANNEL(winemapi); ++ ++static inline WCHAR *heap_strdupAtoW(const char *str) ++{ ++ LPWSTR ret = NULL; ++ ++ if(str) { ++ DWORD len; ++ ++ len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); ++ ret = heap_alloc(len*sizeof(WCHAR)); ++ if(ret) ++ MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); ++ } ++ ++ return ret; ++} ++ ++static void add_argument(char **argv, int *argc, const char *arg, const char *param) ++{ ++ argv[(*argc)] = heap_alloc(strlen(arg) + 1); ++ strcpy(argv[(*argc)++], arg); ++ if (param) ++ { ++ argv[(*argc)] = heap_alloc(strlen(param) + 1); ++ strcpy(argv[(*argc)++], param); ++ } ++} ++ ++static void add_target(char **argv, int *argc, ULONG class, const char *address) ++{ ++ static const char smtp[] = "smtp:"; ++ ++ if (!strncasecmp(address, smtp, sizeof(smtp) - 1)) ++ address += sizeof(smtp) - 1; ++ ++ switch (class) ++ { ++ case MAPI_ORIG: ++ TRACE("From: %s\n (unused)", debugstr_a(address)); ++ break; ++ ++ case MAPI_TO: ++ TRACE("To: %s\n", debugstr_a(address)); ++ add_argument(argv, argc, address, NULL); ++ break; ++ ++ case MAPI_CC: ++ TRACE("CC: %s\n", debugstr_a(address)); ++ add_argument(argv, argc, "--cc", address); ++ break; ++ ++ case MAPI_BCC: ++ TRACE("BCC: %s\n", debugstr_a(address)); ++ add_argument(argv, argc, "--bcc", address); ++ break; ++ ++ default: ++ TRACE("Unknown recipient class: %d\n", class); ++ } ++} ++ ++static void add_file(char **argv, int *argc, const char *path, const char *file) ++{ ++ char fullname[MAX_PATH] = {0}; ++ WCHAR *fullnameW; ++ char *unixpath; ++ ++ if (path) ++ { ++ strcpy(fullname, path); ++ strcat(fullname, "\\"); ++ } ++ if (file) ++ strcat(fullname, file); ++ ++ fullnameW = heap_strdupAtoW(fullname); ++ if(!fullnameW) ++ { ++ ERR("Out of memory\n"); ++ return; ++ } ++ ++ unixpath = wine_get_unix_file_name(fullnameW); ++ if (unixpath) ++ { ++ add_argument(argv, argc, "--attach", unixpath); ++ heap_free(unixpath); ++ } ++ else ++ ERR("Cannot find unix path of '%s'; not attaching.\n", debugstr_w(fullnameW)); ++ ++ heap_free(fullnameW); ++} ++ ++/************************************************************************** ++ * XDGIsAvailable ++ * ++ */ ++BOOLEAN XDGMailAvailable(void) ++{ ++#ifdef HAVE_UNISTD_H ++ char *p, *q, *test; ++ int len; ++ int rc; ++ ++ for (p = getenv("PATH"); p; p = q) ++ { ++ while (*p == ':') ++ p++; ++ ++ if (!*p) ++ break; ++ ++ q = strchr(p, ':'); ++ len = q ? q - p : strlen(p); ++ ++ test = heap_alloc(len + strlen("xdg-email") + 2); /* '/' + NULL */ ++ if(!test) ++ break; ++ memcpy(test, p, len); ++ strcpy(test + len, "/"); ++ strcat(test, "xdg-email"); ++ ++ rc = access(test, X_OK); ++ heap_free(test); ++ ++ if (rc == 0) ++ return TRUE; ++ } ++#endif ++ return FALSE; ++} ++ ++/************************************************************************** ++ * XDGSendMail ++ * ++ * Send a message using xdg-email mail client. ++ * ++ */ ++ULONG XDGSendMail(LHANDLE session, ULONG_PTR uiparam, ++ lpMapiMessage message, FLAGS flags, ULONG reserved) ++{ ++ int i; ++ int argc = 0; ++ int max_args; ++ char **argv = NULL; ++ ULONG ret = MAPI_E_FAILURE; ++ ++ TRACE("(0x%08lx 0x%08lx %p 0x%08x 0x%08x)\n", session, uiparam, message, flags, reserved); ++ ++ if (!message) ++ return MAPI_E_FAILURE; ++ ++ max_args = 1 + (2 + message->nRecipCount + message->nFileCount) * 2; ++ argv = heap_alloc_zero( (max_args + 1) * sizeof(*argv)); ++ ++ add_argument(argv, &argc, "xdg-email", NULL); ++ ++ if (message->lpOriginator) ++ TRACE("From: %s (unused)\n", debugstr_a(message->lpOriginator->lpszAddress)); ++ ++ for (i = 0; i < message->nRecipCount; i++) ++ { ++ if (!message->lpRecips) ++ { ++ WARN("Recipient %d missing\n", i); ++ goto exit; ++ } ++ ++ if (message->lpRecips[i].lpszAddress) ++ add_target(argv, &argc, message->lpRecips[i].ulRecipClass, ++ message->lpRecips[i].lpszAddress); ++ else ++ FIXME("Name resolution and entry identifiers not supported\n"); ++ } ++ ++ for (i = 0; i < message->nFileCount; i++) ++ { ++ TRACE("File Path: %s, name %s\n", debugstr_a(message->lpFiles[i].lpszPathName), ++ debugstr_a(message->lpFiles[i].lpszFileName)); ++ add_file(argv, &argc, message->lpFiles[i].lpszPathName, message->lpFiles[i].lpszFileName); ++ } ++ ++ if (message->lpszSubject) ++ { ++ TRACE("Subject: %s\n", debugstr_a(message->lpszSubject)); ++ add_argument(argv, &argc, "--subject", message->lpszSubject); ++ } ++ ++ if (message->lpszNoteText) ++ { ++ TRACE("Body: %s\n", debugstr_a(message->lpszNoteText)); ++ add_argument(argv, &argc, "--body", message->lpszNoteText); ++ } ++ ++ TRACE("Executing xdg-email; parameters:\n"); ++ for (i = 0; argv[i] && i <= max_args; i++) ++ TRACE(" %d: [%s]\n", i, argv[i]); ++ if (_spawnvp(_P_WAIT, "xdg-email", (const char **) argv) == 0) ++ ret = SUCCESS_SUCCESS; ++ ++exit: ++ heap_free(argv); ++ return ret; ++} +-- +1.9.1 + diff --git a/patches/winemapi-user-xdg-mail/definition b/patches/winemapi-user-xdg-mail/definition new file mode 100644 index 00000000..d8105168 --- /dev/null +++ b/patches/winemapi-user-xdg-mail/definition @@ -0,0 +1 @@ +Fixes [11770] - use xdg-email if it's available.