inetcomm: Implement IMimeMessage_CountBodies.
[wine/wine64.git] / dlls / inetcomm / mimeole.c
blobd6b42740676b246764deff86eccd22f5d497ee4e
1 /*
2 * MIME OLE Interfaces
4 * Copyright 2006 Robert Shearman for CodeWeavers
5 * Copyright 2007 Huw Davies for CodeWeavers
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.
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.
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
22 #define COBJMACROS
23 #define NONAMELESSUNION
25 #include <stdarg.h>
26 #include <stdio.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "objbase.h"
32 #include "ole2.h"
33 #include "mimeole.h"
35 #include "wine/list.h"
36 #include "wine/debug.h"
38 #include "inetcomm_private.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm);
42 typedef struct
44 LPCSTR name;
45 DWORD id;
46 DWORD flags; /* MIMEPROPFLAGS */
47 VARTYPE default_vt;
48 } property_t;
50 typedef struct
52 struct list entry;
53 property_t prop;
54 } property_list_entry_t;
56 static const property_t default_props[] =
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}
80 typedef struct
82 struct list entry;
83 char *name;
84 char *value;
85 } param_t;
87 typedef struct
89 struct list entry;
90 const property_t *prop;
91 PROPVARIANT value;
92 struct list params;
93 } header_t;
95 typedef struct MimeBody
97 const IMimeBodyVtbl *lpVtbl;
98 LONG refs;
100 HBODY handle;
102 struct list headers;
103 struct list new_props; /* FIXME: This should be in a PropertySchema */
104 DWORD next_prop_id;
105 char *content_pri_type;
106 char *content_sub_type;
107 ENCODINGTYPE encoding;
108 void *data;
109 IID data_iid;
110 BODYOFFSETS body_offsets;
111 } MimeBody;
113 static inline MimeBody *impl_from_IMimeBody( IMimeBody *iface )
115 return (MimeBody *)((char*)iface - FIELD_OFFSET(MimeBody, lpVtbl));
118 static LPSTR strdupA(LPCSTR str)
120 char *ret;
121 int len = strlen(str);
122 ret = HeapAlloc(GetProcessHeap(), 0, len + 1);
123 memcpy(ret, str, len + 1);
124 return ret;
127 #define PARSER_BUF_SIZE 1024
129 /*****************************************************
130 * copy_headers_to_buf [internal]
132 * Copies the headers into a '\0' terminated memory block and leave
133 * the stream's current position set to after the blank line.
135 static HRESULT copy_headers_to_buf(IStream *stm, char **ptr)
137 char *buf = NULL;
138 DWORD size = PARSER_BUF_SIZE, offset = 0, last_end = 0;
139 HRESULT hr;
140 int done = 0;
142 *ptr = NULL;
146 char *end;
147 DWORD read;
149 if(!buf)
150 buf = HeapAlloc(GetProcessHeap(), 0, size + 1);
151 else
153 size *= 2;
154 buf = HeapReAlloc(GetProcessHeap(), 0, buf, size + 1);
156 if(!buf)
158 hr = E_OUTOFMEMORY;
159 goto fail;
162 hr = IStream_Read(stm, buf + offset, size - offset, &read);
163 if(FAILED(hr)) goto fail;
165 offset += read;
166 buf[offset] = '\0';
168 if(read == 0) done = 1;
170 while(!done && (end = strstr(buf + last_end, "\r\n")))
172 DWORD new_end = end - buf + 2;
173 if(new_end - last_end == 2)
175 LARGE_INTEGER off;
176 off.QuadPart = new_end;
177 IStream_Seek(stm, off, STREAM_SEEK_SET, NULL);
178 buf[new_end] = '\0';
179 done = 1;
181 else
182 last_end = new_end;
184 } while(!done);
186 *ptr = buf;
187 return S_OK;
189 fail:
190 HeapFree(GetProcessHeap(), 0, buf);
191 return hr;
194 static header_t *read_prop(MimeBody *body, char **ptr)
196 char *colon = strchr(*ptr, ':');
197 const property_t *prop;
198 header_t *ret;
200 if(!colon) return NULL;
202 *colon = '\0';
204 for(prop = default_props; prop->name; prop++)
206 if(!strcasecmp(*ptr, prop->name))
208 TRACE("%s: found match with default property id %d\n", *ptr, prop->id);
209 break;
213 if(!prop->name)
215 property_list_entry_t *prop_entry;
216 LIST_FOR_EACH_ENTRY(prop_entry, &body->new_props, property_list_entry_t, entry)
218 if(!strcasecmp(*ptr, prop_entry->prop.name))
220 TRACE("%s: found match with already added new property id %d\n", *ptr, prop_entry->prop.id);
221 prop = &prop_entry->prop;
222 break;
225 if(!prop->name)
227 prop_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry));
228 prop_entry->prop.name = strdupA(*ptr);
229 prop_entry->prop.id = body->next_prop_id++;
230 prop_entry->prop.flags = 0;
231 prop_entry->prop.default_vt = VT_LPSTR;
232 list_add_tail(&body->new_props, &prop_entry->entry);
233 prop = &prop_entry->prop;
234 TRACE("%s: allocating new prop id %d\n", *ptr, prop_entry->prop.id);
238 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret));
239 ret->prop = prop;
240 PropVariantInit(&ret->value);
241 list_init(&ret->params);
242 *ptr = colon + 1;
244 return ret;
247 static void unfold_header(char *header, int len)
249 char *start = header, *cp = header;
251 do {
252 while(*cp == ' ' || *cp == '\t')
254 cp++;
255 len--;
257 if(cp != start)
258 memmove(start, cp, len + 1);
260 cp = strstr(start, "\r\n");
261 len -= (cp - start);
262 start = cp;
263 *start = ' ';
264 start++;
265 len--;
266 cp += 2;
267 } while(*cp == ' ' || *cp == '\t');
269 *(start - 1) = '\0';
272 static char *unquote_string(const char *str)
274 int quoted = 0;
275 char *ret, *cp;
277 while(*str == ' ' || *str == '\t') str++;
279 if(*str == '"')
281 quoted = 1;
282 str++;
284 ret = strdupA(str);
285 for(cp = ret; *cp; cp++)
287 if(*cp == '\\')
288 memmove(cp, cp + 1, strlen(cp + 1) + 1);
289 else if(*cp == '"')
291 if(!quoted)
293 WARN("quote in unquoted string\n");
295 else
297 *cp = '\0';
298 break;
302 return ret;
305 static void add_param(header_t *header, const char *p)
307 const char *key = p, *value, *cp = p;
308 param_t *param;
309 char *name;
311 TRACE("got param %s\n", p);
313 while (*key == ' ' || *key == '\t' ) key++;
315 cp = strchr(key, '=');
316 if(!cp)
318 WARN("malformed parameter - skipping\n");
319 return;
322 name = HeapAlloc(GetProcessHeap(), 0, cp - key + 1);
323 memcpy(name, key, cp - key);
324 name[cp - key] = '\0';
326 value = cp + 1;
328 param = HeapAlloc(GetProcessHeap(), 0, sizeof(*param));
329 param->name = name;
330 param->value = unquote_string(value);
331 list_add_tail(&header->params, &param->entry);
334 static void split_params(header_t *header, char *value)
336 char *cp = value, *start = value;
337 int in_quote = 0;
338 int done_value = 0;
340 while(*cp)
342 if(!in_quote && *cp == ';')
344 *cp = '\0';
345 if(done_value) add_param(header, start);
346 done_value = 1;
347 start = cp + 1;
349 else if(*cp == '"')
350 in_quote = !in_quote;
351 cp++;
353 if(done_value) add_param(header, start);
356 static void read_value(header_t *header, char **cur)
358 char *end = *cur, *value;
359 DWORD len;
361 do {
362 end = strstr(end, "\r\n");
363 end += 2;
364 } while(*end == ' ' || *end == '\t');
366 len = end - *cur;
367 value = HeapAlloc(GetProcessHeap(), 0, len + 1);
368 memcpy(value, *cur, len);
369 value[len] = '\0';
371 unfold_header(value, len);
372 TRACE("value %s\n", debugstr_a(value));
374 if(header->prop->flags & MPF_HASPARAMS)
376 split_params(header, value);
377 TRACE("value w/o params %s\n", debugstr_a(value));
380 header->value.vt = VT_LPSTR;
381 header->value.u.pszVal = value;
383 *cur = end;
386 static void init_content_type(MimeBody *body, header_t *header)
388 char *slash;
389 DWORD len;
391 if(header->prop->id != PID_HDR_CNTTYPE)
393 ERR("called with header %s\n", header->prop->name);
394 return;
397 slash = strchr(header->value.u.pszVal, '/');
398 if(!slash)
400 WARN("malformed context type value\n");
401 return;
403 len = slash - header->value.u.pszVal;
404 body->content_pri_type = HeapAlloc(GetProcessHeap(), 0, len + 1);
405 memcpy(body->content_pri_type, header->value.u.pszVal, len);
406 body->content_pri_type[len] = '\0';
407 body->content_sub_type = strdupA(slash + 1);
410 static HRESULT parse_headers(MimeBody *body, IStream *stm)
412 char *header_buf, *cur_header_ptr;
413 HRESULT hr;
414 header_t *header;
416 hr = copy_headers_to_buf(stm, &header_buf);
417 if(FAILED(hr)) return hr;
419 cur_header_ptr = header_buf;
420 while((header = read_prop(body, &cur_header_ptr)))
422 read_value(header, &cur_header_ptr);
423 list_add_tail(&body->headers, &header->entry);
425 if(header->prop->id == PID_HDR_CNTTYPE)
426 init_content_type(body, header);
429 HeapFree(GetProcessHeap(), 0, header_buf);
430 return hr;
433 static void empty_param_list(struct list *list)
435 param_t *param, *cursor2;
437 LIST_FOR_EACH_ENTRY_SAFE(param, cursor2, list, param_t, entry)
439 list_remove(&param->entry);
440 HeapFree(GetProcessHeap(), 0, param->name);
441 HeapFree(GetProcessHeap(), 0, param->value);
442 HeapFree(GetProcessHeap(), 0, param);
446 static void empty_header_list(struct list *list)
448 header_t *header, *cursor2;
450 LIST_FOR_EACH_ENTRY_SAFE(header, cursor2, list, header_t, entry)
452 list_remove(&header->entry);
453 PropVariantClear(&header->value);
454 empty_param_list(&header->params);
455 HeapFree(GetProcessHeap(), 0, header);
459 static void empty_new_prop_list(struct list *list)
461 property_list_entry_t *prop, *cursor2;
463 LIST_FOR_EACH_ENTRY_SAFE(prop, cursor2, list, property_list_entry_t, entry)
465 list_remove(&prop->entry);
466 HeapFree(GetProcessHeap(), 0, (char *)prop->prop.name);
467 HeapFree(GetProcessHeap(), 0, prop);
471 static void release_data(REFIID riid, void *data)
473 if(!data) return;
475 if(IsEqualIID(riid, &IID_IStream))
476 IStream_Release((IStream *)data);
477 else
478 FIXME("Unhandled data format %s\n", debugstr_guid(riid));
481 static HRESULT find_prop(MimeBody *body, const char *name, header_t **prop)
483 header_t *header;
485 *prop = NULL;
487 LIST_FOR_EACH_ENTRY(header, &body->headers, header_t, entry)
489 if(!strcasecmp(name, header->prop->name))
491 *prop = header;
492 return S_OK;
496 return MIME_E_NOT_FOUND;
499 static HRESULT WINAPI MimeBody_QueryInterface(IMimeBody* iface,
500 REFIID riid,
501 void** ppvObject)
503 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppvObject);
505 *ppvObject = NULL;
507 if (IsEqualIID(riid, &IID_IUnknown) ||
508 IsEqualIID(riid, &IID_IPersist) ||
509 IsEqualIID(riid, &IID_IPersistStreamInit) ||
510 IsEqualIID(riid, &IID_IMimePropertySet) ||
511 IsEqualIID(riid, &IID_IMimeBody))
513 *ppvObject = iface;
516 if(*ppvObject)
518 IUnknown_AddRef((IUnknown*)*ppvObject);
519 return S_OK;
522 FIXME("no interface for %s\n", debugstr_guid(riid));
523 return E_NOINTERFACE;
526 static ULONG WINAPI MimeBody_AddRef(IMimeBody* iface)
528 MimeBody *This = impl_from_IMimeBody(iface);
529 TRACE("(%p)->()\n", iface);
530 return InterlockedIncrement(&This->refs);
533 static ULONG WINAPI MimeBody_Release(IMimeBody* iface)
535 MimeBody *This = impl_from_IMimeBody(iface);
536 ULONG refs;
538 TRACE("(%p)->()\n", iface);
540 refs = InterlockedDecrement(&This->refs);
541 if (!refs)
543 empty_header_list(&This->headers);
544 empty_new_prop_list(&This->new_props);
546 HeapFree(GetProcessHeap(), 0, This->content_pri_type);
547 HeapFree(GetProcessHeap(), 0, This->content_sub_type);
549 release_data(&This->data_iid, This->data);
551 HeapFree(GetProcessHeap(), 0, This);
554 return refs;
557 static HRESULT WINAPI MimeBody_GetClassID(
558 IMimeBody* iface,
559 CLSID* pClassID)
561 FIXME("stub\n");
562 return E_NOTIMPL;
566 static HRESULT WINAPI MimeBody_IsDirty(
567 IMimeBody* iface)
569 FIXME("stub\n");
570 return E_NOTIMPL;
573 static HRESULT WINAPI MimeBody_Load(
574 IMimeBody* iface,
575 LPSTREAM pStm)
577 MimeBody *This = impl_from_IMimeBody(iface);
578 TRACE("(%p)->(%p)\n", iface, pStm);
579 return parse_headers(This, pStm);
582 static HRESULT WINAPI MimeBody_Save(
583 IMimeBody* iface,
584 LPSTREAM pStm,
585 BOOL fClearDirty)
587 FIXME("stub\n");
588 return E_NOTIMPL;
591 static HRESULT WINAPI MimeBody_GetSizeMax(
592 IMimeBody* iface,
593 ULARGE_INTEGER* pcbSize)
595 FIXME("stub\n");
596 return E_NOTIMPL;
599 static HRESULT WINAPI MimeBody_InitNew(
600 IMimeBody* iface)
602 TRACE("%p->()\n", iface);
603 return S_OK;
606 static HRESULT WINAPI MimeBody_GetPropInfo(
607 IMimeBody* iface,
608 LPCSTR pszName,
609 LPMIMEPROPINFO pInfo)
611 FIXME("stub\n");
612 return E_NOTIMPL;
615 static HRESULT WINAPI MimeBody_SetPropInfo(
616 IMimeBody* iface,
617 LPCSTR pszName,
618 LPCMIMEPROPINFO pInfo)
620 FIXME("stub\n");
621 return E_NOTIMPL;
624 static HRESULT WINAPI MimeBody_GetProp(
625 IMimeBody* iface,
626 LPCSTR pszName,
627 DWORD dwFlags,
628 LPPROPVARIANT pValue)
630 FIXME("stub\n");
631 return E_NOTIMPL;
634 static HRESULT WINAPI MimeBody_SetProp(
635 IMimeBody* iface,
636 LPCSTR pszName,
637 DWORD dwFlags,
638 LPCPROPVARIANT pValue)
640 FIXME("stub\n");
641 return E_NOTIMPL;
644 static HRESULT WINAPI MimeBody_AppendProp(
645 IMimeBody* iface,
646 LPCSTR pszName,
647 DWORD dwFlags,
648 LPPROPVARIANT pValue)
650 FIXME("stub\n");
651 return E_NOTIMPL;
654 static HRESULT WINAPI MimeBody_DeleteProp(
655 IMimeBody* iface,
656 LPCSTR pszName)
658 FIXME("stub\n");
659 return E_NOTIMPL;
662 static HRESULT WINAPI MimeBody_CopyProps(
663 IMimeBody* iface,
664 ULONG cNames,
665 LPCSTR* prgszName,
666 IMimePropertySet* pPropertySet)
668 FIXME("stub\n");
669 return E_NOTIMPL;
672 static HRESULT WINAPI MimeBody_MoveProps(
673 IMimeBody* iface,
674 ULONG cNames,
675 LPCSTR* prgszName,
676 IMimePropertySet* pPropertySet)
678 FIXME("stub\n");
679 return E_NOTIMPL;
682 static HRESULT WINAPI MimeBody_DeleteExcept(
683 IMimeBody* iface,
684 ULONG cNames,
685 LPCSTR* prgszName)
687 FIXME("stub\n");
688 return E_NOTIMPL;
691 static HRESULT WINAPI MimeBody_QueryProp(
692 IMimeBody* iface,
693 LPCSTR pszName,
694 LPCSTR pszCriteria,
695 boolean fSubString,
696 boolean fCaseSensitive)
698 FIXME("stub\n");
699 return E_NOTIMPL;
702 static HRESULT WINAPI MimeBody_GetCharset(
703 IMimeBody* iface,
704 LPHCHARSET phCharset)
706 FIXME("stub\n");
707 return E_NOTIMPL;
710 static HRESULT WINAPI MimeBody_SetCharset(
711 IMimeBody* iface,
712 HCHARSET hCharset,
713 CSETAPPLYTYPE applytype)
715 FIXME("stub\n");
716 return E_NOTIMPL;
719 static HRESULT WINAPI MimeBody_GetParameters(
720 IMimeBody* iface,
721 LPCSTR pszName,
722 ULONG* pcParams,
723 LPMIMEPARAMINFO* pprgParam)
725 MimeBody *This = impl_from_IMimeBody(iface);
726 HRESULT hr;
727 header_t *header;
729 TRACE("(%p)->(%s, %p, %p)\n", iface, debugstr_a(pszName), pcParams, pprgParam);
731 *pprgParam = NULL;
732 *pcParams = 0;
734 hr = find_prop(This, pszName, &header);
735 if(hr != S_OK) return hr;
737 *pcParams = list_count(&header->params);
738 if(*pcParams)
740 IMimeAllocator *alloc;
741 param_t *param;
742 MIMEPARAMINFO *info;
744 MimeOleGetAllocator(&alloc);
746 *pprgParam = info = IMimeAllocator_Alloc(alloc, *pcParams * sizeof(**pprgParam));
747 LIST_FOR_EACH_ENTRY(param, &header->params, param_t, entry)
749 int len;
751 len = strlen(param->name) + 1;
752 info->pszName = IMimeAllocator_Alloc(alloc, len);
753 memcpy(info->pszName, param->name, len);
754 len = strlen(param->value) + 1;
755 info->pszData = IMimeAllocator_Alloc(alloc, len);
756 memcpy(info->pszData, param->value, len);
757 info++;
759 IMimeAllocator_Release(alloc);
761 return S_OK;
764 static HRESULT WINAPI MimeBody_IsContentType(
765 IMimeBody* iface,
766 LPCSTR pszPriType,
767 LPCSTR pszSubType)
769 MimeBody *This = impl_from_IMimeBody(iface);
771 TRACE("(%p)->(%s, %s)\n", This, debugstr_a(pszPriType), debugstr_a(pszSubType));
772 if(pszPriType)
774 const char *pri = This->content_pri_type;
775 if(!pri) pri = "text";
776 if(strcasecmp(pri, pszPriType)) return S_FALSE;
779 if(pszSubType)
781 const char *sub = This->content_sub_type;
782 if(!sub) sub = "plain";
783 if(strcasecmp(sub, pszSubType)) return S_FALSE;
786 return S_OK;
789 static HRESULT WINAPI MimeBody_BindToObject(
790 IMimeBody* iface,
791 REFIID riid,
792 void** ppvObject)
794 FIXME("stub\n");
795 return E_NOTIMPL;
798 static HRESULT WINAPI MimeBody_Clone(
799 IMimeBody* iface,
800 IMimePropertySet** ppPropertySet)
802 FIXME("stub\n");
803 return E_NOTIMPL;
806 static HRESULT WINAPI MimeBody_SetOption(
807 IMimeBody* iface,
808 const TYPEDID oid,
809 LPCPROPVARIANT pValue)
811 FIXME("stub\n");
812 return E_NOTIMPL;
815 static HRESULT WINAPI MimeBody_GetOption(
816 IMimeBody* iface,
817 const TYPEDID oid,
818 LPPROPVARIANT pValue)
820 FIXME("stub\n");
821 return E_NOTIMPL;
824 static HRESULT WINAPI MimeBody_EnumProps(
825 IMimeBody* iface,
826 DWORD dwFlags,
827 IMimeEnumProperties** ppEnum)
829 FIXME("stub\n");
830 return E_NOTIMPL;
833 static HRESULT WINAPI MimeBody_IsType(
834 IMimeBody* iface,
835 IMSGBODYTYPE bodytype)
837 FIXME("stub\n");
838 return E_NOTIMPL;
841 static HRESULT WINAPI MimeBody_SetDisplayName(
842 IMimeBody* iface,
843 LPCSTR pszDisplay)
845 FIXME("stub\n");
846 return E_NOTIMPL;
849 static HRESULT WINAPI MimeBody_GetDisplayName(
850 IMimeBody* iface,
851 LPSTR* ppszDisplay)
853 FIXME("stub\n");
854 return E_NOTIMPL;
857 static HRESULT WINAPI MimeBody_GetOffsets(
858 IMimeBody* iface,
859 LPBODYOFFSETS pOffsets)
861 MimeBody *This = impl_from_IMimeBody(iface);
862 TRACE("(%p)->(%p)\n", This, pOffsets);
864 *pOffsets = This->body_offsets;
866 if(This->body_offsets.cbBodyEnd == 0) return MIME_E_NO_DATA;
867 return S_OK;
870 static HRESULT WINAPI MimeBody_GetCurrentEncoding(
871 IMimeBody* iface,
872 ENCODINGTYPE* pietEncoding)
874 MimeBody *This = impl_from_IMimeBody(iface);
876 TRACE("(%p)->(%p)\n", This, pietEncoding);
878 *pietEncoding = This->encoding;
879 return S_OK;
882 static HRESULT WINAPI MimeBody_SetCurrentEncoding(
883 IMimeBody* iface,
884 ENCODINGTYPE ietEncoding)
886 MimeBody *This = impl_from_IMimeBody(iface);
888 TRACE("(%p)->(%d)\n", This, ietEncoding);
890 This->encoding = ietEncoding;
891 return S_OK;
894 static HRESULT WINAPI MimeBody_GetEstimatedSize(
895 IMimeBody* iface,
896 ENCODINGTYPE ietEncoding,
897 ULONG* pcbSize)
899 FIXME("stub\n");
900 return E_NOTIMPL;
903 static HRESULT WINAPI MimeBody_GetDataHere(
904 IMimeBody* iface,
905 ENCODINGTYPE ietEncoding,
906 IStream* pStream)
908 FIXME("stub\n");
909 return E_NOTIMPL;
912 static HRESULT WINAPI MimeBody_GetData(
913 IMimeBody* iface,
914 ENCODINGTYPE ietEncoding,
915 IStream** ppStream)
917 MimeBody *This = impl_from_IMimeBody(iface);
918 FIXME("(%p)->(%d, %p). Ignoring encoding type.\n", This, ietEncoding, ppStream);
920 *ppStream = This->data;
921 IStream_AddRef(*ppStream);
922 return S_OK;
925 static HRESULT WINAPI MimeBody_SetData(
926 IMimeBody* iface,
927 ENCODINGTYPE ietEncoding,
928 LPCSTR pszPriType,
929 LPCSTR pszSubType,
930 REFIID riid,
931 LPVOID pvObject)
933 MimeBody *This = impl_from_IMimeBody(iface);
934 TRACE("(%p)->(%d, %s, %s, %s %p)\n", This, ietEncoding, debugstr_a(pszPriType), debugstr_a(pszSubType),
935 debugstr_guid(riid), pvObject);
937 if(IsEqualIID(riid, &IID_IStream))
938 IStream_AddRef((IStream *)pvObject);
939 else
941 FIXME("Unhandled object type %s\n", debugstr_guid(riid));
942 return E_INVALIDARG;
945 if(This->data)
946 FIXME("release old data\n");
948 This->data_iid = *riid;
949 This->data = pvObject;
951 IMimeBody_SetCurrentEncoding(iface, ietEncoding);
953 /* FIXME: Update the content type.
954 If pszPriType == NULL use 'application'
955 If pszSubType == NULL use 'octet-stream' */
957 return S_OK;
960 static HRESULT WINAPI MimeBody_EmptyData(
961 IMimeBody* iface)
963 FIXME("stub\n");
964 return E_NOTIMPL;
967 static HRESULT WINAPI MimeBody_CopyTo(
968 IMimeBody* iface,
969 IMimeBody* pBody)
971 FIXME("stub\n");
972 return E_NOTIMPL;
975 static HRESULT WINAPI MimeBody_GetTransmitInfo(
976 IMimeBody* iface,
977 LPTRANSMITINFO pTransmitInfo)
979 FIXME("stub\n");
980 return E_NOTIMPL;
983 static HRESULT WINAPI MimeBody_SaveToFile(
984 IMimeBody* iface,
985 ENCODINGTYPE ietEncoding,
986 LPCSTR pszFilePath)
988 FIXME("stub\n");
989 return E_NOTIMPL;
992 static HRESULT WINAPI MimeBody_GetHandle(
993 IMimeBody* iface,
994 LPHBODY phBody)
996 MimeBody *This = impl_from_IMimeBody(iface);
997 TRACE("(%p)->(%p)\n", iface, phBody);
999 *phBody = This->handle;
1000 return This->handle ? S_OK : MIME_E_NO_DATA;
1003 static IMimeBodyVtbl body_vtbl =
1005 MimeBody_QueryInterface,
1006 MimeBody_AddRef,
1007 MimeBody_Release,
1008 MimeBody_GetClassID,
1009 MimeBody_IsDirty,
1010 MimeBody_Load,
1011 MimeBody_Save,
1012 MimeBody_GetSizeMax,
1013 MimeBody_InitNew,
1014 MimeBody_GetPropInfo,
1015 MimeBody_SetPropInfo,
1016 MimeBody_GetProp,
1017 MimeBody_SetProp,
1018 MimeBody_AppendProp,
1019 MimeBody_DeleteProp,
1020 MimeBody_CopyProps,
1021 MimeBody_MoveProps,
1022 MimeBody_DeleteExcept,
1023 MimeBody_QueryProp,
1024 MimeBody_GetCharset,
1025 MimeBody_SetCharset,
1026 MimeBody_GetParameters,
1027 MimeBody_IsContentType,
1028 MimeBody_BindToObject,
1029 MimeBody_Clone,
1030 MimeBody_SetOption,
1031 MimeBody_GetOption,
1032 MimeBody_EnumProps,
1033 MimeBody_IsType,
1034 MimeBody_SetDisplayName,
1035 MimeBody_GetDisplayName,
1036 MimeBody_GetOffsets,
1037 MimeBody_GetCurrentEncoding,
1038 MimeBody_SetCurrentEncoding,
1039 MimeBody_GetEstimatedSize,
1040 MimeBody_GetDataHere,
1041 MimeBody_GetData,
1042 MimeBody_SetData,
1043 MimeBody_EmptyData,
1044 MimeBody_CopyTo,
1045 MimeBody_GetTransmitInfo,
1046 MimeBody_SaveToFile,
1047 MimeBody_GetHandle
1050 static HRESULT MimeBody_set_offsets(MimeBody *body, const BODYOFFSETS *offsets)
1052 TRACE("setting offsets to %d, %d, %d, %d\n", offsets->cbBoundaryStart,
1053 offsets->cbHeaderStart, offsets->cbBodyStart, offsets->cbBodyEnd);
1055 body->body_offsets = *offsets;
1056 return S_OK;
1059 #define FIRST_CUSTOM_PROP_ID 0x100
1061 HRESULT MimeBody_create(IUnknown *outer, void **obj)
1063 MimeBody *This;
1064 BODYOFFSETS body_offsets;
1066 *obj = NULL;
1068 if(outer) return CLASS_E_NOAGGREGATION;
1070 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1071 if (!This) return E_OUTOFMEMORY;
1073 This->lpVtbl = &body_vtbl;
1074 This->refs = 1;
1075 This->handle = NULL;
1076 list_init(&This->headers);
1077 list_init(&This->new_props);
1078 This->next_prop_id = FIRST_CUSTOM_PROP_ID;
1079 This->content_pri_type = NULL;
1080 This->content_sub_type = NULL;
1081 This->encoding = IET_7BIT;
1082 This->data = NULL;
1083 This->data_iid = IID_NULL;
1085 body_offsets.cbBoundaryStart = body_offsets.cbHeaderStart = 0;
1086 body_offsets.cbBodyStart = body_offsets.cbBodyEnd = 0;
1087 MimeBody_set_offsets(This, &body_offsets);
1089 *obj = (IMimeBody *)&This->lpVtbl;
1090 return S_OK;
1093 typedef struct
1095 IStreamVtbl *lpVtbl;
1096 LONG refs;
1098 IStream *base;
1099 ULARGE_INTEGER pos, start, length;
1100 } sub_stream_t;
1102 static inline sub_stream_t *impl_from_IStream( IStream *iface )
1104 return (sub_stream_t *)((char*)iface - FIELD_OFFSET(sub_stream_t, lpVtbl));
1107 static HRESULT WINAPI sub_stream_QueryInterface(
1108 IStream* iface,
1109 REFIID riid,
1110 void **ppvObject)
1112 sub_stream_t *This = impl_from_IStream(iface);
1114 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
1115 *ppvObject = NULL;
1117 if(IsEqualIID(riid, &IID_IUnknown) ||
1118 IsEqualIID(riid, &IID_ISequentialStream) ||
1119 IsEqualIID(riid, &IID_IStream))
1121 IStream_AddRef(iface);
1122 *ppvObject = iface;
1123 return S_OK;
1125 return E_NOINTERFACE;
1128 static ULONG WINAPI sub_stream_AddRef(
1129 IStream* iface)
1131 sub_stream_t *This = impl_from_IStream(iface);
1133 TRACE("(%p)\n", This);
1134 return InterlockedIncrement(&This->refs);
1137 static ULONG WINAPI sub_stream_Release(
1138 IStream* iface)
1140 sub_stream_t *This = impl_from_IStream(iface);
1141 LONG refs;
1143 TRACE("(%p)\n", This);
1144 refs = InterlockedDecrement(&This->refs);
1145 if(!refs)
1147 IStream_Release(This->base);
1148 HeapFree(GetProcessHeap(), 0, This);
1150 return refs;
1153 static HRESULT WINAPI sub_stream_Read(
1154 IStream* iface,
1155 void *pv,
1156 ULONG cb,
1157 ULONG *pcbRead)
1159 sub_stream_t *This = impl_from_IStream(iface);
1160 HRESULT hr;
1161 ULARGE_INTEGER base_pos;
1162 LARGE_INTEGER tmp_pos;
1164 TRACE("(%p, %d, %p)\n", pv, cb, pcbRead);
1166 tmp_pos.QuadPart = 0;
1167 IStream_Seek(This->base, tmp_pos, STREAM_SEEK_CUR, &base_pos);
1168 tmp_pos.QuadPart = This->pos.QuadPart + This->start.QuadPart;
1169 IStream_Seek(This->base, tmp_pos, STREAM_SEEK_SET, NULL);
1171 if(This->pos.QuadPart + cb > This->length.QuadPart)
1172 cb = This->length.QuadPart - This->pos.QuadPart;
1174 hr = IStream_Read(This->base, pv, cb, pcbRead);
1176 This->pos.QuadPart += *pcbRead;
1178 tmp_pos.QuadPart = base_pos.QuadPart;
1179 IStream_Seek(This->base, tmp_pos, STREAM_SEEK_SET, NULL);
1181 return hr;
1184 static HRESULT WINAPI sub_stream_Write(
1185 IStream* iface,
1186 const void *pv,
1187 ULONG cb,
1188 ULONG *pcbWritten)
1190 FIXME("stub\n");
1191 return E_NOTIMPL;
1194 static HRESULT WINAPI sub_stream_Seek(
1195 IStream* iface,
1196 LARGE_INTEGER dlibMove,
1197 DWORD dwOrigin,
1198 ULARGE_INTEGER *plibNewPosition)
1200 sub_stream_t *This = impl_from_IStream(iface);
1201 LARGE_INTEGER new_pos;
1203 TRACE("(%08x.%08x, %x, %p)\n", dlibMove.u.HighPart, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
1205 switch(dwOrigin)
1207 case STREAM_SEEK_SET:
1208 new_pos = dlibMove;
1209 break;
1210 case STREAM_SEEK_CUR:
1211 new_pos.QuadPart = This->pos.QuadPart + dlibMove.QuadPart;
1212 break;
1213 case STREAM_SEEK_END:
1214 new_pos.QuadPart = This->length.QuadPart + dlibMove.QuadPart;
1215 break;
1218 if(new_pos.QuadPart < 0) new_pos.QuadPart = 0;
1219 else if(new_pos.QuadPart > This->length.QuadPart) new_pos.QuadPart = This->length.QuadPart;
1221 This->pos.QuadPart = new_pos.QuadPart;
1223 if(plibNewPosition) *plibNewPosition = This->pos;
1224 return S_OK;
1227 static HRESULT WINAPI sub_stream_SetSize(
1228 IStream* iface,
1229 ULARGE_INTEGER libNewSize)
1231 FIXME("stub\n");
1232 return E_NOTIMPL;
1235 static HRESULT WINAPI sub_stream_CopyTo(
1236 IStream* iface,
1237 IStream *pstm,
1238 ULARGE_INTEGER cb,
1239 ULARGE_INTEGER *pcbRead,
1240 ULARGE_INTEGER *pcbWritten)
1242 FIXME("stub\n");
1243 return E_NOTIMPL;
1246 static HRESULT WINAPI sub_stream_Commit(
1247 IStream* iface,
1248 DWORD grfCommitFlags)
1250 FIXME("stub\n");
1251 return E_NOTIMPL;
1254 static HRESULT WINAPI sub_stream_Revert(
1255 IStream* iface)
1257 FIXME("stub\n");
1258 return E_NOTIMPL;
1261 static HRESULT WINAPI sub_stream_LockRegion(
1262 IStream* iface,
1263 ULARGE_INTEGER libOffset,
1264 ULARGE_INTEGER cb,
1265 DWORD dwLockType)
1267 FIXME("stub\n");
1268 return E_NOTIMPL;
1271 static HRESULT WINAPI sub_stream_UnlockRegion(
1272 IStream* iface,
1273 ULARGE_INTEGER libOffset,
1274 ULARGE_INTEGER cb,
1275 DWORD dwLockType)
1277 FIXME("stub\n");
1278 return E_NOTIMPL;
1281 static HRESULT WINAPI sub_stream_Stat(
1282 IStream* iface,
1283 STATSTG *pstatstg,
1284 DWORD grfStatFlag)
1286 sub_stream_t *This = impl_from_IStream(iface);
1287 FIXME("(%p)->(%p, %08x)\n", This, pstatstg, grfStatFlag);
1288 memset(pstatstg, 0, sizeof(*pstatstg));
1289 pstatstg->cbSize = This->length;
1290 return S_OK;
1293 static HRESULT WINAPI sub_stream_Clone(
1294 IStream* iface,
1295 IStream **ppstm)
1297 FIXME("stub\n");
1298 return E_NOTIMPL;
1301 static struct IStreamVtbl sub_stream_vtbl =
1303 sub_stream_QueryInterface,
1304 sub_stream_AddRef,
1305 sub_stream_Release,
1306 sub_stream_Read,
1307 sub_stream_Write,
1308 sub_stream_Seek,
1309 sub_stream_SetSize,
1310 sub_stream_CopyTo,
1311 sub_stream_Commit,
1312 sub_stream_Revert,
1313 sub_stream_LockRegion,
1314 sub_stream_UnlockRegion,
1315 sub_stream_Stat,
1316 sub_stream_Clone
1319 static HRESULT create_sub_stream(IStream *stream, ULARGE_INTEGER start, ULARGE_INTEGER length, IStream **out)
1321 sub_stream_t *This;
1323 *out = NULL;
1324 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1325 if(!This) return E_OUTOFMEMORY;
1327 This->lpVtbl = &sub_stream_vtbl;
1328 This->refs = 1;
1329 This->start = start;
1330 This->length = length;
1331 This->pos.QuadPart = 0;
1332 IStream_AddRef(stream);
1333 This->base = stream;
1335 *out = (IStream*)&This->lpVtbl;
1336 return S_OK;
1340 typedef struct body_t
1342 struct list entry;
1343 HBODY hbody;
1344 IMimeBody *mime_body;
1346 struct body_t *parent;
1347 struct list children;
1348 } body_t;
1350 typedef struct MimeMessage
1352 const IMimeMessageVtbl *lpVtbl;
1354 LONG refs;
1355 IStream *stream;
1357 struct list body_tree;
1358 HBODY next_hbody;
1359 } MimeMessage;
1361 static HRESULT WINAPI MimeMessage_QueryInterface(IMimeMessage *iface, REFIID riid, void **ppv)
1363 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
1365 if (IsEqualIID(riid, &IID_IUnknown) ||
1366 IsEqualIID(riid, &IID_IPersist) ||
1367 IsEqualIID(riid, &IID_IPersistStreamInit) ||
1368 IsEqualIID(riid, &IID_IMimeMessageTree) ||
1369 IsEqualIID(riid, &IID_IMimeMessage))
1371 *ppv = iface;
1372 IUnknown_AddRef(iface);
1373 return S_OK;
1376 FIXME("no interface for %s\n", debugstr_guid(riid));
1377 *ppv = NULL;
1378 return E_NOINTERFACE;
1381 static ULONG WINAPI MimeMessage_AddRef(IMimeMessage *iface)
1383 MimeMessage *This = (MimeMessage *)iface;
1384 TRACE("(%p)->()\n", iface);
1385 return InterlockedIncrement(&This->refs);
1388 static void empty_body_list(struct list *list)
1390 body_t *body, *cursor2;
1391 LIST_FOR_EACH_ENTRY_SAFE(body, cursor2, list, body_t, entry)
1393 empty_body_list(&body->children);
1394 list_remove(&body->entry);
1395 IMimeBody_Release(body->mime_body);
1396 HeapFree(GetProcessHeap(), 0, body);
1400 static ULONG WINAPI MimeMessage_Release(IMimeMessage *iface)
1402 MimeMessage *This = (MimeMessage *)iface;
1403 ULONG refs;
1405 TRACE("(%p)->()\n", iface);
1407 refs = InterlockedDecrement(&This->refs);
1408 if (!refs)
1410 empty_body_list(&This->body_tree);
1412 if(This->stream) IStream_Release(This->stream);
1413 HeapFree(GetProcessHeap(), 0, This);
1416 return refs;
1419 /*** IPersist methods ***/
1420 static HRESULT WINAPI MimeMessage_GetClassID(
1421 IMimeMessage *iface,
1422 CLSID *pClassID)
1424 FIXME("(%p)->(%p)\n", iface, pClassID);
1425 return E_NOTIMPL;
1428 /*** IPersistStreamInit methods ***/
1429 static HRESULT WINAPI MimeMessage_IsDirty(
1430 IMimeMessage *iface)
1432 FIXME("(%p)->()\n", iface);
1433 return E_NOTIMPL;
1436 static body_t *new_body_entry(IMimeBody *mime_body, HBODY hbody, body_t *parent)
1438 body_t *body = HeapAlloc(GetProcessHeap(), 0, sizeof(*body));
1439 if(body)
1441 body->mime_body = mime_body;
1442 body->hbody = hbody;
1443 list_init(&body->children);
1444 body->parent = parent;
1446 return body;
1449 typedef struct
1451 struct list entry;
1452 BODYOFFSETS offsets;
1453 } offset_entry_t;
1455 static HRESULT create_body_offset_list(IStream *stm, const char *boundary, struct list *body_offsets)
1457 HRESULT hr;
1458 DWORD read;
1459 int boundary_len = strlen(boundary);
1460 char *buf, *nl_boundary, *ptr, *overlap;
1461 DWORD total_read = 0;
1462 DWORD start = 0, overlap_no;
1463 offset_entry_t *cur_body = NULL;
1464 ULARGE_INTEGER cur;
1465 LARGE_INTEGER zero;
1467 list_init(body_offsets);
1468 nl_boundary = HeapAlloc(GetProcessHeap(), 0, 4 + boundary_len + 1);
1469 memcpy(nl_boundary, "\r\n--", 4);
1470 memcpy(nl_boundary + 4, boundary, boundary_len + 1);
1472 overlap_no = boundary_len + 5;
1474 overlap = buf = HeapAlloc(GetProcessHeap(), 0, overlap_no + PARSER_BUF_SIZE + 1);
1476 zero.QuadPart = 0;
1477 hr = IStream_Seek(stm, zero, STREAM_SEEK_CUR, &cur);
1478 start = cur.LowPart;
1480 do {
1481 hr = IStream_Read(stm, overlap, PARSER_BUF_SIZE, &read);
1482 if(FAILED(hr)) goto end;
1483 if(read == 0) break;
1484 total_read += read;
1485 overlap[read] = '\0';
1487 ptr = buf;
1488 do {
1489 ptr = strstr(ptr, nl_boundary);
1490 if(ptr)
1492 DWORD boundary_start = start + ptr - buf;
1493 char *end = ptr + boundary_len + 4;
1495 if(*end == '\0' || *(end + 1) == '\0')
1496 break;
1498 if(*end == '\r' && *(end + 1) == '\n')
1500 if(cur_body)
1502 cur_body->offsets.cbBodyEnd = boundary_start;
1503 list_add_tail(body_offsets, &cur_body->entry);
1505 cur_body = HeapAlloc(GetProcessHeap(), 0, sizeof(*cur_body));
1506 cur_body->offsets.cbBoundaryStart = boundary_start + 2; /* doesn't including the leading \r\n */
1507 cur_body->offsets.cbHeaderStart = boundary_start + boundary_len + 6;
1509 else if(*end == '-' && *(end + 1) == '-')
1511 if(cur_body)
1513 cur_body->offsets.cbBodyEnd = boundary_start;
1514 list_add_tail(body_offsets, &cur_body->entry);
1515 goto end;
1518 ptr = end + 2;
1520 } while(ptr);
1522 if(overlap == buf) /* 1st iteration */
1524 memcpy(buf, buf + PARSER_BUF_SIZE - overlap_no, overlap_no);
1525 overlap = buf + overlap_no;
1526 start += read - overlap_no;
1528 else
1530 memcpy(buf, buf + PARSER_BUF_SIZE, overlap_no);
1531 start += read;
1533 } while(1);
1535 end:
1536 HeapFree(GetProcessHeap(), 0, buf);
1537 return hr;
1540 static body_t *create_sub_body(MimeMessage *msg, IStream *pStm, BODYOFFSETS *offset, body_t *parent)
1542 IMimeBody *mime_body;
1543 HRESULT hr;
1544 body_t *body;
1545 ULARGE_INTEGER cur;
1546 LARGE_INTEGER zero;
1548 MimeBody_create(NULL, (void**)&mime_body);
1549 IMimeBody_Load(mime_body, pStm);
1550 zero.QuadPart = 0;
1551 hr = IStream_Seek(pStm, zero, STREAM_SEEK_CUR, &cur);
1552 offset->cbBodyStart = cur.LowPart + offset->cbHeaderStart;
1553 if(parent) MimeBody_set_offsets(impl_from_IMimeBody(mime_body), offset);
1554 IMimeBody_SetData(mime_body, IET_BINARY, NULL, NULL, &IID_IStream, pStm);
1555 body = new_body_entry(mime_body, msg->next_hbody, parent);
1556 msg->next_hbody = (HBODY)((DWORD)msg->next_hbody + 1);
1558 if(IMimeBody_IsContentType(mime_body, "multipart", NULL) == S_OK)
1560 MIMEPARAMINFO *param_info;
1561 ULONG count, i;
1562 IMimeAllocator *alloc;
1564 hr = IMimeBody_GetParameters(mime_body, "Content-Type", &count, &param_info);
1565 if(hr != S_OK || count == 0) return body;
1567 MimeOleGetAllocator(&alloc);
1569 for(i = 0; i < count; i++)
1571 if(!strcasecmp(param_info[i].pszName, "boundary"))
1573 struct list offset_list;
1574 offset_entry_t *cur, *cursor2;
1575 hr = create_body_offset_list(pStm, param_info[i].pszData, &offset_list);
1576 LIST_FOR_EACH_ENTRY_SAFE(cur, cursor2, &offset_list, offset_entry_t, entry)
1578 body_t *sub_body;
1579 IStream *sub_stream;
1580 ULARGE_INTEGER start, length;
1582 start.LowPart = cur->offsets.cbHeaderStart;
1583 length.LowPart = cur->offsets.cbBodyEnd - cur->offsets.cbHeaderStart;
1584 create_sub_stream(pStm, start, length, &sub_stream);
1585 sub_body = create_sub_body(msg, sub_stream, &cur->offsets, body);
1586 IStream_Release(sub_stream);
1587 list_add_tail(&body->children, &sub_body->entry);
1588 list_remove(&cur->entry);
1589 HeapFree(GetProcessHeap(), 0, cur);
1591 break;
1594 IMimeAllocator_FreeParamInfoArray(alloc, count, param_info, TRUE);
1595 IMimeAllocator_Release(alloc);
1597 return body;
1600 static HRESULT WINAPI MimeMessage_Load(
1601 IMimeMessage *iface,
1602 LPSTREAM pStm)
1604 MimeMessage *This = (MimeMessage *)iface;
1605 body_t *root_body;
1606 BODYOFFSETS offsets;
1607 ULARGE_INTEGER cur;
1608 LARGE_INTEGER zero;
1610 TRACE("(%p)->(%p)\n", iface, pStm);
1612 if(This->stream)
1614 FIXME("already loaded a message\n");
1615 return E_FAIL;
1618 IStream_AddRef(pStm);
1619 This->stream = pStm;
1620 offsets.cbBoundaryStart = offsets.cbHeaderStart = 0;
1621 offsets.cbBodyStart = offsets.cbBodyEnd = 0;
1623 root_body = create_sub_body(This, pStm, &offsets, NULL);
1625 zero.QuadPart = 0;
1626 IStream_Seek(pStm, zero, STREAM_SEEK_END, &cur);
1627 offsets.cbBodyEnd = cur.LowPart;
1628 MimeBody_set_offsets(impl_from_IMimeBody(root_body->mime_body), &offsets);
1630 list_add_head(&This->body_tree, &root_body->entry);
1632 return S_OK;
1635 static HRESULT WINAPI MimeMessage_Save(
1636 IMimeMessage *iface,
1637 LPSTREAM pStm,
1638 BOOL fClearDirty)
1640 FIXME("(%p)->(%p, %s)\n", iface, pStm, fClearDirty ? "TRUE" : "FALSE");
1641 return E_NOTIMPL;
1644 static HRESULT WINAPI MimeMessage_GetSizeMax(
1645 IMimeMessage *iface,
1646 ULARGE_INTEGER *pcbSize)
1648 FIXME("(%p)->(%p)\n", iface, pcbSize);
1649 return E_NOTIMPL;
1652 static HRESULT WINAPI MimeMessage_InitNew(
1653 IMimeMessage *iface)
1655 FIXME("(%p)->()\n", iface);
1656 return E_NOTIMPL;
1659 /*** IMimeMessageTree methods ***/
1660 static HRESULT WINAPI MimeMessage_GetMessageSource(
1661 IMimeMessage *iface,
1662 IStream **ppStream,
1663 DWORD dwFlags)
1665 FIXME("(%p)->(%p, 0x%x)\n", iface, ppStream, dwFlags);
1666 return E_NOTIMPL;
1669 static HRESULT WINAPI MimeMessage_GetMessageSize(
1670 IMimeMessage *iface,
1671 ULONG *pcbSize,
1672 DWORD dwFlags)
1674 FIXME("(%p)->(%p, 0x%x)\n", iface, pcbSize, dwFlags);
1675 return E_NOTIMPL;
1678 static HRESULT WINAPI MimeMessage_LoadOffsetTable(
1679 IMimeMessage *iface,
1680 IStream *pStream)
1682 FIXME("(%p)->(%p)\n", iface, pStream);
1683 return E_NOTIMPL;
1686 static HRESULT WINAPI MimeMessage_SaveOffsetTable(
1687 IMimeMessage *iface,
1688 IStream *pStream,
1689 DWORD dwFlags)
1691 FIXME("(%p)->(%p, 0x%x)\n", iface, pStream, dwFlags);
1692 return E_NOTIMPL;
1696 static HRESULT WINAPI MimeMessage_GetFlags(
1697 IMimeMessage *iface,
1698 DWORD *pdwFlags)
1700 FIXME("(%p)->(%p)\n", iface, pdwFlags);
1701 return E_NOTIMPL;
1704 static HRESULT WINAPI MimeMessage_Commit(
1705 IMimeMessage *iface,
1706 DWORD dwFlags)
1708 FIXME("(%p)->(0x%x)\n", iface, dwFlags);
1709 return E_NOTIMPL;
1713 static HRESULT WINAPI MimeMessage_HandsOffStorage(
1714 IMimeMessage *iface)
1716 FIXME("(%p)->()\n", iface);
1717 return E_NOTIMPL;
1720 static HRESULT find_body(struct list *list, HBODY hbody, body_t **body)
1722 body_t *cur;
1723 HRESULT hr;
1725 if(hbody == HBODY_ROOT)
1727 *body = LIST_ENTRY(list_head(list), body_t, entry);
1728 return S_OK;
1731 LIST_FOR_EACH_ENTRY(cur, list, body_t, entry)
1733 if(cur->hbody == hbody)
1735 *body = cur;
1736 return S_OK;
1738 hr = find_body(&cur->children, hbody, body);
1739 if(hr == S_OK) return S_OK;
1741 return S_FALSE;
1744 static HRESULT WINAPI MimeMessage_BindToObject(
1745 IMimeMessage *iface,
1746 const HBODY hBody,
1747 REFIID riid,
1748 void **ppvObject)
1750 MimeMessage *This = (MimeMessage *)iface;
1751 HRESULT hr;
1752 body_t *body;
1754 TRACE("(%p)->(%p, %s, %p)\n", iface, hBody, debugstr_guid(riid), ppvObject);
1756 hr = find_body(&This->body_tree, hBody, &body);
1758 if(hr != S_OK) return hr;
1760 if(IsEqualIID(riid, &IID_IMimeBody))
1762 IMimeBody_AddRef(body->mime_body);
1763 *ppvObject = body->mime_body;
1764 return S_OK;
1767 return E_NOINTERFACE;
1770 static HRESULT WINAPI MimeMessage_SaveBody(
1771 IMimeMessage *iface,
1772 HBODY hBody,
1773 DWORD dwFlags,
1774 IStream *pStream)
1776 FIXME("(%p)->(%p, 0x%x, %p)\n", iface, hBody, dwFlags, pStream);
1777 return E_NOTIMPL;
1780 static HRESULT get_body(MimeMessage *msg, BODYLOCATION location, HBODY pivot, body_t **out)
1782 body_t *root = LIST_ENTRY(list_head(&msg->body_tree), body_t, entry);
1783 body_t *body;
1784 HRESULT hr;
1785 struct list *list;
1787 if(location == IBL_ROOT)
1789 *out = root;
1790 return S_OK;
1793 hr = find_body(&msg->body_tree, pivot, &body);
1795 if(hr == S_OK)
1797 switch(location)
1799 case IBL_PARENT:
1800 *out = body->parent;
1801 break;
1803 case IBL_FIRST:
1804 list = list_head(&body->children);
1805 if(list)
1806 *out = LIST_ENTRY(list, body_t, entry);
1807 else
1808 hr = MIME_E_NOT_FOUND;
1809 break;
1811 case IBL_LAST:
1812 list = list_tail(&body->children);
1813 if(list)
1814 *out = LIST_ENTRY(list, body_t, entry);
1815 else
1816 hr = MIME_E_NOT_FOUND;
1817 break;
1819 case IBL_NEXT:
1820 list = list_next(&body->parent->children, &body->entry);
1821 if(list)
1822 *out = LIST_ENTRY(list, body_t, entry);
1823 else
1824 hr = MIME_E_NOT_FOUND;
1825 break;
1827 case IBL_PREVIOUS:
1828 list = list_prev(&body->parent->children, &body->entry);
1829 if(list)
1830 *out = LIST_ENTRY(list, body_t, entry);
1831 else
1832 hr = MIME_E_NOT_FOUND;
1833 break;
1835 default:
1836 hr = E_FAIL;
1837 break;
1841 return hr;
1845 static HRESULT WINAPI MimeMessage_InsertBody(
1846 IMimeMessage *iface,
1847 BODYLOCATION location,
1848 HBODY hPivot,
1849 LPHBODY phBody)
1851 FIXME("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody);
1852 return E_NOTIMPL;
1855 static HRESULT WINAPI MimeMessage_GetBody(
1856 IMimeMessage *iface,
1857 BODYLOCATION location,
1858 HBODY hPivot,
1859 LPHBODY phBody)
1861 MimeMessage *This = (MimeMessage *)iface;
1862 body_t *body;
1863 HRESULT hr;
1865 TRACE("(%p)->(%d, %p, %p)\n", iface, location, hPivot, phBody);
1867 hr = get_body(This, location, hPivot, &body);
1869 if(hr == S_OK) *phBody = body->hbody;
1871 return hr;
1874 static HRESULT WINAPI MimeMessage_DeleteBody(
1875 IMimeMessage *iface,
1876 HBODY hBody,
1877 DWORD dwFlags)
1879 FIXME("(%p)->(%p, %08x)\n", iface, hBody, dwFlags);
1880 return E_NOTIMPL;
1883 static HRESULT WINAPI MimeMessage_MoveBody(
1884 IMimeMessage *iface,
1885 HBODY hBody,
1886 BODYLOCATION location)
1888 FIXME("(%p)->(%d)\n", iface, location);
1889 return E_NOTIMPL;
1892 static void count_children(body_t *body, boolean recurse, ULONG *count)
1894 body_t *child;
1896 LIST_FOR_EACH_ENTRY(child, &body->children, body_t, entry)
1898 (*count)++;
1899 if(recurse) count_children(child, recurse, count);
1903 static HRESULT WINAPI MimeMessage_CountBodies(
1904 IMimeMessage *iface,
1905 HBODY hParent,
1906 boolean fRecurse,
1907 ULONG *pcBodies)
1909 HRESULT hr;
1910 MimeMessage *This = (MimeMessage *)iface;
1911 body_t *body;
1913 TRACE("(%p)->(%p, %s, %p)\n", iface, hParent, fRecurse ? "TRUE" : "FALSE", pcBodies);
1915 hr = find_body(&This->body_tree, hParent, &body);
1916 if(hr != S_OK) return hr;
1918 *pcBodies = 1;
1919 count_children(body, fRecurse, pcBodies);
1921 return S_OK;
1924 static HRESULT WINAPI MimeMessage_FindFirst(
1925 IMimeMessage *iface,
1926 LPFINDBODY pFindBody,
1927 LPHBODY phBody)
1929 FIXME("(%p)->(%p, %p)\n", iface, pFindBody, phBody);
1930 return E_NOTIMPL;
1933 static HRESULT WINAPI MimeMessage_FindNext(
1934 IMimeMessage *iface,
1935 LPFINDBODY pFindBody,
1936 LPHBODY phBody)
1938 FIXME("(%p)->(%p, %p)\n", iface, pFindBody, phBody);
1939 return E_NOTIMPL;
1942 static HRESULT WINAPI MimeMessage_ResolveURL(
1943 IMimeMessage *iface,
1944 HBODY hRelated,
1945 LPCSTR pszBase,
1946 LPCSTR pszURL,
1947 DWORD dwFlags,
1948 LPHBODY phBody)
1950 FIXME("(%p)->(%p, %s, %s, 0x%x, %p)\n", iface, hRelated, pszBase, pszURL, dwFlags, phBody);
1951 return E_NOTIMPL;
1954 static HRESULT WINAPI MimeMessage_ToMultipart(
1955 IMimeMessage *iface,
1956 HBODY hBody,
1957 LPCSTR pszSubType,
1958 LPHBODY phMultipart)
1960 FIXME("(%p)->(%p, %s, %p)\n", iface, hBody, pszSubType, phMultipart);
1961 return E_NOTIMPL;
1964 static HRESULT WINAPI MimeMessage_GetBodyOffsets(
1965 IMimeMessage *iface,
1966 HBODY hBody,
1967 LPBODYOFFSETS pOffsets)
1969 FIXME("(%p)->(%p, %p)\n", iface, hBody, pOffsets);
1970 return E_NOTIMPL;
1973 static HRESULT WINAPI MimeMessage_GetCharset(
1974 IMimeMessage *iface,
1975 LPHCHARSET phCharset)
1977 FIXME("(%p)->(%p)\n", iface, phCharset);
1978 return E_NOTIMPL;
1981 static HRESULT WINAPI MimeMessage_SetCharset(
1982 IMimeMessage *iface,
1983 HCHARSET hCharset,
1984 CSETAPPLYTYPE applytype)
1986 FIXME("(%p)->(%p, %d)\n", iface, hCharset, applytype);
1987 return E_NOTIMPL;
1990 static HRESULT WINAPI MimeMessage_IsBodyType(
1991 IMimeMessage *iface,
1992 HBODY hBody,
1993 IMSGBODYTYPE bodytype)
1995 FIXME("(%p)->(%p, %d)\n", iface, hBody, bodytype);
1996 return E_NOTIMPL;
1999 static HRESULT WINAPI MimeMessage_IsContentType(
2000 IMimeMessage *iface,
2001 HBODY hBody,
2002 LPCSTR pszPriType,
2003 LPCSTR pszSubType)
2005 FIXME("(%p)->(%p, %s, %s)\n", iface, hBody, pszPriType, pszSubType);
2006 return E_NOTIMPL;
2009 static HRESULT WINAPI MimeMessage_QueryBodyProp(
2010 IMimeMessage *iface,
2011 HBODY hBody,
2012 LPCSTR pszName,
2013 LPCSTR pszCriteria,
2014 boolean fSubString,
2015 boolean fCaseSensitive)
2017 FIXME("(%p)->(%p, %s, %s, %s, %s)\n", iface, hBody, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE");
2018 return E_NOTIMPL;
2021 static HRESULT WINAPI MimeMessage_GetBodyProp(
2022 IMimeMessage *iface,
2023 HBODY hBody,
2024 LPCSTR pszName,
2025 DWORD dwFlags,
2026 LPPROPVARIANT pValue)
2028 FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue);
2029 return E_NOTIMPL;
2032 static HRESULT WINAPI MimeMessage_SetBodyProp(
2033 IMimeMessage *iface,
2034 HBODY hBody,
2035 LPCSTR pszName,
2036 DWORD dwFlags,
2037 LPCPROPVARIANT pValue)
2039 FIXME("(%p)->(%p, %s, 0x%x, %p)\n", iface, hBody, pszName, dwFlags, pValue);
2040 return E_NOTIMPL;
2043 static HRESULT WINAPI MimeMessage_DeleteBodyProp(
2044 IMimeMessage *iface,
2045 HBODY hBody,
2046 LPCSTR pszName)
2048 FIXME("(%p)->(%p, %s)\n", iface, hBody, pszName);
2049 return E_NOTIMPL;
2052 static HRESULT WINAPI MimeMessage_SetOption(
2053 IMimeMessage *iface,
2054 const TYPEDID oid,
2055 LPCPROPVARIANT pValue)
2057 FIXME("(%p)->(%d, %p)\n", iface, oid, pValue);
2058 return E_NOTIMPL;
2061 static HRESULT WINAPI MimeMessage_GetOption(
2062 IMimeMessage *iface,
2063 const TYPEDID oid,
2064 LPPROPVARIANT pValue)
2066 FIXME("(%p)->(%d, %p)\n", iface, oid, pValue);
2067 return E_NOTIMPL;
2070 /*** IMimeMessage methods ***/
2071 static HRESULT WINAPI MimeMessage_CreateWebPage(
2072 IMimeMessage *iface,
2073 IStream *pRootStm,
2074 LPWEBPAGEOPTIONS pOptions,
2075 IMimeMessageCallback *pCallback,
2076 IMoniker **ppMoniker)
2078 FIXME("(%p)->(%p, %p, %p, %p)\n", iface, pRootStm, pOptions, pCallback, ppMoniker);
2079 *ppMoniker = NULL;
2080 return E_NOTIMPL;
2083 static HRESULT WINAPI MimeMessage_GetProp(
2084 IMimeMessage *iface,
2085 LPCSTR pszName,
2086 DWORD dwFlags,
2087 LPPROPVARIANT pValue)
2089 FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue);
2090 return E_NOTIMPL;
2093 static HRESULT WINAPI MimeMessage_SetProp(
2094 IMimeMessage *iface,
2095 LPCSTR pszName,
2096 DWORD dwFlags,
2097 LPCPROPVARIANT pValue)
2099 FIXME("(%p)->(%s, 0x%x, %p)\n", iface, pszName, dwFlags, pValue);
2100 return E_NOTIMPL;
2103 static HRESULT WINAPI MimeMessage_DeleteProp(
2104 IMimeMessage *iface,
2105 LPCSTR pszName)
2107 FIXME("(%p)->(%s)\n", iface, pszName);
2108 return E_NOTIMPL;
2111 static HRESULT WINAPI MimeMessage_QueryProp(
2112 IMimeMessage *iface,
2113 LPCSTR pszName,
2114 LPCSTR pszCriteria,
2115 boolean fSubString,
2116 boolean fCaseSensitive)
2118 FIXME("(%p)->(%s, %s, %s, %s)\n", iface, pszName, pszCriteria, fSubString ? "TRUE" : "FALSE", fCaseSensitive ? "TRUE" : "FALSE");
2119 return E_NOTIMPL;
2122 static HRESULT WINAPI MimeMessage_GetTextBody(
2123 IMimeMessage *iface,
2124 DWORD dwTxtType,
2125 ENCODINGTYPE ietEncoding,
2126 IStream **pStream,
2127 LPHBODY phBody)
2129 FIXME("(%p)->(%d, %d, %p, %p)\n", iface, dwTxtType, ietEncoding, pStream, phBody);
2130 return E_NOTIMPL;
2133 static HRESULT WINAPI MimeMessage_SetTextBody(
2134 IMimeMessage *iface,
2135 DWORD dwTxtType,
2136 ENCODINGTYPE ietEncoding,
2137 HBODY hAlternative,
2138 IStream *pStream,
2139 LPHBODY phBody)
2141 FIXME("(%p)->(%d, %d, %p, %p, %p)\n", iface, dwTxtType, ietEncoding, hAlternative, pStream, phBody);
2142 return E_NOTIMPL;
2145 static HRESULT WINAPI MimeMessage_AttachObject(
2146 IMimeMessage *iface,
2147 REFIID riid,
2148 void *pvObject,
2149 LPHBODY phBody)
2151 FIXME("(%p)->(%s, %p, %p)\n", iface, debugstr_guid(riid), pvObject, phBody);
2152 return E_NOTIMPL;
2155 static HRESULT WINAPI MimeMessage_AttachFile(
2156 IMimeMessage *iface,
2157 LPCSTR pszFilePath,
2158 IStream *pstmFile,
2159 LPHBODY phBody)
2161 FIXME("(%p)->(%s, %p, %p)\n", iface, pszFilePath, pstmFile, phBody);
2162 return E_NOTIMPL;
2165 static HRESULT WINAPI MimeMessage_AttachURL(
2166 IMimeMessage *iface,
2167 LPCSTR pszBase,
2168 LPCSTR pszURL,
2169 DWORD dwFlags,
2170 IStream *pstmURL,
2171 LPSTR *ppszCIDURL,
2172 LPHBODY phBody)
2174 FIXME("(%p)->(%s, %s, 0x%x, %p, %p, %p)\n", iface, pszBase, pszURL, dwFlags, pstmURL, ppszCIDURL, phBody);
2175 return E_NOTIMPL;
2178 static HRESULT WINAPI MimeMessage_GetAttachments(
2179 IMimeMessage *iface,
2180 ULONG *pcAttach,
2181 LPHBODY *pprghAttach)
2183 FIXME("(%p)->(%p, %p)\n", iface, pcAttach, pprghAttach);
2184 return E_NOTIMPL;
2187 static HRESULT WINAPI MimeMessage_GetAddressTable(
2188 IMimeMessage *iface,
2189 IMimeAddressTable **ppTable)
2191 FIXME("(%p)->(%p)\n", iface, ppTable);
2192 return E_NOTIMPL;
2195 static HRESULT WINAPI MimeMessage_GetSender(
2196 IMimeMessage *iface,
2197 LPADDRESSPROPS pAddress)
2199 FIXME("(%p)->(%p)\n", iface, pAddress);
2200 return E_NOTIMPL;
2203 static HRESULT WINAPI MimeMessage_GetAddressTypes(
2204 IMimeMessage *iface,
2205 DWORD dwAdrTypes,
2206 DWORD dwProps,
2207 LPADDRESSLIST pList)
2209 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, pList);
2210 return E_NOTIMPL;
2213 static HRESULT WINAPI MimeMessage_GetAddressFormat(
2214 IMimeMessage *iface,
2215 DWORD dwAdrTypes,
2216 ADDRESSFORMAT format,
2217 LPSTR *ppszFormat)
2219 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, format, ppszFormat);
2220 return E_NOTIMPL;
2223 static HRESULT WINAPI MimeMessage_EnumAddressTypes(
2224 IMimeMessage *iface,
2225 DWORD dwAdrTypes,
2226 DWORD dwProps,
2227 IMimeEnumAddressTypes **ppEnum)
2229 FIXME("(%p)->(%d, %d, %p)\n", iface, dwAdrTypes, dwProps, ppEnum);
2230 return E_NOTIMPL;
2233 static HRESULT WINAPI MimeMessage_SplitMessage(
2234 IMimeMessage *iface,
2235 ULONG cbMaxPart,
2236 IMimeMessageParts **ppParts)
2238 FIXME("(%p)->(%d, %p)\n", iface, cbMaxPart, ppParts);
2239 return E_NOTIMPL;
2242 static HRESULT WINAPI MimeMessage_GetRootMoniker(
2243 IMimeMessage *iface,
2244 IMoniker **ppMoniker)
2246 FIXME("(%p)->(%p)\n", iface, ppMoniker);
2247 return E_NOTIMPL;
2250 static const IMimeMessageVtbl MimeMessageVtbl =
2252 MimeMessage_QueryInterface,
2253 MimeMessage_AddRef,
2254 MimeMessage_Release,
2255 MimeMessage_GetClassID,
2256 MimeMessage_IsDirty,
2257 MimeMessage_Load,
2258 MimeMessage_Save,
2259 MimeMessage_GetSizeMax,
2260 MimeMessage_InitNew,
2261 MimeMessage_GetMessageSource,
2262 MimeMessage_GetMessageSize,
2263 MimeMessage_LoadOffsetTable,
2264 MimeMessage_SaveOffsetTable,
2265 MimeMessage_GetFlags,
2266 MimeMessage_Commit,
2267 MimeMessage_HandsOffStorage,
2268 MimeMessage_BindToObject,
2269 MimeMessage_SaveBody,
2270 MimeMessage_InsertBody,
2271 MimeMessage_GetBody,
2272 MimeMessage_DeleteBody,
2273 MimeMessage_MoveBody,
2274 MimeMessage_CountBodies,
2275 MimeMessage_FindFirst,
2276 MimeMessage_FindNext,
2277 MimeMessage_ResolveURL,
2278 MimeMessage_ToMultipart,
2279 MimeMessage_GetBodyOffsets,
2280 MimeMessage_GetCharset,
2281 MimeMessage_SetCharset,
2282 MimeMessage_IsBodyType,
2283 MimeMessage_IsContentType,
2284 MimeMessage_QueryBodyProp,
2285 MimeMessage_GetBodyProp,
2286 MimeMessage_SetBodyProp,
2287 MimeMessage_DeleteBodyProp,
2288 MimeMessage_SetOption,
2289 MimeMessage_GetOption,
2290 MimeMessage_CreateWebPage,
2291 MimeMessage_GetProp,
2292 MimeMessage_SetProp,
2293 MimeMessage_DeleteProp,
2294 MimeMessage_QueryProp,
2295 MimeMessage_GetTextBody,
2296 MimeMessage_SetTextBody,
2297 MimeMessage_AttachObject,
2298 MimeMessage_AttachFile,
2299 MimeMessage_AttachURL,
2300 MimeMessage_GetAttachments,
2301 MimeMessage_GetAddressTable,
2302 MimeMessage_GetSender,
2303 MimeMessage_GetAddressTypes,
2304 MimeMessage_GetAddressFormat,
2305 MimeMessage_EnumAddressTypes,
2306 MimeMessage_SplitMessage,
2307 MimeMessage_GetRootMoniker,
2310 /***********************************************************************
2311 * MimeOleCreateMessage (INETCOMM.@)
2313 HRESULT WINAPI MimeOleCreateMessage(IUnknown *pUnkOuter, IMimeMessage **ppMessage)
2315 MimeMessage *This;
2317 TRACE("(%p, %p)\n", pUnkOuter, ppMessage);
2319 if (pUnkOuter)
2321 FIXME("outer unknown not supported yet\n");
2322 return E_NOTIMPL;
2325 *ppMessage = NULL;
2327 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2328 if (!This) return E_OUTOFMEMORY;
2330 This->lpVtbl = &MimeMessageVtbl;
2331 This->refs = 1;
2332 This->stream = NULL;
2333 list_init(&This->body_tree);
2334 This->next_hbody = (HBODY)1;
2336 *ppMessage = (IMimeMessage *)&This->lpVtbl;
2337 return S_OK;
2340 /***********************************************************************
2341 * MimeOleSetCompatMode (INETCOMM.@)
2343 HRESULT WINAPI MimeOleSetCompatMode(DWORD dwMode)
2345 FIXME("(0x%x)\n", dwMode);
2346 return S_OK;
2349 /***********************************************************************
2350 * MimeOleCreateVirtualStream (INETCOMM.@)
2352 HRESULT WINAPI MimeOleCreateVirtualStream(IStream **ppStream)
2354 HRESULT hr;
2355 FIXME("(%p)\n", ppStream);
2357 hr = CreateStreamOnHGlobal(NULL, TRUE, ppStream);
2358 return hr;
2361 typedef struct MimeSecurity
2363 const IMimeSecurityVtbl *lpVtbl;
2365 LONG refs;
2366 } MimeSecurity;
2368 static HRESULT WINAPI MimeSecurity_QueryInterface(
2369 IMimeSecurity* iface,
2370 REFIID riid,
2371 void** obj)
2373 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), obj);
2375 if (IsEqualIID(riid, &IID_IUnknown) ||
2376 IsEqualIID(riid, &IID_IMimeSecurity))
2378 *obj = iface;
2379 IUnknown_AddRef(iface);
2380 return S_OK;
2383 FIXME("no interface for %s\n", debugstr_guid(riid));
2384 *obj = NULL;
2385 return E_NOINTERFACE;
2388 static ULONG WINAPI MimeSecurity_AddRef(
2389 IMimeSecurity* iface)
2391 MimeSecurity *This = (MimeSecurity *)iface;
2392 TRACE("(%p)->()\n", iface);
2393 return InterlockedIncrement(&This->refs);
2396 static ULONG WINAPI MimeSecurity_Release(
2397 IMimeSecurity* iface)
2399 MimeSecurity *This = (MimeSecurity *)iface;
2400 ULONG refs;
2402 TRACE("(%p)->()\n", iface);
2404 refs = InterlockedDecrement(&This->refs);
2405 if (!refs)
2407 HeapFree(GetProcessHeap(), 0, This);
2410 return refs;
2413 static HRESULT WINAPI MimeSecurity_InitNew(
2414 IMimeSecurity* iface)
2416 FIXME("(%p)->(): stub\n", iface);
2417 return S_OK;
2420 static HRESULT WINAPI MimeSecurity_CheckInit(
2421 IMimeSecurity* iface)
2423 FIXME("(%p)->(): stub\n", iface);
2424 return E_NOTIMPL;
2427 static HRESULT WINAPI MimeSecurity_EncodeMessage(
2428 IMimeSecurity* iface,
2429 IMimeMessageTree* pTree,
2430 DWORD dwFlags)
2432 FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags);
2433 return E_NOTIMPL;
2436 static HRESULT WINAPI MimeSecurity_EncodeBody(
2437 IMimeSecurity* iface,
2438 IMimeMessageTree* pTree,
2439 HBODY hEncodeRoot,
2440 DWORD dwFlags)
2442 FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hEncodeRoot, dwFlags);
2443 return E_NOTIMPL;
2446 static HRESULT WINAPI MimeSecurity_DecodeMessage(
2447 IMimeSecurity* iface,
2448 IMimeMessageTree* pTree,
2449 DWORD dwFlags)
2451 FIXME("(%p)->(%p, %08x): stub\n", iface, pTree, dwFlags);
2452 return E_NOTIMPL;
2455 static HRESULT WINAPI MimeSecurity_DecodeBody(
2456 IMimeSecurity* iface,
2457 IMimeMessageTree* pTree,
2458 HBODY hDecodeRoot,
2459 DWORD dwFlags)
2461 FIXME("(%p)->(%p, %p, %08x): stub\n", iface, pTree, hDecodeRoot, dwFlags);
2462 return E_NOTIMPL;
2465 static HRESULT WINAPI MimeSecurity_EnumCertificates(
2466 IMimeSecurity* iface,
2467 HCAPICERTSTORE hc,
2468 DWORD dwUsage,
2469 PCX509CERT pPrev,
2470 PCX509CERT* ppCert)
2472 FIXME("(%p)->(%p, %08x, %p, %p): stub\n", iface, hc, dwUsage, pPrev, ppCert);
2473 return E_NOTIMPL;
2476 static HRESULT WINAPI MimeSecurity_GetCertificateName(
2477 IMimeSecurity* iface,
2478 const PCX509CERT pX509Cert,
2479 const CERTNAMETYPE cn,
2480 LPSTR* ppszName)
2482 FIXME("(%p)->(%p, %08x, %p): stub\n", iface, pX509Cert, cn, ppszName);
2483 return E_NOTIMPL;
2486 static HRESULT WINAPI MimeSecurity_GetMessageType(
2487 IMimeSecurity* iface,
2488 const HWND hwndParent,
2489 IMimeBody* pBody,
2490 DWORD* pdwSecType)
2492 FIXME("(%p)->(%p, %p, %p): stub\n", iface, hwndParent, pBody, pdwSecType);
2493 return E_NOTIMPL;
2496 static HRESULT WINAPI MimeSecurity_GetCertData(
2497 IMimeSecurity* iface,
2498 const PCX509CERT pX509Cert,
2499 const CERTDATAID dataid,
2500 LPPROPVARIANT pValue)
2502 FIXME("(%p)->(%p, %x, %p): stub\n", iface, pX509Cert, dataid, pValue);
2503 return E_NOTIMPL;
2507 static const IMimeSecurityVtbl MimeSecurityVtbl =
2509 MimeSecurity_QueryInterface,
2510 MimeSecurity_AddRef,
2511 MimeSecurity_Release,
2512 MimeSecurity_InitNew,
2513 MimeSecurity_CheckInit,
2514 MimeSecurity_EncodeMessage,
2515 MimeSecurity_EncodeBody,
2516 MimeSecurity_DecodeMessage,
2517 MimeSecurity_DecodeBody,
2518 MimeSecurity_EnumCertificates,
2519 MimeSecurity_GetCertificateName,
2520 MimeSecurity_GetMessageType,
2521 MimeSecurity_GetCertData
2524 /***********************************************************************
2525 * MimeOleCreateSecurity (INETCOMM.@)
2527 HRESULT WINAPI MimeOleCreateSecurity(IMimeSecurity **ppSecurity)
2529 MimeSecurity *This;
2531 TRACE("(%p)\n", ppSecurity);
2533 *ppSecurity = NULL;
2535 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2536 if (!This) return E_OUTOFMEMORY;
2538 This->lpVtbl = &MimeSecurityVtbl;
2539 This->refs = 1;
2541 *ppSecurity = (IMimeSecurity *)&This->lpVtbl;
2542 return S_OK;
2546 typedef struct
2548 IMimeAllocatorVtbl *lpVtbl;
2549 } MimeAllocator;
2551 static HRESULT WINAPI MimeAlloc_QueryInterface(
2552 IMimeAllocator* iface,
2553 REFIID riid,
2554 void **obj)
2556 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), obj);
2558 if (IsEqualIID(riid, &IID_IUnknown) ||
2559 IsEqualIID(riid, &IID_IMalloc) ||
2560 IsEqualIID(riid, &IID_IMimeAllocator))
2562 *obj = iface;
2563 IUnknown_AddRef(iface);
2564 return S_OK;
2567 FIXME("no interface for %s\n", debugstr_guid(riid));
2568 *obj = NULL;
2569 return E_NOINTERFACE;
2572 static ULONG WINAPI MimeAlloc_AddRef(
2573 IMimeAllocator* iface)
2575 return 2;
2578 static ULONG WINAPI MimeAlloc_Release(
2579 IMimeAllocator* iface)
2581 return 1;
2584 static LPVOID WINAPI MimeAlloc_Alloc(
2585 IMimeAllocator* iface,
2586 ULONG cb)
2588 return CoTaskMemAlloc(cb);
2591 static LPVOID WINAPI MimeAlloc_Realloc(
2592 IMimeAllocator* iface,
2593 LPVOID pv,
2594 ULONG cb)
2596 return CoTaskMemRealloc(pv, cb);
2599 static void WINAPI MimeAlloc_Free(
2600 IMimeAllocator* iface,
2601 LPVOID pv)
2603 return CoTaskMemFree(pv);
2606 static ULONG WINAPI MimeAlloc_GetSize(
2607 IMimeAllocator* iface,
2608 LPVOID pv)
2610 FIXME("stub\n");
2611 return 0;
2614 static int WINAPI MimeAlloc_DidAlloc(
2615 IMimeAllocator* iface,
2616 LPVOID pv)
2618 FIXME("stub\n");
2619 return 0;
2622 static void WINAPI MimeAlloc_HeapMinimize(
2623 IMimeAllocator* iface)
2625 FIXME("stub\n");
2626 return;
2629 static HRESULT WINAPI MimeAlloc_FreeParamInfoArray(
2630 IMimeAllocator* iface,
2631 ULONG cParams,
2632 LPMIMEPARAMINFO prgParam,
2633 boolean fFreeArray)
2635 ULONG i;
2636 TRACE("(%p)->(%d, %p, %d)\n", iface, cParams, prgParam, fFreeArray);
2638 for(i = 0; i < cParams; i++)
2640 IMimeAllocator_Free(iface, prgParam[i].pszName);
2641 IMimeAllocator_Free(iface, prgParam[i].pszData);
2643 if(fFreeArray) IMimeAllocator_Free(iface, prgParam);
2644 return S_OK;
2647 static HRESULT WINAPI MimeAlloc_FreeAddressList(
2648 IMimeAllocator* iface,
2649 LPADDRESSLIST pList)
2651 FIXME("stub\n");
2652 return E_NOTIMPL;
2655 static HRESULT WINAPI MimeAlloc_FreeAddressProps(
2656 IMimeAllocator* iface,
2657 LPADDRESSPROPS pAddress)
2659 FIXME("stub\n");
2660 return E_NOTIMPL;
2663 static HRESULT WINAPI MimeAlloc_ReleaseObjects(
2664 IMimeAllocator* iface,
2665 ULONG cObjects,
2666 IUnknown **prgpUnknown,
2667 boolean fFreeArray)
2669 FIXME("stub\n");
2670 return E_NOTIMPL;
2674 static HRESULT WINAPI MimeAlloc_FreeEnumHeaderRowArray(
2675 IMimeAllocator* iface,
2676 ULONG cRows,
2677 LPENUMHEADERROW prgRow,
2678 boolean fFreeArray)
2680 FIXME("stub\n");
2681 return E_NOTIMPL;
2684 static HRESULT WINAPI MimeAlloc_FreeEnumPropertyArray(
2685 IMimeAllocator* iface,
2686 ULONG cProps,
2687 LPENUMPROPERTY prgProp,
2688 boolean fFreeArray)
2690 FIXME("stub\n");
2691 return E_NOTIMPL;
2694 static HRESULT WINAPI MimeAlloc_FreeThumbprint(
2695 IMimeAllocator* iface,
2696 THUMBBLOB *pthumbprint)
2698 FIXME("stub\n");
2699 return E_NOTIMPL;
2703 static HRESULT WINAPI MimeAlloc_PropVariantClear(
2704 IMimeAllocator* iface,
2705 LPPROPVARIANT pProp)
2707 FIXME("stub\n");
2708 return E_NOTIMPL;
2711 static IMimeAllocatorVtbl mime_alloc_vtbl =
2713 MimeAlloc_QueryInterface,
2714 MimeAlloc_AddRef,
2715 MimeAlloc_Release,
2716 MimeAlloc_Alloc,
2717 MimeAlloc_Realloc,
2718 MimeAlloc_Free,
2719 MimeAlloc_GetSize,
2720 MimeAlloc_DidAlloc,
2721 MimeAlloc_HeapMinimize,
2722 MimeAlloc_FreeParamInfoArray,
2723 MimeAlloc_FreeAddressList,
2724 MimeAlloc_FreeAddressProps,
2725 MimeAlloc_ReleaseObjects,
2726 MimeAlloc_FreeEnumHeaderRowArray,
2727 MimeAlloc_FreeEnumPropertyArray,
2728 MimeAlloc_FreeThumbprint,
2729 MimeAlloc_PropVariantClear
2732 static MimeAllocator mime_allocator =
2734 &mime_alloc_vtbl
2737 HRESULT MimeAllocator_create(IUnknown *outer, void **obj)
2739 if(outer) return CLASS_E_NOAGGREGATION;
2741 *obj = &mime_allocator;
2742 return S_OK;
2745 HRESULT WINAPI MimeOleGetAllocator(IMimeAllocator **alloc)
2747 return MimeAllocator_create(NULL, (void**)alloc);