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 #ifdef __REACTOS__ 24 #define CONST_VTABLE 25 #endif 26 27 #include "initguid.h" 28 #include "windows.h" 29 #include "ole2.h" 30 #include "ocidl.h" 31 32 #include "mimeole.h" 33 #include "wininet.h" 34 35 #include <stdio.h> 36 37 #include "wine/test.h" 38 39 #define DEFINE_EXPECT(func) \ 40 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE 41 42 #define SET_EXPECT(func) \ 43 expect_ ## func = TRUE 44 45 #define CHECK_EXPECT(func) \ 46 do { \ 47 ok(expect_ ##func, "unexpected call " #func "\n"); \ 48 expect_ ## func = FALSE; \ 49 called_ ## func = TRUE; \ 50 }while(0) 51 52 #define CHECK_EXPECT2(func) \ 53 do { \ 54 ok(expect_ ##func, "unexpected call " #func "\n"); \ 55 called_ ## func = TRUE; \ 56 }while(0) 57 58 #define CHECK_CALLED(func) \ 59 do { \ 60 ok(called_ ## func, "expected " #func "\n"); \ 61 expect_ ## func = called_ ## func = FALSE; \ 62 }while(0) 63 64 DEFINE_EXPECT(Stream_Read); 65 DEFINE_EXPECT(Stream_Stat); 66 DEFINE_EXPECT(Stream_Seek); 67 DEFINE_EXPECT(Stream_Seek_END); 68 DEFINE_EXPECT(GetBindInfo); 69 DEFINE_EXPECT(ReportProgress_MIMETYPEAVAILABLE); 70 DEFINE_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE); 71 DEFINE_EXPECT(ReportData); 72 DEFINE_EXPECT(ReportResult); 73 74 static const char msg1[] = 75 "MIME-Version: 1.0\r\n" 76 "Content-Type: multipart/mixed;\r\n" 77 " boundary=\"------------1.5.0.6\";\r\n" 78 " stuff=\"du;nno\";\r\n" 79 " morestuff=\"so\\\\me\\\"thing\\\"\"\r\n" 80 "foo: bar\r\n" 81 "From: Huw Davies <huw@codeweavers.com>\r\n" 82 "From: Me <xxx@codeweavers.com>\r\n" 83 "To: wine-patches <wine-patches@winehq.org>\r\n" 84 "Cc: Huw Davies <huw@codeweavers.com>,\r\n" 85 " \"Fred Bloggs\" <fred@bloggs.com>\r\n" 86 "foo: baz\r\n" 87 "bar: fum\r\n" 88 "\r\n" 89 "This is a multi-part message in MIME format.\r\n" 90 "--------------1.5.0.6\r\n" 91 "Content-Type: text/plain; format=fixed; charset=UTF-8\r\n" 92 "Content-Transfer-Encoding: 8bit\r\n" 93 "\r\n" 94 "Stuff\r\n" 95 "--------------1.5.0.6\r\n" 96 "Content-Type: text/plain; charset=\"us-ascii\"\r\n" 97 "Content-Transfer-Encoding: 7bit\r\n" 98 "\r\n" 99 "More stuff\r\n" 100 "--------------1.5.0.6--\r\n"; 101 102 static const char mhtml_page1[] = 103 "MIME-Version: 1.0\r\n" 104 "Content-Type: multipart/related; type:=\"text/html\"; boundary=\"----=_NextPart_000_00\"\r\n" 105 "\r\n" 106 "------=_NextPart_000_00\r\n" 107 "Content-Type: text/html; charset=\"Windows-1252\"\r\n" 108 "Content-Transfer-Encoding: quoted-printable\r\n" 109 "\r\n" 110 "<HTML></HTML>\r\n" 111 "------=_NextPart_000_00\r\n" 112 "Content-Type: Image/Jpeg\r\n" 113 "Content-Transfer-Encoding: base64\r\n" 114 "Content-Location: http://winehq.org/mhtmltest.html\r\n" 115 "\r\n\t\t\t\tVGVzdA==\r\n\r\n" 116 "------=_NextPart_000_00--"; 117 118 static WCHAR *a2w(const char *str) 119 { 120 WCHAR *ret; 121 int len; 122 123 if(!str) 124 return NULL; 125 126 len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); 127 ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); 128 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); 129 return ret; 130 } 131 132 static int strcmp_wa(const WCHAR *strw, const char *stra) 133 { 134 WCHAR buf[512]; 135 MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, ARRAY_SIZE(buf)); 136 return lstrcmpW(strw, buf); 137 } 138 139 static void test_CreateVirtualStream(void) 140 { 141 HRESULT hr; 142 IStream *pstm; 143 144 hr = MimeOleCreateVirtualStream(&pstm); 145 ok(hr == S_OK, "ret %08x\n", hr); 146 147 IStream_Release(pstm); 148 } 149 150 static void test_CreateSecurity(void) 151 { 152 HRESULT hr; 153 IMimeSecurity *sec; 154 155 hr = MimeOleCreateSecurity(&sec); 156 ok(hr == S_OK, "ret %08x\n", hr); 157 158 IMimeSecurity_Release(sec); 159 } 160 161 static IStream *create_stream_from_string(const char *data) 162 { 163 LARGE_INTEGER off; 164 IStream *stream; 165 HRESULT hr; 166 167 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 168 ok(hr == S_OK, "ret %08x\n", hr); 169 170 hr = IStream_Write(stream, data, strlen(data), NULL); 171 ok(hr == S_OK, "Write failed: %08x\n", hr); 172 173 off.QuadPart = 0; 174 hr = IStream_Seek(stream, off, STREAM_SEEK_SET, NULL); 175 ok(hr == S_OK, "Seek failed: %08x\n", hr); 176 177 return stream; 178 } 179 180 #define test_current_encoding(a,b) _test_current_encoding(__LINE__,a,b) 181 static void _test_current_encoding(unsigned line, IMimeBody *mime_body, ENCODINGTYPE encoding) 182 { 183 ENCODINGTYPE current_encoding; 184 HRESULT hres; 185 186 hres = IMimeBody_GetCurrentEncoding(mime_body, ¤t_encoding); 187 ok_(__FILE__,line)(hres == S_OK, "GetCurrentEncoding failed: %08x\n", hres); 188 ok_(__FILE__,line)(current_encoding == encoding, "encoding = %d, expected %d\n", current_encoding, encoding); 189 } 190 191 static void test_CreateBody(void) 192 { 193 HRESULT hr; 194 IMimeBody *body; 195 HBODY handle = (void *)0xdeadbeef; 196 IStream *in; 197 LARGE_INTEGER off; 198 ULARGE_INTEGER pos; 199 ULONG count, found_param, i; 200 MIMEPARAMINFO *param_info; 201 IMimeAllocator *alloc; 202 BODYOFFSETS offsets; 203 CLSID clsid; 204 205 hr = CoCreateInstance(&CLSID_IMimeBody, NULL, CLSCTX_INPROC_SERVER, &IID_IMimeBody, (void**)&body); 206 ok(hr == S_OK, "ret %08x\n", hr); 207 208 hr = IMimeBody_GetClassID(body, NULL); 209 ok(hr == E_INVALIDARG, "ret %08x\n", hr); 210 211 hr = IMimeBody_GetClassID(body, &clsid); 212 ok(hr == S_OK, "ret %08x\n", hr); 213 ok(IsEqualGUID(&clsid, &IID_IMimeBody), "got %s\n", wine_dbgstr_guid(&clsid)); 214 215 hr = IMimeBody_GetHandle(body, &handle); 216 ok(hr == MIME_E_NO_DATA, "ret %08x\n", hr); 217 ok(handle == NULL, "handle %p\n", handle); 218 219 in = create_stream_from_string(msg1); 220 221 /* Need to call InitNew before Load otherwise Load crashes with native inetcomm */ 222 hr = IMimeBody_InitNew(body); 223 ok(hr == S_OK, "ret %08x\n", hr); 224 225 test_current_encoding(body, IET_7BIT); 226 227 hr = IMimeBody_Load(body, in); 228 ok(hr == S_OK, "ret %08x\n", hr); 229 off.QuadPart = 0; 230 IStream_Seek(in, off, STREAM_SEEK_CUR, &pos); 231 ok(pos.u.LowPart == 359, "pos %u\n", pos.u.LowPart); 232 233 hr = IMimeBody_IsContentType(body, "multipart", "mixed"); 234 ok(hr == S_OK, "ret %08x\n", hr); 235 hr = IMimeBody_IsContentType(body, "text", "plain"); 236 ok(hr == S_FALSE, "ret %08x\n", hr); 237 hr = IMimeBody_IsContentType(body, NULL, "mixed"); 238 ok(hr == S_OK, "ret %08x\n", hr); 239 hr = IMimeBody_IsType(body, IBT_EMPTY); 240 ok(hr == S_OK, "got %08x\n", hr); 241 242 hr = IMimeBody_SetData(body, IET_8BIT, "text", "plain", &IID_IStream, in); 243 ok(hr == S_OK, "ret %08x\n", hr); 244 hr = IMimeBody_IsContentType(body, "text", "plain"); 245 todo_wine 246 ok(hr == S_OK, "ret %08x\n", hr); 247 test_current_encoding(body, IET_8BIT); 248 249 memset(&offsets, 0xcc, sizeof(offsets)); 250 hr = IMimeBody_GetOffsets(body, &offsets); 251 ok(hr == MIME_E_NO_DATA, "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 == 0, "got %d\n", offsets.cbBodyStart); 255 ok(offsets.cbBodyEnd == 0, "got %d\n", offsets.cbBodyEnd); 256 257 hr = IMimeBody_IsType(body, IBT_EMPTY); 258 ok(hr == S_FALSE, "got %08x\n", hr); 259 260 hr = MimeOleGetAllocator(&alloc); 261 ok(hr == S_OK, "ret %08x\n", hr); 262 263 hr = IMimeBody_GetParameters(body, "nothere", &count, ¶m_info); 264 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr); 265 ok(count == 0, "got %d\n", count); 266 ok(!param_info, "got %p\n", param_info); 267 268 hr = IMimeBody_GetParameters(body, "bar", &count, ¶m_info); 269 ok(hr == S_OK, "ret %08x\n", hr); 270 ok(count == 0, "got %d\n", count); 271 ok(!param_info, "got %p\n", param_info); 272 273 hr = IMimeBody_GetParameters(body, "Content-Type", &count, ¶m_info); 274 ok(hr == S_OK, "ret %08x\n", hr); 275 todo_wine /* native adds a charset parameter */ 276 ok(count == 4, "got %d\n", count); 277 ok(param_info != NULL, "got %p\n", param_info); 278 279 found_param = 0; 280 for(i = 0; i < count; i++) 281 { 282 if(!strcmp(param_info[i].pszName, "morestuff")) 283 { 284 found_param++; 285 ok(!strcmp(param_info[i].pszData, "so\\me\"thing\""), 286 "got %s\n", param_info[i].pszData); 287 } 288 else if(!strcmp(param_info[i].pszName, "stuff")) 289 { 290 found_param++; 291 ok(!strcmp(param_info[i].pszData, "du;nno"), 292 "got %s\n", param_info[i].pszData); 293 } 294 } 295 ok(found_param == 2, "matched %d params\n", found_param); 296 297 hr = IMimeAllocator_FreeParamInfoArray(alloc, count, param_info, TRUE); 298 ok(hr == S_OK, "ret %08x\n", hr); 299 IMimeAllocator_Release(alloc); 300 301 IStream_Release(in); 302 IMimeBody_Release(body); 303 } 304 305 typedef struct { 306 IStream IStream_iface; 307 LONG ref; 308 unsigned pos; 309 } TestStream; 310 311 static inline TestStream *impl_from_IStream(IStream *iface) 312 { 313 return CONTAINING_RECORD(iface, TestStream, IStream_iface); 314 } 315 316 static HRESULT WINAPI Stream_QueryInterface(IStream *iface, REFIID riid, void **ppv) 317 { 318 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_ISequentialStream, riid) || IsEqualGUID(&IID_IStream, riid)) { 319 *ppv = iface; 320 return S_OK; 321 } 322 323 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid)); 324 *ppv = NULL; 325 return E_NOINTERFACE; 326 } 327 328 static ULONG WINAPI Stream_AddRef(IStream *iface) 329 { 330 TestStream *This = impl_from_IStream(iface); 331 return InterlockedIncrement(&This->ref); 332 } 333 334 static ULONG WINAPI Stream_Release(IStream *iface) 335 { 336 TestStream *This = impl_from_IStream(iface); 337 ULONG ref = InterlockedDecrement(&This->ref); 338 339 if (!ref) 340 HeapFree(GetProcessHeap(), 0, This); 341 342 return ref; 343 } 344 345 static HRESULT WINAPI Stream_Read(IStream *iface, void *pv, ULONG cb, ULONG *pcbRead) 346 { 347 TestStream *This = impl_from_IStream(iface); 348 BYTE *output = pv; 349 unsigned i; 350 351 CHECK_EXPECT(Stream_Read); 352 353 for(i = 0; i < cb; i++) 354 output[i] = '0' + This->pos++; 355 *pcbRead = i; 356 return S_OK; 357 } 358 359 static HRESULT WINAPI Stream_Write(IStream *iface, const void *pv, ULONG cb, ULONG *pcbWritten) 360 { 361 ok(0, "unexpected call\n"); 362 return E_NOTIMPL; 363 } 364 365 static DWORD expect_seek_pos; 366 367 static HRESULT WINAPI Stream_Seek(IStream *iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, 368 ULARGE_INTEGER *plibNewPosition) 369 { 370 TestStream *This = impl_from_IStream(iface); 371 372 if(dwOrigin == STREAM_SEEK_END) { 373 CHECK_EXPECT(Stream_Seek_END); 374 ok(dlibMove.QuadPart == expect_seek_pos, "unexpected seek pos %u\n", dlibMove.u.LowPart); 375 if(plibNewPosition) 376 plibNewPosition->QuadPart = 10; 377 return S_OK; 378 } 379 380 CHECK_EXPECT(Stream_Seek); 381 382 ok(dlibMove.QuadPart == expect_seek_pos, "unexpected seek pos %u\n", dlibMove.u.LowPart); 383 ok(dwOrigin == STREAM_SEEK_SET, "dwOrigin = %d\n", dwOrigin); 384 This->pos = dlibMove.QuadPart; 385 if(plibNewPosition) 386 plibNewPosition->QuadPart = This->pos; 387 return S_OK; 388 } 389 390 static HRESULT WINAPI Stream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize) 391 { 392 ok(0, "unexpected call\n"); 393 return E_NOTIMPL; 394 } 395 396 static HRESULT WINAPI Stream_CopyTo(IStream *iface, IStream *pstm, ULARGE_INTEGER cb, 397 ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten) 398 { 399 ok(0, "unexpected call\n"); 400 return E_NOTIMPL; 401 } 402 403 static HRESULT WINAPI Stream_Commit(IStream *iface, DWORD grfCommitFlags) 404 { 405 ok(0, "unexpected call\n"); 406 return E_NOTIMPL; 407 } 408 409 static HRESULT WINAPI Stream_Revert(IStream *iface) 410 { 411 ok(0, "unexpected call\n"); 412 return E_NOTIMPL; 413 } 414 415 static HRESULT WINAPI Stream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset, 416 ULARGE_INTEGER cb, DWORD dwLockType) 417 { 418 ok(0, "unexpected call\n"); 419 return E_NOTIMPL; 420 } 421 422 static HRESULT WINAPI Stream_UnlockRegion(IStream *iface, 423 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) 424 { 425 ok(0, "unexpected call\n"); 426 return E_NOTIMPL; 427 } 428 429 static HRESULT WINAPI Stream_Stat(IStream *iface, STATSTG *pstatstg, DWORD dwStatFlag) 430 { 431 CHECK_EXPECT(Stream_Stat); 432 ok(dwStatFlag == STATFLAG_NONAME, "dwStatFlag = %x\n", dwStatFlag); 433 return E_NOTIMPL; 434 } 435 436 static HRESULT WINAPI Stream_Clone(IStream *iface, IStream **ppstm) 437 { 438 ok(0, "unexpected call\n"); 439 return E_NOTIMPL; 440 } 441 442 static const IStreamVtbl StreamVtbl = { 443 Stream_QueryInterface, 444 Stream_AddRef, 445 Stream_Release, 446 Stream_Read, 447 Stream_Write, 448 Stream_Seek, 449 Stream_SetSize, 450 Stream_CopyTo, 451 Stream_Commit, 452 Stream_Revert, 453 Stream_LockRegion, 454 Stream_UnlockRegion, 455 Stream_Stat, 456 Stream_Clone 457 }; 458 459 static IStream *create_test_stream(void) 460 { 461 TestStream *stream; 462 stream = HeapAlloc(GetProcessHeap(), 0, sizeof(*stream)); 463 stream->IStream_iface.lpVtbl = &StreamVtbl; 464 stream->ref = 1; 465 stream->pos = 0; 466 return &stream->IStream_iface; 467 } 468 469 #define test_stream_read(a,b,c,d) _test_stream_read(__LINE__,a,b,c,d) 470 static void _test_stream_read(unsigned line, IStream *stream, HRESULT exhres, const char *exdata, unsigned read_size) 471 { 472 ULONG read = 0xdeadbeed, exread = strlen(exdata); 473 char buf[1024]; 474 HRESULT hres; 475 476 if(read_size == -1) 477 read_size = sizeof(buf)-1; 478 479 hres = IStream_Read(stream, buf, read_size, &read); 480 ok_(__FILE__,line)(hres == exhres, "Read returned %08x, expected %08x\n", hres, exhres); 481 ok_(__FILE__,line)(read == exread, "unexpected read size %u, expected %u\n", read, exread); 482 buf[read] = 0; 483 ok_(__FILE__,line)(read == exread && !memcmp(buf, exdata, read), "unexpected data %s\n", buf); 484 } 485 486 static void test_SetData(void) 487 { 488 IStream *stream, *stream2, *test_stream; 489 IMimeBody *body; 490 HRESULT hr; 491 492 hr = CoCreateInstance(&CLSID_IMimeBody, NULL, CLSCTX_INPROC_SERVER, &IID_IMimeBody, (void**)&body); 493 ok(hr == S_OK, "ret %08x\n", hr); 494 495 /* Need to call InitNew before Load otherwise Load crashes with native inetcomm */ 496 hr = IMimeBody_InitNew(body); 497 ok(hr == S_OK, "ret %08x\n", hr); 498 499 stream = create_stream_from_string(msg1); 500 hr = IMimeBody_Load(body, stream); 501 ok(hr == S_OK, "ret %08x\n", hr); 502 IStream_Release(stream); 503 504 test_stream = create_test_stream(); 505 hr = IMimeBody_SetData(body, IET_BINARY, "text", "plain", &IID_IStream, test_stream); 506 507 ok(hr == S_OK, "ret %08x\n", hr); 508 hr = IMimeBody_IsContentType(body, "text", "plain"); 509 todo_wine 510 ok(hr == S_OK, "ret %08x\n", hr); 511 512 test_current_encoding(body, IET_BINARY); 513 514 SET_EXPECT(Stream_Stat); 515 SET_EXPECT(Stream_Seek_END); 516 hr = IMimeBody_GetData(body, IET_BINARY, &stream); 517 CHECK_CALLED(Stream_Stat); 518 CHECK_CALLED(Stream_Seek_END); 519 ok(hr == S_OK, "GetData failed %08x\n", hr); 520 ok(stream != test_stream, "unexpected stream\n"); 521 522 SET_EXPECT(Stream_Seek); 523 SET_EXPECT(Stream_Read); 524 test_stream_read(stream, S_OK, "012", 3); 525 CHECK_CALLED(Stream_Seek); 526 CHECK_CALLED(Stream_Read); 527 528 SET_EXPECT(Stream_Stat); 529 SET_EXPECT(Stream_Seek_END); 530 hr = IMimeBody_GetData(body, IET_BINARY, &stream2); 531 CHECK_CALLED(Stream_Stat); 532 CHECK_CALLED(Stream_Seek_END); 533 ok(hr == S_OK, "GetData failed %08x\n", hr); 534 ok(stream2 != stream, "unexpected stream\n"); 535 536 SET_EXPECT(Stream_Seek); 537 SET_EXPECT(Stream_Read); 538 test_stream_read(stream2, S_OK, "01", 2); 539 CHECK_CALLED(Stream_Seek); 540 CHECK_CALLED(Stream_Read); 541 542 expect_seek_pos = 3; 543 SET_EXPECT(Stream_Seek); 544 SET_EXPECT(Stream_Read); 545 test_stream_read(stream, S_OK, "345", 3); 546 CHECK_CALLED(Stream_Seek); 547 CHECK_CALLED(Stream_Read); 548 549 IStream_Release(stream); 550 IStream_Release(stream2); 551 IStream_Release(test_stream); 552 553 stream = create_stream_from_string(" \t\r\n|}~YWJj ZGV|}~mZw== \t"); /* "abcdefg" in base64 obscured by invalid chars */ 554 hr = IMimeBody_SetData(body, IET_BASE64, "text", "plain", &IID_IStream, stream); 555 IStream_Release(stream); 556 ok(hr == S_OK, "SetData failed: %08x\n", hr); 557 558 test_current_encoding(body, IET_BASE64); 559 560 hr = IMimeBody_GetData(body, IET_BINARY, &stream); 561 ok(hr == S_OK, "GetData failed %08x\n", hr); 562 563 test_stream_read(stream, S_OK, "abc", 3); 564 test_stream_read(stream, S_OK, "defg", -1); 565 566 IStream_Release(stream); 567 568 hr = IMimeBody_GetData(body, IET_BASE64, &stream); 569 ok(hr == S_OK, "GetData failed %08x\n", hr); 570 571 test_stream_read(stream, S_OK, " \t\r", 3); 572 IStream_Release(stream); 573 574 stream = create_stream_from_string(" =3d=3D\"one\" \t=\r\ntw= o=\nx3\n=34\r\n5"); 575 hr = IMimeBody_SetData(body, IET_QP, "text", "plain", &IID_IStream, stream); 576 IStream_Release(stream); 577 ok(hr == S_OK, "SetData failed: %08x\n", hr); 578 579 test_current_encoding(body, IET_QP); 580 581 hr = IMimeBody_GetData(body, IET_BINARY, &stream); 582 ok(hr == S_OK, "GetData failed %08x\n", hr); 583 584 test_stream_read(stream, S_OK, " ==\"one\" \ttw=o=3\n4\r\n5", -1); 585 586 IStream_Release(stream); 587 588 IMimeBody_Release(body); 589 } 590 591 static void test_Allocator(void) 592 { 593 HRESULT hr; 594 IMimeAllocator *alloc; 595 596 hr = MimeOleGetAllocator(&alloc); 597 ok(hr == S_OK, "ret %08x\n", hr); 598 IMimeAllocator_Release(alloc); 599 } 600 601 static void test_CreateMessage(void) 602 { 603 HRESULT hr; 604 IMimeMessage *msg; 605 IStream *stream; 606 LONG ref; 607 HBODY hbody, hbody2; 608 IMimeBody *body; 609 BODYOFFSETS offsets; 610 ULONG count; 611 FINDBODY find_struct; 612 HCHARSET hcs; 613 HBODY handle = NULL; 614 615 char text[] = "text"; 616 HBODY *body_list; 617 PROPVARIANT prop; 618 static const char att_pritype[] = "att:pri-content-type"; 619 620 hr = MimeOleCreateMessage(NULL, &msg); 621 ok(hr == S_OK, "ret %08x\n", hr); 622 623 stream = create_stream_from_string(msg1); 624 625 hr = IMimeMessage_Load(msg, stream); 626 ok(hr == S_OK, "ret %08x\n", hr); 627 628 hr = IMimeMessage_CountBodies(msg, HBODY_ROOT, TRUE, &count); 629 ok(hr == S_OK, "ret %08x\n", hr); 630 ok(count == 3, "got %d\n", count); 631 632 hr = IMimeMessage_CountBodies(msg, HBODY_ROOT, FALSE, &count); 633 ok(hr == S_OK, "ret %08x\n", hr); 634 ok(count == 3, "got %d\n", count); 635 636 hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body); 637 ok(hr == S_OK, "ret %08x\n", hr); 638 hr = IMimeBody_GetOffsets(body, &offsets); 639 ok(hr == S_OK, "ret %08x\n", hr); 640 ok(offsets.cbBoundaryStart == 0, "got %d\n", offsets.cbBoundaryStart); 641 ok(offsets.cbHeaderStart == 0, "got %d\n", offsets.cbHeaderStart); 642 ok(offsets.cbBodyStart == 359, "got %d\n", offsets.cbBodyStart); 643 ok(offsets.cbBodyEnd == 666, "got %d\n", offsets.cbBodyEnd); 644 IMimeBody_Release(body); 645 646 hr = IMimeMessage_GetBody(msg, IBL_ROOT, NULL, &hbody); 647 ok(hr == S_OK, "ret %08x\n", hr); 648 649 hr = IMimeBody_GetHandle(body, NULL); 650 ok(hr == E_INVALIDARG, "ret %08x\n", hr); 651 652 hr = IMimeBody_GetHandle(body, &handle); 653 ok(hr == S_OK, "ret %08x\n", hr); 654 ok(handle != NULL, "handle %p\n", handle); 655 656 hr = IMimeMessage_GetBody(msg, IBL_PARENT, hbody, NULL); 657 ok(hr == E_INVALIDARG, "ret %08x\n", hr); 658 659 hbody2 = (HBODY)0xdeadbeef; 660 hr = IMimeMessage_GetBody(msg, IBL_PARENT, hbody, &hbody2); 661 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr); 662 ok(hbody2 == NULL, "hbody2 %p\n", hbody2); 663 664 PropVariantInit(&prop); 665 hr = IMimeMessage_GetBodyProp(msg, hbody, att_pritype, 0, &prop); 666 ok(hr == S_OK, "ret %08x\n", hr); 667 ok(prop.vt == VT_LPSTR, "vt %08x\n", prop.vt); 668 ok(!strcasecmp(prop.u.pszVal, "multipart"), "got %s\n", prop.u.pszVal); 669 PropVariantClear(&prop); 670 671 hr = IMimeMessage_GetBody(msg, IBL_FIRST, hbody, &hbody); 672 ok(hr == S_OK, "ret %08x\n", hr); 673 hr = IMimeMessage_BindToObject(msg, hbody, &IID_IMimeBody, (void**)&body); 674 ok(hr == S_OK, "ret %08x\n", hr); 675 676 hr = IMimeBody_GetHandle(body, &handle); 677 ok(hr == S_OK, "ret %08x\n", hr); 678 ok(handle == hbody, "handle %p\n", handle); 679 680 hr = IMimeBody_GetOffsets(body, &offsets); 681 ok(hr == S_OK, "ret %08x\n", hr); 682 ok(offsets.cbBoundaryStart == 405, "got %d\n", offsets.cbBoundaryStart); 683 ok(offsets.cbHeaderStart == 428, "got %d\n", offsets.cbHeaderStart); 684 ok(offsets.cbBodyStart == 518, "got %d\n", offsets.cbBodyStart); 685 ok(offsets.cbBodyEnd == 523, "got %d\n", offsets.cbBodyEnd); 686 687 hr = IMimeBody_GetCharset(body, &hcs); 688 ok(hr == S_OK, "ret %08x\n", hr); 689 todo_wine 690 { 691 ok(hcs != NULL, "Expected non-NULL charset\n"); 692 } 693 694 IMimeBody_Release(body); 695 696 hr = IMimeMessage_GetBody(msg, IBL_NEXT, hbody, &hbody); 697 ok(hr == S_OK, "ret %08x\n", hr); 698 hr = IMimeMessage_BindToObject(msg, hbody, &IID_IMimeBody, (void**)&body); 699 ok(hr == S_OK, "ret %08x\n", hr); 700 701 hr = IMimeBody_GetHandle(body, &handle); 702 ok(hr == S_OK, "ret %08x\n", hr); 703 ok(handle == hbody, "handle %p\n", handle); 704 705 hr = IMimeBody_GetOffsets(body, &offsets); 706 ok(hr == S_OK, "ret %08x\n", hr); 707 ok(offsets.cbBoundaryStart == 525, "got %d\n", offsets.cbBoundaryStart); 708 ok(offsets.cbHeaderStart == 548, "got %d\n", offsets.cbHeaderStart); 709 ok(offsets.cbBodyStart == 629, "got %d\n", offsets.cbBodyStart); 710 ok(offsets.cbBodyEnd == 639, "got %d\n", offsets.cbBodyEnd); 711 IMimeBody_Release(body); 712 713 find_struct.pszPriType = text; 714 find_struct.pszSubType = NULL; 715 716 hr = IMimeMessage_FindFirst(msg, &find_struct, &hbody); 717 ok(hr == S_OK, "ret %08x\n", hr); 718 719 hr = IMimeMessage_FindNext(msg, &find_struct, &hbody); 720 ok(hr == S_OK, "ret %08x\n", hr); 721 722 hr = IMimeMessage_FindNext(msg, &find_struct, &hbody); 723 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr); 724 725 hr = IMimeMessage_GetAttachments(msg, &count, &body_list); 726 ok(hr == S_OK, "ret %08x\n", hr); 727 ok(count == 2, "got %d\n", count); 728 if(count == 2) 729 { 730 IMimeBody *attachment; 731 PROPVARIANT prop; 732 733 PropVariantInit(&prop); 734 735 hr = IMimeMessage_BindToObject(msg, body_list[0], &IID_IMimeBody, (void**)&attachment); 736 ok(hr == S_OK, "ret %08x\n", hr); 737 738 hr = IMimeBody_IsContentType(attachment, "multipart", NULL); 739 ok(hr == S_FALSE, "ret %08x\n", hr); 740 741 test_current_encoding(attachment, IET_8BIT); 742 743 prop.vt = VT_LPSTR; 744 hr = IMimeBody_GetProp(attachment, "Content-Transfer-Encoding", 0, &prop); 745 ok(hr == S_OK, "ret %08x\n", hr); 746 747 ok(prop.vt == VT_LPSTR, "type %d\n", prop.vt); 748 ok(!strcmp(prop.u.pszVal, "8bit"), "got %s\n", prop.u.pszVal); 749 PropVariantClear(&prop); 750 751 hr = IMimeBody_IsType(attachment, IBT_ATTACHMENT); 752 todo_wine ok(hr == S_FALSE, "ret %08x\n", hr); 753 754 IMimeBody_Release(attachment); 755 756 hr = IMimeMessage_BindToObject(msg, body_list[1], &IID_IMimeBody, (void**)&attachment); 757 ok(hr == S_OK, "ret %08x\n", hr); 758 759 hr = IMimeBody_IsContentType(attachment, "multipart", NULL); 760 ok(hr == S_FALSE, "ret %08x\n", hr); 761 762 test_current_encoding(attachment, IET_7BIT); 763 764 prop.vt = VT_LPSTR; 765 hr = IMimeBody_GetProp(attachment, "Content-Transfer-Encoding", 0, &prop); 766 ok(hr == S_OK, "ret %08x\n", hr); 767 ok(prop.vt == VT_LPSTR, "type %d\n", prop.vt); 768 ok(!strcmp(prop.u.pszVal, "7bit"), "got %s\n", prop.u.pszVal); 769 PropVariantClear(&prop); 770 771 hr = IMimeBody_IsType(attachment, IBT_ATTACHMENT); 772 ok(hr == S_OK, "ret %08x\n", hr); 773 774 IMimeBody_Release(attachment); 775 } 776 CoTaskMemFree(body_list); 777 778 hr = IMimeBody_GetCharset(body, &hcs); 779 ok(hr == S_OK, "ret %08x\n", hr); 780 todo_wine 781 { 782 ok(hcs != NULL, "Expected non-NULL charset\n"); 783 } 784 785 IMimeMessage_Release(msg); 786 787 ref = IStream_AddRef(stream); 788 ok(ref == 2 || 789 broken(ref == 1), /* win95 */ 790 "ref %d\n", ref); 791 IStream_Release(stream); 792 793 IStream_Release(stream); 794 } 795 796 static void test_mhtml_message(void) 797 { 798 IMimeMessage *mime_message; 799 IMimeBody *mime_body; 800 HBODY *body_list; 801 IStream *stream; 802 ULONG count; 803 HRESULT hres; 804 805 hres = MimeOleCreateMessage(NULL, &mime_message); 806 ok(hres == S_OK, "MimeOleCreateMessage failed: %08x\n", hres); 807 808 stream = create_stream_from_string(mhtml_page1); 809 hres = IMimeMessage_Load(mime_message, stream); 810 IStream_Release(stream); 811 ok(hres == S_OK, "Load failed: %08x\n", hres); 812 813 hres = IMimeMessage_CountBodies(mime_message, HBODY_ROOT, TRUE, &count); 814 ok(hres == S_OK, "CountBodies failed: %08x\n", hres); 815 ok(count == 3, "got %d\n", count); 816 817 hres = IMimeMessage_GetAttachments(mime_message, &count, &body_list); 818 ok(hres == S_OK, "GetAttachments failed: %08x\n", hres); 819 ok(count == 2, "count = %u\n", count); 820 821 hres = IMimeMessage_BindToObject(mime_message, body_list[0], &IID_IMimeBody, (void**)&mime_body); 822 ok(hres == S_OK, "BindToObject failed: %08x\n", hres); 823 824 hres = IMimeBody_GetData(mime_body, IET_BINARY, &stream); 825 ok(hres == S_OK, "GetData failed: %08x\n", hres); 826 test_stream_read(stream, S_OK, "<HTML></HTML>", -1); 827 IStream_Release(stream); 828 829 test_current_encoding(mime_body, IET_QP); 830 831 IMimeBody_Release(mime_body); 832 833 hres = IMimeMessage_BindToObject(mime_message, body_list[1], &IID_IMimeBody, (void**)&mime_body); 834 ok(hres == S_OK, "BindToObject failed: %08x\n", hres); 835 836 test_current_encoding(mime_body, IET_BASE64); 837 838 hres = IMimeBody_GetData(mime_body, IET_BINARY, &stream); 839 ok(hres == S_OK, "GetData failed: %08x\n", hres); 840 test_stream_read(stream, S_OK, "Test", -1); 841 IStream_Release(stream); 842 843 IMimeBody_Release(mime_body); 844 845 CoTaskMemFree(body_list); 846 847 IMimeMessage_Release(mime_message); 848 } 849 850 static void test_MessageSetProp(void) 851 { 852 static const char topic[] = "wine topic"; 853 static const WCHAR topicW[] = {'w','i','n','e',' ','t','o','p','i','c',0}; 854 HRESULT hr; 855 IMimeMessage *msg; 856 IMimeBody *body; 857 PROPVARIANT prop; 858 859 hr = MimeOleCreateMessage(NULL, &msg); 860 ok(hr == S_OK, "ret %08x\n", hr); 861 862 PropVariantInit(&prop); 863 864 hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body); 865 ok(hr == S_OK, "ret %08x\n", hr); 866 867 hr = IMimeBody_SetProp(body, NULL, 0, &prop); 868 ok(hr == E_INVALIDARG, "ret %08x\n", hr); 869 870 hr = IMimeBody_SetProp(body, "Thread-Topic", 0, NULL); 871 ok(hr == E_INVALIDARG, "ret %08x\n", hr); 872 873 prop.vt = VT_LPSTR; 874 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1); 875 strcpy(prop.u.pszVal, topic); 876 hr = IMimeBody_SetProp(body, "Thread-Topic", 0, &prop); 877 ok(hr == S_OK, "ret %08x\n", hr); 878 PropVariantClear(&prop); 879 880 hr = IMimeBody_GetProp(body, NULL, 0, &prop); 881 ok(hr == E_INVALIDARG, "ret %08x\n", hr); 882 883 hr = IMimeBody_GetProp(body, "Thread-Topic", 0, NULL); 884 ok(hr == E_INVALIDARG, "ret %08x\n", hr); 885 886 hr = IMimeBody_GetProp(body, "Wine-Topic", 0, &prop); 887 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr); 888 889 prop.vt = VT_LPSTR; 890 hr = IMimeBody_GetProp(body, "Thread-Topic", 0, &prop); 891 ok(hr == S_OK, "ret %08x\n", hr); 892 if(hr == S_OK) 893 { 894 ok(prop.vt == VT_LPSTR, "type %d\n", prop.vt); 895 ok(!strcmp(prop.u.pszVal, topic), "got %s\n", prop.u.pszVal); 896 PropVariantClear(&prop); 897 } 898 899 prop.vt = VT_LPSTR; 900 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1); 901 strcpy(prop.u.pszVal, topic); 902 hr = IMimeBody_SetProp(body, PIDTOSTR(PID_HDR_SUBJECT), 0, &prop); 903 ok(hr == S_OK, "ret %08x\n", hr); 904 PropVariantClear(&prop); 905 906 prop.vt = VT_LPSTR; 907 hr = IMimeBody_GetProp(body, PIDTOSTR(PID_HDR_SUBJECT), 0, &prop); 908 ok(hr == S_OK, "ret %08x\n", hr); 909 if(hr == S_OK) 910 { 911 ok(prop.vt == VT_LPSTR, "type %d\n", prop.vt); 912 ok(!strcmp(prop.u.pszVal, topic), "got %s\n", prop.u.pszVal); 913 PropVariantClear(&prop); 914 } 915 916 /* Using the name or PID returns the same result. */ 917 prop.vt = VT_LPSTR; 918 hr = IMimeBody_GetProp(body, "Subject", 0, &prop); 919 ok(hr == S_OK, "ret %08x\n", hr); 920 if(hr == S_OK) 921 { 922 ok(prop.vt == VT_LPSTR, "type %d\n", prop.vt); 923 ok(!strcmp(prop.u.pszVal, topic), "got %s\n", prop.u.pszVal); 924 PropVariantClear(&prop); 925 } 926 927 prop.vt = VT_LPWSTR; 928 hr = IMimeBody_GetProp(body, "Subject", 0, &prop); 929 ok(hr == S_OK, "ret %08x\n", hr); 930 if(hr == S_OK) 931 { 932 ok(prop.vt == VT_LPWSTR, "type %d\n", prop.vt); 933 ok(!lstrcmpW(prop.u.pwszVal, topicW), "got %s\n", wine_dbgstr_w(prop.u.pwszVal)); 934 PropVariantClear(&prop); 935 } 936 937 prop.vt = VT_LPSTR; 938 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1); 939 strcpy(prop.u.pszVal, topic); 940 hr = IMimeBody_SetProp(body, PIDTOSTR(PID_HDR_TO), 0, &prop); 941 ok(hr == S_OK, "ret %08x\n", hr); 942 PropVariantClear(&prop); 943 944 /* Out of Range PID */ 945 prop.vt = VT_LPSTR; 946 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1); 947 strcpy(prop.u.pszVal, topic); 948 hr = IMimeBody_SetProp(body, PIDTOSTR(124), 0, &prop); 949 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr); 950 PropVariantClear(&prop); 951 952 IMimeBody_Release(body); 953 IMimeMessage_Release(msg); 954 } 955 956 static void test_MessageGetPropInfo(void) 957 { 958 static const char topic[] = "wine topic"; 959 static const char subject[] = "wine testing"; 960 HRESULT hr; 961 IMimeMessage *msg; 962 IMimeBody *body; 963 PROPVARIANT prop; 964 MIMEPROPINFO info; 965 966 hr = MimeOleCreateMessage(NULL, &msg); 967 ok(hr == S_OK, "ret %08x\n", hr); 968 969 PropVariantInit(&prop); 970 971 hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body); 972 ok(hr == S_OK, "ret %08x\n", hr); 973 974 prop.vt = VT_LPSTR; 975 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1); 976 strcpy(prop.u.pszVal, topic); 977 hr = IMimeBody_SetProp(body, "Thread-Topic", 0, &prop); 978 ok(hr == S_OK, "ret %08x\n", hr); 979 PropVariantClear(&prop); 980 981 prop.vt = VT_LPSTR; 982 prop.u.pszVal = CoTaskMemAlloc(strlen(subject)+1); 983 strcpy(prop.u.pszVal, subject); 984 hr = IMimeBody_SetProp(body, PIDTOSTR(PID_HDR_SUBJECT), 0, &prop); 985 ok(hr == S_OK, "ret %08x\n", hr); 986 PropVariantClear(&prop); 987 988 memset(&info, 0, sizeof(info)); 989 info.dwMask = PIM_ENCODINGTYPE | PIM_FLAGS | PIM_PROPID; 990 hr = IMimeBody_GetPropInfo(body, NULL, &info); 991 ok(hr == E_INVALIDARG, "ret %08x\n", hr); 992 993 memset(&info, 0, sizeof(info)); 994 info.dwMask = PIM_ENCODINGTYPE | PIM_FLAGS | PIM_PROPID; 995 hr = IMimeBody_GetPropInfo(body, "Subject", NULL); 996 ok(hr == E_INVALIDARG, "ret %08x\n", hr); 997 998 memset(&info, 0xfe, sizeof(info)); 999 info.dwMask = PIM_ENCODINGTYPE | PIM_FLAGS | PIM_PROPID; 1000 hr = IMimeBody_GetPropInfo(body, "Subject", &info); 1001 ok(hr == S_OK, "ret %08x\n", hr); 1002 if(hr == S_OK) 1003 { 1004 ok(info.dwMask & (PIM_ENCODINGTYPE | PIM_FLAGS| PIM_PROPID), "Invalid mask 0x%08x\n", info.dwFlags); 1005 todo_wine ok(info.dwFlags & 0x10000000, "Invalid flags 0x%08x\n", info.dwFlags); 1006 ok(info.ietEncoding == 0, "Invalid encoding %d\n", info.ietEncoding); 1007 ok(info.dwPropId == PID_HDR_SUBJECT, "Invalid propid %d\n", info.dwPropId); 1008 ok(info.cValues == 0xfefefefe, "Invalid cValues %d\n", info.cValues); 1009 } 1010 1011 memset(&info, 0xfe, sizeof(info)); 1012 info.dwMask = 0; 1013 hr = IMimeBody_GetPropInfo(body, "Subject", &info); 1014 ok(hr == S_OK, "ret %08x\n", hr); 1015 if(hr == S_OK) 1016 { 1017 ok(info.dwMask == 0, "Invalid mask 0x%08x\n", info.dwFlags); 1018 ok(info.dwFlags == 0xfefefefe, "Invalid flags 0x%08x\n", info.dwFlags); 1019 ok(info.ietEncoding == -16843010, "Invalid encoding %d\n", info.ietEncoding); 1020 ok(info.dwPropId == -16843010, "Invalid propid %d\n", info.dwPropId); 1021 } 1022 1023 memset(&info, 0xfe, sizeof(info)); 1024 info.dwMask = 0; 1025 info.dwPropId = 1024; 1026 info.ietEncoding = 99; 1027 hr = IMimeBody_GetPropInfo(body, "Subject", &info); 1028 ok(hr == S_OK, "ret %08x\n", hr); 1029 if(hr == S_OK) 1030 { 1031 ok(info.dwMask == 0, "Invalid mask 0x%08x\n", info.dwFlags); 1032 ok(info.dwFlags == 0xfefefefe, "Invalid flags 0x%08x\n", info.dwFlags); 1033 ok(info.ietEncoding == 99, "Invalid encoding %d\n", info.ietEncoding); 1034 ok(info.dwPropId == 1024, "Invalid propid %d\n", info.dwPropId); 1035 } 1036 1037 memset(&info, 0, sizeof(info)); 1038 info.dwMask = PIM_ENCODINGTYPE | PIM_FLAGS | PIM_PROPID; 1039 hr = IMimeBody_GetPropInfo(body, "Invalid Property", &info); 1040 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr); 1041 1042 IMimeBody_Release(body); 1043 IMimeMessage_Release(msg); 1044 } 1045 1046 static void test_MessageOptions(void) 1047 { 1048 static const char string[] = "XXXXX"; 1049 static const char zero[] = "0"; 1050 HRESULT hr; 1051 IMimeMessage *msg; 1052 PROPVARIANT prop; 1053 1054 hr = MimeOleCreateMessage(NULL, &msg); 1055 ok(hr == S_OK, "ret %08x\n", hr); 1056 1057 PropVariantInit(&prop); 1058 1059 prop.vt = VT_BOOL; 1060 prop.u.boolVal = TRUE; 1061 hr = IMimeMessage_SetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop); 1062 ok(hr == S_OK, "ret %08x\n", hr); 1063 PropVariantClear(&prop); 1064 1065 hr = IMimeMessage_GetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop); 1066 todo_wine ok(hr == S_OK, "ret %08x\n", hr); 1067 todo_wine ok(prop.vt == VT_BOOL, "vt %08x\n", prop.vt); 1068 todo_wine ok(prop.u.boolVal == TRUE, "Hide Attachments got %d\n", prop.u.boolVal); 1069 PropVariantClear(&prop); 1070 1071 prop.vt = VT_LPSTR; 1072 prop.u.pszVal = CoTaskMemAlloc(strlen(string)+1); 1073 strcpy(prop.u.pszVal, string); 1074 hr = IMimeMessage_SetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop); 1075 ok(hr == S_OK, "ret %08x\n", hr); 1076 PropVariantClear(&prop); 1077 1078 hr = IMimeMessage_GetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop); 1079 todo_wine ok(hr == S_OK, "ret %08x\n", hr); 1080 todo_wine ok(prop.vt == VT_BOOL, "vt %08x\n", prop.vt); 1081 todo_wine ok(prop.u.boolVal == TRUE, "Hide Attachments got %d\n", prop.u.boolVal); 1082 PropVariantClear(&prop); 1083 1084 /* Invalid property type doesn't change the value */ 1085 prop.vt = VT_LPSTR; 1086 prop.u.pszVal = CoTaskMemAlloc(strlen(zero)+1); 1087 strcpy(prop.u.pszVal, zero); 1088 hr = IMimeMessage_SetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop); 1089 ok(hr == S_OK, "ret %08x\n", hr); 1090 PropVariantClear(&prop); 1091 1092 hr = IMimeMessage_GetOption(msg, OID_HIDE_TNEF_ATTACHMENTS, &prop); 1093 todo_wine ok(hr == S_OK, "ret %08x\n", hr); 1094 todo_wine ok(prop.vt == VT_BOOL, "vt %08x\n", prop.vt); 1095 todo_wine ok(prop.u.boolVal == TRUE, "Hide Attachments got %d\n", prop.u.boolVal); 1096 PropVariantClear(&prop); 1097 1098 /* Invalid OID */ 1099 prop.vt = VT_BOOL; 1100 prop.u.boolVal = TRUE; 1101 hr = IMimeMessage_SetOption(msg, 0xff00000a, &prop); 1102 ok(hr == MIME_E_INVALID_OPTION_ID, "ret %08x\n", hr); 1103 PropVariantClear(&prop); 1104 1105 /* Out of range before type. */ 1106 prop.vt = VT_I4; 1107 prop.u.lVal = 1; 1108 hr = IMimeMessage_SetOption(msg, 0xff00000a, &prop); 1109 ok(hr == MIME_E_INVALID_OPTION_ID, "ret %08x\n", hr); 1110 PropVariantClear(&prop); 1111 1112 IMimeMessage_Release(msg); 1113 } 1114 1115 static void test_BindToObject(void) 1116 { 1117 HRESULT hr; 1118 IMimeMessage *msg; 1119 IMimeBody *body; 1120 ULONG count; 1121 1122 hr = MimeOleCreateMessage(NULL, &msg); 1123 ok(hr == S_OK, "ret %08x\n", hr); 1124 1125 hr = IMimeMessage_CountBodies(msg, HBODY_ROOT, TRUE, &count); 1126 ok(hr == S_OK, "ret %08x\n", hr); 1127 ok(count == 1, "got %d\n", count); 1128 1129 hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body); 1130 ok(hr == S_OK, "ret %08x\n", hr); 1131 IMimeBody_Release(body); 1132 1133 IMimeMessage_Release(msg); 1134 } 1135 1136 static void test_BodyDeleteProp(void) 1137 { 1138 static const char topic[] = "wine topic"; 1139 HRESULT hr; 1140 IMimeMessage *msg; 1141 IMimeBody *body; 1142 PROPVARIANT prop; 1143 1144 hr = MimeOleCreateMessage(NULL, &msg); 1145 ok(hr == S_OK, "ret %08x\n", hr); 1146 1147 PropVariantInit(&prop); 1148 1149 hr = IMimeMessage_BindToObject(msg, HBODY_ROOT, &IID_IMimeBody, (void**)&body); 1150 ok(hr == S_OK, "ret %08x\n", hr); 1151 1152 hr = IMimeBody_DeleteProp(body, "Subject"); 1153 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr); 1154 1155 hr = IMimeBody_DeleteProp(body, PIDTOSTR(PID_HDR_SUBJECT)); 1156 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr); 1157 1158 prop.vt = VT_LPSTR; 1159 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1); 1160 strcpy(prop.u.pszVal, topic); 1161 hr = IMimeBody_SetProp(body, "Subject", 0, &prop); 1162 ok(hr == S_OK, "ret %08x\n", hr); 1163 PropVariantClear(&prop); 1164 1165 hr = IMimeBody_DeleteProp(body, "Subject"); 1166 ok(hr == S_OK, "ret %08x\n", hr); 1167 1168 hr = IMimeBody_GetProp(body, "Subject", 0, &prop); 1169 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr); 1170 1171 prop.vt = VT_LPSTR; 1172 prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1); 1173 strcpy(prop.u.pszVal, topic); 1174 hr = IMimeBody_SetProp(body, PIDTOSTR(PID_HDR_SUBJECT), 0, &prop); 1175 ok(hr == S_OK, "ret %08x\n", hr); 1176 PropVariantClear(&prop); 1177 1178 hr = IMimeBody_DeleteProp(body, PIDTOSTR(PID_HDR_SUBJECT)); 1179 ok(hr == S_OK, "ret %08x\n", hr); 1180 1181 hr = IMimeBody_GetProp(body, PIDTOSTR(PID_HDR_SUBJECT), 0, &prop); 1182 ok(hr == MIME_E_NOT_FOUND, "ret %08x\n", hr); 1183 1184 IMimeBody_Release(body); 1185 IMimeMessage_Release(msg); 1186 } 1187 1188 static void test_MimeOleGetPropertySchema(void) 1189 { 1190 HRESULT hr; 1191 IMimePropertySchema *schema = NULL; 1192 1193 hr = MimeOleGetPropertySchema(&schema); 1194 ok(hr == S_OK, "ret %08x\n", hr); 1195 1196 IMimePropertySchema_Release(schema); 1197 } 1198 1199 typedef struct { 1200 const char *url; 1201 const char *content; 1202 const char *mime; 1203 const char *data; 1204 } mhtml_binding_test_t; 1205 1206 static const mhtml_binding_test_t binding_tests[] = { 1207 { 1208 "mhtml:file://%s", 1209 mhtml_page1, 1210 "text/html", 1211 "<HTML></HTML>" 1212 }, 1213 { 1214 "mhtml:file://%s!http://winehq.org/mhtmltest.html", 1215 mhtml_page1, 1216 "Image/Jpeg", 1217 "Test" 1218 } 1219 }; 1220 1221 static const mhtml_binding_test_t *current_binding_test; 1222 static IInternetProtocol *current_binding_protocol; 1223 1224 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv) 1225 { 1226 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetBindInfo, riid)) { 1227 *ppv = iface; 1228 return S_OK; 1229 } 1230 1231 *ppv = NULL; 1232 ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid)); 1233 return E_NOINTERFACE; 1234 } 1235 1236 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface) 1237 { 1238 return 2; 1239 } 1240 1241 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface) 1242 { 1243 return 1; 1244 } 1245 1246 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfBINDF, BINDINFO *pbindinfo) 1247 { 1248 CHECK_EXPECT(GetBindInfo); 1249 1250 ok(grfBINDF != NULL, "grfBINDF == NULL\n"); 1251 ok(pbindinfo != NULL, "pbindinfo == NULL\n"); 1252 ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %d\n", pbindinfo->cbSize); 1253 1254 *grfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NEEDFILE; 1255 return S_OK; 1256 } 1257 1258 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface, ULONG ulStringType, LPOLESTR *ppwzStr, 1259 ULONG cEl, ULONG *pcElFetched) 1260 { 1261 ok(0, "unexpected call\n"); 1262 return E_NOTIMPL; 1263 } 1264 1265 static IInternetBindInfoVtbl InternetBindInfoVtbl = { 1266 BindInfo_QueryInterface, 1267 BindInfo_AddRef, 1268 BindInfo_Release, 1269 BindInfo_GetBindInfo, 1270 BindInfo_GetBindString 1271 }; 1272 1273 static IInternetBindInfo bind_info = { 1274 &InternetBindInfoVtbl 1275 }; 1276 1277 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) 1278 { 1279 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid)); 1280 *ppv = NULL; 1281 return E_NOINTERFACE; 1282 } 1283 1284 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface) 1285 { 1286 return 2; 1287 } 1288 1289 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface) 1290 { 1291 return 1; 1292 } 1293 1294 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService, 1295 REFIID riid, void **ppv) 1296 { 1297 if(IsEqualGUID(&CLSID_MimeEdit, guidService)) { 1298 *ppv = NULL; 1299 return E_NOINTERFACE; 1300 } 1301 1302 ok(0, "unexpected service %s\n", wine_dbgstr_guid(guidService)); 1303 return E_FAIL; 1304 } 1305 1306 static const IServiceProviderVtbl ServiceProviderVtbl = { 1307 ServiceProvider_QueryInterface, 1308 ServiceProvider_AddRef, 1309 ServiceProvider_Release, 1310 ServiceProvider_QueryService 1311 }; 1312 1313 static IServiceProvider service_provider = { &ServiceProviderVtbl }; 1314 1315 static HRESULT WINAPI ProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv) 1316 { 1317 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocolSink, riid)) { 1318 *ppv = iface; 1319 return S_OK; 1320 } 1321 1322 if(IsEqualGUID(&IID_IServiceProvider, riid)) { 1323 *ppv = &service_provider; 1324 return S_OK; 1325 } 1326 1327 *ppv = NULL; 1328 ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid)); 1329 return E_NOINTERFACE; 1330 } 1331 1332 static ULONG WINAPI ProtocolSink_AddRef(IInternetProtocolSink *iface) 1333 { 1334 return 2; 1335 } 1336 1337 static ULONG WINAPI ProtocolSink_Release(IInternetProtocolSink *iface) 1338 { 1339 return 1; 1340 } 1341 1342 static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData) 1343 { 1344 ok(0, "unexpected call\n"); 1345 return E_NOTIMPL; 1346 } 1347 1348 static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode, 1349 const WCHAR *szStatusText) 1350 { 1351 switch(ulStatusCode) { 1352 case BINDSTATUS_MIMETYPEAVAILABLE: 1353 CHECK_EXPECT(ReportProgress_MIMETYPEAVAILABLE); 1354 ok(!strcmp_wa(szStatusText, current_binding_test->mime), "status text %s\n", wine_dbgstr_w(szStatusText)); 1355 return S_OK; 1356 case BINDSTATUS_CACHEFILENAMEAVAILABLE: 1357 CHECK_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE); 1358 return S_OK; 1359 default: 1360 ok(0, "unexpected call %u %s\n", ulStatusCode, wine_dbgstr_w(szStatusText)); 1361 } 1362 1363 return E_NOTIMPL; 1364 } 1365 1366 static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF, ULONG ulProgress, 1367 ULONG ulProgressMax) 1368 { 1369 char buf[1024]; 1370 DWORD read; 1371 HRESULT hres; 1372 1373 CHECK_EXPECT(ReportData); 1374 1375 ok(!ulProgress, "ulProgress = %u\n", ulProgress); 1376 ok(ulProgress == ulProgressMax, "ulProgress != ulProgressMax\n"); 1377 ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_INTERMEDIATEDATANOTIFICATION 1378 | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE | BSCF_AVAILABLEDATASIZEUNKNOWN), 1379 "grcf = %08x\n", grfBSCF); 1380 1381 hres = IInternetProtocol_Read(current_binding_protocol, buf, sizeof(buf), &read); 1382 ok(hres == S_OK, "Read failed: %08x\n", hres); 1383 buf[read] = 0; 1384 ok(!strcmp(buf, current_binding_test->data), "unexpected data: %s\n", buf); 1385 1386 hres = IInternetProtocol_Read(current_binding_protocol, buf, sizeof(buf), &read); 1387 ok(hres == S_FALSE, "Read failed: %08x\n", hres); 1388 return S_OK; 1389 } 1390 1391 static HRESULT WINAPI ProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult, DWORD dwError, 1392 LPCWSTR szResult) 1393 { 1394 CHECK_EXPECT(ReportResult); 1395 ok(hrResult == S_OK, "hrResult = %08x\n", hrResult); 1396 ok(!dwError, "dwError = %u\n", dwError); 1397 ok(!szResult, "szResult = %s\n", wine_dbgstr_w(szResult)); 1398 return S_OK; 1399 } 1400 1401 static IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = { 1402 ProtocolSink_QueryInterface, 1403 ProtocolSink_AddRef, 1404 ProtocolSink_Release, 1405 ProtocolSink_Switch, 1406 ProtocolSink_ReportProgress, 1407 ProtocolSink_ReportData, 1408 ProtocolSink_ReportResult 1409 }; 1410 1411 static IInternetProtocolSink protocol_sink = { &InternetProtocolSinkVtbl }; 1412 1413 static void test_mhtml_protocol_binding(const mhtml_binding_test_t *test) 1414 { 1415 char file_name[MAX_PATH+32], *p, urla[INTERNET_MAX_URL_LENGTH]; 1416 WCHAR test_url[INTERNET_MAX_URL_LENGTH]; 1417 IInternetProtocol *protocol; 1418 IUnknown *unk; 1419 HRESULT hres; 1420 HANDLE file; 1421 DWORD size; 1422 BOOL ret; 1423 1424 p = file_name + GetCurrentDirectoryA(sizeof(file_name), file_name); 1425 *p++ = '\\'; 1426 strcpy(p, "winetest.mht"); 1427 1428 file = CreateFileA(file_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 1429 FILE_ATTRIBUTE_NORMAL, NULL); 1430 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n"); 1431 1432 WriteFile(file, test->content, strlen(test->content), &size, NULL); 1433 CloseHandle(file); 1434 1435 sprintf(urla, test->url, file_name); 1436 MultiByteToWideChar(CP_ACP, 0, urla, -1, test_url, ARRAY_SIZE(test_url)); 1437 1438 hres = CoCreateInstance(&CLSID_IMimeHtmlProtocol, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void**)&protocol); 1439 ok(hres == S_OK, "Could not create protocol handler: %08x\n", hres); 1440 1441 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolEx, (void**)&unk); 1442 ok(hres == E_NOINTERFACE, "Could get IInternetProtocolEx\n"); 1443 1444 current_binding_test = test; 1445 current_binding_protocol = protocol; 1446 1447 SET_EXPECT(GetBindInfo); 1448 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE); 1449 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE); 1450 SET_EXPECT(ReportData); 1451 SET_EXPECT(ReportResult); 1452 hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, &bind_info, 0, 0); 1453 ok(hres == S_OK, "Start failed: %08x\n", hres); 1454 CHECK_CALLED(GetBindInfo); 1455 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE); 1456 todo_wine CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE); 1457 CHECK_CALLED(ReportData); 1458 CHECK_CALLED(ReportResult); 1459 1460 IInternetProtocol_Release(protocol); 1461 ret = DeleteFileA("winetest.mht"); 1462 ok(ret, "DeleteFile failed: %u\n", GetLastError()); 1463 } 1464 1465 static const struct { 1466 const char *base_url; 1467 const char *relative_url; 1468 const char *expected_result; 1469 BOOL todo; 1470 } combine_tests[] = { 1471 { 1472 "mhtml:file:///c:/dir/test.mht", "http://test.org", 1473 "mhtml:file:///c:/dir/test.mht!x-usc:http://test.org" 1474 }, { 1475 "mhtml:file:///c:/dir/test.mht", "3D\"http://test.org\"", 1476 "mhtml:file:///c:/dir/test.mht!x-usc:3D\"http://test.org\"" 1477 }, { 1478 "mhtml:file:///c:/dir/test.mht", "123abc", 1479 "mhtml:file:///c:/dir/test.mht!x-usc:123abc" 1480 }, { 1481 "mhtml:file:///c:/dir/test.mht!x-usc:http://test.org", "123abc", 1482 "mhtml:file:///c:/dir/test.mht!x-usc:123abc" 1483 }, { 1484 "MhtMl:file:///c:/dir/test.mht!x-usc:http://test.org/dir/dir2/file.html", "../..", 1485 "mhtml:file:///c:/dir/test.mht!x-usc:../.." 1486 }, {"mhtml:file:///c:/dir/test.mht!x-usc:file:///c:/dir/dir2/file.html", "../..", 1487 "mhtml:file:///c:/dir/test.mht!x-usc:../.." 1488 }, { 1489 "mhtml:file:///c:/dir/test.mht!x-usc:http://test.org", "", 1490 "mhtml:file:///c:/dir/test.mht" 1491 }, { 1492 "mhtml:file:///c:/dir/test.mht!x-usc:http://test.org", "mhtml:file:///d:/file.html", 1493 "file:///d:/file.html", TRUE 1494 }, { 1495 "mhtml:file:///c:/dir/test.mht!x-usc:http://test.org", "mhtml:file:///c:/dir2/test.mht!x-usc:http://test.org", 1496 "mhtml:file:///c:/dir2/test.mht!x-usc:http://test.org", TRUE 1497 }, { 1498 "mhtml:file:///c:/dir/test.mht!http://test.org", "123abc", 1499 "mhtml:file:///c:/dir/test.mht!x-usc:123abc" 1500 }, { 1501 "mhtml:file:///c:/dir/test.mht!http://test.org", "", 1502 "mhtml:file:///c:/dir/test.mht" 1503 } 1504 }; 1505 1506 static void test_mhtml_protocol_info(void) 1507 { 1508 WCHAR *base_url, *relative_url, combined_url[INTERNET_MAX_URL_LENGTH]; 1509 IInternetProtocolInfo *protocol_info; 1510 DWORD combined_len; 1511 unsigned i, exlen; 1512 HRESULT hres; 1513 1514 static const WCHAR http_url[] = {'h','t','t','p',':','/','/','t','e','s','t','.','o','r','g',0}; 1515 1516 hres = CoCreateInstance(&CLSID_IMimeHtmlProtocol, NULL, CLSCTX_INPROC_SERVER, 1517 &IID_IInternetProtocolInfo, (void**)&protocol_info); 1518 ok(hres == S_OK, "Could not create protocol info: %08x\n", hres); 1519 1520 for(i = 0; i < ARRAY_SIZE(combine_tests); i++) { 1521 base_url = a2w(combine_tests[i].base_url); 1522 relative_url = a2w(combine_tests[i].relative_url); 1523 1524 combined_len = 0xdeadbeef; 1525 hres = IInternetProtocolInfo_CombineUrl(protocol_info, base_url, relative_url, ICU_BROWSER_MODE, 1526 combined_url, ARRAY_SIZE(combined_url), &combined_len, 0); 1527 todo_wine_if(combine_tests[i].todo) 1528 ok(hres == S_OK, "[%u] CombineUrl failed: %08x\n", i, hres); 1529 if(SUCCEEDED(hres)) { 1530 exlen = strlen(combine_tests[i].expected_result); 1531 ok(combined_len == exlen, "[%u] combined len is %u, expected %u\n", i, combined_len, exlen); 1532 ok(!strcmp_wa(combined_url, combine_tests[i].expected_result), "[%u] combined URL is %s, expected %s\n", 1533 i, wine_dbgstr_w(combined_url), combine_tests[i].expected_result); 1534 1535 combined_len = 0xdeadbeef; 1536 hres = IInternetProtocolInfo_CombineUrl(protocol_info, base_url, relative_url, ICU_BROWSER_MODE, 1537 combined_url, exlen, &combined_len, 0); 1538 ok(hres == E_FAIL, "[%u] CombineUrl returned: %08x\n", i, hres); 1539 ok(!combined_len, "[%u] combined_len = %u\n", i, combined_len); 1540 } 1541 1542 HeapFree(GetProcessHeap(), 0, base_url); 1543 HeapFree(GetProcessHeap(), 0, relative_url); 1544 } 1545 1546 hres = IInternetProtocolInfo_CombineUrl(protocol_info, http_url, http_url, ICU_BROWSER_MODE, 1547 combined_url, ARRAY_SIZE(combined_url), &combined_len, 0); 1548 ok(hres == E_FAIL, "CombineUrl failed: %08x\n", hres); 1549 1550 IInternetProtocolInfo_Release(protocol_info); 1551 } 1552 1553 static HRESULT WINAPI outer_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 1554 { 1555 ok(0, "unexpected call\n"); 1556 return E_NOINTERFACE; 1557 } 1558 1559 static ULONG WINAPI outer_AddRef(IUnknown *iface) 1560 { 1561 return 2; 1562 } 1563 1564 static ULONG WINAPI outer_Release(IUnknown *iface) 1565 { 1566 return 1; 1567 } 1568 1569 static const IUnknownVtbl outer_vtbl = { 1570 outer_QueryInterface, 1571 outer_AddRef, 1572 outer_Release 1573 }; 1574 1575 static BOOL broken_mhtml_resolver; 1576 1577 static void test_mhtml_protocol(void) 1578 { 1579 IUnknown outer = { &outer_vtbl }; 1580 IClassFactory *class_factory; 1581 IUnknown *unk, *unk2; 1582 unsigned i; 1583 HRESULT hres; 1584 1585 /* test class factory */ 1586 hres = CoGetClassObject(&CLSID_IMimeHtmlProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk); 1587 ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres); 1588 1589 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&unk2); 1590 ok(hres == E_NOINTERFACE, "IInternetProtocolInfo supported\n"); 1591 1592 hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&class_factory); 1593 ok(hres == S_OK, "Could not get IClassFactory iface: %08x\n", hres); 1594 IUnknown_Release(unk); 1595 1596 hres = IClassFactory_CreateInstance(class_factory, &outer, &IID_IUnknown, (void**)&unk); 1597 ok(hres == S_OK, "CreateInstance returned: %08x\n", hres); 1598 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocol, (void**)&unk2); 1599 ok(hres == S_OK, "Could not get IInternetProtocol iface: %08x\n", hres); 1600 IUnknown_Release(unk2); 1601 IUnknown_Release(unk); 1602 1603 hres = IClassFactory_CreateInstance(class_factory, (IUnknown*)0xdeadbeef, &IID_IInternetProtocol, (void**)&unk2); 1604 ok(hres == CLASS_E_NOAGGREGATION, "CreateInstance returned: %08x\n", hres); 1605 1606 IClassFactory_Release(class_factory); 1607 1608 if(!broken_mhtml_resolver) 1609 test_mhtml_protocol_info(); 1610 1611 for(i = 0; i < ARRAY_SIZE(binding_tests); i++) 1612 test_mhtml_protocol_binding(binding_tests + i); 1613 } 1614 1615 static void test_MimeOleObjectFromMoniker(void) 1616 { 1617 IMoniker *mon, *new_mon; 1618 WCHAR *mhtml_url, *url; 1619 IBindCtx *bind_ctx; 1620 IUnknown *unk; 1621 unsigned i; 1622 HRESULT hres; 1623 1624 static const struct { 1625 const char *url; 1626 const char *mhtml_url; 1627 } tests[] = { 1628 {"file:///x:\\dir\\file.mht", "mhtml:file://x:\\dir\\file.mht"}, 1629 {"file:///x:/dir/file.mht", "mhtml:file://x:\\dir\\file.mht"}, 1630 {"http://www.winehq.org/index.html?query#hash", "mhtml:http://www.winehq.org/index.html?query#hash"}, 1631 {"../test.mht", "mhtml:../test.mht"} 1632 }; 1633 1634 for(i = 0; i < ARRAY_SIZE(tests); i++) { 1635 url = a2w(tests[i].url); 1636 hres = CreateURLMoniker(NULL, url, &mon); 1637 ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres); 1638 HeapFree(GetProcessHeap(), 0, url); 1639 1640 hres = CreateBindCtx(0, &bind_ctx); 1641 ok(hres == S_OK, "CreateBindCtx failed: %08x\n", hres); 1642 1643 hres = MimeOleObjectFromMoniker(0, mon, bind_ctx, &IID_IUnknown, (void**)&unk, &new_mon); 1644 ok(hres == S_OK || broken(!i && hres == INET_E_RESOURCE_NOT_FOUND), "MimeOleObjectFromMoniker failed: %08x\n", hres); 1645 IBindCtx_Release(bind_ctx); 1646 if(hres == INET_E_RESOURCE_NOT_FOUND) { /* winxp */ 1647 win_skip("Broken MHTML behaviour found. Skipping some tests.\n"); 1648 broken_mhtml_resolver = TRUE; 1649 return; 1650 } 1651 1652 hres = IMoniker_GetDisplayName(new_mon, NULL, NULL, &mhtml_url); 1653 ok(hres == S_OK, "GetDisplayName failed: %08x\n", hres); 1654 ok(!strcmp_wa(mhtml_url, tests[i].mhtml_url), "[%d] unexpected mhtml URL: %s\n", i, wine_dbgstr_w(mhtml_url)); 1655 CoTaskMemFree(mhtml_url); 1656 1657 IUnknown_Release(unk); 1658 IMoniker_Release(new_mon); 1659 IMoniker_Release(mon); 1660 } 1661 } 1662 1663 START_TEST(mimeole) 1664 { 1665 OleInitialize(NULL); 1666 test_CreateVirtualStream(); 1667 test_CreateSecurity(); 1668 test_CreateBody(); 1669 test_SetData(); 1670 test_Allocator(); 1671 test_CreateMessage(); 1672 test_MessageSetProp(); 1673 test_MessageGetPropInfo(); 1674 test_MessageOptions(); 1675 test_BindToObject(); 1676 test_BodyDeleteProp(); 1677 test_MimeOleGetPropertySchema(); 1678 test_mhtml_message(); 1679 test_MimeOleObjectFromMoniker(); 1680 test_mhtml_protocol(); 1681 OleUninitialize(); 1682 } 1683