Last active
March 16, 2025 22:28
-
-
Save markx86/350686b15d01c18a5507cc1532279f0a to your computer and use it in GitHub Desktop.
WINEMAPI Thunderbird patch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- a/dlls/winemapi/sendmail.c 2025-03-07 22:15:56.000000000 +0100 | |
| +++ b/dlls/winemapi/sendmail.c 2025-03-16 23:26:02.574575702 +0100 | |
| @@ -406,6 +406,257 @@ | |
| return ret; | |
| } | |
| +static ULONG send_mail_thunderbird(lpMapiMessage message) { | |
| + 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, att_size = 0; | |
| + unsigned int subj_size, body_size, name_size; | |
| + | |
| + char *to = NULL, *cc = NULL, *bcc = NULL, *subject = NULL, *body = NULL, *attachment = NULL; | |
| + const char *address; | |
| + static const char format[] = | |
| + "/c start %s -compose to='%s',subject='%s',cc='%s',bcc='%s',body='%s',attachment='%s'"; | |
| + static const char smtp[] = "smtp:"; | |
| + LPWSTR wthunderbird = NULL; | |
| + LPWSTR wname = NULL; | |
| + LPSTR file_path = NULL; | |
| + char *cmdstr = NULL; | |
| + char **unix_names = NULL; | |
| + char thunderbird[MAX_PATH]; | |
| + DWORD size; | |
| + | |
| + for (i = 0; i < message->nRecipCount; i++) | |
| + { | |
| + address = message->lpRecips[i].lpszAddress; | |
| + | |
| + if (address) | |
| + { | |
| + if (!_strnicmp(address, smtp, sizeof(smtp) - 1)) | |
| + address += sizeof(smtp) - 1; | |
| + | |
| + switch (message->lpRecips[i].ulRecipClass) | |
| + { | |
| + case MAPI_ORIG: | |
| + TRACE("From: %s\n", debugstr_a(address)); | |
| + break; | |
| + | |
| + case MAPI_TO: | |
| + TRACE("To: %s\n", debugstr_a(address)); | |
| + to_size += lstrlenA(address) + 1; | |
| + break; | |
| + | |
| + case MAPI_CC: | |
| + TRACE("Cc: %s\n", debugstr_a(address)); | |
| + cc_size += lstrlenA(address) + 1; | |
| + break; | |
| + | |
| + case MAPI_BCC: | |
| + TRACE("Bcc: %s\n", debugstr_a(address)); | |
| + bcc_size += lstrlenA(address) + 1; | |
| + break; | |
| + | |
| + default: | |
| + TRACE("Unknown recipient class: %ld\n", | |
| + message->lpRecips[i].ulRecipClass); | |
| + } | |
| + } | |
| + else | |
| + FIXME("Name resolution and entry identifiers not supported\n"); | |
| + } | |
| + | |
| + if (message->nFileCount) | |
| + { | |
| + unix_names = HeapAlloc(GetProcessHeap(), 0, message->nFileCount * sizeof(*unix_names)); | |
| + if (!unix_names) | |
| + { | |
| + WARN("Failed to allocate memory for file path translation\n"); | |
| + goto end_file; | |
| + } | |
| + | |
| + for (i = 0; i < message->nFileCount; i++) | |
| + { | |
| + file_path = message->lpFiles[i].lpszPathName; | |
| + | |
| + TRACE("Translating %s to unix path\n", debugstr_a(file_path)); | |
| + | |
| + name_size = lstrlenA(file_path) + 1; | |
| + wname = HeapAlloc(GetProcessHeap(), 0, 2 * name_size); | |
| + if (!wname) | |
| + { | |
| + WARN("Failed to allocate memory for file path %s\n", debugstr_a(file_path)); | |
| + goto end_file; | |
| + } | |
| + MultiByteToWideChar(CP_ACP, 0, file_path, name_size, wname, name_size); | |
| + | |
| + unix_names[i] = wine_get_unix_file_name(wname); | |
| + HeapFree(GetProcessHeap(), 0, wname); | |
| + | |
| + if (!unix_names[i]) | |
| + { | |
| + TRACE(" -> FAILED!\n"); | |
| + continue; | |
| + } | |
| + TRACE(" -> %s\n", unix_names[i]); | |
| + att_size += lstrlenA(unix_names[i]) + 1; | |
| + } | |
| + | |
| + attachment = HeapAlloc(GetProcessHeap(), 0, att_size); | |
| + if (!attachment) | |
| + { | |
| + WARN("Could not allocate space for attachment\n"); | |
| + goto end_file; | |
| + } | |
| + | |
| + attachment[0] = '\0'; | |
| +end_file: | |
| + if (unix_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]); | |
| + } | |
| + } | |
| + HeapFree(GetProcessHeap(), 0, unix_names); | |
| + unix_names = NULL; | |
| + | |
| + TRACE("Attachments: %s\n", attachment); | |
| + } | |
| + } | |
| + | |
| + /* Escape subject and body */ | |
| + subject = message->lpszSubject; | |
| + body = message->lpszNoteText; | |
| + | |
| + TRACE("Subject: %s\n", debugstr_a(subject)); | |
| + TRACE("Body: %s\n", debugstr_a(body)); | |
| + | |
| + subj_size = lstrlenA(subject); | |
| + body_size = lstrlenA(body); | |
| + | |
| + ret = MAPI_E_INSUFFICIENT_MEMORY; | |
| + | |
| + if (to_size) | |
| + { | |
| + to = HeapAlloc(GetProcessHeap(), 0, to_size); | |
| + | |
| + if (!to) | |
| + goto exit; | |
| + | |
| + to[0] = 0; | |
| + } | |
| + | |
| + if (cc_size) | |
| + { | |
| + cc = HeapAlloc(GetProcessHeap(), 0, cc_size); | |
| + | |
| + if (!cc) | |
| + goto exit; | |
| + | |
| + cc[0] = 0; | |
| + } | |
| + | |
| + if (bcc_size) | |
| + { | |
| + bcc = HeapAlloc(GetProcessHeap(), 0, bcc_size); | |
| + | |
| + if (!bcc) | |
| + goto exit; | |
| + | |
| + bcc[0] = 0; | |
| + } | |
| + | |
| + if (message->lpOriginator) | |
| + TRACE("From: %s\n", debugstr_a(message->lpOriginator->lpszAddress)); | |
| + | |
| + for (i = 0; i < message->nRecipCount; i++) | |
| + { | |
| + address = message->lpRecips[i].lpszAddress; | |
| + | |
| + if (address) | |
| + { | |
| + if (!_strnicmp(address, smtp, sizeof(smtp) - 1)) | |
| + address += sizeof(smtp) - 1; | |
| + | |
| + switch (message->lpRecips[i].ulRecipClass) | |
| + { | |
| + case MAPI_TO: | |
| + if (to_count) | |
| + lstrcatA(to, ","); | |
| + | |
| + lstrcatA(to, address); | |
| + to_count++; | |
| + break; | |
| + | |
| + case MAPI_CC: | |
| + if (cc_count) | |
| + lstrcatA(cc, ","); | |
| + | |
| + lstrcatA(cc, address); | |
| + cc_count++; | |
| + break; | |
| + | |
| + case MAPI_BCC: | |
| + if (bcc_count) | |
| + lstrcatA(bcc, ","); | |
| + | |
| + lstrcatA(bcc, address); | |
| + bcc_count++; | |
| + break; | |
| + } | |
| + } | |
| + } | |
| + ret = MAPI_E_FAILURE; | |
| + | |
| + wthunderbird = wine_get_dos_file_name("/usr/bin/thunderbird"); | |
| + if (!wthunderbird) | |
| + { | |
| + WARN("Unable to convert '/usr/bin/thunderbird' to DOS path\n"); | |
| + goto exit; | |
| + } | |
| + | |
| + WideCharToMultiByte(CP_UNIXCP, 0, wthunderbird, -1, thunderbird, MAX_PATH, NULL, NULL); | |
| + HeapFree(GetProcessHeap(), 0, wthunderbird); | |
| + | |
| + size = sizeof(format) + lstrlenA(thunderbird) + to_size + cc_size + bcc_size + subj_size + body_size + att_size; | |
| + | |
| + cmdstr = HeapAlloc(GetProcessHeap(), 0, size); | |
| + if (!cmdstr) | |
| + { | |
| + WARN("Failed to allocate memory for command buffer\n"); | |
| + goto exit; | |
| + } | |
| + | |
| + sprintf(cmdstr, format, | |
| + thunderbird, | |
| + to ? to : "", | |
| + subject, | |
| + cc ? cc : "", | |
| + bcc ? bcc : "", | |
| + body, | |
| + attachment ? attachment : ""); | |
| + | |
| + size = 1; | |
| + | |
| + TRACE("Executing thunderbird with parameters '%s'\n", debugstr_a(cmdstr)); | |
| + /* FIXME: This is 99.999999% vulnerable to command injections */ | |
| + if ((UINT_PTR) ShellExecuteA(NULL, "open", "cmd.exe", cmdstr, NULL, 0) > 32) | |
| + ret = SUCCESS_SUCCESS; | |
| + | |
| +exit: | |
| + HeapFree(GetProcessHeap(), 0, to); | |
| + HeapFree(GetProcessHeap(), 0, cc); | |
| + HeapFree(GetProcessHeap(), 0, bcc); | |
| + HeapFree(GetProcessHeap(), 0, attachment); | |
| + HeapFree(GetProcessHeap(), 0, cmdstr); | |
| + | |
| + return ret; | |
| +} | |
| + | |
| ULONG WINAPI MAPISendMail(LHANDLE session, ULONG_PTR uiparam, | |
| lpMapiMessage message, FLAGS flags, ULONG reserved) | |
| { | |
| @@ -418,7 +669,10 @@ | |
| if (send_mail_xdg(message)) | |
| return SUCCESS_SUCCESS; | |
| - return send_mail_winebrowser(message); | |
| + if (message->nFileCount) | |
| + return send_mail_thunderbird(message); | |
| + else | |
| + return send_mail_winebrowser(message); | |
| } | |
| ULONG WINAPI MAPISendDocuments(ULONG_PTR uiparam, LPSTR delim, LPSTR paths, | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment