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 HBODY hbody; 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 HBODY next_hbody; 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, HBODY hbody, 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->hbody = hbody; 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_hbody, parent); 1634 msg->next_hbody = (HBODY)((DWORD)msg->next_hbody + 1); 1635 1636 if(IMimeBody_IsContentType(mime_body, "multipart", NULL) == S_OK) 1637 { 1638 MIMEPARAMINFO *param_info; 1639 ULONG count, i; 1640 IMimeAllocator *alloc; 1641 1642 hr = IMimeBody_GetParameters(mime_body, "Content-Type", &count, ¶m_info); 1643 if(hr != S_OK || count == 0) return body; 1644 1645 MimeOleGetAllocator(&alloc); 1646 1647 for(i = 0; i < count; i++) 1648 { 1649 if(!strcasecmp(param_info[i].pszName, "boundary")) 1650 { 1651 struct list offset_list; 1652 offset_entry_t *cur, *cursor2; 1653 hr = create_body_offset_list(pStm, param_info[i].pszData, &offset_list); 1654 LIST_FOR_EACH_ENTRY_SAFE(cur, cursor2, &offset_list, offset_entry_t, entry) 1655 { 1656 body_t *sub_body; 1657 IStream *sub_stream; 1658 ULARGE_INTEGER start, length; 1659 1660 start.QuadPart = cur->offsets.cbHeaderStart; 1661 length.QuadPart = cur->offsets.cbBodyEnd - cur->offsets.cbHeaderStart; 1662 create_sub_stream(pStm, start, length, &sub_stream); 1663 sub_body = create_sub_body(msg, sub_stream, &cur->offsets, body); 1664 IStream_Release(sub_stream); 1665 list_add_tail(&body->children, &sub_body->entry); 1666 list_remove(&cur->entry); 1667 HeapFree(GetProcessHeap(), 0, cur); 1668 } 1669 break; 1670 } 1671 } 1672 IMimeAllocator_FreeParamInfoArray(alloc, count, param_info, TRUE); 1673 IMimeAllocator_Release(alloc); 1674 } 1675 return body; 1676 } 1677 1678 static HRESULT WINAPI MimeMessage_Load( 1679 IMimeMessage *iface, 1680 LPSTREAM pStm) 1681 { 1682 MimeMessage *This = (MimeMessage *)iface; 1683 body_t *root_body; 1684 BODYOFFSETS offsets; 1685 ULARGE_INTEGER cur; 1686 LARGE_INTEGER zero; 1687 1688 TRACE("(%p)->(%p)\n", iface, pStm); 1689 1690 if(This->stream) 1691 { 1692 FIXME("already loaded a message\n"); 1693 return E_FAIL; 1694 } 1695 1696 IStream_AddRef(pStm); 1697 This->stream = pStm; 1698 offsets.cbBoundaryStart = offsets.cbHeaderStart = 0; 1699 offsets.cbBodyStart = offsets.cbBodyEnd = 0; 1700 1701 root_body = create_sub_body(This, pStm, &offsets, NULL); 1702 1703 zero.QuadPart = 0; 1704 IStream_Seek(pStm, zero, STREAM_SEEK_END, &cur); 1705 offsets.cbBodyEnd = cur.u.LowPart; 1706 MimeBody_set_offsets(impl_from_IMimeBody(root_body->mime_body), &offsets); 1707 1708 list_add_head(&This->body_tree, &root_body->entry); 1709 1710 return S_OK; 1711 } 1712 1713 static HRESULT WINAPI MimeMessage_Save( 1714 IMimeMessage *iface, 1715 LPSTREAM pStm, 1716 BOOL fClearDirty) 1717 { 1718 FIXME("(%p)->(%p, %s)\n", iface, pStm, fClearDirty ? "TRUE" : "FALSE"); 1719 return E_NOTIMPL; 1720 } 1721 1722 static HRESULT WINAPI MimeMessage_GetSizeMax( 1723 IMimeMessage *iface, 1724 ULARGE_INTEGER *pcbSize) 1725 { 1726 FIXME("(%p)->(%p)\n", iface, pcbSize); 1727 return E_NOTIMPL; 1728 } 1729 1730 static HRESULT WINAPI MimeMessage_InitNew( 1731 IMimeMessage *iface) 1732 { 1733 FIXME("(%p)->()\n", iface); 1734 return E_NOTIMPL; 1735 } 1736 1737 /*** IMimeMessageTree methods ***/ 1738 static HRESULT WINAPI MimeMessage_GetMessageSource( 1739 IMimeMessage *iface, 1740 IStream **ppStream, 1741 DWORD dwFlags) 1742 { 1743 MimeMessage *This = (MimeMessage *)iface; 1744 FIXME("(%p)->(%p, 0x%x)\n", iface, ppStream, dwFlags); 1745 1746 IStream_AddRef(This->stream); 1747 *ppStream = This->stream; 1748 return S_OK; 1749 } 1750 1751 static HRESULT WINAPI MimeMessage_GetMessageSize( 1752 IMimeMessage *iface, 1753 ULONG *pcbSize, 1754 DWORD dwFlags) 1755 { 1756 FIXME("(%p)->(%p, 0x%x)\n", iface, pcbSize, dwFlags); 1757 return E_NOTIMPL; 1758 } 1759 1760 static HRESULT WINAPI MimeMessage_LoadOffsetTable( 1761 IMimeMessage *iface, 1762 IStream *pStream) 1763 { 1764 FIXME("(%p)->(%p)\n", iface, pStream); 1765 return E_NOTIMPL; 1766 } 1767 1768 static HRESULT WINAPI MimeMessage_SaveOffsetTable( 1769 IMimeMessage *iface, 1770 IStream *pStream, 1771 DWORD dwFlags) 1772 { 1773 FIXME("(%p)->(%p, 0x%x)\n", iface, pStream, dwFlags); 1774 return E_NOTIMPL; 1775 } 1776 1777 1778 static HRESULT WINAPI MimeMessage_GetFlags( 1779 IMimeMessage *iface, 1780 DWORD *pdwFlags) 1781 { 1782 FIXME("(%p)->(%p)\n", iface, pdwFlags); 1783 return E_NOTIMPL; 1784 } 1785 1786 static HRESULT WINAPI MimeMessage_Commit( 1787 IMimeMessage *iface, 1788 DWORD dwFlags) 1789 { 1790 FIXME("(%p)->(0x%x)\n", iface, dwFlags); 1791 return E_NOTIMPL; 1792 } 1793 1794 1795 static HRESULT WINAPI MimeMessage_HandsOffStorage( 1796 IMimeMessage *iface) 1797 { 1798 FIXME("(%p)->()\n", iface); 1799 return E_NOTIMPL; 1800 } 1801 1802 static HRESULT find_body(struct list *list, HBODY hbody, body_t **body) 1803 { 1804 body_t *cur; 1805 HRESULT hr; 1806 1807 if(hbody == HBODY_ROOT) 1808 { 1809 *body = LIST_ENTRY(list_head(list), body_t, entry); 1810 return S_OK; 1811 } 1812 1813 LIST_FOR_EACH_ENTRY(cur, list, body_t, entry) 1814 { 1815 if(cur->hbody == hbody) 1816 { 1817 *body = cur; 1818 return S_OK; 1819 } 1820 hr = find_body(&cur->children, hbody, body); 1821 if(hr == S_OK) return S_OK; 1822 } 1823 return S_FALSE; 1824 } 1825 1826 static HRESULT WINAPI MimeMessage_BindToObject( 1827 IMimeMessage *iface, 1828 const HBODY hBody, 1829 REFIID riid, 1830 void **ppvObject) 1831 { 1832 MimeMessage *This = (MimeMessage *)iface; 1833 HRESULT hr; 1834 body_t *body; 1835 1836 TRACE("(%p)->(%p, %s, %p)\n", iface, hBody, debugstr_guid(riid), ppvObject); 1837 1838 hr = find_body(&This->body_tree, hBody, &body); 1839 1840 if(hr != S_OK) return hr; 1841 1842 if(IsEqualIID(riid, &IID_IMimeBody)) 1843 { 1844 IMimeBody_AddRef(body->mime_body); 1845 *ppvObject = body->mime_body; 1846 return S_OK; 1847 } 1848 1849 return E_NOINTERFACE; 1850 } 1851 1852 static HRESULT WINAPI MimeMessage_SaveBody( 1853 IMimeMessage *iface, 1854 HBODY hBody, 1855 DWORD dwFlags, 1856 IStream *pStream) 1857 { 1858 FIXME("(%p)->(%p, 0x%x, %p)\n", iface, hBody, dwFlags, pStream); 1859 return E_NOTIMPL; 1860 } 1861 1862 static HRESULT get_body(MimeMessage *msg, BODYLOCATION location, HBODY pivot, body_t **out) 1863 { 1864 body_t *root = LIST_ENTRY(list_head(&msg->body_tree), body_t, entry); 1865 body_t *body; 1866 HRESULT hr; 1867 struct list *list; 1868 1869 if(location == IBL_ROOT) 1870 { 1871 *out = root; 1872 return S_OK; 1873 } 1874 1875 hr = find_body(&msg->body_tree, pivot, &body); 1876 1877 if(hr == S_OK) 1878 { 1879 switch(location) 1880 { 1881 case IBL_PARENT: 1882 *out = body->parent; 1883 break; 1884 1885 case IBL_FIRST: 1886 list = list_head(&body->children); 1887 if(list) 1888 *out = LIST_ENTRY(list, body_t, entry); 1889 else 1890 hr = MIME_E_NOT_FOUND; 1891 break; 1892 1893 case IBL_LAST: 1894 list = list_tail(&body->children); 1895 if(list) 1896 *out = LIST_ENTRY(list, body_t, entry); 1897 else 1898 hr = MIME_E_NOT_FOUND; 1899 break; 1900 1901 case IBL_NEXT: 1902 list = list_next(&body->parent->children, &body->entry); 1903 if(list) 1904 *out = LIST_ENTRY(list, body_t, entry); 1905 else 1906 hr = MIME_E_NOT_FOUND; 1907 break; 1908 1909 case IBL_PREVIOUS: 1910 list = list_prev(&body->parent->children, &body->entry); 1911 if(list) 1912 *out = LIST_ENTRY(list, body_t, entry); 1913 else 1914 hr = MIME_E_NOT_FOUND; 1915 break; 1916 1917 default: 1918 hr = E_FAIL; 1919 break; 1920 } 1921 } 1922 1923 return hr; 1924 } 1925 1926 1927 static HRESULT WINAPI MimeMessage_InsertBody( 1928 IMimeMessage *iface, 1929 BODYLOCATION location, 1930 HBODY hPivot, 1931 LPHBODY phBody) 1932 { 1933 FIXME("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody); 1934 return E_NOTIMPL; 1935 } 1936 1937 static HRESULT WINAPI MimeMessage_GetBody( 1938 IMimeMessage *iface, 1939 BODYLOCATION location, 1940 HBODY hPivot, 1941 LPHBODY phBody) 1942 { 1943 MimeMessage *This = (MimeMessage *)iface; 1944 body_t *body; 1945 HRESULT hr; 1946 1947 TRACE("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody); 1948 1949 hr = get_body(This, location, hPivot, &body); 1950 1951 if(hr == S_OK) *phBody = body->hbody; 1952 1953 return hr; 1954 } 1955 1956 static HRESULT WINAPI MimeMessage_DeleteBody( 1957 IMimeMessage *iface, 1958 HBODY hBody, 1959 DWORD dwFlags) 1960 { 1961 FIXME("(%p)->(%p, %08x)\n", iface, hBody, dwFlags); 1962 return E_NOTIMPL; 1963 } 1964 1965 static HRESULT WINAPI MimeMessage_MoveBody( 1966 IMimeMessage *iface, 1967 HBODY hBody, 1968 BODYLOCATION location) 1969 { 1970 FIXME("(%p)->(%d)\n", iface, location); 1971 return E_NOTIMPL; 1972 } 1973 1974 static void count_children(body_t *body, boolean recurse, ULONG *count) 1975 { 1976 body_t *child; 1977 1978 LIST_FOR_EACH_ENTRY(child, &body->children, body_t, entry) 1979 { 1980 (*count)++; 1981 if(recurse) count_children(child, recurse, count); 1982 } 1983 } 1984 1985 static HRESULT WINAPI MimeMessage_CountBodies( 1986 IMimeMessage *iface, 1987 HBODY hParent, 1988 boolean fRecurse, 1989 ULONG *pcBodies) 1990 { 1991 HRESULT hr; 1992 MimeMessage *This = (MimeMessage *)iface; 1993 body_t *body; 1994 1995 TRACE("(%p)->(%p, %s, %p)\n", iface, hParent, fRecurse ? "TRUE" : "FALSE", pcBodies); 1996 1997 hr = find_body(&This->body_tree, hParent, &body); 1998 if(hr != S_OK) return hr; 1999 2000 *pcBodies = 1; 2001 count_children(body, fRecurse, pcBodies); 2002 2003 return S_OK; 2004 } 2005 2006 static HRESULT find_next(IMimeMessage *msg, LPFINDBODY find_body, HBODY *out) 2007 { 2008 HRESULT hr; 2009 IMimeBody *mime_body; 2010 HBODY next; 2011 2012 if(find_body->dwReserved == 0) 2013 find_body->dwReserved = (DWORD)HBODY_ROOT; 2014 else 2015 { 2016 hr = IMimeMessage_GetBody(msg, IBL_FIRST, (HBODY)find_body->dwReserved, &next); 2017 if(hr == S_OK) 2018 find_body->dwReserved = (DWORD)next; 2019 else 2020 { 2021 hr = IMimeMessage_GetBody(msg, IBL_NEXT, (HBODY)find_body->dwReserved, &next); 2022 if(hr == S_OK) 2023 find_body->dwReserved = (DWORD)next; 2024 else 2025 return MIME_E_NOT_FOUND; 2026 } 2027 } 2028 2029 hr = IMimeMessage_BindToObject(msg, (HBODY)find_body->dwReserved, &IID_IMimeBody, (void**)&mime_body); 2030 if(IMimeBody_IsContentType(mime_body, find_body->pszPriType, find_body->pszSubType) == S_OK) 2031 { 2032 IMimeBody_Release(mime_body); 2033 *out = (HBODY)find_body->dwReserved; 2034 return S_OK; 2035 } 2036 IMimeBody_Release(mime_body); 2037 return find_next(msg, find_body, out); 2038 } 2039 2040 static HRESULT WINAPI MimeMessage_FindFirst( 2041 IMimeMessage *iface, 2042 LPFINDBODY pFindBody, 2043 LPHBODY phBody) 2044 { 2045 TRACE("(%p)->(%p, %p)\n", iface, pFindBody, phBody); 2046 2047 pFindBody->dwReserved = 0; 2048 return find_next(iface, pFindBody, phBody); 2049 } 2050 2051 static HRESULT WINAPI MimeMessage_FindNext( 2052 IMimeMessage *iface, 2053 LPFINDBODY pFindBody, 2054 LPHBODY phBody) 2055 { 2056 TRACE("(%p)->(%p, %p)\n", iface, pFindBody, phBody); 2057 2058 return find_next(iface, pFindBody, phBody); 2059 } 2060 2061 static HRESULT WINAPI MimeMessage_ResolveURL( 2062 IMimeMessage *iface, 2063 HBODY hRelated, 2064 LPCSTR pszBase, 2065 LPCSTR pszURL, 2066 DWORD dwFlags, 2067 LPHBODY phBody) 2068 { 2069 FIXME("(%p)->(%p, %s, %s, 0x%x, %p)\n", iface, hRelated, pszBase, pszURL, dwFlags, phBody); 2070 return E_NOTIMPL; 2071 } 2072 2073 static HRESULT WINAPI MimeMessage_ToMultipart( 2074 IMimeMessage *iface, 2075 HBODY hBody, 2076 LPCSTR pszSubType, 2077 LPHBODY phMultipart) 2078 { 2079 FIXME("(%p)->(%p, %s, %p)\n", iface, hBody, pszSubType, phMultipart); 2080 return E_NOTIMPL; 2081 } 2082 2083 static HRESULT WINAPI MimeMessage_GetBodyOffsets( 2084 IMimeMessage *iface, 2085 HBODY hBody, 2086 LPBODYOFFSETS pOffsets) 2087 { 2088 FIXME("(%p)->(%p, %p)\n", iface, hBody, pOffsets); 2089 return E_NOTIMPL; 2090 } 2091 2092 static HRESULT WINAPI MimeMessage_GetCharset( 2093 IMimeMessage *iface, 2094 LPHCHARSET phCharset) 2095 { 2096 FIXME("(%p)->(%p)\n", iface, phCharset); 2097 *phCharset = NULL; 2098 return S_OK; 2099 } 2100 2101 static HRESULT WINAPI MimeMessage_SetCharset( 2102 IMimeMessage *iface, 2103 HCHARSET hCharset, 2104 CSETAPPLYTYPE applytype) 2105 { 2106 FIXME("(%p)->(%p, %d)\n", iface, hCharset, applytype); 2107 return E_NOTIMPL; 2108 } 2109 2110 static HRESULT WINAPI MimeMessage_IsBodyType( 2111 IMimeMessage *iface, 2112 HBODY hBody, 2113 IMSGBODYTYPE bodytype) 2114 { 2115 HRESULT hr; 2116 IMimeBody *mime_body; 2117 TRACE("(%p)->(%p, %d)\n", iface, hBody, bodytype); 2118 2119 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body); 2120 if(hr != S_OK) return hr; 2121 2122 hr = IMimeBody_IsType(mime_body, bodytype); 2123 MimeBody_Release(mime_body); 2124 return hr; 2125 } 2126 2127 static HRESULT WINAPI MimeMessage_IsContentType( 2128 IMimeMessage *iface, 2129 HBODY hBody, 2130 LPCSTR pszPriType, 2131 LPCSTR pszSubType) 2132 { 2133 HRESULT hr; 2134 IMimeBody *mime_body; 2135 TRACE("(%p)->(%p, %s, %s)\n", iface, hBody, pszPriType, pszSubType); 2136 2137 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body); 2138 if(FAILED(hr)) return hr; 2139 2140 hr = IMimeBody_IsContentType(mime_body, pszPriType, pszSubType); 2141 IMimeBody_Release(mime_body); 2142 return hr; 2143 } 2144 2145 static HRESULT WINAPI MimeMessage_QueryBodyProp( 2146 IMimeMessage *iface, 2147 HBODY hBody, 2148 LPCSTR pszName, 2149 LPCSTR pszCriteria, 2150 boolean fSubString, 2151 boolean fCaseSensitive) 2152 { 2153 FIXME("(%p)->(%p, %s, %s, %s, %s)\n", iface, hBody, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE"); 2154 return E_NOTIMPL; 2155 } 2156 2157 static HRESULT WINAPI MimeMessage_GetBodyProp( 2158 IMimeMessage *iface, 2159 HBODY hBody, 2160 LPCSTR pszName, 2161 DWORD dwFlags, 2162 LPPROPVARIANT pValue) 2163 { 2164 HRESULT hr; 2165 IMimeBody *mime_body; 2166 2167 TRACE("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue); 2168 2169 hr = IMimeMessage_BindToObject(iface, hBody, &IID_IMimeBody, (void**)&mime_body); 2170 if(hr != S_OK) return hr; 2171 2172 hr = IMimeBody_GetProp(mime_body, pszName, dwFlags, pValue); 2173 IMimeBody_Release(mime_body); 2174 2175 return hr; 2176 } 2177 2178 static HRESULT WINAPI MimeMessage_SetBodyProp( 2179 IMimeMessage *iface, 2180 HBODY hBody, 2181 LPCSTR pszName, 2182 DWORD dwFlags, 2183 LPCPROPVARIANT pValue) 2184 { 2185 FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue); 2186 return E_NOTIMPL; 2187 } 2188 2189 static HRESULT WINAPI MimeMessage_DeleteBodyProp( 2190 IMimeMessage *iface, 2191 HBODY hBody, 2192 LPCSTR pszName) 2193 { 2194 FIXME("(%p)->(%p, %s)\n", iface, hBody, pszName); 2195 return E_NOTIMPL; 2196 } 2197 2198 static HRESULT WINAPI MimeMessage_SetOption( 2199 IMimeMessage *iface, 2200 const TYPEDID oid, 2201 LPCPROPVARIANT pValue) 2202 { 2203 HRESULT hr = E_NOTIMPL; 2204 TRACE("(%p)->(%08x, %p)\n", iface, oid, pValue); 2205 2206 if(pValue->vt != TYPEDID_TYPE(oid)) 2207 { 2208 WARN("Called with vartype %04x and oid %08x\n", pValue->vt, oid); 2209 return E_INVALIDARG; 2210 } 2211 2212 switch(oid) 2213 { 2214 case OID_HIDE_TNEF_ATTACHMENTS: 2215 FIXME("OID_HIDE_TNEF_ATTACHMENTS (value %d): ignoring\n", pValue->u.boolVal); 2216 hr = S_OK; 2217 break; 2218 case OID_SHOW_MACBINARY: 2219 FIXME("OID_SHOW_MACBINARY (value %d): ignoring\n", pValue->u.boolVal); 2220 hr = S_OK; 2221 break; 2222 default: 2223 FIXME("Unhandled oid %08x\n", oid); 2224 } 2225 2226 return hr; 2227 } 2228 2229 static HRESULT WINAPI MimeMessage_GetOption( 2230 IMimeMessage *iface, 2231 const TYPEDID oid, 2232 LPPROPVARIANT pValue) 2233 { 2234 FIXME("(%p)->(%08x, %p)\n", iface, oid, pValue); 2235 return E_NOTIMPL; 2236 } 2237 2238 /*** IMimeMessage methods ***/ 2239 static HRESULT WINAPI MimeMessage_CreateWebPage( 2240 IMimeMessage *iface, 2241 IStream *pRootStm, 2242 LPWEBPAGEOPTIONS pOptions, 2243 IMimeMessageCallback *pCallback, 2244 IMoniker **ppMoniker) 2245 { 2246 FIXME("(%p)->(%p, %p, %p, %p)\n", iface, pRootStm, pOptions, pCallback, ppMoniker); 2247 *ppMoniker = NULL; 2248 return E_NOTIMPL; 2249 } 2250 2251 static HRESULT WINAPI MimeMessage_GetProp( 2252 IMimeMessage *iface, 2253 LPCSTR pszName, 2254 DWORD dwFlags, 2255 LPPROPVARIANT pValue) 2256 { 2257 FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue); 2258 return E_NOTIMPL; 2259 } 2260 2261 static HRESULT WINAPI MimeMessage_SetProp( 2262 IMimeMessage *iface, 2263 LPCSTR pszName, 2264 DWORD dwFlags, 2265 LPCPROPVARIANT pValue) 2266 { 2267 FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue); 2268 return E_NOTIMPL; 2269 } 2270 2271 static HRESULT WINAPI MimeMessage_DeleteProp( 2272 IMimeMessage *iface, 2273 LPCSTR pszName) 2274 { 2275 FIXME("(%p)->(%s)\n", iface, pszName); 2276 return E_NOTIMPL; 2277 } 2278 2279 static HRESULT WINAPI MimeMessage_QueryProp( 2280 IMimeMessage *iface, 2281 LPCSTR pszName, 2282 LPCSTR pszCriteria, 2283 boolean fSubString, 2284 boolean fCaseSensitive) 2285 { 2286 FIXME("(%p)->(%s, %s, %s, %s)\n", iface, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE"); 2287 return E_NOTIMPL; 2288 } 2289 2290 static HRESULT WINAPI MimeMessage_GetTextBody( 2291 IMimeMessage *iface, 2292 DWORD dwTxtType, 2293 ENCODINGTYPE ietEncoding, 2294 IStream **pStream, 2295 LPHBODY phBody) 2296 { 2297 HRESULT hr; 2298 HBODY hbody; 2299 FINDBODY find_struct; 2300 IMimeBody *mime_body; 2301 static char text[] = "text"; 2302 static char plain[] = "plain"; 2303 static char html[] = "html"; 2304 2305 TRACE("(%p)->(%d, %d, %p, %p)\n", iface, dwTxtType, ietEncoding, pStream, phBody); 2306 2307 find_struct.pszPriType = text; 2308 2309 switch(dwTxtType) 2310 { 2311 case TXT_PLAIN: 2312 find_struct.pszSubType = plain; 2313 break; 2314 case TXT_HTML: 2315 find_struct.pszSubType = html; 2316 break; 2317 default: 2318 return MIME_E_INVALID_TEXT_TYPE; 2319 } 2320 2321 hr = IMimeMessage_FindFirst(iface, &find_struct, &hbody); 2322 if(hr != S_OK) 2323 { 2324 TRACE("not found hr %08x\n", hr); 2325 *phBody = NULL; 2326 return hr; 2327 } 2328 2329 IMimeMessage_BindToObject(iface, hbody, &IID_IMimeBody, (void**)&mime_body); 2330 2331 IMimeBody_GetData(mime_body, ietEncoding, pStream); 2332 *phBody = hbody; 2333 IMimeBody_Release(mime_body); 2334 return hr; 2335 } 2336 2337 static HRESULT WINAPI MimeMessage_SetTextBody( 2338 IMimeMessage *iface, 2339 DWORD dwTxtType, 2340 ENCODINGTYPE ietEncoding, 2341 HBODY hAlternative, 2342 IStream *pStream, 2343 LPHBODY phBody) 2344 { 2345 FIXME("(%p)->(%d, %d, %p, %p, %p)\n", iface, dwTxtType, ietEncoding, hAlternative, pStream, phBody); 2346 return E_NOTIMPL; 2347 } 2348 2349 static HRESULT WINAPI MimeMessage_AttachObject( 2350 IMimeMessage *iface, 2351 REFIID riid, 2352 void *pvObject, 2353 LPHBODY phBody) 2354 { 2355 FIXME("(%p)->(%s, %p, %p)\n", iface, debugstr_guid(riid), pvObject, phBody); 2356 return E_NOTIMPL; 2357 } 2358 2359 static HRESULT WINAPI MimeMessage_AttachFile( 2360 IMimeMessage *iface, 2361 LPCSTR pszFilePath, 2362 IStream *pstmFile, 2363 LPHBODY phBody) 2364 { 2365 FIXME("(%p)->(%s, %p, %p)\n", iface, pszFilePath, pstmFile, phBody); 2366 return E_NOTIMPL; 2367 } 2368 2369 static HRESULT WINAPI MimeMessage_AttachURL( 2370 IMimeMessage *iface, 2371 LPCSTR pszBase, 2372 LPCSTR pszURL, 2373 DWORD dwFlags, 2374 IStream *pstmURL, 2375 LPSTR *ppszCIDURL, 2376 LPHBODY phBody) 2377 { 2378 FIXME("(%p)->(%s, %s, 0x%x, %p, %p, %p)\n", iface, pszBase, pszURL, dwFlags, pstmURL, ppszCIDURL, phBody); 2379 return E_NOTIMPL; 2380 } 2381 2382 static HRESULT WINAPI MimeMessage_GetAttachments( 2383 IMimeMessage *iface, 2384 ULONG *pcAttach, 2385 LPHBODY *pprghAttach) 2386 { 2387 HRESULT hr; 2388 FINDBODY find_struct; 2389 HBODY hbody; 2390 LPHBODY array; 2391 ULONG size = 10; 2392 2393 TRACE("(%p)->(%p, %p)\n", iface, pcAttach, pprghAttach); 2394 2395 *pcAttach = 0; 2396 array = CoTaskMemAlloc(size * sizeof(HBODY)); 2397 2398 find_struct.pszPriType = find_struct.pszSubType = NULL; 2399 hr = IMimeMessage_FindFirst(iface, &find_struct, &hbody); 2400 while(hr == S_OK) 2401 { 2402 hr = IMimeMessage_IsContentType(iface, hbody, "multipart", NULL); 2403 TRACE("IsCT rets %08x %d\n", hr, *pcAttach); 2404 if(hr != S_OK) 2405 { 2406 if(*pcAttach + 1 > size) 2407 { 2408 size *= 2; 2409 array = CoTaskMemRealloc(array, size * sizeof(HBODY)); 2410 } 2411 array[*pcAttach] = hbody; 2412 (*pcAttach)++; 2413 } 2414 hr = IMimeMessage_FindNext(iface, &find_struct, &hbody); 2415 } 2416 2417 *pprghAttach = array; 2418 return S_OK; 2419 } 2420 2421 static HRESULT WINAPI MimeMessage_GetAddressTable( 2422 IMimeMessage *iface, 2423 IMimeAddressTable **ppTable) 2424 { 2425 FIXME("(%p)->(%p)\n", iface, ppTable); 2426 return E_NOTIMPL; 2427 } 2428 2429 static HRESULT WINAPI MimeMessage_GetSender( 2430 IMimeMessage *iface, 2431 LPADDRESSPROPS pAddress) 2432 { 2433 FIXME("(%p)->(%p)\n", iface, pAddress); 2434 return E_NOTIMPL; 2435 } 2436 2437 static HRESULT WINAPI MimeMessage_GetAddressTypes( 2438 IMimeMessage *iface, 2439 DWORD dwAdrTypes, 2440 DWORD dwProps, 2441 LPADDRESSLIST pList) 2442 { 2443 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, pList); 2444 return E_NOTIMPL; 2445 } 2446 2447 static HRESULT WINAPI MimeMessage_GetAddressFormat( 2448 IMimeMessage *iface, 2449 DWORD dwAdrTypes, 2450 ADDRESSFORMAT format, 2451 LPSTR *ppszFormat) 2452 { 2453 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, format, ppszFormat); 2454 return E_NOTIMPL; 2455 } 2456 2457 static HRESULT WINAPI MimeMessage_EnumAddressTypes( 2458 IMimeMessage *iface, 2459 DWORD dwAdrTypes, 2460 DWORD dwProps, 2461 IMimeEnumAddressTypes **ppEnum) 2462 { 2463 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, ppEnum); 2464 return E_NOTIMPL; 2465 } 2466 2467 static HRESULT WINAPI MimeMessage_SplitMessage( 2468 IMimeMessage *iface, 2469 ULONG cbMaxPart, 2470 IMimeMessageParts **ppParts) 2471 { 2472 FIXME("(%p)->(%d, %p)\n", iface, cbMaxPart, ppParts); 2473 return E_NOTIMPL; 2474 } 2475 2476 static HRESULT WINAPI MimeMessage_GetRootMoniker( 2477 IMimeMessage *iface, 2478 IMoniker **ppMoniker) 2479 { 2480 FIXME("(%p)->(%p)\n", iface, ppMoniker); 2481 return E_NOTIMPL; 2482 } 2483 2484 static const IMimeMessageVtbl MimeMessageVtbl = 2485 { 2486 MimeMessage_QueryInterface, 2487 MimeMessage_AddRef, 2488 MimeMessage_Release, 2489 MimeMessage_GetClassID, 2490 MimeMessage_IsDirty, 2491 MimeMessage_Load, 2492 MimeMessage_Save, 2493 MimeMessage_GetSizeMax, 2494 MimeMessage_InitNew, 2495 MimeMessage_GetMessageSource, 2496 MimeMessage_GetMessageSize, 2497 MimeMessage_LoadOffsetTable, 2498 MimeMessage_SaveOffsetTable, 2499 MimeMessage_GetFlags, 2500 MimeMessage_Commit, 2501 MimeMessage_HandsOffStorage, 2502 MimeMessage_BindToObject, 2503 MimeMessage_SaveBody, 2504 MimeMessage_InsertBody, 2505 MimeMessage_GetBody, 2506 MimeMessage_DeleteBody, 2507 MimeMessage_MoveBody, 2508 MimeMessage_CountBodies, 2509 MimeMessage_FindFirst, 2510 MimeMessage_FindNext, 2511 MimeMessage_ResolveURL, 2512 MimeMessage_ToMultipart, 2513 MimeMessage_GetBodyOffsets, 2514 MimeMessage_GetCharset, 2515 MimeMessage_SetCharset, 2516 MimeMessage_IsBodyType, 2517 MimeMessage_IsContentType, 2518 MimeMessage_QueryBodyProp, 2519 MimeMessage_GetBodyProp, 2520 MimeMessage_SetBodyProp, 2521 MimeMessage_DeleteBodyProp, 2522 MimeMessage_SetOption, 2523 MimeMessage_GetOption, 2524 MimeMessage_CreateWebPage, 2525 MimeMessage_GetProp, 2526 MimeMessage_SetProp, 2527 MimeMessage_DeleteProp, 2528 MimeMessage_QueryProp, 2529 MimeMessage_GetTextBody, 2530 MimeMessage_SetTextBody, 2531 MimeMessage_AttachObject, 2532 MimeMessage_AttachFile, 2533 MimeMessage_AttachURL, 2534 MimeMessage_GetAttachments, 2535 MimeMessage_GetAddressTable, 2536 MimeMessage_GetSender, 2537 MimeMessage_GetAddressTypes, 2538 MimeMessage_GetAddressFormat, 2539 MimeMessage_EnumAddressTypes, 2540 MimeMessage_SplitMessage, 2541 MimeMessage_GetRootMoniker, 2542 }; 2543 2544 HRESULT MimeMessage_create(IUnknown *outer, void **obj) 2545 { 2546 MimeMessage *This; 2547 2548 TRACE("(%p, %p)\n", outer, obj); 2549 2550 if (outer) 2551 { 2552 FIXME("outer unknown not supported yet\n"); 2553 return E_NOTIMPL; 2554 } 2555 2556 *obj = NULL; 2557 2558 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 2559 if (!This) return E_OUTOFMEMORY; 2560 2561 This->lpVtbl = &MimeMessageVtbl; 2562 This->refs = 1; 2563 This->stream = NULL; 2564 list_init(&This->body_tree); 2565 This->next_hbody = (HBODY)1; 2566 2567 *obj = &This->lpVtbl; 2568 return S_OK; 2569 } 2570 2571 /*********************************************************************** 2572 * MimeOleCreateMessage (INETCOMM.@) 2573 */ 2574 HRESULT WINAPI MimeOleCreateMessage(IUnknown *pUnkOuter, IMimeMessage **ppMessage) 2575 { 2576 TRACE("(%p, %p)\n", pUnkOuter, ppMessage); 2577 return MimeMessage_create(NULL, (void **)ppMessage); 2578 } 2579 2580 /*********************************************************************** 2581 * MimeOleSetCompatMode (INETCOMM.@) 2582 */ 2583 HRESULT WINAPI MimeOleSetCompatMode(DWORD dwMode) 2584 { 2585 FIXME("(0x%x)\n", dwMode); 2586 return S_OK; 2587 } 2588 2589 /*********************************************************************** 2590 * MimeOleCreateVirtualStream (INETCOMM.@) 2591 */ 2592 HRESULT WINAPI MimeOleCreateVirtualStream(IStream **ppStream) 2593 { 2594 HRESULT hr; 2595 FIXME("(%p)\n", ppStream); 2596 2597 hr = CreateStreamOnHGlobal(NULL, TRUE, ppStream); 2598 return hr; 2599 } 2600 2601 typedef struct MimeSecurity 2602 { 2603 const IMimeSecurityVtbl *lpVtbl; 2604 2605 LONG refs; 2606 } MimeSecurity; 2607 2608 static HRESULT WINAPI MimeSecurity_QueryInterface( 2609 IMimeSecurity* iface, 2610 REFIID riid, 2611 void** obj) 2612 { 2613 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), obj); 2614 2615 if (IsEqualIID(riid, &IID_IUnknown) || 2616 IsEqualIID(riid, &IID_IMimeSecurity)) 2617 { 2618 *obj = iface; 2619 IUnknown_AddRef(iface); 2620 return S_OK; 2621 } 2622 2623 FIXME("no interface for %s\n", debugstr_guid(riid)); 2624 *obj = NULL; 2625 return E_NOINTERFACE; 2626 } 2627 2628 static ULONG WINAPI MimeSecurity_AddRef( 2629 IMimeSecurity* iface) 2630 { 2631 MimeSecurity *This = (MimeSecurity *)iface; 2632 TRACE("(%p)->()\n", iface); 2633 return InterlockedIncrement(&This->refs); 2634 } 2635 2636 static ULONG WINAPI MimeSecurity_Release( 2637 IMimeSecurity* iface) 2638 { 2639 MimeSecurity *This = (MimeSecurity *)iface; 2640 ULONG refs; 2641 2642 TRACE("(%p)->()\n", iface); 2643 2644 refs = InterlockedDecrement(&This->refs); 2645 if (!refs) 2646 { 2647 HeapFree(GetProcessHeap(), 0, This); 2648 } 2649 2650 return refs; 2651 } 2652 2653 static HRESULT WINAPI MimeSecurity_InitNew( 2654 IMimeSecurity* iface) 2655 { 2656 FIXME("(%p)->(): stub\n", iface); 2657 return S_OK; 2658 } 2659 2660 static HRESULT WINAPI MimeSecurity_CheckInit( 2661 IMimeSecurity* iface) 2662 { 2663 FIXME("(%p)->(): stub\n", iface); 2664 return E_NOTIMPL; 2665 } 2666 2667 static HRESULT WINAPI MimeSecurity_EncodeMessage( 2668 IMimeSecurity* iface, 2669 IMimeMessageTree* pTree, 2670 DWORD dwFlags) 2671 { 2672 FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags); 2673 return E_NOTIMPL; 2674 } 2675 2676 static HRESULT WINAPI MimeSecurity_EncodeBody( 2677 IMimeSecurity* iface, 2678 IMimeMessageTree* pTree, 2679 HBODY hEncodeRoot, 2680 DWORD dwFlags) 2681 { 2682 FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hEncodeRoot, dwFlags); 2683 return E_NOTIMPL; 2684 } 2685 2686 static HRESULT WINAPI MimeSecurity_DecodeMessage( 2687 IMimeSecurity* iface, 2688 IMimeMessageTree* pTree, 2689 DWORD dwFlags) 2690 { 2691 FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags); 2692 return E_NOTIMPL; 2693 } 2694 2695 static HRESULT WINAPI MimeSecurity_DecodeBody( 2696 IMimeSecurity* iface, 2697 IMimeMessageTree* pTree, 2698 HBODY hDecodeRoot, 2699 DWORD dwFlags) 2700 { 2701 FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hDecodeRoot, dwFlags); 2702 return E_NOTIMPL; 2703 } 2704 2705 static HRESULT WINAPI MimeSecurity_EnumCertificates( 2706 IMimeSecurity* iface, 2707 HCAPICERTSTORE hc, 2708 DWORD dwUsage, 2709 PCX509CERT pPrev, 2710 PCX509CERT* ppCert) 2711 { 2712 FIXME("(%p)->(%p, %08x, %p, %p): stub\n", iface, hc, dwUsage, pPrev, ppCert); 2713 return E_NOTIMPL; 2714 } 2715 2716 static HRESULT WINAPI MimeSecurity_GetCertificateName( 2717 IMimeSecurity* iface, 2718 const PCX509CERT pX509Cert, 2719 const CERTNAMETYPE cn, 2720 LPSTR* ppszName) 2721 { 2722 FIXME("(%p)->(%p, %08x, %p): stub\n", iface, pX509Cert, cn, ppszName); 2723 return E_NOTIMPL; 2724 } 2725 2726 static HRESULT WINAPI MimeSecurity_GetMessageType( 2727 IMimeSecurity* iface, 2728 const HWND hwndParent, 2729 IMimeBody* pBody, 2730 DWORD* pdwSecType) 2731 { 2732 FIXME("(%p)->(%p, %p, %p): stub\n", iface, hwndParent, pBody, pdwSecType); 2733 return E_NOTIMPL; 2734 } 2735 2736 static HRESULT WINAPI MimeSecurity_GetCertData( 2737 IMimeSecurity* iface, 2738 const PCX509CERT pX509Cert, 2739 const CERTDATAID dataid, 2740 LPPROPVARIANT pValue) 2741 { 2742 FIXME("(%p)->(%p, %x, %p): stub\n", iface, pX509Cert, dataid, pValue); 2743 return E_NOTIMPL; 2744 } 2745 2746 2747 static const IMimeSecurityVtbl MimeSecurityVtbl = 2748 { 2749 MimeSecurity_QueryInterface, 2750 MimeSecurity_AddRef, 2751 MimeSecurity_Release, 2752 MimeSecurity_InitNew, 2753 MimeSecurity_CheckInit, 2754 MimeSecurity_EncodeMessage, 2755 MimeSecurity_EncodeBody, 2756 MimeSecurity_DecodeMessage, 2757 MimeSecurity_DecodeBody, 2758 MimeSecurity_EnumCertificates, 2759 MimeSecurity_GetCertificateName, 2760 MimeSecurity_GetMessageType, 2761 MimeSecurity_GetCertData 2762 }; 2763 2764 HRESULT MimeSecurity_create(IUnknown *outer, void **obj) 2765 { 2766 MimeSecurity *This; 2767 2768 *obj = NULL; 2769 2770 if (outer) return CLASS_E_NOAGGREGATION; 2771 2772 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 2773 if (!This) return E_OUTOFMEMORY; 2774 2775 This->lpVtbl = &MimeSecurityVtbl; 2776 This->refs = 1; 2777 2778 *obj = &This->lpVtbl; 2779 return S_OK; 2780 } 2781 2782 /*********************************************************************** 2783 * MimeOleCreateSecurity (INETCOMM.@) 2784 */ 2785 HRESULT WINAPI MimeOleCreateSecurity(IMimeSecurity **ppSecurity) 2786 { 2787 return MimeSecurity_create(NULL, (void **)ppSecurity); 2788 } 2789 2790 typedef struct 2791 { 2792 IMimeAllocatorVtbl *lpVtbl; 2793 } MimeAllocator; 2794 2795 static HRESULT WINAPI MimeAlloc_QueryInterface( 2796 IMimeAllocator* iface, 2797 REFIID riid, 2798 void **obj) 2799 { 2800 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), obj); 2801 2802 if (IsEqualIID(riid, &IID_IUnknown) || 2803 IsEqualIID(riid, &IID_IMalloc) || 2804 IsEqualIID(riid, &IID_IMimeAllocator)) 2805 { 2806 *obj = iface; 2807 IUnknown_AddRef(iface); 2808 return S_OK; 2809 } 2810 2811 FIXME("no interface for %s\n", debugstr_guid(riid)); 2812 *obj = NULL; 2813 return E_NOINTERFACE; 2814 } 2815 2816 static ULONG WINAPI MimeAlloc_AddRef( 2817 IMimeAllocator* iface) 2818 { 2819 return 2; 2820 } 2821 2822 static ULONG WINAPI MimeAlloc_Release( 2823 IMimeAllocator* iface) 2824 { 2825 return 1; 2826 } 2827 2828 static LPVOID WINAPI MimeAlloc_Alloc( 2829 IMimeAllocator* iface, 2830 ULONG cb) 2831 { 2832 return CoTaskMemAlloc(cb); 2833 } 2834 2835 static LPVOID WINAPI MimeAlloc_Realloc( 2836 IMimeAllocator* iface, 2837 LPVOID pv, 2838 ULONG cb) 2839 { 2840 return CoTaskMemRealloc(pv, cb); 2841 } 2842 2843 static void WINAPI MimeAlloc_Free( 2844 IMimeAllocator* iface, 2845 LPVOID pv) 2846 { 2847 CoTaskMemFree(pv); 2848 } 2849 2850 static ULONG WINAPI MimeAlloc_GetSize( 2851 IMimeAllocator* iface, 2852 LPVOID pv) 2853 { 2854 FIXME("stub\n"); 2855 return 0; 2856 } 2857 2858 static int WINAPI MimeAlloc_DidAlloc( 2859 IMimeAllocator* iface, 2860 LPVOID pv) 2861 { 2862 FIXME("stub\n"); 2863 return 0; 2864 } 2865 2866 static void WINAPI MimeAlloc_HeapMinimize( 2867 IMimeAllocator* iface) 2868 { 2869 FIXME("stub\n"); 2870 return; 2871 } 2872 2873 static HRESULT WINAPI MimeAlloc_FreeParamInfoArray( 2874 IMimeAllocator* iface, 2875 ULONG cParams, 2876 LPMIMEPARAMINFO prgParam, 2877 boolean fFreeArray) 2878 { 2879 ULONG i; 2880 TRACE("(%p)->(%d, %p, %d)\n", iface, cParams, prgParam, fFreeArray); 2881 2882 for(i = 0; i < cParams; i++) 2883 { 2884 IMimeAllocator_Free(iface, prgParam[i].pszName); 2885 IMimeAllocator_Free(iface, prgParam[i].pszData); 2886 } 2887 if(fFreeArray) IMimeAllocator_Free(iface, prgParam); 2888 return S_OK; 2889 } 2890 2891 static HRESULT WINAPI MimeAlloc_FreeAddressList( 2892 IMimeAllocator* iface, 2893 LPADDRESSLIST pList) 2894 { 2895 FIXME("stub\n"); 2896 return E_NOTIMPL; 2897 } 2898 2899 static HRESULT WINAPI MimeAlloc_FreeAddressProps( 2900 IMimeAllocator* iface, 2901 LPADDRESSPROPS pAddress) 2902 { 2903 FIXME("stub\n"); 2904 return E_NOTIMPL; 2905 } 2906 2907 static HRESULT WINAPI MimeAlloc_ReleaseObjects( 2908 IMimeAllocator* iface, 2909 ULONG cObjects, 2910 IUnknown **prgpUnknown, 2911 boolean fFreeArray) 2912 { 2913 FIXME("stub\n"); 2914 return E_NOTIMPL; 2915 } 2916 2917 2918 static HRESULT WINAPI MimeAlloc_FreeEnumHeaderRowArray( 2919 IMimeAllocator* iface, 2920 ULONG cRows, 2921 LPENUMHEADERROW prgRow, 2922 boolean fFreeArray) 2923 { 2924 FIXME("stub\n"); 2925 return E_NOTIMPL; 2926 } 2927 2928 static HRESULT WINAPI MimeAlloc_FreeEnumPropertyArray( 2929 IMimeAllocator* iface, 2930 ULONG cProps, 2931 LPENUMPROPERTY prgProp, 2932 boolean fFreeArray) 2933 { 2934 FIXME("stub\n"); 2935 return E_NOTIMPL; 2936 } 2937 2938 static HRESULT WINAPI MimeAlloc_FreeThumbprint( 2939 IMimeAllocator* iface, 2940 THUMBBLOB *pthumbprint) 2941 { 2942 FIXME("stub\n"); 2943 return E_NOTIMPL; 2944 } 2945 2946 2947 static HRESULT WINAPI MimeAlloc_PropVariantClear( 2948 IMimeAllocator* iface, 2949 LPPROPVARIANT pProp) 2950 { 2951 FIXME("stub\n"); 2952 return E_NOTIMPL; 2953 } 2954 2955 static IMimeAllocatorVtbl mime_alloc_vtbl = 2956 { 2957 MimeAlloc_QueryInterface, 2958 MimeAlloc_AddRef, 2959 MimeAlloc_Release, 2960 MimeAlloc_Alloc, 2961 MimeAlloc_Realloc, 2962 MimeAlloc_Free, 2963 MimeAlloc_GetSize, 2964 MimeAlloc_DidAlloc, 2965 MimeAlloc_HeapMinimize, 2966 MimeAlloc_FreeParamInfoArray, 2967 MimeAlloc_FreeAddressList, 2968 MimeAlloc_FreeAddressProps, 2969 MimeAlloc_ReleaseObjects, 2970 MimeAlloc_FreeEnumHeaderRowArray, 2971 MimeAlloc_FreeEnumPropertyArray, 2972 MimeAlloc_FreeThumbprint, 2973 MimeAlloc_PropVariantClear 2974 }; 2975 2976 static MimeAllocator mime_allocator = 2977 { 2978 &mime_alloc_vtbl 2979 }; 2980 2981 HRESULT MimeAllocator_create(IUnknown *outer, void **obj) 2982 { 2983 if(outer) return CLASS_E_NOAGGREGATION; 2984 2985 *obj = &mime_allocator; 2986 return S_OK; 2987 } 2988 2989 HRESULT WINAPI MimeOleGetAllocator(IMimeAllocator **alloc) 2990 { 2991 return MimeAllocator_create(NULL, (void**)alloc); 2992 } 2993 2994 HRESULT VirtualStream_create(IUnknown *outer, void **obj) 2995 { 2996 FIXME("(%p, %p)\n", outer, obj); 2997 2998 *obj = NULL; 2999 if (outer) return CLASS_E_NOAGGREGATION; 3000 3001 return MimeOleCreateVirtualStream((IStream **)obj); 3002 } 3003