gdi32: GetCharABCWidthsFloatW must succeed with non-TrueType fonts.
[wine] / dlls / winemapi / sendmail.c
1 /*
2  * MAPISendMail implementation
3  *
4  * Copyright 2005 Hans Leidekker
5  * Copyright 2009 Owen Rudge for CodeWeavers
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <stdio.h>
26 #include <stdarg.h>
27
28 #define COBJMACROS
29
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winerror.h"
33 #include "mapi.h"
34 #include "winreg.h"
35 #include "shellapi.h"
36 #include "shlwapi.h"
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(winemapi);
40
41 /* Escapes a string for use in mailto: URL */
42 static char *escape_string(char *in, char *empty_string)
43 {
44     HRESULT res;
45     DWORD size;
46     char *escaped = NULL;
47
48     if (!in)
49         return empty_string;
50
51     size = 1;
52     res = UrlEscapeA(in, empty_string, &size, URL_ESCAPE_PERCENT | URL_ESCAPE_SEGMENT_ONLY);
53
54     if (res == E_POINTER)
55     {
56         escaped = HeapAlloc(GetProcessHeap(), 0, size);
57
58         if (!escaped)
59             return in;
60
61         /* If for some reason UrlEscape fails, just send the original text */
62         if (UrlEscapeA(in, escaped, &size, URL_ESCAPE_PERCENT | URL_ESCAPE_SEGMENT_ONLY) != S_OK)
63         {
64             HeapFree(GetProcessHeap(), 0, escaped);
65             escaped = in;
66         }
67     }
68
69     return escaped ? escaped : empty_string;
70 }
71
72 /**************************************************************************
73  *  MAPISendMail
74  *
75  * Send a message using a native mail client.
76  *
77  * PARAMS
78  *  session  [I] Handle to a MAPI session.
79  *  uiparam  [I] Parent window handle.
80  *  message  [I] Pointer to a MAPIMessage structure.
81  *  flags    [I] Flags.
82  *  reserved [I] Reserved, pass 0.
83  *
84  * RETURNS
85  *  Success: SUCCESS_SUCCESS
86  *  Failure: MAPI_E_FAILURE
87  *
88  */
89 ULONG WINAPI MAPISendMail(LHANDLE session, ULONG_PTR uiparam,
90     lpMapiMessage message, FLAGS flags, ULONG reserved)
91 {
92     ULONG ret = MAPI_E_FAILURE;
93     unsigned int i, to_count = 0, cc_count = 0, bcc_count = 0;
94     unsigned int to_size = 0, cc_size = 0, bcc_size = 0, subj_size, body_size;
95
96     char *to = NULL, *cc = NULL, *bcc = NULL, *subject = NULL, *body = NULL;
97     const char *address;
98     static const char format[] =
99         "mailto:\"%s\"?subject=\"%s\"&cc=\"%s\"&bcc=\"%s\"&body=\"%s\"";
100     static const char smtp[] = "smtp:";
101     char *mailto = NULL, *escape = NULL;
102     char empty_string[] = "";
103     HRESULT res;
104     DWORD size;
105
106     TRACE("(0x%08lx 0x%08lx %p 0x%08x 0x%08x)\n", session, uiparam,
107            message, flags, reserved);
108
109     if (!message)
110         return MAPI_E_FAILURE;
111
112     for (i = 0; i < message->nRecipCount; i++)
113     {
114         if (!message->lpRecips)
115         {
116             WARN("No recipients found\n");
117             return MAPI_E_FAILURE;
118         }
119
120         address = message->lpRecips[i].lpszAddress;
121
122         if (address)
123         {
124             if (!strncasecmp(address, smtp, sizeof(smtp) - 1))
125                 address += sizeof(smtp) - 1;
126
127             switch (message->lpRecips[i].ulRecipClass)
128             {
129                 case MAPI_ORIG:
130                     TRACE("From: %s\n", debugstr_a(address));
131                     break;
132
133                 case MAPI_TO:
134                     TRACE("To: %s\n", debugstr_a(address));
135                     to_size += lstrlenA(address) + 1;
136                     break;
137
138                 case MAPI_CC:
139                     TRACE("Cc: %s\n", debugstr_a(address));
140                     cc_size += lstrlenA(address) + 1;
141                     break;
142
143                 case MAPI_BCC:
144                     TRACE("Bcc: %s\n", debugstr_a(address));
145                     bcc_size += lstrlenA(address) + 1;
146                     break;
147
148                 default:
149                     TRACE("Unknown recipient class: %d\n",
150                            message->lpRecips[i].ulRecipClass);
151             }
152         }
153         else
154             FIXME("Name resolution and entry identifiers not supported\n");
155     }
156
157     if (message->nFileCount)
158         FIXME("Ignoring attachments\n");
159
160     /* Escape subject and body */
161     subject = escape_string(message->lpszSubject, empty_string);
162     body = escape_string(message->lpszNoteText, empty_string);
163
164     TRACE("Subject: %s\n", debugstr_a(subject));
165     TRACE("Body: %s\n", debugstr_a(body));
166
167     subj_size = lstrlenA(subject);
168     body_size = lstrlenA(body);
169
170     ret = MAPI_E_INSUFFICIENT_MEMORY;
171
172     if (to_size)
173     {
174         to = HeapAlloc(GetProcessHeap(), 0, to_size);
175
176         if (!to)
177             goto exit;
178
179         to[0] = 0;
180     }
181
182     if (cc_size)
183     {
184         cc = HeapAlloc(GetProcessHeap(), 0, cc_size);
185
186         if (!cc)
187             goto exit;
188
189         cc[0] = 0;
190     }
191
192     if (bcc_size)
193     {
194         bcc = HeapAlloc(GetProcessHeap(), 0, bcc_size);
195
196         if (!bcc)
197             goto exit;
198
199         bcc[0] = 0;
200     }
201
202     if (message->lpOriginator)
203         TRACE("From: %s\n", debugstr_a(message->lpOriginator->lpszAddress));
204
205     for (i = 0; i < message->nRecipCount; i++)
206     {
207         address = message->lpRecips[i].lpszAddress;
208
209         if (address)
210         {
211             if (!strncasecmp(address, smtp, sizeof(smtp) - 1))
212                 address += sizeof(smtp) - 1;
213
214             switch (message->lpRecips[i].ulRecipClass)
215             {
216                 case MAPI_TO:
217                     if (to_count)
218                         lstrcatA(to, ",");
219
220                     lstrcatA(to, address);
221                     to_count++;
222                     break;
223
224                 case MAPI_CC:
225                     if (cc_count)
226                         lstrcatA(cc, ",");
227
228                     lstrcatA(cc, address);
229                     cc_count++;
230                     break;
231
232                 case MAPI_BCC:
233                     if (bcc_count)
234                         lstrcatA(bcc, ",");
235
236                     lstrcatA(bcc, address);
237                     bcc_count++;
238                     break;
239             }
240         }
241     }
242     ret = MAPI_E_FAILURE;
243     size = sizeof(format) + to_size + cc_size + bcc_size + subj_size + body_size;
244
245     mailto = HeapAlloc(GetProcessHeap(), 0, size);
246
247     if (!mailto)
248         goto exit;
249
250     sprintf(mailto, format, to ? to : "", subject, cc ? cc : "", bcc ? bcc : "", body);
251
252     size = 1;
253     res = UrlEscapeA(mailto, empty_string, &size, URL_ESCAPE_SPACES_ONLY);
254
255     if (res != E_POINTER)
256         goto exit;
257
258     escape = HeapAlloc(GetProcessHeap(), 0, size);
259
260     if (!escape)
261         goto exit;
262
263     res = UrlEscapeA(mailto, escape, &size, URL_ESCAPE_SPACES_ONLY);
264
265     if (res != S_OK)
266         goto exit;
267
268     TRACE("Executing winebrowser.exe with parameters '%s'\n", debugstr_a(escape));
269
270     if ((UINT_PTR) ShellExecuteA(NULL, "open", "winebrowser.exe", escape, NULL, 0) > 32)
271         ret = SUCCESS_SUCCESS;
272
273 exit:
274     HeapFree(GetProcessHeap(), 0, to);
275     HeapFree(GetProcessHeap(), 0, cc);
276     HeapFree(GetProcessHeap(), 0, bcc);
277     HeapFree(GetProcessHeap(), 0, mailto);
278     HeapFree(GetProcessHeap(), 0, escape);
279
280     if (subject != empty_string)
281         HeapFree(GetProcessHeap(), 0, subject);
282
283     if (body != empty_string)
284         HeapFree(GetProcessHeap(), 0, body);
285
286     return ret;
287 }
288
289 ULONG WINAPI MAPISendDocuments(ULONG_PTR uiparam, LPSTR delim, LPSTR paths,
290     LPSTR filenames, ULONG reserved)
291 {
292     return MAPI_E_NOT_SUPPORTED;
293 }