f0fac0859e6f02c4db4e0ba19d576bbd7ea213e8
[reactos.git] / rostests / winetests / inetcomm / mimeole.c
1 /*
2 * MimeOle tests
3 *
4 * Copyright 2007 Huw Davies
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define COBJMACROS
22 #define NONAMELESSUNION
23
24 #include "initguid.h"
25 #include "windows.h"
26 #include "ole2.h"
27 #include "ocidl.h"
28
29 #include "mimeole.h"
30
31 #include <stdio.h>
32
33 #include "wine/test.h"
34
35 static const char msg1[] =
36 "MIME-Version: 1.0\r\n"
37 "Content-Type: multipart/mixed;\r\n"
38 " boundary=\"------------1.5.0.6\";\r\n"
39 " stuff=\"du;nno\";\r\n"
40 " morestuff=\"so\\\\me\\\"thing\\\"\"\r\n"
41 "foo: bar\r\n"
42 "From: Huw Davies <huw@codeweavers.com>\r\n"
43 "From: Me <xxx@codeweavers.com>\r\n"
44 "To: wine-patches <wine-patches@winehq.org>\r\n"
45 "Cc: Huw Davies <huw@codeweavers.com>,\r\n"
46 " \"Fred Bloggs\" <fred@bloggs.com>\r\n"
47 "foo: baz\r\n"
48 "bar: fum\r\n"
49 "\r\n"
50 "This is a multi-part message in MIME format.\r\n"
51 "--------------1.5.0.6\r\n"
52 "Content-Type: text/plain; format=fixed; charset=UTF-8\r\n"
53 "Content-Transfer-Encoding: 8bit\r\n"
54 "\r\n"
55 "Stuff\r\n"
56 "--------------1.5.0.6\r\n"
57 "Content-Type: text/plain; charset=\"us-ascii\"\r\n"
58 "Content-Transfer-Encoding: 7bit\r\n"
59 "\r\n"
60 "More stuff\r\n"
61 "--------------1.5.0.6--\r\n";
62
63 static void test_CreateVirtualStream(void)
64 {
65 HRESULT hr;
66 IStream *pstm;
67
68 hr = MimeOleCreateVirtualStream(&pstm);
69 ok(hr == S_OK, "ret %08x\n", hr);
70
71 IStream_Release(pstm);
72 }
73
74 static void test_CreateSecurity(void)
75 {
76 HRESULT hr;
77 IMimeSecurity *sec;
78
79 hr = MimeOleCreateSecurity(&sec);
80 ok(hr == S_OK, "ret %08x\n", hr);
81
82 IMimeSecurity_Release(sec);
83 }
84
85 static void test_CreateBody(void)
86 {
87 HRESULT hr;
88 IMimeBody *body;
89 HBODY handle = (void *)0xdeadbeef;
90 IStream *in;
91 LARGE_INTEGER off;
92 ULARGE_INTEGER pos;
93 ENCODINGTYPE enc;
94 ULONG count, found_param, i;
95 MIMEPARAMINFO *param_info;
96 IMimeAllocator *alloc;
97 BODYOFFSETS offsets;
98
99 hr = CoCreateInstance(&CLSID_IMimeBody, NULL, CLSCTX_INPROC_SERVER, &IID_IMimeBody, (void**)&body);
100 ok(hr == S_OK, "ret %08x\n", hr);
101
102 hr = IMimeBody_GetHandle(body, &handle);
103 ok(hr == MIME_E_NO_DATA, "ret %08x\n", hr);
104 ok(handle == NULL, "handle %p\n", handle);
105
106 hr = CreateStreamOnHGlobal(NULL, TRUE, &in);
107 ok(hr == S_OK, "ret %08x\n", hr);
108 IStream_Write(in, msg1, sizeof(msg1) - 1, NULL);
109 off.QuadPart = 0;
110 IStream_Seek(in, off, STREAM_SEEK_SET, NULL);
111
112 /* Need to call InitNew before Load otherwise Load crashes with native inetcomm */
113 hr = IMimeBody_InitNew(body);
114 ok(hr == S_OK, "ret %08x\n", hr);
115
116 hr = IMimeBody_GetCurrentEncoding(body, &enc);
117 ok(hr == S_OK, "ret %08x\n", hr);
118 ok(enc == IET_7BIT, "encoding %d\n", enc);
119
120 hr = IMimeBody_Load(body, in);
121 ok(hr == S_OK, "ret %08x\n", hr);
122 off.QuadPart = 0;
123 IStream_Seek(in, off, STREAM_SEEK_CUR, &pos);
124 ok(pos.u.LowPart == 359, "pos %u\n", pos.u.LowPart);
125
126 hr = IMimeBody_IsContentType(body, "multipart", "mixed");
127 ok(hr == S_OK, "ret %08x\n", hr);
128 hr = IMimeBody_IsContentType(body, "text", "plain");
129 ok(hr == S_FALSE, "ret %08x\n", hr);
130 hr = IMimeBody_IsContentType(body, NULL, "mixed");
131 ok(hr == S_OK, "ret %08x\n", hr);
132 hr = IMimeBody_IsType(body, IBT_EMPTY);
133 ok(hr == S_OK, "got %08x\n", hr);
134
135 hr = IMimeBody_SetData(body, IET_8BIT, "text", "plain", &IID_IStream, in);
136 ok(hr == S_OK, "ret %08x\n", hr);
137 hr = IMimeBody_IsContentType(body, "text", "plain");
138 todo_wine
139 ok(hr == S_OK, "ret %08x\n", hr);
140 hr = IMimeBody_GetCurrentEncoding(body, &enc);
141 ok(hr == S_OK, "ret %08x\n", hr);
142 ok(enc == IET_8BIT, "encoding %d\n", enc);
143
144 memset(&offsets, 0xcc, sizeof(offsets));
145 hr = IMimeBody_GetOffsets(body, &offsets);
146 ok(hr == MIME_E_NO_DATA, "ret %08x\n", hr);
147 ok(offsets.cbBoundaryStart == 0, "got %d\n", offsets.cbBoundaryStart);
148 ok(offsets.cbHeaderStart == 0, "got %d\n", offsets.cbHeaderStart);
149 ok(offsets.cbBodyStart == 0, "got %d\n", offsets.cbBodyStart);
150 ok(offsets.cbBodyEnd == 0, "got %d\n", offsets.cbBodyEnd);
151
152 hr = IMimeBody_IsType(body, IBT_EMPTY);
153 ok(hr == S_FALSE, "got %08x\n", hr);
154
155 hr = MimeOleGetAllocator(&alloc);
156 ok(hr == S_OK, "ret %08x\n", hr);
157
158 hr = IMimeBody_GetParameters(body, "nothere", &count, &param_info);
159 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
160 ok(count == 0, "got %d\n", count);
161 ok(!param_info, "got %p\n", param_info);
162
163 hr = IMimeBody_GetParameters(body, "bar", &count, &param_info);
164 ok(hr == S_OK, "ret %08x\n", hr);
165 ok(count == 0, "got %d\n", count);
166 ok(!param_info, "got %p\n", param_info);
167
168 hr = IMimeBody_GetParameters(body, "Content-Type", &count, &param_info);
169 ok(hr == S_OK, "ret %08x\n", hr);
170 todo_wine /* native adds a charset parameter */
171 ok(count == 4, "got %d\n", count);
172 ok(param_info != NULL, "got %p\n", param_info);
173
174 found_param = 0;
175 for(i = 0; i < count; i++)
176 {
177 if(!strcmp(param_info[i].pszName, "morestuff"))
178 {
179 found_param++;
180 ok(!strcmp(param_info[i].pszData, "so\\me\"thing\""),
181 "got %s\n", param_info[i].pszData);
182 }
183 else if(!strcmp(param_info[i].pszName, "stuff"))
184 {
185 found_param++;
186 ok(!strcmp(param_info[i].pszData, "du;nno"),
187 "got %s\n", param_info[i].pszData);
188 }
189 }
190 ok(found_param == 2, "matched %d params\n", found_param);
191
192 hr = IMimeAllocator_FreeParamInfoArray(alloc, count, param_info, TRUE);
193 ok(hr == S_OK, "ret %08x\n", hr);
194 IMimeAllocator_Release(alloc);
195
196 IStream_Release(in);
197 IMimeBody_Release(body);
198 }
199
200 static void test_Allocator(void)
201 {
202 HRESULT hr;
203 IMimeAllocator *alloc;
204
205 hr = MimeOleGetAllocator(&alloc);
206 ok(hr == S_OK, "ret %08x\n", hr);
207 IMimeAllocator_Release(alloc);
208 }
209
210 static void test_CreateMessage(void)
211 {
212 HRESULT hr;
213 IMimeMessage *msg;
214 IStream *stream;
215 LARGE_INTEGER pos;
216 LONG ref;
217 HBODY hbody;
218 IMimeBody *body;
219 BODYOFFSETS offsets;
220 ULONG count;
221 FINDBODY find_struct;
222 HCHARSET hcs;
223
224 char text[] = "text";
225 HBODY *body_list;
226 PROPVARIANT prop;
227 static const char att_pritype[] = "att:pri-content-type";
228
229 hr = MimeOleCreateMessage(NULL, &msg);
230 ok(hr == S_OK, "ret %08x\n", hr);
231
232 CreateStreamOnHGlobal(NULL, TRUE, &stream);
233 IStream_Write(stream, msg1, sizeof(msg1) - 1, NULL);
234 pos.QuadPart = 0;
235 IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
236
237 hr = IMimeMessage_Load(msg, stream);
238 ok(hr == S_OK, "ret %08x\n", hr);
239
240 hr = IMimeMessage_CountBodies(msg, HBODY_ROOT, TRUE, &count);
241 ok(hr == S_OK, "ret %08x\n", hr);
242 ok(count == 3, "got %d\n", count);
243
244 hr = IMimeMessage_CountBodies(msg, HBODY_ROOT, FALSE, &count);
245 ok(hr == S_OK, "ret %08x\n", hr);
246 ok(count == 3, "got %d\n", count);
247
248 hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body);
249 ok(hr == S_OK, "ret %08x\n", hr);
250 hr = IMimeBody_GetOffsets(body, &offsets);
251 ok(hr == S_OK, "ret %08x\n", hr);
252 ok(offsets.cbBoundaryStart == 0, "got %d\n", offsets.cbBoundaryStart);
253 ok(offsets.cbHeaderStart == 0, "got %d\n", offsets.cbHeaderStart);
254 ok(offsets.cbBodyStart == 359, "got %d\n", offsets.cbBodyStart);
255 ok(offsets.cbBodyEnd == 666, "got %d\n", offsets.cbBodyEnd);
256 IMimeBody_Release(body);
257
258 hr = IMimeMessage_GetBody(msg, IBL_ROOT, NULL, &hbody);
259 ok(hr == S_OK, "ret %08x\n", hr);
260
261 PropVariantInit(&prop);
262 hr = IMimeMessage_GetBodyProp(msg, hbody, att_pritype, 0, &prop);
263 ok(hr == S_OK, "ret %08x\n", hr);
264 ok(prop.vt == VT_LPSTR, "vt %08x\n", prop.vt);
265 ok(!strcasecmp(prop.u.pszVal, "multipart"), "got %s\n", prop.u.pszVal);
266 PropVariantClear(&prop);
267
268 hr = IMimeMessage_GetBody(msg, IBL_FIRST, hbody, &hbody);
269 ok(hr == S_OK, "ret %08x\n", hr);
270 hr = IMimeMessage_BindToObject(msg, hbody, &IID_IMimeBody, (void**)&body);
271 ok(hr == S_OK, "ret %08x\n", hr);
272 hr = IMimeBody_GetOffsets(body, &offsets);
273 ok(hr == S_OK, "ret %08x\n", hr);
274 ok(offsets.cbBoundaryStart == 405, "got %d\n", offsets.cbBoundaryStart);
275 ok(offsets.cbHeaderStart == 428, "got %d\n", offsets.cbHeaderStart);
276 ok(offsets.cbBodyStart == 518, "got %d\n", offsets.cbBodyStart);
277 ok(offsets.cbBodyEnd == 523, "got %d\n", offsets.cbBodyEnd);
278
279 hr = IMimeBody_GetCharset(body, &hcs);
280 ok(hr == S_OK, "ret %08x\n", hr);
281 todo_wine
282 {
283 ok(hcs != NULL, "Expected non-NULL charset\n");
284 }
285
286 IMimeBody_Release(body);
287
288 hr = IMimeMessage_GetBody(msg, IBL_NEXT, hbody, &hbody);
289 ok(hr == S_OK, "ret %08x\n", hr);
290 hr = IMimeMessage_BindToObject(msg, hbody, &IID_IMimeBody, (void**)&body);
291 ok(hr == S_OK, "ret %08x\n", hr);
292 hr = IMimeBody_GetOffsets(body, &offsets);
293 ok(hr == S_OK, "ret %08x\n", hr);
294 ok(offsets.cbBoundaryStart == 525, "got %d\n", offsets.cbBoundaryStart);
295 ok(offsets.cbHeaderStart == 548, "got %d\n", offsets.cbHeaderStart);
296 ok(offsets.cbBodyStart == 629, "got %d\n", offsets.cbBodyStart);
297 ok(offsets.cbBodyEnd == 639, "got %d\n", offsets.cbBodyEnd);
298 IMimeBody_Release(body);
299
300 find_struct.pszPriType = text;
301 find_struct.pszSubType = NULL;
302
303 hr = IMimeMessage_FindFirst(msg, &find_struct, &hbody);
304 ok(hr == S_OK, "ret %08x\n", hr);
305
306 hr = IMimeMessage_FindNext(msg, &find_struct, &hbody);
307 ok(hr == S_OK, "ret %08x\n", hr);
308
309 hr = IMimeMessage_FindNext(msg, &find_struct, &hbody);
310 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
311
312 hr = IMimeMessage_GetAttachments(msg, &count, &body_list);
313 ok(hr == S_OK, "ret %08x\n", hr);
314 ok(count == 2, "got %d\n", count);
315 CoTaskMemFree(body_list);
316
317 hr = IMimeBody_GetCharset(body, &hcs);
318 ok(hr == S_OK, "ret %08x\n", hr);
319 todo_wine
320 {
321 ok(hcs != NULL, "Expected non-NULL charset\n");
322 }
323
324 IMimeMessage_Release(msg);
325
326 ref = IStream_AddRef(stream);
327 ok(ref == 2 ||
328 broken(ref == 1), /* win95 */
329 "ref %d\n", ref);
330 IStream_Release(stream);
331
332 IStream_Release(stream);
333 }
334
335 static void test_MessageSetProp(void)
336 {
337 static const char topic[] = "wine topic";
338 HRESULT hr;
339 IMimeMessage *msg;
340 IMimeBody *body;
341 PROPVARIANT prop;
342
343 hr = MimeOleCreateMessage(NULL, &msg);
344 ok(hr == S_OK, "ret %08x\n", hr);
345
346 PropVariantInit(&prop);
347
348 hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body);
349 ok(hr == S_OK, "ret %08x\n", hr);
350
351 hr = IMimeBody_SetProp(body, NULL, 0, &prop);
352 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
353
354 hr = IMimeBody_SetProp(body, "Thread-Topic", 0, NULL);
355 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
356
357 prop.vt = VT_LPSTR;
358 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1);
359 strcpy(prop.u.pszVal, topic);
360 hr = IMimeBody_SetProp(body, "Thread-Topic", 0, &prop);
361 ok(hr == S_OK, "ret %08x\n", hr);
362 PropVariantClear(&prop);
363
364 hr = IMimeBody_GetProp(body, NULL, 0, &prop);
365 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
366
367 hr = IMimeBody_GetProp(body, "Thread-Topic", 0, NULL);
368 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
369
370 hr = IMimeBody_GetProp(body, "Wine-Topic", 0, &prop);
371 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
372
373 hr = IMimeBody_GetProp(body, "Thread-Topic", 0, &prop);
374 ok(hr == S_OK, "ret %08x\n", hr);
375 if(hr == S_OK)
376 {
377 ok(prop.vt == VT_LPSTR, "type %d\n", prop.vt);
378 ok(!strcmp(prop.u.pszVal, topic), "got %s\n", prop.u.pszVal);
379 PropVariantClear(&prop);
380 }
381
382 IMimeBody_Release(body);
383 IMimeMessage_Release(msg);
384 }
385
386 static void test_MessageOptions(void)
387 {
388 static const char string[] = "XXXXX";
389 static const char zero[] = "0";
390 HRESULT hr;
391 IMimeMessage *msg;
392 PROPVARIANT prop;
393
394 hr = MimeOleCreateMessage(NULL, &msg);
395 ok(hr == S_OK, "ret %08x\n", hr);
396
397 PropVariantInit(&prop);
398
399 prop.vt = VT_BOOL;
400 prop.u.boolVal = TRUE;
401 hr = IMimeMessage_SetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
402 ok(hr == S_OK, "ret %08x\n", hr);
403 PropVariantClear(&prop);
404
405 hr = IMimeMessage_GetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
406 todo_wine ok(hr == S_OK, "ret %08x\n", hr);
407 todo_wine ok(prop.vt == VT_BOOL, "vt %08x\n", prop.vt);
408 todo_wine ok(prop.u.boolVal == TRUE, "Hide Attachments got %d\n", prop.u.boolVal);
409 PropVariantClear(&prop);
410
411 prop.vt = VT_LPSTR;
412 prop.u.pszVal = CoTaskMemAlloc(strlen(string)+1);
413 strcpy(prop.u.pszVal, string);
414 hr = IMimeMessage_SetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
415 ok(hr == S_OK, "ret %08x\n", hr);
416 PropVariantClear(&prop);
417
418 hr = IMimeMessage_GetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
419 todo_wine ok(hr == S_OK, "ret %08x\n", hr);
420 todo_wine ok(prop.vt == VT_BOOL, "vt %08x\n", prop.vt);
421 todo_wine ok(prop.u.boolVal == TRUE, "Hide Attachments got %d\n", prop.u.boolVal);
422 PropVariantClear(&prop);
423
424 /* Invalid property type doesn't change the value */
425 prop.vt = VT_LPSTR;
426 prop.u.pszVal = CoTaskMemAlloc(strlen(zero)+1);
427 strcpy(prop.u.pszVal, zero);
428 hr = IMimeMessage_SetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
429 ok(hr == S_OK, "ret %08x\n", hr);
430 PropVariantClear(&prop);
431
432 hr = IMimeMessage_GetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
433 todo_wine ok(hr == S_OK, "ret %08x\n", hr);
434 todo_wine ok(prop.vt == VT_BOOL, "vt %08x\n", prop.vt);
435 todo_wine ok(prop.u.boolVal == TRUE, "Hide Attachments got %d\n", prop.u.boolVal);
436 PropVariantClear(&prop);
437
438 /* Invalid OID */
439 prop.vt = VT_BOOL;
440 prop.u.boolVal = TRUE;
441 hr = IMimeMessage_SetOption(msg, 0xff00000a, &prop);
442 ok(hr == MIME_E_INVALID_OPTION_ID, "ret %08x\n", hr);
443 PropVariantClear(&prop);
444
445 /* Out of range before type. */
446 prop.vt = VT_I4;
447 prop.u.lVal = 1;
448 hr = IMimeMessage_SetOption(msg, 0xff00000a, &prop);
449 ok(hr == MIME_E_INVALID_OPTION_ID, "ret %08x\n", hr);
450 PropVariantClear(&prop);
451
452 IMimeMessage_Release(msg);
453 }
454
455 static void test_BindToObject(void)
456 {
457 HRESULT hr;
458 IMimeMessage *msg;
459 IMimeBody *body;
460 ULONG count;
461
462 hr = MimeOleCreateMessage(NULL, &msg);
463 ok(hr == S_OK, "ret %08x\n", hr);
464
465 hr = IMimeMessage_CountBodies(msg, HBODY_ROOT, TRUE, &count);
466 ok(hr == S_OK, "ret %08x\n", hr);
467 ok(count == 1, "got %d\n", count);
468
469 hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body);
470 ok(hr == S_OK, "ret %08x\n", hr);
471 IMimeBody_Release(body);
472
473 IMimeMessage_Release(msg);
474 }
475
476 static void test_MimeOleGetPropertySchema(void)
477 {
478 HRESULT hr;
479 IMimePropertySchema *schema = NULL;
480
481 hr = MimeOleGetPropertySchema(&schema);
482 ok(hr == S_OK, "ret %08x\n", hr);
483
484 IMimePropertySchema_Release(schema);
485 }
486
487 START_TEST(mimeole)
488 {
489 OleInitialize(NULL);
490 test_CreateVirtualStream();
491 test_CreateSecurity();
492 test_CreateBody();
493 test_Allocator();
494 test_CreateMessage();
495 test_MessageSetProp();
496 test_MessageOptions();
497 test_BindToObject();
498 test_MimeOleGetPropertySchema();
499 OleUninitialize();
500 }