1 /* 2 * MIME OLE Interfaces 3 * 4 * Copyright 2006 Robert Shearman for CodeWeavers 5 * Copyright 2007 Huw Davies for CodeWeavers 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #define COBJMACROS 23 #define NONAMELESSUNION 24 25 #include <stdarg.h> 26 #include <stdio.h> 27 28 #include "windef.h" 29 #include "winbase.h" 30 #include "winuser.h" 31 #include "objbase.h" 32 #include "ole2.h" 33 #include "mimeole.h" 34 35 #include "wine/list.h" 36 #include "wine/debug.h" 37 38 #include "inetcomm_private.h" 39 40 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm); 41 42 typedef struct 43 { 44 LPCSTR name; 45 DWORD id; 46 DWORD flags; /* MIMEPROPFLAGS */ 47 VARTYPE default_vt; 48 } property_t; 49 50 typedef struct 51 { 52 struct list entry; 53 property_t prop; 54 } property_list_entry_t; 55 56 static const property_t default_props[] = 57 { 58 {"References", PID_HDR_REFS, 0, VT_LPSTR}, 59 {"Subject", PID_HDR_SUBJECT, 0, VT_LPSTR}, 60 {"From", PID_HDR_FROM, MPF_ADDRESS, VT_LPSTR}, 61 {"Message-ID", PID_HDR_MESSAGEID, 0, VT_LPSTR}, 62 {"Return-Path", PID_HDR_RETURNPATH, MPF_ADDRESS, VT_LPSTR}, 63 {"Date", PID_HDR_DATE, 0, VT_LPSTR}, 64 {"Received", PID_HDR_RECEIVED, 0, VT_LPSTR}, 65 {"Reply-To", PID_HDR_REPLYTO, MPF_ADDRESS, VT_LPSTR}, 66 {"X-Mailer", PID_HDR_XMAILER, 0, VT_LPSTR}, 67 {"Bcc", PID_HDR_BCC, MPF_ADDRESS, VT_LPSTR}, 68 {"MIME-Version", PID_HDR_MIMEVER, MPF_MIME, VT_LPSTR}, 69 {"Content-Type", PID_HDR_CNTTYPE, MPF_MIME | MPF_HASPARAMS, VT_LPSTR}, 70 {"Content-Transfer-Encoding", PID_HDR_CNTXFER, MPF_MIME, VT_LPSTR}, 71 {"Content-ID", PID_HDR_CNTID, MPF_MIME, VT_LPSTR}, 72 {"Content-Disposition", PID_HDR_CNTDISP, MPF_MIME | MPF_HASPARAMS, VT_LPSTR}, 73 {"To", PID_HDR_TO, MPF_ADDRESS, VT_LPSTR}, 74 {"Cc", PID_HDR_CC, MPF_ADDRESS, VT_LPSTR}, 75 {"Sender", PID_HDR_SENDER, MPF_ADDRESS, VT_LPSTR}, 76 {"In-Reply-To", PID_HDR_INREPLYTO, 0, VT_LPSTR}, 77 {NULL, 0, 0, 0} 78 }; 79 80 typedef struct 81 { 82 struct list entry; 83 char *name; 84 char *value; 85 } param_t; 86 87 typedef struct 88 { 89 struct list entry; 90 const property_t *prop; 91 PROPVARIANT value; 92 struct list params; 93 } header_t; 94 95 typedef struct MimeBody 96 { 97 const IMimeBodyVtbl *lpVtbl; 98 LONG refs; 99 100 HBODY handle; 101 102 struct list headers; 103 struct list new_props; /* FIXME: This should be in a PropertySchema */ 104 DWORD next_prop_id; 105 char *content_pri_type; 106 char *content_sub_type; 107 ENCODINGTYPE encoding; 108 void *data; 109 IID data_iid; 110 BODYOFFSETS body_offsets; 111 } MimeBody; 112 113 static inline MimeBody *impl_from_IMimeBody( IMimeBody *iface ) 114 { 115 return (MimeBody *)((char*)iface - FIELD_OFFSET(MimeBody, lpVtbl)); 116 } 117 118 static LPSTR strdupA(LPCSTR str) 119 { 120 char *ret; 121 int len = strlen(str); 122 ret = HeapAlloc(GetProcessHeap(), 0, len + 1); 123 memcpy(ret, str, len + 1); 124 return ret; 125 } 126 127 #define PARSER_BUF_SIZE 1024 128 129 /***************************************************** 130 * copy_headers_to_buf [internal] 131 * 132 * Copies the headers into a '\0' terminated memory block and leave 133 * the stream's current position set to after the blank line. 134 */ 135 static HRESULT copy_headers_to_buf(IStream *stm, char **ptr) 136 { 137 char *buf = NULL; 138 DWORD size = PARSER_BUF_SIZE, offset = 0, last_end = 0; 139 HRESULT hr; 140 int done = 0; 141 142 *ptr = NULL; 143 144 do 145 { 146 char *end; 147 DWORD read; 148 149 if(!buf) 150 buf = HeapAlloc(GetProcessHeap(), 0, size + 1); 151 else 152 { 153 size *= 2; 154 buf = HeapReAlloc(GetProcessHeap(), 0, buf, size + 1); 155 } 156 if(!buf) 157 { 158 hr = E_OUTOFMEMORY; 159 goto fail; 160 } 161 162 hr = IStream_Read(stm, buf + offset, size - offset, &read); 163 if(FAILED(hr)) goto fail; 164 165 offset += read; 166 buf[offset] = '\0'; 167 168 if(read == 0) done = 1; 169 170 while(!done && (end = strstr(buf + last_end, "\r\n"))) 171 { 172 DWORD new_end = end - buf + 2; 173 if(new_end - last_end == 2) 174 { 175 LARGE_INTEGER off; 176 off.QuadPart = new_end; 177 IStream_Seek(stm, off, STREAM_SEEK_SET, NULL); 178 buf[new_end] = '\0'; 179 done = 1; 180 } 181 else 182 last_end = new_end; 183 } 184 } while(!done); 185 186 *ptr = buf; 187 return S_OK; 188 189 fail: 190 HeapFree(GetProcessHeap(), 0, buf); 191 return hr; 192 } 193 194 static header_t *read_prop(MimeBody *body, char **ptr) 195 { 196 char *colon = strchr(*ptr, ':'); 197 const property_t *prop; 198 header_t *ret; 199 200 if(!colon) return NULL; 201 202 *colon = '\0'; 203 204 for(prop = default_props; prop->name; prop++) 205 { 206 if(!strcasecmp(*ptr, prop->name)) 207 { 208 TRACE("%s: found match with default property id %d\n", *ptr, prop->id); 209 break; 210 } 211 } 212 213 if(!prop->name) 214 { 215 property_list_entry_t *prop_entry; 216 LIST_FOR_EACH_ENTRY(prop_entry, &body->new_props, property_list_entry_t, entry) 217 { 218 if(!strcasecmp(*ptr, prop_entry->prop.name)) 219 { 220 TRACE("%s: found match with already added new property id %d\n", *ptr, prop_entry->prop.id); 221 prop = &prop_entry->prop; 222 break; 223 } 224 } 225 if(!prop->name) 226 { 227 prop_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry)); 228 prop_entry->prop.name = strdupA(*ptr); 229 prop_entry->prop.id = body->next_prop_id++; 230 prop_entry->prop.flags = 0; 231 prop_entry->prop.default_vt = VT_LPSTR; 232 list_add_tail(&body->new_props, &prop_entry->entry); 233 prop = &prop_entry->prop; 234 TRACE("%s: allocating new prop id %d\n", *ptr, prop_entry->prop.id); 235 } 236 } 237 238 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret)); 239 ret->prop = prop; 240 PropVariantInit(&ret->value); 241 list_init(&ret->params); 242 *ptr = colon + 1; 243 244 return ret; 245 } 246 247 static void unfold_header(char *header, int len) 248 { 249 char *start = header, *cp = header; 250 251 do { 252 while(*cp == ' ' || *cp == '\t') 253 { 254 cp++; 255 len--; 256 } 257 if(cp != start) 258 memmove(start, cp, len + 1); 259 260 cp = strstr(start, "\r\n"); 261 len -= (cp - start); 262 start = cp; 263 *start = ' '; 264 start++; 265 len--; 266 cp += 2; 267 } while(*cp == ' ' || *cp == '\t'); 268 269 *(start - 1) = '\0'; 270 } 271 272 static char *unquote_string(const char *str) 273 { 274 int quoted = 0; 275 char *ret, *cp; 276 277 while(*str == ' ' || *str == '\t') str++; 278 279 if(*str == '"') 280 { 281 quoted = 1; 282 str++; 283 } 284 ret = strdupA(str); 285 for(cp = ret; *cp; cp++) 286 { 287 if(*cp == '\\') 288 memmove(cp, cp + 1, strlen(cp + 1) + 1); 289 else if(*cp == '"') 290 { 291 if(!quoted) 292 { 293 WARN("quote in unquoted string\n"); 294 } 295 else 296 { 297 *cp = '\0'; 298 break; 299 } 300 } 301 } 302 return ret; 303 } 304 305 static void add_param(header_t *header, const char *p) 306 { 307 const char *key = p, *value, *cp = p; 308 param_t *param; 309 char *name; 310 311 TRACE("got param %s\n", p); 312 313 while (*key == ' ' || *key == '\t' ) key++; 314 315 cp = strchr(key, '='); 316 if(!cp) 317 { 318 WARN("malformed parameter - skipping\n"); 319 return; 320 } 321 322 name = HeapAlloc(GetProcessHeap(), 0, cp - key + 1); 323 memcpy(name, key, cp - key); 324 name[cp - key] = '\0'; 325 326 value = cp + 1; 327 328 param = HeapAlloc(GetProcessHeap(), 0, sizeof(*param)); 329 param->name = name; 330 param->value = unquote_string(value); 331 list_add_tail(&header->params, ¶m->entry); 332 } 333 334 static void split_params(header_t *header, char *value) 335 { 336 char *cp = value, *start = value; 337 int in_quote = 0; 338 int done_value = 0; 339 340 while(*cp) 341 { 342 if(!in_quote && *cp == ';') 343 { 344 *cp = '\0'; 345 if(done_value) add_param(header, start); 346 done_value = 1; 347 start = cp + 1; 348 } 349 else if(*cp == '"') 350 in_quote = !in_quote; 351 cp++; 352 } 353 if(done_value) add_param(header, start); 354 } 355 356 static void read_value(header_t *header, char **cur) 357 { 358 char *end = *cur, *value; 359 DWORD len; 360 361 do { 362 end = strstr(end, "\r\n"); 363 end += 2; 364 } while(*end == ' ' || *end == '\t'); 365 366 len = end - *cur; 367 value = HeapAlloc(GetProcessHeap(), 0, len + 1); 368 memcpy(value, *cur, len); 369 value[len] = '\0'; 370 371 unfold_header(value, len); 372 TRACE("value %s\n", debugstr_a(value)); 373 374 if(header->prop->flags & MPF_HASPARAMS) 375 { 376 split_params(header, value); 377 TRACE("value w/o params %s\n", debugstr_a(value)); 378 } 379 380 header->value.vt = VT_LPSTR; 381 header->value.u.pszVal = value; 382 383 *cur = end; 384 } 385 386 static void init_content_type(MimeBody *body, header_t *header) 387 { 388 char *slash; 389 DWORD len; 390 391 if(header->prop->id != PID_HDR_CNTTYPE) 392 { 393 ERR("called with header %s\n", header->prop->name); 394 return; 395 } 396 397 slash = strchr(header->value.u.pszVal, '/'); 398 if(!slash) 399 { 400 WARN("malformed context type value\n"); 401 return; 402 } 403 len = slash - header->value.u.pszVal; 404 body->content_pri_type = HeapAlloc(GetProcessHeap(), 0, len + 1); 405 memcpy(body->content_pri_type, header->value.u.pszVal, len); 406 body->content_pri_type[len] = '\0'; 407 body->content_sub_type = strdupA(slash + 1); 408 } 409 410 static HRESULT parse_headers(MimeBody *body, IStream *stm) 411 { 412 char *header_buf, *cur_header_ptr; 413 HRESULT hr; 414 header_t *header; 415 416 hr = copy_headers_to_buf(stm, &header_buf); 417 if(FAILED(hr)) return hr; 418 419 cur_header_ptr = header_buf; 420 while((header = read_prop(body, &cur_header_ptr))) 421 { 422 read_value(header, &cur_header_ptr); 423 list_add_tail(&body->headers, &header->entry); 424 425 if(header->prop->id == PID_HDR_CNTTYPE) 426 init_content_type(body, header); 427 } 428 429 HeapFree(GetProcessHeap(), 0, header_buf); 430 return hr; 431 } 432 433 static void empty_param_list(struct list *list) 434 { 435 param_t *param, *cursor2; 436 437 LIST_FOR_EACH_ENTRY_SAFE(param, cursor2, list, param_t, entry) 438 { 439 list_remove(¶m->entry); 440 HeapFree(GetProcessHeap(), 0, param->name); 441 HeapFree(GetProcessHeap(), 0, param->value); 442 HeapFree(GetProcessHeap(), 0, param); 443 } 444 } 445 446 static void empty_header_list(struct list *list) 447 { 448 header_t *header, *cursor2; 449 450 LIST_FOR_EACH_ENTRY_SAFE(header, cursor2, list, header_t, entry) 451 { 452 list_remove(&header->entry); 453 PropVariantClear(&header->value); 454 empty_param_list(&header->params); 455 HeapFree(GetProcessHeap(), 0, header); 456 } 457 } 458 459 static void empty_new_prop_list(struct list *list) 460 { 461 property_list_entry_t *prop, *cursor2; 462 463 LIST_FOR_EACH_ENTRY_SAFE(prop, cursor2, list, property_list_entry_t, entry) 464 { 465 list_remove(&prop->entry); 466 HeapFree(GetProcessHeap(), 0, (char *)prop->prop.name); 467 HeapFree(GetProcessHeap(), 0, prop); 468 } 469 } 470 471 static void release_data(REFIID riid, void *data) 472 { 473 if(!data) return; 474 475 if(IsEqualIID(riid, &IID_IStream)) 476 IStream_Release((IStream *)data); 477 else 478 FIXME("Unhandled data format %s\n", debugstr_guid(riid)); 479 } 480 481 static HRESULT find_prop(MimeBody *body, const char *name, header_t **prop) 482 { 483 header_t *header; 484 485 *prop = NULL; 486 487 LIST_FOR_EACH_ENTRY(header, &body->headers, header_t, entry) 488 { 489 if(!strcasecmp(name, header->prop->name)) 490 { 491 *prop = header; 492 return S_OK; 493 } 494 } 495 496 return MIME_E_NOT_FOUND; 497 } 498 499 static HRESULT WINAPI MimeBody_QueryInterface(IMimeBody* iface, 500 REFIID riid, 501 void** ppvObject) 502 { 503 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppvObject); 504 505 *ppvObject = NULL; 506 507 if (IsEqualIID(riid, &IID_IUnknown) || 508 IsEqualIID(riid, &IID_IPersist) || 509 IsEqualIID(riid, &IID_IPersistStreamInit) || 510 IsEqualIID(riid, &IID_IMimePropertySet) || 511 IsEqualIID(riid, &IID_IMimeBody)) 512 { 513 *ppvObject = iface; 514 } 515 516 if(*ppvObject) 517 { 518 IUnknown_AddRef((IUnknown*)*ppvObject); 519 return S_OK; 520 } 521 522 FIXME("no interface for %s\n", debugstr_guid(riid)); 523 return E_NOINTERFACE; 524 } 525 526 static ULONG WINAPI MimeBody_AddRef(IMimeBody* iface) 527 { 528 MimeBody *This = impl_from_IMimeBody(iface); 529 TRACE("(%p)->()\n", iface); 530 return InterlockedIncrement(&This->refs); 531 } 532 533 static ULONG WINAPI MimeBody_Release(IMimeBody* iface) 534 { 535 MimeBody *This = impl_from_IMimeBody(iface); 536 ULONG refs; 537 538 TRACE("(%p)->()\n", iface); 539 540 refs = InterlockedDecrement(&This->refs); 541 if (!refs) 542 { 543 empty_header_list(&This->headers); 544 empty_new_prop_list(&This->new_props); 545 546 HeapFree(GetProcessHeap(), 0, This->content_pri_type); 547 HeapFree(GetProcessHeap(), 0, This->content_sub_type); 548 549 release_data(&This->data_iid, This->data); 550 551 HeapFree(GetProcessHeap(), 0, This); 552 } 553 554 return refs; 555 } 556 557 static HRESULT WINAPI MimeBody_GetClassID( 558 IMimeBody* iface, 559 CLSID* pClassID) 560 { 561 FIXME("stub\n"); 562 return E_NOTIMPL; 563 } 564 565 566 static HRESULT WINAPI MimeBody_IsDirty( 567 IMimeBody* iface) 568 { 569 FIXME("stub\n"); 570 return E_NOTIMPL; 571 } 572 573 static HRESULT WINAPI MimeBody_Load( 574 IMimeBody* iface, 575 LPSTREAM pStm) 576 { 577 MimeBody *This = impl_from_IMimeBody(iface); 578 TRACE("(%p)->(%p)\n", iface, pStm); 579 return parse_headers(This, pStm); 580 } 581 582 static HRESULT WINAPI MimeBody_Save( 583 IMimeBody* iface, 584 LPSTREAM pStm, 585 BOOL fClearDirty) 586 { 587 FIXME("stub\n"); 588 return E_NOTIMPL; 589 } 590 591 static HRESULT WINAPI MimeBody_GetSizeMax( 592 IMimeBody* iface, 593 ULARGE_INTEGER* pcbSize) 594 { 595 FIXME("stub\n"); 596 return E_NOTIMPL; 597 } 598 599 static HRESULT WINAPI MimeBody_InitNew( 600 IMimeBody* iface) 601 { 602 TRACE("%p->()\n", iface); 603 return S_OK; 604 } 605 606 static HRESULT WINAPI MimeBody_GetPropInfo( 607 IMimeBody* iface, 608 LPCSTR pszName, 609 LPMIMEPROPINFO pInfo) 610 { 611 FIXME("stub\n"); 612 return E_NOTIMPL; 613 } 614 615 static HRESULT WINAPI MimeBody_SetPropInfo( 616 IMimeBody* iface, 617 LPCSTR pszName, 618 LPCMIMEPROPINFO pInfo) 619 { 620 FIXME("stub\n"); 621 return E_NOTIMPL; 622 } 623 624 static HRESULT WINAPI MimeBody_GetProp( 625 IMimeBody* iface, 626 LPCSTR pszName, 627 DWORD dwFlags, 628 LPPROPVARIANT pValue) 629 { 630 MimeBody *This = impl_from_IMimeBody(iface); 631 TRACE("(%p)->(%s, %d, %p)\n", This, pszName, dwFlags, pValue); 632 633 if(!strcasecmp(pszName, "att:pri-content-type")) 634 { 635 PropVariantClear(pValue); 636 pValue->vt = VT_LPSTR; 637 pValue->u.pszVal = strdupA(This->content_pri_type); 638 return S_OK; 639 } 640 641 FIXME("stub!\n"); 642 return E_FAIL; 643 } 644 645 static HRESULT WINAPI MimeBody_SetProp( 646 IMimeBody* iface, 647 LPCSTR pszName, 648 DWORD dwFlags, 649 LPCPROPVARIANT pValue) 650 { 651 FIXME("stub\n"); 652 return E_NOTIMPL; 653 } 654 655 static HRESULT WINAPI MimeBody_AppendProp( 656 IMimeBody* iface, 657 LPCSTR pszName, 658 DWORD dwFlags, 659 LPPROPVARIANT pValue) 660 { 661 FIXME("stub\n"); 662 return E_NOTIMPL; 663 } 664 665 static HRESULT WINAPI MimeBody_DeleteProp( 666 IMimeBody* iface, 667 LPCSTR pszName) 668 { 669 FIXME("stub\n"); 670 return E_NOTIMPL; 671 } 672 673 static HRESULT WINAPI MimeBody_CopyProps( 674 IMimeBody* iface, 675 ULONG cNames, 676 LPCSTR* prgszName, 677 IMimePropertySet* pPropertySet) 678 { 679 FIXME("stub\n"); 680 return E_NOTIMPL; 681 } 682 683 static HRESULT WINAPI MimeBody_MoveProps( 684 IMimeBody* iface, 685 ULONG cNames, 686 LPCSTR* prgszName, 687 IMimePropertySet* pPropertySet) 688 { 689 FIXME("stub\n"); 690 return E_NOTIMPL; 691 } 692 693 static HRESULT WINAPI MimeBody_DeleteExcept( 694 IMimeBody* iface, 695 ULONG cNames, 696 LPCSTR* prgszName) 697 { 698 FIXME("stub\n"); 699 return E_NOTIMPL; 700 } 701 702 static HRESULT WINAPI MimeBody_QueryProp( 703 IMimeBody* iface, 704 LPCSTR pszName, 705 LPCSTR pszCriteria, 706 boolean fSubString, 707 boolean fCaseSensitive) 708 { 709 FIXME("stub\n"); 710 return E_NOTIMPL; 711 } 712 713 static HRESULT WINAPI MimeBody_GetCharset( 714 IMimeBody* iface, 715 LPHCHARSET phCharset) 716 { 717 FIXME("stub\n"); 718 *phCharset = NULL; 719 return S_OK; 720 } 721 722 static HRESULT WINAPI MimeBody_SetCharset( 723 IMimeBody* iface, 724 HCHARSET hCharset, 725 CSETAPPLYTYPE applytype) 726 { 727 FIXME("stub\n"); 728 return E_NOTIMPL; 729 } 730 731 static HRESULT WINAPI MimeBody_GetParameters( 732 IMimeBody* iface, 733 LPCSTR pszName, 734 ULONG* pcParams, 735 LPMIMEPARAMINFO* pprgParam) 736 { 737 MimeBody *This = impl_from_IMimeBody(iface); 738 HRESULT hr; 739 header_t *header; 740 741 TRACE("(%p)->(%s, %p, %p)\n", iface, debugstr_a(pszName), pcParams, pprgParam); 742 743 *pprgParam = NULL; 744 *pcParams = 0; 745 746 hr = find_prop(This, pszName, &header); 747 if(hr != S_OK) return hr; 748 749 *pcParams = list_count(&header->params); 750 if(*pcParams) 751 { 752 IMimeAllocator *alloc; 753 param_t *param; 754 MIMEPARAMINFO *info; 755 756 MimeOleGetAllocator(&alloc); 757 758 *pprgParam = info = IMimeAllocator_Alloc(alloc, *pcParams * sizeof(**pprgParam)); 759 LIST_FOR_EACH_ENTRY(param, &header->params, param_t, entry) 760 { 761 int len; 762 763 len = strlen(param->name) + 1; 764 info->pszName = IMimeAllocator_Alloc(alloc, len); 765 memcpy(info->pszName, param->name, len); 766 len = strlen(param->value) + 1; 767 info->pszData = IMimeAllocator_Alloc(alloc, len); 768 memcpy(info->pszData, param->value, len); 769 info++; 770 } 771 IMimeAllocator_Release(alloc); 772 } 773 return S_OK; 774 } 775 776 static HRESULT WINAPI MimeBody_IsContentType( 777 IMimeBody* iface, 778 LPCSTR pszPriType, 779 LPCSTR pszSubType) 780 { 781 MimeBody *This = impl_from_IMimeBody(iface); 782 783 TRACE("(%p)->(%s, %s)\n", This, debugstr_a(pszPriType), debugstr_a(pszSubType)); 784 if(pszPriType) 785 { 786 const char *pri = This->content_pri_type; 787 if(!pri) pri = "text"; 788 if(strcasecmp(pri, pszPriType)) return S_FALSE; 789 } 790 791 if(pszSubType) 792 { 793 const char *sub = This->content_sub_type; 794 if(!sub) sub = "plain"; 795 if(strcasecmp(sub, pszSubType)) return S_FALSE; 796 } 797 798 return S_OK; 799 } 800 801 static HRESULT WINAPI MimeBody_BindToObject( 802 IMimeBody* iface, 803 REFIID riid, 804 void** ppvObject) 805 { 806 FIXME("stub\n"); 807 return E_NOTIMPL; 808 } 809 810 static HRESULT WINAPI MimeBody_Clone( 811 IMimeBody* iface, 812 IMimePropertySet** ppPropertySet) 813 { 814 FIXME("stub\n"); 815 return E_NOTIMPL; 816 } 817 818 static HRESULT WINAPI MimeBody_SetOption( 819 IMimeBody* iface, 820 const TYPEDID oid, 821 LPCPROPVARIANT pValue) 822 { 823 HRESULT hr = E_NOTIMPL; 824 TRACE("(%p)->(%08x, %p)\n", iface, oid, pValue); 825 826 if(pValue->vt != TYPEDID_TYPE(oid)) 827 { 828 WARN("Called with vartype %04x and oid %08x\n", pValue->vt, oid); 829 return E_INVALIDARG; 830 } 831 832 switch(oid) 833 { 834 case OID_SECURITY_HWND_OWNER: 835 FIXME("OID_SECURITY_HWND_OWNER (value %08x): ignoring\n", pValue->u.ulVal); 836 hr = S_OK; 837 break; 838 default: 839 FIXME("Unhandled oid %08x\n", oid); 840 } 841 842 return hr; 843 } 844 845 static HRESULT WINAPI MimeBody_GetOption( 846 IMimeBody* iface, 847 const TYPEDID oid, 848 LPPROPVARIANT pValue) 849 { 850 FIXME("(%p)->(%08x, %p): stub\n", iface, oid, pValue); 851 return E_NOTIMPL; 852 } 853 854 static HRESULT WINAPI MimeBody_EnumProps( 855 IMimeBody* iface, 856 DWORD dwFlags, 857 IMimeEnumProperties** ppEnum) 858 { 859 FIXME("stub\n"); 860 return E_NOTIMPL; 861 } 862 863 static HRESULT WINAPI MimeBody_IsType( 864 IMimeBody* iface, 865 IMSGBODYTYPE bodytype) 866 { 867 MimeBody *This = impl_from_IMimeBody(iface); 868 869 TRACE("(%p)->(%d)\n", iface, bodytype); 870 switch(bodytype) 871 { 872 case IBT_EMPTY: 873 return This->data ? S_FALSE : S_OK; 874 default: 875 FIXME("Unimplemented bodytype %d - returning S_OK\n", bodytype); 876 } 877 return S_OK; 878 } 879 880 static HRESULT WINAPI MimeBody_SetDisplayName( 881 IMimeBody* iface, 882 LPCSTR pszDisplay) 883 { 884 FIXME("stub\n"); 885 return E_NOTIMPL; 886 } 887 888 static HRESULT WINAPI MimeBody_GetDisplayName( 889 IMimeBody* iface, 890 LPSTR* ppszDisplay) 891 { 892 FIXME("stub\n"); 893 return E_NOTIMPL; 894 } 895 896 static HRESULT WINAPI MimeBody_GetOffsets( 897 IMimeBody* iface, 898 LPBODYOFFSETS pOffsets) 899 { 900 MimeBody *This = impl_from_IMimeBody(iface); 901 TRACE("(%p)->(%p)\n", This, pOffsets); 902 903 *pOffsets = This->body_offsets; 904 905 if(This->body_offsets.cbBodyEnd == 0) return MIME_E_NO_DATA; 906 return S_OK; 907 } 908 909 static HRESULT WINAPI MimeBody_GetCurrentEncoding( 910 IMimeBody* iface, 911 ENCODINGTYPE* pietEncoding) 912 { 913 MimeBody *This = impl_from_IMimeBody(iface); 914 915 TRACE("(%p)->(%p)\n", This, pietEncoding); 916 917 *pietEncoding = This->encoding; 918 return S_OK; 919 } 920 921 static HRESULT WINAPI MimeBody_SetCurrentEncoding( 922 IMimeBody* iface, 923 ENCODINGTYPE ietEncoding) 924 { 925 MimeBody *This = impl_from_IMimeBody(iface); 926 927 TRACE("(%p)->(%d)\n", This, ietEncoding); 928 929 This->encoding = ietEncoding; 930 return S_OK; 931 } 932 933 static HRESULT WINAPI MimeBody_GetEstimatedSize( 934 IMimeBody* iface, 935 ENCODINGTYPE ietEncoding, 936 ULONG* pcbSize) 937 { 938 FIXME("stub\n"); 939 return E_NOTIMPL; 940 } 941 942 static HRESULT WINAPI MimeBody_GetDataHere( 943 IMimeBody* iface, 944 ENCODINGTYPE ietEncoding, 945 IStream* pStream) 946 { 947 FIXME("stub\n"); 948 return E_NOTIMPL; 949 } 950 951 static HRESULT WINAPI MimeBody_GetData( 952 IMimeBody* iface, 953 ENCODINGTYPE ietEncoding, 954 IStream** ppStream) 955 { 956 MimeBody *This = impl_from_IMimeBody(iface); 957 FIXME("(%p)->(%d, %p). Ignoring encoding type.\n", This, ietEncoding, ppStream); 958 959 *ppStream = This->data; 960 IStream_AddRef(*ppStream); 961 return S_OK; 962 } 963 964 static HRESULT WINAPI MimeBody_SetData( 965 IMimeBody* iface, 966 ENCODINGTYPE ietEncoding, 967 LPCSTR pszPriType, 968 LPCSTR pszSubType, 969 REFIID riid, 970 LPVOID pvObject) 971 { 972 MimeBody *This = impl_from_IMimeBody(iface); 973 TRACE("(%p)->(%d, %s, %s, %s %p)\n", This, ietEncoding, debugstr_a(pszPriType), debugstr_a(pszSubType), 974 debugstr_guid(riid), pvObject); 975 976 if(IsEqualIID(riid, &IID_IStream)) 977 IStream_AddRef((IStream *)pvObject); 978 else 979 { 980 FIXME("Unhandled object type %s\n", debugstr_guid(riid)); 981 return E_INVALIDARG; 982 } 983 984 if(This->data) 985 FIXME("release old data\n"); 986 987 This->data_iid = *riid; 988 This->data = pvObject; 989 990 IMimeBody_SetCurrentEncoding(iface, ietEncoding); 991 992 /* FIXME: Update the content type. 993 If pszPriType == NULL use 'application' 994 If pszSubType == NULL use 'octet-stream' */ 995 996 return S_OK; 997 } 998 999 static HRESULT WINAPI MimeBody_EmptyData( 1000 IMimeBody* iface) 1001 { 1002 FIXME("stub\n"); 1003 return E_NOTIMPL; 1004 } 1005 1006 static HRESULT WINAPI MimeBody_CopyTo( 1007 IMimeBody* iface, 1008 IMimeBody* pBody) 1009 { 1010 FIXME("stub\n"); 1011 return E_NOTIMPL; 1012 } 1013 1014 static HRESULT WINAPI MimeBody_GetTransmitInfo( 1015 IMimeBody* iface, 1016 LPTRANSMITINFO pTransmitInfo) 1017 { 1018 FIXME("stub\n"); 1019 return E_NOTIMPL; 1020 } 1021 1022 static HRESULT WINAPI MimeBody_SaveToFile( 1023 IMimeBody* iface, 1024 ENCODINGTYPE ietEncoding, 1025 LPCSTR pszFilePath) 1026 { 1027 FIXME("stub\n"); 1028 return E_NOTIMPL; 1029 } 1030 1031 static HRESULT WINAPI MimeBody_GetHandle( 1032 IMimeBody* iface, 1033 LPHBODY phBody) 1034 { 1035 MimeBody *This = impl_from_IMimeBody(iface); 1036 TRACE("(%p)->(%p)\n", iface, phBody); 1037 1038 *phBody = This->handle; 1039 return This->handle ? S_OK : MIME_E_NO_DATA; 1040 } 1041 1042 static IMimeBodyVtbl body_vtbl = 1043 { 1044 MimeBody_QueryInterface, 1045 MimeBody_AddRef, 1046 MimeBody_Release, 1047 MimeBody_GetClassID, 1048 MimeBody_IsDirty, 1049 MimeBody_Load, 1050 MimeBody_Save, 1051 MimeBody_GetSizeMax, 1052 MimeBody_InitNew, 1053 MimeBody_GetPropInfo, 1054 MimeBody_SetPropInfo, 1055 MimeBody_GetProp, 1056 MimeBody_SetProp, 1057 MimeBody_AppendProp, 1058 MimeBody_DeleteProp, 1059 MimeBody_CopyProps, 1060 MimeBody_MoveProps, 1061 MimeBody_DeleteExcept, 1062 MimeBody_QueryProp, 1063 MimeBody_GetCharset, 1064 MimeBody_SetCharset, 1065 MimeBody_GetParameters, 1066 MimeBody_IsContentType, 1067 MimeBody_BindToObject, 1068 MimeBody_Clone, 1069 MimeBody_SetOption, 1070 MimeBody_GetOption, 1071 MimeBody_EnumProps, 1072 MimeBody_IsType, 1073 MimeBody_SetDisplayName, 1074 MimeBody_GetDisplayName, 1075 MimeBody_GetOffsets, 1076 MimeBody_GetCurrentEncoding, 1077 MimeBody_SetCurrentEncoding, 1078 MimeBody_GetEstimatedSize, 1079 MimeBody_GetDataHere, 1080 MimeBody_GetData, 1081 MimeBody_SetData, 1082 MimeBody_EmptyData, 1083 MimeBody_CopyTo, 1084 MimeBody_GetTransmitInfo, 1085 MimeBody_SaveToFile, 1086 MimeBody_GetHandle 1087 }; 1088 1089 static HRESULT MimeBody_set_offsets(MimeBody *body, const BODYOFFSETS *offsets) 1090 { 1091 TRACE("setting offsets to %d, %d, %d, %d\n", offsets->cbBoundaryStart, 1092 offsets->cbHeaderStart, offsets->cbBodyStart, offsets->cbBodyEnd); 1093 1094 body->body_offsets = *offsets; 1095 return S_OK; 1096 } 1097 1098 #define FIRST_CUSTOM_PROP_ID 0x100 1099 1100 HRESULT MimeBody_create(IUnknown *outer, void **obj) 1101 { 1102 MimeBody *This; 1103 BODYOFFSETS body_offsets; 1104 1105 *obj = NULL; 1106 1107 if(outer) return CLASS_E_NOAGGREGATION; 1108 1109 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 1110 if (!This) return E_OUTOFMEMORY; 1111 1112 This->lpVtbl = &body_vtbl; 1113 This->refs = 1; 1114 This->handle = NULL; 1115 list_init(&This->headers); 1116 list_init(&This->new_props); 1117 This->next_prop_id = FIRST_CUSTOM_PROP_ID; 1118 This->content_pri_type = NULL; 1119 This->content_sub_type = NULL; 1120 This->encoding = IET_7BIT; 1121 This->data = NULL; 1122 This->data_iid = IID_NULL; 1123 1124 body_offsets.cbBoundaryStart = body_offsets.cbHeaderStart = 0; 1125 body_offsets.cbBodyStart = body_offsets.cbBodyEnd = 0; 1126 MimeBody_set_offsets(This, &body_offsets); 1127 1128 *obj = &This->lpVtbl; 1129 return S_OK; 1130 } 1131 1132 typedef struct 1133 { 1134 IStreamVtbl *lpVtbl; 1135 LONG refs; 1136 1137 IStream *base; 1138 ULARGE_INTEGER pos, start, length; 1139 } sub_stream_t; 1140 1141 static inline sub_stream_t *impl_from_IStream( IStream *iface ) 1142 { 1143 return (sub_stream_t *)((char*)iface - FIELD_OFFSET(sub_stream_t, lpVtbl)); 1144 } 1145 1146 static HRESULT WINAPI sub_stream_QueryInterface( 1147 IStream* iface, 1148 REFIID riid, 1149 void **ppvObject) 1150 { 1151 sub_stream_t *This = impl_from_IStream(iface); 1152 1153 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject); 1154 *ppvObject = NULL; 1155 1156 if(IsEqualIID(riid, &IID_IUnknown) || 1157 IsEqualIID(riid, &IID_ISequentialStream) || 1158 IsEqualIID(riid, &IID_IStream)) 1159 { 1160 IStream_AddRef(iface); 1161 *ppvObject = iface; 1162 return S_OK; 1163 } 1164 return E_NOINTERFACE; 1165 } 1166 1167 static ULONG WINAPI sub_stream_AddRef( 1168 IStream* iface) 1169 { 1170 sub_stream_t *This = impl_from_IStream(iface); 1171 1172 TRACE("(%p)\n", This); 1173 return InterlockedIncrement(&This->refs); 1174 } 1175 1176 static ULONG WINAPI sub_stream_Release( 1177 IStream* iface) 1178 { 1179 sub_stream_t *This = impl_from_IStream(iface); 1180 LONG refs; 1181 1182 TRACE("(%p)\n", This); 1183 refs = InterlockedDecrement(&This->refs); 1184 if(!refs) 1185 { 1186 IStream_Release(This->base); 1187 HeapFree(GetProcessHeap(), 0, This); 1188 } 1189 return refs; 1190 } 1191 1192 static HRESULT WINAPI sub_stream_Read( 1193 IStream* iface, 1194 void *pv, 1195 ULONG cb, 1196 ULONG *pcbRead) 1197 { 1198 sub_stream_t *This = impl_from_IStream(iface); 1199 HRESULT hr; 1200 ULARGE_INTEGER base_pos; 1201 LARGE_INTEGER tmp_pos; 1202 1203 TRACE("(%p, %d, %p)\n", pv, cb, pcbRead); 1204 1205 tmp_pos.QuadPart = 0; 1206 IStream_Seek(This->base, tmp_pos, STREAM_SEEK_CUR, &base_pos); 1207 tmp_pos.QuadPart = This->pos.QuadPart + This->start.QuadPart; 1208 IStream_Seek(This->base, tmp_pos, STREAM_SEEK_SET, NULL); 1209 1210 if(This->pos.QuadPart + cb > This->length.QuadPart) 1211 cb = This->length.QuadPart - This->pos.QuadPart; 1212 1213 hr = IStream_Read(This->base, pv, cb, pcbRead); 1214 1215 This->pos.QuadPart += *pcbRead; 1216 1217 tmp_pos.QuadPart = base_pos.QuadPart; 1218 IStream_Seek(This->base, tmp_pos, STREAM_SEEK_SET, NULL); 1219 1220 return hr; 1221 } 1222 1223 static HRESULT WINAPI sub_stream_Write( 1224 IStream* iface, 1225 const void *pv, 1226 ULONG cb, 1227 ULONG *pcbWritten) 1228 { 1229 FIXME("stub\n"); 1230 return E_NOTIMPL; 1231 } 1232 1233 static HRESULT WINAPI sub_stream_Seek( 1234 IStream* iface, 1235 LARGE_INTEGER dlibMove, 1236 DWORD dwOrigin, 1237 ULARGE_INTEGER *plibNewPosition) 1238 { 1239 sub_stream_t *This = impl_from_IStream(iface); 1240 LARGE_INTEGER new_pos; 1241 1242 TRACE("(%08x.%08x, %x, %p)\n", dlibMove.u.HighPart, dlibMove.u.LowPart, dwOrigin, plibNewPosition); 1243 1244 switch(dwOrigin) 1245 { 1246 case STREAM_SEEK_SET: 1247 new_pos = dlibMove; 1248 break; 1249 case STREAM_SEEK_CUR: 1250 new_pos.QuadPart = This->pos.QuadPart + dlibMove.QuadPart; 1251 break; 1252 case STREAM_SEEK_END: 1253 new_pos.QuadPart = This->length.QuadPart + dlibMove.QuadPart; 1254 break; 1255 default: 1256 return STG_E_INVALIDFUNCTION; 1257 } 1258 1259 if(new_pos.QuadPart < 0) new_pos.QuadPart = 0; 1260 else if(new_pos.QuadPart > This->length.QuadPart) new_pos.QuadPart = This->length.QuadPart; 1261 1262 This->pos.QuadPart = new_pos.QuadPart; 1263 1264 if(plibNewPosition) *plibNewPosition = This->pos; 1265 return S_OK; 1266 } 1267 1268 static HRESULT WINAPI sub_stream_SetSize( 1269 IStream* iface, 1270 ULARGE_INTEGER libNewSize) 1271 { 1272 FIXME("stub\n"); 1273 return E_NOTIMPL; 1274 } 1275 1276 static HRESULT WINAPI sub_stream_CopyTo( 1277 IStream* iface, 1278 IStream *pstm, 1279 ULARGE_INTEGER cb, 1280 ULARGE_INTEGER *pcbRead, 1281 ULARGE_INTEGER *pcbWritten) 1282 { 1283 HRESULT hr = S_OK; 1284 BYTE tmpBuffer[128]; 1285 ULONG bytesRead, bytesWritten, copySize; 1286 ULARGE_INTEGER totalBytesRead; 1287 ULARGE_INTEGER totalBytesWritten; 1288 1289 TRACE("(%p)->(%p, %d, %p, %p)\n", iface, pstm, cb.u.LowPart, pcbRead, pcbWritten); 1290 1291 totalBytesRead.QuadPart = 0; 1292 totalBytesWritten.QuadPart = 0; 1293 1294 while ( cb.QuadPart > 0 ) 1295 { 1296 if ( cb.QuadPart >= sizeof(tmpBuffer) ) 1297 copySize = sizeof(tmpBuffer); 1298 else 1299 copySize = cb.u.LowPart; 1300 1301 hr = IStream_Read(iface, tmpBuffer, copySize, &bytesRead); 1302 if (FAILED(hr)) break; 1303 1304 totalBytesRead.QuadPart += bytesRead; 1305 1306 if (bytesRead) 1307 { 1308 hr = IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten); 1309 if (FAILED(hr)) break; 1310 totalBytesWritten.QuadPart += bytesWritten; 1311 } 1312 1313 if (bytesRead != copySize) 1314 cb.QuadPart = 0; 1315 else 1316 cb.QuadPart -= bytesRead; 1317 } 1318 1319 if (pcbRead) pcbRead->QuadPart = totalBytesRead.QuadPart; 1320 if (pcbWritten) pcbWritten->QuadPart = totalBytesWritten.QuadPart; 1321 1322 return hr; 1323 } 1324 1325 static HRESULT WINAPI sub_stream_Commit( 1326 IStream* iface, 1327 DWORD grfCommitFlags) 1328 { 1329 FIXME("stub\n"); 1330 return E_NOTIMPL; 1331 } 1332 1333 static HRESULT WINAPI sub_stream_Revert( 1334 IStream* iface) 1335 { 1336 FIXME("stub\n"); 1337 return E_NOTIMPL; 1338 } 1339 1340 static HRESULT WINAPI sub_stream_LockRegion( 1341 IStream* iface, 1342 ULARGE_INTEGER libOffset, 1343 ULARGE_INTEGER cb, 1344 DWORD dwLockType) 1345 { 1346 FIXME("stub\n"); 1347 return E_NOTIMPL; 1348 } 1349 1350 static HRESULT WINAPI sub_stream_UnlockRegion( 1351 IStream* iface, 1352 ULARGE_INTEGER libOffset, 1353 ULARGE_INTEGER cb, 1354 DWORD dwLockType) 1355 { 1356 FIXME("stub\n"); 1357 return E_NOTIMPL; 1358 } 1359 1360 static HRESULT WINAPI sub_stream_Stat( 1361 IStream* iface, 1362 STATSTG *pstatstg, 1363 DWORD grfStatFlag) 1364 { 1365 sub_stream_t *This = impl_from_IStream(iface); 1366 FIXME("(%p)->(%p, %08x)\n", This, pstatstg, grfStatFlag); 1367 memset(pstatstg, 0, sizeof(*pstatstg)); 1368 pstatstg->cbSize = This->length; 1369 return S_OK; 1370 } 1371 1372 static HRESULT WINAPI sub_stream_Clone( 1373 IStream* iface, 1374 IStream **ppstm) 1375 { 1376 FIXME("stub\n"); 1377 return E_NOTIMPL; 1378 } 1379 1380 static struct IStreamVtbl sub_stream_vtbl = 1381 { 1382 sub_stream_QueryInterface, 1383 sub_stream_AddRef, 1384 sub_stream_Release, 1385 sub_stream_Read, 1386 sub_stream_Write, 1387 sub_stream_Seek, 1388 sub_stream_SetSize, 1389 sub_stream_CopyTo, 1390 sub_stream_Commit, 1391 sub_stream_Revert, 1392 sub_stream_LockRegion, 1393 sub_stream_UnlockRegion, 1394 sub_stream_Stat, 1395 sub_stream_Clone 1396 }; 1397 1398 static HRESULT create_sub_stream(IStream *stream, ULARGE_INTEGER start, ULARGE_INTEGER length, IStream **out) 1399 { 1400 sub_stream_t *This; 1401 1402 *out = NULL; 1403 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 1404 if(!This) return E_OUTOFMEMORY; 1405 1406 This->lpVtbl = &sub_stream_vtbl; 1407 This->refs = 1; 1408 This->start = start; 1409 This->length = length; 1410 This->pos.QuadPart = 0; 1411 IStream_AddRef(stream); 1412 This->base = stream; 1413 1414 *out = (IStream*)&This->lpVtbl; 1415 return S_OK; 1416 } 1417 1418 1419 typedef struct body_t 1420 { 1421 struct list entry; 1422 DWORD index; 1423 IMimeBody *mime_body; 1424 1425 struct body_t *parent; 1426 struct list children; 1427 } body_t; 1428 1429 typedef struct MimeMessage 1430 { 1431 const IMimeMessageVtbl *lpVtbl; 1432 1433 LONG refs; 1434 IStream *stream; 1435 1436 struct list body_tree; 1437 DWORD next_index; 1438 } MimeMessage; 1439 1440 static HRESULT WINAPI MimeMessage_QueryInterface(IMimeMessage *iface, REFIID riid, void **ppv) 1441 { 1442 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); 1443 1444 if (IsEqualIID(riid, &IID_IUnknown) || 1445 IsEqualIID(riid, &IID_IPersist) || 1446 IsEqualIID(riid, &IID_IPersistStreamInit) || 1447 IsEqualIID(riid, &IID_IMimeMessageTree) || 1448 IsEqualIID(riid, &IID_IMimeMessage)) 1449 { 1450 *ppv = iface; 1451 IUnknown_AddRef(iface); 1452 return S_OK; 1453 } 1454 1455 FIXME("no interface for %s\n", debugstr_guid(riid)); 1456 *ppv = NULL; 1457 return E_NOINTERFACE; 1458 } 1459 1460 static ULONG WINAPI MimeMessage_AddRef(IMimeMessage *iface) 1461 { 1462 MimeMessage *This = (MimeMessage *)iface; 1463 TRACE("(%p)->()\n", iface); 1464 return InterlockedIncrement(&This->refs); 1465 } 1466 1467 static void empty_body_list(struct list *list) 1468 { 1469 body_t *body, *cursor2; 1470 LIST_FOR_EACH_ENTRY_SAFE(body, cursor2, list, body_t, entry) 1471 { 1472 empty_body_list(&body->children); 1473 list_remove(&body->entry); 1474 IMimeBody_Release(body->mime_body); 1475 HeapFree(GetProcessHeap(), 0, body); 1476 } 1477 } 1478 1479 static ULONG WINAPI MimeMessage_Release(IMimeMessage *iface) 1480 { 1481 MimeMessage *This = (MimeMessage *)iface; 1482 ULONG refs; 1483 1484 TRACE("(%p)->()\n", iface); 1485 1486 refs = InterlockedDecrement(&This->refs); 1487 if (!refs) 1488 { 1489 empty_body_list(&This->body_tree); 1490 1491 if(This->stream) IStream_Release(This->stream); 1492 HeapFree(GetProcessHeap(), 0, This); 1493 } 1494 1495 return refs; 1496 } 1497 1498 /*** IPersist methods ***/ 1499 static HRESULT WINAPI MimeMessage_GetClassID( 1500 IMimeMessage *iface, 1501 CLSID *pClassID) 1502 { 1503 FIXME("(%p)->(%p)\n", iface, pClassID); 1504 return E_NOTIMPL; 1505 } 1506 1507 /*** IPersistStreamInit methods ***/ 1508 static HRESULT WINAPI MimeMessage_IsDirty( 1509 IMimeMessage *iface) 1510 { 1511 FIXME("(%p)->()\n", iface); 1512 return E_NOTIMPL; 1513 } 1514 1515 static body_t *new_body_entry(IMimeBody *mime_body, DWORD index, body_t *parent) 1516 { 1517 body_t *body = HeapAlloc(GetProcessHeap(), 0, sizeof(*body)); 1518 if(body) 1519 { 1520 body->mime_body = mime_body; 1521 body->index = index; 1522 list_init(&body->children); 1523 body->parent = parent; 1524 } 1525 return body; 1526 } 1527 1528 typedef struct 1529 { 1530 struct list entry; 1531 BODYOFFSETS offsets; 1532 } offset_entry_t; 1533 1534 static HRESULT create_body_offset_list(IStream *stm, const char *boundary, struct list *body_offsets) 1535 { 1536 HRESULT hr; 1537 DWORD read; 1538 int boundary_len = strlen(boundary); 1539 char *buf, *nl_boundary, *ptr, *overlap; 1540 DWORD start = 0, overlap_no; 1541 offset_entry_t *cur_body = NULL; 1542 ULARGE_INTEGER cur; 1543 LARGE_INTEGER zero; 1544 1545 list_init(body_offsets); 1546 nl_boundary = HeapAlloc(GetProcessHeap(), 0, 4 + boundary_len + 1); 1547 memcpy(nl_boundary, "\r\n--", 4); 1548 memcpy(nl_boundary + 4, boundary, boundary_len + 1); 1549 1550 overlap_no = boundary_len + 5; 1551 1552 overlap = buf = HeapAlloc(GetProcessHeap(), 0, overlap_no + PARSER_BUF_SIZE + 1); 1553 1554 zero.QuadPart = 0; 1555 hr = IStream_Seek(stm, zero, STREAM_SEEK_CUR, &cur); 1556 start = cur.u.LowPart; 1557 1558 do { 1559 hr = IStream_Read(stm, overlap, PARSER_BUF_SIZE, &read); 1560 if(FAILED(hr)) goto end; 1561 if(read == 0) break; 1562 overlap[read] = '\0'; 1563 1564 ptr = buf; 1565 do { 1566 ptr = strstr(ptr, nl_boundary); 1567 if(ptr) 1568 { 1569 DWORD boundary_start = start + ptr - buf; 1570 char *end = ptr + boundary_len + 4; 1571 1572 if(*end == '\0' || *(end + 1) == '\0') 1573 break; 1574 1575 if(*end == '\r' && *(end + 1) == '\n') 1576 { 1577 if(cur_body) 1578 { 1579 cur_body->offsets.cbBodyEnd = boundary_start; 1580 list_add_tail(body_offsets, &cur_body->entry); 1581 } 1582 cur_body = HeapAlloc(GetProcessHeap(), 0, sizeof(*cur_body)); 1583 cur_body->offsets.cbBoundaryStart = boundary_start + 2; /* doesn't including the leading \r\n */ 1584 cur_body->offsets.cbHeaderStart = boundary_start + boundary_len + 6; 1585 } 1586 else if(*end == '-' && *(end + 1) == '-') 1587 { 1588 if(cur_body) 1589 { 1590 cur_body->offsets.cbBodyEnd = boundary_start; 1591 list_add_tail(body_offsets, &cur_body->entry); 1592 goto end; 1593 } 1594 } 1595 ptr = end + 2; 1596 } 1597 } while(ptr); 1598 1599 if(overlap == buf) /* 1st iteration */ 1600 { 1601 memcpy(buf, buf + PARSER_BUF_SIZE - overlap_no, overlap_no); 1602 overlap = buf + overlap_no; 1603 start += read - overlap_no; 1604 } 1605 else 1606 { 1607 memcpy(buf, buf + PARSER_BUF_SIZE, overlap_no); 1608 start += read; 1609 } 1610 } while(1); 1611 1612 end: 1613 HeapFree(GetProcessHeap(), 0, nl_boundary); 1614 HeapFree(GetProcessHeap(), 0, buf); 1615 return hr; 1616 } 1617 1618 static body_t *create_sub_body(MimeMessage *msg, IStream *pStm, BODYOFFSETS *offset, body_t *parent) 1619 { 1620 IMimeBody *mime_body; 1621 HRESULT hr; 1622 body_t *body; 1623 ULARGE_INTEGER cur; 1624 LARGE_INTEGER zero; 1625 1626 MimeBody_create(NULL, (void**)&mime_body); 1627 IMimeBody_Load(mime_body, pStm); 1628 zero.QuadPart = 0; 1629 hr = IStream_Seek(pStm, zero, STREAM_SEEK_CUR, &cur); 1630 offset->cbBodyStart = cur.u.LowPart + offset->cbHeaderStart; 1631 if(parent) MimeBody_set_offsets(impl_from_IMimeBody(mime_body), offset); 1632 IMimeBody_SetData(mime_body, IET_BINARY, NULL, NULL, &IID_IStream, pStm); 1633 body = new_body_entry(mime_body, msg->next_index++, parent); 1634 1635 if(IMimeBody_IsContentType(mime_body, "multipart", NULL) == S_OK) 1636 { 1637 MIMEPARAMINFO *param_info; 1638 ULONG count, i; 1639 IMimeAllocator *alloc; 1640 1641 hr = IMimeBody_GetParameters(mime_body, "Content-Type", &count, ¶m_info); 1642 if(hr != S_OK || count == 0) return body; 1643 1644 MimeOleGetAllocator(&alloc); 1645 1646 for(i = 0; i < count; i++) 1647 { 1648 if(!strcasecmp(param_info[i].pszName, "boundary")) 1649 { 1650 struct list offset_list; 1651 offset_entry_t *cur, *cursor2; 1652 hr = create_body_offset_list(pStm, param_info[i].pszData, &offset_list); 1653 LIST_FOR_EACH_ENTRY_SAFE(cur, cursor2, &offset_list, offset_entry_t, entry) 1654 { 1655 body_t *sub_body; 1656 IStream *sub_stream; 1657 ULARGE_INTEGER start, length; 1658 1659 start.QuadPart = cur->offsets.cbHeaderStart; 1660 length.QuadPart = cur->offsets.cbBodyEnd - cur->offsets.cbHeaderStart; 1661 create_sub_stream(pStm, start, length, &sub_stream); 1662 sub_body = create_sub_body(msg, sub_stream, &cur->offsets, body); 1663 IStream_Release(sub_stream); 1664 list_add_tail(&body->children, &sub_body->entry); 1665 list_remove(&cur->entry); 1666 HeapFree(GetProcessHeap(), 0, cur); 1667 } 1668 break; 1669 } 1670 } 1671 IMimeAllocator_FreeParamInfoArray(alloc, count, param_info, TRUE); 1672 IMimeAllocator_Release(alloc); 1673 } 1674 return body; 1675 } 1676 1677 static HRESULT WINAPI MimeMessage_Load( 1678 IMimeMessage *iface, 1679 LPSTREAM pStm) 1680 { 1681 MimeMessage *This = (MimeMessage *)iface; 1682 body_t *root_body; 1683 BODYOFFSETS offsets; 1684 ULARGE_INTEGER cur; 1685 LARGE_INTEGER zero; 1686 1687 TRACE("(%p)->(%p)\n", iface, pStm); 1688 1689 if(This->stream) 1690 { 1691 FIXME("already loaded a message\n"); 1692 return E_FAIL; 1693 } 1694 1695 IStream_AddRef(pStm); 1696 This->stream = pStm; 1697 offsets.cbBoundaryStart = offsets.cbHeaderStart = 0; 1698 offsets.cbBodyStart = offsets.cbBodyEnd = 0; 1699 1700 root_body = create_sub_body(This, pStm, &offsets, NULL); 1701 1702 zero.QuadPart = 0; 1703 IStream_Seek(pStm, zero, STREAM_SEEK_END, &cur); 1704 offsets.cbBodyEnd = cur.u.LowPart; 1705 MimeBody_set_offsets(impl_from_IMimeBody(root_body->mime_body), &offsets); 1706 1707 list_add_head(&This->body_tree, &root_body->entry); 1708 1709 return S_OK; 1710 } 1711 1712 static HRESULT WINAPI MimeMessage_Save( 1713 IMimeMessage *iface, 1714 LPSTREAM pStm, 1715 BOOL fClearDirty) 1716 { 1717 FIXME("(%p)->(%p, %s)\n", iface, pStm, fClearDirty ? "TRUE" : "FALSE"); 1718 return E_NOTIMPL; 1719 } 1720 1721 static HRESULT WINAPI MimeMessage_GetSizeMax( 1722 IMimeMessage *iface, 1723 ULARGE_INTEGER *pcbSize) 1724 { 1725 FIXME("(%p)->(%p)\n", iface, pcbSize); 1726 return E_NOTIMPL; 1727 } 1728 1729 static HRESULT WINAPI MimeMessage_InitNew( 1730 IMimeMessage *iface) 1731 { 1732 FIXME("(%p)->()\n", iface); 1733 return E_NOTIMPL; 1734 } 1735 1736 /*** IMimeMessageTree methods ***/ 1737 static HRESULT WINAPI MimeMessage_GetMessageSource( 1738 IMimeMessage *iface, 1739 IStream **ppStream, 1740 DWORD dwFlags) 1741 { 1742 MimeMessage *This = (MimeMessage *)iface; 1743 FIXME("(%p)->(%p, 0x%x)\n", iface, ppStream, dwFlags); 1744 1745 IStream_AddRef(This->stream); 1746 *ppStream = This->stream; 1747 return S_OK; 1748 } 1749 1750 static HRESULT WINAPI MimeMessage_GetMessageSize( 1751 IMimeMessage *iface, 1752 ULONG *pcbSize, 1753 DWORD dwFlags) 1754 { 1755 FIXME("(%p)->(%p, 0x%x)\n", iface, pcbSize, dwFlags); 1756 return E_NOTIMPL; 1757 } 1758 1759 static HRESULT WINAPI MimeMessage_LoadOffsetTable( 1760 IMimeMessage *iface, 1761 IStream *pStream) 1762 { 1763 FIXME("(%p)->(%p)\n", iface, pStream); 1764 return E_NOTIMPL; 1765 } 1766 1767 static HRESULT WINAPI MimeMessage_SaveOffsetTable( 1768 IMimeMessage *iface, 1769 IStream *pStream, 1770 DWORD dwFlags) 1771 { 1772 FIXME("(%p)->(%p, 0x%x)\n", iface, pStream, dwFlags); 1773 return E_NOTIMPL; 1774 } 1775 1776 1777 static HRESULT WINAPI MimeMessage_GetFlags( 1778 IMimeMessage *iface, 1779 DWORD *pdwFlags) 1780 { 1781 FIXME("(%p)->(%p)\n", iface, pdwFlags); 1782 return E_NOTIMPL; 1783 } 1784 1785 static HRESULT WINAPI MimeMessage_Commit( 1786 IMimeMessage *iface, 1787 DWORD dwFlags) 1788 { 1789 FIXME("(%p)->(0x%x)\n", iface, dwFlags); 1790 return E_NOTIMPL; 1791 } 1792 1793 1794 static HRESULT WINAPI MimeMessage_HandsOffStorage( 1795 IMimeMessage *iface) 1796 { 1797 FIXME("(%p)->()\n", iface); 1798 return E_NOTIMPL; 1799 } 1800 1801 static HRESULT find_body(struct list *list, HBODY hbody, body_t **body) 1802 { 1803 body_t *cur; 1804 HRESULT hr; 1805 1806 if(hbody == HBODY_ROOT) 1807 { 1808 *body = LIST_ENTRY(list_head(list), body_t, entry); 1809 return S_OK; 1810 } 1811 1812 LIST_FOR_EACH_ENTRY(cur, list, body_t, entry) 1813 { 1814 if(cur->index == HandleToUlong(hbody)) 1815 { 1816 *body = cur; 1817 return S_OK; 1818 } 1819 hr = find_body(&cur->children, hbody, body); 1820 if(hr == S_OK) return S_OK; 1821 } 1822 return S_FALSE; 1823 } 1824 1825 static HRESULT WINAPI MimeMessage_BindToObject( 1826 IMimeMessage *iface, 1827 const HBODY hBody, 1828 REFIID riid, 1829 void **ppvObject) 1830 { 1831 MimeMessage *This = (MimeMessage *)iface; 1832 HRESULT hr; 1833 body_t *body; 1834 1835 TRACE("(%p)->(%p, %s, %p)\n", iface, hBody, debugstr_guid(riid), ppvObject); 1836 1837 hr = find_body(&This->body_tree, hBody, &body); 1838 1839 if(hr != S_OK) return hr; 1840 1841 if(IsEqualIID(riid, &IID_IMimeBody)) 1842 { 1843 IMimeBody_AddRef(body->mime_body); 1844 *ppvObject = body->mime_body; 1845 return S_OK; 1846 } 1847 1848 return E_NOINTERFACE; 1849 } 1850 1851 static HRESULT WINAPI MimeMessage_SaveBody( 1852 IMimeMessage *iface, 1853 HBODY hBody, 1854 DWORD dwFlags, 1855 IStream *pStream) 1856 { 1857 FIXME("(%p)->(%p, 0x%x, %p)\n", iface, hBody, dwFlags, pStream); 1858 return E_NOTIMPL; 1859 } 1860 1861 static HRESULT get_body(MimeMessage *msg, BODYLOCATION location, HBODY pivot, body_t **out) 1862 { 1863 body_t *root = LIST_ENTRY(list_head(&msg->body_tree), body_t, entry); 1864 body_t *body; 1865 HRESULT hr; 1866 struct list *list; 1867 1868 if(location == IBL_ROOT) 1869 { 1870 *out = root; 1871 return S_OK; 1872 } 1873 1874 hr = find_body(&msg->body_tree, pivot, &body); 1875 1876 if(hr == S_OK) 1877 { 1878 switch(location) 1879 { 1880 case IBL_PARENT: 1881 *out = body->parent; 1882 break; 1883 1884 case IBL_FIRST: 1885 list = list_head(&body->children); 1886 if(list) 1887 *out = LIST_ENTRY(list, body_t, entry); 1888 else 1889 hr = MIME_E_NOT_FOUND; 1890 break; 1891 1892 case IBL_LAST: 1893 list = list_tail(&body->children); 1894 if(list) 1895 *out = LIST_ENTRY(list, body_t, entry); 1896 else 1897 hr = MIME_E_NOT_FOUND; 1898 break; 1899 1900 case IBL_NEXT: 1901 list = list_next(&body->parent->children, &body->entry); 1902 if(list) 1903 *out = LIST_ENTRY(list, body_t, entry); 1904 else 1905 hr = MIME_E_NOT_FOUND; 1906 break; 1907 1908 case IBL_PREVIOUS: 1909 list = list_prev(&body->parent->children, &body->entry); 1910 if(list) 1911 *out = LIST_ENTRY(list, body_t, entry); 1912 else 1913 hr = MIME_E_NOT_FOUND; 1914 break; 1915 1916 default: 1917 hr = E_FAIL; 1918 break; 1919 } 1920 } 1921 1922 return hr; 1923 } 1924 1925 1926 static HRESULT WINAPI MimeMessage_InsertBody( 1927 IMimeMessage *iface, 1928 BODYLOCATION location, 1929 HBODY hPivot, 1930 LPHBODY phBody) 1931 { 1932 FIXME("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody); 1933 return E_NOTIMPL; 1934 } 1935 1936 static HRESULT WINAPI MimeMessage_GetBody( 1937 IMimeMessage *iface, 1938 BODYLOCATION location, 1939 HBODY hPivot, 1940 LPHBODY phBody) 1941 { 1942 MimeMessage *This = (MimeMessage *)iface; 1943 body_t *body; 1944 HRESULT hr; 1945 1946 TRACE("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody); 1947 1948 hr = get_body(This, location, hPivot, &body); 1949 1950 if(hr == S_OK) *phBody = UlongToHandle(body->index); 1951 1952 return hr; 1953 } 1954 1955 static HRESULT WINAPI MimeMessage_DeleteBody( 1956 IMimeMessage *iface, 1957 HBODY hBody, 1958 DWORD dwFlags) 1959 { 1960 FIXME("(%p)->(%p, %08x)\n", iface, hBody, dwFlags); 1961 return E_NOTIMPL; 1962 } 1963 1964 static HRESULT WINAPI MimeMessage_MoveBody( 1965 IMimeMessage *iface, 1966 HBODY hBody, 1967 BODYLOCATION location) 1968 { 1969 FIXME("(%p)->(%d)\n", iface, location); 1970 return E_NOTIMPL; 1971 } 1972 1973 static void count_children(body_t *body, boolean recurse, ULONG *count) 1974 { 1975 body_t *child; 1976 1977 LIST_FOR_EACH_ENTRY(child, &body->children, body_t, entry) 1978 { 1979 (*count)++; 1980 if(recurse) count_children(child, recurse, count); 1981 } 1982 } 1983 1984 static HRESULT WINAPI MimeMessage_CountBodies( 1985 IMimeMessage *iface, 1986 HBODY hParent, 1987 boolean fRecurse, 1988 ULONG *pcBodies) 1989 { 1990 HRESULT hr; 1991 MimeMessage *This = (MimeMessage *)iface; 1992 body_t *body; 1993 1994 TRACE("(%p)->(%p, %s, %p)\n", iface, hParent, fRecurse ? "TRUE" : "FALSE", pcBodies); 1995 1996 hr = find_body(&This->body_tree, hParent, &body); 1997 if(hr != S_OK) return hr; 1998 1999 *pcBodies = 1; 2000 count_children(body, fRecurse, pcBodies); 2001 2002 return S_OK; 2003 } 2004 2005 static HRESULT find_next(IMimeMessage *msg, body_t *body, LPFINDBODY find, HBODY *out) 2006 { 2007 MimeMessage *This = (MimeMessage *)msg; 2008 struct list *ptr; 2009 HBODY next; 2010 2011 for (;;) 2012 { 2013 if (!body) ptr = list_head( &This->body_tree ); 2014 else 2015 { 2016 ptr = list_head( &body->children ); 2017 while (!ptr) 2018 { 2019 if (!body->parent) return MIME_E_NOT_FOUND; 2020 if (!(ptr = list_next( &body->parent->children, &body->entry ))) body = body->parent; 2021 } 2022 } 2023 2024 body = LIST_ENTRY( ptr, body_t, entry ); 2025 next = UlongToHandle( body->index ); 2026 find->dwReserved = body->index; 2027 if (IMimeBody_IsContentType(body->mime_body, find->pszPriType, find->pszSubType) == S_OK) 2028 { 2029 *out = next; 2030 return S_OK; 2031 } 2032 } 2033 return MIME_E_NOT_FOUND; 2034 } 2035 2036 static HRESULT WINAPI MimeMessage_FindFirst( 2037 IMimeMessage *iface, 2038 LPFINDBODY pFindBody, 2039 LPHBODY phBody) 2040 { 2041 TRACE("(%p)->(%p, %p)\n", iface, pFindBody, phBody); 2042 2043 pFindBody->dwReserved = 0; 2044 return find_next( iface, NULL, pFindBody, phBody ); 2045 } 2046 2047 static HRESULT WINAPI MimeMessage_FindNext( 2048 IMimeMessage *iface, 2049 LPFINDBODY pFindBody, 2050 LPHBODY phBody) 2051 { 2052 MimeMessage *This = (MimeMessage *)iface; 2053 body_t *body; 2054 HRESULT hr; 2055 2056 TRACE("(%p)->(%p, %p)\n", iface, pFindBody, phBody); 2057 2058 hr = find_body( &This->body_tree, UlongToHandle( pFindBody->dwReserved ), &body ); 2059 if (hr != S_OK) return MIME_E_NOT_FOUND; 2060 return find_next( iface, body, pFindBody, phBody ); 2061 } 2062 2063 static HRESULT WINAPI MimeMessage_ResolveURL( 2064 IMimeMessage *iface, 2065 HBODY hRelated, 2066 LPCSTR pszBase, 2067 LPCSTR pszURL, 2068 DWORD dwFlags, 2069 LPHBODY phBody) 2070 { 2071 FIXME("(%p)->(%p, %s, %s, 0x%x, %p)\n", iface, hRelated, pszBase, pszURL, dwFlags, phBody); 2072 return E_NOTIMPL; 2073 } 2074 2075 static HRESULT WINAPI MimeMessage_ToMultipart( 2076 IMimeMessage *iface, 2077 HBODY hBody, 2078 LPCSTR pszSubType, 2079 LPHBODY phMultipart) 2080 { 2081 FIXME("(%p)->(%p, %s, %p)\n", iface, hBody, pszSubType, phMultipart); 2082 return E_NOTIMPL; 2083 } 2084 2085 static HRESULT WINAPI MimeMessage_GetBodyOffsets( 2086 IMimeMessage *iface, 2087 HBODY hBody, 2088 LPBODYOFFSETS pOffsets) 2089 { 2090 FIXME("(%p)->(%p, %p)\n", iface, hBody, pOffsets); 2091 return E_NOTIMPL; 2092 } 2093 2094 static HRESULT WINAPI MimeMessage_GetCharset( 2095 IMimeMessage *iface, 2096 LPHCHARSET phCharset) 2097 { 2098 FIXME("(%p)->(%p)\n", iface, phCharset); 2099 *phCharset = NULL; 2100 return S_OK; 2101 } 2102 2103 static HRESULT WINAPI MimeMessage_SetCharset( 2104 IMimeMessage *iface, 2105 HCHARSET hCharset, 2106 CSETAPPLYTYPE applytype) 2107 { 2108 FIXME("(%p)->(%p, %d)\n", iface, hCharset, applytype); 2109 return E_NOTIMPL; 2110 } 2111 2112 static HRESULT WINAPI MimeMessage_IsBodyType( 2113 IMimeMessage *iface, 2114 HBODY hBody, 2115 IMSGBODYTYPE bodytype) 2116 { 2117 HRESULT hr; 2118 IMimeBody *mime_body; 2119 TRACE("(%p)->(%p, %d)\n", iface, hBody, bodytype); 2120 2121 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body); 2122 if(hr != S_OK) return hr; 2123 2124 hr = IMimeBody_IsType(mime_body, bodytype); 2125 MimeBody_Release(mime_body); 2126 return hr; 2127 } 2128 2129 static HRESULT WINAPI MimeMessage_IsContentType( 2130 IMimeMessage *iface, 2131 HBODY hBody, 2132 LPCSTR pszPriType, 2133 LPCSTR pszSubType) 2134 { 2135 HRESULT hr; 2136 IMimeBody *mime_body; 2137 TRACE("(%p)->(%p, %s, %s)\n", iface, hBody, pszPriType, pszSubType); 2138 2139 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body); 2140 if(FAILED(hr)) return hr; 2141 2142 hr = IMimeBody_IsContentType(mime_body, pszPriType, pszSubType); 2143 IMimeBody_Release(mime_body); 2144 return hr; 2145 } 2146 2147 static HRESULT WINAPI MimeMessage_QueryBodyProp( 2148 IMimeMessage *iface, 2149 HBODY hBody, 2150 LPCSTR pszName, 2151 LPCSTR pszCriteria, 2152 boolean fSubString, 2153 boolean fCaseSensitive) 2154 { 2155 FIXME("(%p)->(%p, %s, %s, %s, %s)\n", iface, hBody, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE"); 2156 return E_NOTIMPL; 2157 } 2158 2159 static HRESULT WINAPI MimeMessage_GetBodyProp( 2160 IMimeMessage *iface, 2161 HBODY hBody, 2162 LPCSTR pszName, 2163 DWORD dwFlags, 2164 LPPROPVARIANT pValue) 2165 { 2166 HRESULT hr; 2167 IMimeBody *mime_body; 2168 2169 TRACE("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue); 2170 2171 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body); 2172 if(hr != S_OK) return hr; 2173 2174 hr = IMimeBody_GetProp(mime_body, pszName, dwFlags, pValue); 2175 IMimeBody_Release(mime_body); 2176 2177 return hr; 2178 } 2179 2180 static HRESULT WINAPI MimeMessage_SetBodyProp( 2181 IMimeMessage *iface, 2182 HBODY hBody, 2183 LPCSTR pszName, 2184 DWORD dwFlags, 2185 LPCPROPVARIANT pValue) 2186 { 2187 FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue); 2188 return E_NOTIMPL; 2189 } 2190 2191 static HRESULT WINAPI MimeMessage_DeleteBodyProp( 2192 IMimeMessage *iface, 2193 HBODY hBody, 2194 LPCSTR pszName) 2195 { 2196 FIXME("(%p)->(%p, %s)\n", iface, hBody, pszName); 2197 return E_NOTIMPL; 2198 } 2199 2200 static HRESULT WINAPI MimeMessage_SetOption( 2201 IMimeMessage *iface, 2202 const TYPEDID oid, 2203 LPCPROPVARIANT pValue) 2204 { 2205 HRESULT hr = E_NOTIMPL; 2206 TRACE("(%p)->(%08x, %p)\n", iface, oid, pValue); 2207 2208 if(pValue->vt != TYPEDID_TYPE(oid)) 2209 { 2210 WARN("Called with vartype %04x and oid %08x\n", pValue->vt, oid); 2211 return E_INVALIDARG; 2212 } 2213 2214 switch(oid) 2215 { 2216 case OID_HIDE_TNEF_ATTACHMENTS: 2217 FIXME("OID_HIDE_TNEF_ATTACHMENTS (value %d): ignoring\n", pValue->u.boolVal); 2218 hr = S_OK; 2219 break; 2220 case OID_SHOW_MACBINARY: 2221 FIXME("OID_SHOW_MACBINARY (value %d): ignoring\n", pValue->u.boolVal); 2222 hr = S_OK; 2223 break; 2224 default: 2225 FIXME("Unhandled oid %08x\n", oid); 2226 } 2227 2228 return hr; 2229 } 2230 2231 static HRESULT WINAPI MimeMessage_GetOption( 2232 IMimeMessage *iface, 2233 const TYPEDID oid, 2234 LPPROPVARIANT pValue) 2235 { 2236 FIXME("(%p)->(%08x, %p)\n", iface, oid, pValue); 2237 return E_NOTIMPL; 2238 } 2239 2240 /*** IMimeMessage methods ***/ 2241 static HRESULT WINAPI MimeMessage_CreateWebPage( 2242 IMimeMessage *iface, 2243 IStream *pRootStm, 2244 LPWEBPAGEOPTIONS pOptions, 2245 IMimeMessageCallback *pCallback, 2246 IMoniker **ppMoniker) 2247 { 2248 FIXME("(%p)->(%p, %p, %p, %p)\n", iface, pRootStm, pOptions, pCallback, ppMoniker); 2249 *ppMoniker = NULL; 2250 return E_NOTIMPL; 2251 } 2252 2253 static HRESULT WINAPI MimeMessage_GetProp( 2254 IMimeMessage *iface, 2255 LPCSTR pszName, 2256 DWORD dwFlags, 2257 LPPROPVARIANT pValue) 2258 { 2259 FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue); 2260 return E_NOTIMPL; 2261 } 2262 2263 static HRESULT WINAPI MimeMessage_SetProp( 2264 IMimeMessage *iface, 2265 LPCSTR pszName, 2266 DWORD dwFlags, 2267 LPCPROPVARIANT pValue) 2268 { 2269 FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue); 2270 return E_NOTIMPL; 2271 } 2272 2273 static HRESULT WINAPI MimeMessage_DeleteProp( 2274 IMimeMessage *iface, 2275 LPCSTR pszName) 2276 { 2277 FIXME("(%p)->(%s)\n", iface, pszName); 2278 return E_NOTIMPL; 2279 } 2280 2281 static HRESULT WINAPI MimeMessage_QueryProp( 2282 IMimeMessage *iface, 2283 LPCSTR pszName, 2284 LPCSTR pszCriteria, 2285 boolean fSubString, 2286 boolean fCaseSensitive) 2287 { 2288 FIXME("(%p)->(%s, %s, %s, %s)\n", iface, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE"); 2289 return E_NOTIMPL; 2290 } 2291 2292 static HRESULT WINAPI MimeMessage_GetTextBody( 2293 IMimeMessage *iface, 2294 DWORD dwTxtType, 2295 ENCODINGTYPE ietEncoding, 2296 IStream **pStream, 2297 LPHBODY phBody) 2298 { 2299 HRESULT hr; 2300 HBODY hbody; 2301 FINDBODY find_struct; 2302 IMimeBody *mime_body; 2303 static char text[] = "text"; 2304 static char plain[] = "plain"; 2305 static char html[] = "html"; 2306 2307 TRACE("(%p)->(%d, %d, %p, %p)\n", iface, dwTxtType, ietEncoding, pStream, phBody); 2308 2309 find_struct.pszPriType = text; 2310 2311 switch(dwTxtType) 2312 { 2313 case TXT_PLAIN: 2314 find_struct.pszSubType = plain; 2315 break; 2316 case TXT_HTML: 2317 find_struct.pszSubType = html; 2318 break; 2319 default: 2320 return MIME_E_INVALID_TEXT_TYPE; 2321 } 2322 2323 hr = IMimeMessage_FindFirst(iface, &find_struct, &hbody); 2324 if(hr != S_OK) 2325 { 2326 TRACE("not found hr %08x\n", hr); 2327 *phBody = NULL; 2328 return hr; 2329 } 2330 2331 IMimeMessage_BindToObject(iface, hbody, &IID_IMimeBody, (void**)&mime_body); 2332 2333 IMimeBody_GetData(mime_body, ietEncoding, pStream); 2334 *phBody = hbody; 2335 IMimeBody_Release(mime_body); 2336 return hr; 2337 } 2338 2339 static HRESULT WINAPI MimeMessage_SetTextBody( 2340 IMimeMessage *iface, 2341 DWORD dwTxtType, 2342 ENCODINGTYPE ietEncoding, 2343 HBODY hAlternative, 2344 IStream *pStream, 2345 LPHBODY phBody) 2346 { 2347 FIXME("(%p)->(%d, %d, %p, %p, %p)\n", iface, dwTxtType, ietEncoding, hAlternative, pStream, phBody); 2348 return E_NOTIMPL; 2349 } 2350 2351 static HRESULT WINAPI MimeMessage_AttachObject( 2352 IMimeMessage *iface, 2353 REFIID riid, 2354 void *pvObject, 2355 LPHBODY phBody) 2356 { 2357 FIXME("(%p)->(%s, %p, %p)\n", iface, debugstr_guid(riid), pvObject, phBody); 2358 return E_NOTIMPL; 2359 } 2360 2361 static HRESULT WINAPI MimeMessage_AttachFile( 2362 IMimeMessage *iface, 2363 LPCSTR pszFilePath, 2364 IStream *pstmFile, 2365 LPHBODY phBody) 2366 { 2367 FIXME("(%p)->(%s, %p, %p)\n", iface, pszFilePath, pstmFile, phBody); 2368 return E_NOTIMPL; 2369 } 2370 2371 static HRESULT WINAPI MimeMessage_AttachURL( 2372 IMimeMessage *iface, 2373 LPCSTR pszBase, 2374 LPCSTR pszURL, 2375 DWORD dwFlags, 2376 IStream *pstmURL, 2377 LPSTR *ppszCIDURL, 2378 LPHBODY phBody) 2379 { 2380 FIXME("(%p)->(%s, %s, 0x%x, %p, %p, %p)\n", iface, pszBase, pszURL, dwFlags, pstmURL, ppszCIDURL, phBody); 2381 return E_NOTIMPL; 2382 } 2383 2384 static HRESULT WINAPI MimeMessage_GetAttachments( 2385 IMimeMessage *iface, 2386 ULONG *pcAttach, 2387 LPHBODY *pprghAttach) 2388 { 2389 HRESULT hr; 2390 FINDBODY find_struct; 2391 HBODY hbody; 2392 LPHBODY array; 2393 ULONG size = 10; 2394 2395 TRACE("(%p)->(%p, %p)\n", iface, pcAttach, pprghAttach); 2396 2397 *pcAttach = 0; 2398 array = CoTaskMemAlloc(size * sizeof(HBODY)); 2399 2400 find_struct.pszPriType = find_struct.pszSubType = NULL; 2401 hr = IMimeMessage_FindFirst(iface, &find_struct, &hbody); 2402 while(hr == S_OK) 2403 { 2404 hr = IMimeMessage_IsContentType(iface, hbody, "multipart", NULL); 2405 TRACE("IsCT rets %08x %d\n", hr, *pcAttach); 2406 if(hr != S_OK) 2407 { 2408 if(*pcAttach + 1 > size) 2409 { 2410 size *= 2; 2411 array = CoTaskMemRealloc(array, size * sizeof(HBODY)); 2412 } 2413 array[*pcAttach] = hbody; 2414 (*pcAttach)++; 2415 } 2416 hr = IMimeMessage_FindNext(iface, &find_struct, &hbody); 2417 } 2418 2419 *pprghAttach = array; 2420 return S_OK; 2421 } 2422 2423 static HRESULT WINAPI MimeMessage_GetAddressTable( 2424 IMimeMessage *iface, 2425 IMimeAddressTable **ppTable) 2426 { 2427 FIXME("(%p)->(%p)\n", iface, ppTable); 2428 return E_NOTIMPL; 2429 } 2430 2431 static HRESULT WINAPI MimeMessage_GetSender( 2432 IMimeMessage *iface, 2433 LPADDRESSPROPS pAddress) 2434 { 2435 FIXME("(%p)->(%p)\n", iface, pAddress); 2436 return E_NOTIMPL; 2437 } 2438 2439 static HRESULT WINAPI MimeMessage_GetAddressTypes( 2440 IMimeMessage *iface, 2441 DWORD dwAdrTypes, 2442 DWORD dwProps, 2443 LPADDRESSLIST pList) 2444 { 2445 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, pList); 2446 return E_NOTIMPL; 2447 } 2448 2449 static HRESULT WINAPI MimeMessage_GetAddressFormat( 2450 IMimeMessage *iface, 2451 DWORD dwAdrTypes, 2452 ADDRESSFORMAT format, 2453 LPSTR *ppszFormat) 2454 { 2455 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, format, ppszFormat); 2456 return E_NOTIMPL; 2457 } 2458 2459 static HRESULT WINAPI MimeMessage_EnumAddressTypes( 2460 IMimeMessage *iface, 2461 DWORD dwAdrTypes, 2462 DWORD dwProps, 2463 IMimeEnumAddressTypes **ppEnum) 2464 { 2465 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, ppEnum); 2466 return E_NOTIMPL; 2467 } 2468 2469 static HRESULT WINAPI MimeMessage_SplitMessage( 2470 IMimeMessage *iface, 2471 ULONG cbMaxPart, 2472 IMimeMessageParts **ppParts) 2473 { 2474 FIXME("(%p)->(%d, %p)\n", iface, cbMaxPart, ppParts); 2475 return E_NOTIMPL; 2476 } 2477 2478 static HRESULT WINAPI MimeMessage_GetRootMoniker( 2479 IMimeMessage *iface, 2480 IMoniker **ppMoniker) 2481 { 2482 FIXME("(%p)->(%p)\n", iface, ppMoniker); 2483 return E_NOTIMPL; 2484 } 2485 2486 static const IMimeMessageVtbl MimeMessageVtbl = 2487 { 2488 MimeMessage_QueryInterface, 2489 MimeMessage_AddRef, 2490 MimeMessage_Release, 2491 MimeMessage_GetClassID, 2492 MimeMessage_IsDirty, 2493 MimeMessage_Load, 2494 MimeMessage_Save, 2495 MimeMessage_GetSizeMax, 2496 MimeMessage_InitNew, 2497 MimeMessage_GetMessageSource, 2498 MimeMessage_GetMessageSize, 2499 MimeMessage_LoadOffsetTable, 2500 MimeMessage_SaveOffsetTable, 2501 MimeMessage_GetFlags, 2502 MimeMessage_Commit, 2503 MimeMessage_HandsOffStorage, 2504 MimeMessage_BindToObject, 2505 MimeMessage_SaveBody, 2506 MimeMessage_InsertBody, 2507 MimeMessage_GetBody, 2508 MimeMessage_DeleteBody, 2509 MimeMessage_MoveBody, 2510 MimeMessage_CountBodies, 2511 MimeMessage_FindFirst, 2512 MimeMessage_FindNext, 2513 MimeMessage_ResolveURL, 2514 MimeMessage_ToMultipart, 2515 MimeMessage_GetBodyOffsets, 2516 MimeMessage_GetCharset, 2517 MimeMessage_SetCharset, 2518 MimeMessage_IsBodyType, 2519 MimeMessage_IsContentType, 2520 MimeMessage_QueryBodyProp, 2521 MimeMessage_GetBodyProp, 2522 MimeMessage_SetBodyProp, 2523 MimeMessage_DeleteBodyProp, 2524 MimeMessage_SetOption, 2525 MimeMessage_GetOption, 2526 MimeMessage_CreateWebPage, 2527 MimeMessage_GetProp, 2528 MimeMessage_SetProp, 2529 MimeMessage_DeleteProp, 2530 MimeMessage_QueryProp, 2531 MimeMessage_GetTextBody, 2532 MimeMessage_SetTextBody, 2533 MimeMessage_AttachObject, 2534 MimeMessage_AttachFile, 2535 MimeMessage_AttachURL, 2536 MimeMessage_GetAttachments, 2537 MimeMessage_GetAddressTable, 2538 MimeMessage_GetSender, 2539 MimeMessage_GetAddressTypes, 2540 MimeMessage_GetAddressFormat, 2541 MimeMessage_EnumAddressTypes, 2542 MimeMessage_SplitMessage, 2543 MimeMessage_GetRootMoniker, 2544 }; 2545 2546 HRESULT MimeMessage_create(IUnknown *outer, void **obj) 2547 { 2548 MimeMessage *This; 2549 2550 TRACE("(%p, %p)\n", outer, obj); 2551 2552 if (outer) 2553 { 2554 FIXME("outer unknown not supported yet\n"); 2555 return E_NOTIMPL; 2556 } 2557 2558 *obj = NULL; 2559 2560 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 2561 if (!This) return E_OUTOFMEMORY; 2562 2563 This->lpVtbl = &MimeMessageVtbl; 2564 This->refs = 1; 2565 This->stream = NULL; 2566 list_init(&This->body_tree); 2567 This->next_index = 1; 2568 2569 *obj = &This->lpVtbl; 2570 return S_OK; 2571 } 2572 2573 /*********************************************************************** 2574 * MimeOleCreateMessage (INETCOMM.@) 2575 */ 2576 HRESULT WINAPI MimeOleCreateMessage(IUnknown *pUnkOuter, IMimeMessage **ppMessage) 2577 { 2578 TRACE("(%p, %p)\n", pUnkOuter, ppMessage); 2579 return MimeMessage_create(NULL, (void **)ppMessage); 2580 } 2581 2582 /*********************************************************************** 2583 * MimeOleSetCompatMode (INETCOMM.@) 2584 */ 2585 HRESULT WINAPI MimeOleSetCompatMode(DWORD dwMode) 2586 { 2587 FIXME("(0x%x)\n", dwMode); 2588 return S_OK; 2589 } 2590 2591 /*********************************************************************** 2592 * MimeOleCreateVirtualStream (INETCOMM.@) 2593 */ 2594 HRESULT WINAPI MimeOleCreateVirtualStream(IStream **ppStream) 2595 { 2596 HRESULT hr; 2597 FIXME("(%p)\n", ppStream); 2598 2599 hr = CreateStreamOnHGlobal(NULL, TRUE, ppStream); 2600 return hr; 2601 } 2602 2603 typedef struct MimeSecurity 2604 { 2605 const IMimeSecurityVtbl *lpVtbl; 2606 2607 LONG refs; 2608 } MimeSecurity; 2609 2610 static HRESULT WINAPI MimeSecurity_QueryInterface( 2611 IMimeSecurity* iface, 2612 REFIID riid, 2613 void** obj) 2614 { 2615 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), obj); 2616 2617 if (IsEqualIID(riid, &IID_IUnknown) || 2618 IsEqualIID(riid, &IID_IMimeSecurity)) 2619 { 2620 *obj = iface; 2621 IUnknown_AddRef(iface); 2622 return S_OK; 2623 } 2624 2625 FIXME("no interface for %s\n", debugstr_guid(riid)); 2626 *obj = NULL; 2627 return E_NOINTERFACE; 2628 } 2629 2630 static ULONG WINAPI MimeSecurity_AddRef( 2631 IMimeSecurity* iface) 2632 { 2633 MimeSecurity *This = (MimeSecurity *)iface; 2634 TRACE("(%p)->()\n", iface); 2635 return InterlockedIncrement(&This->refs); 2636 } 2637 2638 static ULONG WINAPI MimeSecurity_Release( 2639 IMimeSecurity* iface) 2640 { 2641 MimeSecurity *This = (MimeSecurity *)iface; 2642 ULONG refs; 2643 2644 TRACE("(%p)->()\n", iface); 2645 2646 refs = InterlockedDecrement(&This->refs); 2647 if (!refs) 2648 { 2649 HeapFree(GetProcessHeap(), 0, This); 2650 } 2651 2652 return refs; 2653 } 2654 2655 static HRESULT WINAPI MimeSecurity_InitNew( 2656 IMimeSecurity* iface) 2657 { 2658 FIXME("(%p)->(): stub\n", iface); 2659 return S_OK; 2660 } 2661 2662 static HRESULT WINAPI MimeSecurity_CheckInit( 2663 IMimeSecurity* iface) 2664 { 2665 FIXME("(%p)->(): stub\n", iface); 2666 return E_NOTIMPL; 2667 } 2668 2669 static HRESULT WINAPI MimeSecurity_EncodeMessage( 2670 IMimeSecurity* iface, 2671 IMimeMessageTree* pTree, 2672 DWORD dwFlags) 2673 { 2674 FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags); 2675 return E_NOTIMPL; 2676 } 2677 2678 static HRESULT WINAPI MimeSecurity_EncodeBody( 2679 IMimeSecurity* iface, 2680 IMimeMessageTree* pTree, 2681 HBODY hEncodeRoot, 2682 DWORD dwFlags) 2683 { 2684 FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hEncodeRoot, dwFlags); 2685 return E_NOTIMPL; 2686 } 2687 2688 static HRESULT WINAPI MimeSecurity_DecodeMessage( 2689 IMimeSecurity* iface, 2690 IMimeMessageTree* pTree, 2691 DWORD dwFlags) 2692 { 2693 FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags); 2694 return E_NOTIMPL; 2695 } 2696 2697 static HRESULT WINAPI MimeSecurity_DecodeBody( 2698 IMimeSecurity* iface, 2699 IMimeMessageTree* pTree, 2700 HBODY hDecodeRoot, 2701 DWORD dwFlags) 2702 { 2703 FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hDecodeRoot, dwFlags); 2704 return E_NOTIMPL; 2705 } 2706 2707 static HRESULT WINAPI MimeSecurity_EnumCertificates( 2708 IMimeSecurity* iface, 2709 HCAPICERTSTORE hc, 2710 DWORD dwUsage, 2711 PCX509CERT pPrev, 2712 PCX509CERT* ppCert) 2713 { 2714 FIXME("(%p)->(%p, %08x, %p, %p): stub\n", iface, hc, dwUsage, pPrev, ppCert); 2715 return E_NOTIMPL; 2716 } 2717 2718 static HRESULT WINAPI MimeSecurity_GetCertificateName( 2719 IMimeSecurity* iface, 2720 const PCX509CERT pX509Cert, 2721 const CERTNAMETYPE cn, 2722 LPSTR* ppszName) 2723 { 2724 FIXME("(%p)->(%p, %08x, %p): stub\n", iface, pX509Cert, cn, ppszName); 2725 return E_NOTIMPL; 2726 } 2727 2728 static HRESULT WINAPI MimeSecurity_GetMessageType( 2729 IMimeSecurity* iface, 2730 const HWND hwndParent, 2731 IMimeBody* pBody, 2732 DWORD* pdwSecType) 2733 { 2734 FIXME("(%p)->(%p, %p, %p): stub\n", iface, hwndParent, pBody, pdwSecType); 2735 return E_NOTIMPL; 2736 } 2737 2738 static HRESULT WINAPI MimeSecurity_GetCertData( 2739 IMimeSecurity* iface, 2740 const PCX509CERT pX509Cert, 2741 const CERTDATAID dataid, 2742 LPPROPVARIANT pValue) 2743 { 2744 FIXME("(%p)->(%p, %x, %p): stub\n", iface, pX509Cert, dataid, pValue); 2745 return E_NOTIMPL; 2746 } 2747 2748 2749 static const IMimeSecurityVtbl MimeSecurityVtbl = 2750 { 2751 MimeSecurity_QueryInterface, 2752 MimeSecurity_AddRef, 2753 MimeSecurity_Release, 2754 MimeSecurity_InitNew, 2755 MimeSecurity_CheckInit, 2756 MimeSecurity_EncodeMessage, 2757 MimeSecurity_EncodeBody, 2758 MimeSecurity_DecodeMessage, 2759 MimeSecurity_DecodeBody, 2760 MimeSecurity_EnumCertificates, 2761 MimeSecurity_GetCertificateName, 2762 MimeSecurity_GetMessageType, 2763 MimeSecurity_GetCertData 2764 }; 2765 2766 HRESULT MimeSecurity_create(IUnknown *outer, void **obj) 2767 { 2768 MimeSecurity *This; 2769 2770 *obj = NULL; 2771 2772 if (outer) return CLASS_E_NOAGGREGATION; 2773 2774 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 2775 if (!This) return E_OUTOFMEMORY; 2776 2777 This->lpVtbl = &MimeSecurityVtbl; 2778 This->refs = 1; 2779 2780 *obj = &This->lpVtbl; 2781 return S_OK; 2782 } 2783 2784 /*********************************************************************** 2785 * MimeOleCreateSecurity (INETCOMM.@) 2786 */ 2787 HRESULT WINAPI MimeOleCreateSecurity(IMimeSecurity **ppSecurity) 2788 { 2789 return MimeSecurity_create(NULL, (void **)ppSecurity); 2790 } 2791 2792 typedef struct 2793 { 2794 IMimeAllocatorVtbl *lpVtbl; 2795 } MimeAllocator; 2796 2797 static HRESULT WINAPI MimeAlloc_QueryInterface( 2798 IMimeAllocator* iface, 2799 REFIID riid, 2800 void **obj) 2801 { 2802 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), obj); 2803 2804 if (IsEqualIID(riid, &IID_IUnknown) || 2805 IsEqualIID(riid, &IID_IMalloc) || 2806 IsEqualIID(riid, &IID_IMimeAllocator)) 2807 { 2808 *obj = iface; 2809 IUnknown_AddRef(iface); 2810 return S_OK; 2811 } 2812 2813 FIXME("no interface for %s\n", debugstr_guid(riid)); 2814 *obj = NULL; 2815 return E_NOINTERFACE; 2816 } 2817 2818 static ULONG WINAPI MimeAlloc_AddRef( 2819 IMimeAllocator* iface) 2820 { 2821 return 2; 2822 } 2823 2824 static ULONG WINAPI MimeAlloc_Release( 2825 IMimeAllocator* iface) 2826 { 2827 return 1; 2828 } 2829 2830 static LPVOID WINAPI MimeAlloc_Alloc( 2831 IMimeAllocator* iface, 2832 ULONG cb) 2833 { 2834 return CoTaskMemAlloc(cb); 2835 } 2836 2837 static LPVOID WINAPI MimeAlloc_Realloc( 2838 IMimeAllocator* iface, 2839 LPVOID pv, 2840 ULONG cb) 2841 { 2842 return CoTaskMemRealloc(pv, cb); 2843 } 2844 2845 static void WINAPI MimeAlloc_Free( 2846 IMimeAllocator* iface, 2847 LPVOID pv) 2848 { 2849 CoTaskMemFree(pv); 2850 } 2851 2852 static ULONG WINAPI MimeAlloc_GetSize( 2853 IMimeAllocator* iface, 2854 LPVOID pv) 2855 { 2856 FIXME("stub\n"); 2857 return 0; 2858 } 2859 2860 static int WINAPI MimeAlloc_DidAlloc( 2861 IMimeAllocator* iface, 2862 LPVOID pv) 2863 { 2864 FIXME("stub\n"); 2865 return 0; 2866 } 2867 2868 static void WINAPI MimeAlloc_HeapMinimize( 2869 IMimeAllocator* iface) 2870 { 2871 FIXME("stub\n"); 2872 return; 2873 } 2874 2875 static HRESULT WINAPI MimeAlloc_FreeParamInfoArray( 2876 IMimeAllocator* iface, 2877 ULONG cParams, 2878 LPMIMEPARAMINFO prgParam, 2879 boolean fFreeArray) 2880 { 2881 ULONG i; 2882 TRACE("(%p)->(%d, %p, %d)\n", iface, cParams, prgParam, fFreeArray); 2883 2884 for(i = 0; i < cParams; i++) 2885 { 2886 IMimeAllocator_Free(iface, prgParam[i].pszName); 2887 IMimeAllocator_Free(iface, prgParam[i].pszData); 2888 } 2889 if(fFreeArray) IMimeAllocator_Free(iface, prgParam); 2890 return S_OK; 2891 } 2892 2893 static HRESULT WINAPI MimeAlloc_FreeAddressList( 2894 IMimeAllocator* iface, 2895 LPADDRESSLIST pList) 2896 { 2897 FIXME("stub\n"); 2898 return E_NOTIMPL; 2899 } 2900 2901 static HRESULT WINAPI MimeAlloc_FreeAddressProps( 2902 IMimeAllocator* iface, 2903 LPADDRESSPROPS pAddress) 2904 { 2905 FIXME("stub\n"); 2906 return E_NOTIMPL; 2907 } 2908 2909 static HRESULT WINAPI MimeAlloc_ReleaseObjects( 2910 IMimeAllocator* iface, 2911 ULONG cObjects, 2912 IUnknown **prgpUnknown, 2913 boolean fFreeArray) 2914 { 2915 FIXME("stub\n"); 2916 return E_NOTIMPL; 2917 } 2918 2919 2920 static HRESULT WINAPI MimeAlloc_FreeEnumHeaderRowArray( 2921 IMimeAllocator* iface, 2922 ULONG cRows, 2923 LPENUMHEADERROW prgRow, 2924 boolean fFreeArray) 2925 { 2926 FIXME("stub\n"); 2927 return E_NOTIMPL; 2928 } 2929 2930 static HRESULT WINAPI MimeAlloc_FreeEnumPropertyArray( 2931 IMimeAllocator* iface, 2932 ULONG cProps, 2933 LPENUMPROPERTY prgProp, 2934 boolean fFreeArray) 2935 { 2936 FIXME("stub\n"); 2937 return E_NOTIMPL; 2938 } 2939 2940 static HRESULT WINAPI MimeAlloc_FreeThumbprint( 2941 IMimeAllocator* iface, 2942 THUMBBLOB *pthumbprint) 2943 { 2944 FIXME("stub\n"); 2945 return E_NOTIMPL; 2946 } 2947 2948 2949 static HRESULT WINAPI MimeAlloc_PropVariantClear( 2950 IMimeAllocator* iface, 2951 LPPROPVARIANT pProp) 2952 { 2953 FIXME("stub\n"); 2954 return E_NOTIMPL; 2955 } 2956 2957 static IMimeAllocatorVtbl mime_alloc_vtbl = 2958 { 2959 MimeAlloc_QueryInterface, 2960 MimeAlloc_AddRef, 2961 MimeAlloc_Release, 2962 MimeAlloc_Alloc, 2963 MimeAlloc_Realloc, 2964 MimeAlloc_Free, 2965 MimeAlloc_GetSize, 2966 MimeAlloc_DidAlloc, 2967 MimeAlloc_HeapMinimize, 2968 MimeAlloc_FreeParamInfoArray, 2969 MimeAlloc_FreeAddressList, 2970 MimeAlloc_FreeAddressProps, 2971 MimeAlloc_ReleaseObjects, 2972 MimeAlloc_FreeEnumHeaderRowArray, 2973 MimeAlloc_FreeEnumPropertyArray, 2974 MimeAlloc_FreeThumbprint, 2975 MimeAlloc_PropVariantClear 2976 }; 2977 2978 static MimeAllocator mime_allocator = 2979 { 2980 &mime_alloc_vtbl 2981 }; 2982 2983 HRESULT MimeAllocator_create(IUnknown *outer, void **obj) 2984 { 2985 if(outer) return CLASS_E_NOAGGREGATION; 2986 2987 *obj = &mime_allocator; 2988 return S_OK; 2989 } 2990 2991 HRESULT WINAPI MimeOleGetAllocator(IMimeAllocator **alloc) 2992 { 2993 return MimeAllocator_create(NULL, (void**)alloc); 2994 } 2995 2996 HRESULT VirtualStream_create(IUnknown *outer, void **obj) 2997 { 2998 FIXME("(%p, %p)\n", outer, obj); 2999 3000 *obj = NULL; 3001 if (outer) return CLASS_E_NOAGGREGATION; 3002 3003 return MimeOleCreateVirtualStream((IStream **)obj); 3004 } 3005