mshtml: Added IHTMLStyleSheet::get_rules implementation.
[wine] / dlls / inetcomm / mimeole.c
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
24 #include <stdarg.h>
25 #include <stdio.h>
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "objbase.h"
31 #include "ole2.h"
32 #include "mimeole.h"
33
34 #include "wine/list.h"
35 #include "wine/debug.h"
36
37 #include "inetcomm_private.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm);
40
41 typedef struct
42 {
43     LPCSTR     name;
44     DWORD      id;
45     DWORD      flags; /* MIMEPROPFLAGS */
46     VARTYPE    default_vt;
47 } property_t;
48
49 typedef struct
50 {
51     struct list entry;
52     property_t prop;
53 } property_list_entry_t;
54
55 static const property_t default_props[] =
56 {
57     {"References",                   PID_HDR_REFS,       0,                               VT_LPSTR},
58     {"Subject",                      PID_HDR_SUBJECT,    0,                               VT_LPSTR},
59     {"From",                         PID_HDR_FROM,       MPF_ADDRESS,                     VT_LPSTR},
60     {"Message-ID",                   PID_HDR_MESSAGEID,  0,                               VT_LPSTR},
61     {"Return-Path",                  PID_HDR_RETURNPATH, MPF_ADDRESS,                     VT_LPSTR},
62     {"Date",                         PID_HDR_DATE,       0,                               VT_LPSTR},
63     {"Received",                     PID_HDR_RECEIVED,   0,                               VT_LPSTR},
64     {"Reply-To",                     PID_HDR_REPLYTO,    MPF_ADDRESS,                     VT_LPSTR},
65     {"X-Mailer",                     PID_HDR_XMAILER,    0,                               VT_LPSTR},
66     {"Bcc",                          PID_HDR_BCC,        MPF_ADDRESS,                     VT_LPSTR},
67     {"MIME-Version",                 PID_HDR_MIMEVER,    MPF_MIME,                        VT_LPSTR},
68     {"Content-Type",                 PID_HDR_CNTTYPE,    MPF_MIME | MPF_HASPARAMS,        VT_LPSTR},
69     {"Content-Transfer-Encoding",    PID_HDR_CNTXFER,    MPF_MIME,                        VT_LPSTR},
70     {"Content-ID",                   PID_HDR_CNTID,      MPF_MIME,                        VT_LPSTR},
71     {"Content-Disposition",          PID_HDR_CNTDISP,    MPF_MIME,                        VT_LPSTR},
72     {"To",                           PID_HDR_TO,         MPF_ADDRESS,                     VT_LPSTR},
73     {"Cc",                           PID_HDR_CC,         MPF_ADDRESS,                     VT_LPSTR},
74     {"Sender",                       PID_HDR_SENDER,     MPF_ADDRESS,                     VT_LPSTR},
75     {"In-Reply-To",                  PID_HDR_INREPLYTO,  0,                               VT_LPSTR},
76     {NULL,                           0,                  0,                               0}
77 };
78
79 typedef struct
80 {
81     struct list entry;
82     char *name;
83     char *value;
84 } param_t;
85
86 typedef struct
87 {
88     struct list entry;
89     const property_t *prop;
90     PROPVARIANT value;
91     struct list params;
92 } header_t;
93
94 typedef struct MimeBody
95 {
96     const IMimeBodyVtbl *lpVtbl;
97     LONG refs;
98
99     HBODY handle;
100
101     struct list headers;
102     struct list new_props; /* FIXME: This should be in a PropertySchema */
103     DWORD next_prop_id;
104     char *content_pri_type;
105     char *content_sub_type;
106     ENCODINGTYPE encoding;
107     void *data;
108     IID data_iid;
109 } MimeBody;
110
111 static inline MimeBody *impl_from_IMimeBody( IMimeBody *iface )
112 {
113     return (MimeBody *)((char*)iface - FIELD_OFFSET(MimeBody, lpVtbl));
114 }
115
116 static LPSTR strdupA(LPCSTR str)
117 {
118     char *ret;
119     int len = strlen(str);
120     ret = HeapAlloc(GetProcessHeap(), 0, len + 1);
121     memcpy(ret, str, len + 1);
122     return ret;
123 }
124
125 #define PARSER_BUF_SIZE 1024
126
127 /*****************************************************
128  *        copy_headers_to_buf [internal]
129  *
130  * Copies the headers into a '\0' terminated memory block and leave
131  * the stream's current position set to after the blank line.
132  */
133 static HRESULT copy_headers_to_buf(IStream *stm, char **ptr)
134 {
135     char *buf = NULL;
136     DWORD size = PARSER_BUF_SIZE, offset = 0, last_end = 0;
137     HRESULT hr;
138     int done = 0;
139
140     *ptr = NULL;
141
142     do
143     {
144         char *end;
145         DWORD read;
146
147         if(!buf)
148             buf = HeapAlloc(GetProcessHeap(), 0, size + 1);
149         else
150         {
151             size *= 2;
152             buf = HeapReAlloc(GetProcessHeap(), 0, buf, size + 1);
153         }
154         if(!buf)
155         {
156             hr = E_OUTOFMEMORY;
157             goto fail;
158         }
159
160         hr = IStream_Read(stm, buf + offset, size - offset, &read);
161         if(FAILED(hr)) goto fail;
162
163         offset += read;
164         buf[offset] = '\0';
165
166         if(read == 0) done = 1;
167
168         while(!done && (end = strstr(buf + last_end, "\r\n")))
169         {
170             DWORD new_end = end - buf + 2;
171             if(new_end - last_end == 2)
172             {
173                 LARGE_INTEGER off;
174                 off.QuadPart = new_end;
175                 IStream_Seek(stm, off, STREAM_SEEK_SET, NULL);
176                 buf[new_end] = '\0';
177                 done = 1;
178             }
179             else
180                 last_end = new_end;
181         }
182     } while(!done);
183
184     *ptr = buf;
185     return S_OK;
186
187 fail:
188     HeapFree(GetProcessHeap(), 0, buf);
189     return hr;
190 }
191
192 static header_t *read_prop(MimeBody *body, char **ptr)
193 {
194     char *colon = strchr(*ptr, ':');
195     const property_t *prop;
196     header_t *ret;
197
198     if(!colon) return NULL;
199
200     *colon = '\0';
201
202     for(prop = default_props; prop->name; prop++)
203     {
204         if(!strcasecmp(*ptr, prop->name))
205         {
206             TRACE("%s: found match with default property id %d\n", *ptr, prop->id);
207             break;
208         }
209     }
210
211     if(!prop->name)
212     {
213         property_list_entry_t *prop_entry;
214         LIST_FOR_EACH_ENTRY(prop_entry, &body->new_props, property_list_entry_t, entry)
215         {
216             if(!strcasecmp(*ptr, prop_entry->prop.name))
217             {
218                 TRACE("%s: found match with already added new property id %d\n", *ptr, prop_entry->prop.id);
219                 prop = &prop_entry->prop;
220                 break;
221             }
222         }
223         if(!prop->name)
224         {
225             prop_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry));
226             prop_entry->prop.name = strdupA(*ptr);
227             prop_entry->prop.id = body->next_prop_id++;
228             prop_entry->prop.flags = 0;
229             prop_entry->prop.default_vt = VT_LPSTR;
230             list_add_tail(&body->new_props, &prop_entry->entry);
231             prop = &prop_entry->prop;
232             TRACE("%s: allocating new prop id %d\n", *ptr, prop_entry->prop.id);
233         }
234     }
235
236     ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret));
237     ret->prop = prop;
238     PropVariantInit(&ret->value);
239     list_init(&ret->params);
240     *ptr = colon + 1;
241
242     return ret;
243 }
244
245 static void unfold_header(char *header, int len)
246 {
247     char *start = header, *cp = header;
248
249     do {
250         while(*cp == ' ' || *cp == '\t')
251         {
252             cp++;
253             len--;
254         }
255         if(cp != start)
256             memmove(start, cp, len + 1);
257
258         cp = strstr(start, "\r\n");
259         len -= (cp - start);
260         start = cp;
261         *start = ' ';
262         start++;
263         len--;
264         cp += 2;
265     } while(*cp == ' ' || *cp == '\t');
266
267     *(start - 1) = '\0';
268 }
269
270 static void add_param(header_t *header, const char *p)
271 {
272     const char *key = p, *value, *cp = p;
273     param_t *param;
274     char *name;
275
276     TRACE("got param %s\n", p);
277
278     while (*key == ' ' || *key == '\t' ) key++;
279
280     cp = strchr(key, '=');
281     if(!cp)
282     {
283         WARN("malformed parameter - skipping\n");
284         return;
285     }
286
287     name = HeapAlloc(GetProcessHeap(), 0, cp - key + 1);
288     memcpy(name, key, cp - key);
289     name[cp - key] = '\0';
290
291     value = cp + 1;
292
293     param = HeapAlloc(GetProcessHeap(), 0, sizeof(*param));
294     param->name = name;
295     param->value = strdupA(value);
296     list_add_tail(&header->params, &param->entry);
297 }
298
299 static void split_params(header_t *header, char *value)
300 {
301     char *cp = value, *start = value;
302     int in_quote = 0;
303     int done_value = 0;
304
305     while(*cp)
306     {
307         if(!in_quote && *cp == ';')
308         {
309             *cp = '\0';
310             if(done_value) add_param(header, start);
311             done_value = 1;
312             start = cp + 1;
313         }
314         else if(*cp == '"')
315             in_quote = !in_quote;
316         cp++;
317     }
318     if(done_value) add_param(header, start);
319 }
320
321 static void read_value(header_t *header, char **cur)
322 {
323     char *end = *cur, *value;
324     DWORD len;
325
326     do {
327         end = strstr(end, "\r\n");
328         end += 2;
329     } while(*end == ' ' || *end == '\t');
330
331     len = end - *cur;
332     value = HeapAlloc(GetProcessHeap(), 0, len + 1);
333     memcpy(value, *cur, len);
334     value[len] = '\0';
335
336     unfold_header(value, len);
337     TRACE("value %s\n", debugstr_a(value));
338
339     if(header->prop->flags & MPF_HASPARAMS)
340     {
341         split_params(header, value);
342         TRACE("value w/o params %s\n", debugstr_a(value));
343     }
344
345     header->value.vt = VT_LPSTR;
346     header->value.pszVal = value;
347
348     *cur = end;
349 }
350
351 static void init_content_type(MimeBody *body, header_t *header)
352 {
353     char *slash;
354     DWORD len;
355
356     if(header->prop->id != PID_HDR_CNTTYPE)
357     {
358         ERR("called with header %s\n", header->prop->name);
359         return;
360     }
361
362     slash = strchr(header->value.pszVal, '/');
363     if(!slash)
364     {
365         WARN("malformed context type value\n");
366         return;
367     }
368     len = slash - header->value.pszVal;
369     body->content_pri_type = HeapAlloc(GetProcessHeap(), 0, len + 1);
370     memcpy(body->content_pri_type, header->value.pszVal, len);
371     body->content_pri_type[len] = '\0';
372     body->content_sub_type = strdupA(slash + 1);
373 }
374
375 static HRESULT parse_headers(MimeBody *body, IStream *stm)
376 {
377     char *header_buf, *cur_header_ptr;
378     HRESULT hr;
379     header_t *header;
380
381     hr = copy_headers_to_buf(stm, &header_buf);
382     if(FAILED(hr)) return hr;
383
384     cur_header_ptr = header_buf;
385     while((header = read_prop(body, &cur_header_ptr)))
386     {
387         read_value(header, &cur_header_ptr);
388         list_add_tail(&body->headers, &header->entry);
389
390         if(header->prop->id == PID_HDR_CNTTYPE)
391             init_content_type(body, header);
392     }
393
394     HeapFree(GetProcessHeap(), 0, header_buf);
395     return hr;
396 }
397
398 static void emptry_param_list(struct list *list)
399 {
400     param_t *param, *cursor2;
401
402     LIST_FOR_EACH_ENTRY_SAFE(param, cursor2, list, param_t, entry)
403     {
404         list_remove(&param->entry);
405         HeapFree(GetProcessHeap(), 0, param->name);
406         HeapFree(GetProcessHeap(), 0, param->value);
407         HeapFree(GetProcessHeap(), 0, param);
408     }
409 }
410
411 static void empty_header_list(struct list *list)
412 {
413     header_t *header, *cursor2;
414
415     LIST_FOR_EACH_ENTRY_SAFE(header, cursor2, list, header_t, entry)
416     {
417         list_remove(&header->entry);
418         PropVariantClear(&header->value);
419         emptry_param_list(&header->params);
420         HeapFree(GetProcessHeap(), 0, header);
421     }
422 }
423
424 static void empty_new_prop_list(struct list *list)
425 {
426     property_list_entry_t *prop, *cursor2;
427
428     LIST_FOR_EACH_ENTRY_SAFE(prop, cursor2, list, property_list_entry_t, entry)
429     {
430         list_remove(&prop->entry);
431         HeapFree(GetProcessHeap(), 0, (char *)prop->prop.name);
432         HeapFree(GetProcessHeap(), 0, prop);
433     }
434 }
435
436 static void release_data(REFIID riid, void *data)
437 {
438     if(!data) return;
439
440     if(IsEqualIID(riid, &IID_IStream))
441         IStream_Release((IStream *)data);
442     else
443         FIXME("Unhandled data format %s\n", debugstr_guid(riid));
444 }
445
446 static HRESULT WINAPI MimeBody_QueryInterface(IMimeBody* iface,
447                                      REFIID riid,
448                                      void** ppvObject)
449 {
450     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppvObject);
451
452     *ppvObject = NULL;
453
454     if (IsEqualIID(riid, &IID_IUnknown) ||
455         IsEqualIID(riid, &IID_IPersist) ||
456         IsEqualIID(riid, &IID_IPersistStreamInit) ||
457         IsEqualIID(riid, &IID_IMimePropertySet) ||
458         IsEqualIID(riid, &IID_IMimeBody))
459     {
460         *ppvObject = iface;
461     }
462
463     if(*ppvObject)
464     {
465         IUnknown_AddRef((IUnknown*)*ppvObject);
466         return S_OK;
467     }
468
469     FIXME("no interface for %s\n", debugstr_guid(riid));
470     return E_NOINTERFACE;
471 }
472
473 static ULONG WINAPI MimeBody_AddRef(IMimeBody* iface)
474 {
475     MimeBody *This = impl_from_IMimeBody(iface);
476     TRACE("(%p)->()\n", iface);
477     return InterlockedIncrement(&This->refs);
478 }
479
480 static ULONG WINAPI MimeBody_Release(IMimeBody* iface)
481 {
482     MimeBody *This = impl_from_IMimeBody(iface);
483     ULONG refs;
484
485     TRACE("(%p)->()\n", iface);
486
487     refs = InterlockedDecrement(&This->refs);
488     if (!refs)
489     {
490         empty_header_list(&This->headers);
491         empty_new_prop_list(&This->new_props);
492
493         HeapFree(GetProcessHeap(), 0, This->content_pri_type);
494         HeapFree(GetProcessHeap(), 0, This->content_sub_type);
495
496         release_data(&This->data_iid, This->data);
497
498         HeapFree(GetProcessHeap(), 0, This);
499     }
500
501     return refs;
502 }
503
504 static HRESULT WINAPI MimeBody_GetClassID(
505                                  IMimeBody* iface,
506                                  CLSID* pClassID)
507 {
508     FIXME("stub\n");
509     return E_NOTIMPL;
510 }
511
512
513 static HRESULT WINAPI MimeBody_IsDirty(
514                               IMimeBody* iface)
515 {
516     FIXME("stub\n");
517     return E_NOTIMPL;
518 }
519
520 static HRESULT WINAPI MimeBody_Load(
521                            IMimeBody* iface,
522                            LPSTREAM pStm)
523 {
524     MimeBody *This = impl_from_IMimeBody(iface);
525     TRACE("(%p)->(%p)\n", iface, pStm);
526     return parse_headers(This, pStm);
527 }
528
529 static HRESULT WINAPI MimeBody_Save(
530                            IMimeBody* iface,
531                            LPSTREAM pStm,
532                            BOOL fClearDirty)
533 {
534     FIXME("stub\n");
535     return E_NOTIMPL;
536 }
537
538 static HRESULT WINAPI MimeBody_GetSizeMax(
539                                  IMimeBody* iface,
540                                  ULARGE_INTEGER* pcbSize)
541 {
542     FIXME("stub\n");
543     return E_NOTIMPL;
544 }
545
546 static HRESULT WINAPI MimeBody_InitNew(
547                               IMimeBody* iface)
548 {
549     TRACE("%p->()\n", iface);
550     return S_OK;
551 }
552
553 static HRESULT WINAPI MimeBody_GetPropInfo(
554                                   IMimeBody* iface,
555                                   LPCSTR pszName,
556                                   LPMIMEPROPINFO pInfo)
557 {
558     FIXME("stub\n");
559     return E_NOTIMPL;
560 }
561
562 static HRESULT WINAPI MimeBody_SetPropInfo(
563                                   IMimeBody* iface,
564                                   LPCSTR pszName,
565                                   LPCMIMEPROPINFO pInfo)
566 {
567     FIXME("stub\n");
568     return E_NOTIMPL;
569 }
570
571 static HRESULT WINAPI MimeBody_GetProp(
572                               IMimeBody* iface,
573                               LPCSTR pszName,
574                               DWORD dwFlags,
575                               LPPROPVARIANT pValue)
576 {
577     FIXME("stub\n");
578     return E_NOTIMPL;
579 }
580
581 static HRESULT WINAPI MimeBody_SetProp(
582                               IMimeBody* iface,
583                               LPCSTR pszName,
584                               DWORD dwFlags,
585                               LPCPROPVARIANT pValue)
586 {
587     FIXME("stub\n");
588     return E_NOTIMPL;
589 }
590
591 static HRESULT WINAPI MimeBody_AppendProp(
592                                  IMimeBody* iface,
593                                  LPCSTR pszName,
594                                  DWORD dwFlags,
595                                  LPPROPVARIANT pValue)
596 {
597     FIXME("stub\n");
598     return E_NOTIMPL;
599 }
600
601 static HRESULT WINAPI MimeBody_DeleteProp(
602                                  IMimeBody* iface,
603                                  LPCSTR pszName)
604 {
605     FIXME("stub\n");
606     return E_NOTIMPL;
607 }
608
609 static HRESULT WINAPI MimeBody_CopyProps(
610                                 IMimeBody* iface,
611                                 ULONG cNames,
612                                 LPCSTR* prgszName,
613                                 IMimePropertySet* pPropertySet)
614 {
615     FIXME("stub\n");
616     return E_NOTIMPL;
617 }
618
619 static HRESULT WINAPI MimeBody_MoveProps(
620                                 IMimeBody* iface,
621                                 ULONG cNames,
622                                 LPCSTR* prgszName,
623                                 IMimePropertySet* pPropertySet)
624 {
625     FIXME("stub\n");
626     return E_NOTIMPL;
627 }
628
629 static HRESULT WINAPI MimeBody_DeleteExcept(
630                                    IMimeBody* iface,
631                                    ULONG cNames,
632                                    LPCSTR* prgszName)
633 {
634     FIXME("stub\n");
635     return E_NOTIMPL;
636 }
637
638 static HRESULT WINAPI MimeBody_QueryProp(
639                                 IMimeBody* iface,
640                                 LPCSTR pszName,
641                                 LPCSTR pszCriteria,
642                                 boolean fSubString,
643                                 boolean fCaseSensitive)
644 {
645     FIXME("stub\n");
646     return E_NOTIMPL;
647 }
648
649 static HRESULT WINAPI MimeBody_GetCharset(
650                                  IMimeBody* iface,
651                                  LPHCHARSET phCharset)
652 {
653     FIXME("stub\n");
654     return E_NOTIMPL;
655 }
656
657 static HRESULT WINAPI MimeBody_SetCharset(
658                                  IMimeBody* iface,
659                                  HCHARSET hCharset,
660                                  CSETAPPLYTYPE applytype)
661 {
662     FIXME("stub\n");
663     return E_NOTIMPL;
664 }
665
666 static HRESULT WINAPI MimeBody_GetParameters(
667                                     IMimeBody* iface,
668                                     LPCSTR pszName,
669                                     ULONG* pcParams,
670                                     LPMIMEPARAMINFO* pprgParam)
671 {
672     FIXME("stub\n");
673     return E_NOTIMPL;
674 }
675
676 static HRESULT WINAPI MimeBody_IsContentType(
677                                     IMimeBody* iface,
678                                     LPCSTR pszPriType,
679                                     LPCSTR pszSubType)
680 {
681     MimeBody *This = impl_from_IMimeBody(iface);
682
683     TRACE("(%p)->(%s, %s)\n", This, debugstr_a(pszPriType), debugstr_a(pszSubType));
684     if(pszPriType)
685     {
686         const char *pri = This->content_pri_type;
687         if(!pri) pri = "text";
688         if(strcasecmp(pri, pszPriType)) return S_FALSE;
689     }
690
691     if(pszSubType)
692     {
693         const char *sub = This->content_sub_type;
694         if(!sub) sub = "plain";
695         if(strcasecmp(sub, pszSubType)) return S_FALSE;
696     }
697
698     return S_OK;
699 }
700
701 static HRESULT WINAPI MimeBody_BindToObject(
702                                    IMimeBody* iface,
703                                    REFIID riid,
704                                    void** ppvObject)
705 {
706     FIXME("stub\n");
707     return E_NOTIMPL;
708 }
709
710 static HRESULT WINAPI MimeBody_Clone(
711                             IMimeBody* iface,
712                             IMimePropertySet** ppPropertySet)
713 {
714     FIXME("stub\n");
715     return E_NOTIMPL;
716 }
717
718 static HRESULT WINAPI MimeBody_SetOption(
719                                 IMimeBody* iface,
720                                 const TYPEDID oid,
721                                 LPCPROPVARIANT pValue)
722 {
723     FIXME("stub\n");
724     return E_NOTIMPL;
725 }
726
727 static HRESULT WINAPI MimeBody_GetOption(
728                                 IMimeBody* iface,
729                                 const TYPEDID oid,
730                                 LPPROPVARIANT pValue)
731 {
732     FIXME("stub\n");
733     return E_NOTIMPL;
734 }
735
736 static HRESULT WINAPI MimeBody_EnumProps(
737                                 IMimeBody* iface,
738                                 DWORD dwFlags,
739                                 IMimeEnumProperties** ppEnum)
740 {
741     FIXME("stub\n");
742     return E_NOTIMPL;
743 }
744
745 static HRESULT WINAPI MimeBody_IsType(
746                              IMimeBody* iface,
747                              IMSGBODYTYPE bodytype)
748 {
749     FIXME("stub\n");
750     return E_NOTIMPL;
751 }
752
753 static HRESULT WINAPI MimeBody_SetDisplayName(
754                                      IMimeBody* iface,
755                                      LPCSTR pszDisplay)
756 {
757     FIXME("stub\n");
758     return E_NOTIMPL;
759 }
760
761 static HRESULT WINAPI MimeBody_GetDisplayName(
762                                      IMimeBody* iface,
763                                      LPSTR* ppszDisplay)
764 {
765     FIXME("stub\n");
766     return E_NOTIMPL;
767 }
768
769 static HRESULT WINAPI MimeBody_GetOffsets(
770                                  IMimeBody* iface,
771                                  LPBODYOFFSETS pOffsets)
772 {
773     FIXME("stub\n");
774     return E_NOTIMPL;
775 }
776
777 static HRESULT WINAPI MimeBody_GetCurrentEncoding(
778                                          IMimeBody* iface,
779                                          ENCODINGTYPE* pietEncoding)
780 {
781     MimeBody *This = impl_from_IMimeBody(iface);
782
783     TRACE("(%p)->(%p)\n", This, pietEncoding);
784
785     *pietEncoding = This->encoding;
786     return S_OK;
787 }
788
789 static HRESULT WINAPI MimeBody_SetCurrentEncoding(
790                                          IMimeBody* iface,
791                                          ENCODINGTYPE ietEncoding)
792 {
793     MimeBody *This = impl_from_IMimeBody(iface);
794
795     TRACE("(%p)->(%d)\n", This, ietEncoding);
796
797     This->encoding = ietEncoding;
798     return S_OK;
799 }
800
801 static HRESULT WINAPI MimeBody_GetEstimatedSize(
802                                        IMimeBody* iface,
803                                        ENCODINGTYPE ietEncoding,
804                                        ULONG* pcbSize)
805 {
806     FIXME("stub\n");
807     return E_NOTIMPL;
808 }
809
810 static HRESULT WINAPI MimeBody_GetDataHere(
811                                   IMimeBody* iface,
812                                   ENCODINGTYPE ietEncoding,
813                                   IStream* pStream)
814 {
815     FIXME("stub\n");
816     return E_NOTIMPL;
817 }
818
819 static HRESULT WINAPI MimeBody_GetData(
820                               IMimeBody* iface,
821                               ENCODINGTYPE ietEncoding,
822                               IStream** ppStream)
823 {
824     FIXME("stub\n");
825     return E_NOTIMPL;
826 }
827
828 static HRESULT WINAPI MimeBody_SetData(
829                               IMimeBody* iface,
830                               ENCODINGTYPE ietEncoding,
831                               LPCSTR pszPriType,
832                               LPCSTR pszSubType,
833                               REFIID riid,
834                               LPVOID pvObject)
835 {
836     MimeBody *This = impl_from_IMimeBody(iface);
837     TRACE("(%p)->(%d, %s, %s, %s %p)\n", This, ietEncoding, debugstr_a(pszPriType), debugstr_a(pszSubType),
838           debugstr_guid(riid), pvObject);
839
840     if(IsEqualIID(riid, &IID_IStream))
841         IStream_AddRef((IStream *)pvObject);
842     else
843     {
844         FIXME("Unhandled object type %s\n", debugstr_guid(riid));
845         return E_INVALIDARG;
846     }
847
848     if(This->data)
849         FIXME("release old data\n");
850
851     This->data_iid = *riid;
852     This->data = pvObject;
853
854     IMimeBody_SetCurrentEncoding(iface, ietEncoding);
855
856     /* FIXME: Update the content type.
857        If pszPriType == NULL use 'application'
858        If pszSubType == NULL use 'octet-stream' */
859
860     return S_OK;
861 }
862
863 static HRESULT WINAPI MimeBody_EmptyData(
864                                 IMimeBody* iface)
865 {
866     FIXME("stub\n");
867     return E_NOTIMPL;
868 }
869
870 static HRESULT WINAPI MimeBody_CopyTo(
871                              IMimeBody* iface,
872                              IMimeBody* pBody)
873 {
874     FIXME("stub\n");
875     return E_NOTIMPL;
876 }
877
878 static HRESULT WINAPI MimeBody_GetTransmitInfo(
879                                       IMimeBody* iface,
880                                       LPTRANSMITINFO pTransmitInfo)
881 {
882     FIXME("stub\n");
883     return E_NOTIMPL;
884 }
885
886 static HRESULT WINAPI MimeBody_SaveToFile(
887                                  IMimeBody* iface,
888                                  ENCODINGTYPE ietEncoding,
889                                  LPCSTR pszFilePath)
890 {
891     FIXME("stub\n");
892     return E_NOTIMPL;
893 }
894
895 static HRESULT WINAPI MimeBody_GetHandle(
896                                 IMimeBody* iface,
897                                 LPHBODY phBody)
898 {
899     MimeBody *This = impl_from_IMimeBody(iface);
900     TRACE("(%p)->(%p)\n", iface, phBody);
901
902     *phBody = This->handle;
903     return This->handle ? S_OK : MIME_E_NO_DATA;
904 }
905
906 static IMimeBodyVtbl body_vtbl =
907 {
908     MimeBody_QueryInterface,
909     MimeBody_AddRef,
910     MimeBody_Release,
911     MimeBody_GetClassID,
912     MimeBody_IsDirty,
913     MimeBody_Load,
914     MimeBody_Save,
915     MimeBody_GetSizeMax,
916     MimeBody_InitNew,
917     MimeBody_GetPropInfo,
918     MimeBody_SetPropInfo,
919     MimeBody_GetProp,
920     MimeBody_SetProp,
921     MimeBody_AppendProp,
922     MimeBody_DeleteProp,
923     MimeBody_CopyProps,
924     MimeBody_MoveProps,
925     MimeBody_DeleteExcept,
926     MimeBody_QueryProp,
927     MimeBody_GetCharset,
928     MimeBody_SetCharset,
929     MimeBody_GetParameters,
930     MimeBody_IsContentType,
931     MimeBody_BindToObject,
932     MimeBody_Clone,
933     MimeBody_SetOption,
934     MimeBody_GetOption,
935     MimeBody_EnumProps,
936     MimeBody_IsType,
937     MimeBody_SetDisplayName,
938     MimeBody_GetDisplayName,
939     MimeBody_GetOffsets,
940     MimeBody_GetCurrentEncoding,
941     MimeBody_SetCurrentEncoding,
942     MimeBody_GetEstimatedSize,
943     MimeBody_GetDataHere,
944     MimeBody_GetData,
945     MimeBody_SetData,
946     MimeBody_EmptyData,
947     MimeBody_CopyTo,
948     MimeBody_GetTransmitInfo,
949     MimeBody_SaveToFile,
950     MimeBody_GetHandle
951 };
952
953 #define FIRST_CUSTOM_PROP_ID 0x100
954
955 HRESULT MimeBody_create(IUnknown *outer, void **obj)
956 {
957     MimeBody *This;
958
959     *obj = NULL;
960
961     if(outer) return CLASS_E_NOAGGREGATION;
962
963     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
964     if (!This) return E_OUTOFMEMORY;
965
966     This->lpVtbl = &body_vtbl;
967     This->refs = 1;
968     This->handle = NULL;
969     list_init(&This->headers);
970     list_init(&This->new_props);
971     This->next_prop_id = FIRST_CUSTOM_PROP_ID;
972     This->content_pri_type = NULL;
973     This->content_sub_type = NULL;
974     This->encoding = IET_7BIT;
975     This->data = NULL;
976     This->data_iid = IID_NULL;
977
978     *obj = (IMimeBody *)&This->lpVtbl;
979     return S_OK;
980 }
981
982 typedef struct MimeMessage
983 {
984     const IMimeMessageVtbl *lpVtbl;
985
986     LONG refs;
987 } MimeMessage;
988
989 static HRESULT WINAPI MimeMessage_QueryInterface(IMimeMessage *iface, REFIID riid, void **ppv)
990 {
991     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
992
993     if (IsEqualIID(riid, &IID_IUnknown) ||
994         IsEqualIID(riid, &IID_IPersist) ||
995         IsEqualIID(riid, &IID_IPersistStreamInit) ||
996         IsEqualIID(riid, &IID_IMimeMessageTree) ||
997         IsEqualIID(riid, &IID_IMimeMessage))
998     {
999         *ppv = iface;
1000         IUnknown_AddRef(iface);
1001         return S_OK;
1002     }
1003
1004     FIXME("no interface for %s\n", debugstr_guid(riid));
1005     *ppv = NULL;
1006     return E_NOINTERFACE;
1007 }
1008
1009 static ULONG WINAPI MimeMessage_AddRef(IMimeMessage *iface)
1010 {
1011     MimeMessage *This = (MimeMessage *)iface;
1012     TRACE("(%p)->()\n", iface);
1013     return InterlockedIncrement(&This->refs);
1014 }
1015
1016 static ULONG WINAPI MimeMessage_Release(IMimeMessage *iface)
1017 {
1018     MimeMessage *This = (MimeMessage *)iface;
1019     ULONG refs;
1020
1021     TRACE("(%p)->()\n", iface);
1022
1023     refs = InterlockedDecrement(&This->refs);
1024     if (!refs)
1025     {
1026         HeapFree(GetProcessHeap(), 0, This);
1027     }
1028
1029     return refs;
1030 }
1031
1032 /*** IPersist methods ***/
1033 static HRESULT WINAPI MimeMessage_GetClassID(
1034     IMimeMessage *iface,
1035     CLSID *pClassID)
1036 {
1037     FIXME("(%p)->(%p)\n", iface, pClassID);
1038     return E_NOTIMPL;
1039 }
1040
1041 /*** IPersistStreamInit methods ***/
1042 static HRESULT WINAPI MimeMessage_IsDirty(
1043     IMimeMessage *iface)
1044 {
1045     FIXME("(%p)->()\n", iface);
1046     return E_NOTIMPL;
1047 }
1048
1049 static HRESULT WINAPI MimeMessage_Load(
1050     IMimeMessage *iface,
1051     LPSTREAM pStm){
1052     FIXME("(%p)->(%p)\n", iface, pStm);
1053     return E_NOTIMPL;
1054 }
1055
1056 static HRESULT WINAPI MimeMessage_Save(
1057     IMimeMessage *iface,
1058     LPSTREAM pStm,
1059     BOOL fClearDirty)
1060 {
1061     FIXME("(%p)->(%p, %s)\n", iface, pStm, fClearDirty ? "TRUE" : "FALSE");
1062     return E_NOTIMPL;
1063 }
1064
1065 static HRESULT WINAPI MimeMessage_GetSizeMax(
1066     IMimeMessage *iface,
1067     ULARGE_INTEGER *pcbSize)
1068 {
1069     FIXME("(%p)->(%p)\n", iface, pcbSize);
1070     return E_NOTIMPL;
1071 }
1072
1073 static HRESULT WINAPI MimeMessage_InitNew(
1074     IMimeMessage *iface)
1075 {
1076     FIXME("(%p)->()\n", iface);
1077     return E_NOTIMPL;
1078 }
1079
1080 /*** IMimeMessageTree methods ***/
1081 static HRESULT WINAPI MimeMessage_GetMessageSource(
1082     IMimeMessage *iface,
1083     IStream **ppStream,
1084     DWORD dwFlags)
1085 {
1086     FIXME("(%p)->(%p, 0x%x)\n", iface, ppStream, dwFlags);
1087     return E_NOTIMPL;
1088 }
1089
1090 static HRESULT WINAPI MimeMessage_GetMessageSize(
1091     IMimeMessage *iface,
1092     ULONG *pcbSize,
1093     DWORD dwFlags)
1094 {
1095     FIXME("(%p)->(%p, 0x%x)\n", iface, pcbSize, dwFlags);
1096     return E_NOTIMPL;
1097 }
1098
1099 static HRESULT WINAPI MimeMessage_LoadOffsetTable(
1100     IMimeMessage *iface,
1101     IStream *pStream)
1102 {
1103     FIXME("(%p)->(%p)\n", iface, pStream);
1104     return E_NOTIMPL;
1105 }
1106
1107 static HRESULT WINAPI MimeMessage_SaveOffsetTable(
1108     IMimeMessage *iface,
1109     IStream *pStream,
1110     DWORD dwFlags)
1111 {
1112     FIXME("(%p)->(%p, 0x%x)\n", iface, pStream, dwFlags);
1113     return E_NOTIMPL;
1114 }
1115
1116
1117 static HRESULT WINAPI MimeMessage_GetFlags(
1118     IMimeMessage *iface,
1119     DWORD *pdwFlags)
1120 {
1121     FIXME("(%p)->(%p)\n", iface, pdwFlags);
1122     return E_NOTIMPL;
1123 }
1124
1125 static HRESULT WINAPI MimeMessage_Commit(
1126     IMimeMessage *iface,
1127     DWORD dwFlags)
1128 {
1129     FIXME("(%p)->(0x%x)\n", iface, dwFlags);
1130     return E_NOTIMPL;
1131 }
1132
1133
1134 static HRESULT WINAPI MimeMessage_HandsOffStorage(
1135     IMimeMessage *iface)
1136 {
1137     FIXME("(%p)->()\n", iface);
1138     return E_NOTIMPL;
1139 }
1140
1141 static HRESULT WINAPI MimeMessage_BindToObject(
1142     IMimeMessage *iface,
1143     const HBODY hBody,
1144     REFIID riid,
1145     void **ppvObject)
1146 {
1147     FIXME("(%p)->(%p, %s, %p)\n", iface, hBody, debugstr_guid(riid), ppvObject);
1148     return E_NOTIMPL;
1149 }
1150
1151 static HRESULT WINAPI MimeMessage_SaveBody(
1152     IMimeMessage *iface,
1153     HBODY hBody,
1154     DWORD dwFlags,
1155     IStream *pStream)
1156 {
1157     FIXME("(%p)->(%p, 0x%x, %p)\n", iface, hBody, dwFlags, pStream);
1158     return E_NOTIMPL;
1159 }
1160
1161 static HRESULT WINAPI MimeMessage_InsertBody(
1162     IMimeMessage *iface,
1163     BODYLOCATION location,
1164     HBODY hPivot,
1165     LPHBODY phBody)
1166 {
1167     FIXME("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody);
1168     return E_NOTIMPL;
1169 }
1170
1171 static HRESULT WINAPI MimeMessage_GetBody(
1172     IMimeMessage *iface,
1173     BODYLOCATION location,
1174     HBODY hPivot,
1175     LPHBODY phBody)
1176 {
1177     FIXME("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody);
1178     return E_NOTIMPL;
1179 }
1180
1181 static HRESULT WINAPI MimeMessage_DeleteBody(
1182     IMimeMessage *iface,
1183     HBODY hBody,
1184     DWORD dwFlags)
1185 {
1186     FIXME("(%p)->(%p, %08x)\n", iface, hBody, dwFlags);
1187     return E_NOTIMPL;
1188 }
1189
1190 static HRESULT WINAPI MimeMessage_MoveBody(
1191     IMimeMessage *iface,
1192     HBODY hBody,
1193     BODYLOCATION location)
1194 {
1195     FIXME("(%p)->(%d)\n", iface, location);
1196     return E_NOTIMPL;
1197 }
1198
1199 static HRESULT WINAPI MimeMessage_CountBodies(
1200     IMimeMessage *iface,
1201     HBODY hParent,
1202     boolean fRecurse,
1203     ULONG *pcBodies)
1204 {
1205     FIXME("(%p)->(%p, %s, %p)\n", iface, hParent, fRecurse ? "TRUE" : "FALSE", pcBodies);
1206     return E_NOTIMPL;
1207 }
1208
1209 static HRESULT WINAPI MimeMessage_FindFirst(
1210     IMimeMessage *iface,
1211     LPFINDBODY pFindBody,
1212     LPHBODY phBody)
1213 {
1214     FIXME("(%p)->(%p, %p)\n", iface, pFindBody, phBody);
1215     return E_NOTIMPL;
1216 }
1217
1218 static HRESULT WINAPI MimeMessage_FindNext(
1219     IMimeMessage *iface,
1220     LPFINDBODY pFindBody,
1221     LPHBODY phBody)
1222 {
1223     FIXME("(%p)->(%p, %p)\n", iface, pFindBody, phBody);
1224     return E_NOTIMPL;
1225 }
1226
1227 static HRESULT WINAPI MimeMessage_ResolveURL(
1228     IMimeMessage *iface,
1229     HBODY hRelated,
1230     LPCSTR pszBase,
1231     LPCSTR pszURL,
1232     DWORD dwFlags,
1233     LPHBODY phBody)
1234 {
1235     FIXME("(%p)->(%p, %s, %s, 0x%x, %p)\n", iface, hRelated, pszBase, pszURL, dwFlags, phBody);
1236     return E_NOTIMPL;
1237 }
1238
1239 static HRESULT WINAPI MimeMessage_ToMultipart(
1240     IMimeMessage *iface,
1241     HBODY hBody,
1242     LPCSTR pszSubType,
1243     LPHBODY phMultipart)
1244 {
1245     FIXME("(%p)->(%p, %s, %p)\n", iface, hBody, pszSubType, phMultipart);
1246     return E_NOTIMPL;
1247 }
1248
1249 static HRESULT WINAPI MimeMessage_GetBodyOffsets(
1250     IMimeMessage *iface,
1251     HBODY hBody,
1252     LPBODYOFFSETS pOffsets)
1253 {
1254     FIXME("(%p)->(%p, %p)\n", iface, hBody, pOffsets);
1255     return E_NOTIMPL;
1256 }
1257
1258 static HRESULT WINAPI MimeMessage_GetCharset(
1259     IMimeMessage *iface,
1260     LPHCHARSET phCharset)
1261 {
1262     FIXME("(%p)->(%p)\n", iface, phCharset);
1263     return E_NOTIMPL;
1264 }
1265
1266 static HRESULT WINAPI MimeMessage_SetCharset(
1267     IMimeMessage *iface,
1268     HCHARSET hCharset,
1269     CSETAPPLYTYPE applytype)
1270 {
1271     FIXME("(%p)->(%p, %d)\n", iface, hCharset, applytype);
1272     return E_NOTIMPL;
1273 }
1274
1275 static HRESULT WINAPI MimeMessage_IsBodyType(
1276     IMimeMessage *iface,
1277     HBODY hBody,
1278     IMSGBODYTYPE bodytype)
1279 {
1280     FIXME("(%p)->(%p, %d)\n", iface, hBody, bodytype);
1281     return E_NOTIMPL;
1282 }
1283
1284 static HRESULT WINAPI MimeMessage_IsContentType(
1285     IMimeMessage *iface,
1286     HBODY hBody,
1287     LPCSTR pszPriType,
1288     LPCSTR pszSubType)
1289 {
1290     FIXME("(%p)->(%p, %s, %s)\n", iface, hBody, pszPriType, pszSubType);
1291     return E_NOTIMPL;
1292 }
1293
1294 static HRESULT WINAPI MimeMessage_QueryBodyProp(
1295     IMimeMessage *iface,
1296     HBODY hBody,
1297     LPCSTR pszName,
1298     LPCSTR pszCriteria,
1299     boolean fSubString,
1300     boolean fCaseSensitive)
1301 {
1302     FIXME("(%p)->(%p, %s, %s, %s, %s)\n", iface, hBody, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE");
1303     return E_NOTIMPL;
1304 }
1305
1306 static HRESULT WINAPI MimeMessage_GetBodyProp(
1307     IMimeMessage *iface,
1308     HBODY hBody,
1309     LPCSTR pszName,
1310     DWORD dwFlags,
1311     LPPROPVARIANT pValue)
1312 {
1313     FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue);
1314     return E_NOTIMPL;
1315 }
1316
1317 static HRESULT WINAPI MimeMessage_SetBodyProp(
1318     IMimeMessage *iface,
1319     HBODY hBody,
1320     LPCSTR pszName,
1321     DWORD dwFlags,
1322     LPCPROPVARIANT pValue)
1323 {
1324     FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue);
1325     return E_NOTIMPL;
1326 }
1327
1328 static HRESULT WINAPI MimeMessage_DeleteBodyProp(
1329     IMimeMessage *iface,
1330     HBODY hBody,
1331     LPCSTR pszName)
1332 {
1333     FIXME("(%p)->(%p, %s)\n", iface, hBody, pszName);
1334     return E_NOTIMPL;
1335 }
1336
1337 static HRESULT WINAPI MimeMessage_SetOption(
1338     IMimeMessage *iface,
1339     const TYPEDID oid,
1340     LPCPROPVARIANT pValue)
1341 {
1342     FIXME("(%p)->(%d, %p)\n", iface, oid, pValue);
1343     return E_NOTIMPL;
1344 }
1345
1346 static HRESULT WINAPI MimeMessage_GetOption(
1347     IMimeMessage *iface,
1348     const TYPEDID oid,
1349     LPPROPVARIANT pValue)
1350 {
1351     FIXME("(%p)->(%d, %p)\n", iface, oid, pValue);
1352     return E_NOTIMPL;
1353 }
1354
1355 /*** IMimeMessage methods ***/
1356 static HRESULT WINAPI MimeMessage_CreateWebPage(
1357     IMimeMessage *iface,
1358     IStream *pRootStm,
1359     LPWEBPAGEOPTIONS pOptions,
1360     IMimeMessageCallback *pCallback,
1361     IMoniker **ppMoniker)
1362 {
1363     FIXME("(%p)->(%p, %p, %p, %p)\n", iface, pRootStm, pOptions, pCallback, ppMoniker);
1364     *ppMoniker = NULL;
1365     return E_NOTIMPL;
1366 }
1367
1368 static HRESULT WINAPI MimeMessage_GetProp(
1369     IMimeMessage *iface,
1370     LPCSTR pszName,
1371     DWORD dwFlags,
1372     LPPROPVARIANT pValue)
1373 {
1374     FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue);
1375     return E_NOTIMPL;
1376 }
1377
1378 static HRESULT WINAPI MimeMessage_SetProp(
1379     IMimeMessage *iface,
1380     LPCSTR pszName,
1381     DWORD dwFlags,
1382     LPCPROPVARIANT pValue)
1383 {
1384     FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue);
1385     return E_NOTIMPL;
1386 }
1387
1388 static HRESULT WINAPI MimeMessage_DeleteProp(
1389     IMimeMessage *iface,
1390     LPCSTR pszName)
1391 {
1392     FIXME("(%p)->(%s)\n", iface, pszName);
1393     return E_NOTIMPL;
1394 }
1395
1396 static HRESULT WINAPI MimeMessage_QueryProp(
1397     IMimeMessage *iface,
1398     LPCSTR pszName,
1399     LPCSTR pszCriteria,
1400     boolean fSubString,
1401     boolean fCaseSensitive)
1402 {
1403     FIXME("(%p)->(%s, %s, %s, %s)\n", iface, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE");
1404     return E_NOTIMPL;
1405 }
1406
1407 static HRESULT WINAPI MimeMessage_GetTextBody(
1408     IMimeMessage *iface,
1409     DWORD dwTxtType,
1410     ENCODINGTYPE ietEncoding,
1411     IStream **pStream,
1412     LPHBODY phBody)
1413 {
1414     FIXME("(%p)->(%d, %d, %p, %p)\n", iface, dwTxtType, ietEncoding, pStream, phBody);
1415     return E_NOTIMPL;
1416 }
1417
1418 static HRESULT WINAPI MimeMessage_SetTextBody(
1419     IMimeMessage *iface,
1420     DWORD dwTxtType,
1421     ENCODINGTYPE ietEncoding,
1422     HBODY hAlternative,
1423     IStream *pStream,
1424     LPHBODY phBody)
1425 {
1426     FIXME("(%p)->(%d, %d, %p, %p, %p)\n", iface, dwTxtType, ietEncoding, hAlternative, pStream, phBody);
1427     return E_NOTIMPL;
1428 }
1429
1430 static HRESULT WINAPI MimeMessage_AttachObject(
1431     IMimeMessage *iface,
1432     REFIID riid,
1433     void *pvObject,
1434     LPHBODY phBody)
1435 {
1436     FIXME("(%p)->(%s, %p, %p)\n", iface, debugstr_guid(riid), pvObject, phBody);
1437     return E_NOTIMPL;
1438 }
1439
1440 static HRESULT WINAPI MimeMessage_AttachFile(
1441     IMimeMessage *iface,
1442     LPCSTR pszFilePath,
1443     IStream *pstmFile,
1444     LPHBODY phBody)
1445 {
1446     FIXME("(%p)->(%s, %p, %p)\n", iface, pszFilePath, pstmFile, phBody);
1447     return E_NOTIMPL;
1448 }
1449
1450 static HRESULT WINAPI MimeMessage_AttachURL(
1451     IMimeMessage *iface,
1452     LPCSTR pszBase,
1453     LPCSTR pszURL,
1454     DWORD dwFlags,
1455     IStream *pstmURL,
1456     LPSTR *ppszCIDURL,
1457     LPHBODY phBody)
1458 {
1459     FIXME("(%p)->(%s, %s, 0x%x, %p, %p, %p)\n", iface, pszBase, pszURL, dwFlags, pstmURL, ppszCIDURL, phBody);
1460     return E_NOTIMPL;
1461 }
1462
1463 static HRESULT WINAPI MimeMessage_GetAttachments(
1464     IMimeMessage *iface,
1465     ULONG *pcAttach,
1466     LPHBODY *pprghAttach)
1467 {
1468     FIXME("(%p)->(%p, %p)\n", iface, pcAttach, pprghAttach);
1469     return E_NOTIMPL;
1470 }
1471
1472 static HRESULT WINAPI MimeMessage_GetAddressTable(
1473     IMimeMessage *iface,
1474     IMimeAddressTable **ppTable)
1475 {
1476     FIXME("(%p)->(%p)\n", iface, ppTable);
1477     return E_NOTIMPL;
1478 }
1479
1480 static HRESULT WINAPI MimeMessage_GetSender(
1481     IMimeMessage *iface,
1482     LPADDRESSPROPS pAddress)
1483 {
1484     FIXME("(%p)->(%p)\n", iface, pAddress);
1485     return E_NOTIMPL;
1486 }
1487
1488 static HRESULT WINAPI MimeMessage_GetAddressTypes(
1489     IMimeMessage *iface,
1490     DWORD dwAdrTypes,
1491     DWORD dwProps,
1492     LPADDRESSLIST pList)
1493 {
1494     FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, pList);
1495     return E_NOTIMPL;
1496 }
1497
1498 static HRESULT WINAPI MimeMessage_GetAddressFormat(
1499     IMimeMessage *iface,
1500     DWORD dwAdrTypes,
1501     ADDRESSFORMAT format,
1502     LPSTR *ppszFormat)
1503 {
1504     FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, format, ppszFormat);
1505     return E_NOTIMPL;
1506 }
1507
1508 static HRESULT WINAPI MimeMessage_EnumAddressTypes(
1509     IMimeMessage *iface,
1510     DWORD dwAdrTypes,
1511     DWORD dwProps,
1512     IMimeEnumAddressTypes **ppEnum)
1513 {
1514     FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, ppEnum);
1515     return E_NOTIMPL;
1516 }
1517
1518 static HRESULT WINAPI MimeMessage_SplitMessage(
1519     IMimeMessage *iface,
1520     ULONG cbMaxPart,
1521     IMimeMessageParts **ppParts)
1522 {
1523     FIXME("(%p)->(%d, %p)\n", iface, cbMaxPart, ppParts);
1524     return E_NOTIMPL;
1525 }
1526
1527 static HRESULT WINAPI MimeMessage_GetRootMoniker(
1528     IMimeMessage *iface,
1529     IMoniker **ppMoniker)
1530 {
1531     FIXME("(%p)->(%p)\n", iface, ppMoniker);
1532     return E_NOTIMPL;
1533 }
1534
1535 static const IMimeMessageVtbl MimeMessageVtbl =
1536 {
1537     MimeMessage_QueryInterface,
1538     MimeMessage_AddRef,
1539     MimeMessage_Release,
1540     MimeMessage_GetClassID,
1541     MimeMessage_IsDirty,
1542     MimeMessage_Load,
1543     MimeMessage_Save,
1544     MimeMessage_GetSizeMax,
1545     MimeMessage_InitNew,
1546     MimeMessage_GetMessageSource,
1547     MimeMessage_GetMessageSize,
1548     MimeMessage_LoadOffsetTable,
1549     MimeMessage_SaveOffsetTable,
1550     MimeMessage_GetFlags,
1551     MimeMessage_Commit,
1552     MimeMessage_HandsOffStorage,
1553     MimeMessage_BindToObject,
1554     MimeMessage_SaveBody,
1555     MimeMessage_InsertBody,
1556     MimeMessage_GetBody,
1557     MimeMessage_DeleteBody,
1558     MimeMessage_MoveBody,
1559     MimeMessage_CountBodies,
1560     MimeMessage_FindFirst,
1561     MimeMessage_FindNext,
1562     MimeMessage_ResolveURL,
1563     MimeMessage_ToMultipart,
1564     MimeMessage_GetBodyOffsets,
1565     MimeMessage_GetCharset,
1566     MimeMessage_SetCharset,
1567     MimeMessage_IsBodyType,
1568     MimeMessage_IsContentType,
1569     MimeMessage_QueryBodyProp,
1570     MimeMessage_GetBodyProp,
1571     MimeMessage_SetBodyProp,
1572     MimeMessage_DeleteBodyProp,
1573     MimeMessage_SetOption,
1574     MimeMessage_GetOption,
1575     MimeMessage_CreateWebPage,
1576     MimeMessage_GetProp,
1577     MimeMessage_SetProp,
1578     MimeMessage_DeleteProp,
1579     MimeMessage_QueryProp,
1580     MimeMessage_GetTextBody,
1581     MimeMessage_SetTextBody,
1582     MimeMessage_AttachObject,
1583     MimeMessage_AttachFile,
1584     MimeMessage_AttachURL,
1585     MimeMessage_GetAttachments,
1586     MimeMessage_GetAddressTable,
1587     MimeMessage_GetSender,
1588     MimeMessage_GetAddressTypes,
1589     MimeMessage_GetAddressFormat,
1590     MimeMessage_EnumAddressTypes,
1591     MimeMessage_SplitMessage,
1592     MimeMessage_GetRootMoniker,
1593 };
1594
1595 /***********************************************************************
1596  *              MimeOleCreateMessage (INETCOMM.@)
1597  */
1598 HRESULT WINAPI MimeOleCreateMessage(IUnknown *pUnkOuter, IMimeMessage **ppMessage)
1599 {
1600     MimeMessage *This;
1601
1602     TRACE("(%p, %p)\n", pUnkOuter, ppMessage);
1603
1604     if (pUnkOuter)
1605     {
1606         FIXME("outer unknown not supported yet\n");
1607         return E_NOTIMPL;
1608     }
1609
1610     *ppMessage = NULL;
1611
1612     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1613     if (!This) return E_OUTOFMEMORY;
1614
1615     This->lpVtbl = &MimeMessageVtbl;
1616     This->refs = 1;
1617
1618     *ppMessage = (IMimeMessage *)&This->lpVtbl;
1619     return S_OK;
1620 }
1621
1622 /***********************************************************************
1623  *              MimeOleSetCompatMode (INETCOMM.@)
1624  */
1625 HRESULT WINAPI MimeOleSetCompatMode(DWORD dwMode)
1626 {
1627     FIXME("(0x%x)\n", dwMode);
1628     return S_OK;
1629 }
1630
1631 /***********************************************************************
1632  *              MimeOleCreateVirtualStream (INETCOMM.@)
1633  */
1634 HRESULT WINAPI MimeOleCreateVirtualStream(IStream **ppStream)
1635 {
1636     HRESULT hr;
1637     FIXME("(%p)\n", ppStream);
1638
1639     hr = CreateStreamOnHGlobal(NULL, TRUE, ppStream);
1640     return hr;
1641 }
1642
1643 typedef struct MimeSecurity
1644 {
1645     const IMimeSecurityVtbl *lpVtbl;
1646
1647     LONG refs;
1648 } MimeSecurity;
1649
1650 static HRESULT WINAPI MimeSecurity_QueryInterface(
1651         IMimeSecurity* iface,
1652         REFIID riid,
1653         void** obj)
1654 {
1655     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), obj);
1656
1657     if (IsEqualIID(riid, &IID_IUnknown) ||
1658         IsEqualIID(riid, &IID_IMimeSecurity))
1659     {
1660         *obj = iface;
1661         IUnknown_AddRef(iface);
1662         return S_OK;
1663     }
1664
1665     FIXME("no interface for %s\n", debugstr_guid(riid));
1666     *obj = NULL;
1667     return E_NOINTERFACE;
1668 }
1669
1670 static ULONG WINAPI MimeSecurity_AddRef(
1671         IMimeSecurity* iface)
1672 {
1673     MimeSecurity *This = (MimeSecurity *)iface;
1674     TRACE("(%p)->()\n", iface);
1675     return InterlockedIncrement(&This->refs);
1676 }
1677
1678 static ULONG WINAPI MimeSecurity_Release(
1679         IMimeSecurity* iface)
1680 {
1681     MimeSecurity *This = (MimeSecurity *)iface;
1682     ULONG refs;
1683
1684     TRACE("(%p)->()\n", iface);
1685
1686     refs = InterlockedDecrement(&This->refs);
1687     if (!refs)
1688     {
1689         HeapFree(GetProcessHeap(), 0, This);
1690     }
1691
1692     return refs;
1693 }
1694
1695 static HRESULT WINAPI MimeSecurity_InitNew(
1696         IMimeSecurity* iface)
1697 {
1698     FIXME("(%p)->(): stub\n", iface);
1699     return S_OK;
1700 }
1701
1702 static HRESULT WINAPI MimeSecurity_CheckInit(
1703         IMimeSecurity* iface)
1704 {
1705     FIXME("(%p)->(): stub\n", iface);
1706     return E_NOTIMPL;
1707 }
1708
1709 static HRESULT WINAPI MimeSecurity_EncodeMessage(
1710         IMimeSecurity* iface,
1711         IMimeMessageTree* pTree,
1712         DWORD dwFlags)
1713 {
1714     FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags);
1715     return E_NOTIMPL;
1716 }
1717
1718 static HRESULT WINAPI MimeSecurity_EncodeBody(
1719         IMimeSecurity* iface,
1720         IMimeMessageTree* pTree,
1721         HBODY hEncodeRoot,
1722         DWORD dwFlags)
1723 {
1724     FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hEncodeRoot, dwFlags);
1725     return E_NOTIMPL;
1726 }
1727
1728 static HRESULT WINAPI MimeSecurity_DecodeMessage(
1729         IMimeSecurity* iface,
1730         IMimeMessageTree* pTree,
1731         DWORD dwFlags)
1732 {
1733     FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags);
1734     return E_NOTIMPL;
1735 }
1736
1737 static HRESULT WINAPI MimeSecurity_DecodeBody(
1738         IMimeSecurity* iface,
1739         IMimeMessageTree* pTree,
1740         HBODY hDecodeRoot,
1741         DWORD dwFlags)
1742 {
1743     FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hDecodeRoot, dwFlags);
1744     return E_NOTIMPL;
1745 }
1746
1747 static HRESULT WINAPI MimeSecurity_EnumCertificates(
1748         IMimeSecurity* iface,
1749         HCAPICERTSTORE hc,
1750         DWORD dwUsage,
1751         PCX509CERT pPrev,
1752         PCX509CERT* ppCert)
1753 {
1754     FIXME("(%p)->(%p, %08x, %p, %p): stub\n", iface, hc, dwUsage, pPrev, ppCert);
1755     return E_NOTIMPL;
1756 }
1757
1758 static HRESULT WINAPI MimeSecurity_GetCertificateName(
1759         IMimeSecurity* iface,
1760         const PCX509CERT pX509Cert,
1761         const CERTNAMETYPE cn,
1762         LPSTR* ppszName)
1763 {
1764     FIXME("(%p)->(%p, %08x, %p): stub\n", iface, pX509Cert, cn, ppszName);
1765     return E_NOTIMPL;
1766 }
1767
1768 static HRESULT WINAPI MimeSecurity_GetMessageType(
1769         IMimeSecurity* iface,
1770         const HWND hwndParent,
1771         IMimeBody* pBody,
1772         DWORD* pdwSecType)
1773 {
1774     FIXME("(%p)->(%p, %p, %p): stub\n", iface, hwndParent, pBody, pdwSecType);
1775     return E_NOTIMPL;
1776 }
1777
1778 static HRESULT WINAPI MimeSecurity_GetCertData(
1779         IMimeSecurity* iface,
1780         const PCX509CERT pX509Cert,
1781         const CERTDATAID dataid,
1782         LPPROPVARIANT pValue)
1783 {
1784     FIXME("(%p)->(%p, %x, %p): stub\n", iface, pX509Cert, dataid, pValue);
1785     return E_NOTIMPL;
1786 }
1787
1788
1789 static const IMimeSecurityVtbl MimeSecurityVtbl =
1790 {
1791     MimeSecurity_QueryInterface,
1792     MimeSecurity_AddRef,
1793     MimeSecurity_Release,
1794     MimeSecurity_InitNew,
1795     MimeSecurity_CheckInit,
1796     MimeSecurity_EncodeMessage,
1797     MimeSecurity_EncodeBody,
1798     MimeSecurity_DecodeMessage,
1799     MimeSecurity_DecodeBody,
1800     MimeSecurity_EnumCertificates,
1801     MimeSecurity_GetCertificateName,
1802     MimeSecurity_GetMessageType,
1803     MimeSecurity_GetCertData
1804 };
1805
1806 /***********************************************************************
1807  *              MimeOleCreateSecurity (INETCOMM.@)
1808  */
1809 HRESULT WINAPI MimeOleCreateSecurity(IMimeSecurity **ppSecurity)
1810 {
1811     MimeSecurity *This;
1812
1813     TRACE("(%p)\n", ppSecurity);
1814
1815     *ppSecurity = NULL;
1816
1817     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1818     if (!This) return E_OUTOFMEMORY;
1819
1820     This->lpVtbl = &MimeSecurityVtbl;
1821     This->refs = 1;
1822
1823     *ppSecurity = (IMimeSecurity *)&This->lpVtbl;
1824     return S_OK;
1825 }