[INETCOMM] Sync with Wine Staging 1.9.23. CORE-12409
[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 CoTaskMemFree(body_list);
342
343 hr = IMimeBody_GetCharset(body, &hcs);
344 ok(hr == S_OK, "ret %08x\n", hr);
345 todo_wine
346 {
347 ok(hcs != NULL, "Expected non-NULL charset\n");
348 }
349
350 IMimeMessage_Release(msg);
351
352 ref = IStream_AddRef(stream);
353 ok(ref == 2 ||
354 broken(ref == 1), /* win95 */
355 "ref %d\n", ref);
356 IStream_Release(stream);
357
358 IStream_Release(stream);
359 }
360
361 static void test_MessageSetProp(void)
362 {
363 static const char topic[] = "wine topic";
364 static const WCHAR topicW[] = {'w','i','n','e',' ','t','o','p','i','c',0};
365 HRESULT hr;
366 IMimeMessage *msg;
367 IMimeBody *body;
368 PROPVARIANT prop;
369
370 hr = MimeOleCreateMessage(NULL, &msg);
371 ok(hr == S_OK, "ret %08x\n", hr);
372
373 PropVariantInit(&prop);
374
375 hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body);
376 ok(hr == S_OK, "ret %08x\n", hr);
377
378 hr = IMimeBody_SetProp(body, NULL, 0, &prop);
379 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
380
381 hr = IMimeBody_SetProp(body, "Thread-Topic", 0, NULL);
382 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
383
384 prop.vt = VT_LPSTR;
385 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1);
386 strcpy(prop.u.pszVal, topic);
387 hr = IMimeBody_SetProp(body, "Thread-Topic", 0, &prop);
388 ok(hr == S_OK, "ret %08x\n", hr);
389 PropVariantClear(&prop);
390
391 hr = IMimeBody_GetProp(body, NULL, 0, &prop);
392 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
393
394 hr = IMimeBody_GetProp(body, "Thread-Topic", 0, NULL);
395 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
396
397 hr = IMimeBody_GetProp(body, "Wine-Topic", 0, &prop);
398 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
399
400 prop.vt = VT_LPSTR;
401 hr = IMimeBody_GetProp(body, "Thread-Topic", 0, &prop);
402 ok(hr == S_OK, "ret %08x\n", hr);
403 if(hr == S_OK)
404 {
405 ok(prop.vt == VT_LPSTR, "type %d\n", prop.vt);
406 ok(!strcmp(prop.u.pszVal, topic), "got %s\n", prop.u.pszVal);
407 PropVariantClear(&prop);
408 }
409
410 prop.vt = VT_LPSTR;
411 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1);
412 strcpy(prop.u.pszVal, topic);
413 hr = IMimeBody_SetProp(body, PIDTOSTR(PID_HDR_SUBJECT), 0, &prop);
414 ok(hr == S_OK, "ret %08x\n", hr);
415 PropVariantClear(&prop);
416
417 prop.vt = VT_LPSTR;
418 hr = IMimeBody_GetProp(body, PIDTOSTR(PID_HDR_SUBJECT), 0, &prop);
419 ok(hr == S_OK, "ret %08x\n", hr);
420 if(hr == S_OK)
421 {
422 ok(prop.vt == VT_LPSTR, "type %d\n", prop.vt);
423 ok(!strcmp(prop.u.pszVal, topic), "got %s\n", prop.u.pszVal);
424 PropVariantClear(&prop);
425 }
426
427 /* Using the name or PID returns the same result. */
428 prop.vt = VT_LPSTR;
429 hr = IMimeBody_GetProp(body, "Subject", 0, &prop);
430 ok(hr == S_OK, "ret %08x\n", hr);
431 if(hr == S_OK)
432 {
433 ok(prop.vt == VT_LPSTR, "type %d\n", prop.vt);
434 ok(!strcmp(prop.u.pszVal, topic), "got %s\n", prop.u.pszVal);
435 PropVariantClear(&prop);
436 }
437
438 prop.vt = VT_LPWSTR;
439 hr = IMimeBody_GetProp(body, "Subject", 0, &prop);
440 ok(hr == S_OK, "ret %08x\n", hr);
441 if(hr == S_OK)
442 {
443 ok(prop.vt == VT_LPWSTR, "type %d\n", prop.vt);
444 ok(!lstrcmpW(prop.u.pwszVal, topicW), "got %s\n", wine_dbgstr_w(prop.u.pwszVal));
445 PropVariantClear(&prop);
446 }
447
448 prop.vt = VT_LPSTR;
449 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1);
450 strcpy(prop.u.pszVal, topic);
451 hr = IMimeBody_SetProp(body, PIDTOSTR(PID_HDR_TO), 0, &prop);
452 ok(hr == S_OK, "ret %08x\n", hr);
453 PropVariantClear(&prop);
454
455 /* Out of Range PID */
456 prop.vt = VT_LPSTR;
457 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1);
458 strcpy(prop.u.pszVal, topic);
459 hr = IMimeBody_SetProp(body, PIDTOSTR(124), 0, &prop);
460 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
461 PropVariantClear(&prop);
462
463 IMimeBody_Release(body);
464 IMimeMessage_Release(msg);
465 }
466
467 static void test_MessageGetPropInfo(void)
468 {
469 static const char topic[] = "wine topic";
470 static const char subject[] = "wine testing";
471 HRESULT hr;
472 IMimeMessage *msg;
473 IMimeBody *body;
474 PROPVARIANT prop;
475 MIMEPROPINFO info;
476
477 hr = MimeOleCreateMessage(NULL, &msg);
478 ok(hr == S_OK, "ret %08x\n", hr);
479
480 PropVariantInit(&prop);
481
482 hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body);
483 ok(hr == S_OK, "ret %08x\n", hr);
484
485 prop.vt = VT_LPSTR;
486 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1);
487 strcpy(prop.u.pszVal, topic);
488 hr = IMimeBody_SetProp(body, "Thread-Topic", 0, &prop);
489 ok(hr == S_OK, "ret %08x\n", hr);
490 PropVariantClear(&prop);
491
492 prop.vt = VT_LPSTR;
493 prop.u.pszVal = CoTaskMemAlloc(strlen(subject)+1);
494 strcpy(prop.u.pszVal, subject);
495 hr = IMimeBody_SetProp(body, PIDTOSTR(PID_HDR_SUBJECT), 0, &prop);
496 ok(hr == S_OK, "ret %08x\n", hr);
497 PropVariantClear(&prop);
498
499 memset(&info, 0, sizeof(info));
500 info.dwMask = PIM_ENCODINGTYPE | PIM_FLAGS | PIM_PROPID;
501 hr = IMimeBody_GetPropInfo(body, NULL, &info);
502 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
503
504 memset(&info, 0, sizeof(info));
505 info.dwMask = PIM_ENCODINGTYPE | PIM_FLAGS | PIM_PROPID;
506 hr = IMimeBody_GetPropInfo(body, "Subject", NULL);
507 ok(hr == E_INVALIDARG, "ret %08x\n", hr);
508
509 memset(&info, 0xfe, sizeof(info));
510 info.dwMask = PIM_ENCODINGTYPE | PIM_FLAGS | PIM_PROPID;
511 hr = IMimeBody_GetPropInfo(body, "Subject", &info);
512 ok(hr == S_OK, "ret %08x\n", hr);
513 if(hr == S_OK)
514 {
515 ok(info.dwMask & (PIM_ENCODINGTYPE | PIM_FLAGS| PIM_PROPID), "Invalid mask 0x%08x\n", info.dwFlags);
516 todo_wine ok(info.dwFlags & 0x10000000, "Invalid flags 0x%08x\n", info.dwFlags);
517 ok(info.ietEncoding == 0, "Invalid encoding %d\n", info.ietEncoding);
518 ok(info.dwPropId == PID_HDR_SUBJECT, "Invalid propid %d\n", info.dwPropId);
519 ok(info.cValues == 0xfefefefe, "Invalid cValues %d\n", info.cValues);
520 }
521
522 memset(&info, 0xfe, sizeof(info));
523 info.dwMask = 0;
524 hr = IMimeBody_GetPropInfo(body, "Subject", &info);
525 ok(hr == S_OK, "ret %08x\n", hr);
526 if(hr == S_OK)
527 {
528 ok(info.dwMask == 0, "Invalid mask 0x%08x\n", info.dwFlags);
529 ok(info.dwFlags == 0xfefefefe, "Invalid flags 0x%08x\n", info.dwFlags);
530 ok(info.ietEncoding == -16843010, "Invalid encoding %d\n", info.ietEncoding);
531 ok(info.dwPropId == -16843010, "Invalid propid %d\n", info.dwPropId);
532 }
533
534 memset(&info, 0xfe, sizeof(info));
535 info.dwMask = 0;
536 info.dwPropId = 1024;
537 info.ietEncoding = 99;
538 hr = IMimeBody_GetPropInfo(body, "Subject", &info);
539 ok(hr == S_OK, "ret %08x\n", hr);
540 if(hr == S_OK)
541 {
542 ok(info.dwMask == 0, "Invalid mask 0x%08x\n", info.dwFlags);
543 ok(info.dwFlags == 0xfefefefe, "Invalid flags 0x%08x\n", info.dwFlags);
544 ok(info.ietEncoding == 99, "Invalid encoding %d\n", info.ietEncoding);
545 ok(info.dwPropId == 1024, "Invalid propid %d\n", info.dwPropId);
546 }
547
548 memset(&info, 0, sizeof(info));
549 info.dwMask = PIM_ENCODINGTYPE | PIM_FLAGS | PIM_PROPID;
550 hr = IMimeBody_GetPropInfo(body, "Invalid Property", &info);
551 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
552
553 IMimeBody_Release(body);
554 IMimeMessage_Release(msg);
555 }
556
557 static void test_MessageOptions(void)
558 {
559 static const char string[] = "XXXXX";
560 static const char zero[] = "0";
561 HRESULT hr;
562 IMimeMessage *msg;
563 PROPVARIANT prop;
564
565 hr = MimeOleCreateMessage(NULL, &msg);
566 ok(hr == S_OK, "ret %08x\n", hr);
567
568 PropVariantInit(&prop);
569
570 prop.vt = VT_BOOL;
571 prop.u.boolVal = TRUE;
572 hr = IMimeMessage_SetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
573 ok(hr == S_OK, "ret %08x\n", hr);
574 PropVariantClear(&prop);
575
576 hr = IMimeMessage_GetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
577 todo_wine ok(hr == S_OK, "ret %08x\n", hr);
578 todo_wine ok(prop.vt == VT_BOOL, "vt %08x\n", prop.vt);
579 todo_wine ok(prop.u.boolVal == TRUE, "Hide Attachments got %d\n", prop.u.boolVal);
580 PropVariantClear(&prop);
581
582 prop.vt = VT_LPSTR;
583 prop.u.pszVal = CoTaskMemAlloc(strlen(string)+1);
584 strcpy(prop.u.pszVal, string);
585 hr = IMimeMessage_SetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
586 ok(hr == S_OK, "ret %08x\n", hr);
587 PropVariantClear(&prop);
588
589 hr = IMimeMessage_GetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
590 todo_wine ok(hr == S_OK, "ret %08x\n", hr);
591 todo_wine ok(prop.vt == VT_BOOL, "vt %08x\n", prop.vt);
592 todo_wine ok(prop.u.boolVal == TRUE, "Hide Attachments got %d\n", prop.u.boolVal);
593 PropVariantClear(&prop);
594
595 /* Invalid property type doesn't change the value */
596 prop.vt = VT_LPSTR;
597 prop.u.pszVal = CoTaskMemAlloc(strlen(zero)+1);
598 strcpy(prop.u.pszVal, zero);
599 hr = IMimeMessage_SetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
600 ok(hr == S_OK, "ret %08x\n", hr);
601 PropVariantClear(&prop);
602
603 hr = IMimeMessage_GetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop);
604 todo_wine ok(hr == S_OK, "ret %08x\n", hr);
605 todo_wine ok(prop.vt == VT_BOOL, "vt %08x\n", prop.vt);
606 todo_wine ok(prop.u.boolVal == TRUE, "Hide Attachments got %d\n", prop.u.boolVal);
607 PropVariantClear(&prop);
608
609 /* Invalid OID */
610 prop.vt = VT_BOOL;
611 prop.u.boolVal = TRUE;
612 hr = IMimeMessage_SetOption(msg, 0xff00000a, &prop);
613 ok(hr == MIME_E_INVALID_OPTION_ID, "ret %08x\n", hr);
614 PropVariantClear(&prop);
615
616 /* Out of range before type. */
617 prop.vt = VT_I4;
618 prop.u.lVal = 1;
619 hr = IMimeMessage_SetOption(msg, 0xff00000a, &prop);
620 ok(hr == MIME_E_INVALID_OPTION_ID, "ret %08x\n", hr);
621 PropVariantClear(&prop);
622
623 IMimeMessage_Release(msg);
624 }
625
626 static void test_BindToObject(void)
627 {
628 HRESULT hr;
629 IMimeMessage *msg;
630 IMimeBody *body;
631 ULONG count;
632
633 hr = MimeOleCreateMessage(NULL, &msg);
634 ok(hr == S_OK, "ret %08x\n", hr);
635
636 hr = IMimeMessage_CountBodies(msg, HBODY_ROOT, TRUE, &count);
637 ok(hr == S_OK, "ret %08x\n", hr);
638 ok(count == 1, "got %d\n", count);
639
640 hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body);
641 ok(hr == S_OK, "ret %08x\n", hr);
642 IMimeBody_Release(body);
643
644 IMimeMessage_Release(msg);
645 }
646
647 static void test_BodyDeleteProp(void)
648 {
649 static const char topic[] = "wine topic";
650 HRESULT hr;
651 IMimeMessage *msg;
652 IMimeBody *body;
653 PROPVARIANT prop;
654
655 hr = MimeOleCreateMessage(NULL, &msg);
656 ok(hr == S_OK, "ret %08x\n", hr);
657
658 PropVariantInit(&prop);
659
660 hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body);
661 ok(hr == S_OK, "ret %08x\n", hr);
662
663 hr = IMimeBody_DeleteProp(body, "Subject");
664 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
665
666 hr = IMimeBody_DeleteProp(body, PIDTOSTR(PID_HDR_SUBJECT));
667 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
668
669 prop.vt = VT_LPSTR;
670 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1);
671 strcpy(prop.u.pszVal, topic);
672 hr = IMimeBody_SetProp(body, "Subject", 0, &prop);
673 ok(hr == S_OK, "ret %08x\n", hr);
674 PropVariantClear(&prop);
675
676 hr = IMimeBody_DeleteProp(body, "Subject");
677 ok(hr == S_OK, "ret %08x\n", hr);
678
679 hr = IMimeBody_GetProp(body, "Subject", 0, &prop);
680 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
681
682 prop.vt = VT_LPSTR;
683 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1);
684 strcpy(prop.u.pszVal, topic);
685 hr = IMimeBody_SetProp(body, PIDTOSTR(PID_HDR_SUBJECT), 0, &prop);
686 ok(hr == S_OK, "ret %08x\n", hr);
687 PropVariantClear(&prop);
688
689 hr = IMimeBody_DeleteProp(body, PIDTOSTR(PID_HDR_SUBJECT));
690 ok(hr == S_OK, "ret %08x\n", hr);
691
692 hr = IMimeBody_GetProp(body, PIDTOSTR(PID_HDR_SUBJECT), 0, &prop);
693 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr);
694
695 IMimeBody_Release(body);
696 IMimeMessage_Release(msg);
697 }
698
699 static void test_MimeOleGetPropertySchema(void)
700 {
701 HRESULT hr;
702 IMimePropertySchema *schema = NULL;
703
704 hr = MimeOleGetPropertySchema(&schema);
705 ok(hr == S_OK, "ret %08x\n", hr);
706
707 IMimePropertySchema_Release(schema);
708 }
709
710 START_TEST(mimeole)
711 {
712 OleInitialize(NULL);
713 test_CreateVirtualStream();
714 test_CreateSecurity();
715 test_CreateBody();
716 test_Allocator();
717 test_CreateMessage();
718 test_MessageSetProp();
719 test_MessageGetPropInfo();
720 test_MessageOptions();
721 test_BindToObject();
722 test_BodyDeleteProp();
723 test_MimeOleGetPropertySchema();
724 OleUninitialize();
725 }