ce1e4af5a71e0e3d73814ff6aa7e6934a8bebe91
[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, hbody2;
218 IMimeBody *body;
219 BODYOFFSETS offsets;
220 ULONG count;
221 FINDBODY find_struct;
222 HCHARSET hcs;
223 HBODY handle = NULL;
224
225 char text[] = "text";
226 HBODY *body_list;
227 PROPVARIANT prop;
228 static const char att_pritype[] = "att:pri-content-type";
229
230 hr = MimeOleCreateMessage(NULL, &msg);
231 ok(hr == S_OK, "ret %08x\n", hr);
232
233 CreateStreamOnHGlobal(NULL, TRUE, &stream);
234 IStream_Write(stream, msg1, sizeof(msg1) - 1, NULL);
235 pos.QuadPart = 0;
236 IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
237
238 hr = IMimeMessage_Load(msg, stream);
239 ok(hr == S_OK, "ret %08x\n", hr);
240
241 hr = IMimeMessage_CountBodies(msg, HBODY_ROOT, TRUE, &count);
242 ok(hr == S_OK, "ret %08x\n", hr);
243 ok(count == 3, "got %d\n", count);
244
245 hr = IMimeMessage_CountBodies(msg, HBODY_ROOT, FALSE, &count);
246 ok(hr == S_OK, "ret %08x\n", hr);
247 ok(count == 3, "got %d\n", count);
248
249 hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body);
250 ok(hr == S_OK, "ret %08x\n", hr);
251 hr = IMimeBody_GetOffsets(body, &offsets);
252 ok(hr == S_OK, "ret %08x\n", hr);
253 ok(offsets.cbBoundaryStart == 0, "got %d\n", offsets.cbBoundaryStart);
254 ok(offsets.cbHeaderStart == 0, "got %d\n", offsets.cbHeaderStart);
255 ok(offsets.cbBodyStart == 359, "got %d\n", offsets.cbBodyStart);
256 ok(offsets.cbBodyEnd == 666, "got %d\n", offsets.cbBodyEnd);
257 IMimeBody_Release(body);
258
259 hr = IMimeMessage_GetBody(msg, IBL_ROOT, NULL, &hbody);
260 ok(hr == S_OK, "ret %08x\n", hr);
261
262 hr = IMimeBody_GetHandle(body, NULL);
263 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
264
265 hr = IMimeBody_GetHandle(body, &handle);
266 ok(hr == S_OK, "ret %08x\n", hr);
267 ok(handle != NULL, "handle %p\n", handle);
268
269 hr = IMimeMessage_GetBody(msg, IBL_PARENT, hbody, NULL);
270 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
271
272 hbody2 = (HBODY)0xdeadbeef;
273 hr = IMimeMessage_GetBody(msg, IBL_PARENT, hbody, &hbody2);
274 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
275 ok(hbody2 == NULL, "hbody2 %p\n", hbody2);
276
277 PropVariantInit(&prop);
278 hr = IMimeMessage_GetBodyProp(msg, hbody, att_pritype, 0, &prop);
279 ok(hr == S_OK, "ret %08x\n", hr);
280 ok(prop.vt == VT_LPSTR, "vt %08x\n", prop.vt);
281 ok(!strcasecmp(prop.u.pszVal, "multipart"), "got %s\n", prop.u.pszVal);
282 PropVariantClear(&prop);
283
284 hr = IMimeMessage_GetBody(msg, IBL_FIRST, hbody, &hbody);
285 ok(hr == S_OK, "ret %08x\n", hr);
286 hr = IMimeMessage_BindToObject(msg, hbody, &IID_IMimeBody, (void**)&body);
287 ok(hr == S_OK, "ret %08x\n", hr);
288
289 hr = IMimeBody_GetHandle(body, &handle);
290 ok(hr == S_OK, "ret %08x\n", hr);
291 ok(handle == hbody, "handle %p\n", handle);
292
293 hr = IMimeBody_GetOffsets(body, &offsets);
294 ok(hr == S_OK, "ret %08x\n", hr);
295 ok(offsets.cbBoundaryStart == 405, "got %d\n", offsets.cbBoundaryStart);
296 ok(offsets.cbHeaderStart == 428, "got %d\n", offsets.cbHeaderStart);
297 ok(offsets.cbBodyStart == 518, "got %d\n", offsets.cbBodyStart);
298 ok(offsets.cbBodyEnd == 523, "got %d\n", offsets.cbBodyEnd);
299
300 hr = IMimeBody_GetCharset(body, &hcs);
301 ok(hr == S_OK, "ret %08x\n", hr);
302 todo_wine
303 {
304 ok(hcs != NULL, "Expected non-NULL charset\n");
305 }
306
307 IMimeBody_Release(body);
308
309 hr = IMimeMessage_GetBody(msg, IBL_NEXT, hbody, &hbody);
310 ok(hr == S_OK, "ret %08x\n", hr);
311 hr = IMimeMessage_BindToObject(msg, hbody, &IID_IMimeBody, (void**)&body);
312 ok(hr == S_OK, "ret %08x\n", hr);
313
314 hr = IMimeBody_GetHandle(body, &handle);
315 ok(hr == S_OK, "ret %08x\n", hr);
316 ok(handle == hbody, "handle %p\n", handle);
317
318 hr = IMimeBody_GetOffsets(body, &offsets);
319 ok(hr == S_OK, "ret %08x\n", hr);
320 ok(offsets.cbBoundaryStart == 525, "got %d\n", offsets.cbBoundaryStart);
321 ok(offsets.cbHeaderStart == 548, "got %d\n", offsets.cbHeaderStart);
322 ok(offsets.cbBodyStart == 629, "got %d\n", offsets.cbBodyStart);
323 ok(offsets.cbBodyEnd == 639, "got %d\n", offsets.cbBodyEnd);
324 IMimeBody_Release(body);
325
326 find_struct.pszPriType = text;
327 find_struct.pszSubType = NULL;
328
329 hr = IMimeMessage_FindFirst(msg, &find_struct, &hbody);
330 ok(hr == S_OK, "ret %08x\n", hr);
331
332 hr = IMimeMessage_FindNext(msg, &find_struct, &hbody);
333 ok(hr == S_OK, "ret %08x\n", hr);
334
335 hr = IMimeMessage_FindNext(msg, &find_struct, &hbody);
336 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
337
338 hr = IMimeMessage_GetAttachments(msg, &count, &body_list);
339 ok(hr == S_OK, "ret %08x\n", hr);
340 ok(count == 2, "got %d\n", count);
341 if(count == 2)
342 {
343 ENCODINGTYPE encoding;
344 IMimeBody *attachment;
345 PROPVARIANT prop;
346
347 PropVariantInit(&prop);
348
349 hr = IMimeMessage_BindToObject(msg, body_list[0], &IID_IMimeBody, (void**)&attachment);
350 ok(hr == S_OK, "ret %08x\n", hr);
351
352 hr = IMimeBody_IsContentType(attachment, "multipart", NULL);
353 ok(hr == S_FALSE, "ret %08x\n", hr);
354
355 hr = IMimeBody_GetCurrentEncoding(attachment, &encoding);
356 ok(hr == S_OK, "ret %08x\n", hr);
357 todo_wine ok(encoding == IET_8BIT, "ret %d\n", encoding);
358
359 prop.vt = VT_LPSTR;
360 hr = IMimeBody_GetProp(attachment, "Content-Transfer-Encoding", 0, &prop);
361 ok(hr == S_OK, "ret %08x\n", hr);
362
363 ok(prop.vt == VT_LPSTR, "type %d\n", prop.vt);
364 ok(!strcmp(prop.u.pszVal, "8bit"), "got %s\n", prop.u.pszVal);
365 PropVariantClear(&prop);
366
367 hr = IMimeBody_IsType(attachment, IBT_ATTACHMENT);
368 todo_wine ok(hr == S_FALSE, "ret %08x\n", hr);
369
370 IMimeBody_Release(attachment);
371
372 hr = IMimeMessage_BindToObject(msg, body_list[1], &IID_IMimeBody, (void**)&attachment);
373 ok(hr == S_OK, "ret %08x\n", hr);
374
375 hr = IMimeBody_IsContentType(attachment, "multipart", NULL);
376 ok(hr == S_FALSE, "ret %08x\n", hr);
377
378 hr = IMimeBody_GetCurrentEncoding(attachment, &encoding);
379 ok(hr == S_OK, "ret %08x\n", hr);
380 todo_wine ok(encoding == IET_7BIT, "ret %d\n", encoding);
381
382 prop.vt = VT_LPSTR;
383 hr = IMimeBody_GetProp(attachment, "Content-Transfer-Encoding", 0, &prop);
384 ok(hr == S_OK, "ret %08x\n", hr);
385 ok(prop.vt == VT_LPSTR, "type %d\n", prop.vt);
386 ok(!strcmp(prop.u.pszVal, "7bit"), "got %s\n", prop.u.pszVal);
387 PropVariantClear(&prop);
388
389 hr = IMimeBody_IsType(attachment, IBT_ATTACHMENT);
390 ok(hr == S_OK, "ret %08x\n", hr);
391
392 IMimeBody_Release(attachment);
393 }
394 CoTaskMemFree(body_list);
395
396 hr = IMimeBody_GetCharset(body, &hcs);
397 ok(hr == S_OK, "ret %08x\n", hr);
398 todo_wine
399 {
400 ok(hcs != NULL, "Expected non-NULL charset\n");
401 }
402
403 IMimeMessage_Release(msg);
404
405 ref = IStream_AddRef(stream);
406 ok(ref == 2 ||
407 broken(ref == 1), /* win95 */
408 "ref %d\n", ref);
409 IStream_Release(stream);
410
411 IStream_Release(stream);
412 }
413
414 static void test_MessageSetProp(void)
415 {
416 static const char topic[] = "wine topic";
417 static const WCHAR topicW[] = {'w','i','n','e',' ','t','o','p','i','c',0};
418 HRESULT hr;
419 IMimeMessage *msg;
420 IMimeBody *body;
421 PROPVARIANT prop;
422
423 hr = MimeOleCreateMessage(NULL, &msg);
424 ok(hr == S_OK, "ret %08x\n", hr);
425
426 PropVariantInit(&prop);
427
428 hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body);
429 ok(hr == S_OK, "ret %08x\n", hr);
430
431 hr = IMimeBody_SetProp(body, NULL, 0, &prop);
432 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
433
434 hr = IMimeBody_SetProp(body, "Thread-Topic", 0, NULL);
435 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
436
437 prop.vt = VT_LPSTR;
438 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1);
439 strcpy(prop.u.pszVal, topic);
440 hr = IMimeBody_SetProp(body, "Thread-Topic", 0, &prop);
441 ok(hr == S_OK, "ret %08x\n", hr);
442 PropVariantClear(&prop);
443
444 hr = IMimeBody_GetProp(body, NULL, 0, &prop);
445 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
446
447 hr = IMimeBody_GetProp(body, "Thread-Topic", 0, NULL);
448 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
449
450 hr = IMimeBody_GetProp(body, "Wine-Topic", 0, &prop);
451 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
452
453 prop.vt = VT_LPSTR;
454 hr = IMimeBody_GetProp(body, "Thread-Topic", 0, &prop);
455 ok(hr == S_OK, "ret %08x\n", hr);
456 if(hr == S_OK)
457 {
458 ok(prop.vt == VT_LPSTR, "type %d\n", prop.vt);
459 ok(!strcmp(prop.u.pszVal, topic), "got %s\n", prop.u.pszVal);
460 PropVariantClear(&prop);
461 }
462
463 prop.vt = VT_LPSTR;
464 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1);
465 strcpy(prop.u.pszVal, topic);
466 hr = IMimeBody_SetProp(body, PIDTOSTR(PID_HDR_SUBJECT), 0, &prop);
467 ok(hr == S_OK, "ret %08x\n", hr);
468 PropVariantClear(&prop);
469
470 prop.vt = VT_LPSTR;
471 hr = IMimeBody_GetProp(body, PIDTOSTR(PID_HDR_SUBJECT), 0, &prop);
472 ok(hr == S_OK, "ret %08x\n", hr);
473 if(hr == S_OK)
474 {
475 ok(prop.vt == VT_LPSTR, "type %d\n", prop.vt);
476 ok(!strcmp(prop.u.pszVal, topic), "got %s\n", prop.u.pszVal);
477 PropVariantClear(&prop);
478 }
479
480 /* Using the name or PID returns the same result. */
481 prop.vt = VT_LPSTR;
482 hr = IMimeBody_GetProp(body, "Subject", 0, &prop);
483 ok(hr == S_OK, "ret %08x\n", hr);
484 if(hr == S_OK)
485 {
486 ok(prop.vt == VT_LPSTR, "type %d\n", prop.vt);
487 ok(!strcmp(prop.u.pszVal, topic), "got %s\n", prop.u.pszVal);
488 PropVariantClear(&prop);
489 }
490
491 prop.vt = VT_LPWSTR;
492 hr = IMimeBody_GetProp(body, "Subject", 0, &prop);
493 ok(hr == S_OK, "ret %08x\n", hr);
494 if(hr == S_OK)
495 {
496 ok(prop.vt == VT_LPWSTR, "type %d\n", prop.vt);
497 ok(!lstrcmpW(prop.u.pwszVal, topicW), "got %s\n", wine_dbgstr_w(prop.u.pwszVal));
498 PropVariantClear(&prop);
499 }
500
501 prop.vt = VT_LPSTR;
502 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1);
503 strcpy(prop.u.pszVal, topic);
504 hr = IMimeBody_SetProp(body, PIDTOSTR(PID_HDR_TO), 0, &prop);
505 ok(hr == S_OK, "ret %08x\n", hr);
506 PropVariantClear(&prop);
507
508 /* Out of Range PID */
509 prop.vt = VT_LPSTR;
510 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1);
511 strcpy(prop.u.pszVal, topic);
512 hr = IMimeBody_SetProp(body, PIDTOSTR(124), 0, &prop);
513 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
514 PropVariantClear(&prop);
515
516 IMimeBody_Release(body);
517 IMimeMessage_Release(msg);
518 }
519
520 static void test_MessageGetPropInfo(void)
521 {
522 static const char topic[] = "wine topic";
523 static const char subject[] = "wine testing";
524 HRESULT hr;
525 IMimeMessage *msg;
526 IMimeBody *body;
527 PROPVARIANT prop;
528 MIMEPROPINFO info;
529
530 hr = MimeOleCreateMessage(NULL, &msg);
531 ok(hr == S_OK, "ret %08x\n", hr);
532
533 PropVariantInit(&prop);
534
535 hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body);
536 ok(hr == S_OK, "ret %08x\n", hr);
537
538 prop.vt = VT_LPSTR;
539 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1);
540 strcpy(prop.u.pszVal, topic);
541 hr = IMimeBody_SetProp(body, "Thread-Topic", 0, &prop);
542 ok(hr == S_OK, "ret %08x\n", hr);
543 PropVariantClear(&prop);
544
545 prop.vt = VT_LPSTR;
546 prop.u.pszVal = CoTaskMemAlloc(strlen(subject)+1);
547 strcpy(prop.u.pszVal, subject);
548 hr = IMimeBody_SetProp(body, PIDTOSTR(PID_HDR_SUBJECT), 0, &prop);
549 ok(hr == S_OK, "ret %08x\n", hr);
550 PropVariantClear(&prop);
551
552 memset(&info, 0, sizeof(info));
553 info.dwMask = PIM_ENCODINGTYPE | PIM_FLAGS | PIM_PROPID;
554 hr = IMimeBody_GetPropInfo(body, NULL, &info);
555 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
556
557 memset(&info, 0, sizeof(info));
558 info.dwMask = PIM_ENCODINGTYPE | PIM_FLAGS | PIM_PROPID;
559 hr = IMimeBody_GetPropInfo(body, "Subject", NULL);
560 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
561
562 memset(&info, 0xfe, sizeof(info));
563 info.dwMask = PIM_ENCODINGTYPE | PIM_FLAGS | PIM_PROPID;
564 hr = IMimeBody_GetPropInfo(body, "Subject", &info);
565 ok(hr == S_OK, "ret %08x\n", hr);
566 if(hr == S_OK)
567 {
568 ok(info.dwMask & (PIM_ENCODINGTYPE | PIM_FLAGS| PIM_PROPID), "Invalid mask 0x%08x\n", info.dwFlags);
569 todo_wine ok(info.dwFlags & 0x10000000, "Invalid flags 0x%08x\n", info.dwFlags);
570 ok(info.ietEncoding == 0, "Invalid encoding %d\n", info.ietEncoding);
571 ok(info.dwPropId == PID_HDR_SUBJECT, "Invalid propid %d\n", info.dwPropId);
572 ok(info.cValues == 0xfefefefe, "Invalid cValues %d\n", info.cValues);
573 }
574
575 memset(&info, 0xfe, sizeof(info));
576 info.dwMask = 0;
577 hr = IMimeBody_GetPropInfo(body, "Subject", &info);
578 ok(hr == S_OK, "ret %08x\n", hr);
579 if(hr == S_OK)
580 {
581 ok(info.dwMask == 0, "Invalid mask 0x%08x\n", info.dwFlags);
582 ok(info.dwFlags == 0xfefefefe, "Invalid flags 0x%08x\n", info.dwFlags);
583 ok(info.ietEncoding == -16843010, "Invalid encoding %d\n", info.ietEncoding);
584 ok(info.dwPropId == -16843010, "Invalid propid %d\n", info.dwPropId);
585 }
586
587 memset(&info, 0xfe, sizeof(info));
588 info.dwMask = 0;
589 info.dwPropId = 1024;
590 info.ietEncoding = 99;
591 hr = IMimeBody_GetPropInfo(body, "Subject", &info);
592 ok(hr == S_OK, "ret %08x\n", hr);
593 if(hr == S_OK)
594 {
595 ok(info.dwMask == 0, "Invalid mask 0x%08x\n", info.dwFlags);
596 ok(info.dwFlags == 0xfefefefe, "Invalid flags 0x%08x\n", info.dwFlags);
597 ok(info.ietEncoding == 99, "Invalid encoding %d\n", info.ietEncoding);
598 ok(info.dwPropId == 1024, "Invalid propid %d\n", info.dwPropId);
599 }
600
601 memset(&info, 0, sizeof(info));
602 info.dwMask = PIM_ENCODINGTYPE | PIM_FLAGS | PIM_PROPID;
603 hr = IMimeBody_GetPropInfo(body, "Invalid Property", &info);
604 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
605
606 IMimeBody_Release(body);
607 IMimeMessage_Release(msg);
608 }
609
610 static void test_MessageOptions(void)
611 {
612 static const char string[] = "XXXXX";
613 static const char zero[] = "0";
614 HRESULT hr;
615 IMimeMessage *msg;
616 PROPVARIANT prop;
617
618 hr = MimeOleCreateMessage(NULL, &msg);
619 ok(hr == S_OK, "ret %08x\n", hr);
620
621 PropVariantInit(&prop);
622
623 prop.vt = VT_BOOL;
624 prop.u.boolVal = TRUE;
625 hr = IMimeMessage_SetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
626 ok(hr == S_OK, "ret %08x\n", hr);
627 PropVariantClear(&prop);
628
629 hr = IMimeMessage_GetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
630 todo_wine ok(hr == S_OK, "ret %08x\n", hr);
631 todo_wine ok(prop.vt == VT_BOOL, "vt %08x\n", prop.vt);
632 todo_wine ok(prop.u.boolVal == TRUE, "Hide Attachments got %d\n", prop.u.boolVal);
633 PropVariantClear(&prop);
634
635 prop.vt = VT_LPSTR;
636 prop.u.pszVal = CoTaskMemAlloc(strlen(string)+1);
637 strcpy(prop.u.pszVal, string);
638 hr = IMimeMessage_SetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
639 ok(hr == S_OK, "ret %08x\n", hr);
640 PropVariantClear(&prop);
641
642 hr = IMimeMessage_GetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
643 todo_wine ok(hr == S_OK, "ret %08x\n", hr);
644 todo_wine ok(prop.vt == VT_BOOL, "vt %08x\n", prop.vt);
645 todo_wine ok(prop.u.boolVal == TRUE, "Hide Attachments got %d\n", prop.u.boolVal);
646 PropVariantClear(&prop);
647
648 /* Invalid property type doesn't change the value */
649 prop.vt = VT_LPSTR;
650 prop.u.pszVal = CoTaskMemAlloc(strlen(zero)+1);
651 strcpy(prop.u.pszVal, zero);
652 hr = IMimeMessage_SetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
653 ok(hr == S_OK, "ret %08x\n", hr);
654 PropVariantClear(&prop);
655
656 hr = IMimeMessage_GetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
657 todo_wine ok(hr == S_OK, "ret %08x\n", hr);
658 todo_wine ok(prop.vt == VT_BOOL, "vt %08x\n", prop.vt);
659 todo_wine ok(prop.u.boolVal == TRUE, "Hide Attachments got %d\n", prop.u.boolVal);
660 PropVariantClear(&prop);
661
662 /* Invalid OID */
663 prop.vt = VT_BOOL;
664 prop.u.boolVal = TRUE;
665 hr = IMimeMessage_SetOption(msg, 0xff00000a, &prop);
666 ok(hr == MIME_E_INVALID_OPTION_ID, "ret %08x\n", hr);
667 PropVariantClear(&prop);
668
669 /* Out of range before type. */
670 prop.vt = VT_I4;
671 prop.u.lVal = 1;
672 hr = IMimeMessage_SetOption(msg, 0xff00000a, &prop);
673 ok(hr == MIME_E_INVALID_OPTION_ID, "ret %08x\n", hr);
674 PropVariantClear(&prop);
675
676 IMimeMessage_Release(msg);
677 }
678
679 static void test_BindToObject(void)
680 {
681 HRESULT hr;
682 IMimeMessage *msg;
683 IMimeBody *body;
684 ULONG count;
685
686 hr = MimeOleCreateMessage(NULL, &msg);
687 ok(hr == S_OK, "ret %08x\n", hr);
688
689 hr = IMimeMessage_CountBodies(msg, HBODY_ROOT, TRUE, &count);
690 ok(hr == S_OK, "ret %08x\n", hr);
691 ok(count == 1, "got %d\n", count);
692
693 hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body);
694 ok(hr == S_OK, "ret %08x\n", hr);
695 IMimeBody_Release(body);
696
697 IMimeMessage_Release(msg);
698 }
699
700 static void test_BodyDeleteProp(void)
701 {
702 static const char topic[] = "wine topic";
703 HRESULT hr;
704 IMimeMessage *msg;
705 IMimeBody *body;
706 PROPVARIANT prop;
707
708 hr = MimeOleCreateMessage(NULL, &msg);
709 ok(hr == S_OK, "ret %08x\n", hr);
710
711 PropVariantInit(&prop);
712
713 hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body);
714 ok(hr == S_OK, "ret %08x\n", hr);
715
716 hr = IMimeBody_DeleteProp(body, "Subject");
717 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
718
719 hr = IMimeBody_DeleteProp(body, PIDTOSTR(PID_HDR_SUBJECT));
720 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
721
722 prop.vt = VT_LPSTR;
723 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1);
724 strcpy(prop.u.pszVal, topic);
725 hr = IMimeBody_SetProp(body, "Subject", 0, &prop);
726 ok(hr == S_OK, "ret %08x\n", hr);
727 PropVariantClear(&prop);
728
729 hr = IMimeBody_DeleteProp(body, "Subject");
730 ok(hr == S_OK, "ret %08x\n", hr);
731
732 hr = IMimeBody_GetProp(body, "Subject", 0, &prop);
733 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
734
735 prop.vt = VT_LPSTR;
736 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1);
737 strcpy(prop.u.pszVal, topic);
738 hr = IMimeBody_SetProp(body, PIDTOSTR(PID_HDR_SUBJECT), 0, &prop);
739 ok(hr == S_OK, "ret %08x\n", hr);
740 PropVariantClear(&prop);
741
742 hr = IMimeBody_DeleteProp(body, PIDTOSTR(PID_HDR_SUBJECT));
743 ok(hr == S_OK, "ret %08x\n", hr);
744
745 hr = IMimeBody_GetProp(body, PIDTOSTR(PID_HDR_SUBJECT), 0, &prop);
746 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
747
748 IMimeBody_Release(body);
749 IMimeMessage_Release(msg);
750 }
751
752 static void test_MimeOleGetPropertySchema(void)
753 {
754 HRESULT hr;
755 IMimePropertySchema *schema = NULL;
756
757 hr = MimeOleGetPropertySchema(&schema);
758 ok(hr == S_OK, "ret %08x\n", hr);
759
760 IMimePropertySchema_Release(schema);
761 }
762
763 START_TEST(mimeole)
764 {
765 OleInitialize(NULL);
766 test_CreateVirtualStream();
767 test_CreateSecurity();
768 test_CreateBody();
769 test_Allocator();
770 test_CreateMessage();
771 test_MessageSetProp();
772 test_MessageGetPropInfo();
773 test_MessageOptions();
774 test_BindToObject();
775 test_BodyDeleteProp();
776 test_MimeOleGetPropertySchema();
777 OleUninitialize();
778 }