Skip to content

Instantly share code, notes, and snippets.

@markx86
Last active February 3, 2023 13:59
Show Gist options
  • Save markx86/350686b15d01c18a5507cc1532279f0a to your computer and use it in GitHub Desktop.
Save markx86/350686b15d01c18a5507cc1532279f0a to your computer and use it in GitHub Desktop.
WINEMAPI Thunderbird patch
--- wine-8.0/dlls/winemapi/sendmail.c 2023-01-24 16:06:25.000000000 +0100
+++ sendmail.c 2023-02-03 14:47:20.039651438 +0100
@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include <windows.h>
#include <stdio.h>
#include <stdarg.h>
@@ -36,37 +37,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(winemapi);
-/* Escapes a string for use in mailto: URL */
-static char *escape_string(char *in, char *empty_string)
-{
- HRESULT res;
- DWORD size;
- char *escaped = NULL;
-
- if (!in)
- return empty_string;
-
- size = 1;
- res = UrlEscapeA(in, empty_string, &size, URL_ESCAPE_PERCENT | URL_ESCAPE_SEGMENT_ONLY);
-
- if (res == E_POINTER)
- {
- escaped = HeapAlloc(GetProcessHeap(), 0, size);
-
- if (!escaped)
- return in;
-
- /* If for some reason UrlEscape fails, just send the original text */
- if (UrlEscapeA(in, escaped, &size, URL_ESCAPE_PERCENT | URL_ESCAPE_SEGMENT_ONLY) != S_OK)
- {
- HeapFree(GetProcessHeap(), 0, escaped);
- escaped = in;
- }
- }
-
- return escaped ? escaped : empty_string;
-}
-
+
/**************************************************************************
* MAPISendMail
*
@@ -90,16 +61,21 @@
ULONG ret = MAPI_E_FAILURE;
unsigned int i, to_count = 0, cc_count = 0, bcc_count = 0;
unsigned int to_size = 0, cc_size = 0, bcc_size = 0, subj_size, body_size;
+ unsigned int att_size = 0;
- char *to = NULL, *cc = NULL, *bcc = NULL, *subject = NULL, *body = NULL;
+ char *to = NULL, *cc = NULL, *bcc = NULL, *subject = NULL, *body = NULL, *attachment = NULL;
const char *address;
static const char format[] =
- "mailto:\"%s\"?subject=\"%s\"&cc=\"%s\"&bcc=\"%s\"&body=\"%s\"";
+ "/c start %s -compose to='%s',subject='%s',cc='%s',bcc='%s',body='%s',attachment='%s'";
static const char smtp[] = "smtp:";
- char *mailto = NULL, *escape = NULL;
+ char *mailto = NULL;
char empty_string[] = "";
- HRESULT res;
+ char path[MAX_PATH];
DWORD size;
+ WCHAR *windows_name;
+ LPWSTR (*CDECL wine_get_dos_file_name_ptr)(LPCSTR) = NULL;
+
+ (void)(empty_string);
TRACE("(0x%08Ix 0x%08Ix %p 0x%08lx 0x%08lx)\n", session, uiparam,
message, flags, reserved);
@@ -107,6 +83,7 @@
if (!message)
return MAPI_E_FAILURE;
+ TRACE("%d recipients\n", message->nRecipCount);
for (i = 0; i < message->nRecipCount; i++)
{
if (!message->lpRecips)
@@ -154,16 +131,60 @@
if (message->nFileCount)
{
- FIXME("Ignoring %lu attachments:\n", message->nFileCount);
- for (i = 0; i < message->nFileCount; i++)
- FIXME("\t%s (%s)\n", debugstr_a(message->lpFiles[i].lpszPathName),
- debugstr_a(message->lpFiles[i].lpszFileName));
+ LPSTR (*CDECL wine_get_unix_file_name_ptr)(LPCWSTR) = NULL;
+ wine_get_unix_file_name_ptr = (void*)
+ GetProcAddress(GetModuleHandleA("KERNEL32"),
+ "wine_get_unix_file_name");
+ if (wine_get_unix_file_name_ptr == NULL) {
+ WARN("Cannot get the address of 'wine_get_unix_file_name'\n");
+ } else {
+ char** unix_names = HeapAlloc(GetProcessHeap(), 0, message->nFileCount * sizeof(char*));
+
+ if (!unix_names)
+ goto exit;
+
+ for (i = 0; i < message->nFileCount; i++) {
+ unsigned int namesize = lstrlenA(message->lpFiles[i].lpszPathName) + 1;
+ LPWSTR wname = HeapAlloc(GetProcessHeap(), 0, 2 * namesize);
+
+ TRACE("Translating %s to unix path\n", debugstr_a(message->lpFiles[i].lpszPathName));
+ MultiByteToWideChar(CP_ACP, 0, message->lpFiles[i].lpszPathName, namesize, wname, namesize);
+ unix_names[i] = wine_get_unix_file_name_ptr(wname);
+ HeapFree(GetProcessHeap(), 0, wname);
+ TRACE(" -> %s\n", unix_names[i]);
+
+ if (unix_names[i]) {
+ // compute overall size, account for trailing ',' or '\0'
+ att_size += lstrlenA(unix_names[i]) + 1;
+ }
+ }
+
+ // conversion is done, build list of attachments string
+ attachment = HeapAlloc(GetProcessHeap(), 0, att_size);
+
+ if (!attachment)
+ goto exit;
+
+ attachment[0] = '\0';
+
+ // concatenate all file names in one string and free the individual names
+ for (i = 0; i < message->nFileCount; i++) {
+ if (unix_names[i]) {
+ if (attachment[0] != '\0')
+ lstrcatA(attachment, ",");
+
+ lstrcatA(attachment, unix_names[i]);
+ HeapFree(GetProcessHeap(), 0, unix_names[i]);
+ }
+ }
+ TRACE("Attachments: %s\n", attachment);
+ }
}
/* Escape subject and body */
- subject = escape_string(message->lpszSubject, empty_string);
- body = escape_string(message->lpszNoteText, empty_string);
-
+ subject = message->lpszSubject;
+ body = message->lpszNoteText;
+
TRACE("Subject: %s\n", debugstr_a(subject));
TRACE("Body: %s\n", debugstr_a(body));
@@ -243,34 +264,37 @@
}
}
ret = MAPI_E_FAILURE;
- size = sizeof(format) + to_size + cc_size + bcc_size + subj_size + body_size;
-
- mailto = HeapAlloc(GetProcessHeap(), 0, size);
-
- if (!mailto)
+
+ wine_get_dos_file_name_ptr = (void*)
+ GetProcAddress(GetModuleHandleA("KERNEL32"),
+ "wine_get_dos_file_name");
+ if (wine_get_dos_file_name_ptr == NULL) {
+ WARN("Cannot get the address of 'wine_get_dos_file_name'\n");
goto exit;
+ }
- sprintf(mailto, format, to ? to : "", subject, cc ? cc : "", bcc ? bcc : "", body);
-
- size = 1;
- res = UrlEscapeA(mailto, empty_string, &size, URL_ESCAPE_SPACES_ONLY);
-
- if (res != E_POINTER)
+ if ((windows_name = wine_get_dos_file_name_ptr("/usr/bin/thunderbird")))
+ {
+ WideCharToMultiByte(CP_UNIXCP, 0, windows_name, -1, path, MAX_PATH, NULL, NULL);
+ HeapFree( GetProcessHeap(), 0, windows_name );
+ }
+ else
+ {
+ WARN("Unable to convert '/usr/bin/thunderbird' to DOS path\n");
goto exit;
+ }
- escape = HeapAlloc(GetProcessHeap(), 0, size);
-
- if (!escape)
- goto exit;
+ size = sizeof(format) + lstrlenA(path) + to_size + cc_size + bcc_size + subj_size + body_size + att_size;
- res = UrlEscapeA(mailto, escape, &size, URL_ESCAPE_SPACES_ONLY);
+ mailto = HeapAlloc(GetProcessHeap(), 0, size);
- if (res != S_OK)
+ if (!mailto)
goto exit;
- TRACE("Executing winebrowser.exe with parameters '%s'\n", debugstr_a(escape));
+ sprintf(mailto, format, path, to ? to : "", subject, cc ? cc : "", bcc ? bcc : "", body, attachment ? attachment : "");
+ TRACE("Executing cmd %s\n", mailto);
- if ((UINT_PTR) ShellExecuteA(NULL, "open", "winebrowser.exe", escape, NULL, 0) > 32)
+ if ((UINT_PTR) ShellExecuteA(NULL, "open", "cmd.exe", mailto, NULL, 0) > 32)
ret = SUCCESS_SUCCESS;
exit:
@@ -278,13 +302,9 @@
HeapFree(GetProcessHeap(), 0, cc);
HeapFree(GetProcessHeap(), 0, bcc);
HeapFree(GetProcessHeap(), 0, mailto);
- HeapFree(GetProcessHeap(), 0, escape);
-
- if (subject != empty_string)
- HeapFree(GetProcessHeap(), 0, subject);
- if (body != empty_string)
- HeapFree(GetProcessHeap(), 0, body);
+ if (attachment != NULL)
+ HeapFree(GetProcessHeap(), 0, attachment);
return ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment