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